Flutter Engine
The Flutter Engine
PrecompileColorFilter.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2024 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
9
21
22namespace skgpu::graphite {
23
24//--------------------------------------------------------------------------------------------------
26
28 sk_sp<PrecompileColorFilter> inner) const {
29 if (!inner) {
30 return sk_ref_sp(this);
31 }
32
33 return PrecompileColorFilters::Compose({ sk_ref_sp(this) }, { std::move(inner) });
34}
35
36//--------------------------------------------------------------------------------------------------
37//--------------------------------------------------------------------------------------------------
38namespace {
39
40// If all the options are null the span is considered empty
42 if (options.empty()) {
43 return true;
44 }
45
46 for (const auto& o : options) {
47 if (o) {
48 return false;
49 }
50 }
51
52 return true;
53}
54
55} // anonymous namespace
56
57//--------------------------------------------------------------------------------------------------
59public:
61 SkSpan<const sk_sp<PrecompileColorFilter>> innerOptions)
62 : fOuterOptions(outerOptions.begin(), outerOptions.end())
63 , fInnerOptions(innerOptions.begin(), innerOptions.end()) {
64
65 fNumOuterCombos = 0;
66 for (const auto& outerOption : fOuterOptions) {
67 fNumOuterCombos += outerOption ? outerOption->priv().numCombinations() : 1;
68 }
69
70 fNumInnerCombos = 0;
71 for (const auto& innerOption : fInnerOptions) {
72 fNumInnerCombos += innerOption ? innerOption->priv().numCombinations() : 1;
73 }
74 }
75
76private:
77 int numChildCombinations() const override { return fNumOuterCombos * fNumInnerCombos; }
78
79 void addToKey(const KeyContext& keyContext,
80 PaintParamsKeyBuilder* builder,
81 PipelineDataGatherer* gatherer,
82 int desiredCombination) const override {
83 SkASSERT(desiredCombination < this->numCombinations());
84
85 const int desiredOuterCombination = desiredCombination % fNumOuterCombos;
86 int remainingCombinations = desiredCombination / fNumOuterCombos;
87
88 const int desiredInnerCombination = remainingCombinations % fNumInnerCombos;
89 remainingCombinations /= fNumInnerCombos;
90
91 SkASSERT(!remainingCombinations);
92
94 int innerChildOptions, outerChildOptions;
95
96 std::tie(outer, outerChildOptions) = SelectOption<PrecompileColorFilter>(
97 fOuterOptions, desiredOuterCombination);
98 std::tie(inner, innerChildOptions) = SelectOption<PrecompileColorFilter>(
99 fInnerOptions, desiredInnerCombination);
100
101 if (!inner && !outer) {
102 // A "passthrough" color filter returns the input color as-is.
104 } else if (!inner) {
105 outer->priv().addToKey(keyContext, builder, gatherer, outerChildOptions);
106 } else if (!outer) {
107 inner->priv().addToKey(keyContext, builder, gatherer, innerChildOptions);
108 } else {
109 Compose(keyContext, builder, gatherer,
110 /* addInnerToKey= */ [&]() -> void {
111 inner->priv().addToKey(keyContext, builder, gatherer, innerChildOptions);
112 },
113 /* addOuterToKey= */ [&]() -> void {
114 outer->priv().addToKey(keyContext, builder, gatherer, outerChildOptions);
115 });
116 }
117 }
118
119 std::vector<sk_sp<PrecompileColorFilter>> fOuterOptions;
120 std::vector<sk_sp<PrecompileColorFilter>> fInnerOptions;
121
122 int fNumOuterCombos;
123 int fNumInnerCombos;
124};
125
127 SkSpan<const sk_sp<PrecompileColorFilter>> outerOptions,
128 SkSpan<const sk_sp<PrecompileColorFilter>> innerOptions) {
129 if (is_empty(outerOptions) && is_empty(innerOptions)) {
130 return nullptr;
131 }
132
133 return sk_make_sp<PrecompileComposeColorFilter>(outerOptions, innerOptions);
134}
135
136//--------------------------------------------------------------------------------------------------
138public:
140
141private:
142 void addToKey(const KeyContext& keyContext,
144 PipelineDataGatherer* gatherer,
145 int desiredCombination) const override {
146 SkASSERT(desiredCombination == 0);
147
148 // Here, kSrcOver and the white color are just a stand-ins for some later blend mode
149 // and color.
150 AddBlendModeColorFilter(keyContext, builder, gatherer,
152 }
153};
154
156 return sk_make_sp<PrecompileBlendModeColorFilter>();
157}
158
159//--------------------------------------------------------------------------------------------------
161 void addToKey(const KeyContext& keyContext,
163 PipelineDataGatherer* gatherer,
164 int desiredCombination) const override {
165 SkASSERT(desiredCombination == 0);
166
167 static constexpr float kIdentity[20] = { 1, 0, 0, 0, 0,
168 0, 1, 0, 0, 0,
169 0, 0, 1, 0, 0,
170 0, 0, 0, 1, 0 };
171
172 MatrixColorFilterBlock::MatrixColorFilterData matrixCFData(kIdentity, /* inHSLA= */ false);
173
174 MatrixColorFilterBlock::AddBlock(keyContext, builder, gatherer, matrixCFData);
175 }
176};
177
179 return sk_make_sp<PrecompileMatrixColorFilter>();
180}
181
183 return sk_make_sp<PrecompileMatrixColorFilter>();
184}
185
186//--------------------------------------------------------------------------------------------------
188 void addToKey(const KeyContext& keyContext,
190 PipelineDataGatherer* gatherer,
191 int desiredCombination) const override {
192 SkASSERT(desiredCombination == 0);
193
194 constexpr SkAlphaType kAlphaType = kPremul_SkAlphaType;
196 sk_srgb_singleton(), kAlphaType);
197
198 ColorSpaceTransformBlock::AddBlock(keyContext, builder, gatherer, csData);
199 }
200};
201
203 return sk_make_sp<PrecompileColorSpaceXformColorFilter>();
204}
205
207 return sk_make_sp<PrecompileColorSpaceXformColorFilter>();
208}
209
211 return sk_make_sp<PrecompileColorSpaceXformColorFilter>();
212}
213
214//--------------------------------------------------------------------------------------------------
216 SkSpan<const sk_sp<PrecompileColorFilter>> dstOptions,
217 SkSpan<const sk_sp<PrecompileColorFilter>> srcOptions) {
218
219 if (dstOptions.empty() && srcOptions.empty()) {
220 return nullptr;
221 }
222
223 const SkRuntimeEffect* lerpEffect =
224 GetKnownRuntimeEffect(SkKnownRuntimeEffects::StableKey::kLerp);
225
226 // Since the RuntimeEffect Precompile objects behave differently we have to manually create
227 // all the combinations here (b/332690425).
229 combos.reserve(dstOptions.size() * srcOptions.size());
230 for (const sk_sp<PrecompileColorFilter>& d : dstOptions) {
231 for (const sk_sp<PrecompileColorFilter>& s : srcOptions) {
232 combos.push_back({ d, s });
233 }
234 }
236 comboSpans.reserve(combos.size());
237 for (const std::array<const PrecompileChildPtr, 2>& combo : combos) {
238 comboSpans.push_back({ combo });
239 }
240
241 return MakePrecompileColorFilter(sk_ref_sp(lerpEffect), comboSpans);
242}
243
244//--------------------------------------------------------------------------------------------------
246 void addToKey(const KeyContext& keyContext,
248 PipelineDataGatherer* gatherer,
249 int desiredCombination) const override {
250 SkASSERT(desiredCombination == 0);
251
253
254 TableColorFilterBlock::AddBlock(keyContext, builder, gatherer, data);
255 }
256};
257
259 return sk_make_sp<PrecompileTableColorFilter>();
260}
261
262//--------------------------------------------------------------------------------------------------
265}
266
267//--------------------------------------------------------------------------------------------------
269 const SkRuntimeEffect* highContrastEffect =
271
273 if (!cf) {
274 return nullptr;
275 }
276 return PrecompileColorFiltersPriv::WithWorkingFormat({ std::move(cf) });
277}
278
279//--------------------------------------------------------------------------------------------------
281 const SkRuntimeEffect* lumaEffect =
282 GetKnownRuntimeEffect(SkKnownRuntimeEffects::StableKey::kLuma);
283
284 return MakePrecompileColorFilter(sk_ref_sp(lumaEffect));
285}
286
287//--------------------------------------------------------------------------------------------------
289 const SkRuntimeEffect* overdrawEffect =
290 GetKnownRuntimeEffect(SkKnownRuntimeEffects::StableKey::kOverdraw);
291
292 return MakePrecompileColorFilter(sk_ref_sp(overdrawEffect));
293}
294
295//--------------------------------------------------------------------------------------------------
297 void addToKey(const KeyContext& keyContext,
299 PipelineDataGatherer* gatherer,
300 int desiredCombination) const override {
301 SkASSERT(desiredCombination == 0);
302
304 }
305};
306
308 return sk_make_sp<PrecompileGaussianColorFilter>();
309}
310
311//--------------------------------------------------------------------------------------------------
313public:
315 : fChildOptions(childOptions.begin(), childOptions.end()) {
316
317 fNumChildCombos = 0;
318 for (const auto& childOption : fChildOptions) {
319 fNumChildCombos += childOption->priv().numCombinations();
320 }
321 }
322
323private:
324 int numChildCombinations() const override { return fNumChildCombos; }
325
326 void addToKey(const KeyContext& keyContext,
327 PaintParamsKeyBuilder* builder,
328 PipelineDataGatherer* gatherer,
329 int desiredCombination) const override {
330 SkASSERT(desiredCombination < fNumChildCombos);
331
332 constexpr SkAlphaType kAlphaType = kPremul_SkAlphaType;
333 ColorSpaceTransformBlock::ColorSpaceTransformData csData(sk_srgb_singleton(), kAlphaType,
334 sk_srgb_singleton(), kAlphaType);
335
336 // Use two nested compose blocks to chain (dst->working), child, and (working->dst) together
337 // while appearing as one block to the parent node.
338 Compose(keyContext, builder, gatherer,
339 /* addInnerToKey= */ [&]() -> void {
340 // Inner compose
341 Compose(keyContext, builder, gatherer,
342 /* addInnerToKey= */ [&]() -> void {
343 // Innermost (inner of inner compose)
344 ColorSpaceTransformBlock::AddBlock(keyContext, builder, gatherer,
345 csData);
346 },
347 /* addOuterToKey= */ [&]() -> void {
348 // Middle (outer of inner compose)
349 AddToKey<PrecompileColorFilter>(keyContext, builder, gatherer,
350 fChildOptions, desiredCombination);
351 });
352 },
353 /* addOuterToKey= */ [&]() -> void {
354 // Outermost (outer of outer compose)
355 ColorSpaceTransformBlock::AddBlock(keyContext, builder, gatherer, csData);
356 });
357 }
358
359 std::vector<sk_sp<PrecompileColorFilter>> fChildOptions;
360
361 int fNumChildCombos;
362};
363
365 SkSpan<const sk_sp<PrecompileColorFilter>> childOptions) {
366 return sk_make_sp<PrecompileWithWorkingFormatColorFilter>(childOptions);
367}
368
369} // namespace skgpu::graphite
const char * options
static void is_empty(skiatest::Reporter *reporter, const SkPath &p)
SkAlphaType
Definition: SkAlphaType.h:26
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition: SkAlphaType.h:29
#define SkASSERT(cond)
Definition: SkAssert.h:116
@ kSrcOver
r = s + (1-sa)*d
constexpr SkPMColor4f SK_PMColor4fWHITE
Definition: SkColorData.h:380
SkColorSpace * sk_srgb_singleton()
sk_sp< T > sk_ref_sp(T *obj)
Definition: SkRefCnt.h:381
sk_sp< PrecompileColorFilter > makeComposed(sk_sp< PrecompileColorFilter > inner) const
PrecompileComposeColorFilter(SkSpan< const sk_sp< PrecompileColorFilter > > outerOptions, SkSpan< const sk_sp< PrecompileColorFilter > > innerOptions)
PrecompileWithWorkingFormatColorFilter(SkSpan< const sk_sp< PrecompileColorFilter > > childOptions)
void reserve(int n)
Definition: SkTArray.h:170
int size() const
Definition: SkTArray.h:421
static const char * begin(const StringSlice &s)
Definition: editor.cpp:252
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition: main.cc:19
struct MyStruct s
glong glong end
static const FlSetting kHighContrast
const SkRuntimeEffect * GetKnownRuntimeEffect(StableKey stableKey)
sk_sp< PrecompileColorFilter > WithWorkingFormat(SkSpan< const sk_sp< PrecompileColorFilter > > childOptions)
sk_sp< PrecompileColorFilter > ColorSpaceXform()
SK_API sk_sp< PrecompileColorFilter > HSLAMatrix()
SK_API sk_sp< PrecompileColorFilter > Blend()
SK_API sk_sp< PrecompileColorFilter > Matrix()
SK_API sk_sp< PrecompileColorFilter > Overdraw()
SK_API sk_sp< PrecompileColorFilter > Lighting()
SK_API sk_sp< PrecompileColorFilter > Luma()
SK_API sk_sp< PrecompileColorFilter > Compose(SkSpan< const sk_sp< PrecompileColorFilter > > outer, SkSpan< const sk_sp< PrecompileColorFilter > > inner)
SK_API sk_sp< PrecompileColorFilter > HighContrast()
SK_API sk_sp< PrecompileColorFilter > SRGBToLinearGamma()
SK_API sk_sp< PrecompileColorFilter > LinearToSRGBGamma()
SK_API sk_sp< PrecompileColorFilter > Table()
SK_API sk_sp< PrecompileColorFilter > Lerp(SkSpan< const sk_sp< PrecompileColorFilter > > dstOptions, SkSpan< const sk_sp< PrecompileColorFilter > > srcOptions)
void AddBlendModeColorFilter(const KeyContext &keyContext, PaintParamsKeyBuilder *builder, PipelineDataGatherer *gatherer, SkBlendMode bm, const SkPMColor4f &srcColor)
void Compose(const KeyContext &keyContext, PaintParamsKeyBuilder *keyBuilder, PipelineDataGatherer *gatherer, AddToKeyFn addInnerToKey, AddToKeyFn addOuterToKey)
sk_sp< PrecompileColorFilter > MakePrecompileColorFilter(sk_sp< SkRuntimeEffect > effect, SkSpan< const PrecompileChildOptions > childOptions)
static void AddBlock(const KeyContext &, PaintParamsKeyBuilder *, PipelineDataGatherer *, const ColorSpaceTransformData &)
static void AddBlock(const KeyContext &, PaintParamsKeyBuilder *, PipelineDataGatherer *, const MatrixColorFilterData &)
Definition: KeyHelpers.cpp:992
static void AddBlock(const KeyContext &, PaintParamsKeyBuilder *, PipelineDataGatherer *, const TableColorFilterData &)
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63