runtime shaders
This extends the runStriped to all for return data.
GPU impl not done yet, will be done in a follow-on CL.
Change-Id: Ib107d2945f6fdb34ce1b5405a6c88a5ae7e9f7ac
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/221539
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Mike Reed <reed@google.com>
diff --git a/src/shaders/SkRTShader.cpp b/src/shaders/SkRTShader.cpp
new file mode 100644
index 0000000..bd5586e
--- /dev/null
+++ b/src/shaders/SkRTShader.cpp
@@ -0,0 +1,116 @@
+/*
+ * 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 "src/shaders/SkRTShader.h"
+#include "src/core/SkArenaAlloc.h"
+#include "src/core/SkRasterPipeline.h"
+#include "src/core/SkReadBuffer.h"
+#include "src/core/SkWriteBuffer.h"
+
+#if SK_SUPPORT_GPU
+#include "src/gpu/GrFragmentProcessor.h"
+#include "src/gpu/effects/generated/GrMixerEffect.h"
+#include "src/gpu/effects/GrSkSLFP.h"
+#endif
+
+#include "src/sksl/SkSLByteCode.h"
+#include "src/sksl/SkSLCompiler.h"
+
+SkRTShader::SkRTShader(SkString sksl, sk_sp<SkData> inputs, const SkMatrix* localMatrix,
+ bool isOpaque)
+ : SkShaderBase(localMatrix)
+ , fSkSL(std::move(sksl))
+ , fInputs(std::move(inputs))
+ , fIsOpaque(isOpaque)
+{}
+
+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->inputs = fInputs->data();
+ ctx->ninputs = fInputs->size() / 4;
+ ctx->shader_convention = true;
+
+ SkAutoMutexExclusive ama(fByteCodeMutex);
+ if (!fByteCode) {
+ SkSL::Compiler c;
+ auto prog = c.convertProgram(SkSL::Program::kGeneric_Kind,
+ SkSL::String(fSkSL.c_str()),
+ SkSL::Program::Settings());
+ if (c.errorCount()) {
+ SkDebugf("%s\n", c.errorText().c_str());
+ return false;
+ }
+ fByteCode = c.toByteCode(*prog);
+ if (c.errorCount()) {
+ SkDebugf("%s\n", c.errorText().c_str());
+ return false;
+ }
+ SkASSERT(fByteCode);
+ }
+ ctx->byteCode = fByteCode.get();
+ ctx->fn = ctx->byteCode->fFunctions[0].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(fSkSL.c_str());
+ if (fInputs) {
+ buffer.writeDataAsByteArray(fInputs.get());
+ } else {
+ buffer.writeByteArray(nullptr, 0);
+ }
+ buffer.write32(flags);
+ if (flags & kHasLocalMatrix_Flag) {
+ buffer.writeMatrix(this->getLocalMatrix());
+ }
+}
+
+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;
+ }
+
+ return sk_sp<SkFlattenable>(new SkRTShader(std::move(sksl), std::move(inputs),
+ localMPtr, isOpaque));
+}
+
+sk_sp<SkShader> SkRuntimeShaderMaker(SkString sksl, sk_sp<SkData> inputs,
+ const SkMatrix* localMatrix, bool isOpaque) {
+ return sk_sp<SkShader>(new SkRTShader(std::move(sksl), std::move(inputs),
+ localMatrix, isOpaque));
+}