xref: /aosp_15_r20/external/skia/src/core/SkRuntimeBlender.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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