Use Windowing system-specific WindowContext factories.

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2169543002

Review-Url: https://codereview.chromium.org/2169543002
diff --git a/include/gpu/vk/GrVkBackendContext.h b/include/gpu/vk/GrVkBackendContext.h
index 25e73a4..608df83 100644
--- a/include/gpu/vk/GrVkBackendContext.h
+++ b/include/gpu/vk/GrVkBackendContext.h
@@ -51,13 +51,14 @@
     uint32_t                          fFeatures;
     SkAutoTUnref<const GrVkInterface> fInterface;
 
+    using CanPresentFn = std::function<bool(VkInstance, VkPhysicalDevice,
+                                            uint32_t queueFamilyIndex)>;
+
     // Helper function to create the default Vulkan objects needed by the GrVkGpu object
     // If presentQueueIndex is non-NULL, will try to set up presentQueue as part of device
-    // creation. canPresent() is a device-dependent function.
+    // creation using the platform-specific canPresent() function.
     static const GrVkBackendContext* Create(uint32_t* presentQueueIndex = nullptr,
-                    bool(*canPresent)(VkInstance, VkPhysicalDevice, uint32_t queueIndex,
-                                      void* platformData) = nullptr,
-                    void* platformData = nullptr);
+                                            CanPresentFn = CanPresentFn());
 
     ~GrVkBackendContext() override;
 };
