blob: bd5586ef00327f943a3647ca27e7d7be3604fcfe [file] [log] [blame]
Mike Reed3fd3cc92019-06-20 12:40:30 -04001/*
2 * Copyright 2019 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "include/core/SkData.h"
9#include "src/shaders/SkRTShader.h"
10#include "src/core/SkArenaAlloc.h"
11#include "src/core/SkRasterPipeline.h"
12#include "src/core/SkReadBuffer.h"
13#include "src/core/SkWriteBuffer.h"
14
15#if SK_SUPPORT_GPU
16#include "src/gpu/GrFragmentProcessor.h"
17#include "src/gpu/effects/generated/GrMixerEffect.h"
18#include "src/gpu/effects/GrSkSLFP.h"
19#endif
20
21#include "src/sksl/SkSLByteCode.h"
22#include "src/sksl/SkSLCompiler.h"
23
24SkRTShader::SkRTShader(SkString sksl, sk_sp<SkData> inputs, const SkMatrix* localMatrix,
25 bool isOpaque)
26 : SkShaderBase(localMatrix)
27 , fSkSL(std::move(sksl))
28 , fInputs(std::move(inputs))
29 , fIsOpaque(isOpaque)
30{}
31
32bool SkRTShader::onAppendStages(const SkStageRec& rec) const {
33 SkMatrix inverse;
34 if (!this->computeTotalInverse(rec.fCTM, rec.fLocalM, &inverse)) {
35 return false;
36 }
37
38 auto ctx = rec.fAlloc->make<SkRasterPipeline_InterpreterCtx>();
39 ctx->inputs = fInputs->data();
40 ctx->ninputs = fInputs->size() / 4;
41 ctx->shader_convention = true;
42
43 SkAutoMutexExclusive ama(fByteCodeMutex);
44 if (!fByteCode) {
45 SkSL::Compiler c;
46 auto prog = c.convertProgram(SkSL::Program::kGeneric_Kind,
47 SkSL::String(fSkSL.c_str()),
48 SkSL::Program::Settings());
49 if (c.errorCount()) {
50 SkDebugf("%s\n", c.errorText().c_str());
51 return false;
52 }
53 fByteCode = c.toByteCode(*prog);
54 if (c.errorCount()) {
55 SkDebugf("%s\n", c.errorText().c_str());
56 return false;
57 }
58 SkASSERT(fByteCode);
59 }
60 ctx->byteCode = fByteCode.get();
61 ctx->fn = ctx->byteCode->fFunctions[0].get();
62
63 rec.fPipeline->append(SkRasterPipeline::seed_shader);
64 rec.fPipeline->append_matrix(rec.fAlloc, inverse);
65 rec.fPipeline->append(SkRasterPipeline::interpreter, ctx);
66 return true;
67}
68
69enum Flags {
70 kIsOpaque_Flag = 1 << 0,
71 kHasLocalMatrix_Flag = 1 << 1,
72};
73
74void SkRTShader::flatten(SkWriteBuffer& buffer) const {
75 uint32_t flags = 0;
76 if (fIsOpaque) {
77 flags |= kIsOpaque_Flag;
78 }
79 if (!this->getLocalMatrix().isIdentity()) {
80 flags |= kHasLocalMatrix_Flag;
81 }
82
83 buffer.writeString(fSkSL.c_str());
84 if (fInputs) {
85 buffer.writeDataAsByteArray(fInputs.get());
86 } else {
87 buffer.writeByteArray(nullptr, 0);
88 }
89 buffer.write32(flags);
90 if (flags & kHasLocalMatrix_Flag) {
91 buffer.writeMatrix(this->getLocalMatrix());
92 }
93}
94
95sk_sp<SkFlattenable> SkRTShader::CreateProc(SkReadBuffer& buffer) {
96 SkString sksl;
97 buffer.readString(&sksl);
98 sk_sp<SkData> inputs = buffer.readByteArrayAsData();
99 uint32_t flags = buffer.read32();
100
101 bool isOpaque = SkToBool(flags & kIsOpaque_Flag);
102 SkMatrix localM, *localMPtr = nullptr;
103 if (flags & kHasLocalMatrix_Flag) {
104 buffer.readMatrix(&localM);
105 localMPtr = &localM;
106 }
107
108 return sk_sp<SkFlattenable>(new SkRTShader(std::move(sksl), std::move(inputs),
109 localMPtr, isOpaque));
110}
111
112sk_sp<SkShader> SkRuntimeShaderMaker(SkString sksl, sk_sp<SkData> inputs,
113 const SkMatrix* localMatrix, bool isOpaque) {
114 return sk_sp<SkShader>(new SkRTShader(std::move(sksl), std::move(inputs),
115 localMatrix, isOpaque));
116}