Flutter Engine
The Flutter Engine
FactoryFunctions.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2022 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
28
29namespace skgpu::graphite {
30
31namespace {
32
33#ifdef SK_DEBUG
34
35bool precompilebase_is_valid_as_child(const PrecompileBase *child) {
36 if (!child) {
37 return true;
38 }
39
40 switch (child->type()) {
44 return true;
45 default:
46 return false;
47 }
48}
49
50#endif // SK_DEBUG
51
52} // anonymous namespace
53
54//--------------------------------------------------------------------------------------------------
56public:
58
59private:
60 // non-cubic and cubic sampling
61 inline static constexpr int kNumIntrinsicCombinations = 2;
62
63 int numIntrinsicCombinations() const override { return kNumIntrinsicCombinations; }
64
65 void addToKey(const KeyContext& keyContext,
66 PaintParamsKeyBuilder* builder,
67 PipelineDataGatherer* gatherer,
68 int desiredCombination) const override {
69 SkASSERT(desiredCombination < kNumIntrinsicCombinations);
70
71 static constexpr SkSamplingOptions kDefaultCubicSampling(SkCubicResampler::Mitchell());
72 static constexpr SkSamplingOptions kDefaultSampling;
73
74 YUVImageShaderBlock::ImageData imgData(desiredCombination == 1 ? kDefaultCubicSampling
75 : kDefaultSampling,
78
79 YUVImageShaderBlock::AddBlock(keyContext, builder, gatherer, imgData);
80 }
81};
82
84 return sk_make_sp<PrecompileYUVImageShader>();
85}
86
87//--------------------------------------------------------------------------------------------------
88sk_sp<PrecompileColorFilter> PrecompileImageFilter::asAColorFilter() const {
90 if (!tmp) {
91 return nullptr;
92 }
93 SkASSERT(this->countInputs() == 1);
94 if (this->getInput(0)) {
95 return nullptr;
96 }
97 // TODO: as in SkImageFilter::asAColorFilter, handle the special case of
98 // affectsTransparentBlack. This is tricky for precompilation since we don't,
99 // necessarily, have all the parameters of the ColorFilter in order to evaluate
100 // filterColor4f(SkColors::kTransparent) - the normal API's implementation.
101 return tmp;
102}
103
104//--------------------------------------------------------------------------------------------------
106public:
110 , fBlender(std::move(blender)) {
111 }
112
113private:
114 void onCreatePipelines(
115 const KeyContext& keyContext,
116 PipelineDataGatherer* gatherer,
117 const PaintOptionsPriv::ProcessCombination& processCombination) const override {
118
119 PaintOptions paintOptions;
120
124
126 SkSpan<const sk_sp<PrecompileBlender>>(&fBlender, 1),
127 { imageShader },
128 { imageShader });
129
130 paintOptions.setShaders({ std::move(blendShader) });
131
132 paintOptions.priv().buildCombinations(keyContext,
133 gatherer,
135 /* withPrimitiveBlender= */ false,
137 processCombination);
138 }
139
141};
142
145 sk_sp<PrecompileImageFilter> foreground) {
146 return Blend(PrecompileBlenders::Arithmetic(), std::move(background), std::move(foreground));
147}
148
150 SkBlendMode bm,
152 sk_sp<PrecompileImageFilter> foreground) {
153 return Blend(PrecompileBlenders::Mode(bm), std::move(background), std::move(foreground));
154}
155
159 sk_sp<PrecompileImageFilter> foreground) {
160
161 if (!blender) {
163 }
164
165 if (std::optional<SkBlendMode> bm = blender->priv().asBlendMode()) {
166 if (bm == SkBlendMode::kSrc) {
167 return foreground;
168 } else if (bm == SkBlendMode::kDst) {
169 return background;
170 } else if (bm == SkBlendMode::kClear) {
171 return nullptr; // TODO: actually return PrecompileImageFilters::Empty
172 }
173 }
174
175 sk_sp<PrecompileImageFilter> inputs[2] = { std::move(background), std::move(foreground) };
176 return sk_make_sp<PrecompileBlendFilterImageFilter>(std::move(blender), inputs);
177}
178
179namespace {
180
181void create_blur_imagefilter_pipelines(
182 const KeyContext& keyContext,
183 PipelineDataGatherer* gatherer,
184 const PaintOptionsPriv::ProcessCombination& processCombination) {
185
186 PaintOptions blurPaintOptions;
187
188 // For blur imagefilters we know we don't have alpha-only textures and don't need cubic
189 // filtering.
192
193 static const SkBlendMode kBlurBlendModes[] = { SkBlendMode::kSrc };
194 blurPaintOptions.setShaders({ PrecompileShadersPriv::Blur(imageShader) });
195 blurPaintOptions.setBlendModes(kBlurBlendModes);
196
197 blurPaintOptions.priv().buildCombinations(keyContext,
198 gatherer,
200 /* withPrimitiveBlender= */ false,
202 processCombination);
203}
204
205} // anonymous namespace
206
208public:
211 }
212
213private:
214 void onCreatePipelines(
215 const KeyContext& keyContext,
216 PipelineDataGatherer* gatherer,
217 const PaintOptionsPriv::ProcessCombination& processCombination) const override {
218
219 create_blur_imagefilter_pipelines(keyContext, gatherer, processCombination);
220 }
221};
222
225 return sk_make_sp<PrecompileBlurImageFilter>(SkSpan(&input, 1));
226}
227
228//--------------------------------------------------------------------------------------------------
230public:
233 : PrecompileImageFilter(SkSpan(&input, 1))
234 , fColorFilter(std::move(colorFilter)) {
235 }
236
237private:
238 sk_sp<PrecompileColorFilter> isColorFilterNode() const override {
239 return fColorFilter;
240 }
241
242 void onCreatePipelines(
243 const KeyContext& keyContext,
244 PipelineDataGatherer* gatherer,
245 const PaintOptionsPriv::ProcessCombination& processCombination) const override {
246 PaintOptions paintOptions;
247
251
252 static const SkBlendMode kBlendModes[] = { SkBlendMode::kDstOut };
253 paintOptions.setShaders({ std::move(imageShader) });
254 paintOptions.setColorFilters({ fColorFilter });
255 paintOptions.setBlendModes(kBlendModes);
256
257 paintOptions.priv().buildCombinations(keyContext,
258 gatherer,
260 /* withPrimitiveBlender= */ false,
262 processCombination);
263 }
264
265 sk_sp<PrecompileColorFilter> fColorFilter;
266};
267
271 if (colorFilter && input) {
272 sk_sp<PrecompileColorFilter> inputCF = input->isColorFilterNode();
273 if (inputCF) {
274 colorFilter = colorFilter->makeComposed(std::move(inputCF));
275 input = sk_ref_sp(input->getInput(0));
276 }
277 }
278
279 sk_sp<PrecompileImageFilter> filter = std::move(input);
280 if (colorFilter) {
281 filter = sk_make_sp<PrecompileColorFilterImageFilter>(std::move(colorFilter),
282 std::move(filter));
283 }
284 return filter;
285}
286
287//--------------------------------------------------------------------------------------------------
289public:
292 }
293
294private:
295 void onCreatePipelines(
296 const KeyContext& keyContext,
297 PipelineDataGatherer* gatherer,
298 const PaintOptionsPriv::ProcessCombination& processCombination) const override {
299
300 PaintOptions displacement;
301
302 // For displacement imagefilters we know we don't have alpha-only textures and don't need
303 // cubic filtering.
307
308 displacement.setShaders({ PrecompileShadersPriv::Displacement(imageShader, imageShader) });
309
310 displacement.priv().buildCombinations(keyContext,
311 gatherer,
313 /* withPrimitiveBlender= */ false,
315 processCombination);
316 }
317};
318
321 return sk_make_sp<PrecompileDisplacementMapImageFilter>(SkSpan(&input, 1));
322}
323
324//--------------------------------------------------------------------------------------------------
326public:
329 }
330
331private:
332 void onCreatePipelines(
333 const KeyContext& keyContext,
334 PipelineDataGatherer* gatherer,
335 const PaintOptionsPriv::ProcessCombination& processCombination) const override {
336
340
341 PaintOptions lighting;
342 lighting.setShaders({ PrecompileShadersPriv::Lighting(std::move(imageShader)) });
343
344 lighting.priv().buildCombinations(keyContext,
345 gatherer,
347 /* withPrimitiveBlender= */ false,
349 processCombination);
350 }
351};
352
355 return sk_make_sp<PrecompileLightingImageFilter>(SkSpan(&input, 1));
356}
357
358//--------------------------------------------------------------------------------------------------
360public:
363 }
364
365private:
366 void onCreatePipelines(
367 const KeyContext& keyContext,
368 PipelineDataGatherer* gatherer,
369 const PaintOptionsPriv::ProcessCombination& processCombination) const override {
370
371 PaintOptions matrixConv;
372
373 // For matrix convolution imagefilters we know we don't have alpha-only textures and don't
374 // need cubic filtering.
378
379 matrixConv.setShaders({ PrecompileShadersPriv::MatrixConvolution(imageShader) });
380
381 matrixConv.priv().buildCombinations(keyContext,
382 gatherer,
384 /* withPrimitiveBlender= */ false,
386 processCombination);
387 }
388};
389
392 return sk_make_sp<PrecompileMatrixConvolutionImageFilter>(SkSpan(&input, 1));
393}
394
395//--------------------------------------------------------------------------------------------------
397public:
400 }
401
402private:
403 void onCreatePipelines(
404 const KeyContext& keyContext,
405 PipelineDataGatherer* gatherer,
406 const PaintOptionsPriv::ProcessCombination& processCombination) const override {
407
408 // For morphology imagefilters we know we don't have alpha-only textures and don't need
409 // cubic filtering.
412
413 {
414 PaintOptions sparse;
415
416 static const SkBlendMode kBlendModes[] = { SkBlendMode::kSrc };
418 sparse.setBlendModes(kBlendModes);
419
420 sparse.priv().buildCombinations(keyContext,
421 gatherer,
423 /* withPrimitiveBlender= */ false,
425 processCombination);
426 }
427
428 {
430
431 static const SkBlendMode kBlendModes[] = { SkBlendMode::kSrcOver };
432 linear.setShaders({ PrecompileShadersPriv::LinearMorphology(std::move(imageShader)) });
433 linear.setBlendModes(kBlendModes);
434
435 linear.priv().buildCombinations(keyContext,
436 gatherer,
438 /* withPrimitiveBlender= */ false,
440 processCombination);
441 }
442 }
443};
444
447 return sk_make_sp<PrecompileMorphologyImageFilter>(SkSpan(&input, 1));
448}
449
450//--------------------------------------------------------------------------------------------------
451// TODO(b/342413572): the analytic blurmasks are triggered off of the simple DrawType thus
452// over-generate when a simple draw doesn't have a blur mask.
454public:
456
457private:
458 void createPipelines(
459 const KeyContext& keyContext,
460 PipelineDataGatherer* gatherer,
461 const PaintOptionsPriv::ProcessCombination& processCombination) const override {
462 create_blur_imagefilter_pipelines(keyContext, gatherer, processCombination);
463 }
464};
465
467 return sk_make_sp<PrecompileBlurMaskFilter>();
468}
469
470//--------------------------------------------------------------------------------------------------
471
472//--------------------------------------------------------------------------------------------------
473//--------------------------------------------------------------------------------------------------
476 : fChild(std::move(cf)) {
477}
479
481 : fChild(std::move(child)) {
482 SkASSERT(precompilebase_is_valid_as_child(fChild.get()));
483}
484
485std::optional<SkRuntimeEffect::ChildType> PrecompileChildPtr::type() const {
486 if (fChild) {
487 switch (fChild->type()) {
494 default:
495 break;
496 }
497 }
498 return std::nullopt;
499}
500
502 return (fChild && fChild->type() == PrecompileBase::Type::kShader)
503 ? static_cast<PrecompileShader*>(fChild.get())
504 : nullptr;
505}
506
508 return (fChild && fChild->type() == PrecompileBase::Type::kColorFilter)
509 ? static_cast<PrecompileColorFilter*>(fChild.get())
510 : nullptr;
511}
512
514 return (fChild && fChild->type() == PrecompileBase::Type::kBlender)
515 ? static_cast<PrecompileBlender*>(fChild.get())
516 : nullptr;
517}
518
519//--------------------------------------------------------------------------------------------------
520namespace {
521
522int num_options_in_set(const std::vector<PrecompileChildPtr>& optionSet) {
523 int numOptions = 1;
524 for (const PrecompileChildPtr& childOption : optionSet) {
525 // A missing child will fall back to a passthrough object
526 if (childOption.base()) {
527 numOptions *= childOption.base()->priv().numCombinations();
528 }
529 }
530
531 return numOptions;
532}
533
534// This is the precompile correlate to KeyHelper.cpp's add_children_to_key
535void add_children_to_key(const KeyContext& keyContext,
536 PaintParamsKeyBuilder* builder,
537 PipelineDataGatherer* gatherer,
538 int desiredCombination,
539 const std::vector<PrecompileChildPtr>& optionSet,
542
543 SkASSERT(optionSet.size() == childInfo.size());
544
545 KeyContextWithScope childContext(keyContext, KeyContext::Scope::kRuntimeEffect);
546
547 int remainingCombinations = desiredCombination;
548
549 for (size_t index = 0; index < optionSet.size(); ++index) {
550 const PrecompileChildPtr& childOption = optionSet[index];
551
552 const int numChildCombos = childOption.base() ? childOption.base()->priv().numCombinations()
553 : 1;
554 const int curCombo = remainingCombinations % numChildCombos;
555 remainingCombinations /= numChildCombos;
556
557 std::optional<ChildType> type = childOption.type();
558 if (type == ChildType::kShader) {
559 childOption.shader()->priv().addToKey(childContext, builder, gatherer, curCombo);
560 } else if (type == ChildType::kColorFilter) {
561 childOption.colorFilter()->priv().addToKey(childContext, builder, gatherer, curCombo);
562 } else if (type == ChildType::kBlender) {
563 childOption.blender()->priv().addToKey(childContext, builder, gatherer, curCombo);
564 } else {
565 SkASSERT(curCombo == 0);
566
567 // We don't have a child effect. Substitute in a no-op effect.
568 switch (childInfo[index].type) {
570 // A missing shader returns transparent black
571 SolidColorShaderBlock::AddBlock(childContext, builder, gatherer,
573 break;
574
576 // A "passthrough" shader returns the input color as-is.
578 break;
579
581 // A "passthrough" blender performs `blend_src_over(src, dest)`.
582 AddKnownModeBlend(childContext, builder, gatherer, SkBlendMode::kSrcOver);
583 break;
584 }
585 }
586 }
587}
588
589} // anonymous namespace
590
591template<typename T>
592class PrecompileRTEffect : public T {
593public:
596 : fEffect(std::move(effect)) {
597 fChildOptions.reserve(childOptions.size());
598 for (PrecompileChildOptions c : childOptions) {
599 fChildOptions.push_back({ c.begin(), c.end() });
600 }
601 }
602
603private:
604 int numChildCombinations() const override {
605 int numOptions = 0;
606 for (const std::vector<PrecompileChildPtr>& optionSet : fChildOptions) {
607 numOptions += num_options_in_set(optionSet);
608 }
609
610 return numOptions ? numOptions : 1;
611 }
612
613 void addToKey(const KeyContext& keyContext,
614 PaintParamsKeyBuilder* builder,
615 PipelineDataGatherer* gatherer,
616 int desiredCombination) const override {
617
618 SkASSERT(desiredCombination < this->numCombinations());
619
620 SkSpan<const SkRuntimeEffect::Child> childInfo = fEffect->children();
621
622 RuntimeEffectBlock::BeginBlock(keyContext, builder, gatherer, { fEffect });
623
624 for (const std::vector<PrecompileChildPtr>& optionSet : fChildOptions) {
625 int numOptionsInSet = num_options_in_set(optionSet);
626
627 if (desiredCombination < numOptionsInSet) {
628 add_children_to_key(keyContext, builder, gatherer, desiredCombination, optionSet,
629 childInfo);
630 break;
631 }
632
633 desiredCombination -= numOptionsInSet;
634 }
635
636 builder->endBlock();
637 }
638
640 std::vector<std::vector<PrecompileChildPtr>> fChildOptions;
641};
642
646 // TODO: check that 'effect' has the kAllowShader_Flag bit set and:
647 // for each entry in childOptions:
648 // all the SkPrecompileChildPtrs have the same type as the corresponding child in the effect
649 return sk_make_sp<PrecompileRTEffect<PrecompileShader>>(std::move(effect), childOptions);
650}
651
655 // TODO: check that 'effect' has the kAllowColorFilter_Flag bit set and:
656 // for each entry in childOptions:
657 // all the SkPrecompileChildPtrs have the same type as the corresponding child in the effect
658 return sk_make_sp<PrecompileRTEffect<PrecompileColorFilter>>(std::move(effect), childOptions);
659}
660
664 // TODO: check that 'effect' has the kAllowBlender_Flag bit set and:
665 // for each entry in childOptions:
666 // all the SkPrecompileChildPtrs have the same type as the corresponding child in the effect
667 return sk_make_sp<PrecompileRTEffect<PrecompileBlender>>(std::move(effect), childOptions);
668}
669
670} // namespace skgpu::graphite
671
672//--------------------------------------------------------------------------------------------------
#define SkASSERT(cond)
Definition: SkAssert.h:116
SkBlendMode
Definition: SkBlendMode.h:38
@ kSrcOver
r = s + (1-sa)*d
@ kDstOut
r = d * (1-sa)
@ kClear
r = 0
constexpr SkPMColor4f SK_PMColor4fTRANSPARENT
Definition: SkColorData.h:378
sk_sp< T > sk_ref_sp(T *obj)
Definition: SkRefCnt.h:381
SkSpan(Container &&) -> SkSpan< std::remove_pointer_t< decltype(std::data(std::declval< Container >()))> >
GLenum type
SkSpan< const Child > children() const
constexpr size_t size() const
Definition: SkSpan_impl.h:95
PaintOptions::ProcessCombination ProcessCombination
void buildCombinations(const KeyContext &keyContext, PipelineDataGatherer *gatherer, DrawTypeFlags drawTypes, bool withPrimitiveBlender, Coverage coverage, const ProcessCombination &processCombination) const
void setBlendModes(SkSpan< const SkBlendMode > blendModes)
void setShaders(SkSpan< const sk_sp< PrecompileShader > > shaders)
PrecompileBlendFilterImageFilter(sk_sp< PrecompileBlender > blender, SkSpan< sk_sp< PrecompileImageFilter > > inputs)
PrecompileBlurImageFilter(SkSpan< sk_sp< PrecompileImageFilter > > inputs)
PrecompileShader * shader() const
PrecompileBlender * blender() const
std::optional< SkRuntimeEffect::ChildType > type() const
PrecompileColorFilter * colorFilter() const
PrecompileColorFilterImageFilter(sk_sp< PrecompileColorFilter > colorFilter, sk_sp< PrecompileImageFilter > input)
PrecompileDisplacementMapImageFilter(SkSpan< sk_sp< PrecompileImageFilter > > inputs)
virtual sk_sp< PrecompileColorFilter > isColorFilterNode() const
const PrecompileImageFilter * getInput(int index) const
PrecompileLightingImageFilter(SkSpan< sk_sp< PrecompileImageFilter > > inputs)
PrecompileMatrixConvolutionImageFilter(SkSpan< sk_sp< PrecompileImageFilter > > inputs)
PrecompileMorphologyImageFilter(SkSpan< sk_sp< PrecompileImageFilter > > inputs)
PrecompileRTEffect(sk_sp< SkRuntimeEffect > effect, SkSpan< const PrecompileChildOptions > childOptions)
static bool b
struct MyStruct s
SK_API sk_sp< PrecompileBlender > Arithmetic()
SK_API sk_sp< PrecompileBlender > Mode(SkBlendMode)
SK_API sk_sp< PrecompileImageFilter > Blur(sk_sp< PrecompileImageFilter > input)
SK_API sk_sp< PrecompileImageFilter > ColorFilter(sk_sp< PrecompileColorFilter > colorFilter, sk_sp< PrecompileImageFilter > input)
SK_API sk_sp< PrecompileImageFilter > MatrixConvolution(sk_sp< PrecompileImageFilter > input)
SK_API sk_sp< PrecompileImageFilter > DisplacementMap(sk_sp< PrecompileImageFilter > input)
SK_API sk_sp< PrecompileImageFilter > Arithmetic(sk_sp< PrecompileImageFilter > background, sk_sp< PrecompileImageFilter > foreground)
SK_API sk_sp< PrecompileImageFilter > Morphology(sk_sp< PrecompileImageFilter > input)
SK_API sk_sp< PrecompileImageFilter > Lighting(sk_sp< PrecompileImageFilter > input)
SK_API sk_sp< PrecompileImageFilter > Blend(SkBlendMode bm, sk_sp< PrecompileImageFilter > background, sk_sp< PrecompileImageFilter > foreground)
SK_API sk_sp< PrecompileMaskFilter > Blur()
sk_sp< PrecompileShader > Lighting(sk_sp< PrecompileShader > wrapped)
sk_sp< PrecompileShader > Image(SkEnumBitMask< PrecompileImageShaderFlags >)
sk_sp< PrecompileShader > Displacement(sk_sp< PrecompileShader > displacement, sk_sp< PrecompileShader > color)
sk_sp< PrecompileShader > LinearMorphology(sk_sp< PrecompileShader > wrapped)
sk_sp< PrecompileShader > MatrixConvolution(sk_sp< PrecompileShader > wrapped)
sk_sp< PrecompileShader > SparseMorphology(sk_sp< PrecompileShader > wrapped)
sk_sp< PrecompileShader > Blur(sk_sp< PrecompileShader > wrapped)
SK_API sk_sp< PrecompileShader > Blend(SkSpan< const SkBlendMode > blendModes, SkSpan< const sk_sp< PrecompileShader > > dsts, SkSpan< const sk_sp< PrecompileShader > > srcs)
SK_API sk_sp< PrecompileShader > YUVImage()
sk_sp< PrecompileBlender > MakePrecompileBlender(sk_sp< SkRuntimeEffect > effect, SkSpan< const PrecompileChildOptions > childOptions)
sk_sp< PrecompileShader > MakePrecompileShader(sk_sp< SkRuntimeEffect > effect, SkSpan< const PrecompileChildOptions > childOptions)
void AddKnownModeBlend(const KeyContext &keyContext, PaintParamsKeyBuilder *builder, PipelineDataGatherer *gatherer, SkBlendMode bm)
void Blend(const KeyContext &keyContext, PaintParamsKeyBuilder *keyBuilder, PipelineDataGatherer *gatherer, AddToKeyFn addBlendToKey, AddToKeyFn addSrcToKey, AddToKeyFn addDstToKey)
Definition: PaintParams.cpp:95
sk_sp< PrecompileColorFilter > MakePrecompileColorFilter(sk_sp< SkRuntimeEffect > effect, SkSpan< const PrecompileChildOptions > childOptions)
Definition: ref_ptr.h:256
#define T
Definition: precompiler.cc:65
static constexpr SkCubicResampler Mitchell()
static constexpr SkISize MakeEmpty()
Definition: SkSize.h:22
static constexpr SkRect MakeEmpty()
Definition: SkRect.h:595
static void BeginBlock(const KeyContext &, PaintParamsKeyBuilder *, PipelineDataGatherer *, const ShaderData &)
static void AddBlock(const KeyContext &, PaintParamsKeyBuilder *, PipelineDataGatherer *, const SkPMColor4f &)
Definition: KeyHelpers.cpp:102
static void AddBlock(const KeyContext &, PaintParamsKeyBuilder *, PipelineDataGatherer *, const ImageData &)
Definition: KeyHelpers.cpp:804
static sk_sp< SkShader > linear(sk_sp< SkShader > shader)