SkSurfaceProps now has a gamma-correct ("AllowSRGBInputs") flag. That's propagated in a few places so that the backend can do the right thing for L32 vs S32 mode.

Also added SkSurfaceProps to SkSpecialImage, so that Image -> Surface conversion can preserve the desired behavior during filtering.

Many small changes, including a bunch of comments about places where we may be losing information right now. My approach was to ensure that if anything fails, it will always fall back to "legacy" mode - gamma-correctness is opt-in, so I'll just have to feed things through as missing cases are exposed.
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1838953007

Review URL: https://codereview.chromium.org/1845283003
diff --git a/src/effects/SkBlurImageFilter.cpp b/src/effects/SkBlurImageFilter.cpp
index b7745e2..10c8a0b 100644
--- a/src/effects/SkBlurImageFilter.cpp
+++ b/src/effects/SkBlurImageFilter.cpp
@@ -113,6 +113,7 @@
         SkAutoTUnref<GrTexture> tex(SkGpuBlurUtils::GaussianBlur(inputTexture->getContext(),
                                                                  inputTexture,
                                                                  false,
+                                                                 source->props().allowSRGBInputs(),
                                                                  SkRect::Make(dstBounds),
                                                                  &inputBoundsF,
                                                                  sigma.x(),
@@ -124,7 +125,7 @@
         return SkSpecialImage::MakeFromGpu(source->internal_getProxy(),
                                            SkIRect::MakeWH(dstBounds.width(), dstBounds.height()),
                                            kNeedNewImageUniqueID_SpecialImage,
-                                           tex);
+                                           tex, &source->props());
     }
 #endif
 
@@ -216,7 +217,7 @@
     return SkSpecialImage::MakeFromRaster(source->internal_getProxy(),
                                           SkIRect::MakeWH(dstBounds.width(),
                                                           dstBounds.height()),
-                                          dst);
+                                          dst, &source->props());
 }
 
 
diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp
index bb6a8a5..609e168 100644
--- a/src/effects/SkBlurMaskFilter.cpp
+++ b/src/effects/SkBlurMaskFilter.cpp
@@ -1243,7 +1243,8 @@
     // gaussianBlur.  Otherwise, we need to save it for later compositing.
     bool isNormalBlur = (kNormal_SkBlurStyle == fBlurStyle);
     *result = SkGpuBlurUtils::GaussianBlur(context, src, isNormalBlur && canOverwriteSrc,
-                                           clipRect, nullptr, xformedSigma, xformedSigma);
+                                           false, clipRect, nullptr,
+                                           xformedSigma, xformedSigma);
     if (nullptr == *result) {
         return false;
     }
diff --git a/src/effects/SkDisplacementMapEffect.cpp b/src/effects/SkDisplacementMapEffect.cpp
index 447a20b..6debea1 100644
--- a/src/effects/SkDisplacementMapEffect.cpp
+++ b/src/effects/SkDisplacementMapEffect.cpp
@@ -431,6 +431,7 @@
     ctx.ctm().mapVectors(&scale, 1);
 
     GrPaint paint;
+    // SRGBTODO: AllowSRGBInputs?
     SkMatrix offsetMatrix = GrCoordTransform::MakeDivByTextureWHMatrix(displacement);
     offsetMatrix.preTranslate(SkIntToScalar(colorOffset.fX - displacementOffset.fX),
                               SkIntToScalar(colorOffset.fY - displacementOffset.fY));
