From eeb54b992253b28430c1b902f575c7a09d4cab71 Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Wed, 28 Oct 2009 11:00:11 +0100 Subject: [PATCH] wined3d: Keep better track of where we're using wined3d contexts. The idea here is that we can restore the thread's current GL context on context_release() if it doesn't correspond to the current wined3d context on context_acquire(). --- dlls/wined3d/arb_program_shader.c | 38 +++++++---- dlls/wined3d/basetexture.c | 15 ++-- dlls/wined3d/buffer.c | 34 ++++++++-- dlls/wined3d/context.c | 26 +++++-- dlls/wined3d/cubetexture.c | 7 +- dlls/wined3d/device.c | 69 +++++++++++++------ dlls/wined3d/drawprim.c | 14 ++-- dlls/wined3d/glsl_shader.c | 8 ++- dlls/wined3d/query.c | 33 ++++++--- dlls/wined3d/surface.c | 139 ++++++++++++++++++++++++++++---------- dlls/wined3d/swapchain.c | 6 +- dlls/wined3d/texture.c | 7 +- dlls/wined3d/volumetexture.c | 8 +-- dlls/wined3d/wined3d_private.h | 6 +- 14 files changed, 298 insertions(+), 112 deletions(-) diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index abbdf4177f7..ec2b0056a71 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -4427,15 +4427,22 @@ static void shader_arb_destroy(IWineD3DBaseShader *iface) { UINT i; if(!shader_data) return; /* This can happen if a shader was never compiled */ - ENTER_GL(); - if(shader_data->num_gl_shaders) ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); + if (shader_data->num_gl_shaders) + { + struct wined3d_context *context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); + + ENTER_GL(); + 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(); - 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))"); + context_release(context); } - LEAVE_GL(); + HeapFree(GetProcessHeap(), 0, shader_data->gl_shaders); HeapFree(GetProcessHeap(), 0, shader_data); This->baseShader.backend_data = NULL; @@ -4445,15 +4452,22 @@ static void shader_arb_destroy(IWineD3DBaseShader *iface) { UINT i; if(!shader_data) return; /* This can happen if a shader was never compiled */ - ENTER_GL(); - if(shader_data->num_gl_shaders) ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); + if (shader_data->num_gl_shaders) + { + struct wined3d_context *context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); + + ENTER_GL(); + 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(); - 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))"); + context_release(context); } - LEAVE_GL(); + HeapFree(GetProcessHeap(), 0, shader_data->gl_shaders); HeapFree(GetProcessHeap(), 0, shader_data); This->baseShader.backend_data = NULL; diff --git a/dlls/wined3d/basetexture.c b/dlls/wined3d/basetexture.c index be885067313..dd2a82e453e 100644 --- a/dlls/wined3d/basetexture.c +++ b/dlls/wined3d/basetexture.c @@ -83,10 +83,11 @@ void basetexture_unload(IWineD3DBaseTexture *iface) { IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface; IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + struct wined3d_context *context = NULL; - if(This->baseTexture.texture_rgb.name || - This->baseTexture.texture_srgb.name) { - ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); + if (This->baseTexture.texture_rgb.name || This->baseTexture.texture_srgb.name) + { + context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); } if(This->baseTexture.texture_rgb.name) { @@ -95,6 +96,9 @@ void basetexture_unload(IWineD3DBaseTexture *iface) if(This->baseTexture.texture_srgb.name) { gltexture_delete(&This->baseTexture.texture_srgb); } + + if (context) context_release(context); + This->baseTexture.texture_rgb.dirty = TRUE; This->baseTexture.texture_srgb.dirty = TRUE; } @@ -161,7 +165,8 @@ HRESULT basetexture_set_autogen_filter_type(IWineD3DBaseTexture *iface, WINED3DT * Or should we delay the applying until the texture is used for drawing? For now, apply * immediately. */ - ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); + struct wined3d_context *context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); + ENTER_GL(); glBindTexture(textureDimensions, This->baseTexture.texture_rgb.name); checkGLcall("glBindTexture"); @@ -183,6 +188,8 @@ HRESULT basetexture_set_autogen_filter_type(IWineD3DBaseTexture *iface, WINED3DT checkGLcall("glTexParameteri(textureDimensions, GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST)"); } LEAVE_GL(); + + context_release(context); } This->baseTexture.filterType = FilterType; TRACE("(%p) :\n", This); diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c index c82fe178896..d2548c6f38d 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c @@ -605,8 +605,9 @@ static void STDMETHODCALLTYPE buffer_UnLoad(IWineD3DBuffer *iface) if (This->buffer_object) { IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + struct wined3d_context *context; - ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); /* Download the buffer, but don't permanently enable double buffering */ if(!(This->flags & WINED3D_BUFFER_DOUBLEBUFFER)) @@ -621,6 +622,8 @@ static void STDMETHODCALLTYPE buffer_UnLoad(IWineD3DBuffer *iface) LEAVE_GL(); This->buffer_object = 0; This->flags |= WINED3D_BUFFER_CREATEBO; /* Recreate the buffer object next load */ + + context_release(context); } } @@ -688,13 +691,14 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface) struct wined3d_buffer *This = (struct wined3d_buffer *)iface; IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; UINT start = 0, end = 0, vertices; + struct wined3d_context *context; BOOL decl_changed = FALSE; unsigned int i, j; BYTE *data; TRACE("iface %p\n", iface); - ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); if (!This->buffer_object) { @@ -706,6 +710,7 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface) } else { + context_release(context); return; /* Not doing any conversion */ } } @@ -717,7 +722,11 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface) This->flags |= WINED3D_BUFFER_HASDESC; } - if (!decl_changed && !(This->flags & WINED3D_BUFFER_HASDESC && This->flags & WINED3D_BUFFER_DIRTY)) return; + if (!decl_changed && !(This->flags & WINED3D_BUFFER_HASDESC && This->flags & WINED3D_BUFFER_DIRTY)) + { + context_release(context); + return; + } /* If applications change the declaration over and over, reconverting all the time is a huge * performance hit. So count the declaration changes and release the VBO if there are too many @@ -745,7 +754,7 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface) * rarely */ IWineD3DDeviceImpl_MarkStateDirty(device, STATE_STREAMSRC); - + context_release(context); return; } buffer_check_buffer_object_size(This); @@ -800,7 +809,11 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface) TRACE("No conversion needed\n"); /* Nothing to do because we locked directly into the vbo */ - if(!(This->flags & WINED3D_BUFFER_DOUBLEBUFFER)) return; + if (!(This->flags & WINED3D_BUFFER_DOUBLEBUFFER)) + { + context_release(context); + return; + } ENTER_GL(); GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object)); @@ -808,6 +821,8 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface) GL_EXTCALL(glBufferSubDataARB(This->buffer_type_hint, start, end-start, This->resource.allocatedMemory + start)); checkGLcall("glBufferSubDataARB"); LEAVE_GL(); + + context_release(context); return; } @@ -901,6 +916,7 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface) } HeapFree(GetProcessHeap(), 0, data); + context_release(context); } static WINED3DRESOURCETYPE STDMETHODCALLTYPE buffer_GetType(IWineD3DBuffer *iface) @@ -944,17 +960,19 @@ static HRESULT STDMETHODCALLTYPE buffer_Map(IWineD3DBuffer *iface, UINT offset, if(count == 1) { IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + struct wined3d_context *context; if(This->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB) { IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_INDEXBUFFER); } - ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); ENTER_GL(); GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object)); This->resource.allocatedMemory = GL_EXTCALL(glMapBufferARB(This->buffer_type_hint, GL_READ_WRITE_ARB)); LEAVE_GL(); + context_release(context); } } else @@ -996,17 +1014,19 @@ static HRESULT STDMETHODCALLTYPE buffer_Unmap(IWineD3DBuffer *iface) if(!(This->flags & WINED3D_BUFFER_DOUBLEBUFFER) && This->buffer_object) { IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + struct wined3d_context *context; if(This->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB) { IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_INDEXBUFFER); } - ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); ENTER_GL(); GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object)); GL_EXTCALL(glUnmapBufferARB(This->buffer_type_hint)); LEAVE_GL(); + context_release(context); This->resource.allocatedMemory = NULL; } diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index 30377b890fb..9865f9f2261 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -831,6 +831,21 @@ BOOL context_set_current(struct wined3d_context *ctx) return TlsSetValue(wined3d_context_tls_idx, ctx); } +void context_release(struct wined3d_context *context) +{ + TRACE("Releasing context %p, level %u.\n", context, context->level); + + if (WARN_ON(d3d)) + { + if (!context->level) + WARN("Context %p is not active.\n", context); + else if (context != context_get_current()) + WARN("Context %p is not the current context.\n", context); + } + + --context->level; +} + /***************************************************************************** * Context_MarkStateDirty * @@ -1954,14 +1969,14 @@ retry: BOOL oldInDraw = This->isInDraw; /* surface_internal_preload() requires a context to load the - * texture, so it will call ActivateContext. Set isInDraw to true + * texture, so it will call context_acquire(). Set isInDraw to true * to signal surface_internal_preload() that it has a context. */ /* FIXME: This is just broken. There's no guarantee whatsoever * that the currently active context, if any, is appropriate for * reading back the render target. We should probably call * context_set_current(context) here and then rely on - * ActivateContext() doing the right thing. */ + * context_acquire() doing the right thing. */ This->isInDraw = TRUE; /* Read the back buffer of the old drawable into the destination texture. */ @@ -2035,7 +2050,7 @@ static void context_apply_draw_buffer(struct wined3d_context *context, BOOL blit } /***************************************************************************** - * ActivateContext + * context_acquire * * Finds a rendering context and drawable matching the device and render * target for the current thread, activates them and puts them into the @@ -2047,7 +2062,7 @@ static void context_apply_draw_buffer(struct wined3d_context *context, BOOL blit * usage: Prepares the context for blitting, drawing or other actions * *****************************************************************************/ -struct wined3d_context *ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, enum ContextUsage usage) +struct wined3d_context *context_acquire(IWineD3DDeviceImpl *This, IWineD3DSurface *target, enum ContextUsage usage) { struct wined3d_context *current_context = context_get_current(); DWORD tid = GetCurrentThreadId(); @@ -2060,6 +2075,9 @@ struct wined3d_context *ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurfac TRACE("(%p): Selecting context for render target %p, thread %d\n", This, target, tid); context = FindContext(This, target, tid); + ++context->level; + TRACE("Found context %p, level %u.\n", context, context->level); + if (!context->valid) return context; gl_info = context->gl_info; diff --git a/dlls/wined3d/cubetexture.c b/dlls/wined3d/cubetexture.c index 6e314cbb9e1..ade200f9de7 100644 --- a/dlls/wined3d/cubetexture.c +++ b/dlls/wined3d/cubetexture.c @@ -34,6 +34,7 @@ static void cubetexture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3 /* Override the IWineD3DResource Preload method. */ IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface; IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + struct wined3d_context *context = NULL; unsigned int i, j; BOOL srgb_mode; BOOL *dirty; @@ -65,9 +66,9 @@ static void cubetexture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3 * activated at the beginning of drawPrimitive. */ if (!device->isInDraw) { - /* No danger of recursive calls, ActivateContext sets isInDraw to true + /* No danger of recursive calls, context_acquire() sets isInDraw to true * when loading offscreen render targets into their texture. */ - ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); } if (This->resource.format_desc->format == WINED3DFMT_P8_UINT @@ -109,6 +110,8 @@ static void cubetexture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3 /* No longer dirty. */ *dirty = FALSE; + + if (context) context_release(context); } static void cubetexture_cleanup(IWineD3DCubeTextureImpl *This) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index d7c251aa116..185d6cb4610 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -1960,8 +1960,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; - const struct wined3d_context *context; const struct wined3d_gl_info *gl_info; + struct wined3d_context *context; int sampler; UINT i; TRACE("(%p)\n", This); @@ -1971,7 +1971,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, /* I don't think that the interface guarantees that the device is destroyed from the same thread * it was created. Thus make sure a context is active for the glDelete* calls */ - context = ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(This, NULL, CTXUSAGE_RESOURCELOAD); gl_info = context->gl_info; if(This->logo_surface) IWineD3DSurface_Release(This->logo_surface); @@ -2080,6 +2080,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, This->auto_depth_stencil_buffer = NULL; } + context_release(context); + for(i=0; i < This->NumberOfSwapChains; i++) { TRACE("Releasing the implicit swapchain %d\n", i); if (D3DCB_DestroySwapChain(This->swapchains[i]) > 0) { @@ -4065,7 +4067,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; struct wined3d_stream_info stream_info; + struct wined3d_context *context; BOOL vbo = FALSE, streamWasUP = This->stateBlock->streamIsUP; + HRESULT hr; + TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags); if(pVertexDecl) { @@ -4073,7 +4078,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, } /* Need any context to write to the vbo. */ - ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(This, NULL, CTXUSAGE_RESOURCELOAD); /* ProcessVertices reads from vertex buffers, which have to be assigned. DrawPrimitive and DrawPrimitiveUP * control the streamIsUP flag, thus restore it afterwards. @@ -4110,8 +4115,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, } } - return process_vertices_strided(This, DestIndex, VertexCount, &stream_info, + hr = process_vertices_strided(This, DestIndex, VertexCount, &stream_info, (struct wined3d_buffer *)pDestBuffer, Flags, DestFVF); + + context_release(context); + + return hr; } /***** @@ -4457,8 +4466,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) { return WINED3D_OK; } -static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) { +static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) +{ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + struct wined3d_context *context; + TRACE("(%p)\n", This); if(!This->inScene) { @@ -4466,12 +4478,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) { return WINED3DERR_INVALIDCALL; } - ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(This, NULL, CTXUSAGE_RESOURCELOAD); /* We only have to do this if we need to read the, swapbuffers performs a flush for us */ wglFlush(); /* No checkGLcall here to avoid locking the lock just for checking a call that hardly ever - * fails - */ + * fails. */ + context_release(context); This->inScene = FALSE; return WINED3D_OK; @@ -4546,7 +4558,7 @@ HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This, IWineD3DSurfa } } - context = ActivateContext(This, (IWineD3DSurface *)target, CTXUSAGE_CLEAR); + context = context_acquire(This, (IWineD3DSurface *)target, CTXUSAGE_CLEAR); target->get_drawable_size(context, &drawable_width, &drawable_height); @@ -4686,6 +4698,8 @@ HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This, IWineD3DSurfa IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain); } + context_release(context); + return WINED3D_OK; } @@ -5346,6 +5360,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, DWORD sampler; int bpp; CONVERT_TYPES convert = NO_CONVERSION; + struct wined3d_context *context; WINED3DSURFACE_DESC winedesc; @@ -5389,7 +5404,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc); } - ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(This, NULL, CTXUSAGE_RESOURCELOAD); ENTER_GL(); GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB)); @@ -5480,6 +5495,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, checkGLcall("glTexSubImage2D"); LEAVE_GL(); + context_release(context); IWineD3DSurface_ModifyLocation(pDestinationSurface, SFLAG_INTEXTURE, TRUE); sampler = This->rev_tex_unit_map[0]; @@ -5635,7 +5651,7 @@ static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurface *surface, TRACE("Surface %p is onscreen\n", surface); - context = ActivateContext(This, surface, CTXUSAGE_RESOURCELOAD); + context = context_acquire(This, surface, CTXUSAGE_RESOURCELOAD); ENTER_GL(); context_bind_fbo(context, GL_FRAMEBUFFER, NULL); buffer = surface_get_gl_buffer(surface, swapchain); @@ -5644,7 +5660,7 @@ static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurface *surface, } else { TRACE("Surface %p is offscreen\n", surface); - context = ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(This, NULL, CTXUSAGE_RESOURCELOAD); ENTER_GL(); context_bind_fbo(context, GL_FRAMEBUFFER, &context->dst_fbo); context_attach_surface_fbo(context, GL_FRAMEBUFFER, 0, surface); @@ -5683,6 +5699,7 @@ static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurface *surface, } LEAVE_GL(); + context_release(context); } static inline DWORD argb_to_fmt(DWORD color, WINED3DFORMAT destfmt) { @@ -6035,9 +6052,9 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED src_swapchain = get_swapchain(src_surface); dst_swapchain = get_swapchain(dst_surface); - if (src_swapchain) context = ActivateContext(This, src_surface, CTXUSAGE_RESOURCELOAD); - else if (dst_swapchain) context = ActivateContext(This, dst_surface, CTXUSAGE_RESOURCELOAD); - else context = ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD); + if (src_swapchain) context = context_acquire(This, src_surface, CTXUSAGE_RESOURCELOAD); + else if (dst_swapchain) context = context_acquire(This, dst_surface, CTXUSAGE_RESOURCELOAD); + else context = context_acquire(This, NULL, CTXUSAGE_RESOURCELOAD); gl_info = context->gl_info; @@ -6138,6 +6155,8 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, WINED checkGLcall("glDrawBuffer()"); } LEAVE_GL(); + + context_release(context); } static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) { @@ -6220,9 +6239,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice * || ((IWineD3DSurfaceImpl *)This->stencilBufferTarget)->Flags & SFLAG_DISCARD) { surface_modify_ds_location(This->stencilBufferTarget, SFLAG_DS_DISCARDED); } else { - struct wined3d_context *context = ActivateContext(This, This->render_targets[0], CTXUSAGE_RESOURCELOAD); + struct wined3d_context *context = context_acquire(This, This->render_targets[0], CTXUSAGE_RESOURCELOAD); surface_load_ds_location(This->stencilBufferTarget, context, SFLAG_DS_OFFSCREEN); surface_modify_ds_location(This->stencilBufferTarget, SFLAG_DS_OFFSCREEN); + context_release(context); } } @@ -6255,10 +6275,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* i /* some basic validation checks */ if(This->cursorTexture) { - ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD); + struct wined3d_context *context = context_acquire(This, NULL, CTXUSAGE_RESOURCELOAD); ENTER_GL(); glDeleteTextures(1, &This->cursorTexture); LEAVE_GL(); + context_release(context); This->cursorTexture = 0; } @@ -6299,6 +6320,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* i { const struct GlPixelFormatDesc *glDesc = getFormatDescEntry(WINED3DFMT_B8G8R8A8_UNORM, &This->adapter->gl_info); + struct wined3d_context *context; char *mem, *bits = rect.pBits; GLint intfmt = glDesc->glInternal; GLint format = glDesc->glFormat; @@ -6316,7 +6338,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* i memcpy(&mem[width * bpp * i], &bits[rect.Pitch * i], width * bpp); IWineD3DSurface_UnlockRect(pCursorBitmap); - ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(This, NULL, CTXUSAGE_RESOURCELOAD); ENTER_GL(); @@ -6349,6 +6371,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* i } LEAVE_GL(); + + context_release(context); } else { @@ -6516,10 +6540,11 @@ static void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, const WINED3DPRESENT if (surface->texture_name) { - ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD); + struct wined3d_context *context = context_acquire(This, NULL, CTXUSAGE_RESOURCELOAD); ENTER_GL(); glDeleteTextures(1, &surface->texture_name); LEAVE_GL(); + context_release(context); surface->texture_name = 0; surface->Flags &= ~SFLAG_CLIENT; } @@ -6578,12 +6603,12 @@ static BOOL is_display_mode_supported(IWineD3DDeviceImpl *This, const WINED3DPRE void delete_opengl_contexts(IWineD3DDevice *iface, IWineD3DSwapChain *swapchain_iface) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; IWineD3DSwapChainImpl *swapchain = (IWineD3DSwapChainImpl *) swapchain_iface; - const struct wined3d_context *context; const struct wined3d_gl_info *gl_info; + struct wined3d_context *context; UINT i; IWineD3DBaseShaderImpl *shader; - context = ActivateContext(This, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(This, NULL, CTXUSAGE_RESOURCELOAD); gl_info = context->gl_info; IWineD3DDevice_EnumResources(iface, reset_unload_resources, NULL); @@ -6618,6 +6643,8 @@ void delete_opengl_contexts(IWineD3DDevice *iface, IWineD3DSwapChain *swapchain_ } LEAVE_GL(); + context_release(context); + while(This->numContexts) { DestroyContext(This, This->contexts[0]); } diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c index acf89be1885..c6d50b01ce6 100644 --- a/dlls/wined3d/drawprim.c +++ b/dlls/wined3d/drawprim.c @@ -596,10 +596,10 @@ void drawPrimitive(IWineD3DDevice *iface, UINT index_count, UINT StartIdx, UINT /* Signals other modules that a drawing is in progress and the stateblock finalized */ This->isInDraw = TRUE; - context = ActivateContext(This, This->render_targets[0], CTXUSAGE_DRAWPRIM); + context = context_acquire(This, This->render_targets[0], CTXUSAGE_DRAWPRIM); if (This->stencilBufferTarget) { - /* Note that this depends on the ActivateContext call above to set + /* Note that this depends on the context_acquire() call above to set * This->render_offscreen properly. We don't currently take the * Z-compare function into account, but we could skip loading the * depthstencil for D3DCMP_NEVER and D3DCMP_ALWAYS as well. Also note @@ -683,6 +683,8 @@ void drawPrimitive(IWineD3DDevice *iface, UINT index_count, UINT StartIdx, UINT /* Finished updating the screen, restore lock */ LEAVE_GL(); + context_release(context); + TRACE("Done all gl drawing\n"); /* Diagnostics */ @@ -766,7 +768,7 @@ HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This, float max_x = 0.0f, max_y = 0.0f, max_z = 0.0f, neg_z = 0.0f; struct wined3d_stream_info stream_info; struct wined3d_stream_info_element *e; - const struct wined3d_context *context; + struct wined3d_context *context; const BYTE *data; const WINED3DRECTPATCH_INFO *info = &patch->RectPatchInfo; DWORD vtxStride; @@ -776,7 +778,7 @@ HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This, /* Simply activate the context for blitting. This disables all the things we don't want and * takes care of dirtifying. Dirtifying is preferred over pushing / popping, since drawing the * patch (as opposed to normal draws) will most likely need different changes anyway. */ - context = ActivateContext(This, NULL, CTXUSAGE_BLIT); + context = context_acquire(This, NULL, CTXUSAGE_BLIT); /* First, locate the position data. This is provided in a vertex buffer in the stateblock. * Beware of vbos @@ -959,11 +961,13 @@ HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This, LEAVE_GL(); ERR("Feedback failed. Expected %d elements back\n", buffer_size); HeapFree(GetProcessHeap(), 0, feedbuffer); + context_release(context); return WINED3DERR_DRIVERINTERNALERROR; } else if(i != buffer_size) { LEAVE_GL(); ERR("Unexpected amount of elements returned. Expected %d, got %d\n", buffer_size, i); HeapFree(GetProcessHeap(), 0, feedbuffer); + context_release(context); return WINED3DERR_DRIVERINTERNALERROR; } else { TRACE("Got %d elements as expected\n", i); @@ -1078,6 +1082,8 @@ HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This, checkGLcall("glDisable vertex attrib generation"); LEAVE_GL(); + context_release(context); + HeapFree(GetProcessHeap(), 0, feedbuffer); vtxStride = 3 * sizeof(float); diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 74439f43d2b..25e2f610802 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -4374,10 +4374,10 @@ static void shader_glsl_destroy(IWineD3DBaseShader *iface) { IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *) iface; IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)This->baseShader.device; struct shader_glsl_priv *priv = device->shader_priv; - const struct wined3d_context *context; const struct wined3d_gl_info *gl_info; IWineD3DPixelShaderImpl *ps = NULL; IWineD3DVertexShaderImpl *vs = NULL; + struct wined3d_context *context; /* Note: Do not use QueryInterface here to find out which shader type this is because this code * can be called from IWineD3DBaseShader::Release @@ -4395,7 +4395,7 @@ static void shader_glsl_destroy(IWineD3DBaseShader *iface) { return; } - context = ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); gl_info = context->gl_info; if (priv->glsl_program && (IWineD3DBaseShader *)priv->glsl_program->pshader == iface) @@ -4415,7 +4415,7 @@ static void shader_glsl_destroy(IWineD3DBaseShader *iface) { return; } - context = ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); gl_info = context->gl_info; if (priv->glsl_program && (IWineD3DBaseShader *)priv->glsl_program->vshader == iface) @@ -4474,6 +4474,8 @@ static void shader_glsl_destroy(IWineD3DBaseShader *iface) { HeapFree(GetProcessHeap(), 0, shader_data); vs->baseShader.backend_data = NULL; } + + context_release(context); } static int glsl_program_key_compare(const void *key, const struct wine_rb_entry *entry) diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c index 2a2c1b1ecb6..1db6e7a5c91 100644 --- a/dlls/wined3d/query.c +++ b/dlls/wined3d/query.c @@ -3,6 +3,7 @@ * * Copyright 2005 Oliver Stieber * Copyright 2007-2008 Stefan Dösinger for CodeWeavers + * Copyright 2009 Henri Verbeet for CodeWeavers. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -271,6 +272,7 @@ static HRESULT WINAPI IWineD3DQueryImpl_GetData(IWineD3DQuery* iface, void* pDa static HRESULT WINAPI IWineD3DOcclusionQueryImpl_GetData(IWineD3DQuery* iface, void* pData, DWORD dwSize, DWORD dwGetDataFlags) { IWineD3DQueryImpl *This = (IWineD3DQueryImpl *) iface; struct wined3d_occlusion_query *query = This->extendedData; + struct wined3d_context *context; DWORD* data = pData; GLuint available; GLuint samples; @@ -309,7 +311,7 @@ static HRESULT WINAPI IWineD3DOcclusionQueryImpl_GetData(IWineD3DQuery* iface, return S_OK; } - ActivateContext(This->wineD3DDevice, query->context->current_rt, CTXUSAGE_RESOURCELOAD); + context = context_acquire(This->wineD3DDevice, query->context->current_rt, CTXUSAGE_RESOURCELOAD); ENTER_GL(); @@ -335,13 +337,16 @@ static HRESULT WINAPI IWineD3DOcclusionQueryImpl_GetData(IWineD3DQuery* iface, LEAVE_GL(); + context_release(context); + return res; } static HRESULT WINAPI IWineD3DEventQueryImpl_GetData(IWineD3DQuery* iface, void* pData, DWORD dwSize, DWORD dwGetDataFlags) { IWineD3DQueryImpl *This = (IWineD3DQueryImpl *) iface; struct wined3d_event_query *query = This->extendedData; - BOOL* data = pData; + struct wined3d_context *context; + BOOL *data = pData; TRACE("(%p) : type D3DQUERY_EVENT, pData %p, dwSize %#x, dwGetDataFlags %#x\n", This, pData, dwSize, dwGetDataFlags); @@ -364,7 +369,7 @@ static HRESULT WINAPI IWineD3DEventQueryImpl_GetData(IWineD3DQuery* iface, void return S_OK; } - ActivateContext(This->wineD3DDevice, query->context->current_rt, CTXUSAGE_RESOURCELOAD); + context = context_acquire(This->wineD3DDevice, query->context->current_rt, CTXUSAGE_RESOURCELOAD); ENTER_GL(); @@ -386,6 +391,8 @@ static HRESULT WINAPI IWineD3DEventQueryImpl_GetData(IWineD3DQuery* iface, void LEAVE_GL(); + context_release(context); + return S_OK; } @@ -472,17 +479,17 @@ static HRESULT WINAPI IWineD3DEventQueryImpl_Issue(IWineD3DQuery* iface, DWORD if (query->context->tid != GetCurrentThreadId()) { context_free_event_query(query); - context = ActivateContext(This->wineD3DDevice, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(This->wineD3DDevice, NULL, CTXUSAGE_RESOURCELOAD); context_alloc_event_query(context, query); } else { - ActivateContext(This->wineD3DDevice, query->context->current_rt, CTXUSAGE_RESOURCELOAD); + context = context_acquire(This->wineD3DDevice, query->context->current_rt, CTXUSAGE_RESOURCELOAD); } } else { - context = ActivateContext(This->wineD3DDevice, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(This->wineD3DDevice, NULL, CTXUSAGE_RESOURCELOAD); context_alloc_event_query(context, query); } @@ -500,6 +507,8 @@ static HRESULT WINAPI IWineD3DEventQueryImpl_Issue(IWineD3DQuery* iface, DWORD } LEAVE_GL(); + + context_release(context); } else if(dwIssueFlags & WINED3DISSUE_BEGIN) { @@ -534,12 +543,12 @@ static HRESULT WINAPI IWineD3DOcclusionQueryImpl_Issue(IWineD3DQuery* iface, D FIXME("Wrong thread, can't restart query.\n"); context_free_occlusion_query(query); - context = ActivateContext(This->wineD3DDevice, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(This->wineD3DDevice, NULL, CTXUSAGE_RESOURCELOAD); context_alloc_occlusion_query(context, query); } else { - ActivateContext(This->wineD3DDevice, query->context->current_rt, CTXUSAGE_RESOURCELOAD); + context = context_acquire(This->wineD3DDevice, query->context->current_rt, CTXUSAGE_RESOURCELOAD); ENTER_GL(); GL_EXTCALL(glEndQueryARB(GL_SAMPLES_PASSED_ARB)); @@ -550,7 +559,7 @@ static HRESULT WINAPI IWineD3DOcclusionQueryImpl_Issue(IWineD3DQuery* iface, D else { if (query->context) context_free_occlusion_query(query); - context = ActivateContext(This->wineD3DDevice, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(This->wineD3DDevice, NULL, CTXUSAGE_RESOURCELOAD); context_alloc_occlusion_query(context, query); } @@ -558,6 +567,8 @@ static HRESULT WINAPI IWineD3DOcclusionQueryImpl_Issue(IWineD3DQuery* iface, D GL_EXTCALL(glBeginQueryARB(GL_SAMPLES_PASSED_ARB, query->id)); checkGLcall("glBeginQuery()"); LEAVE_GL(); + + context_release(context); } if (dwIssueFlags & WINED3DISSUE_END) { /* Msdn says _END on a non-building occlusion query returns an error, but @@ -572,12 +583,14 @@ static HRESULT WINAPI IWineD3DOcclusionQueryImpl_Issue(IWineD3DQuery* iface, D } else { - ActivateContext(This->wineD3DDevice, query->context->current_rt, CTXUSAGE_RESOURCELOAD); + context = context_acquire(This->wineD3DDevice, query->context->current_rt, CTXUSAGE_RESOURCELOAD); ENTER_GL(); GL_EXTCALL(glEndQueryARB(GL_SAMPLES_PASSED_ARB)); checkGLcall("glEndQuery()"); LEAVE_GL(); + + context_release(context); } } } diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index a3043cd88f4..086f9bd8711 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -40,6 +40,7 @@ static void surface_cleanup(IWineD3DSurfaceImpl *This) { IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + struct wined3d_context *context = NULL; renderbuffer_entry_t *entry, *entry2; TRACE("(%p) : Cleaning up.\n", This); @@ -50,7 +51,7 @@ static void surface_cleanup(IWineD3DSurfaceImpl *This) * target, Uninit3D() will activate a context before doing anything. */ if (device->render_targets && device->render_targets[0]) { - ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); } ENTER_GL(); @@ -93,6 +94,8 @@ static void surface_cleanup(IWineD3DSurfaceImpl *This) HeapFree(GetProcessHeap(), 0, This->palette9); resource_cleanup((IWineD3DResource *)This); + + if (context) context_release(context); } UINT surface_calculate_size(const struct GlPixelFormatDesc *format_desc, UINT alignment, UINT width, UINT height) @@ -758,11 +761,11 @@ void surface_internal_preload(IWineD3DSurface *iface, enum WINED3DSRGB srgb) tex_impl->baseTexture.internal_preload(baseTexture, srgb); IWineD3DBaseTexture_Release(baseTexture); } else { + struct wined3d_context *context = NULL; + TRACE("(%p) : About to load surface\n", This); - if(!device->isInDraw) { - ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); - } + if (!device->isInDraw) context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); if (This->resource.format_desc->format == WINED3DFMT_P8_UINT || This->resource.format_desc->format == WINED3DFMT_P8_UINT_A8_UNORM) @@ -786,6 +789,8 @@ void surface_internal_preload(IWineD3DSurface *iface, enum WINED3DSRGB srgb) glPrioritizeTextures(1, &This->texture_name, &tmp); LEAVE_GL(); } + + if (context) context_release(context); } return; } @@ -817,9 +822,10 @@ static void WINAPI IWineD3DSurfaceImpl_UnLoad(IWineD3DSurface *iface) { IWineD3DBaseTexture *texture = NULL; IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; - const struct wined3d_context *context; const struct wined3d_gl_info *gl_info; renderbuffer_entry_t *entry, *entry2; + struct wined3d_context *context; + TRACE("(%p)\n", iface); if(This->resource.pool == WINED3DPOOL_DEFAULT) { @@ -849,7 +855,7 @@ static void WINAPI IWineD3DSurfaceImpl_UnLoad(IWineD3DSurface *iface) { IWineD3DSurface_ModifyLocation(iface, SFLAG_INSRGBTEX, FALSE); This->Flags &= ~(SFLAG_ALLOCATED | SFLAG_SRGBALLOCATED); - context = ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); gl_info = context->gl_info; /* Destroy PBOs, but load them into real sysmem before */ @@ -885,6 +891,9 @@ static void WINAPI IWineD3DSurfaceImpl_UnLoad(IWineD3DSurface *iface) { } else { IWineD3DBaseTexture_Release(texture); } + + context_release(context); + return; } @@ -896,6 +905,7 @@ static void WINAPI IWineD3DSurfaceImpl_UnLoad(IWineD3DSurface *iface) { static void read_from_framebuffer(IWineD3DSurfaceImpl *This, CONST RECT *rect, void *dest, UINT pitch) { IWineD3DSwapChainImpl *swapchain; IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice; + struct wined3d_context *context; BYTE *mem; GLint fmt; GLint type; @@ -922,7 +932,7 @@ static void read_from_framebuffer(IWineD3DSurfaceImpl *This, CONST RECT *rect, v * should help here. Furthermore unlockrect will need the context set up for blitting. The context manager will find * context->last_was_blit set on the unlock. */ - ActivateContext(myDevice, (IWineD3DSurface *) This, CTXUSAGE_BLIT); + context = context_acquire(myDevice, (IWineD3DSurface *) This, CTXUSAGE_BLIT); ENTER_GL(); /* Select the correct read buffer, and give some debug output. @@ -1090,6 +1100,7 @@ static void read_from_framebuffer(IWineD3DSurfaceImpl *This, CONST RECT *rect, v } LEAVE_GL(); + context_release(context); /* For P8 textures we need to perform an inverse palette lookup. This is done by searching for a palette * index which matches the RGB value. Note this isn't guaranteed to work when there are multiple entries for @@ -1137,6 +1148,7 @@ static void read_from_framebuffer_texture(IWineD3DSurfaceImpl *This, BOOL srgb) { IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; IWineD3DSwapChainImpl *swapchain; + struct wined3d_context *context; int bpp; GLenum format, internal, type; CONVERT_TYPES convert; @@ -1149,7 +1161,7 @@ static void read_from_framebuffer_texture(IWineD3DSurfaceImpl *This, BOOL srgb) * locking during offscreen rendering). RESOURCELOAD is ok because glCopyTexSubImage2D isn't affected by any * states in the stateblock, and no driver was found yet that had bugs in that regard. */ - ActivateContext(device, (IWineD3DSurface *) This, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, (IWineD3DSurface *) This, CTXUSAGE_RESOURCELOAD); surface_bind_and_dirtify(This, srgb); ENTER_GL(); @@ -1203,6 +1215,9 @@ static void read_from_framebuffer_texture(IWineD3DSurfaceImpl *This, BOOL srgb) checkGLcall("glReadBuffer"); LEAVE_GL(); + + context_release(context); + TRACE("Updated target %d\n", This->texture_target); } @@ -1223,11 +1238,15 @@ static void surface_prepare_system_memory(IWineD3DSurfaceImpl *This) { /* Create a PBO for dynamically locked surfaces but don't do it for converted or non-pow2 surfaces. * Also don't create a PBO for systemmem surfaces. */ - if(GL_SUPPORT(ARB_PIXEL_BUFFER_OBJECT) && (This->Flags & SFLAG_DYNLOCK) && !(This->Flags & (SFLAG_PBO | SFLAG_CONVERTED | SFLAG_NONPOW2)) && (This->resource.pool != WINED3DPOOL_SYSTEMMEM)) { + if (GL_SUPPORT(ARB_PIXEL_BUFFER_OBJECT) && (This->Flags & SFLAG_DYNLOCK) + && !(This->Flags & (SFLAG_PBO | SFLAG_CONVERTED | SFLAG_NONPOW2)) + && (This->resource.pool != WINED3DPOOL_SYSTEMMEM)) + { GLenum error; IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + struct wined3d_context *context; - ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); ENTER_GL(); GL_EXTCALL(glGenBuffersARB(1, &This->pbo)); @@ -1255,7 +1274,10 @@ static void surface_prepare_system_memory(IWineD3DSurfaceImpl *This) { This->resource.allocatedMemory = NULL; This->Flags |= SFLAG_PBO; LEAVE_GL(); - } else if(!(This->resource.allocatedMemory || This->Flags & SFLAG_PBO)) { + context_release(context); + } + else if (!(This->resource.allocatedMemory || This->Flags & SFLAG_PBO)) + { /* Whatever surface we have, make sure that there is memory allocated for the downloaded copy, * or a pbo to map */ @@ -1322,8 +1344,11 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED } lock_end: - if(This->Flags & SFLAG_PBO) { - ActivateContext(myDevice, NULL, CTXUSAGE_RESOURCELOAD); + if (This->Flags & SFLAG_PBO) + { + struct wined3d_context *context; + + context = context_acquire(myDevice, NULL, CTXUSAGE_RESOURCELOAD); ENTER_GL(); GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo)); checkGLcall("glBindBufferARB"); @@ -1341,6 +1366,7 @@ lock_end: checkGLcall("glBindBufferARB"); LEAVE_GL(); + context_release(context); } if (Flags & (WINED3DLOCK_NO_DIRTY_UPDATE | WINED3DLOCK_READONLY)) { @@ -1373,9 +1399,10 @@ static void flush_to_framebuffer_drawpixels(IWineD3DSurfaceImpl *This, GLenum fm UINT pitch = IWineD3DSurface_GetPitch((IWineD3DSurface *) This); /* target is argb, 4 byte */ IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice; IWineD3DSwapChainImpl *swapchain; + struct wined3d_context *context; /* Activate the correct context for the render target */ - ActivateContext(myDevice, (IWineD3DSurface *) This, CTXUSAGE_BLIT); + context = context_acquire(myDevice, (IWineD3DSurface *) This, CTXUSAGE_BLIT); ENTER_GL(); if (SUCCEEDED(IWineD3DSurface_GetContainer((IWineD3DSurface *)This, &IID_IWineD3DSwapChain, (void **)&swapchain))) { @@ -1467,6 +1494,7 @@ static void flush_to_framebuffer_drawpixels(IWineD3DSurfaceImpl *This, GLenum fm checkGLcall("glDrawBuffer(GL_FRONT)"); } LEAVE_GL(); + context_release(context); return; } @@ -1481,15 +1509,21 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) { return WINEDDERR_NOTLOCKED; } - if (This->Flags & SFLAG_PBO) { + if (This->Flags & SFLAG_PBO) + { + struct wined3d_context *context; + TRACE("Freeing PBO memory\n"); - ActivateContext(myDevice, NULL, CTXUSAGE_RESOURCELOAD); + + context = context_acquire(myDevice, NULL, CTXUSAGE_RESOURCELOAD); ENTER_GL(); GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo)); GL_EXTCALL(glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB)); GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); checkGLcall("glUnmapBufferARB"); LEAVE_GL(); + context_release(context); + This->resource.allocatedMemory = NULL; } @@ -2612,14 +2646,16 @@ static void WINAPI IWineD3DSurfaceImpl_BindTexture(IWineD3DSurface *iface, BOOL TRACE("Passing to container\n"); IWineD3DBaseTexture_BindTexture(baseTexture, srgb); IWineD3DBaseTexture_Release(baseTexture); - } else { + } + else + { + struct wined3d_context *context = NULL; GLuint *name; + TRACE("(%p) : Binding surface\n", This); name = srgb ? &This->texture_name_srgb : &This->texture_name; - if(!device->isInDraw) { - ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); - } + if (!device->isInDraw) context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); ENTER_GL(); @@ -2653,6 +2689,8 @@ static void WINAPI IWineD3DSurfaceImpl_BindTexture(IWineD3DSurface *iface, BOOL checkGLcall("glBindTexture"); LEAVE_GL(); + + if (context) context_release(context); } return; } @@ -3023,9 +3061,10 @@ static inline void fb_copy_to_texture_direct(IWineD3DSurfaceImpl *This, IWineD3D float xrel, yrel; UINT row; IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface; + struct wined3d_context *context; - ActivateContext(myDevice, SrcSurface, CTXUSAGE_BLIT); + context = context_acquire(myDevice, SrcSurface, CTXUSAGE_BLIT); surface_internal_preload((IWineD3DSurface *) This, SRGB_RGB); ENTER_GL(); @@ -3100,6 +3139,7 @@ static inline void fb_copy_to_texture_direct(IWineD3DSurfaceImpl *This, IWineD3D checkGLcall("glCopyTexSubImage2D"); LEAVE_GL(); + context_release(context); /* The texture is now most up to date - If the surface is a render target and has a drawable, this * path is never entered @@ -3125,7 +3165,7 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine TRACE("Using hwstretch blit\n"); /* Activate the Proper context for reading from the source surface, set it up for blitting */ - context = ActivateContext(myDevice, SrcSurface, CTXUSAGE_BLIT); + context = context_acquire(myDevice, SrcSurface, CTXUSAGE_BLIT); surface_internal_preload((IWineD3DSurface *) This, SRGB_RGB); noBackBufferBackup = !swapchain && wined3d_settings.offscreen_rendering_mode == ORM_FBO; @@ -3352,6 +3392,7 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine } LEAVE_GL(); + context_release(context); /* The texture is now most up to date - If the surface is a render target and has a drawable, this * path is never entered @@ -3634,6 +3675,7 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, const float glTexCoord[4]; DWORD oldCKeyFlags = Src->CKeyFlags; WINEDDCOLORKEY oldBltCKey = Src->SrcBltCKey; + struct wined3d_context *context; RECT SourceRectangle; BOOL paletteOverride = FALSE; @@ -3710,7 +3752,7 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, const surface_internal_preload((IWineD3DSurface *) Src, SRGB_RGB); /* Activate the destination context, set it up for blitting */ - ActivateContext(myDevice, (IWineD3DSurface *) This, CTXUSAGE_BLIT); + context = context_acquire(myDevice, (IWineD3DSurface *)This, CTXUSAGE_BLIT); /* The coordinates of the ddraw front buffer are always fullscreen ('screen coordinates', * while OpenGL coordinates are window relative. @@ -3828,6 +3870,8 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, const if(dstSwapchain && (This == (IWineD3DSurfaceImpl *) dstSwapchain->frontBuffer || dstSwapchain->num_contexts >= 2)) wglFlush(); + context_release(context); + /* TODO: If the surface is locked often, perform the Blt in software on the memory instead */ /* The surface is now in the drawable. On onscreen surfaces or without fbos the texture * is outdated now @@ -4076,6 +4120,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_RealizePalette(IWineD3DSurface *iface) if((This->resource.usage & WINED3DUSAGE_RENDERTARGET) && (convert == NO_CONVERSION)) { IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + struct wined3d_context *context; /* Make sure the texture is up to date. This call doesn't do anything if the texture is already up to date. */ IWineD3DSurface_LoadLocation(iface, SFLAG_INTEXTURE, NULL); @@ -4084,8 +4129,9 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_RealizePalette(IWineD3DSurface *iface) IWineD3DSurface_ModifyLocation(iface, SFLAG_INDRAWABLE, FALSE); /* Re-upload the palette */ - ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); d3dfmt_p8_upload_palette(iface, convert); + context_release(context); } else { if(!(This->Flags & SFLAG_INSYSMEM)) { TRACE("Palette changed with surface that does not have an up to date system memory copy\n"); @@ -4546,7 +4592,7 @@ static inline void cube_coords_float(const RECT *r, UINT w, UINT h, struct float static inline void surface_blt_to_drawable(IWineD3DSurfaceImpl *This, const RECT *rect_in) { - const struct wined3d_context *context; + struct wined3d_context *context; struct coords coords[4]; RECT rect; IWineD3DSwapChain *swapchain; @@ -4653,7 +4699,7 @@ static inline void surface_blt_to_drawable(IWineD3DSurfaceImpl *This, const RECT return; } - context = ActivateContext(device, (IWineD3DSurface*)This, CTXUSAGE_BLIT); + context = context_acquire(device, (IWineD3DSurface*)This, CTXUSAGE_BLIT); ENTER_GL(); @@ -4713,6 +4759,8 @@ static inline void surface_blt_to_drawable(IWineD3DSurfaceImpl *This, const RECT IWineD3DBaseTexture_Release(texture); } } + + context_release(context); } /***************************************************************************** @@ -4778,12 +4826,19 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D surface_prepare_system_memory(This); /* Download the surface to system memory */ - if(This->Flags & (SFLAG_INTEXTURE | SFLAG_INSRGBTEX)) { - if (!device->isInDraw) ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); - surface_bind_and_dirtify(This, !(This->Flags & SFLAG_INTEXTURE)); + if (This->Flags & (SFLAG_INTEXTURE | SFLAG_INSRGBTEX)) + { + struct wined3d_context *context = NULL; + if (!device->isInDraw) context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); + + surface_bind_and_dirtify(This, !(This->Flags & SFLAG_INTEXTURE)); surface_download_data(This); - } else { + + if (context) context_release(context); + } + else + { /* Note: It might be faster to download into a texture first. */ read_from_framebuffer(This, rect, This->resource.allocatedMemory, @@ -4809,10 +4864,15 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D /* Don't use PBOs for converted surfaces. During PBO conversion we look at SFLAG_CONVERTED * but it isn't set (yet) in all cases it is getting called. */ - if((convert != NO_CONVERSION) && (This->Flags & SFLAG_PBO)) { + if ((convert != NO_CONVERSION) && (This->Flags & SFLAG_PBO)) + { + struct wined3d_context *context = NULL; + TRACE("Removing the pbo attached to surface %p\n", This); - if (!device->isInDraw) ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); + + if (!device->isInDraw) context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); surface_remove_pbo(This); + if (context) context_release(context); } if((convert != NO_CONVERSION) && This->resource.allocatedMemory) { @@ -4844,10 +4904,16 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D } else /* if(flag & (SFLAG_INTEXTURE | SFLAG_INSRGBTEX)) */ { if (drawable_read_ok && (This->Flags & SFLAG_INDRAWABLE)) { read_from_framebuffer_texture(This, flag == SFLAG_INSRGBTEX); - } else { /* Upload from system memory */ + } + else + { + /* Upload from system memory */ BOOL srgb = flag == SFLAG_INSRGBTEX; DWORD alloc_flag = srgb ? SFLAG_SRGBALLOCATED : SFLAG_ALLOCATED; - d3dfmt_get_conv(This, TRUE /* We need color keying */, TRUE /* We will use textures */, &format, &internal, &type, &convert, &bpp, srgb); + struct wined3d_context *context = NULL; + + d3dfmt_get_conv(This, TRUE /* We need color keying */, TRUE /* We will use textures */, + &format, &internal, &type, &convert, &bpp, srgb); if(srgb) { if((This->Flags & (SFLAG_INTEXTURE | SFLAG_INSYSMEM)) == SFLAG_INTEXTURE) { @@ -4869,7 +4935,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D IWineD3DSurfaceImpl_LoadLocation(iface, SFLAG_INSYSMEM, rect); } - if (!device->isInDraw) ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); + if (!device->isInDraw) context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); surface_bind_and_dirtify(This, srgb); if(This->CKeyFlags & WINEDDSD_CKSRCBLT) { @@ -4899,6 +4965,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D mem = HeapAlloc(GetProcessHeap(), 0, outpitch * height); if(!mem) { ERR("Out of memory %d, %d!\n", outpitch, height); + context_release(context); return WINED3DERR_OUTOFVIDEOMEMORY; } d3dfmt_convert_surface(This->resource.allocatedMemory, mem, pitch, width, height, outpitch, convert, This); @@ -4948,6 +5015,8 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); LEAVE_GL(); + if (context) context_release(context); + /* Don't delete PBO memory */ if((mem != This->resource.allocatedMemory) && !(This->Flags & SFLAG_PBO)) HeapFree(GetProcessHeap(), 0, mem); diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index 3b31d153765..b89d61f6f44 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -97,11 +97,11 @@ static void WINAPI IWineD3DSwapChainImpl_Destroy(IWineD3DSwapChain *iface) static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CONST RECT *pSourceRect, CONST RECT *pDestRect, HWND hDestWindowOverride, CONST RGNDATA *pDirtyRegion, DWORD dwFlags) { IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; + struct wined3d_context *context; unsigned int sync; int retval; - - ActivateContext(This->wineD3DDevice, This->backBuffer[0], CTXUSAGE_RESOURCELOAD); + context = context_acquire(This->wineD3DDevice, This->backBuffer[0], CTXUSAGE_RESOURCELOAD); /* Render the cursor onto the back buffer, using our nifty directdraw blitting code :-) */ if(This->wineD3DDevice->bCursorVisible && This->wineD3DDevice->cursorTexture) { @@ -320,6 +320,8 @@ static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CO } } + context_release(context); + TRACE("returning\n"); return WINED3D_OK; } diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 36d83166e56..eae78c0f7b1 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -34,6 +34,7 @@ static void texture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3DSRG /* Override the IWineD3DResource PreLoad method. */ IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface; IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + struct wined3d_context *context = NULL; unsigned int i; BOOL srgb_mode; BOOL *dirty; @@ -62,9 +63,9 @@ static void texture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3DSRG if (!device->isInDraw) { - /* ActivateContext sets isInDraw to TRUE when loading a pbuffer into a texture, + /* context_acquire() sets isInDraw to TRUE when loading a pbuffer into a texture, * thus no danger of recursive calls. */ - ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); + context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); } if (This->resource.format_desc->format == WINED3DFMT_P8_UINT @@ -97,6 +98,8 @@ static void texture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3DSRG TRACE("(%p) Texture not dirty, nothing to do.\n", iface); } + if (context) context_release(context); + /* No longer dirty. */ *dirty = FALSE; } diff --git a/dlls/wined3d/volumetexture.c b/dlls/wined3d/volumetexture.c index 446b94a1817..cad73604a06 100644 --- a/dlls/wined3d/volumetexture.c +++ b/dlls/wined3d/volumetexture.c @@ -34,16 +34,14 @@ static void volumetexture_internal_preload(IWineD3DBaseTexture *iface, enum WINE IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface; IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + struct wined3d_context *context = NULL; BOOL srgb_mode = This->baseTexture.is_srgb; BOOL srgb_was_toggled = FALSE; unsigned int i; TRACE("(%p) : About to load texture.\n", This); - if (!device->isInDraw) - { - ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD); - } + if (!device->isInDraw) context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); else if (GL_SUPPORT(EXT_TEXTURE_SRGB) && This->baseTexture.bindCount > 0) { srgb_mode = device->stateBlock->samplerState[This->baseTexture.sampler][WINED3DSAMP_SRGBTEXTURE]; @@ -73,6 +71,8 @@ static void volumetexture_internal_preload(IWineD3DBaseTexture *iface, enum WINE TRACE("(%p) Texture not dirty, nothing to do.\n", iface); } + if (context) context_release(context); + /* No longer dirty */ This->baseTexture.texture_rgb.dirty = FALSE; } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 79bf95d49bf..207088ac426 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1059,6 +1059,7 @@ struct wined3d_context char *vshader_const_dirty, *pshader_const_dirty; /* The actual opengl context */ + UINT level; HGLRC glCtx; HWND win_handle; HDC hdc; @@ -1161,11 +1162,11 @@ typedef enum ContextUsage { CTXUSAGE_CLEAR = 4, /* Drawable and states are set up for clearing */ } ContextUsage; -struct wined3d_context *ActivateContext(IWineD3DDeviceImpl *This, - IWineD3DSurface *target, enum ContextUsage usage) DECLSPEC_HIDDEN; struct wined3d_context *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *target, HWND win, BOOL create_pbuffer, const WINED3DPRESENT_PARAMETERS *pPresentParms) DECLSPEC_HIDDEN; void DestroyContext(IWineD3DDeviceImpl *This, struct wined3d_context *context) DECLSPEC_HIDDEN; +struct wined3d_context *context_acquire(IWineD3DDeviceImpl *This, + IWineD3DSurface *target, enum ContextUsage usage) DECLSPEC_HIDDEN; void context_alloc_event_query(struct wined3d_context *context, struct wined3d_event_query *query) DECLSPEC_HIDDEN; void context_alloc_occlusion_query(struct wined3d_context *context, @@ -1181,6 +1182,7 @@ void context_free_event_query(struct wined3d_event_query *query) DECLSPEC_HIDDEN void context_free_occlusion_query(struct wined3d_occlusion_query *query) DECLSPEC_HIDDEN; struct wined3d_context *context_get_current(void) DECLSPEC_HIDDEN; DWORD context_get_tls_idx(void) DECLSPEC_HIDDEN; +void context_release(struct wined3d_context *context) DECLSPEC_HIDDEN; BOOL context_set_current(struct wined3d_context *ctx) DECLSPEC_HIDDEN; void context_set_tls_idx(DWORD idx) DECLSPEC_HIDDEN; -- 2.11.4.GIT