Sync to trunk head (r47736)
[reactos.git] / dll / directx / wine / wined3d / glsl_shader.c
index cb23ee6..056e9ad 100644 (file)
@@ -39,8 +39,6 @@ WINE_DECLARE_DEBUG_CHANNEL(d3d_constants);
 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
 WINE_DECLARE_DEBUG_CHANNEL(d3d);
 
-#define GLINFO_LOCATION      (*gl_info)
-
 #define WINED3D_GLSL_SAMPLE_PROJECTED   0x1
 #define WINED3D_GLSL_SAMPLE_RECT        0x2
 #define WINED3D_GLSL_SAMPLE_LOD         0x4
@@ -89,7 +87,8 @@ struct shader_glsl_priv {
     struct constant_heap vconst_heap;
     struct constant_heap pconst_heap;
     unsigned char *stack;
-    GLhandleARB depth_blt_program[tex_type_count];
+    GLhandleARB depth_blt_program_full[tex_type_count];
+    GLhandleARB depth_blt_program_masked[tex_type_count];
     UINT next_constant_version;
 };
 
@@ -255,7 +254,7 @@ static void print_glsl_info_log(const struct wined3d_gl_info *gl_info, GLhandleA
 /* GL locking is done by the caller. */
 static void shader_glsl_dump_program_source(const struct wined3d_gl_info *gl_info, GLhandleARB program)
 {
-    GLint i, object_count, source_size;
+    GLint i, object_count, source_size = -1;
     GLhandleARB *objects;
     char *source = NULL;
 
@@ -275,7 +274,7 @@ static void shader_glsl_dump_program_source(const struct wined3d_gl_info *gl_inf
 
         GL_EXTCALL(glGetObjectParameterivARB(objects[i], GL_OBJECT_SHADER_SOURCE_LENGTH_ARB, &tmp));
 
-        if (!source || source_size < tmp)
+        if (source_size < tmp)
         {
             HeapFree(GetProcessHeap(), 0, source);
 
@@ -719,8 +718,8 @@ static void shader_glsl_load_np2fixup_constants(
 static void shader_glsl_load_constants(const struct wined3d_context *context,
         char usePixelShader, char useVertexShader)
 {
-    IWineD3DDeviceImpl *device = ((IWineD3DSurfaceImpl *)context->surface)->resource.device;
     const struct wined3d_gl_info *gl_info = context->gl_info;
+    IWineD3DDeviceImpl *device = context->swapchain->device;
     IWineD3DStateBlockImpl* stateBlock = device->stateBlock;
     struct shader_glsl_priv *priv = device->shader_priv;
 
@@ -807,7 +806,7 @@ static void shader_glsl_load_constants(const struct wined3d_context *context,
                 correction_params[1] = 1.0f;
             } else {
                 /* position is window relative, not viewport relative */
-                correction_params[0] = ((IWineD3DSurfaceImpl *)context->current_rt)->currentDesc.Height;
+                correction_params[0] = context->current_rt->currentDesc.Height;
                 correction_params[1] = -1.0f;
             }
             GL_EXTCALL(glUniform4fvARB(prog->ycorrection_location, 1, correction_params));
@@ -1034,7 +1033,7 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
                  */
                 FIXME("Cannot find a free uniform for vpos correction params\n");
                 shader_addline(buffer, "const vec4 ycorrection = vec4(%f, %f, 0.0, 0.0);\n",
-                        context->render_offscreen ? 0.0f : ((IWineD3DSurfaceImpl *)device->render_targets[0])->currentDesc.Height,
+                        context->render_offscreen ? 0.0f : device->render_targets[0]->currentDesc.Height,
                         context->render_offscreen ? 1.0f : -1.0f);
             }
             shader_addline(buffer, "vec4 vpos;\n");
@@ -1048,20 +1047,37 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont
             switch (reg_maps->sampler_type[i])
             {
                 case WINED3DSTT_1D:
-                    shader_addline(buffer, "uniform sampler1D %csampler%u;\n", prefix, i);
+                    if (pshader && ps_args->shadow & (1 << i))
+                        shader_addline(buffer, "uniform sampler1DShadow %csampler%u;\n", prefix, i);
+                    else
+                        shader_addline(buffer, "uniform sampler1D %csampler%u;\n", prefix, i);
                     break;
                 case WINED3DSTT_2D:
-                    if(device->stateBlock->textures[i] &&
-                       IWineD3DBaseTexture_GetTextureDimensions(device->stateBlock->textures[i]) == GL_TEXTURE_RECTANGLE_ARB) {
-                        shader_addline(buffer, "uniform sampler2DRect %csampler%u;\n", prefix, i);
-                    } else {
-                        shader_addline(buffer, "uniform sampler2D %csampler%u;\n", prefix, i);
+                    if (pshader && ps_args->shadow & (1 << i))
+                    {
+                        if (device->stateBlock->textures[i]
+                                && IWineD3DBaseTexture_GetTextureDimensions(device->stateBlock->textures[i])
+                                == GL_TEXTURE_RECTANGLE_ARB)
+                            shader_addline(buffer, "uniform sampler2DRectShadow %csampler%u;\n", prefix, i);
+                        else
+                            shader_addline(buffer, "uniform sampler2DShadow %csampler%u;\n", prefix, i);
+                    }
+                    else
+                    {
+                        if (device->stateBlock->textures[i]
+                                && IWineD3DBaseTexture_GetTextureDimensions(device->stateBlock->textures[i])
+                                == GL_TEXTURE_RECTANGLE_ARB)
+                            shader_addline(buffer, "uniform sampler2DRect %csampler%u;\n", prefix, i);
+                        else
+                            shader_addline(buffer, "uniform sampler2D %csampler%u;\n", prefix, i);
                     }
                     break;
                 case WINED3DSTT_CUBE:
+                    if (pshader && ps_args->shadow & (1 << i)) FIXME("Unsupported Cube shadow sampler.\n");
                     shader_addline(buffer, "uniform samplerCube %csampler%u;\n", prefix, i);
                     break;
                 case WINED3DSTT_VOLUME:
+                    if (pshader && ps_args->shadow & (1 << i)) FIXME("Unsupported 3D shadow sampler.\n");
                     shader_addline(buffer, "uniform sampler3D %csampler%u;\n", prefix, i);
                     break;
                 default:
@@ -1642,9 +1658,13 @@ static inline const char *shader_get_comp_op(DWORD op)
     }
 }
 
-static void shader_glsl_get_sample_function(const struct wined3d_gl_info *gl_info,
-        DWORD sampler_type, DWORD flags, glsl_sample_function_t *sample_function)
+static void shader_glsl_get_sample_function(const struct wined3d_shader_context *ctx,
+        DWORD sampler_idx, DWORD flags, glsl_sample_function_t *sample_function)
 {
+    WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ctx->reg_maps->sampler_type[sampler_idx];
+    const struct wined3d_gl_info *gl_info = ctx->gl_info;
+    BOOL shadow = shader_is_pshader_version(ctx->reg_maps->shader_version.type)
+            && (((const struct shader_glsl_ctx_priv *)ctx->backend_data)->cur_ps_args->shadow & (1 << sampler_idx));
     BOOL projected = flags & WINED3D_GLSL_SAMPLE_PROJECTED;
     BOOL texrect = flags & WINED3D_GLSL_SAMPLE_RECT;
     BOOL lod = flags & WINED3D_GLSL_SAMPLE_LOD;
@@ -1653,115 +1673,225 @@ static void shader_glsl_get_sample_function(const struct wined3d_gl_info *gl_inf
     /* Note that there's no such thing as a projected cube texture. */
     switch(sampler_type) {
         case WINED3DSTT_1D:
-            if(lod) {
-                sample_function->name = projected ? "texture1DProjLod" : "texture1DLod";
-            }
-            else  if (grad)
+            if (shadow)
             {
-                if (gl_info->supported[EXT_GPU_SHADER4])
-                    sample_function->name = projected ? "texture1DProjGrad" : "texture1DGrad";
-                else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD])
-                    sample_function->name = projected ? "texture1DProjGradARB" : "texture1DGradARB";
-                else
+                if (lod)
                 {
-                    FIXME("Unsupported 1D grad function.\n");
-                    sample_function->name = "unsupported1DGrad";
+                    sample_function->name = projected ? "shadow1DProjLod" : "shadow1DLod";
                 }
-            }
-            else
-            {
-                sample_function->name = projected ? "texture1DProj" : "texture1D";
-            }
-            sample_function->coord_mask = WINED3DSP_WRITEMASK_0;
-            break;
-        case WINED3DSTT_2D:
-            if(texrect) {
-                if(lod) {
-                    sample_function->name = projected ? "texture2DRectProjLod" : "texture2DRectLod";
-                }
-                else  if (grad)
+                else if (grad)
                 {
                     if (gl_info->supported[EXT_GPU_SHADER4])
-                        sample_function->name = projected ? "texture2DRectProjGrad" : "texture2DRectGrad";
+                        sample_function->name = projected ? "shadow1DProjGrad" : "shadow1DGrad";
                     else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD])
-                        sample_function->name = projected ? "texture2DRectProjGradARB" : "texture2DRectGradARB";
+                        sample_function->name = projected ? "shadow1DProjGradARB" : "shadow1DGradARB";
                     else
                     {
-                        FIXME("Unsupported RECT grad function.\n");
-                        sample_function->name = "unsupported2DRectGrad";
+                        FIXME("Unsupported 1D shadow grad function.\n");
+                        sample_function->name = "unsupported1DGrad";
                     }
                 }
                 else
                 {
-                    sample_function->name = projected ? "texture2DRectProj" : "texture2DRect";
+                    sample_function->name = projected ? "shadow1DProj" : "shadow1D";
                 }
-            } else {
-                if(lod) {
-                    sample_function->name = projected ? "texture2DProjLod" : "texture2DLod";
+                sample_function->coord_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1;
+            }
+            else
+            {
+                if (lod)
+                {
+                    sample_function->name = projected ? "texture1DProjLod" : "texture1DLod";
                 }
-                else  if (grad)
+                else if (grad)
                 {
                     if (gl_info->supported[EXT_GPU_SHADER4])
-                        sample_function->name = projected ? "texture2DProjGrad" : "texture2DGrad";
+                        sample_function->name = projected ? "texture1DProjGrad" : "texture1DGrad";
                     else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD])
-                        sample_function->name = projected ? "texture2DProjGradARB" : "texture2DGradARB";
+                        sample_function->name = projected ? "texture1DProjGradARB" : "texture1DGradARB";
                     else
                     {
-                        FIXME("Unsupported 2D grad function.\n");
-                        sample_function->name = "unsupported2DGrad";
+                        FIXME("Unsupported 1D grad function.\n");
+                        sample_function->name = "unsupported1DGrad";
                     }
                 }
                 else
                 {
-                    sample_function->name = projected ? "texture2DProj" : "texture2D";
+                    sample_function->name = projected ? "texture1DProj" : "texture1D";
                 }
+                sample_function->coord_mask = WINED3DSP_WRITEMASK_0;
             }
-            sample_function->coord_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1;
             break;
-        case WINED3DSTT_CUBE:
-            if(lod) {
-                sample_function->name = "textureCubeLod";
-            }
-            else if (grad)
+
+        case WINED3DSTT_2D:
+            if (shadow)
             {
-                if (gl_info->supported[EXT_GPU_SHADER4])
-                    sample_function->name = "textureCubeGrad";
-                else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD])
-                    sample_function->name = "textureCubeGradARB";
+                if (texrect)
+                {
+                    if (lod)
+                    {
+                        sample_function->name = projected ? "shadow2DRectProjLod" : "shadow2DRectLod";
+                    }
+                    else if (grad)
+                    {
+                        if (gl_info->supported[EXT_GPU_SHADER4])
+                            sample_function->name = projected ? "shadow2DRectProjGrad" : "shadow2DRectGrad";
+                        else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD])
+                            sample_function->name = projected ? "shadow2DRectProjGradARB" : "shadow2DRectGradARB";
+                        else
+                        {
+                            FIXME("Unsupported RECT shadow grad function.\n");
+                            sample_function->name = "unsupported2DRectGrad";
+                        }
+                    }
+                    else
+                    {
+                        sample_function->name = projected ? "shadow2DRectProj" : "shadow2DRect";
+                    }
+                }
                 else
                 {
-                    FIXME("Unsupported Cube grad function.\n");
-                    sample_function->name = "unsupportedCubeGrad";
+                    if (lod)
+                    {
+                        sample_function->name = projected ? "shadow2DProjLod" : "shadow2DLod";
+                    }
+                    else if (grad)
+                    {
+                        if (gl_info->supported[EXT_GPU_SHADER4])
+                            sample_function->name = projected ? "shadow2DProjGrad" : "shadow2DGrad";
+                        else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD])
+                            sample_function->name = projected ? "shadow2DProjGradARB" : "shadow2DGradARB";
+                        else
+                        {
+                            FIXME("Unsupported 2D shadow grad function.\n");
+                            sample_function->name = "unsupported2DGrad";
+                        }
+                    }
+                    else
+                    {
+                        sample_function->name = projected ? "shadow2DProj" : "shadow2D";
+                    }
                 }
