From 320573f8fc1eddded223eea5b4dbbb6ff0b545ab Mon Sep 17 00:00:00 2001 From: Brian Osman Date: Wed, 21 Dec 2016 13:36:02 -0500 Subject: Add color space xform fallback to GrMorphologyEffect 99% of the time (or maybe 100%?) morphology will trigger pad_image, so the input texture will already be in the destimation color space. If that doesn't happen, then just force the source to be converted, which keeps the morphology effect and driver code simple. BUG=skia: Change-Id: I98876af4f9e9a5da031973213ed76349752ce68f Reviewed-on: https://skia-review.googlesource.com/6388 Reviewed-by: Brian Salomon Commit-Queue: Brian Osman --- src/effects/SkMorphologyImageFilter.cpp | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) (limited to 'src/effects/SkMorphologyImageFilter.cpp') diff --git a/src/effects/SkMorphologyImageFilter.cpp b/src/effects/SkMorphologyImageFilter.cpp index 130f099d85..42986ce9de 100644 --- a/src/effects/SkMorphologyImageFilter.cpp +++ b/src/effects/SkMorphologyImageFilter.cpp @@ -13,6 +13,7 @@ #include "SkReadBuffer.h" #include "SkRect.h" #include "SkSpecialImage.h" +#include "SkSpecialSurface.h" #include "SkWriteBuffer.h" #if SK_SUPPORT_GPU @@ -492,6 +493,9 @@ static sk_sp apply_morphology( sk_sp colorSpace = sk_ref_sp(outputProperties.colorSpace()); GrPixelConfig config = GrRenderableConfigForColorSpace(colorSpace.get()); + // We force the inputs to this filter into the destination color space in the calling code. + SkASSERT(input->getColorSpace() == colorSpace.get()); + // setup new clip const GrFixedClip clip(SkIRect::MakeWH(srcTexture->width(), srcTexture->height())); @@ -507,7 +511,7 @@ static sk_sp apply_morphology( return nullptr; } - apply_morphology_pass(context->textureProvider(), + apply_morphology_pass(context->textureProvider(), dstRTContext.get(), clip, srcTexture.get(), srcRect, dstRect, radius.fWidth, morphType, Gr1DKernelEffect::kX_Direction); @@ -542,6 +546,23 @@ static sk_sp apply_morphology( std::move(srcTexture), std::move(colorSpace), &input->props()); } + +// Return a copy of 'src' transformed to the output's color space +static sk_sp image_to_color_space(SkSpecialImage* src, + const SkImageFilter::OutputProperties& outProps) { + sk_sp surf(src->makeSurface( + outProps, SkISize::Make(src->width(), src->height()))); + if (!surf) { + return sk_ref_sp(src); + } + + SkCanvas* canvas = surf->getCanvas(); + SkASSERT(canvas); + + src->draw(canvas, 0, 0, nullptr); + + return surf->makeImageSnapshot(); +} #endif sk_sp SkMorphologyImageFilter::onFilterImage(SkSpecialImage* source, @@ -582,6 +603,16 @@ sk_sp SkMorphologyImageFilter::onFilterImage(SkSpecialImage* sou if (source->isTextureBacked()) { GrContext* context = source->getContext(); + // If the input is not yet already in the destination color space, do an explicit up-front + // conversion. This is extremely unlikely (maybe even impossible). Typically, applyCropRect + // will have called pad_image to account for our dilation of bounds, so the result will + // already be moved to the destination color space. If someone makes a filter DAG that + // avoids that, then we use this fall-back, which saves us from having to do the xform + // during the filter itself. + if (input->getColorSpace() != ctx.outputProperties().colorSpace()) { + input = image_to_color_space(input.get(), ctx.outputProperties()); + } + auto type = (kDilate_Op == this->op()) ? GrMorphologyEffect::kDilate_MorphologyType : GrMorphologyEffect::kErode_MorphologyType; sk_sp result(apply_morphology(context, input.get(), srcBounds, type, -- cgit v1.2.3