• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2023 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/effects/colorfilters/SkRuntimeColorFilter.h"
8 
9 #include "include/core/SkCapabilities.h"
10 #include "include/core/SkColor.h"
11 #include "include/core/SkColorFilter.h"
12 #include "include/core/SkData.h"
13 #include "include/core/SkMatrix.h"
14 #include "include/core/SkString.h"
15 #include "include/effects/SkLumaColorFilter.h"
16 #include "include/effects/SkOverdrawColorFilter.h"
17 #include "include/effects/SkRuntimeEffect.h"
18 #include "include/private/SkSLSampleUsage.h"
19 #include "include/private/base/SkDebug.h"
20 #include "include/private/base/SkFloatingPoint.h"
21 #include "include/private/base/SkTArray.h"
22 #include "src/core/SkColorData.h"
23 #include "src/core/SkEffectPriv.h"
24 #include "src/core/SkKnownRuntimeEffects.h"
25 #include "src/core/SkPicturePriv.h"
26 #include "src/core/SkReadBuffer.h"
27 #include "src/core/SkRuntimeEffectPriv.h"
28 #include "src/core/SkWriteBuffer.h"
29 #include "src/shaders/SkShaderBase.h"
30 #include "src/sksl/codegen/SkSLRasterPipelineBuilder.h"
31 
32 #include <cstdint>
33 #include <string>
34 #include <utility>
35 
36 #if defined(SK_BUILD_FOR_DEBUGGER)
37     constexpr bool kLenientSkSLDeserialization = true;
38 #else
39     constexpr bool kLenientSkSLDeserialization = false;
40 #endif
41 
SkRuntimeColorFilter(sk_sp<SkRuntimeEffect> effect,sk_sp<const SkData> uniforms,SkSpan<const SkRuntimeEffect::ChildPtr> children)42 SkRuntimeColorFilter::SkRuntimeColorFilter(sk_sp<SkRuntimeEffect> effect,
43                                            sk_sp<const SkData> uniforms,
44                                            SkSpan<const SkRuntimeEffect::ChildPtr> children)
45         : fEffect(std::move(effect))
46         , fUniforms(std::move(uniforms))
47         , fChildren(children.begin(), children.end()) {}
48 
appendStages(const SkStageRec & rec,bool) const49 bool SkRuntimeColorFilter::appendStages(const SkStageRec& rec, bool) const {
50     if (!SkRuntimeEffectPriv::CanDraw(SkCapabilities::RasterBackend().get(), fEffect.get())) {
51         // SkRP has support for many parts of #version 300 already, but for now, we restrict its
52         // usage in runtime effects to just #version 100.
53         return false;
54     }
55     if (const SkSL::RP::Program* program = fEffect->getRPProgram(/*debugTrace=*/nullptr)) {
56         SkSpan<const float> uniforms =
57                 SkRuntimeEffectPriv::UniformsAsSpan(fEffect->uniforms(),
58                                                     fUniforms,
59                                                     /*alwaysCopyIntoAlloc=*/false,
60                                                     rec.fDstCS,
61                                                     rec.fAlloc);
62         SkShaders::MatrixRec matrix(SkMatrix::I());
63         matrix.markCTMApplied();
64         RuntimeEffectRPCallbacks callbacks(rec, matrix, fChildren, fEffect->fSampleUsages);
65         bool success = program->appendStages(rec.fPipeline, rec.fAlloc, &callbacks, uniforms);
66         return success;
67     }
68     return false;
69 }
70 
onIsAlphaUnchanged() const71 bool SkRuntimeColorFilter::onIsAlphaUnchanged() const {
72     return fEffect->isAlphaUnchanged();
73 }
74 
flatten(SkWriteBuffer & buffer) const75 void SkRuntimeColorFilter::flatten(SkWriteBuffer& buffer) const {
76     if (SkKnownRuntimeEffects::IsSkiaKnownRuntimeEffect(fEffect->fStableKey)) {
77         // We only serialize Skia-internal stableKeys. First party stable keys are not serialized.
78         buffer.write32(fEffect->fStableKey);
79     } else {
80         buffer.write32(0);
81         buffer.writeString(fEffect->source().c_str());
82     }
83     buffer.writeDataAsByteArray(fUniforms.get());
84     SkRuntimeEffectPriv::WriteChildEffects(buffer, fChildren);
85 }
86 
asRuntimeEffect() const87 SkRuntimeEffect* SkRuntimeColorFilter::asRuntimeEffect() const { return fEffect.get(); }
88 
CreateProc(SkReadBuffer & buffer)89 sk_sp<SkFlattenable> SkRuntimeColorFilter::CreateProc(SkReadBuffer& buffer) {
90     if (!buffer.validate(buffer.allowSkSL())) {
91         return nullptr;
92     }
93 
94     sk_sp<SkRuntimeEffect> effect;
95     if (!buffer.isVersionLT(SkPicturePriv::kSerializeStableKeys)) {
96         uint32_t candidateStableKey = buffer.readUInt();
97         effect = SkKnownRuntimeEffects::MaybeGetKnownRuntimeEffect(candidateStableKey);
98         if (!effect && !buffer.validate(candidateStableKey == 0)) {
99             return nullptr;
100         }
101     }
102 
103     if (!effect) {
104         SkString sksl;
105         buffer.readString(&sksl);
106         effect = SkMakeCachedRuntimeEffect(SkRuntimeEffect::MakeForColorFilter, std::move(sksl));
107     }
108     if constexpr (!kLenientSkSLDeserialization) {
109         if (!buffer.validate(effect != nullptr)) {
110             return nullptr;
111         }
112     }
113 
114     sk_sp<SkData> uniforms = buffer.readByteArrayAsData();
115 
116     skia_private::STArray<4, SkRuntimeEffect::ChildPtr> children;
117     if (!SkRuntimeEffectPriv::ReadChildEffects(buffer, effect.get(), &children)) {
118         return nullptr;
119     }
120 
121     if constexpr (kLenientSkSLDeserialization) {
122         if (!effect) {
123             SkDebugf("Serialized SkSL failed to compile. Ignoring/dropping SkSL color filter.\n");
124             return nullptr;
125         }
126     }
127 
128     return effect->makeColorFilter(std::move(uniforms), SkSpan(children));
129 }
130 
131 /////////////////////////////////////////////////////////////////////////////////////////////////
132 
Lerp(float weight,sk_sp<SkColorFilter> cf0,sk_sp<SkColorFilter> cf1)133 sk_sp<SkColorFilter> SkColorFilters::Lerp(float weight, sk_sp<SkColorFilter> cf0,
134                                                         sk_sp<SkColorFilter> cf1) {
135     using namespace SkKnownRuntimeEffects;
136 
137     if (!cf0 && !cf1) {
138         return nullptr;
139     }
140     if (SkIsNaN(weight)) {
141         return nullptr;
142     }
143 
144     if (cf0 == cf1) {
145         return cf0; // or cf1
146     }
147 
148     if (weight <= 0) {
149         return cf0;
150     }
151     if (weight >= 1) {
152         return cf1;
153     }
154 
155     const SkRuntimeEffect* lerpEffect = GetKnownRuntimeEffect(StableKey::kLerp);
156 
157     sk_sp<SkColorFilter> inputs[] = {cf0,cf1};
158     return lerpEffect->makeColorFilter(SkData::MakeWithCopy(&weight, sizeof(weight)),
159                                        inputs, std::size(inputs));
160 }
161 
Make()162 sk_sp<SkColorFilter> SkLumaColorFilter::Make() {
163     using namespace SkKnownRuntimeEffects;
164 
165     const SkRuntimeEffect* lumaEffect = GetKnownRuntimeEffect(StableKey::kLuma);
166 
167     return lumaEffect->makeColorFilter(SkData::MakeEmpty());
168 }
169 
MakeWithSkColors(const SkColor colors[kNumColors])170 sk_sp<SkColorFilter> SkOverdrawColorFilter::MakeWithSkColors(const SkColor colors[kNumColors]) {
171     using namespace SkKnownRuntimeEffects;
172 
173     const SkRuntimeEffect* overdrawEffect = GetKnownRuntimeEffect(StableKey::kOverdraw);
174 
175     auto data = SkData::MakeUninitialized(kNumColors * sizeof(SkPMColor4f));
176     SkPMColor4f* premul = (SkPMColor4f*)data->writable_data();
177     for (int i = 0; i < kNumColors; ++i) {
178         premul[i] = SkColor4f::FromColor(colors[i]).premul();
179     }
180     return overdrawEffect->makeColorFilter(std::move(data));
181 }
182