+                sample_function->coord_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
             }
             else
             {
-                sample_function->name = "textureCube";
+                if (texrect)
+                {
+                    if (lod)
+                    {
+                        sample_function->name = projected ? "texture2DRectProjLod" : "texture2DRectLod";
+                    }
+                    else if (grad)
+                    {
+                        if (gl_info->supported[EXT_GPU_SHADER4])
+                            sample_function->name = projected ? "texture2DRectProjGrad" : "texture2DRectGrad";
+                        else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD])
+                            sample_function->name = projected ? "texture2DRectProjGradARB" : "texture2DRectGradARB";
+                        else
+                        {
+                            FIXME("Unsupported RECT grad function.\n");
+                            sample_function->name = "unsupported2DRectGrad";
+                        }
+                    }
+                    else
+                    {
+                        sample_function->name = projected ? "texture2DRectProj" : "texture2DRect";
+                    }
+                }
+                else
+                {
+                    if (lod)
+                    {
+                        sample_function->name = projected ? "texture2DProjLod" : "texture2DLod";
+                    }
+                    else if (grad)
+                    {
+                        if (gl_info->supported[EXT_GPU_SHADER4])
+                            sample_function->name = projected ? "texture2DProjGrad" : "texture2DGrad";
+                        else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD])
+                            sample_function->name = projected ? "texture2DProjGradARB" : "texture2DGradARB";
+                        else
+                        {
+                            FIXME("Unsupported 2D grad function.\n");
+                            sample_function->name = "unsupported2DGrad";
+                        }
+                    }
+                    else
+                    {
+                        sample_function->name = projected ? "texture2DProj" : "texture2D";
+                    }
+                }
+                sample_function->coord_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1;
             }