diff --git a/src/effects/SkGpuBlurUtils.cpp b/src/effects/SkGpuBlurUtils.cpp
index c43f273..90619f9 100644
--- a/src/effects/SkGpuBlurUtils.cpp
+++ b/src/effects/SkGpuBlurUtils.cpp
@@ -56,6 +56,7 @@
                                  bool useBounds,
                                  float bounds[2]) {
     GrPaint paint;
+    paint.setAllowSRGBInputs(drawContext->allowSRGBInputs());
     SkAutoTUnref<GrFragmentProcessor> conv(GrConvolutionEffect::CreateGaussian(
         texture, direction, radius, sigma, useBounds, bounds));
     paint.addColorFragmentProcessor(conv);
@@ -78,6 +79,7 @@
     SkISize size = SkISize::Make(2 * radiusX + 1,  2 * radiusY + 1);
     SkIPoint kernelOffset = SkIPoint::Make(radiusX, radiusY);
     GrPaint paint;
+    paint.setAllowSRGBInputs(drawContext->allowSRGBInputs());
     SkIRect bounds;
     if (srcBounds) {
         srcBounds->roundOut(&bounds);
@@ -164,6 +166,7 @@
 GrTexture* GaussianBlur(GrContext* context,
                         GrTexture* srcTexture,
                         bool canClobberSrc,
+                        bool allowSRGBInputs,
                         const SkRect& dstBounds,
                         const SkRect* srcBounds,
                         float sigmaX,
@@ -229,6 +232,7 @@
 
     for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
         GrPaint paint;
+        paint.setAllowSRGBInputs(allowSRGBInputs);
         SkMatrix matrix;
         matrix.setIDiv(srcTexture->width(), srcTexture->height());
         SkRect dstRect(srcRect);
@@ -268,6 +272,9 @@
         localSrcBounds = srcRect;
     }
 
+    SkSurfaceProps props(allowSRGBInputs ? SkSurfaceProps::kAllowSRGBInputs_Flag : 0,
+                         SkSurfaceProps::kLegacyFontHost_InitType);
+
     // For really small blurs (certainly no wider than 5x5 on desktop gpus) it is faster to just
     // launch a single non separable kernel vs two launches
     srcRect = localDstBounds;
@@ -277,7 +284,7 @@
         SkASSERT((1 == scaleFactorX) && (1 == scaleFactorY));
 
         SkAutoTUnref<GrDrawContext> dstDrawContext(
-                                             context->drawContext(dstTexture->asRenderTarget()));
+            context->drawContext(dstTexture->asRenderTarget(), &props));
         if (!dstDrawContext) {
             return nullptr;
         }
@@ -311,7 +318,7 @@
             }
 
             SkAutoTUnref<GrDrawContext> dstDrawContext(
-                                             context->drawContext(dstTexture->asRenderTarget()));
+                context->drawContext(dstTexture->asRenderTarget(), &props));
             if (!dstDrawContext) {
                 return nullptr;
             }
@@ -344,7 +351,7 @@
             }
 
             SkAutoTUnref<GrDrawContext> dstDrawContext(
-                                               context->drawContext(dstTexture->asRenderTarget()));
+                context->drawContext(dstTexture->asRenderTarget(), &props));
             if (!dstDrawContext) {
                 return nullptr;
             }
@@ -375,6 +382,7 @@
         matrix.setIDiv(srcTexture->width(), srcTexture->height());
 
         GrPaint paint;
+        paint.setAllowSRGBInputs(allowSRGBInputs);
         // FIXME:  this should be mitchell, not bilinear.
         GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode);
         paint.addColorTextureProcessor(srcTexture, matrix, params);
diff --git a/src/effects/SkGpuBlurUtils.h b/src/effects/SkGpuBlurUtils.h
index 013d11b..e81e5da 100644
--- a/src/effects/SkGpuBlurUtils.h
+++ b/src/effects/SkGpuBlurUtils.h
@@ -26,6 +26,7 @@
     * @param srcTexture      The source texture to be blurred.
     * @param canClobberSrc   If true, srcTexture may be overwritten, and
     *                        may be returned as the result.
+    * @param allowSRGBInputs Should sRGB inputs be allowed to perform sRGB to linear conversion.
     * @param dstBounds       The destination bounds, relative to the source texture.
     * @param srcBounds       The source bounds, relative to the source texture. If non-null,
     *                        no pixels will be sampled outside of this rectangle.
