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

Commit 66a2dcb

Browse files
committed
Raster cache should preserve RTree for overlay layers
1 parent 864b9b0 commit 66a2dcb

8 files changed

+114
-18
lines changed

flow/layers/display_list_raster_cache_item.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,8 @@ bool DisplayListRasterCacheItem::Draw(const PaintContext& context,
133133
return false;
134134
}
135135
if (cache_state_ == CacheState::kCurrent) {
136-
return context.raster_cache->Draw(key_id_, *canvas, paint);
136+
return context.raster_cache->Draw(key_id_, *canvas, paint,
137+
context.is_root_canvas);
137138
}
138139
return false;
139140
}

flow/layers/layer.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,11 @@ struct PaintContext {
106106
LayerStateStack& state_stack;
107107
DlCanvas* canvas;
108108

109+
// Whether current canvas is root canvas. Used to determine if the raster
110+
// cache is painting to bottom-most surface, in which case it will not attempt
111+
// to preserve the RTree.
112+
bool is_root_canvas = true;
113+
109114
GrDirectContext* gr_context;
110115
SkColorSpace* dst_color_space;
111116
ExternalViewEmbedder* view_embedder;

flow/layers/layer_raster_cache_item.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,11 +183,12 @@ bool LayerRasterCacheItem::Draw(const PaintContext& context,
183183
case RasterCacheItem::kNone:
184184
return false;
185185
case RasterCacheItem::kCurrent: {
186-
return context.raster_cache->Draw(key_id_, *canvas, paint);
186+
return context.raster_cache->Draw(key_id_, *canvas, paint,
187+
context.is_root_canvas);
187188
}
188189
case RasterCacheItem::kChildren: {
189190
return context.raster_cache->Draw(layer_children_id_.value(), *canvas,
190-
paint);
191+
paint, context.is_root_canvas);
191192
}
192193
}
193194
}

flow/layers/platform_view_layer.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ void PlatformViewLayer::Paint(PaintContext& context) const {
4444
DlCanvas* canvas = context.view_embedder->CompositeEmbeddedView(view_id_);
4545
context.canvas = canvas;
4646
context.state_stack.set_delegate(canvas);
47+
context.is_root_canvas = false;
4748
}
4849

4950
} // namespace flutter

flow/raster_cache.cc

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <vector>
99