-            sample_function->coord_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
             break;
-        case WINED3DSTT_VOLUME:
-            if(lod) {
-                sample_function->name = projected ? "texture3DProjLod" : "texture3DLod";
+
+        case WINED3DSTT_CUBE:
+            if (shadow)
+            {
+                FIXME("Unsupported Cube shadow function.\n ");
+                sample_function->name = "unsupportedCubeShadow";
+                sample_function->coord_mask = 0;
             }
-            else  if (grad)
+            else
             {
-                if (gl_info->supported[EXT_GPU_SHADER4])
-                    sample_function->name = projected ? "texture3DProjGrad" : "texture3DGrad";
-                else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD])
-                    sample_function->name = projected ? "texture3DProjGradARB" : "texture3DGradARB";
+                if (lod)
+                {
+                    sample_function->name = "textureCubeLod";
+                }
+                else if (grad)
+                {
+                    if (gl_info->supported[EXT_GPU_SHADER4])
+                        sample_function->name = "textureCubeGrad";
+                    else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD])
+                        sample_function->name = "textureCubeGradARB";
+                    else
+                    {
+                        FIXME("Unsupported Cube grad function.\n");
+                        sample_function->name = "unsupportedCubeGrad";
+                    }
+                }
                 else
                 {
-                    FIXME("Unsupported 3D grad function.\n");
-                    sample_function->name = "unsupported3DGrad";
+                    sample_function->name = "textureCube";
                 }
