Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
display_list.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_DISPLAY_LIST_H_
6#define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_H_
7
8#include <memory>
9#include <optional>
10
11#include "flutter/display_list/dl_sampling_options.h"
12#include "flutter/display_list/geometry/dl_rtree.h"
13#include "flutter/fml/logging.h"
14
15// The Flutter DisplayList mechanism encapsulates a persistent sequence of
16// rendering operations.
17//
18// This file contains the definitions for:
19// DisplayList: the base class that holds the information about the
20// sequence of operations and can dispatch them to a DlOpReceiver
21// DlOpReceiver: a pure virtual interface which can be implemented to field
22// the requests for purposes such as sending them to an SkCanvas
23// or detecting various rendering optimization scenarios
24// DisplayListBuilder: a class for constructing a DisplayList from DlCanvas
25// method calls and which can act as a DlOpReceiver as well
26//
27// Other files include various class definitions for dealing with display
28// lists, such as:
29// skia/dl_sk_*.h: classes to interact between SkCanvas and DisplayList
30// (SkCanvas->DisplayList adapter and vice versa)
31//
32// display_list_utils.h: various utility classes to ease implementing
33// a DlOpReceiver, including NOP implementations of
34// the attribute, clip, and transform methods,
35// classes to track attributes, clips, and transforms
36// and a class to compute the bounds of a DisplayList
37// Any class implementing DlOpReceiver can inherit from
38// these utility classes to simplify its creation
39//
40// The Flutter DisplayList mechanism is used in a similar manner to the Skia
41// SkPicture mechanism.
42//
43// A DisplayList must be created using a DisplayListBuilder using its stateless
44// methods inherited from DlCanvas.
45//
46// A DisplayList can be read back by implementing the DlOpReceiver virtual
47// methods (with help from some of the classes in the utils file) and
48// passing an instance to the Dispatch() method, or it can be rendered
49// to Skia using a DlSkCanvasDispatcher.
50//
51// The mechanism is inspired by the SkLiteDL class that is not directly
52// supported by Skia, but has been recommended as a basis for custom
53// display lists for a number of their customers.
54
55namespace flutter {
56
57#define FOR_EACH_DISPLAY_LIST_OP(V) \
58 V(SetAntiAlias) \
59 V(SetInvertColors) \
60 \
61 V(SetStrokeCap) \
62 V(SetStrokeJoin) \
63 \
64 V(SetStyle) \
65 V(SetStrokeWidth) \
66 V(SetStrokeMiter) \
67 \
68 V(SetColor) \
69 V(SetBlendMode) \
70 \
71 V(SetPodPathEffect) \
72 V(ClearPathEffect) \
73 \
74 V(ClearColorFilter) \
75 V(SetPodColorFilter) \
76 \
77 V(ClearColorSource) \
78 V(SetPodColorSource) \
79 V(SetImageColorSource) \
80 V(SetRuntimeEffectColorSource) \
81 \
82 V(ClearImageFilter) \
83 V(SetPodImageFilter) \
84 V(SetSharedImageFilter) \
85 \
86 V(ClearMaskFilter) \
87 V(SetPodMaskFilter) \
88 \
89 V(Save) \
90 V(SaveLayer) \
91 V(SaveLayerBackdrop) \
92 V(Restore) \
93 \
94 V(Translate) \
95 V(Scale) \
96 V(Rotate) \
97 V(Skew) \
98 V(Transform2DAffine) \
99 V(TransformFullPerspective) \
100 V(TransformReset) \
101 \
102 V(ClipIntersectRect) \
103 V(ClipIntersectRRect) \
104 V(ClipIntersectPath) \
105 V(ClipDifferenceRect) \
106 V(ClipDifferenceRRect) \
107 V(ClipDifferencePath) \
108 \
109 V(DrawPaint) \
110 V(DrawColor) \
111 \
112 V(DrawLine) \
113 V(DrawRect) \
114 V(DrawOval) \
115 V(DrawCircle) \
116 V(DrawRRect) \
117 V(DrawDRRect) \
118 V(DrawArc) \
119 V(DrawPath) \
120 \
121 V(DrawPoints) \
122 V(DrawLines) \
123 V(DrawPolygon) \
124 V(DrawVertices) \
125 \
126 V(DrawImage) \
127 V(DrawImageWithAttr) \
128 V(DrawImageRect) \
129 V(DrawImageNine) \
130 V(DrawImageNineWithAttr) \
131 V(DrawAtlas) \
132 V(DrawAtlasCulled) \
133 \
134 V(DrawDisplayList) \
135 V(DrawTextBlob) \
136 V(DrawTextFrame) \
137 \
138 V(DrawShadow) \
139 V(DrawShadowTransparentOccluder)
140
141#define DL_OP_TO_ENUM_VALUE(name) k##name,
144#ifdef IMPELLER_ENABLE_3D
145 DL_OP_TO_ENUM_VALUE(SetSceneColorSource)
146#endif // IMPELLER_ENABLE_3D
147};
148#undef DL_OP_TO_ENUM_VALUE
149
150class DlOpReceiver;
151class DisplayListBuilder;
152
154 public:
157
162
169
173 options.fRendersWithAttributes = true;
174 return options;
175 }
176
180 options.fCanDistributeOpacity = true;
181 return options;
182 }
183
184 // Returns true iff the bounds for the saveLayer operation were provided
185 // by the caller, otherwise the bounds will have been computed by the
186 // DisplayListBuilder and provided for reference.
187 bool bounds_from_caller() const { return fBoundsFromCaller; }
190 options.fBoundsFromCaller = true;
191 return options;
192 }
195 options.fBoundsFromCaller = false;
196 return options;
197 }
199
200 // Returns true iff the bounds for the saveLayer do not fully cover the
201 // contained rendering operations. This will only occur if the original
202 // caller supplied bounds and those bounds were not a strict superset
203 // of the content bounds computed by the DisplayListBuilder.
204 bool content_is_clipped() const { return fContentIsClipped; }
207 options.fContentIsClipped = true;
208 return options;
209 }
210
212 flags_ = other.flags_;
213 return *this;
214 }
215 bool operator==(const SaveLayerOptions& other) const {
216 return flags_ == other.flags_;
217 }
218 bool operator!=(const SaveLayerOptions& other) const {
219 return flags_ != other.flags_;
220 }
221
222 private:
223 union {
224 struct {
227 unsigned fBoundsFromCaller : 1;
228 unsigned fContentIsClipped : 1;
229 };
230 uint32_t flags_;
231 };
232};
233
234// Manages a buffer allocated with malloc.
236 public:
239
240 uint8_t* get() const { return ptr_.get(); }
241
242 void realloc(size_t count) {
243 ptr_.reset(static_cast<uint8_t*>(std::realloc(ptr_.release(), count)));
244 FML_CHECK(ptr_);
245 }
246
247 private:
248 struct FreeDeleter {
249 void operator()(uint8_t* p) { std::free(p); }
250 };
251 std::unique_ptr<uint8_t, FreeDeleter> ptr_;
252};
253
254class Culler;
255
256// The base class that contains a sequence of rendering operations
257// for dispatch to a DlOpReceiver. These objects must be instantiated
258// through an instance of DisplayListBuilder::build().
259class DisplayList : public SkRefCnt {
260 public:
261 DisplayList();
262
263 ~DisplayList();
264
265 void Dispatch(DlOpReceiver& ctx) const;
266 void Dispatch(DlOpReceiver& ctx, const SkRect& cull_rect) const;
267 void Dispatch(DlOpReceiver& ctx, const SkIRect& cull_rect) const;
268
269 // From historical behavior, SkPicture always included nested bytes,
270 // but nested ops are only included if requested. The defaults used
271 // here for these accessors follow that pattern.
272 size_t bytes(bool nested = true) const {
273 return sizeof(DisplayList) + byte_count_ +
274 (nested ? nested_byte_count_ : 0);
275 }
276
277 uint32_t op_count(bool nested = false) const {
278 return op_count_ + (nested ? nested_op_count_ : 0);
279 }
280
281 uint32_t total_depth() const { return total_depth_; }
282
283 uint32_t unique_id() const { return unique_id_; }
284
285 const SkRect& bounds() const { return bounds_; }
286
287 bool has_rtree() const { return rtree_ != nullptr; }
288 sk_sp<const DlRTree> rtree() const { return rtree_; }
289
290 bool Equals(const DisplayList* other) const;
291 bool Equals(const DisplayList& other) const { return Equals(&other); }
292 bool Equals(const sk_sp<const DisplayList>& other) const {
293 return Equals(other.get());
294 }
295
296 bool can_apply_group_opacity() const { return can_apply_group_opacity_; }
297 bool isUIThreadSafe() const { return is_ui_thread_safe_; }
298
299 /// @brief Indicates if there are any rendering operations in this
300 /// DisplayList that will modify a surface of transparent black
301 /// pixels.
302 ///
303 /// This condition can be used to determine whether to create a cleared
304 /// surface, render a DisplayList into it, and then composite the
305 /// result into a scene. It is not uncommon for code in the engine to
306 /// come across such degenerate DisplayList objects when slicing up a
307 /// frame between platform views.
309 return modifies_transparent_black_;
310 }
311
312 private:
314 size_t byte_count,
315 uint32_t op_count,
316 size_t nested_byte_count,
317 uint32_t nested_op_count,
318 uint32_t total_depth,
319 const SkRect& bounds,
321 bool is_ui_thread_safe,
324
325 static uint32_t next_unique_id();
326
327 static void DisposeOps(uint8_t* ptr, uint8_t* end);
328
329 const DisplayListStorage storage_;
330 const size_t byte_count_;
331 const uint32_t op_count_;
332
333 const size_t nested_byte_count_;
334 const uint32_t nested_op_count_;
335
336 const uint32_t total_depth_;
337
338 const uint32_t unique_id_;
339 const SkRect bounds_;
340
341 const bool can_apply_group_opacity_;
342 const bool is_ui_thread_safe_;
343 const bool modifies_transparent_black_;
344
345 const sk_sp<const DlRTree> rtree_;
346
347 void Dispatch(DlOpReceiver& ctx,
348 uint8_t* ptr,
349 uint8_t* end,
350 Culler& culler) const;
351
352 friend class DisplayListBuilder;
353};
354
355} // namespace flutter
356
357#endif // FLUTTER_DISPLAY_LIST_DISPLAY_LIST_H_
const char * options
int count
void realloc(size_t count)
DisplayListStorage(DisplayListStorage &&)=default
bool Equals(const sk_sp< const DisplayList > &other) const
bool Equals(const DisplayList &other) const
const SkRect & bounds() const
uint32_t unique_id() const
bool modifies_transparent_black() const
Indicates if there are any rendering operations in this DisplayList that will modify a surface of tra...
bool can_apply_group_opacity() const
bool Equals(const DisplayList *other) const
uint32_t total_depth() const
size_t bytes(bool nested=true) const
bool isUIThreadSafe() const
bool has_rtree() const
uint32_t op_count(bool nested=false) const
void Dispatch(DlOpReceiver &ctx) const
sk_sp< const DlRTree > rtree() const
Internal API for rendering recorded display lists to backends.
bool content_is_clipped() const
bool operator!=(const SaveLayerOptions &other) const
static const SaveLayerOptions kNoAttributes
SaveLayerOptions with_renders_with_attributes() const
SaveLayerOptions & operator=(const SaveLayerOptions &other)
SaveLayerOptions with_can_distribute_opacity() const
bool renders_with_attributes() const
bool operator==(const SaveLayerOptions &other) const
SaveLayerOptions with_bounds_from_caller() const
SaveLayerOptions(const SaveLayerOptions *options)
bool bounds_from_caller() const
bool bounds_were_calculated() const
SaveLayerOptions without_bounds_from_caller() const
static const SaveLayerOptions kWithAttributes
SaveLayerOptions without_optimizations() const
SaveLayerOptions with_content_is_clipped() const
SaveLayerOptions(const SaveLayerOptions &options)
bool can_distribute_opacity() const
T * get() const
Definition SkRefCnt.h:303
#define FOR_EACH_DISPLAY_LIST_OP(V)
#define DL_OP_TO_ENUM_VALUE(name)
glong glong end
#define FML_CHECK(condition)
Definition logging.h:85