From 2a6f73cb276ba502b0f52b507ea1daaaaec507d2 Mon Sep 17 00:00:00 2001 From: John Stiles Date: Thu, 29 Jul 2021 19:36:20 -0400 Subject: [PATCH] Create FP GrFragmentProcessor::UseDestColorAsInput. Returns a fragment processor which samples the passed-in fragment processor using `args.fDestColor` as its input color. Pass a null FP and it will return `args.fDestColor` directly. (This is only meaningful in contexts like blenders, which use a source and dest color.) This also fixes a bug in invokeChild which failed to forward along the dest color when one blend function invokes another blend function, and fixes an edge case where GrSkSLFP where it would fail to enable the blend-function mode when the dstFP is null. Change-Id: I46c8bffeb602d0c0b2b4dd1723a893582f3007ed Bug: skia:12257 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/434681 Reviewed-by: Brian Osman Commit-Queue: John Stiles --- src/gpu/GrFragmentProcessor.cpp | 14 ++++++++++++++ src/gpu/GrFragmentProcessor.h | 8 ++++++++ src/gpu/effects/GrSkSLFP.cpp | 6 ++++-- src/gpu/effects/GrSkSLFP.h | 6 ++++-- src/gpu/glsl/GrGLSLFragmentProcessor.cpp | 10 ++++++++-- 5 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/gpu/GrFragmentProcessor.cpp b/src/gpu/GrFragmentProcessor.cpp index 66447e74ba..8997daf2f8 100644 --- a/src/gpu/GrFragmentProcessor.cpp +++ b/src/gpu/GrFragmentProcessor.cpp @@ -441,6 +441,20 @@ std::unique_ptr GrFragmentProcessor::OverrideInput( ////////////////////////////////////////////////////////////////////////////// +std::unique_ptr GrFragmentProcessor::UseDestColorAsInput( + std::unique_ptr fp) { + static auto effect = SkMakeRuntimeEffect(SkRuntimeEffect::MakeForBlender, R"( + uniform colorFilter fp; // Declared as colorFilter so we can use sample(..., color) + half4 main(half4 src, half4 dst) { + return sample(fp, dst); + } + )"); + return GrSkSLFP::Make(effect, "UseDestColorAsInput", /*inputFP=*/nullptr, + GrSkSLFP::OptFlags::kNone, "fp", std::move(fp)); +} + +////////////////////////////////////////////////////////////////////////////// + std::unique_ptr GrFragmentProcessor::MakeInputOpaqueAndPostApplyAlpha( std::unique_ptr fp) { if (!fp) { diff --git a/src/gpu/GrFragmentProcessor.h b/src/gpu/GrFragmentProcessor.h index a86454a8cb..a14a603d3c 100644 --- a/src/gpu/GrFragmentProcessor.h +++ b/src/gpu/GrFragmentProcessor.h @@ -93,6 +93,14 @@ public: const SkPMColor4f&, bool useUniform = true); + /** + * Returns a fragment processor which samples the passed-in fragment processor using + * `args.fDestColor` as its input color. Pass a null FP to access `args.fDestColor` directly. + * (This is only meaningful in contexts like blenders, which use a source and dest color.) + */ + static std::unique_ptr UseDestColorAsInput( + std::unique_ptr); + /** * Returns a parent fragment processor that adopts the passed fragment processor as a child. * The parent will unpremul its input color, make it opaque, and pass that as the input to diff --git a/src/gpu/effects/GrSkSLFP.cpp b/src/gpu/effects/GrSkSLFP.cpp index 44a6aa932c..49bc7a4b82 100644 --- a/src/gpu/effects/GrSkSLFP.cpp +++ b/src/gpu/effects/GrSkSLFP.cpp @@ -270,17 +270,19 @@ std::unique_ptr GrSkSLFP::MakeWithData( size_t uniformSize = uniforms->size(); size_t uniformFlagSize = effect->uniforms().count() * sizeof(UniformFlags); std::unique_ptr fp(new (uniformSize + uniformFlagSize) - GrSkSLFP(std::move(effect), name, OptFlags::kNone)); + GrSkSLFP(effect, name, OptFlags::kNone)); sk_careful_memcpy(fp->uniformData(), uniforms->data(), uniformSize); for (auto& childFP : childFPs) { fp->addChild(std::move(childFP), /*mergeOptFlags=*/true); } + if (effect->allowBlender()) { + fp->setIsBlendFunction(); + } if (inputFP) { fp->setInput(std::move(inputFP)); } if (destColorFP) { fp->setDestColorFP(std::move(destColorFP)); - fp->setIsBlendFunction(); } return fp; } diff --git a/src/gpu/effects/GrSkSLFP.h b/src/gpu/effects/GrSkSLFP.h index b7affa6ebe..67c262ae7f 100644 --- a/src/gpu/effects/GrSkSLFP.h +++ b/src/gpu/effects/GrSkSLFP.h @@ -147,9 +147,11 @@ public: #endif size_t uniformPayloadSize = UniformPayloadSize(effect.get()); - std::unique_ptr fp(new (uniformPayloadSize) - GrSkSLFP(std::move(effect), name, optFlags)); + std::unique_ptr fp(new (uniformPayloadSize) GrSkSLFP(effect, name, optFlags)); fp->appendArgs(fp->uniformData(), fp->uniformFlags(), std::forward(args)...); + if (effect->allowBlender()) { + fp->setIsBlendFunction(); + } if (inputFP) { fp->setInput(std::move(inputFP)); } diff --git a/src/gpu/glsl/GrGLSLFragmentProcessor.cpp b/src/gpu/glsl/GrGLSLFragmentProcessor.cpp index 44b61a2865..1de6760cdf 100644 --- a/src/gpu/glsl/GrGLSLFragmentProcessor.cpp +++ b/src/gpu/glsl/GrGLSLFragmentProcessor.cpp @@ -57,7 +57,10 @@ SkString GrGLSLFragmentProcessor::invokeChild(int childIndex, inputColor); if (childProc->isBlendFunction()) { - invocation.appendf(", %s", destColor ? destColor : "half4(1)"); + if (!destColor) { + destColor = args.fFp.isBlendFunction() ? args.fDestColor : "half4(1)"; + } + invocation.appendf(", %s", destColor); } if (childProc->isSampledWithExplicitCoords()) { @@ -100,7 +103,10 @@ SkString GrGLSLFragmentProcessor::invokeChildWithMatrix(int childIndex, const ch inputColor); if (childProc->isBlendFunction()) { - invocation.appendf(", %s", destColor ? destColor : "half4(1)"); + if (!destColor) { + destColor = args.fFp.isBlendFunction() ? args.fDestColor : "half4(1)"; + } + invocation.appendf(", %s", destColor); } // Produce a string containing the call to the helper function. We have a uniform variable