Flutter Engine
The 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
5#include "flutter/flow/layers/layer_state_stack.h"
6
7#include "flutter/display_list/utils/dl_matrix_clip_tracker.h"
8#include "flutter/flow/layers/layer.h"
9#include "flutter/flow/paint_utils.h"
10#include "flutter/flow/raster_cache_util.h"
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 SkRect local_cull_rect() const override {
31 error();
32 return {};
33 }
34 SkRect device_cull_rect() const override {
35 error();
36 return {};
37 }
38 SkM44 matrix_4x4() const override {
39 error();
40 return {};
41 }
42 SkMatrix matrix_3x3() const override {
43 error();
44 return {};
45 }
46 bool content_culled(const SkRect& content_bounds) const override {
47 error();
48 return true;
49 }
50
51 void save() override {}
52 void saveLayer(const SkRect& bounds,
53 LayerStateStack::RenderingAttributes& attributes,
55 const DlImageFilter* backdrop) override {}
56 void restore() override {}
57
58 void translate(SkScalar tx, SkScalar ty) override {}
59 void transform(const SkM44& m44) override {}
60 void transform(const SkMatrix& matrix) override {}
61 void integralTransform() override {}
62
63 void clipRect(const SkRect& rect, ClipOp op, bool is_aa) override {}
64 void clipRRect(const SkRRect& rrect, ClipOp op, bool is_aa) override {}
65 void clipPath(const SkPath& path, ClipOp op, bool is_aa) override {}
66
67 private:
68 static void error() {
69 FML_DCHECK(false) << "LayerStateStack state queried without a delegate";
70 }
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 SkRect local_cull_rect() const override {
85 return canvas_->GetLocalClipBounds();
86 }
87 SkRect device_cull_rect() const override {
88 return canvas_->GetDestinationClipBounds();
89 }
90 SkM44 matrix_4x4() const override {
91 return canvas_->GetTransformFullPerspective();
92 }
93 SkMatrix matrix_3x3() const override { return canvas_->GetTransform(); }
94 bool content_culled(const SkRect& content_bounds) const override {
95 return canvas_->QuickReject(content_bounds);
96 }
97
98 void save() override { canvas_->Save(); }
99 void saveLayer(const SkRect& bounds,
100 LayerStateStack::RenderingAttributes& attributes,
101 DlBlendMode blend_mode,
102 const DlImageFilter* backdrop) override {
103 TRACE_EVENT0("flutter", "Canvas::saveLayer");
105 canvas_->SaveLayer(&bounds, attributes.fill(paint, blend_mode), backdrop);
106 }
107 void restore() override { canvas_->Restore(); }
108
109 void translate(SkScalar tx, SkScalar ty) override {
110 canvas_->Translate(tx, ty);
111 }
112 void transform(const SkM44& m44) override { canvas_->Transform(m44); }
113 void transform(const SkMatrix& matrix) override {
114 canvas_->Transform(matrix);
115 }
116 void integralTransform() override {
117 SkM44 integral;
119 canvas_->SetTransform(integral);
120 }
121 }
122
123 void clipRect(const SkRect& rect, ClipOp op, bool is_aa) override {
124 canvas_->ClipRect(rect, op, is_aa);
125 }
126 void clipRRect(const SkRRect& rrect, ClipOp op, bool is_aa) override {
127 canvas_->ClipRRect(rrect, op, is_aa);
128 }
129 void clipPath(const SkPath& path, ClipOp op, bool is_aa) override {
130 canvas_->ClipPath(path, op, is_aa);
131 }
132
133 private:
134 DlCanvas* canvas_;
135 const int initial_save_level_;
136};
137
138class PrerollDelegate : public LayerStateStack::Delegate {
139 public:
140 PrerollDelegate(const SkRect& cull_rect, const SkMatrix& matrix)
141 : tracker_(cull_rect, matrix) {}
142
143 void decommission() override {}
144
145 SkM44 matrix_4x4() const override { return tracker_.matrix_4x4(); }
146 SkMatrix matrix_3x3() const override { return tracker_.matrix_3x3(); }
147 SkRect local_cull_rect() const override { return tracker_.local_cull_rect(); }
148 SkRect device_cull_rect() const override {
149 return tracker_.device_cull_rect();
150 }
151 bool content_culled(const SkRect& content_bounds) const override {
152 return tracker_.content_culled(content_bounds);
153 }
154
155 void save() override { tracker_.save(); }
156 void saveLayer(const SkRect& bounds,
157 LayerStateStack::RenderingAttributes& attributes,
159 const DlImageFilter* backdrop) override {
160 tracker_.save();
161 }
162 void restore() override { tracker_.restore(); }
163
164 void translate(SkScalar tx, SkScalar ty) override {
165 tracker_.translate(tx, ty);
166 }
167 void transform(const SkM44& m44) override { tracker_.transform(m44); }
168 void transform(const SkMatrix& matrix) override {
169 tracker_.transform(matrix);
170 }
171 void integralTransform() override {
172 if (tracker_.using_4x4_matrix()) {
173 SkM44 integral;
175 &integral)) {
176 tracker_.setTransform(integral);
177 }
178 } else {
179 SkMatrix integral;
181 &integral)) {
182 tracker_.setTransform(integral);
183 }
184 }
185 }
186
187 void clipRect(const SkRect& rect, ClipOp op, bool is_aa) override {
188 tracker_.clipRect(rect, op, is_aa);
189 }
190 void clipRRect(const SkRRect& rrect, ClipOp op, bool is_aa) override {
191 tracker_.clipRRect(rrect, op, is_aa);
192 }
193 void clipPath(const SkPath& path, ClipOp op, bool is_aa) override {
194 tracker_.clipPath(path, op, is_aa);
195 }
196
197 private:
199};
200
201// ==============================================================
202// StateEntry subclasses
203// ==============================================================
204
205class SaveEntry : public LayerStateStack::StateEntry {
206 public:
207 SaveEntry() = default;
208
209 void apply(LayerStateStack* stack) const override {
210 stack->delegate_->save();
211 }
212 void restore(LayerStateStack* stack) const override {
213 stack->delegate_->restore();
214 }
215
217};
218
219class SaveLayerEntry : public LayerStateStack::StateEntry {
220 public:
221 SaveLayerEntry(const SkRect& bounds,
222 DlBlendMode blend_mode,
223 const LayerStateStack::RenderingAttributes& prev)
224 : bounds_(bounds), blend_mode_(blend_mode), old_attributes_(prev) {}
225
226 void apply(LayerStateStack* stack) const override {
227 stack->delegate_->saveLayer(bounds_, stack->outstanding_, blend_mode_,
228 nullptr);
229 stack->outstanding_ = {};
230 }
231 void restore(LayerStateStack* stack) const override {
232 if (stack->checkerboard_func_) {
233 DlCanvas* canvas = stack->canvas_delegate();
234 if (canvas != nullptr) {
235 (*stack->checkerboard_func_)(canvas, bounds_);
236 }
237 }
238 stack->delegate_->restore();
239 stack->outstanding_ = old_attributes_;
240 }
241
242 protected:
245 const LayerStateStack::RenderingAttributes old_attributes_;
246
248};
249
250class OpacityEntry : public LayerStateStack::StateEntry {
251 public:
252 OpacityEntry(const SkRect& bounds,
253 SkScalar opacity,
254 const LayerStateStack::RenderingAttributes& prev)
255 : bounds_(bounds),
256 opacity_(opacity),
257 old_opacity_(prev.opacity),
258 old_bounds_(prev.save_layer_bounds) {}
259
260 void apply(LayerStateStack* stack) const override {
261 stack->outstanding_.save_layer_bounds = bounds_;
262 stack->outstanding_.opacity *= opacity_;
263 }
264 void restore(LayerStateStack* stack) const override {
265 stack->outstanding_.save_layer_bounds = old_bounds_;
266 stack->outstanding_.opacity = old_opacity_;
267 }
268 void update_mutators(MutatorsStack* mutators_stack) const override {
269 mutators_stack->PushOpacity(DlColor::toAlpha(opacity_));
270 }
271
272 private:
273 const SkRect bounds_;
274 const SkScalar opacity_;
275 const SkScalar old_opacity_;
276 const SkRect old_bounds_;
277
279};
280
281class ImageFilterEntry : public LayerStateStack::StateEntry {
282 public:
284 const std::shared_ptr<const DlImageFilter>& filter,
285 const LayerStateStack::RenderingAttributes& prev)
286 : bounds_(bounds),
287 filter_(filter),
288 old_filter_(prev.image_filter),
289 old_bounds_(prev.save_layer_bounds) {}
290 ~ImageFilterEntry() override = default;
291
292 void apply(LayerStateStack* stack) const override {
293 stack->outstanding_.save_layer_bounds = bounds_;
294 stack->outstanding_.image_filter = filter_;
295 }
296 void restore(LayerStateStack* stack) const override {
297 stack->outstanding_.save_layer_bounds = old_bounds_;
298 stack->outstanding_.image_filter = old_filter_;
299 }
300
301 // There is no ImageFilter mutator currently
302 // void update_mutators(MutatorsStack* mutators_stack) const override;
303
304 private:
305 const SkRect bounds_;
306 const std::shared_ptr<const DlImageFilter> filter_;
307 const std::shared_ptr<const DlImageFilter> old_filter_;
308 const SkRect old_bounds_;
309
311};
312
313class ColorFilterEntry : public LayerStateStack::StateEntry {
314 public:
316 const std::shared_ptr<const DlColorFilter>& filter,
317 const LayerStateStack::RenderingAttributes& prev)
318 : bounds_(bounds),
319 filter_(filter),
320 old_filter_(prev.color_filter),
321 old_bounds_(prev.save_layer_bounds) {}
322 ~ColorFilterEntry() override = default;
323
324 void apply(LayerStateStack* stack) const override {
325 stack->outstanding_.save_layer_bounds = bounds_;
326 stack->outstanding_.color_filter = filter_;
327 }
328 void restore(LayerStateStack* stack) const override {
329 stack->outstanding_.save_layer_bounds = old_bounds_;
330 stack->outstanding_.color_filter = old_filter_;
331 }
332
333 // There is no ColorFilter mutator currently
334 // void update_mutators(MutatorsStack* mutators_stack) const override;
335
336 private:
337 const SkRect bounds_;
338 const std::shared_ptr<const DlColorFilter> filter_;
339 const std::shared_ptr<const DlColorFilter> old_filter_;
340 const SkRect old_bounds_;
341
343};
344
346 public:
348 const std::shared_ptr<const DlImageFilter>& filter,
349 DlBlendMode blend_mode,
350 const LayerStateStack::RenderingAttributes& prev)
351 : SaveLayerEntry(bounds, blend_mode, prev), filter_(filter) {}
352 ~BackdropFilterEntry() override = default;
353
354 void apply(LayerStateStack* stack) const override {
355 stack->delegate_->saveLayer(bounds_, stack->outstanding_, blend_mode_,
356 filter_.get());
357 stack->outstanding_ = {};
358 }
359
360 void reapply(LayerStateStack* stack) const override {
361 // On the reapply for subsequent overlay layers, we do not
362 // want to reapply the backdrop filter, but we do need to
363 // do a saveLayer to encapsulate the contents and match the
364 // restore that will be forthcoming. Note that this is not
365 // perfect if the BlendMode is not associative as we will be
366 // compositing multiple parts of the content in batches.
367 // Luckily the most common SrcOver is associative.
369 }
370
371 private:
372 const std::shared_ptr<const DlImageFilter> filter_;
373
375};
376
377class TranslateEntry : public LayerStateStack::StateEntry {
378 public:
379 TranslateEntry(SkScalar tx, SkScalar ty) : tx_(tx), ty_(ty) {}
380
381 void apply(LayerStateStack* stack) const override {
382 stack->delegate_->translate(tx_, ty_);
383 }
384 void update_mutators(MutatorsStack* mutators_stack) const override {
385 mutators_stack->PushTransform(SkMatrix::Translate(tx_, ty_));
386 }
387
388 private:
389 const SkScalar tx_;
390 const SkScalar ty_;
391
393};
394
395class TransformMatrixEntry : public LayerStateStack::StateEntry {
396 public:
397 explicit TransformMatrixEntry(const SkMatrix& matrix) : matrix_(matrix) {}
398
399 void apply(LayerStateStack* stack) const override {
400 stack->delegate_->transform(matrix_);
401 }
402 void update_mutators(MutatorsStack* mutators_stack) const override {
403 mutators_stack->PushTransform(matrix_);
404 }
405
406 private:
407 const SkMatrix matrix_;
408
410};
411
412class TransformM44Entry : public LayerStateStack::StateEntry {
413 public:
414 explicit TransformM44Entry(const SkM44& m44) : m44_(m44) {}
415
416 void apply(LayerStateStack* stack) const override {
417 stack->delegate_->transform(m44_);
418 }
419 void update_mutators(MutatorsStack* mutators_stack) const override {
420 mutators_stack->PushTransform(m44_.asM33());
421 }
422
423 private:
424 const SkM44 m44_;
425
427};
428
429class IntegralTransformEntry : public LayerStateStack::StateEntry {
430 public:
432
433 void apply(LayerStateStack* stack) const override {
434 stack->delegate_->integralTransform();
435 }
436
437 private:
439};
440
441class ClipRectEntry : public LayerStateStack::StateEntry {
442 public:
443 ClipRectEntry(const SkRect& clip_rect, bool is_aa)
444 : clip_rect_(clip_rect), is_aa_(is_aa) {}
445
446 void apply(LayerStateStack* stack) const override {
447 stack->delegate_->clipRect(clip_rect_, DlCanvas::ClipOp::kIntersect,
448 is_aa_);
449 }
450 void update_mutators(MutatorsStack* mutators_stack) const override {
451 mutators_stack->PushClipRect(clip_rect_);
452 }
453
454 private:
455 const SkRect clip_rect_;
456 const bool is_aa_;
457
459};
460
461class ClipRRectEntry : public LayerStateStack::StateEntry {
462 public:
463 ClipRRectEntry(const SkRRect& clip_rrect, bool is_aa)
464 : clip_rrect_(clip_rrect), is_aa_(is_aa) {}
465
466 void apply(LayerStateStack* stack) const override {
467 stack->delegate_->clipRRect(clip_rrect_, DlCanvas::ClipOp::kIntersect,
468 is_aa_);
469 }
470 void update_mutators(MutatorsStack* mutators_stack) const override {
471 mutators_stack->PushClipRRect(clip_rrect_);
472 }
473
474 private:
475 const SkRRect clip_rrect_;
476 const bool is_aa_;
477
479};
480
481class ClipPathEntry : public LayerStateStack::StateEntry {
482 public:
483 ClipPathEntry(const SkPath& clip_path, bool is_aa)
484 : clip_path_(clip_path), is_aa_(is_aa) {}
485 ~ClipPathEntry() override = default;
486
487 void apply(LayerStateStack* stack) const override {
488 stack->delegate_->clipPath(clip_path_, DlCanvas::ClipOp::kIntersect,
489 is_aa_);
490 }
491 void update_mutators(MutatorsStack* mutators_stack) const override {
492 mutators_stack->PushClipPath(clip_path_);
493 }
494
495 private:
496 const SkPath 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);
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 SkRect& bounds, SkScalar opacity) {
541 if (opacity < SK_Scalar1) {
542 layer_state_stack_->push_opacity(bounds, opacity);
543 }
544}
545
547 const SkRect& bounds,
548 const std::shared_ptr<const DlImageFilter>& filter) {
549 if (filter) {
550 layer_state_stack_->push_image_filter(bounds, filter);
551 }
552}
553
555 const SkRect& 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 SkRect& bounds,
564 const std::shared_ptr<const DlImageFilter>& filter,
565 DlBlendMode blend_mode) {
566 layer_state_stack_->push_backdrop(bounds, filter, blend_mode);
567}
568
570 if (!(tx == 0 && ty == 0)) {
571 layer_state_stack_->maybe_save_layer_for_transform(save_needed_);
572 save_needed_ = false;
573 layer_state_stack_->push_translate(tx, ty);
574 }
575}
576
578 if (matrix.isTranslate()) {
579 translate(matrix.getTranslateX(), matrix.getTranslateY());
580 } else if (!matrix.isIdentity()) {
581 layer_state_stack_->maybe_save_layer_for_transform(save_needed_);
582 save_needed_ = false;
583 layer_state_stack_->push_transform(matrix);
584 }
585}
586
589 transform(m44.asM33());
590 } else {
591 layer_state_stack_->maybe_save_layer_for_transform(save_needed_);
592 save_needed_ = false;
593 layer_state_stack_->push_transform(m44);
594 }
595}
596
598 layer_state_stack_->maybe_save_layer_for_transform(save_needed_);
599 save_needed_ = false;
600 layer_state_stack_->push_integral_transform();
601}
602
603void MutatorContext::clipRect(const SkRect& rect, bool is_aa) {
604 layer_state_stack_->maybe_save_layer_for_clip(save_needed_);
605 save_needed_ = false;
606 layer_state_stack_->push_clip_rect(rect, is_aa);
607}
608
609void MutatorContext::clipRRect(const SkRRect& rrect, bool is_aa) {
610 layer_state_stack_->maybe_save_layer_for_clip(save_needed_);
611 save_needed_ = false;
612 layer_state_stack_->push_clip_rrect(rrect, is_aa);
613}
614
615void MutatorContext::clipPath(const SkPath& path, bool is_aa) {
616 layer_state_stack_->maybe_save_layer_for_clip(save_needed_);
617 save_needed_ = false;
618 layer_state_stack_->push_clip_path(path, is_aa);
619}
620
621// ==============================================================
622// LayerStateStack methods
623// ==============================================================
624
626
628 delegate_->decommission();
629 delegate_ = DummyDelegate::kInstance;
630}
631
633 if (delegate_) {
634 if (canvas == delegate_->canvas()) {
635 return;
636 }
638 }
639 if (canvas) {
640 delegate_ = std::make_shared<DlCanvasDelegate>(canvas);
641 reapply_all();
642 }
643}
644
646 set_preroll_delegate(cull_rect, SkMatrix::I());
647}
652 const SkMatrix& matrix) {
654 delegate_ = std::make_shared<PrerollDelegate>(cull_rect, matrix);
655 reapply_all();
656}
657
658void LayerStateStack::reapply_all() {
659 // We use a local RenderingAttributes instance so that it can track the
660 // necessary state changes independently as they occur in the stack.
661 // Reusing |outstanding_| would wreak havoc on the current state of
662 // the stack. When we are finished, though, the local attributes
663 // contents should match the current outstanding_ values;
664 RenderingAttributes attributes = outstanding_;
665 outstanding_ = {};
666 for (auto& state : state_stack_) {
667 state->reapply(this);
668 }
669 FML_DCHECK(attributes == outstanding_);
670}
671
673 for (auto& state : state_stack_) {
674 state->update_mutators(mutators);
675 }
676}
677
678void LayerStateStack::restore_to_count(size_t restore_count) {
679 while (state_stack_.size() > restore_count) {
680 state_stack_.back()->restore(this);
681 state_stack_.pop_back();
682 }
683}
684
685void LayerStateStack::push_opacity(const SkRect& bounds, SkScalar opacity) {
686 maybe_save_layer(opacity);
687 state_stack_.emplace_back(
688 std::make_unique<OpacityEntry>(bounds, opacity, outstanding_));
689 apply_last_entry();
690}
691
692void LayerStateStack::push_color_filter(
693 const SkRect& bounds,
694 const std::shared_ptr<const DlColorFilter>& filter) {
695 maybe_save_layer(filter);
696 state_stack_.emplace_back(
697 std::make_unique<ColorFilterEntry>(bounds, filter, outstanding_));
698 apply_last_entry();
699}
700
701void LayerStateStack::push_image_filter(
702 const SkRect& bounds,
703 const std::shared_ptr<const DlImageFilter>& filter) {
704 maybe_save_layer(filter);
705 state_stack_.emplace_back(
706 std::make_unique<ImageFilterEntry>(bounds, filter, outstanding_));
707 apply_last_entry();
708}
709
710void LayerStateStack::push_backdrop(
711 const SkRect& bounds,
712 const std::shared_ptr<const DlImageFilter>& filter,
713 DlBlendMode blend_mode) {
714 state_stack_.emplace_back(std::make_unique<BackdropFilterEntry>(
715 bounds, filter, blend_mode, outstanding_));
716 apply_last_entry();
717}
718
719void LayerStateStack::push_translate(SkScalar tx, SkScalar ty) {
720 state_stack_.emplace_back(std::make_unique<TranslateEntry>(tx, ty));
721 apply_last_entry();
722}
723
724void LayerStateStack::push_transform(const SkM44& m44) {
725 state_stack_.emplace_back(std::make_unique<TransformM44Entry>(m44));
726 apply_last_entry();
727}
728
729void LayerStateStack::push_transform(const SkMatrix& matrix) {
730 state_stack_.emplace_back(std::make_unique<TransformMatrixEntry>(matrix));
731 apply_last_entry();
732}
733
734void LayerStateStack::push_integral_transform() {
735 state_stack_.emplace_back(std::make_unique<IntegralTransformEntry>());
736 apply_last_entry();
737}
738
739void LayerStateStack::push_clip_rect(const SkRect& rect, bool is_aa) {
740 state_stack_.emplace_back(std::make_unique<ClipRectEntry>(rect, is_aa));
741 apply_last_entry();
742}
743
744void LayerStateStack::push_clip_rrect(const SkRRect& rrect, bool is_aa) {
745 state_stack_.emplace_back(std::make_unique<ClipRRectEntry>(rrect, is_aa));
746 apply_last_entry();
747}
748
749void LayerStateStack::push_clip_path(const SkPath& path, bool is_aa) {
750 state_stack_.emplace_back(std::make_unique<ClipPathEntry>(path, is_aa));
751 apply_last_entry();
752}
753
754bool LayerStateStack::needs_save_layer(int flags) const {
755 if (outstanding_.opacity < SK_Scalar1 &&
757 return true;
758 }
759 if (outstanding_.image_filter &&
761 return true;
762 }
763 if (outstanding_.color_filter &&
765 return true;
766 }
767 return false;
768}
769
770void LayerStateStack::do_save() {
771 state_stack_.emplace_back(std::make_unique<SaveEntry>());
772 apply_last_entry();
773}
774
775void LayerStateStack::save_layer(const SkRect& bounds) {
776 state_stack_.emplace_back(std::make_unique<SaveLayerEntry>(
777 bounds, DlBlendMode::kSrcOver, outstanding_));
778 apply_last_entry();
779}
780
781void LayerStateStack::maybe_save_layer_for_transform(bool save_needed) {
782 // Alpha and ColorFilter don't care about transform
783 if (outstanding_.image_filter) {
784 save_layer(outstanding_.save_layer_bounds);
785 } else if (save_needed) {
786 do_save();
787 }
788}
789
790void LayerStateStack::maybe_save_layer_for_clip(bool save_needed) {
791 // Alpha and ColorFilter don't care about clipping
792 // - Alpha of clipped content == clip of alpha content
793 // - Color-filtering of clipped content == clip of color-filtered content
794 if (outstanding_.image_filter) {
795 save_layer(outstanding_.save_layer_bounds);
796 } else if (save_needed) {
797 do_save();
798 }
799}
800
801void LayerStateStack::maybe_save_layer(int apply_flags) {
802 if (needs_save_layer(apply_flags)) {
803 save_layer(outstanding_.save_layer_bounds);
804 }
805}
806
807void LayerStateStack::maybe_save_layer(SkScalar opacity) {
808 if (outstanding_.image_filter) {
809 save_layer(outstanding_.save_layer_bounds);
810 }
811}
812
813void LayerStateStack::maybe_save_layer(
814 const std::shared_ptr<const DlColorFilter>& filter) {
815 if (outstanding_.color_filter || outstanding_.image_filter ||
816 (outstanding_.opacity < SK_Scalar1 &&
817 !filter->can_commute_with_opacity())) {
818 // TBD: compose the 2 color filters together.
819 save_layer(outstanding_.save_layer_bounds);
820 }
821}
822
823void LayerStateStack::maybe_save_layer(
824 const std::shared_ptr<const DlImageFilter>& filter) {
825 if (outstanding_.image_filter) {
826 // TBD: compose the 2 image filters together.
827 save_layer(outstanding_.save_layer_bounds);
828 }
829}
830
831} // namespace flutter
static void apply_flags(SkFont *font, unsigned flags)
Definition FontTest.cpp:65
static float prev(float f)
static sk_sp< SkImage > color_filter(const SkImage *image, SkColorFilter *colorFilter)
#define SK_Scalar1
Definition SkScalar.h:18
Definition SkM44.h:150
SkMatrix asM33() const
Definition SkM44.h:409
static SkMatrix Translate(SkScalar dx, SkScalar dy)
Definition SkMatrix.h:91
static const SkMatrix & I()
void apply(LayerStateStack *stack) const override
~BackdropFilterEntry() override=default
BackdropFilterEntry(const SkRect &bounds, const std::shared_ptr< const DlImageFilter > &filter, DlBlendMode blend_mode, const LayerStateStack::RenderingAttributes &prev)
void reapply(LayerStateStack *stack) const override
ClipPathEntry(const SkPath &clip_path, bool is_aa)
void apply(LayerStateStack *stack) const override
void update_mutators(MutatorsStack *mutators_stack) const override
~ClipPathEntry() override=default
void apply(LayerStateStack *stack) const override
void update_mutators(MutatorsStack *mutators_stack) const override
ClipRRectEntry(const SkRRect &clip_rrect, bool is_aa)
ClipRectEntry(const SkRect &clip_rect, bool is_aa)
void update_mutators(MutatorsStack *mutators_stack) const override
void apply(LayerStateStack *stack) const override
void restore(LayerStateStack *stack) const override
~ColorFilterEntry() override=default
void apply(LayerStateStack *stack) const override
ColorFilterEntry(const SkRect &bounds, const std::shared_ptr< const DlColorFilter > &filter, const LayerStateStack::RenderingAttributes &prev)
void clipRect(const DlRect &rect, ClipOp op, bool is_aa)
void clipPath(const SkPath &path, ClipOp op, bool is_aa)
void translate(SkScalar tx, SkScalar ty)
void clipRRect(const SkRRect &rrect, ClipOp op, bool is_aa)
bool content_culled(const SkRect &content_bounds) const
void saveLayer(const SkRect &bounds, LayerStateStack::RenderingAttributes &attributes, DlBlendMode blend_mode, const DlImageFilter *backdrop) override
void clipPath(const SkPath &path, ClipOp op, bool is_aa) override
SkRect local_cull_rect() const override
SkM44 matrix_4x4() const override
DlCanvasDelegate(DlCanvas *canvas)
void transform(const SkMatrix &matrix) override
void clipRRect(const SkRRect &rrect, ClipOp op, bool is_aa) override
void transform(const SkM44 &m44) override
bool content_culled(const SkRect &content_bounds) const override
SkMatrix matrix_3x3() const override
DlCanvas * canvas() const override
void translate(SkScalar tx, SkScalar ty) override
void clipRect(const SkRect &rect, ClipOp op, bool is_aa) override
SkRect device_cull_rect() const override
Developer-facing API for rendering anything within the engine.
Definition dl_canvas.h:37
virtual void Transform(const SkMatrix *matrix)=0
virtual void ClipRect(const SkRect &rect, ClipOp clip_op=ClipOp::kIntersect, bool is_aa=false)=0
virtual SkM44 GetTransformFullPerspective() const =0
virtual void SetTransform(const SkMatrix *matrix)=0
virtual SkRect GetDestinationClipBounds() const =0
virtual void SaveLayer(const SkRect *bounds, const DlPaint *paint=nullptr, const DlImageFilter *backdrop=nullptr)=0
virtual SkRect GetLocalClipBounds() const =0
virtual bool QuickReject(const SkRect &bounds) const =0
virtual void Restore()=0
virtual void RestoreToCount(int restore_count)=0
virtual void Translate(SkScalar tx, SkScalar ty)=0
virtual SkMatrix GetTransform() const =0
virtual void ClipPath(const SkPath &path, ClipOp clip_op=ClipOp::kIntersect, bool is_aa=false)=0
virtual void ClipRRect(const SkRRect &rrect, ClipOp clip_op=ClipOp::kIntersect, bool is_aa=false)=0
virtual void Save()=0
bool content_culled(const SkRect &content_bounds) const override
static const std::shared_ptr< DummyDelegate > kInstance
SkM44 matrix_4x4() const override
void clipRRect(const SkRRect &rrect, ClipOp op, bool is_aa) override
void integralTransform() override
void saveLayer(const SkRect &bounds, LayerStateStack::RenderingAttributes &attributes, DlBlendMode blend, const DlImageFilter *backdrop) override
SkRect local_cull_rect() const override
void clipPath(const SkPath &path, ClipOp op, bool is_aa) override
void transform(const SkM44 &m44) override
SkRect device_cull_rect() const override
void translate(SkScalar tx, SkScalar ty) override
void clipRect(const SkRect &rect, ClipOp op, bool is_aa) override
SkMatrix matrix_3x3() const override
void transform(const SkMatrix &matrix) override
~ImageFilterEntry() override=default
void apply(LayerStateStack *stack) const override
void restore(LayerStateStack *stack) const override
ImageFilterEntry(const SkRect &bounds, const std::shared_ptr< const DlImageFilter > &filter, const LayerStateStack::RenderingAttributes &prev)
void apply(LayerStateStack *stack) const override
void applyColorFilter(const SkRect &bounds, const std::shared_ptr< const DlColorFilter > &filter)
void translate(SkScalar tx, SkScalar ty)
void applyImageFilter(const SkRect &bounds, const std::shared_ptr< const DlImageFilter > &filter)
void clipPath(const SkPath &path, bool is_aa)
void applyBackdropFilter(const SkRect &bounds, const std::shared_ptr< const DlImageFilter > &filter, DlBlendMode blend_mode)
void clipRRect(const SkRRect &rrect, bool is_aa)
void clipRect(const SkRect &rect, bool is_aa)
void applyOpacity(const SkRect &bounds, SkScalar opacity)
void fill(MutatorsStack *mutators)
void set_preroll_delegate(const SkRect &cull_rect, const SkMatrix &matrix)
static constexpr int kCallerCanApplyColorFilter
void set_delegate(DlCanvas *canvas)
static constexpr int kCallerCanApplyImageFilter
static constexpr int kCallerCanApplyOpacity
void PushClipPath(const SkPath &path)
void PushOpacity(const int &alpha)
void PushClipRect(const SkRect &rect)
void PushTransform(const SkMatrix &matrix)
void PushClipRRect(const SkRRect &rrect)
void update_mutators(MutatorsStack *mutators_stack) const override
void restore(LayerStateStack *stack) const override
OpacityEntry(const SkRect &bounds, SkScalar opacity, const LayerStateStack::RenderingAttributes &prev)
void apply(LayerStateStack *stack) const override
void clipRect(const SkRect &rect, ClipOp op, bool is_aa) override
SkMatrix matrix_3x3() const override
void clipRRect(const SkRRect &rrect, ClipOp op, bool is_aa) override
bool content_culled(const SkRect &content_bounds) const override
void clipPath(const SkPath &path, ClipOp op, bool is_aa) override
void saveLayer(const SkRect &bounds, LayerStateStack::RenderingAttributes &attributes, DlBlendMode blend, const DlImageFilter *backdrop) override
SkRect device_cull_rect() const override
SkRect local_cull_rect() const override
void transform(const SkMatrix &matrix) override
void transform(const SkM44 &m44) override
SkM44 matrix_4x4() const override
void translate(SkScalar tx, SkScalar ty) override
PrerollDelegate(const SkRect &cull_rect, const SkMatrix &matrix)
FML_DISALLOW_COPY_ASSIGN_AND_MOVE(SaveEntry)
void apply(LayerStateStack *stack) const override
void restore(LayerStateStack *stack) const override
const LayerStateStack::RenderingAttributes old_attributes_
SaveLayerEntry(const SkRect &bounds, DlBlendMode blend_mode, const LayerStateStack::RenderingAttributes &prev)
void apply(LayerStateStack *stack) const override
void restore(LayerStateStack *stack) const override
FML_DISALLOW_COPY_ASSIGN_AND_MOVE(SaveLayerEntry)
const DlBlendMode blend_mode_
TransformM44Entry(const SkM44 &m44)
void apply(LayerStateStack *stack) const override
void update_mutators(MutatorsStack *mutators_stack) const override
void update_mutators(MutatorsStack *mutators_stack) const override
TransformMatrixEntry(const SkMatrix &matrix)
void apply(LayerStateStack *stack) const override
void apply(LayerStateStack *stack) const override
void update_mutators(MutatorsStack *mutators_stack) const override
TranslateEntry(SkScalar tx, SkScalar ty)
const Paint & paint
float SkScalar
Definition extension.cpp:12
AtkStateType state
FlutterSemanticsFlag flags
#define FML_DCHECK(condition)
Definition logging.h:103
#define FML_DISALLOW_COPY_ASSIGN_AND_MOVE(TypeName)
Definition macros.h:31
static SkColor blend(SkColor dst, SkColor src, void(*mode)(float, float, float, float *, float *, float *))
Definition hsl.cpp:142
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 switches.h:57
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
Definition switches.h:228
static constexpr SkRect kGiantRect
Definition layer.h:49
@ kSrcOver
r = s + (1-sa)*d
static constexpr uint8_t toAlpha(SkScalar opacity)
Definition dl_color.h:17
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|.
#define TRACE_EVENT0(category_group, name)