+                sample_function->coord_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
+            }
+            break;
+
+        case WINED3DSTT_VOLUME:
+            if (shadow)
+            {
+                FIXME("Unsupported 3D shadow function.\n ");
+                sample_function->name = "unsupported3DShadow";
+                sample_function->coord_mask = 0;
             }
             else
             {
-                sample_function->name = projected ? "texture3DProj" : "texture3D";
+                if (lod)
+                {
+                    sample_function->name = projected ? "texture3DProjLod" : "texture3DLod";
+                }
+                else  if (grad)
+                {
+                    if (gl_info->supported[EXT_GPU_SHADER4])
+                        sample_function->name = projected ? "texture3DProjGrad" : "texture3DGrad";
+                    else if (gl_info->supported[ARB_SHADER_TEXTURE_LOD])
+                        sample_function->name = projected ? "texture3DProjGradARB" : "texture3DGradARB";
+                    else
+                    {
+                        FIXME("Unsupported 3D grad function.\n");
+                        sample_function->name = "unsupported3DGrad";
+                    }
+                }
+                else
+                {
+                    sample_function->name = projected ? "texture3DProj" : "texture3D";
+                }
+                sample_function->coord_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
             }
-            sample_function->coord_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
             break;
+
         default:
             sample_function->name = "";
             sample_function->coord_mask = 0;
@@ -2164,16 +2294,26 @@ static void shader_glsl_nrm(const struct wined3d_shader_instruction *ins)
 {
     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
     glsl_src_param_t src_param;
+    unsigned int mask_size;
     DWORD write_mask;
     char dst_mask[6];
 
     write_mask = shader_glsl_get_write_mask(ins->dst, dst_mask);
+    mask_size = shader_glsl_get_write_mask_size(write_mask);
     shader_glsl_add_src_param(ins, &ins->src[0], write_mask, &src_param);
 
     shader_addline(buffer, "tmp0.x = length(%s);\n", src_param.param_str);
     shader_glsl_append_dst(buffer, ins);
-    shader_addline(buffer, "tmp0.x == 0.0 ? (%s * FLT_MAX) : (%s / tmp0.x));",
-            src_param.param_str, src_param.param_str);
+    if (mask_size > 1)
+    {
+        shader_addline(buffer, "tmp0.x == 0.0 ? vec%u(0.0) : (%s / tmp0.x));\n",
+                mask_size, src_param.param_str);
+    }
+    else
+    {
+        shader_addline(buffer, "tmp0.x == 0.0 ? 0.0 : (%s / tmp0.x));\n",
+                src_param.param_str);
+    }
 }
 
 /** Process the WINED3DSIO_EXPP instruction in GLSL:
@@ -2868,10 +3008,8 @@ static void shader_glsl_tex(const struct wined3d_shader_instruction *ins)
     IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *)shader->baseShader.device;
     DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major,
             ins->ctx->reg_maps->shader_version.minor);
-    const struct wined3d_gl_info *gl_info = ins->ctx->gl_info;
     glsl_sample_function_t sample_function;
     DWORD sample_flags = 0;
-    WINED3DSAMPLER_TEXTURE_TYPE sampler_type;
     DWORD sampler_idx;
     DWORD mask = 0, swizzle;
 
@@ -2879,11 +3017,11 @@ static void shader_glsl_tex(const struct wined3d_shader_instruction *ins)
      * 2.0+: Use provided sampler source. */
     if (shader_version < WINED3D_SHADER_VERSION(2,0)) sampler_idx = ins->dst[0].reg.idx;
     else sampler_idx = ins->src[1].reg.idx;
-    sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx];
 
     if (shader_version < WINED3D_SHADER_VERSION(1,4))
     {
         DWORD flags = deviceImpl->stateBlock->textureState[sampler_idx][WINED3DTSS_TEXTURETRANSFORMFLAGS];
+        WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx];
 
         /* Projected cube textures don't make a lot of sense, the resulting coordinates stay the same. */
         if (flags & WINED3DTTFF_PROJECTED && sampler_type != WINED3DSTT_CUBE) {
@@ -2922,7 +3060,7 @@ static void shader_glsl_tex(const struct wined3d_shader_instruction *ins)
         sample_flags |= WINED3D_GLSL_SAMPLE_RECT;
     }
 
