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_bounds_accumulator.h"
18#define DL_BUILDER_PAGE 4096
23template <
typename S,
typename... Rest>
24static void CopyV(
void* dst,
const S* src,
int n, Rest&&... rest) {
25 FML_DCHECK(((uintptr_t)dst & (
alignof(S) - 1)) == 0)
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 (layer_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 compatible = current_layer_->is_group_opacity_compatible();
78 bool is_safe = is_ui_thread_safe_;
79 bool affects_transparency = current_layer_->affects_transparent_layer();
82 SkRect bounds = rtree ? rtree->bounds() : this->bounds();
84 used_ = allocated_ = render_op_count_ = op_index_ = 0;
85 nested_bytes_ = nested_op_count_ = 0;
87 is_ui_thread_safe_ =
true;
89 layer_stack_.pop_back();
90 layer_stack_.emplace_back();
91 current_layer_ = &layer_stack_.back();
93 layer_tracker_.reset();
98 nested_count, total_depth, bounds,
compatible, is_safe,
99 affects_transparency, std::move(rtree)));
106 accumulator_ = std::make_unique<RTreeBoundsAccumulator>();
108 accumulator_ = std::make_unique<RectBoundsAccumulator>();
111 layer_stack_.emplace_back();
112 current_layer_ = &layer_stack_.back();
116 uint8_t* ptr = storage_.
get();
118 DisplayList::DisposeOps(ptr, ptr + used_);
131void DisplayListBuilder::onSetAntiAlias(
bool aa) {
133 Push<SetAntiAliasOp>(0, aa);
135void DisplayListBuilder::onSetInvertColors(
bool invert) {
137 Push<SetInvertColorsOp>(0,
invert);
138 UpdateCurrentOpacityCompatibility();
140void DisplayListBuilder::onSetStrokeCap(
DlStrokeCap cap) {
142 Push<SetStrokeCapOp>(0, cap);
144void DisplayListBuilder::onSetStrokeJoin(
DlStrokeJoin join) {
146 Push<SetStrokeJoinOp>(0, join);
148void DisplayListBuilder::onSetDrawStyle(
DlDrawStyle style) {
150 Push<SetStyleOp>(0, style);
152void DisplayListBuilder::onSetStrokeWidth(
float width) {
154 Push<SetStrokeWidthOp>(0,
width);
156void DisplayListBuilder::onSetStrokeMiter(
float limit) {
158 Push<SetStrokeMiterOp>(0, limit);
160void DisplayListBuilder::onSetColor(DlColor
color) {
162 Push<SetColorOp>(0,
color);
166 Push<SetBlendModeOp>(0,
mode);
167 UpdateCurrentOpacityCompatibility();
170void DisplayListBuilder::onSetColorSource(
const DlColorSource*
source) {
173 Push<ClearColorSourceOp>(0);
176 is_ui_thread_safe_ = is_ui_thread_safe_ &&
source->isUIThreadSafe();
179 const DlColorColorSource* color_source =
source->asColor();
187 Push<SetImageColorSourceOp>(0, image_source);
191 const DlLinearGradientColorSource*
linear =
source->asLinearGradient();
193 void* pod = Push<SetPodColorSourceOp>(
linear->size());
194 new (pod) DlLinearGradientColorSource(
linear);
198 const DlRadialGradientColorSource* radial =
source->asRadialGradient();
200 void* pod = Push<SetPodColorSourceOp>(radial->size());
201 new (pod) DlRadialGradientColorSource(radial);
205 const DlConicalGradientColorSource* conical =
206 source->asConicalGradient();
208 void* pod = Push<SetPodColorSourceOp>(conical->size());
209 new (pod) DlConicalGradientColorSource(conical);
213 const DlSweepGradientColorSource* sweep =
source->asSweepGradient();
215 void* pod = Push<SetPodColorSourceOp>(sweep->size());
216 new (pod) DlSweepGradientColorSource(sweep);
220 const DlRuntimeEffectColorSource* effect =
source->asRuntimeEffect();
222 Push<SetRuntimeEffectColorSourceOp>(0, effect);
225#ifdef IMPELLER_ENABLE_3D
226 case DlColorSourceType::kScene: {
227 const DlSceneColorSource* scene =
source->asScene();
229 Push<SetSceneColorSourceOp>(0, scene);
236void DisplayListBuilder::onSetImageFilter(
const DlImageFilter* filter) {
237 if (filter ==
nullptr) {
239 Push<ClearImageFilterOp>(0);
242 switch (filter->type()) {
244 const DlBlurImageFilter* blur_filter = filter->asBlur();
246 void* pod = Push<SetPodImageFilterOp>(blur_filter->size());
247 new (pod) DlBlurImageFilter(blur_filter);
251 const DlDilateImageFilter* dilate_filter = filter->asDilate();
253 void* pod = Push<SetPodImageFilterOp>(dilate_filter->size());
254 new (pod) DlDilateImageFilter(dilate_filter);
258 const DlErodeImageFilter* erode_filter = filter->asErode();
260 void* pod = Push<SetPodImageFilterOp>(erode_filter->size());
261 new (pod) DlErodeImageFilter(erode_filter);
265 const DlMatrixImageFilter* matrix_filter = filter->asMatrix();
267 void* pod = Push<SetPodImageFilterOp>(matrix_filter->size());
268 new (pod) DlMatrixImageFilter(matrix_filter);
274 Push<SetSharedImageFilterOp>(0, filter);
280void DisplayListBuilder::onSetColorFilter(
const DlColorFilter* filter) {
281 if (filter ==
nullptr) {
283 Push<ClearColorFilterOp>(0);
286 switch (filter->type()) {
288 const DlBlendColorFilter* blend_filter = filter->asBlend();
290 void* pod = Push<SetPodColorFilterOp>(blend_filter->size());
291 new (pod) DlBlendColorFilter(blend_filter);
295 const DlMatrixColorFilter* matrix_filter = filter->asMatrix();
297 void* pod = Push<SetPodColorFilterOp>(matrix_filter->size());
298 new (pod) DlMatrixColorFilter(matrix_filter);
302 void* pod = Push<SetPodColorFilterOp>(filter->size());
303 new (pod) DlSrgbToLinearGammaColorFilter();
307 void* pod = Push<SetPodColorFilterOp>(filter->size());
308 new (pod) DlLinearToSrgbGammaColorFilter();
313 UpdateCurrentOpacityCompatibility();
315void DisplayListBuilder::onSetPathEffect(
const DlPathEffect* effect) {
316 if (effect ==
nullptr) {
318 Push<ClearPathEffectOp>(0);
321 switch (effect->type()) {
323 const DlDashPathEffect* dash_effect = effect->asDash();
324 void* pod = Push<SetPodPathEffectOp>(dash_effect->size());
325 new (pod) DlDashPathEffect(dash_effect);
331void DisplayListBuilder::onSetMaskFilter(
const DlMaskFilter* filter) {
332 if (filter ==
nullptr) {
334 render_op_depth_cost_ = 1u;
335 Push<ClearMaskFilterOp>(0);
338 render_op_depth_cost_ = 2u;
339 switch (filter->type()) {
341 const DlBlurMaskFilter* blur_filter = filter->asBlur();
343 void* pod = Push<SetPodMaskFilterOp>(blur_filter->size());
344 new (pod) DlBlurMaskFilter(blur_filter);
351void DisplayListBuilder::SetAttributesFromPaint(
352 const DlPaint&
paint,
353 const DisplayListAttributeFlags
flags) {
354 if (
flags.applies_anti_alias()) {
357 if (
flags.applies_alpha_or_color()) {
360 if (
flags.applies_blend()) {
363 if (
flags.applies_style()) {
372 if (
flags.applies_shader()) {
375 if (
flags.applies_color_filter()) {
379 if (
flags.applies_image_filter()) {
382 if (
flags.applies_path_effect()) {
385 if (
flags.applies_mask_filter()) {
390void DisplayListBuilder::checkForDeferredSave() {
391 if (current_layer_->has_deferred_save_op_) {
392 size_t save_offset_ = used_;
394 current_layer_->save_offset_ = save_offset_;
395 current_layer_->start_depth_ = depth_;
396 current_layer_->has_deferred_save_op_ =
false;
401 layer_stack_.emplace_back();
402 current_layer_ = &layer_stack_.back();
408 auto parent_layer = &layer_stack_.end()[-2];
410 current_layer_->has_deferred_save_op_ =
true;
411 current_layer_->is_nop_ = parent_layer->is_nop_;
413 if (parent_layer->layer_accumulator_) {
419 current_layer_->layer_accumulator_ = parent_layer->layer_accumulator_;
420 layer_tracker_->save();
426 accumulator()->
save();
430 if (layer_stack_.size() <= 1) {
435 current_layer_->save_offset());
437 if (!current_layer_->has_deferred_save_op_) {
441 if (current_layer_->is_save_layer()) {
445 depth_ += render_op_depth_cost_;
449 std::shared_ptr<const DlImageFilter> filter = current_layer_->filter();
453 auto parent_layer = &layer_stack_.end()[-2];
455 if (current_layer_->is_save_layer()) {
458 FML_DCHECK(!current_layer_->has_deferred_save_op_);
459 FML_DCHECK(current_layer_->layer_accumulator_);
461 SkRect content_bounds = current_layer_->layer_accumulator_->bounds();
464 case DisplayListOpType::kSaveLayer:
465 case DisplayListOpType::kSaveLayerBackdrop: {
468 if (!content_bounds.
isEmpty() &&
474 layer_op->
rect = content_bounds;
481 if (layer_tracker_->getSaveCount() > 1) {
482 layer_tracker_->restore();
486 FML_DCHECK(!parent_layer->layer_accumulator_);
487 layer_tracker_.reset();
490 if (parent_layer->layer_accumulator_) {
491 SkRect bounds_for_parent = content_bounds;
493 if (!filter->map_local_bounds(bounds_for_parent, bounds_for_parent)) {
494 parent_layer->set_unbounded();
504 layer_tracker_->mapRect(&bounds_for_parent);
505 parent_layer->layer_accumulator_->accumulate(bounds_for_parent);
508 if (current_layer_->is_group_opacity_compatible()) {
524 if (layer_tracker_) {
525 FML_DCHECK(layer_tracker_->getSaveCount() > 1);
526 layer_tracker_->restore();
530 if (current_layer_->cannot_inherit_opacity()) {
531 parent_layer->mark_incompatible();
532 }
else if (current_layer_->has_compatible_op()) {
533 parent_layer->add_compatible_op();
540 bool popped_was_unbounded = current_layer_->is_unbounded();
543 layer_stack_.pop_back();
545 current_layer_ = &layer_stack_.back();
556 bool ret = filter->map_device_bounds(input.
roundOut(), matrix,
558 output.set(output_bounds);
562 popped_was_unbounded =
true;
568 if (popped_was_unbounded) {
569 AccumulateUnbounded();
586 if (
result == OpResult::kNoEffect) {
588 current_layer_->is_nop_ =
true;
592 size_t save_layer_offset = used_;
594 if (
options.renders_with_attributes()) {
603 if (!paint_nops_on_transparency()) {
608 [[maybe_unused]]
bool unclipped = AccumulateUnbounded();
611 CheckLayerOpacityCompatibility(
true);
612 layer_stack_.emplace_back(save_layer_offset, depth_);
615 CheckLayerOpacityCompatibility(
false);
616 layer_stack_.emplace_back(save_layer_offset, depth_);
618 current_layer_ = &layer_stack_.back();
619 current_layer_->is_save_layer_ =
true;
622 accumulator()->
save();
627 record_bounds = bounds;
632 if (layer_tracker_) {
633 layer_tracker_->save();
642 layer_tracker_.reset(
651 [[maybe_unused]]
bool unclipped = AccumulateUnbounded();
653 Push<SaveLayerBackdropOp>(0,
options, record_bounds, backdrop);
655 Push<SaveLayerOp>(0,
options, record_bounds);
658 if (
options.renders_with_attributes()) {
663 if (!current_opacity_compatibility_ ||
665 UpdateLayerOpacityCompatibility(
false);
668 UpdateLayerResult(
result);
687 tracker_.
clipRect(bounds, ClipOp::kIntersect,
false);
697 temp_bounds = *bounds;
701 if (
paint !=
nullptr) {
703 SetAttributesFromPaint(*
paint,
710 if (std::isfinite(tx) && std::isfinite(ty) && (tx != 0.0 || ty != 0.0)) {
711 checkForDeferredSave();
712 Push<TranslateOp>(0, tx, ty);
714 if (layer_tracker_) {
715 layer_tracker_->translate(tx, ty);
720 if (std::isfinite(sx) && std::isfinite(sy) && (sx != 1.0 || sy != 1.0)) {
721 checkForDeferredSave();
722 Push<ScaleOp>(0, sx, sy);
723 tracker_.
scale(sx, sy);
724 if (layer_tracker_) {
725 layer_tracker_->scale(sx, sy);
731 checkForDeferredSave();
732 Push<RotateOp>(0, degrees);
734 if (layer_tracker_) {
735 layer_tracker_->rotate(degrees);
740 if (std::isfinite(sx) && std::isfinite(sy) && (sx != 0.0 || sy != 0.0)) {
741 checkForDeferredSave();
742 Push<SkewOp>(0, sx, sy);
743 tracker_.
skew(sx, sy);
744 if (layer_tracker_) {
745 layer_tracker_->skew(sx, sy);
756 if (std::isfinite(mxx) && std::isfinite(myx) &&
757 std::isfinite(mxy) && std::isfinite(myy) &&
758 std::isfinite(mxt) && std::isfinite(myt)) {
759 if (mxx == 1 && mxy == 0 &&
760 myx == 0 && myy == 1) {
763 checkForDeferredSave();
764 Push<Transform2DAffineOp>(0,
769 if (layer_tracker_) {
770 layer_tracker_->transform2DAffine(mxx, mxy, mxt,
784 mzx == 0 && mzy == 0 && mzz == 1 && mzt == 0 &&
785 mwx == 0 && mwy == 0 && mwz == 0 && mwt == 1) {
788 }
else if (std::isfinite(mxx) && std::isfinite(mxy) &&
789 std::isfinite(mxz) && std::isfinite(mxt) &&
790 std::isfinite(myx) && std::isfinite(myy) &&
791 std::isfinite(myz) && std::isfinite(myt) &&
792 std::isfinite(mzx) && std::isfinite(mzy) &&
793 std::isfinite(mzz) && std::isfinite(mzt) &&
794 std::isfinite(mwx) && std::isfinite(mwy) &&
795 std::isfinite(mwz) && std::isfinite(mwt)) {
796 checkForDeferredSave();
797 Push<TransformFullPerspectiveOp>(0,
806 if (layer_tracker_) {
807 layer_tracker_->transformFullPerspective(mxx, mxy, mxz, mxt,
816 checkForDeferredSave();
817 Push<TransformResetOp>(0);
818 if (layer_tracker_) {
830 if (!layer_tracker_->inverseTransform(tracker_)) {
842 if (matrix !=
nullptr) {
847 if (m44 !=
nullptr) {
849 m44->
rc(0, 0), m44->
rc(0, 1), m44->
rc(0, 2), m44->
rc(0, 3),
850 m44->
rc(1, 0), m44->
rc(1, 1), m44->
rc(1, 2), m44->
rc(1, 3),
851 m44->
rc(2, 0), m44->
rc(2, 1), m44->
rc(2, 2), m44->
rc(2, 3),
852 m44->
rc(3, 0), m44->
rc(3, 1), m44->
rc(3, 2), m44->
rc(3, 3));
859 if (!rect.isFinite()) {
862 tracker_.
clipRect(rect, clip_op, is_aa);
864 current_layer_->is_nop_ =
true;
867 checkForDeferredSave();
869 case ClipOp::kIntersect:
870 Push<ClipIntersectRectOp>(0, rect, is_aa);
872 case ClipOp::kDifference:
873 Push<ClipDifferenceRectOp>(0, rect, is_aa);
883 tracker_.
clipRRect(rrect, clip_op, is_aa);
885 current_layer_->is_nop_ =
true;
888 checkForDeferredSave();
890 case ClipOp::kIntersect:
891 Push<ClipIntersectRRectOp>(0, rrect, is_aa);
893 case ClipOp::kDifference:
894 Push<ClipDifferenceRRectOp>(0, rrect, is_aa);
902 if (!
path.isInverseFillType()) {
904 if (
path.isRect(&rect)) {
905 this->
clipRect(rect, clip_op, is_aa);
909 if (
path.isOval(&rect)) {
914 if (
path.isRRect(&rrect)) {
921 current_layer_->is_nop_ =
true;
924 checkForDeferredSave();
926 case ClipOp::kIntersect:
927 Push<ClipIntersectPathOp>(0,
path, is_aa);
929 case ClipOp::kDifference:
930 Push<ClipDifferencePathOp>(0,
path, is_aa);
941 if (
result != OpResult::kNoEffect && AccumulateUnbounded()) {
942 Push<DrawPaintOp>(0);
943 CheckLayerOpacityCompatibility();
944 UpdateLayerResult(
result);
953 if (
result != OpResult::kNoEffect && AccumulateUnbounded()) {
955 CheckLayerOpacityCompatibility(
mode);
956 UpdateLayerResult(
result);
962 (bounds.width() > 0.0f && bounds.height() > 0.0f) ?
kDrawLineFlags
965 if (
result != OpResult::kNoEffect && AccumulateOpBounds(bounds,
flags)) {
966 Push<DrawLineOp>(0, p0, p1);
967 CheckLayerOpacityCompatibility();
968 UpdateLayerResult(
result);
980 if (
result != OpResult::kNoEffect &&
981 AccumulateOpBounds(rect.makeSorted(),
flags)) {
982 Push<DrawRectOp>(0, rect);
983 CheckLayerOpacityCompatibility();
984 UpdateLayerResult(
result);
994 if (
result != OpResult::kNoEffect &&
995 AccumulateOpBounds(bounds.makeSorted(),
flags)) {
996 Push<DrawOvalOp>(0, bounds);
997 CheckLayerOpacityCompatibility();
998 UpdateLayerResult(
result);
1008 if (
result != OpResult::kNoEffect) {
1011 if (AccumulateOpBounds(bounds,
flags)) {
1012 Push<DrawCircleOp>(0,
center, radius);
1013 CheckLayerOpacityCompatibility();
1014 UpdateLayerResult(
result);
1027 }
else if (rrect.
isOval()) {
1032 if (
result != OpResult::kNoEffect &&
1034 Push<DrawRRectOp>(0, rrect);
1035 CheckLayerOpacityCompatibility();
1036 UpdateLayerResult(
result);
1048 if (
result != OpResult::kNoEffect &&
1050 Push<DrawDRRectOp>(0, outer, inner);
1051 CheckLayerOpacityCompatibility();
1052 UpdateLayerResult(
result);
1064 if (
result != OpResult::kNoEffect) {
1065 bool is_visible =
path.isInverseFillType()
1066 ? AccumulateUnbounded()
1067 : AccumulateOpBounds(
path.getBounds(),
flags);
1069 Push<DrawPathOp>(0,
path);
1070 CheckLayerOpacityHairlineCompatibility();
1071 UpdateLayerResult(
result);
1092 if (
result != OpResult::kNoEffect && AccumulateOpBounds(bounds,
flags)) {
1093 Push<DrawArcOp>(0, bounds,
start, sweep, useCenter);
1095 CheckLayerOpacityHairlineCompatibility();
1097 CheckLayerOpacityCompatibility();
1099 UpdateLayerResult(
result);
1107 SetAttributesFromPaint(
1117 case PointMode::kLines:
1119 case PointMode::kPolygon:
1132 if (
result == OpResult::kNoEffect) {
1139 for (
size_t i = 0; i <
count; i++) {
1142 SkRect point_bounds = ptBounds.bounds();
1143 if (!AccumulateOpBounds(point_bounds,
flags)) {
1149 case PointMode::kPoints:
1150 data_ptr = Push<DrawPointsOp>(bytes,
count);
1152 case PointMode::kLines:
1153 data_ptr = Push<DrawLinesOp>(bytes,
count);
1155 case PointMode::kPolygon:
1156 data_ptr = Push<DrawPolygonOp>(bytes,
count);
1168 UpdateLayerOpacityCompatibility(
false);
1169 UpdateLayerResult(
result);
1175 SetAttributesFromPaint(
paint, FlagsForPointMode(
mode));
1182 if (
result != OpResult::kNoEffect &&
1184 void* pod = Push<DrawVerticesOp>(vertices->
size(),
mode);
1190 UpdateLayerOpacityCompatibility(
false);
1191 UpdateLayerResult(
result);
1204 bool render_with_attributes) {
1209 if (
result == OpResult::kNoEffect) {
1214 if (AccumulateOpBounds(bounds,
flags)) {
1215 render_with_attributes
1216 ? Push<DrawImageWithAttrOp>(0,
image, point, sampling)
1217 : Push<DrawImageOp>(0,
image, point, sampling);
1218 CheckLayerOpacityCompatibility(render_with_attributes);
1219 UpdateLayerResult(
result);
1220 is_ui_thread_safe_ = is_ui_thread_safe_ &&
image->isUIThreadSafe();
1227 if (
paint !=
nullptr) {
1228 SetAttributesFromPaint(*
paint,
1239 bool render_with_attributes,
1245 if (
result != OpResult::kNoEffect && AccumulateOpBounds(dst,
flags)) {
1246 Push<DrawImageRectOp>(0,
image, src, dst, sampling, render_with_attributes,
1248 CheckLayerOpacityCompatibility(render_with_attributes);
1249 UpdateLayerResult(
result);
1250 is_ui_thread_safe_ = is_ui_thread_safe_ &&
image->isUIThreadSafe();
1259 if (
paint !=
nullptr) {
1260 SetAttributesFromPaint(*
paint,
1271 bool render_with_attributes) {
1276 if (
result != OpResult::kNoEffect && AccumulateOpBounds(dst,
flags)) {
1277 render_with_attributes
1278 ? Push<DrawImageNineWithAttrOp>(0,
image,
center, dst, filter)
1279 : Push<DrawImageNineOp>(0,
image,
center, dst, filter);
1280 CheckLayerOpacityCompatibility(render_with_attributes);
1281 UpdateLayerResult(
result);
1282 is_ui_thread_safe_ = is_ui_thread_safe_ &&
image->isUIThreadSafe();
1290 if (
paint !=
nullptr) {
1291 SetAttributesFromPaint(*
paint,
1306 bool render_with_attributes) {
1311 if (
result == OpResult::kNoEffect) {
1316 for (
int i = 0; i <
count; i++) {
1317 const SkRect& src = tex[i];
1318 xform[i].
toQuad(src.width(), src.height(), quad);
1319 for (
int j = 0; j < 4; j++) {
1324 !AccumulateOpBounds(atlasBounds.
bounds(),
flags)) {
1330 if (colors !=
nullptr) {
1332 if (cull_rect !=
nullptr) {
1334 Push<DrawAtlasCulledOp>(bytes, atlas,
count,
mode, sampling,
true,
1335 *cull_rect, render_with_attributes);
1337 data_ptr = Push<DrawAtlasOp>(bytes, atlas,
count,
mode, sampling,
true,
1338 render_with_attributes);
1342 if (cull_rect !=
nullptr) {
1344 Push<DrawAtlasCulledOp>(bytes, atlas,
count,
mode, sampling,
false,
1345 *cull_rect, render_with_attributes);
1347 data_ptr = Push<DrawAtlasOp>(bytes, atlas,
count,
mode, sampling,
false,
1348 render_with_attributes);
1355 UpdateLayerOpacityCompatibility(
false);
1356 UpdateLayerResult(
result);
1357 is_ui_thread_safe_ = is_ui_thread_safe_ && atlas->isUIThreadSafe();
1368 if (
paint !=
nullptr) {
1369 SetAttributesFromPaint(*
paint,
1382 display_list->op_count() == 0 || display_list->bounds().isEmpty() ||
1383 current_layer_->is_nop_) {
1386 const SkRect bounds = display_list->bounds();
1388 switch (accumulator()->
type()) {
1393 auto rtree = display_list->rtree();
1395 std::list<SkRect> rects =
1397 accumulated =
false;
1398 for (
const SkRect& rect : rects) {
1414 DlPaint current_paint = current_;
1415 Push<DrawDisplayListOp>(0, display_list,
1426 depth_ += display_list->total_depth();
1428 is_ui_thread_safe_ = is_ui_thread_safe_ && display_list->isUIThreadSafe();
1432 SetAttributesFromPaint(current_paint,
1441 nested_op_count_ += display_list->op_count(
true) - 1;
1442 nested_bytes_ += display_list->bytes(
true);
1443 UpdateLayerOpacityCompatibility(display_list->can_apply_group_opacity());
1446 UpdateLayerResult(display_list->modifies_transparent_black()
1447 ? OpResult::kAffectsAll
1448 : OpResult::kPreservesTransparency);
1455 if (
result == OpResult::kNoEffect) {
1458 bool unclipped = AccumulateOpBounds(blob->bounds().makeOffset(
x,
y),
flags);
1463#if defined(OS_FUCHSIA)
1467 Push<DrawTextBlobOp>(0, blob,
x,
y);
1473 UpdateLayerOpacityCompatibility(
false);
1474 UpdateLayerResult(
result);
1486 const std::shared_ptr<impeller::TextFrame>& text_frame,
1491 if (
result == OpResult::kNoEffect) {
1496 bounds.GetRight(), bounds.GetBottom());
1502#if defined(OS_FUCHSIA)
1506 Push<DrawTextFrameOp>(0, text_frame,
x,
y);
1512 UpdateLayerOpacityCompatibility(
false);
1513 UpdateLayerResult(
result);
1518 const std::shared_ptr<impeller::TextFrame>& text_frame,
1529 bool transparent_occluder,
1532 if (
result != OpResult::kNoEffect) {
1536 transparent_occluder
1537 ? Push<DrawShadowTransparentOccluderOp>(0,
path,
color, elevation,
1539 : Push<DrawShadowOp>(0,
path,
color, elevation, dpr);
1540 UpdateLayerOpacityCompatibility(
false);
1541 UpdateLayerResult(
result);
1546bool DisplayListBuilder::AdjustBoundsForPaint(
SkRect& bounds,
1548 if (
flags.ignores_paint()) {
1552 if (
flags.is_geometric()) {
1556 DisplayListSpecialGeometryFlags special_flags =
1559 auto effect_bounds = current_.
getPathEffect()->effect_bounds(bounds);
1560 if (!effect_bounds.has_value()) {
1563 bounds = effect_bounds.value();
1570 special_flags.may_have_acute_joins()) {
1574 special_flags.may_have_diagonal_caps()) {
1578 pad *= std::max(current_.
getStrokeWidth() * 0.5f, min_stroke_width);
1583 if (
flags.applies_mask_filter()) {
1586 switch (filter->type()) {
1589 SkScalar mask_sigma_pad = filter->asBlur()->sigma() * 3.0;
1590 bounds.outset(mask_sigma_pad, mask_sigma_pad);
1601 if (
flags.applies_image_filter()) {
1603 if (filter && !filter->map_local_bounds(bounds, bounds)) {
1611bool DisplayListBuilder::AccumulateUnbounded() {
1617 if (current_layer_->layer_accumulator_) {
1619 current_layer_->layer_accumulator_->accumulate(
1620 layer_tracker_->device_cull_rect());
1625bool DisplayListBuilder::AccumulateOpBounds(
SkRect& bounds,
1626 DisplayListAttributeFlags
flags) {
1627 if (AdjustBoundsForPaint(bounds,
flags)) {
1628 return AccumulateBounds(bounds);
1630 return AccumulateUnbounded();
1633bool DisplayListBuilder::AccumulateBounds(
SkRect& bounds) {
1636 tracker_.
mapRect(bounds, &device_bounds);
1638 accumulator()->
accumulate(device_bounds, op_index_);
1639 if (current_layer_->layer_accumulator_) {
1642 layer_tracker_->mapRect(bounds, &layer_bounds);
1643 current_layer_->layer_accumulator_->accumulate(layer_bounds);
1651bool DisplayListBuilder::paint_nops_on_transparency() {
1725DlColor DisplayListBuilder::GetEffectiveColor(
const DlPaint&
paint,
1726 DisplayListAttributeFlags
flags) {
1728 if (
flags.applies_color()) {
1729 const DlColorSource*
source =
paint.getColorSourcePtr();
1739 }
else if (
flags.applies_alpha()) {
1750 if (
flags.applies_image_filter()) {
1751 auto filter =
paint.getImageFilterPtr();
1753 if (!
color.isTransparent() || filter->modifies_transparent_black()) {
1758 if (
flags.applies_color_filter()) {
1759 auto filter =
paint.getColorFilterPtr();
1761 if (!
color.isTransparent() || filter->modifies_transparent_black()) {
1769DisplayListBuilder::OpResult DisplayListBuilder::PaintResult(
1770 const DlPaint&
paint,
1771 DisplayListAttributeFlags
flags) {
1772 if (current_layer_->is_nop_) {
1773 return OpResult::kNoEffect;
1775 if (
flags.applies_blend()) {
1776 switch (
paint.getBlendMode()) {
1779 return OpResult::kNoEffect;
1783 return OpResult::kPreservesTransparency;
1791 ? OpResult::kNoEffect
1792 : OpResult::kAffectsAll;
1796 return OpResult::kPreservesTransparency;
1802 ? OpResult::kNoEffect
1803 : OpResult::kPreservesTransparency;
1810 ? OpResult::kPreservesTransparency
1811 : OpResult::kAffectsAll;
1817 ? OpResult::kNoEffect
1818 : OpResult::kPreservesTransparency;
1837 ? OpResult::kNoEffect
1838 : OpResult::kAffectsAll;
1843 ? OpResult::kNoEffect
1844 : OpResult::kPreservesTransparency;
1847 return OpResult::kAffectsAll;
static bool compatible(const MTLRenderPassAttachmentDescriptor *first, const MTLRenderPassAttachmentDescriptor *second, const GrMtlPipelineState *pipelineState)
static constexpr T SkAlignPtr(T x)
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
#define SkScalarMod(x, y)
#define SK_ScalarNearlyZero
static SkScalar center(float pos0, float pos1)
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)
static const SkMatrix & I()
const SkRect & rect() const
void setOval(const SkRect &oval)
const SkRect & getBounds() const
virtual void accumulate(const SkRect &r, int index=0)=0
void setBlendMode(DlBlendMode mode) override
void Skew(SkScalar sx, SkScalar sy) override
SkISize GetBaseLayerSize() const override
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
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
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
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
void setDrawStyle(DlDrawStyle style) override
void Transform(const SkMatrix *matrix) override
void setStrokeCap(DlStrokeCap cap) override
void setMaskFilter(const DlMaskFilter *filter) override
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
void setImageFilter(const DlImageFilter *filter) override
void TransformReset() override
void ClipRRect(const SkRRect &rrect, ClipOp clip_op=ClipOp::kIntersect, bool is_aa=false) override
void setStrokeMiter(float limit) override
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 Scale(SkScalar sx, SkScalar sy) override
void DrawPath(const SkPath &path, const DlPaint &paint) override
SkMatrix GetTransform() const 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, bool render_with_attributes) override
void Rotate(SkScalar degrees) override
void setStrokeJoin(DlStrokeJoin join) 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
void setStrokeWidth(float width) override
DisplayListBuilder(bool prepare_rtree)
void drawImageNine(const sk_sp< DlImage > image, const SkIRect ¢er, 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
SkImageInfo GetImageInfo() const override
void drawRRect(const SkRRect &rrect) override
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 DrawShadow(const SkPath &path, const DlColor color, const SkScalar elevation, bool transparent_occluder, SkScalar dpr) override
void drawPaint() override
void setAntiAlias(bool aa) override
void DrawPaint(const DlPaint &paint) override
void SaveLayer(const SkRect *bounds, const DlPaint *paint=nullptr, const DlImageFilter *backdrop=nullptr) override
void setPathEffect(const DlPathEffect *effect) override
sk_sp< DisplayList > Build()
void setInvertColors(bool invert) override
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 setColorFilter(const DlColorFilter *filter) override
void DrawDisplayList(const sk_sp< DisplayList > display_list, SkScalar opacity=SK_Scalar1) override
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 ¢er, const SkRect &dst, DlFilterMode filter, const DlPaint *paint=nullptr) override
void drawCircle(const SkPoint ¢er, 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
void drawLine(const SkPoint &p0, const SkPoint &p1) 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 setColor(DlColor color) override
void drawImage(const sk_sp< DlImage > image, const SkPoint point, DlImageSampling sampling, bool render_with_attributes) override
void clipRect(const DlRect &rect, ClipOp op, bool is_aa)
void scale(SkScalar sx, SkScalar sy)
SkRect local_cull_rect() const
SkRect device_cull_rect() const
void clipPath(const SkPath &path, ClipOp op, bool is_aa)
void transform2DAffine(SkScalar mxx, SkScalar mxy, SkScalar mxt, SkScalar myx, SkScalar myy, SkScalar myt)
void resetLocalCullRect(const DlRect *cull_rect=nullptr)
void translate(SkScalar tx, SkScalar ty)
void clipRRect(const SkRRect &rrect, 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 is_cull_rect_empty() const
SkRect base_device_cull_rect() const
bool content_culled(const SkRect &content_bounds) const
bool mapRect(DlRect *rect) const
void rotate(SkScalar degrees)
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)
@ 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 & setPathEffect(const std::shared_ptr< DlPathEffect > &pathEffect)
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
std::shared_ptr< const DlPathEffect > getPathEffect() 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
const DlPathEffect * getPathEffectPtr() 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.
SkRect bounds() const override
void accumulate(SkScalar x, SkScalar y)
SaveLayerOptions with_can_distribute_opacity() const
bool bounds_from_caller() const
SaveLayerOptions without_optimizations() const
SaveLayerOptions with_content_is_clipped() const
FlutterSemanticsFlag flags
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
#define FML_UNREACHABLE()
#define FML_DCHECK(condition)
Optional< SkRect > bounds
@ 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)
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
@ 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
static SkImageInfo MakeUnknown()
SkRect makeSorted() const
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)
static constexpr DlColor kWhite()
static constexpr DlColor kBlack()
static constexpr DlColor kTransparent()
constexpr bool isTransparent() const
constexpr bool isOpaque() const
uint32_t total_content_depth
static sk_sp< SkShader > linear(sk_sp< SkShader > shader)