5#include "flutter/display_list/dl_builder.h"
7#include "flutter/display_list/display_list.h"
8#include "flutter/display_list/dl_blend_mode.h"
9#include "flutter/display_list/dl_op_flags.h"
10#include "flutter/display_list/dl_op_records.h"
11#include "flutter/display_list/effects/dl_color_source.h"
12#include "flutter/display_list/utils/dl_accumulation_rect.h"
18#define DL_BUILDER_PAGE 4096
23template <
typename S,
typename... Rest>
26 <<
"Expected " <<
dst <<
" to be aligned for at least " <<
alignof(
S)
30 memcpy(
dst,
src, n *
sizeof(
S));
31 dst =
reinterpret_cast<void*
>(
reinterpret_cast<uint8_t*
>(
dst) +
35 CopyV(
dst, std::forward<Rest>(rest)...);
42template <
typename T,
typename... Args>
43void* DisplayListBuilder::Push(
size_t pod, Args&&...
args) {
46 if (used_ +
size > allocated_) {
48 "This math needs updating for non-pow2.");
53 memset(storage_.
get() + used_, 0, allocated_ - used_);
56 auto op =
reinterpret_cast<T*
>(storage_.
get() + used_);
58 new (op)
T{std::forward<Args>(
args)...};
61 render_op_count_ += T::kRenderOpInc;
62 depth_ += T::kDepthInc * render_op_depth_cost_;
68 while (save_stack_.size() > 1) {
73 int count = render_op_count_;
74 size_t nested_bytes = nested_bytes_;
75 int nested_count = nested_op_count_;
76 uint32_t total_depth = depth_;
77 bool opacity_compatible = current_layer().is_group_opacity_compatible();
78 bool is_safe = is_ui_thread_safe_;
79 bool affects_transparency = current_layer().affects_transparent_layer;
80 bool root_has_backdrop_filter = current_layer().contains_backdrop_filter;
81 DlBlendMode max_root_blend_mode = current_layer().max_blend_mode;
85 if (rtree_data_.has_value()) {
86 auto& rects = rtree_data_->rects;
87 auto& indices = rtree_data_->indices;
88 rtree = sk_make_sp<DlRTree>(rects.data(), rects.size(), indices.data(),
89 [](
int id) { return id >= 0; });
96 bounds = current_layer().global_space_accumulator.bounds();
99 used_ = allocated_ = render_op_count_ = op_index_ = 0;
100 nested_bytes_ = nested_op_count_ = 0;
102 is_ui_thread_safe_ =
true;
103 current_opacity_compatibility_ =
true;
104 render_op_depth_cost_ = 1u;
107 save_stack_.pop_back();
108 Init(rtree !=
nullptr);
112 std::move(storage_), bytes,
count, nested_bytes, nested_count,
113 total_depth,
bounds, opacity_compatible, is_safe, affects_transparency,
114 max_root_blend_mode, root_has_backdrop_filter, std::move(rtree)));
130void DisplayListBuilder::Init(
bool prepare_rtree) {
134 save_stack_.emplace_back(original_cull_rect_);
135 current_info().is_nop = original_cull_rect_.
IsEmpty();
137 rtree_data_.emplace();
142 uint8_t* ptr = storage_.
get();
144 DisplayList::DisposeOps(ptr, ptr + used_);
157void DisplayListBuilder::onSetAntiAlias(
bool aa) {
159 Push<SetAntiAliasOp>(0, aa);
161void DisplayListBuilder::onSetInvertColors(
bool invert) {
163 Push<SetInvertColorsOp>(0,
invert);
164 UpdateCurrentOpacityCompatibility();
166void DisplayListBuilder::onSetStrokeCap(
DlStrokeCap cap) {
168 Push<SetStrokeCapOp>(0, cap);
172 Push<SetStrokeJoinOp>(0,
join);
174void DisplayListBuilder::onSetDrawStyle(
DlDrawStyle style) {
176 Push<SetStyleOp>(0, style);
178void DisplayListBuilder::onSetStrokeWidth(
float width) {
180 Push<SetStrokeWidthOp>(0,
width);
182void DisplayListBuilder::onSetStrokeMiter(
float limit) {
184 Push<SetStrokeMiterOp>(0, limit);
188 Push<SetColorOp>(0,
color);
192 Push<SetBlendModeOp>(0,
mode);
193 UpdateCurrentOpacityCompatibility();
196void DisplayListBuilder::onSetColorSource(
const DlColorSource*
source) {
199 Push<ClearColorSourceOp>(0);
202 is_ui_thread_safe_ = is_ui_thread_safe_ &&
source->isUIThreadSafe();
205 const DlColorColorSource* color_source =
source->asColor();
207 setColor(color_source->color());
213 Push<SetImageColorSourceOp>(0, image_source);
217 const DlLinearGradientColorSource*
linear =
source->asLinearGradient();
219 void* pod = Push<SetPodColorSourceOp>(
linear->size());
220 new (pod) DlLinearGradientColorSource(
linear);
224 const DlRadialGradientColorSource* radial =
source->asRadialGradient();
226 void* pod = Push<SetPodColorSourceOp>(radial->size());
227 new (pod) DlRadialGradientColorSource(radial);
231 const DlConicalGradientColorSource* conical =
232 source->asConicalGradient();
234 void* pod = Push<SetPodColorSourceOp>(conical->size());
235 new (pod) DlConicalGradientColorSource(conical);
239 const DlSweepGradientColorSource* sweep =
source->asSweepGradient();
241 void* pod = Push<SetPodColorSourceOp>(sweep->size());
242 new (pod) DlSweepGradientColorSource(sweep);
246 const DlRuntimeEffectColorSource* effect =
source->asRuntimeEffect();
248 Push<SetRuntimeEffectColorSourceOp>(0, effect);
251#ifdef IMPELLER_ENABLE_3D
252 case DlColorSourceType::kScene: {
253 const DlSceneColorSource* scene =
source->asScene();
255 Push<SetSceneColorSourceOp>(0, scene);
262void DisplayListBuilder::onSetImageFilter(
const DlImageFilter* filter) {
263 if (filter ==
nullptr) {
265 Push<ClearImageFilterOp>(0);
268 switch (filter->type()) {
270 const DlBlurImageFilter* blur_filter = filter->asBlur();
272 void* pod = Push<SetPodImageFilterOp>(blur_filter->size());
273 new (pod) DlBlurImageFilter(blur_filter);
277 const DlDilateImageFilter* dilate_filter = filter->asDilate();
279 void* pod = Push<SetPodImageFilterOp>(dilate_filter->size());
280 new (pod) DlDilateImageFilter(dilate_filter);
284 const DlErodeImageFilter* erode_filter = filter->asErode();
286 void* pod = Push<SetPodImageFilterOp>(erode_filter->size());
287 new (pod) DlErodeImageFilter(erode_filter);
291 const DlMatrixImageFilter* matrix_filter = filter->asMatrix();
293 void* pod = Push<SetPodImageFilterOp>(matrix_filter->size());
294 new (pod) DlMatrixImageFilter(matrix_filter);
300 Push<SetSharedImageFilterOp>(0, filter);
306void DisplayListBuilder::onSetColorFilter(
const DlColorFilter* filter) {
307 if (filter ==
nullptr) {
309 Push<ClearColorFilterOp>(0);
312 switch (filter->type()) {
314 const DlBlendColorFilter* blend_filter = filter->asBlend();
316 void* pod = Push<SetPodColorFilterOp>(blend_filter->size());
317 new (pod) DlBlendColorFilter(blend_filter);
321 const DlMatrixColorFilter* matrix_filter = filter->asMatrix();
323 void* pod = Push<SetPodColorFilterOp>(matrix_filter->size());
324 new (pod) DlMatrixColorFilter(matrix_filter);
328 void* pod = Push<SetPodColorFilterOp>(filter->size());
329 new (pod) DlSrgbToLinearGammaColorFilter();
333 void* pod = Push<SetPodColorFilterOp>(filter->size());
334 new (pod) DlLinearToSrgbGammaColorFilter();
339 UpdateCurrentOpacityCompatibility();
341void DisplayListBuilder::onSetMaskFilter(
const DlMaskFilter* filter) {
342 if (filter ==
nullptr) {
344 render_op_depth_cost_ = 1u;
345 Push<ClearMaskFilterOp>(0);
348 render_op_depth_cost_ = 2u;
349 switch (filter->type()) {
351 const DlBlurMaskFilter* blur_filter = filter->asBlur();
353 void* pod = Push<SetPodMaskFilterOp>(blur_filter->size());
354 new (pod) DlBlurMaskFilter(blur_filter);
361void DisplayListBuilder::SetAttributesFromPaint(
363 const DisplayListAttributeFlags
flags) {
364 if (
flags.applies_anti_alias()) {
365 setAntiAlias(
paint.isAntiAlias());
367 if (
flags.applies_alpha_or_color()) {
368 setColor(
paint.getColor());
370 if (
flags.applies_blend()) {
371 setBlendMode(
paint.getBlendMode());
373 if (
flags.applies_style()) {
374 setDrawStyle(
paint.getDrawStyle());
377 setStrokeWidth(
paint.getStrokeWidth());
378 setStrokeMiter(
paint.getStrokeMiter());
379 setStrokeCap(
paint.getStrokeCap());
380 setStrokeJoin(
paint.getStrokeJoin());
382 if (
flags.applies_shader()) {
383 setColorSource(
paint.getColorSource().
get());
385 if (
flags.applies_color_filter()) {
386 setInvertColors(
paint.isInvertColors());
387 setColorFilter(
paint.getColorFilter().
get());
389 if (
flags.applies_image_filter()) {
390 setImageFilter(
paint.getImageFilter().
get());
392 if (
flags.applies_mask_filter()) {
393 setMaskFilter(
paint.getMaskFilter().
get());
397void DisplayListBuilder::checkForDeferredSave() {
398 if (current_info().has_deferred_save_op) {
399 size_t save_offset = used_;
401 current_info().save_offset = save_offset;
402 current_info().save_depth = depth_;
403 current_info().has_deferred_save_op =
false;
408 bool was_nop = current_info().is_nop;
409 save_stack_.emplace_back(¤t_info());
410 current_info().is_nop = was_nop;
413 FML_DCHECK(current_info().has_deferred_save_op);
424 if (
result == OpResult::kNoEffect) {
432 current_info().is_nop =
true;
437 current_layer().contains_backdrop_filter =
true;
443 size_t save_offset = used_;
444 uint32_t save_depth = depth_;
447 bool will_be_unbounded = (
backdrop !=
nullptr);
448 std::shared_ptr<const DlImageFilter> filter;
450 if (
options.renders_with_attributes()) {
451 if (!paint_nops_on_transparency()) {
453 will_be_unbounded =
true;
456 CheckLayerOpacityCompatibility(
true);
457 UpdateLayerResult(
result,
true);
459 CheckLayerOpacityCompatibility(
false);
460 UpdateLayerResult(
result,
false);
471 if (will_be_unbounded) {
475 [[maybe_unused]]
bool unclipped = AccumulateUnbounded();
483 rtree_data_.has_value() ? rtree_data_->rects.size() : 0u;
485 save_stack_.emplace_back(¤t_info(), filter, rtree_index);
488 FML_DCHECK(!current_info().has_deferred_save_op);
489 current_info().save_offset = save_offset;
490 current_info().save_depth = save_depth;
496 SkRect outer_cull_rect = current_info().global_state.device_cull_rect();
501 if (filter->get_input_device_bounds(output_bounds,
matrix,
503 current_info().global_state.resetDeviceCullRect(
509 current_info().global_state.resetDeviceCullRect(
kMaxCullRect);
535 Push<SaveLayerOp>(0,
options, record_bounds);
539 if (
options.renders_with_attributes()) {
544 if (!current_opacity_compatibility_ || filter) {
545 UpdateLayerOpacityCompatibility(
false);
560 if (
paint !=
nullptr) {
562 SetAttributesFromPaint(*
paint,
569 if (save_stack_.size() <= 1) {
573 if (!current_info().has_deferred_save_op) {
575 current_info().save_offset);
577 op->
type == DisplayListOpType::kSaveLayer ||
578 op->
type == DisplayListOpType::kSaveLayerBackdrop);
583 if (current_info().is_save_layer) {
595 save_stack_.pop_back();
598void DisplayListBuilder::RestoreLayer() {
601 FML_DCHECK(!current_info().has_deferred_save_op);
606 depth_ += render_op_depth_cost_;
608 SkRect content_bounds = current_layer().layer_local_accumulator.bounds();
611 storage_.
get() + current_info().save_offset);
613 layer_op->
type == DisplayListOpType::kSaveLayerBackdrop);
621 layer_op->
rect = content_bounds;
624 if (current_layer().contains_backdrop_filter) {
628 if (current_layer().is_group_opacity_compatible()) {
635 TransferLayerBounds(content_bounds);
669void DisplayListBuilder::TransferLayerBounds(
const SkRect& content_bounds) {
670 auto& filter = current_layer().filter;
676 current_layer().global_space_accumulator.is_empty());
678 parent_info().AccumulateBoundsLocal(content_bounds);
679 parent_layer().global_space_accumulator.accumulate(
680 current_layer().global_space_accumulator);
684 bool parent_is_flooded =
false;
685 SkRect bounds_for_parent = content_bounds;
692 const SkRect clip = parent_info().global_state.device_cull_rect();
695 if (rtree_data_.has_value()) {
698 FML_DCHECK(current_layer().global_space_accumulator.is_empty());
699 FML_DCHECK(parent_layer().global_space_accumulator.is_empty());
711 if (AdjustRTreeRects(rtree_data_.value(), *filter,
matrix,
clip,
712 current_layer().rtree_rects_start_index)) {
713 parent_is_flooded =
true;
716 SkRect global_bounds = current_layer().global_space_accumulator.bounds();
717 if (!global_bounds.
isEmpty()) {
719 if (!filter->map_device_bounds(global_ibounds,
matrix, global_ibounds)) {
720 parent_is_flooded =
true;
722 global_bounds.
set(global_ibounds);
724 parent_layer().global_space_accumulator.accumulate(global_bounds);
740 if (!parent_is_flooded && !bounds_for_parent.
isEmpty()) {
741 if (!filter->map_local_bounds(bounds_for_parent, bounds_for_parent)) {
742 parent_is_flooded =
true;
746 if (parent_is_flooded) {
756 AccumulateUnbounded(parent_info());
758 parent_info().AccumulateBoundsLocal(bounds_for_parent);
762bool DisplayListBuilder::AdjustRTreeRects(RTreeData&
data,
763 const DlImageFilter& filter,
766 size_t rect_start_index) {
767 auto& rects =
data.rects;
768 auto& indices =
data.indices;
771 auto rect_keep = rect_start_index;
772 for (
size_t i = rect_start_index;
i < rects.size();
i++) {
775 if (filter.map_device_bounds(
bounds.roundOut(),
matrix, ibounds)) {
782 indices[rect_keep] = indices[
i];
783 rects[rect_keep] =
bounds;
787 indices.resize(rect_keep);
788 rects.resize(rect_keep);
801 checkForDeferredSave();
802 Push<TranslateOp>(0, tx, ty);
809 checkForDeferredSave();
810 Push<ScaleOp>(0, sx, sy);
811 global_state().
scale(sx, sy);
812 layer_local_state().
scale(sx, sy);
817 checkForDeferredSave();
818 Push<RotateOp>(0, degrees);
819 global_state().
rotate(degrees);
820 layer_local_state().
rotate(degrees);
825 checkForDeferredSave();
826 Push<SkewOp>(0, sx, sy);
827 global_state().
skew(sx, sy);
828 layer_local_state().
skew(sx, sy);
841 if (mxx == 1 && mxy == 0 &&
842 myx == 0 && myy == 1) {
845 checkForDeferredSave();
846 Push<Transform2DAffineOp>(0,
864 mzx == 0 && mzy == 0 && mzz == 1 && mzt == 0 &&
865 mwx == 0 && mwy == 0 && mwz == 0 && mwt == 1) {
876 checkForDeferredSave();
877 Push<TransformFullPerspectiveOp>(0,
894 checkForDeferredSave();
895 Push<TransformResetOp>(0);
908 if (!layer_local_state().inverseTransform(global_state())) {
925 if (m44 !=
nullptr) {
926 transformFullPerspective(
927 m44->
rc(0, 0), m44->
rc(0, 1), m44->
rc(0, 2), m44->
rc(0, 3),
928 m44->
rc(1, 0), m44->
rc(1, 1), m44->
rc(1, 2), m44->
rc(1, 3),
929 m44->
rc(2, 0), m44->
rc(2, 1), m44->
rc(2, 2), m44->
rc(2, 3),
930 m44->
rc(3, 0), m44->
rc(3, 1), m44->
rc(3, 2), m44->
rc(3, 3));
937 if (!
rect.isFinite()) {
940 if (current_info().is_nop) {
943 if (current_info().has_valid_clip &&
945 layer_local_state().rect_covers_cull(
rect)) {
950 if (global_state().is_cull_rect_empty() ||
951 layer_local_state().is_cull_rect_empty()) {
952 current_info().is_nop =
true;
955 current_info().has_valid_clip =
true;
956 checkForDeferredSave();
959 Push<ClipIntersectRectOp>(0,
rect, is_aa);
962 Push<ClipDifferenceRectOp>(0,
rect, is_aa);
973 if (current_info().is_nop) {
976 if (current_info().has_valid_clip &&
978 layer_local_state().rrect_covers_cull(
rrect)) {
983 if (global_state().is_cull_rect_empty() ||
984 layer_local_state().is_cull_rect_empty()) {
985 current_info().is_nop =
true;
988 current_info().has_valid_clip =
true;
989 checkForDeferredSave();
992 Push<ClipIntersectRRectOp>(0,
rrect, is_aa);
995 Push<ClipDifferenceRRectOp>(0,
rrect, is_aa);
1002 if (current_info().is_nop) {
1005 if (!
path.isInverseFillType()) {
1008 this->clipRect(
rect, clip_op, is_aa);
1014 this->clipRRect(
rrect, clip_op, is_aa);
1018 this->clipRRect(
rrect, clip_op, is_aa);
1024 if (global_state().is_cull_rect_empty() ||
1025 layer_local_state().is_cull_rect_empty()) {
1026 current_info().is_nop =
true;
1029 current_info().has_valid_clip =
true;
1030 checkForDeferredSave();
1033 Push<ClipIntersectPathOp>(0,
path, is_aa);
1036 Push<ClipDifferencePathOp>(0,
path, is_aa);
1045void DisplayListBuilder::drawPaint() {
1047 if (
result != OpResult::kNoEffect && AccumulateUnbounded()) {
1048 Push<DrawPaintOp>(0);
1049 CheckLayerOpacityCompatibility();
1050 UpdateLayerResult(
result);
1059 if (
result != OpResult::kNoEffect && AccumulateUnbounded()) {
1061 CheckLayerOpacityCompatibility(
mode);
1065void DisplayListBuilder::drawLine(
const SkPoint& p0,
const SkPoint& p1) {
1072 Push<DrawLineOp>(0, p0, p1);
1073 CheckLayerOpacityCompatibility();
1074 UpdateLayerResult(
result);
1083void DisplayListBuilder::drawDashedLine(
const DlPoint& p0,
1093 Push<DrawDashedLineOp>(0, p0, p1, on_length, off_length);
1094 CheckLayerOpacityCompatibility();
1095 UpdateLayerResult(
result);
1104 drawDashedLine(p0, p1, on_length, off_length);
1106void DisplayListBuilder::drawRect(
const SkRect&
rect) {
1109 if (
result != OpResult::kNoEffect &&
1110 AccumulateOpBounds(
rect.makeSorted(),
flags)) {
1111 Push<DrawRectOp>(0,
rect);
1112 CheckLayerOpacityCompatibility();
1113 UpdateLayerResult(
result);
1120void DisplayListBuilder::drawOval(
const SkRect&
bounds) {
1123 if (
result != OpResult::kNoEffect &&
1125 Push<DrawOvalOp>(0,
bounds);
1126 CheckLayerOpacityCompatibility();
1127 UpdateLayerResult(
result);
1134void DisplayListBuilder::drawCircle(
const SkPoint& center,
SkScalar radius) {
1137 if (
result != OpResult::kNoEffect) {
1139 center.fX + radius, center.fY + radius);
1141 Push<DrawCircleOp>(0, center, radius);
1142 CheckLayerOpacityCompatibility();
1143 UpdateLayerResult(
result);
1151 drawCircle(center, radius);
1153void DisplayListBuilder::drawRRect(
const SkRRect&
rrect) {
1161 if (
result != OpResult::kNoEffect &&
1163 Push<DrawRRectOp>(0,
rrect);
1164 CheckLayerOpacityCompatibility();
1165 UpdateLayerResult(
result);
1173void DisplayListBuilder::drawDRRect(
const SkRRect& outer,
1177 if (
result != OpResult::kNoEffect &&
1179 Push<DrawDRRectOp>(0, outer, inner);
1180 CheckLayerOpacityCompatibility();
1181 UpdateLayerResult(
result);
1188 drawDRRect(outer, inner);
1190void DisplayListBuilder::drawPath(
const SkPath&
path) {
1193 if (
result != OpResult::kNoEffect) {
1194 bool is_visible =
path.isInverseFillType()
1195 ? AccumulateUnbounded()
1196 : AccumulateOpBounds(
path.getBounds(),
flags);
1198 Push<DrawPathOp>(0,
path);
1199 CheckLayerOpacityHairlineCompatibility();
1200 UpdateLayerResult(
result);
1222 Push<DrawArcOp>(0,
bounds, start, sweep, useCenter);
1224 CheckLayerOpacityHairlineCompatibility();
1226 CheckLayerOpacityCompatibility();
1228 UpdateLayerResult(
result);
1236 SetAttributesFromPaint(
1259 DisplayListAttributeFlags
flags = FlagsForPointMode(
mode);
1261 if (
result == OpResult::kNoEffect) {
1267 AccumulationRect accumulator;
1268 for (
size_t i = 0;
i <
count;
i++) {
1269 accumulator.accumulate(pts[
i]);
1271 SkRect point_bounds = accumulator.bounds();
1272 if (!AccumulateOpBounds(point_bounds,
flags)) {
1279 data_ptr = Push<DrawPointsOp>(bytes,
count);
1282 data_ptr = Push<DrawLinesOp>(bytes,
count);
1285 data_ptr = Push<DrawPolygonOp>(bytes,
count);
1297 current_layer().layer_local_accumulator.record_overlapping_bounds();
1302 CheckLayerOpacityCompatibility();
1303 UpdateLayerResult(
result);
1309 SetAttributesFromPaint(
paint, FlagsForPointMode(
mode));
1312void DisplayListBuilder::drawVertices(
const DlVertices* vertices,
1316 if (
result != OpResult::kNoEffect &&
1318 void* pod = Push<DrawVerticesOp>(vertices->
size(),
mode);
1324 UpdateLayerOpacityCompatibility(
false);
1325 UpdateLayerResult(
result);
1334 current_layer().layer_local_accumulator.record_overlapping_bounds();
1341 drawVertices(vertices,
mode);
1347 bool render_with_attributes) {
1352 if (
result == OpResult::kNoEffect) {
1358 render_with_attributes
1361 CheckLayerOpacityCompatibility(render_with_attributes);
1362 UpdateLayerResult(
result, render_with_attributes);
1363 is_ui_thread_safe_ = is_ui_thread_safe_ &&
image->isUIThreadSafe();
1370 if (
paint !=
nullptr) {
1371 SetAttributesFromPaint(*
paint,
1382 bool render_with_attributes,
1383 SrcRectConstraint constraint) {
1388 if (
result != OpResult::kNoEffect && AccumulateOpBounds(
dst,
flags)) {
1391 CheckLayerOpacityCompatibility(render_with_attributes);
1392 UpdateLayerResult(
result, render_with_attributes);
1393 is_ui_thread_safe_ = is_ui_thread_safe_ &&
image->isUIThreadSafe();
1402 if (
paint !=
nullptr) {
1403 SetAttributesFromPaint(*
paint,
1414 bool render_with_attributes) {
1419 if (
result != OpResult::kNoEffect && AccumulateOpBounds(
dst,
flags)) {
1420 render_with_attributes
1421 ? Push<DrawImageNineWithAttrOp>(0,
image, center,
dst, filter)
1422 : Push<DrawImageNineOp>(0,
image, center,
dst, filter);
1423 CheckLayerOpacityCompatibility(render_with_attributes);
1424 UpdateLayerResult(
result, render_with_attributes);
1425 is_ui_thread_safe_ = is_ui_thread_safe_ &&
image->isUIThreadSafe();
1433 if (
paint !=
nullptr) {
1434 SetAttributesFromPaint(*
paint,
1436 drawImageNine(
image, center,
dst, filter,
true);
1438 drawImageNine(
image, center,
dst, filter,
false);
1449 bool render_with_attributes) {
1454 if (
result == OpResult::kNoEffect) {
1458 AccumulationRect accumulator;
1462 for (
int j = 0; j < 4; j++) {
1463 accumulator.accumulate(quad[j]);
1466 if (accumulator.is_empty() ||
1467 !AccumulateOpBounds(accumulator.bounds(),
flags)) {
1480 if (accumulator.overlap_detected()) {
1481 current_layer().layer_local_accumulator.record_overlapping_bounds();
1488 if (cull_rect !=
nullptr) {
1491 *cull_rect, render_with_attributes);
1494 render_with_attributes);
1498 if (cull_rect !=
nullptr) {
1501 *cull_rect, render_with_attributes);
1504 render_with_attributes);
1511 UpdateLayerOpacityCompatibility(
false);
1512 UpdateLayerResult(
result, render_with_attributes);
1513 is_ui_thread_safe_ = is_ui_thread_safe_ &&
atlas->isUIThreadSafe();
1524 if (
paint !=
nullptr) {
1525 SetAttributesFromPaint(*
paint,
1538 display_list->op_count() == 0 || display_list->bounds().isEmpty() ||
1539 current_info().is_nop) {
1545 if (!rtree_data_.has_value() || !(rtree = display_list->rtree())) {
1548 std::list<SkRect> rects =
1550 accumulated =
false;
1563 DlPaint current_paint = current_;
1564 Push<DrawDisplayListOp>(0, display_list,
1575 depth_ += display_list->total_depth();
1577 is_ui_thread_safe_ = is_ui_thread_safe_ && display_list->isUIThreadSafe();
1581 SetAttributesFromPaint(current_paint,
1590 nested_op_count_ += display_list->op_count(
true) - 1;
1591 nested_bytes_ += display_list->bytes(
true);
1592 UpdateLayerOpacityCompatibility(display_list->can_apply_group_opacity());
1595 UpdateLayerResult(display_list->modifies_transparent_black()
1596 ? OpResult::kAffectsAll
1597 : OpResult::kPreservesTransparency,
1598 display_list->max_root_blend_mode());
1599 if (display_list->root_has_backdrop_filter()) {
1600 current_layer().contains_backdrop_filter =
true;
1608 if (
result == OpResult::kNoEffect) {
1616#if defined(OS_FUCHSIA)
1620 Push<DrawTextBlobOp>(0, blob,
x,
y);
1626 UpdateLayerOpacityCompatibility(
false);
1627 UpdateLayerResult(
result);
1635 drawTextBlob(blob,
x,
y);
1639 const std::shared_ptr<impeller::TextFrame>& text_frame,
1644 if (
result == OpResult::kNoEffect) {
1655#if defined(OS_FUCHSIA)
1659 Push<DrawTextFrameOp>(0, text_frame,
x,
y);
1665 UpdateLayerOpacityCompatibility(
false);
1666 UpdateLayerResult(
result);
1671 const std::shared_ptr<impeller::TextFrame>& text_frame,
1682 bool transparent_occluder,
1685 if (
result != OpResult::kNoEffect) {
1689 transparent_occluder
1690 ? Push<DrawShadowTransparentOccluderOp>(0,
path,
color, elevation,
1692 : Push<DrawShadowOp>(0,
path,
color, elevation, dpr);
1693 UpdateLayerOpacityCompatibility(
false);
1699bool DisplayListBuilder::AdjustBoundsForPaint(
SkRect&
bounds,
1701 if (
flags.ignores_paint()) {
1705 if (
flags.is_geometric()) {
1709 DisplayListSpecialGeometryFlags special_flags =
1710 flags.GeometryFlags(is_stroked);
1716 special_flags.may_have_acute_joins()) {
1720 special_flags.may_have_diagonal_caps()) {
1729 if (
flags.applies_mask_filter()) {
1732 switch (filter->type()) {
1735 SkScalar mask_sigma_pad = filter->asBlur()->sigma() * 3.0;
1736 bounds.outset(mask_sigma_pad, mask_sigma_pad);
1747 if (
flags.applies_image_filter()) {
1749 if (filter && !filter->map_local_bounds(
bounds,
bounds)) {
1757bool DisplayListBuilder::AccumulateUnbounded(
const SaveInfo& save) {
1758 SkRect global_clip = save.global_state.device_cull_rect();
1759 SkRect layer_clip = save.global_state.local_cull_rect();
1760 if (global_clip.
isEmpty() || !save.layer_state.mapAndClipRect(&layer_clip)) {
1763 if (rtree_data_.has_value()) {
1764 FML_DCHECK(save.layer_info->global_space_accumulator.is_empty());
1765 rtree_data_->rects.push_back(global_clip);
1766 rtree_data_->indices.push_back(op_index_);
1768 save.layer_info->global_space_accumulator.accumulate(global_clip);
1770 save.layer_info->layer_local_accumulator.accumulate(layer_clip);
1774bool DisplayListBuilder::AccumulateOpBounds(
SkRect&
bounds,
1775 DisplayListAttributeFlags
flags) {
1777 return AccumulateBounds(
bounds);
1779 return AccumulateUnbounded();
1783bool DisplayListBuilder::AccumulateBounds(
const SkRect&
bounds,
1791 if (!layer.global_state.mapAndClipRect(
bounds, &global_bounds) ||
1792 !layer.layer_state.mapAndClipRect(
bounds, &layer_bounds)) {
1795 if (rtree_data_.has_value()) {
1796 FML_DCHECK(layer.layer_info->global_space_accumulator.is_empty());
1798 rtree_data_->rects.push_back(global_bounds);
1799 rtree_data_->indices.push_back(
id);
1802 layer.layer_info->global_space_accumulator.accumulate(global_bounds);
1804 layer.layer_info->layer_local_accumulator.accumulate(layer_bounds);
1808bool DisplayListBuilder::SaveInfo::AccumulateBoundsLocal(
const SkRect&
bounds) {
1813 if (!layer_state.mapAndClipRect(
bounds, &local_bounds)) {
1816 layer_info->layer_local_accumulator.accumulate(local_bounds);
1820bool DisplayListBuilder::paint_nops_on_transparency() {
1895 DisplayListAttributeFlags
flags) {
1897 if (
flags.applies_color()) {
1898 const DlColorSource*
source =
paint.getColorSourcePtr();
1908 }
else if (
flags.applies_alpha()) {
1919 if (
flags.applies_image_filter()) {
1920 auto filter =
paint.getImageFilterPtr();
1922 if (!
color.isTransparent() || filter->modifies_transparent_black()) {
1927 if (
flags.applies_color_filter()) {
1928 auto filter =
paint.getColorFilterPtr();
1930 if (!
color.isTransparent() || filter->modifies_transparent_black()) {
1938DisplayListBuilder::OpResult DisplayListBuilder::PaintResult(
1940 DisplayListAttributeFlags
flags) {
1941 if (current_info().is_nop) {
1942 return OpResult::kNoEffect;
1944 if (
flags.applies_blend()) {
1945 switch (
paint.getBlendMode()) {
1948 return OpResult::kNoEffect;
1952 return OpResult::kPreservesTransparency;
1960 ? OpResult::kNoEffect
1961 : OpResult::kAffectsAll;
1965 return OpResult::kPreservesTransparency;
1971 ? OpResult::kNoEffect
1972 : OpResult::kPreservesTransparency;
1979 ? OpResult::kPreservesTransparency
1980 : OpResult::kAffectsAll;
1986 ? OpResult::kNoEffect
1987 : OpResult::kPreservesTransparency;
2006 ? OpResult::kNoEffect
2007 : OpResult::kAffectsAll;
2012 ? OpResult::kNoEffect
2013 : OpResult::kPreservesTransparency;
2016 return OpResult::kAffectsAll;
static constexpr T SkAlignPtr(T x)
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
#define SkScalarMod(x, y)
#define SK_ScalarNearlyZero
const sk_sp< Effect > & get() const
sk_sp< SkImage > asImage() const
SkScalar rc(int r, int c) const
static SkMatrix Scale(SkScalar sx, SkScalar sy)
const SkRect & rect() const
void setOval(const SkRect &oval)
const SkRect & getBounds() const
const SkRect & bounds() const
static constexpr SkRect kMaxCullRect
void Skew(SkScalar sx, SkScalar sy) override
SkISize GetBaseLayerSize() const override
void DrawLine(const SkPoint &p0, const SkPoint &p1, const DlPaint &paint) override
void RestoreToCount(int restore_count) override
void DrawDRRect(const SkRRect &outer, const SkRRect &inner, const DlPaint &paint) override
void DrawVertices(const DlVertices *vertices, DlBlendMode mode, 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
SkRect GetLocalClipBounds() const override
void DrawRect(const SkRect &rect, const DlPaint &paint) override
void Transform(const SkMatrix *matrix) override
void DrawColor(DlColor color, DlBlendMode mode) override
void DrawOval(const SkRect &bounds, const DlPaint &paint) override
void TransformReset() override
void ClipRRect(const SkRRect &rrect, ClipOp clip_op=ClipOp::kIntersect, bool is_aa=false) 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 Scale(SkScalar sx, SkScalar sy) override
void DrawPath(const SkPath &path, const DlPaint &paint) override
SkMatrix GetTransform() const override
void Rotate(SkScalar degrees) override
void DrawCircle(const SkPoint ¢er, 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
DisplayListBuilder(bool prepare_rtree)
void drawTextFrame(const std::shared_ptr< impeller::TextFrame > &text_frame, SkScalar x, SkScalar y) override
SkImageInfo GetImageInfo() const 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 DrawShadow(const SkPath &path, const DlColor color, const SkScalar elevation, bool transparent_occluder, SkScalar dpr) override
void DrawPaint(const DlPaint &paint) override
void SaveLayer(const SkRect *bounds, const DlPaint *paint=nullptr, const DlImageFilter *backdrop=nullptr) override
void DrawDashedLine(const DlPoint &p0, const DlPoint &p1, DlScalar on_length, DlScalar off_length, const DlPaint &paint) override
sk_sp< DisplayList > Build()
void ClipRect(const SkRect &rect, ClipOp clip_op=ClipOp::kIntersect, bool is_aa=false) override
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 DrawDisplayList(const sk_sp< DisplayList > display_list, SkScalar opacity=SK_Scalar1) 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 ¢er, const SkRect &dst, DlFilterMode filter, const DlPaint *paint=nullptr) override
int GetSaveCount() const override
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 scale(SkScalar sx, SkScalar sy)
void clipRRect(const SkRRect &rrect, ClipOp op, bool is_aa)
void clipRect(const DlRect &rect, ClipOp op, bool is_aa)
void rotate(SkScalar degrees)
void transform2DAffine(SkScalar mxx, SkScalar mxy, SkScalar mxt, SkScalar myx, SkScalar myy, SkScalar myt)
void setTransform(const DlMatrix &matrix)
void clipPath(const SkPath &path, ClipOp op, bool is_aa)
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)
void skew(SkScalar skx, SkScalar sky)
bool content_culled(const DlRect &content_bounds) const
void translate(SkScalar tx, SkScalar ty)
static constexpr DisplayListAttributeFlags kDrawAtlasFlags
static constexpr DisplayListAttributeFlags kDrawVerticesFlags
static constexpr DisplayListAttributeFlags kDrawArcWithCenterFlags
static constexpr DisplayListAttributeFlags kDrawPaintFlags
static constexpr DisplayListAttributeFlags kDrawArcNoCenterFlags
static constexpr DisplayListAttributeFlags kDrawImageRectWithPaintFlags
static constexpr DisplayListAttributeFlags kSaveLayerFlags
static constexpr DisplayListAttributeFlags kDrawOvalFlags
static constexpr DisplayListAttributeFlags kDrawTextBlobFlags
static constexpr DisplayListAttributeFlags kDrawPointsAsLinesFlags
static constexpr DisplayListAttributeFlags kDrawPointsAsPolygonFlags
static constexpr DisplayListAttributeFlags kDrawImageRectFlags
static constexpr DisplayListAttributeFlags kDrawCircleFlags
static constexpr DisplayListAttributeFlags kDrawDisplayListFlags
static constexpr DisplayListAttributeFlags kDrawPathFlags
static constexpr DisplayListAttributeFlags kDrawAtlasWithPaintFlags
static constexpr DisplayListAttributeFlags kDrawImageNineFlags
static constexpr DisplayListAttributeFlags kDrawLineFlags
static constexpr DisplayListAttributeFlags kSaveLayerWithPaintFlags
static constexpr DisplayListAttributeFlags kDrawPointsAsPointsFlags
static constexpr DisplayListAttributeFlags kDrawImageWithPaintFlags
static constexpr DisplayListAttributeFlags kDrawImageNineWithPaintFlags
static constexpr DisplayListAttributeFlags kDrawShadowFlags
static constexpr DisplayListAttributeFlags kDrawImageFlags
static constexpr DisplayListAttributeFlags kDrawHVLineFlags
static constexpr DisplayListAttributeFlags kDrawRRectFlags
static constexpr DisplayListAttributeFlags kDrawDRRectFlags
static constexpr DisplayListAttributeFlags kDrawRectFlags
void realloc(size_t count)
@ kLines
draw each separate pair of points as a line segment
@ kPolygon
draw each pair of overlapping points as a line segment
@ kPoints
draw each point separately
static SkRect ComputeShadowBounds(const SkPath &path, float elevation, SkScalar dpr, const SkMatrix &ctm)
virtual bool modifies_transparent_black() const =0
virtual bool modifies_transparent_black() const =0
static constexpr int kMaxDrawPointsCount
DlStrokeCap getStrokeCap() const
DlPaint & setColor(DlColor color)
DlPaint & setAntiAlias(bool isAntiAlias)
DlPaint & setInvertColors(bool isInvertColors)
DlBlendMode getBlendMode() const
DlPaint & setColorFilter(const std::shared_ptr< const DlColorFilter > &filter)
DlPaint & setMaskFilter(const std::shared_ptr< DlMaskFilter > &filter)
float getStrokeMiter() const
DlStrokeJoin getStrokeJoin() const
DlPaint & setStrokeCap(DlStrokeCap cap)
DlPaint & setStrokeWidth(float width)
const DlColorFilter * getColorFilterPtr() const
DlPaint & setStrokeMiter(float miter)
DlPaint & setBlendMode(DlBlendMode mode)
const DlImageFilter * getImageFilterPtr() const
DlDrawStyle getDrawStyle() const
std::shared_ptr< const DlMaskFilter > getMaskFilter() const
DlPaint & setImageFilter(const std::shared_ptr< const DlImageFilter > &filter)
float getStrokeWidth() const
std::shared_ptr< const DlImageFilter > getImageFilter() const
DlPaint & setDrawStyle(DlDrawStyle style)
DlPaint & setStrokeJoin(DlStrokeJoin join)
DlPaint & setColorSource(std::shared_ptr< const DlColorSource > source)
Holds all of the data (both required and optional) for a DisplayList drawVertices call.
SkRect bounds() const
Returns the bounds of the vertices.
size_t size() const
Returns the size of the object including all of the inlined data.
SaveLayerOptions with_can_distribute_opacity() const
bool bounds_from_caller() const
SaveLayerOptions with_contains_backdrop_filter() const
SaveLayerOptions without_optimizations() const
SaveLayerOptions with_content_is_clipped() const
FlutterSemanticsFlag flags
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
#define FML_CHECK(condition)
#define FML_UNREACHABLE()
#define FML_DCHECK(condition)
static float max(float r, float g, float b)
sk_sp< const SkImage > atlas
unsigned useCenter Optional< SkMatrix > matrix
Optional< SkRect > bounds
sk_sp< const SkImage > image
sk_sp< const SkImageFilter > backdrop
sk_sp< SkBlender > blender SkRect rect
PODArray< SkColor > colors
SkSamplingOptions sampling
DlCanvas::PointMode PointMode
impeller::Scalar DlScalar
static constexpr DlRect kEmpty
@ kMiter
extends to miter limit
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
static constexpr bool is_power_of_two(int value)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
static void CopyV(void *dst)
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
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 keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
static const DlRect & ProtectEmpty(const SkRect &rect)
const DlRect & ToDlRect(const SkRect &rect)
const SkISize & ToSkISize(const DlISize &size)
@ kExclusion
rc = s + d - two(s*d), ra = kSrcOver
@ kSaturation
saturation of source with hue and luminosity of destination
@ kColorBurn
darken destination to reflect source
@ kLighten
rc = s + d - min(s*da, d*sa), ra = kSrcOver
@ kHue
hue of source with saturation and luminosity of destination
@ kMultiply
r = s*(1-da) + d*(1-sa) + s*d
@ kColorDodge
brighten destination to reflect source
@ kSrcOver
r = s + (1-sa)*d
@ kXor
r = s*(1-da) + d*(1-sa)
@ kLuminosity
luminosity of source with hue and saturation of destination
@ kSoftLight
lighten or darken, depending on source
@ kDifference
rc = s + d - 2*(min(s*da, d*sa)), ra = kSrcOver
@ kOverlay
multiply or screen, depending on destination
@ kSrcATop
r = s*da + d*(1-sa)
@ kDstATop
r = d*sa + s*(1-da)
@ kDstOver
r = d + (1-da)*s
@ kColor
hue and saturation of source with luminosity of destination
@ kHardLight
multiply or screen, depending on source
@ kDarken
rc = s + d - max(s*da, d*sa), ra = kSrcOver
SINT bool isfinite(const Vec< N, T > &v)
flutter::DisplayList DisplayList
static SkString join(const CommandLineFlags::StringArray &)
static SkImageInfo MakeUnknown()
SkRect makeSorted() const
static SkRect Make(const SkISize &size)
constexpr SkRect makeOffset(float dx, float dy) const
bool intersect(const SkRect &r)
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
bool contains(SkScalar x, SkScalar y) const
void roundOut(SkIRect *dst) const
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
void set(const SkIRect &src)
static constexpr DlColor kWhite()
static constexpr DlColor kBlack()
static constexpr DlColor kTransparent()
constexpr bool isTransparent() const
constexpr bool isOpaque() const
DlBlendMode max_blend_mode
uint32_t total_content_depth
constexpr bool IsEmpty() const
Returns true if either of the width or height are 0, negative, or NaN.
RoundOut(const TRect< U > &r)
static sk_sp< SkShader > linear(sk_sp< SkShader > shader)