diff --git a/engine/src/flutter/flow/layers/color_filter_layer.cc b/engine/src/flutter/flow/layers/color_filter_layer.cc index bc588058174..5624c063cc0 100644 --- a/engine/src/flutter/flow/layers/color_filter_layer.cc +++ b/engine/src/flutter/flow/layers/color_filter_layer.cc @@ -7,7 +7,7 @@ namespace flutter { ColorFilterLayer::ColorFilterLayer(sk_sp filter) - : filter_(std::move(filter)) {} + : filter_(std::move(filter)), render_count_(1) {} void ColorFilterLayer::Diff(DiffContext* context, const Layer* old_layer) { DiffContext::AutoSubtreeRestore subtree(context); @@ -29,12 +29,32 @@ void ColorFilterLayer::Preroll(PrerollContext* context, Layer::AutoPrerollSaveLayerState save = Layer::AutoPrerollSaveLayerState::Create(context); ContainerLayer::Preroll(context, matrix); + + if (render_count_ >= kMinimumRendersBeforeCachingFilterLayer) { + TryToPrepareRasterCache(context, this, matrix); + } else { + render_count_++; + TryToPrepareRasterCache(context, GetCacheableChild(), matrix); + } } void ColorFilterLayer::Paint(PaintContext& context) const { TRACE_EVENT0("flutter", "ColorFilterLayer::Paint"); FML_DCHECK(needs_painting(context)); + if (context.raster_cache) { + if (context.raster_cache->Draw(this, *context.leaf_nodes_canvas)) { + return; + } + SkPaint paint; + paint.setColorFilter(filter_); + + if (context.raster_cache->Draw(GetCacheableChild(), + *context.leaf_nodes_canvas, &paint)) { + return; + } + } + SkPaint paint; paint.setColorFilter(filter_); diff --git a/engine/src/flutter/flow/layers/color_filter_layer.h b/engine/src/flutter/flow/layers/color_filter_layer.h index e19d69377a5..51432cea6a7 100644 --- a/engine/src/flutter/flow/layers/color_filter_layer.h +++ b/engine/src/flutter/flow/layers/color_filter_layer.h @@ -10,7 +10,7 @@ namespace flutter { -class ColorFilterLayer : public ContainerLayer { +class ColorFilterLayer : public MergedContainerLayer { public: explicit ColorFilterLayer(sk_sp filter); @@ -23,6 +23,9 @@ class ColorFilterLayer : public ContainerLayer { private: sk_sp filter_; + static constexpr int kMinimumRendersBeforeCachingFilterLayer = 3; + int render_count_; + FML_DISALLOW_COPY_AND_ASSIGN(ColorFilterLayer); }; diff --git a/engine/src/flutter/flow/layers/color_filter_layer_unittests.cc b/engine/src/flutter/flow/layers/color_filter_layer_unittests.cc index a48ca564096..fe29ceac3a9 100644 --- a/engine/src/flutter/flow/layers/color_filter_layer_unittests.cc +++ b/engine/src/flutter/flow/layers/color_filter_layer_unittests.cc @@ -213,5 +213,70 @@ TEST_F(ColorFilterLayerTest, Readback) { EXPECT_FALSE(preroll_context()->surface_needs_readback); } +TEST_F(ColorFilterLayerTest, ChildIsCached) { + auto layer_filter = + SkColorMatrixFilter::MakeLightingFilter(SK_ColorGREEN, SK_ColorYELLOW); + auto initial_transform = SkMatrix::Translate(50.0, 25.5); + auto other_transform = SkMatrix::Scale(1.0, 2.0); + const SkPath child_path = SkPath().addRect(SkRect::MakeWH(5.0f, 5.0f)); + auto mock_layer = std::make_shared(child_path); + auto layer = std::make_shared(layer_filter); + layer->Add(mock_layer); + + SkMatrix cache_ctm = initial_transform; + SkCanvas cache_canvas; + cache_canvas.setMatrix(cache_ctm); + SkCanvas other_canvas; + other_canvas.setMatrix(other_transform); + + use_mock_raster_cache(); + + EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)0); + EXPECT_FALSE(raster_cache()->Draw(mock_layer.get(), other_canvas)); + EXPECT_FALSE(raster_cache()->Draw(mock_layer.get(), cache_canvas)); + + layer->Preroll(preroll_context(), initial_transform); + + EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)1); + EXPECT_FALSE(raster_cache()->Draw(mock_layer.get(), other_canvas)); + EXPECT_TRUE(raster_cache()->Draw(mock_layer.get(), cache_canvas)); +} + +TEST_F(ColorFilterLayerTest, ChildrenNotCached) { + auto layer_filter = + SkColorMatrixFilter::MakeLightingFilter(SK_ColorGREEN, SK_ColorYELLOW); + auto initial_transform = SkMatrix::Translate(50.0, 25.5); + auto other_transform = SkMatrix::Scale(1.0, 2.0); + const SkPath child_path1 = SkPath().addRect(SkRect::MakeWH(5.0f, 5.0f)); + const SkPath child_path2 = SkPath().addRect(SkRect::MakeWH(5.0f, 5.0f)); + auto mock_layer1 = std::make_shared(child_path1); + auto mock_layer2 = std::make_shared(child_path2); + auto layer = std::make_shared(layer_filter); + layer->Add(mock_layer1); + layer->Add(mock_layer2); + + SkMatrix cache_ctm = initial_transform; + SkCanvas cache_canvas; + cache_canvas.setMatrix(cache_ctm); + SkCanvas other_canvas; + other_canvas.setMatrix(other_transform); + + use_mock_raster_cache(); + + EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)0); + EXPECT_FALSE(raster_cache()->Draw(mock_layer1.get(), other_canvas)); + EXPECT_FALSE(raster_cache()->Draw(mock_layer1.get(), cache_canvas)); + EXPECT_FALSE(raster_cache()->Draw(mock_layer2.get(), other_canvas)); + EXPECT_FALSE(raster_cache()->Draw(mock_layer2.get(), cache_canvas)); + + layer->Preroll(preroll_context(), initial_transform); + + EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)1); + EXPECT_FALSE(raster_cache()->Draw(mock_layer1.get(), other_canvas)); + EXPECT_FALSE(raster_cache()->Draw(mock_layer1.get(), cache_canvas)); + EXPECT_FALSE(raster_cache()->Draw(mock_layer2.get(), other_canvas)); + EXPECT_FALSE(raster_cache()->Draw(mock_layer2.get(), cache_canvas)); +} + } // namespace testing } // namespace flutter