diff --git a/src/gpu/vk/GrVkBackendContext.cpp b/src/gpu/vk/GrVkBackendContext.cpp
index 8256294..e859b19 100644
--- a/src/gpu/vk/GrVkBackendContext.cpp
+++ b/src/gpu/vk/GrVkBackendContext.cpp
@@ -40,9 +40,7 @@
 
 // Create the base Vulkan objects needed by the GrVkGpu object
 const GrVkBackendContext* GrVkBackendContext::Create(uint32_t* presentQueueIndexPtr,
-                             bool(*canPresent)(VkInstance, VkPhysicalDevice, uint32_t queueIndex,
-                                               void* platformData),
-                             void* platformData) {
+                                                     CanPresentFn canPresent) {
     VkPhysicalDevice physDev;
     VkDevice device;
     VkInstance inst;
@@ -161,7 +159,7 @@
     uint32_t presentQueueIndex = graphicsQueueIndex;
     if (presentQueueIndexPtr && canPresent) {
         for (uint32_t i = 0; i < queueCount; i++) {
-            if (canPresent(inst, physDev, i, platformData)) {
+            if (canPresent(inst, physDev, i)) {
                 presentQueueIndex = i;
                 break;
             }
diff --git a/tools/viewer/sk_app/GLWindowContext.cpp b/tools/viewer/sk_app/GLWindowContext.cpp
index 31ba01c..cc09abd 100644
--- a/tools/viewer/sk_app/GLWindowContext.cpp
+++ b/tools/viewer/sk_app/GLWindowContext.cpp
@@ -21,19 +21,16 @@
 
 namespace sk_app {
 
-GLWindowContext::GLWindowContext(void* platformData, const DisplayParams& params) 
+GLWindowContext::GLWindowContext(const DisplayParams& params)
     : WindowContext()
     , fBackendContext(nullptr)
     , fRenderTarget(nullptr)
     , fSurface(nullptr) {
+    fDisplayParams = params;
 }
 
-void GLWindowContext::initializeContext(void* platformData, const DisplayParams& params) {
-
-    this->onInitializeContext(platformData, params);
-
-    fDisplayParams = params;
-
+void GLWindowContext::initializeContext() {
+    this->onInitializeContext();
     SkAutoTUnref<const GrGLInterface> glInterface;
     glInterface.reset(GrGLCreateNativeInterface());
     fBackendContext.reset(GrGLInterfaceRemoveNVPR(glInterface.get()));
@@ -98,14 +95,13 @@
 
 void GLWindowContext::resize(uint32_t w, uint32_t h) {
     this->destroyContext();
-
-    this->initializeContext(nullptr, fDisplayParams);
+    this->initializeContext();
 }
 
 void GLWindowContext::setDisplayParams(const DisplayParams& params) {
     this->destroyContext();
-
-    this->initializeContext(nullptr, params);
+    fDisplayParams = params;
+    this->initializeContext();
 }
 
 }   //namespace sk_app
diff --git a/tools/viewer/sk_app/GLWindowContext.h b/tools/viewer/sk_app/GLWindowContext.h
index acf15a3..e9abffd 100644
--- a/tools/viewer/sk_app/GLWindowContext.h
+++ b/tools/viewer/sk_app/GLWindowContext.h
@@ -23,9 +23,6 @@
 
 class GLWindowContext : public WindowContext {
 public:
-    // This is defined in the platform .cpp file
-    static GLWindowContext* Create(void* platformData, const DisplayParams& params);
-
     sk_sp<SkSurface> getBackbufferSurface() override;
 
     bool isValid() override { return SkToBool(fBackendContext.get()); }
@@ -40,11 +37,18 @@
     }
 
 protected:
-    GLWindowContext(void*, const DisplayParams&);
-    void initializeContext(void*, const DisplayParams&);
-    virtual void onInitializeContext(void*, const DisplayParams&) = 0;
+    GLWindowContext(const DisplayParams&);
+    // This should be called by subclass constructor. It is also called when window/display
+    // parameters change. This will in turn call onInitializeContext().
+    void initializeContext();
+    virtual void onInitializeContext() = 0;
+
+    // This should be called by subclass destructor. It is also called when window/display
+    // parameters change prior to initializing a new GL context. This will in turn call
+    // onDestroyContext().
     void destroyContext();
     virtual void onDestroyContext() = 0;
+
     virtual void onSwapBuffers() = 0;
 
     SkAutoTUnref<const GrGLInterface> fBackendContext;
diff --git a/tools/viewer/sk_app/RasterWindowContext.h b/tools/viewer/sk_app/RasterWindowContext.h
index f116b8e..0393e9a 100644
--- a/tools/viewer/sk_app/RasterWindowContext.h
+++ b/tools/viewer/sk_app/RasterWindowContext.h
@@ -14,9 +14,6 @@
 
 class RasterWindowContext : public WindowContext {
 public:
-    // This is defined in the platform .cpp file
-    static RasterWindowContext* Create(void* platformData, const DisplayParams& params);
-
     // Explicitly convert nullptr to GrBackendContext is needed for compiling
     GrBackendContext getBackendContext() override { return (GrBackendContext) nullptr; }
 
diff --git a/tools/viewer/sk_app/VulkanWindowContext.cpp b/tools/viewer/sk_app/VulkanWindowContext.cpp
index c969f28..74c0674 100644
--- a/tools/viewer/sk_app/VulkanWindowContext.cpp
+++ b/tools/viewer/sk_app/VulkanWindowContext.cpp
@@ -25,7 +25,9 @@
 
 namespace sk_app {
 
-VulkanWindowContext::VulkanWindowContext(void* platformData, const DisplayParams& params)
+VulkanWindowContext::VulkanWindowContext(const DisplayParams& params,
+                                         CreateVkSurfaceFn createVkSurface,
+                                         CanPresentFn canPresent)
     : WindowContext()
     , fSurface(VK_NULL_HANDLE)
     , fSwapchain(VK_NULL_HANDLE)
@@ -36,13 +38,7 @@
     , fBackbuffers(nullptr) {
 
     // any config code here (particularly for msaa)?
-
-    this->initializeContext(platformData, params);
-}
-
-void VulkanWindowContext::initializeContext(void* platformData, const DisplayParams& params) {
-    fBackendContext.reset(GrVkBackendContext::Create(&fPresentQueueIndex, canPresent, 
-                                                     platformData));
+    fBackendContext.reset(GrVkBackendContext::Create(&fPresentQueueIndex, canPresent));
 
     if (!(fBackendContext->fExtensions & kKHR_surface_GrVkExtensionFlag) ||
         !(fBackendContext->fExtensions & kKHR_swapchain_GrVkExtensionFlag)) {
@@ -65,7 +61,7 @@
 
     fContext = GrContext::Create(kVulkan_GrBackend, (GrBackendContext) fBackendContext.get());
 
-    fSurface = createVkSurface(instance, platformData);
+    fSurface = createVkSurface(instance);
     if (VK_NULL_HANDLE == fSurface) {
         fBackendContext.reset(nullptr);
         return;
diff --git a/tools/viewer/sk_app/VulkanWindowContext.h b/tools/viewer/sk_app/VulkanWindowContext.h
index 63b52bc..d40adf6 100644
--- a/tools/viewer/sk_app/VulkanWindowContext.h
+++ b/tools/viewer/sk_app/VulkanWindowContext.h
@@ -23,20 +23,6 @@
 public:
     ~VulkanWindowContext() override;
 
-    // each platform will have to implement these in its CPP file
-    static VkSurfaceKHR createVkSurface(VkInstance, void* platformData);
-    static bool canPresent(VkInstance, VkPhysicalDevice, uint32_t queueFamilyIndex,
-                           void* platformData);
-
-    static VulkanWindowContext* Create(void* platformData, const DisplayParams& params) {
-        VulkanWindowContext* ctx = new VulkanWindowContext(platformData, params);
-        if (!ctx->isValid()) {
-            delete ctx;
-            return nullptr;
-        }
-        return ctx;
-    }
-
     sk_sp<SkSurface> getBackbufferSurface() override;
     void swapBuffers() override;
 
@@ -54,9 +40,14 @@
         return (GrBackendContext) fBackendContext.get(); 
     }
 
+    /** Platform specific function that creates a VkSurfaceKHR for a window */
+    using CreateVkSurfaceFn = std::function<VkSurfaceKHR(VkInstance)>;
+    /** Platform specific function that determines whether presentation will succeed. */
+    using CanPresentFn = GrVkBackendContext::CanPresentFn;
+
+    VulkanWindowContext(const DisplayParams&, CreateVkSurfaceFn, CanPresentFn);
+
 private:
-    VulkanWindowContext(void*, const DisplayParams&);
-    void initializeContext(void*, const DisplayParams&);
     void destroyContext();
 
     struct BackbufferInfo {
diff --git a/tools/viewer/sk_app/android/GLWindowContext_android.cpp b/tools/viewer/sk_app/android/GLWindowContext_android.cpp
index be62ab2..3348d80 100644
--- a/tools/viewer/sk_app/android/GLWindowContext_android.cpp
+++ b/tools/viewer/sk_app/android/GLWindowContext_android.cpp
@@ -8,50 +8,53 @@
 
 #include <GLES/gl.h> 
 
-#include "GLWindowContext_android.h"
+#include "WindowContextFactory_android.h"
+#include "../GLWindowContext.h"
+#include <EGL/egl.h>
 
-#include <android/native_window_jni.h>
+using sk_app::GLWindowContext;
+using sk_app::DisplayParams;
 
-namespace sk_app {
+namespace {
+class GLWindowContext_android : public GLWindowContext {
+public:
 
-// Most of the following 3 functions (GLWindowContext::Create, constructor, desctructor)
-// are copied from Unix/Win platform with unix/win changed to android
+    GLWindowContext_android(ANativeWindow*, const DisplayParams&);
 
-// platform-dependent create
-GLWindowContext* GLWindowContext::Create(void* platformData, const DisplayParams& params) {
-    GLWindowContext_android* ctx = new GLWindowContext_android(platformData, params);
-    if (!ctx->isValid()) {
-        delete ctx;
-        return nullptr;
-    }
-    return ctx;
-}
+    ~GLWindowContext_android() override;
 
-GLWindowContext_android::GLWindowContext_android(void* platformData, const DisplayParams& params)
-    : GLWindowContext(platformData, params)
+    void onSwapBuffers() override;
+
+    void onInitializeContext() override;
+    void onDestroyContext() override;
+
+private:
+
+    EGLDisplay fDisplay;
+    EGLContext fEGLContext;
+    EGLSurface fSurface;
+
+    // For setDisplayParams and resize which call onInitializeContext with null platformData
+    ANativeWindow* fNativeWindow = nullptr;
+};
+
+GLWindowContext_android::GLWindowContext_android(ANativeWindow* window, const DisplayParams& params)
+    : GLWindowContext(params)
     , fDisplay(EGL_NO_DISPLAY)
     , fEGLContext(EGL_NO_CONTEXT)
-    , fSurface(EGL_NO_SURFACE) {
+    , fSurface(EGL_NO_SURFACE)
+    , fNativeWindow(window) {
 
     // any config code here (particularly for msaa)?
 
-    this->initializeContext(platformData, params);
+    this->initializeContext();
 }
 
 GLWindowContext_android::~GLWindowContext_android() {
     this->destroyContext();
 }
 
-void GLWindowContext_android::onInitializeContext(void* platformData, const DisplayParams& params) {
-    if (platformData != nullptr) {
-        ContextPlatformData_android* androidPlatformData =
-                reinterpret_cast<ContextPlatformData_android*>(platformData);
-        fNativeWindow = androidPlatformData->fNativeWindow;
-    } else {
-        SkASSERT(fNativeWindow);
-    }
-
-
+void GLWindowContext_android::onInitializeContext() {
     fWidth = ANativeWindow_getWidth(fNativeWindow);
     fHeight = ANativeWindow_getHeight(fNativeWindow);
 
@@ -100,7 +103,7 @@
     };
     const EGLint* windowAttribs = nullptr;
     auto srgbColorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
-    if (srgbColorSpace == params.fColorSpace && majorVersion == 1 && minorVersion >= 2) {
+    if (srgbColorSpace == fDisplayParams.fColorSpace && majorVersion == 1 && minorVersion >= 2) {
         windowAttribs = srgbWindowAttribs;
     }
 
@@ -146,4 +149,19 @@
     }
 }
 
+}  // anonymous namespace
+
+namespace sk_app {
+namespace window_context_factory {
+
+WindowContext* NewGLForAndroid(ANativeWindow* window, const DisplayParams& params) {
+    WindowContext* ctx = new GLWindowContext_android(window, params);
+    if (!ctx->isValid()) {
+        delete ctx;
+        return nullptr;
+    }
+    return ctx;
 }
+
+}  // namespace window_context_factory
+}  // namespace sk_app
diff --git a/tools/viewer/sk_app/android/GLWindowContext_android.h b/tools/viewer/sk_app/android/GLWindowContext_android.h
deleted file mode 100644
index 5f4c031..0000000
--- a/tools/viewer/sk_app/android/GLWindowContext_android.h
+++ /dev/null
@@ -1,45 +0,0 @@
-
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#ifndef GLWindowContext_android_DEFINED
-#define GLWindowContext_android_DEFINED
-
-#include "../GLWindowContext.h"
-#include "Window_android.h"
-
-#include <EGL/egl.h>
-
-struct ANativeWindow;
-
-namespace sk_app {
-
-class GLWindowContext_android : public GLWindowContext {
-public:
-    friend GLWindowContext* GLWindowContext::Create(void* platformData, const DisplayParams&);
-
-    ~GLWindowContext_android() override;
-
-    void onSwapBuffers() override;
-
-    void onInitializeContext(void*, const DisplayParams&) override;
-    void onDestroyContext() override;
-
-private:
-    GLWindowContext_android(void*, const DisplayParams&);
-
-    EGLDisplay fDisplay;
-    EGLContext fEGLContext;
-    EGLSurface fSurface;
-
-    // For setDisplayParams and resize which call onInitializeContext with null platformData
-    ANativeWindow* fNativeWindow = nullptr;
-};
-
-
-}
-
-#endif
diff --git a/tools/viewer/sk_app/android/RasterWindowContext_android.cpp b/tools/viewer/sk_app/android/RasterWindowContext_android.cpp
index e2e2c0b..ae49405 100644
--- a/tools/viewer/sk_app/android/RasterWindowContext_android.cpp
+++ b/tools/viewer/sk_app/android/RasterWindowContext_android.cpp
@@ -6,30 +6,38 @@
  * found in the LICENSE file.
  */
 
-#include "RasterWindowContext_android.h"
-
+#include "WindowContextFactory_android.h"
+#include "../RasterWindowContext.h"
 #include "SkSurface.h"
 #include "SkTypes.h"
 
-#include "Window_android.h"
+using sk_app::RasterWindowContext;
+using sk_app::DisplayParams;
 
-namespace sk_app {
+namespace {
+class RasterWindowContext_android : public RasterWindowContext {
+public:
+    RasterWindowContext_android(ANativeWindow*, const DisplayParams& params);
 
-RasterWindowContext* RasterWindowContext::Create(void* platformData, const DisplayParams& params) {
-    RasterWindowContext* ctx = new RasterWindowContext_android(platformData, params);
-    if (!ctx->isValid()) {
-        delete ctx;
-        ctx = nullptr;
-    }
-    return ctx;
-}
+    sk_sp<SkSurface> getBackbufferSurface() override;
+    void swapBuffers() override;
 
-RasterWindowContext_android::RasterWindowContext_android(
-        void* platformData, const DisplayParams& params) {
+    bool isValid() override { return SkToBool(fNativeWindow); }
+    void resize(uint32_t w, uint32_t h) override;
+    void setDisplayParams(const DisplayParams& params) override;
+
+private:
+    void setBuffersGeometry();
+    sk_sp<SkSurface> fBackbufferSurface = nullptr;
+    ANativeWindow* fNativeWindow = nullptr;
+    ANativeWindow_Buffer fBuffer;
+    ARect fBounds;
+};
+
+RasterWindowContext_android::RasterWindowContext_android(ANativeWindow* window,
+                                                         const DisplayParams& params) {
     fDisplayParams = params;
-    ContextPlatformData_android* androidPlatformData =
-            reinterpret_cast<ContextPlatformData_android*>(platformData);
-    fNativeWindow = androidPlatformData->fNativeWindow;
+    fNativeWindow = window;
     fWidth = ANativeWindow_getWidth(fNativeWindow);
     fHeight = ANativeWindow_getHeight(fNativeWindow);
     this->setBuffersGeometry();
@@ -80,5 +88,19 @@
     ANativeWindow_unlockAndPost(fNativeWindow);
     fBackbufferSurface.reset(nullptr);
 }
+}  // anonymous namespace
 
+namespace sk_app {
+namespace window_context_factory {
+
+WindowContext* NewRasterForAndroid(ANativeWindow* window, const DisplayParams& params) {
+    WindowContext* ctx = new RasterWindowContext_android(window, params);
+    if (!ctx->isValid()) {
+        delete ctx;
+        return nullptr;
+    }
+    return ctx;
+}
+
+}
 }   // namespace sk_app
diff --git a/tools/viewer/sk_app/android/RasterWindowContext_android.h b/tools/viewer/sk_app/android/RasterWindowContext_android.h
deleted file mode 100644
index 7bb24ba..0000000
--- a/tools/viewer/sk_app/android/RasterWindowContext_android.h
+++ /dev/null
@@ -1,40 +0,0 @@
-
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#ifndef RasterWindowContext_android_DEFINED
-#define RasterWindowContext_android_DEFINED
-
-#include <android/native_window_jni.h>
-
-#include "../RasterWindowContext.h"
-
-namespace sk_app {
-
-class RasterWindowContext_android : public RasterWindowContext {
-public:
-    friend RasterWindowContext* RasterWindowContext::Create(
-            void* platformData, const DisplayParams&);
-
-    sk_sp<SkSurface> getBackbufferSurface() override;
-    void swapBuffers() override;
-
-    bool isValid() override { return SkToBool(fNativeWindow); }
-    void resize(uint32_t w, uint32_t h) override;
-    void setDisplayParams(const DisplayParams& params) override;
-
-private:
-    RasterWindowContext_android(void* platformData, const DisplayParams& params);
-    void setBuffersGeometry();
-    sk_sp<SkSurface> fBackbufferSurface = nullptr;
-    ANativeWindow* fNativeWindow = nullptr;
-    ANativeWindow_Buffer fBuffer;
-    ARect fBounds;
-};
-
-}   // namespace sk_app
-
-#endif
diff --git a/tools/viewer/sk_app/android/VulkanWindowContext_android.cpp b/tools/viewer/sk_app/android/VulkanWindowContext_android.cpp
index 15dc0b0..68f2051 100644
--- a/tools/viewer/sk_app/android/VulkanWindowContext_android.cpp
+++ b/tools/viewer/sk_app/android/VulkanWindowContext_android.cpp
@@ -6,43 +6,47 @@
  * found in the LICENSE file.
  */
 
+#include "WindowContextFactory_android.h"
 #include "../VulkanWindowContext.h"
-#include "WindowContext_android.h"
-
-#include "vk/GrVkInterface.h"
-#include "vk/GrVkUtil.h"
 
 namespace sk_app {
 
-VkSurfaceKHR VulkanWindowContext::createVkSurface(VkInstance instance, void* platformData) {
-    static PFN_vkCreateAndroidSurfaceKHR createAndroidSurfaceKHR = nullptr;
-    if (!createAndroidSurfaceKHR) {
-        createAndroidSurfaceKHR = (PFN_vkCreateAndroidSurfaceKHR)vkGetInstanceProcAddr(instance,
-                                                                       "vkCreateAndroidSurfaceKHR");
+namespace window_context_factory {
+
+WindowContext* NewVulkanForAndroid(ANativeWindow* window, const DisplayParams& params) {
+    auto createVkSurface = [window] (VkInstance instance) -> VkSurfaceKHR {
+        static PFN_vkCreateAndroidSurfaceKHR createAndroidSurfaceKHR = nullptr;
+        if (!createAndroidSurfaceKHR) {
+            createAndroidSurfaceKHR = (PFN_vkCreateAndroidSurfaceKHR)vkGetInstanceProcAddr(
+                instance, "vkCreateAndroidSurfaceKHR");
+        }
+
+        if (!window) {
+            return VK_NULL_HANDLE;
+        }
+        VkSurfaceKHR surface;
+
+        VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo;
+        memset(&surfaceCreateInfo, 0, sizeof(VkAndroidSurfaceCreateInfoKHR));
+        surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
+        surfaceCreateInfo.pNext = nullptr;
+        surfaceCreateInfo.flags = 0;
+        surfaceCreateInfo.window = window;
+
+        VkResult res = createAndroidSurfaceKHR(instance, &surfaceCreateInfo,
+                                               nullptr, &surface);
+        return (VK_SUCCESS == res) ? surface : VK_NULL_HANDLE;
+    };
+
+    auto canPresent = [](VkInstance, VkPhysicalDevice, uint32_t) { return true; };
+
+    WindowContext* ctx = new VulkanWindowContext(params, createVkSurface, canPresent);
+    if (!ctx->isValid()) {
+        delete ctx;
+        return nullptr;
     }
-
-    if (!platformData) {
-        return VK_NULL_HANDLE;
-    }
-    ContextPlatformData_android* androidPlatformData =
-                                           reinterpret_cast<ContextPlatformData_android*>(platformData);
-    VkSurfaceKHR surface;
-
-    VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo;
-    memset(&surfaceCreateInfo, 0, sizeof(VkAndroidSurfaceCreateInfoKHR));
-    surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
-    surfaceCreateInfo.pNext = nullptr;
-    surfaceCreateInfo.flags = 0;
-    surfaceCreateInfo.window = androidPlatformData->fNativeWindow;
-
-    VkResult res = createAndroidSurfaceKHR(instance, &surfaceCreateInfo,
-                                           nullptr, &surface);
-    return (VK_SUCCESS == res) ? surface : VK_NULL_HANDLE;
+    return ctx;
 }
 
-bool VulkanWindowContext::canPresent(VkInstance instance, VkPhysicalDevice physDev,
-                                     uint32_t queueFamilyIndex, void*) {
-    return true;
-}
-
-}   // namespace sk_app
+}  // namespace window_context_factory
+}  // namespace sk_app
diff --git a/tools/viewer/sk_app/android/WindowContextFactory_android.h b/tools/viewer/sk_app/android/WindowContextFactory_android.h
new file mode 100644
index 0000000..00198da
--- /dev/null
+++ b/tools/viewer/sk_app/android/WindowContextFactory_android.h
@@ -0,0 +1,32 @@
+
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef WindowContextFactory_android_DEFINED
+#define WindowContextFactory_android_DEFINED
+
+#include <android/native_window_jni.h>
+
+
+namespace sk_app {
+
+class WindowContext;
+struct DisplayParams;
+
+namespace window_context_factory {
+
+WindowContext* NewVulkanForAndroid(ANativeWindow*, const DisplayParams&);
+
+WindowContext* NewGLForAndroid(ANativeWindow*, const DisplayParams&);
+
+WindowContext* NewRasterForAndroid(ANativeWindow*, const DisplayParams&);
+
+}  // namespace window_context_factory
+
+}  // namespace sk_app
+
+#endif
diff --git a/tools/viewer/sk_app/android/WindowContext_android.h b/tools/viewer/sk_app/android/WindowContext_android.h
deleted file mode 100644
index f0529fe..0000000
--- a/tools/viewer/sk_app/android/WindowContext_android.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
-* Copyright 2016 Google Inc.
-*
-* Use of this source code is governed by a BSD-style license that can be
-* found in the LICENSE file.
-*/
-
-#ifndef WindowContext_android_DEFINED
-#define WindowContext_android_DEFINED
-
-#include <android/native_window_jni.h>
-
-namespace sk_app {
-
-struct ContextPlatformData_android {
-    ANativeWindow* fNativeWindow;
-};
-
-}   // namespace sk_app
-
-#endif // WindowContext_android_DEFINED
diff --git a/tools/viewer/sk_app/android/Window_android.cpp b/tools/viewer/sk_app/android/Window_android.cpp
index 60d89eb..86f20be 100644
--- a/tools/viewer/sk_app/android/Window_android.cpp
+++ b/tools/viewer/sk_app/android/Window_android.cpp
@@ -6,11 +6,8 @@
 */
 
 #include "Window_android.h"
-#include "../GLWindowContext.h"
-#ifdef SK_VULKAN
-#include "../VulkanWindowContext.h"
-#endif
-#include "../RasterWindowContext.h"
+#include "WindowContextFactory_android.h"
+#include "../WindowContext.h"
 
 namespace sk_app {
 
@@ -60,19 +57,17 @@
 
 void Window_android::initDisplay(ANativeWindow* window) {
     SkASSERT(window);
-    ContextPlatformData_android platformData;
-    platformData.fNativeWindow = window;
     switch (fBackendType) {
         case kNativeGL_BackendType:
         default:
-            fWindowContext = GLWindowContext::Create((void*)&platformData, fDisplayParams);
+            fWindowContext = window_context_factory::NewGLForAndroid(window, fDisplayParams);
             break;
         case kRaster_BackendType:
-            fWindowContext = RasterWindowContext::Create((void*)&platformData, fDisplayParams);
+            fWindowContext = window_context_factory::NewRasterForAndroid(window, fDisplayParams);
             break;
 #ifdef SK_VULKAN
         case kVulkan_BackendType:
-            fWindowContext = VulkanWindowContext::Create((void*)&platformData, fDisplayParams);
+            fWindowContext = window_context_factory::NewVulkanForAndroid(window, fDisplayParams);
             break;
 #endif
     }
diff --git a/tools/viewer/sk_app/android/Window_android.h b/tools/viewer/sk_app/android/Window_android.h
index f61ad6f..b6e37cb 100644
--- a/tools/viewer/sk_app/android/Window_android.h
+++ b/tools/viewer/sk_app/android/Window_android.h
@@ -9,7 +9,6 @@
 #define Window_android_DEFINED
 
 #include "../Window.h"
-#include "WindowContext_android.h"
 #include "surface_glue_android.h"
 
 namespace sk_app {
diff --git a/tools/viewer/sk_app/mac/GLWindowContext_mac.cpp b/tools/viewer/sk_app/mac/GLWindowContext_mac.cpp
index aa700e3..c2de0df 100644
--- a/tools/viewer/sk_app/mac/GLWindowContext_mac.cpp
+++ b/tools/viewer/sk_app/mac/GLWindowContext_mac.cpp
@@ -6,26 +6,41 @@
  * found in the LICENSE file.
  */
 
-#include "GLWindowContext_mac.h"
+#include "../GLWindowContext.h"
+#include "WindowContextFactory_mac.h"
 
 //#include <GL/gl.h>
 
-#include "Window_mac.h"
+using sk_app::DisplayParams;
+using sk_app::window_context_factory::MacWindowInfo;
+using sk_app::GLWindowContext;
 
-namespace sk_app {
+namespace {
 
-// platform-dependent create
-GLWindowContext* GLWindowContext::Create(void* platformData, const DisplayParams& params) {
-    GLWindowContext_mac* ctx = new GLWindowContext_mac(platformData, params);
-    if (!ctx->isValid()) {
-        delete ctx;
-        return nullptr;
-    }
-    return ctx;
-}
+class GLWindowContext_mac : public GLWindowContext {
+public:
+    GLWindowContext_mac(const MacWindowInfo&, const DisplayParams&);
+    
+    ~GLWindowContext_mac() override;
+    
+    void onSwapBuffers() override;
+    
+    void onInitializeContext() override;
+    void onDestroyContext() override;
+    
+private:
+  
+#if 0
+    // TODO: add Mac-specific GL display objects
+    Display*     fDisplay;
+    XWindow      fWindow;
+    XVisualInfo* fVisualInfo;
+    GLXContext   fGLContext;
+#endif
+};
 
-GLWindowContext_mac::GLWindowContext_mac(void* platformData, const DisplayParams& params)
-    : GLWindowContext(platformData, params)
+GLWindowContext_mac::GLWindowContext_mac(const MacWindowInfo& info, const DisplayParams& params)
+    : GLWindowContext(params)
 #if 0
     // TODO: init Mac-specific OpenGL objects
     , fDisplay(nullptr)
@@ -36,24 +51,16 @@
 
     // any config code here (particularly for msaa)?
 
-    this->initializeContext(platformData, params);
+    this->initializeContext();
 }
 
 GLWindowContext_mac::~GLWindowContext_mac() {
     this->destroyContext();
 }
 
-void GLWindowContext_mac::onInitializeContext(void* platformData, const DisplayParams& params) {
+void GLWindowContext_mac::onInitializeContext() {
 #if 0
     // TODO: Init for Mac
-    ContextPlatformData_mac* unixPlatformData =
-        reinterpret_cast<ContextPlatformData_mac*>(platformData);
-
-    if (unixPlatformData) {
-        fDisplay = unixPlatformData->fDisplay;
-        fWindow = unixPlatformData->fWindow;
-        fVisualInfo = unixPlatformData->fVisualInfo;
-    }
     SkASSERT(fDisplay);
 
     fGLContext = glXCreateContext(fDisplay, fVisualInfo, nullptr, GL_TRUE);
@@ -107,5 +114,20 @@
 #endif
 }
 
+}  // anonymous namespace
 
-}   //namespace sk_app
+
+namespace sk_app {
+namespace window_context_factory {
+
+WindowContext* MakeGLForMac(const MacWindowInfo& info, const DisplayParams& params) {
+    WindowContext* ctx = new GLWindowContext_mac(info, params);
+    if (!ctx->isValid()) {
+        delete ctx;
+        return nullptr;
+    }
+    return ctx;
+}
+
+}  // namespace window_context_factory
+}  // namespace sk_app
diff --git a/tools/viewer/sk_app/mac/GLWindowContext_mac.h b/tools/viewer/sk_app/mac/GLWindowContext_mac.h
deleted file mode 100644
index e889c4c..0000000
--- a/tools/viewer/sk_app/mac/GLWindowContext_mac.h
+++ /dev/null
@@ -1,42 +0,0 @@
-
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#ifndef GLWindowContext_mac_DEFINED
-#define GLWindowContext_mac_DEFINED
-
-#include "../GLWindowContext.h"
-#include "Window_mac.h"
-
-namespace sk_app {
-
-class GLWindowContext_mac : public GLWindowContext {
-public:
-    friend GLWindowContext* GLWindowContext::Create(void* platformData, const DisplayParams&);
-
-    ~GLWindowContext_mac() override;
-
-    void onSwapBuffers() override;
-
-    void onInitializeContext(void*, const DisplayParams&) override;
-    void onDestroyContext() override;
-
-private:
-    GLWindowContext_mac(void*, const DisplayParams&);
-
-#if 0
-    // TODO: add Mac-specific GL display objects
-    Display*     fDisplay;
-    XWindow      fWindow;
-    XVisualInfo* fVisualInfo;
-    GLXContext   fGLContext;
-#endif
-};
-
-
-}
-
-#endif
diff --git a/tools/viewer/sk_app/mac/WindowContextFactory_mac.h b/tools/viewer/sk_app/mac/WindowContextFactory_mac.h
new file mode 100644
index 0000000..a86fc73
--- /dev/null
+++ b/tools/viewer/sk_app/mac/WindowContextFactory_mac.h
@@ -0,0 +1,38 @@
+
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef WindowContextFactory_mac_DEFINED
+#define WindowContextFactory_mac_DEFINED
+
+namespace sk_app {
+
+class WindowContext;
+struct DisplayParams;
+
+namespace window_context_factory {
+
+struct MacWindowInfo {
+#if 0 // TODO: use Mac-specific objects
+    Display*     fDisplay;
+    XWindow      fWindow;
+    XVisualInfo* fVisualInfo;
+#endif
+};
+
+inline WindowContext* NewVulkanForMac(const MacWindowInfo&, const DisplayParams&) {
+    // No Vulkan support on Mac.
+    return nullptr;
+}
+
+WindowContext* NewGLForMac(const MacWindowInfo&, const DisplayParams&);
+
+}  // namespace window_context_factory
+
+}  // namespace sk_app
+
+#endif
diff --git a/tools/viewer/sk_app/mac/Window_mac.cpp b/tools/viewer/sk_app/mac/Window_mac.cpp
index fdc6f80..b1ab5c9 100644
--- a/tools/viewer/sk_app/mac/Window_mac.cpp
+++ b/tools/viewer/sk_app/mac/Window_mac.cpp
@@ -9,7 +9,7 @@
 
 #include "SkUtils.h"
 #include "Timer.h"
-#include "../GLWindowContext.h"
+#include "WindowContextFactory_mac.h"
 #include "Window_mac.h"
 
 namespace sk_app {
@@ -270,19 +270,20 @@
 bool Window_mac::attach(BackendType attachType, const DisplayParams& params) {
     this->initWindow(fDisplay, &params);
 
-    ContextPlatformData_mac platformData;
-    platformData.fDisplay = fDisplay;
-    platformData.fWindow = fWindow;
-    platformData.fVisualInfo = fVisualInfo;
+    MacWindowInfo info;
+#if 0
+    // Init Mac window info here
+    info.foo = foo;
+#endif
     switch (attachType) {
 #ifdef SK_VULKAN
         case kVulkan_BackendType:
-            fWindowContext = VulkanWindowContext::Create((void*)&platformData, params);
+            fWindowContext = NewVulkanForMac(info, params);
             break;
 #endif
         case kNativeGL_BackendType:
         default:
-            fWindowContext = GLWindowContext::Create((void*)&platformData, params);
+            fWindowContext = NewGLForMac(info, params);
             break;
     }
 
diff --git a/tools/viewer/sk_app/mac/Window_mac.h b/tools/viewer/sk_app/mac/Window_mac.h
index 016b134..a5f2aa1 100644
--- a/tools/viewer/sk_app/mac/Window_mac.h
+++ b/tools/viewer/sk_app/mac/Window_mac.h
@@ -14,15 +14,6 @@
 
 namespace sk_app {
 
-struct ContextPlatformData_mac {
-#if 0
-    // TODO: use Mac-specific objects
-    Display*     fDisplay;
-    XWindow      fWindow;
-    XVisualInfo* fVisualInfo;
-#endif
-};
-
 class Window_mac : public Window {
 public:
     Window_mac() : Window()
diff --git a/tools/viewer/sk_app/unix/GLWindowContext_unix.cpp b/tools/viewer/sk_app/unix/GLWindowContext_unix.cpp
index cde1eb2..6df1a52 100644
--- a/tools/viewer/sk_app/unix/GLWindowContext_unix.cpp
+++ b/tools/viewer/sk_app/unix/GLWindowContext_unix.cpp
@@ -6,50 +6,50 @@
  * found in the LICENSE file.
  */
 
-#include "GLWindowContext_unix.h"
+#include "../GLWindowContext.h"
+#include "WindowContextFactory_unix.h"
 
 #include <GL/gl.h>
 
-#include "Window_unix.h"
+using sk_app::window_context_factory::XlibWindowInfo;
+using sk_app::DisplayParams;
+using sk_app::GLWindowContext;
 
-namespace sk_app {
+namespace {
 
-// platform-dependent create
-GLWindowContext* GLWindowContext::Create(void* platformData, const DisplayParams& params) {
-    GLWindowContext_unix* ctx = new GLWindowContext_unix(platformData, params);
-    if (!ctx->isValid()) {
-        delete ctx;
-        return nullptr;
-    }
-    return ctx;
+class GLWindowContext_xlib : public GLWindowContext {
+public:
+    GLWindowContext_xlib(const XlibWindowInfo&, const DisplayParams&);
+    ~GLWindowContext_xlib() override;
+
+    void onSwapBuffers() override;
+
+    void onDestroyContext() override;
+
+protected:
+    void onInitializeContext() override;
+
+private:
+    GLWindowContext_xlib(void*, const DisplayParams&);
+
+    Display*     fDisplay;
+    XWindow      fWindow;
+    XVisualInfo* fVisualInfo;
+    GLXContext   fGLContext;
+};
+
+GLWindowContext_xlib::GLWindowContext_xlib(const XlibWindowInfo& winInfo, const DisplayParams& params)
+        : GLWindowContext(params)
+        , fDisplay(winInfo.fDisplay)
+        , fWindow(winInfo.fWindow)
+        , fVisualInfo(winInfo.fVisualInfo)
+        , fGLContext() {
+    this->initializeContext();
 }
 
-GLWindowContext_unix::GLWindowContext_unix(void* platformData, const DisplayParams& params)
-    : GLWindowContext(platformData, params)
-    , fDisplay(nullptr)
-    , fWindow(0)
-    , fGLContext(0) {
-
+void GLWindowContext_xlib::onInitializeContext() {
     // any config code here (particularly for msaa)?
-
-    this->initializeContext(platformData, params);
-}
-
-GLWindowContext_unix::~GLWindowContext_unix() {
-    this->destroyContext();
-}
-
-void GLWindowContext_unix::onInitializeContext(void* platformData, const DisplayParams& params) {
-    ContextPlatformData_unix* unixPlatformData =
-        reinterpret_cast<ContextPlatformData_unix*>(platformData);
-
-    if (unixPlatformData) {
-        fDisplay = unixPlatformData->fDisplay;
-        fWindow = unixPlatformData->fWindow;
-        fVisualInfo = unixPlatformData->fVisualInfo;
-    }
     SkASSERT(fDisplay);
-
     fGLContext = glXCreateContext(fDisplay, fVisualInfo, nullptr, GL_TRUE);
     if (!fGLContext) {
         return;
@@ -73,12 +73,16 @@
         int x, y;
         unsigned int border_width, depth;
         XGetGeometry(fDisplay, fWindow, &root, &x, &y,
-                     (unsigned int*)&fWidth, (unsigned int*)&fHeight, &border_width, &depth); 
+                     (unsigned int*)&fWidth, (unsigned int*)&fHeight, &border_width, &depth);
         glViewport(0, 0, fWidth, fHeight);
     }
 }
 
-void GLWindowContext_unix::onDestroyContext() {
+GLWindowContext_xlib::~GLWindowContext_xlib() {
+    this->destroyContext();
+}
+
+void GLWindowContext_xlib::onDestroyContext() {
     if (!fDisplay || !fGLContext) {
         return;
     }
@@ -87,12 +91,27 @@
     fGLContext = nullptr;
 }
 
-
-void GLWindowContext_unix::onSwapBuffers() {
+void GLWindowContext_xlib::onSwapBuffers() {
     if (fDisplay && fGLContext) {
         glXSwapBuffers(fDisplay, fWindow);
     }
 }
 
+}  // anonymous namespace
 
-}   //namespace sk_app
+namespace sk_app {
+
+namespace window_context_factory {
+
+WindowContext* NewGLForXlib(const XlibWindowInfo& winInfo, const DisplayParams& params) {
+    WindowContext* ctx = new GLWindowContext_xlib(winInfo, params);
+    if (!ctx->isValid()) {
+        delete ctx;
+        return nullptr;
+    }
+    return ctx;
+}
+
+}  // namespace window_context_factory
+
+}  // namespace sk_app
diff --git a/tools/viewer/sk_app/unix/GLWindowContext_unix.h b/tools/viewer/sk_app/unix/GLWindowContext_unix.h
deleted file mode 100644
index 2d76254..0000000
--- a/tools/viewer/sk_app/unix/GLWindowContext_unix.h
+++ /dev/null
@@ -1,39 +0,0 @@
-
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#ifndef GLWindowContext_unix_DEFINED
-#define GLWindowContext_unix_DEFINED
-
-#include "../GLWindowContext.h"
-#include "Window_unix.h"
-
-namespace sk_app {
-
-class GLWindowContext_unix : public GLWindowContext {
-public:
-    friend GLWindowContext* GLWindowContext::Create(void* platformData, const DisplayParams&);
-
-    ~GLWindowContext_unix() override;
-
-    void onSwapBuffers() override;
-
-    void onInitializeContext(void*, const DisplayParams&) override;
-    void onDestroyContext() override;
-
-private:
-    GLWindowContext_unix(void*, const DisplayParams&);
-
-    Display*     fDisplay;
-    XWindow      fWindow;
-    XVisualInfo* fVisualInfo;
-    GLXContext   fGLContext;
-};
-
-
-}
-
-#endif
diff --git a/tools/viewer/sk_app/unix/VulkanWindowContext_unix.cpp b/tools/viewer/sk_app/unix/VulkanWindowContext_unix.cpp
index 02bf516..b94e8ed 100644
--- a/tools/viewer/sk_app/unix/VulkanWindowContext_unix.cpp
+++ b/tools/viewer/sk_app/unix/VulkanWindowContext_unix.cpp
@@ -6,70 +6,74 @@
  * found in the LICENSE file.
  */
 
-#include "../VulkanWindowContext.h"
-#include "Window_unix.h"
 
 #include "vk/GrVkInterface.h"
 #include "vk/GrVkUtil.h"
 
 #include <X11/Xlib-xcb.h>
 
+#include "WindowContextFactory_unix.h"
+#include "../VulkanWindowContext.h"
+
 namespace sk_app {
 
-// Platform dependant call
-VkSurfaceKHR VulkanWindowContext::createVkSurface(VkInstance instance, void* platformData) {
-    static PFN_vkCreateXcbSurfaceKHR createXcbSurfaceKHR = nullptr;
-    if (!createXcbSurfaceKHR) {
-        createXcbSurfaceKHR = (PFN_vkCreateXcbSurfaceKHR) vkGetInstanceProcAddr(instance,
-                                                                        "vkCreateXcbSurfaceKHR");
+namespace window_context_factory {
+
+WindowContext* NewVulkanForXlib(const XlibWindowInfo& info, const DisplayParams& displayParams) {
+    auto createVkSurface = [&info](VkInstance instance) -> VkSurfaceKHR {
+        static PFN_vkCreateXcbSurfaceKHR createXcbSurfaceKHR = nullptr;
+        if (!createXcbSurfaceKHR) {
+            createXcbSurfaceKHR =
+                    (PFN_vkCreateXcbSurfaceKHR) vkGetInstanceProcAddr(instance,
+                                                                      "vkCreateXcbSurfaceKHR");
+        }
+
+        VkSurfaceKHR surface;
+
+        VkXcbSurfaceCreateInfoKHR surfaceCreateInfo;
+        memset(&surfaceCreateInfo, 0, sizeof(VkXcbSurfaceCreateInfoKHR));
+        surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
+        surfaceCreateInfo.pNext = nullptr;
+        surfaceCreateInfo.flags = 0;
+        surfaceCreateInfo.connection = XGetXCBConnection(info.fDisplay);
+        surfaceCreateInfo.window = info.fWindow;
+
+        VkResult res = createXcbSurfaceKHR(instance, &surfaceCreateInfo, nullptr, &surface);
+        if (VK_SUCCESS != res) {
+            return VK_NULL_HANDLE;
+        }
+
+        return surface;
+    };
+
+    auto canPresent = [&info](VkInstance instance, VkPhysicalDevice physDev,
+                              uint32_t queueFamilyIndex) {
+        static PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR
+                                                getPhysicalDeviceXcbPresentationSupportKHR = nullptr;
+        if (!getPhysicalDeviceXcbPresentationSupportKHR) {
+            getPhysicalDeviceXcbPresentationSupportKHR =
+                (PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)
+                        vkGetInstanceProcAddr(instance,
+                                              "vkGetPhysicalDeviceXcbPresentationSupportKHR");
+        }
+
+
+        Display* display = info.fDisplay;
+        VisualID visualID = info.fVisualInfo->visualid;
+        VkBool32 check = getPhysicalDeviceXcbPresentationSupportKHR(physDev,
+                                                                    queueFamilyIndex,
+                                                                    XGetXCBConnection(display),
+                                                                    visualID);
+        return (VK_FALSE != check);
+    };
+    WindowContext* context = new VulkanWindowContext(displayParams, createVkSurface, canPresent);
+    if (!context->isValid()) {
+        delete context;
+        return nullptr;
     }
-
-    if (!platformData) {
-        return VK_NULL_HANDLE;
-    }
-    ContextPlatformData_unix* unixPlatformData =
-                                          reinterpret_cast<ContextPlatformData_unix*>(platformData);
-
-
-    VkSurfaceKHR surface;
-
-    VkXcbSurfaceCreateInfoKHR surfaceCreateInfo;
-    memset(&surfaceCreateInfo, 0, sizeof(VkXcbSurfaceCreateInfoKHR));
-    surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
-    surfaceCreateInfo.pNext = nullptr;
-    surfaceCreateInfo.flags = 0;
-    surfaceCreateInfo.connection = XGetXCBConnection(unixPlatformData->fDisplay);
-    surfaceCreateInfo.window = unixPlatformData->fWindow;
-
-    VkResult res = createXcbSurfaceKHR(instance, &surfaceCreateInfo, nullptr, &surface);
-    if (VK_SUCCESS != res) {
-        return VK_NULL_HANDLE;
-    }
-
-    return surface;
+    return context;
 }
 
-// Platform dependant call
-bool VulkanWindowContext::canPresent(VkInstance instance, VkPhysicalDevice physDev,
-                                     uint32_t queueFamilyIndex, void* platformData) {
-    static PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR
-                                            getPhysicalDeviceXcbPresentationSupportKHR = nullptr;
-    if (!getPhysicalDeviceXcbPresentationSupportKHR) {
-        getPhysicalDeviceXcbPresentationSupportKHR =
-            (PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR) vkGetInstanceProcAddr(instance,
-                                                 "vkGetPhysicalDeviceXcbPresentationSupportKHR");
-    }
+}  // namespace VulkanWindowContextFactory
 
-    ContextPlatformData_unix* unixPlatformData =
-                                          reinterpret_cast<ContextPlatformData_unix*>(platformData);
-
-    Display* display = unixPlatformData->fDisplay;
-    VisualID visualID = unixPlatformData->fVisualInfo->visualid;
-    VkBool32 check = getPhysicalDeviceXcbPresentationSupportKHR(physDev, 
-                                                                queueFamilyIndex, 
-                                                                XGetXCBConnection(display),
-                                                                visualID);
-    return (VK_FALSE != check);
-}
-
-}   // namespace sk_app
+}  // namespace sk_app
diff --git a/tools/viewer/sk_app/unix/WindowContextFactory_unix.h b/tools/viewer/sk_app/unix/WindowContextFactory_unix.h
new file mode 100644
index 0000000..fb15689
--- /dev/null
+++ b/tools/viewer/sk_app/unix/WindowContextFactory_unix.h
@@ -0,0 +1,37 @@
+
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef WindowContextFactory_unix_DEFINED
+#define WindowContextFactory_unix_DEFINED
+
+#include <X11/Xlib.h>
+#include <GL/glx.h>
+typedef Window XWindow;
+
+namespace sk_app {
+
+class WindowContext;
+struct DisplayParams;
+
+namespace window_context_factory {
+
+struct XlibWindowInfo {
+    Display*     fDisplay;
+    XWindow      fWindow;
+    XVisualInfo* fVisualInfo;
+};
+
+WindowContext* NewVulkanForXlib(const XlibWindowInfo&, const DisplayParams&);
+
+WindowContext* NewGLForXlib(const XlibWindowInfo&, const DisplayParams&);
+
+}  // namespace window_context_factory
+
+}  // namespace sk_app
+
+#endif
diff --git a/tools/viewer/sk_app/unix/Window_unix.cpp b/tools/viewer/sk_app/unix/Window_unix.cpp
index c472926..e6edfd9 100644
--- a/tools/viewer/sk_app/unix/Window_unix.cpp
+++ b/tools/viewer/sk_app/unix/Window_unix.cpp
@@ -7,12 +7,11 @@
 
 //#include <tchar.h>
 
+#include "WindowContextFactory_unix.h"
+
 #include "SkUtils.h"
 #include "Timer.h"
 #include "../GLWindowContext.h"
-#ifdef SK_VULKAN
-#include "../VulkanWindowContext.h"
-#endif
 #include "Window_unix.h"
 
 extern "C" {
@@ -273,19 +272,19 @@
 bool Window_unix::attach(BackendType attachType, const DisplayParams& params) {
     this->initWindow(fDisplay, &params);
 
-    ContextPlatformData_unix platformData;
-    platformData.fDisplay = fDisplay;
-    platformData.fWindow = fWindow;
-    platformData.fVisualInfo = fVisualInfo;
+    window_context_factory::XlibWindowInfo xwinInfo;
+    xwinInfo.fDisplay = fDisplay;
+    xwinInfo.fWindow = fWindow;
+    xwinInfo.fVisualInfo = fVisualInfo;
     switch (attachType) {
 #ifdef SK_VULKAN
         case kVulkan_BackendType:
-            fWindowContext = VulkanWindowContext::Create((void*)&platformData, params);
+            fWindowContext = window_context_factory::NewVulkanForXlib(xwinInfo, params);
             break;
 #endif
         case kNativeGL_BackendType:
         default:
-            fWindowContext = GLWindowContext::Create((void*)&platformData, params);
+            fWindowContext = window_context_factory::NewGLForXlib(xwinInfo, params);
             break;
     }
 
diff --git a/tools/viewer/sk_app/unix/Window_unix.h b/tools/viewer/sk_app/unix/Window_unix.h
index b6d40e6..462214d 100644
--- a/tools/viewer/sk_app/unix/Window_unix.h
+++ b/tools/viewer/sk_app/unix/Window_unix.h
@@ -18,12 +18,6 @@
 
 namespace sk_app {
 
-struct ContextPlatformData_unix {
-    Display*     fDisplay;
-    XWindow      fWindow;
-    XVisualInfo* fVisualInfo;
-};
-
 class Window_unix : public Window {
 public:
     Window_unix() : Window()
diff --git a/tools/viewer/sk_app/win/GLWindowContext_win.cpp b/tools/viewer/sk_app/win/GLWindowContext_win.cpp
index 0694db3..eca8829 100644
--- a/tools/viewer/sk_app/win/GLWindowContext_win.cpp
+++ b/tools/viewer/sk_app/win/GLWindowContext_win.cpp
@@ -6,51 +6,53 @@
  * found in the LICENSE file.
  */
 
-#include "GLWindowContext_win.h"
-
+#include "WindowContextFactory_win.h"
 #include <GL/gl.h>
 
  // windows stuff
 #include "win/SkWGL.h"
-#include "Window_win.h"
 
-namespace sk_app {
+#include "../GLWindowContext.h"
 
-// platform-dependent create
-GLWindowContext* GLWindowContext::Create(void* platformData, const DisplayParams& params) {
-    GLWindowContext_win* ctx = new GLWindowContext_win(platformData, params);
-    if (!ctx->isValid()) {
-        delete ctx;
-        return nullptr;
-    }
-    return ctx;
-}
+using sk_app::GLWindowContext;
+using sk_app::DisplayParams;
 
-GLWindowContext_win::GLWindowContext_win(void* platformData, const DisplayParams& params)
-    : GLWindowContext(platformData, params)
-    , fHWND(0)
+namespace {
+
+class GLWindowContext_win : public GLWindowContext {
+public:
+    GLWindowContext_win(HWND, const DisplayParams&);
+    ~GLWindowContext_win() override;
+
+protected:
+    void onSwapBuffers() override;
+
+    void onInitializeContext() override;
+    void onDestroyContext() override;
+
+private:
+    HWND              fHWND;
+    HGLRC             fHGLRC;
+};
+
+GLWindowContext_win::GLWindowContext_win(HWND wnd, const DisplayParams& params)
+    : GLWindowContext(params)
+    , fHWND(wnd)
     , fHGLRC(NULL) {
 
     // any config code here (particularly for msaa)?
 
-    this->initializeContext(platformData, params);
+    this->initializeContext();
 }
 
 GLWindowContext_win::~GLWindowContext_win() {
     this->destroyContext();
 }
 
-void GLWindowContext_win::onInitializeContext(void* platformData, const DisplayParams& params) {
-
-    ContextPlatformData_win* winPlatformData =
-        reinterpret_cast<ContextPlatformData_win*>(platformData);
-
-    if (winPlatformData) {
-        fHWND = winPlatformData->fHWnd;
-    }
+void GLWindowContext_win::onInitializeContext() {
     HDC dc = GetDC(fHWND);
 
-    fHGLRC = SkCreateWGLContext(dc, params.fMSAASampleCount, params.fDeepColor,
+    fHGLRC = SkCreateWGLContext(dc, fDisplayParams.fMSAASampleCount, fDisplayParams.fDeepColor,
                                 kGLPreferCompatibilityProfile_SkWGLContextRequest);
     if (NULL == fHGLRC) {
         return;
@@ -107,4 +109,19 @@
 }
 
 
-}   //namespace sk_app
+}  // anonymous namespace
+
+namespace sk_app {
+namespace window_context_factory {
+
+WindowContext* NewGLForWin(HWND wnd, const DisplayParams& params) {
+    GLWindowContext_win* ctx = new GLWindowContext_win(wnd, params);
+    if (!ctx->isValid()) {
+        delete ctx;
+        return nullptr;
+    }
+    return ctx;
+}
+
+}  // namespace window_context_factory
+}  // namespace sk_app
diff --git a/tools/viewer/sk_app/win/GLWindowContext_win.h b/tools/viewer/sk_app/win/GLWindowContext_win.h
deleted file mode 100644
index f30a805..0000000
--- a/tools/viewer/sk_app/win/GLWindowContext_win.h
+++ /dev/null
@@ -1,37 +0,0 @@
-
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#ifndef GLWindowContext_win_DEFINED
-#define GLWindowContext_win_DEFINED
-
-#include <windows.h>
-#include "../GLWindowContext.h"
-
-namespace sk_app {
-
-class GLWindowContext_win : public GLWindowContext {
-public:
-    friend GLWindowContext* GLWindowContext::Create(void* platformData, const DisplayParams&);
-
-    ~GLWindowContext_win() override;
-
-    void onSwapBuffers() override;
-
-    void onInitializeContext(void*, const DisplayParams&) override;
-    void onDestroyContext() override;
-
-private:
-    GLWindowContext_win(void*, const DisplayParams&);
-
-    HWND              fHWND;
-    HGLRC             fHGLRC;
-};
-
-
-}
-
-#endif
diff --git a/tools/viewer/sk_app/win/VulkanWindowContext_win.cpp b/tools/viewer/sk_app/win/VulkanWindowContext_win.cpp
index e4251b8..521a1ee 100644
--- a/tools/viewer/sk_app/win/VulkanWindowContext_win.cpp
+++ b/tools/viewer/sk_app/win/VulkanWindowContext_win.cpp
@@ -6,6 +6,9 @@
  * found in the LICENSE file.
  */
 
+#include <Windows.h>
+#include "WindowContextFactory_win.h"
+
 #include "../VulkanWindowContext.h"
 #include "Window_win.h"
 
@@ -13,51 +16,56 @@
 #include "vk/GrVkUtil.h"
 
 namespace sk_app {
+namespace window_context_factory {
 
-// Platform dependant call
-VkSurfaceKHR VulkanWindowContext::createVkSurface(VkInstance instance, void* platformData) {
-    static PFN_vkCreateWin32SurfaceKHR createWin32SurfaceKHR = nullptr;
-    if (!createWin32SurfaceKHR) {
-        createWin32SurfaceKHR = (PFN_vkCreateWin32SurfaceKHR) vkGetInstanceProcAddr(instance,
-                                                                        "vkCreateWin32SurfaceKHR");
-    }
+WindowContext* NewVulkanForWin(HWND hwnd, const DisplayParams& params) {
+    auto createVkSurface = [hwnd] (VkInstance instance) -> VkSurfaceKHR {
+        static PFN_vkCreateWin32SurfaceKHR createWin32SurfaceKHR = nullptr;
+        if (!createWin32SurfaceKHR) {
+            createWin32SurfaceKHR = (PFN_vkCreateWin32SurfaceKHR)
+                vkGetInstanceProcAddr(instance, "vkCreateWin32SurfaceKHR");
+        }
+        HINSTANCE hinstance = GetModuleHandle(0);
+        VkSurfaceKHR surface;
 
-    if (!platformData) {
-        return VK_NULL_HANDLE;
-    }
-    ContextPlatformData_win* winPlatformData =
-                                          reinterpret_cast<ContextPlatformData_win*>(platformData);
-    VkSurfaceKHR surface;
+        VkWin32SurfaceCreateInfoKHR surfaceCreateInfo;
+        memset(&surfaceCreateInfo, 0, sizeof(VkWin32SurfaceCreateInfoKHR));
+        surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
+        surfaceCreateInfo.pNext = nullptr;
+        surfaceCreateInfo.flags = 0;
+        surfaceCreateInfo.hinstance = hinstance;
+        surfaceCreateInfo.hwnd = hwnd;
 
-    VkWin32SurfaceCreateInfoKHR surfaceCreateInfo;
-    memset(&surfaceCreateInfo, 0, sizeof(VkWin32SurfaceCreateInfoKHR));
-    surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
-    surfaceCreateInfo.pNext = nullptr;
-    surfaceCreateInfo.flags = 0;
-    surfaceCreateInfo.hinstance = winPlatformData->fHInstance;
-    surfaceCreateInfo.hwnd = winPlatformData->fHWnd;
+        VkResult res = createWin32SurfaceKHR(instance, &surfaceCreateInfo, nullptr, &surface);
+        if (VK_SUCCESS != res) {
+            return VK_NULL_HANDLE;
+        }
 
-    VkResult res = createWin32SurfaceKHR(instance, &surfaceCreateInfo, nullptr, &surface);
-    if (VK_SUCCESS != res) {
-        return VK_NULL_HANDLE;
-    }
+        return surface;
+    };
 
-    return surface;
-}
-
-// Platform dependant call
-bool VulkanWindowContext::canPresent(VkInstance instance, VkPhysicalDevice physDev,
-                                     uint32_t queueFamilyIndex, void*) {
-    static PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR
+    auto canPresent = [hwnd] (VkInstance instance, VkPhysicalDevice physDev,
+                             uint32_t queueFamilyIndex) {
+        static PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR
                                             getPhysicalDeviceWin32PresentationSupportKHR = nullptr;
-    if (!getPhysicalDeviceWin32PresentationSupportKHR) {
-        getPhysicalDeviceWin32PresentationSupportKHR =
-            (PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR) vkGetInstanceProcAddr(instance,
-                                                 "vkGetPhysicalDeviceWin32PresentationSupportKHR");
-    }
+        if (!getPhysicalDeviceWin32PresentationSupportKHR) {
+            getPhysicalDeviceWin32PresentationSupportKHR =
+                (PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)
+                    vkGetInstanceProcAddr(instance,
+                                          "vkGetPhysicalDeviceWin32PresentationSupportKHR");
+        }
 
-    VkBool32 check = getPhysicalDeviceWin32PresentationSupportKHR(physDev, queueFamilyIndex);
-    return (VK_FALSE != check);
+        VkBool32 check = getPhysicalDeviceWin32PresentationSupportKHR(physDev, queueFamilyIndex);
+        return (VK_FALSE != check);
+    };
+
+    WindowContext* ctx = new VulkanWindowContext(params, createVkSurface, canPresent);
+    if (!ctx->isValid()) {
+        delete ctx;
+        return nullptr;
+    }
+    return ctx;
 }
 
-}   // namespace sk_app
+}  // namespace window_context_factory
+}  // namespace sk_app
diff --git a/tools/viewer/sk_app/win/WindowContextFactory_win.h b/tools/viewer/sk_app/win/WindowContextFactory_win.h
new file mode 100644
index 0000000..7aa4538
--- /dev/null
+++ b/tools/viewer/sk_app/win/WindowContextFactory_win.h
@@ -0,0 +1,29 @@
+
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef WindowContextFactory_win_DEFINED
+#define WindowContextFactory_win_DEFINED
+
+#include <Windows.h>
+
+namespace sk_app {
+
+class WindowContext;
+struct DisplayParams;
+
+namespace window_context_factory {
+
+WindowContext* NewVulkanForWin(HWND, const DisplayParams&);
+
+WindowContext* NewGLForWin(HWND, const DisplayParams&);
+
+}  // namespace window_context_factory
+
+}  // namespace sk_app
+
+#endif
diff --git a/tools/viewer/sk_app/win/Window_win.cpp b/tools/viewer/sk_app/win/Window_win.cpp
index 03537ca..e9905d4 100644
--- a/tools/viewer/sk_app/win/Window_win.cpp
+++ b/tools/viewer/sk_app/win/Window_win.cpp
@@ -12,7 +12,7 @@
 #include <windowsx.h>
 
 #include "SkUtils.h"
-#include "../GLWindowContext.h"
+#include "WindowContextFactory_win.h"
 #ifdef SK_VULKAN
 #include "../VulkanWindowContext.h"
 #endif
@@ -268,18 +268,14 @@
 
 
 bool Window_win::attach(BackendType attachType, const DisplayParams& params) {
-    ContextPlatformData_win platformData;
-    platformData.fHInstance = fHInstance;
-    platformData.fHWnd = fHWnd;
-
     switch (attachType) {
         case kNativeGL_BackendType:
         default:
-            fWindowContext = GLWindowContext::Create((void*)&platformData, params);
+            fWindowContext = window_context_factory::NewGLForWin(fHWnd, params);
             break;
 #ifdef SK_VULKAN
         case kVulkan_BackendType:
-            fWindowContext = VulkanWindowContext::Create((void*)&platformData, params);
+            fWindowContext = window_context_factory::NewVulkanForWin(fHWnd, params);
             break;
 #endif
     }
diff --git a/tools/viewer/sk_app/win/Window_win.h b/tools/viewer/sk_app/win/Window_win.h
index 36c0505..19541a0 100644
--- a/tools/viewer/sk_app/win/Window_win.h
+++ b/tools/viewer/sk_app/win/Window_win.h
@@ -13,12 +13,6 @@
 
 namespace sk_app {
 
-// for Windows
-struct ContextPlatformData_win {
-    HINSTANCE fHInstance;
-    HWND      fHWnd;
-};
-
 class Window_win : public Window {
 public:
     Window_win() : Window() {}