diff options
author | Brian Salomon <bsalomon@google.com> | 2017-11-16 10:17:20 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-11-16 16:30:53 +0000 |
commit | 5627d65146cb92624b682389e017d488872228c7 (patch) | |
tree | 9b90fe789341a23d05dc0e896eeafc1a20b70a26 /tools/gpu/gl | |
parent | 47f6029d3dc5ee9e484931a13a14dcbe9d3f23d3 (diff) |
Add method to sk_gpu_test::TestContext to automatically restore the previous context.
The motivation for this is to allow a GM to create a GL context, do some some work in it, and then return to the context that was set when it was invoked.
Change-Id: Ie8496072a10f8f3ff36a08889e593a6ca961b61a
Reviewed-on: https://skia-review.googlesource.com/70720
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Diffstat (limited to 'tools/gpu/gl')
-rw-r--r-- | tools/gpu/gl/angle/GLTestContext_angle.cpp | 24 | ||||
-rw-r--r-- | tools/gpu/gl/command_buffer/GLTestContext_command_buffer.cpp | 86 | ||||
-rw-r--r-- | tools/gpu/gl/command_buffer/GLTestContext_command_buffer.h | 2 | ||||
-rw-r--r-- | tools/gpu/gl/debug/DebugGLTestContext.cpp | 1 | ||||
-rw-r--r-- | tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp | 25 | ||||
-rw-r--r-- | tools/gpu/gl/glx/CreatePlatformGLTestContext_glx.cpp | 22 | ||||
-rw-r--r-- | tools/gpu/gl/iOS/CreatePlatformGLTestContext_iOS.mm | 15 | ||||
-rw-r--r-- | tools/gpu/gl/mac/CreatePlatformGLTestContext_mac.cpp | 19 | ||||
-rw-r--r-- | tools/gpu/gl/null/NullGLTestContext.cpp | 1 | ||||
-rw-r--r-- | tools/gpu/gl/win/CreatePlatformGLTestContext_win.cpp | 16 |
10 files changed, 192 insertions, 19 deletions
diff --git a/tools/gpu/gl/angle/GLTestContext_angle.cpp b/tools/gpu/gl/angle/GLTestContext_angle.cpp index 52cc5128da..3b55c40bac 100644 --- a/tools/gpu/gl/angle/GLTestContext_angle.cpp +++ b/tools/gpu/gl/angle/GLTestContext_angle.cpp @@ -34,6 +34,16 @@ struct Libs { void* fEGLLib; }; +std::function<void()> context_restorer() { + auto display = eglGetCurrentDisplay(); + auto dsurface = eglGetCurrentSurface(EGL_DRAW); + auto rsurface = eglGetCurrentSurface(EGL_READ); + auto context = eglGetCurrentContext(); + return [display, dsurface, rsurface, context] { + eglMakeCurrent(display, dsurface, rsurface, context); + }; +} + static GrGLFuncPtr angle_get_gl_proc(void* ctx, const char name[]) { const Libs* libs = reinterpret_cast<const Libs*>(ctx); GrGLFuncPtr proc = (GrGLFuncPtr) GetProcedureAddress(libs->fGLLib, name); @@ -87,6 +97,7 @@ private: void destroyGLContext(); void onPlatformMakeCurrent() const override; + std::function<void()> onPlatformGetAutoContextRestore() const override; void onPlatformSwapBuffers() const override; GrGLFuncPtr onPlatformGetProcAddress(const char* name) const override; @@ -214,6 +225,7 @@ ANGLEGLContext::ANGLEGLContext(ANGLEBackend type, ANGLEContextVersion version, fSurface = eglCreatePbufferSurface(fDisplay, surfaceConfig, surfaceAttribs); + SkScopeExit restorer(context_restorer()); if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) { SkDebugf("Could not set the context."); this->destroyGLContext(); @@ -320,7 +332,10 @@ std::unique_ptr<sk_gpu_test::GLTestContext> ANGLEGLContext::makeNew() const { void ANGLEGLContext::destroyGLContext() { if (EGL_NO_DISPLAY != fDisplay) { - eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (eglGetCurrentContext() == fContext) { + // This will ensure that the context is immediately deleted. + eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + } if (EGL_NO_CONTEXT != fContext) { eglDestroyContext(fDisplay, fContext); @@ -355,6 +370,13 @@ void ANGLEGLContext::onPlatformMakeCurrent() const { } } +std::function<void()> ANGLEGLContext::onPlatformGetAutoContextRestore() const { + if (eglGetCurrentContext() == fContext) { + return nullptr; + } + return context_restorer(); +} + void ANGLEGLContext::onPlatformSwapBuffers() const { if (!eglSwapBuffers(fDisplay, fSurface)) { SkDebugf("Could not complete eglSwapBuffers.\n"); diff --git a/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.cpp b/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.cpp index 54845fc28b..18e150611a 100644 --- a/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.cpp +++ b/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.cpp @@ -25,6 +25,7 @@ typedef void* EGLNativeDisplayType; typedef void* EGLNativeWindowType; typedef void (*__eglMustCastToProperFunctionPointerType)(void); #define EGL_FALSE 0 +#define EGL_TRUE 1 #define EGL_OPENGL_ES2_BIT 0x0004 #define EGL_CONTEXT_CLIENT_VERSION 0x3098 #define EGL_NO_SURFACE ((EGLSurface)0) @@ -45,6 +46,8 @@ typedef void (*__eglMustCastToProperFunctionPointerType)(void); #define EGL_NONE 0x3038 #define EGL_WIDTH 0x3057 #define EGL_HEIGHT 0x3056 +#define EGL_DRAW 0x3059 +#define EGL_READ 0x305A typedef EGLDisplay (*GetDisplayProc)(EGLNativeDisplayType display_id); typedef EGLBoolean (*InitializeProc)(EGLDisplay dpy, EGLint *major, EGLint *minor); @@ -77,6 +80,37 @@ static GetProcAddressProc gfGetProcAddress = nullptr; static void* gLibrary = nullptr; static bool gfFunctionsLoadedSuccessfully = false; +// The command buffer does not correctly implement eglGetCurrent. It always returns EGL_NO_<foo>. +// So we implement them ourselves and hook eglMakeCurrent to store the current values in TLS. +thread_local EGLDisplay gCurrDisplay = EGL_NO_DISPLAY; +thread_local EGLSurface gCurrReadSurface = EGL_NO_SURFACE; +thread_local EGLSurface gCurrDrawSurface = EGL_NO_SURFACE; +thread_local EGLContext gCurrContext = EGL_NO_CONTEXT; + +EGLDisplay fakeGetCurrentDisplay() { return gCurrDisplay; } +EGLSurface fakeGetCurrentSurface(EGLint readdraw) { + switch (readdraw) { + case EGL_DRAW: + return gCurrDrawSurface; + case EGL_READ: + return gCurrReadSurface; + default: + return EGL_NO_SURFACE; + } +} +EGLContext fakeGetCurrentContext() { return gCurrContext; } + +EGLBoolean hookedMakeCurrent(EGLDisplay display, EGLSurface draw, EGLSurface read, EGLContext ctx) { + if (gfFunctionsLoadedSuccessfully && EGL_TRUE == gfMakeCurrent(display, draw, read, ctx)) { + gCurrDisplay = display; + gCurrDrawSurface = draw; + gCurrReadSurface = read; + gCurrContext = ctx; + return EGL_TRUE; + } + return EGL_FALSE; +} + namespace { static void load_command_buffer_functions() { if (!gLibrary) { @@ -104,12 +138,11 @@ static void load_command_buffer_functions() { gfSwapBuffers = (SwapBuffersProc)GetProcedureAddress(gLibrary, "eglSwapBuffers"); gfGetProcAddress = (GetProcAddressProc)GetProcedureAddress(gLibrary, "eglGetProcAddress"); - gfFunctionsLoadedSuccessfully = gfGetDisplay && gfInitialize && gfTerminate && - gfChooseConfig && gfCreateWindowSurface && - gfCreatePbufferSurface && gfDestroySurface && - gfCreateContext && gfDestroyContext && gfMakeCurrent && - gfSwapBuffers && gfGetProcAddress; - + gfFunctionsLoadedSuccessfully = + gfGetDisplay && gfInitialize && gfTerminate && gfChooseConfig && + gfCreateWindowSurface && gfCreatePbufferSurface && gfDestroySurface && + gfCreateContext && gfDestroyContext && gfMakeCurrent && gfSwapBuffers && + gfGetProcAddress; } } } @@ -134,6 +167,19 @@ static const GrGLInterface* create_command_buffer_interface() { return GrGLAssembleGLESInterface(gLibrary, command_buffer_get_gl_proc); } +std::function<void()> context_restorer() { + if (!gfFunctionsLoadedSuccessfully) { + return nullptr; + } + auto display = fakeGetCurrentDisplay(); + auto dsurface = fakeGetCurrentSurface(EGL_DRAW); + auto rsurface = fakeGetCurrentSurface(EGL_READ); + auto context = fakeGetCurrentContext(); + return [display, dsurface, rsurface, context] { + hookedMakeCurrent(display, dsurface, rsurface, context); + }; +} + } // anonymous namespace namespace sk_gpu_test { @@ -204,7 +250,8 @@ CommandBufferGLTestContext::CommandBufferGLTestContext(CommandBufferGLTestContex return; } - if (!gfMakeCurrent(fDisplay, fSurface, fSurface, fContext)) { + SkScopeExit restorer(context_restorer()); + if (!hookedMakeCurrent(fDisplay, fSurface, fSurface, fContext)) { SkDebugf("Command Buffer: Could not make EGL context current.\n"); this->destroyGLContext(); return; @@ -237,15 +284,19 @@ void CommandBufferGLTestContext::destroyGLContext() { if (EGL_NO_DISPLAY == fDisplay) { return; } + bool wasCurrent = false; if (EGL_NO_CONTEXT != fContext) { + wasCurrent = fakeGetCurrentContext() == fContext; gfDestroyContext(fDisplay, fContext); fContext = EGL_NO_CONTEXT; } - // Call MakeCurrent after destroying the context, so that the EGL implementation knows that - // the context is not used anymore after it is released from being current. This way - // command buffer does not need to abandon the context before destruction, and no - // client-side errors are printed. - gfMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (wasCurrent) { + // Call MakeCurrent after destroying the context, so that the EGL implementation knows that + // the context is not used anymore after it is released from being current.This way the + // command buffer does not need to abandon the context before destruction, and no + // client-side errors are printed. + hookedMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + } if (EGL_NO_SURFACE != fSurface) { gfDestroySurface(fDisplay, fSurface); @@ -258,11 +309,18 @@ void CommandBufferGLTestContext::onPlatformMakeCurrent() const { if (!gfFunctionsLoadedSuccessfully) { return; } - if (!gfMakeCurrent(fDisplay, fSurface, fSurface, fContext)) { + if (!hookedMakeCurrent(fDisplay, fSurface, fSurface, fContext)) { SkDebugf("Command Buffer: Could not make EGL context current.\n"); } } +std::function<void()> CommandBufferGLTestContext::onPlatformGetAutoContextRestore() const { + if (!gfFunctionsLoadedSuccessfully || fakeGetCurrentContext() == fContext) { + return nullptr; + } + return context_restorer(); +} + void CommandBufferGLTestContext::onPlatformSwapBuffers() const { if (!gfFunctionsLoadedSuccessfully) { return; @@ -288,7 +346,7 @@ void CommandBufferGLTestContext::presentCommandBuffer() { } bool CommandBufferGLTestContext::makeCurrent() { - return gfMakeCurrent(fDisplay, fSurface, fSurface, fContext) != EGL_FALSE; + return hookedMakeCurrent(fDisplay, fSurface, fSurface, fContext) != EGL_FALSE; } int CommandBufferGLTestContext::getStencilBits() { diff --git a/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.h b/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.h index 7582f16351..6a631be8fb 100644 --- a/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.h +++ b/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.h @@ -42,6 +42,8 @@ private: void onPlatformMakeCurrent() const override; + std::function<void()> onPlatformGetAutoContextRestore() const override; + void onPlatformSwapBuffers() const override; GrGLFuncPtr onPlatformGetProcAddress(const char *name) const override; diff --git a/tools/gpu/gl/debug/DebugGLTestContext.cpp b/tools/gpu/gl/debug/DebugGLTestContext.cpp index f16692e8e0..e28a3a7f13 100644 --- a/tools/gpu/gl/debug/DebugGLTestContext.cpp +++ b/tools/gpu/gl/debug/DebugGLTestContext.cpp @@ -1203,6 +1203,7 @@ public: private: void onPlatformMakeCurrent() const override {} + std::function<void()> onPlatformGetAutoContextRestore() const override { return nullptr; } void onPlatformSwapBuffers() const override {} GrGLFuncPtr onPlatformGetProcAddress(const char*) const override { return nullptr; } }; diff --git a/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp b/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp index 74cadfcb62..7fa88c094a 100644 --- a/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp +++ b/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp @@ -39,6 +39,16 @@ private: typedef sk_gpu_test::FenceSync INHERITED; }; +std::function<void()> context_restorer() { + auto display = eglGetCurrentDisplay(); + auto dsurface = eglGetCurrentSurface(EGL_DRAW); + auto rsurface = eglGetCurrentSurface(EGL_READ); + auto context = eglGetCurrentContext(); + return [display, dsurface, rsurface, context] { + eglMakeCurrent(display, dsurface, rsurface, context); + }; +} + class EGLGLTestContext : public sk_gpu_test::GLTestContext { public: EGLGLTestContext(GrGLStandard forcedGpuAPI, EGLGLTestContext* shareContext); @@ -53,6 +63,7 @@ private: void destroyGLContext(); void onPlatformMakeCurrent() const override; + std::function<void()> onPlatformGetAutoContextRestore() const override; void onPlatformSwapBuffers() const override; GrGLFuncPtr onPlatformGetProcAddress(const char*) const override; @@ -168,6 +179,7 @@ EGLGLTestContext::EGLGLTestContext(GrGLStandard forcedGpuAPI, EGLGLTestContext* continue; } + SkScopeExit restorer(context_restorer()); if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) { SkDebugf("eglMakeCurrent failed. EGL Error: 0x%08x\n", eglGetError()); this->destroyGLContext(); @@ -199,9 +211,11 @@ EGLGLTestContext::~EGLGLTestContext() { void EGLGLTestContext::destroyGLContext() { if (fDisplay) { - eglMakeCurrent(fDisplay, 0, 0, 0); - if (fContext) { + if (eglGetCurrentContext() == fContext) { + // This will ensure that the context is immediately deleted. + eglMakeCurrent(fDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + } eglDestroyContext(fDisplay, fContext); fContext = EGL_NO_CONTEXT; } @@ -284,6 +298,13 @@ void EGLGLTestContext::onPlatformMakeCurrent() const { } } +std::function<void()> EGLGLTestContext::onPlatformGetAutoContextRestore() const { + if (eglGetCurrentContext() == fContext) { + return nullptr; + } + return context_restorer(); +} + void EGLGLTestContext::onPlatformSwapBuffers() const { if (!eglSwapBuffers(fDisplay, fSurface)) { SkDebugf("Could not complete eglSwapBuffers.\n"); diff --git a/tools/gpu/gl/glx/CreatePlatformGLTestContext_glx.cpp b/tools/gpu/gl/glx/CreatePlatformGLTestContext_glx.cpp index 76b6d21661..cb1215261a 100644 --- a/tools/gpu/gl/glx/CreatePlatformGLTestContext_glx.cpp +++ b/tools/gpu/gl/glx/CreatePlatformGLTestContext_glx.cpp @@ -51,6 +51,13 @@ static int ctxErrorHandler(Display *dpy, XErrorEvent *ev) { return 0; } +std::function<void()> context_restorer() { + auto display = glXGetCurrentDisplay(); + auto drawable = glXGetCurrentDrawable(); + auto context = glXGetCurrentContext(); + return [display, drawable, context] { glXMakeCurrent(display, drawable, context); }; +} + class GLXGLTestContext : public sk_gpu_test::GLTestContext { public: GLXGLTestContext(GrGLStandard forcedGpuAPI, GLXGLTestContext* shareList); @@ -62,6 +69,7 @@ private: GLXContext glxSharedContext); void onPlatformMakeCurrent() const override; + std::function<void()> onPlatformGetAutoContextRestore() const override; void onPlatformSwapBuffers() const override; GrGLFuncPtr onPlatformGetProcAddress(const char*) const override; @@ -214,6 +222,7 @@ GLXGLTestContext::GLXGLTestContext(GrGLStandard forcedGpuAPI, GLXGLTestContext* //SkDebugf("Direct GLX rendering context obtained.\n"); } + SkScopeExit restorer(context_restorer()); //SkDebugf("Making context current.\n"); if (!glXMakeCurrent(fDisplay, fGlxPixmap, fContext)) { SkDebugf("Could not set the context.\n"); @@ -245,9 +254,11 @@ GLXGLTestContext::~GLXGLTestContext() { void GLXGLTestContext::destroyGLContext() { if (fDisplay) { - glXMakeCurrent(fDisplay, 0, 0); - if (fContext) { + if (glXGetCurrentContext() == fContext) { + // This will ensure that the context is immediately deleted. + glXMakeContextCurrent(fDisplay, None, None, nullptr); + } glXDestroyContext(fDisplay, fContext); fContext = nullptr; } @@ -334,6 +345,13 @@ void GLXGLTestContext::onPlatformMakeCurrent() const { } } +std::function<void()> GLXGLTestContext::onPlatformGetAutoContextRestore() const { + if (glXGetCurrentContext() == fContext) { + return nullptr; + } + return context_restorer(); +} + void GLXGLTestContext::onPlatformSwapBuffers() const { glXSwapBuffers(fDisplay, fGlxPixmap); } diff --git a/tools/gpu/gl/iOS/CreatePlatformGLTestContext_iOS.mm b/tools/gpu/gl/iOS/CreatePlatformGLTestContext_iOS.mm index e897e8c7c4..65d2861483 100644 --- a/tools/gpu/gl/iOS/CreatePlatformGLTestContext_iOS.mm +++ b/tools/gpu/gl/iOS/CreatePlatformGLTestContext_iOS.mm @@ -14,6 +14,11 @@ namespace { +std::function<void()> context_restorer() { + EAGLContext* context = [EAGLContext currentContext]; + return [context] { [EAGLContext setCurrentContext:context]; }; +} + class IOSGLTestContext : public sk_gpu_test::GLTestContext { public: IOSGLTestContext(IOSGLTestContext* shareContext); @@ -23,6 +28,7 @@ private: void destroyGLContext(); void onPlatformMakeCurrent() const override; + std::function<void()> onPlatformGetAutoContextRestore() const override; void onPlatformSwapBuffers() const override; GrGLFuncPtr onPlatformGetProcAddress(const char*) const override; @@ -41,6 +47,7 @@ IOSGLTestContext::IOSGLTestContext(IOSGLTestContext* shareContext) } else { fEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; } + SkScopeExit restorer(context_restorer()); [EAGLContext setCurrentContext:fEAGLContext]; sk_sp<const GrGLInterface> gl(GrGLCreateNativeInterface()); @@ -70,6 +77,7 @@ IOSGLTestContext::~IOSGLTestContext() { void IOSGLTestContext::destroyGLContext() { if (fEAGLContext) { if ([EAGLContext currentContext] == fEAGLContext) { + // This will ensure that the context is immediately deleted. [EAGLContext setCurrentContext:nil]; } fEAGLContext = nil; @@ -86,6 +94,13 @@ void IOSGLTestContext::onPlatformMakeCurrent() const { } } +std::function<void()> IOSGLTestContext::onPlatformGetAutoContextRestore() const { + if ([EAGLContext currentContext] == fEAGLContext) { + return nullptr; + } + return context_restorer(); +} + void IOSGLTestContext::onPlatformSwapBuffers() const { } GrGLFuncPtr IOSGLTestContext::onPlatformGetProcAddress(const char* procName) const { diff --git a/tools/gpu/gl/mac/CreatePlatformGLTestContext_mac.cpp b/tools/gpu/gl/mac/CreatePlatformGLTestContext_mac.cpp index a94f503d48..9f1c61e564 100644 --- a/tools/gpu/gl/mac/CreatePlatformGLTestContext_mac.cpp +++ b/tools/gpu/gl/mac/CreatePlatformGLTestContext_mac.cpp @@ -14,6 +14,12 @@ #include <dlfcn.h> namespace { + +std::function<void()> context_restorer() { + auto context = CGLGetCurrentContext(); + return [context] { CGLSetCurrentContext(context); }; +} + class MacGLTestContext : public sk_gpu_test::GLTestContext { public: MacGLTestContext(MacGLTestContext* shareContext); @@ -23,6 +29,7 @@ private: void destroyGLContext(); void onPlatformMakeCurrent() const override; + std::function<void()> onPlatformGetAutoContextRestore() const override; void onPlatformSwapBuffers() const override; GrGLFuncPtr onPlatformGetProcAddress(const char*) const override; @@ -58,6 +65,7 @@ MacGLTestContext::MacGLTestContext(MacGLTestContext* shareContext) return; } + SkScopeExit restorer(context_restorer()); CGLSetCurrentContext(fContext); sk_sp<const GrGLInterface> gl(GrGLCreateNativeInterface()); @@ -86,6 +94,10 @@ MacGLTestContext::~MacGLTestContext() { void MacGLTestContext::destroyGLContext() { if (fContext) { + if (CGLGetCurrentContext() == fContext) { + // This will ensure that the context is immediately deleted. + CGLSetCurrentContext(nullptr); + } CGLReleaseContext(fContext); fContext = nullptr; } @@ -98,6 +110,13 @@ void MacGLTestContext::onPlatformMakeCurrent() const { CGLSetCurrentContext(fContext); } +std::function<void()> MacGLTestContext::onPlatformGetAutoContextRestore() const { + if (CGLGetCurrentContext() == fContext) { + return nullptr; + } + return context_restorer(); +} + void MacGLTestContext::onPlatformSwapBuffers() const { CGLFlushDrawable(fContext); } diff --git a/tools/gpu/gl/null/NullGLTestContext.cpp b/tools/gpu/gl/null/NullGLTestContext.cpp index 894de0709a..9e7279b501 100644 --- a/tools/gpu/gl/null/NullGLTestContext.cpp +++ b/tools/gpu/gl/null/NullGLTestContext.cpp @@ -22,6 +22,7 @@ public: private: void onPlatformMakeCurrent() const override {} + std::function<void()> onPlatformGetAutoContextRestore() const override { return nullptr; } void onPlatformSwapBuffers() const override {} GrGLFuncPtr onPlatformGetProcAddress(const char*) const override { return nullptr; } }; diff --git a/tools/gpu/gl/win/CreatePlatformGLTestContext_win.cpp b/tools/gpu/gl/win/CreatePlatformGLTestContext_win.cpp index 0e97153794..5fc355a22a 100644 --- a/tools/gpu/gl/win/CreatePlatformGLTestContext_win.cpp +++ b/tools/gpu/gl/win/CreatePlatformGLTestContext_win.cpp @@ -16,6 +16,12 @@ namespace { +std::function<void()> context_restorer() { + auto glrc = wglGetCurrentContext(); + auto dc = wglGetCurrentDC(); + return [glrc, dc] { wglMakeCurrent(dc, glrc); }; +} + class WinGLTestContext : public sk_gpu_test::GLTestContext { public: WinGLTestContext(GrGLStandard forcedGpuAPI, WinGLTestContext* shareContext); @@ -25,6 +31,7 @@ private: void destroyGLContext(); void onPlatformMakeCurrent() const override; + std::function<void()> onPlatformGetAutoContextRestore() const override; void onPlatformSwapBuffers() const override; GrGLFuncPtr onPlatformGetProcAddress(const char* name) const override; @@ -113,6 +120,7 @@ WinGLTestContext::WinGLTestContext(GrGLStandard forcedGpuAPI, WinGLTestContext* glrc = fPbufferContext->getGLRC(); } + SkScopeExit restorer(context_restorer()); if (!(wglMakeCurrent(dc, glrc))) { SkDebugf("Could not set the context.\n"); this->destroyGLContext(); @@ -142,6 +150,7 @@ WinGLTestContext::~WinGLTestContext() { void WinGLTestContext::destroyGLContext() { SkSafeSetNull(fPbufferContext); if (fGlRenderContext) { + // This deletes the context immediately even if it is current. wglDeleteContext(fGlRenderContext); fGlRenderContext = 0; } @@ -172,6 +181,13 @@ void WinGLTestContext::onPlatformMakeCurrent() const { } } +std::function<void()> WinGLTestContext::onPlatformGetAutoContextRestore() const { + if (wglGetCurrentContext() == fGlRenderContext) { + return nullptr; + } + return context_restorer(); +} + void WinGLTestContext::onPlatformSwapBuffers() const { HDC dc; |