Commit 1a430306 authored by Henri Verbeet's avatar Henri Verbeet Committed by Alexandre Julliard

wined3d: Keep track of a thread's wined3d context.

parent 8dd1d9b9
......@@ -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));
......
......@@ -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");
......
......@@ -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;
}
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment