SW backend for viewer on Windows
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2182273002

Review-Url: https://codereview.chromium.org/2182273002
diff --git a/tools/viewer/sk_app/GLWindowContext.cpp b/tools/viewer/sk_app/GLWindowContext.cpp
index cc09abd..2a5761c 100644
--- a/tools/viewer/sk_app/GLWindowContext.cpp
+++ b/tools/viewer/sk_app/GLWindowContext.cpp
@@ -93,7 +93,7 @@
     this->onSwapBuffers();
 }
 
-void GLWindowContext::resize(uint32_t w, uint32_t h) {
+void GLWindowContext::resize(int  w, int h) {
     this->destroyContext();
     this->initializeContext();
 }
diff --git a/tools/viewer/sk_app/GLWindowContext.h b/tools/viewer/sk_app/GLWindowContext.h
index e9abffd..98a312f 100644
--- a/tools/viewer/sk_app/GLWindowContext.h
+++ b/tools/viewer/sk_app/GLWindowContext.h
@@ -27,7 +27,7 @@
 
     bool isValid() override { return SkToBool(fBackendContext.get()); }
 
-    void resize(uint32_t w, uint32_t h) override;
+    void resize(int w, int h) override;
     void swapBuffers() override;
 
     void setDisplayParams(const DisplayParams& params) override;
diff --git a/tools/viewer/sk_app/VulkanWindowContext.cpp b/tools/viewer/sk_app/VulkanWindowContext.cpp
index 74c0674..f2fc1e5 100644
--- a/tools/viewer/sk_app/VulkanWindowContext.cpp
+++ b/tools/viewer/sk_app/VulkanWindowContext.cpp
@@ -85,7 +85,7 @@
     vkGetDeviceQueue(fBackendContext->fDevice, fPresentQueueIndex, 0, &fPresentQueue);
 }
 
-bool VulkanWindowContext::createSwapchain(uint32_t width, uint32_t height,
+bool VulkanWindowContext::createSwapchain(int width, int height,
                                           const DisplayParams& params) {
     // check for capabilities
     VkSurfaceCapabilitiesKHR caps;
diff --git a/tools/viewer/sk_app/VulkanWindowContext.h b/tools/viewer/sk_app/VulkanWindowContext.h
index d40adf6..1953d75 100644
--- a/tools/viewer/sk_app/VulkanWindowContext.h
+++ b/tools/viewer/sk_app/VulkanWindowContext.h
@@ -28,7 +28,7 @@
 
     bool isValid() override { return SkToBool(fBackendContext.get()); }
 
-    void resize(uint32_t w, uint32_t h) override {
+    void resize(int w, int h) override {
         this->createSwapchain(w, h, fDisplayParams);
     }
 
@@ -59,7 +59,7 @@
     };
 
     BackbufferInfo* getAvailableBackbuffer();
-    bool createSwapchain(uint32_t width, uint32_t height, const DisplayParams& params);
+    bool createSwapchain(int width, int height, const DisplayParams& params);
     void createBuffers(VkFormat format);
     void destroyBuffers();
 
diff --git a/tools/viewer/sk_app/Window.cpp b/tools/viewer/sk_app/Window.cpp
index 7122335..4a04363 100644
--- a/tools/viewer/sk_app/Window.cpp
+++ b/tools/viewer/sk_app/Window.cpp
@@ -88,7 +88,7 @@
     }
 }
 
