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