mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-11 17:20:56 +00:00
Add special push/pop logic for WGL contexts
* We can't easily restore the application's context if the DC that was current has been released. Instead we check to see if the last known window is still valid - if so, we get the DC handle from it. If not then we assume that rendering to the application's context setup would have failed so we bind our own backdoor window (but with the application's context still).
This commit is contained in:
@@ -711,8 +711,10 @@ void DoVendorChecks(GLPlatform &platform, GLWindowingData context)
|
||||
|
||||
if(child.ctx)
|
||||
{
|
||||
GLWindowingData saved;
|
||||
|
||||
// switch to child
|
||||
platform.MakeContextCurrent(child);
|
||||
platform.PushChildContext(context, child, &saved);
|
||||
|
||||
// these shouldn't be visible
|
||||
VendorCheck[VendorCheck_EXT_fbo_shared] = (GL.glIsFramebuffer(fbo) != GL_FALSE);
|
||||
@@ -724,7 +726,7 @@ void DoVendorChecks(GLPlatform &platform, GLWindowingData context)
|
||||
RDCWARN("VAOs are shared on this implementation");
|
||||
|
||||
// switch back to context
|
||||
platform.MakeContextCurrent(context);
|
||||
platform.PopChildContext(context, child, saved);
|
||||
|
||||
platform.DeleteClonedContext(child);
|
||||
}
|
||||
|
||||
@@ -274,6 +274,20 @@ struct GLPlatform
|
||||
virtual GLWindowingData MakeOutputWindow(WindowingData window, bool depth,
|
||||
GLWindowingData share_context) = 0;
|
||||
|
||||
// for pushing and popping a child context. The default implementation just does
|
||||
// MakeContextCurrent but platforms can override this if they need more complex state handling
|
||||
virtual bool PushChildContext(GLWindowingData existing, GLWindowingData newChild,
|
||||
GLWindowingData *saved)
|
||||
{
|
||||
bool success = MakeContextCurrent(newChild);
|
||||
*saved = existing;
|
||||
return success;
|
||||
}
|
||||
virtual void PopChildContext(GLWindowingData existing, GLWindowingData newChild,
|
||||
GLWindowingData saved)
|
||||
{
|
||||
MakeContextCurrent(saved);
|
||||
}
|
||||
// for 'backwards compatible' overlay rendering
|
||||
virtual void DrawQuads(float width, float height, const rdcarray<Vec4f> &vertices) = 0;
|
||||
|
||||
|
||||
@@ -567,7 +567,9 @@ bool GLResourceManager::Prepare_InitialState(GLResource res)
|
||||
|
||||
ContextShareGroup *shareGroup = (ContextShareGroup *)res.ContextShareGroup;
|
||||
|
||||
if(m_Driver->m_Platform.MakeContextCurrent(shareGroup->m_BackDoor))
|
||||
GLWindowingData savedContext;
|
||||
|
||||
if(m_Driver->m_Platform.PushChildContext(oldContextData, shareGroup->m_BackDoor, &savedContext))
|
||||
{
|
||||
m_Driver->m_ActiveContexts[Threading::GetCurrentID()] = shareGroup->m_BackDoor;
|
||||
|
||||
@@ -575,7 +577,7 @@ bool GLResourceManager::Prepare_InitialState(GLResource res)
|
||||
|
||||
// restore the context
|
||||
m_Driver->m_ActiveContexts[Threading::GetCurrentID()] = oldContextData;
|
||||
m_Driver->m_Platform.MakeContextCurrent(oldContextData);
|
||||
m_Driver->m_Platform.PopChildContext(oldContextData, shareGroup->m_BackDoor, savedContext);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1807,7 +1809,7 @@ bool GLResourceManager::Serialise_InitialState(WriteSerialiser &ser, ResourceId
|
||||
GLResourceRecord *record,
|
||||
const GLInitialContents *initial)
|
||||
{
|
||||
GLResource res = GetCurrentResource(id);
|
||||
GLResource res = record->Resource;
|
||||
|
||||
if(IsResourceTrackedForPersistency(res))
|
||||
{
|
||||
@@ -1815,7 +1817,9 @@ bool GLResourceManager::Serialise_InitialState(WriteSerialiser &ser, ResourceId
|
||||
|
||||
GLWindowingData backdoor = ((ContextShareGroup *)res.ContextShareGroup)->m_BackDoor;
|
||||
|
||||
if(m_Driver->m_Platform.MakeContextCurrent(backdoor))
|
||||
GLWindowingData savedContext;
|
||||
|
||||
if(m_Driver->m_Platform.PushChildContext(oldContextData, backdoor, &savedContext))
|
||||
{
|
||||
m_Driver->m_ActiveContexts[Threading::GetCurrentID()] = backdoor;
|
||||
|
||||
@@ -1824,7 +1828,7 @@ bool GLResourceManager::Serialise_InitialState(WriteSerialiser &ser, ResourceId
|
||||
// restore the context
|
||||
m_Driver->m_ActiveContexts[Threading::GetCurrentID()] = oldContextData;
|
||||
|
||||
m_Driver->m_Platform.MakeContextCurrent(oldContextData);
|
||||
m_Driver->m_Platform.PopChildContext(oldContextData, backdoor, savedContext);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@@ -145,12 +145,18 @@ bool GLResourceManager::ResourceTypeRelease(GLResource res)
|
||||
{
|
||||
ContextShareGroup *contextShareGroup = (ContextShareGroup *)res.ContextShareGroup;
|
||||
|
||||
if(m_Driver->m_Platform.MakeContextCurrent(contextShareGroup->m_BackDoor))
|
||||
GLWindowingData oldContextData = m_Driver->m_ActiveContexts[Threading::GetCurrentID()];
|
||||
|
||||
GLWindowingData savedContext;
|
||||
|
||||
if(m_Driver->m_Platform.PushChildContext(oldContextData, contextShareGroup->m_BackDoor,
|
||||
&savedContext))
|
||||
{
|
||||
m_Driver->ReleaseResource(res);
|
||||
|
||||
// restore the context
|
||||
m_Driver->m_Platform.MakeContextCurrent(m_Driver->m_ActiveContexts[Threading::GetCurrentID()]);
|
||||
m_Driver->m_Platform.PopChildContext(oldContextData, contextShareGroup->m_BackDoor,
|
||||
savedContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -37,6 +37,41 @@ class WGLPlatform : public GLPlatform
|
||||
return false;
|
||||
}
|
||||
|
||||
// pushing/popping contexts is complex on windows due to the really awful rules for DC lifetimes.
|
||||
// Changing to the child context is easy, but getting back to where we started is hard. The
|
||||
// 'current' DC may no longer be valid, as it may have been released in the meantime (while
|
||||
// rendering is still A-OK). We check that the window behind the DC is valid, stored the 'wnd'
|
||||
// member. If that window is valid then we use GetDC() to get a temporary DC and bind that,
|
||||
// assuming all will be well. If the window isn't valid then we can't get a valid DC so we can't
|
||||
// rebind the context exactly as it was, however we assume that rendering to that setup was broken
|
||||
// (because the bound DC wasn't pointing to a valid window) so instead we just bind the old
|
||||
// context but with our DC.
|
||||
|
||||
virtual bool PushChildContext(GLWindowingData existing, GLWindowingData newChild,
|
||||
GLWindowingData *saved)
|
||||
{
|
||||
bool success = MakeContextCurrent(newChild);
|
||||
*saved = existing;
|
||||
if(::IsWindow(existing.wnd))
|
||||
{
|
||||
saved->DC = GetDC(existing.wnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
saved->wnd = newChild.wnd;
|
||||
saved->DC = newChild.DC;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
virtual void PopChildContext(GLWindowingData existing, GLWindowingData newChild,
|
||||
GLWindowingData saved)
|
||||
{
|
||||
MakeContextCurrent(saved);
|
||||
// release the DC now, if we didn't use our own because theirs was invalid
|
||||
if(saved.DC != newChild.DC)
|
||||
::ReleaseDC(saved.wnd, saved.DC);
|
||||
}
|
||||
GLWindowingData CloneTemporaryContext(GLWindowingData share)
|
||||
{
|
||||
GLWindowingData ret = share;
|
||||
|
||||
Reference in New Issue
Block a user