Flutter Engine
 
Loading...
Searching...
No Matches
layer_state_stack.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
11
12namespace flutter {
13
14// ==============================================================
15// Delegate subclasses
16// ==============================================================
17
18// The DummyDelegate class implements most Delegate methods as NOP
19// but throws errors if the caller starts executing query methods
20// that require an active delegate to be tracking. It is specifically
21// designed to be immutable, lightweight, and a singleton so that it
22// can be substituted into the delegate slot in a LayerStateStack
23// quickly and cheaply when no externally supplied delegates are present.
24class DummyDelegate : public LayerStateStack::Delegate {
25 public:
26 static const std::shared_ptr<DummyDelegate> kInstance;
27
28 void decommission() override {}
29
30 DlRect local_cull_rect() const override {
31 error();
32 return {};
33 }
34 DlRect device_cull_rect() const override {
35 error();
36 return {};
37 }
38 DlMatrix matrix() const override {
39 error();
40 return dummy_matrix_;
41 }
42 bool content_culled(const DlRect& content_bounds) const override {
43 error();
44 return true;
45 }
46
47 void save() override {}
48 void saveLayer(const DlRect& bounds,
49 LayerStateStack::RenderingAttributes& attributes,
50 DlBlendMode blend,
51 const DlImageFilter* backdrop,
52 std::optional<int64_t> backdrop_id) override {}
53 void restore() override {}
54
55 void translate(DlScalar tx, DlScalar ty) override {}
56 void transform(const DlMatrix& matrix) override {}
57 void integralTransform() override {}
58
59 void clipRect(const DlRect& rect, DlClipOp op, bool is_aa) override {}
60 void clipRRect(const DlRoundRect& rrect, DlClipOp op, bool is_aa) override {}
62 DlClipOp op,
63 bool is_aa) override {}
64 void clipPath(const DlPath& path, DlClipOp op, bool is_aa) override {}
65
66 private:
67 static void error() {
68 FML_DCHECK(false) << "LayerStateStack state queried without a delegate";
69 }
70 const DlMatrix dummy_matrix_;
71};
72const std::shared_ptr<DummyDelegate> DummyDelegate::kInstance =
73 std::make_shared<DummyDelegate>();
74
75class DlCanvasDelegate : public LayerStateStack::Delegate {
76 public:
78 : canvas_(canvas), initial_save_level_(canvas->GetSaveCount()) {}
79
80 void decommission() override { canvas_->RestoreToCount(initial_save_level_); }
81
82 DlCanvas* canvas() const override { return canvas_; }
83
84 DlRect local_cull_rect() const override {
85 return canvas_->GetLocalClipCoverage();
86 }
87 DlRect device_cull_rect() const override {
88 return canvas_->GetDestinationClipCoverage();
89 }
90 DlMatrix matrix() const override { return canvas_->GetMatrix(); }
91 bool content_culled(const DlRect& content_bounds) const override {
92 return canvas_->QuickReject(content_bounds);
93 }
94
95 void save() override { canvas_->Save(); }
96 void saveLayer(const DlRect& bounds,
97 LayerStateStack::RenderingAttributes& attributes,
98 DlBlendMode blend_mode,
99 const DlImageFilter* backdrop,
100 std::optional<int64_t> backdrop_id) override {
101 TRACE_EVENT0("flutter", "Canvas::saveLayer");
102 DlPaint paint;
103 canvas_->SaveLayer(bounds, attributes.fill(paint, blend_mode), backdrop,
104 backdrop_id);
105 }
106 void restore() override { canvas_->Restore(); }
107
108 void translate(DlScalar tx, DlScalar ty) override {
109 canvas_->Translate(tx, ty);
110 }
111 void transform(const DlMatrix& matrix) override {
112 canvas_->Transform(matrix);
113 }
114 void integralTransform() override {
115 DlMatrix integral;
117 canvas_->SetTransform(integral);
118 }
119 }
120
121 void clipRect(const DlRect& rect, DlClipOp op, bool is_aa) override {
122 canvas_->ClipRect(rect, op, is_aa);
123 }
124 void clipRRect(const DlRoundRect& rrect, DlClipOp op, bool is_aa) override {
125 canvas_->ClipRoundRect(rrect, op, is_aa);
126 }
128 DlClipOp op,
129 bool is_aa) override {
130 canvas_->ClipRoundSuperellipse(rse, op, is_aa);
131 }
132 void clipPath(const DlPath& path, DlClipOp op, bool is_aa) override {
133 canvas_->ClipPath(path, op, is_aa);
134 }
135
136 private:
137 DlCanvas* canvas_;
138 const int initial_save_level_;
139};
140
141class PrerollDelegate : public LayerStateStack::Delegate {
142 public:
143 PrerollDelegate(const DlRect& cull_rect, const DlMatrix& matrix) {
144 save_stack_.emplace_back(cull_rect, matrix);
145 }
146
147 void decommission() override {}
148
149 DlMatrix matrix() const override { return state().matrix(); }
150 DlRect local_cull_rect() const override {
151 return state().GetLocalCullCoverage();
152 }
153 DlRect device_cull_rect() const override {
154 return state().GetDeviceCullCoverage();
155 }
156 bool content_culled(const DlRect& content_bounds) const override {
157 return state().content_culled(content_bounds);
158 }
159
160 void save() override { save_stack_.emplace_back(state()); }
161 void saveLayer(const DlRect& bounds,
162 LayerStateStack::RenderingAttributes& attributes,
163 DlBlendMode blend,
164 const DlImageFilter* backdrop,
165 std::optional<int64_t> backdrop_id) override {
166 save_stack_.emplace_back(state());
167 }
168 void restore() override { save_stack_.pop_back(); }
169
170 void translate(DlScalar tx, DlScalar ty) override {
171 state().translate(tx, ty);
172 }
173 void transform(const DlMatrix& matrix) override { state().transform(matrix); }
174 void integralTransform() override {
175 DlMatrix integral;
176 if (RasterCacheUtil::ComputeIntegralTransCTM(state().matrix(), &integral)) {
177 state().setTransform(integral);
178 }
179 }
180
181 void clipRect(const DlRect& rect, DlClipOp op, bool is_aa) override {
182 state().clipRect(rect, op, is_aa);
183 }
184 void clipRRect(const DlRoundRect& rrect, DlClipOp op, bool is_aa) override {
185 state().clipRRect(rrect, op, is_aa);
186 }
188 DlClipOp op,
189 bool is_aa) override {
190 state().clipRSuperellipse(rse, op, is_aa);
191 }
192 void clipPath(const DlPath& path, DlClipOp op, bool is_aa) override {
193 state().clipPath(path, op, is_aa);
194 }
195
196 private:
197 DisplayListMatrixClipState& state() { return save_stack_.back(); }
198 const DisplayListMatrixClipState& state() const { return save_stack_.back(); }
199
200 std::vector<DisplayListMatrixClipState> save_stack_;
201};
202
203// ==============================================================
204// StateEntry subclasses
205// ==============================================================
206
207class SaveEntry : public LayerStateStack::StateEntry {
208 public:
209 SaveEntry() = default;
210
211 void apply(LayerStateStack* stack) const override {
212 stack->delegate_->save();
213 }
214 void restore(LayerStateStack* stack) const override {
215 stack->delegate_->restore();
216 }
217
219};
220
221class SaveLayerEntry : public LayerStateStack::StateEntry {
222 public:
223 SaveLayerEntry(const DlRect& bounds,
224 DlBlendMode blend_mode,
225 const LayerStateStack::RenderingAttributes& prev)
226 : bounds_(bounds), blend_mode_(blend_mode), old_attributes_(prev) {}
227
228 void apply(LayerStateStack* stack) const override {
229 stack->delegate_->saveLayer(bounds_, stack->outstanding_, blend_mode_,
230 nullptr);
231 stack->outstanding_ = {};
232 }
233 void restore(LayerStateStack* stack) const override {
234 stack->delegate_->restore();
235 stack->outstanding_ = old_attributes_;
236 }
237
238 protected:
241 const LayerStateStack::RenderingAttributes old_attributes_;
242
244};
245
246class OpacityEntry : public LayerStateStack::StateEntry {
247 public:
248 OpacityEntry(const DlRect& bounds,
249 DlScalar opacity,
250 const LayerStateStack::RenderingAttributes& prev)
251 : bounds_(bounds),
252 opacity_(opacity),
253 old_opacity_(prev.opacity),
254 old_bounds_(prev.save_layer_bounds) {}
255
256 void apply(LayerStateStack* stack) const override {
257 stack->outstanding_.save_layer_bounds = bounds_;
258 stack->outstanding_.opacity *= opacity_;
259 }
260 void restore(LayerStateStack* stack) const override {
261 stack->outstanding_.save_layer_bounds = old_bounds_;
262 stack->outstanding_.opacity = old_opacity_;
263 }
264 void update_mutators(MutatorsStack* mutators_stack) const override {
265 mutators_stack->PushOpacity(DlColor::toAlpha(opacity_));
266 }
267
268 private:
269 const DlRect bounds_;
270 const DlScalar opacity_;
271 const DlScalar old_opacity_;
272 const DlRect old_bounds_;
273
275};
276
277class ImageFilterEntry : public LayerStateStack::StateEntry {
278 public:
280 const std::shared_ptr<DlImageFilter>& filter,
281 const LayerStateStack::RenderingAttributes& prev)
282 : bounds_(bounds),
283 filter_(filter),
284 old_filter_(prev.image_filter),
285 old_bounds_(prev.save_layer_bounds) {}
286 ~ImageFilterEntry() override = default;
287
288 void apply(LayerStateStack* stack) const override {
289 stack->outstanding_.save_layer_bounds = bounds_;
290 stack->outstanding_.image_filter = filter_;
291 }
292 void restore(LayerStateStack* stack) const override {
293 stack->outstanding_.save_layer_bounds = old_bounds_;
294 stack->outstanding_.image_filter = old_filter_;
295 }
296
297 // There is no ImageFilter mutator currently
298 // void update_mutators(MutatorsStack* mutators_stack) const override;
299
300 private:
301 const DlRect bounds_;
302 const std::shared_ptr<DlImageFilter> filter_;
303 const std::shared_ptr<DlImageFilter> old_filter_;
304 const DlRect old_bounds_;
305
307};
308
309class ColorFilterEntry : public LayerStateStack::StateEntry {
310 public:
312 const std::shared_ptr<const DlColorFilter>& filter,
313 const LayerStateStack::RenderingAttributes& prev)
314 : bounds_(bounds),
315 filter_(filter),
316 old_filter_(prev.color_filter),
317 old_bounds_(prev.save_layer_bounds) {}
318 ~ColorFilterEntry() override = default;
319
320 void apply(LayerStateStack* stack) const override {
321 stack->outstanding_.save_layer_bounds = bounds_;
322 stack->outstanding_.color_filter = filter_;
323 }
324 void restore(LayerStateStack* stack) const override {
325 stack->outstanding_.save_layer_bounds = old_bounds_;
326 stack->outstanding_.color_filter = old_filter_;
327 }
328
329 // There is no ColorFilter mutator currently
330 // void update_mutators(MutatorsStack* mutators_stack) const override;
331
332 private:
333 const DlRect bounds_;
334 const std::shared_ptr<const DlColorFilter> filter_;
335 const std::shared_ptr<const DlColorFilter> old_filter_;
336 const DlRect old_bounds_;
337
339};
340
342 public:
344 const std::shared_ptr<DlImageFilter>& filter,
345 DlBlendMode blend_mode,
346 std::optional<int64_t> backdrop_id,
347 const LayerStateStack::RenderingAttributes& prev)
348 : SaveLayerEntry(bounds, blend_mode, prev),
349 filter_(filter),
350 backdrop_id_(backdrop_id) {}
351 ~BackdropFilterEntry() override = default;
352
353 void apply(LayerStateStack* stack) const override {
354 stack->delegate_->saveLayer(bounds_, stack->outstanding_, blend_mode_,
355 filter_.get(), backdrop_id_);
356 stack->outstanding_ = {};
357 }
358
359 void reapply(LayerStateStack* stack) const override {
360 // On the reapply for subsequent overlay layers, we do not
361 // want to reapply the backdrop filter, but we do need to
362 // do a saveLayer to encapsulate the contents and match the
363 // restore that will be forthcoming. Note that this is not
364 // perfect if the BlendMode is not associative as we will be
365 // compositing multiple parts of the content in batches.
366 // Luckily the most common SrcOver is associative.
368 }
369
370 private:
371 const std::shared_ptr<DlImageFilter> filter_;
372 std::optional<int64_t> backdrop_id_;
373
375};
376
377class TranslateEntry : public LayerStateStack::StateEntry {
378 public:
379 TranslateEntry(DlScalar tx, DlScalar ty) : translation_(tx, ty) {}
380
381 void apply(LayerStateStack* stack) const override {
382 stack->delegate_->translate(translation_.x, translation_.y);
383 }
384 void update_mutators(MutatorsStack* mutators_stack) const override {
385 mutators_stack->PushTransform(DlMatrix::MakeTranslation(translation_));
386 }
387
388 private:
389 const DlPoint translation_;
390
392};
393
394class TransformMatrixEntry : public LayerStateStack::StateEntry {
395 public:
396 explicit TransformMatrixEntry(const DlMatrix& matrix) : matrix_(matrix) {}
397
398 void apply(LayerStateStack* stack) const override {
399 stack->delegate_->transform(matrix_);
400 }
401 void update_mutators(MutatorsStack* mutators_stack) const override {
402 mutators_stack->PushTransform(matrix_);
403 }
404
405 private:
406 const DlMatrix matrix_;
407
409};
410
411class IntegralTransformEntry : public LayerStateStack::StateEntry {
412 public:
414
415 void apply(LayerStateStack* stack) const override {
416 stack->delegate_->integralTransform();
417 }
418
419 private:
421};
422
423class ClipRectEntry : public LayerStateStack::StateEntry {
424 public:
425 ClipRectEntry(const DlRect& clip_rect, bool is_aa)
426 : clip_rect_(clip_rect), is_aa_(is_aa) {}
427
428 void apply(LayerStateStack* stack) const override {
429 stack->delegate_->clipRect(clip_rect_, DlClipOp::kIntersect, is_aa_);
430 }
431 void update_mutators(MutatorsStack* mutators_stack) const override {
432 mutators_stack->PushClipRect(clip_rect_);
433 }
434
435 private:
436 const DlRect clip_rect_;
437 const bool is_aa_;
438
440};
441
442class ClipRRectEntry : public LayerStateStack::StateEntry {
443 public:
444 ClipRRectEntry(const DlRoundRect& clip_rrect, bool is_aa)
445 : clip_rrect_(clip_rrect), is_aa_(is_aa) {}
446
447 void apply(LayerStateStack* stack) const override {
448 stack->delegate_->clipRRect(clip_rrect_, DlClipOp::kIntersect, is_aa_);
449 }
450 void update_mutators(MutatorsStack* mutators_stack) const override {
451 mutators_stack->PushClipRRect(clip_rrect_);
452 }
453
454 private:
455 const DlRoundRect clip_rrect_;
456 const bool is_aa_;
457
459};
460
461class ClipRSuperellipseEntry : public LayerStateStack::StateEntry {
462 public:
464 bool is_aa)
465 : clip_rsuperellipse_(clip_rsuperellipse), is_aa_(is_aa) {}
466
467 void apply(LayerStateStack* stack) const override {
468 stack->delegate_->clipRSuperellipse(clip_rsuperellipse_,
469 DlClipOp::kIntersect, is_aa_);
470 }
471 void update_mutators(MutatorsStack* mutators_stack) const override {
472 mutators_stack->PushClipRSE(clip_rsuperellipse_);
473 }
474
475 private:
476 const DlRoundSuperellipse clip_rsuperellipse_;
477 const bool is_aa_;
478
480};
481
482class ClipPathEntry : public LayerStateStack::StateEntry {
483 public:
484 ClipPathEntry(const DlPath& clip_path, bool is_aa)
485 : clip_path_(clip_path), is_aa_(is_aa) {}
486 ~ClipPathEntry() override = default;
487
488 void apply(LayerStateStack* stack) const override {
489 stack->delegate_->clipPath(clip_path_, DlClipOp::kIntersect, is_aa_);
490 }
491 void update_mutators(MutatorsStack* mutators_stack) const override {
492 mutators_stack->PushClipPath(clip_path_);
493 }
494
495 private:
496 const DlPath clip_path_;
497 const bool is_aa_;
498
500};
501
502// ==============================================================
503// RenderingAttributes methods
504// ==============================================================
505
506DlPaint* LayerStateStack::RenderingAttributes::fill(DlPaint& paint,
507 DlBlendMode mode) const {
508 DlPaint* ret = nullptr;
509 if (opacity < SK_Scalar1) {
510 paint.setOpacity(std::max(opacity, 0.0f));
511 ret = &paint;
512 } else {
513 paint.setOpacity(SK_Scalar1);
514 }
515 paint.setColorFilter(color_filter);
516 if (color_filter) {
517 ret = &paint;
518 }
519 paint.setImageFilter(image_filter);
520 if (image_filter) {
521 ret = &paint;
522 }
523 paint.setBlendMode(mode);
524 if (mode != DlBlendMode::kSrcOver) {
525 ret = &paint;
526 }
527 return ret;
528}
529
530// ==============================================================
531// MutatorContext methods
532// ==============================================================
533
535
537 layer_state_stack_->save_layer(bounds);
538}
539
540void MutatorContext::applyOpacity(const DlRect& bounds, DlScalar opacity) {
541 if (opacity < SK_Scalar1) {
542 layer_state_stack_->push_opacity(bounds, opacity);
543 }
544}
545
547 const DlRect& bounds,
548 const std::shared_ptr<DlImageFilter>& filter) {
549 if (filter) {
550 layer_state_stack_->push_image_filter(bounds, filter);
551 }
552}
553
555 const DlRect& bounds,
556 const std::shared_ptr<const DlColorFilter>& filter) {
557 if (filter) {
558 layer_state_stack_->push_color_filter(bounds, filter);
559 }
560}
561
563 const DlRect& bounds,
564 const std::shared_ptr<DlImageFilter>& filter,
565 DlBlendMode blend_mode,
566 std::optional<int64_t> backdrop_id) {
567 layer_state_stack_->push_backdrop(bounds, filter, blend_mode, backdrop_id);
568}
569
570void MutatorContext::translate(SkScalar tx, SkScalar ty) {
571 if (!(tx == 0 && ty == 0)) {
572 layer_state_stack_->maybe_save_layer_for_transform(save_needed_);
573 save_needed_ = false;
574 layer_state_stack_->push_translate(tx, ty);
575 }
576}
577
580 translate(matrix.m[12], matrix.m[13]);
581 } else if (!matrix.IsIdentity()) {
582 layer_state_stack_->maybe_save_layer_for_transform(save_needed_);
583 save_needed_ = false;
584 layer_state_stack_->push_transform(matrix);
585 }
586}
587
589 layer_state_stack_->maybe_save_layer_for_transform(save_needed_);
590 save_needed_ = false;
591 layer_state_stack_->push_integral_transform();
592}
593
594void MutatorContext::clipRect(const DlRect& rect, bool is_aa) {
595 layer_state_stack_->maybe_save_layer_for_clip(save_needed_);
596 save_needed_ = false;
597 layer_state_stack_->push_clip_rect(rect, is_aa);
598}
599
600void MutatorContext::clipRRect(const DlRoundRect& rrect, bool is_aa) {
601 layer_state_stack_->maybe_save_layer_for_clip(save_needed_);
602 save_needed_ = false;
603 layer_state_stack_->push_clip_rrect(rrect, is_aa);
604}
605
607 bool is_aa) {
608 layer_state_stack_->maybe_save_layer_for_clip(save_needed_);
609 save_needed_ = false;
610 layer_state_stack_->push_clip_rsuperellipse(rse, is_aa);
611}
612
613void MutatorContext::clipPath(const DlPath& path, bool is_aa) {
614 layer_state_stack_->maybe_save_layer_for_clip(save_needed_);
615 save_needed_ = false;
616 layer_state_stack_->push_clip_path(path, is_aa);
617}
618
619// ==============================================================
620// LayerStateStack methods
621// ==============================================================
622
624
626 delegate_->decommission();
627 delegate_ = DummyDelegate::kInstance;
628}
629
631 if (delegate_) {
632 if (canvas == delegate_->canvas()) {
633 return;
634 }
636 }
637 if (canvas) {
638 delegate_ = std::make_shared<DlCanvasDelegate>(canvas);
639 reapply_all();
640 }
641}
642
644 set_preroll_delegate(cull_rect, DlMatrix());
645}
650 const DlMatrix& matrix) {
652 delegate_ = std::make_shared<PrerollDelegate>(cull_rect, matrix);
653 reapply_all();
654}
655
656void LayerStateStack::reapply_all() {
657 // We use a local RenderingAttributes instance so that it can track the
658 // necessary state changes independently as they occur in the stack.
659 // Reusing |outstanding_| would wreak havoc on the current state of
660 // the stack. When we are finished, though, the local attributes
661 // contents should match the current outstanding_ values;
662 RenderingAttributes attributes = outstanding_;
663 outstanding_ = {};
664 for (auto& state : state_stack_) {
665 state->reapply(this);
666 }
667 FML_DCHECK(attributes == outstanding_);
668}
669
671 for (auto& state : state_stack_) {
672 state->update_mutators(mutators);
673 }
674}
675
676void LayerStateStack::restore_to_count(size_t restore_count) {
677 while (state_stack_.size() > restore_count) {
678 state_stack_.back()->restore(this);
679 state_stack_.pop_back();
680 }
681}
682
683void LayerStateStack::push_opacity(const DlRect& bounds, DlScalar opacity) {
684 maybe_save_layer(opacity);
685 state_stack_.emplace_back(
686 std::make_unique<OpacityEntry>(bounds, opacity, outstanding_));
687 apply_last_entry();
688}
689
690void LayerStateStack::push_color_filter(
691 const DlRect& bounds,
692 const std::shared_ptr<const DlColorFilter>& filter) {
693 maybe_save_layer(filter);
694 state_stack_.emplace_back(
695 std::make_unique<ColorFilterEntry>(bounds, filter, outstanding_));
696 apply_last_entry();
697}
698
699void LayerStateStack::push_image_filter(
700 const DlRect& bounds,
701 const std::shared_ptr<DlImageFilter>& filter) {
702 maybe_save_layer(filter);
703 state_stack_.emplace_back(
704 std::make_unique<ImageFilterEntry>(bounds, filter, outstanding_));
705 apply_last_entry();
706}
707
708void LayerStateStack::push_backdrop(
709 const DlRect& bounds,
710 const std::shared_ptr<DlImageFilter>& filter,
711 DlBlendMode blend_mode,
712 std::optional<int64_t> backdrop_id) {
713 state_stack_.emplace_back(std::make_unique<BackdropFilterEntry>(
714 bounds, filter, blend_mode, backdrop_id, outstanding_));
715 apply_last_entry();
716}
717
718void LayerStateStack::push_translate(SkScalar tx, SkScalar ty) {
719 state_stack_.emplace_back(std::make_unique<TranslateEntry>(tx, ty));
720 apply_last_entry();
721}
722
723void LayerStateStack::push_transform(const DlMatrix& matrix) {
724 state_stack_.emplace_back(std::make_unique<TransformMatrixEntry>(matrix));
725 apply_last_entry();
726}
727
728void LayerStateStack::push_integral_transform() {
729 state_stack_.emplace_back(std::make_unique<IntegralTransformEntry>());
730 apply_last_entry();
731}
732
733void LayerStateStack::push_clip_rect(const DlRect& rect, bool is_aa) {
734 state_stack_.emplace_back(std::make_unique<ClipRectEntry>(rect, is_aa));
735 apply_last_entry();
736}
737
738void LayerStateStack::push_clip_rrect(const DlRoundRect& rrect, bool is_aa) {
739 state_stack_.emplace_back(std::make_unique<ClipRRectEntry>(rrect, is_aa));
740 apply_last_entry();
741}
742
743void LayerStateStack::push_clip_rsuperellipse(const DlRoundSuperellipse& rse,
744 bool is_aa) {
745 state_stack_.emplace_back(
746 std::make_unique<ClipRSuperellipseEntry>(rse, is_aa));
747 apply_last_entry();
748}
749
750void LayerStateStack::push_clip_path(const DlPath& path, bool is_aa) {
751 state_stack_.emplace_back(std::make_unique<ClipPathEntry>(path, is_aa));
752 apply_last_entry();
753}
754
755bool LayerStateStack::needs_save_layer(int flags) const {
756 if (outstanding_.opacity < SK_Scalar1 &&
758 return true;
759 }
760 if (outstanding_.image_filter &&
762 return true;
763 }
764 if (outstanding_.color_filter &&
766 return true;
767 }
768 return false;
769}
770
771void LayerStateStack::do_save() {
772 state_stack_.emplace_back(std::make_unique<SaveEntry>());
773 apply_last_entry();
774}
775
776void LayerStateStack::save_layer(const DlRect& bounds) {
777 state_stack_.emplace_back(std::make_unique<SaveLayerEntry>(
778 bounds, DlBlendMode::kSrcOver, outstanding_));
779 apply_last_entry();
780}
781
782void LayerStateStack::maybe_save_layer_for_transform(bool save_needed) {
783 // Alpha and ColorFilter don't care about transform
784 if (outstanding_.image_filter) {
785 save_layer(outstanding_.save_layer_bounds);
786 } else if (save_needed) {
787 do_save();
788 }
789}
790
791void LayerStateStack::maybe_save_layer_for_clip(bool save_needed) {
792 // Alpha and ColorFilter don't care about clipping
793 // - Alpha of clipped content == clip of alpha content
794 // - Color-filtering of clipped content == clip of color-filtered content
795 if (outstanding_.image_filter) {
796 save_layer(outstanding_.save_layer_bounds);
797 } else if (save_needed) {
798 do_save();
799 }
800}
801
802void LayerStateStack::maybe_save_layer(int apply_flags) {
803 if (needs_save_layer(apply_flags)) {
804 save_layer(outstanding_.save_layer_bounds);
805 }
806}
807
808void LayerStateStack::maybe_save_layer(SkScalar opacity) {
809 if (outstanding_.image_filter) {
810 save_layer(outstanding_.save_layer_bounds);
811 }
812}
813
814void LayerStateStack::maybe_save_layer(
815 const std::shared_ptr<const DlColorFilter>& filter) {
816 if (outstanding_.color_filter || outstanding_.image_filter ||
817 (outstanding_.opacity < SK_Scalar1 &&
818 !filter->can_commute_with_opacity())) {
819 // TBD: compose the 2 color filters together.
820 save_layer(outstanding_.save_layer_bounds);
821 }
822}
823
824void LayerStateStack::maybe_save_layer(
825 const std::shared_ptr<DlImageFilter>& filter) {
826 if (outstanding_.image_filter) {
827 // TBD: compose the 2 image filters together.
828 save_layer(outstanding_.save_layer_bounds);
829 }
830}
831
832} // namespace flutter
BackdropFilterEntry(const DlRect &bounds, const std::shared_ptr< DlImageFilter > &filter, DlBlendMode blend_mode, std::optional< int64_t > backdrop_id, const LayerStateStack::RenderingAttributes &prev)
void apply(LayerStateStack *stack) const override
~BackdropFilterEntry() override=default
void reapply(LayerStateStack *stack) const override
void apply(LayerStateStack *stack) const override
void update_mutators(MutatorsStack *mutators_stack) const override
~ClipPathEntry() override=default
ClipPathEntry(const DlPath &clip_path, bool is_aa)
ClipRRectEntry(const DlRoundRect &clip_rrect, bool is_aa)
void apply(LayerStateStack *stack) const override
void update_mutators(MutatorsStack *mutators_stack) const override
ClipRSuperellipseEntry(const DlRoundSuperellipse &clip_rsuperellipse, bool is_aa)
void apply(LayerStateStack *stack) const override
void update_mutators(MutatorsStack *mutators_stack) const override
ClipRectEntry(const DlRect &clip_rect, bool is_aa)
void update_mutators(MutatorsStack *mutators_stack) const override
void apply(LayerStateStack *stack) const override
ColorFilterEntry(const DlRect &bounds, const std::shared_ptr< const DlColorFilter > &filter, const LayerStateStack::RenderingAttributes &prev)
void restore(LayerStateStack *stack) const override
~ColorFilterEntry() override=default
void apply(LayerStateStack *stack) const override
void translate(DlScalar tx, DlScalar ty)
void clipRect(const DlRect &rect, DlClipOp op, bool is_aa)
void clipRRect(const DlRoundRect &rrect, DlClipOp op, bool is_aa)
void clipRSuperellipse(const DlRoundSuperellipse &rse, DlClipOp op, bool is_aa)
void setTransform(const DlMatrix &matrix)
bool content_culled(const DlRect &content_bounds) const
void transform(const DlMatrix &matrix)
void clipPath(const DlPath &path, DlClipOp op, bool is_aa)
void saveLayer(const DlRect &bounds, LayerStateStack::RenderingAttributes &attributes, DlBlendMode blend_mode, const DlImageFilter *backdrop, std::optional< int64_t > backdrop_id) override
void clipPath(const DlPath &path, DlClipOp op, bool is_aa) override
DlRect device_cull_rect() const override
void clipRRect(const DlRoundRect &rrect, DlClipOp op, bool is_aa) override
bool content_culled(const DlRect &content_bounds) const override
DlCanvasDelegate(DlCanvas *canvas)
void clipRect(const DlRect &rect, DlClipOp op, bool is_aa) override
DlCanvas * canvas() const override
DlMatrix matrix() const override
DlRect local_cull_rect() const override
void translate(DlScalar tx, DlScalar ty) override
void clipRSuperellipse(const DlRoundSuperellipse &rse, DlClipOp op, bool is_aa) override
void transform(const DlMatrix &matrix) override
Developer-facing API for rendering anything within the engine.
Definition dl_canvas.h:32
virtual void Transform(const DlMatrix &matrix)=0
virtual void ClipRoundSuperellipse(const DlRoundSuperellipse &rse, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false)=0
virtual void ClipRect(const DlRect &rect, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false)=0
virtual void ClipRoundRect(const DlRoundRect &rrect, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false)=0
virtual DlRect GetDestinationClipCoverage() const =0
virtual DlRect GetLocalClipCoverage() const =0
virtual bool QuickReject(const DlRect &bounds) const =0
virtual void SaveLayer(const std::optional< DlRect > &bounds, const DlPaint *paint=nullptr, const DlImageFilter *backdrop=nullptr, std::optional< int64_t > backdrop_id=std::nullopt)=0
virtual void SetTransform(const DlMatrix &matrix)=0
virtual void Translate(DlScalar tx, DlScalar ty)=0
virtual DlMatrix GetMatrix() const =0
virtual void Restore()=0
virtual void RestoreToCount(int restore_count)=0
virtual void ClipPath(const DlPath &path, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false)=0
virtual void Save()=0
DlPaint & setBlendMode(DlBlendMode mode)
Definition dl_paint.h:85
DlPaint & setImageFilter(std::nullptr_t filter)
Definition dl_paint.h:167
DlPaint & setOpacity(DlScalar opacity)
Definition dl_paint.h:78
DlPaint & setColorFilter(std::nullptr_t filter)
Definition dl_paint.h:149
static const std::shared_ptr< DummyDelegate > kInstance
void clipRSuperellipse(const DlRoundSuperellipse &rse, DlClipOp op, bool is_aa) override
void saveLayer(const DlRect &bounds, LayerStateStack::RenderingAttributes &attributes, DlBlendMode blend, const DlImageFilter *backdrop, std::optional< int64_t > backdrop_id) override
void integralTransform() override
void translate(DlScalar tx, DlScalar ty) override
DlRect local_cull_rect() const override
DlMatrix matrix() const override
void transform(const DlMatrix &matrix) override
void clipRRect(const DlRoundRect &rrect, DlClipOp op, bool is_aa) override
void clipPath(const DlPath &path, DlClipOp op, bool is_aa) override
bool content_culled(const DlRect &content_bounds) const override
void clipRect(const DlRect &rect, DlClipOp op, bool is_aa) override
DlRect device_cull_rect() const override
~ImageFilterEntry() override=default
void apply(LayerStateStack *stack) const override
void restore(LayerStateStack *stack) const override
ImageFilterEntry(const DlRect &bounds, const std::shared_ptr< DlImageFilter > &filter, const LayerStateStack::RenderingAttributes &prev)
void apply(LayerStateStack *stack) const override
IntegralTransformEntry()=default
void applyColorFilter(const DlRect &bounds, const std::shared_ptr< const DlColorFilter > &filter)
void clipPath(const DlPath &path, bool is_aa)
void clipRSuperellipse(const DlRoundSuperellipse &rse, bool is_aa)
void translate(DlScalar tx, DlScalar ty)
void clipRRect(const DlRoundRect &rrect, bool is_aa)
void applyOpacity(const DlRect &bounds, DlScalar opacity)
void clipRect(const DlRect &rect, bool is_aa)
void applyBackdropFilter(const DlRect &bounds, const std::shared_ptr< DlImageFilter > &filter, DlBlendMode blend_mode, std::optional< int64_t > backdrop_id)
void applyImageFilter(const DlRect &bounds, const std::shared_ptr< DlImageFilter > &filter)
void fill(MutatorsStack *mutators)
static constexpr int kCallerCanApplyColorFilter
void set_delegate(DlCanvas *canvas)
void set_preroll_delegate(const DlRect &cull_rect, const DlMatrix &matrix)
static constexpr int kCallerCanApplyImageFilter
const DlMatrix matrix() const
static constexpr int kCallerCanApplyOpacity
void PushTransform(const DlMatrix &matrix)
void PushClipRect(const DlRect &rect)
void PushClipPath(const DlPath &path)
void PushClipRRect(const DlRoundRect &rrect)
void PushOpacity(const uint8_t &alpha)
void PushClipRSE(const DlRoundSuperellipse &rrect)
void update_mutators(MutatorsStack *mutators_stack) const override
void restore(LayerStateStack *stack) const override
void apply(LayerStateStack *stack) const override
OpacityEntry(const DlRect &bounds, DlScalar opacity, const LayerStateStack::RenderingAttributes &prev)
DlRect device_cull_rect() const override
DlMatrix matrix() const override
void transform(const DlMatrix &matrix) override
PrerollDelegate(const DlRect &cull_rect, const DlMatrix &matrix)
bool content_culled(const DlRect &content_bounds) const override
void translate(DlScalar tx, DlScalar ty) override
DlRect local_cull_rect() const override
void clipRRect(const DlRoundRect &rrect, DlClipOp op, bool is_aa) override
void saveLayer(const DlRect &bounds, LayerStateStack::RenderingAttributes &attributes, DlBlendMode blend, const DlImageFilter *backdrop, std::optional< int64_t > backdrop_id) override
void clipPath(const DlPath &path, DlClipOp op, bool is_aa) override
void clipRSuperellipse(const DlRoundSuperellipse &rse, DlClipOp op, bool is_aa) override
void clipRect(const DlRect &rect, DlClipOp op, bool is_aa) override
FML_DISALLOW_COPY_ASSIGN_AND_MOVE(SaveEntry)
void apply(LayerStateStack *stack) const override
void restore(LayerStateStack *stack) const override
SaveEntry()=default
const LayerStateStack::RenderingAttributes old_attributes_
void apply(LayerStateStack *stack) const override
void restore(LayerStateStack *stack) const override
SaveLayerEntry(const DlRect &bounds, DlBlendMode blend_mode, const LayerStateStack::RenderingAttributes &prev)
FML_DISALLOW_COPY_ASSIGN_AND_MOVE(SaveLayerEntry)
const DlRect bounds_
const DlBlendMode blend_mode_
TransformMatrixEntry(const DlMatrix &matrix)
void update_mutators(MutatorsStack *mutators_stack) const override
void apply(LayerStateStack *stack) const override
void apply(LayerStateStack *stack) const override
void update_mutators(MutatorsStack *mutators_stack) const override
TranslateEntry(DlScalar tx, DlScalar ty)
#define FML_DCHECK(condition)
Definition logging.h:122
#define FML_DISALLOW_COPY_ASSIGN_AND_MOVE(TypeName)
Definition macros.h:31
impeller::Scalar DlScalar
impeller::RoundRect DlRoundRect
impeller::Matrix DlMatrix
impeller::Rect DlRect
impeller::RoundSuperellipse DlRoundSuperellipse
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition switch_defs.h:52
static constexpr DlRect kGiantRect
Definition layer.h:40
impeller::BlendMode DlBlendMode
BlendMode
Definition color.h:58
static uint8_t toAlpha(DlScalar opacity)
Definition dl_color.h:64
static bool ComputeIntegralTransCTM(const SkMatrix &in, SkMatrix *out)
Snap the translation components of the |in| matrix to integers and store the snapped matrix in |out|.
A 4x4 matrix using column-major storage.
Definition matrix.h:37
constexpr bool IsTranslationOnly() const
Returns true if the matrix has no entries other than translation components. Note that an identity ma...
Definition matrix.h:480
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition matrix.h:95
constexpr bool IsIdentity() const
Definition matrix.h:467
Scalar m[16]
Definition matrix.h:39
#define TRACE_EVENT0(category_group, name)