• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
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/core/SkArenaAlloc.h"
10  #include "src/core/SkRasterPipeline.h"
11  #include "src/core/SkReadBuffer.h"
12  #include "src/core/SkWriteBuffer.h"
13  #include "src/shaders/SkRTShader.h"
14  
15  #include "src/sksl/SkSLByteCode.h"
16  #include "src/sksl/SkSLCompiler.h"
17  
18  #if SK_SUPPORT_GPU
19  #include "include/private/GrRecordingContext.h"
20  #include "src/gpu/GrCaps.h"
21  #include "src/gpu/GrColorSpaceInfo.h"
22  #include "src/gpu/GrRecordingContextPriv.h"
23  #include "src/gpu/SkGr.h"
24  
25  #include "src/gpu/GrFragmentProcessor.h"
26  #include "src/gpu/effects/GrSkSLFP.h"
27  #include "src/gpu/effects/generated/GrMixerEffect.h"
28  
new_sksl_unique_id()29  static inline uint32_t new_sksl_unique_id() {
30      return GrSkSLFP::NewIndex();
31  }
32  #else
new_sksl_unique_id()33  static inline uint32_t new_sksl_unique_id() {
34      return 0;   // not used w/o GPU
35  }
36  #endif
37  
SkRTShader(SkString sksl,sk_sp<SkData> inputs,const SkMatrix * localMatrix,bool isOpaque)38  SkRTShader::SkRTShader(SkString sksl, sk_sp<SkData> inputs, const SkMatrix* localMatrix,
39                         bool isOpaque)
40      : SkShaderBase(localMatrix)
41      , fSkSL(std::move(sksl))
42      , fInputs(std::move(inputs))
43      , fUniqueID(new_sksl_unique_id())
44      , fIsOpaque(isOpaque)
45  {}
46  
onAppendStages(const SkStageRec & rec) const47  bool SkRTShader::onAppendStages(const SkStageRec& rec) const {
48      SkMatrix inverse;
49      if (!this->computeTotalInverse(rec.fCTM, rec.fLocalM, &inverse)) {
50          return false;
51      }
52  
53      auto ctx = rec.fAlloc->make<SkRasterPipeline_InterpreterCtx>();
54      ctx->paintColor = rec.fPaint.getColor4f();
55      ctx->inputs = fInputs->data();
56      ctx->ninputs = fInputs->size() / 4;
57      ctx->shaderConvention = true;
58  
59      SkAutoMutexExclusive ama(fByteCodeMutex);
60      if (!fByteCode) {
61          SkSL::Compiler c;
62          auto prog = c.convertProgram(SkSL::Program::kGeneric_Kind,
63                                       SkSL::String(fSkSL.c_str()),
64                                       SkSL::Program::Settings());
65          if (c.errorCount()) {
66              SkDebugf("%s\n", c.errorText().c_str());
67              return false;
68          }
69          fByteCode = c.toByteCode(*prog);
70          if (c.errorCount()) {
71              SkDebugf("%s\n", c.errorText().c_str());
72              return false;
73          }
74          SkASSERT(fByteCode);
75          if (!fByteCode->getFunction("main")) {
76              return false;
77          }
78      }
79      ctx->byteCode = fByteCode.get();
80      ctx->fn = ctx->byteCode->getFunction("main");
81  
82      rec.fPipeline->append(SkRasterPipeline::seed_shader);
83      rec.fPipeline->append_matrix(rec.fAlloc, inverse);
84      rec.fPipeline->append(SkRasterPipeline::interpreter, ctx);
85      return true;
86  }
87  
88  enum Flags {
89      kIsOpaque_Flag          = 1 << 0,
90      kHasLocalMatrix_Flag    = 1 << 1,
91  };
92  
flatten(SkWriteBuffer & buffer) const93  void SkRTShader::flatten(SkWriteBuffer& buffer) const {
94      uint32_t flags = 0;
95      if (fIsOpaque) {
96          flags |= kIsOpaque_Flag;
97      }
98      if (!this->getLocalMatrix().isIdentity()) {
99          flags |= kHasLocalMatrix_Flag;
100      }
101  
102      buffer.writeString(fSkSL.c_str());
103      if (fInputs) {
104          buffer.writeDataAsByteArray(fInputs.get());
105      } else {
106          buffer.writeByteArray(nullptr, 0);
107      }
108      buffer.write32(flags);
109      if (flags & kHasLocalMatrix_Flag) {
110          buffer.writeMatrix(this->getLocalMatrix());
111      }
112  }
113  
CreateProc(SkReadBuffer & buffer)114  sk_sp<SkFlattenable> SkRTShader::CreateProc(SkReadBuffer& buffer) {
115      SkString sksl;
116      buffer.readString(&sksl);
117      sk_sp<SkData> inputs = buffer.readByteArrayAsData();
118      uint32_t flags = buffer.read32();
119  
120      bool isOpaque = SkToBool(flags & kIsOpaque_Flag);
121      SkMatrix localM, *localMPtr = nullptr;
122      if (flags & kHasLocalMatrix_Flag) {
123          buffer.readMatrix(&localM);
124          localMPtr = &localM;
125      }
126  
127      return sk_sp<SkFlattenable>(new SkRTShader(std::move(sksl), std::move(inputs),
128                                                 localMPtr, isOpaque));
129  }
130  
SkRuntimeShaderMaker(SkString sksl,sk_sp<SkData> inputs,const SkMatrix * localMatrix,bool isOpaque)131  sk_sp<SkShader> SkRuntimeShaderMaker(SkString sksl, sk_sp<SkData> inputs,
132                                       const SkMatrix* localMatrix, bool isOpaque) {
133      return sk_sp<SkShader>(new SkRTShader(std::move(sksl), std::move(inputs),
134                                            localMatrix, isOpaque));
135  }
136  
137  #if SK_SUPPORT_GPU
asFragmentProcessor(const GrFPArgs & args) const138  std::unique_ptr<GrFragmentProcessor> SkRTShader::asFragmentProcessor(const GrFPArgs& args) const {
139      SkMatrix matrix;
140      if (!this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix)->invert(&matrix)) {
141          return nullptr;
142      }
143      return GrSkSLFP::Make(args.fContext, fUniqueID, "runtime-shader", fSkSL,
144                            fInputs->data(), fInputs->size(), SkSL::Program::kPipelineStage_Kind,
145                            &matrix);
146  }
147  #endif
148