diff --git a/display_list/display_list_image_filter.cc b/display_list/display_list_image_filter.cc index 8d4a98fb89e6a..4e43649a208e0 100644 --- a/display_list/display_list_image_filter.cc +++ b/display_list/display_list_image_filter.cc @@ -28,7 +28,7 @@ std::shared_ptr DlImageFilter::From( } std::shared_ptr DlImageFilter::makeWithLocalMatrix( - const SkMatrix& matrix) { + const SkMatrix& matrix) const { if (matrix.isIdentity()) { return shared(); } diff --git a/display_list/display_list_image_filter.h b/display_list/display_list_image_filter.h index 4a0063b8b48cb..c495c4cf098b2 100644 --- a/display_list/display_list_image_filter.h +++ b/display_list/display_list_image_filter.h @@ -95,7 +95,7 @@ class DlImageFilter } virtual std::shared_ptr makeWithLocalMatrix( - const SkMatrix& matrix); + const SkMatrix& matrix) const; // Return a DlComposeImageFilter pointer to this object iff it is a Compose // type of ImageFilter, otherwise return nullptr. @@ -634,7 +634,7 @@ class DlColorFilterImageFilter final : public DlImageFilter { } std::shared_ptr makeWithLocalMatrix( - const SkMatrix& matrix) override { + const SkMatrix& matrix) const override { return shared(); } @@ -764,7 +764,7 @@ class DlUnknownImageFilter final : public DlImageFilter { SkRect* map_local_bounds(const SkRect& input_bounds, SkRect& output_bounds) const override { - if (modifies_transparent_black()) { + if (!sk_filter_ || modifies_transparent_black()) { output_bounds = input_bounds; return nullptr; } @@ -775,7 +775,7 @@ class DlUnknownImageFilter final : public DlImageFilter { SkIRect* map_device_bounds(const SkIRect& input_bounds, const SkMatrix& ctm, SkIRect& output_bounds) const override { - if (modifies_transparent_black()) { + if (!sk_filter_ || modifies_transparent_black()) { output_bounds = input_bounds; return nullptr; } @@ -787,7 +787,7 @@ class DlUnknownImageFilter final : public DlImageFilter { SkIRect* get_input_device_bounds(const SkIRect& output_bounds, const SkMatrix& ctm, SkIRect& input_bounds) const override { - if (modifies_transparent_black()) { + if (!sk_filter_ || modifies_transparent_black()) { input_bounds = output_bounds; return nullptr; } diff --git a/flow/layers/image_filter_layer.cc b/flow/layers/image_filter_layer.cc index 4793bfd8f0d03..addccef60d533 100644 --- a/flow/layers/image_filter_layer.cc +++ b/flow/layers/image_filter_layer.cc @@ -3,12 +3,13 @@ // found in the LICENSE file. #include "flutter/flow/layers/image_filter_layer.h" +#include "flutter/display_list/display_list_comparable.h" #include "flutter/flow/layers/layer.h" #include "flutter/flow/raster_cache_util.h" namespace flutter { -ImageFilterLayer::ImageFilterLayer(sk_sp filter) +ImageFilterLayer::ImageFilterLayer(std::shared_ptr filter) : CacheableContainerLayer( RasterCacheUtil::kMinimumRendersBeforeCachingFilterLayer), filter_(std::move(filter)), @@ -19,7 +20,7 @@ void ImageFilterLayer::Diff(DiffContext* context, const Layer* old_layer) { auto* prev = static_cast(old_layer); if (!context->IsSubtreeDirty()) { FML_DCHECK(prev); - if (filter_ != prev->filter_) { + if (NotEquals(filter_, prev->filter_)) { context->MarkSubtreeDirty(context->GetOldLayerPaintRegion(old_layer)); } } @@ -29,9 +30,10 @@ void ImageFilterLayer::Diff(DiffContext* context, const Layer* old_layer) { if (filter) { // This transform will be applied to every child rect in the subtree context->PushFilterBoundsAdjustment([filter](SkRect rect) { - return SkRect::Make( - filter->filterBounds(rect.roundOut(), SkMatrix::I(), - SkImageFilter::kForward_MapDirection)); + SkIRect filter_out_bounds; + filter->map_device_bounds(rect.roundOut(), SkMatrix::I(), + filter_out_bounds); + return SkRect::Make(filter_out_bounds); }); } } @@ -50,7 +52,6 @@ void ImageFilterLayer::Preroll(PrerollContext* context, SkRect child_bounds = SkRect::MakeEmpty(); PrerollChildren(context, matrix, &child_bounds); - context->subtree_can_inherit_opacity = true; // We always paint with a saveLayer (or a cached rendering), // so we can always apply opacity in any of those cases. @@ -61,10 +62,11 @@ void ImageFilterLayer::Preroll(PrerollContext* context, return; } - const SkIRect filter_input_bounds = child_bounds.roundOut(); - SkIRect filter_output_bounds = filter_->filterBounds( - filter_input_bounds, SkMatrix::I(), SkImageFilter::kForward_MapDirection); - child_bounds = SkRect::Make(filter_output_bounds); + const SkIRect filter_in_bounds = child_bounds.roundOut(); + SkIRect filter_out_bounds; + filter_->map_device_bounds(filter_in_bounds, SkMatrix::I(), + filter_out_bounds); + child_bounds = SkRect::Make(filter_out_bounds); set_paint_bounds(child_bounds); @@ -83,23 +85,31 @@ void ImageFilterLayer::Paint(PaintContext& context) const { FML_DCHECK(needs_painting(context)); AutoCachePaint cache_paint(context); - - if (layer_raster_cache_item_->IsCacheChildren()) { - cache_paint.setImageFilter(transformed_filter_); - } - if (layer_raster_cache_item_->Draw(context, cache_paint.sk_paint())) { - return; + if (context.raster_cache) { + if (layer_raster_cache_item_->IsCacheChildren()) { + cache_paint.setImageFilter(transformed_filter_.get()); + } + if (layer_raster_cache_item_->Draw(context, cache_paint.sk_paint())) { + return; + } } - cache_paint.setImageFilter(filter_); - - // Normally a save_layer is sized to the current layer bounds, but in this - // case the bounds of the child may not be the same as the filtered version - // so we use the bounds of the child container which do not include any - // modifications that the filter might apply. - Layer::AutoSaveLayer save_layer = Layer::AutoSaveLayer::Create( - context, child_paint_bounds(), cache_paint.sk_paint()); - PaintChildren(context); + cache_paint.setImageFilter(filter_.get()); + if (context.leaf_nodes_builder) { + FML_DCHECK(context.builder_multiplexer); + context.builder_multiplexer->saveLayer(&child_paint_bounds(), + cache_paint.dl_paint()); + PaintChildren(context); + context.builder_multiplexer->restore(); + } else { + // Normally a save_layer is sized to the current layer bounds, but in this + // case the bounds of the child may not be the same as the filtered version + // so we use the bounds of the child container which do not include any + // modifications that the filter might apply. + Layer::AutoSaveLayer save_layer = Layer::AutoSaveLayer::Create( + context, child_paint_bounds(), cache_paint.sk_paint()); + PaintChildren(context); + } } } // namespace flutter diff --git a/flow/layers/image_filter_layer.h b/flow/layers/image_filter_layer.h index bb2f3a6d60335..e4987bd9fb75b 100644 --- a/flow/layers/image_filter_layer.h +++ b/flow/layers/image_filter_layer.h @@ -5,15 +5,17 @@ #ifndef FLUTTER_FLOW_LAYERS_IMAGE_FILTER_LAYER_H_ #define FLUTTER_FLOW_LAYERS_IMAGE_FILTER_LAYER_H_ +#include #include "flutter/flow/layers/cacheable_layer.h" #include "flutter/flow/layers/layer.h" +#include "include/core/SkRefCnt.h" #include "third_party/skia/include/core/SkImageFilter.h" namespace flutter { class ImageFilterLayer : public CacheableContainerLayer { public: - explicit ImageFilterLayer(sk_sp filter); + explicit ImageFilterLayer(std::shared_ptr filter); void Diff(DiffContext* context, const Layer* old_layer) override; @@ -22,8 +24,8 @@ class ImageFilterLayer : public CacheableContainerLayer { void Paint(PaintContext& context) const override; private: - sk_sp filter_; - sk_sp transformed_filter_; + std::shared_ptr filter_; + std::shared_ptr transformed_filter_; FML_DISALLOW_COPY_AND_ASSIGN(ImageFilterLayer); }; diff --git a/flow/layers/image_filter_layer_unittests.cc b/flow/layers/image_filter_layer_unittests.cc index 546331452a9fa..2ad4a7e3e86d6 100644 --- a/flow/layers/image_filter_layer_unittests.cc +++ b/flow/layers/image_filter_layer_unittests.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "flutter/display_list/display_list_tile_mode.h" #include "flutter/flow/layers/image_filter_layer.h" #include "flutter/flow/layers/layer_tree.h" @@ -23,7 +24,7 @@ using ImageFilterLayerTest = LayerTest; #ifndef NDEBUG TEST_F(ImageFilterLayerTest, PaintingEmptyLayerDies) { - auto layer = std::make_shared(sk_sp()); + auto layer = std::make_shared(nullptr); layer->Preroll(preroll_context(), SkMatrix()); EXPECT_EQ(layer->paint_bounds(), kEmptyRect); @@ -37,7 +38,7 @@ TEST_F(ImageFilterLayerTest, PaintBeforePrerollDies) { const SkRect child_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f); const SkPath child_path = SkPath().addRect(child_bounds); auto mock_layer = std::make_shared(child_path); - auto layer = std::make_shared(sk_sp()); + auto layer = std::make_shared(nullptr); layer->Add(mock_layer); EXPECT_EQ(layer->paint_bounds(), kEmptyRect); @@ -81,11 +82,10 @@ TEST_F(ImageFilterLayerTest, SimpleFilter) { const SkRect child_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f); const SkPath child_path = SkPath().addRect(child_bounds); const SkPaint child_paint = SkPaint(SkColors::kYellow); - auto layer_filter = SkImageFilters::MatrixTransform( - SkMatrix(), - SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear), nullptr); + auto dl_image_filter = std::make_shared( + SkMatrix(), DlImageSampling::kMipmapLinear); auto mock_layer = std::make_shared(child_path, child_paint); - auto layer = std::make_shared(layer_filter); + auto layer = std::make_shared(dl_image_filter); layer->Add(mock_layer); const SkRect child_rounded_bounds = @@ -97,18 +97,23 @@ TEST_F(ImageFilterLayerTest, SimpleFilter) { EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_matrix(), initial_transform); - SkPaint filter_paint; - filter_paint.setImageFilter(layer_filter); - layer->Paint(paint_context()); - EXPECT_EQ(mock_canvas().draw_calls(), - std::vector({ - MockCanvas::DrawCall{ - 0, MockCanvas::SaveLayerData{child_bounds, filter_paint, - nullptr, 1}}, - MockCanvas::DrawCall{ - 1, MockCanvas::DrawPathData{child_path, child_paint}}, - MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}, - })); + DisplayListBuilder expected_builder; + /* ImageFilterLayer::Paint() */ { + DlPaint dl_paint; + dl_paint.setImageFilter(dl_image_filter.get()); + expected_builder.saveLayer(&child_bounds, &dl_paint); + { + /* MockLayer::Paint() */ { + expected_builder.drawPath(child_path, + DlPaint().setColor(DlColor::kYellow())); + } + } + } + expected_builder.restore(); + auto expected_display_list = expected_builder.Build(); + + layer->Paint(display_list_paint_context()); + EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_display_list)); } TEST_F(ImageFilterLayerTest, SimpleFilterBounds) { @@ -117,11 +122,11 @@ TEST_F(ImageFilterLayerTest, SimpleFilterBounds) { const SkPath child_path = SkPath().addRect(child_bounds); const SkPaint child_paint = SkPaint(SkColors::kYellow); const SkMatrix filter_transform = SkMatrix::Scale(2.0, 2.0); - auto layer_filter = SkImageFilters::MatrixTransform( - filter_transform, - SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear), nullptr); + + auto dl_image_filter = std::make_shared( + filter_transform, DlImageSampling::kMipmapLinear); auto mock_layer = std::make_shared(child_path, child_paint); - auto layer = std::make_shared(layer_filter); + auto layer = std::make_shared(dl_image_filter); layer->Add(mock_layer); const SkRect filter_bounds = SkRect::MakeLTRB(10.0f, 12.0f, 42.0f, 44.0f); @@ -132,18 +137,23 @@ TEST_F(ImageFilterLayerTest, SimpleFilterBounds) { EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_matrix(), initial_transform); - SkPaint filter_paint; - filter_paint.setImageFilter(layer_filter); - layer->Paint(paint_context()); - EXPECT_EQ(mock_canvas().draw_calls(), - std::vector({ - MockCanvas::DrawCall{ - 0, MockCanvas::SaveLayerData{child_bounds, filter_paint, - nullptr, 1}}, - MockCanvas::DrawCall{ - 1, MockCanvas::DrawPathData{child_path, child_paint}}, - MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}, - })); + DisplayListBuilder expected_builder; + /* ImageFilterLayer::Paint() */ { + DlPaint dl_paint; + dl_paint.setImageFilter(dl_image_filter.get()); + expected_builder.saveLayer(&child_bounds, &dl_paint); + { + /* MockLayer::Paint() */ { + expected_builder.drawPath(child_path, + DlPaint().setColor(DlColor::kYellow())); + } + } + } + expected_builder.restore(); + auto expected_display_list = expected_builder.Build(); + + layer->Paint(display_list_paint_context()); + EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_display_list)); } TEST_F(ImageFilterLayerTest, MultipleChildren) { @@ -154,12 +164,11 @@ TEST_F(ImageFilterLayerTest, MultipleChildren) { SkPath().addRect(child_bounds.makeOffset(3.0f, 0.0f)); const SkPaint child_paint1 = SkPaint(SkColors::kYellow); const SkPaint child_paint2 = SkPaint(SkColors::kCyan); - auto layer_filter = SkImageFilters::MatrixTransform( - SkMatrix(), - SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear), nullptr); + auto dl_image_filter = std::make_shared( + SkMatrix(), DlImageSampling::kMipmapLinear); auto mock_layer1 = std::make_shared(child_path1, child_paint1); auto mock_layer2 = std::make_shared(child_path2, child_paint2); - auto layer = std::make_shared(layer_filter); + auto layer = std::make_shared(dl_image_filter); layer->Add(mock_layer1); layer->Add(mock_layer2); @@ -178,19 +187,27 @@ TEST_F(ImageFilterLayerTest, MultipleChildren) { EXPECT_EQ(mock_layer1->parent_matrix(), initial_transform); EXPECT_EQ(mock_layer2->parent_matrix(), initial_transform); - SkPaint filter_paint; - filter_paint.setImageFilter(layer_filter); - layer->Paint(paint_context()); - EXPECT_EQ( - mock_canvas().draw_calls(), - std::vector({MockCanvas::DrawCall{ - 0, MockCanvas::SaveLayerData{children_bounds, - filter_paint, nullptr, 1}}, - MockCanvas::DrawCall{ - 1, MockCanvas::DrawPathData{child_path1, child_paint1}}, - MockCanvas::DrawCall{ - 1, MockCanvas::DrawPathData{child_path2, child_paint2}}, - MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}})); + DisplayListBuilder expected_builder; + /* ImageFilterLayer::Paint() */ { + DlPaint dl_paint; + dl_paint.setImageFilter(dl_image_filter.get()); + expected_builder.saveLayer(&children_bounds, &dl_paint); + { + /* MockLayer::Paint() */ { + expected_builder.drawPath(child_path1, + DlPaint().setColor(DlColor::kYellow())); + } + /* MockLayer::Paint() */ { + expected_builder.drawPath(child_path2, + DlPaint().setColor(DlColor::kCyan())); + } + } + } + expected_builder.restore(); + auto expected_display_list = expected_builder.Build(); + + layer->Paint(display_list_paint_context()); + EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_display_list)); } TEST_F(ImageFilterLayerTest, Nested) { @@ -201,16 +218,14 @@ TEST_F(ImageFilterLayerTest, Nested) { SkPath().addRect(child_bounds.makeOffset(3.0f, 0.0f)); const SkPaint child_paint1 = SkPaint(SkColors::kYellow); const SkPaint child_paint2 = SkPaint(SkColors::kCyan); - auto layer_filter1 = SkImageFilters::MatrixTransform( - SkMatrix(), - SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear), nullptr); - auto layer_filter2 = SkImageFilters::MatrixTransform( - SkMatrix(), - SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear), nullptr); + auto dl_image_filter1 = std::make_shared( + SkMatrix(), DlImageSampling::kMipmapLinear); + auto dl_image_filter2 = std::make_shared( + SkMatrix(), DlImageSampling::kMipmapLinear); auto mock_layer1 = std::make_shared(child_path1, child_paint1); auto mock_layer2 = std::make_shared(child_path2, child_paint2); - auto layer1 = std::make_shared(layer_filter1); - auto layer2 = std::make_shared(layer_filter2); + auto layer1 = std::make_shared(dl_image_filter1); + auto layer2 = std::make_shared(dl_image_filter2); layer2->Add(mock_layer2); layer1->Add(mock_layer1); layer1->Add(layer2); @@ -236,35 +251,43 @@ TEST_F(ImageFilterLayerTest, Nested) { EXPECT_EQ(mock_layer1->parent_matrix(), initial_transform); EXPECT_EQ(mock_layer2->parent_matrix(), initial_transform); - SkPaint filter_paint1, filter_paint2; - filter_paint1.setImageFilter(layer_filter1); - filter_paint2.setImageFilter(layer_filter2); - layer1->Paint(paint_context()); - EXPECT_EQ(mock_canvas().draw_calls(), - std::vector({ - MockCanvas::DrawCall{ - 0, MockCanvas::SaveLayerData{children_bounds, filter_paint1, - nullptr, 1}}, - MockCanvas::DrawCall{ - 1, MockCanvas::DrawPathData{child_path1, child_paint1}}, - MockCanvas::DrawCall{ - 1, MockCanvas::SaveLayerData{child_path2.getBounds(), - filter_paint2, nullptr, 2}}, - MockCanvas::DrawCall{ - 2, MockCanvas::DrawPathData{child_path2, child_paint2}}, - MockCanvas::DrawCall{2, MockCanvas::RestoreData{1}}, - MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}, - })); + DisplayListBuilder expected_builder; + /* ImageFilterLayer::Paint() */ { + DlPaint dl_paint; + dl_paint.setImageFilter(dl_image_filter1.get()); + expected_builder.saveLayer(&children_bounds, &dl_paint); + { + /* MockLayer::Paint() */ { + expected_builder.drawPath(child_path1, + DlPaint().setColor(DlColor::kYellow())); + } + /* ImageFilterLayer::Paint() */ { + DlPaint child_paint; + child_paint.setImageFilter(dl_image_filter2.get()); + expected_builder.saveLayer(&child_path2.getBounds(), &child_paint); + /* MockLayer::Paint() */ { + expected_builder.drawPath(child_path2, + DlPaint().setColor(DlColor::kCyan())); + } + expected_builder.restore(); + } + } + } + expected_builder.restore(); + auto expected_display_list = expected_builder.Build(); + + layer1->Paint(display_list_paint_context()); + EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_display_list)); } TEST_F(ImageFilterLayerTest, Readback) { - auto layer_filter = SkImageFilters::MatrixTransform( - SkMatrix(), - SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear), nullptr); + auto dl_image_filter = std::make_shared( + SkMatrix(), DlImageSampling::kLinear); + auto initial_transform = SkMatrix(); // ImageFilterLayer does not read from surface - auto layer = std::make_shared(layer_filter); + auto layer = std::make_shared(dl_image_filter); preroll_context()->surface_needs_readback = false; layer->Preroll(preroll_context(), initial_transform); EXPECT_FALSE(preroll_context()->surface_needs_readback); @@ -279,14 +302,13 @@ TEST_F(ImageFilterLayerTest, Readback) { } TEST_F(ImageFilterLayerTest, CacheChild) { - auto layer_filter = SkImageFilters::MatrixTransform( - SkMatrix(), - SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear), nullptr); + auto dl_image_filter = std::make_shared( + SkMatrix(), DlImageSampling::kMipmapLinear); 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); + auto layer = std::make_shared(dl_image_filter); layer->Add(mock_layer); SkMatrix cache_ctm = initial_transform; @@ -320,9 +342,8 @@ TEST_F(ImageFilterLayerTest, CacheChild) { } TEST_F(ImageFilterLayerTest, CacheChildren) { - auto layer_filter = SkImageFilters::MatrixTransform( - SkMatrix(), - SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear), nullptr); + auto dl_image_filter = std::make_shared( + SkMatrix(), DlImageSampling::kMipmapLinear); auto initial_transform = SkMatrix::Translate(50.0, 25.5); auto other_transform = SkMatrix::Scale(1.0, 2.0); SkPaint paint = SkPaint(); @@ -330,7 +351,7 @@ TEST_F(ImageFilterLayerTest, CacheChildren) { 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); + auto layer = std::make_shared(dl_image_filter); layer->Add(mock_layer1); layer->Add(mock_layer2); @@ -366,14 +387,14 @@ TEST_F(ImageFilterLayerTest, CacheChildren) { } TEST_F(ImageFilterLayerTest, CacheImageFilterLayerSelf) { - auto layer_filter = SkImageFilters::MatrixTransform( - SkMatrix(), - SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear), nullptr); + auto dl_image_filter = std::make_shared( + SkMatrix(), DlImageSampling::kMipmapLinear); + 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); + auto layer = std::make_shared(dl_image_filter); layer->Add(mock_layer); SkMatrix cache_ctm = initial_transform; @@ -416,12 +437,12 @@ TEST_F(ImageFilterLayerTest, OpacityInheritance) { const SkRect child_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f); const SkPath child_path = SkPath().addRect(child_bounds); const SkPaint child_paint = SkPaint(SkColors::kYellow); - auto layer_filter = SkImageFilters::MatrixTransform( - SkMatrix(), - SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear), nullptr); + auto dl_image_filter = std::make_shared( + SkMatrix(), DlImageSampling::kMipmapLinear); + // The mock_layer child will not be compatible with opacity auto mock_layer = MockLayer::Make(child_path, child_paint); - auto image_filter_layer = std::make_shared(layer_filter); + auto image_filter_layer = std::make_shared(dl_image_filter); image_filter_layer->Add(mock_layer); PrerollContext* context = preroll_context(); @@ -439,20 +460,20 @@ TEST_F(ImageFilterLayerTest, OpacityInheritance) { opacity_layer->Preroll(context, SkMatrix::I()); EXPECT_TRUE(opacity_layer->children_can_accept_opacity()); - auto dl_image_filter = DlImageFilter::From(layer_filter); DisplayListBuilder expected_builder; /* OpacityLayer::Paint() */ { expected_builder.save(); { expected_builder.translate(offset.fX, offset.fY); /* ImageFilterLayer::Paint() */ { - expected_builder.setColor(opacity_alpha << 24); - expected_builder.setImageFilter(dl_image_filter.get()); - expected_builder.saveLayer(&child_path.getBounds(), true); + DlPaint image_filter_paint; + image_filter_paint.setColor(opacity_alpha << 24); + image_filter_paint.setImageFilter(dl_image_filter.get()); + expected_builder.saveLayer(&child_path.getBounds(), + &image_filter_paint); /* MockLayer::Paint() */ { - expected_builder.setColor(child_paint.getColor()); - expected_builder.setImageFilter(nullptr); - expected_builder.drawPath(child_path); + expected_builder.drawPath(child_path, + DlPaint().setColor(child_paint.getColor())); } expected_builder.restore(); } @@ -467,18 +488,18 @@ TEST_F(ImageFilterLayerTest, OpacityInheritance) { using ImageFilterLayerDiffTest = DiffContextTest; TEST_F(ImageFilterLayerDiffTest, ImageFilterLayer) { - auto filter = SkImageFilters::Blur(10, 10, SkTileMode::kClamp, nullptr); - + auto dl_blur_filter = + std::make_shared(10, 10, DlTileMode::kClamp); { // tests later assume 30px paint area, fail early if that's not the case - auto paint_rect = - filter->filterBounds(SkIRect::MakeWH(10, 10), SkMatrix::I(), - SkImageFilter::kForward_MapDirection); - EXPECT_EQ(paint_rect, SkIRect::MakeLTRB(-30, -30, 40, 40)); + SkIRect input_bounds; + dl_blur_filter->get_input_device_bounds(SkIRect::MakeWH(10, 10), + SkMatrix::I(), input_bounds); + EXPECT_EQ(input_bounds, SkIRect::MakeLTRB(-30, -30, 40, 40)); } MockLayerTree l1; - auto filter_layer = std::make_shared(filter); + auto filter_layer = std::make_shared(dl_blur_filter); auto path = SkPath().addRect(SkRect::MakeLTRB(100, 100, 110, 110)); filter_layer->Add(std::make_shared(path)); l1.root()->Add(filter_layer); @@ -514,21 +535,22 @@ TEST_F(ImageFilterLayerDiffTest, ImageFilterLayer) { } TEST_F(ImageFilterLayerDiffTest, ImageFilterLayerInflatestChildSize) { - auto filter = SkImageFilters::Blur(10, 10, SkTileMode::kClamp, nullptr); + auto dl_blur_filter = + std::make_shared(10, 10, DlTileMode::kClamp); { // tests later assume 30px paint area, fail early if that's not the case - auto paint_rect = - filter->filterBounds(SkIRect::MakeWH(10, 10), SkMatrix::I(), - SkImageFilter::kForward_MapDirection); - EXPECT_EQ(paint_rect, SkIRect::MakeLTRB(-30, -30, 40, 40)); + SkIRect input_bounds; + dl_blur_filter->get_input_device_bounds(SkIRect::MakeWH(10, 10), + SkMatrix::I(), input_bounds); + EXPECT_EQ(input_bounds, SkIRect::MakeLTRB(-30, -30, 40, 40)); } MockLayerTree l1; // Use nested filter layers to check if both contribute to child bounds - auto filter_layer_1_1 = std::make_shared(filter); - auto filter_layer_1_2 = std::make_shared(filter); + auto filter_layer_1_1 = std::make_shared(dl_blur_filter); + auto filter_layer_1_2 = std::make_shared(dl_blur_filter); filter_layer_1_1->Add(filter_layer_1_2); auto path = SkPath().addRect(SkRect::MakeLTRB(100, 100, 110, 110)); filter_layer_1_2->Add( @@ -537,9 +559,9 @@ TEST_F(ImageFilterLayerDiffTest, ImageFilterLayerInflatestChildSize) { // second layer tree with identical filter layers but different child layer MockLayerTree l2; - auto filter_layer2_1 = std::make_shared(filter); + auto filter_layer2_1 = std::make_shared(dl_blur_filter); filter_layer2_1->AssignOldLayer(filter_layer_1_1.get()); - auto filter_layer2_2 = std::make_shared(filter); + auto filter_layer2_2 = std::make_shared(dl_blur_filter); filter_layer2_2->AssignOldLayer(filter_layer_1_2.get()); filter_layer2_1->Add(filter_layer2_2); filter_layer2_2->Add( diff --git a/flow/layers/layer.h b/flow/layers/layer.h index 17d5dc92ac0a3..bb57b430fa3b0 100644 --- a/flow/layers/layer.h +++ b/flow/layers/layer.h @@ -227,16 +227,14 @@ class Layer { ~AutoCachePaint() { context_.inherited_opacity = sk_paint_.getAlphaf(); } - void setImageFilter(sk_sp filter) { - sk_paint_.setImageFilter(filter); - dl_paint_.setImageFilter(DlImageFilter::From(filter)); + void setImageFilter(const DlImageFilter* filter) { + sk_paint_.setImageFilter(!filter ? nullptr : filter->skia_object()); + dl_paint_.setImageFilter(filter); update_needs_paint(); } void setColorFilter(const DlColorFilter* filter) { - if (!filter) - return; - sk_paint_.setColorFilter(filter->skia_object()); + sk_paint_.setColorFilter(!filter ? nullptr : filter->skia_object()); dl_paint_.setColorFilter(filter); update_needs_paint(); } diff --git a/flow/layers/opacity_layer_unittests.cc b/flow/layers/opacity_layer_unittests.cc index c662e73284ec4..6844b9bc50682 100644 --- a/flow/layers/opacity_layer_unittests.cc +++ b/flow/layers/opacity_layer_unittests.cc @@ -523,7 +523,7 @@ TEST_F(OpacityLayerTest, OpacityInheritanceThroughImageFilter) { auto opacityLayer = std::make_shared(128, SkPoint::Make(20, 20)); auto filterLayer = std::make_shared( - SkImageFilters::Blur(5.0, 5.0, nullptr)); + std::make_shared(5.0, 5.0, DlTileMode::kClamp)); auto mockLayer = MockLayer::MakeOpacityCompatible(SkPath()); filterLayer->Add(mockLayer); opacityLayer->Add(filterLayer); diff --git a/lib/ui/compositing/scene_builder.cc b/lib/ui/compositing/scene_builder.cc index 74859e2b8df4b..3967c20088d9b 100644 --- a/lib/ui/compositing/scene_builder.cc +++ b/lib/ui/compositing/scene_builder.cc @@ -152,8 +152,8 @@ void SceneBuilder::pushColorFilter(Dart_Handle layer_handle, void SceneBuilder::pushImageFilter(Dart_Handle layer_handle, const ImageFilter* image_filter, fml::RefPtr oldLayer) { - auto layer = std::make_shared( - image_filter->filter()->skia_object()); + auto layer = + std::make_shared(image_filter->filter()); PushLayer(layer); EngineLayer::MakeRetained(layer_handle, layer);