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) {