Prepare sRGB encoding conversion for the removal of GrPixelConfig

Standardizes that GrGpu subclass's onRead/WritePixels never do sRGB<->linear conversion. This means that they can eventually take a color type rather than config. It also means direct callers of GrGpu::read/writePixels can never expect conversion (which in practice is no change).

Consolidate logic about whether to do sRGB<->linear encoding conversions in GrContext::read/writeSurfacePixels helpers. No change in when conversions are done (yet). This prepares this logic to operate on SkColorSpace and color type rather than config WRT the CPU data.

Bug: skia:6718
Change-Id: I346d669624861578f1bb9ea465a7ab4b549117fa
Reviewed-on: https://skia-review.googlesource.com/105286
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 09985e6..f8522f0 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -542,6 +542,63 @@
            (kRGBA_8888_GrPixelConfig == config || kBGRA_8888_GrPixelConfig == config);
 }
 
+static GrSRGBConversion determine_write_pixels_srgb_conversion(
+        GrPixelConfig srcConfig,
+        const SkColorSpace* srcColorSpace,
+        GrSRGBEncoded dstSRGBEncoded,
+        const SkColorSpace* dstColorSpace) {
+    // No support for sRGB-encoded alpha.
+    if (GrPixelConfigIsAlphaOnly(srcConfig)) {
+        return GrSRGBConversion::kNone;
+    }
+    // When the destination has no color space or it has a ~sRGB gamma but isn't sRGB encoded
+    // (because of caps) then we act in "legacy" mode where no conversions are performed.
+    if (!dstColorSpace ||
+        (dstColorSpace->gammaCloseToSRGB() && GrSRGBEncoded::kNo == dstSRGBEncoded)) {
+        return GrSRGBConversion::kNone;
+    }
+    // Similarly, if the src was sRGB gamma and 8888 but we didn't choose a sRGB config we must be
+    // in legacy mode. For now, anyway.
+    if (srcColorSpace && srcColorSpace->gammaCloseToSRGB() &&
+        GrSRGBEncoded::kNo == GrPixelConfigIsSRGBEncoded(srcConfig) &&
+        GrPixelConfigIs8888Unorm(srcConfig)) {
+        return GrSRGBConversion::kNone;
+    }
+
+    bool srcColorSpaceIsSRGB = srcColorSpace && srcColorSpace->gammaCloseToSRGB();
+    bool dstColorSpaceIsSRGB = dstColorSpace->gammaCloseToSRGB();
+
+    // For now we are assuming that if color space of the dst does not have sRGB gamma then the
+    // texture format is not sRGB encoded and vice versa. Note that we already checked for "legacy"
+    // mode being forced on by caps above. This may change in the future.
+    SkASSERT(dstColorSpaceIsSRGB == (GrSRGBEncoded::kYes == dstSRGBEncoded));
+
+    // Similarly we are assuming that if the color space of the src does not have sRGB gamma then
+    // the CPU pixels don't have a sRGB pixel config. This will become moot soon as we will not
+    // be using GrPixelConfig to describe CPU pixel allocations.
+     SkASSERT(srcColorSpaceIsSRGB == GrPixelConfigIsSRGB(srcConfig));
+
+    if (srcColorSpaceIsSRGB == dstColorSpaceIsSRGB) {
+        return GrSRGBConversion::kNone;
+    }
+    return srcColorSpaceIsSRGB ? GrSRGBConversion::kSRGBToLinear : GrSRGBConversion::kLinearToSRGB;
+}
+
+static GrSRGBConversion determine_read_pixels_srgb_conversion(
+        GrSRGBEncoded srcSRGBEncoded,
+        const SkColorSpace* srcColorSpace,
+        GrPixelConfig dstConfig,
+        const SkColorSpace* dstColorSpace) {
+    // This is symmetrical with the write version.
+    switch (determine_write_pixels_srgb_conversion(dstConfig, dstColorSpace, srcSRGBEncoded,
+                                                   srcColorSpace)) {
+        case GrSRGBConversion::kNone:         return GrSRGBConversion::kNone;
+        case GrSRGBConversion::kLinearToSRGB: return GrSRGBConversion::kSRGBToLinear;
+        case GrSRGBConversion::kSRGBToLinear: return GrSRGBConversion::kLinearToSRGB;
+    }
+    return GrSRGBConversion::kNone;
+}
+
 bool GrContextPriv::writeSurfacePixels(GrSurfaceContext* dst,
                                        int left, int top, int width, int height,
                                        GrPixelConfig srcConfig, SkColorSpace* srcColorSpace,
@@ -590,8 +647,12 @@
     GrGpu::DrawPreference drawPreference = premulOnGpu ? GrGpu::kCallerPrefersDraw_DrawPreference
                                                        : GrGpu::kNoDraw_DrawPreference;
     GrGpu::WritePixelTempDrawInfo tempDrawInfo;
+    GrSRGBConversion srgbConversion = determine_write_pixels_srgb_conversion(
+            srcConfig, srcColorSpace, GrPixelConfigIsSRGBEncoded(dstProxy->config()),
+            dst->colorSpaceInfo().colorSpace());
     if (!fContext->fGpu->getWritePixelsInfo(dstSurface, dstProxy->origin(), width, height,
-                                            srcConfig, &drawPreference, &tempDrawInfo)) {
+                                            srcConfig, srgbConversion, &drawPreference,
+                                            &tempDrawInfo)) {
         return false;
     }
 
@@ -723,8 +784,12 @@
     GrGpu::DrawPreference drawPreference = unpremulOnGpu ? GrGpu::kCallerPrefersDraw_DrawPreference
                                                          : GrGpu::kNoDraw_DrawPreference;
     GrGpu::ReadPixelTempDrawInfo tempDrawInfo;
+    GrSRGBConversion srgbConversion = determine_read_pixels_srgb_conversion(
+            GrPixelConfigIsSRGBEncoded(srcProxy->config()), src->colorSpaceInfo().colorSpace(),
+            dstConfig, dstColorSpace);
     if (!fContext->fGpu->getReadPixelsInfo(srcSurface, srcProxy->origin(), width, height, rowBytes,
-                                           dstConfig, &drawPreference, &tempDrawInfo)) {
+                                           dstConfig, srgbConversion, &drawPreference,
+                                           &tempDrawInfo)) {
         return false;
     }