[Impeller] Fix the transform and geometry criteria for an optimization in TiledTextureContents (flutter/engine#47341)

TiledTextureContents::RenderToSnapshot should only create a snapshot directly from the texture if the geometry is an axis-aligned rectangle.

Fixes https://github.com/flutter/flutter/issues/136504
This commit is contained in:
Jason Simmons 2023-10-26 13:08:21 -07:00 committed by GitHub
parent 5316d75378
commit 6ef260d4b5
6 changed files with 73 additions and 2 deletions

View File

@ -3781,5 +3781,55 @@ TEST_P(AiksTest, EmptySaveLayerRendersWithClear) {
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
TEST_P(AiksTest, BlurredRectangleWithShader) {
Canvas canvas;
canvas.Scale(GetContentScale());
auto paint_lines = [&canvas](Scalar dx, Scalar dy, Paint paint) {
auto draw_line = [&canvas, &paint](Point a, Point b) {
canvas.DrawPath(PathBuilder{}.AddLine(a, b).TakePath(), paint);
};
paint.stroke_width = 5;
paint.style = Paint::Style::kStroke;
draw_line(Point(dx + 100, dy + 100), Point(dx + 200, dy + 200));
draw_line(Point(dx + 100, dy + 200), Point(dx + 200, dy + 100));
draw_line(Point(dx + 150, dy + 100), Point(dx + 200, dy + 150));
draw_line(Point(dx + 100, dy + 150), Point(dx + 150, dy + 200));
};
AiksContext renderer(GetContext(), nullptr);
Canvas recorder_canvas;
for (int x = 0; x < 5; ++x) {
for (int y = 0; y < 5; ++y) {
Rect rect = Rect::MakeXYWH(x * 20, y * 20, 20, 20);
Paint paint{.color =
((x + y) & 1) == 0 ? Color::Yellow() : Color::Blue()};
recorder_canvas.DrawRect(rect, paint);
}
}
Picture picture = recorder_canvas.EndRecordingAsPicture();
std::shared_ptr<Texture> texture =
picture.ToImage(renderer, ISize{100, 100})->GetTexture();
ColorSource image_source = ColorSource::MakeImage(
texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {}, {});
std::shared_ptr<ImageFilter> blur_filter = ImageFilter::MakeBlur(
Sigma(5), Sigma(5), FilterContents::BlurStyle::kNormal,
Entity::TileMode::kDecal);
canvas.DrawRect(Rect::MakeLTRB(0, 0, 300, 600),
Paint{.color = Color::DarkGreen()});
canvas.DrawRect(Rect::MakeLTRB(100, 100, 200, 200),
Paint{.color_source = image_source});
canvas.DrawRect(Rect::MakeLTRB(300, 0, 600, 600),
Paint{.color = Color::Red()});
canvas.DrawRect(
Rect::MakeLTRB(400, 100, 500, 200),
Paint{.color_source = image_source, .image_filter = blur_filter});
paint_lines(0, 300, Paint{.color_source = image_source});
paint_lines(300, 300,
Paint{.color_source = image_source, .image_filter = blur_filter});
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
} // namespace testing
} // namespace impeller

View File

@ -202,10 +202,18 @@ std::optional<Snapshot> TiledTextureContents::RenderToSnapshot(
const std::optional<SamplerDescriptor>& sampler_descriptor,
bool msaa_enabled,
const std::string& label) const {
if (GetInverseEffectTransform().IsIdentity()) {
if (GetInverseEffectTransform().IsIdentity() &&
GetGeometry()->IsAxisAlignedRect()) {
auto coverage = GetCoverage(entity);
if (!coverage.has_value()) {
return std::nullopt;
}
auto scale = Vector2(coverage->size / Size(texture_->GetSize()));
return Snapshot{
.texture = texture_,
.transform = entity.GetTransformation(),
.transform = Matrix::MakeTranslation(coverage->origin) *
Matrix::MakeScale(scale),
.sampler_descriptor = sampler_descriptor.value_or(sampler_descriptor_),
.opacity = GetOpacityFactor(),
};

View File

@ -147,4 +147,8 @@ bool Geometry::CoversArea(const Matrix& transform, const Rect& rect) const {
return false;
}
bool Geometry::IsAxisAlignedRect() const {
return false;
}
} // namespace impeller

View File

@ -101,6 +101,8 @@ class Geometry {
/// given `rect`. May return `false` in many undetected cases where
/// the transformed geometry does in fact cover the `rect`.
virtual bool CoversArea(const Matrix& transform, const Rect& rect) const;
virtual bool IsAxisAlignedRect() const;
};
} // namespace impeller

View File

@ -55,4 +55,8 @@ bool RectGeometry::CoversArea(const Matrix& transform, const Rect& rect) const {
return coverage.Contains(rect);
}
bool RectGeometry::IsAxisAlignedRect() const {
return true;
}
} // namespace impeller

View File

@ -17,6 +17,9 @@ class RectGeometry : public Geometry {
// |Geometry|
bool CoversArea(const Matrix& transform, const Rect& rect) const override;
// |Geometry|
bool IsAxisAlignedRect() const override;
private:
// |Geometry|
GeometryResult GetPositionBuffer(const ContentContext& renderer,