wined3d: Manage ps_compiled_shader in the backends.
diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index ac03105..2c38ab3 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -98,6 +98,16 @@
     const struct ps_compile_args    *cur_ps_args;
 };
 
+struct arb_ps_compiled_shader {
+    struct ps_compile_args          args;
+    GLuint                          prgId;
+};
+
+struct arb_pshader_private {
+    struct arb_ps_compiled_shader   *gl_shaders;
+    UINT                            num_gl_shaders, shader_array_size;
+};
+
 /********************************************************
  * ARB_[vertex/fragment]_program helper functions follow
  ********************************************************/
@@ -2204,28 +2214,35 @@
 {
     UINT i;
     DWORD new_size;
-    struct ps_compiled_shader *new_array;
+    struct arb_ps_compiled_shader *new_array;
     SHADER_BUFFER buffer;
+    struct arb_pshader_private *shader_data;
+    GLuint ret;
+
+    if(!shader->backend_priv) {
+        shader->backend_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct arb_pshader_private));
+    }
+    shader_data = shader->backend_priv;
 
     /* 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;
+    for(i = 0; i < shader_data->num_gl_shaders; i++) {
+        if(memcmp(&shader_data->gl_shaders[i].args, args, sizeof(*args)) == 0) {
+            return shader_data->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)
+    if(shader_data->shader_array_size == shader_data->num_gl_shaders) {
+        if (shader_data->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));
+            new_size = shader_data->shader_array_size + max(1, shader_data->shader_array_size / 2);
+            new_array = HeapReAlloc(GetProcessHeap(), 0, shader_data->gl_shaders,
+                                    new_size * sizeof(*shader_data->gl_shaders));
         } else {
-            new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*shader->gl_shaders));
+            new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*shader_data->gl_shaders));
             new_size = 1;
         }
 
@@ -2233,21 +2250,21 @@
             ERR("Out of memory\n");
             return 0;
         }
-        shader->gl_shaders = new_array;
-        shader->shader_array_size = new_size;
+        shader_data->gl_shaders = new_array;
+        shader_data->shader_array_size = new_size;
     }
 
-    shader->gl_shaders[shader->num_gl_shaders].args = *args;
+    shader_data->gl_shaders[shader_data->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(shader, &buffer, args);
+    ret = shader_arb_generate_pshader(shader, &buffer, args);
     shader_buffer_free(&buffer);
+    shader_data->gl_shaders[shader_data->num_gl_shaders++].prgId = ret;
 
-    return shader->gl_shaders[shader->num_gl_shaders++].prgId;
+    return ret;
 }
 
 static inline BOOL vs_args_equal(const struct vs_compile_args *stored, const struct vs_compile_args *new,
@@ -2419,18 +2436,19 @@
     if (shader_is_pshader_version(baseShader->baseShader.reg_maps.shader_version.type))
     {
         IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *) iface;
+        struct arb_pshader_private *shader_data = This->backend_priv;
         UINT i;
 
+        if(!shader_data) return; /* This can happen if a shader was never compiled */
         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))");
+        for(i = 0; i < shader_data->num_gl_shaders; i++) {
+            GL_EXTCALL(glDeleteProgramsARB(1, &shader_data->gl_shaders[i].prgId));
+            checkGLcall("GL_EXTCALL(glDeleteProgramsARB(1, &shader_data->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;
+        HeapFree(GetProcessHeap(), 0, shader_data->gl_shaders);
+        HeapFree(GetProcessHeap(), 0, shader_data);
+        This->backend_priv = NULL;
     } else {
         IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *) iface;
         UINT i;
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 65c71de..597c7d9 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -127,6 +127,18 @@
     const struct ps_compile_args    *cur_ps_args;
 };
 
+struct glsl_ps_compiled_shader
+{
+    struct ps_compile_args          args;
+    GLhandleARB                     prgId;
+};
+
+struct glsl_pshader_private
+{
+    struct glsl_ps_compiled_shader  *gl_shaders;
+    UINT                            num_gl_shaders, shader_array_size;
+};
+
 /* Extract a line from the info log.
  * Note that this modifies the source string. */
 static char *get_info_log_line(char **ptr)
