Flutter Engine
The Flutter Engine
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
8#include "flutter/display_list/display_list.h"
9#include "flutter/display_list/dl_blend_mode.h"
10#include "flutter/display_list/dl_canvas.h"
11#include "flutter/display_list/dl_op_flags.h"
12#include "flutter/display_list/dl_op_receiver.h"
13#include "flutter/display_list/dl_paint.h"
14#include "flutter/display_list/dl_sampling_options.h"
15#include "flutter/display_list/effects/dl_path_effect.h"
16#include "flutter/display_list/image/dl_image.h"
17#include "flutter/display_list/utils/dl_bounds_accumulator.h"
18#include "flutter/display_list/utils/dl_comparable.h"
19#include "flutter/display_list/utils/dl_matrix_clip_tracker.h"
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 SkRect kMaxCullRect =
33 SkRect::MakeLTRB(-1E9F, -1E9F, 1E9F, 1E9F);
34
35 explicit DisplayListBuilder(bool prepare_rtree)
36 : DisplayListBuilder(kMaxCullRect, prepare_rtree) {}
37
38 explicit DisplayListBuilder(const SkRect& cull_rect = kMaxCullRect,
39 bool prepare_rtree = false);
40
42
43 // |DlCanvas|
44 SkISize GetBaseLayerSize() const override;
45 // |DlCanvas|
46 SkImageInfo GetImageInfo() const override;
47
48 // |DlCanvas|
49 void Save() override;
50
51 // |DlCanvas|
52 void SaveLayer(const SkRect* bounds,
53 const DlPaint* paint = nullptr,
54 const DlImageFilter* backdrop = nullptr) override;
55 // |DlCanvas|
56 void Restore() override;
57 // |DlCanvas|
58 int GetSaveCount() const override { return layer_stack_.size(); }
59 // |DlCanvas|
60 void RestoreToCount(int restore_count) override;
61
62 // |DlCanvas|
63 void Translate(SkScalar tx, SkScalar ty) override;
64 // |DlCanvas|
65 void Scale(SkScalar sx, SkScalar sy) override;
66 // |DlCanvas|
67 void Rotate(SkScalar degrees) override;
68 // |DlCanvas|
69 void Skew(SkScalar sx, SkScalar sy) override;
70
71 // clang-format off
72 // 2x3 2D affine subset of a 4x4 transform in row major order
73 // |DlCanvas|
75 SkScalar myx, SkScalar myy, SkScalar myt) override;
76 // full 4x4 transform in row major order
77 // |DlCanvas|
79 SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt,
80 SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt,
81 SkScalar mzx, SkScalar mzy, SkScalar mzz, SkScalar mzt,
82 SkScalar mwx, SkScalar mwy, SkScalar mwz, SkScalar mwt) override;
83 // clang-format on
84 // |DlCanvas|
85 void TransformReset() override;
86 // |DlCanvas|
87 void Transform(const SkMatrix* matrix) override;
88 // |DlCanvas|
89 void Transform(const SkM44* matrix44) override;
90 // |DlCanvas|
91 void SetTransform(const SkMatrix* matrix) override {
93 Transform(matrix);
94 }
95 // |DlCanvas|
96 void SetTransform(const SkM44* matrix44) override {
98 Transform(matrix44);
99 }
101
102 /// Returns the 4x4 full perspective transform representing all transform
103 /// operations executed so far in this DisplayList within the enclosing
104 /// save stack.
105 // |DlCanvas|
107 return tracker_.matrix_4x4();
108 }
109 /// Returns the 3x3 partial perspective transform representing all transform
110 /// operations executed so far in this DisplayList within the enclosing
111 /// save stack.
112 // |DlCanvas|
113 SkMatrix GetTransform() const override { return tracker_.matrix_3x3(); }
114
115 // |DlCanvas|
116 void ClipRect(const SkRect& rect,
117 ClipOp clip_op = ClipOp::kIntersect,
118 bool is_aa = false) override;
119 // |DlCanvas|
120 void ClipRRect(const SkRRect& rrect,
121 ClipOp clip_op = ClipOp::kIntersect,
122 bool is_aa = false) override;
123 // |DlCanvas|
124 void ClipPath(const SkPath& path,
125 ClipOp clip_op = ClipOp::kIntersect,
126 bool is_aa = false) override;
127
128 /// Conservative estimate of the bounds of all outstanding clip operations
129 /// measured in the coordinate space within which this DisplayList will
130 /// be rendered.
131 // |DlCanvas|
133 return tracker_.device_cull_rect();
134 }
135 /// Conservative estimate of the bounds of all outstanding clip operations
136 /// transformed into the local coordinate space in which currently
137 /// recorded rendering operations are interpreted.
138 // |DlCanvas|
139 SkRect GetLocalClipBounds() const override {
140 return tracker_.local_cull_rect();
141 }
142
143 /// Return true iff the supplied bounds are easily shown to be outside
144 /// of the current clip bounds. This method may conservatively return
145 /// false if it cannot make the determination.
146 // |DlCanvas|
147 bool QuickReject(const SkRect& bounds) const override;
148
149 // |DlCanvas|
150 void DrawPaint(const DlPaint& paint) override;
151 // |DlCanvas|
152 void DrawColor(DlColor color, DlBlendMode mode) override;
153 // |DlCanvas|
154 void DrawLine(const SkPoint& p0,
155 const SkPoint& p1,
156 const DlPaint& paint) override;
157 // |DlCanvas|
158 void DrawRect(const SkRect& rect, const DlPaint& paint) override;
159 // |DlCanvas|
160 void DrawOval(const SkRect& bounds, const DlPaint& paint) override;
161 // |DlCanvas|
162 void DrawCircle(const SkPoint& center,
163 SkScalar radius,
164 const DlPaint& paint) override;
165 // |DlCanvas|
166 void DrawRRect(const SkRRect& rrect, const DlPaint& paint) override;
167 // |DlCanvas|
168 void DrawDRRect(const SkRRect& outer,
169 const SkRRect& inner,
170 const DlPaint& paint) override;
171 // |DlCanvas|
172 void DrawPath(const SkPath& path, const DlPaint& paint) override;
173 // |DlCanvas|
174 void DrawArc(const SkRect& bounds,
176 SkScalar sweep,
177 bool useCenter,
178 const DlPaint& paint) override;
179 // |DlCanvas|
181 uint32_t count,
182 const SkPoint pts[],
183 const DlPaint& paint) override;
184 // |DlCanvas|
185 void DrawVertices(const DlVertices* vertices,
187 const DlPaint& paint) override;
189 // |DlCanvas|
190 void DrawImage(const sk_sp<DlImage>& image,
191 const SkPoint point,
192 DlImageSampling sampling,
193 const DlPaint* paint = nullptr) override;
194 // |DlCanvas|
195 void DrawImageRect(
196 const sk_sp<DlImage>& image,
197 const SkRect& src,
198 const SkRect& dst,
199 DlImageSampling sampling,
200 const DlPaint* paint = nullptr,
201 SrcRectConstraint constraint = SrcRectConstraint::kFast) override;
203 // |DlCanvas|
205 const SkIRect& center,
206 const SkRect& dst,
207 DlFilterMode filter,
208 const DlPaint* paint = nullptr) override;
209 // |DlCanvas|
210 void DrawAtlas(const sk_sp<DlImage>& atlas,
211 const SkRSXform xform[],
212 const SkRect tex[],
213 const DlColor colors[],
214 int count,
216 DlImageSampling sampling,
217 const SkRect* cullRect,
218 const DlPaint* paint = nullptr) override;
219 // |DlCanvas|
220 void DrawDisplayList(const sk_sp<DisplayList> display_list,
221 SkScalar opacity = SK_Scalar1) override;
222 // |DlCanvas|
223 void DrawTextBlob(const sk_sp<SkTextBlob>& blob,
224 SkScalar x,
225 SkScalar y,
226 const DlPaint& paint) override;
227
228 void drawTextFrame(const std::shared_ptr<impeller::TextFrame>& text_frame,
229 SkScalar x,
230 SkScalar y) override;
231
232 void DrawTextFrame(const std::shared_ptr<impeller::TextFrame>& text_frame,
233 SkScalar x,
234 SkScalar y,
235 const DlPaint& paint) override;
236
237 // |DlCanvas|
238 void DrawShadow(const SkPath& path,
239 const DlColor color,
240 const SkScalar elevation,
241 bool transparent_occluder,
242 SkScalar dpr) override;
243
244 // |DlCanvas|
245 void Flush() override {}
246
248
249 private:
250 // This method exposes the internal stateful DlOpReceiver implementation
251 // of the DisplayListBuilder, primarily for testing purposes. Its use
252 // is obsolete and forbidden in every other case and is only shared to a
253 // pair of "friend" accessors in the benchmark/unittest files.
254 DlOpReceiver& asReceiver() { return *this; }
255
256 friend DlOpReceiver& DisplayListBuilderBenchmarkAccessor(
257 DisplayListBuilder& builder);
258 friend DlOpReceiver& DisplayListBuilderTestingAccessor(
259 DisplayListBuilder& builder);
261 DisplayListBuilder& builder);
262
263 void SetAttributesFromPaint(const DlPaint& paint,
264 const DisplayListAttributeFlags flags);
265
266 // |DlOpReceiver|
267 void setAntiAlias(bool aa) override {
268 if (current_.isAntiAlias() != aa) {
269 onSetAntiAlias(aa);
270 }
271 }
272 // |DlOpReceiver|
273 void setInvertColors(bool invert) override {
274 if (current_.isInvertColors() != invert) {
275 onSetInvertColors(invert);
276 }
277 }
278 // |DlOpReceiver|
279 void setStrokeCap(DlStrokeCap cap) override {
280 if (current_.getStrokeCap() != cap) {
281 onSetStrokeCap(cap);
282 }
283 }
284 // |DlOpReceiver|
285 void setStrokeJoin(DlStrokeJoin join) override {
286 if (current_.getStrokeJoin() != join) {
287 onSetStrokeJoin(join);
288 }
289 }
290 // |DlOpReceiver|
291 void setDrawStyle(DlDrawStyle style) override {
292 if (current_.getDrawStyle() != style) {
293 onSetDrawStyle(style);
294 }
295 }
296 // |DlOpReceiver|
297 void setStrokeWidth(float width) override {
298 if (current_.getStrokeWidth() != width) {
299 onSetStrokeWidth(width);
300 }
301 }
302 // |DlOpReceiver|
303 void setStrokeMiter(float limit) override {
304 if (current_.getStrokeMiter() != limit) {
305 onSetStrokeMiter(limit);
306 }
307 }
308 // |DlOpReceiver|
309 void setColor(DlColor color) override {
310 if (current_.getColor() != color) {
311 onSetColor(color);
312 }
313 }
314 // |DlOpReceiver|
316 if (current_.getBlendMode() != mode) {
317 onSetBlendMode(mode);
318 }
319 }
320 // |DlOpReceiver|
321 void setColorSource(const DlColorSource* source) override {
322 if (NotEquals(current_.getColorSource(), source)) {
323 onSetColorSource(source);
324 }
325 }
326 // |DlOpReceiver|
327 void setImageFilter(const DlImageFilter* filter) override {
328 if (NotEquals(current_.getImageFilter(), filter)) {
329 onSetImageFilter(filter);
330 }
331 }
332 // |DlOpReceiver|
333 void setColorFilter(const DlColorFilter* filter) override {
334 if (NotEquals(current_.getColorFilter(), filter)) {
335 onSetColorFilter(filter);
336 }
337 }
338 // |DlOpReceiver|
339 void setPathEffect(const DlPathEffect* effect) override {
340 if (NotEquals(current_.getPathEffect(), effect)) {
341 onSetPathEffect(effect);
342 }
343 }
344 // |DlOpReceiver|
345 void setMaskFilter(const DlMaskFilter* filter) override {
346 if (NotEquals(current_.getMaskFilter(), filter)) {
347 onSetMaskFilter(filter);
348 }
349 }
350
351 DlPaint CurrentAttributes() const { return current_; }
352
353 // |DlOpReceiver|
354 void save() override { Save(); }
355 // Only the |renders_with_attributes()| option will be accepted here. Any
356 // other flags will be ignored and calculated anew as the DisplayList is
357 // built. Alternatively, use the |saveLayer(SkRect, bool)| method.
358 // |DlOpReceiver|
359 void saveLayer(const SkRect& bounds,
361 const DlImageFilter* backdrop) override;
362 // |DlOpReceiver|
363 void restore() override { Restore(); }
364
365 // |DlOpReceiver|
366 void translate(SkScalar tx, SkScalar ty) override { Translate(tx, ty); }
367 // |DlOpReceiver|
368 void scale(SkScalar sx, SkScalar sy) override { Scale(sx, sy); }
369 // |DlOpReceiver|
370 void rotate(SkScalar degrees) override { Rotate(degrees); }
371 // |DlOpReceiver|
372 void skew(SkScalar sx, SkScalar sy) override { Skew(sx, sy); }
373
374 // clang-format off
375 // |DlOpReceiver|
377 SkScalar myx, SkScalar myy, SkScalar myt) override {
378 Transform2DAffine(mxx, mxy, mxt, myx, myy, myt);
379 }
380 // |DlOpReceiver|
382 SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt,
383 SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt,
384 SkScalar mzx, SkScalar mzy, SkScalar mzz, SkScalar mzt,
385 SkScalar mwx, SkScalar mwy, SkScalar mwz, SkScalar mwt) override {
386 TransformFullPerspective(mxx, mxy, mxz, mxt,
387 myx, myy, myz, myt,
388 mzx, mzy, mzz, mzt,
389 mwx, mwy, mwz, mwt);
390 }
391 // clang-format off
392 // |DlOpReceiver|
393 void transformReset() override { TransformReset(); }
394
395 // |DlOpReceiver|
396 void clipRect(const SkRect& rect, ClipOp clip_op, bool is_aa) override {
397 ClipRect(rect, clip_op, is_aa);
398 }
399 // |DlOpReceiver|
400 void clipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) override {
401 ClipRRect(rrect, clip_op, is_aa);
402 }
403 // |DlOpReceiver|
404 void clipPath(const SkPath& path, ClipOp clip_op, bool is_aa) override {
405 ClipPath(path, clip_op, is_aa);
406 }
407
408 // |DlOpReceiver|
409 void drawPaint() override;
410 // |DlOpReceiver|
413 }
414 // |DlOpReceiver|
415 void drawLine(const SkPoint& p0, const SkPoint& p1) override;
416 // |DlOpReceiver|
417 void drawRect(const SkRect& rect) override;
418 // |DlOpReceiver|
419 void drawOval(const SkRect& bounds) override;
420 // |DlOpReceiver|
421 void drawCircle(const SkPoint& center, SkScalar radius) override;
422 // |DlOpReceiver|
423 void drawRRect(const SkRRect& rrect) override;
424 // |DlOpReceiver|
425 void drawDRRect(const SkRRect& outer, const SkRRect& inner) override;
426 // |DlOpReceiver|
427 void drawPath(const SkPath& path) override;
428 // |DlOpReceiver|
429 void drawArc(const SkRect& bounds,
431 SkScalar sweep,
432 bool useCenter) override;
433 // |DlOpReceiver|
434 void drawPoints(PointMode mode, uint32_t count, const SkPoint pts[]) override;
435 // |DlOpReceiver|
436 void drawVertices(const DlVertices* vertices, DlBlendMode mode) override;
437
438 // |DlOpReceiver|
439 void drawImage(const sk_sp<DlImage> image,
440 const SkPoint point,
441 DlImageSampling sampling,
442 bool render_with_attributes) override;
443 // |DlOpReceiver|
444 void drawImageRect(
445 const sk_sp<DlImage> image,
446 const SkRect& src,
447 const SkRect& dst,
448 DlImageSampling sampling,
449 bool render_with_attributes,
450 SrcRectConstraint constraint = SrcRectConstraint::kFast) override;
451 // |DlOpReceiver|
453 const SkIRect& center,
454 const SkRect& dst,
455 DlFilterMode filter,
456 bool render_with_attributes) override;
457 // |DlOpReceiver|
458 void drawAtlas(const sk_sp<DlImage> atlas,
459 const SkRSXform xform[],
460 const SkRect tex[],
461 const DlColor colors[],
462 int count,
464 DlImageSampling sampling,
465 const SkRect* cullRect,
466 bool render_with_attributes) override;
467
468 // |DlOpReceiver|
469 void drawDisplayList(const sk_sp<DisplayList> display_list,
470 SkScalar opacity) override {
471 DrawDisplayList(display_list, opacity);
472 }
473 // |DlOpReceiver|
474 void drawTextBlob(const sk_sp<SkTextBlob> blob,
475 SkScalar x,
476 SkScalar y) override;
477 // |DlOpReceiver|
478 void drawShadow(const SkPath& path,
479 const DlColor color,
480 const SkScalar elevation,
481 bool transparent_occluder,
482 SkScalar dpr) override {
483 DrawShadow(path, color, elevation, transparent_occluder, dpr);
484 }
485
486 void checkForDeferredSave();
487
488 DisplayListStorage storage_;
489 size_t used_ = 0u;
490 size_t allocated_ = 0u;
491 uint32_t render_op_count_ = 0u;
492 uint32_t depth_ = 0u;
493 // Most rendering ops will use 1 depth value, but some attributes may
494 // require an additional depth value (due to implicit saveLayers)
495 uint32_t render_op_depth_cost_ = 1u;
496 int op_index_ = 0;
497
498 // bytes and ops from |drawPicture| and |drawDisplayList|
499 size_t nested_bytes_ = 0;
500 uint32_t nested_op_count_ = 0;
501
502 bool is_ui_thread_safe_ = true;
503
504 template <typename T, typename... Args>
505 void* Push(size_t extra, Args&&... args);
506
507 void intersect(const SkRect& rect);
508
509 // kInvalidSigma is used to indicate that no MaskBlur is currently set.
510 static constexpr SkScalar kInvalidSigma = 0.0;
511 static bool mask_sigma_valid(SkScalar sigma) {
512 return std::isfinite(sigma) && sigma > 0.0;
513 }
514
515 class SaveInfo {
516 public:
517 explicit SaveInfo(size_t save_offset = 0, uint32_t start_depth = 0)
518 : save_offset_(save_offset), start_depth_(start_depth) {}
519
520 // The offset into the memory buffer where the save DLOp record
521 // for this save() call is placed. This may be needed if the
522 // eventual restore() call has discovered important information about
523 // the records inside the saveLayer that may impact how the saveLayer
524 // is handled (e.g., |cannot_inherit_opacity| == false).
525 // This offset is only valid if |has_layer| is true.
526 size_t save_offset() const { return save_offset_; }
527
528 bool is_save_layer() const { return is_save_layer_; }
529 bool cannot_inherit_opacity() const { return cannot_inherit_opacity_; }
530 bool has_compatible_op() const { return has_compatible_op_; }
531 bool affects_transparent_layer() const {
532 return affects_transparent_layer_;
533 }
534
535 bool is_group_opacity_compatible() const {
536 return !cannot_inherit_opacity_;
537 }
538
539 void mark_incompatible() { cannot_inherit_opacity_ = true; }
540
541 // For now this only allows a single compatible op to mark the
542 // layer as being compatible with group opacity. If we start
543 // computing bounds of ops in the Builder methods then we
544 // can upgrade this to checking for overlapping ops.
545 // See https://github.com/flutter/flutter/issues/93899
546 void add_compatible_op() {
547 if (!cannot_inherit_opacity_) {
548 if (has_compatible_op_) {
549 cannot_inherit_opacity_ = true;
550 } else {
551 has_compatible_op_ = true;
552 }
553 }
554 }
555
556 // Records that the current layer contains an op that produces visible
557 // output on a transparent surface.
558 void add_visible_op() {
559 affects_transparent_layer_ = true;
560 }
561
562 // The filter to apply to the layer bounds when it is restored
563 std::shared_ptr<const DlImageFilter> filter() { return filter_; }
564
565 // is_unbounded should be set to true if we ever encounter an operation
566 // on a layer that either is unrestricted (|drawColor| or |drawPaint|)
567 // or cannot compute its bounds (some effects and filters) and there
568 // was no outstanding clip op at the time.
569 // When the layer is restored, the outer layer may then process this
570 // unbounded state by accumulating its own clip or transferring the
571 // unbounded state to its own outer layer.
572 // Typically the DisplayList will have been constructed with a cull
573 // rect which will act as a default clip for the outermost layer and
574 // the unbounded state of all sub layers will eventually be caught by
575 // that cull rect so that the overall unbounded state of the entire
576 // DisplayList will never be true.
577 //
578 // For historical consistency it is worth noting that SkPicture used
579 // to treat these same conditions as a Nop (they accumulate the
580 // SkPicture cull rect, but if no cull rect was specified then it is
581 // an empty Rect and so has no effect on the bounds).
582 //
583 // Flutter is unlikely to ever run into this as the Dart mechanisms
584 // all supply a non-null cull rect for all Dart Picture objects,
585 // even if that cull rect is kGiantRect.
586 void set_unbounded() { is_unbounded_ = true; }
587
588 // |is_unbounded| should be called after |getLayerBounds| in case
589 // a problem was found during the computation of those bounds,
590 // the layer will have one last chance to flag an unbounded state.
591 bool is_unbounded() const { return is_unbounded_; }
592
593 private:
594 size_t save_offset_;
595 uint32_t start_depth_;
596 bool is_save_layer_ = false;
597 bool cannot_inherit_opacity_ = false;
598 bool has_compatible_op_ = false;
599 std::shared_ptr<const DlImageFilter> filter_;
600 bool is_unbounded_ = false;
601 bool has_deferred_save_op_ = false;
602 bool is_nop_ = false;
603 bool affects_transparent_layer_ = false;
604 std::shared_ptr<BoundsAccumulator> layer_accumulator_;
605
606 friend class DisplayListBuilder;
607 };
608
609 std::vector<SaveInfo> layer_stack_;
610 SaveInfo* current_layer_;
611 DisplayListMatrixClipTracker tracker_;
612 std::unique_ptr<DisplayListMatrixClipTracker> layer_tracker_;
613 std::unique_ptr<BoundsAccumulator> accumulator_;
614 BoundsAccumulator* accumulator() { return accumulator_.get(); }
615
616 // This flag indicates whether or not the current rendering attributes
617 // are compatible with rendering ops applying an inherited opacity.
618 bool current_opacity_compatibility_ = true;
619
620 // Returns the compatibility of a given blend mode for applying an
621 // inherited opacity value to modulate the visibility of the op.
622 // For now we only accept SrcOver blend modes but this could be expanded
623 // in the future to include other (rarely used) modes that also modulate
624 // the opacity of a rendering operation at the cost of a switch statement
625 // or lookup table.
626 static bool IsOpacityCompatible(DlBlendMode mode) {
627 return (mode == DlBlendMode::kSrcOver);
628 }
629
630 void UpdateCurrentOpacityCompatibility() {
631 current_opacity_compatibility_ = //
632 current_.getColorFilter() == nullptr && //
633 !current_.isInvertColors() && //
634 IsOpacityCompatible(current_.getBlendMode());
635 }
636
637 // Update the opacity compatibility flags of the current layer for an op
638 // that has determined its compatibility as indicated by |compatible|.
639 void UpdateLayerOpacityCompatibility(bool compatible) {
640 if (compatible) {
641 current_layer_->add_compatible_op();
642 } else {
643 current_layer_->mark_incompatible();
644 }
645 }
646
647 // Check for opacity compatibility for an op that may or may not use the
648 // current rendering attributes as indicated by |uses_blend_attribute|.
649 // If the flag is false then the rendering op will be able to substitute
650 // a default Paint object with the opacity applied using the default SrcOver
651 // blend mode which is always compatible with applying an inherited opacity.
652 void CheckLayerOpacityCompatibility(bool uses_blend_attribute = true) {
653 UpdateLayerOpacityCompatibility(!uses_blend_attribute ||
654 current_opacity_compatibility_);
655 }
656
657 void CheckLayerOpacityHairlineCompatibility() {
658 UpdateLayerOpacityCompatibility(
659 current_opacity_compatibility_ &&
660 (current_.getDrawStyle() == DlDrawStyle::kFill ||
661 current_.getStrokeWidth() > 0));
662 }
663
664 // Check for opacity compatibility for an op that ignores the current
665 // attributes and uses the indicated blend |mode| to render to the layer.
666 // This is only used by |drawColor| currently.
667 void CheckLayerOpacityCompatibility(DlBlendMode mode) {
668 UpdateLayerOpacityCompatibility(IsOpacityCompatible(mode));
669 }
670
671 void onSetAntiAlias(bool aa);
672 void onSetInvertColors(bool invert);
673 void onSetStrokeCap(DlStrokeCap cap);
674 void onSetStrokeJoin(DlStrokeJoin join);
675 void onSetDrawStyle(DlDrawStyle style);
676 void onSetStrokeWidth(SkScalar width);
677 void onSetStrokeMiter(SkScalar limit);
678 void onSetColor(DlColor color);
679 void onSetBlendMode(DlBlendMode mode);
680 void onSetColorSource(const DlColorSource* source);
681 void onSetImageFilter(const DlImageFilter* filter);
682 void onSetColorFilter(const DlColorFilter* filter);
683 void onSetPathEffect(const DlPathEffect* effect);
684 void onSetMaskFilter(const DlMaskFilter* filter);
685
686 // The DisplayList had an unbounded call with no cull rect or clip
687 // to contain it. Should only be called after the stream is fully
688 // built.
689 // Unbounded operations are calls like |drawColor| which are defined
690 // to flood the entire surface, or calls that relied on a rendering
691 // attribute which is unable to compute bounds (should be rare).
692 // In those cases the bounds will represent only the accumulation
693 // of the bounded calls and this flag will be set to indicate that
694 // condition.
695 bool is_unbounded() const {
696 FML_DCHECK(layer_stack_.size() == 1);
697 return layer_stack_.front().is_unbounded();
698 }
699
700 SkRect bounds() const {
701 FML_DCHECK(layer_stack_.size() == 1);
702 if (is_unbounded()) {
703 FML_LOG(INFO) << "returning partial bounds for unbounded DisplayList";
704 }
705
706 return accumulator_->bounds();
707 }
708
709 sk_sp<DlRTree> rtree() {
710 FML_DCHECK(layer_stack_.size() == 1);
711 if (is_unbounded()) {
712 FML_LOG(INFO) << "returning partial rtree for unbounded DisplayList";
713 }
714
715 return accumulator_->rtree();
716 }
717
718 static DisplayListAttributeFlags FlagsForPointMode(PointMode mode);
719
720 enum class OpResult {
721 kNoEffect,
722 kPreservesTransparency,
723 kAffectsAll,
724 };
725
726 bool paint_nops_on_transparency();
727 OpResult PaintResult(const DlPaint& paint,
728 DisplayListAttributeFlags flags = kDrawPaintFlags);
729
730 void UpdateLayerResult(OpResult result) {
731 switch (result) {
732 case OpResult::kNoEffect:
733 case OpResult::kPreservesTransparency:
734 break;
735 case OpResult::kAffectsAll:
736 current_layer_->add_visible_op();
737 break;
738 }
739 }
740
741 // kAnyColor is a non-opaque and non-transparent color that will not
742 // trigger any short-circuit tests about the results of a blend.
743 static constexpr DlColor kAnyColor = DlColor::kMidGrey().withAlpha(0x80);
744 static_assert(!kAnyColor.isOpaque());
745 static_assert(!kAnyColor.isTransparent());
746 static DlColor GetEffectiveColor(const DlPaint& paint,
747 DisplayListAttributeFlags flags);
748
749 // Adjusts the indicated bounds for the given flags and returns true if
750 // the calculation was possible, or false if it could not be estimated.
751 bool AdjustBoundsForPaint(SkRect& bounds, DisplayListAttributeFlags flags);
752
753 // Records the fact that we encountered an op that either could not
754 // estimate its bounds or that fills all of the destination space.
755 bool AccumulateUnbounded();
756
757 // Records the bounds for an op after modifying them according to the
758 // supplied attribute flags and transforming by the current matrix.
759 bool AccumulateOpBounds(const SkRect& bounds,
760 DisplayListAttributeFlags flags) {
761 SkRect safe_bounds = bounds;
762 return AccumulateOpBounds(safe_bounds, flags);
763 }
764
765 // Records the bounds for an op after modifying them according to the
766 // supplied attribute flags and transforming by the current matrix
767 // and clipping against the current clip.
768 bool AccumulateOpBounds(SkRect& bounds, DisplayListAttributeFlags flags);
769
770 // Records the given bounds after transforming by the current matrix
771 // and clipping against the current clip.
772 bool AccumulateBounds(SkRect& bounds);
773
774 DlPaint current_;
775};
776
777} // namespace flutter
778
779#endif // FLUTTER_DISPLAY_LIST_DL_BUILDER_H_
const char * options
int count
static bool compatible(const MTLRenderPassAttachmentDescriptor *first, const MTLRenderPassAttachmentDescriptor *second, const GrMtlPipelineState *pipelineState)
SkColor4f color
#define SK_Scalar1
Definition SkScalar.h:18
static SkScalar center(float pos0, float pos1)
Definition SkM44.h:150
static constexpr SkRect kMaxCullRect
Definition dl_builder.h:32
void setBlendMode(DlBlendMode mode) override
Definition dl_builder.h:315
void Skew(SkScalar sx, SkScalar sy) override
SkISize GetBaseLayerSize() const override
friend DlOpReceiver & DisplayListBuilderBenchmarkAccessor(DisplayListBuilder &builder)
void DrawLine(const SkPoint &p0, const SkPoint &p1, const DlPaint &paint) override
void drawRect(const SkRect &rect) override
void RestoreToCount(int restore_count) override
void clipRRect(const SkRRect &rrect, ClipOp clip_op, bool is_aa) override
Definition dl_builder.h:400
void DrawDRRect(const SkRRect &outer, const SkRRect &inner, const DlPaint &paint) override
void DrawVertices(const DlVertices *vertices, DlBlendMode mode, const DlPaint &paint) override
void setColorSource(const DlColorSource *source) override
Definition dl_builder.h:321
void TransformFullPerspective(SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt, SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt, SkScalar mzx, SkScalar mzy, SkScalar mzz, SkScalar mzt, SkScalar mwx, SkScalar mwy, SkScalar mwz, SkScalar mwt) override
void drawPath(const SkPath &path) override
SkRect GetLocalClipBounds() const override
Definition dl_builder.h:139
void DrawRect(const SkRect &rect, const DlPaint &paint) override
void transformFullPerspective(SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt, SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt, SkScalar mzx, SkScalar mzy, SkScalar mzz, SkScalar mzt, SkScalar mwx, SkScalar mwy, SkScalar mwz, SkScalar mwt) override
Definition dl_builder.h:381
void setDrawStyle(DlDrawStyle style) override
Definition dl_builder.h:291
void SetTransform(const SkM44 *matrix44) override
Definition dl_builder.h:96
void Transform(const SkMatrix *matrix) override
void setStrokeCap(DlStrokeCap cap) override
Definition dl_builder.h:279
void setMaskFilter(const DlMaskFilter *filter) override
Definition dl_builder.h:345
void transformReset() override
Definition dl_builder.h:393
void drawShadow(const SkPath &path, const DlColor color, const SkScalar elevation, bool transparent_occluder, SkScalar dpr) override
Definition dl_builder.h:478
void DrawColor(DlColor color, DlBlendMode mode) override
void DrawOval(const SkRect &bounds, const DlPaint &paint) override
void clipRect(const SkRect &rect, ClipOp clip_op, bool is_aa) override
Definition dl_builder.h:396
void setImageFilter(const DlImageFilter *filter) override
Definition dl_builder.h:327
void TransformReset() override
void clipPath(const SkPath &path, ClipOp clip_op, bool is_aa) override
Definition dl_builder.h:404
void ClipRRect(const SkRRect &rrect, ClipOp clip_op=ClipOp::kIntersect, bool is_aa=false) override
void setStrokeMiter(float limit) override
Definition dl_builder.h:303
friend DlOpReceiver & DisplayListBuilderTestingAccessor(DisplayListBuilder &builder)
void saveLayer(const SkRect &bounds, const SaveLayerOptions options, const DlImageFilter *backdrop) override
bool QuickReject(const SkRect &bounds) const override
void Translate(SkScalar tx, SkScalar ty) override
void DrawTextFrame(const std::shared_ptr< impeller::TextFrame > &text_frame, SkScalar x, SkScalar y, const DlPaint &paint) override
void DrawRRect(const SkRRect &rrect, const DlPaint &paint) override
void DrawPath(const SkPath &path, const DlPaint &paint) override
SkMatrix GetTransform() const override
Definition dl_builder.h:113
void drawAtlas(const sk_sp< DlImage > atlas, const SkRSXform xform[], const SkRect tex[], const DlColor colors[], int count, DlBlendMode mode, DlImageSampling sampling, const SkRect *cullRect, bool render_with_attributes) override
void skew(SkScalar sx, SkScalar sy) override
Definition dl_builder.h:372
void Rotate(SkScalar degrees) override
void setStrokeJoin(DlStrokeJoin join) override
Definition dl_builder.h:285
void DrawCircle(const SkPoint &center, SkScalar radius, const DlPaint &paint) override
void DrawPoints(PointMode mode, uint32_t count, const SkPoint pts[], const DlPaint &paint) override
void Transform2DAffine(SkScalar mxx, SkScalar mxy, SkScalar mxt, SkScalar myx, SkScalar myy, SkScalar myt) override
void setStrokeWidth(float width) override
Definition dl_builder.h:297
DisplayListBuilder(bool prepare_rtree)
Definition dl_builder.h:35
void drawImageNine(const sk_sp< DlImage > image, const SkIRect &center, const SkRect &dst, DlFilterMode filter, bool render_with_attributes) override
void drawArc(const SkRect &bounds, SkScalar start, SkScalar sweep, bool useCenter) override
void drawTextFrame(const std::shared_ptr< impeller::TextFrame > &text_frame, SkScalar x, SkScalar y) override
void rotate(SkScalar degrees) override
Definition dl_builder.h:370
SkImageInfo GetImageInfo() const override
void SetTransform(const SkMatrix *matrix) override
Definition dl_builder.h:91
void drawRRect(const SkRRect &rrect) override
void transform2DAffine(SkScalar mxx, SkScalar mxy, SkScalar mxt, SkScalar myx, SkScalar myy, SkScalar myt) override
Definition dl_builder.h:376
void drawDRRect(const SkRRect &outer, const SkRRect &inner) override
void drawImageRect(const sk_sp< DlImage > image, const SkRect &src, const SkRect &dst, DlImageSampling sampling, bool render_with_attributes, SrcRectConstraint constraint=SrcRectConstraint::kFast) override
void DrawTextBlob(const sk_sp< SkTextBlob > &blob, SkScalar x, SkScalar y, const DlPaint &paint) override
void DrawImage(const sk_sp< DlImage > &image, const SkPoint point, DlImageSampling sampling, const DlPaint *paint=nullptr) override
void drawVertices(const DlVertices *vertices, DlBlendMode mode) override
void translate(SkScalar tx, SkScalar ty) override
Definition dl_builder.h:366
void DrawShadow(const SkPath &path, const DlColor color, const SkScalar elevation, bool transparent_occluder, SkScalar dpr) override
void setAntiAlias(bool aa) override
Definition dl_builder.h:267
void DrawPaint(const DlPaint &paint) override
void SaveLayer(const SkRect *bounds, const DlPaint *paint=nullptr, const DlImageFilter *backdrop=nullptr) override
void drawDisplayList(const sk_sp< DisplayList > display_list, SkScalar opacity) override
Definition dl_builder.h:469
void setPathEffect(const DlPathEffect *effect) override
Definition dl_builder.h:339
sk_sp< DisplayList > Build()
Definition dl_builder.cc:67
void setInvertColors(bool invert) override
Definition dl_builder.h:273
SkM44 GetTransformFullPerspective() const override
Definition dl_builder.h:106
void DrawImageRect(const sk_sp< DlImage > &image, const SkRect &src, const SkRect &dst, DlImageSampling sampling, const DlPaint *paint=nullptr, SrcRectConstraint constraint=SrcRectConstraint::kFast) override
void setColorFilter(const DlColorFilter *filter) override
Definition dl_builder.h:333
void DrawDisplayList(const sk_sp< DisplayList > display_list, SkScalar opacity=SK_Scalar1) override
SkRect GetDestinationClipBounds() const override
Definition dl_builder.h:132
friend DlPaint DisplayListBuilderTestingAttributes(DisplayListBuilder &builder)
void drawPoints(PointMode mode, uint32_t count, const SkPoint pts[]) override
void ClipPath(const SkPath &path, ClipOp clip_op=ClipOp::kIntersect, bool is_aa=false) override
void DrawImageNine(const sk_sp< DlImage > &image, const SkIRect &center, const SkRect &dst, DlFilterMode filter, const DlPaint *paint=nullptr) override
void drawCircle(const SkPoint &center, SkScalar radius) override
void drawOval(const SkRect &bounds) override
void drawTextBlob(const sk_sp< SkTextBlob > blob, SkScalar x, SkScalar y) override
int GetSaveCount() const override
Definition dl_builder.h:58
void drawLine(const SkPoint &p0, const SkPoint &p1) override
void drawColor(DlColor color, DlBlendMode mode) override
Definition dl_builder.h:411
void scale(SkScalar sx, SkScalar sy) override
Definition dl_builder.h:368
void DrawArc(const SkRect &bounds, SkScalar start, SkScalar sweep, bool useCenter, const DlPaint &paint) override
void DrawAtlas(const sk_sp< DlImage > &atlas, const SkRSXform xform[], const SkRect tex[], const DlColor colors[], int count, DlBlendMode mode, DlImageSampling sampling, const SkRect *cullRect, const DlPaint *paint=nullptr) override
void setColor(DlColor color) override
Definition dl_builder.h:309
void drawImage(const sk_sp< DlImage > image, const SkPoint point, DlImageSampling sampling, bool render_with_attributes) override
static constexpr DisplayListAttributeFlags kDrawPaintFlags
Developer-facing API for rendering anything within the engine.
Definition dl_canvas.h:37
virtual void Transform(const SkMatrix *matrix)=0
virtual void DrawVertices(const DlVertices *vertices, DlBlendMode mode, const DlPaint &paint)=0
virtual void DrawImageRect(const sk_sp< DlImage > &image, const SkRect &src, const SkRect &dst, DlImageSampling sampling, const DlPaint *paint=nullptr, SrcRectConstraint constraint=SrcRectConstraint::kFast)=0
Internal API for rendering recorded display lists to backends.
bool isAntiAlias() const
Definition dl_paint.h:58
DlStrokeCap getStrokeCap() const
Definition dl_paint.h:100
DlColor getColor() const
Definition dl_paint.h:70
DlBlendMode getBlendMode() const
Definition dl_paint.h:84
float getStrokeMiter() const
Definition dl_paint.h:122
std::shared_ptr< const DlPathEffect > getPathEffect() const
Definition dl_paint.h:180
std::shared_ptr< const DlColorSource > getColorSource() const
Definition dl_paint.h:128
DlStrokeJoin getStrokeJoin() const
Definition dl_paint.h:108
DlDrawStyle getDrawStyle() const
Definition dl_paint.h:92
std::shared_ptr< const DlMaskFilter > getMaskFilter() const
Definition dl_paint.h:167
std::shared_ptr< const DlColorFilter > getColorFilter() const
Definition dl_paint.h:141
float getStrokeWidth() const
Definition dl_paint.h:116
std::shared_ptr< const DlImageFilter > getImageFilter() const
Definition dl_paint.h:154
bool isInvertColors() const
Definition dl_paint.h:64
Holds all of the data (both required and optional) for a DisplayList drawVertices call.
Definition dl_vertices.h:71
const Paint & paint
sk_sp< SkImage > image
Definition examples.cpp:29
SkBitmap source
Definition examples.cpp:28
float SkScalar
Definition extension.cpp:12
FlutterSemanticsFlag flags
gboolean invert
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
GAsyncResult * result
#define FML_LOG(severity)
Definition logging.h:82
#define FML_DCHECK(condition)
Definition logging.h:103
double y
double x
Optional< SkRect > bounds
Definition SkRecords.h:189
DlStrokeJoin
Definition dl_paint.h:38
bool NotEquals(const T *a, const T *b)
DlStrokeCap
Definition dl_paint.h:29
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
DlDrawStyle
Definition dl_paint.h:20
@ kFill
fills interior of shapes
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
@ kSrcOver
r = s + (1-sa)*d
#define T
int32_t width
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
Definition SkRect.h:646
constexpr DlColor withAlpha(uint8_t alpha) const
Definition dl_color.h:59
static constexpr DlColor kMidGrey()
Definition dl_color.h:31