Module: wine Branch: master Commit: 1a43030664e796da843316d12d3bf3300ab66c0f URL: http://source.winehq.org/git/wine.git/?a=commit;h=1a43030664e796da843316d12d...
Author: Henri Verbeet hverbeet@codeweavers.com Date: Wed Jul 22 14:03:36 2009 +0200
wined3d: Keep track of a thread's wined3d context.
---
dlls/wined3d/context.c | 75 ++++++++++++++++++++++++++++----------- dlls/wined3d/directx.c | 5 +++ dlls/wined3d/wined3d_main.c | 32 +++++++++++++++++ dlls/wined3d/wined3d_private.h | 4 ++ 4 files changed, 95 insertions(+), 21 deletions(-)
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index de428cd..5e43467 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -35,6 +35,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); * change the opengl context. This flag allows to keep track which device is active */ static IWineD3DDeviceImpl *last_device; +static DWORD wined3d_context_tls_idx;
void context_set_last_device(IWineD3DDeviceImpl *device) { @@ -557,6 +558,53 @@ void context_resource_released(IWineD3DDevice *iface, IWineD3DResource *resource } }
+DWORD context_get_tls_idx(void) +{ + return wined3d_context_tls_idx; +} + +void context_set_tls_idx(DWORD idx) +{ + wined3d_context_tls_idx = idx; +} + +struct WineD3DContext *context_get_current(void) +{ + return TlsGetValue(wined3d_context_tls_idx); +} + +BOOL context_set_current(struct WineD3DContext *ctx) +{ + struct WineD3DContext *old = context_get_current(); + + if (old == ctx) + { + TRACE("Already using D3D context %p.\n", ctx); + return TRUE; + } + + if (ctx) + { + TRACE("Switching to D3D context %p, GL context %p, device context %p.\n", ctx, ctx->glCtx, ctx->hdc); + if (!pwglMakeCurrent(ctx->hdc, ctx->glCtx)) + { + ERR("Failed to make GL context %p current on device context %p.\n", ctx->glCtx, ctx->hdc); + return FALSE; + } + } + else + { + TRACE("Clearing current D3D context.\n"); + if (!pwglMakeCurrent(NULL, NULL)) + { + ERR("Failed to clear current GL context.\n"); + return FALSE; + } + } + + return TlsSetValue(wined3d_context_tls_idx, ctx); +} + /***************************************************************************** * Context_MarkStateDirty * @@ -1038,7 +1086,8 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar list_init(&ret->fbo_list);
/* Set up the context defaults */ - if(pwglMakeCurrent(hdc, ctx) == FALSE) { + if (!context_set_current(ret)) + { ERR("Cannot activate context to set up defaults\n"); goto out; } @@ -1247,10 +1296,9 @@ void DestroyContext(IWineD3DDeviceImpl *This, WineD3DContext *context) { TRACE("Destroying the active context.\n"); }
- /* Cleanup the GL context */ - if (!pwglMakeCurrent(NULL, NULL)) + if (!context_set_current(NULL)) { - ERR("Failed to disable GL context.\n"); + ERR("Failed to clear current D3D context.\n"); }
if(context->isPBuffer) { @@ -1779,24 +1827,9 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU
/* Activate the opengl context */ if(last_device != This || context != This->activeContext) { - BOOL ret; - - /* Prevent an unneeded context switch as those are expensive */ - if(context->glCtx && (context->glCtx == pwglGetCurrentContext())) { - TRACE("Already using gl context %p\n", context->glCtx); - } - else { - TRACE("Switching gl ctx to %p, hdc=%p ctx=%p\n", context, context->hdc, context->glCtx); + if (!context_set_current(context)) ERR("Failed to activate the new context.\n"); + else This->frag_pipe->enable_extension((IWineD3DDevice *)This, !context->last_was_blit);
- ret = pwglMakeCurrent(context->hdc, context->glCtx); - if(ret == FALSE) { - ERR("Failed to activate the new context\n"); - } else if(!context->last_was_blit) { - This->frag_pipe->enable_extension((IWineD3DDevice *) This, TRUE); - } else { - This->frag_pipe->enable_extension((IWineD3DDevice *) This, FALSE); - } - } if(This->activeContext->vshader_const_dirty) { memset(This->activeContext->vshader_const_dirty, 1, sizeof(*This->activeContext->vshader_const_dirty) * GL_LIMITS(vshader_constantsF)); diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 3036bfc..9daffaa 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -274,6 +274,11 @@ static BOOL WineD3D_CreateFakeGLContext(struct wined3d_fake_gl_ctx *ctx) }
/* Make it the current GL context. */ + if (!context_set_current(NULL)) + { + ERR_(d3d_caps)("Failed to clear current D3D context.\n"); + } + if (!pwglMakeCurrent(ctx->dc, ctx->gl_ctx)) { ERR_(d3d_caps)("Failed to make fake GL context current.\n"); diff --git a/dlls/wined3d/wined3d_main.c b/dlls/wined3d/wined3d_main.c index f996aec..045eea0 100644 --- a/dlls/wined3d/wined3d_main.c +++ b/dlls/wined3d/wined3d_main.c @@ -97,6 +97,7 @@ static void CDECL wined3d_do_nothing(void)
static BOOL wined3d_init(HINSTANCE hInstDLL) { + DWORD wined3d_context_tls_idx; HMODULE mod; char buffer[MAX_PATH+10]; DWORD size = sizeof(buffer); @@ -105,6 +106,15 @@ static BOOL wined3d_init(HINSTANCE hInstDLL) DWORD len, tmpvalue; WNDCLASSA wc;
+ wined3d_context_tls_idx = TlsAlloc(); + if (wined3d_context_tls_idx == TLS_OUT_OF_INDEXES) + { + DWORD err = GetLastError(); + ERR("Failed to allocate context TLS index, err %#x.\n", err); + return FALSE; + } + context_set_tls_idx(wined3d_context_tls_idx); + /* We need our own window class for a fake window which we use to retrieve GL capabilities */ /* We might need CS_OWNDC in the future if we notice strange things on Windows. * Various articles/posts about OpenGL problems on Windows recommend this. */ @@ -122,6 +132,11 @@ static BOOL wined3d_init(HINSTANCE hInstDLL) if (!RegisterClassA(&wc)) { ERR("Failed to register window class 'WineD3D_OpenGL'!\n"); + if (!TlsFree(wined3d_context_tls_idx)) + { + DWORD err = GetLastError(); + ERR("Failed to free context TLS index, err %#x.\n", err); + } return FALSE; }
@@ -322,6 +337,14 @@ static BOOL wined3d_init(HINSTANCE hInstDLL)
static BOOL wined3d_destroy(HINSTANCE hInstDLL) { + DWORD wined3d_context_tls_idx = context_get_tls_idx(); + + if (!TlsFree(wined3d_context_tls_idx)) + { + DWORD err = GetLastError(); + ERR("Failed to free context TLS index, err %#x.\n", err); + } + HeapFree(GetProcessHeap(), 0, wined3d_settings.logo); UnregisterClassA(WINED3D_OPENGL_WINDOW_CLASS_NAME, hInstDLL);
@@ -341,6 +364,15 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) case DLL_PROCESS_DETACH: return wined3d_destroy(hInstDLL);
+ case DLL_THREAD_DETACH: + { + if (!context_set_current(NULL)) + { + ERR("Failed to clear current context.\n"); + } + return TRUE; + } + default: return TRUE; } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index b7085c5..63c71d4 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1271,6 +1271,10 @@ void context_attach_depth_stencil_fbo(struct WineD3DContext *context, void context_attach_surface_fbo(const struct WineD3DContext *context, GLenum fbo_target, DWORD idx, IWineD3DSurface *surface); void context_set_last_device(IWineD3DDeviceImpl *device); +struct WineD3DContext *context_get_current(void); +DWORD context_get_tls_idx(void); +BOOL context_set_current(struct WineD3DContext *ctx); +void context_set_tls_idx(DWORD idx);
void delete_opengl_contexts(IWineD3DDevice *iface, IWineD3DSwapChain *swapchain); HRESULT create_primary_opengl_context(IWineD3DDevice *iface, IWineD3DSwapChain *swapchain);