wined3d: Avoid destroying contexts that are current in another thread.
This commit is contained in:
parent
1a43030664
commit
377cda97e7
|
@ -558,6 +558,59 @@ void context_resource_released(IWineD3DDevice *iface, IWineD3DResource *resource
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void context_destroy_gl_resources(struct WineD3DContext *context)
|
||||||
|
{
|
||||||
|
const struct wined3d_gl_info *gl_info = context->gl_info;
|
||||||
|
struct fbo_entry *entry, *entry2;
|
||||||
|
BOOL has_glctx;
|
||||||
|
|
||||||
|
has_glctx = pwglMakeCurrent(context->hdc, context->glCtx);
|
||||||
|
if (!has_glctx) WARN("Failed to activate context. Window already destroyed?\n");
|
||||||
|
|
||||||
|
ENTER_GL();
|
||||||
|
|
||||||
|
LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &context->fbo_list, struct fbo_entry, entry) {
|
||||||
|
if (!has_glctx) entry->id = 0;
|
||||||
|
context_destroy_fbo_entry(context, entry);
|
||||||
|
}
|
||||||
|
if (has_glctx)
|
||||||
|
{
|
||||||
|
if (context->src_fbo)
|
||||||
|
{
|
||||||
|
TRACE("Destroy src FBO %d\n", context->src_fbo);
|
||||||
|
context_destroy_fbo(context, &context->src_fbo);
|
||||||
|
}
|
||||||
|
if (context->dst_fbo)
|
||||||
|
{
|
||||||
|
TRACE("Destroy dst FBO %d\n", context->dst_fbo);
|
||||||
|
context_destroy_fbo(context, &context->dst_fbo);
|
||||||
|
}
|
||||||
|
if (context->dummy_arbfp_prog)
|
||||||
|
{
|
||||||
|
GL_EXTCALL(glDeleteProgramsARB(1, &context->dummy_arbfp_prog));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LEAVE_GL();
|
||||||
|
|
||||||
|
if (!pwglMakeCurrent(NULL, NULL))
|
||||||
|
{
|
||||||
|
ERR("Failed to disable GL context.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context->isPBuffer)
|
||||||
|
{
|
||||||
|
GL_EXTCALL(wglReleasePbufferDCARB(context->pbuffer, context->hdc));
|
||||||
|
GL_EXTCALL(wglDestroyPbufferARB(context->pbuffer));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ReleaseDC(context->win_handle, context->hdc);
|
||||||
|
}
|
||||||
|
|
||||||
|
pwglDeleteContext(context->glCtx);
|
||||||
|
}
|
||||||
|
|
||||||
DWORD context_get_tls_idx(void)
|
DWORD context_get_tls_idx(void)
|
||||||
{
|
{
|
||||||
return wined3d_context_tls_idx;
|
return wined3d_context_tls_idx;
|
||||||
|
@ -583,6 +636,20 @@ BOOL context_set_current(struct WineD3DContext *ctx)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (old)
|
||||||
|
{
|
||||||
|
if (old->destroyed)
|
||||||
|
{
|
||||||
|
TRACE("Switching away from destroyed context %p.\n", old);
|
||||||
|
context_destroy_gl_resources(old);
|
||||||
|
HeapFree(GetProcessHeap(), 0, old);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
old->current = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx)
|
if (ctx)
|
||||||
{
|
{
|
||||||
TRACE("Switching to D3D context %p, GL context %p, device context %p.\n", ctx, ctx->glCtx, ctx->hdc);
|
TRACE("Switching to D3D context %p, GL context %p, device context %p.\n", ctx, ctx->glCtx, ctx->hdc);
|
||||||
|
@ -591,6 +658,7 @@ BOOL context_set_current(struct WineD3DContext *ctx)
|
||||||
ERR("Failed to make GL context %p current on device context %p.\n", ctx->glCtx, ctx->hdc);
|
ERR("Failed to make GL context %p current on device context %p.\n", ctx->glCtx, ctx->hdc);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
ctx->current = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1205,7 +1273,6 @@ static void RemoveContextFromArray(IWineD3DDeviceImpl *This, WineD3DContext *con
|
||||||
{
|
{
|
||||||
if (This->contexts[i] == context)
|
if (This->contexts[i] == context)
|
||||||
{
|
{
|
||||||
HeapFree(GetProcessHeap(), 0, context);
|
|
||||||
found = TRUE;
|
found = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1251,65 +1318,40 @@ static void RemoveContextFromArray(IWineD3DDeviceImpl *This, WineD3DContext *con
|
||||||
* context: Context to destroy
|
* context: Context to destroy
|
||||||
*
|
*
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
void DestroyContext(IWineD3DDeviceImpl *This, WineD3DContext *context) {
|
void DestroyContext(IWineD3DDeviceImpl *This, WineD3DContext *context)
|
||||||
const struct wined3d_gl_info *gl_info = context->gl_info;
|
{
|
||||||
struct fbo_entry *entry, *entry2;
|
BOOL destroy;
|
||||||
BOOL has_glctx;
|
|
||||||
|
|
||||||
TRACE("Destroying ctx %p\n", context);
|
TRACE("Destroying ctx %p\n", context);
|
||||||
|
|
||||||
/* The correct GL context needs to be active to cleanup the GL resources below */
|
if (context->tid == GetCurrentThreadId() || !context->current)
|
||||||
has_glctx = pwglMakeCurrent(context->hdc, context->glCtx);
|
|
||||||
context_set_last_device(NULL);
|
|
||||||
|
|
||||||
if (!has_glctx) WARN("Failed to activate context. Window already destroyed?\n");
|
|
||||||
|
|
||||||
ENTER_GL();
|
|
||||||
|
|
||||||
LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &context->fbo_list, struct fbo_entry, entry) {
|
|
||||||
if (!has_glctx) entry->id = 0;
|
|
||||||
context_destroy_fbo_entry(context, entry);
|
|
||||||
}
|
|
||||||
if (has_glctx)
|
|
||||||
{
|
{
|
||||||
if (context->src_fbo)
|
context_destroy_gl_resources(context);
|
||||||
|
destroy = TRUE;
|
||||||
|
|
||||||
|
context_set_last_device(NULL);
|
||||||
|
|
||||||
|
if (This->activeContext == context)
|
||||||
{
|
{
|
||||||
TRACE("Destroy src FBO %d\n", context->src_fbo);
|
This->activeContext = NULL;
|
||||||
context_destroy_fbo(context, &context->src_fbo);
|
TRACE("Destroying the active context.\n");
|
||||||
}
|
}
|
||||||
if (context->dst_fbo)
|
|
||||||
|
if (!context_set_current(NULL))
|
||||||
{
|
{
|
||||||
TRACE("Destroy dst FBO %d\n", context->dst_fbo);
|
ERR("Failed to clear current D3D context.\n");
|
||||||
context_destroy_fbo(context, &context->dst_fbo);
|
|
||||||
}
|
|
||||||
if (context->dummy_arbfp_prog)
|
|
||||||
{
|
|
||||||
GL_EXTCALL(glDeleteProgramsARB(1, &context->dummy_arbfp_prog));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
LEAVE_GL();
|
|
||||||
|
|
||||||
if (This->activeContext == context)
|
|
||||||
{
|
{
|
||||||
This->activeContext = NULL;
|
context->destroyed = 1;
|
||||||
TRACE("Destroying the active context.\n");
|
destroy = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!context_set_current(NULL))
|
|
||||||
{
|
|
||||||
ERR("Failed to clear current D3D context.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(context->isPBuffer) {
|
|
||||||
GL_EXTCALL(wglReleasePbufferDCARB(context->pbuffer, context->hdc));
|
|
||||||
GL_EXTCALL(wglDestroyPbufferARB(context->pbuffer));
|
|
||||||
} else ReleaseDC(context->win_handle, context->hdc);
|
|
||||||
pwglDeleteContext(context->glCtx);
|
|
||||||
|
|
||||||
HeapFree(GetProcessHeap(), 0, context->vshader_const_dirty);
|
HeapFree(GetProcessHeap(), 0, context->vshader_const_dirty);
|
||||||
HeapFree(GetProcessHeap(), 0, context->pshader_const_dirty);
|
HeapFree(GetProcessHeap(), 0, context->pshader_const_dirty);
|
||||||
RemoveContextFromArray(This, context);
|
RemoveContextFromArray(This, context);
|
||||||
|
if (destroy) HeapFree(GetProcessHeap(), 0, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* GL locking is done by the caller */
|
/* GL locking is done by the caller */
|
||||||
|
|
|
@ -1219,7 +1219,9 @@ struct WineD3DContext
|
||||||
WORD isPBuffer : 1;
|
WORD isPBuffer : 1;
|
||||||
WORD fog_enabled : 1;
|
WORD fog_enabled : 1;
|
||||||
WORD num_untracked_materials : 2; /* Max value 2 */
|
WORD num_untracked_materials : 2; /* Max value 2 */
|
||||||
WORD padding : 3;
|
WORD current : 1;
|
||||||
|
WORD destroyed : 1;
|
||||||
|
WORD padding : 1;
|
||||||
BYTE texShaderBumpMap; /* MAX_TEXTURES, 8 */
|
BYTE texShaderBumpMap; /* MAX_TEXTURES, 8 */
|
||||||
BYTE lastWasPow2Texture; /* MAX_TEXTURES, 8 */
|
BYTE lastWasPow2Texture; /* MAX_TEXTURES, 8 */
|
||||||
DWORD numbered_array_mask;
|
DWORD numbered_array_mask;
|
||||||
|
|
Loading…
Reference in New Issue