-    shader_glsl_get_sample_function(gl_info, sampler_type, sample_flags, &sample_function);
+    shader_glsl_get_sample_function(ins->ctx, sampler_idx, sample_flags, &sample_function);
     mask |= sample_function.coord_mask;
 
     if (shader_version < WINED3D_SHADER_VERSION(2,0)) swizzle = WINED3DSP_NOSWIZZLE;
@@ -2960,7 +3098,6 @@ static void shader_glsl_texldd(const struct wined3d_shader_instruction *ins)
     glsl_sample_function_t sample_function;
     glsl_src_param_t coord_param, dx_param, dy_param;
     DWORD sample_flags = WINED3D_GLSL_SAMPLE_GRAD;
-    DWORD sampler_type;
     DWORD sampler_idx;
     DWORD swizzle = ins->src[1].swizzle;
 
@@ -2971,13 +3108,12 @@ static void shader_glsl_texldd(const struct wined3d_shader_instruction *ins)
     }
 
     sampler_idx = ins->src[1].reg.idx;
-    sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx];
     if(deviceImpl->stateBlock->textures[sampler_idx] &&
        IWineD3DBaseTexture_GetTextureDimensions(deviceImpl->stateBlock->textures[sampler_idx]) == GL_TEXTURE_RECTANGLE_ARB) {
         sample_flags |= WINED3D_GLSL_SAMPLE_RECT;
     }
 
-    shader_glsl_get_sample_function(gl_info, sampler_type, sample_flags, &sample_function);
+    shader_glsl_get_sample_function(ins->ctx, sampler_idx, sample_flags, &sample_function);
     shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param);
     shader_glsl_add_src_param(ins, &ins->src[2], sample_function.coord_mask, &dx_param);
     shader_glsl_add_src_param(ins, &ins->src[3], sample_function.coord_mask, &dy_param);
@@ -2994,17 +3130,15 @@ static void shader_glsl_texldl(const struct wined3d_shader_instruction *ins)
     glsl_sample_function_t sample_function;
     glsl_src_param_t coord_param, lod_param;
     DWORD sample_flags = WINED3D_GLSL_SAMPLE_LOD;
-    DWORD sampler_type;
     DWORD sampler_idx;
     DWORD swizzle = ins->src[1].swizzle;
 
     sampler_idx = ins->src[1].reg.idx;
-    sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx];
     if(deviceImpl->stateBlock->textures[sampler_idx] &&
        IWineD3DBaseTexture_GetTextureDimensions(deviceImpl->stateBlock->textures[sampler_idx]) == GL_TEXTURE_RECTANGLE_ARB) {
         sample_flags |= WINED3D_GLSL_SAMPLE_RECT;
     }
-    shader_glsl_get_sample_function(gl_info, sampler_type, sample_flags, &sample_function);
+    shader_glsl_get_sample_function(ins->ctx, sampler_idx, sample_flags, &sample_function);
     shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &coord_param);
 
     shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_3, &lod_param);
@@ -3071,12 +3205,10 @@ static void shader_glsl_texcoord(const struct wined3d_shader_instruction *ins)
  * then perform a 1D texture lookup from stage dstregnum, place into dst. */
 static void shader_glsl_texdp3tex(const struct wined3d_shader_instruction *ins)
 {
-    const struct wined3d_gl_info *gl_info = ins->ctx->gl_info;
     glsl_src_param_t src0_param;
     glsl_sample_function_t sample_function;
     DWORD sampler_idx = ins->dst[0].reg.idx;
     DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
-    WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx];
     UINT mask_size;
 
     shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
@@ -3086,7 +3218,7 @@ static void shader_glsl_texdp3tex(const struct wined3d_shader_instruction *ins)
      *
      * It is a dependent read - not valid with conditional NP2 textures
      */
-    shader_glsl_get_sample_function(gl_info, sampler_type, 0, &sample_function);
+    shader_glsl_get_sample_function(ins->ctx, sampler_idx, 0, &sample_function);
     mask_size = shader_glsl_get_write_mask_size(sample_function.coord_mask);
 
     switch(mask_size)
@@ -3199,18 +3331,16 @@ static void shader_glsl_texm3x3pad(const struct wined3d_shader_instruction *ins)
 
 static void shader_glsl_texm3x2tex(const struct wined3d_shader_instruction *ins)
 {
-    const struct wined3d_gl_info *gl_info = ins->ctx->gl_info;
     DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
     DWORD reg = ins->dst[0].reg.idx;
     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
     glsl_src_param_t src0_param;
-    WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ins->ctx->reg_maps->sampler_type[reg];
     glsl_sample_function_t sample_function;
 
     shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
     shader_addline(buffer, "tmp0.y = dot(T%u.xyz, %s);\n", reg, src0_param.param_str);
 
-    shader_glsl_get_sample_function(gl_info, sampler_type, 0, &sample_function);
+    shader_glsl_get_sample_function(ins->ctx, reg, 0, &sample_function);
 
     /* Sample the texture using the calculated coordinates */
     shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, "tmp0.xy");
