Skip to content

Commit a7a25d3

Browse files
authored
Revert again "Remove layer integral offset snapping" (flutter#18132)
1 parent 663bfe8 commit a7a25d3

19 files changed

+150
-59
lines changed

flow/layers/container_layer.cc

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,6 @@ void ContainerLayer::PaintChildren(PaintContext& context) const {
6565
}
6666
}
6767

68-
void ContainerLayer::TryToPrepareRasterCache(PrerollContext* context,
69-
Layer* layer,
70-
const SkMatrix& matrix) {
71-
if (!context->has_platform_view && context->raster_cache &&
72-
SkRect::Intersects(context->cull_rect, layer->paint_bounds())) {
73-
context->raster_cache->Prepare(context, layer, matrix);
74-
}
75-
}
76-
7768
#if defined(OS_FUCHSIA)
7869

7970
void ContainerLayer::UpdateScene(SceneUpdateContext& context) {

flow/layers/container_layer.h

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,20 +37,6 @@ class ContainerLayer : public Layer {
3737
// For OpacityLayer to restructure to have a single child.
3838
void ClearChildren() { layers_.clear(); }
3939

40-
// Try to prepare the raster cache for a given layer.
41-
//
42-
// The raster cache would fail if either of the followings is true:
43-
// 1. The context has a platform view.
44-
// 2. The context does not have a valid raster cache.
45-
// 3. The layer's paint bounds does not intersect with the cull rect.
46-
//
47-
// We make this a static function instead of a member function that directy
48-
// uses the "this" pointer as the layer because we sometimes need to raster
49-
// cache a child layer and one can't access its child's protected method.
50-
static void TryToPrepareRasterCache(PrerollContext* context,
51-
Layer* layer,
52-
const SkMatrix& matrix);
53-
5440
private:
5541
std::vector<std::shared_ptr<Layer>> layers_;
5642

flow/layers/image_filter_layer.cc

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,26 @@ void ImageFilterLayer::Preroll(PrerollContext* context,
2828
set_paint_bounds(child_paint_bounds_);
2929
}
3030

31-
TryToPrepareRasterCache(context, this, matrix);
31+
if (!context->has_platform_view && context->raster_cache &&
32+
SkRect::Intersects(context->cull_rect, paint_bounds())) {
33+
SkMatrix ctm = matrix;
34+
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
35+
ctm = RasterCache::GetIntegralTransCTM(ctm);
36+
#endif
37+
context->raster_cache->Prepare(context, this, ctm);
38+
}
3239
}
3340

3441
void ImageFilterLayer::Paint(PaintContext& context) const {
3542
TRACE_EVENT0("flutter", "ImageFilterLayer::Paint");
3643
FML_DCHECK(needs_painting());
3744

45+
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
46+
SkAutoCanvasRestore save(context.leaf_nodes_canvas, true);
47+
context.leaf_nodes_canvas->setMatrix(RasterCache::GetIntegralTransCTM(
48+
context.leaf_nodes_canvas->getTotalMatrix()));
49+
#endif
50+
3851
if (context.raster_cache &&
3952
context.raster_cache->Draw(this, *context.leaf_nodes_canvas)) {
4053
return;

flow/layers/image_filter_layer_unittests.cc

Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,14 @@ TEST_F(ImageFilterLayerTest, EmptyFilter) {
6060
layer->Paint(paint_context());
6161
EXPECT_EQ(mock_canvas().draw_calls(),
6262
std::vector({
63+
MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
64+
MockCanvas::DrawCall{1, MockCanvas::SetMatrixData{SkMatrix()}},
6365
MockCanvas::DrawCall{
64-
0, MockCanvas::SaveLayerData{child_bounds, filter_paint,
65-
nullptr, 1}},
66+
1, MockCanvas::SaveLayerData{child_bounds, filter_paint,
67+
nullptr, 2}},
6668
MockCanvas::DrawCall{
67-
1, MockCanvas::DrawPathData{child_path, child_paint}},
69+
2, MockCanvas::DrawPathData{child_path, child_paint}},
70+
MockCanvas::DrawCall{2, MockCanvas::RestoreData{1}},
6871
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}},
6972
}));
7073
}
@@ -93,11 +96,14 @@ TEST_F(ImageFilterLayerTest, SimpleFilter) {
9396
layer->Paint(paint_context());
9497
EXPECT_EQ(mock_canvas().draw_calls(),
9598
std::vector({
99+
MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
100+
MockCanvas::DrawCall{1, MockCanvas::SetMatrixData{SkMatrix()}},
96101
MockCanvas::DrawCall{
97-
0, MockCanvas::SaveLayerData{child_bounds, filter_paint,
98-
nullptr, 1}},
102+
1, MockCanvas::SaveLayerData{child_bounds, filter_paint,
103+
nullptr, 2}},
99104
MockCanvas::DrawCall{
100-
1, MockCanvas::DrawPathData{child_path, child_paint}},
105+
2, MockCanvas::DrawPathData{child_path, child_paint}},
106+
MockCanvas::DrawCall{2, MockCanvas::RestoreData{1}},
101107
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}},
102108
}));
103109
}
@@ -126,11 +132,14 @@ TEST_F(ImageFilterLayerTest, SimpleFilterBounds) {
126132
layer->Paint(paint_context());
127133
EXPECT_EQ(mock_canvas().draw_calls(),
128134
std::vector({
135+
MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
136+
MockCanvas::DrawCall{1, MockCanvas::SetMatrixData{SkMatrix()}},
129137
MockCanvas::DrawCall{
130-
0, MockCanvas::SaveLayerData{child_bounds, filter_paint,
131-
nullptr, 1}},
138+
1, MockCanvas::SaveLayerData{child_bounds, filter_paint,
139+
nullptr, 2}},
132140
MockCanvas::DrawCall{
133-
1, MockCanvas::DrawPathData{child_path, child_paint}},
141+
2, MockCanvas::DrawPathData{child_path, child_paint}},
142+
MockCanvas::DrawCall{2, MockCanvas::RestoreData{1}},
134143
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}},
135144
}));
136145
}
@@ -168,16 +177,19 @@ TEST_F(ImageFilterLayerTest, MultipleChildren) {
168177
SkPaint filter_paint;
169178
filter_paint.setImageFilter(layer_filter);
170179
layer->Paint(paint_context());
171-
EXPECT_EQ(
172-
mock_canvas().draw_calls(),
173-
std::vector({MockCanvas::DrawCall{
174-
0, MockCanvas::SaveLayerData{children_bounds,
175-
filter_paint, nullptr, 1}},
176-
MockCanvas::DrawCall{
177-
1, MockCanvas::DrawPathData{child_path1, child_paint1}},
178-
MockCanvas::DrawCall{
179-
1, MockCanvas::DrawPathData{child_path2, child_paint2}},
180-
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}));
180+
EXPECT_EQ(mock_canvas().draw_calls(),
181+
std::vector(
182+
{MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
183+
MockCanvas::DrawCall{1, MockCanvas::SetMatrixData{SkMatrix()}},
184+
MockCanvas::DrawCall{
185+
1, MockCanvas::SaveLayerData{children_bounds, filter_paint,
186+
nullptr, 2}},
187+
MockCanvas::DrawCall{
188+
2, MockCanvas::DrawPathData{child_path1, child_paint1}},
189+
MockCanvas::DrawCall{
190+
2, MockCanvas::DrawPathData{child_path2, child_paint2}},
191+
MockCanvas::DrawCall{2, MockCanvas::RestoreData{1}},
192+
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}));
181193
}
182194

