wined3d: Don't call shader_select() in depth_blt().

Calling shader_select() from inside depth_blt() isn't necessarily
safe. shader_select() assumes CompileShader() has been called for the
current shaders, but that depends on STATE_VSHADER / STATE_PIXELSHADER
being applied. That isn't always true when depth_blt() gets called,
with the result that sometimes GLSL programs could be created with no
shader objects attached.
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 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 @@
     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 @@
     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 @@
 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 @@
     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 @@
 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 @@
 
 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 @@
 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 @@
 
     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 @@
     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 @@
 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 @@
 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 @@
 
 /* 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;
 };