Add GrRuntimeFPBuilder
Like SkRuntimeShaderBuilder but for internal use for creating FPs.
Currently it requires that the code be a static string so it can
easily make a static SkRuntimeEffect instance for each effect.
Bug: skia:11771
Change-Id: I18148eb33e7d28c804e4a13bcef88c89c06b2c9b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/386889
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/gn/gpu.gni b/gn/gpu.gni
index 409d7eb..a8a0560 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -342,8 +342,6 @@
"$_src/gpu/effects/generated/GrClampFragmentProcessor.h",
"$_src/gpu/effects/generated/GrColorMatrixFragmentProcessor.cpp",
"$_src/gpu/effects/generated/GrColorMatrixFragmentProcessor.h",
- "$_src/gpu/effects/generated/GrComposeLerpEffect.cpp",
- "$_src/gpu/effects/generated/GrComposeLerpEffect.h",
"$_src/gpu/effects/generated/GrConfigConversionEffect.cpp",
"$_src/gpu/effects/generated/GrConfigConversionEffect.h",
"$_src/gpu/effects/generated/GrConstColorProcessor.cpp",
diff --git a/gn/sksl.gni b/gn/sksl.gni
index 58d7f68..2c5bc51 100644
--- a/gn/sksl.gni
+++ b/gn/sksl.gni
@@ -187,7 +187,6 @@
"$_src/gpu/effects/GrCircleEffect.fp",
"$_src/gpu/effects/GrClampFragmentProcessor.fp",
"$_src/gpu/effects/GrColorMatrixFragmentProcessor.fp",
- "$_src/gpu/effects/GrComposeLerpEffect.fp",
"$_src/gpu/effects/GrConfigConversionEffect.fp",
"$_src/gpu/effects/GrConstColorProcessor.fp",
"$_src/gpu/effects/GrDeviceSpaceEffect.fp",
diff --git a/include/effects/SkRuntimeEffect.h b/include/effects/SkRuntimeEffect.h
index 819a794..4248a13 100644
--- a/include/effects/SkRuntimeEffect.h
+++ b/include/effects/SkRuntimeEffect.h
@@ -17,6 +17,7 @@
#include <vector>
+class GrFragmentProcessor;
class GrRecordingContext;
class SkColorFilter;
class SkImage;
@@ -96,7 +97,7 @@
sk_sp<SkShader> children[],
size_t childCount,
const SkMatrix* localMatrix,
- bool isOpaque);
+ bool isOpaque) const;
sk_sp<SkImage> makeImage(GrRecordingContext*,
sk_sp<SkData> uniforms,
@@ -104,12 +105,12 @@
size_t childCount,
const SkMatrix* localMatrix,
SkImageInfo resultInfo,
- bool mipmapped);
+ bool mipmapped) const;
- sk_sp<SkColorFilter> makeColorFilter(sk_sp<SkData> uniforms);
+ sk_sp<SkColorFilter> makeColorFilter(sk_sp<SkData> uniforms) const;
sk_sp<SkColorFilter> makeColorFilter(sk_sp<SkData> uniforms,
sk_sp<SkColorFilter> children[],
- size_t childCount);
+ size_t childCount) const;
const SkString& source() const { return fSkSL; }
@@ -145,6 +146,14 @@
static void RegisterFlattenables();
~SkRuntimeEffect() override;
+#if SK_SUPPORT_GPU
+ // For internal use.
+ std::unique_ptr<GrFragmentProcessor> makeFP(GrRecordingContext*,
+ sk_sp<SkData> uniforms,
+ std::unique_ptr<GrFragmentProcessor> children[],
+ size_t childCount) const;
+#endif
+
private:
SkRuntimeEffect(SkString sksl,
std::unique_ptr<SkSL::Program> baseProgram,
@@ -184,31 +193,9 @@
bool fAllowColorFilter;
};
-/**
- * SkRuntimeShaderBuilder is a utility to simplify creating SkShader objects from SkRuntimeEffects.
- *
- * NOTE: Like SkRuntimeEffect, this API is experimental and subject to change!
- *
- * Given an SkRuntimeEffect, the SkRuntimeShaderBuilder manages creating an input data block and
- * provides named access to the 'uniform' variables in that block, as well as named access
- * to a list of child shader slots. Usage:
- *
- * sk_sp<SkRuntimeEffect> effect = ...;
- * SkRuntimeShaderBuilder builder(effect);
- * builder.uniform("some_uniform_float") = 3.14f;
- * builder.uniform("some_uniform_matrix") = SkM44::Rotate(...);
- * builder.child("some_child_effect") = mySkImage->makeShader(...);
- * ...
- * sk_sp<SkShader> shader = builder.makeShader(nullptr, false);
- *
- * Note that SkRuntimeShaderBuilder is built entirely on the public API of SkRuntimeEffect,
- * so can be used as-is or serve as inspiration for other interfaces or binding techniques.
- */
-class SkRuntimeShaderBuilder {
+/** Base class for SkRuntimeShaderBuilder, defined below. */
+template <typename Child> class SkRuntimeEffectBuilder {
public:
- SkRuntimeShaderBuilder(sk_sp<SkRuntimeEffect>);
- ~SkRuntimeShaderBuilder();
-
struct BuilderUniform {
// Copy 'val' to this variable. No type conversion is performed - 'val' must be same
// size as expected by the effect. Information about the variable can be queried by
@@ -259,14 +246,21 @@
return true;
}
- SkRuntimeShaderBuilder* fOwner;
+ SkRuntimeEffectBuilder* fOwner;
const SkRuntimeEffect::Uniform* fVar; // nullptr if the variable was not found
};
struct BuilderChild {
- BuilderChild& operator=(const sk_sp<SkShader>& val);
+ template <typename C> BuilderChild& operator=(C&& val) {
+ if (fIndex < 0) {
+ SkDEBUGFAIL("Assigning to missing child");
+ } else {
+ fOwner->fChildren[fIndex] = std::forward<C>(val);
+ }
+ return *this;
+ }
- SkRuntimeShaderBuilder* fOwner;
+ SkRuntimeEffectBuilder* fOwner;
int fIndex; // -1 if the child was not found
};
@@ -275,6 +269,60 @@
BuilderUniform uniform(const char* name) { return { this, fEffect->findUniform(name) }; }
BuilderChild child(const char* name) { return { this, fEffect->findChild(name) }; }
+protected:
+ explicit SkRuntimeEffectBuilder(sk_sp<SkRuntimeEffect> effect)
+ : fEffect(std::move(effect))
+ , fUniforms(SkData::MakeUninitialized(fEffect->uniformSize()))
+ , fChildren(fEffect->children().count()) {}
+
+ SkRuntimeEffectBuilder(SkRuntimeEffectBuilder&&) = default;
+ SkRuntimeEffectBuilder(const SkRuntimeEffectBuilder&) = delete;
+
+ SkRuntimeEffectBuilder& operator=(SkRuntimeEffectBuilder&&) = default;
+ SkRuntimeEffectBuilder& operator=(const SkRuntimeEffectBuilder&) = delete;
+
+ sk_sp<SkData> uniforms() { return fUniforms; }
+ Child* children() { return fChildren.data(); }
+ size_t numChildren() { return fChildren.size(); }
+
+private:
+ void* writableUniformData() {
+ if (!fUniforms->unique()) {
+ fUniforms = SkData::MakeWithCopy(fUniforms->data(), fUniforms->size());
+ }
+ return fUniforms->writable_data();
+ }
+
+ sk_sp<SkRuntimeEffect> fEffect;
+ sk_sp<SkData> fUniforms;
+ std::vector<Child> fChildren;
+};
+
+/**
+ * SkRuntimeShaderBuilder is a utility to simplify creating SkShader objects from SkRuntimeEffects.
+ *
+ * NOTE: Like SkRuntimeEffect, this API is experimental and subject to change!
+ *
+ * Given an SkRuntimeEffect, the SkRuntimeShaderBuilder manages creating an input data block and
+ * provides named access to the 'uniform' variables in that block, as well as named access
+ * to a list of child shader slots. Usage:
+ *
+ * sk_sp<SkRuntimeEffect> effect = ...;
+ * SkRuntimeShaderBuilder builder(effect);
+ * builder.uniform("some_uniform_float") = 3.14f;
+ * builder.uniform("some_uniform_matrix") = SkM44::Rotate(...);
+ * builder.child("some_child_effect") = mySkImage->makeShader(...);
+ * ...
+ * sk_sp<SkShader> shader = builder.makeShader(nullptr, false);
+ *
+ * Note that SkRuntimeShaderBuilder is built entirely on the public API of SkRuntimeEffect,
+ * so can be used as-is or serve as inspiration for other interfaces or binding techniques.
+ */
+class SK_API SkRuntimeShaderBuilder : public SkRuntimeEffectBuilder<sk_sp<SkShader>> {
+public:
+ explicit SkRuntimeShaderBuilder(sk_sp<SkRuntimeEffect>);
+ ~SkRuntimeShaderBuilder();
+
sk_sp<SkShader> makeShader(const SkMatrix* localMatrix, bool isOpaque);
sk_sp<SkImage> makeImage(GrRecordingContext*,
const SkMatrix* localMatrix,
@@ -282,11 +330,7 @@
bool mipmapped);
private:
- void* writableUniformData();
-
- sk_sp<SkRuntimeEffect> fEffect;
- sk_sp<SkData> fUniforms;
- std::vector<sk_sp<SkShader>> fChildren;
+ using INHERITED = SkRuntimeEffectBuilder<sk_sp<SkShader>>;
};
#endif
diff --git a/src/core/SkRuntimeEffect.cpp b/src/core/SkRuntimeEffect.cpp
index 6b9362d..0d2e302 100644
--- a/src/core/SkRuntimeEffect.cpp
+++ b/src/core/SkRuntimeEffect.cpp
@@ -799,9 +799,28 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
+#if SK_SUPPORT_GPU
+std::unique_ptr<GrFragmentProcessor> SkRuntimeEffect::makeFP(
+ GrRecordingContext* recordingContext,
+ sk_sp<SkData> uniforms,
+ std::unique_ptr<GrFragmentProcessor> children[],
+ size_t childCount) const {
+ if (!uniforms) {
+ uniforms = SkData::MakeEmpty();
+ }
+ auto fp = GrSkSLFP::Make(recordingContext, sk_ref_sp(this), "make_fp", std::move(uniforms));
+ for (size_t i = 0; i < childCount; ++i) {
+ fp->addChild(std::move(children[i]));
+ }
+ return std::move(fp);
+}
+#endif
+
sk_sp<SkShader> SkRuntimeEffect::makeShader(sk_sp<SkData> uniforms,
- sk_sp<SkShader> children[], size_t childCount,
- const SkMatrix* localMatrix, bool isOpaque) {
+ sk_sp<SkShader> children[],
+ size_t childCount,
+ const SkMatrix* localMatrix,
+ bool isOpaque) const {
if (!uniforms) {
uniforms = SkData::MakeEmpty();
}
@@ -817,7 +836,7 @@
size_t childCount,
const SkMatrix* localMatrix,
SkImageInfo resultInfo,
- bool mipmapped) {
+ bool mipmapped) const {
if (recordingContext) {
#if SK_SUPPORT_GPU
if (!recordingContext->priv().caps()->mipmapSupport()) {
@@ -897,7 +916,7 @@
sk_sp<SkColorFilter> SkRuntimeEffect::makeColorFilter(sk_sp<SkData> uniforms,
sk_sp<SkColorFilter> children[],
- size_t childCount) {
+ size_t childCount) const {
if (!fAllowColorFilter) {
return nullptr;
}
@@ -910,7 +929,7 @@
: nullptr;
}
-sk_sp<SkColorFilter> SkRuntimeEffect::makeColorFilter(sk_sp<SkData> uniforms) {
+sk_sp<SkColorFilter> SkRuntimeEffect::makeColorFilter(sk_sp<SkData> uniforms) const {
return this->makeColorFilter(std::move(uniforms), nullptr, 0);
}
@@ -922,42 +941,27 @@
}
SkRuntimeShaderBuilder::SkRuntimeShaderBuilder(sk_sp<SkRuntimeEffect> effect)
- : fEffect(std::move(effect))
- , fUniforms(SkData::MakeUninitialized(fEffect->uniformSize()))
- , fChildren(fEffect->children().count()) {}
+ : INHERITED(std::move(effect)) {}
SkRuntimeShaderBuilder::~SkRuntimeShaderBuilder() = default;
-void* SkRuntimeShaderBuilder::writableUniformData() {
- if (!fUniforms->unique()) {
- fUniforms = SkData::MakeWithCopy(fUniforms->data(), fUniforms->size());
- }
- return fUniforms->writable_data();
-}
-
-sk_sp<SkShader> SkRuntimeShaderBuilder::makeShader(const SkMatrix* localMatrix, bool isOpaque) {
- return fEffect->makeShader(fUniforms, fChildren.data(), fChildren.size(), localMatrix, isOpaque);
-}
-
sk_sp<SkImage> SkRuntimeShaderBuilder::makeImage(GrRecordingContext* recordingContext,
const SkMatrix* localMatrix,
SkImageInfo resultInfo,
bool mipmapped) {
- return fEffect->makeImage(recordingContext,
- fUniforms,
- fChildren.data(),
- fChildren.size(),
- localMatrix,
- resultInfo,
- mipmapped);
+ return this->effect()->makeImage(recordingContext,
+ this->uniforms(),
+ this->children(),
+ this->numChildren(),
+ localMatrix,
+ resultInfo,
+ mipmapped);
}
-SkRuntimeShaderBuilder::BuilderChild&
-SkRuntimeShaderBuilder::BuilderChild::operator=(const sk_sp<SkShader>& val) {
- if (fIndex < 0) {
- SkDEBUGFAIL("Assigning to missing child");
- } else {
- fOwner->fChildren[fIndex] = val;
- }
- return *this;
+sk_sp<SkShader> SkRuntimeShaderBuilder::makeShader(const SkMatrix* localMatrix, bool isOpaque) {
+ return this->effect()->makeShader(this->uniforms(),
+ this->children(),
+ this->numChildren(),
+ localMatrix,
+ isOpaque);
}
diff --git a/src/gpu/GrProcessor.h b/src/gpu/GrProcessor.h
index 507646c..e14278b 100644
--- a/src/gpu/GrProcessor.h
+++ b/src/gpu/GrProcessor.h
@@ -67,7 +67,6 @@
kGrClampFragmentProcessor_ClassID,
kGrColorMatrixFragmentProcessor_ClassID,
kGrColorSpaceXformEffect_ClassID,
- kGrComposeLerpEffect_ClassID,
kGrConfigConversionEffect_ClassID,
kGrConicEffect_ClassID,
kGrConstColorProcessor_ClassID,
diff --git a/src/gpu/effects/GrComposeLerpEffect.fp b/src/gpu/effects/GrComposeLerpEffect.fp
deleted file mode 100644
index 7449541..0000000
--- a/src/gpu/effects/GrComposeLerpEffect.fp
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright 2019 Google LLC.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-in fragmentProcessor child1;
-in fragmentProcessor child2;
-in uniform float weight;
-
-half4 main() {
- return mix(sample(child1), sample(child2), half(weight));
-}
diff --git a/src/gpu/effects/GrSkSLFP.cpp b/src/gpu/effects/GrSkSLFP.cpp
index 9d4e472..f984cdb 100644
--- a/src/gpu/effects/GrSkSLFP.cpp
+++ b/src/gpu/effects/GrSkSLFP.cpp
@@ -254,3 +254,18 @@
}
#endif
+
+/**************************************************************************************************/
+
+GrRuntimeFPBuilder::GrRuntimeFPBuilder(sk_sp<SkRuntimeEffect> effect)
+ : INHERITED(std::move(effect)) {}
+
+GrRuntimeFPBuilder::~GrRuntimeFPBuilder() = default;
+
+std::unique_ptr<GrFragmentProcessor> GrRuntimeFPBuilder::makeFP(
+ GrRecordingContext* recordingContext) {
+ return this->effect()->makeFP(recordingContext,
+ this->uniforms(),
+ this->children(),
+ this->numChildren());
+}
diff --git a/src/gpu/effects/GrSkSLFP.h b/src/gpu/effects/GrSkSLFP.h
index 5b4dd54..7566898 100644
--- a/src/gpu/effects/GrSkSLFP.h
+++ b/src/gpu/effects/GrSkSLFP.h
@@ -9,6 +9,7 @@
#define GrSkSLFP_DEFINED
#include "include/core/SkRefCnt.h"
+#include "include/effects/SkRuntimeEffect.h"
#include "include/gpu/GrContextOptions.h"
#include "src/gpu/GrFragmentProcessor.h"
#include <atomic>
@@ -65,4 +66,27 @@
friend class GrSkSLFPFactory;
};
+class GrRuntimeFPBuilder : public SkRuntimeEffectBuilder<std::unique_ptr<GrFragmentProcessor>> {
+public:
+ ~GrRuntimeFPBuilder();
+
+ template <const char* CODE> static GrRuntimeFPBuilder Make() {
+ static const SkRuntimeEffect::Result gResult = SkRuntimeEffect::Make(SkString(CODE));
+#ifdef SK_DEBUG
+ if (!gResult.effect) {
+ SK_ABORT("Code failed: %s", gResult.errorText.c_str());
+ }
+#endif
+ return GrRuntimeFPBuilder(gResult.effect);
+ }
+
+ std::unique_ptr<GrFragmentProcessor> makeFP(GrRecordingContext*);
+
+private:
+ explicit GrRuntimeFPBuilder(sk_sp<SkRuntimeEffect>);
+ GrRuntimeFPBuilder(GrRuntimeFPBuilder&& that) = default;
+
+ using INHERITED = SkRuntimeEffectBuilder<std::unique_ptr<GrFragmentProcessor>>;
+};
+
#endif
diff --git a/src/gpu/effects/generated/GrComposeLerpEffect.cpp b/src/gpu/effects/generated/GrComposeLerpEffect.cpp
deleted file mode 100644
index 155cc78..0000000
--- a/src/gpu/effects/generated/GrComposeLerpEffect.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2019 Google LLC.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/**************************************************************************************************
- *** This file was autogenerated from GrComposeLerpEffect.fp; do not modify.
- **************************************************************************************************/
-#include "GrComposeLerpEffect.h"
-
-#include "src/core/SkUtils.h"
-#include "src/gpu/GrTexture.h"
-#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
-#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
-#include "src/gpu/glsl/GrGLSLProgramBuilder.h"
-#include "src/sksl/SkSLCPP.h"
-#include "src/sksl/SkSLUtil.h"
-class GrGLSLComposeLerpEffect : public GrGLSLFragmentProcessor {
-public:
- GrGLSLComposeLerpEffect() {}
- void emitCode(EmitArgs& args) override {
- GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
- const GrComposeLerpEffect& _outer = args.fFp.cast<GrComposeLerpEffect>();
- (void)_outer;
- auto weight = _outer.weight;
- (void)weight;
- weightVar = args.fUniformHandler->addUniform(
- &_outer, kFragment_GrShaderFlag, kFloat_GrSLType, "weight");
- SkString _sample0 = this->invokeChild(0, args);
- SkString _sample1 = this->invokeChild(1, args);
- fragBuilder->codeAppendf(
- R"SkSL(return mix(%s, %s, half(%s));
-)SkSL",
- _sample0.c_str(),
- _sample1.c_str(),
- args.fUniformHandler->getUniformCStr(weightVar));
- }
-
-private:
- void onSetData(const GrGLSLProgramDataManager& pdman,
- const GrFragmentProcessor& _proc) override {
- const GrComposeLerpEffect& _outer = _proc.cast<GrComposeLerpEffect>();
- { pdman.set1f(weightVar, (_outer.weight)); }
- }
- UniformHandle weightVar;
-};
-std::unique_ptr<GrGLSLFragmentProcessor> GrComposeLerpEffect::onMakeProgramImpl() const {
- return std::make_unique<GrGLSLComposeLerpEffect>();
-}
-void GrComposeLerpEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
- GrProcessorKeyBuilder* b) const {}
-bool GrComposeLerpEffect::onIsEqual(const GrFragmentProcessor& other) const {
- const GrComposeLerpEffect& that = other.cast<GrComposeLerpEffect>();
- (void)that;
- if (weight != that.weight) return false;
- return true;
-}
-GrComposeLerpEffect::GrComposeLerpEffect(const GrComposeLerpEffect& src)
- : INHERITED(kGrComposeLerpEffect_ClassID, src.optimizationFlags()), weight(src.weight) {
- this->cloneAndRegisterAllChildProcessors(src);
-}
-std::unique_ptr<GrFragmentProcessor> GrComposeLerpEffect::clone() const {
- return std::make_unique<GrComposeLerpEffect>(*this);
-}
-#if GR_TEST_UTILS
-SkString GrComposeLerpEffect::onDumpInfo() const { return SkStringPrintf("(weight=%f)", weight); }
-#endif
diff --git a/src/gpu/effects/generated/GrComposeLerpEffect.h b/src/gpu/effects/generated/GrComposeLerpEffect.h
deleted file mode 100644
index 5e44e1a..0000000
--- a/src/gpu/effects/generated/GrComposeLerpEffect.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2019 Google LLC.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/**************************************************************************************************
- *** This file was autogenerated from GrComposeLerpEffect.fp; do not modify.
- **************************************************************************************************/
-#ifndef GrComposeLerpEffect_DEFINED
-#define GrComposeLerpEffect_DEFINED
-
-#include "include/core/SkM44.h"
-#include "include/core/SkTypes.h"
-
-#include "src/gpu/GrFragmentProcessor.h"
-
-class GrComposeLerpEffect : public GrFragmentProcessor {
-public:
- static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> child1,
- std::unique_ptr<GrFragmentProcessor> child2,
- float weight) {
- return std::unique_ptr<GrFragmentProcessor>(
- new GrComposeLerpEffect(std::move(child1), std::move(child2), weight));
- }
- GrComposeLerpEffect(const GrComposeLerpEffect& src);
- std::unique_ptr<GrFragmentProcessor> clone() const override;
- const char* name() const override { return "ComposeLerpEffect"; }
- float weight;
-
-private:
- GrComposeLerpEffect(std::unique_ptr<GrFragmentProcessor> child1,
- std::unique_ptr<GrFragmentProcessor> child2,
- float weight)
- : INHERITED(kGrComposeLerpEffect_ClassID, kNone_OptimizationFlags), weight(weight) {
- this->registerChild(std::move(child1), SkSL::SampleUsage::PassThrough());
- this->registerChild(std::move(child2), SkSL::SampleUsage::PassThrough());
- }
- std::unique_ptr<GrGLSLFragmentProcessor> onMakeProgramImpl() const override;
- void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
- bool onIsEqual(const GrFragmentProcessor&) const override;
-#if GR_TEST_UTILS
- SkString onDumpInfo() const override;
-#endif
- GR_DECLARE_FRAGMENT_PROCESSOR_TEST
- using INHERITED = GrFragmentProcessor;
-};
-#endif
diff --git a/src/shaders/SkComposeShader.cpp b/src/shaders/SkComposeShader.cpp
index 19d7334..0bc012d 100644
--- a/src/shaders/SkComposeShader.cpp
+++ b/src/shaders/SkComposeShader.cpp
@@ -201,7 +201,7 @@
#include "include/gpu/GrRecordingContext.h"
#include "src/gpu/effects/GrBlendFragmentProcessor.h"
-#include "src/gpu/effects/generated/GrComposeLerpEffect.h"
+#include "src/gpu/effects/GrSkSLFP.h"
#include "src/gpu/effects/generated/GrConstColorProcessor.h"
static std::unique_ptr<GrFragmentProcessor> as_fp(const GrFPArgs& args, SkShader* shader) {
@@ -221,6 +221,19 @@
const GrFPArgs::WithPreLocalMatrix args(orig_args, this->getLocalMatrix());
auto fpA = as_fp(args, fDst.get());
auto fpB = as_fp(args, fSrc.get());
- return GrComposeLerpEffect::Make(std::move(fpA), std::move(fpB), fWeight);
+
+ static constexpr char kCode[] = R"(
+ uniform shader a;
+ uniform shader b;
+ uniform half w;
+
+ half4 main() { return mix(sample(a), sample(b), w); }
+ )";
+
+ auto builder = GrRuntimeFPBuilder::Make<kCode>();
+ builder.uniform("w") = fWeight;
+ builder.child("a") = std::move(fpA);
+ builder.child("b") = std::move(fpB);
+ return builder.makeFP(args.fContext);
}
#endif