Skip to content

Commit

Permalink
[flow] fix RasterCache to round out device bounds
Browse files Browse the repository at this point in the history
With fractional coordinates, it's not enough to round up device bounds
width and height. Round out to get a large enough integer-size texture.

Fixes: flutter/flutter#107733
Fixes: flutter/flutter#107921
Fixes: flutter/flutter#109608
  • Loading branch information
jpnurmi committed Aug 19, 2022
1 parent da611f8 commit 3a6fff3
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 7 deletions.
16 changes: 9 additions & 7 deletions flow/raster_cache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,16 @@ void RasterCacheResult::draw(SkCanvas& canvas, const SkPaint* paint) const {

SkRect bounds =
RasterCacheUtil::GetDeviceBounds(logical_rect_, canvas.getTotalMatrix());
bounds.roundOut(&bounds);
#ifndef NDEBUG
// The image dimensions should always be larger than the device bounds and
// smaller than the device bounds plus one pixel, at the same time, we must
// introduce epsilon to solve the round-off error. The value of epsilon is
// 1/512, which represents half of an AA sample.
float epsilon = 1 / 512.0;
FML_DCHECK(image_->dimensions().width() - bounds.width() > -epsilon &&
image_->dimensions().height() - bounds.height() > -epsilon &&
image_->dimensions().width() - bounds.width() < 1 + epsilon &&
image_->dimensions().height() - bounds.height() < 1 + epsilon);
FML_DCHECK(
std::abs(bounds.width() - image_->dimensions().width()) <= 1 + epsilon &&
std::abs(bounds.height() - image_->dimensions().height()) <= 1 + epsilon);
#endif
canvas.resetMatrix();
flow_.Step();
Expand All @@ -65,11 +65,13 @@ std::unique_ptr<RasterCacheResult> RasterCache::Rasterize(
const {
TRACE_EVENT0("flutter", "RasterCachePopulate");

SkRect dest_rect =
SkRect bounds =
RasterCacheUtil::GetDeviceBounds(context.logical_rect, context.matrix);
// we always round out here so that the texture is integer sized.
int width = SkScalarCeilToInt(dest_rect.width());
int height = SkScalarCeilToInt(dest_rect.height());
SkIRect dest_rect;
bounds.roundOut(&dest_rect);
int width = dest_rect.width();
int height = dest_rect.height();

const SkImageInfo image_info = SkImageInfo::MakeN32Premul(
width, height, sk_ref_sp(context.dst_color_space));
Expand Down
29 changes: 29 additions & 0 deletions flow/raster_cache_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,35 @@ TEST(RasterCache, DeviceRectRoundOutForDisplayList) {
ASSERT_TRUE(display_list_item.Draw(paint_context, &canvas, &paint));
}

TEST(RasterCache, DeviceRectRoundOutRasterize) {
flutter::RasterCache cache(1);
FixedRefreshRateStopwatch raster_time;
FixedRefreshRateStopwatch ui_time;
PaintContextHolder paint_context_holder =
GetSamplePaintContextHolder(&cache, &raster_time, &ui_time);
auto& paint_context = paint_context_holder.paint_context;
int surface_width = -1;
int surface_height = -1;
auto dummy_draw_function = [&](SkCanvas* canvas) {
SkSurface* surface = canvas->getSurface();
surface_width = surface->width();
surface_height = surface->height();
};
RasterCache::Context r_context = {
// clang-format off
.gr_context = paint_context.gr_context,
.dst_color_space = paint_context.dst_color_space,
.matrix = SkMatrix::I(),
.logical_rect = SkRect::MakeLTRB(-52.1, -19.5, 878.6, 457.5),
.flow_type = "RasterCacheFlow::DisplayList",
// clang-format on
};

cache.Rasterize(r_context, dummy_draw_function, nullptr);
ASSERT_EQ(surface_width, 932);
ASSERT_EQ(surface_height, 478);
}

TEST(RasterCache, NestedOpCountMetricUsedForDisplayList) {
size_t threshold = 1;
flutter::RasterCache cache(threshold);
Expand Down

0 comments on commit 3a6fff3

Please sign in to comment.