Add sRGB mode toggle to Viewer.

Unlike SampleApp, this just switches out the format of the window
surface (and then adjusts the gamma-correct flag on the SkSurfaces).

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1950983007

Review-Url: https://codereview.chromium.org/1950983007
diff --git a/tools/viewer/sk_app/DisplayParams.h b/tools/viewer/sk_app/DisplayParams.h
new file mode 100644
index 0000000..836b02e
--- /dev/null
+++ b/tools/viewer/sk_app/DisplayParams.h
@@ -0,0 +1,27 @@
+/*
+ * 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 DisplayParams_DEFINED
+#define DisplayParams_DEFINED
+
+#include "SkImageInfo.h"
+
+namespace sk_app {
+
+struct DisplayParams {
+    DisplayParams()
+        : fColorType(kN32_SkColorType)
+        , fProfileType(kLinear_SkColorProfileType)
+        , fMSAASampleCount(0) {}
+
+    SkColorType fColorType;
+    SkColorProfileType fProfileType;
+    int fMSAASampleCount;
+};
+
+}   // namespace sk_app
+
+#endif
diff --git a/tools/viewer/sk_app/VulkanWindowContext.cpp b/tools/viewer/sk_app/VulkanWindowContext.cpp
index 8f5f420..f21ec9c 100644
--- a/tools/viewer/sk_app/VulkanWindowContext.cpp
+++ b/tools/viewer/sk_app/VulkanWindowContext.cpp
@@ -24,7 +24,7 @@
 
 namespace sk_app {
 
-VulkanWindowContext::VulkanWindowContext(void* platformData, int msaaSampleCount)
+VulkanWindowContext::VulkanWindowContext(void* platformData, const DisplayParams& params)
     : fSurface(VK_NULL_HANDLE)
     , fSwapchain(VK_NULL_HANDLE)
     , fCommandPool(VK_NULL_HANDLE)
@@ -32,10 +32,10 @@
 
     // any config code here (particularly for msaa)?
 
-    this->initializeContext(platformData);
+    this->initializeContext(platformData, params);
 }
 
-void VulkanWindowContext::initializeContext(void* platformData) {
+void VulkanWindowContext::initializeContext(void* platformData, const DisplayParams& params) {
 
     fBackendContext.reset(GrVkBackendContext::Create(&fPresentQueueIndex, canPresent));
     if (!(fBackendContext->fExtensions & kKHR_surface_GrVkExtensionFlag) ||
@@ -74,7 +74,7 @@
         return;
     }
 
-    if (!this->createSwapchain(-1, -1)) {
+    if (!this->createSwapchain(-1, -1, params)) {
         this->destroyContext();
         return;
     }
@@ -83,7 +83,8 @@
     vkGetDeviceQueue(fBackendContext->fDevice, fPresentQueueIndex, 0, &fPresentQueue);
 }
 
-bool VulkanWindowContext::createSwapchain(uint32_t width, uint32_t height) {
+bool VulkanWindowContext::createSwapchain(uint32_t width, uint32_t height,
+                                          const DisplayParams& params) {
     // check for capabilities
     VkSurfaceCapabilitiesKHR caps;
     VkResult res = fGetPhysicalDeviceSurfaceCapabilitiesKHR(fBackendContext->fPhysicalDevice,
@@ -162,9 +163,24 @@
                                         VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR :
                                         VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
 
-    // Pick our surface format -- for now, the first one
-    VkFormat surfaceFormat = surfaceFormats[0].format;
-    VkColorSpaceKHR colorSpace = surfaceFormats[0].colorSpace;
+    // Pick our surface format. For now, just make sure it matches our sRGB request:
+    VkFormat surfaceFormat = VK_FORMAT_UNDEFINED;
+    VkColorSpaceKHR colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
+    bool wantSRGB = kSRGB_SkColorProfileType == params.fProfileType;
+    for (uint32_t i = 0; i < surfaceFormatCount; ++i) {
+        GrPixelConfig config;
+        if (GrVkFormatToPixelConfig(surfaceFormats[i].format, &config) &&
+            GrPixelConfigIsSRGB(config) == wantSRGB) {
+            surfaceFormat = surfaceFormats[i].format;
+            colorSpace = surfaceFormats[i].colorSpace;
+            break;
+        }
+    }
+    fDisplayParams = params;
+
+    if (VK_FORMAT_UNDEFINED == surfaceFormat) {
+        return false;
+    }
 
     // If mailbox mode is available, use it, as it is the lowest-latency non-
     // tearing mode. If not, fall back to FIFO which is always available.
@@ -252,7 +268,9 @@
         desc.fSampleCnt = 0;
         desc.fStencilBits = 0;
         desc.fRenderTargetHandle = (GrBackendObject) &info;
-        SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
+        SkSurfaceProps props(GrPixelConfigIsSRGB(fPixelConfig)
+                             ? SkSurfaceProps::kGammaCorrect_Flag : 0,
+                             kUnknown_SkPixelGeometry);
         fSurfaces[i] = SkSurface::MakeFromBackendRenderTarget(fContext, desc, &props);
     }
 
@@ -420,7 +438,7 @@
     }
     if (VK_ERROR_OUT_OF_DATE_KHR == res) {
         // tear swapchain down and try again
-        if (!this->createSwapchain(0, 0)) {
+        if (!this->createSwapchain(0, 0, fDisplayParams)) {
             return nullptr;
         }
 
diff --git a/tools/viewer/sk_app/VulkanWindowContext.h b/tools/viewer/sk_app/VulkanWindowContext.h
index 48f8ed5..e186881 100644
--- a/tools/viewer/sk_app/VulkanWindowContext.h
+++ b/tools/viewer/sk_app/VulkanWindowContext.h
@@ -26,8 +26,8 @@
     static VkSurfaceKHR createVkSurface(VkInstance, void* platformData);
     static bool canPresent(VkInstance, VkPhysicalDevice, uint32_t queueFamilyIndex);
 
-    static VulkanWindowContext* Create(void* platformData, int msaaSampleCount) {
-        VulkanWindowContext* ctx = new VulkanWindowContext(platformData, msaaSampleCount);
+    static VulkanWindowContext* Create(void* platformData, const DisplayParams& params) {
+        VulkanWindowContext* ctx = new VulkanWindowContext(platformData, params);
         if (!ctx->isValid()) {
             delete ctx;
             return nullptr;
@@ -43,7 +43,12 @@
     bool isValid() override { return SkToBool(fBackendContext.get()); }
 
     void resize(uint32_t w, uint32_t h) override {
-        this->createSwapchain(w, h);
+        this->createSwapchain(w, h, fDisplayParams);
+    }
+
+    const DisplayParams& getDisplayParams() { return fDisplayParams; }
+    void setDisplayParams(const DisplayParams& params) {
+        this->createSwapchain(fWidth, fHeight, params);
     }
 
     GrBackendContext getBackendContext() override { 
@@ -51,9 +56,8 @@
     }
 
 private:
-    VulkanWindowContext();
-    VulkanWindowContext(void*, int msaaSampleCount);
-    void initializeContext(void*);
+    VulkanWindowContext(void*, const DisplayParams&);
+    void initializeContext(void*, const DisplayParams&);
     void destroyContext();
 
     struct BackbufferInfo {
@@ -65,7 +69,7 @@
     };
 
     BackbufferInfo* getAvailableBackbuffer();
-    bool createSwapchain(uint32_t width, uint32_t height);
+    bool createSwapchain(uint32_t width, uint32_t height, const DisplayParams& params);
     void createBuffers(VkFormat format);
     void destroyBuffers();
 
@@ -102,6 +106,7 @@
     VkQueue           fPresentQueue;
     int               fWidth;
     int               fHeight;
+    DisplayParams     fDisplayParams;
     GrPixelConfig     fPixelConfig;
 
     uint32_t          fImageCount;
diff --git a/tools/viewer/sk_app/Window.cpp b/tools/viewer/sk_app/Window.cpp
index a7fd6b0..47053be 100644
--- a/tools/viewer/sk_app/Window.cpp
+++ b/tools/viewer/sk_app/Window.cpp
@@ -75,4 +75,12 @@
     fWindowContext->resize(w, h);
 }
 
+const DisplayParams& Window::getDisplayParams() {
+    return fWindowContext->getDisplayParams();
+}
+
+void Window::setDisplayParams(const DisplayParams& params) {
+    fWindowContext->setDisplayParams(params);
+}
+
 }   // namespace sk_app
diff --git a/tools/viewer/sk_app/Window.h b/tools/viewer/sk_app/Window.h
index 3dd558e..56444a6 100644
--- a/tools/viewer/sk_app/Window.h
+++ b/tools/viewer/sk_app/Window.h
@@ -8,6 +8,7 @@
 #ifndef Window_DEFINED
 #define Window_DEFINED
 
+#include "DisplayParams.h"
 #include "SkTypes.h"
 #include "SkRect.h"
 
@@ -36,7 +37,7 @@
         kVulkan_BackendType
     };
 
-    virtual bool attach(BackEndType attachType, int msaaSampleCount) = 0;
+    virtual bool attach(BackEndType attachType,  const DisplayParams& params) = 0;
     void detach();
 
     // input handling
@@ -129,6 +130,9 @@
     uint32_t width() { return fWidth; }
     uint32_t height() { return fHeight;  }
 
+    const DisplayParams& getDisplayParams();
+    void setDisplayParams(const DisplayParams& params);
+
 protected:
     Window();
 
diff --git a/tools/viewer/sk_app/WindowContext.h b/tools/viewer/sk_app/WindowContext.h
index 5811bed..d48e38e 100644
--- a/tools/viewer/sk_app/WindowContext.h
+++ b/tools/viewer/sk_app/WindowContext.h
@@ -7,6 +7,7 @@
 #ifndef WindowContext_DEFINED
 #define WindowContext_DEFINED
 
+#include "DisplayParams.h"
 #include "GrTypes.h"
 
 class SkSurface;
@@ -28,6 +29,9 @@
 
     virtual void resize(uint32_t w, uint32_t h) = 0;
 
+    virtual const DisplayParams& getDisplayParams() = 0;
+    virtual void setDisplayParams(const DisplayParams& params) = 0;
+
     virtual GrBackendContext getBackendContext() = 0;
 };
 
diff --git a/tools/viewer/sk_app/android/Window_android.cpp b/tools/viewer/sk_app/android/Window_android.cpp
index 94be02c..9def29f 100644
--- a/tools/viewer/sk_app/android/Window_android.cpp
+++ b/tools/viewer/sk_app/android/Window_android.cpp
@@ -37,12 +37,12 @@
     SkDebugf("Title: %s", title);
 }
 
-bool Window_android::attach(BackEndType attachType, int msaaSampleCount) {
+bool Window_android::attach(BackEndType attachType, const DisplayParams& params) {
     if (kVulkan_BackendType != attachType) {
         return false;
     }
 
-    mSampleCount = msaaSampleCount;
+    fDisplayParams = params;
 
     // We delay the creation of fTestContext until Android informs us that
     // the native window is ready to use.
@@ -53,7 +53,7 @@
     SkASSERT(window);
     ContextPlatformData_android platformData;
     platformData.fNativeWindow = window;
-    fWindowContext = VulkanWindowContext::Create((void*)&platformData, mSampleCount);
+    fWindowContext = VulkanWindowContext::Create((void*)&platformData, mSampleCount, fSRGB);
 }
 
 static void android_app_write_cmd(struct android_app* android_app, int8_t cmd) {
diff --git a/tools/viewer/sk_app/android/Window_android.h b/tools/viewer/sk_app/android/Window_android.h
index d41f0a5..b570615 100644
--- a/tools/viewer/sk_app/android/Window_android.h
+++ b/tools/viewer/sk_app/android/Window_android.h
@@ -31,7 +31,7 @@
     void setTitle(const char*) override;
     void show() override {}
 
-    bool attach(BackEndType attachType, int msaaSampleCount, bool deepColor) override;
+    bool attach(BackEndType attachType, const DisplayParams& params) override;
     void inval() override;
 
     void paintIfNeeded();
@@ -44,7 +44,7 @@
 private:
     android_app* mApp = nullptr;
     SkRect mContentRect;
-    int mSampleCount = 0;
+    DisplayParams fDisplayParams;
 };
 
 }   // namespace sk_app
diff --git a/tools/viewer/sk_app/win/Window_win.cpp b/tools/viewer/sk_app/win/Window_win.cpp
index 1dd07a6..16afcc7 100644
--- a/tools/viewer/sk_app/win/Window_win.cpp
+++ b/tools/viewer/sk_app/win/Window_win.cpp
@@ -264,7 +264,7 @@
 }
 
 
-bool Window_win::attach(BackEndType attachType, int msaaSampleCount) {
+bool Window_win::attach(BackEndType attachType, const DisplayParams& params) {
     if (kVulkan_BackendType != attachType) {
         return false;
     }
@@ -273,7 +273,7 @@
     platformData.fHInstance = fHInstance;
     platformData.fHWnd = fHWnd;
 
-    fWindowContext = VulkanWindowContext::Create((void*)&platformData, msaaSampleCount);
+    fWindowContext = VulkanWindowContext::Create((void*)&platformData, params);
 
     return (SkToBool(fWindowContext));
 }
diff --git a/tools/viewer/sk_app/win/Window_win.h b/tools/viewer/sk_app/win/Window_win.h
index e295212..3501b06 100644
--- a/tools/viewer/sk_app/win/Window_win.h
+++ b/tools/viewer/sk_app/win/Window_win.h
@@ -23,7 +23,7 @@
     void setTitle(const char*) override;
     void show() override;
 
-    bool attach(BackEndType attachType, int msaaSampleCount) override;
+    bool attach(BackEndType attachType, const DisplayParams& params) override;
 
     void inval() override;