-void Window::onResize(uint32_t w, uint32_t h) {
+void Window::onResize(int w, int h) {
     fWidth = w;
     fHeight = h;
     fWindowContext->resize(w, h);
diff --git a/tools/viewer/sk_app/Window.h b/tools/viewer/sk_app/Window.h
index eab8c1d..fc46e0d 100644
--- a/tools/viewer/sk_app/Window.h
+++ b/tools/viewer/sk_app/Window.h
@@ -156,7 +156,7 @@
     bool onTouch(intptr_t owner, InputState state, float x, float y);  // multi-owner = multi-touch
     void onUIStateChanged(const SkString& stateName, const SkString& stateValue);
     void onPaint();
-    void onResize(uint32_t width, uint32_t height);
+    void onResize(int width, int height);
 
     int width() { return fWidth; }
     int height() { return fHeight;  }
diff --git a/tools/viewer/sk_app/WindowContext.h b/tools/viewer/sk_app/WindowContext.h
index 917eb4e..f63009c 100644
--- a/tools/viewer/sk_app/WindowContext.h
+++ b/tools/viewer/sk_app/WindowContext.h
@@ -31,7 +31,7 @@
 
     virtual bool isValid() = 0;
 
-    virtual void resize(uint32_t w, uint32_t h) = 0;
+    virtual void resize(int w, int h) = 0;
 
     const DisplayParams& getDisplayParams() { return fDisplayParams; }
     virtual void setDisplayParams(const DisplayParams& params) = 0;
diff --git a/tools/viewer/sk_app/android/RasterWindowContext_android.cpp b/tools/viewer/sk_app/android/RasterWindowContext_android.cpp
index ae49405..7077e2c 100644
--- a/tools/viewer/sk_app/android/RasterWindowContext_android.cpp
+++ b/tools/viewer/sk_app/android/RasterWindowContext_android.cpp
@@ -23,7 +23,7 @@
     void swapBuffers() override;
 
     bool isValid() override { return SkToBool(fNativeWindow); }
-    void resize(uint32_t w, uint32_t h) override;
+    void resize(int w, int h) override;
     void setDisplayParams(const DisplayParams& params) override;
 
 private:
@@ -63,7 +63,7 @@
     this->setBuffersGeometry();
 }
 
-void RasterWindowContext_android::resize(uint32_t w, uint32_t h) {
+void RasterWindowContext_android::resize(int w, int h) {
     fWidth = w;
     fHeight = h;
     this->setBuffersGeometry();
diff --git a/tools/viewer/sk_app/unix/RasterWindowContext_unix.cpp b/tools/viewer/sk_app/unix/RasterWindowContext_unix.cpp
index aaf1712..16b11a9 100644
--- a/tools/viewer/sk_app/unix/RasterWindowContext_unix.cpp
+++ b/tools/viewer/sk_app/unix/RasterWindowContext_unix.cpp
@@ -21,7 +21,7 @@
     sk_sp<SkSurface> getBackbufferSurface() override;
     void swapBuffers() override;
     bool isValid() override { return SkToBool(fWindow); }
-    void resize(uint32_t w, uint32_t h) override;
+    void resize(int  w, int h) override;
     void setDisplayParams(const DisplayParams& params) override;
 
 protected:
@@ -49,7 +49,7 @@
     this->resize(attrs.width, attrs.height);
 }
 
-void RasterWindowContext_xlib::resize(uint32_t w, uint32_t h) {
+void RasterWindowContext_xlib::resize(int  w, int h) {
     SkImageInfo info = SkImageInfo::Make(w, h, fDisplayParams.fColorType, kPremul_SkAlphaType,
                                          fDisplayParams.fColorSpace);
     fBackbufferSurface = SkSurface::MakeRaster(info);
diff --git a/tools/viewer/sk_app/win/RasterWindowContext_win.cpp b/tools/viewer/sk_app/win/RasterWindowContext_win.cpp
new file mode 100644
index 0000000..ca738db
--- /dev/null
+++ b/tools/viewer/sk_app/win/RasterWindowContext_win.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "WindowContextFactory_win.h"
+#include "../RasterWindowContext.h"
+#include "SkSurface.h"
+
+#include <Windows.h>
+
+using sk_app::RasterWindowContext;
+using sk_app::DisplayParams;
+
+namespace {
+
+class RasterWindowContext_win : public RasterWindowContext {
+public:
+    RasterWindowContext_win(HWND, const DisplayParams&);
+
+    sk_sp<SkSurface> getBackbufferSurface() override;
+    void swapBuffers() override;
+    bool isValid() override { return SkToBool(fWnd); }
+    void resize(int w, int h) override;
+    void setDisplayParams(const DisplayParams& params) override;
+
+protected:
+    SkAutoMalloc fSurfaceMemory;
+    sk_sp<SkSurface> fBackbufferSurface;
+    HWND fWnd;
+};
+
+RasterWindowContext_win::RasterWindowContext_win(HWND wnd, const DisplayParams& params)
+        : fWnd(wnd) {
+    fDisplayParams = params;
+    RECT rect;
+    GetWindowRect(wnd, &rect);
+    this->resize(rect.right - rect.left, rect.bottom - rect.top);
+}
+
+void RasterWindowContext_win::setDisplayParams(const DisplayParams& params) {
+    fDisplayParams = params;
+    RECT rect;
+    GetWindowRect(fWnd, &rect);
+    this->resize(rect.right - rect.left, rect.bottom - rect.top);
+}
+
+void RasterWindowContext_win::resize(int w, int h) {
+    fWidth = w;
+    fHeight = h;
+    fBackbufferSurface.reset();
+    const size_t bmpSize = sizeof(BITMAPINFOHEADER) + w * h * sizeof(uint32_t);
+    fSurfaceMemory.reset(bmpSize);
+    BITMAPINFO* bmpInfo = reinterpret_cast<BITMAPINFO*>(fSurfaceMemory.get());
+    ZeroMemory(bmpInfo, sizeof(BITMAPINFO));
+    bmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+    bmpInfo->bmiHeader.biWidth = w;
+    bmpInfo->bmiHeader.biHeight = -h; // negative means top-down bitmap. Skia draws top-down.
+    bmpInfo->bmiHeader.biPlanes = 1;
+    bmpInfo->bmiHeader.biBitCount = 32;
+    bmpInfo->bmiHeader.biCompression = BI_RGB;
+    void* pixels = bmpInfo->bmiColors;
+
+    SkImageInfo info = SkImageInfo::Make(w, h, fDisplayParams.fColorType, kPremul_SkAlphaType,
+                                         fDisplayParams.fColorSpace);
+    fBackbufferSurface = SkSurface::MakeRasterDirect(info, pixels, sizeof(uint32_t) * w);
+}
+
+sk_sp<SkSurface> RasterWindowContext_win::getBackbufferSurface() { return fBackbufferSurface; }
+
+void RasterWindowContext_win::swapBuffers() {
+    BITMAPINFO* bmpInfo = reinterpret_cast<BITMAPINFO*>(fSurfaceMemory.get());
+    HDC dc = GetDC(fWnd);
+    StretchDIBits(dc, 0, 0, fWidth, fHeight, 0, 0, fWidth, fHeight, bmpInfo->bmiColors, bmpInfo,
+                  DIB_RGB_COLORS, SRCCOPY);
+    ReleaseDC(fWnd, dc);
+}
+
+}  // anonymous namespace
+
+namespace sk_app {
+namespace window_context_factory {
+
+WindowContext* NewRasterForWin(HWND wnd, const DisplayParams& params) {
+    WindowContext* ctx = new RasterWindowContext_win(wnd, params);
+    if (!ctx->isValid()) {
+        delete ctx;
+        ctx = nullptr;
+    }
+    return ctx;
+}
+
+}  // 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
index 7aa4538..4367492 100644
--- a/tools/viewer/sk_app/win/WindowContextFactory_win.h
+++ b/tools/viewer/sk_app/win/WindowContextFactory_win.h
@@ -22,6 +22,8 @@
 
 WindowContext* NewGLForWin(HWND, const DisplayParams&);
 
+WindowContext* NewRasterForWin(HWND, const DisplayParams&);
+
 }  // namespace window_context_factory
 
 }  // namespace sk_app
diff --git a/tools/viewer/sk_app/win/Window_win.cpp b/tools/viewer/sk_app/win/Window_win.cpp
index e9905d4..2f72478 100644
--- a/tools/viewer/sk_app/win/Window_win.cpp
+++ b/tools/viewer/sk_app/win/Window_win.cpp
@@ -270,9 +270,11 @@
 bool Window_win::attach(BackendType attachType, const DisplayParams& params) {
     switch (attachType) {
         case kNativeGL_BackendType:
-        default:
             fWindowContext = window_context_factory::NewGLForWin(fHWnd, params);
             break;
+        case kRaster_BackendType:
+            fWindowContext = window_context_factory::NewRasterForWin(fHWnd, params);
+            break;
 #ifdef SK_VULKAN
         case kVulkan_BackendType:
             fWindowContext = window_context_factory::NewVulkanForWin(fHWnd, params);