wined3d: Keep track of a thread's wined3d context.
This commit is contained in:
parent
8dd1d9b92e
commit
1a43030664
|
@ -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;
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue