wined3d: Remove the forward declaration added in the last patch.

This commit is contained in:
Stefan Dösinger 2009-05-26 13:57:03 +02:00 committed by Alexandre Julliard
parent d0d681c81e
commit 732a9a15d5
2 changed files with 401 additions and 407 deletions

View File

@ -1926,232 +1926,6 @@ static GLuint create_arb_blt_fragment_program(const WineD3D_GL_Info *gl_info, en
return program_id;
}
static GLuint shader_arb_generate_pshader(IWineD3DPixelShader *iface,
SHADER_BUFFER *buffer, const struct ps_compile_args *args);
/* GL locking is done by the caller */
static GLuint find_arb_pshader(IWineD3DPixelShaderImpl *shader, const struct ps_compile_args *args)
{
UINT i;
DWORD new_size;
struct ps_compiled_shader *new_array;
SHADER_BUFFER buffer;
/* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2),
* so a linear search is more performant than a hashmap or a binary search
* (cache coherency etc)
*/
for(i = 0; i < shader->num_gl_shaders; i++) {
if(memcmp(&shader->gl_shaders[i].args, args, sizeof(*args)) == 0) {
return shader->gl_shaders[i].prgId;
}
}
TRACE("No matching GL shader found, compiling a new shader\n");
if(shader->shader_array_size == shader->num_gl_shaders) {
if (shader->num_gl_shaders)
{
new_size = shader->shader_array_size + max(1, shader->shader_array_size / 2);
new_array = HeapReAlloc(GetProcessHeap(), 0, shader->gl_shaders,
new_size * sizeof(*shader->gl_shaders));
} else {
new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*shader->gl_shaders));
new_size = 1;
}
if(!new_array) {
ERR("Out of memory\n");
return 0;
}
shader->gl_shaders = new_array;
shader->shader_array_size = new_size;
}
shader->gl_shaders[shader->num_gl_shaders].args = *args;
pixelshader_update_samplers(&shader->baseShader.reg_maps,
((IWineD3DDeviceImpl *)shader->baseShader.device)->stateBlock->textures);
shader_buffer_init(&buffer);
shader->gl_shaders[shader->num_gl_shaders].prgId =
shader_arb_generate_pshader((IWineD3DPixelShader *)shader, &buffer, args);
shader_buffer_free(&buffer);
return shader->gl_shaders[shader->num_gl_shaders++].prgId;
}
/* GL locking is done by the caller */
static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
struct shader_arb_priv *priv = This->shader_priv;
const WineD3D_GL_Info *gl_info = &This->adapter->gl_info;
if (useVS) {
struct vs_compile_args compile_args;
TRACE("Using vertex shader\n");
find_vs_compile_args((IWineD3DVertexShaderImpl *) This->stateBlock->vertexShader, This->stateBlock, &compile_args);
priv->current_vprogram_id = find_gl_vshader((IWineD3DVertexShaderImpl *) This->stateBlock->vertexShader, &compile_args);
/* Bind the vertex program */
GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id));
checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id);");
/* Enable OpenGL vertex programs */
glEnable(GL_VERTEX_PROGRAM_ARB);
checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
TRACE("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n", This, priv->current_vprogram_id);
} else if(GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
priv->current_vprogram_id = 0;
glDisable(GL_VERTEX_PROGRAM_ARB);
checkGLcall("glDisable(GL_VERTEX_PROGRAM_ARB)");
}
if (usePS) {
struct ps_compile_args compile_args;
TRACE("Using pixel shader\n");
find_ps_compile_args((IWineD3DPixelShaderImpl *) This->stateBlock->pixelShader, This->stateBlock, &compile_args);
priv->current_fprogram_id = find_arb_pshader((IWineD3DPixelShaderImpl *) This->stateBlock->pixelShader,
&compile_args);
/* Bind the fragment program */
GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id));
checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id);");
if(!priv->use_arbfp_fixed_func) {
/* Enable OpenGL fragment programs */
glEnable(GL_FRAGMENT_PROGRAM_ARB);
checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
}
TRACE("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n", This, priv->current_fprogram_id);
shader_arb_ps_local_constants(This);
} else if(GL_SUPPORT(ARB_FRAGMENT_PROGRAM) && !priv->use_arbfp_fixed_func) {
/* Disable only if we're not using arbfp fixed function fragment processing. If this is used,
* keep GL_FRAGMENT_PROGRAM_ARB enabled, and the fixed function pipeline will bind the fixed function
* replacement shader
*/
glDisable(GL_FRAGMENT_PROGRAM_ARB);
checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)");
priv->current_fprogram_id = 0;
}
}
/* GL locking is done by the caller */
static void shader_arb_select_depth_blt(IWineD3DDevice *iface, enum tex_types tex_type) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
struct shader_arb_priv *priv = This->shader_priv;
GLuint *blt_fprogram = &priv->depth_blt_fprogram_id[tex_type];
const WineD3D_GL_Info *gl_info = &This->adapter->gl_info;
if (!priv->depth_blt_vprogram_id) priv->depth_blt_vprogram_id = create_arb_blt_vertex_program(gl_info);
GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->depth_blt_vprogram_id));
glEnable(GL_VERTEX_PROGRAM_ARB);
if (!*blt_fprogram) *blt_fprogram = create_arb_blt_fragment_program(gl_info, tex_type);
GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, *blt_fprogram));
glEnable(GL_FRAGMENT_PROGRAM_ARB);
}
/* GL locking is done by the caller */
static void shader_arb_deselect_depth_blt(IWineD3DDevice *iface) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
struct shader_arb_priv *priv = This->shader_priv;
const WineD3D_GL_Info *gl_info = &This->adapter->gl_info;
if (priv->current_vprogram_id) {
GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id));
checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);");
glEnable(GL_VERTEX_PROGRAM_ARB);
checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
TRACE("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n", This, priv->current_vprogram_id);
} else {
glDisable(GL_VERTEX_PROGRAM_ARB);
checkGLcall("glDisable(GL_VERTEX_PROGRAM_ARB)");
}
if (priv->current_fprogram_id) {
GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id));
checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixelShader->prgId);");
glEnable(GL_FRAGMENT_PROGRAM_ARB);
checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
TRACE("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n", This, priv->current_fprogram_id);
} else {
glDisable(GL_FRAGMENT_PROGRAM_ARB);
checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)");
}
}
static void shader_arb_destroy(IWineD3DBaseShader *iface) {
IWineD3DBaseShaderImpl *baseShader = (IWineD3DBaseShaderImpl *) iface;
const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)baseShader->baseShader.device)->adapter->gl_info;
if (shader_is_pshader_version(baseShader->baseShader.reg_maps.shader_version.type))
{
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *) iface;
UINT i;
ENTER_GL();
for(i = 0; i < This->num_gl_shaders; i++) {
GL_EXTCALL(glDeleteProgramsARB(1, &This->gl_shaders[i].prgId));
checkGLcall("GL_EXTCALL(glDeleteProgramsARB(1, &This->gl_shaders[i].prgId))");
}
LEAVE_GL();
HeapFree(GetProcessHeap(), 0, This->gl_shaders);
This->gl_shaders = NULL;
This->num_gl_shaders = 0;
This->shader_array_size = 0;
} else {
IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *) iface;
UINT i;
ENTER_GL();
for(i = 0; i < This->num_gl_shaders; i++) {
GL_EXTCALL(glDeleteProgramsARB(1, &This->gl_shaders[i].prgId));
checkGLcall("GL_EXTCALL(glDeleteProgramsARB(1, &This->gl_shaders[i].prgId))");
}
LEAVE_GL();
HeapFree(GetProcessHeap(), 0, This->gl_shaders);
This->gl_shaders = NULL;
This->num_gl_shaders = 0;
This->shader_array_size = 0;
}
}
static HRESULT shader_arb_alloc(IWineD3DDevice *iface) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
This->shader_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct shader_arb_priv));
return WINED3D_OK;
}
static void shader_arb_free(IWineD3DDevice *iface) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
const WineD3D_GL_Info *gl_info = &This->adapter->gl_info;
struct shader_arb_priv *priv = This->shader_priv;
int i;
ENTER_GL();
if(priv->depth_blt_vprogram_id) {
GL_EXTCALL(glDeleteProgramsARB(1, &priv->depth_blt_vprogram_id));
}
for (i = 0; i < tex_type_count; ++i) {
if (priv->depth_blt_fprogram_id[i]) {
GL_EXTCALL(glDeleteProgramsARB(1, &priv->depth_blt_fprogram_id[i]));
}
}
LEAVE_GL();
HeapFree(GetProcessHeap(), 0, This->shader_priv);
}
static BOOL shader_arb_dirty_const(IWineD3DDevice *iface) {
return TRUE;
}
static void arbfp_add_sRGB_correction(SHADER_BUFFER *buffer, const char *fragcolor, const char *tmp1,
const char *tmp2, const char *tmp3) {
/* Perform sRGB write correction. See GLX_EXT_framebuffer_sRGB */
@ -2169,7 +1943,6 @@ static void arbfp_add_sRGB_correction(SHADER_BUFFER *buffer, const char *fragcol
shader_addline(buffer, "CMP result.color.xyz, %s, %s, %s;\n", tmp3, tmp2, tmp1);
}
/* GL locking is done by the caller */
static GLuint shader_arb_generate_pshader(IWineD3DPixelShader *iface,
SHADER_BUFFER *buffer, const struct ps_compile_args *args)
{
@ -2427,6 +2200,229 @@ static GLuint shader_arb_generate_vshader(IWineD3DVertexShader *iface,
return ret;
}
/* GL locking is done by the caller */
static GLuint find_arb_pshader(IWineD3DPixelShaderImpl *shader, const struct ps_compile_args *args)
{
UINT i;
DWORD new_size;
struct ps_compiled_shader *new_array;
SHADER_BUFFER buffer;
/* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2),
* so a linear search is more performant than a hashmap or a binary search
* (cache coherency etc)
*/
for(i = 0; i < shader->num_gl_shaders; i++) {
if(memcmp(&shader->gl_shaders[i].args, args, sizeof(*args)) == 0) {
return shader->gl_shaders[i].prgId;
}
}
TRACE("No matching GL shader found, compiling a new shader\n");
if(shader->shader_array_size == shader->num_gl_shaders) {
if (shader->num_gl_shaders)
{
new_size = shader->shader_array_size + max(1, shader->shader_array_size / 2);
new_array = HeapReAlloc(GetProcessHeap(), 0, shader->gl_shaders,
new_size * sizeof(*shader->gl_shaders));
} else {
new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*shader->gl_shaders));
new_size = 1;
}
if(!new_array) {
ERR("Out of memory\n");
return 0;
}
shader->gl_shaders = new_array;
shader->shader_array_size = new_size;
}
shader->gl_shaders[shader->num_gl_shaders].args = *args;
pixelshader_update_samplers(&shader->baseShader.reg_maps,
((IWineD3DDeviceImpl *)shader->baseShader.device)->stateBlock->textures);
shader_buffer_init(&buffer);
shader->gl_shaders[shader->num_gl_shaders].prgId =
shader_arb_generate_pshader((IWineD3DPixelShader *)shader, &buffer, args);
shader_buffer_free(&buffer);
return shader->gl_shaders[shader->num_gl_shaders++].prgId;
}
/* GL locking is done by the caller */
static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
struct shader_arb_priv *priv = This->shader_priv;
const WineD3D_GL_Info *gl_info = &This->adapter->gl_info;
if (useVS) {
struct vs_compile_args compile_args;
TRACE("Using vertex shader\n");
find_vs_compile_args((IWineD3DVertexShaderImpl *) This->stateBlock->vertexShader, This->stateBlock, &compile_args);
priv->current_vprogram_id = find_gl_vshader((IWineD3DVertexShaderImpl *) This->stateBlock->vertexShader, &compile_args);
/* Bind the vertex program */
GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id));
checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id);");
/* Enable OpenGL vertex programs */
glEnable(GL_VERTEX_PROGRAM_ARB);
checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
TRACE("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n", This, priv->current_vprogram_id);
} else if(GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
priv->current_vprogram_id = 0;
glDisable(GL_VERTEX_PROGRAM_ARB);
checkGLcall("glDisable(GL_VERTEX_PROGRAM_ARB)");
}
if (usePS) {
struct ps_compile_args compile_args;
TRACE("Using pixel shader\n");
find_ps_compile_args((IWineD3DPixelShaderImpl *) This->stateBlock->pixelShader, This->stateBlock, &compile_args);
priv->current_fprogram_id = find_arb_pshader((IWineD3DPixelShaderImpl *) This->stateBlock->pixelShader,
&compile_args);
/* Bind the fragment program */
GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id));
checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id);");
if(!priv->use_arbfp_fixed_func) {
/* Enable OpenGL fragment programs */
glEnable(GL_FRAGMENT_PROGRAM_ARB);
checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
}
TRACE("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n", This, priv->current_fprogram_id);
shader_arb_ps_local_constants(This);
} else if(GL_SUPPORT(ARB_FRAGMENT_PROGRAM) && !priv->use_arbfp_fixed_func) {
/* Disable only if we're not using arbfp fixed function fragment processing. If this is used,
* keep GL_FRAGMENT_PROGRAM_ARB enabled, and the fixed function pipeline will bind the fixed function
* replacement shader
*/
glDisable(GL_FRAGMENT_PROGRAM_ARB);
checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)");
priv->current_fprogram_id = 0;
}
}
/* GL locking is done by the caller */
static void shader_arb_select_depth_blt(IWineD3DDevice *iface, enum tex_types tex_type) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
struct shader_arb_priv *priv = This->shader_priv;
GLuint *blt_fprogram = &priv->depth_blt_fprogram_id[tex_type];
const WineD3D_GL_Info *gl_info = &This->adapter->gl_info;
if (!priv->depth_blt_vprogram_id) priv->depth_blt_vprogram_id = create_arb_blt_vertex_program(gl_info);
GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->depth_blt_vprogram_id));
glEnable(GL_VERTEX_PROGRAM_ARB);
if (!*blt_fprogram) *blt_fprogram = create_arb_blt_fragment_program(gl_info, tex_type);
GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, *blt_fprogram));
glEnable(GL_FRAGMENT_PROGRAM_ARB);
}
/* GL locking is done by the caller */
static void shader_arb_deselect_depth_blt(IWineD3DDevice *iface) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
struct shader_arb_priv *priv = This->shader_priv;
const WineD3D_GL_Info *gl_info = &This->adapter->gl_info;
if (priv->current_vprogram_id) {
GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id));
checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);");
glEnable(GL_VERTEX_PROGRAM_ARB);
checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
TRACE("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n", This, priv->current_vprogram_id);
} else {
glDisable(GL_VERTEX_PROGRAM_ARB);
checkGLcall("glDisable(GL_VERTEX_PROGRAM_ARB)");
}
if (priv->current_fprogram_id) {
GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id));
checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixelShader->prgId);");
glEnable(GL_FRAGMENT_PROGRAM_ARB);
checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
TRACE("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n", This, priv->current_fprogram_id);
} else {
glDisable(GL_FRAGMENT_PROGRAM_ARB);
checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)");
}
}
static void shader_arb_destroy(IWineD3DBaseShader *iface) {
IWineD3DBaseShaderImpl *baseShader = (IWineD3DBaseShaderImpl *) iface;
const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)baseShader->baseShader.device)->adapter->gl_info;
if (shader_is_pshader_version(baseShader->baseShader.reg_maps.shader_version.type))
{
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *) iface;
UINT i;
ENTER_GL();
for(i = 0; i < This->num_gl_shaders; i++) {
GL_EXTCALL(glDeleteProgramsARB(1, &This->gl_shaders[i].prgId));
checkGLcall("GL_EXTCALL(glDeleteProgramsARB(1, &This->gl_shaders[i].prgId))");
}
LEAVE_GL();
HeapFree(GetProcessHeap(), 0, This->gl_shaders);
This->gl_shaders = NULL;
This->num_gl_shaders = 0;
This->shader_array_size = 0;
} else {
IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *) iface;
UINT i;
ENTER_GL();
for(i = 0; i < This->num_gl_shaders; i++) {
GL_EXTCALL(glDeleteProgramsARB(1, &This->gl_shaders[i].prgId));
checkGLcall("GL_EXTCALL(glDeleteProgramsARB(1, &This->gl_shaders[i].prgId))");
}
LEAVE_GL();
HeapFree(GetProcessHeap(), 0, This->gl_shaders);
This->gl_shaders = NULL;
This->num_gl_shaders = 0;
This->shader_array_size = 0;
}
}
static HRESULT shader_arb_alloc(IWineD3DDevice *iface) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
This->shader_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct shader_arb_priv));
return WINED3D_OK;
}
static void shader_arb_free(IWineD3DDevice *iface) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
const WineD3D_GL_Info *gl_info = &This->adapter->gl_info;
struct shader_arb_priv *priv = This->shader_priv;
int i;
ENTER_GL();
if(priv->depth_blt_vprogram_id) {
GL_EXTCALL(glDeleteProgramsARB(1, &priv->depth_blt_vprogram_id));
}
for (i = 0; i < tex_type_count; ++i) {
if (priv->depth_blt_fprogram_id[i]) {
GL_EXTCALL(glDeleteProgramsARB(1, &priv->depth_blt_fprogram_id[i]));
}
}
LEAVE_GL();
HeapFree(GetProcessHeap(), 0, This->shader_priv);
}
static BOOL shader_arb_dirty_const(IWineD3DDevice *iface) {
return TRUE;
}
static void shader_arb_get_caps(WINED3DDEVTYPE devtype, const WineD3D_GL_Info *gl_info, struct shader_caps *pCaps)
{
/* We don't have an ARB fixed function pipeline yet, so let the none backend set its caps,

View File

@ -3608,8 +3608,185 @@ static void hardcode_local_constants(IWineD3DBaseShaderImpl *shader, const WineD
checkGLcall("Hardcoding local constants\n");
}
/* GL locking is done by the caller */
static GLuint shader_glsl_generate_pshader(IWineD3DPixelShader *iface,
SHADER_BUFFER *buffer, const struct ps_compile_args *args);
SHADER_BUFFER *buffer, const struct ps_compile_args *args)
{
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
const struct shader_reg_maps *reg_maps = &This->baseShader.reg_maps;
CONST DWORD *function = This->baseShader.function;
const char *fragcolor;
const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)This->baseShader.device)->adapter->gl_info;
struct shader_glsl_ctx_priv priv_ctx;
/* Create the hw GLSL shader object and assign it as the shader->prgId */
GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB));
memset(&priv_ctx, 0, sizeof(priv_ctx));
priv_ctx.cur_ps_args = args;
shader_addline(buffer, "#version 120\n");
if (GL_SUPPORT(ARB_DRAW_BUFFERS)) {
shader_addline(buffer, "#extension GL_ARB_draw_buffers : enable\n");
}
if(GL_SUPPORT(ARB_SHADER_TEXTURE_LOD) && reg_maps->usestexldd) {
shader_addline(buffer, "#extension GL_ARB_shader_texture_lod : enable\n");
}
if (GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
/* The spec says that it doesn't have to be explicitly enabled, but the nvidia
* drivers write a warning if we don't do so
*/
shader_addline(buffer, "#extension GL_ARB_texture_rectangle : enable\n");
}
/* Base Declarations */
shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION, args);
/* Pack 3.0 inputs */
if (reg_maps->shader_version.major >= 3 && args->vp_mode != vertexshader)
{
pshader_glsl_input_pack(iface, buffer, This->input_signature, reg_maps, args->vp_mode);
}
/* Base Shader Body */
shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function, &priv_ctx);
/* Pixel shaders < 2.0 place the resulting color in R0 implicitly */
if (reg_maps->shader_version.major < 2)
{
/* Some older cards like GeforceFX ones don't support multiple buffers, so also not gl_FragData */
if(GL_SUPPORT(ARB_DRAW_BUFFERS))
shader_addline(buffer, "gl_FragData[0] = R0;\n");
else
shader_addline(buffer, "gl_FragColor = R0;\n");
}
if(GL_SUPPORT(ARB_DRAW_BUFFERS)) {
fragcolor = "gl_FragData[0]";
} else {
fragcolor = "gl_FragColor";
}
if(args->srgb_correction) {
shader_addline(buffer, "tmp0.xyz = pow(%s.xyz, vec3(%f, %f, %f)) * vec3(%f, %f, %f) - vec3(%f, %f, %f);\n",
fragcolor, srgb_pow, srgb_pow, srgb_pow, srgb_mul_high, srgb_mul_high, srgb_mul_high,
srgb_sub_high, srgb_sub_high, srgb_sub_high);
shader_addline(buffer, "tmp1.xyz = %s.xyz * srgb_mul_low.xyz;\n", fragcolor);
shader_addline(buffer, "%s.x = %s.x < srgb_comparison.x ? tmp1.x : tmp0.x;\n", fragcolor, fragcolor);
shader_addline(buffer, "%s.y = %s.y < srgb_comparison.y ? tmp1.y : tmp0.y;\n", fragcolor, fragcolor);
shader_addline(buffer, "%s.z = %s.z < srgb_comparison.z ? tmp1.z : tmp0.z;\n", fragcolor, fragcolor);
shader_addline(buffer, "%s = clamp(%s, 0.0, 1.0);\n", fragcolor, fragcolor);
}
/* Pixel shader < 3.0 do not replace the fog stage.
* This implements linear fog computation and blending.
* TODO: non linear fog
* NOTE: gl_Fog.start and gl_Fog.end don't hold fog start s and end e but
* -1/(e-s) and e/(e-s) respectively.
*/
if (reg_maps->shader_version.major < 3)
{
switch(args->fog) {
case FOG_OFF: break;
case FOG_LINEAR:
shader_addline(buffer, "float fogstart = -1.0 / (gl_Fog.end - gl_Fog.start);\n");
shader_addline(buffer, "float fogend = gl_Fog.end * -fogstart;\n");
shader_addline(buffer, "float Fog = clamp(gl_FogFragCoord * fogstart + fogend, 0.0, 1.0);\n");
shader_addline(buffer, "%s.xyz = mix(gl_Fog.color.xyz, %s.xyz, Fog);\n", fragcolor, fragcolor);
break;
case FOG_EXP:
/* Fog = e^(-gl_Fog.density * gl_FogFragCoord) */
shader_addline(buffer, "float Fog = exp(-gl_Fog.density * gl_FogFragCoord);\n");
shader_addline(buffer, "Fog = clamp(Fog, 0.0, 1.0);\n");
shader_addline(buffer, "%s.xyz = mix(gl_Fog.color.xyz, %s.xyz, Fog);\n", fragcolor, fragcolor);
break;
case FOG_EXP2:
/* Fog = e^(-(gl_Fog.density * gl_FogFragCoord)^2) */
shader_addline(buffer, "float Fog = exp(-gl_Fog.density * gl_Fog.density * gl_FogFragCoord * gl_FogFragCoord);\n");
shader_addline(buffer, "Fog = clamp(Fog, 0.0, 1.0);\n");
shader_addline(buffer, "%s.xyz = mix(gl_Fog.color.xyz, %s.xyz, Fog);\n", fragcolor, fragcolor);
break;
}
}
shader_addline(buffer, "}\n");
TRACE("Compiling shader object %u\n", shader_obj);
GL_EXTCALL(glShaderSourceARB(shader_obj, 1, (const char**)&buffer->buffer, NULL));
GL_EXTCALL(glCompileShaderARB(shader_obj));
print_glsl_info_log(&GLINFO_LOCATION, shader_obj);
/* Store the shader object */
return shader_obj;
}
/* GL locking is done by the caller */
/* GL locking is done by the caller */
static GLuint shader_glsl_generate_vshader(IWineD3DVertexShader *iface,
SHADER_BUFFER *buffer, const struct vs_compile_args *args)
{
IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
const struct shader_reg_maps *reg_maps = &This->baseShader.reg_maps;
CONST DWORD *function = This->baseShader.function;
const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)This->baseShader.device)->adapter->gl_info;
struct shader_glsl_ctx_priv priv_ctx;
/* Create the hw GLSL shader program and assign it as the shader->prgId */
GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB));
shader_addline(buffer, "#version 120\n");
memset(&priv_ctx, 0, sizeof(priv_ctx));
priv_ctx.cur_vs_args = args;
/* Base Declarations */
shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION, NULL);
/* Base Shader Body */
shader_generate_main((IWineD3DBaseShader*)This, buffer, reg_maps, function, &priv_ctx);
/* Unpack 3.0 outputs */
if (reg_maps->shader_version.major >= 3) shader_addline(buffer, "order_ps_input(OUT);\n");
else shader_addline(buffer, "order_ps_input();\n");
/* The D3DRS_FOGTABLEMODE render state defines if the shader-generated fog coord is used
* or if the fragment depth is used. If the fragment depth is used(FOGTABLEMODE != NONE),
* the fog frag coord is thrown away. If the fog frag coord is used, but not written by
* the shader, it is set to 0.0(fully fogged, since start = 1.0, end = 0.0)
*/
if(args->fog_src == VS_FOG_Z) {
shader_addline(buffer, "gl_FogFragCoord = gl_Position.z;\n");
} else if (!reg_maps->fog) {
shader_addline(buffer, "gl_FogFragCoord = 0.0;\n");
}
/* Write the final position.
*
* OpenGL coordinates specify the center of the pixel while d3d coords specify
* the corner. The offsets are stored in z and w in posFixup. posFixup.y contains
* 1.0 or -1.0 to turn the rendering upside down for offscreen rendering. PosFixup.x
* contains 1.0 to allow a mad.
*/
shader_addline(buffer, "gl_Position.y = gl_Position.y * posFixup.y;\n");
shader_addline(buffer, "gl_Position.xy += posFixup.zw * gl_Position.ww;\n");
shader_addline(buffer, "gl_ClipVertex = gl_Position;\n");
/* Z coord [0;1]->[-1;1] mapping, see comment in transform_projection in state.c
*
* Basically we want (in homogeneous coordinates) z = z * 2 - 1. However, shaders are run
* before the homogeneous divide, so we have to take the w into account: z = ((z / w) * 2 - 1) * w,
* which is the same as z = z * 2 - w.
*/
shader_addline(buffer, "gl_Position.z = gl_Position.z * 2.0 - gl_Position.w;\n");
shader_addline(buffer, "}\n");
TRACE("Compiling shader object %u\n", shader_obj);
GL_EXTCALL(glShaderSourceARB(shader_obj, 1, (const char**)&buffer->buffer, NULL));
GL_EXTCALL(glCompileShaderARB(shader_obj));
print_glsl_info_log(&GLINFO_LOCATION, shader_obj);
return shader_obj;
}
static GLhandleARB find_glsl_pshader(IWineD3DPixelShaderImpl *shader, const struct ps_compile_args *args)
{
@ -4213,185 +4390,6 @@ static BOOL shader_glsl_dirty_const(IWineD3DDevice *iface) {
return FALSE;
}
/* GL locking is done by the caller */
static GLuint shader_glsl_generate_pshader(IWineD3DPixelShader *iface,
SHADER_BUFFER *buffer, const struct ps_compile_args *args)
{
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
const struct shader_reg_maps *reg_maps = &This->baseShader.reg_maps;
CONST DWORD *function = This->baseShader.function;
const char *fragcolor;
const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)This->baseShader.device)->adapter->gl_info;
struct shader_glsl_ctx_priv priv_ctx;
/* Create the hw GLSL shader object and assign it as the shader->prgId */
GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB));
memset(&priv_ctx, 0, sizeof(priv_ctx));
priv_ctx.cur_ps_args = args;
shader_addline(buffer, "#version 120\n");
if (GL_SUPPORT(ARB_DRAW_BUFFERS)) {
shader_addline(buffer, "#extension GL_ARB_draw_buffers : enable\n");
}
if(GL_SUPPORT(ARB_SHADER_TEXTURE_LOD) && reg_maps->usestexldd) {
shader_addline(buffer, "#extension GL_ARB_shader_texture_lod : enable\n");
}
if (GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
/* The spec says that it doesn't have to be explicitly enabled, but the nvidia
* drivers write a warning if we don't do so
*/
shader_addline(buffer, "#extension GL_ARB_texture_rectangle : enable\n");
}
/* Base Declarations */
shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION, args);
/* Pack 3.0 inputs */
if (reg_maps->shader_version.major >= 3 && args->vp_mode != vertexshader)
{
pshader_glsl_input_pack(iface, buffer, This->input_signature, reg_maps, args->vp_mode);
}
/* Base Shader Body */
shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function, &priv_ctx);
/* Pixel shaders < 2.0 place the resulting color in R0 implicitly */
if (reg_maps->shader_version.major < 2)
{
/* Some older cards like GeforceFX ones don't support multiple buffers, so also not gl_FragData */
if(GL_SUPPORT(ARB_DRAW_BUFFERS))
shader_addline(buffer, "gl_FragData[0] = R0;\n");
else
shader_addline(buffer, "gl_FragColor = R0;\n");
}
if(GL_SUPPORT(ARB_DRAW_BUFFERS)) {
fragcolor = "gl_FragData[0]";
} else {
fragcolor = "gl_FragColor";
}
if(args->srgb_correction) {
shader_addline(buffer, "tmp0.xyz = pow(%s.xyz, vec3(%f, %f, %f)) * vec3(%f, %f, %f) - vec3(%f, %f, %f);\n",
fragcolor, srgb_pow, srgb_pow, srgb_pow, srgb_mul_high, srgb_mul_high, srgb_mul_high,
srgb_sub_high, srgb_sub_high, srgb_sub_high);
shader_addline(buffer, "tmp1.xyz = %s.xyz * srgb_mul_low.xyz;\n", fragcolor);
shader_addline(buffer, "%s.x = %s.x < srgb_comparison.x ? tmp1.x : tmp0.x;\n", fragcolor, fragcolor);
shader_addline(buffer, "%s.y = %s.y < srgb_comparison.y ? tmp1.y : tmp0.y;\n", fragcolor, fragcolor);
shader_addline(buffer, "%s.z = %s.z < srgb_comparison.z ? tmp1.z : tmp0.z;\n", fragcolor, fragcolor);
shader_addline(buffer, "%s = clamp(%s, 0.0, 1.0);\n", fragcolor, fragcolor);
}
/* Pixel shader < 3.0 do not replace the fog stage.
* This implements linear fog computation and blending.
* TODO: non linear fog
* NOTE: gl_Fog.start and gl_Fog.end don't hold fog start s and end e but
* -1/(e-s) and e/(e-s) respectively.
*/
if (reg_maps->shader_version.major < 3)
{
switch(args->fog) {
case FOG_OFF: break;
case FOG_LINEAR:
shader_addline(buffer, "float fogstart = -1.0 / (gl_Fog.end - gl_Fog.start);\n");
shader_addline(buffer, "float fogend = gl_Fog.end * -fogstart;\n");
shader_addline(buffer, "float Fog = clamp(gl_FogFragCoord * fogstart + fogend, 0.0, 1.0);\n");
shader_addline(buffer, "%s.xyz = mix(gl_Fog.color.xyz, %s.xyz, Fog);\n", fragcolor, fragcolor);
break;
case FOG_EXP:
/* Fog = e^(-gl_Fog.density * gl_FogFragCoord) */
shader_addline(buffer, "float Fog = exp(-gl_Fog.density * gl_FogFragCoord);\n");
shader_addline(buffer, "Fog = clamp(Fog, 0.0, 1.0);\n");
shader_addline(buffer, "%s.xyz = mix(gl_Fog.color.xyz, %s.xyz, Fog);\n", fragcolor, fragcolor);
break;
case FOG_EXP2:
/* Fog = e^(-(gl_Fog.density * gl_FogFragCoord)^2) */
shader_addline(buffer, "float Fog = exp(-gl_Fog.density * gl_Fog.density * gl_FogFragCoord * gl_FogFragCoord);\n");
shader_addline(buffer, "Fog = clamp(Fog, 0.0, 1.0);\n");
shader_addline(buffer, "%s.xyz = mix(gl_Fog.color.xyz, %s.xyz, Fog);\n", fragcolor, fragcolor);
break;
}
}
shader_addline(buffer, "}\n");
TRACE("Compiling shader object %u\n", shader_obj);
GL_EXTCALL(glShaderSourceARB(shader_obj, 1, (const char**)&buffer->buffer, NULL));
GL_EXTCALL(glCompileShaderARB(shader_obj));
print_glsl_info_log(&GLINFO_LOCATION, shader_obj);
/* Store the shader object */
return shader_obj;
}
/* GL locking is done by the caller */
static GLuint shader_glsl_generate_vshader(IWineD3DVertexShader *iface,
SHADER_BUFFER *buffer, const struct vs_compile_args *args)
{
IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
const struct shader_reg_maps *reg_maps = &This->baseShader.reg_maps;
CONST DWORD *function = This->baseShader.function;
const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)This->baseShader.device)->adapter->gl_info;
struct shader_glsl_ctx_priv priv_ctx;
/* Create the hw GLSL shader program and assign it as the shader->prgId */
GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB));
shader_addline(buffer, "#version 120\n");
memset(&priv_ctx, 0, sizeof(priv_ctx));
priv_ctx.cur_vs_args = args;
/* Base Declarations */
shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION, NULL);
/* Base Shader Body */
shader_generate_main((IWineD3DBaseShader*)This, buffer, reg_maps, function, &priv_ctx);
/* Unpack 3.0 outputs */
if (reg_maps->shader_version.major >= 3) shader_addline(buffer, "order_ps_input(OUT);\n");
else shader_addline(buffer, "order_ps_input();\n");
/* The D3DRS_FOGTABLEMODE render state defines if the shader-generated fog coord is used
* or if the fragment depth is used. If the fragment depth is used(FOGTABLEMODE != NONE),
* the fog frag coord is thrown away. If the fog frag coord is used, but not written by
* the shader, it is set to 0.0(fully fogged, since start = 1.0, end = 0.0)
*/
if(args->fog_src == VS_FOG_Z) {
shader_addline(buffer, "gl_FogFragCoord = gl_Position.z;\n");
} else if (!reg_maps->fog) {
shader_addline(buffer, "gl_FogFragCoord = 0.0;\n");
}
/* Write the final position.
*
* OpenGL coordinates specify the center of the pixel while d3d coords specify
* the corner. The offsets are stored in z and w in posFixup. posFixup.y contains
* 1.0 or -1.0 to turn the rendering upside down for offscreen rendering. PosFixup.x
* contains 1.0 to allow a mad.
*/
shader_addline(buffer, "gl_Position.y = gl_Position.y * posFixup.y;\n");
shader_addline(buffer, "gl_Position.xy += posFixup.zw * gl_Position.ww;\n");
shader_addline(buffer, "gl_ClipVertex = gl_Position;\n");
/* Z coord [0;1]->[-1;1] mapping, see comment in transform_projection in state.c
*
* Basically we want (in homogeneous coordinates) z = z * 2 - 1. However, shaders are run
* before the homogeneous divide, so we have to take the w into account: z = ((z / w) * 2 - 1) * w,
* which is the same as z = z * 2 - w.
*/
shader_addline(buffer, "gl_Position.z = gl_Position.z * 2.0 - gl_Position.w;\n");
shader_addline(buffer, "}\n");
TRACE("Compiling shader object %u\n", shader_obj);
GL_EXTCALL(glShaderSourceARB(shader_obj, 1, (const char**)&buffer->buffer, NULL));
GL_EXTCALL(glCompileShaderARB(shader_obj));
print_glsl_info_log(&GLINFO_LOCATION, shader_obj);
return shader_obj;
}
static void shader_glsl_get_caps(WINED3DDEVTYPE devtype, const WineD3D_GL_Info *gl_info, struct shader_caps *pCaps)
{
/* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati