diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index d6ca4a87739..4a08f7013c3 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -1723,10 +1723,14 @@ static void shader_arb_cleanup(IWineD3DDevice *iface) { if (GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) glDisable(GL_FRAGMENT_PROGRAM_ARB); } +static void shader_arb_destroy(IWineD3DBaseShader *iface) { +} + const shader_backend_t arb_program_shader_backend = { &shader_arb_select, &shader_arb_select_depth_blt, &shader_arb_load_constants, &shader_arb_cleanup, - &shader_arb_color_correction + &shader_arb_color_correction, + &shader_arb_destroy }; diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c index 35d8d325935..638db902f08 100644 --- a/dlls/wined3d/baseshader.c +++ b/dlls/wined3d/baseshader.c @@ -1080,12 +1080,16 @@ static void shader_none_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) {} static void shader_none_select_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) {} +static void shader_none_destroy(IWineD3DBaseShader *iface) {} const shader_backend_t none_shader_backend = { &shader_none_select, &shader_none_select_depth_blt, &shader_none_load_constants, - &shader_none_cleanup + &shader_none_cleanup, + &shader_none_color_correction, + &shader_none_destroy }; /* ******************************************* @@ -1115,14 +1119,17 @@ ULONG WINAPI IWineD3DBaseShaderImpl_AddRef(IWineD3DBaseShader *iface) { ULONG WINAPI IWineD3DBaseShaderImpl_Release(IWineD3DBaseShader *iface) { IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)iface; + IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *) This->baseShader.device; ULONG ref; TRACE("(%p) : Releasing from %d\n", This, This->baseShader.ref); ref = InterlockedDecrement(&This->baseShader.ref); if (ref == 0) { + deviceImpl->shader_backend->shader_destroy(iface); HeapFree(GetProcessHeap(), 0, This->baseShader.function); shader_delete_constant_list(&This->baseShader.constantsF); shader_delete_constant_list(&This->baseShader.constantsB); shader_delete_constant_list(&This->baseShader.constantsI); + HeapFree(GetProcessHeap(), 0, This); } return ref; } diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 5d988e40b4b..1cc3ec8274f 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -3176,10 +3176,44 @@ static void shader_glsl_cleanup(IWineD3DDevice *iface) { GL_EXTCALL(glUseProgramObjectARB(0)); } +static void shader_glsl_destroy(IWineD3DBaseShader *iface) { + struct list *linked_programs; + IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *) iface; + WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *) This->baseShader.device)->adapter->gl_info; + + /* Note: Do not use QueryInterface here to find out which shader type this is because this code + * can be called from IWineD3DBaseShader::Release + */ + char pshader = shader_is_pshader_version(This->baseShader.hex_version); + + if(This->baseShader.prgId == 0) return; + linked_programs = &This->baseShader.linked_programs; + + TRACE("Deleting linked programs\n"); + if (linked_programs->next) { + struct glsl_shader_prog_link *entry, *entry2; + + if(pshader) { + LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs, struct glsl_shader_prog_link, pshader_entry) { + delete_glsl_program_entry(This->baseShader.device, entry); + } + } else { + LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs, struct glsl_shader_prog_link, vshader_entry) { + delete_glsl_program_entry(This->baseShader.device, entry); + } + } + } + + TRACE("Deleting shader object %u\n", This->baseShader.prgId); + GL_EXTCALL(glDeleteObjectARB(This->baseShader.prgId)); + checkGLcall("glDeleteObjectARB"); +} + const shader_backend_t glsl_shader_backend = { &shader_glsl_select, &shader_glsl_select_depth_blt, &shader_glsl_load_constants, &shader_glsl_cleanup, - &shader_glsl_color_correction + &shader_glsl_color_correction, + &shader_glsl_destroy }; diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c index 5654c46c07d..b9fbd75482d 100644 --- a/dlls/wined3d/pixelshader.c +++ b/dlls/wined3d/pixelshader.c @@ -51,35 +51,8 @@ static ULONG WINAPI IWineD3DPixelShaderImpl_AddRef(IWineD3DPixelShader *iface) return IWineD3DBaseShaderImpl_AddRef((IWineD3DBaseShader *) iface); } -static void destroy_glsl_pshader(IWineD3DPixelShaderImpl *This) { - struct list *linked_programs = &This->baseShader.linked_programs; - - TRACE("Deleting linked programs\n"); - if (linked_programs->next) { - struct glsl_shader_prog_link *entry, *entry2; - LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs, struct glsl_shader_prog_link, pshader_entry) { - delete_glsl_program_entry(This->baseShader.device, entry); - } - } - - TRACE("Deleting shader object %u\n", This->baseShader.prgId); - GL_EXTCALL(glDeleteObjectARB(This->baseShader.prgId)); - checkGLcall("glDeleteObjectARB"); -} - static ULONG WINAPI IWineD3DPixelShaderImpl_Release(IWineD3DPixelShader *iface) { - IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface; - ULONG ref; - ref = IWineD3DBaseShaderImpl_Release((IWineD3DBaseShader *) iface); - - if(ref == 0) { - if (This->baseShader.shader_mode == SHADER_GLSL && This->baseShader.prgId != 0) { - destroy_glsl_pshader(This); - } - HeapFree(GetProcessHeap(), 0, This); - } - - return ref; + return IWineD3DBaseShaderImpl_Release((IWineD3DBaseShader *) iface); } /* ******************************************* @@ -658,9 +631,7 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_CompileShader(IWineD3DPixelShader This->baseShader.recompile_count++; } - if (This->baseShader.shader_mode == SHADER_GLSL && This->baseShader.prgId != 0) { - destroy_glsl_pshader(This); - } + deviceImpl->shader_backend->shader_destroy((IWineD3DBaseShader *) iface); } /* We don't need to compile */ diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c index 934fed0b6ed..2b16f0403ca 100644 --- a/dlls/wined3d/vertexshader.c +++ b/dlls/wined3d/vertexshader.c @@ -445,33 +445,8 @@ static ULONG WINAPI IWineD3DVertexShaderImpl_AddRef(IWineD3DVertexShader *iface return IWineD3DBaseShaderImpl_AddRef((IWineD3DBaseShader *) iface); } -static void destroy_glsl_vshader(IWineD3DVertexShaderImpl *This) { - struct list *linked_programs = &This->baseShader.linked_programs; - - TRACE("Deleting linked programs\n"); - if (linked_programs->next) { - struct glsl_shader_prog_link *entry, *entry2; - LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs, struct glsl_shader_prog_link, vshader_entry) { - delete_glsl_program_entry(This->baseShader.device, entry); - } - } - - TRACE("Deleting shader object %u\n", This->baseShader.prgId); - GL_EXTCALL(glDeleteObjectARB(This->baseShader.prgId)); - checkGLcall("glDeleteObjectARB"); -} static ULONG WINAPI IWineD3DVertexShaderImpl_Release(IWineD3DVertexShader *iface) { - IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface; - ULONG ref; - ref = IWineD3DBaseShaderImpl_Release((IWineD3DBaseShader *) iface); - - if (ref == 0) { - if (This->baseShader.shader_mode == SHADER_GLSL && This->baseShader.prgId != 0) { - destroy_glsl_vshader(This); - } - HeapFree(GetProcessHeap(), 0, This); - } - return ref; + return IWineD3DBaseShaderImpl_Release((IWineD3DBaseShader *) iface); } /* ******************************************* diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index c77d2af6a74..5c6d7e9b83f 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -211,6 +211,7 @@ typedef struct { void (*shader_load_constants)(IWineD3DDevice *iface, char usePS, char useVS); void (*shader_cleanup)(IWineD3DDevice *iface); void (*shader_color_correction)(struct SHADER_OPCODE_ARG *arg); + void (*shader_destroy)(IWineD3DBaseShader *iface); } shader_backend_t; extern const shader_backend_t glsl_shader_backend;