Flutter Engine
 
Loading...
Searching...
No Matches
display_list.h File Reference

Go to the source code of this file.

Classes

class  flutter::SaveLayerOptions
 
class  flutter::DisplayList
 
class  flutter::DisplayList::Iterator
 Iterator utility class used for the |DisplayListbegin| and |DisplayListend| methods. It implements just the basic methods to enable iteration-style for loops. More...
 

Namespaces

namespace  flutter
 

Macros

#define FOR_EACH_DISPLAY_LIST_OP(V)
 
#define DL_OP_TO_ENUM_VALUE(name)   k##name,
 

Typedefs

using flutter::DlIndex = uint32_t
 

Enumerations

enum class  flutter::DisplayListOpType {
  flutter::kInvalidOp ,
  flutter::kMaxOp = kInvalidOp
}
 
enum class  flutter::DisplayListOpCategory {
  flutter::kAttribute ,
  flutter::kTransform ,
  flutter::kClip ,
  flutter::kSave ,
  flutter::kSaveLayer ,
  flutter::kRestore ,
  flutter::kRendering ,
  flutter::kSubDisplayList ,
  flutter::kInvalidCategory ,
  flutter::kMaxCategory = kInvalidCategory
}
 

Macro Definition Documentation

◆ DL_OP_TO_ENUM_VALUE

#define DL_OP_TO_ENUM_VALUE (   name)    k##name,

Definition at line 141 of file display_list.h.

◆ FOR_EACH_DISPLAY_LIST_OP

#define FOR_EACH_DISPLAY_LIST_OP (   V)

Definition at line 55 of file display_list.h.

