aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/gpu/gl
diff options
context:
space:
mode:
authorGravatar Brian Salomon <bsalomon@google.com>2017-11-16 10:17:20 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-11-16 16:30:53 +0000
commit5627d65146cb92624b682389e017d488872228c7 (patch)
tree9b90fe789341a23d05dc0e896eeafc1a20b70a26 /tools/gpu/gl
parent47f6029d3dc5ee9e484931a13a14dcbe9d3f23d3 (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.cpp24
-rw-r--r--tools/gpu/gl/command_buffer/GLTestContext_command_buffer.cpp86
-rw-r--r--tools/gpu/gl/command_buffer/GLTestContext_command_buffer.h2
-rw-r--r--tools/gpu/gl/debug/DebugGLTestContext.cpp1
-rw-r--r--tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp25
-rw-r--r--tools/gpu/gl/glx/CreatePlatformGLTestContext_glx.cpp22
-rw-r--r--tools/gpu/gl/iOS/CreatePlatformGLTestContext_iOS.mm15
-rw-r--r--tools/gpu/gl/mac/CreatePlatformGLTestContext_mac.cpp19
-rw-r--r--tools/gpu/gl/null/NullGLTestContext.cpp1
-rw-r--r--tools/gpu/gl/win/CreatePlatformGLTestContext_win.cpp16
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;