From 732a9a15d59680e21897502e9afe2b3fefa6428b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Tue, 26 May 2009 13:57:03 +0200 Subject: [PATCH] wined3d: Remove the forward declaration added in the last patch. --- dlls/wined3d/arb_program_shader.c | 450 +++++++++++++++--------------- dlls/wined3d/glsl_shader.c | 358 ++++++++++++------------ 2 files changed, 401 insertions(+), 407 deletions(-) diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index 6ae72d86e73..0e4178355e2 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -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, diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 2780d8c053c..50df195e231 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -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