Support shared GL contexts in GrContextFactory

Mostly plumbing, plus some minimal testing to make sure that
the platform APIs don't explode. I plan to add testing of
SkCrossContextImageData using this, which should verify that
textures are actually shared.

Also found a factory and some related code in the
CommandBuffer test context that was totally unused.
BUG=skia:

Change-Id: I05bbc22c4d1ef946b702a5cc7f67788785219c62
Reviewed-on: https://skia-review.googlesource.com/8808
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/tools/gpu/GrContextFactory.cpp b/tools/gpu/GrContextFactory.cpp
index 401189a..965e646 100644
--- a/tools/gpu/GrContextFactory.cpp
+++ b/tools/gpu/GrContextFactory.cpp
@@ -103,61 +103,90 @@
     GrContextFactory::kGLES_ContextType;
 #endif
 
-ContextInfo GrContextFactory::getContextInfo(ContextType type, ContextOverrides overrides) {
+ContextInfo GrContextFactory::getContextInfo(ContextType type, ContextOverrides overrides,
+                                             GrContext* shareContext, uint32_t shareIndex) {
+    // (shareIndex != 0) -> (shareContext != nullptr)
+    SkASSERT((shareIndex == 0) || (shareContext != nullptr));
+
     for (int i = 0; i < fContexts.count(); ++i) {
         Context& context = fContexts[i];
         if (context.fType == type &&
             context.fOverrides == overrides &&
+            context.fShareContext == shareContext &&
+            context.fShareIndex == shareIndex &&
             !context.fAbandoned) {
             context.fTestContext->makeCurrent();
             return ContextInfo(context.fBackend, context.fTestContext, context.fGrContext);
         }
     }
+
+    // If we're trying to create a context in a share group, find the master context
+    Context* masterContext = nullptr;
+    if (shareContext) {
+        for (int i = 0; i < fContexts.count(); ++i) {
+            if (!fContexts[i].fAbandoned && fContexts[i].fGrContext == shareContext) {
+                masterContext = &fContexts[i];
+                break;
+            }
+        }
+
+        if (!masterContext || masterContext->fType != type) {
+            return ContextInfo();
+        }
+    }
+
     std::unique_ptr<TestContext> testCtx;
-    sk_sp<GrContext> grCtx;
     GrBackendContext backendContext = 0;
     sk_sp<const GrGLInterface> glInterface;
     GrBackend backend = ContextTypeBackend(type);
     switch (backend) {
         case kOpenGL_GrBackend: {
+            GLTestContext* glShareContext = masterContext
+                    ? static_cast<GLTestContext*>(masterContext->fTestContext) : nullptr;
             GLTestContext* glCtx;
             switch (type) {
                 case kGL_ContextType:
-                    glCtx = CreatePlatformGLTestContext(kGL_GrGLStandard);
+                    glCtx = CreatePlatformGLTestContext(kGL_GrGLStandard, glShareContext);
                     break;
                 case kGLES_ContextType:
-                    glCtx = CreatePlatformGLTestContext(kGLES_GrGLStandard);
+                    glCtx = CreatePlatformGLTestContext(kGLES_GrGLStandard, glShareContext);
                     break;
 #if SK_ANGLE
                 case kANGLE_D3D9_ES2_ContextType:
-                    glCtx = MakeANGLETestContext(ANGLEBackend::kD3D9, ANGLEContextVersion::kES2).release();
+                    glCtx = MakeANGLETestContext(ANGLEBackend::kD3D9, ANGLEContextVersion::kES2,
+                                                 glShareContext).release();
                     break;
                 case kANGLE_D3D11_ES2_ContextType:
-                    glCtx = MakeANGLETestContext(ANGLEBackend::kD3D11, ANGLEContextVersion::kES2).release();
+                    glCtx = MakeANGLETestContext(ANGLEBackend::kD3D11, ANGLEContextVersion::kES2,
+                                                 glShareContext).release();
                     break;
                 case kANGLE_D3D11_ES3_ContextType:
-                    glCtx = MakeANGLETestContext(ANGLEBackend::kD3D11, ANGLEContextVersion::kES3).release();
+                    glCtx = MakeANGLETestContext(ANGLEBackend::kD3D11, ANGLEContextVersion::kES3,
+                                                 glShareContext).release();
                     break;
                 case kANGLE_GL_ES2_ContextType:
-                    glCtx = MakeANGLETestContext(ANGLEBackend::kOpenGL, ANGLEContextVersion::kES2).release();
+                    glCtx = MakeANGLETestContext(ANGLEBackend::kOpenGL, ANGLEContextVersion::kES2,
+                                                 glShareContext).release();
                     break;
                 case kANGLE_GL_ES3_ContextType:
-                    glCtx = MakeANGLETestContext(ANGLEBackend::kOpenGL, ANGLEContextVersion::kES3).release();
+                    glCtx = MakeANGLETestContext(ANGLEBackend::kOpenGL, ANGLEContextVersion::kES3,
+                                                 glShareContext).release();
                     break;
 #endif
                 case kCommandBuffer_ContextType:
-                    glCtx = CommandBufferGLTestContext::Create();
+                    glCtx = CommandBufferGLTestContext::Create(glShareContext);
                     break;
 #if SK_MESA
                 case kMESA_ContextType:
-                    glCtx = CreateMesaGLTestContext();
+                    glCtx = CreateMesaGLTestContext(glShareContext);
                     break;
 #endif
                 case kNullGL_ContextType:
-                    glCtx = CreateNullGLTestContext(ContextOverrides::kRequireNVPRSupport & overrides);
+                    glCtx = CreateNullGLTestContext(
+                            ContextOverrides::kRequireNVPRSupport & overrides, glShareContext);
                     break;
                 case kDebugGL_ContextType:
-                    glCtx = CreateDebugGLTestContext();
+                    glCtx = CreateDebugGLTestContext(glShareContext);
                     break;
                 default:
                     return ContextInfo();
@@ -178,6 +207,10 @@
         }
 #ifdef SK_VULKAN
         case kVulkan_GrBackend:
+            if (masterContext) {
+                // Shared contexts not supported yet
+                return ContextInfo();
+            }
             SkASSERT(kVulkan_ContextType == type);
             if (ContextOverrides::kRequireNVPRSupport & overrides) {
                 return ContextInfo();
@@ -211,7 +244,7 @@
     if (ContextOverrides::kAllowSRGBWithoutDecodeControl & overrides) {
         grOptions.fRequireDecodeDisableForSRGB = false;
     }
-    grCtx.reset(GrContext::Create(backend, backendContext, grOptions));
+    sk_sp<GrContext> grCtx(GrContext::Create(backend, backendContext, grOptions));
     if (!grCtx.get()) {
         return ContextInfo();
     }
@@ -238,6 +271,9 @@
     context.fType = type;
     context.fOverrides = overrides;
     context.fAbandoned = false;
+    context.fShareContext = shareContext;
+    context.fShareIndex = shareIndex;
     return ContextInfo(context.fBackend, context.fTestContext, context.fGrContext);
 }
+
 }  // namespace sk_gpu_test
diff --git a/tools/gpu/GrContextFactory.h b/tools/gpu/GrContextFactory.h
index 48b250d..e42f34c 100644
--- a/tools/gpu/GrContextFactory.h
+++ b/tools/gpu/GrContextFactory.h
@@ -144,9 +144,13 @@
 
     /**
      * Get a context initialized with a type of GL context. It also makes the GL context current.
+     * If shareContextInfo is supplied, then a context is created or returned in the same share
+     * group (able to share resources). To get multiple contexts in a single share group, pass the
+     * same shareContextInfo, with different values for shareIndex.
      */
     ContextInfo getContextInfo(ContextType type,
-                               ContextOverrides overrides = ContextOverrides::kNone);
+                               ContextOverrides overrides = ContextOverrides::kNone,
+                               GrContext* shareContext = nullptr, uint32_t shareIndex = 0);
     /**
      * Get a GrContext initialized with a type of GL context. It also makes the GL context current.
      */
@@ -162,7 +166,10 @@
         GrBackend         fBackend;
         TestContext*      fTestContext;
         GrContext*        fGrContext;
-        bool              fAbandoned;
+        GrContext*        fShareContext;
+        uint32_t          fShareIndex;
+
+        bool            fAbandoned;
     };
     SkTArray<Context, true>         fContexts;
     std::unique_ptr<GLTestContext>  fSentinelGLContext;
diff --git a/tools/gpu/gl/angle/GLTestContext_angle.cpp b/tools/gpu/gl/angle/GLTestContext_angle.cpp
index c3ec431..c0ea485 100644
--- a/tools/gpu/gl/angle/GLTestContext_angle.cpp
+++ b/tools/gpu/gl/angle/GLTestContext_angle.cpp
@@ -76,7 +76,7 @@
 
 class ANGLEGLContext : public sk_gpu_test::GLTestContext {
 public:
-    ANGLEGLContext(ANGLEBackend, ANGLEContextVersion);
+    ANGLEGLContext(ANGLEBackend, ANGLEContextVersion, ANGLEGLContext* shareContext);
     ~ANGLEGLContext() override;
 
     GrEGLImage texture2DToEGLImage(GrGLuint texID) const override;
@@ -98,7 +98,8 @@
     ANGLEContextVersion         fVersion;
 };
 
-ANGLEGLContext::ANGLEGLContext(ANGLEBackend type, ANGLEContextVersion version)
+ANGLEGLContext::ANGLEGLContext(ANGLEBackend type, ANGLEContextVersion version,
+                               ANGLEGLContext* shareContext)
     : fContext(EGL_NO_CONTEXT)
     , fDisplay(EGL_NO_DISPLAY)
     , fSurface(EGL_NO_SURFACE)
@@ -134,7 +135,8 @@
         EGL_CONTEXT_CLIENT_VERSION, versionNum,
         EGL_NONE
     };