183195
TEST_F(ImageFilterLayerTest, Nested) {
@@ -225,16 +237,22 @@ TEST_F(ImageFilterLayerTest, Nested) {
225237
layer1->Paint(paint_context());
226238
EXPECT_EQ(mock_canvas().draw_calls(),
227239
std::vector({
240+
MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
241+
MockCanvas::DrawCall{1, MockCanvas::SetMatrixData{SkMatrix()}},
228242
MockCanvas::DrawCall{
229-
0, MockCanvas::SaveLayerData{children_bounds, filter_paint1,
230-
nullptr, 1}},
243+
1, MockCanvas::SaveLayerData{children_bounds, filter_paint1,
244+
nullptr, 2}},
231245
MockCanvas::DrawCall{
232-
1, MockCanvas::DrawPathData{child_path1, child_paint1}},
246+
2, MockCanvas::DrawPathData{child_path1, child_paint1}},
247+
MockCanvas::DrawCall{2, MockCanvas::SaveData{3}},
248+
MockCanvas::DrawCall{3, MockCanvas::SetMatrixData{SkMatrix()}},
233249
MockCanvas::DrawCall{
234-
1, MockCanvas::SaveLayerData{child_path2.getBounds(),
235-
filter_paint2, nullptr, 2}},
250+
3, MockCanvas::SaveLayerData{child_path2.getBounds(),
251+
filter_paint2, nullptr, 4}},
236252
MockCanvas::DrawCall{
237-
2, MockCanvas::DrawPathData{child_path2, child_paint2}},
253+
4, MockCanvas::DrawPathData{child_path2, child_paint2}},
254+
MockCanvas::DrawCall{4, MockCanvas::RestoreData{3}},
255+
MockCanvas::DrawCall{3, MockCanvas::RestoreData{2}},
238256
MockCanvas::DrawCall{2, MockCanvas::RestoreData{1}},
239257
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}},
240258
}));

