From 898235c4864df66aa7f6d32bc2a8b8551040ce1e Mon Sep 17 00:00:00 2001 From: brianosman Date: Wed, 6 Apr 2016 07:38:23 -0700 Subject: 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 --- dm/DM.cpp | 7 ++- dm/DMGpuSupport.h | 3 ++ gm/constcolorprocessor.cpp | 3 +- gm/dftext.cpp | 8 ++- gm/surface.cpp | 13 +++-- gm/textblobgeometrychange.cpp | 7 ++- gm/textblobmixedsizes.cpp | 8 ++- gm/textblobrandomfont.cpp | 8 ++- gm/xfermodes3.cpp | 4 +- include/core/SkCanvas.h | 7 +++ include/core/SkDevice.h | 11 ++-- include/core/SkImageInfo.h | 10 ++++ include/core/SkSurfaceProps.h | 12 +++++ include/gpu/GrDrawContext.h | 1 + include/gpu/GrPaint.h | 9 ++++ include/gpu/GrTypes.h | 10 ---- src/core/SkCanvas.cpp | 15 +++++- src/core/SkDevice.cpp | 3 +- src/core/SkImageFilter.cpp | 9 ++-- src/core/SkSpecialImage.cpp | 74 ++++++++++++++++++--------- src/core/SkSpecialImage.h | 29 ++++++----- src/core/SkSpecialSurface.cpp | 6 ++- src/effects/SkBlurImageFilter.cpp | 5 +- src/effects/SkBlurMaskFilter.cpp | 3 +- src/effects/SkDisplacementMapEffect.cpp | 1 + src/effects/SkGpuBlurUtils.cpp | 14 +++-- src/effects/SkGpuBlurUtils.h | 2 + src/effects/SkImageSource.cpp | 4 +- src/effects/SkLightingImageFilter.cpp | 1 + src/effects/SkMorphologyImageFilter.cpp | 6 ++- src/effects/SkXfermodeImageFilter.cpp | 1 + src/gpu/GrBlurUtils.cpp | 3 +- src/gpu/GrContext.cpp | 4 ++ src/gpu/GrLayerHoister.cpp | 3 +- src/gpu/GrPaint.cpp | 1 + src/gpu/GrPipeline.cpp | 3 ++ src/gpu/GrPipeline.h | 4 ++ src/gpu/GrPipelineBuilder.cpp | 2 + src/gpu/GrPipelineBuilder.h | 9 +++- src/gpu/SkGpuDevice.cpp | 60 ++++++++++++++-------- src/gpu/SkGpuDevice_drawTexture.cpp | 2 +- src/gpu/SkGr.cpp | 19 ++++--- src/gpu/SkGrPriv.h | 9 +++- src/gpu/gl/GrGLGpu.cpp | 6 +-- src/gpu/text/GrAtlasTextContext.cpp | 5 +- src/gpu/text/GrStencilAndCoverTextContext.cpp | 4 +- src/views/SkWindow.cpp | 11 ++-- tools/gpu/GrTest.cpp | 3 +- 48 files changed, 315 insertions(+), 127 deletions(-) diff --git a/dm/DM.cpp b/dm/DM.cpp index 4a81cee9e1..9611f493f1 100644 --- a/dm/DM.cpp +++ b/dm/DM.cpp @@ -822,8 +822,8 @@ static Sink* create_sink(const SkCommandLineConfig* config) { contextOptions = static_cast( contextOptions | GrContextFactory::kEnableNVPR_ContextOptions); } - if (kSRGB_SkColorProfileType == gpuConfig->getProfileType() || - kRGBA_F16_SkColorType == gpuConfig->getColorType()) { + if (SkColorAndProfileAreGammaCorrect(gpuConfig->getColorType(), + gpuConfig->getProfileType())) { contextOptions = static_cast( contextOptions | GrContextFactory::kRequireSRGBSupport_ContextOptions); } @@ -1169,8 +1169,7 @@ struct Task { const SkBitmap* bitmap) { bool gammaCorrect = false; if (bitmap) { - gammaCorrect = bitmap->profileType() == kSRGB_SkColorProfileType - || bitmap-> colorType() == kRGBA_F16_SkColorType; + gammaCorrect = SkImageInfoIsGammaCorrect(bitmap->info()); } JsonWriter::BitmapResult result; diff --git a/dm/DMGpuSupport.h b/dm/DMGpuSupport.h index 2352f83ae4..42c5eb30ae 100644 --- a/dm/DMGpuSupport.h +++ b/dm/DMGpuSupport.h @@ -36,6 +36,9 @@ static inline sk_sp NewGpuSurface( int samples, bool useDIText) { uint32_t flags = useDIText ? SkSurfaceProps::kUseDeviceIndependentFonts_Flag : 0; + if (SkImageInfoIsGammaCorrect(info)) { + flags |= SkSurfaceProps::kAllowSRGBInputs_Flag; + } SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType); return SkSurface::MakeRenderTarget(grFactory->get(type, options), SkBudgeted::kNo, info, samples, &props); diff --git a/gm/constcolorprocessor.cpp b/gm/constcolorprocessor.cpp index 8c91a722ec..37295c78cc 100644 --- a/gm/constcolorprocessor.cpp +++ b/gm/constcolorprocessor.cpp @@ -104,7 +104,8 @@ protected: } else { skPaint.setColor(kPaintColors[paintType]); } - SkAssertResult(SkPaintToGrPaint(context, skPaint, viewMatrix, &grPaint)); + // SRGBTODO: No sRGB inputs allowed here? + SkAssertResult(SkPaintToGrPaint(context, skPaint, viewMatrix, false, &grPaint)); GrConstColorProcessor::InputMode mode = (GrConstColorProcessor::InputMode) m; GrColor color = kColors[procColor]; diff --git a/gm/dftext.cpp b/gm/dftext.cpp index 0d5b1ff4e9..c66064a8d4 100644 --- a/gm/dftext.cpp +++ b/gm/dftext.cpp @@ -48,8 +48,12 @@ protected: // set up offscreen rendering with distance field text #if SK_SUPPORT_GPU GrContext* ctx = inputCanvas->getGrContext(); - SkImageInfo info = SkImageInfo::MakeN32Premul(onISize()); - SkSurfaceProps props(SkSurfaceProps::kUseDeviceIndependentFonts_Flag, + SkImageInfo info = SkImageInfo::MakeN32Premul(onISize(), + inputCanvas->imageInfo().profileType()); + SkSurfaceProps canvasProps(SkSurfaceProps::kLegacyFontHost_InitType); + uint32_t allowSRGBInputs = inputCanvas->getProps(&canvasProps) + ? canvasProps.flags() & SkSurfaceProps::kAllowSRGBInputs_Flag : 0; + SkSurfaceProps props(SkSurfaceProps::kUseDeviceIndependentFonts_Flag | allowSRGBInputs, SkSurfaceProps::kLegacyFontHost_InitType); auto surface(SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info, 0, &props)); SkCanvas* canvas = surface ? surface->getCanvas() : inputCanvas; diff --git a/gm/surface.cpp b/gm/surface.cpp index 901e324397..e104cb5ecf 100644 --- a/gm/surface.cpp +++ b/gm/surface.cpp @@ -22,7 +22,7 @@ static sk_sp make_shader() { } static sk_sp make_surface(GrContext* ctx, const SkImageInfo& info, SkPixelGeometry geo, - int disallowAA, int disallowDither) { + int disallowAA, int disallowDither, bool allowSRGBInputs) { uint32_t flags = 0; if (disallowAA) { flags |= SkSurfaceProps::kDisallowAntiAlias_Flag; @@ -30,6 +30,9 @@ static sk_sp make_surface(GrContext* ctx, const SkImageInfo& info, Sk if (disallowDither) { flags |= SkSurfaceProps::kDisallowDither_Flag; } + if (allowSRGBInputs) { + flags |= SkSurfaceProps::kAllowSRGBInputs_Flag; + } SkSurfaceProps props(flags, geo); if (ctx) { @@ -74,7 +77,10 @@ protected: GrContext* ctx = canvas->getGrContext(); // must be opaque to have a hope of testing LCD text - const SkImageInfo info = SkImageInfo::MakeN32(W, H, kOpaque_SkAlphaType); + const SkImageInfo info = SkImageInfo::MakeN32(W, H, kOpaque_SkAlphaType, + canvas->imageInfo().profileType()); + SkSurfaceProps canvasProps(SkSurfaceProps::kLegacyFontHost_InitType); + bool allowSRGBInputs = canvas->getProps(&canvasProps) && canvasProps.allowSRGBInputs(); const struct { SkPixelGeometry fGeo; @@ -92,7 +98,8 @@ protected: for (int disallowDither = 0; disallowDither <= 1; ++disallowDither) { SkScalar y = 0; for (size_t i = 0; i < SK_ARRAY_COUNT(rec); ++i) { - auto surface(make_surface(ctx, info, rec[i].fGeo, disallowAA, disallowDither)); + auto surface(make_surface(ctx, info, rec[i].fGeo, disallowAA, disallowDither, + allowSRGBInputs)); test_draw(surface->getCanvas(), rec[i].fLabel); surface->draw(canvas, x, y, nullptr); y += H; diff --git a/gm/textblobgeometrychange.cpp b/gm/textblobgeometrychange.cpp index 0632908dfb..b1c5b17988 100644 --- a/gm/textblobgeometrychange.cpp +++ b/gm/textblobgeometrychange.cpp @@ -42,8 +42,11 @@ protected: SkAutoTUnref blob(builder.build()); - SkImageInfo info = SkImageInfo::MakeN32Premul(200, 200); - SkSurfaceProps props(0, kUnknown_SkPixelGeometry); + SkImageInfo info = SkImageInfo::MakeN32Premul(200, 200, canvas->imageInfo().profileType()); + SkSurfaceProps canvasProps(SkSurfaceProps::kLegacyFontHost_InitType); + uint32_t allowSRGBInputs = canvas->getProps(&canvasProps) + ? canvasProps.flags() & SkSurfaceProps::kAllowSRGBInputs_Flag : 0; + SkSurfaceProps props(allowSRGBInputs, kUnknown_SkPixelGeometry); auto surface(canvas->makeSurface(info, &props)); if (surface) { SkCanvas* c = surface->getCanvas(); diff --git a/gm/textblobmixedsizes.cpp b/gm/textblobmixedsizes.cpp index 82a0dbbd2a..6041e521fd 100644 --- a/gm/textblobmixedsizes.cpp +++ b/gm/textblobmixedsizes.cpp @@ -103,8 +103,12 @@ protected: #if SK_SUPPORT_GPU // Create a new Canvas to enable DFT GrContext* ctx = inputCanvas->getGrContext(); - SkImageInfo info = SkImageInfo::MakeN32Premul(onISize()); - SkSurfaceProps props(SkSurfaceProps::kUseDeviceIndependentFonts_Flag, + SkImageInfo info = SkImageInfo::MakeN32Premul(onISize(), + inputCanvas->imageInfo().profileType()); + SkSurfaceProps canvasProps(SkSurfaceProps::kLegacyFontHost_InitType); + uint32_t allowSRGBInputs = inputCanvas->getProps(&canvasProps) + ? canvasProps.flags() & SkSurfaceProps::kAllowSRGBInputs_Flag : 0; + SkSurfaceProps props(SkSurfaceProps::kUseDeviceIndependentFonts_Flag | allowSRGBInputs, SkSurfaceProps::kLegacyFontHost_InitType); surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info, 0, &props); canvas = surface.get() ? surface->getCanvas() : inputCanvas; diff --git a/gm/textblobrandomfont.cpp b/gm/textblobrandomfont.cpp index ce726f2e86..285ba5b923 100644 --- a/gm/textblobrandomfont.cpp +++ b/gm/textblobrandomfont.cpp @@ -100,8 +100,12 @@ protected: canvas->drawColor(sk_tool_utils::color_to_565(SK_ColorWHITE)); - SkImageInfo info = SkImageInfo::MakeN32Premul(kWidth, kHeight); - SkSurfaceProps props(0, kUnknown_SkPixelGeometry); + SkImageInfo info = SkImageInfo::MakeN32Premul(kWidth, kHeight, + canvas->imageInfo().profileType()); + SkSurfaceProps canvasProps(SkSurfaceProps::kLegacyFontHost_InitType); + uint32_t allowSRGBInputs = canvas->getProps(&canvasProps) + ? canvasProps.flags() & SkSurfaceProps::kAllowSRGBInputs_Flag : 0; + SkSurfaceProps props(allowSRGBInputs, kUnknown_SkPixelGeometry); auto surface(canvas->makeSurface(info, &props)); if (surface) { SkPaint paint; diff --git a/gm/xfermodes3.cpp b/gm/xfermodes3.cpp index 84bc1e2218..e5c8dd5eb7 100644 --- a/gm/xfermodes3.cpp +++ b/gm/xfermodes3.cpp @@ -128,7 +128,9 @@ private: SkImageInfo baseInfo = baseCanvas->imageInfo(); SkImageInfo info = SkImageInfo::Make(w, h, baseInfo.colorType(), baseInfo.alphaType(), baseInfo.profileType()); - return SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info, 0, nullptr); + SkSurfaceProps canvasProps(SkSurfaceProps::kLegacyFontHost_InitType); + baseCanvas->getProps(&canvasProps); + return SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info, 0, &canvasProps); #else return nullptr; #endif diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h index 91952c3050..8e675b42fc 100644 --- a/include/core/SkCanvas.h +++ b/include/core/SkCanvas.h @@ -122,6 +122,13 @@ public: */ SkImageInfo imageInfo() const; + /** + * If the canvas is backed by pixels (cpu or gpu), this writes a copy of the SurfaceProps + * for the canvas to the location supplied by the caller, and returns true. Otherwise, + * return false and leave the supplied props unchanged. + */ + bool getProps(SkSurfaceProps*) const; + /////////////////////////////////////////////////////////////////////////// /** diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h index 55b08a762c..c15aeccf82 100644 --- a/include/core/SkDevice.h +++ b/include/core/SkDevice.h @@ -40,6 +40,13 @@ public: */ virtual SkImageInfo imageInfo() const; + /** + * Return SurfaceProps for this device. + */ + const SkSurfaceProps& surfaceProps() const { + return fSurfaceProps; + } + /** * Return the bounds of the device in the coordinate space of the root * canvas. The root device will have its top-left at 0,0, but other devices @@ -317,10 +324,6 @@ protected: virtual bool onAccessPixels(SkPixmap*) { return false; } - const SkSurfaceProps& surfaceProps() const { - return fSurfaceProps; - } - /** * PRIVATE / EXPERIMENTAL -- do not call * This entry point gives the backend an opportunity to take over the rendering diff --git a/include/core/SkImageInfo.h b/include/core/SkImageInfo.h index b2dda3f021..c55edd36c2 100644 --- a/include/core/SkImageInfo.h +++ b/include/core/SkImageInfo.h @@ -318,4 +318,14 @@ private: {} }; +/////////////////////////////////////////////////////////////////////////////// + +static inline bool SkColorAndProfileAreGammaCorrect(SkColorType ct, SkColorProfileType pt) { + return kSRGB_SkColorProfileType == pt || kRGBA_F16_SkColorType == ct; +} + +static inline bool SkImageInfoIsGammaCorrect(const SkImageInfo& info) { + return SkColorAndProfileAreGammaCorrect(info.colorType(), info.profileType()); +} + #endif diff --git a/include/core/SkSurfaceProps.h b/include/core/SkSurfaceProps.h index 735561f1dc..bd4fa8e7fc 100644 --- a/include/core/SkSurfaceProps.h +++ b/include/core/SkSurfaceProps.h @@ -54,6 +54,17 @@ public: kDisallowAntiAlias_Flag = 1 << 0, kDisallowDither_Flag = 1 << 1, kUseDeviceIndependentFonts_Flag = 1 << 2, + + /** + * This flag causes sRGB inputs to the color pipeline (images and other sRGB-tagged + * colors) to be gamma-corrected (converted to linear) before use. Without this flag, + * texture scaling and filtering is not gamma correct, preserving the behavior of Skia + * up through 2015. + * + * It is recommended to enable this flag when rendering to an sRGB or floating point + * surface. + */ + kAllowSRGBInputs_Flag = 1 << 3, }; /** Deprecated alias used by Chromium. Will be removed. */ static const Flags kUseDistanceFieldFonts_Flag = kUseDeviceIndependentFonts_Flag; @@ -75,6 +86,7 @@ public: bool isUseDeviceIndependentFonts() const { return SkToBool(fFlags & kUseDeviceIndependentFonts_Flag); } + bool allowSRGBInputs() const { return SkToBool(fFlags & kAllowSRGBInputs_Flag); } private: SkSurfaceProps(); diff --git a/include/gpu/GrDrawContext.h b/include/gpu/GrDrawContext.h index 1643cc9678..06954dc1bb 100644 --- a/include/gpu/GrDrawContext.h +++ b/include/gpu/GrDrawContext.h @@ -276,6 +276,7 @@ public: int width() const { return fRenderTarget->width(); } int height() const { return fRenderTarget->height(); } int numColorSamples() const { return fRenderTarget->numColorSamples(); } + bool allowSRGBInputs() const { return fSurfaceProps.allowSRGBInputs(); } GrRenderTarget* accessRenderTarget() { return fRenderTarget; } diff --git a/include/gpu/GrPaint.h b/include/gpu/GrPaint.h index 3f06f092ab..87e0368655 100644 --- a/include/gpu/GrPaint.h +++ b/include/gpu/GrPaint.h @@ -63,6 +63,13 @@ public: void setDisableOutputConversionToSRGB(bool srgb) { fDisableOutputConversionToSRGB = srgb; } bool getDisableOutputConversionToSRGB() const { return fDisableOutputConversionToSRGB; } + /** + * Should sRGB inputs be allowed to perform sRGB to linear conversion. With this flag + * set to false, sRGB textures will be treated as linear (including filtering). + */ + void setAllowSRGBInputs(bool allowSRGBInputs) { fAllowSRGBInputs = allowSRGBInputs; } + bool getAllowSRGBInputs() const { return fAllowSRGBInputs; } + const GrXPFactory* setXPFactory(const GrXPFactory* xpFactory) { fXPFactory.reset(SkSafeRef(xpFactory)); return xpFactory; @@ -120,6 +127,7 @@ public: GrPaint& operator=(const GrPaint& paint) { fAntiAlias = paint.fAntiAlias; fDisableOutputConversionToSRGB = paint.fDisableOutputConversionToSRGB; + fAllowSRGBInputs = paint.fAllowSRGBInputs; fColor = paint.fColor; this->resetFragmentProcessors(); @@ -163,6 +171,7 @@ private: bool fAntiAlias; bool fDisableOutputConversionToSRGB; + bool fAllowSRGBInputs; GrColor fColor; }; diff --git a/include/gpu/GrTypes.h b/include/gpu/GrTypes.h index 9be500d3b2..47c13ec02d 100644 --- a/include/gpu/GrTypes.h +++ b/include/gpu/GrTypes.h @@ -399,16 +399,6 @@ static inline bool GrPixelConfigIsAlphaOnly(GrPixelConfig config) { } } -static inline bool GrAllowSRGBForDestinationPixelConfig(GrPixelConfig config) { - switch (config) { - case kRGBA_8888_GrPixelConfig: - case kBGRA_8888_GrPixelConfig: - return false; - default: - return true; - } -} - /** * Optional bitfield flags that can be set on GrSurfaceDesc (below). */ diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index 2f6477c41d..de69c368cd 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -1334,6 +1334,18 @@ SkImageInfo SkCanvas::imageInfo() const { } } +bool SkCanvas::getProps(SkSurfaceProps* props) const { + SkBaseDevice* dev = this->getDevice(); + if (dev) { + if (props) { + *props = fProps; + } + return true; + } else { + return false; + } +} + #ifdef SK_SUPPORT_LEGACY_PEEKPIXELS_PARMS const void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) { SkPixmap pmap; @@ -1406,7 +1418,8 @@ void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, SkAutoTUnref cache(dstDev->getImageFilterCache()); SkImageFilter::Context ctx(matrix, clipBounds, cache.get()); - sk_sp srcImg(SkSpecialImage::internal_fromBM(&proxy, srcBM)); + sk_sp srcImg(SkSpecialImage::internal_fromBM(&proxy, srcBM, + &dstDev->surfaceProps())); if (!srcImg) { continue; // something disastrous happened } diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp index 3a4090e2d3..1b22856528 100644 --- a/src/core/SkDevice.cpp +++ b/src/core/SkDevice.cpp @@ -418,7 +418,8 @@ void SkBaseDevice::drawSpriteWithFilter(const SkDraw& draw, const SkBitmap& bitm SkAutoTUnref cache(this->getImageFilterCache()); SkImageFilter::Context ctx(matrix, clipBounds, cache.get()); - sk_sp srcImg(SkSpecialImage::internal_fromBM(&proxy, bitmap)); + sk_sp srcImg(SkSpecialImage::internal_fromBM(&proxy, bitmap, + &this->surfaceProps())); if (!srcImg) { return; // something disastrous happened } diff --git a/src/core/SkImageFilter.cpp b/src/core/SkImageFilter.cpp index 0e0df3625f..743dc2ad1a 100644 --- a/src/core/SkImageFilter.cpp +++ b/src/core/SkImageFilter.cpp @@ -295,7 +295,8 @@ bool SkImageFilter::filterInputDeprecated(int index, Proxy* proxy, const SkBitma return true; } - sk_sp specialSrc(SkSpecialImage::internal_fromBM(proxy, src)); + // SRGBTODO: Don't handle sRGB here, in anticipation of this code path being deleted. + sk_sp specialSrc(SkSpecialImage::internal_fromBM(proxy, src, nullptr)); if (!specialSrc) { return false; } @@ -377,7 +378,7 @@ sk_sp SkImageFilter::onFilterImage(SkSpecialImage* src, const Co return nullptr; } - return SkSpecialImage::internal_fromBM(src->internal_getProxy(), resultBM); + return SkSpecialImage::internal_fromBM(src->internal_getProxy(), resultBM, &src->props()); } bool SkImageFilter::canFilterImageGPU() const { @@ -418,6 +419,7 @@ bool SkImageFilter::filterImageGPUDeprecated(Proxy* proxy, const SkBitmap& src, SkMatrix matrix(ctx.ctm()); matrix.postTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top())); GrPaint paint; + // SRGBTODO: Don't handle sRGB here, in anticipation of this code path being deleted. if (this->asFragmentProcessor(&fp, srcTexture, matrix, bounds)) { SkASSERT(fp); paint.addColorFragmentProcessor(fp)->unref(); @@ -620,7 +622,8 @@ bool SkImageFilter::filterInputGPUDeprecated(int index, SkImageFilter::Proxy* pr return true; } - sk_sp specialSrc(SkSpecialImage::internal_fromBM(proxy, src)); + // SRGBTODO: Don't handle sRGB here, in anticipation of this code path being deleted. + sk_sp specialSrc(SkSpecialImage::internal_fromBM(proxy, src, nullptr)); if (!specialSrc) { return false; } diff --git a/src/core/SkSpecialImage.cpp b/src/core/SkSpecialImage.cpp index 681c224ad8..abac9471cd 100644 --- a/src/core/SkSpecialImage.cpp +++ b/src/core/SkSpecialImage.cpp @@ -15,12 +15,14 @@ #include "SkCanvas.h" #include "SkImage_Base.h" #include "SkSpecialSurface.h" +#include "SkSurfacePriv.h" /////////////////////////////////////////////////////////////////////////////// class SkSpecialImage_Base : public SkSpecialImage { public: - SkSpecialImage_Base(SkImageFilter::Proxy* proxy, const SkIRect& subset, uint32_t uniqueID) - : INHERITED(proxy, subset, uniqueID) { + SkSpecialImage_Base(SkImageFilter::Proxy* proxy, const SkIRect& subset, uint32_t uniqueID, + const SkSurfaceProps* props) + : INHERITED(proxy, subset, uniqueID, props) { } virtual ~SkSpecialImage_Base() { } @@ -52,6 +54,16 @@ static inline const SkSpecialImage_Base* as_SIB(const SkSpecialImage* image) { return static_cast(image); } +SkSpecialImage::SkSpecialImage(SkImageFilter::Proxy* proxy, + const SkIRect& subset, + uint32_t uniqueID, + const SkSurfaceProps* props) + : fProps(SkSurfacePropsCopyOrDefault(props)) + , fSubset(subset) + , fUniqueID(kNeedNewImageUniqueID_SpecialImage == uniqueID ? SkNextID::ImageID() : uniqueID) + , fProxy(proxy) { +} + sk_sp SkSpecialImage::makeTextureImage(SkImageFilter::Proxy* proxy, GrContext* context) { #if SK_SUPPORT_GPU @@ -68,7 +80,7 @@ sk_sp SkSpecialImage::makeTextureImage(SkImageFilter::Proxy* pro } if (bmp.empty()) { - return SkSpecialImage::MakeFromRaster(proxy, SkIRect::MakeEmpty(), bmp); + return SkSpecialImage::MakeFromRaster(proxy, SkIRect::MakeEmpty(), bmp, &this->props()); } SkAutoTUnref resultTex( @@ -82,7 +94,7 @@ sk_sp SkSpecialImage::makeTextureImage(SkImageFilter::Proxy* pro return SkSpecialImage::MakeFromGpu(proxy, SkIRect::MakeWH(resultTex->width(), resultTex->height()), this->uniqueID(), - resultTex, at); + resultTex, &this->props(), at); #else return nullptr; #endif @@ -126,16 +138,18 @@ sk_sp SkSpecialImage::makeTightSubset(const SkIRect& subset) const { #endif sk_sp SkSpecialImage::internal_fromBM(SkImageFilter::Proxy* proxy, - const SkBitmap& src) { + const SkBitmap& src, + const SkSurfaceProps* props) { // Need to test offset case! (see skbug.com/4967) if (src.getTexture()) { return SkSpecialImage::MakeFromGpu(proxy, src.bounds(), src.getGenerationID(), - src.getTexture()); + src.getTexture(), + props); } - return SkSpecialImage::MakeFromRaster(proxy, src.bounds(), src); + return SkSpecialImage::MakeFromRaster(proxy, src.bounds(), src, props); } bool SkSpecialImage::internal_getBM(SkBitmap* result) { @@ -160,8 +174,9 @@ class SkSpecialImage_Image : public SkSpecialImage_Base { public: SkSpecialImage_Image(SkImageFilter::Proxy* proxy, const SkIRect& subset, - sk_sp image) - : INHERITED(proxy, subset, image->uniqueID()) + sk_sp image, + const SkSurfaceProps* props) + : INHERITED(proxy, subset, image->uniqueID(), props) , fImage(image) { } @@ -240,7 +255,8 @@ public: return SkSpecialImage::MakeFromImage(this->internal_getProxy(), SkIRect::MakeWH(subset.width(), subset.height()), - subsetImg); + subsetImg, + &this->props()); } sk_sp onMakeTightSubset(const SkIRect& subset) const override { @@ -279,10 +295,11 @@ static bool rect_fits(const SkIRect& rect, int width, int height) { sk_sp SkSpecialImage::MakeFromImage(SkImageFilter::Proxy* proxy, const SkIRect& subset, - sk_sp image) { + sk_sp image, + const SkSurfaceProps* props) { SkASSERT(rect_fits(subset, image->width(), image->height())); - return sk_make_sp(proxy, subset, image); + return sk_make_sp(proxy, subset, image, props); } /////////////////////////////////////////////////////////////////////////////// @@ -292,8 +309,9 @@ sk_sp SkSpecialImage::MakeFromImage(SkImageFilter::Proxy* proxy, class SkSpecialImage_Raster : public SkSpecialImage_Base { public: - SkSpecialImage_Raster(SkImageFilter::Proxy* proxy, const SkIRect& subset, const SkBitmap& bm) - : INHERITED(proxy, subset, bm.getGenerationID()) + SkSpecialImage_Raster(SkImageFilter::Proxy* proxy, const SkIRect& subset, const SkBitmap& bm, + const SkSurfaceProps* props) + : INHERITED(proxy, subset, bm.getGenerationID(), props) , fBitmap(bm) { if (bm.pixelRef() && bm.pixelRef()->isPreLocked()) { // we only preemptively lock if there is no chance of triggering something expensive @@ -306,8 +324,9 @@ public: const SkIRect& subset, const SkPixmap& pixmap, RasterReleaseProc releaseProc, - ReleaseContext context) - : INHERITED(proxy, subset, kNeedNewImageUniqueID_SpecialImage) { + ReleaseContext context, + const SkSurfaceProps* props) + : INHERITED(proxy, subset, kNeedNewImageUniqueID_SpecialImage, props) { fBitmap.installPixels(pixmap.info(), pixmap.writable_addr(), pixmap.rowBytes(), pixmap.ctable(), releaseProc, context); @@ -364,7 +383,8 @@ public: return SkSpecialImage::MakeFromRaster(this->internal_getProxy(), SkIRect::MakeWH(subset.width(), subset.height()), - subsetBM); + subsetBM, + &this->props()); } sk_sp onMakeTightSubset(const SkIRect& subset) const override { @@ -389,23 +409,25 @@ private: sk_sp SkSpecialImage::MakeFromRaster(SkImageFilter::Proxy* proxy, const SkIRect& subset, - const SkBitmap& bm) { + const SkBitmap& bm, + const SkSurfaceProps* props) { SkASSERT(nullptr == bm.getTexture()); SkASSERT(rect_fits(subset, bm.width(), bm.height())); - return sk_make_sp(proxy, subset, bm); + return sk_make_sp(proxy, subset, bm, props); } sk_sp SkSpecialImage::MakeFromPixmap(SkImageFilter::Proxy* proxy, const SkIRect& subset, const SkPixmap& src, RasterReleaseProc releaseProc, - ReleaseContext context) { + ReleaseContext context, + const SkSurfaceProps* props) { if (!src.addr()) { return nullptr; } - return sk_make_sp(proxy, subset, src, releaseProc, context); + return sk_make_sp(proxy, subset, src, releaseProc, context, props); } @@ -417,8 +439,9 @@ sk_sp SkSpecialImage::MakeFromPixmap(SkImageFilter::Proxy* proxy class SkSpecialImage_Gpu : public SkSpecialImage_Base { public: SkSpecialImage_Gpu(SkImageFilter::Proxy* proxy, const SkIRect& subset, - uint32_t uniqueID, GrTexture* tex, SkAlphaType at) - : INHERITED(proxy, subset, uniqueID) + uint32_t uniqueID, GrTexture* tex, SkAlphaType at, + const SkSurfaceProps* props) + : INHERITED(proxy, subset, uniqueID, props) , fTexture(SkRef(tex)) , fAlphaType(at) { } @@ -496,6 +519,7 @@ public: subset, this->uniqueID(), fTexture, + &this->props(), fAlphaType); } @@ -539,9 +563,10 @@ sk_sp SkSpecialImage::MakeFromGpu(SkImageFilter::Proxy* proxy, const SkIRect& subset, uint32_t uniqueID, GrTexture* tex, + const SkSurfaceProps* props, SkAlphaType at) { SkASSERT(rect_fits(subset, tex->width(), tex->height())); - return sk_make_sp(proxy, subset, uniqueID, tex, at); + return sk_make_sp(proxy, subset, uniqueID, tex, at, props); } #else @@ -550,6 +575,7 @@ sk_sp SkSpecialImage::MakeFromGpu(SkImageFilter::Proxy* proxy, const SkIRect& subset, uint32_t uniqueID, GrTexture* tex, + const SkSurfaceProps* props, SkAlphaType at) { return nullptr; } diff --git a/src/core/SkSpecialImage.h b/src/core/SkSpecialImage.h index 4de28ebd16..57785fa445 100644 --- a/src/core/SkSpecialImage.h +++ b/src/core/SkSpecialImage.h @@ -10,6 +10,7 @@ #include "SkNextID.h" #include "SkRefCnt.h" +#include "SkSurfaceProps.h" // remove this when internal_getProxy goes away (see skbug.com/4965) #include "SkImageFilter.h" @@ -47,6 +48,8 @@ public: typedef void* ReleaseContext; typedef void(*RasterReleaseProc)(void* pixels, ReleaseContext); + const SkSurfaceProps& props() const { return fProps; } + int width() const { return fSubset.width(); } int height() const { return fSubset.height(); } const SkIRect& subset() const { return fSubset; } @@ -69,20 +72,24 @@ public: static sk_sp MakeFromImage(SkImageFilter::Proxy*, const SkIRect& subset, - sk_sp); + sk_sp, + const SkSurfaceProps* = nullptr); static sk_sp MakeFromRaster(SkImageFilter::Proxy*, const SkIRect& subset, - const SkBitmap&); + const SkBitmap&, + const SkSurfaceProps* = nullptr); static sk_sp MakeFromGpu(SkImageFilter::Proxy*, const SkIRect& subset, uint32_t uniqueID, GrTexture*, + const SkSurfaceProps* = nullptr, SkAlphaType at = kPremul_SkAlphaType); static sk_sp MakeFromPixmap(SkImageFilter::Proxy*, const SkIRect& subset, const SkPixmap&, RasterReleaseProc, - ReleaseContext); + ReleaseContext, + const SkSurfaceProps* = nullptr); /** * Create a new special surface with a backend that is compatible with this special image. @@ -110,7 +117,8 @@ public: // These three internal methods will go away (see skbug.com/4965) bool internal_getBM(SkBitmap* result); - static sk_sp internal_fromBM(SkImageFilter::Proxy*, const SkBitmap&); + static sk_sp internal_fromBM(SkImageFilter::Proxy*, const SkBitmap&, + const SkSurfaceProps*); SkImageFilter::Proxy* internal_getProxy() const; // TODO: hide this when GrLayerHoister uses SkSpecialImages more fully (see skbug.com/5063) @@ -135,12 +143,8 @@ public: bool peekPixels(SkPixmap*) const; protected: - SkSpecialImage(SkImageFilter::Proxy* proxy, const SkIRect& subset, uint32_t uniqueID) - : fSubset(subset) - , fUniqueID(kNeedNewImageUniqueID_SpecialImage == uniqueID ? SkNextID::ImageID() - : uniqueID) - , fProxy(proxy) { - } + SkSpecialImage(SkImageFilter::Proxy*, const SkIRect& subset, uint32_t uniqueID, + const SkSurfaceProps*); // The following 2 are for testing and shouldn't be used. friend class TestingSpecialImageAccess; @@ -154,8 +158,9 @@ protected: SkImageFilter::Proxy* proxy() const { return fProxy; } private: - const SkIRect fSubset; - const uint32_t fUniqueID; + const SkSurfaceProps fProps; + const SkIRect fSubset; + const uint32_t fUniqueID; // TODO: remove this ASAP (see skbug.com/4965) SkImageFilter::Proxy* fProxy; diff --git a/src/core/SkSpecialSurface.cpp b/src/core/SkSpecialSurface.cpp index 2ac71ffb52..7dced71eb2 100644 --- a/src/core/SkSpecialSurface.cpp +++ b/src/core/SkSpecialSurface.cpp @@ -82,7 +82,8 @@ public: ~SkSpecialSurface_Raster() override { } sk_sp onMakeImageSnapshot() override { - return SkSpecialImage::MakeFromRaster(this->proxy(), this->subset(), fBitmap); + return SkSpecialImage::MakeFromRaster(this->proxy(), this->subset(), fBitmap, + &this->props()); } private: @@ -139,7 +140,8 @@ public: sk_sp onMakeImageSnapshot() override { return SkSpecialImage::MakeFromGpu(this->proxy(), this->subset(), - kNeedNewImageUniqueID_SpecialImage, fTexture); + kNeedNewImageUniqueID_SpecialImage, fTexture, + &this->props()); } private: diff --git a/src/effects/SkBlurImageFilter.cpp b/src/effects/SkBlurImageFilter.cpp index b7745e27bf..10c8a0b17b 100644 --- a/src/effects/SkBlurImageFilter.cpp +++ b/src/effects/SkBlurImageFilter.cpp @@ -113,6 +113,7 @@ sk_sp SkBlurImageFilter::onFilterImage(SkSpecialImage* source, SkAutoTUnref tex(SkGpuBlurUtils::GaussianBlur(inputTexture->getContext(), inputTexture, false, + source->props().allowSRGBInputs(), SkRect::Make(dstBounds), &inputBoundsF, sigma.x(), @@ -124,7 +125,7 @@ sk_sp SkBlurImageFilter::onFilterImage(SkSpecialImage* source, return SkSpecialImage::MakeFromGpu(source->internal_getProxy(), SkIRect::MakeWH(dstBounds.width(), dstBounds.height()), kNeedNewImageUniqueID_SpecialImage, - tex); + tex, &source->props()); } #endif @@ -216,7 +217,7 @@ sk_sp SkBlurImageFilter::onFilterImage(SkSpecialImage* source, 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 bb6a8a5ae6..609e168f01 100644 --- a/src/effects/SkBlurMaskFilter.cpp +++ b/src/effects/SkBlurMaskFilter.cpp @@ -1243,7 +1243,8 @@ bool SkBlurMaskFilterImpl::filterMaskGPU(GrTexture* src, // 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 447a20bcb2..6debea16e4 100644 --- a/src/effects/SkDisplacementMapEffect.cpp +++ b/src/effects/SkDisplacementMapEffect.cpp @@ -431,6 +431,7 @@ bool SkDisplacementMapEffect::filterImageGPUDeprecated(Proxy* proxy, const SkBit 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 c43f27303e..90619f9dc8 100644 --- a/src/effects/SkGpuBlurUtils.cpp +++ b/src/effects/SkGpuBlurUtils.cpp @@ -56,6 +56,7 @@ static void convolve_gaussian_1d(GrDrawContext* drawContext, bool useBounds, float bounds[2]) { GrPaint paint; + paint.setAllowSRGBInputs(drawContext->allowSRGBInputs()); SkAutoTUnref conv(GrConvolutionEffect::CreateGaussian( texture, direction, radius, sigma, useBounds, bounds)); paint.addColorFragmentProcessor(conv); @@ -78,6 +79,7 @@ static void convolve_gaussian_2d(GrDrawContext* drawContext, 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 @@ static void convolve_gaussian(GrDrawContext* drawContext, GrTexture* GaussianBlur(GrContext* context, GrTexture* srcTexture, bool canClobberSrc, + bool allowSRGBInputs, const SkRect& dstBounds, const SkRect* srcBounds, float sigmaX, @@ -229,6 +232,7 @@ GrTexture* GaussianBlur(GrContext* context, 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 @@ GrTexture* GaussianBlur(GrContext* context, 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 @@ GrTexture* GaussianBlur(GrContext* context, SkASSERT((1 == scaleFactorX) && (1 == scaleFactorY)); SkAutoTUnref dstDrawContext( - context->drawContext(dstTexture->asRenderTarget())); + context->drawContext(dstTexture->asRenderTarget(), &props)); if (!dstDrawContext) { return nullptr; } @@ -311,7 +318,7 @@ GrTexture* GaussianBlur(GrContext* context, } SkAutoTUnref dstDrawContext( - context->drawContext(dstTexture->asRenderTarget())); + context->drawContext(dstTexture->asRenderTarget(), &props)); if (!dstDrawContext) { return nullptr; } @@ -344,7 +351,7 @@ GrTexture* GaussianBlur(GrContext* context, } SkAutoTUnref dstDrawContext( - context->drawContext(dstTexture->asRenderTarget())); + context->drawContext(dstTexture->asRenderTarget(), &props)); if (!dstDrawContext) { return nullptr; } @@ -375,6 +382,7 @@ GrTexture* GaussianBlur(GrContext* context, 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 013d11b517..e81e5daddb 100644 --- a/src/effects/SkGpuBlurUtils.h +++ b/src/effects/SkGpuBlurUtils.h @@ -26,6 +26,7 @@ namespace SkGpuBlurUtils { * @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 @@ namespace SkGpuBlurUtils { 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 cf8cae2c39..6a4eb8d3aa 100644 --- a/src/effects/SkImageSource.cpp +++ b/src/effects/SkImageSource.cpp @@ -68,11 +68,13 @@ sk_sp SkImageSource::onFilterImage(SkSpecialImage* source, const 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 c27a55476f..e276dc0fde 100644 --- a/src/effects/SkLightingImageFilter.cpp +++ b/src/effects/SkLightingImageFilter.cpp @@ -387,6 +387,7 @@ void SkLightingImageFilterInternal::drawRect(GrDrawContext* drawContext, 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 ea714e59f6..616c0d2e8b 100644 --- a/src/effects/SkMorphologyImageFilter.cpp +++ b/src/effects/SkMorphologyImageFilter.cpp @@ -370,6 +370,7 @@ static void apply_morphology_rect(GrDrawContext* drawContext, float bounds[2], Gr1DKernelEffect::Direction direction) { GrPaint paint; + // SRGBTODO: AllowSRGBInputs? paint.addColorFragmentProcessor(GrMorphologyEffect::Create(texture, direction, radius, @@ -389,6 +390,7 @@ static void apply_morphology_rect_no_bounds(GrDrawContext* drawContext, GrMorphologyEffect::MorphologyType morphType, Gr1DKernelEffect::Direction direction) { GrPaint paint; + // SRGBTODO: AllowSRGBInputs? paint.addColorFragmentProcessor(GrMorphologyEffect::Create(texture, direction, radius, @@ -511,7 +513,7 @@ static sk_sp apply_morphology(SkSpecialImage* input, return SkSpecialImage::MakeFromGpu(input->internal_getProxy(), SkIRect::MakeWH(rect.width(), rect.height()), kNeedNewImageUniqueID_SpecialImage, - srcTexture); + srcTexture, &input->props()); } #endif @@ -619,5 +621,5 @@ sk_sp SkMorphologyImageFilter::onFilterImage(SkSpecialImage* sou 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 a29136a0dd..330f839152 100644 --- a/src/effects/SkXfermodeImageFilter.cpp +++ b/src/effects/SkXfermodeImageFilter.cpp @@ -174,6 +174,7 @@ bool SkXfermodeImageFilter::filterImageGPUDeprecated(Proxy* proxy, } GrPaint paint; + // SRGBTODO: AllowSRGBInputs? SkAutoTUnref bgFP; if (backgroundTex) { diff --git a/src/gpu/GrBlurUtils.cpp b/src/gpu/GrBlurUtils.cpp index 65b18a5edc..0dd518fdf7 100644 --- a/src/gpu/GrBlurUtils.cpp +++ b/src/gpu/GrBlurUtils.cpp @@ -335,7 +335,8 @@ void GrBlurUtils::drawPathWithMaskFilter(GrContext* context, } GrPaint grPaint; - if (!SkPaintToGrPaint(context, paint, viewMatrix, &grPaint)) { + if (!SkPaintToGrPaint(context, paint, viewMatrix, drawContext->allowSRGBInputs(), + &grPaint)) { return; } diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 1d6bb32142..c223a60213 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -366,6 +366,8 @@ bool GrContext::writeSurfacePixels(GrSurface* surface, if (!drawContext) { return false; } + // SRGBTODO: AllowSRGBInputs? (We could force it on here, so we don't need the + // per-texture override in config conversion effect?) GrPaint paint; paint.addColorFragmentProcessor(fp); paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); @@ -476,6 +478,8 @@ bool GrContext::readSurfacePixels(GrSurface* src, GrConfigConversionEffect::kNone_PMConversion, textureMatrix)); } if (fp) { + // SRGBTODO: AllowSRGBInputs? (We could force it on here, so we don't need the + // per-texture override in config conversion effect?) GrPaint paint; paint.addColorFragmentProcessor(fp); paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); diff --git a/src/gpu/GrLayerHoister.cpp b/src/gpu/GrLayerHoister.cpp index 80ea3cdc50..dd8a48547a 100644 --- a/src/gpu/GrLayerHoister.cpp +++ b/src/gpu/GrLayerHoister.cpp @@ -306,7 +306,8 @@ void GrLayerHoister::FilterLayer(GrContext* context, const SkIRect subset = SkIRect::MakeWH(layer->texture()->width(), layer->texture()->height()); sk_sp img(SkSpecialImage::MakeFromGpu(&proxy, subset, kNeedNewImageUniqueID_SpecialImage, - layer->texture())); + layer->texture(), + &device->surfaceProps())); SkIPoint offset = SkIPoint::Make(0, 0); sk_sp result(layer->filter()->filterImage(img.get(), diff --git a/src/gpu/GrPaint.cpp b/src/gpu/GrPaint.cpp index af93e8fa90..f41469e08e 100644 --- a/src/gpu/GrPaint.cpp +++ b/src/gpu/GrPaint.cpp @@ -15,6 +15,7 @@ GrPaint::GrPaint() : fAntiAlias(false) , fDisableOutputConversionToSRGB(false) + , fAllowSRGBInputs(false) , fColor(GrColor_WHITE) {} void GrPaint::setCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage) { diff --git a/src/gpu/GrPipeline.cpp b/src/gpu/GrPipeline.cpp index d8e2e5d98e..55cbf345a0 100644 --- a/src/gpu/GrPipeline.cpp +++ b/src/gpu/GrPipeline.cpp @@ -84,6 +84,9 @@ GrPipeline* GrPipeline::CreateAt(void* memory, const CreateArgs& args, if (builder.getDisableOutputConversionToSRGB()) { pipeline->fFlags |= kDisableOutputConversionToSRGB_Flag; } + if (builder.getAllowSRGBInputs()) { + pipeline->fFlags |= kAllowSRGBInputs_Flag; + } int firstColorProcessorIdx = args.fOpts.fColorPOI.firstEffectiveProcessorIndex(); diff --git a/src/gpu/GrPipeline.h b/src/gpu/GrPipeline.h index bdcc7d991b..f64b875f13 100644 --- a/src/gpu/GrPipeline.h +++ b/src/gpu/GrPipeline.h @@ -148,6 +148,9 @@ public: bool getDisableOutputConversionToSRGB() const { return SkToBool(fFlags & kDisableOutputConversionToSRGB_Flag); } + bool getAllowSRGBInputs() const { + return SkToBool(fFlags & kAllowSRGBInputs_Flag); + } GrXferBarrierType xferBarrierType(const GrCaps& caps) const { return this->getXferProcessor().xferBarrierType(fRenderTarget.get(), caps); @@ -190,6 +193,7 @@ private: kHWAA_Flag = 0x1, kSnapVertices_Flag = 0x2, kDisableOutputConversionToSRGB_Flag = 0x4, + kAllowSRGBInputs_Flag = 0x8, }; typedef GrPendingIOResource RenderTarget; diff --git a/src/gpu/GrPipelineBuilder.cpp b/src/gpu/GrPipelineBuilder.cpp index d82ee1c0c2..252c26577e 100644 --- a/src/gpu/GrPipelineBuilder.cpp +++ b/src/gpu/GrPipelineBuilder.cpp @@ -46,6 +46,8 @@ GrPipelineBuilder::GrPipelineBuilder(const GrPaint& paint, GrRenderTarget* rt, c rt->isUnifiedMultisampled() && paint.isAntiAlias()); this->setState(GrPipelineBuilder::kDisableOutputConversionToSRGB_Flag, paint.getDisableOutputConversionToSRGB()); + this->setState(GrPipelineBuilder::kAllowSRGBInputs_Flag, + paint.getAllowSRGBInputs()); } //////////////////////////////////////////////////////////////////////////////s diff --git a/src/gpu/GrPipelineBuilder.h b/src/gpu/GrPipelineBuilder.h index 4190070efb..08ac5db8b7 100644 --- a/src/gpu/GrPipelineBuilder.h +++ b/src/gpu/GrPipelineBuilder.h @@ -288,7 +288,12 @@ public: */ kDisableOutputConversionToSRGB_Flag = 0x04, - kLast_Flag = kDisableOutputConversionToSRGB_Flag, + /** + * Allow sRGB -> linear conversion when reading from sRGB inputs. + */ + kAllowSRGBInputs_Flag = 0x08, + + kLast_Flag = kAllowSRGBInputs_Flag, }; bool isHWAntialias() const { return SkToBool(fFlags & kHWAntialias_Flag); } @@ -296,6 +301,8 @@ public: return SkToBool(fFlags & kSnapVerticesToPixelCenters_Flag); } bool getDisableOutputConversionToSRGB() const { return SkToBool(fFlags & kDisableOutputConversionToSRGB_Flag); } + bool getAllowSRGBInputs() const { + return SkToBool(fFlags & kAllowSRGBInputs_Flag); } /** * Enable render state settings. diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index d0c526b170..d9727415b2 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -396,7 +396,8 @@ void SkGpuDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) { GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawPaint", fContext); GrPaint grPaint; - if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) { + if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, + this->surfaceProps().allowSRGBInputs(), &grPaint)) { return; } @@ -446,7 +447,8 @@ void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, if (paint.getPathEffect() && 2 == count && SkCanvas::kLines_PointMode == mode) { GrStrokeInfo strokeInfo(paint, SkPaint::kStroke_Style); GrPaint grPaint; - if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) { + if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, + this->surfaceProps().allowSRGBInputs(), &grPaint)) { return; } SkPath path; @@ -466,7 +468,8 @@ void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, } GrPaint grPaint; - if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) { + if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, + this->surfaceProps().allowSRGBInputs(), &grPaint)) { return; } @@ -518,7 +521,8 @@ void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect, const SkPaint } GrPaint grPaint; - if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) { + if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, + this->surfaceProps().allowSRGBInputs(), &grPaint)) { return; } @@ -536,7 +540,8 @@ void SkGpuDevice::drawRRect(const SkDraw& draw, const SkRRect& rect, CHECK_SHOULD_DRAW(draw); GrPaint grPaint; - if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) { + if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, + this->surfaceProps().allowSRGBInputs(), &grPaint)) { return; } @@ -611,7 +616,8 @@ void SkGpuDevice::drawDRRect(const SkDraw& draw, const SkRRect& outer, if (stroke.isFillStyle() && !paint.getMaskFilter() && !paint.getPathEffect()) { GrPaint grPaint; - if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) { + if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, + this->surfaceProps().allowSRGBInputs(), &grPaint)) { return; } @@ -655,7 +661,8 @@ void SkGpuDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPaint } GrPaint grPaint; - if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) { + if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, + this->surfaceProps().allowSRGBInputs(), &grPaint)) { return; } @@ -1139,7 +1146,8 @@ void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap, GrPaint grPaint; if (!SkPaintToGrPaintWithTexture(this->context(), paint, viewMatrix, fp, - kAlpha_8_SkColorType == bitmap.colorType(), &grPaint)) { + kAlpha_8_SkColorType == bitmap.colorType(), + this->surfaceProps().allowSRGBInputs(), &grPaint)) { return; } @@ -1233,7 +1241,8 @@ void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap, } else { fp.reset(GrFragmentProcessor::MulOutputByInputAlpha(fp)); } - if (!SkPaintToGrPaintReplaceShader(this->context(), paint, fp, &grPaint)) { + if (!SkPaintToGrPaintReplaceShader(this->context(), paint, fp, + this->surfaceProps().allowSRGBInputs(), &grPaint)) { return; } @@ -1393,7 +1402,8 @@ void SkGpuDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device, fp.reset(GrFragmentProcessor::MulOutputByInputAlpha(fp)); } - if (!SkPaintToGrPaintReplaceShader(this->context(), paint, fp, &grPaint)) { + if (!SkPaintToGrPaintReplaceShader(this->context(), paint, fp, + this->surfaceProps().allowSRGBInputs(), &grPaint)) { return; } @@ -1532,7 +1542,8 @@ void SkGpuDevice::drawProducerNine(const SkDraw& draw, GrTextureProducer* produc &kMode)); GrPaint grPaint; if (!SkPaintToGrPaintWithTexture(this->context(), paint, *draw.fMatrix, fp, - producer->isAlphaOnly(), &grPaint)) { + producer->isAlphaOnly(), + this->surfaceProps().allowSRGBInputs(), &grPaint)) { return; } @@ -1599,7 +1610,8 @@ void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode, GrPaint grPaint; // we ignore the shader if texs is null. - if (!SkPaintToGrPaintNoShader(this->context(), copy, &grPaint)) { + if (!SkPaintToGrPaintNoShader(this->context(), copy, + this->surfaceProps().allowSRGBInputs(), &grPaint)) { return; } @@ -1671,12 +1683,14 @@ void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode, colorMode = SkXfermode::kModulate_Mode; } if (!SkPaintToGrPaintWithXfermode(this->context(), paint, *draw.fMatrix, colorMode, - false, &grPaint)) { + false, this->surfaceProps().allowSRGBInputs(), + &grPaint)) { return; } } else { // We have a shader, but no colors to blend it against. - if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) { + if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, + this->surfaceProps().allowSRGBInputs(), &grPaint)) { return; } } @@ -1684,12 +1698,15 @@ void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode, if (colors) { // We have colors, but either have no shader or no texture coords (which implies that // we should ignore the shader). - if (!SkPaintToGrPaintWithPrimitiveColor(this->context(), paint, &grPaint)) { + if (!SkPaintToGrPaintWithPrimitiveColor(this->context(), paint, + this->surfaceProps().allowSRGBInputs(), + &grPaint)) { return; } } else { // No colors and no shaders. Just draw with the paint color. - if (!SkPaintToGrPaintNoShader(this->context(), paint, &grPaint)) { + if (!SkPaintToGrPaintNoShader(this->context(), paint, + this->surfaceProps().allowSRGBInputs(), &grPaint)) { return; } } @@ -1727,11 +1744,12 @@ void SkGpuDevice::drawAtlas(const SkDraw& draw, const SkImage* atlas, const SkRS GrPaint grPaint; if (colors) { if (!SkPaintToGrPaintWithXfermode(this->context(), p, *draw.fMatrix, mode, true, - &grPaint)) { + this->surfaceProps().allowSRGBInputs(), &grPaint)) { return; } } else { - if (!SkPaintToGrPaint(this->context(), p, *draw.fMatrix, &grPaint)) { + if (!SkPaintToGrPaint(this->context(), p, *draw.fMatrix, + this->surfaceProps().allowSRGBInputs(), &grPaint)) { return; } } @@ -1750,7 +1768,8 @@ void SkGpuDevice::drawText(const SkDraw& draw, const void* text, GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawText", fContext); GrPaint grPaint; - if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) { + if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, + this->surfaceProps().allowSRGBInputs(), &grPaint)) { return; } @@ -1768,7 +1787,8 @@ void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text, size_t byteL CHECK_SHOULD_DRAW(draw); GrPaint grPaint; - if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) { + if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, + this->surfaceProps().allowSRGBInputs(), &grPaint)) { return; } diff --git a/src/gpu/SkGpuDevice_drawTexture.cpp b/src/gpu/SkGpuDevice_drawTexture.cpp index 1be2dd59bc..8464895eab 100644 --- a/src/gpu/SkGpuDevice_drawTexture.cpp +++ b/src/gpu/SkGpuDevice_drawTexture.cpp @@ -206,7 +206,7 @@ void SkGpuDevice::drawTextureProducerImpl(GrTextureProducer* producer, GrPaint grPaint; if (!SkPaintToGrPaintWithTexture(fContext, paint, viewMatrix, fp, producer->isAlphaOnly(), - &grPaint)) { + this->surfaceProps().allowSRGBInputs(), &grPaint)) { return; } diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp index 905af81a79..716909133a 100644 --- a/src/gpu/SkGr.cpp +++ b/src/gpu/SkGr.cpp @@ -495,8 +495,10 @@ static inline bool skpaint_to_grpaint_impl(GrContext* context, const GrFragmentProcessor** shaderProcessor, SkXfermode::Mode* primColorMode, bool primitiveIsSrc, + bool allowSRGBInputs, GrPaint* grPaint) { grPaint->setAntiAlias(skPaint.isAntiAlias()); + grPaint->setAllowSRGBInputs(allowSRGBInputs); // Setup the initial color considering the shader, the SkPaint color, and the presence or not // of per-vertex colors. @@ -623,31 +625,34 @@ static inline bool skpaint_to_grpaint_impl(GrContext* context, } bool SkPaintToGrPaint(GrContext* context, const SkPaint& skPaint, const SkMatrix& viewM, - GrPaint* grPaint) { - return skpaint_to_grpaint_impl(context, skPaint, viewM, nullptr, nullptr, false, grPaint); + bool allowSRGBInputs, GrPaint* grPaint) { + return skpaint_to_grpaint_impl(context, skPaint, viewM, nullptr, nullptr, false, + allowSRGBInputs, grPaint); } /** Replaces the SkShader (if any) on skPaint with the passed in GrFragmentProcessor. */ bool SkPaintToGrPaintReplaceShader(GrContext* context, const SkPaint& skPaint, const GrFragmentProcessor* shaderFP, + bool allowSRGBInputs, GrPaint* grPaint) { if (!shaderFP) { return false; } return skpaint_to_grpaint_impl(context, skPaint, SkMatrix::I(), &shaderFP, nullptr, false, - grPaint); + allowSRGBInputs, grPaint); } /** Ignores the SkShader (if any) on skPaint. */ bool SkPaintToGrPaintNoShader(GrContext* context, const SkPaint& skPaint, + bool allowSRGBInputs, GrPaint* grPaint) { // Use a ptr to a nullptr to to indicate that the SkShader is ignored and not replaced. static const GrFragmentProcessor* kNullShaderFP = nullptr; static const GrFragmentProcessor** kIgnoreShader = &kNullShaderFP; return skpaint_to_grpaint_impl(context, skPaint, SkMatrix::I(), kIgnoreShader, nullptr, false, - grPaint); + allowSRGBInputs, grPaint); } /** Blends the SkPaint's shader (or color if no shader) with a per-primitive color which must @@ -657,9 +662,10 @@ bool SkPaintToGrPaintWithXfermode(GrContext* context, const SkMatrix& viewM, SkXfermode::Mode primColorMode, bool primitiveIsSrc, + bool allowSRGBInputs, GrPaint* grPaint) { return skpaint_to_grpaint_impl(context, skPaint, viewM, nullptr, &primColorMode, primitiveIsSrc, - grPaint); + allowSRGBInputs, grPaint); } bool SkPaintToGrPaintWithTexture(GrContext* context, @@ -667,6 +673,7 @@ bool SkPaintToGrPaintWithTexture(GrContext* context, const SkMatrix& viewM, const GrFragmentProcessor* fp, bool textureIsAlphaOnly, + bool allowSRGBInputs, GrPaint* grPaint) { SkAutoTUnref shaderFP; if (textureIsAlphaOnly) { @@ -687,7 +694,7 @@ bool SkPaintToGrPaintWithTexture(GrContext* context, shaderFP.reset(GrFragmentProcessor::MulOutputByInputAlpha(fp)); } - return SkPaintToGrPaintReplaceShader(context, paint, shaderFP.get(), grPaint); + return SkPaintToGrPaintReplaceShader(context, paint, shaderFP.get(), allowSRGBInputs, grPaint); } diff --git a/src/gpu/SkGrPriv.h b/src/gpu/SkGrPriv.h index f43a4e9595..46be3a53cf 100644 --- a/src/gpu/SkGrPriv.h +++ b/src/gpu/SkGrPriv.h @@ -48,11 +48,13 @@ void GrInstallBitmapUniqueKeyInvalidator(const GrUniqueKey& key, SkPixelRef* pix bool SkPaintToGrPaint(GrContext*, const SkPaint& skPaint, const SkMatrix& viewM, + bool allowSRGBInputs, GrPaint* grPaint); /** Same as above but ignores the SkShader (if any) on skPaint. */ bool SkPaintToGrPaintNoShader(GrContext* context, const SkPaint& skPaint, + bool allowSRGBInputs, GrPaint* grPaint); /** Replaces the SkShader (if any) on skPaint with the passed in GrFragmentProcessor. The processor @@ -61,6 +63,7 @@ bool SkPaintToGrPaintNoShader(GrContext* context, bool SkPaintToGrPaintReplaceShader(GrContext*, const SkPaint& skPaint, const GrFragmentProcessor* shaderFP, + bool allowSRGBInputs, GrPaint* grPaint); /** Blends the SkPaint's shader (or color if no shader) with the color which specified via a @@ -72,6 +75,7 @@ bool SkPaintToGrPaintWithXfermode(GrContext* context, const SkMatrix& viewM, SkXfermode::Mode primColorMode, bool primitiveIsSrc, + bool allowSRGBInputs, GrPaint* grPaint); /** This is used when there is a primitive color, but the shader should be ignored. Currently, @@ -79,9 +83,9 @@ bool SkPaintToGrPaintWithXfermode(GrContext* context, unpremultiplied so that interpolation is done in unpremul space. The paint's alpha will be applied to the primitive color after interpolation. */ inline bool SkPaintToGrPaintWithPrimitiveColor(GrContext* context, const SkPaint& skPaint, - GrPaint* grPaint) { + bool allowSRGBInputs, GrPaint* grPaint) { return SkPaintToGrPaintWithXfermode(context, skPaint, SkMatrix::I(), SkXfermode::kDst_Mode, - false, grPaint); + false, allowSRGBInputs, grPaint); } /** This is used when there may or may not be a shader, and the caller wants to plugin a texture @@ -91,6 +95,7 @@ bool SkPaintToGrPaintWithTexture(GrContext* context, const SkMatrix& viewM, const GrFragmentProcessor* fp, bool textureIsAlphaOnly, + bool allowSRGBInputs, GrPaint* grPaint); ////////////////////////////////////////////////////////////////////////////// diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index c8c12a388d..0063b3d16c 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -2051,15 +2051,13 @@ bool GrGLGpu::flushGLState(const GrPipeline& pipeline, const GrPrimitiveProcesso SkSTArray<8, const GrTextureAccess*> textureAccesses; program->setData(primProc, pipeline, &textureAccesses); - GrGLRenderTarget* glRT = static_cast(pipeline.getRenderTarget()); - bool allowSRGB = GrAllowSRGBForDestinationPixelConfig(glRT->config()); - int numTextureAccesses = textureAccesses.count(); for (int i = 0; i < numTextureAccesses; i++) { - this->bindTexture(i, textureAccesses[i]->getParams(), allowSRGB, + this->bindTexture(i, textureAccesses[i]->getParams(), pipeline.getAllowSRGBInputs(), static_cast(textureAccesses[i]->getTexture())); } + GrGLRenderTarget* glRT = static_cast(pipeline.getRenderTarget()); this->flushStencil(pipeline.getStencil()); this->flushScissor(pipeline.getScissorState(), glRT->getViewport(), glRT->origin()); this->flushHWAAState(glRT, pipeline.isHWAntialiasState(), !pipeline.getStencil().isDisabled()); diff --git a/src/gpu/text/GrAtlasTextContext.cpp b/src/gpu/text/GrAtlasTextContext.cpp index ec9e40cbae..918d6d29f7 100644 --- a/src/gpu/text/GrAtlasTextContext.cpp +++ b/src/gpu/text/GrAtlasTextContext.cpp @@ -112,7 +112,7 @@ void GrAtlasTextContext::drawTextBlob(GrContext* context, GrDrawContext* dc, // Though for the time being runs in the textblob can override the paint, they only touch font // info. GrPaint grPaint; - if (!SkPaintToGrPaint(context, skPaint, viewMatrix, &grPaint)) { + if (!SkPaintToGrPaint(context, skPaint, viewMatrix, props.allowSRGBInputs(), &grPaint)) { return; } @@ -382,7 +382,8 @@ DRAW_BATCH_TEST_DEFINE(TextBlobBatch) { skPaint.setSubpixelText(random->nextBool()); GrPaint grPaint; - if (!SkPaintToGrPaint(context, skPaint, viewMatrix, &grPaint)) { + if (!SkPaintToGrPaint(context, skPaint, viewMatrix, gSurfaceProps.allowSRGBInputs(), + &grPaint)) { SkFAIL("couldn't convert paint\n"); } diff --git a/src/gpu/text/GrStencilAndCoverTextContext.cpp b/src/gpu/text/GrStencilAndCoverTextContext.cpp index 4c2a615a66..151858b8b9 100644 --- a/src/gpu/text/GrStencilAndCoverTextContext.cpp +++ b/src/gpu/text/GrStencilAndCoverTextContext.cpp @@ -165,7 +165,7 @@ void GrStencilAndCoverTextContext::uncachedDrawTextBlob(GrContext* context, runPaint.setFlags(GrTextUtils::FilterTextFlags(props, runPaint)); GrPaint grPaint; - if (!SkPaintToGrPaint(context, runPaint, viewMatrix, &grPaint)) { + if (!SkPaintToGrPaint(context, runPaint, viewMatrix, dc->allowSRGBInputs(), &grPaint)) { return; } @@ -220,7 +220,7 @@ void GrStencilAndCoverTextContext::drawTextBlob(GrContext* context, GrDrawContex } GrPaint paint; - if (!SkPaintToGrPaint(context, skPaint, viewMatrix, &paint)) { + if (!SkPaintToGrPaint(context, skPaint, viewMatrix, dc->allowSRGBInputs(), &paint)) { return; } diff --git a/src/views/SkWindow.cpp b/src/views/SkWindow.cpp index 481a1f9eb2..bcc7b0298f 100644 --- a/src/views/SkWindow.cpp +++ b/src/views/SkWindow.cpp @@ -70,6 +70,13 @@ void SkWindow::resize(int width, int height) { void SkWindow::setColorType(SkColorType ct, SkColorProfileType pt) { const SkImageInfo& info = fBitmap.info(); this->resize(SkImageInfo::Make(info.width(), info.height(), ct, kPremul_SkAlphaType, pt)); + + // Set the global flag that enables or disables "legacy" mode, depending on our format. + // With sRGB 32-bit or linear FP 16, we turn on gamma-correct handling of inputs: + SkSurfaceProps props = this->getSurfaceProps(); + uint32_t flags = (props.flags() & ~SkSurfaceProps::kAllowSRGBInputs_Flag) | + (SkColorAndProfileAreGammaCorrect(ct, pt) ? SkSurfaceProps::kAllowSRGBInputs_Flag : 0); + this->setSurfaceProps(SkSurfaceProps(flags, props.pixelGeometry())); } bool SkWindow::handleInval(const SkRect* localR) { @@ -333,9 +340,7 @@ GrRenderTarget* SkWindow::renderTarget(const AttachmentInfo& attachmentInfo, // // Also, we may not have real sRGB support (ANGLE, in particular), so check for // that, and fall back to L32: - desc.fConfig = grContext->caps()->srgbSupport() && - (info().profileType() == kSRGB_SkColorProfileType || - info().colorType() == kRGBA_F16_SkColorType) + desc.fConfig = grContext->caps()->srgbSupport() && SkImageInfoIsGammaCorrect(info()) ? kSkiaGamma8888_GrPixelConfig : kSkia8888_GrPixelConfig; desc.fOrigin = kBottomLeft_GrSurfaceOrigin; diff --git a/tools/gpu/GrTest.cpp b/tools/gpu/GrTest.cpp index 818bf6462d..1fec1a694b 100644 --- a/tools/gpu/GrTest.cpp +++ b/tools/gpu/GrTest.cpp @@ -155,7 +155,8 @@ void SkGpuDevice::drawTexture(GrTexture* tex, const SkRect& dst, const SkPaint& GrPaint grPaint; SkMatrix mat; mat.reset(); - if (!SkPaintToGrPaint(this->context(), paint, mat, &grPaint)) { + if (!SkPaintToGrPaint(this->context(), paint, mat, + this->surfaceProps().allowSRGBInputs(), &grPaint)) { return; } SkMatrix textureMat; -- cgit v1.2.3