1 /*
2 * Copyright 2019 Google LLC
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 #include "src/core/SkRuntimeBlender.h"
8
9 #include "include/core/SkCapabilities.h"
10 #include "include/core/SkData.h"
11 #include "include/core/SkMatrix.h"
12 #include "include/core/SkString.h"
13 #include "include/effects/SkRuntimeEffect.h"
14 #include "include/private/SkSLSampleUsage.h"
15 #include "include/private/base/SkDebug.h"
16 #include "include/private/base/SkTArray.h"
17 #include "src/core/SkEffectPriv.h"
18 #include "src/core/SkReadBuffer.h"
19 #include "src/core/SkRuntimeEffectPriv.h"
20 #include "src/core/SkWriteBuffer.h"
21 #include "src/shaders/SkShaderBase.h"
22 #include "src/sksl/codegen/SkSLRasterPipelineBuilder.h"
23
24 #include <string>
25
26 using namespace skia_private;
27
28 #if defined(SK_BUILD_FOR_DEBUGGER)
29 constexpr bool kLenientSkSLDeserialization = true;
30 #else
31 constexpr bool kLenientSkSLDeserialization = false;
32 #endif
33
CreateProc(SkReadBuffer & buffer)34 sk_sp<SkFlattenable> SkRuntimeBlender::CreateProc(SkReadBuffer& buffer) {
35 if (!buffer.validate(buffer.allowSkSL())) {
36 return nullptr;
37 }
38
39 SkString sksl;
40 buffer.readString(&sksl);
41 sk_sp<SkData> uniforms = buffer.readByteArrayAsData();
42
43 auto effect = SkMakeCachedRuntimeEffect(SkRuntimeEffect::MakeForBlender, std::move(sksl));
44 if constexpr (!kLenientSkSLDeserialization) {
45 if (!buffer.validate(effect != nullptr)) {
46 return nullptr;
47 }
48 }
49
50 STArray<4, SkRuntimeEffect::ChildPtr> children;
51 if (!SkRuntimeEffectPriv::ReadChildEffects(buffer, effect.get(), &children)) {
52 return nullptr;
53 }
54
55 if constexpr (kLenientSkSLDeserialization) {
56 if (!effect) {
57 SkDebugf("Serialized SkSL failed to compile. Ignoring/dropping SkSL blender.\n");
58 return nullptr;
59 }
60 }
61
62 return effect->makeBlender(std::move(uniforms), SkSpan(children));
63 }
64
onAppendStages(const SkStageRec & rec) const65 bool SkRuntimeBlender::onAppendStages(const SkStageRec& rec) const {
66 if (!SkRuntimeEffectPriv::CanDraw(SkCapabilities::RasterBackend().get(), fEffect.get())) {
67 // SkRP has support for many parts of #version 300 already, but for now, we restrict its
68 // usage in runtime effects to just #version 100.
69 return false;
70 }
71 if (const SkSL::RP::Program* program = fEffect->getRPProgram(/*debugTrace=*/nullptr)) {
72 SkSpan<const float> uniforms = SkRuntimeEffectPriv::UniformsAsSpan(
73 fEffect->uniforms(),
74 fUniforms,
75 /*alwaysCopyIntoAlloc=*/false,
76 rec.fDstCS,
77 rec.fAlloc);
78 SkShaders::MatrixRec matrix(SkMatrix::I());
79 matrix.markCTMApplied();
80 RuntimeEffectRPCallbacks callbacks(rec, matrix, fChildren, fEffect->fSampleUsages);
81 bool success = program->appendStages(rec.fPipeline, rec.fAlloc, &callbacks, uniforms);
82 return success;
83 }
84 return false;
85 }
86
flatten(SkWriteBuffer & buffer) const87 void SkRuntimeBlender::flatten(SkWriteBuffer& buffer) const {
88 buffer.writeString(fEffect->source().c_str());
89 buffer.writeDataAsByteArray(fUniforms.get());
90 SkRuntimeEffectPriv::WriteChildEffects(buffer, fChildren);
91 }
92
93