--- dlls/wined3d/arb_program_shader.c | 52 ++++++++++++++++++++++++++++++------ dlls/wined3d/ati_fragment_shader.c | 5 +++ dlls/wined3d/baseshader.c | 2 + dlls/wined3d/drawprim.c | 6 +--- dlls/wined3d/glsl_shader.c | 14 ++++++++++ dlls/wined3d/wined3d_private.h | 3 ++ 6 files changed, 69 insertions(+), 13 deletions(-) diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index a62aed7..ee0a7c8 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -1766,22 +1766,24 @@ static GLuint create_arb_blt_fragment_program(WineD3D_GL_Info *gl_info) { static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + struct shader_arb_priv *priv = (struct shader_arb_priv *) This->shader_priv; WineD3D_GL_Info *gl_info = &This->adapter->gl_info; if (useVS) { TRACE("Using vertex shader\n"); + priv->current_vprogram_id = ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId; + /* Bind the vertex program */ - GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, - ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId)); + GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id)); checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);"); /* 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, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId); + 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)"); } @@ -1789,17 +1791,18 @@ static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) { if (usePS) { TRACE("Using pixel shader\n"); + priv->current_fprogram_id = ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId; + /* Bind the fragment program */ - GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, - ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId)); + GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id)); checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixelShader->prgId);"); /* 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, ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId); + TRACE("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n", This, priv->current_fprogram_id); } else if(GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) { + priv->current_fprogram_id = 0; glDisable(GL_FRAGMENT_PROGRAM_ARB); checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)"); } @@ -1819,6 +1822,38 @@ static void shader_arb_select_depth_blt(IWineD3DDevice *iface) { glEnable(GL_FRAGMENT_PROGRAM_ARB); } +static void shader_arb_deselect_depth_blt(IWineD3DDevice *iface) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + struct shader_arb_priv *priv = (struct shader_arb_priv *) This->shader_priv; + 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 if(GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) { + glDisable(GL_FRAGMENT_PROGRAM_ARB); + checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)"); + } +} + static void shader_arb_cleanup(IWineD3DDevice *iface) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; WineD3D_GL_Info *gl_info = &This->adapter->gl_info; @@ -2092,6 +2127,7 @@ static void shader_arb_fragment_enable(IWineD3DDevice *iface, BOOL enable) { const shader_backend_t arb_program_shader_backend = { shader_arb_select, shader_arb_select_depth_blt, + shader_arb_deselect_depth_blt, shader_arb_load_constants, shader_arb_cleanup, shader_arb_color_correction, diff --git a/dlls/wined3d/ati_fragment_shader.c b/dlls/wined3d/ati_fragment_shader.c index 0c34474..853f6f2 100644 --- a/dlls/wined3d/ati_fragment_shader.c +++ b/dlls/wined3d/ati_fragment_shader.c @@ -976,6 +976,10 @@ static void shader_atifs_select_depth_blt(IWineD3DDevice *iface) { arb_program_shader_backend.shader_select_depth_blt(iface); } +static void shader_atifs_deselect_depth_blt(IWineD3DDevice *iface) { + arb_program_shader_backend.shader_deselect_depth_blt(iface); +} + static void shader_atifs_load_constants(IWineD3DDevice *iface, char usePS, char useVS) { arb_program_shader_backend.shader_load_constants(iface, usePS, useVS); } @@ -1107,6 +1111,7 @@ static void shader_atifs_fragment_enable(IWineD3DDevice *iface, BOOL enable) { const shader_backend_t atifs_shader_backend = { shader_atifs_select, shader_atifs_select_depth_blt, + shader_atifs_deselect_depth_blt, shader_atifs_load_constants, shader_atifs_cleanup, shader_atifs_color_correction, diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c index a8806d3..6b019d3 100644 --- a/dlls/wined3d/baseshader.c +++ b/dlls/wined3d/baseshader.c @@ -1091,6 +1091,7 @@ void shader_trace_init( static void shader_none_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) {} static void shader_none_select_depth_blt(IWineD3DDevice *iface) {} +static void shader_none_deselect_depth_blt(IWineD3DDevice *iface) {} static void shader_none_load_constants(IWineD3DDevice *iface, char usePS, char useVS) {} static void shader_none_cleanup(IWineD3DDevice *iface) {} static void shader_none_color_correction(SHADER_OPCODE_ARG* arg) {} @@ -1201,6 +1202,7 @@ static void shader_none_fragment_enable(IWineD3DDevice *iface, BOOL enable) { const shader_backend_t none_shader_backend = { shader_none_select, shader_none_select_depth_blt, + shader_none_deselect_depth_blt, shader_none_load_constants, shader_none_cleanup, shader_none_color_correction, diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c index f07980a..9a47f8b 100644 --- a/dlls/wined3d/drawprim.c +++ b/dlls/wined3d/drawprim.c @@ -753,11 +753,7 @@ void depth_blt(IWineD3DDevice *iface, GLuint texture) { glPopAttrib(); - /* Reselect the old shaders. There doesn't seem to be any glPushAttrib bit for arb shaders, - * and this seems easier and more efficient than providing the shader backend with a private - * storage to read and restore the old shader settings - */ - This->shader_backend->shader_select(iface, use_ps(This), use_vs(This)); + This->shader_backend->shader_deselect_depth_blt(iface); } static inline void drawStridedInstanced(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd, UINT numberOfVertices, diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 1ff7e11..762e130 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -3398,6 +3398,19 @@ static void shader_glsl_select_depth_blt(IWineD3DDevice *iface) { GL_EXTCALL(glUniform1iARB(loc, 0)); } +static void shader_glsl_deselect_depth_blt(IWineD3DDevice *iface) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + WineD3D_GL_Info *gl_info = &This->adapter->gl_info; + struct shader_glsl_priv *priv = (struct shader_glsl_priv *) This->shader_priv; + GLhandleARB program_id; + + program_id = priv->glsl_program ? priv->glsl_program->programId : 0; + if (program_id) TRACE("Using GLSL program %u\n", program_id); + + GL_EXTCALL(glUseProgramObjectARB(program_id)); + checkGLcall("glUseProgramObjectARB"); +} + static void shader_glsl_cleanup(IWineD3DDevice *iface) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; WineD3D_GL_Info *gl_info = &This->adapter->gl_info; @@ -3695,6 +3708,7 @@ static void shader_glsl_fragment_enable(IWineD3DDevice *iface, BOOL enable) { const shader_backend_t glsl_shader_backend = { shader_glsl_select, shader_glsl_select_depth_blt, + shader_glsl_deselect_depth_blt, shader_glsl_load_constants, shader_glsl_cleanup, shader_glsl_color_correction, diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index b11a3f5..35cb760 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -242,6 +242,7 @@ struct shader_caps { typedef struct { void (*shader_select)(IWineD3DDevice *iface, BOOL usePS, BOOL useVS); void (*shader_select_depth_blt)(IWineD3DDevice *iface); + void (*shader_deselect_depth_blt)(IWineD3DDevice *iface); void (*shader_load_constants)(IWineD3DDevice *iface, char usePS, char useVS); void (*shader_cleanup)(IWineD3DDevice *iface); void (*shader_color_correction)(struct SHADER_OPCODE_ARG *arg); @@ -269,6 +270,8 @@ struct shader_glsl_priv { /* ARB_program_shader private data */ struct shader_arb_priv { + GLuint current_vprogram_id; + GLuint current_fprogram_id; GLuint depth_blt_vprogram_id; GLuint depth_blt_fprogram_id; };