Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
dl_builder.h
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#ifndef FLUTTER_DISPLAY_LIST_DL_BUILDER_H_
6#define FLUTTER_DISPLAY_LIST_DL_BUILDER_H_
7
20#include "flutter/fml/macros.h"
21
22namespace flutter {
23
24// The primary class used to build a display list. The list of methods
25// here matches the list of methods invoked on a |DlOpReceiver| combined
26// with the list of methods invoked on a |DlCanvas|.
27class DisplayListBuilder final : public virtual DlCanvas,
28 public SkRefCnt,
29 virtual DlOpReceiver,
31 public:
32 static constexpr DlRect kMaxCullRect =
33 DlRect::MakeLTRB(-1E9F, -1E9F, 1E9F, 1E9F);
34
35 explicit DisplayListBuilder(bool prepare_rtree)
36 : DisplayListBuilder(kMaxCullRect, prepare_rtree) {}
37
38 explicit DisplayListBuilder(const DlRect& cull_rect = kMaxCullRect,
39 bool prepare_rtree = false);
40
43
45
46 // |DlCanvas|
47 DlISize GetBaseLayerDimensions() const override;
48 // |DlCanvas|
49 SkImageInfo GetImageInfo() const override;
50
51 /// @brief Return the number of records currently recorded in the
52 /// builder.
53 /// @return The number of records already recorded.
54 size_t GetRecordCount() const;
55
56 /// @brief Return true if the builder has not yet recorded any commands.
57 /// @return Whether the builder is empty.
58 bool IsEmpty() const;
59
60 // |DlCanvas|
61 void Save() override;
62
63 // |DlCanvas|
64 void SaveLayer(const std::optional<DlRect>& bounds,
65 const DlPaint* paint = nullptr,
66 const DlImageFilter* backdrop = nullptr,
67 std::optional<int64_t> backdrop_id = std::nullopt) override;
68 // |DlCanvas|
69 void Restore() override;
70 // |DlCanvas|
71 int GetSaveCount() const override { return save_stack_.size(); }
72 // |DlCanvas|
73 void RestoreToCount(int restore_count) override;
74
75 // |DlCanvas|
76 void Translate(DlScalar tx, DlScalar ty) override;
77 // |DlCanvas|
78 void Scale(DlScalar sx, DlScalar sy) override;
79 // |DlCanvas|
80 void Rotate(DlScalar degrees) override;
81 // |DlCanvas|
82 void Skew(DlScalar sx, DlScalar sy) override;
83
84 // clang-format off
85 // 2x3 2D affine subset of a 4x4 transform in row major order
86 // |DlCanvas|
88 DlScalar myx, DlScalar myy, DlScalar myt) override;
89 // full 4x4 transform in row major order
90 // |DlCanvas|
92 DlScalar mxx, DlScalar mxy, DlScalar mxz, DlScalar mxt,
93 DlScalar myx, DlScalar myy, DlScalar myz, DlScalar myt,
94 DlScalar mzx, DlScalar mzy, DlScalar mzz, DlScalar mzt,
95 DlScalar mwx, DlScalar mwy, DlScalar mwz, DlScalar mwt) override;
96 // clang-format on
97 // |DlCanvas|
98 void TransformReset() override;
99 // |DlCanvas|
100 void Transform(const DlMatrix& matrix) override;
101 // |DlCanvas|
102 void SetTransform(const DlMatrix& matrix) override {
104 Transform(matrix);
105 }
106
107 /// Returns the 4x4 full perspective transform representing all transform
108 /// operations executed so far in this DisplayList within the enclosing
109 /// save stack.
110 // |DlCanvas|
111 DlMatrix GetMatrix() const override { return global_state().matrix(); }
112
113 // |DlCanvas|
114 void ClipRect(const DlRect& rect,
116 bool is_aa = false) override;
117 // |DlCanvas|
118 void ClipOval(const DlRect& bounds,
120 bool is_aa = false) override;
121 // |DlCanvas|
122 void ClipRoundRect(const DlRoundRect& rrect,
124 bool is_aa = false) override;
125 // |DlCanvas|
128 bool is_aa = false) override;
129 // |DlCanvas|
130 void ClipPath(const DlPath& path,
132 bool is_aa = false) override;
133
134 /// Conservative estimate of the bounds of all outstanding clip operations
135 /// measured in the coordinate space within which this DisplayList will
136 /// be rendered.
137 // |DlCanvas|
139 return global_state().GetDeviceCullCoverage();
140 }
141 /// Conservative estimate of the bounds of all outstanding clip operations
142 /// transformed into the local coordinate space in which currently
143 /// recorded rendering operations are interpreted.
144 // |DlCanvas|
145 DlRect GetLocalClipCoverage() const override {
146 return global_state().GetLocalCullCoverage();
147 }
148
149 /// Return true iff the supplied bounds are easily shown to be outside
150 /// of the current clip bounds. This method may conservatively return
151 /// false if it cannot make the determination.
152 // |DlCanvas|
153 bool QuickReject(const DlRect& bounds) const override;
154
155 // |DlCanvas|
156 void DrawPaint(const DlPaint& paint) override;
157 // |DlCanvas|
158 void DrawColor(DlColor color, DlBlendMode mode) override;
159 // |DlCanvas|
160 void DrawLine(const DlPoint& p0,
161 const DlPoint& p1,
162 const DlPaint& paint) override;
163 // |DlCanvas|
164 void DrawDashedLine(const DlPoint& p0,
165 const DlPoint& p1,
166 DlScalar on_length,
167 DlScalar off_length,
168 const DlPaint& paint) override;
169 // |DlCanvas|
170 void DrawRect(const DlRect& rect, const DlPaint& paint) override;
171 // |DlCanvas|
172 void DrawOval(const DlRect& bounds, const DlPaint& paint) override;
173 // |DlCanvas|
174 void DrawCircle(const DlPoint& center,
175 DlScalar radius,
176 const DlPaint& paint) override;
177 // |DlCanvas|
178 void DrawRoundRect(const DlRoundRect& rrect, const DlPaint& paint) override;
179 // |DlCanvas|
180 void DrawDiffRoundRect(const DlRoundRect& outer,
181 const DlRoundRect& inner,
182 const DlPaint& paint) override;
183 // |DlCanvas|
185 const DlPaint& paint) override;
186 // |DlCanvas|
187 void DrawPath(const DlPath& path, const DlPaint& paint) override;
188 // |DlCanvas|
189 void DrawArc(const DlRect& bounds,
190 DlScalar start,
191 DlScalar sweep,
192 bool useCenter,
193 const DlPaint& paint) override;
194 // |DlCanvas|
195 void DrawPoints(DlPointMode mode,
196 uint32_t count,
197 const DlPoint pts[],
198 const DlPaint& paint) override;
199 // |DlCanvas|
200 void DrawVertices(const std::shared_ptr<DlVertices>& vertices,
201 DlBlendMode mode,
202 const DlPaint& paint) override;
203 // |DlCanvas|
204 void DrawImage(const sk_sp<DlImage>& image,
205 const DlPoint& point,
206 DlImageSampling sampling,
207 const DlPaint* paint = nullptr) override;
208 // |DlCanvas|
209 void DrawImageRect(
210 const sk_sp<DlImage>& image,
211 const DlRect& src,
212 const DlRect& dst,
213 DlImageSampling sampling,
214 const DlPaint* paint = nullptr,
215 DlSrcRectConstraint constraint = DlSrcRectConstraint::kFast) override;
216 // include overloads from the virtual base class
218
219 // |DlCanvas|
220 void DrawImageNine(const sk_sp<DlImage>& image,
221 const DlIRect& center,
222 const DlRect& dst,
223 DlFilterMode filter,
224 const DlPaint* paint = nullptr) override;
225 // |DlCanvas|
226 void DrawAtlas(const sk_sp<DlImage>& atlas,
227 const DlRSTransform xform[],
228 const DlRect tex[],
229 const DlColor colors[],
230 int count,
231 DlBlendMode mode,
232 DlImageSampling sampling,
233 const DlRect* cullRect,
234 const DlPaint* paint = nullptr) override;
235 // |DlCanvas|
236 void DrawDisplayList(const sk_sp<DisplayList> display_list,
237 DlScalar opacity = SK_Scalar1) override;
238 // |DlCanvas|
239 void DrawText(const std::shared_ptr<DlText>& text,
240 DlScalar x,
241 DlScalar y,
242 const DlPaint& paint) override;
243
244 // |DlCanvas|
245 void DrawShadow(const DlPath& path,
246 const DlColor color,
247 const DlScalar elevation,
248 bool transparent_occluder,
249 DlScalar dpr) override;
250
251 // |DlCanvas|
252 void Flush() override {}
253
254 sk_sp<DisplayList> Build();
255
256 private:
257 void Init(bool prepare_rtree);
258
259 // This method exposes the internal stateful DlOpReceiver implementation
260 // of the DisplayListBuilder, primarily for testing purposes. Its use
261 // is obsolete and forbidden in every other case and is only shared to a
262 // pair of "friend" accessors in the benchmark/unittest files.
263 DlOpReceiver& asReceiver() { return *this; }
264
265 friend DlOpReceiver& DisplayListBuilderBenchmarkAccessor(
266 DisplayListBuilder& builder);
267 friend DlOpReceiver& DisplayListBuilderTestingAccessor(
268 DisplayListBuilder& builder);
270 DisplayListBuilder& builder);
271 friend int DisplayListBuilderTestingLastOpIndex(DisplayListBuilder& builder);
272
273 void SetAttributesFromPaint(const DlPaint& paint,
274 const DisplayListAttributeFlags flags);
275
276 // |DlOpReceiver|
277 void setAntiAlias(bool aa) override {
278 if (current_.isAntiAlias() != aa) {
279 onSetAntiAlias(aa);
280 }
281 }
282 // |DlOpReceiver|
283 void setInvertColors(bool invert) override {
284 if (current_.isInvertColors() != invert) {
285 onSetInvertColors(invert);
286 }
287 }
288 // |DlOpReceiver|
289 void setStrokeCap(DlStrokeCap cap) override {
290 if (current_.getStrokeCap() != cap) {
291 onSetStrokeCap(cap);
292 }
293 }
294 // |DlOpReceiver|
295 void setStrokeJoin(DlStrokeJoin join) override {
296 if (current_.getStrokeJoin() != join) {
297 onSetStrokeJoin(join);
298 }
299 }
300 // |DlOpReceiver|
301 void setDrawStyle(DlDrawStyle style) override {
302 if (current_.getDrawStyle() != style) {
303 onSetDrawStyle(style);
304 }
305 }
306 // |DlOpReceiver|
307 void setStrokeWidth(float width) override {
308 if (current_.getStrokeWidth() != width) {
309 onSetStrokeWidth(width);
310 }
311 }
312 // |DlOpReceiver|
313 void setStrokeMiter(float limit) override {
314 if (current_.getStrokeMiter() != limit) {
315 onSetStrokeMiter(limit);
316 }
317 }
318 // |DlOpReceiver|
319 void setColor(DlColor color) override {
320 if (current_.getColor() != color) {
321 onSetColor(color);
322 }
323 }
324 // |DlOpReceiver|
325 void setBlendMode(DlBlendMode mode) override {
326 if (current_.getBlendMode() != mode) {
327 onSetBlendMode(mode);
328 }
329 }
330 // |DlOpReceiver|
331 void setColorSource(const DlColorSource* source) override {
332 if (NotEquals(current_.getColorSourcePtr(), source)) {
333 onSetColorSource(source);
334 }
335 }
336 // |DlOpReceiver|
337 void setImageFilter(const DlImageFilter* filter) override {
338 if (NotEquals(current_.getImageFilterPtr(), filter)) {
339 onSetImageFilter(filter);
340 }
341 }
342 // |DlOpReceiver|
343 void setColorFilter(const DlColorFilter* filter) override {
344 if (NotEquals(current_.getColorFilterPtr(), filter)) {
345 onSetColorFilter(filter);
346 }
347 }
348 // |DlOpReceiver|
349 void setMaskFilter(const DlMaskFilter* filter) override {
350 if (NotEquals(current_.getMaskFilterPtr(), filter)) {
351 onSetMaskFilter(filter);
352 }
353 }
354
355 DlPaint CurrentAttributes() const { return current_; }
356 int LastOpIndex() const { return op_index_ - 1; }
357
358 // |DlOpReceiver|
359 void save() override { Save(); }
360 // Only the |renders_with_attributes()| option will be accepted here. Any
361 // other flags will be ignored and calculated anew as the DisplayList is
362 // built. Alternatively, use the |saveLayer(DlRect, bool)| method.
363 // |DlOpReceiver|
364 void saveLayer(const DlRect& bounds,
365 const SaveLayerOptions options,
366 const DlImageFilter* backdrop,
367 std::optional<int64_t> backdrop_id) override;
368 // |DlOpReceiver|
369 void restore() override { Restore(); }
370
371 // |DlOpReceiver|
372 void translate(DlScalar tx, DlScalar ty) override { Translate(tx, ty); }
373 // |DlOpReceiver|
374 void scale(DlScalar sx, DlScalar sy) override { Scale(sx, sy); }
375 // |DlOpReceiver|
376 void rotate(DlScalar degrees) override { Rotate(degrees); }
377 // |DlOpReceiver|
378 void skew(DlScalar sx, DlScalar sy) override { Skew(sx, sy); }
379
380 // clang-format off
381 // |DlOpReceiver|
382 void transform2DAffine(DlScalar mxx, DlScalar mxy, DlScalar mxt,
383 DlScalar myx, DlScalar myy, DlScalar myt) override {
384 Transform2DAffine(mxx, mxy, mxt, myx, myy, myt);
385 }
386 // |DlOpReceiver|
387 void transformFullPerspective(
388 DlScalar mxx, DlScalar mxy, DlScalar mxz, DlScalar mxt,
389 DlScalar myx, DlScalar myy, DlScalar myz, DlScalar myt,
390 DlScalar mzx, DlScalar mzy, DlScalar mzz, DlScalar mzt,
391 DlScalar mwx, DlScalar mwy, DlScalar mwz, DlScalar mwt) override {
392 TransformFullPerspective(mxx, mxy, mxz, mxt,
393 myx, myy, myz, myt,
394 mzx, mzy, mzz, mzt,
395 mwx, mwy, mwz, mwt);
396 }
397 // clang-format off
398 // |DlOpReceiver|
399 void transformReset() override { TransformReset(); }
400
401 // |DlOpReceiver|
402 void clipRect(const DlRect& rect, DlClipOp clip_op, bool is_aa) override {
403 ClipRect(rect, clip_op, is_aa);
404 }
405 // |DlOpReceiver|
406 void clipOval(const DlRect& bounds, DlClipOp clip_op, bool is_aa) override {
407 ClipOval(bounds, clip_op, is_aa);
408 }
409 // |DlOpReceiver|
410 void clipRoundRect(const DlRoundRect& rrect,
411 DlClipOp clip_op,
412 bool is_aa) override {
413 ClipRoundRect(rrect, clip_op, is_aa);
414 }
415 // |DlOpReceiver|
416 void clipRoundSuperellipse(const DlRoundSuperellipse& rse,
417 DlClipOp clip_op,
418 bool is_aa) override {
419 ClipRoundSuperellipse(rse, clip_op, is_aa);
420 }
421 // |DlOpReceiver|
422 void clipPath(const DlPath& path, DlClipOp clip_op, bool is_aa) override {
423 ClipPath(path, clip_op, is_aa);
424 }
425
426 // |DlOpReceiver|
427 void drawPaint() override;
428 // |DlOpReceiver|
429 void drawColor(DlColor color, DlBlendMode mode) override {
430 DrawColor(color, mode);
431 }
432 // |DlOpReceiver|
433 void drawLine(const DlPoint& p0, const DlPoint& p1) override;
434 // |DlOpReceiver|
435 void drawDashedLine(const DlPoint& p0,
436 const DlPoint& p1,
437 DlScalar on_length,
438 DlScalar off_length) override;
439 // |DlOpReceiver|
440 void drawRect(const DlRect& rect) override;
441 // |DlOpReceiver|
442 void drawOval(const DlRect& bounds) override;
443 // |DlOpReceiver|
444 void drawCircle(const DlPoint& center, DlScalar radius) override;
445 // |DlOpReceiver|
446 void drawRoundRect(const DlRoundRect& rrect) override;
447 // |DlOpReceiver|
448 void drawDiffRoundRect(const DlRoundRect& outer,
449 const DlRoundRect& inner) override;
450 // |DlOpReceiver|
451 void drawRoundSuperellipse(const DlRoundSuperellipse& rse) override;
452 // |DlOpReceiver|
453 void drawPath(const DlPath& path) override;
454 // |DlOpReceiver|
455 void drawArc(const DlRect& bounds,
456 DlScalar start,
457 DlScalar sweep,
458 bool useCenter) override;
459 // |DlOpReceiver|
460 void drawPoints(DlPointMode mode, uint32_t count, const DlPoint pts[]) override;
461 // |DlOpReceiver|
462 void drawVertices(const std::shared_ptr<DlVertices>& vertices,
463 DlBlendMode mode) override;
464
465 // |DlOpReceiver|
466 void drawImage(const sk_sp<DlImage> image,
467 const DlPoint& point,
468 DlImageSampling sampling,
469 bool render_with_attributes) override;
470 // |DlOpReceiver|
471 void drawImageRect(
472 const sk_sp<DlImage> image,
473 const DlRect& src,
474 const DlRect& dst,
475 DlImageSampling sampling,
476 bool render_with_attributes,
477 DlSrcRectConstraint constraint = DlSrcRectConstraint::kFast) override;
478 // |DlOpReceiver|
479 void drawImageNine(const sk_sp<DlImage> image,
480 const DlIRect& center,
481 const DlRect& dst,
482 DlFilterMode filter,
483 bool render_with_attributes) override;
484 // |DlOpReceiver|
485 void drawAtlas(const sk_sp<DlImage> atlas,
486 const DlRSTransform xform[],
487 const DlRect tex[],
488 const DlColor colors[],
489 int count,
490 DlBlendMode mode,
491 DlImageSampling sampling,
492 const DlRect* cullRect,
493 bool render_with_attributes) override;
494
495 // |DlOpReceiver|
496 void drawDisplayList(const sk_sp<DisplayList> display_list,
497 DlScalar opacity) override {
498 DrawDisplayList(display_list, opacity);
499 }
500
501 // |DlOpReceiver|
502 void drawText(const std::shared_ptr<DlText>& text,
503 DlScalar x,
504 DlScalar y) override;
505
506 // |DlOpReceiver|
507 void drawShadow(const DlPath& path,
508 const DlColor color,
509 const DlScalar elevation,
510 bool transparent_occluder,
511 DlScalar dpr) override {
512 DrawShadow(path, color, elevation, transparent_occluder, dpr);
513 }
514
515 void checkForDeferredSave();
516
517 DisplayListStorage storage_;
518 std::vector<size_t> offsets_;
519 uint32_t render_op_count_ = 0u;
520 uint32_t depth_ = 0u;
521 // Most rendering ops will use 1 depth value, but some attributes may
522 // require an additional depth value (due to implicit saveLayers)
523 uint32_t render_op_depth_cost_ = 1u;
524 DlIndex op_index_ = 0;
525
526 // bytes and ops from |drawPicture| and |drawDisplayList|
527 size_t nested_bytes_ = 0;
528 uint32_t nested_op_count_ = 0;
529
530 bool is_ui_thread_safe_ = true;
531
532 template <typename T, typename... Args>
533 void* Push(size_t extra, Args&&... args);
534
535 struct RTreeData {
536 std::vector<DlRect> rects;
537 std::vector<int> indices;
538 };
539
540 struct LayerInfo {
541 LayerInfo(const std::shared_ptr<DlImageFilter>& filter,
542 size_t rtree_rects_start_index)
543 : filter(filter),
544 rtree_rects_start_index(rtree_rects_start_index) {}
545
546 // The filter that will be applied to the contents of the saveLayer
547 // when it is restored into the parent layer.
548 const std::shared_ptr<DlImageFilter> filter;
549
550 // The index of the rtree rects when the saveLayer was called, used
551 // only in the case that the saveLayer has a filter so that the
552 // accumulated rects can be updated in the corresponding restore call.
553 const size_t rtree_rects_start_index = 0;
554
555 // The bounds accumulator for the entire DisplayList, relative to its root
556 // (not used when accumulating rects for an rtree, though)
557 AccumulationRect global_space_accumulator;
558
559 // The bounds accumulator to set/verify the bounds of the most recently
560 // invoked saveLayer call, relative to the root of that saveLayer
561 AccumulationRect layer_local_accumulator;
562
563 DlBlendMode max_blend_mode = DlBlendMode::kClear;
564
565 bool opacity_incompatible_op_detected = false;
566 bool affects_transparent_layer = false;
567 bool contains_backdrop_filter = false;
568 bool is_unbounded = false;
569
570 bool is_group_opacity_compatible() const {
571 return !opacity_incompatible_op_detected &&
572 !layer_local_accumulator.overlap_detected();
573 }
574
575 void update_blend_mode(DlBlendMode mode) {
576 if (max_blend_mode < mode) {
577 max_blend_mode = mode;
578 }
579 }
580 };
581
582 // The SaveInfo class stores internal data common to both Save and
583 // SaveLayer calls
584 class SaveInfo {
585 public:
586 // For vector reallocation calls to copy vector data
587 SaveInfo(const SaveInfo& copy) = default;
588 SaveInfo(SaveInfo&& copy) = default;
589
590 // For constructor (root layer) initialization
591 explicit SaveInfo(const DlRect& cull_rect)
592 : is_save_layer(true),
593 has_valid_clip(false),
594 global_state(cull_rect),
595 layer_state(cull_rect),
596 layer_info(new LayerInfo(nullptr, 0u)) {}
597
598 // For regular save calls:
599 // Passing a pointer to the parent_info so as to distinguish this
600 // call from the copy constructors used during vector reallocations
601 explicit SaveInfo(const SaveInfo* parent_info)
602 : is_save_layer(false),
603 has_deferred_save_op(true),
604 has_valid_clip(parent_info->has_valid_clip),
605 global_state(parent_info->global_state),
606 layer_state(parent_info->layer_state),
607 layer_info(parent_info->layer_info) {}
608
609 // For saveLayer calls:
610 explicit SaveInfo(const SaveInfo* parent_info,
611 const std::shared_ptr<DlImageFilter>& filter,
612 int rtree_rect_index)
613 : is_save_layer(true),
614 has_valid_clip(false),
615 global_state(parent_info->global_state),
616 layer_state(kMaxCullRect),
617 layer_info(new LayerInfo(filter, rtree_rect_index)) {}
618
619 const bool is_save_layer;
620
621 bool has_deferred_save_op = false;
622 bool is_nop = false;
623 bool has_valid_clip;
624
625 // The depth when the save call is recorded, used to compute the total
626 // depth of its content when the associated restore is called.
627 uint32_t save_depth = 0;
628
629 // The offset into the buffer where the associated save op is recorded
630 // (which is not necessarily the same as when the Save() method is called
631 // due to deferred saves)
632 size_t save_offset = 0;
633
634 // The transform and clip accumulated since the root of the DisplayList
635 DisplayListMatrixClipState global_state;
636
637 // The transform and clip accumulated since the most recent saveLayer,
638 // used to compute and update its bounds when the restore is called.
639 DisplayListMatrixClipState layer_state;
640
641 std::shared_ptr<LayerInfo> layer_info;
642
643 // Records the given bounds after transforming by the global and
644 // layer matrices.
645 bool AccumulateBoundsLocal(const DlRect& bounds);
646
647 // Simply transfers the local bounds to the parent
648 void TransferBoundsToParent(const SaveInfo& parent);
649 };
650
651 const DlRect original_cull_rect_;
652 std::vector<SaveInfo> save_stack_;
653 std::optional<RTreeData> rtree_data_;
654
655 DlPaint current_;
656
657 // Returns a reference to the SaveInfo structure at the top of the current
658 // save_stack vector. Note that the clip and matrix state can be accessed
659 // more directly through global_state() and layer_state().
660 SaveInfo& current_info() { return save_stack_.back(); }
661 const SaveInfo& current_info() const { return save_stack_.back(); }
662
663 // Returns a reference to the SaveInfo structure just below the top
664 // of the current save_stack state.
665 SaveInfo& parent_info() { return *std::prev(save_stack_.end(), 2); }
666 const SaveInfo& parent_info() const {
667 return *std::prev(save_stack_.end(), 2);
668 }
669
670 // Returns a reference to the LayerInfo structure at the top of the current
671 // save_stack vector. Note that the clip and matrix state can be accessed
672 // more directly through global_state() and layer_state().
673 LayerInfo& current_layer() { return *save_stack_.back().layer_info; }
674 const LayerInfo& current_layer() const {
675 return *save_stack_.back().layer_info;
676 }
677
678 // Returns a reference to the LayerInfo structure just below the top
679 // of the current save_stack state.
680 LayerInfo& parent_layer() {
681 return *std::prev(save_stack_.end(), 2)->layer_info;
682 }
683 const LayerInfo& parent_layer() const {
684 return *std::prev(save_stack_.end(), 2)->layer_info;
685 }
686
687 // Returns a reference to the matrix and clip state for the entire
688 // DisplayList. The initial transform of this state is identity and
689 // the initial cull_rect is the root original_cull_rect supplied
690 // in the constructor. It is a summary of all transform and clip
691 // calls that have happened since the DisplayList was created
692 // (and have not yet been removed by a restore() call).
693 DisplayListMatrixClipState& global_state() {
694 return current_info().global_state;
695 }
696 const DisplayListMatrixClipState& global_state() const {
697 return current_info().global_state;
698 }
699
700 // Returns a reference to the matrix and clip state relative to the
701 // current layer, whether that is defined by the most recent saveLayer
702 // call, or by the initial root state of the entire DisplayList for
703 // calls not surrounded by a saveLayer/restore pair. It is a summary
704 // of only those transform and clip calls that have happened since
705 // the creation of the DisplayList or since the most recent saveLayer
706 // (and have not yet been removed by a restore() call).
707 DisplayListMatrixClipState& layer_local_state() {
708 return current_info().layer_state;
709 }
710 const DisplayListMatrixClipState& layer_local_state() const {
711 return current_info().layer_state;
712 }
713
714 void RestoreLayer();
715 void TransferLayerBounds(const DlRect& content_bounds);
716 bool AdjustRTreeRects(RTreeData& data,
717 const DlImageFilter& filter,
718 const DlMatrix& matrix,
719 const DlRect& clip,
720 size_t rect_index);
721
722 // This flag indicates whether or not the current rendering attributes
723 // are compatible with rendering ops applying an inherited opacity.
724 bool current_opacity_compatibility_ = true;
725
726 // Returns the compatibility of a given blend mode for applying an
727 // inherited opacity value to modulate the visibility of the op.
728 // For now we only accept SrcOver blend modes but this could be expanded
729 // in the future to include other (rarely used) modes that also modulate
730 // the opacity of a rendering operation at the cost of a switch statement
731 // or lookup table.
732 static bool IsOpacityCompatible(DlBlendMode mode) {
733 return (mode == DlBlendMode::kSrcOver);
734 }
735
736 void UpdateCurrentOpacityCompatibility() {
737 current_opacity_compatibility_ = //
738 current_.getColorFilter() == nullptr && //
739 !current_.isInvertColors() && //
740 !current_.usesRuntimeEffect() && //
741 IsOpacityCompatible(current_.getBlendMode());
742 }
743
744 // Update the opacity compatibility flags of the current layer for an op
745 // that has determined its compatibility as indicated by |compatible|.
746 void UpdateLayerOpacityCompatibility(bool compatible) {
747 if (!compatible) {
748 current_layer().opacity_incompatible_op_detected = true;
749 }
750 }
751
752 // Check for opacity compatibility for an op that may or may not use the
753 // current rendering attributes as indicated by |uses_blend_attribute|.
754 // If the flag is false then the rendering op will be able to substitute
755 // a default Paint object with the opacity applied using the default SrcOver
756 // blend mode which is always compatible with applying an inherited opacity.
757 void CheckLayerOpacityCompatibility(bool uses_blend_attribute = true) {
758 UpdateLayerOpacityCompatibility(!uses_blend_attribute ||
759 current_opacity_compatibility_);
760 }
761
762 void CheckLayerOpacityHairlineCompatibility() {
763 UpdateLayerOpacityCompatibility(
764 current_opacity_compatibility_ &&
765 (current_.getDrawStyle() == DlDrawStyle::kFill ||
766 current_.getStrokeWidth() > 0));
767 }
768
769 // Check for opacity compatibility for an op that ignores the current
770 // attributes and uses the indicated blend |mode| to render to the layer.
771 // This is only used by |drawColor| currently.
772 void CheckLayerOpacityCompatibility(DlBlendMode mode) {
773 UpdateLayerOpacityCompatibility(IsOpacityCompatible(mode));
774 }
775
776 void onSetAntiAlias(bool aa);
777 void onSetInvertColors(bool invert);
778 void onSetStrokeCap(DlStrokeCap cap);
779 void onSetStrokeJoin(DlStrokeJoin join);
780 void onSetDrawStyle(DlDrawStyle style);
781 void onSetStrokeWidth(DlScalar width);
782 void onSetStrokeMiter(DlScalar limit);
783 void onSetColor(DlColor color);
784 void onSetBlendMode(DlBlendMode mode);
785 void onSetColorSource(const DlColorSource* source);
786 void onSetImageFilter(const DlImageFilter* filter);
787 void onSetColorFilter(const DlColorFilter* filter);
788 void onSetMaskFilter(const DlMaskFilter* filter);
789
790 static DisplayListAttributeFlags FlagsForPointMode(DlPointMode mode);
791
792 enum class OpResult {
793 kNoEffect,
794 kPreservesTransparency,
795 kAffectsAll,
796 };
797
798 bool paint_nops_on_transparency();
799 OpResult PaintResult(const DlPaint& paint,
800 DisplayListAttributeFlags flags = kDrawPaintFlags);
801
802 void UpdateLayerResult(OpResult result, DlBlendMode mode) {
803 switch (result) {
804 case OpResult::kNoEffect:
805 case OpResult::kPreservesTransparency:
806 break;
807 case OpResult::kAffectsAll:
808 current_layer().affects_transparent_layer = true;
809 break;
810 }
811 current_layer().update_blend_mode(mode);
812 }
813 void UpdateLayerResult(OpResult result, bool uses_attributes = true) {
814 UpdateLayerResult(result, uses_attributes ? current_.getBlendMode()
816 }
817
818 // kAnyColor is a non-opaque and non-transparent color that will not
819 // trigger any short-circuit tests about the results of a blend.
820 static constexpr DlColor kAnyColor = DlColor::kMidGrey().withAlphaF(0.5f);
821 static_assert(!kAnyColor.isOpaque());
822 static_assert(!kAnyColor.isTransparent());
823 static DlColor GetEffectiveColor(const DlPaint& paint,
824 DisplayListAttributeFlags flags);
825
826 // Adjusts the indicated bounds for the given flags and returns true if
827 // the calculation was possible, or false if it could not be estimated.
828 bool AdjustBoundsForPaint(DlRect& bounds, DisplayListAttributeFlags flags);
829
830 // Records the fact that we encountered an op that either could not
831 // estimate its bounds or that fills all of the destination space.
832 bool AccumulateUnbounded(const SaveInfo& save);
833 bool AccumulateUnbounded() {
834 return AccumulateUnbounded(current_info());
835 }
836
837 // Records the bounds for an op after modifying them according to the
838 // supplied attribute flags and transforming by the current matrix.
839 bool AccumulateOpBounds(const DlRect& bounds,
840 DisplayListAttributeFlags flags) {
841 DlRect safe_bounds = bounds;
842 return AccumulateOpBounds(safe_bounds, flags);
843 }
844
845 // Records the bounds for an op after modifying them according to the
846 // supplied attribute flags and transforming by the current matrix
847 // and clipping against the current clip.
848 bool AccumulateOpBounds(DlRect& bounds, DisplayListAttributeFlags flags);
849
850 // Records the given bounds after transforming by the current matrix
851 // and clipping against the current clip.
852 bool AccumulateBounds(const DlRect& bounds, SaveInfo& layer, int id);
853 bool AccumulateBounds(const DlRect& bounds) {
854 return AccumulateBounds(bounds, current_info(), op_index_);
855 }
856};
857
858} // namespace flutter
859
860#endif // FLUTTER_DISPLAY_LIST_DL_BUILDER_H_
void DrawOval(const DlRect &bounds, const DlPaint &paint) override
static constexpr DlRect kMaxCullRect
Definition dl_builder.h:32
friend DlOpReceiver & DisplayListBuilderBenchmarkAccessor(DisplayListBuilder &builder)
void ClipRect(const DlRect &rect, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false) override
void DrawImageRect(const sk_sp< DlImage > &image, const DlRect &src, const DlRect &dst, DlImageSampling sampling, const DlPaint *paint=nullptr, DlSrcRectConstraint constraint=DlSrcRectConstraint::kFast) override
void DrawVertices(const std::shared_ptr< DlVertices > &vertices, DlBlendMode mode, const DlPaint &paint) override
void DrawImageNine(const sk_sp< DlImage > &image, const DlIRect &center, const DlRect &dst, DlFilterMode filter, const DlPaint *paint=nullptr) override
void DrawAtlas(const sk_sp< DlImage > &atlas, const DlRSTransform xform[], const DlRect tex[], const DlColor colors[], int count, DlBlendMode mode, DlImageSampling sampling, const DlRect *cullRect, const DlPaint *paint=nullptr) override
void DrawRoundRect(const DlRoundRect &rrect, const DlPaint &paint) override
void RestoreToCount(int restore_count) override
void DrawArc(const DlRect &bounds, DlScalar start, DlScalar sweep, bool useCenter, const DlPaint &paint) override
void DrawShadow(const DlPath &path, const DlColor color, const DlScalar elevation, bool transparent_occluder, DlScalar dpr) override
Draws the shadow of the given |path| rendered in the provided |color| (which is only consulted for it...
void DrawImage(const sk_sp< DlImage > &image, const DlPoint &point, DlImageSampling sampling, const DlPaint *paint=nullptr) override
void DrawColor(DlColor color, DlBlendMode mode) override
void SetTransform(const DlMatrix &matrix) override
Definition dl_builder.h:102
DlMatrix GetMatrix() const override
Definition dl_builder.h:111
void DrawCircle(const DlPoint &center, DlScalar radius, const DlPaint &paint) override
void TransformReset() override
friend DlOpReceiver & DisplayListBuilderTestingAccessor(DisplayListBuilder &builder)
void SaveLayer(const std::optional< DlRect > &bounds, const DlPaint *paint=nullptr, const DlImageFilter *backdrop=nullptr, std::optional< int64_t > backdrop_id=std::nullopt) override
void ClipRoundSuperellipse(const DlRoundSuperellipse &rse, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false) override
void DrawLine(const DlPoint &p0, const DlPoint &p1, const DlPaint &paint) override
DlISize GetBaseLayerDimensions() const override
void ClipRoundRect(const DlRoundRect &rrect, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false) override
bool IsEmpty() const
Return true if the builder has not yet recorded any commands.
void Rotate(DlScalar degrees) override
DisplayListBuilder(bool prepare_rtree)
Definition dl_builder.h:35
void DrawRoundSuperellipse(const DlRoundSuperellipse &rse, const DlPaint &paint) override
void Scale(DlScalar sx, DlScalar sy) override
void DrawDisplayList(const sk_sp< DisplayList > display_list, DlScalar opacity=SK_Scalar1) override
friend int DisplayListBuilderTestingLastOpIndex(DisplayListBuilder &builder)
SkImageInfo GetImageInfo() const override
void Skew(DlScalar sx, DlScalar sy) override
void Translate(DlScalar tx, DlScalar ty) override
void Transform2DAffine(DlScalar mxx, DlScalar mxy, DlScalar mxt, DlScalar myx, DlScalar myy, DlScalar myt) override
void DrawPaint(const DlPaint &paint) override
DisplayListBuilder(DlScalar width, DlScalar height)
Definition dl_builder.h:41
size_t GetRecordCount() const
Return the number of records currently recorded in the builder.
void DrawDashedLine(const DlPoint &p0, const DlPoint &p1, DlScalar on_length, DlScalar off_length, const DlPaint &paint) override
sk_sp< DisplayList > Build()
void DrawPath(const DlPath &path, const DlPaint &paint) override
bool QuickReject(const DlRect &bounds) const override
DlRect GetDestinationClipCoverage() const override
Definition dl_builder.h:138
friend DlPaint DisplayListBuilderTestingAttributes(DisplayListBuilder &builder)
void ClipPath(const DlPath &path, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false) override
void DrawPoints(DlPointMode mode, uint32_t count, const DlPoint pts[], const DlPaint &paint) override
void ClipOval(const DlRect &bounds, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false) override
DlRect GetLocalClipCoverage() const override
Definition dl_builder.h:145
int GetSaveCount() const override
Definition dl_builder.h:71
void TransformFullPerspective(DlScalar mxx, DlScalar mxy, DlScalar mxz, DlScalar mxt, DlScalar myx, DlScalar myy, DlScalar myz, DlScalar myt, DlScalar mzx, DlScalar mzy, DlScalar mzz, DlScalar mzt, DlScalar mwx, DlScalar mwy, DlScalar mwz, DlScalar mwt) override
void DrawDiffRoundRect(const DlRoundRect &outer, const DlRoundRect &inner, const DlPaint &paint) override
void Transform(const DlMatrix &matrix) override
void DrawRect(const DlRect &rect, const DlPaint &paint) override
static constexpr DisplayListAttributeFlags kDrawPaintFlags
Developer-facing API for rendering anything within the engine.
Definition dl_canvas.h:32
virtual void DrawImageRect(const sk_sp< DlImage > &image, const DlRect &src, const DlRect &dst, DlImageSampling sampling, const DlPaint *paint=nullptr, DlSrcRectConstraint constraint=DlSrcRectConstraint::kFast)=0
Internal API for rendering recorded display lists to backends.
bool isAntiAlias() const
Definition dl_paint.h:57
DlStrokeCap getStrokeCap() const
Definition dl_paint.h:98
DlColor getColor() const
Definition dl_paint.h:69
DlBlendMode getBlendMode() const
Definition dl_paint.h:82
float getStrokeMiter() const
Definition dl_paint.h:120
DlStrokeJoin getStrokeJoin() const
Definition dl_paint.h:106
const DlColorSource * getColorSourcePtr() const
Definition dl_paint.h:129
const DlMaskFilter * getMaskFilterPtr() const
Definition dl_paint.h:183
const DlColorFilter * getColorFilterPtr() const
Definition dl_paint.h:147
const DlImageFilter * getImageFilterPtr() const
Definition dl_paint.h:165
DlDrawStyle getDrawStyle() const
Definition dl_paint.h:90
float getStrokeWidth() const
Definition dl_paint.h:114
bool isInvertColors() const
Definition dl_paint.h:63
int32_t x
FlutterVulkanImage * image
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
std::u16string text
double y
impeller::Scalar DlScalar
uint32_t DlIndex
DlStrokeJoin
Definition dl_paint.h:37
impeller::RoundRect DlRoundRect
DlStrokeCap
Definition dl_paint.h:28
impeller::RSTransform DlRSTransform
impeller::Matrix DlMatrix
impeller::Rect DlRect
impeller::RoundSuperellipse DlRoundSuperellipse
DlPointMode
Definition dl_types.h:15
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
DlDrawStyle
Definition dl_paint.h:19
@ kFill
fills interior of shapes
impeller::IRect32 DlIRect
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition switch_defs.h:36
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all 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
impeller::BlendMode DlBlendMode
bool NotEquals(const T *a, const U *b)
impeller::Point DlPoint
DlSrcRectConstraint
Definition dl_types.h:21
BlendMode
Definition color.h:58
flutter::DlColor DlColor
flutter::DlPaint DlPaint
int32_t height
int32_t width
static constexpr DlColor kMidGrey()
Definition dl_color.h:78
constexpr DlColor withAlphaF(float alpha) const
Definition dl_color.h:132
A 4x4 matrix using column-major storage.
Definition matrix.h:37
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition rect.h:129
#define DrawText