@@ -3789,28 +3801,35 @@
 {
     UINT i;
     DWORD new_size;
-    struct ps_compiled_shader *new_array;
+    struct glsl_ps_compiled_shader *new_array;
     SHADER_BUFFER buffer;
+    struct glsl_pshader_private *shader_data;
+    GLhandleARB ret;
+
+    if(!shader->backend_priv) {
+        shader->backend_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct glsl_pshader_private));
+    }
+    shader_data = shader->backend_priv;
 
     /* 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;
+    for(i = 0; i < shader_data->num_gl_shaders; i++) {
+        if(memcmp(&shader_data->gl_shaders[i].args, args, sizeof(*args)) == 0) {
+            return shader_data->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)
+    if(shader_data->shader_array_size == shader_data->num_gl_shaders) {
+        if (shader_data->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));
+            new_size = shader_data->shader_array_size + max(1, shader_data->shader_array_size / 2);
+            new_array = HeapReAlloc(GetProcessHeap(), 0, shader_data->gl_shaders,
+                                    new_size * sizeof(*shader_data->gl_shaders));
         } else {
-            new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*shader->gl_shaders));
+            new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*shader_data->gl_shaders));
             new_size = 1;
         }
 
@@ -3818,20 +3837,21 @@
             ERR("Out of memory\n");
             return 0;
         }
-        shader->gl_shaders = new_array;
-        shader->shader_array_size = new_size;
+        shader_data->gl_shaders = new_array;
+        shader_data->shader_array_size = new_size;
     }
 
-    shader->gl_shaders[shader->num_gl_shaders].args = *args;
+    shader_data->gl_shaders[shader_data->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_glsl_generate_pshader(shader, &buffer, args);
-    shader_buffer_free(&buffer);
 
-    return shader->gl_shaders[shader->num_gl_shaders++].prgId;
+    shader_buffer_init(&buffer);
+    ret = shader_glsl_generate_pshader(shader, &buffer, args);
+    shader_buffer_free(&buffer);
+    shader_data->gl_shaders[shader_data->num_gl_shaders++].prgId = ret;
+
+    return ret;
 }
 
 static inline BOOL vs_args_equal(const struct vs_compile_args *stored, const struct vs_compile_args *new,
@@ -4258,8 +4278,16 @@
     char pshader = shader_is_pshader_version(This->baseShader.reg_maps.shader_version.type);
 
     if(pshader) {
+        struct glsl_pshader_private *shader_data;
         ps = (IWineD3DPixelShaderImpl *) This;
-        if(ps->num_gl_shaders == 0) return;
+        shader_data = ps->backend_priv;
+        if(!shader_data || shader_data->num_gl_shaders == 0)
+        {
+            HeapFree(GetProcessHeap(), 0, shader_data);
+            ps->backend_priv = NULL;
+            return;
+        }
+
         if (priv->glsl_program && (IWineD3DBaseShader *)priv->glsl_program->pshader == iface)
         {
             ENTER_GL();
@@ -4298,18 +4326,18 @@
 
     if(pshader) {
         UINT i;
+        struct glsl_pshader_private *shader_data = ps->backend_priv;
 
         ENTER_GL();
-        for(i = 0; i < ps->num_gl_shaders; i++) {
-            TRACE("deleting pshader %u\n", ps->gl_shaders[i].prgId);
-            GL_EXTCALL(glDeleteObjectARB(ps->gl_shaders[i].prgId));
+        for(i = 0; i < shader_data->num_gl_shaders; i++) {
+            TRACE("deleting pshader %u\n", shader_data->gl_shaders[i].prgId);
+            GL_EXTCALL(glDeleteObjectARB(shader_data->gl_shaders[i].prgId));
             checkGLcall("glDeleteObjectARB");
         }
         LEAVE_GL();
-        HeapFree(GetProcessHeap(), 0, ps->gl_shaders);
-        ps->gl_shaders = NULL;
-        ps->num_gl_shaders = 0;
-        ps->shader_array_size = 0;
+        HeapFree(GetProcessHeap(), 0, shader_data->gl_shaders);
+        HeapFree(GetProcessHeap(), 0, shader_data);
+        ps->backend_priv = NULL;
     } else {
         UINT i;
 
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index ec18a06..fe48f9f 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2691,11 +2691,6 @@
 /*****************************************************************************
  * IDirect3DPixelShader implementation structure
  */
-struct ps_compiled_shader {
-    struct ps_compile_args      args;
-    GLuint                      prgId;
-};
-
 typedef struct IWineD3DPixelShaderImpl {
     /* IUnknown parts */
     const IWineD3DPixelShaderVtbl *lpVtbl;
@@ -2713,8 +2708,7 @@
     int                         declared_in_count;
 
     /* The GL shader */
-    struct ps_compiled_shader   *gl_shaders;
-    UINT                        num_gl_shaders, shader_array_size;
+    void                        *backend_priv;
 
     /* Some information about the shader behavior */
     struct stb_const_desc       bumpenvmatconst[MAX_TEXTURES];