diff --git a/flow/layers/color_filter_layer.cc b/flow/layers/color_filter_layer.cc index deb4f09579cd5..91d2527f8bbbc 100644 --- a/flow/layers/color_filter_layer.cc +++ b/flow/layers/color_filter_layer.cc @@ -41,12 +41,12 @@ void ColorFilterLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { Layer::AutoPrerollSaveLayerState save = Layer::AutoPrerollSaveLayerState::Create(context); - AutoCache cache = AutoCache(layer_raster_cache_item_.get(), context, matrix); - SkMatrix child_matrix = matrix; if (context->raster_cache) { child_matrix = RasterCacheUtil::GetIntegralTransCTM(child_matrix); } + AutoCache cache = + AutoCache(layer_raster_cache_item_.get(), context, child_matrix); ContainerLayer::Preroll(context, child_matrix); // We always use a saveLayer (or a cached rendering), so we diff --git a/flow/layers/image_filter_layer.cc b/flow/layers/image_filter_layer.cc index fce658b17b1ee..a6b62d4e76a02 100644 --- a/flow/layers/image_filter_layer.cc +++ b/flow/layers/image_filter_layer.cc @@ -52,14 +52,16 @@ void ImageFilterLayer::Preroll(PrerollContext* context, Layer::AutoPrerollSaveLayerState save = Layer::AutoPrerollSaveLayerState::Create(context); - - AutoCache cache = AutoCache(layer_raster_cache_item_.get(), context, matrix); - - SkRect child_bounds = SkRect::MakeEmpty(); SkMatrix child_matrix = matrix; if (context->raster_cache) { child_matrix = RasterCacheUtil::GetIntegralTransCTM(child_matrix); } + + AutoCache cache = + AutoCache(layer_raster_cache_item_.get(), context, child_matrix); + + SkRect child_bounds = SkRect::MakeEmpty(); + PrerollChildren(context, child_matrix, &child_bounds); // We always paint with a saveLayer (or a cached rendering), diff --git a/flow/layers/shader_mask_layer.cc b/flow/layers/shader_mask_layer.cc index 44ef92fa1e907..21e056f3584ed 100644 --- a/flow/layers/shader_mask_layer.cc +++ b/flow/layers/shader_mask_layer.cc @@ -38,10 +38,15 @@ void ShaderMaskLayer::Diff(DiffContext* context, const Layer* old_layer) { void ShaderMaskLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { Layer::AutoPrerollSaveLayerState save = Layer::AutoPrerollSaveLayerState::Create(context); + SkMatrix child_matrix = matrix; + if (context->raster_cache) { + child_matrix = RasterCacheUtil::GetIntegralTransCTM(child_matrix); + } - AutoCache cache = AutoCache(layer_raster_cache_item_.get(), context, matrix); + AutoCache cache = + AutoCache(layer_raster_cache_item_.get(), context, child_matrix); - ContainerLayer::Preroll(context, matrix); + ContainerLayer::Preroll(context, child_matrix); // We always paint with a saveLayer (or a cached rendering), // so we can always apply opacity in any of those cases. context->subtree_can_inherit_opacity = true; diff --git a/flow/layers/shader_mask_layer_unittests.cc b/flow/layers/shader_mask_layer_unittests.cc index 86912c04902e1..f19d72e8bd742 100644 --- a/flow/layers/shader_mask_layer_unittests.cc +++ b/flow/layers/shader_mask_layer_unittests.cc @@ -7,6 +7,7 @@ #include "flutter/flow/layers/layer_tree.h" #include "flutter/flow/layers/opacity_layer.h" #include "flutter/flow/raster_cache.h" +#include "flutter/flow/raster_cache_util.h" #include "flutter/flow/testing/layer_test.h" #include "flutter/flow/testing/mock_layer.h" #include "flutter/fml/macros.h" @@ -394,5 +395,46 @@ TEST_F(ShaderMaskLayerTest, OpacityInheritance) { EXPECT_TRUE(DisplayListsEQ_Verbose(expected_builder.Build(), display_list())); } +TEST_F(ShaderMaskLayerTest, SimpleFilterWithRasterCache) { + use_mock_raster_cache(); // Ensure non-fractional alignment. + + const SkMatrix initial_transform = SkMatrix::Translate(0.5f, 1.0f); + const SkRect child_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f); + const SkRect layer_bounds = SkRect::MakeLTRB(2.0f, 4.0f, 6.5f, 6.5f); + const SkPath child_path = SkPath().addRect(child_bounds); + const SkPaint child_paint = SkPaint(SkColors::kYellow); + auto layer_filter = + SkPerlinNoiseShader::MakeFractalNoise(1.0f, 1.0f, 1, 1.0f); + auto dl_filter = DlColorSource::From(layer_filter); + auto mock_layer = std::make_shared(child_path, child_paint); + auto layer = std::make_shared(dl_filter, layer_bounds, + DlBlendMode::kSrc); + layer->Add(mock_layer); + layer->Preroll(preroll_context(), initial_transform); + + SkPaint filter_paint; + filter_paint.setBlendMode(SkBlendMode::kSrc); + filter_paint.setShader(layer_filter); + layer->Paint(paint_context()); + EXPECT_EQ( + mock_canvas().draw_calls(), + std::vector({MockCanvas::DrawCall{0, MockCanvas::SetMatrixData{SkM44( + SkMatrix::Translate(0.0, 0.0))}}, + MockCanvas::DrawCall{ + 0, MockCanvas::SaveLayerData{child_bounds, SkPaint(), + nullptr, 1}}, + MockCanvas::DrawCall{ + 1, MockCanvas::DrawPathData{child_path, child_paint}}, + MockCanvas::DrawCall{ + 1, MockCanvas::ConcatMatrixData{SkM44::Translate( + layer_bounds.fLeft, layer_bounds.fTop)}}, + MockCanvas::DrawCall{ + 1, MockCanvas::DrawRectData{SkRect::MakeWH( + layer_bounds.width(), + layer_bounds.height()), + filter_paint}}, + MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}})); +} + } // namespace testing } // namespace flutter diff --git a/flow/testing/mock_layer.cc b/flow/testing/mock_layer.cc index 42eb85524fea3..fb89a8e3a0c1e 100644 --- a/flow/testing/mock_layer.cc +++ b/flow/testing/mock_layer.cc @@ -65,18 +65,27 @@ void MockCacheableContainerLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { Layer::AutoPrerollSaveLayerState save = Layer::AutoPrerollSaveLayerState::Create(context); - auto cache = AutoCache(layer_raster_cache_item_.get(), context, matrix); + SkMatrix child_matrix = matrix; + if (context->raster_cache) { + child_matrix = RasterCacheUtil::GetIntegralTransCTM(child_matrix); + } + + auto cache = AutoCache(layer_raster_cache_item_.get(), context, child_matrix); - ContainerLayer::Preroll(context, matrix); + ContainerLayer::Preroll(context, child_matrix); } void MockCacheableLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { Layer::AutoPrerollSaveLayerState save = Layer::AutoPrerollSaveLayerState::Create(context); - auto cache = AutoCache(raster_cache_item_.get(), context, matrix); + SkMatrix child_matrix = matrix; + if (context->raster_cache) { + child_matrix = RasterCacheUtil::GetIntegralTransCTM(child_matrix); + } + auto cache = AutoCache(raster_cache_item_.get(), context, child_matrix); - MockLayer::Preroll(context, matrix); + MockLayer::Preroll(context, child_matrix); } } // namespace testing