Revert "Move runtime shader/colorfilter into SkRuntimeEffect.cpp"

This reverts commit 8980acd623.

Reason for revert: Win-Shared

Original change's description:
> Move runtime shader/colorfilter into SkRuntimeEffect.cpp
> 
> Better organization that lets us share a bunch of code between these
> (very similar) objects.
> 
> Change-Id: Ie559d6e144d8588b98a95d4170e2e6c19d9623bd
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/270736
> Reviewed-by: Mike Reed <reed@google.com>
> Commit-Queue: Brian Osman <brianosman@google.com>

TBR=brianosman@google.com,ethannicholas@google.com,reed@google.com

Change-Id: Ic13d85b7c4f2d593a6c15dde067f118ea5753eb6
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/271600
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
Brian Osman 2020-02-18 19:30:51 +00:00 committed by Skia Commit-Bot
parent 8980acd623
commit 7281a86237
7 changed files with 352 additions and 278 deletions

View File

@ -445,6 +445,7 @@ skia_core_sources = [
"$_src/shaders/SkLights.h",
"$_src/shaders/SkLocalMatrixShader.cpp",
"$_src/shaders/SkLocalMatrixShader.h",
"$_src/shaders/SkRTShader.cpp",
"$_src/shaders/SkShader.cpp",
"$_src/shaders/SkShaderBase.h",

View File

@ -127,8 +127,6 @@ public:
ByteCodeResult toByteCode(const void* inputs);
static void RegisterFlattenables();
private:
SkRuntimeEffect(SkString sksl, std::unique_ptr<SkSL::Compiler> compiler,
std::unique_ptr<SkSL::Program> baseProgram,

View File

@ -9,6 +9,7 @@
#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"
@ -18,6 +19,7 @@
#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"
@ -389,6 +391,129 @@ sk_sp<SkColorFilter> SkColorFilters::Lerp(float weight, sk_sp<SkColorFilter> cf0
///////////////////////////////////////////////////////////////////////////////////////////////////
#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 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() {
@ -396,4 +521,5 @@ void SkColorFilter::RegisterFlattenables() {
SK_REGISTER_FLATTENABLE(SkModeColorFilter);
SK_REGISTER_FLATTENABLE(SkSRGBGammaColorFilter);
SK_REGISTER_FLATTENABLE(SkMixerColorFilter);
SK_REGISTER_FLATTENABLE(SkRuntimeColorFilter);
}

View File

@ -9,22 +9,11 @@
#include "include/core/SkData.h"
#include "include/effects/SkRuntimeEffect.h"
#include "include/private/SkChecksum.h"
#include "include/private/SkMutex.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"
#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,
@ -304,257 +293,6 @@ SkRuntimeEffect::ByteCodeResult SkRuntimeEffect::toByteCode(const void* inputs)
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 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 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) {
@ -567,19 +305,14 @@ sk_sp<SkShader> SkRuntimeEffect::makeShader(sk_sp<SkData> inputs,
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);
return inputs && inputs->size() == this->inputSize() && childCount == fChildren.size()
? sk_sp<SkColorFilter>(new SkRuntimeColorFilter(sk_ref_sp(this), std::move(inputs),
children, childCount))
? SkMakeRuntimeColorFilter(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);
}

View File

@ -27,7 +27,6 @@
#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"
@ -46,6 +45,7 @@
#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,6 +70,7 @@
SK_REGISTER_FLATTENABLE(SkEmptyShader);
SK_REGISTER_FLATTENABLE(SkLocalMatrixShader);
SK_REGISTER_FLATTENABLE(SkPictureShader);
SK_REGISTER_FLATTENABLE(SkRTShader);
SkGradientShader::RegisterFlattenables();
SkLightingShader::RegisterFlattenables();
SkPerlinNoiseShader::RegisterFlattenables();
@ -83,9 +84,6 @@
SkOverdrawColorFilter::RegisterFlattenables();
SkTableColorFilter::RegisterFlattenables();
// Shader & color filter.
SkRuntimeEffect::RegisterFlattenables();
// Mask filters.
SK_REGISTER_FLATTENABLE(SkEmbossMaskFilter);
SkMaskFilter::RegisterFlattenables();

156
src/shaders/SkRTShader.cpp Normal file
View File

@ -0,0 +1,156 @@
/*
* 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 fp;
}
}
#endif

62
src/shaders/SkRTShader.h Normal file
View File

@ -0,0 +1,62 @@
/*
* 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