[Impeller] Turn off Aiks bounds tracking for filtered SaveLayers. (flutter/engine#49076)

We use this bounds rect for querying the DisplayList rtree when culling.
But when sub-DisplayLists are being dispatched, the DisplayList's rtree
is local and doesn't incorporate parent layer filters. So
sub-DisplayLists are getting culled as if no filters are being applied.

Technically our local bounds tracking in Aiks is actually correct here,
but this is a quick fix to alleviate the problem. I don't know what the
best longterm solution for this is.
This commit is contained in:
Brandon DeRosier 2023-12-15 13:34:37 -08:00 committed by GitHub
parent 46564e6588
commit 96e13e165f
2 changed files with 26 additions and 0 deletions

View File

@ -681,6 +681,14 @@ void Canvas::SaveLayer(const Paint& paint,
TRACE_EVENT0("flutter", "Canvas::saveLayer");
Save(true, paint.blend_mode, backdrop_filter);
// The DisplayList bounds/rtree doesn't account for filters applied to parent
// layers, and so sub-DisplayLists are getting culled as if no filters are
// applied.
// See also: https://github.com/flutter/flutter/issues/139294
if (paint.image_filter) {
transform_stack_.back().cull_rect = std::nullopt;
}
auto& new_layer_pass = GetCurrentPass();
new_layer_pass.SetBoundsLimit(bounds);

View File

@ -4,6 +4,7 @@
#include "flutter/testing/testing.h"
#include "impeller/aiks/canvas.h"
#include "impeller/aiks/image_filter.h"
#include "impeller/geometry/path_builder.h"
// TODO(zanderso): https://github.com/flutter/flutter/issues/127701
@ -336,6 +337,23 @@ TEST(AiksCanvasTest, PathClipDiffAgainstFullyCoveredCullRect) {
ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
}
TEST(AiksCanvasTest, DisableLocalBoundsRectForFilteredSaveLayers) {
Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
Canvas canvas(initial_cull);
ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
canvas.Save();
canvas.SaveLayer(
Paint{.image_filter = ImageFilter::MakeBlur(
Sigma(10), Sigma(10), FilterContents::BlurStyle::kNormal,
Entity::TileMode::kDecal)});
ASSERT_FALSE(canvas.GetCurrentLocalCullingBounds().has_value());
canvas.Restore();
ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
}
} // namespace testing
} // namespace impeller