-    fContext = eglCreateContext(fDisplay, surfaceConfig, nullptr, contextAttribs);
+    EGLContext eglShareContext = shareContext ? shareContext->fContext : nullptr;
+    fContext = eglCreateContext(fDisplay, surfaceConfig, eglShareContext, contextAttribs);
 
 
     static const EGLint surfaceAttribs[] = {
@@ -287,8 +289,10 @@
     return GrGLAssembleGLESInterface(&gLibs, angle_get_gl_proc);
 }
 
-std::unique_ptr<GLTestContext> MakeANGLETestContext(ANGLEBackend type, ANGLEContextVersion version){
-    std::unique_ptr<GLTestContext> ctx(new ANGLEGLContext(type, version));
+std::unique_ptr<GLTestContext> MakeANGLETestContext(ANGLEBackend type, ANGLEContextVersion version,
+                                                    GLTestContext* shareContext){
+    ANGLEGLContext* angleShareContext = reinterpret_cast<ANGLEGLContext*>(shareContext);
+    std::unique_ptr<GLTestContext> ctx(new ANGLEGLContext(type, version, angleShareContext));
     if (!ctx->isValid()) {
         return nullptr;
     }
diff --git a/tools/gpu/gl/angle/GLTestContext_angle.h b/tools/gpu/gl/angle/GLTestContext_angle.h
index 9314710..5433ee0 100644
--- a/tools/gpu/gl/angle/GLTestContext_angle.h
+++ b/tools/gpu/gl/angle/GLTestContext_angle.h
@@ -30,7 +30,8 @@
 };
 
 /** Creates a GLTestContext backed by ANGLE. */
-std::unique_ptr<GLTestContext> MakeANGLETestContext(ANGLEBackend, ANGLEContextVersion);
+std::unique_ptr<GLTestContext> MakeANGLETestContext(ANGLEBackend, ANGLEContextVersion,
+                                                    GLTestContext* shareContext = nullptr);
 
 }  // namespace sk_gpu_test
 #endif