@@ -37,6 +38,7 @@
     GrTexture* GaussianBlur(GrContext* context,
                             GrTexture* srcTexture,
                             bool canClobberSrc,
+                            bool allowSRGBInputs,
                             const SkRect& dstBounds,
                             const SkRect* srcBounds,
                             float sigmaX,
diff --git a/src/effects/SkImageSource.cpp b/src/effects/SkImageSource.cpp
index cf8cae2..6a4eb8d 100644
--- a/src/effects/SkImageSource.cpp
+++ b/src/effects/SkImageSource.cpp
@@ -68,11 +68,13 @@
         offset->fX = offset->fY = 0;
         return SkSpecialImage::MakeFromImage(source->internal_getProxy(),
                                              SkIRect::MakeWH(fImage->width(), fImage->height()),
-                                             fImage);
+                                             fImage,
+                                             &source->props());
     }
 
     const SkIRect dstIRect = dstRect.roundOut();
 
+    // SRGBTODO: Propagate SkColorType?
     const SkImageInfo info = SkImageInfo::MakeN32(dstIRect.width(), dstIRect.height(),
                                                   kPremul_SkAlphaType);
 
diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp
index c27a554..e276dc0 100644
--- a/src/effects/SkLightingImageFilter.cpp
+++ b/src/effects/SkLightingImageFilter.cpp
@@ -387,6 +387,7 @@
                                              const SkIRect& bounds) const {
     SkRect srcRect = dstRect.makeOffset(SkIntToScalar(bounds.x()), SkIntToScalar(bounds.y()));
     GrPaint paint;
+    // SRGBTODO: AllowSRGBInputs?
     GrFragmentProcessor* fp = this->getFragmentProcessor(src, matrix, srcBounds, boundaryMode);
     paint.addColorFragmentProcessor(fp)->unref();
     paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
diff --git a/src/effects/SkMorphologyImageFilter.cpp b/src/effects/SkMorphologyImageFilter.cpp
index ea714e5..616c0d2 100644
--- a/src/effects/SkMorphologyImageFilter.cpp
+++ b/src/effects/SkMorphologyImageFilter.cpp
@@ -370,6 +370,7 @@
                                   float bounds[2],
                                   Gr1DKernelEffect::Direction direction) {
     GrPaint paint;
+    // SRGBTODO: AllowSRGBInputs?
     paint.addColorFragmentProcessor(GrMorphologyEffect::Create(texture,
                                                                direction,
                                                                radius,
@@ -389,6 +390,7 @@
                                             GrMorphologyEffect::MorphologyType morphType,
                                             Gr1DKernelEffect::Direction direction) {
     GrPaint paint;
+    // SRGBTODO: AllowSRGBInputs?
     paint.addColorFragmentProcessor(GrMorphologyEffect::Create(texture,
                                                                direction,
                                                                radius,
@@ -511,7 +513,7 @@
     return SkSpecialImage::MakeFromGpu(input->internal_getProxy(),
                                        SkIRect::MakeWH(rect.width(), rect.height()),
                                        kNeedNewImageUniqueID_SpecialImage,
-                                       srcTexture);
+                                       srcTexture, &input->props());
 }
 #endif
 
@@ -619,5 +621,5 @@
 
     return SkSpecialImage::MakeFromRaster(source->internal_getProxy(),
                                           SkIRect::MakeWH(bounds.width(), bounds.height()),
-                                          dst);
+                                          dst, &source->props());
 }
diff --git a/src/effects/SkXfermodeImageFilter.cpp b/src/effects/SkXfermodeImageFilter.cpp
index a29136a..330f839 100644
--- a/src/effects/SkXfermodeImageFilter.cpp
+++ b/src/effects/SkXfermodeImageFilter.cpp
@@ -174,6 +174,7 @@
     }
 
     GrPaint paint;
+    // SRGBTODO: AllowSRGBInputs?
     SkAutoTUnref<const GrFragmentProcessor> bgFP;
 
     if (backgroundTex) {