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

Commit 01a52b9

Browse files
authored
Try rasterizing images and layers only once, even when their rasterization fails. Further enforce the same access threshold on layers as on Pictures. Previously layers would always be cached. The latter is a semantic change. (#16545)
If Rasterization fails, i.e. image.is_valid() is false, the cache might try rasterizing the image again on the next frame. Not only is this wasteful put might also prevent other pictures to be cached within the current frame budget.
1 parent 76d12d2 commit 01a52b9

File tree

3 files changed

+64
-34
lines changed

3 files changed

+64
-34
lines changed

flow/raster_cache.cc

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -119,24 +119,15 @@ static RasterCacheResult Rasterize(
119119
return {surface->makeImageSnapshot(), logical_rect};
120120
}
121121

122-
RasterCacheResult RasterizePicture(SkPicture* picture,
123-
GrContext* context,
124-
const SkMatrix& ctm,
125-
SkColorSpace* dst_color_space,
126-
bool checkerboard) {
127-
return Rasterize(context, ctm, dst_color_space, checkerboard,
128-
picture->cullRect(),
129-
[=](SkCanvas* canvas) { canvas->drawPicture(picture); });
130-
}
131-
132-
void RasterCache::Prepare(PrerollContext* context,
122+
bool RasterCache::Prepare(PrerollContext* context,
133123
Layer* layer,
134124
const SkMatrix& ctm) {
135125
LayerRasterCacheKey cache_key(layer->unique_id(), ctm);
126+
136127
Entry& entry = layer_cache_[cache_key];
137-
entry.access_count++;
138-
entry.used_this_frame = true;
139-
if (!entry.image.is_valid()) {
128+
129+
if (!entry.did_rasterize && !entry.image.is_valid() &&
130+
entry.access_count >= access_threshold_) {
140131
entry.image = Rasterize(
141132
context->gr_context, ctm, context->dst_color_space,
142133
checkerboard_images_, layer->paint_bounds(),
@@ -161,7 +152,12 @@ void RasterCache::Prepare(PrerollContext* context,
161152
layer->Paint(paintContext);
162153
}
163154
});
155+
156+
entry.did_rasterize = true;
157+
158+
return true;
164159
}
160+
return false;
165161
}
166162

167163
bool RasterCache::Prepare(GrContext* context,
@@ -200,12 +196,19 @@ bool RasterCache::Prepare(GrContext* context,
200196
return false;
201197
}
202198

203-
if (!entry.image.is_valid()) {
204-
entry.image = RasterizePicture(picture, context, transformation_matrix,
205-
dst_color_space, checkerboard_images_);
199+
// Don't try to rasterize pictures that were already attempted to be
200+
// rasterized even if the image is invalid.
201+
if (!entry.did_rasterize && !entry.image.is_valid()) {
202+
entry.image =
203+
Rasterize(context, transformation_matrix, dst_color_space,
204+
checkerboard_images_, picture->cullRect(),
205+
[=](SkCanvas* canvas) { canvas->drawPicture(picture); });
206+
207+
entry.did_rasterize = true;
206208
picture_cached_this_frame_++;
209+
return true;
207210
}
208-
return true;
211+
return false;
209212
}
210213

211214
RasterCacheResult RasterCache::Get(const SkPicture& picture,

flow/raster_cache.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ class RasterCache {
8484
bool is_complex,
8585
bool will_change);
8686

87-
void Prepare(PrerollContext* context, Layer* layer, const SkMatrix& ctm);
87+
bool Prepare(PrerollContext* context, Layer* layer, const SkMatrix& ctm);
8888

8989
RasterCacheResult Get(const SkPicture& picture, const SkMatrix& ctm) const;
9090

@@ -101,6 +101,7 @@ class RasterCache {
101101
private:
102102
struct Entry {
103103
bool used_this_frame = false;
104+
bool did_rasterize = false;
104105
size_t access_count = 0;
105106
RasterCacheResult image;
106107
};

flow/raster_cache_unittests.cc

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include "flutter/flow/raster_cache.h"
66

7+
#include "flutter/flow/layers/container_layer.h"
78
#include "gtest/gtest.h"
89
#include "third_party/skia/include/core/SkPicture.h"
910
#include "third_party/skia/include/core/SkPictureRecorder.h"
@@ -29,16 +30,14 @@ TEST(RasterCache, SimpleInitialization) {
2930
ASSERT_TRUE(true);
3031
}
3132

32-
TEST(RasterCache, ThresholdIsRespected) {
33+
TEST(RasterCache, ThresholdIsRespectedForPictures) {
3334
size_t threshold = 2;
3435
flutter::RasterCache cache(threshold);
3536

3637
SkMatrix matrix = SkMatrix::I();
3738

3839
auto picture = GetSamplePicture();
3940

40-
sk_sp<SkImage> image;
41-
4241
sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB();
4342
ASSERT_FALSE(
4443
cache.Prepare(NULL, picture.get(), matrix, srgb.get(), true, false));
@@ -61,21 +60,28 @@ TEST(RasterCache, ThresholdIsRespected) {
6160
ASSERT_TRUE(cache.Get(*picture, matrix).is_valid());
6261
}
6362

64-
TEST(RasterCache, AccessThresholdOfZeroDisablesCaching) {
65-
size_t threshold = 0;
63+
TEST(RasterCache, ThresholdIsRespectedForLayers) {
64+
size_t threshold = 2;
6665
flutter::RasterCache cache(threshold);
6766

6867
SkMatrix matrix = SkMatrix::I();
6968

70-
auto picture = GetSamplePicture();
71-
72-
sk_sp<SkImage> image;
69+
ContainerLayer layer;
7370

7471
sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB();
75-
ASSERT_FALSE(
76-
cache.Prepare(NULL, picture.get(), matrix, srgb.get(), true, false));
72+
ASSERT_FALSE(cache.Prepare(nullptr, &layer, matrix));
73+
ASSERT_FALSE(cache.Prepare(nullptr, &layer, matrix));
74+
ASSERT_FALSE(cache.Prepare(nullptr, &layer, matrix));
7775

78-
ASSERT_FALSE(cache.Get(*picture, matrix).is_valid());
76+
// 1st access.
77+
ASSERT_FALSE(cache.Get(&layer, matrix).is_valid());
78+
79+
ASSERT_FALSE(cache.Prepare(nullptr, &layer, matrix));
80+
81+
// 2st access.
82+
ASSERT_FALSE(cache.Get(&layer, matrix).is_valid());
83+
84+
// Calling Prepare now would crash due to the nullptr.
7985
}
8086

8187
TEST(RasterCache, PictureCacheLimitPerFrameIsRespectedWhenZero) {
@@ -86,8 +92,6 @@ TEST(RasterCache, PictureCacheLimitPerFrameIsRespectedWhenZero) {
8692

8793
auto picture = GetSamplePicture();
8894

89-
sk_sp<SkImage> image;
90-
9195
sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB();
9296
ASSERT_FALSE(
9397
cache.Prepare(NULL, picture.get(), matrix, srgb.get(), true, false));
@@ -103,8 +107,6 @@ TEST(RasterCache, SweepsRemoveUnusedFrames) {
103107

104108
auto picture = GetSamplePicture();
105109

106-
sk_sp<SkImage> image;
107-
108110
sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB();
109111
ASSERT_FALSE(cache.Prepare(NULL, picture.get(), matrix, srgb.get(), true,
110112
false)); // 1
@@ -122,5 +124,29 @@ TEST(RasterCache, SweepsRemoveUnusedFrames) {
122124
ASSERT_FALSE(cache.Get(*picture, matrix).is_valid());
123125
}
124126

127+
TEST(RasterCache, TryRasterizngOnlyOnce) {
128+
size_t threshold = 1;
129+
flutter::RasterCache cache(threshold);
130+
131+
SkMatrix matrix = SkMatrix::I();
132+
// Test picture too large to successfully rasterize.
133+
auto picture = SkPicture::MakePlaceholder(SkRect::MakeWH(2e12, 2e12));
134+
135+
sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB();
136+
ASSERT_FALSE(cache.Prepare(nullptr, picture.get(), matrix, srgb.get(), true,
137+
false)); // 1
138+
ASSERT_FALSE(cache.Get(*picture, matrix).is_valid());
139+
140+
// Rasterization ran, though Get() below returns an invalid image.
141+
ASSERT_TRUE(cache.Prepare(nullptr, picture.get(), matrix, srgb.get(), true,
142+
false)); // 2
143+
ASSERT_FALSE(cache.Get(*picture, matrix).is_valid());
144+
145+
// This time we should not try again to rasterize.
146+
ASSERT_FALSE(cache.Prepare(nullptr, picture.get(), matrix, srgb.get(), true,
147+
false)); // 2
148+
ASSERT_FALSE(cache.Get(*picture, matrix).is_valid());
149+
}
150+
125151
} // namespace testing
126152
} // namespace flutter

0 commit comments

Comments
 (0)