diff --git a/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.cpp b/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.cpp
index 888270e..56bc5da 100644
--- a/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.cpp
+++ b/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.cpp
@@ -138,7 +138,7 @@
 
 namespace sk_gpu_test {
 
-CommandBufferGLTestContext::CommandBufferGLTestContext()
+CommandBufferGLTestContext::CommandBufferGLTestContext(CommandBufferGLTestContext* shareContext)
     : fContext(EGL_NO_CONTEXT), fDisplay(EGL_NO_DISPLAY), fSurface(EGL_NO_SURFACE) {
 
     static const EGLint configAttribs[] = {
@@ -157,32 +157,6 @@
         EGL_NONE
     };
 
-    initializeGLContext(nullptr, configAttribs, surfaceAttribs);
-}
-
-CommandBufferGLTestContext::CommandBufferGLTestContext(void *nativeWindow, int msaaSampleCount) {
-    static const EGLint surfaceAttribs[] = {EGL_NONE};
-
-    EGLint configAttribs[] = {
-        EGL_RED_SIZE, 8,
-        EGL_GREEN_SIZE, 8,
-        EGL_BLUE_SIZE, 8,
-        EGL_ALPHA_SIZE, 8,
-        EGL_DEPTH_SIZE, 8,
-        EGL_STENCIL_SIZE, 8,
-        EGL_SAMPLE_BUFFERS, 1,
-        EGL_SAMPLES, msaaSampleCount,
-        EGL_NONE
-    };
-    if (msaaSampleCount == 0) {
-        configAttribs[12] = EGL_NONE;
-    }
-
-    initializeGLContext(nativeWindow, configAttribs, surfaceAttribs);
-}
-
-void CommandBufferGLTestContext::initializeGLContext(void *nativeWindow, const int *configAttribs,
-                                                 const int *surfaceAttribs) {
     load_command_buffer_once();
     if (!gfFunctionsLoadedSuccessfully) {
         static SkOnce once;
@@ -208,16 +182,10 @@
         return;
     }
 
-    if (nativeWindow) {
-        fSurface = gfCreateWindowSurface(fDisplay,
-                                         static_cast<EGLConfig>(fConfig),
-                                         (EGLNativeWindowType) nativeWindow,
-                                         surfaceAttribs);
-    } else {
-        fSurface = gfCreatePbufferSurface(fDisplay,
-                                          static_cast<EGLConfig>(fConfig),
-                                          surfaceAttribs);
-    }
+    fSurface = gfCreatePbufferSurface(fDisplay,
+                                        static_cast<EGLConfig>(fConfig),
+                                        surfaceAttribs);
+
     if (EGL_NO_SURFACE == fSurface) {
         SkDebugf("Command Buffer: Could not create EGL surface.\n");
         this->destroyGLContext();
@@ -228,7 +196,10 @@
         EGL_CONTEXT_CLIENT_VERSION, 2,
         EGL_NONE
     };
-    fContext = gfCreateContext(fDisplay, static_cast<EGLConfig>(fConfig), nullptr, contextAttribs);
+    EGLContext eglShareContext = shareContext
+            ? reinterpret_cast<EGLContext>(shareContext->fContext) : nullptr;
+    fContext = gfCreateContext(fDisplay, static_cast<EGLConfig>(fConfig), eglShareContext,
+                               contextAttribs);
     if (EGL_NO_CONTEXT == fContext) {
         SkDebugf("Command Buffer: Could not create EGL context.\n");
         this->destroyGLContext();
diff --git a/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.h b/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.h
index 0994c98..7582f16 100644
--- a/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.h
+++ b/tools/gpu/gl/command_buffer/GLTestContext_command_buffer.h
@@ -16,17 +16,10 @@
 public:
     ~CommandBufferGLTestContext() override;
 
-    static CommandBufferGLTestContext *Create() {
-        CommandBufferGLTestContext *ctx = new CommandBufferGLTestContext;
-        if (!ctx->isValid()) {
-            delete ctx;
-            return nullptr;
-        }
-        return ctx;
-    }
-
-    static CommandBufferGLTestContext *Create(void *nativeWindow, int msaaSampleCount) {
-        CommandBufferGLTestContext *ctx = new CommandBufferGLTestContext(nativeWindow, msaaSampleCount);
+    static CommandBufferGLTestContext *Create(GLTestContext* shareContext) {
+        CommandBufferGLTestContext* cbShareContext =
+                reinterpret_cast<CommandBufferGLTestContext*>(shareContext);
+        CommandBufferGLTestContext *ctx = new CommandBufferGLTestContext(cbShareContext);
         if (!ctx->isValid()) {
             delete ctx;
             return nullptr;
@@ -43,12 +36,7 @@
     int getSampleCount();
 
 private:
-    CommandBufferGLTestContext();
-
-    CommandBufferGLTestContext(void *nativeWindow, int msaaSampleCount);
-
-    void initializeGLContext(void *nativeWindow, const int *configAttribs,
-                             const int *surfaceAttribs);
+    CommandBufferGLTestContext(CommandBufferGLTestContext* shareContext);
 
     void destroyGLContext();
 
diff --git a/tools/gpu/gl/debug/DebugGLTestContext.cpp b/tools/gpu/gl/debug/DebugGLTestContext.cpp
index cf8a9e42..e8eea8f 100644
--- a/tools/gpu/gl/debug/DebugGLTestContext.cpp
+++ b/tools/gpu/gl/debug/DebugGLTestContext.cpp
@@ -1208,7 +1208,10 @@
 }  // anonymous namespace
 
 namespace sk_gpu_test {
-GLTestContext* CreateDebugGLTestContext() {
+GLTestContext* CreateDebugGLTestContext(GLTestContext* shareContext) {
+    if (shareContext) {
+        return nullptr;
+    }
     GLTestContext* ctx = new DebugGLContext();
     if (ctx->isValid()) {
         return ctx;
diff --git a/tools/gpu/gl/debug/DebugGLTestContext.h b/tools/gpu/gl/debug/DebugGLTestContext.h
index 3f2646b..9b9abe5 100644
--- a/tools/gpu/gl/debug/DebugGLTestContext.h
+++ b/tools/gpu/gl/debug/DebugGLTestContext.h
@@ -11,7 +11,7 @@
 #include "gl/GLTestContext.h"
 
 namespace sk_gpu_test {
-GLTestContext* CreateDebugGLTestContext();
+GLTestContext* CreateDebugGLTestContext(GLTestContext* shareContext = nullptr);
 }  // namespace sk_gpu_test
 
 #endif
diff --git a/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp b/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp
index a281559..d41adff 100644
--- a/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp
+++ b/tools/gpu/gl/egl/CreatePlatformGLTestContext_egl.cpp
@@ -38,7 +38,7 @@
 
 class EGLGLTestContext : public sk_gpu_test::GLTestContext {
 public:
-    EGLGLTestContext(GrGLStandard forcedGpuAPI);
+    EGLGLTestContext(GrGLStandard forcedGpuAPI, EGLGLTestContext* shareContext);
     ~EGLGLTestContext() override;
 
     GrEGLImage texture2DToEGLImage(GrGLuint texID) const override;
@@ -58,10 +58,13 @@
     EGLSurface fSurface;
 };
 
-EGLGLTestContext::EGLGLTestContext(GrGLStandard forcedGpuAPI)
+EGLGLTestContext::EGLGLTestContext(GrGLStandard forcedGpuAPI, EGLGLTestContext* shareContext)
     : fContext(EGL_NO_CONTEXT)
     , fDisplay(EGL_NO_DISPLAY)
     , fSurface(EGL_NO_SURFACE) {
+
+    EGLContext eglShareContext = shareContext ? shareContext->fContext : nullptr;
+
     static const EGLint kEGLContextAttribsForOpenGL[] = {
         EGL_NONE
     };
@@ -142,7 +145,8 @@
             continue;
         }
 
-        fContext = eglCreateContext(fDisplay, surfaceConfig, nullptr, kAPIs[api].fContextAttribs);
+        fContext = eglCreateContext(fDisplay, surfaceConfig, eglShareContext,
+                                    kAPIs[api].fContextAttribs);
         if (EGL_NO_CONTEXT == fContext) {
             SkDebugf("eglCreateContext failed.  EGL Error: 0x%08x\n", eglGetError());
             continue;
@@ -256,7 +260,8 @@
 }
 
 std::unique_ptr<sk_gpu_test::GLTestContext> EGLGLTestContext::makeNew() const {
-    std::unique_ptr<sk_gpu_test::GLTestContext> ctx(new EGLGLTestContext(this->gl()->fStandard));
+    std::unique_ptr<sk_gpu_test::GLTestContext> ctx(new EGLGLTestContext(this->gl()->fStandard,
+                                                                         nullptr));
     if (ctx) {
         ctx->makeCurrent();
     }
@@ -327,11 +332,8 @@
 namespace sk_gpu_test {
 GLTestContext *CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI,
                                            GLTestContext *shareContext) {
-    SkASSERT(!shareContext);
-    if (shareContext) {
-        return nullptr;
-    }
-    EGLGLTestContext *ctx = new EGLGLTestContext(forcedGpuAPI);
+    EGLGLTestContext* eglShareContext = reinterpret_cast<EGLGLTestContext*>(shareContext);
+    EGLGLTestContext *ctx = new EGLGLTestContext(forcedGpuAPI, eglShareContext);
     if (!ctx->isValid()) {
         delete ctx;
         return nullptr;
diff --git a/tools/gpu/gl/iOS/CreatePlatformGLTestContext_iOS.mm b/tools/gpu/gl/iOS/CreatePlatformGLTestContext_iOS.mm
index 4c1aa01..954e88e 100644
--- a/tools/gpu/gl/iOS/CreatePlatformGLTestContext_iOS.mm
+++ b/tools/gpu/gl/iOS/CreatePlatformGLTestContext_iOS.mm
@@ -16,7 +16,7 @@
 
 class IOSGLTestContext : public sk_gpu_test::GLTestContext {
 public:
-    IOSGLTestContext();
+    IOSGLTestContext(IOSGLTestContext* shareContext);
     ~IOSGLTestContext() override;
 
 private:
@@ -30,11 +30,17 @@
     void* fGLLibrary;
 };
 
-IOSGLTestContext::IOSGLTestContext()
+IOSGLTestContext::IOSGLTestContext(IOSGLTestContext* shareContext)
     : fEAGLContext(NULL)
     , fGLLibrary(RTLD_DEFAULT) {
 
-    fEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
+    if (shareContext) {
+        EAGLContext* iosShareContext = (EAGLContext*)(shareContext->fEAGLContext);
+        fEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2
+                                            sharegroup: [iosShareContext sharegroup]];
+    } else {
+        fEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
+    }
     [EAGLContext setCurrentContext:EAGLCTX];
 
     sk_sp<const GrGLInterface> gl(GrGLCreateNativeInterface());
@@ -92,14 +98,11 @@
 namespace sk_gpu_test {
 GLTestContext *CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI,
                                            GLTestContext *shareContext) {
-    SkASSERT(!shareContext);
-    if (shareContext) {
-        return NULL;
-    }
     if (kGL_GrGLStandard == forcedGpuAPI) {
         return NULL;
     }
-    IOSGLTestContext *ctx = new IOSGLTestContext;
+    IOSGLTestContext* iosShareContext = reinterpret_cast<IOSGLTestContext*>(shareContext);
+    IOSGLTestContext *ctx = new IOSGLTestContext(iosShareContext);
     if (!ctx->isValid()) {
         delete ctx;
         return NULL;
diff --git a/tools/gpu/gl/mac/CreatePlatformGLTestContext_mac.cpp b/tools/gpu/gl/mac/CreatePlatformGLTestContext_mac.cpp
index 2a908f8..8ce687d 100644
--- a/tools/gpu/gl/mac/CreatePlatformGLTestContext_mac.cpp
+++ b/tools/gpu/gl/mac/CreatePlatformGLTestContext_mac.cpp
@@ -16,7 +16,7 @@
 namespace {
 class MacGLTestContext : public sk_gpu_test::GLTestContext {
 public:
-    MacGLTestContext();
+    MacGLTestContext(MacGLTestContext* shareContext);
     ~MacGLTestContext() override;
 
 private:
@@ -30,7 +30,7 @@
     void* fGLLibrary;
 };
 
-MacGLTestContext::MacGLTestContext()
+MacGLTestContext::MacGLTestContext(MacGLTestContext* shareContext)
     : fContext(nullptr)
     , fGLLibrary(RTLD_DEFAULT) {
     CGLPixelFormatAttribute attributes[] = {
@@ -50,7 +50,7 @@
         return;
     }
 
-    CGLCreateContext(pixFormat, nullptr, &fContext);
+    CGLCreateContext(pixFormat, shareContext ? shareContext->fContext : nullptr, &fContext);
     CGLReleasePixelFormat(pixFormat);
 
     if (nullptr == fContext) {
@@ -111,15 +111,11 @@
 namespace sk_gpu_test {
 GLTestContext* CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI,
                                            GLTestContext* shareContext) {
-    SkASSERT(!shareContext);
-    if (shareContext) {
-        return nullptr;
-    }
-
     if (kGLES_GrGLStandard == forcedGpuAPI) {
         return nullptr;
     }
-    MacGLTestContext* ctx = new MacGLTestContext;
+    MacGLTestContext* macShareContext = reinterpret_cast<MacGLTestContext*>(shareContext);
+    MacGLTestContext* ctx = new MacGLTestContext(macShareContext);
     if (!ctx->isValid()) {
         delete ctx;
         return nullptr;
diff --git a/tools/gpu/gl/mesa/GLTestContext_mesa.cpp b/tools/gpu/gl/mesa/GLTestContext_mesa.cpp
index 1a1c79d..33be94c 100644
--- a/tools/gpu/gl/mesa/GLTestContext_mesa.cpp
+++ b/tools/gpu/gl/mesa/GLTestContext_mesa.cpp
@@ -37,7 +37,7 @@
     typedef intptr_t Context;
 
 public:
-    MesaGLContext();
+    MesaGLContext(MesaGLContext* shareContext);
     ~MesaGLContext() override;
 
 private:
@@ -53,15 +53,18 @@
     GrGLubyte *fImage;
 };
 
-MesaGLContext::MesaGLContext() : fContext(static_cast<Context>(0)), fImage(nullptr) {
+MesaGLContext::MesaGLContext(MesaGLContext* shareContext)
+        : fContext(static_cast<Context>(0))
+        , fImage(nullptr) {
     GR_STATIC_ASSERT(sizeof(Context) == sizeof(OSMesaContext));
+    Context mesaShareContext = shareContext ? shareContext->fContext : nullptr;
 
     /* Create an RGBA-mode context */
 #if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305
     /* specify Z, stencil, accum sizes */
-    fContext = (Context)OSMesaCreateContextExt(OSMESA_BGRA, 0, 0, 0, nullptr);
+    fContext = (Context)OSMesaCreateContextExt(OSMESA_BGRA, 0, 0, 0, mesaShareContext);
 #else
-    fContext = (Context) OSMesaCreateContext(OSMESA_BGRA, nullptr);
+    fContext = (Context) OSMesaCreateContext(OSMESA_BGRA, mesaShareContext);
 #endif
     if (!fContext) {
         SkDebugf("OSMesaCreateContext failed!\n");
@@ -140,8 +143,9 @@
 
 
 namespace sk_gpu_test {
-GLTestContext *CreateMesaGLTestContext() {
-    MesaGLContext *ctx = new MesaGLContext;
+GLTestContext *CreateMesaGLTestContext(GLTestContext* shareContext) {
+    MesaGLContext* mesaShareContext = reinterpret_cast<MesaGLContext*>(shareContext);
+    MesaGLContext *ctx = new MesaGLContext(mesaShareContext);
     if (!ctx->isValid()) {
         delete ctx;
         return nullptr;
diff --git a/tools/gpu/gl/mesa/GLTestContext_mesa.h b/tools/gpu/gl/mesa/GLTestContext_mesa.h
index 17c072e..40184aa 100644
--- a/tools/gpu/gl/mesa/GLTestContext_mesa.h
+++ b/tools/gpu/gl/mesa/GLTestContext_mesa.h
@@ -11,7 +11,7 @@
 #include "gl/GLTestContext.h"
 
 namespace sk_gpu_test {
-GLTestContext* CreateMesaGLTestContext();
+GLTestContext* CreateMesaGLTestContext(GLTestContext* shareContext);
 }  // namespace sk_gpu_test
 
 #endif
diff --git a/tools/gpu/gl/null/NullGLTestContext.cpp b/tools/gpu/gl/null/NullGLTestContext.cpp
index dcb6231..894de07 100644
--- a/tools/gpu/gl/null/NullGLTestContext.cpp
+++ b/tools/gpu/gl/null/NullGLTestContext.cpp
@@ -29,7 +29,10 @@
 }  // anonymous namespace
 
 namespace sk_gpu_test {
-GLTestContext* CreateNullGLTestContext(bool enableNVPR) {
+GLTestContext* CreateNullGLTestContext(bool enableNVPR, GLTestContext* shareContext) {
+    if (shareContext) {
+        return nullptr;
+    }
     GLTestContext* ctx = new NullGLContext(enableNVPR);
     if (ctx->isValid()) {
         return ctx;
diff --git a/tools/gpu/gl/null/NullGLTestContext.h b/tools/gpu/gl/null/NullGLTestContext.h
index 909ec2e..9062e88 100644
--- a/tools/gpu/gl/null/NullGLTestContext.h
+++ b/tools/gpu/gl/null/NullGLTestContext.h
@@ -11,7 +11,7 @@
 #include "gl/GLTestContext.h"
 
 namespace sk_gpu_test {
-GLTestContext* CreateNullGLTestContext(bool enableNVPR);
+GLTestContext* CreateNullGLTestContext(bool enableNVPR, GLTestContext* shareContext);
 }  // namespace sk_gpu_test
 
 #endif
diff --git a/tools/gpu/gl/win/CreatePlatformGLTestContext_win.cpp b/tools/gpu/gl/win/CreatePlatformGLTestContext_win.cpp
index a37413e..af35b7b 100644
--- a/tools/gpu/gl/win/CreatePlatformGLTestContext_win.cpp
+++ b/tools/gpu/gl/win/CreatePlatformGLTestContext_win.cpp
@@ -18,8 +18,8 @@
 
 class WinGLTestContext : public sk_gpu_test::GLTestContext {
 public:
-    WinGLTestContext(GrGLStandard forcedGpuAPI);
-	~WinGLTestContext() override;
+    WinGLTestContext(GrGLStandard forcedGpuAPI, WinGLTestContext* shareContext);
+    ~WinGLTestContext() override;
 
 private:
     void destroyGLContext();
@@ -37,7 +37,7 @@
 
 ATOM WinGLTestContext::gWC = 0;
 
-WinGLTestContext::WinGLTestContext(GrGLStandard forcedGpuAPI)
+WinGLTestContext::WinGLTestContext(GrGLStandard forcedGpuAPI, WinGLTestContext* shareContext)
     : fWindow(nullptr)
     , fDeviceContext(nullptr)
     , fGlRenderContext(0)
@@ -85,13 +85,14 @@
         kGLES_GrGLStandard == forcedGpuAPI ?
         kGLES_SkWGLContextRequest : kGLPreferCompatibilityProfile_SkWGLContextRequest;
 
-    fPbufferContext = SkWGLPbufferContext::Create(fDeviceContext, 0, contextType);
+    HGLRC winShareContext = shareContext ? shareContext->fGlRenderContext : nullptr;
+    fPbufferContext = SkWGLPbufferContext::Create(fDeviceContext, 0, contextType, winShareContext);
 
     HDC dc;
     HGLRC glrc;
-
     if (nullptr == fPbufferContext) {
-        if (!(fGlRenderContext = SkCreateWGLContext(fDeviceContext, 0, false, contextType))) {
+        if (!(fGlRenderContext = SkCreateWGLContext(fDeviceContext, 0, false, contextType,
+                                                    winShareContext))) {
             SkDebugf("Could not create rendering context.\n");
             this->destroyGLContext();
             return;
@@ -189,11 +190,8 @@
 namespace sk_gpu_test {
 GLTestContext* CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI,
                                            GLTestContext *shareContext) {
-    SkASSERT(!shareContext);
-    if (shareContext) {
-        return nullptr;
-    }
-    WinGLTestContext *ctx = new WinGLTestContext(forcedGpuAPI);
+    WinGLTestContext* winShareContext = reinterpret_cast<WinGLTestContext*>(shareContext);
+    WinGLTestContext *ctx = new WinGLTestContext(forcedGpuAPI, winShareContext);
     if (!ctx->isValid()) {
         delete ctx;
         return nullptr;