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:
parent
8980acd623
commit
7281a86237
@ -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",
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
156
src/shaders/SkRTShader.cpp
Normal 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
62
src/shaders/SkRTShader.h
Normal 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
|
Loading…
Reference in New Issue
Block a user