@@ -3223,17 +3353,15 @@ static void shader_glsl_texm3x3tex(const struct wined3d_shader_instruction *ins)
     DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
     IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader;
     SHADER_PARSE_STATE *current_state = &shader->baseShader.parse_state;
-    const struct wined3d_gl_info *gl_info = ins->ctx->gl_info;
     glsl_src_param_t src0_param;
     DWORD reg = ins->dst[0].reg.idx;
-    WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ins->ctx->reg_maps->sampler_type[reg];
     glsl_sample_function_t sample_function;
 
     shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
     shader_addline(ins->ctx->buffer, "tmp0.z = dot(T%u.xyz, %s);\n", reg, src0_param.param_str);
 
     /* Dependent read, not valid with conditional NP2 */
-    shader_glsl_get_sample_function(gl_info, sampler_type, 0, &sample_function);
+    shader_glsl_get_sample_function(ins->ctx, reg, 0, &sample_function);
 
     /* Sample the texture using the calculated coordinates */
     shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, "tmp0.xyz");
@@ -3266,13 +3394,11 @@ static void shader_glsl_texm3x3(const struct wined3d_shader_instruction *ins)
 static void shader_glsl_texm3x3spec(const struct wined3d_shader_instruction *ins)
 {
     IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader;
-    const struct wined3d_gl_info *gl_info = ins->ctx->gl_info;
     DWORD reg = ins->dst[0].reg.idx;
     glsl_src_param_t src0_param;
     glsl_src_param_t src1_param;
     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
     SHADER_PARSE_STATE* current_state = &shader->baseShader.parse_state;
-    WINED3DSAMPLER_TEXTURE_TYPE stype = ins->ctx->reg_maps->sampler_type[reg];
     DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
     glsl_sample_function_t sample_function;
 
@@ -3285,7 +3411,7 @@ static void shader_glsl_texm3x3spec(const struct wined3d_shader_instruction *ins
     shader_addline(buffer, "tmp0.xyz = -reflect((%s), normalize(tmp0.xyz));\n", src1_param.param_str);
 
     /* Dependent read, not valid with conditional NP2 */
-    shader_glsl_get_sample_function(gl_info, stype, 0, &sample_function);
+    shader_glsl_get_sample_function(ins->ctx, reg, 0, &sample_function);
 
     /* Sample the texture */
     shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, "tmp0.xyz");
@@ -3298,13 +3424,11 @@ static void shader_glsl_texm3x3spec(const struct wined3d_shader_instruction *ins
 static void shader_glsl_texm3x3vspec(const struct wined3d_shader_instruction *ins)
 {
     IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader;
-    const struct wined3d_gl_info *gl_info = ins->ctx->gl_info;
     DWORD reg = ins->dst[0].reg.idx;
     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
     SHADER_PARSE_STATE* current_state = &shader->baseShader.parse_state;
     glsl_src_param_t src0_param;
     DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
-    WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ins->ctx->reg_maps->sampler_type[reg];
     glsl_sample_function_t sample_function;
 
     shader_glsl_add_src_param(ins, &ins->src[0], src_mask, &src0_param);
@@ -3318,7 +3442,7 @@ static void shader_glsl_texm3x3vspec(const struct wined3d_shader_instruction *in
     shader_addline(buffer, "tmp0.xyz = -reflect(tmp1.xyz, normalize(tmp0.xyz));\n");
 
     /* Dependent read, not valid with conditional NP2 */
-    shader_glsl_get_sample_function(gl_info, sampler_type, 0, &sample_function);
+    shader_glsl_get_sample_function(ins->ctx, reg, 0, &sample_function);
 
     /* Sample the texture using the calculated coordinates */
     shader_glsl_gen_sample_code(ins, reg, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL, "tmp0.xyz");
@@ -3334,10 +3458,8 @@ static void shader_glsl_texbem(const struct wined3d_shader_instruction *ins)
 {
     IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader;
     IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *)shader->baseShader.device;
-    const struct wined3d_gl_info *gl_info = ins->ctx->gl_info;
     glsl_sample_function_t sample_function;
     glsl_src_param_t coord_param;
-    WINED3DSAMPLER_TEXTURE_TYPE sampler_type;
     DWORD sampler_idx;
     DWORD mask;
     DWORD flags;
@@ -3346,9 +3468,8 @@ static void shader_glsl_texbem(const struct wined3d_shader_instruction *ins)
     sampler_idx = ins->dst[0].reg.idx;
     flags = deviceImpl->stateBlock->textureState[sampler_idx][WINED3DTSS_TEXTURETRANSFORMFLAGS];
 
-    sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx];
     /* Dependent read, not valid with conditional NP2 */
-    shader_glsl_get_sample_function(gl_info, sampler_type, 0, &sample_function);
+    shader_glsl_get_sample_function(ins->ctx, sampler_idx, 0, &sample_function);
     mask = sample_function.coord_mask;
 
     shader_glsl_write_mask_to_str(mask, coord_mask);
@@ -3407,15 +3528,13 @@ static void shader_glsl_bem(const struct wined3d_shader_instruction *ins)
  * Sample 2D texture at dst using the alpha & red (wx) components of src as texture coordinates */
 static void shader_glsl_texreg2ar(const struct wined3d_shader_instruction *ins)
 {
-    const struct wined3d_gl_info *gl_info = ins->ctx->gl_info;
     glsl_src_param_t src0_param;
     DWORD sampler_idx = ins->dst[0].reg.idx;
-    WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx];
     glsl_sample_function_t sample_function;
 
     shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_ALL, &src0_param);
 
-    shader_glsl_get_sample_function(gl_info, sampler_type, 0, &sample_function);
+    shader_glsl_get_sample_function(ins->ctx, sampler_idx, 0, &sample_function);
     shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL,
             "%s.wx", src0_param.reg_name);
 }