1010
#include "flutter/common/constants.h"
11+
#include "flutter/display_list/skia/dl_sk_dispatcher.h"
1112
#include "flutter/flow/layers/container_layer.h"
1213
#include "flutter/flow/layers/layer.h"
1314
#include "flutter/flow/paint_utils.h"
@@ -26,10 +27,16 @@ namespace flutter {
2627

2728
RasterCacheResult::RasterCacheResult(sk_sp<DlImage> image,
2829
const SkRect& logical_rect,
29-
const char* type)
30-
: image_(std::move(image)), logical_rect_(logical_rect), flow_(type) {}
31-
32-
void RasterCacheResult::draw(DlCanvas& canvas, const DlPaint* paint) const {
30+
const char* type,
31+
sk_sp<const DlRTree> rtree)
32+
: image_(std::move(image)),
33+
logical_rect_(logical_rect),
34+
flow_(type),
35+
rtree_(std::move(rtree)) {}
36+
37+
void RasterCacheResult::draw(DlCanvas& canvas,
38+
const DlPaint* paint,
39+
bool is_root_canvas) const {
3340
DlAutoCanvasRestore auto_restore(&canvas, true);
3441

3542
auto matrix = RasterCacheUtil::GetIntegralTransCTM(canvas.GetTransform());
@@ -39,8 +46,21 @@ void RasterCacheResult::draw(DlCanvas& canvas, const DlPaint* paint) const {
3946
std::abs(bounds.height() - image_->dimensions().height()) <= 1);
4047
canvas.TransformReset();
4148
flow_.Step();
42-
canvas.DrawImage(image_, {bounds.fLeft, bounds.fTop},
43-
DlImageSampling::kNearestNeighbor, paint);
49+
if (is_root_canvas || !rtree_) {
50+
canvas.DrawImage(image_, {bounds.fLeft, bounds.fTop},
51+
DlImageSampling::kNearestNeighbor, paint);
52+
} else {
53+
// On some platforms RTree from overlay layers is used for unobstructed
54+
// platform views and hit testing. To preserve the RTree raster cache must
55+
// paint individual rects instead of the whole image.
56+
auto rects = rtree_->searchAndConsolidateRects(kGiantRect);
57+
for (auto rect : rects) {
58+
SkRect dst(rect);
59+
dst.offset(bounds.fLeft, bounds.fTop);
60+
canvas.DrawImageRect(image_, rect, dst, DlImageSampling::kNearestNeighbor,
61+
paint);
62+
}
63+
}
4464
}
4565

4666
RasterCache::RasterCache(size_t access_threshold,
@@ -73,8 +93,12 @@ std::unique_ptr<RasterCacheResult> RasterCache::Rasterize(
7393
return nullptr;
7494
}
7595

76-
DlSkCanvasAdapter canvas(surface->getCanvas());
77-
canvas.Clear(DlColor::kTransparent());
96+
// Clear the surface canvas directly to avoid RTree storing a giant clear
97+
// rect.
98+
auto surfaceCanvas = surface->getCanvas();
99+
surfaceCanvas->clear(SK_ColorTRANSPARENT);
100+
101+
DisplayListBuilder canvas(true);
78102
canvas.Translate(-dest_rect.left(), -dest_rect.top());
79103
canvas.Transform(matrix);
80104
draw_function(&canvas);
@@ -83,9 +107,13 @@ std::unique_ptr<RasterCacheResult> RasterCache::Rasterize(
83107
draw_checkerboard(&canvas, context.logical_rect);
84108
}
85109

110+
auto display_list = canvas.Build();
111+
DlSkCanvasDispatcher dispatcher(surfaceCanvas);
112+
display_list->Dispatch(dispatcher);
113+
auto rtree = display_list->rtree();
86114
auto image = DlImage::Make(surface->makeImageSnapshot());
87115
return std::make_unique<RasterCacheResult>(image, context.logical_rect,
88-
context.flow_type);
116+
context.flow_type, rtree);
89117
}
90118