flow/layers/opacity_layer.cc

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,14 @@ void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
4848

4949
{
5050
set_paint_bounds(paint_bounds().makeOffset(offset_.fX, offset_.fY));
51-
TryToPrepareRasterCache(context, container, child_matrix);
51+
if (!context->has_platform_view && context->raster_cache &&
52+
SkRect::Intersects(context->cull_rect, paint_bounds())) {
53+
SkMatrix ctm = child_matrix;
54+
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
55+
ctm = RasterCache::GetIntegralTransCTM(ctm);
56+
#endif
57+
context->raster_cache->Prepare(context, container, ctm);
58+
}
5259
}
5360
}
5461

@@ -62,6 +69,11 @@ void OpacityLayer::Paint(PaintContext& context) const {
6269
SkAutoCanvasRestore save(context.internal_nodes_canvas, true);
6370
context.internal_nodes_canvas->translate(offset_.fX, offset_.fY);
6471

72+
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
73+
context.internal_nodes_canvas->setMatrix(RasterCache::GetIntegralTransCTM(
74+
context.leaf_nodes_canvas->getTotalMatrix()));
75+
#endif
76+
6577
if (context.raster_cache &&
6678
context.raster_cache->Draw(GetChildContainer(),
6779
*context.leaf_nodes_canvas, &paint)) {
@@ -71,7 +83,8 @@ void OpacityLayer::Paint(PaintContext& context) const {
7183
// Skia may clip the content with saveLayerBounds (although it's not a
7284
// guaranteed clip). So we have to provide a big enough saveLayerBounds. To do
7385
// so, we first remove the offset from paint bounds since it's already in the
74-
// matrix. Then we round out the bounds.
86+
// matrix. Then we round out the bounds because of our
87+
// RasterCache::GetIntegralTransCTM optimization.
7588
//
7689
// Note that the following lines are only accessible when the raster cache is
7790
// not available (e.g., when we're using the software backend in golden

flow/layers/opacity_layer_unittests.cc

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ TEST_F(OpacityLayerTest, FullyOpaque) {
5858
const SkMatrix initial_transform = SkMatrix::MakeTrans(0.5f, 0.5f);
5959
const SkMatrix layer_transform =
6060
SkMatrix::MakeTrans(layer_offset.fX, layer_offset.fY);
61+
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
62+
const SkMatrix integral_layer_transform = RasterCache::GetIntegralTransCTM(
63+
SkMatrix::Concat(initial_transform, layer_transform));
64+
#endif
6165
const SkPaint child_paint = SkPaint(SkColors::kGreen);
6266
const SkRect expected_layer_bounds =
6367
layer_transform.mapRect(child_path.getBounds());
@@ -82,6 +86,10 @@ TEST_F(OpacityLayerTest, FullyOpaque) {
8286
auto expected_draw_calls = std::vector(
8387
{MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
8488
MockCanvas::DrawCall{1, MockCanvas::ConcatMatrixData{layer_transform}},
89+
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
90+
MockCanvas::DrawCall{
91+
1, MockCanvas::SetMatrixData{integral_layer_transform}},
92+
#endif
8593
MockCanvas::DrawCall{
8694
1, MockCanvas::SaveLayerData{opacity_bounds, opacity_paint, nullptr,
8795
2}},
@@ -99,6 +107,10 @@ TEST_F(OpacityLayerTest, FullyTransparent) {
99107
const SkMatrix initial_transform = SkMatrix::MakeTrans(0.5f, 0.5f);
100108
const SkMatrix layer_transform =
101109
SkMatrix::MakeTrans(layer_offset.fX, layer_offset.fY);
110+
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
111+
const SkMatrix integral_layer_transform = RasterCache::GetIntegralTransCTM(
112+
SkMatrix::Concat(initial_transform, layer_transform));
113+
#endif
102114
const SkPaint child_paint = SkPaint(SkColors::kGreen);
103115
const SkRect expected_layer_bounds =
104116
layer_transform.mapRect(child_path.getBounds());
@@ -121,6 +133,10 @@ TEST_F(OpacityLayerTest, FullyTransparent) {
121133
auto expected_draw_calls = std::vector(
122134
{MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
123135
MockCanvas::DrawCall{1, MockCanvas::ConcatMatrixData{layer_transform}},
136+
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
137+
MockCanvas::DrawCall{
138+
1, MockCanvas::SetMatrixData{integral_layer_transform}},
139+
#endif
124140
MockCanvas::DrawCall{1, MockCanvas::SaveData{2}},
125141
MockCanvas::DrawCall{
126142
2, MockCanvas::ClipRectData{kEmptyRect, SkClipOp::kIntersect,
@@ -139,6 +155,10 @@ TEST_F(OpacityLayerTest, HalfTransparent) {
139155
const SkMatrix initial_transform = SkMatrix::MakeTrans(0.5f, 0.5f);
140156
const SkMatrix layer_transform =
141157
SkMatrix::MakeTrans(layer_offset.fX, layer_offset.fY);
158+
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
159+
const SkMatrix integral_layer_transform = RasterCache::GetIntegralTransCTM(
160+
SkMatrix::Concat(initial_transform, layer_transform));
161+
#endif
142162
const SkPaint child_paint = SkPaint(SkColors::kGreen);
143163
const SkRect expected_layer_bounds =
144164
layer_transform.mapRect(child_path.getBounds());
@@ -165,6 +185,10 @@ TEST_F(OpacityLayerTest, HalfTransparent) {
165185
auto expected_draw_calls = std::vector(
166186
{MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
167187
MockCanvas::DrawCall{1, MockCanvas::ConcatMatrixData{layer_transform}},
188+
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
189+
MockCanvas::DrawCall{
190+
1, MockCanvas::SetMatrixData{integral_layer_transform}},
191+
#endif
168192
MockCanvas::DrawCall{
169193
1, MockCanvas::SaveLayerData{opacity_bounds, opacity_paint, nullptr,
170194
2}},
@@ -187,6 +211,13 @@ TEST_F(OpacityLayerTest, Nested) {
187211
SkMatrix::MakeTrans(layer1_offset.fX, layer1_offset.fY);
188212
const SkMatrix layer2_transform =
189213
SkMatrix::MakeTrans(layer2_offset.fX, layer2_offset.fY);
214+
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
215+
const SkMatrix integral_layer1_transform = RasterCache::GetIntegralTransCTM(
216+
SkMatrix::Concat(initial_transform, layer1_transform));
217+
const SkMatrix integral_layer2_transform = RasterCache::GetIntegralTransCTM(
218+
SkMatrix::Concat(SkMatrix::Concat(initial_transform, layer1_transform),
219+
layer2_transform));
220+
#endif
190221
const SkPaint child1_paint = SkPaint(SkColors::kRed);
191222
const SkPaint child2_paint = SkPaint(SkColors::kBlue);
192223
const SkPaint child3_paint = SkPaint(SkColors::kGreen);
@@ -247,13 +278,21 @@ TEST_F(OpacityLayerTest, Nested) {
247278
auto expected_draw_calls = std::vector(
248279
{MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
249280
MockCanvas::DrawCall{1, MockCanvas::ConcatMatrixData{layer1_transform}},
281+
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
282+
MockCanvas::DrawCall{
283+
1, MockCanvas::SetMatrixData{integral_layer1_transform}},
284+
#endif
250285
MockCanvas::DrawCall{
251286
1, MockCanvas::SaveLayerData{opacity1_bounds, opacity1_paint,
252287
nullptr, 2}},
253288
MockCanvas::DrawCall{
254289
2, MockCanvas::DrawPathData{child1_path, child1_paint}},
255290
MockCanvas::DrawCall{2, MockCanvas::SaveData{3}},
256291
MockCanvas::DrawCall{3, MockCanvas::ConcatMatrixData{layer2_transform}},
292+
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
293+
MockCanvas::DrawCall{
294+
3, MockCanvas::SetMatrixData{integral_layer2_transform}},
295+
#endif
257296
MockCanvas::DrawCall{
258297
3, MockCanvas::SaveLayerData{opacity2_bounds, opacity2_paint,
259298
nullptr, 4}},

flow/layers/picture_layer.cc

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,12 @@ void PictureLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
2424
if (auto* cache = context->raster_cache) {
2525
TRACE_EVENT0("flutter", "PictureLayer::RasterCache (Preroll)");
2626

27-
cache->Prepare(context->gr_context, sk_picture, matrix,
27+
SkMatrix ctm = matrix;
28+
ctm.postTranslate(offset_.x(), offset_.y());
29+
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
30+
ctm = RasterCache::GetIntegralTransCTM(ctm);
31+
#endif
32+
cache->Prepare(context->gr_context, sk_picture, ctm,
2833
context->dst_color_space, is_complex_, will_change_);
2934
}
3035

@@ -39,6 +44,10 @@ void PictureLayer::Paint(PaintContext& context) const {
3944

4045
SkAutoCanvasRestore save(context.leaf_nodes_canvas, true);
4146
context.leaf_nodes_canvas->translate(offset_.x(), offset_.y());
47+
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
48+
context.leaf_nodes_canvas->setMatrix(RasterCache::GetIntegralTransCTM(
49+
context.leaf_nodes_canvas->getTotalMatrix()));
50+
#endif
4251

4352
if (context.raster_cache &&
4453
context.raster_cache->Draw(*picture(), *context.leaf_nodes_canvas)) {

flow/layers/picture_layer_unittests.cc

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
#include "flutter/testing/mock_canvas.h"
1212
#include "third_party/skia/include/core/SkPicture.h"
1313

14+
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
15+
#include "flutter/flow/raster_cache.h"
16+
#endif
17+
1418
namespace flutter {
1519
namespace testing {
1620

@@ -81,11 +85,16 @@ TEST_F(PictureLayerTest, SimplePicture) {
8185
EXPECT_FALSE(layer->needs_system_composite());
8286

8387
layer->Paint(paint_context());
84-
auto expected_draw_calls =
85-
std::vector({MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
86-
MockCanvas::DrawCall{
87-
1, MockCanvas::ConcatMatrixData{layer_offset_matrix}},
88-
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}});
88+
auto expected_draw_calls = std::vector(
89+
{MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
90+
MockCanvas::DrawCall{1,
91+
MockCanvas::ConcatMatrixData{layer_offset_matrix}},
92+
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
93+
MockCanvas::DrawCall{
94+
1, MockCanvas::SetMatrixData{RasterCache::GetIntegralTransCTM(
95+
layer_offset_matrix)}},
96+
#endif
97+
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}});
8998
EXPECT_EQ(mock_canvas().draw_calls(), expected_draw_calls);
9099
}
91100

flow/raster_cache.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,13 @@ class RasterCache {
6262
return bounds;
6363
}
6464

65+
static SkMatrix GetIntegralTransCTM(const SkMatrix& ctm) {
66+
SkMatrix result = ctm;
67+
result[SkMatrix::kMTransX] = SkScalarRoundToScalar(ctm.getTranslateX());
68+
result[SkMatrix::kMTransY] = SkScalarRoundToScalar(ctm.getTranslateY());
69+
return result;
70+
}
71+
6572
// Return true if the cache is generated.
6673
//
6774
// We may return false and not generate the cache if

0 commit comments

Comments
 (0)