@@ -3424,15 +3543,13 @@ static void shader_glsl_texreg2ar(const struct wined3d_shader_instruction *ins)
  * Sample 2D texture at dst using the green & blue (yz) components of src as texture coordinates */
 static void shader_glsl_texreg2gb(const struct wined3d_shader_instruction *ins)
 {
-    const struct wined3d_gl_info *gl_info = ins->ctx->gl_info;
     glsl_src_param_t src0_param;
     DWORD sampler_idx = ins->dst[0].reg.idx;
-    WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx];
     glsl_sample_function_t sample_function;
 
     shader_glsl_add_src_param(ins, &ins->src[0], WINED3DSP_WRITEMASK_ALL, &src0_param);
 
-    shader_glsl_get_sample_function(gl_info, sampler_type, 0, &sample_function);
+    shader_glsl_get_sample_function(ins->ctx, sampler_idx, 0, &sample_function);
     shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL,
             "%s.yz", src0_param.reg_name);
 }
@@ -3441,14 +3558,12 @@ static void shader_glsl_texreg2gb(const struct wined3d_shader_instruction *ins)
  * Sample texture at dst using the rgb (xyz) components of src as texture coordinates */
 static void shader_glsl_texreg2rgb(const struct wined3d_shader_instruction *ins)
 {
-    const struct wined3d_gl_info *gl_info = ins->ctx->gl_info;
     glsl_src_param_t src0_param;
     DWORD sampler_idx = ins->dst[0].reg.idx;
-    WINED3DSAMPLER_TEXTURE_TYPE sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx];
     glsl_sample_function_t sample_function;
 
     /* Dependent read, not valid with conditional NP2 */
