Flutter Engine
The Flutter Engine
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 save_stack_.emplace_back(cull_rect, matrix);
142 }
143
144 void decommission() override {}
145
146 SkM44 matrix_4x4() const override { return state().matrix_4x4(); }
147 SkMatrix matrix_3x3() const override { return state().matrix_3x3(); }
148 SkRect local_cull_rect() const override { return state().local_cull_rect(); }
149 SkRect device_cull_rect() const override {
150 return state().device_cull_rect();
151 }
152 bool content_culled(const SkRect& content_bounds) const override {
153 return state().content_culled(content_bounds);
154 }
155
156 void save() override { save_stack_.emplace_back(state()); }
158 LayerStateStack::RenderingAttributes& attributes,
160 const DlImageFilter* backdrop) override {
161 save_stack_.emplace_back(state());
162 }
163 void restore() override { save_stack_.pop_back(); }
164
165 void translate(SkScalar tx, SkScalar ty) override {
166 state().translate(tx, ty);
167 }
168 void transform(const SkM44& m44) override { state().transform(m44); }
169 void transform(const SkMatrix& matrix) override { state().transform(matrix); }
170 void integralTransform() override {
171 if (state().using_4x4_matrix()) {
172 SkM44 integral;
174 &integral)) {
175 state().setTransform(integral);
176 }
177 } else {
178 SkMatrix integral;
180 &integral)) {
181 state().setTransform(integral);
182 }
183 }
184 }
185
186 void clipRect(const SkRect& rect, ClipOp op, bool is_aa) override {
187 state().clipRect(rect, op, is_aa);
188 }
189 void clipRRect(const SkRRect& rrect, ClipOp op, bool is_aa) override {
190 state().clipRRect(rrect, op, is_aa);
191 }
192 void clipPath(const SkPath& path, ClipOp 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:
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:
249 SkScalar 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 SkRect bounds_;
270 const SkScalar opacity_;
271 const SkScalar old_opacity_;
272 const SkRect old_bounds_;
273
274 FML_DISALLOW_COPY_ASSIGN_AND_MOVE(OpacityEntry);
275};
276
277class ImageFilterEntry : public LayerStateStack::StateEntry {
278 public:
280 const std::shared_ptr<const 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 SkRect bounds_;
302 const std::shared_ptr<const DlImageFilter> filter_;
303 const std::shared_ptr<const DlImageFilter> old_filter_;
304 const SkRect old_bounds_;
305
306 FML_DISALLOW_COPY_ASSIGN_AND_MOVE(ImageFilterEntry);
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 SkRect bounds_;
334 const std::shared_ptr<const DlColorFilter> filter_;
335 const std::shared_ptr<const DlColorFilter> old_filter_;
336 const SkRect old_bounds_;
337
338 FML_DISALLOW_COPY_ASSIGN_AND_MOVE(ColorFilterEntry);
339};
340
342 public:
344 const std::shared_ptr<const DlImageFilter>& filter,
345 DlBlendMode blend_mode,
346 const LayerStateStack::RenderingAttributes& prev)
347 : SaveLayerEntry(bounds, blend_mode, prev), filter_(filter) {}
348 ~BackdropFilterEntry() override = default;
349
350 void apply(LayerStateStack* stack) const override {
351 stack->delegate_->saveLayer(bounds_, stack->outstanding_, blend_mode_,
352 filter_.get());
353 stack->outstanding_ = {};
354 }
355
356 void reapply(LayerStateStack* stack) const override {
357 // On the reapply for subsequent overlay layers, we do not
358 // want to reapply the backdrop filter, but we do need to
359 // do a saveLayer to encapsulate the contents and match the
360 // restore that will be forthcoming. Note that this is not
361 // perfect if the BlendMode is not associative as we will be
362 // compositing multiple parts of the content in batches.
363 // Luckily the most common SrcOver is associative.
365 }
366
367 private:
368 const std::shared_ptr<const DlImageFilter> filter_;
369
370 FML_DISALLOW_COPY_ASSIGN_AND_MOVE(BackdropFilterEntry);
371};
372
373class TranslateEntry : public LayerStateStack::StateEntry {
374 public:
375 TranslateEntry(SkScalar tx, SkScalar ty) : tx_(tx), ty_(ty) {}
376
377 void apply(LayerStateStack* stack) const override {
378 stack->delegate_->translate(tx_, ty_);
379 }
380 void update_mutators(MutatorsStack* mutators_stack) const override {
381 mutators_stack->PushTransform(SkMatrix::Translate(tx_, ty_));
382 }
383
384 private:
385 const SkScalar tx_;
386 const SkScalar ty_;
387
388 FML_DISALLOW_COPY_ASSIGN_AND_MOVE(TranslateEntry);
389};
390
391class TransformMatrixEntry : public LayerStateStack::StateEntry {
392 public:
393 explicit TransformMatrixEntry(const SkMatrix& matrix) : matrix_(matrix) {}
394
395 void apply(LayerStateStack* stack) const override {
396 stack->delegate_->transform(matrix_);
397 }
398 void update_mutators(MutatorsStack* mutators_stack) const override {
399 mutators_stack->PushTransform(matrix_);
400 }
401
402 private:
403 const SkMatrix matrix_;
404
405 FML_DISALLOW_COPY_ASSIGN_AND_MOVE(TransformMatrixEntry);
406};
407
408class TransformM44Entry : public LayerStateStack::StateEntry {
409 public:
410 explicit TransformM44Entry(const SkM44& m44) : m44_(m44) {}
411
412 void apply(LayerStateStack* stack) const override {
413 stack->delegate_->transform(m44_);
414 }
415 void update_mutators(MutatorsStack* mutators_stack) const override {
416 mutators_stack->PushTransform(m44_.asM33());
417 }
418
419 private:
420 const SkM44 m44_;
421
422 FML_DISALLOW_COPY_ASSIGN_AND_MOVE(TransformM44Entry);
423};
424
425class IntegralTransformEntry : public LayerStateStack::StateEntry {
426 public:
428
429 void apply(LayerStateStack* stack) const override {
430 stack->delegate_->integralTransform();
431 }
432
433 private:
434 FML_DISALLOW_COPY_ASSIGN_AND_MOVE(IntegralTransformEntry);
435};
436
437class ClipRectEntry : public LayerStateStack::StateEntry {
438 public:
439 ClipRectEntry(const SkRect& clip_rect, bool is_aa)
440 : clip_rect_(clip_rect), is_aa_(is_aa) {}
441
442 void apply(LayerStateStack* stack) const override {
443 stack->delegate_->clipRect(clip_rect_, DlCanvas::ClipOp::kIntersect,
444 is_aa_);
445 }
446 void update_mutators(MutatorsStack* mutators_stack) const override {
447 mutators_stack->PushClipRect(clip_rect_);
448 }
449
450 private:
451 const SkRect clip_rect_;
452 const bool is_aa_;
453
454 FML_DISALLOW_COPY_ASSIGN_AND_MOVE(ClipRectEntry);
455};
456
457class ClipRRectEntry : public LayerStateStack::StateEntry {
458 public:
459 ClipRRectEntry(const SkRRect& clip_rrect, bool is_aa)
460 : clip_rrect_(clip_rrect), is_aa_(is_aa) {}
461
462 void apply(LayerStateStack* stack) const override {
463 stack->delegate_->clipRRect(clip_rrect_, DlCanvas::ClipOp::kIntersect,
464 is_aa_);
465 }
466 void update_mutators(MutatorsStack* mutators_stack) const override {
467 mutators_stack->PushClipRRect(clip_rrect_);
468 }
469
470 private:
471 const SkRRect clip_rrect_;
472 const bool is_aa_;
473
474 FML_DISALLOW_COPY_ASSIGN_AND_MOVE(ClipRRectEntry);
475};
476
477class ClipPathEntry : public LayerStateStack::StateEntry {
478 public:
479 ClipPathEntry(const SkPath& clip_path, bool is_aa)
480 : clip_path_(clip_path), is_aa_(is_aa) {}
481 ~ClipPathEntry() override = default;
482
483 void apply(LayerStateStack* stack) const override {
484 stack->delegate_->clipPath(clip_path_, DlCanvas::ClipOp::kIntersect,
485 is_aa_);
486 }
487 void update_mutators(MutatorsStack* mutators_stack) const override {
488 mutators_stack->PushClipPath(clip_path_);
489 }
490
491 private:
492 const SkPath clip_path_;
493 const bool is_aa_;
494
495 FML_DISALLOW_COPY_ASSIGN_AND_MOVE(ClipPathEntry);
496};
497
498// ==============================================================
499// RenderingAttributes methods
500// ==============================================================
501
502DlPaint* LayerStateStack::RenderingAttributes::fill(DlPaint& paint,
503 DlBlendMode mode) const {
504 DlPaint* ret = nullptr;
505 if (opacity < SK_Scalar1) {
506 paint.setOpacity(std::max(opacity, 0.0f));
507 ret = &paint;
508 } else {
509 paint.setOpacity(SK_Scalar1);
510 }
511 paint.setColorFilter(color_filter);
512 if (color_filter) {
513 ret = &paint;
514 }
515 paint.setImageFilter(image_filter);
516 if (image_filter) {
517 ret = &paint;
518 }
519 paint.setBlendMode(mode);
521 ret = &paint;
522 }
523 return ret;
524}
525
526// ==============================================================
527// MutatorContext methods
528// ==============================================================
529
531
533 layer_state_stack_->save_layer(bounds);
534}
535
537 if (opacity < SK_Scalar1) {
538 layer_state_stack_->push_opacity(bounds, opacity);
539 }
540}
541
543 const SkRect& bounds,
544 const std::shared_ptr<const DlImageFilter>& filter) {
545 if (filter) {
546 layer_state_stack_->push_image_filter(bounds, filter);
547 }
548}
549
551 const SkRect& bounds,
552 const std::shared_ptr<const DlColorFilter>& filter) {
553 if (filter) {
554 layer_state_stack_->push_color_filter(bounds, filter);
555 }
556}
557
559 const SkRect& bounds,
560 const std::shared_ptr<const DlImageFilter>& filter,
561 DlBlendMode blend_mode) {
562 layer_state_stack_->push_backdrop(bounds, filter, blend_mode);
563}
564
566 if (!(tx == 0 && ty == 0)) {
567 layer_state_stack_->maybe_save_layer_for_transform(save_needed_);
568 save_needed_ = false;
569 layer_state_stack_->push_translate(tx, ty);
570 }
571}
572
574 if (matrix.isTranslate()) {
575 translate(matrix.getTranslateX(), matrix.getTranslateY());
576 } else if (!matrix.isIdentity()) {
577 layer_state_stack_->maybe_save_layer_for_transform(save_needed_);
578 save_needed_ = false;
579 layer_state_stack_->push_transform(matrix);
580 }
581}
582
585 transform(m44.asM33());
586 } else {
587 layer_state_stack_->maybe_save_layer_for_transform(save_needed_);
588 save_needed_ = false;
589 layer_state_stack_->push_transform(m44);
590 }
591}
592
594 layer_state_stack_->maybe_save_layer_for_transform(save_needed_);
595 save_needed_ = false;
596 layer_state_stack_->push_integral_transform();
597}
598
599void MutatorContext::clipRect(const SkRect& rect, bool is_aa) {
600 layer_state_stack_->maybe_save_layer_for_clip(save_needed_);
601 save_needed_ = false;
602 layer_state_stack_->push_clip_rect(rect, is_aa);
603}
604
605void MutatorContext::clipRRect(const SkRRect& rrect, bool is_aa) {
606 layer_state_stack_->maybe_save_layer_for_clip(save_needed_);
607 save_needed_ = false;
608 layer_state_stack_->push_clip_rrect(rrect, is_aa);
609}
610
611void MutatorContext::clipPath(const SkPath& path, bool is_aa) {
612 layer_state_stack_->maybe_save_layer_for_clip(save_needed_);
613 save_needed_ = false;
614 layer_state_stack_->push_clip_path(path, is_aa);
615}
616
617// ==============================================================
618// LayerStateStack methods
619// ==============================================================
620
622
624 delegate_->decommission();
625 delegate_ = DummyDelegate::kInstance;
626}
627
629 if (delegate_) {
630 if (canvas == delegate_->canvas()) {
631 return;
632 }
634 }
635 if (canvas) {
636 delegate_ = std::make_shared<DlCanvasDelegate>(canvas);
637 reapply_all();
638 }
639}
640
642 set_preroll_delegate(cull_rect, SkMatrix::I());
643}
646}
648 const SkMatrix& matrix) {
650 delegate_ = std::make_shared<PrerollDelegate>(cull_rect, matrix);
651 reapply_all();
652}
653
654void LayerStateStack::reapply_all() {
655 // We use a local RenderingAttributes instance so that it can track the
656 // necessary state changes independently as they occur in the stack.
657 // Reusing |outstanding_| would wreak havoc on the current state of
658 // the stack. When we are finished, though, the local attributes
659 // contents should match the current outstanding_ values;
660 RenderingAttributes attributes = outstanding_;
661 outstanding_ = {};
662 for (auto& state : state_stack_) {
663 state->reapply(this);
664 }
665 FML_DCHECK(attributes == outstanding_);
666}
667
669 for (auto& state : state_stack_) {
670 state->update_mutators(mutators);
671 }
672}
673
674void LayerStateStack::restore_to_count(size_t restore_count) {
675 while (state_stack_.size() > restore_count) {
676 state_stack_.back()->restore(this);
677 state_stack_.pop_back();
678 }
679}
680
681void LayerStateStack::push_opacity(const SkRect& bounds, SkScalar opacity) {
682 maybe_save_layer(opacity);
683 state_stack_.emplace_back(
684 std::make_unique<OpacityEntry>(bounds, opacity, outstanding_));
685 apply_last_entry();
686}
687
688void LayerStateStack::push_color_filter(
689 const SkRect& bounds,
690 const std::shared_ptr<const DlColorFilter>& filter) {
691 maybe_save_layer(filter);
692 state_stack_.emplace_back(
693 std::make_unique<ColorFilterEntry>(bounds, filter, outstanding_));
694 apply_last_entry();
695}
696
697void LayerStateStack::push_image_filter(
698 const SkRect& bounds,
699 const std::shared_ptr<const DlImageFilter>& filter) {
700 maybe_save_layer(filter);
701 state_stack_.emplace_back(
702 std::make_unique<ImageFilterEntry>(bounds, filter, outstanding_));
703 apply_last_entry();
704}
705
706void LayerStateStack::push_backdrop(
707 const SkRect& bounds,
708 const std::shared_ptr<const DlImageFilter>& filter,
709 DlBlendMode blend_mode) {
710 state_stack_.emplace_back(std::make_unique<BackdropFilterEntry>(
711 bounds, filter, blend_mode, outstanding_));
712 apply_last_entry();
713}
714
715void LayerStateStack::push_translate(SkScalar tx, SkScalar ty) {
716 state_stack_.emplace_back(std::make_unique<TranslateEntry>(tx, ty));
717 apply_last_entry();
718}
719
720void LayerStateStack::push_transform(const SkM44& m44) {
721 state_stack_.emplace_back(std::make_unique<TransformM44Entry>(m44));
722 apply_last_entry();
723}
724
725void LayerStateStack::push_transform(const SkMatrix& matrix) {
726 state_stack_.emplace_back(std::make_unique<TransformMatrixEntry>(matrix));
727 apply_last_entry();
728}
729
730void LayerStateStack::push_integral_transform() {
731 state_stack_.emplace_back(std::make_unique<IntegralTransformEntry>());
732 apply_last_entry();
733}
734
735void LayerStateStack::push_clip_rect(const SkRect& rect, bool is_aa) {
736 state_stack_.emplace_back(std::make_unique<ClipRectEntry>(rect, is_aa));
737 apply_last_entry();
738}
739
740void LayerStateStack::push_clip_rrect(const SkRRect& rrect, bool is_aa) {
741 state_stack_.emplace_back(std::make_unique<ClipRRectEntry>(rrect, is_aa));
742 apply_last_entry();
743}
744
745void LayerStateStack::push_clip_path(const SkPath& path, bool is_aa) {
746 state_stack_.emplace_back(std::make_unique<ClipPathEntry>(path, is_aa));
747 apply_last_entry();
748}
749
750bool LayerStateStack::needs_save_layer(int flags) const {
751 if (outstanding_.opacity < SK_Scalar1 &&
753 return true;
754 }
755 if (outstanding_.image_filter &&
757 return true;
758 }
759 if (outstanding_.color_filter &&
761 return true;
762 }
763 return false;
764}
765
766void LayerStateStack::do_save() {
767 state_stack_.emplace_back(std::make_unique<SaveEntry>());
768 apply_last_entry();
769}
770
771void LayerStateStack::save_layer(const SkRect& bounds) {
772 state_stack_.emplace_back(std::make_unique<SaveLayerEntry>(
773 bounds, DlBlendMode::kSrcOver, outstanding_));
774 apply_last_entry();
775}
776
777void LayerStateStack::maybe_save_layer_for_transform(bool save_needed) {
778 // Alpha and ColorFilter don't care about transform
779 if (outstanding_.image_filter) {
780 save_layer(outstanding_.save_layer_bounds);
781 } else if (save_needed) {
782 do_save();
783 }
784}
785
786void LayerStateStack::maybe_save_layer_for_clip(bool save_needed) {
787 // Alpha and ColorFilter don't care about clipping
788 // - Alpha of clipped content == clip of alpha content
789 // - Color-filtering of clipped content == clip of color-filtered content
790 if (outstanding_.image_filter) {
791 save_layer(outstanding_.save_layer_bounds);
792 } else if (save_needed) {
793 do_save();
794 }
795}
796
797void LayerStateStack::maybe_save_layer(int apply_flags) {
798 if (needs_save_layer(apply_flags)) {
799 save_layer(outstanding_.save_layer_bounds);
800 }
801}
802
803void LayerStateStack::maybe_save_layer(SkScalar opacity) {
804 if (outstanding_.image_filter) {
805 save_layer(outstanding_.save_layer_bounds);
806 }
807}
808
809void LayerStateStack::maybe_save_layer(
810 const std::shared_ptr<const DlColorFilter>& filter) {
811 if (outstanding_.color_filter || outstanding_.image_filter ||
812 (outstanding_.opacity < SK_Scalar1 &&
813 !filter->can_commute_with_opacity())) {
814 // TBD: compose the 2 color filters together.
815 save_layer(outstanding_.save_layer_bounds);
816 }
817}
818
819void LayerStateStack::maybe_save_layer(
820 const std::shared_ptr<const DlImageFilter>& filter) {
821 if (outstanding_.image_filter) {
822 // TBD: compose the 2 image filters together.
823 save_layer(outstanding_.save_layer_bounds);
824 }
825}
826
827} // 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()
Definition: SkMatrix.cpp:1544
Definition: SkPath.h:59
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 clipRRect(const SkRRect &rrect, ClipOp op, bool is_aa)
void clipRect(const DlRect &rect, ClipOp op, bool is_aa)
void setTransform(const DlMatrix &matrix)
void clipPath(const SkPath &path, ClipOp op, bool is_aa)
bool content_culled(const DlRect &content_bounds) const
void transform(const DlMatrix &matrix)
static bool is_3x3(const SkM44 &m44)
void translate(SkScalar tx, SkScalar ty)
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:38
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 decommission() 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
void integralTransform() 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
Definition: color_source.cc:38
float SkScalar
Definition: extension.cpp:12
AtkStateType state
FlutterSemanticsFlag flags
#define FML_DCHECK(condition)
Definition: logging.h:103
static SkColor blend(SkColor dst, SkColor src, void(*mode)(float, float, float, float *, float *, float *))
Definition: hsl.cpp:142
static float max(float r, float g, float b)
Definition: hsl.cpp:49
unsigned useCenter Optional< SkMatrix > matrix
Definition: SkRecords.h:258
Optional< SkRect > bounds
Definition: SkRecords.h:189
sk_sp< const SkImageFilter > backdrop
Definition: SkRecords.h:191
SkRRect rrect
Definition: SkRecords.h:232
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
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:50
@ kSrcOver
r = s + (1-sa)*d
flutter::DlPaint DlPaint
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)
Definition: trace_event.h:131