91119
bool RasterCache::UpdateCacheEntry(
@@ -146,7 +174,8 @@ bool RasterCache::HasEntry(const RasterCacheKeyID& id,
146174

147175
bool RasterCache::Draw(const RasterCacheKeyID& id,
148176
DlCanvas& canvas,
149-
const DlPaint* paint) const {
177+
const DlPaint* paint,
178+
bool is_root_canvas) const {
150179
auto it = cache_.find(RasterCacheKey(id, canvas.GetTransform()));
151180
if (it == cache_.end()) {
152181
return false;
@@ -155,7 +184,7 @@ bool RasterCache::Draw(const RasterCacheKeyID& id,
155184
Entry& entry = it->second;
156185

157186
if (entry.image) {
158-
entry.image->draw(canvas, paint);
187+
entry.image->draw(canvas, paint, is_root_canvas);
159188
return true;
160189
}
161190

flow/raster_cache.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,14 @@ class RasterCacheResult {
3030
public:
3131
RasterCacheResult(sk_sp<DlImage> image,
3232
const SkRect& logical_rect,
33-
const char* type);
33+
const char* type,
34+
sk_sp<const DlRTree> rtree = nullptr);
3435

3536
virtual ~RasterCacheResult() = default;
3637

37-
virtual void draw(DlCanvas& canvas, const DlPaint* paint) const;
38+
virtual void draw(DlCanvas& canvas,
39+
const DlPaint* paint,
40+
bool is_root_canvas) const;
3841

3942
virtual SkISize image_dimensions() const {
4043
return image_ ? image_->dimensions() : SkISize::Make(0, 0);
@@ -48,6 +51,7 @@ class RasterCacheResult {
4851
sk_sp<DlImage> image_;
4952
SkRect logical_rect_;
5053
fml::tracing::TraceFlow flow_;
54+
sk_sp<const DlRTree> rtree_;
5155
};
5256

5357
class Layer;
@@ -143,9 +147,12 @@ class RasterCache {
143147
// if the item was disabled due to conditions discovered during |Preroll|
144148
// or if the attempt to populate the entry failed due to bounds overflow
145149
// conditions.
150+
// If |is_root_canvas| is false, the raster cache will preserve the original
151+
// RTree of cached content.
146152
bool Draw(const RasterCacheKeyID& id,
147153
DlCanvas& canvas,
148-
const DlPaint* paint) const;
154+
const DlPaint* paint,
155+
bool is_root_canvas = true) const;
149156

150157
bool HasEntry(const RasterCacheKeyID& id, const SkMatrix&) const;
151158

flow/raster_cache_unittests.cc

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -886,6 +886,56 @@ TEST_F(RasterCacheTest, RasterCacheKeyIDLayerChildrenIds) {
886886
ASSERT_EQ(ids, expected_ids);
887887
}
888888

889+
TEST(RasterCache, PreservesRTree) {
890+
flutter::RasterCache cache(1);
891+
LayerStateStack preroll_state_stack;
892+
SkMatrix matrix = SkMatrix::I();
893+
preroll_state_stack.set_preroll_delegate(kGiantRect, matrix);
894+
895+
FixedRefreshRateStopwatch raster_time;
896+
FixedRefreshRateStopwatch ui_time;
897+
PaintContextHolder paint_context_holder = GetSamplePaintContextHolder(
898+
preroll_state_stack, &cache, &raster_time, &ui_time);
899+
auto& paint_context = paint_context_holder.paint_context;
900+
RasterCache::Context r_context = {
901+
// clang-format off
902+
.gr_context = paint_context.gr_context,
903+
.dst_color_space = paint_context.dst_color_space,
904+
.matrix = matrix,
905+
.logical_rect = SkRect::MakeWH(100, 100),
906+
.flow_type = "RasterCacheFlow::DisplayList",
907+
// clang-format on
908+
};
909+
910+
RasterCacheKeyID id(10, RasterCacheKeyType::kLayer);
911+
cache.UpdateCacheEntry(id, r_context, [&](DlCanvas* canvas) {
912+
canvas->DrawRect(SkRect::MakeXYWH(0, 0, 100, 10), DlPaint());
913+
canvas->DrawRect(SkRect::MakeXYWH(0, 40, 100, 10), DlPaint());
914+
});
915+
916+
{
917+
DisplayListBuilder canvas(true);
918+
cache.Draw(id, canvas, nullptr, true);
919+
auto display_list = canvas.Build();
920+
auto rtree = display_list->rtree();
921+
auto rects = rtree->searchAndConsolidateRects(kGiantRect);
922+
// For root canvas the display may clober the RTree.
923+
ASSERT_EQ(rects.size(), 1u);
924+
ASSERT_EQ(rects.front(), SkRect::MakeWH(100, 100));
925+
}
926+
{
927+
DisplayListBuilder canvas(true);
928+
cache.Draw(id, canvas, nullptr, false);
929+
auto display_list = canvas.Build();
930+
auto rtree = display_list->rtree();
931+
auto rects = rtree->searchAndConsolidateRects(kGiantRect);
932+
// For non-root canvas the RTree must be preserved
933+
ASSERT_EQ(rects.size(), 2u);
934+
ASSERT_EQ(rects.front(), SkRect::MakeXYWH(0, 0, 100, 10));
935+
ASSERT_EQ(*std::next(rects.begin(), 1), SkRect::MakeXYWH(0, 40, 100, 10));
936+
}
937+
}
938+
889939
} // namespace testing
890940
} // namespace flutter
891941

flow/testing/mock_raster_cache.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ class MockRasterCacheResult : public RasterCacheResult {
2929
public:
3030
explicit MockRasterCacheResult(SkRect device_rect);
3131

32-
void draw(DlCanvas& canvas, const DlPaint* paint = nullptr) const override{};
32+
void draw(DlCanvas& canvas,
33+
const DlPaint* paint = nullptr,
34+
bool is_root_canvas = true) const override{};
3335

3436
SkISize image_dimensions() const override {
3537
return SkSize::Make(device_rect_.width(), device_rect_.height()).toCeil();

0 commit comments

Comments
 (0)