-    shader_glsl_get_sample_function(gl_info, sampler_type, 0, &sample_function);
+    shader_glsl_get_sample_function(ins->ctx, sampler_idx, 0, &sample_function);
     shader_glsl_add_src_param(ins, &ins->src[0], sample_function.coord_mask, &src0_param);
 
     shader_glsl_gen_sample_code(ins, sampler_idx, &sample_function, WINED3DSP_NOSWIZZLE, NULL, NULL, NULL,
@@ -4453,10 +4568,12 @@ static void set_glsl_shader_program(const struct wined3d_context *context,
 }
 
 /* GL locking is done by the caller */
-static GLhandleARB create_glsl_blt_shader(const struct wined3d_gl_info *gl_info, enum tex_types tex_type)
+static GLhandleARB create_glsl_blt_shader(const struct wined3d_gl_info *gl_info, enum tex_types tex_type, BOOL masked)
 {
     GLhandleARB program_id;
     GLhandleARB vshader_id, pshader_id;
+    const char *blt_pshader;
+
     static const char *blt_vshader[] =
     {
         "#version 120\n"
@@ -4468,7 +4585,7 @@ static GLhandleARB create_glsl_blt_shader(const struct wined3d_gl_info *gl_info,
         "}\n"
     };
 
-    static const char *blt_pshaders[tex_type_count] =
+    static const char *blt_pshaders_full[tex_type_count] =
     {
         /* tex_1d */
         NULL,
@@ -4498,7 +4615,44 @@ static GLhandleARB create_glsl_blt_shader(const struct wined3d_gl_info *gl_info,
         "}\n",
     };
 
-    if (!blt_pshaders[tex_type])
+    static const char *blt_pshaders_masked[tex_type_count] =
+    {
+        /* tex_1d */
+        NULL,
+        /* tex_2d */
+        "#version 120\n"
+        "uniform sampler2D sampler;\n"
+        "uniform vec4 mask;\n"
+        "void main(void)\n"
+        "{\n"
+        "    if (all(lessThan(gl_FragCoord.xy, mask.zw))) discard;\n"
+        "    gl_FragDepth = texture2D(sampler, gl_TexCoord[0].xy).x;\n"
+        "}\n",
+        /* tex_3d */
+        NULL,
+        /* tex_cube */
+        "#version 120\n"
+        "uniform samplerCube sampler;\n"
+        "uniform vec4 mask;\n"
+        "void main(void)\n"
+        "{\n"
+        "    if (all(lessThan(gl_FragCoord.xy, mask.zw))) discard;\n"
+        "    gl_FragDepth = textureCube(sampler, gl_TexCoord[0].xyz).x;\n"
+        "}\n",
+        /* tex_rect */
+        "#version 120\n"
+        "#extension GL_ARB_texture_rectangle : enable\n"
+        "uniform sampler2DRect sampler;\n"
+        "uniform vec4 mask;\n"
+        "void main(void)\n"
+        "{\n"
+        "    if (all(lessThan(gl_FragCoord.xy, mask.zw))) discard;\n"
+        "    gl_FragDepth = texture2DRect(sampler, gl_TexCoord[0].xy).x;\n"
+        "}\n",
+    };
+
+    blt_pshader = masked ? blt_pshaders_masked[tex_type] : blt_pshaders_full[tex_type];
+    if (!blt_pshader)
     {
         FIXME("tex_type %#x not supported\n", tex_type);
         tex_type = tex_2d;
@@ -4509,7 +4663,7 @@ static GLhandleARB create_glsl_blt_shader(const struct wined3d_gl_info *gl_info,
     GL_EXTCALL(glCompileShaderARB(vshader_id));
 
     pshader_id = GL_EXTCALL(glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB));
-    GL_EXTCALL(glShaderSourceARB(pshader_id, 1, &blt_pshaders[tex_type], NULL));
+    GL_EXTCALL(glShaderSourceARB(pshader_id, 1, &blt_pshader, NULL));
     GL_EXTCALL(glCompileShaderARB(pshader_id));
 
     program_id = GL_EXTCALL(glCreateProgramObjectARB());
@@ -4530,8 +4684,8 @@ static GLhandleARB create_glsl_blt_shader(const struct wined3d_gl_info *gl_info,
 /* GL locking is done by the caller */
 static void shader_glsl_select(const struct wined3d_context *context, BOOL usePS, BOOL useVS)
 {
-    IWineD3DDeviceImpl *device = ((IWineD3DSurfaceImpl *)context->surface)->resource.device;
     const struct wined3d_gl_info *gl_info = context->gl_info;
+    IWineD3DDeviceImpl *device = context->swapchain->device;
     struct shader_glsl_priv *priv = device->shader_priv;
     GLhandleARB program_id = 0;
     GLenum old_vertex_color_clamp, current_vertex_color_clamp;
@@ -4571,21 +4725,34 @@ static void shader_glsl_select(const struct wined3d_context *context, BOOL usePS
 }
 
 /* GL locking is done by the caller */
-static void shader_glsl_select_depth_blt(IWineD3DDevice *iface, enum tex_types tex_type) {
+static void shader_glsl_select_depth_blt(IWineD3DDevice *iface,
+        enum tex_types tex_type, const SIZE *ds_mask_size)
+{
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
     const struct wined3d_gl_info *gl_info = &This->adapter->gl_info;
+    BOOL masked = ds_mask_size->cx && ds_mask_size->cy;
     struct shader_glsl_priv *priv = This->shader_priv;
-    GLhandleARB *blt_program = &priv->depth_blt_program[tex_type];
+    GLhandleARB *blt_program;
+    GLint loc;
 
-    if (!*blt_program) {
-        GLint loc;
-        *blt_program = create_glsl_blt_shader(gl_info, tex_type);
+    blt_program = masked ? &priv->depth_blt_program_masked[tex_type] : &priv->depth_blt_program_full[tex_type];
+    if (!*blt_program)
+    {
+        *blt_program = create_glsl_blt_shader(gl_info, tex_type, masked);
         loc = GL_EXTCALL(glGetUniformLocationARB(*blt_program, "sampler"));
         GL_EXTCALL(glUseProgramObjectARB(*blt_program));
         GL_EXTCALL(glUniform1iARB(loc, 0));
-    } else {
+    }
+    else
+    {
         GL_EXTCALL(glUseProgramObjectARB(*blt_program));
     }
+
+    if (masked)
+    {
+        loc = GL_EXTCALL(glGetUniformLocationARB(*blt_program, "mask"));
+        GL_EXTCALL(glUniform4fARB(loc, 0.0f, 0.0f, (float)ds_mask_size->cx, (float)ds_mask_size->cy));
+    }
 }
 
 /* GL locking is done by the caller */
@@ -4625,7 +4792,7 @@ static void shader_glsl_destroy(IWineD3DBaseShader *iface) {
             return;
         }
 
-        context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD);
+        context = context_acquire(device, NULL);
         gl_info = context->gl_info;
 
         if (priv->glsl_program && (IWineD3DBaseShader *)priv->glsl_program->pshader == iface)
@@ -4644,7 +4811,7 @@ static void shader_glsl_destroy(IWineD3DBaseShader *iface) {
             return;
         }
 
-        context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD);
+        context = context_acquire(device, NULL);
         gl_info = context->gl_info;
 
         if (priv->glsl_program && (IWineD3DBaseShader *)priv->glsl_program->vshader == iface)
@@ -4821,9 +4988,13 @@ static void shader_glsl_free(IWineD3DDevice *iface) {
     ENTER_GL();
     for (i = 0; i < tex_type_count; ++i)
     {
-        if (priv->depth_blt_program[i])
+        if (priv->depth_blt_program_full[i])
+        {
+            GL_EXTCALL(glDeleteObjectARB(priv->depth_blt_program_full[i]));
+        }
+        if (priv->depth_blt_program_masked[i])
         {
-            GL_EXTCALL(glDeleteObjectARB(priv->depth_blt_program[i]));
+            GL_EXTCALL(glDeleteObjectARB(priv->depth_blt_program_masked[i]));
         }
     }
     LEAVE_GL();