141 {
143
144 // empty comment to make formatter happy
147};
148#undef DL_OP_TO_ENUM_VALUE
149
150enum class DisplayListOpCategory {
153 kClip,
154 kSave,
156 kRestore,
161};
162
163class DlOpReceiver;
164class DisplayListBuilder;
165
166class SaveLayerOptions {
167 public:
168 static const SaveLayerOptions kWithAttributes;
169 static const SaveLayerOptions kNoAttributes;
170
171 SaveLayerOptions() : flags_(0) {}
172 SaveLayerOptions(const SaveLayerOptions& options) : flags_(options.flags_) {}
173 explicit SaveLayerOptions(const SaveLayerOptions* options)
174 : flags_(options->flags_) {}
175
176 SaveLayerOptions without_optimizations() const {
177 SaveLayerOptions options;
178 options.fRendersWithAttributes = fRendersWithAttributes;
179 options.fBoundsFromCaller = fBoundsFromCaller;
180 return options;
181 }
182
183 bool renders_with_attributes() const { return fRendersWithAttributes; }
184 SaveLayerOptions with_renders_with_attributes() const {
185 SaveLayerOptions options(this);
186 options.fRendersWithAttributes = true;
187 return options;
188 }
189
190 bool can_distribute_opacity() const { return fCanDistributeOpacity; }
191 SaveLayerOptions with_can_distribute_opacity() const {
192 SaveLayerOptions options(this);
193 options.fCanDistributeOpacity = true;
194 return options;
195 }
196
197 // Returns true iff the bounds for the saveLayer operation were provided
198 // by the caller, otherwise the bounds will have been computed by the
199 // DisplayListBuilder and provided for reference.
200 bool bounds_from_caller() const { return fBoundsFromCaller; }
201 SaveLayerOptions with_bounds_from_caller() const {
202 SaveLayerOptions options(this);
203 options.fBoundsFromCaller = true;
204 return options;
205 }
206 SaveLayerOptions without_bounds_from_caller() const {
207 SaveLayerOptions options(this);
208 options.fBoundsFromCaller = false;
209 return options;
210 }
211 bool bounds_were_calculated() const { return !fBoundsFromCaller; }
212
213 // Returns true iff the bounds for the saveLayer do not fully cover the
214 // contained rendering operations. This will only occur if the original
215 // caller supplied bounds and those bounds were not a strict superset
216 // of the content bounds computed by the DisplayListBuilder.
217 bool content_is_clipped() const { return fContentIsClipped; }
218 SaveLayerOptions with_content_is_clipped() const {
219 SaveLayerOptions options(this);
220 options.fContentIsClipped = true;
221 return options;
222 }
223
224 bool contains_backdrop_filter() const { return fHasBackdropFilter; }
225 SaveLayerOptions with_contains_backdrop_filter() const {
226 SaveLayerOptions options(this);
227 options.fHasBackdropFilter = true;
228 return options;
229 }
230
231 bool content_is_unbounded() const { return fContentIsUnbounded; }
232 SaveLayerOptions with_content_is_unbounded() const {
233 SaveLayerOptions options(this);
234 options.fContentIsUnbounded = true;
235 return options;
236 }
237
238 SaveLayerOptions& operator=(const SaveLayerOptions& other) {
239 flags_ = other.flags_;
240 return *this;
241 }
242 bool operator==(const SaveLayerOptions& other) const {
243 return flags_ == other.flags_;
244 }
245
246 private:
247 union {
248 struct {
249 unsigned fRendersWithAttributes : 1;
250 unsigned fCanDistributeOpacity : 1;
251 unsigned fBoundsFromCaller : 1;
252 unsigned fContentIsClipped : 1;
253 unsigned fHasBackdropFilter : 1;
254 unsigned fContentIsUnbounded : 1;
255 };
256 uint32_t flags_;
257 };
258};
259
260using DlIndex = uint32_t;
261
262// The base class that contains a sequence of rendering operations
263// for dispatch to a DlOpReceiver. These objects must be instantiated
264// through an instance of DisplayListBuilder::build().
265class DisplayList : public SkRefCnt {
266 public:
267 DisplayList();
268
269 ~DisplayList();
270
271 void Dispatch(DlOpReceiver& ctx) const;
272 void Dispatch(DlOpReceiver& ctx, const DlRect& cull_rect) const;
273 void Dispatch(DlOpReceiver& ctx, const DlIRect& cull_rect) const;
274
275 // From historical behavior, SkPicture always included nested bytes,
276 // but nested ops are only included if requested. The defaults used
277 // here for these accessors follow that pattern.
278 size_t bytes(bool nested = true) const {
279 return sizeof(DisplayList) + storage_.size() +
280 (nested ? nested_byte_count_ : 0);
281 }
282
283 uint32_t op_count(bool nested = false) const {
284 return op_count_ + (nested ? nested_op_count_ : 0);
285 }
286
287 uint32_t total_depth() const { return total_depth_; }
288
289 uint32_t unique_id() const { return unique_id_; }
290
291 const DlRect& GetBounds() const { return bounds_; }
292
293 bool has_rtree() const { return rtree_ != nullptr; }
294 sk_sp<const DlRTree> rtree() const { return rtree_; }
295
296 bool Equals(const DisplayList* other) const;
297 bool Equals(const DisplayList& other) const { return Equals(&other); }
298 bool Equals(const sk_sp<const DisplayList>& other) const {
299 return Equals(other.get());
300 }
301
302 bool can_apply_group_opacity() const { return can_apply_group_opacity_; }
303 bool isUIThreadSafe() const { return is_ui_thread_safe_; }
304
305 /// @brief Indicates if there are any rendering operations in this
306 /// DisplayList that will modify a surface of transparent black
307 /// pixels.
308 ///
309 /// This condition can be used to determine whether to create a cleared
310 /// surface, render a DisplayList into it, and then composite the
311 /// result into a scene. It is not uncommon for code in the engine to
312 /// come across such degenerate DisplayList objects when slicing up a
313 /// frame between platform views.
314 bool modifies_transparent_black() const {
315 return modifies_transparent_black_;
316 }
317
318 const DisplayListStorage& GetStorage() const { return storage_; }
319
320 /// @brief Indicates if there are any saveLayer operations at the root
321 /// surface level of the DisplayList that use a backdrop filter.
322 ///
323 /// This condition can be used to determine what kind of surface to create
324 /// for the root layer into which to render the DisplayList as some GPUs
325 /// can support surfaces that do or do not support the readback that would
326 /// be required for the backdrop filter to do its work.
327 bool root_has_backdrop_filter() const { return root_has_backdrop_filter_; }
328
329 /// @brief Indicates if a rendering operation at the root level of the
330 /// DisplayList had an unbounded result, not otherwise limited by
331 /// a clip operation.
332 ///
333 /// This condition can occur in a number of situations. The most common
334 /// situation is when there is a drawPaint or drawColor rendering
335 /// operation which fills out the entire drawable surface unless it is
336 /// bounded by a clip. Other situations include an operation rendered
337 /// through an ImageFilter that cannot compute the resulting bounds or
338 /// when an unclipped backdrop filter is applied by a save layer.
339 bool root_is_unbounded() const { return root_is_unbounded_; }
340
341 /// @brief Indicates the maximum DlBlendMode used on any rendering op
342 /// in the root surface of the DisplayList.
343 ///
344 /// This condition can be used to determine what kind of surface to create
345 /// for the root layer into which to render the DisplayList as some GPUs
346 /// can support surfaces that do or do not support the readback that would
347 /// be required for the indicated blend mode to do its work.
348 DlBlendMode max_root_blend_mode() const { return max_root_blend_mode_; }
349
350 /// @brief Iterator utility class used for the |DisplayList::begin|
351 /// and |DisplayList::end| methods. It implements just the
352 /// basic methods to enable iteration-style for loops.
353 class Iterator {
354 public:
355 DlIndex operator*() const { return value_; }
356 bool operator!=(const Iterator& other) { return value_ != other.value_; }
357 Iterator& operator++() {
358 value_++;
359 return *this;
360 }
361
362 private:
363 explicit Iterator(DlIndex value) : value_(value) {}
364
365 DlIndex value_;
366
367 friend class DisplayList;
368 };
369
370 /// @brief Return the number of stored records in the DisplayList.
371 ///
372 /// Each stored record represents a dispatchable operation that will be
373 /// sent to a |DlOpReceiver| by the |Dispatch| method. You can directly
374 /// simulate the |Dispatch| method using a simple for loop on the indices:
375 ///
376 /// {
377 /// for (DlIndex i = 0u; i < display_list->GetRecordCount(); i++) {
378 /// display_list->Dispatch(my_receiver, i);
379 /// }
380 /// }
381 ///
382 /// @see |Dispatch(receiver, index)|
383 /// @see |begin|
384 /// @see |end|
385 /// @see |GetCulledIndices|
386 DlIndex GetRecordCount() const { return offsets_.size(); }
387
388 /// @brief Return an iterator to the start of the stored records,
389 /// enabling the iteration form of a for loop.
390 ///
391 /// Each stored record represents a dispatchable operation that will be
392 /// sent to a |DlOpReceiver| by the |Dispatch| method. You can directly
393 /// simulate the |Dispatch| method using a simple for loop on the indices:
394 ///
395 /// {
396 /// for (DlIndex i : *display_list) {
397 /// display_list->Dispatch(my_receiver, i);
398 /// }
399 /// }
400 ///
401 /// @see |end|
402 /// @see |GetCulledIndices|
403 Iterator begin() const { return Iterator(0u); }
404
405 /// @brief Return an iterator to the end of the stored records,
406 /// enabling the iteration form of a for loop.
407 ///
408 /// Each stored record represents a dispatchable operation that will be
409 /// sent to a |DlOpReceiver| by the |Dispatch| method. You can directly
410 /// simulate the |Dispatch| method using a simple for loop on the indices:
411 ///
412 /// {
413 /// for (DlIndex i : *display_list) {
414 /// display_list->Dispatch(my_receiver, i);
415 /// }
416 /// }
417 ///
418 /// @see |begin|
419 /// @see |GetCulledIndices|
420 Iterator end() const { return Iterator(offsets_.size()); }
421
422 /// @brief Dispatch a single stored operation by its index.
423 ///
424 /// Each stored record represents a dispatchable operation that will be
425 /// sent to a |DlOpReceiver| by the |Dispatch| method. You can use this
426 /// method to dispatch a single operation to your receiver with an index
427 /// between |0u| (inclusive) and |GetRecordCount()| (exclusive), as in:
428 ///
429 /// {
430 /// for (DlIndex i = 0u; i < display_list->GetRecordCount(); i++) {
431 /// display_list->Dispatch(my_receiver, i);
432 /// }
433 /// }
434 ///
435 /// If the index is out of the range of the stored records, this method
436 /// will not call any methods on the receiver and return false. You can
437 /// check the return value for true if you want to make sure you are
438 /// using valid indices.
439 ///
440 /// @see |GetRecordCount|
441 /// @see |begin|
442 /// @see |end|
443 /// @see |GetCulledIndices|
444 bool Dispatch(DlOpReceiver& receiver, DlIndex index) const;
445
446 /// @brief Return an enum describing the specific op type stored at
447 /// the indicated index.
448 ///
449 /// The specific types of the records are subject to change without notice
450 /// as the DisplayList code is developed and optimized. These values are
451 /// useful mostly for debugging purposes and should not be used in
452 /// production code.
453 ///
454 /// @see |GetOpCategory| for a more stable description of the records
455 DisplayListOpType GetOpType(DlIndex index) const;
456
457 /// @brief Return an enum describing the general category of the
458 /// operation record stored at the indicated index.
459 ///
460 /// The categories are general and stable and can be used fairly safely
461 /// in production code to plan how to dispatch or reorder ops during
462 /// final rendering.
463 ///
464 /// @see |GetOpType| for a more detailed description of the records
465 /// primarily for debugging use
466 DisplayListOpCategory GetOpCategory(DlIndex index) const;
467
468 /// @brief Return an enum describing the general category of the
469 /// operation record with the given type.
470 ///
471 /// @see |GetOpType| for a more detailed description of the records
472 /// primarily for debugging use
473 static DisplayListOpCategory GetOpCategory(DisplayListOpType type);
474
475 /// @brief Return a vector of valid indices for records stored in
476 /// the DisplayList that must be dispatched if you are
477 /// restricted to the indicated cull_rect.
478 ///
479 /// This method can be used along with indexed dispatching to implement
480 /// RTree culling while still maintaining control over planning of
481 /// operations to be rendered, as in:
482 ///
483 /// {
484 /// std::vector<DlIndex> indices =
485 /// display_list->GetCulledIndices(cull-rect);
486 /// for (DlIndex i : indices) {
487 /// display_list->Dispatch(my_receiver, i);
488 /// }
489 /// }
490 ///
491 /// The indices returned in the vector will automatically deal with
492 /// including or culling related operations such as attributes, clips
493 /// and transforms that will provide state for any rendering operations
494 /// selected by the culling checks.
495 ///
496 /// @see |GetOpType| for a more detailed description of the records
497 /// primarily for debugging use
498 ///
499 /// @see |Dispatch(receiver, index)|
500 std::vector<DlIndex> GetCulledIndices(const DlRect& cull_rect) const;
501
502 private:
503 DisplayList(DisplayListStorage&& ptr,
504 std::vector<size_t>&& offsets,
505 uint32_t op_count,
506 size_t nested_byte_count,
507 uint32_t nested_op_count,
508 uint32_t total_depth,
509 const DlRect& bounds,
510 bool can_apply_group_opacity,
511 bool is_ui_thread_safe,
512 bool modifies_transparent_black,
513 DlBlendMode max_root_blend_mode,
514 bool root_has_backdrop_filter,
515 bool root_is_unbounded,
516 sk_sp<const DlRTree> rtree);
517
518 static uint32_t next_unique_id();
519
520 static void DisposeOps(const DisplayListStorage& storage,
521 const std::vector<size_t>& offsets);
522
523 const DisplayListStorage storage_;
524 const std::vector<size_t> offsets_;
525
526 const uint32_t op_count_;
527 const size_t nested_byte_count_;
528 const uint32_t nested_op_count_;
529
530 const uint32_t total_depth_;
531
532 const uint32_t unique_id_;
533 const DlRect bounds_;
534
535 const bool can_apply_group_opacity_;
536 const bool is_ui_thread_safe_;
537 const bool modifies_transparent_black_;
538 const bool root_has_backdrop_filter_;
539 const bool root_is_unbounded_;
540 const DlBlendMode max_root_blend_mode_;
541
542 const sk_sp<const DlRTree> rtree_;
543
544 void DispatchOneOp(DlOpReceiver& receiver, const uint8_t* ptr) const;
545
546 void RTreeResultsToIndexVector(std::vector<DlIndex>& indices,
547 const std::vector<int>& rtree_results) const;
548
549 friend class DisplayListBuilder;
550};
551
552} // namespace flutter
553
554#endif // FLUTTER_DISPLAY_LIST_DISPLAY_LIST_H_
GLenum type
#define FOR_EACH_DISPLAY_LIST_OP(V)
#define DL_OP_TO_ENUM_VALUE(name)
int32_t value
bool operator==(const FlutterPoint &a, const FlutterPoint &b)
static constexpr char kTransform[]
uint32_t DlIndex
DisplayListOpCategory
impeller::Rect DlRect
bool Equals(const T *a, const U *b)
impeller::BlendMode DlBlendMode
bool operator!=(const T &value, const UniqueObject< T, Traits > &object)
constexpr Color operator*(T value, const Color &c)
Definition color.h:909
flutter::DisplayList DisplayList
flutter::SaveLayerOptions SaveLayerOptions
const size_t end