From 178f61abd0e51132f601205ec5886d1ba5341d7d Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 6 Jul 2018 13:01:38 +0100 Subject: [PATCH] Separate out function to make shared context for vendor checks * This is only to be used to make a temporary context to share with. We make sure to use the same visual/config as the parent context to ensure it will successfully share. --- renderdoc/driver/gl/cgl_platform.cpp | 4 +- renderdoc/driver/gl/egl_hooks.cpp | 7 ++++ renderdoc/driver/gl/egl_platform.cpp | 38 +++++++++---------- renderdoc/driver/gl/gl_common.cpp | 4 +- renderdoc/driver/gl/gl_common.h | 23 ++++++++---- renderdoc/driver/gl/gl_replay.cpp | 10 ++--- renderdoc/driver/gl/glx_dispatch_table.h | 2 + renderdoc/driver/gl/glx_hooks.cpp | 42 ++++++++++++++++++++- renderdoc/driver/gl/glx_platform.cpp | 48 +++++++++--------------- renderdoc/driver/gl/wgl_platform.cpp | 10 +++-- 10 files changed, 113 insertions(+), 75 deletions(-) diff --git a/renderdoc/driver/gl/cgl_platform.cpp b/renderdoc/driver/gl/cgl_platform.cpp index f45e15595..00eadae69 100644 --- a/renderdoc/driver/gl/cgl_platform.cpp +++ b/renderdoc/driver/gl/cgl_platform.cpp @@ -27,13 +27,13 @@ class CGLPlatform : public GLPlatform { bool MakeContextCurrent(GLWindowingData data) { return false; } - GLWindowingData MakeContext(GLWindowingData share) + GLWindowingData CloneTemporaryContext(GLWindowingData share) { GLWindowingData ret; return ret; } - void DeleteContext(GLWindowingData context) {} + void DeleteClonedContext(GLWindowingData context) {} void DeleteReplayContext(GLWindowingData context) {} void SwapBuffers(GLWindowingData context) {} void GetOutputWindowDimensions(GLWindowingData context, int32_t &w, int32_t &h) { w = h = 0; } diff --git a/renderdoc/driver/gl/egl_hooks.cpp b/renderdoc/driver/gl/egl_hooks.cpp index b985aa385..a5f91b8a9 100644 --- a/renderdoc/driver/gl/egl_hooks.cpp +++ b/renderdoc/driver/gl/egl_hooks.cpp @@ -51,6 +51,7 @@ public: void *handle = DEFAULT_HANDLE; WrappedOpenGL driver; std::set contexts; + std::map configs; } eglhook; HOOK_EXPORT EGLDisplay eglGetDisplay(EGLNativeDisplayType display) @@ -165,6 +166,9 @@ HOOK_EXPORT EGLContext eglCreateContext(EGLDisplay display, EGLConfig config, data.egl_dpy = display; data.egl_wnd = (EGLSurface)NULL; data.egl_ctx = ret; + data.egl_cfg = config; + + eglhook.configs[ret] = config; eglhook.driver.SetDriverType(RDCDriver::OpenGLES); { @@ -231,6 +235,9 @@ HOOK_EXPORT EGLBoolean eglMakeCurrent(EGLDisplay display, EGLSurface draw, EGLSu data.egl_wnd = draw; data.egl_ctx = ctx; + // we could query this out technically but it's easier to keep a map + data.egl_cfg = eglhook.configs[ctx]; + eglhook.driver.SetDriverType(RDCDriver::OpenGLES); eglhook.driver.ActivateContext(data); diff --git a/renderdoc/driver/gl/egl_platform.cpp b/renderdoc/driver/gl/egl_platform.cpp index 755cb9e5d..d72d55144 100644 --- a/renderdoc/driver/gl/egl_platform.cpp +++ b/renderdoc/driver/gl/egl_platform.cpp @@ -50,23 +50,25 @@ class EGLPlatform : public GLPlatform return false; } - GLWindowingData MakeContext(GLWindowingData share) + GLWindowingData CloneTemporaryContext(GLWindowingData share) { - GLWindowingData ret; + GLWindowingData ret = share; - if(EGL.CreateContext && EGL.ChooseConfig && EGL.CreatePbufferSurface) + ret.egl_ctx = NULL; + + if(EGL.CreateContext) { - ret = CreateWindowingData(share.egl_dpy, share.ctx, 0); + EGLint baseAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_CONTEXT_FLAGS_KHR, + EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR, EGL_NONE}; + + ret.egl_ctx = EGL.CreateContext(share.egl_dpy, share.egl_cfg, share.egl_ctx, baseAttribs); } return ret; } - void DeleteContext(GLWindowingData context) + void DeleteClonedContext(GLWindowingData context) { - if(context.wnd && EGL.DestroySurface) - EGL.DestroySurface(context.egl_dpy, context.egl_wnd); - if(context.ctx && EGL.DestroyContext) EGL.DestroyContext(context.egl_dpy, context.egl_ctx); } @@ -159,8 +161,7 @@ class EGLPlatform : public GLPlatform EGL_NONE}; EGLint numConfigs; - EGLConfig config; - if(!EGL.ChooseConfig(eglDisplay, configAttribs, &config, 1, &numConfigs)) + if(!EGL.ChooseConfig(eglDisplay, configAttribs, &ret.egl_cfg, 1, &numConfigs)) { RDCERR("Couldn't find a suitable EGL config"); return ret; @@ -185,7 +186,7 @@ class EGLPlatform : public GLPlatform { verAttribs[1] = v.major; verAttribs[3] = v.minor; - ctx = EGL.CreateContext(eglDisplay, config, share_ctx, verAttribs); + ctx = EGL.CreateContext(eglDisplay, ret.egl_cfg, share_ctx, verAttribs); if(ctx) break; @@ -197,7 +198,7 @@ class EGLPlatform : public GLPlatform static const EGLint baseAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_CONTEXT_FLAGS_KHR, EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR, EGL_NONE}; - ctx = EGL.CreateContext(eglDisplay, config, share_ctx, baseAttribs); + ctx = EGL.CreateContext(eglDisplay, ret.egl_cfg, share_ctx, baseAttribs); } if(ctx == NULL) @@ -211,7 +212,7 @@ class EGLPlatform : public GLPlatform EGLSurface surface = 0; if(window != 0) { - surface = EGL.CreateWindowSurface(eglDisplay, config, window, NULL); + surface = EGL.CreateWindowSurface(eglDisplay, ret.egl_cfg, window, NULL); if(surface == NULL) RDCERR("Couldn't create surface for window"); @@ -219,7 +220,7 @@ class EGLPlatform : public GLPlatform else { static const EGLint pbAttribs[] = {EGL_WIDTH, 32, EGL_HEIGHT, 32, EGL_NONE}; - surface = EGL.CreatePbufferSurface(eglDisplay, config, pbAttribs); + surface = EGL.CreatePbufferSurface(eglDisplay, ret.egl_cfg, pbAttribs); if(surface == NULL) RDCERR("Couldn't create a suitable PBuffer"); @@ -254,17 +255,12 @@ class EGLPlatform : public GLPlatform int major, minor; EGL.Initialize(eglDisplay, &major, &minor); - GLWindowingData base; - base.egl_dpy = eglDisplay; - base.egl_ctx = EGL_NO_CONTEXT; - base.egl_wnd = 0; - - replayContext = MakeContext(base); + replayContext = CreateWindowingData(eglDisplay, EGL_NO_CONTEXT, 0); if(!replayContext.ctx || !replayContext.wnd) { RDCERR("Couldn't create OpenGL ES 3.x replay context - required for replay"); - DeleteContext(replayContext); + DeleteReplayContext(replayContext); RDCEraseEl(replayContext); return ReplayStatus::APIHardwareUnsupported; } diff --git a/renderdoc/driver/gl/gl_common.cpp b/renderdoc/driver/gl/gl_common.cpp index 5b9762ddf..1bec250f2 100644 --- a/renderdoc/driver/gl/gl_common.cpp +++ b/renderdoc/driver/gl/gl_common.cpp @@ -718,7 +718,7 @@ void DoVendorChecks(GLPlatform &platform, GLWindowingData context) GL.glBindVertexArray(vao); // make a context that shares with the current one, and switch to it - GLWindowingData child = platform.MakeContext(context); + GLWindowingData child = platform.CloneTemporaryContext(context); if(child.ctx) { @@ -737,7 +737,7 @@ void DoVendorChecks(GLPlatform &platform, GLWindowingData context) // switch back to context platform.MakeContextCurrent(context); - platform.DeleteContext(child); + platform.DeleteClonedContext(child); } GL.glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, prevFBO); diff --git a/renderdoc/driver/gl/gl_common.h b/renderdoc/driver/gl/gl_common.h index 9f0fec3b9..40ceec691 100644 --- a/renderdoc/driver/gl/gl_common.h +++ b/renderdoc/driver/gl/gl_common.h @@ -96,7 +96,6 @@ struct GLWindowingData wnd = NULL; } - void SetCtx(void *c) { ctx = (HGLRC)c; } union { HDC DC; @@ -112,6 +111,8 @@ struct GLWindowingData HWND wnd; EGLSurface egl_wnd; }; + + EGLConfig egl_cfg; }; #elif ENABLED(RDOC_LINUX) @@ -149,26 +150,28 @@ struct GLWindowingData wnd = 0; } - void SetCtx(void *c) { ctx = (GLContextPtr)c; } - #if defined(RENDERDOC_SUPPORT_GL) typedef Display *GLDisplayPtr; typedef GLXContext GLContextPtr; typedef GLXDrawable GLWindowPtr; + typedef XVisualInfo *GLConfigPtr; #else typedef void *GLDisplayPtr; typedef void *GLContextPtr; typedef void *GLWindowPtr; + typedef void *GLConfigPtr; #endif #if defined(RENDERDOC_SUPPORT_GLES) typedef EGLDisplay GLESDisplayPtr; typedef EGLContext GLESContextPtr; typedef EGLSurface GLESWindowPtr; + typedef EGLConfig GLESConfigPtr; #else typedef void *GLESDisplayPtr; typedef void *GLESContextPtr; typedef void *GLESWindowPtr; + typedef vpod *GLESConfigPtr; #endif union @@ -186,6 +189,11 @@ struct GLWindowingData GLWindowPtr wnd; GLESWindowPtr egl_wnd; }; + union + { + GLConfigPtr cfg; + GLESConfigPtr egl_cfg; + }; }; #elif ENABLED(RDOC_APPLE) @@ -198,7 +206,6 @@ struct GLWindowingData wnd = 0; } - void SetCtx(void *c) { ctx = (void *)c; } void *ctx; void *wnd; }; @@ -222,19 +229,19 @@ struct GLWindowingData egl_wnd = 0; } - void SetCtx(void *c) { egl_ctx = (void *)c; } union { // currently required to allow compatiblity with the driver parts void *ctx; EGLContext egl_ctx; }; - EGLDisplay egl_dpy; union { EGLSurface egl_wnd; void *wnd; }; + EGLDisplay egl_dpy; + EGLConfig egl_cfg; }; #else @@ -246,8 +253,8 @@ struct GLWindowingData struct GLPlatform { // simple wrapper for OS functions to make/delete a context - virtual GLWindowingData MakeContext(GLWindowingData share) = 0; - virtual void DeleteContext(GLWindowingData context) = 0; + virtual GLWindowingData CloneTemporaryContext(GLWindowingData share) = 0; + virtual void DeleteClonedContext(GLWindowingData context) = 0; virtual void DeleteReplayContext(GLWindowingData context) = 0; virtual bool MakeContextCurrent(GLWindowingData data) = 0; virtual void SwapBuffers(GLWindowingData context) = 0; diff --git a/renderdoc/driver/gl/gl_replay.cpp b/renderdoc/driver/gl/gl_replay.cpp index 1f973e8b6..4fc64424f 100644 --- a/renderdoc/driver/gl/gl_replay.cpp +++ b/renderdoc/driver/gl/gl_replay.cpp @@ -3251,7 +3251,7 @@ ReplayStatus CreateReplayDevice(RDCFile *rdc, GLPlatform &platform, IReplayDrive if(!current) { RDCERR("Couldn't active the created GL ES context"); - platform.DeleteContext(data); + platform.DeleteReplayContext(data); return ReplayStatus::APIInitFailed; } @@ -3269,14 +3269,14 @@ ReplayStatus CreateReplayDevice(RDCFile *rdc, GLPlatform &platform, IReplayDrive if(!extensionsValidated) { - platform.DeleteContext(data); + platform.DeleteReplayContext(data); return ReplayStatus::APIInitFailed; } bool functionsValidated = ValidateFunctionPointers(); if(!functionsValidated) { - platform.DeleteContext(data); + platform.DeleteReplayContext(data); return ReplayStatus::APIHardwareUnsupported; } @@ -3299,8 +3299,8 @@ ReplayStatus CreateReplayDevice(RDCFile *rdc, GLPlatform &platform, IReplayDrive class GLDummyPlatform : public GLPlatform { - virtual GLWindowingData MakeContext(GLWindowingData share) { return GLWindowingData(); } - virtual void DeleteContext(GLWindowingData context) {} + virtual GLWindowingData CloneTemporaryContext(GLWindowingData share) { return GLWindowingData(); } + virtual void DeleteClonedContext(GLWindowingData context) {} virtual void DeleteReplayContext(GLWindowingData context) {} virtual bool MakeContextCurrent(GLWindowingData data) { return true; } virtual void SwapBuffers(GLWindowingData context) {} diff --git a/renderdoc/driver/gl/glx_dispatch_table.h b/renderdoc/driver/gl/glx_dispatch_table.h index cd503cf3e..effe37af2 100644 --- a/renderdoc/driver/gl/glx_dispatch_table.h +++ b/renderdoc/driver/gl/glx_dispatch_table.h @@ -33,6 +33,7 @@ typedef void (*PFN_glXDestroyContext)(Display *dpy, GLXContext ctx); typedef Bool (*PFN_glXMakeCurrent)(Display *dpy, GLXDrawable drawable, GLXContext ctx); typedef void (*PFN_glXSwapBuffers)(Display *dpy, GLXDrawable drawable); typedef int (*PFN_glXGetConfig)(Display *dpy, XVisualInfo *vis, int attrib, int *value); +typedef int (*PFN_glXQueryContext)(Display *dpy, GLXContext ctx, int attribute, int *value); typedef Bool (*PFN_glXIsDirect)(Display *dpy, GLXContext ctx); typedef __GLXextFuncPtr (*PFN_glXGetProcAddress)(const GLubyte *); typedef __GLXextFuncPtr (*PFN_glXGetProcAddressARB)(const GLubyte *); @@ -74,6 +75,7 @@ typedef void (*PFN_glEnd)(); #define GLX_NONHOOKED_SYMBOLS(FUNC) \ FUNC(glXGetConfig); \ + FUNC(glXQueryContext); \ FUNC(glXIsDirect); \ FUNC(glXGetVisualFromFBConfig); \ FUNC(glXChooseFBConfig); \ diff --git a/renderdoc/driver/gl/glx_hooks.cpp b/renderdoc/driver/gl/glx_hooks.cpp index 36d836d6a..7ef0c794d 100644 --- a/renderdoc/driver/gl/glx_hooks.cpp +++ b/renderdoc/driver/gl/glx_hooks.cpp @@ -113,6 +113,7 @@ HOOK_EXPORT GLXContext glXCreateContext(Display *dpy, XVisualInfo *vis, GLXConte data.dpy = dpy; data.wnd = (GLXDrawable)NULL; data.ctx = ret; + data.cfg = vis; { SCOPED_LOCK(glLock); @@ -249,18 +250,19 @@ HOOK_EXPORT GLXContext glXCreateContextAttribsARB(Display *dpy, GLXFBConfig conf GLX.glXGetConfig(dpy, vis, GLX_SAMPLES_ARB, &value); init.isSRGB = RDCMAX(1, value); - XFree(vis); - GLWindowingData data; data.dpy = dpy; data.wnd = (GLXDrawable)NULL; data.ctx = ret; + data.cfg = vis; { SCOPED_LOCK(glLock); glxhook.driver.CreateContext(data, shareList, init, core, true); } + XFree(vis); + return ret; } @@ -299,7 +301,25 @@ HOOK_EXPORT Bool glXMakeCurrent(Display *dpy, GLXDrawable drawable, GLXContext c data.wnd = drawable; data.ctx = ctx; + int fbconfigid = -1; + GLX.glXQueryContext(dpy, ctx, GLX_FBCONFIG_ID, &fbconfigid); + + int attribs[] = {GLX_FBCONFIG_ID, fbconfigid, 0}; + + int numElems = 0; + GLXFBConfig *config = GLX.glXChooseFBConfig(dpy, DefaultScreen(dpy), attribs, &numElems); + + if(config) + data.cfg = GLX.glXGetVisualFromFBConfig(dpy, *config); + else + data.cfg = NULL; + glxhook.driver.ActivateContext(data); + + if(config) + XFree(config); + if(data.cfg) + XFree(data.cfg); } return ret; @@ -341,7 +361,25 @@ HOOK_EXPORT Bool glXMakeContextCurrent(Display *dpy, GLXDrawable draw, GLXDrawab data.wnd = draw; data.ctx = ctx; + int fbconfigid = -1; + GLX.glXQueryContext(dpy, ctx, GLX_FBCONFIG_ID, &fbconfigid); + + int attribs[] = {GLX_FBCONFIG_ID, fbconfigid, 0}; + + int numElems = 0; + GLXFBConfig *config = GLX.glXChooseFBConfig(dpy, DefaultScreen(dpy), attribs, &numElems); + + if(config) + data.cfg = GLX.glXGetVisualFromFBConfig(dpy, *config); + else + data.cfg = NULL; + glxhook.driver.ActivateContext(data); + + if(config) + XFree(config); + if(data.cfg) + XFree(data.cfg); } return ret; diff --git a/renderdoc/driver/gl/glx_platform.cpp b/renderdoc/driver/gl/glx_platform.cpp index 10aa22063..6cb1b0a28 100644 --- a/renderdoc/driver/gl/glx_platform.cpp +++ b/renderdoc/driver/gl/glx_platform.cpp @@ -55,58 +55,44 @@ class GLXPlatform : public GLPlatform return false; } - GLWindowingData MakeContext(GLWindowingData share) + GLWindowingData CloneTemporaryContext(GLWindowingData share) { - GLWindowingData ret = {}; + GLWindowingData ret = share; - if(!GLX.glXCreateContextAttribsARB) + ret.ctx = NULL; + + if(!GLX.glXCreateContext) return ret; - const int attribs[] = { - GLX_CONTEXT_MAJOR_VERSION_ARB, - 3, - GLX_CONTEXT_MINOR_VERSION_ARB, - 2, - GLX_CONTEXT_FLAGS_ARB, - 0, - GLX_CONTEXT_PROFILE_MASK_ARB, - GLX_CONTEXT_CORE_PROFILE_BIT_ARB, - 0, - 0, - }; bool is_direct = false; if(GLX.glXIsDirect) is_direct = GLX.glXIsDirect(share.dpy, share.ctx); - if(GLX.glXChooseFBConfig && GLX.glXCreatePbuffer) + XVisualInfo *cfg = share.cfg; + + if(cfg == NULL) { - // don't need to care about the fb config as we won't be using the default framebuffer - // (backbuffer) - int visAttribs[] = {0}; + static int visAttribs[] = {0}; int numCfgs = 0; GLXFBConfig *fbcfg = GLX.glXChooseFBConfig(share.dpy, DefaultScreen(share.dpy), visAttribs, &numCfgs); - // don't care about pbuffer properties as we won't render directly to this - int pbAttribs[] = {GLX_PBUFFER_WIDTH, 32, GLX_PBUFFER_HEIGHT, 32, 0}; + cfg = GLX.glXGetVisualFromFBConfig(share.dpy, fbcfg[0]); + } - if(fbcfg) - { - ret.wnd = GLX.glXCreatePbuffer(share.dpy, fbcfg[0], pbAttribs); - ret.dpy = share.dpy; - ret.ctx = GLX.glXCreateContextAttribsARB(share.dpy, fbcfg[0], share.ctx, is_direct, attribs); - } + ret.ctx = GLX.glXCreateContext(share.dpy, cfg, share.ctx, is_direct); + + if(cfg != share.cfg) + { + XFree(cfg); } return ret; } - void DeleteContext(GLWindowingData context) + void DeleteClonedContext(GLWindowingData context) { - if(context.wnd && GLX.glXDestroyPbuffer) - GLX.glXDestroyPbuffer(context.dpy, context.wnd); - if(context.ctx && GLX.glXDestroyContext) GLX.glXDestroyContext(context.dpy, context.ctx); } diff --git a/renderdoc/driver/gl/wgl_platform.cpp b/renderdoc/driver/gl/wgl_platform.cpp index 7cda07365..d045a7fc7 100644 --- a/renderdoc/driver/gl/wgl_platform.cpp +++ b/renderdoc/driver/gl/wgl_platform.cpp @@ -37,9 +37,11 @@ class WGLPlatform : public GLPlatform return false; } - GLWindowingData MakeContext(GLWindowingData share) + GLWindowingData CloneTemporaryContext(GLWindowingData share) { - GLWindowingData ret; + GLWindowingData ret = share; + ret.ctx = NULL; + if(!WGL.wglCreateContextAttribsARB) return ret; @@ -55,13 +57,13 @@ class WGLPlatform : public GLPlatform 0, 0, }; - ret.DC = share.DC; + ret.ctx = WGL.wglCreateContextAttribsARB(share.DC, share.ctx, attribs); return ret; } - void DeleteContext(GLWindowingData context) + void DeleteClonedContext(GLWindowingData context) { if(context.ctx && WGL.wglDeleteContext) WGL.wglDeleteContext(context.ctx);