Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 9cebbb8

Browse files
committed
RTree from DisplayList
1 parent 843ad81 commit 9cebbb8

12 files changed

+575
-109
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ FILE: ../../../flutter/display_list/display_list_paint_unittests.cc
100100
FILE: ../../../flutter/display_list/display_list_path_effect.cc
101101
FILE: ../../../flutter/display_list/display_list_path_effect.h
102102
FILE: ../../../flutter/display_list/display_list_path_effect_unittests.cc
103+
FILE: ../../../flutter/display_list/display_list_rtree.cc
104+
FILE: ../../../flutter/display_list/display_list_rtree.h
103105
FILE: ../../../flutter/display_list/display_list_sampling_options.h
104106
FILE: ../../../flutter/display_list/display_list_test_utils.cc
105107
FILE: ../../../flutter/display_list/display_list_test_utils.h

display_list/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ source_set("display_list") {
4949
"display_list_paint.h",
5050
"display_list_path_effect.cc",
5151
"display_list_path_effect.h",
52+
"display_list_rtree.cc",
53+
"display_list_rtree.h",
5254
"display_list_sampling_options.h",
5355
"display_list_tile_mode.h",
5456
"display_list_utils.cc",

display_list/display_list.cc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "flutter/display_list/display_list_ops.h"
1111
#include "flutter/display_list/display_list_utils.h"
1212
#include "flutter/fml/trace_event.h"
13+
#include "include/core/SkRefCnt.h"
1314

1415
namespace flutter {
1516

@@ -34,15 +35,17 @@ DisplayList::DisplayList(uint8_t* ptr,
3435
unsigned int nested_op_count,
3536
const SkRect& bounds,
3637
const SkRect& cull_rect,
37-
bool can_apply_group_opacity)
38+
bool can_apply_group_opacity,
39+
sk_sp<const DlRTree> rtree)
3840
: storage_(ptr),
3941
byte_count_(byte_count),
4042
op_count_(op_count),
4143
nested_byte_count_(nested_byte_count),
4244
nested_op_count_(nested_op_count),
4345
bounds_(bounds),
4446
bounds_cull_(cull_rect),
45-
can_apply_group_opacity_(can_apply_group_opacity) {
47+
can_apply_group_opacity_(can_apply_group_opacity),
48+
rtree_(rtree) {
4649
static std::atomic<uint32_t> nextID{1};
4750
do {
4851
unique_id_ = nextID.fetch_add(+1, std::memory_order_relaxed);

display_list/display_list.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
#ifndef FLUTTER_DISPLAY_LIST_DISPLAY_LIST_H_
66
#define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_H_
77

8+
#include <memory>
89
#include <optional>
910

11+
#include "flutter/display_list/display_list_rtree.h"
1012
#include "flutter/display_list/display_list_sampling_options.h"
1113
#include "flutter/display_list/types.h"
1214
#include "flutter/fml/logging.h"
@@ -247,6 +249,8 @@ class DisplayList : public SkRefCnt {
247249

248250
const SkRect& bounds() { return bounds_; }
249251

252+
sk_sp<const DlRTree> rtree() { return rtree_; }
253+
250254
bool Equals(const DisplayList* other) const;
251255
bool Equals(const DisplayList& other) const { return Equals(&other); }
252256
bool Equals(sk_sp<const DisplayList> other) const {
@@ -265,7 +269,8 @@ class DisplayList : public SkRefCnt {
265269
unsigned int nested_op_count,
266270
const SkRect& bounds,
267271
const SkRect& cull_rect,
268-
bool can_apply_group_opacity);
272+
bool can_apply_group_opacity,
273+
sk_sp<const DlRTree> rtree = nullptr);
269274

270275
std::unique_ptr<uint8_t, SkFunctionWrapper<void(void*), sk_free>> storage_;
271276
size_t byte_count_;
@@ -276,12 +281,13 @@ class DisplayList : public SkRefCnt {
276281

277282
uint32_t unique_id_;
278283
SkRect bounds_;
279-
280284
// Only used for drawPaint() and drawColor()
281285
SkRect bounds_cull_;
282286

283287
bool can_apply_group_opacity_;
284288

289+
sk_sp<const DlRTree> rtree_;
290+
285291
void Dispatch(Dispatcher& ctx, uint8_t* ptr, uint8_t* end) const;
286292

287293
friend class DisplayListBuilder;

display_list/display_list_builder.cc

Lines changed: 34 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,13 @@ void* DisplayListBuilder::Push(size_t pod, int op_inc, Args&&... args) {
5050
}
5151

5252
sk_sp<DisplayList> DisplayListBuilder::Build() {
53-
5453
FML_DCHECK(build_count_ == 0);
5554
build_count_++;
5655

5756
while (layer_stack_.size() > 1) {
5857
restore();
5958
}
60-
59+
6160
size_t bytes = used_;
6261
int count = op_count_;
6362
size_t nested_bytes = nested_bytes_;
@@ -67,18 +66,17 @@ sk_sp<DisplayList> DisplayListBuilder::Build() {
6766
storage_.realloc(bytes);
6867
bool compatible = layer_stack_.back().is_group_opacity_compatible();
6968
FML_DCHECK(current_layer_ == &layer_stack_.back());
70-
FML_DCHECK(accumulator_ == layer_stack_.back().layer_accumulator());
71-
// accumulator_ = layer_stack_.back().layer_accumulator();
7269
return sk_sp<DisplayList>(new DisplayList(storage_.release(), bytes, count,
7370
nested_bytes, nested_count,
74-
bounds(), cull_rect_, compatible));
71+
bounds(), cull_rect_, compatible, rtree()));
7572
}
7673

7774
DisplayListBuilder::DisplayListBuilder(const SkRect& cull_rect)
7875
: ClipBoundsDispatchHelper(&cull_rect), cull_rect_(cull_rect) {
79-
layer_stack_.emplace_back(SkM44(), cull_rect, nullptr);
76+
layer_stack_.emplace_back(SkM44(), cull_rect);
8077
current_layer_ = &layer_stack_.back();
81-
accumulator_ = current_layer_->layer_accumulator();
78+
combine_bounds_accumulator_.push_back(&rect_bounds_accumulator_);
79+
combine_bounds_accumulator_.push_back(&rtree_bounds_accumulator_);
8280
}
8381

8482
DisplayListBuilder::~DisplayListBuilder() {
@@ -436,72 +434,50 @@ void DisplayListBuilder::setAttributesFromPaint(
436434
void DisplayListBuilder::save() {
437435
ClipBoundsDispatchHelper::save();
438436
Push<SaveOp>(0, 1);
439-
layer_stack_.emplace_back(current_layer_, accumulator_);
437+
layer_stack_.emplace_back(current_layer_);
440438
current_layer_ = &layer_stack_.back();
441-
accumulator_ = current_layer_->layer_accumulator();
439+
accumulator()->save();
442440
}
443441
void DisplayListBuilder::restore() {
444442
if (layer_stack_.size() > 1) {
445443
// Grab the current layer info before we push the restore
446444
// on the stack.
447-
LayerInfo& layer_info = layer_stack_.back();
445+
LayerInfo layer_info = layer_stack_.back();
448446

449447
ClipBoundsDispatchHelper::restore();
450-
451-
// BoundsAccumulator* outer_accumulator = layer_info.restore_accumulator();
452448
bool is_unbounded = layer_info.is_unbounded();
453449

454450
// Before we pop_back we will get the current layer bounds from the
455451
// current accumulator and adjust ot as required based on the filter.
456-
SkRect layer_bounds = accumulator_->bounds();
457452
std::shared_ptr<const DlImageFilter> filter = layer_info.filter();
453+
const SkRect* clip = has_clip() ? &clip_bounds() : nullptr;
458454
if (filter) {
459-
SkIRect filter_bounds;
460-
if (filter->map_device_bounds(layer_bounds.roundOut(), matrix(),
461-
filter_bounds)) {
462-
layer_bounds.set(filter_bounds);
463-
464-
// We could leave the clipping to the code below that will
465-
// finally accumulate the layer bounds, but the bounds do
466-
// not normally need clipping unless they were modified by
467-
// entering this filtering code path.
468-
if (has_clip() && !layer_bounds.intersect(clip_bounds())) {
469-
layer_bounds.setEmpty();
470-
}
471-
} else {
472-
// If the filter cannot compute bounds then it might take an
473-
// unbounded amount of space. This can sometimes happen if it
474-
// modifies transparent black which means its affect will not
475-
// be bounded by the transparent pixels outside of the layer
476-
// drawable.
455+
if (!accumulator()->restore(
456+
[filter = filter, matrix = matrix()](const SkRect& input,
457+
SkRect& output) {
458+
SkIRect output_bounds;
459+
bool ret = filter->map_device_bounds(input.roundOut(), matrix,
460+
output_bounds);
461+
output.set(output_bounds);
462+
return ret;
463+
},
464+
clip)) {
477465
is_unbounded = true;
478466
}
467+
} else {
468+
accumulator()->restore(clip);
479469
}
480470

481-
482-
483-
LayerInfo layer_info1 = layer_info;
484-
485471
layer_stack_.pop_back();
486472
current_layer_ = &layer_stack_.back();
487-
// Restore the accumulator before popping the LayerInfo so that
488-
// it nevers points to an out of scope instance.
489-
accumulator_ = current_layer_->layer_accumulator();
490473
Push<RestoreOp>(0, 1);
491474

492-
// Finally accumulate the impact of the layer into the new scope.
493-
// Note that the bounds were already accumulated in device pixels
494-
// and clipped to any clips involved so we do not need to go
495-
// through any transforms or clips to accuulate them into this
496-
// layer.
497-
accumulator_->accumulate(layer_bounds);
498-
499475
if (is_unbounded) {
500476
AccumulateUnbounded();
501477
}
502478

503-
if (layer_info1.has_layer) {
504-
if (layer_info1.is_group_opacity_compatible()) {
479+
if (layer_info.has_layer) {
480+
if (layer_info.is_group_opacity_compatible()) {
505481
// We are now going to go back and modify the matching saveLayer
506482
// call to add the option indicating it can distribute an opacity
507483
// value to its children.
@@ -515,15 +491,15 @@ void DisplayListBuilder::restore() {
515491
// Once built, the DisplayList records must remain read only to
516492
// ensure consistency of rendering and |Equals()| behavior.
517493
SaveLayerOp* op = reinterpret_cast<SaveLayerOp*>(
518-
storage_.get() + layer_info1.save_layer_offset);
494+
storage_.get() + layer_info.save_layer_offset);
519495
op->options = op->options.with_can_distribute_opacity();
520496
}
521497
} else {
522498
// For regular save() ops there was no protecting layer so we have to
523499
// accumulate the values into the enclosing layer.
524-
if (layer_info1.cannot_inherit_opacity) {
500+
if (layer_info.cannot_inherit_opacity) {
525501
current_layer_->mark_incompatible();
526-
} else if (layer_info1.has_compatible_op) {
502+
} else if (layer_info.has_compatible_op) {
527503
current_layer_->add_compatible_op();
528504
}
529505
}
@@ -561,15 +537,13 @@ void DisplayListBuilder::saveLayer(const SkRect* bounds,
561537
// We will fill the clip of the outer layer when we restore
562538
AccumulateUnbounded();
563539
}
564-
layer_stack_.emplace_back(current_layer_, accumulator_, save_layer_offset,
565-
true, current_.getImageFilter());
540+
layer_stack_.emplace_back(current_layer_, save_layer_offset, true,
541+
current_.getImageFilter());
566542
} else {
567-
layer_stack_.emplace_back(current_layer_, accumulator_, save_layer_offset,
568-
true, nullptr);
543+
layer_stack_.emplace_back(current_layer_, save_layer_offset, true, nullptr);
569544
}
570-
545+
accumulator()->save();
571546
current_layer_ = &layer_stack_.back();
572-
accumulator_ = layer_stack_.back().layer_accumulator();
573547
if (options.renders_with_attributes()) {
574548
// |current_opacity_compatibility_| does not take an ImageFilter into
575549
// account because an individual primitive with an ImageFilter can apply
@@ -936,7 +910,7 @@ void DisplayListBuilder::drawPoints(SkCanvas::PointMode mode,
936910
UpdateLayerOpacityCompatibility(false);
937911

938912
if (count > 0) {
939-
BoundsAccumulator ptBounds;
913+
RectBoundsAccumulator ptBounds;
940914
for (size_t i = 0; i < count; i++) {
941915
ptBounds.accumulate(pts[i]);
942916
}
@@ -1152,7 +1126,7 @@ void DisplayListBuilder::drawAtlas(const sk_sp<DlImage> atlas,
11521126
UpdateLayerOpacityCompatibility(false);
11531127

11541128
SkPoint quad[4];
1155-
BoundsAccumulator atlasBounds;
1129+
RectBoundsAccumulator atlasBounds;
11561130
for (int i = 0; i < count; i++) {
11571131
const SkRect& src = tex[i];
11581132
xform[i].toQuad(src.width(), src.height(), quad);
@@ -1322,7 +1296,7 @@ bool DisplayListBuilder::AdjustBoundsForPaint(SkRect& bounds,
13221296

13231297
void DisplayListBuilder::AccumulateUnbounded() {
13241298
if (has_clip()) {
1325-
accumulator_->accumulate(clip_bounds());
1299+
accumulator()->accumulate(clip_bounds());
13261300
} else {
13271301
layer_stack_.back().set_unbounded();
13281302
}
@@ -1339,7 +1313,7 @@ void DisplayListBuilder::AccumulateOpBounds(SkRect& bounds,
13391313
void DisplayListBuilder::AccumulateBounds(SkRect& bounds) {
13401314
matrix().mapRect(&bounds);
13411315
if (!has_clip() || bounds.intersect(clip_bounds())) {
1342-
accumulator_->accumulate(bounds);
1316+
accumulator()->accumulate(bounds);
13431317
}
13441318
}
13451319

display_list/display_list_builder.h

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -375,9 +375,6 @@ class DisplayListBuilder final : public virtual Dispatcher,
375375
static constexpr SkRect kMaxCullRect_ =
376376
SkRect::MakeLTRB(-1E9F, -1E9F, 1E9F, 1E9F);
377377

378-
// current accumulator based on saveLayer history
379-
BoundsAccumulator* accumulator_;
380-
381378
template <typename T, typename... Args>
382379
void* Push(size_t extra, int op_inc, Args&&... args);
383380

@@ -393,7 +390,6 @@ class DisplayListBuilder final : public virtual Dispatcher,
393390
struct LayerInfo {
394391
explicit LayerInfo(const SkM44& matrix,
395392
const SkRect& clip_bounds,
396-
BoundsAccumulator* outer,
397393
size_t save_layer_offset = 0,
398394
bool has_layer = false,
399395
std::shared_ptr<const DlImageFilter> filter = nullptr)
@@ -403,18 +399,15 @@ class DisplayListBuilder final : public virtual Dispatcher,
403399
has_compatible_op(false),
404400
matrix(matrix),
405401
clip_bounds(clip_bounds),
406-
outer_(outer),
407402
filter_(filter),
408403
is_unbounded_(false) {}
409404

410405
explicit LayerInfo(const LayerInfo* current_layer,
411-
BoundsAccumulator* outer,
412406
size_t save_layer_offset = 0,
413407
bool has_layer = false,
414408
std::shared_ptr<const DlImageFilter> filter = nullptr)
415409
: LayerInfo(current_layer->matrix,
416410
current_layer->clip_bounds,
417-
outer,
418411
save_layer_offset,
419412
has_layer,
420413
filter) {}
@@ -434,8 +427,6 @@ class DisplayListBuilder final : public virtual Dispatcher,
434427
SkM44 matrix;
435428
SkRect clip_bounds;
436429

437-
BoundsAccumulator layer_accumulator_;
438-
BoundsAccumulator* outer_;
439430
std::shared_ptr<const DlImageFilter> filter_;
440431
bool is_unbounded_;
441432

@@ -458,14 +449,6 @@ class DisplayListBuilder final : public virtual Dispatcher,
458449
}
459450
}
460451

461-
// The accumulator to use while this layer is put in play by
462-
// a |save| or |saveLayer|
463-
BoundsAccumulator* layer_accumulator() { return &layer_accumulator_; }
464-
465-
// The accumulator to use after this layer is removed from play
466-
// via |restore|
467-
BoundsAccumulator* restore_accumulator() { return outer_; }
468-
469452
// The filter to apply to the layer bounds when it is restored
470453
std::shared_ptr<const DlImageFilter> filter() { return filter_; }
471454

@@ -502,6 +485,10 @@ class DisplayListBuilder final : public virtual Dispatcher,
502485

503486
std::vector<LayerInfo> layer_stack_;
504487
LayerInfo* current_layer_;
488+
RectBoundsAccumulator rect_bounds_accumulator_;
489+
RTreeBoundsAccumulator rtree_bounds_accumulator_;
490+
CombineBoundsAccumulator combine_bounds_accumulator_;
491+
BoundsAccumulator* accumulator() { return &combine_bounds_accumulator_; }
505492

506493
// This flag indicates whether or not the current rendering attributes
507494
// are compatible with rendering ops applying an inherited opacity.
@@ -596,7 +583,15 @@ class DisplayListBuilder final : public virtual Dispatcher,
596583
if (is_unbounded()) {
597584
FML_LOG(INFO) << "returning partial bounds for unbounded DisplayList";
598585
}
599-
return accumulator_->bounds();
586+
return rect_bounds_accumulator_.bounds();
587+
}
588+
589+
sk_sp<const DlRTree> rtree() const {
590+
FML_DCHECK(layer_stack_.size() == 1);
591+
if (is_unbounded()) {
592+
FML_LOG(INFO) << "returning partial rtree for unbounded DisplayList";
593+
}
594+
return rtree_bounds_accumulator_.rtree();
600595
}
601596

602597
bool paint_nops_on_transparency();

0 commit comments

Comments
 (0)