Reland "Move runtime shader/colorfilter into SkRuntimeEffect.cpp"
This reverts commit 7281a8623799021d47ebcdb5d0efa6d200cca1cd.
Change-Id: I1759358ede39e2466362cc4d3f0b9530eff08c9e
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/271656
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/gn/core.gni b/gn/core.gni
index dff7111..7d59209 100644
--- a/gn/core.gni
+++ b/gn/core.gni
@@ -445,7 +445,6 @@
"$_src/shaders/SkLights.h",
"$_src/shaders/SkLocalMatrixShader.cpp",
"$_src/shaders/SkLocalMatrixShader.h",
- "$_src/shaders/SkRTShader.cpp",
"$_src/shaders/SkShader.cpp",
"$_src/shaders/SkShaderBase.h",
diff --git a/include/effects/SkRuntimeEffect.h b/include/effects/SkRuntimeEffect.h
index 921b42e..0840422 100644
--- a/include/effects/SkRuntimeEffect.h
+++ b/include/effects/SkRuntimeEffect.h
@@ -127,6 +127,10 @@
ByteCodeResult toByteCode(const void* inputs);
+ static void RegisterFlattenables();
+
+ ~SkRuntimeEffect();
+
private:
SkRuntimeEffect(SkString sksl, std::unique_ptr<SkSL::Compiler> compiler,
std::unique_ptr<SkSL::Program> baseProgram,
diff --git a/src/core/SkColorFilter.cpp b/src/core/SkColorFilter.cpp
index 38cd478..9a86a2f 100644
--- a/src/core/SkColorFilter.cpp
+++ b/src/core/SkColorFilter.cpp
@@ -9,7 +9,6 @@
#include "include/core/SkRefCnt.h"
#include "include/core/SkString.h"
#include "include/core/SkUnPreMultiply.h"
-#include "include/effects/SkRuntimeEffect.h"
#include "include/private/SkNx.h"
#include "include/private/SkTDArray.h"
#include "src/core/SkArenaAlloc.h"
@@ -19,7 +18,6 @@
#include "src/core/SkReadBuffer.h"
#include "src/core/SkVM.h"
#include "src/core/SkWriteBuffer.h"
-#include "src/sksl/SkSLInterpreter.h"
#if SK_SUPPORT_GPU
#include "src/gpu/GrFragmentProcessor.h"
@@ -391,129 +389,6 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
-#include "include/private/SkMutex.h"
-#include "src/sksl/SkSLByteCode.h"
-
-#if SK_SUPPORT_GPU
-#include "include/private/GrRecordingContext.h"
-#include "src/gpu/effects/GrSkSLFP.h"
-#endif
-
-class SkRuntimeColorFilter : public SkColorFilter {
-public:
- SkRuntimeColorFilter(sk_sp<SkRuntimeEffect> effect, sk_sp<SkData> inputs,
- sk_sp<SkColorFilter> children[], size_t childCount)
- : fEffect(std::move(effect))
- , fInputs(std::move(inputs))
- , fChildren(children, children + childCount) {}
-
-#if SK_SUPPORT_GPU
- std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(
- GrRecordingContext* context, const GrColorInfo& colorInfo) const override {
- auto fp = GrSkSLFP::Make(context, fEffect, "Runtime Color Filter", fInputs);
- for (const auto& child : fChildren) {
- auto childFP = child ? child->asFragmentProcessor(context, colorInfo) : nullptr;
- if (!childFP) {
- // TODO: This is the case that should eventually mean "the original input color"
- return nullptr;
- }
- fp->addChild(std::move(childFP));
- }
- return std::move(fp);
- }
-#endif
-
- bool onAppendStages(const SkStageRec& rec, bool shaderIsOpaque) const override {
- auto ctx = rec.fAlloc->make<SkRasterPipeline_InterpreterCtx>();
- // don't need to set ctx->paintColor
- ctx->inputs = fInputs->data();
- ctx->ninputs = fEffect->uniformSize() / 4;
- ctx->shaderConvention = false;
-
- SkAutoMutexExclusive ama(fInterpreterMutex);
- if (!fInterpreter) {
- auto [byteCode, errorText] = fEffect->toByteCode(fInputs->data());
- if (!byteCode) {
- SkDebugf("%s\n", errorText.c_str());
- return false;
- }
- fMain = byteCode->getFunction("main");
- fInterpreter.reset(
- new SkSL::Interpreter<SkRasterPipeline_InterpreterCtx::VECTOR_WIDTH>(
- std::move(byteCode)));
- }
- ctx->fn = fMain;
- ctx->interpreter = fInterpreter.get();
- rec.fPipeline->append(SkRasterPipeline::interpreter, ctx);
- return true;
- }
-
-protected:
- void flatten(SkWriteBuffer& buffer) const override {
- buffer.writeString(fEffect->source().c_str());
- if (fInputs) {
- buffer.writeDataAsByteArray(fInputs.get());
- } else {
- buffer.writeByteArray(nullptr, 0);
- }
- buffer.write32(fChildren.size());
- for (const auto& child : fChildren) {
- buffer.writeFlattenable(child.get());
- }
- }
-
-private:
- SK_FLATTENABLE_HOOKS(SkRuntimeColorFilter)
-
- sk_sp<SkRuntimeEffect> fEffect;
- sk_sp<SkData> fInputs;
- std::vector<sk_sp<SkColorFilter>> fChildren;
-
- mutable SkMutex fInterpreterMutex;
- mutable std::unique_ptr<SkSL::Interpreter<SkRasterPipeline_InterpreterCtx::VECTOR_WIDTH>>
- fInterpreter;
- mutable const SkSL::ByteCodeFunction* fMain;
-
- friend class SkColorFilter;
-
- typedef SkColorFilter INHERITED;
-};
-
-sk_sp<SkFlattenable> SkRuntimeColorFilter::CreateProc(SkReadBuffer& buffer) {
- SkString sksl;
- buffer.readString(&sksl);
- sk_sp<SkData> inputs = buffer.readByteArrayAsData();
-
- auto effect = std::get<0>(SkRuntimeEffect::Make(std::move(sksl)));
- if (!effect) {
- buffer.validate(false);
- return nullptr;
- }
-
- size_t childCount = buffer.read32();
- if (childCount != effect->children().count()) {
- buffer.validate(false);
- return nullptr;
- }
-
- std::vector<sk_sp<SkColorFilter>> children;
- children.resize(childCount);
- for (size_t i = 0; i < children.size(); ++i) {
- children[i] = buffer.readColorFilter();
- }
-
- return effect->makeColorFilter(std::move(inputs), children.data(), children.size());
-}
-
-// Private helper method so SkRuntimeEffect can access SkRuntimeColorFilter
-sk_sp<SkColorFilter> SkMakeRuntimeColorFilter(sk_sp<SkRuntimeEffect> effect, sk_sp<SkData> inputs,
- sk_sp<SkColorFilter> children[], size_t childCount) {
- return sk_sp<SkColorFilter>(
- new SkRuntimeColorFilter(std::move(effect), std::move(inputs), children, childCount));
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
#include "src/core/SkModeColorFilter.h"
void SkColorFilter::RegisterFlattenables() {
@@ -521,5 +396,4 @@
SK_REGISTER_FLATTENABLE(SkModeColorFilter);
SK_REGISTER_FLATTENABLE(SkSRGBGammaColorFilter);
SK_REGISTER_FLATTENABLE(SkMixerColorFilter);
- SK_REGISTER_FLATTENABLE(SkRuntimeColorFilter);
}
diff --git a/src/core/SkRuntimeEffect.cpp b/src/core/SkRuntimeEffect.cpp
index 283e540..24640f9 100644
--- a/src/core/SkRuntimeEffect.cpp
+++ b/src/core/SkRuntimeEffect.cpp
@@ -9,11 +9,22 @@
#include "include/core/SkData.h"
#include "include/effects/SkRuntimeEffect.h"
#include "include/private/SkChecksum.h"
-#include "src/shaders/SkRTShader.h"
+#include "include/private/SkMutex.h"
+#include "src/core/SkRasterPipeline.h"
+#include "src/core/SkReadBuffer.h"
+#include "src/core/SkWriteBuffer.h"
#include "src/sksl/SkSLByteCode.h"
#include "src/sksl/SkSLCompiler.h"
+#include "src/sksl/SkSLInterpreter.h"
#include "src/sksl/ir/SkSLVarDeclarations.h"
+#if SK_SUPPORT_GPU
+#include "include/private/GrRecordingContext.h"
+#include "src/gpu/GrColorInfo.h"
+#include "src/gpu/GrFPArgs.h"
+#include "src/gpu/effects/GrSkSLFP.h"
+#endif
+
SkRuntimeEffect::EffectResult SkRuntimeEffect::Make(SkString sksl) {
auto compiler = std::make_unique<SkSL::Compiler>();
auto program = compiler->convertProgram(SkSL::Program::kPipelineStage_Kind,
@@ -206,6 +217,8 @@
SkASSERT(fUniformSize <= this->inputSize());
}
+SkRuntimeEffect::~SkRuntimeEffect() = default;
+
size_t SkRuntimeEffect::inputSize() const {
return fInAndUniformVars.empty() ? 0
: SkAlign4(fInAndUniformVars.back().fOffset +
@@ -293,6 +306,257 @@
return ByteCodeResult(std::move(byteCode), SkString(fCompiler->errorText().c_str()));
}
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+static constexpr int kVectorWidth = SkRasterPipeline_InterpreterCtx::VECTOR_WIDTH;
+
+class SkRuntimeColorFilter : public SkColorFilter {
+public:
+ SkRuntimeColorFilter(sk_sp<SkRuntimeEffect> effect, sk_sp<SkData> inputs,
+ sk_sp<SkColorFilter> children[], size_t childCount)
+ : fEffect(std::move(effect))
+ , fInputs(std::move(inputs))
+ , fChildren(children, children + childCount) {}
+
+#if SK_SUPPORT_GPU
+ std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(
+ GrRecordingContext* context, const GrColorInfo& colorInfo) const override {
+ auto fp = GrSkSLFP::Make(context, fEffect, "Runtime Color Filter", fInputs);
+ for (const auto& child : fChildren) {
+ auto childFP = child ? child->asFragmentProcessor(context, colorInfo) : nullptr;
+ if (!childFP) {
+ // TODO: This is the case that should eventually mean "the original input color"
+ return nullptr;
+ }
+ fp->addChild(std::move(childFP));
+ }
+ return std::move(fp);
+ }
+#endif
+
+ bool onAppendStages(const SkStageRec& rec, bool shaderIsOpaque) const override {
+ auto ctx = rec.fAlloc->make<SkRasterPipeline_InterpreterCtx>();
+ // don't need to set ctx->paintColor
+ ctx->inputs = fInputs->data();
+ ctx->ninputs = fEffect->uniformSize() / 4;
+ ctx->shaderConvention = false;
+
+ SkAutoMutexExclusive ama(fInterpreterMutex);
+ if (!fInterpreter) {
+ auto [byteCode, errorText] = fEffect->toByteCode(fInputs->data());
+ if (!byteCode) {
+ SkDebugf("%s\n", errorText.c_str());
+ return false;
+ }
+ fMain = byteCode->getFunction("main");
+ fInterpreter.reset(new SkSL::Interpreter<kVectorWidth>(std::move(byteCode)));
+ }
+ ctx->fn = fMain;
+ ctx->interpreter = fInterpreter.get();
+ rec.fPipeline->append(SkRasterPipeline::interpreter, ctx);
+ return true;
+ }
+
+ void flatten(SkWriteBuffer& buffer) const override {
+ buffer.writeString(fEffect->source().c_str());
+ if (fInputs) {
+ buffer.writeDataAsByteArray(fInputs.get());
+ } else {
+ buffer.writeByteArray(nullptr, 0);
+ }
+ buffer.write32(fChildren.size());
+ for (const auto& child : fChildren) {
+ buffer.writeFlattenable(child.get());
+ }
+ }
+
+ SK_FLATTENABLE_HOOKS(SkRuntimeColorFilter)
+
+private:
+ sk_sp<SkRuntimeEffect> fEffect;
+ sk_sp<SkData> fInputs;
+ std::vector<sk_sp<SkColorFilter>> fChildren;
+
+ mutable SkMutex fInterpreterMutex;
+ mutable std::unique_ptr<SkSL::Interpreter<kVectorWidth>> fInterpreter;
+ mutable const SkSL::ByteCodeFunction* fMain;
+};
+
+sk_sp<SkFlattenable> SkRuntimeColorFilter::CreateProc(SkReadBuffer& buffer) {
+ SkString sksl;
+ buffer.readString(&sksl);
+ sk_sp<SkData> inputs = buffer.readByteArrayAsData();
+
+ auto effect = std::get<0>(SkRuntimeEffect::Make(std::move(sksl)));
+ if (!effect) {
+ buffer.validate(false);
+ return nullptr;
+ }
+
+ size_t childCount = buffer.read32();
+ if (childCount != effect->children().count()) {
+ buffer.validate(false);
+ return nullptr;
+ }
+
+ std::vector<sk_sp<SkColorFilter>> children;
+ children.resize(childCount);
+ for (size_t i = 0; i < children.size(); ++i) {
+ children[i] = buffer.readColorFilter();
+ }
+
+ return effect->makeColorFilter(std::move(inputs), children.data(), children.size());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class SkRTShader : public SkShaderBase {
+public:
+ SkRTShader(sk_sp<SkRuntimeEffect> effect, sk_sp<SkData> inputs, const SkMatrix* localMatrix,
+ sk_sp<SkShader>* children, size_t childCount, bool isOpaque)
+ : SkShaderBase(localMatrix)
+ , fEffect(std::move(effect))
+ , fIsOpaque(isOpaque)
+ , fInputs(std::move(inputs))
+ , fChildren(children, children + childCount) {}
+
+ bool isOpaque() const override { return fIsOpaque; }
+
+#if SK_SUPPORT_GPU
+ std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(const GrFPArgs& args) const override {
+ SkMatrix matrix;
+ if (!this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix)->invert(&matrix)) {
+ return nullptr;
+ }
+ auto fp = GrSkSLFP::Make(args.fContext, fEffect, "runtime-shader", fInputs, &matrix);
+ for (const auto& child : fChildren) {
+ auto childFP = child ? as_SB(child)->asFragmentProcessor(args) : nullptr;
+ if (!childFP) {
+ // TODO: This is the case that should eventually mean "the original input color"
+ return nullptr;
+ }
+ fp->addChild(std::move(childFP));
+ }
+ if (GrColorTypeClampType(args.fDstColorInfo->colorType()) != GrClampType::kNone) {
+ return GrFragmentProcessor::ClampPremulOutput(std::move(fp));
+ } else {
+ return std::move(fp);
+ }
+ }
+#endif
+
+ bool onAppendStages(const SkStageRec& rec) const override {
+ SkMatrix inverse;
+ if (!this->computeTotalInverse(rec.fCTM, rec.fLocalM, &inverse)) {
+ return false;
+ }
+
+ auto ctx = rec.fAlloc->make<SkRasterPipeline_InterpreterCtx>();
+ ctx->paintColor = rec.fPaint.getColor4f();
+ ctx->inputs = fInputs->data();
+ ctx->ninputs = fEffect->uniformSize() / 4;
+ ctx->shaderConvention = true;
+
+ SkAutoMutexExclusive ama(fInterpreterMutex);
+ if (!fInterpreter) {
+ auto[byteCode, errorText] = fEffect->toByteCode(fInputs->data());
+ if (!byteCode) {
+ SkDebugf("%s\n", errorText.c_str());
+ return false;
+ }
+ fMain = byteCode->getFunction("main");
+ fInterpreter.reset(new SkSL::Interpreter<kVectorWidth>(std::move(byteCode)));
+ }
+ ctx->fn = fMain;
+ ctx->interpreter = fInterpreter.get();
+
+ rec.fPipeline->append(SkRasterPipeline::seed_shader);
+ rec.fPipeline->append_matrix(rec.fAlloc, inverse);
+ rec.fPipeline->append(SkRasterPipeline::interpreter, ctx);
+ return true;
+ }
+
+ void flatten(SkWriteBuffer& buffer) const override {
+ uint32_t flags = 0;
+ if (fIsOpaque) {
+ flags |= kIsOpaque_Flag;
+ }
+ if (!this->getLocalMatrix().isIdentity()) {
+ flags |= kHasLocalMatrix_Flag;
+ }
+
+ buffer.writeString(fEffect->source().c_str());
+ if (fInputs) {
+ buffer.writeDataAsByteArray(fInputs.get());
+ } else {
+ buffer.writeByteArray(nullptr, 0);
+ }
+ buffer.write32(flags);
+ if (flags & kHasLocalMatrix_Flag) {
+ buffer.writeMatrix(this->getLocalMatrix());
+ }
+ buffer.write32(fChildren.size());
+ for (const auto& child : fChildren) {
+ buffer.writeFlattenable(child.get());
+ }
+ }
+
+ SK_FLATTENABLE_HOOKS(SkRTShader)
+
+private:
+ enum Flags {
+ kIsOpaque_Flag = 1 << 0,
+ kHasLocalMatrix_Flag = 1 << 1,
+ };
+
+ sk_sp<SkRuntimeEffect> fEffect;
+ bool fIsOpaque;
+
+ sk_sp<SkData> fInputs;
+ std::vector<sk_sp<SkShader>> fChildren;
+
+ mutable SkMutex fInterpreterMutex;
+ mutable std::unique_ptr<SkSL::Interpreter<kVectorWidth>> fInterpreter;
+ mutable const SkSL::ByteCodeFunction* fMain;
+};
+
+sk_sp<SkFlattenable> SkRTShader::CreateProc(SkReadBuffer& buffer) {
+ SkString sksl;
+ buffer.readString(&sksl);
+ sk_sp<SkData> inputs = buffer.readByteArrayAsData();
+ uint32_t flags = buffer.read32();
+
+ bool isOpaque = SkToBool(flags & kIsOpaque_Flag);
+ SkMatrix localM, *localMPtr = nullptr;
+ if (flags & kHasLocalMatrix_Flag) {
+ buffer.readMatrix(&localM);
+ localMPtr = &localM;
+ }
+
+ auto effect = std::get<0>(SkRuntimeEffect::Make(std::move(sksl)));
+ if (!effect) {
+ buffer.validate(false);
+ return nullptr;
+ }
+
+ size_t childCount = buffer.read32();
+ if (childCount != effect->children().count()) {
+ buffer.validate(false);
+ return nullptr;
+ }
+
+ std::vector<sk_sp<SkShader>> children;
+ children.resize(childCount);
+ for (size_t i = 0; i < children.size(); ++i) {
+ children[i] = buffer.readShader();
+ }
+
+ return effect->makeShader(std::move(inputs), children.data(), children.size(), localMPtr,
+ isOpaque);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
sk_sp<SkShader> SkRuntimeEffect::makeShader(sk_sp<SkData> inputs,
sk_sp<SkShader> children[], size_t childCount,
const SkMatrix* localMatrix, bool isOpaque) {
@@ -308,17 +572,22 @@
sk_sp<SkColorFilter> SkRuntimeEffect::makeColorFilter(sk_sp<SkData> inputs,
sk_sp<SkColorFilter> children[],
size_t childCount) {
- extern sk_sp<SkColorFilter> SkMakeRuntimeColorFilter(sk_sp<SkRuntimeEffect>, sk_sp<SkData>,
- sk_sp<SkColorFilter>[], size_t);
-
if (!inputs) {
inputs = SkData::MakeEmpty();
}
- return inputs->size() == this->inputSize() && childCount == fChildren.size()
- ? SkMakeRuntimeColorFilter(sk_ref_sp(this), std::move(inputs), children, childCount)
+ return inputs && inputs->size() == this->inputSize() && childCount == fChildren.size()
+ ? sk_sp<SkColorFilter>(new SkRuntimeColorFilter(sk_ref_sp(this), std::move(inputs),
+ children, childCount))
: nullptr;
}
sk_sp<SkColorFilter> SkRuntimeEffect::makeColorFilter(sk_sp<SkData> inputs) {
return this->makeColorFilter(std::move(inputs), nullptr, 0);
}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+void SkRuntimeEffect::RegisterFlattenables() {
+ SK_REGISTER_FLATTENABLE(SkRuntimeColorFilter);
+ SK_REGISTER_FLATTENABLE(SkRTShader);
+}
diff --git a/src/ports/SkGlobalInitialization_default.cpp b/src/ports/SkGlobalInitialization_default.cpp
index 30d41da..7ef7c31 100644
--- a/src/ports/SkGlobalInitialization_default.cpp
+++ b/src/ports/SkGlobalInitialization_default.cpp
@@ -27,6 +27,7 @@
#include "include/effects/SkLumaColorFilter.h"
#include "include/effects/SkOverdrawColorFilter.h"
#include "include/effects/SkPerlinNoiseShader.h"
+ #include "include/effects/SkRuntimeEffect.h"
#include "include/effects/SkShaderMaskFilter.h"
#include "include/effects/SkTableColorFilter.h"
#include "src/core/SkColorFilter_Matrix.h"
@@ -45,7 +46,6 @@
#include "src/shaders/SkLightingShader.h"
#include "src/shaders/SkLocalMatrixShader.h"
#include "src/shaders/SkPictureShader.h"
- #include "src/shaders/SkRTShader.h"
#include "src/shaders/SkShaderBase.h"
#include "include/effects/SkImageFilters.h"
@@ -70,7 +70,6 @@
SK_REGISTER_FLATTENABLE(SkEmptyShader);
SK_REGISTER_FLATTENABLE(SkLocalMatrixShader);
SK_REGISTER_FLATTENABLE(SkPictureShader);
- SK_REGISTER_FLATTENABLE(SkRTShader);
SkGradientShader::RegisterFlattenables();
SkLightingShader::RegisterFlattenables();
SkPerlinNoiseShader::RegisterFlattenables();
@@ -84,6 +83,9 @@
SkOverdrawColorFilter::RegisterFlattenables();
SkTableColorFilter::RegisterFlattenables();
+ // Shader & color filter.
+ SkRuntimeEffect::RegisterFlattenables();
+
// Mask filters.
SK_REGISTER_FLATTENABLE(SkEmbossMaskFilter);
SkMaskFilter::RegisterFlattenables();
diff --git a/src/shaders/SkRTShader.cpp b/src/shaders/SkRTShader.cpp
deleted file mode 100644
index f966cc7..0000000
--- a/src/shaders/SkRTShader.cpp
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright 2019 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "include/core/SkData.h"
-#include "include/effects/SkRuntimeEffect.h"
-#include "src/core/SkArenaAlloc.h"
-#include "src/core/SkRasterPipeline.h"
-#include "src/core/SkReadBuffer.h"
-#include "src/core/SkWriteBuffer.h"
-#include "src/shaders/SkRTShader.h"
-
-#include "src/sksl/SkSLByteCode.h"
-#include "src/sksl/SkSLCompiler.h"
-#include "src/sksl/SkSLInterpreter.h"
-
-#if SK_SUPPORT_GPU
-#include "src/gpu/GrColorInfo.h"
-#include "src/gpu/GrFPArgs.h"
-#include "src/gpu/effects/GrSkSLFP.h"
-#endif
-
-SkRTShader::SkRTShader(sk_sp<SkRuntimeEffect> effect, sk_sp<SkData> inputs,
- const SkMatrix* localMatrix, sk_sp<SkShader>* children, size_t childCount,
- bool isOpaque)
- : SkShaderBase(localMatrix)
- , fEffect(std::move(effect))
- , fIsOpaque(isOpaque)
- , fInputs(std::move(inputs))
- , fChildren(children, children + childCount) {
-}
-
-SkRTShader::~SkRTShader() = default;
-
-bool SkRTShader::onAppendStages(const SkStageRec& rec) const {
- SkMatrix inverse;
- if (!this->computeTotalInverse(rec.fCTM, rec.fLocalM, &inverse)) {
- return false;
- }
-
- auto ctx = rec.fAlloc->make<SkRasterPipeline_InterpreterCtx>();
- ctx->paintColor = rec.fPaint.getColor4f();
- ctx->inputs = fInputs->data();
- ctx->ninputs = fEffect->uniformSize() / 4;
- ctx->shaderConvention = true;
-
- SkAutoMutexExclusive ama(fInterpreterMutex);
- if (!fInterpreter) {
- auto [byteCode, errorText] = fEffect->toByteCode(fInputs->data());
- if (!byteCode) {
- SkDebugf("%s\n", errorText.c_str());
- return false;
- }
- fMain = byteCode->getFunction("main");
- fInterpreter.reset(new SkSL::Interpreter<SkRasterPipeline_InterpreterCtx::VECTOR_WIDTH>(
- std::move(byteCode)));
- }
- ctx->fn = fMain;
- ctx->interpreter = fInterpreter.get();
-
- rec.fPipeline->append(SkRasterPipeline::seed_shader);
- rec.fPipeline->append_matrix(rec.fAlloc, inverse);
- rec.fPipeline->append(SkRasterPipeline::interpreter, ctx);
- return true;
-}
-
-enum Flags {
- kIsOpaque_Flag = 1 << 0,
- kHasLocalMatrix_Flag = 1 << 1,
-};
-
-void SkRTShader::flatten(SkWriteBuffer& buffer) const {
- uint32_t flags = 0;
- if (fIsOpaque) {
- flags |= kIsOpaque_Flag;
- }
- if (!this->getLocalMatrix().isIdentity()) {
- flags |= kHasLocalMatrix_Flag;
- }
-
- buffer.writeString(fEffect->source().c_str());
- if (fInputs) {
- buffer.writeDataAsByteArray(fInputs.get());
- } else {
- buffer.writeByteArray(nullptr, 0);
- }
- buffer.write32(flags);
- if (flags & kHasLocalMatrix_Flag) {
- buffer.writeMatrix(this->getLocalMatrix());
- }
- buffer.write32(fChildren.size());
- for (const auto& child : fChildren) {
- buffer.writeFlattenable(child.get());
- }
-}
-
-sk_sp<SkFlattenable> SkRTShader::CreateProc(SkReadBuffer& buffer) {
- SkString sksl;
- buffer.readString(&sksl);
- sk_sp<SkData> inputs = buffer.readByteArrayAsData();
- uint32_t flags = buffer.read32();
-
- bool isOpaque = SkToBool(flags & kIsOpaque_Flag);
- SkMatrix localM, *localMPtr = nullptr;
- if (flags & kHasLocalMatrix_Flag) {
- buffer.readMatrix(&localM);
- localMPtr = &localM;
- }
-
- auto effect = std::get<0>(SkRuntimeEffect::Make(std::move(sksl)));
- if (!effect) {
- buffer.validate(false);
- return nullptr;
- }
-
- size_t childCount = buffer.read32();
- if (childCount != effect->children().count()) {
- buffer.validate(false);
- return nullptr;
- }
-
- std::vector<sk_sp<SkShader>> children;
- children.resize(childCount);
- for (size_t i = 0; i < children.size(); ++i) {
- children[i] = buffer.readShader();
- }
-
- return effect->makeShader(std::move(inputs), children.data(), children.size(), localMPtr,
- isOpaque);
-}
-
-#if SK_SUPPORT_GPU
-std::unique_ptr<GrFragmentProcessor> SkRTShader::asFragmentProcessor(const GrFPArgs& args) const {
- SkMatrix matrix;
- if (!this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix)->invert(&matrix)) {
- return nullptr;
- }
- auto fp = GrSkSLFP::Make(args.fContext, fEffect, "runtime-shader", fInputs, &matrix);
- for (const auto& child : fChildren) {
- auto childFP = child ? as_SB(child)->asFragmentProcessor(args) : nullptr;
- if (!childFP) {
- // TODO: This is the case that should eventually mean "the original input color"
- return nullptr;
- }
- fp->addChild(std::move(childFP));
- }
- if (GrColorTypeClampType(args.fDstColorInfo->colorType()) != GrClampType::kNone) {
- return GrFragmentProcessor::ClampPremulOutput(std::move(fp));
- } else {
- return std::move(fp);
- }
-}
-#endif
diff --git a/src/shaders/SkRTShader.h b/src/shaders/SkRTShader.h
deleted file mode 100644
index 1ac56ec..0000000
--- a/src/shaders/SkRTShader.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2019 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkRTShader_DEFINED
-#define SkRTShader_DEFINED
-
-#include "include/core/SkString.h"
-#include "include/private/SkMutex.h"
-#include "src/shaders/SkShaderBase.h"
-
-struct GrFPArgs;
-class GrFragmentProcessor;
-class SkData;
-class SkMatrix;
-class SkRuntimeEffect;
-
-namespace SkSL {
- class ByteCodeFunction;
-
- template<int width>
- class Interpreter;
-}
-
-class SkRTShader : public SkShaderBase {
-public:
- SkRTShader(sk_sp<SkRuntimeEffect> effect, sk_sp<SkData> inputs, const SkMatrix* localMatrix,
- sk_sp<SkShader>* children, size_t childCount, bool isOpaque);
- ~SkRTShader() override;
-
- bool isOpaque() const override { return fIsOpaque; }
-
-#if SK_SUPPORT_GPU
- std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(const GrFPArgs&) const override;
-#endif
-
-protected:
- void flatten(SkWriteBuffer&) const override;
- bool onAppendStages(const SkStageRec& rec) const override;
-
-private:
- static constexpr int VECTOR_WIDTH = 8;
-
- SK_FLATTENABLE_HOOKS(SkRTShader)
-
- sk_sp<SkRuntimeEffect> fEffect;
- bool fIsOpaque;
-
- sk_sp<SkData> fInputs;
- std::vector<sk_sp<SkShader>> fChildren;
-
- mutable SkMutex fInterpreterMutex;
- mutable std::unique_ptr<SkSL::Interpreter<VECTOR_WIDTH>> fInterpreter;
- mutable const SkSL::ByteCodeFunction* fMain;
-
- typedef SkShaderBase INHERITED;
-};
-
-#endif