[Impeller] remove framebuffer blending from atlas, fix transform scale (#42254)
Fixes https://github.com/flutter/flutter/issues/127374
diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc
index eeecc60..f29d0bd 100644
--- a/impeller/aiks/aiks_unittests.cc
+++ b/impeller/aiks/aiks_unittests.cc
@@ -2373,6 +2373,70 @@
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
+// Regression test for https://github.com/flutter/flutter/issues/127374.
+TEST_P(AiksTest, DrawAtlasWithColorAdvancedAndTransform) {
+ // Draws the image as four squares stiched together.
+ auto atlas = CreateTextureForFixture("bay_bridge.jpg");
+ auto size = atlas->GetSize();
+ auto image = std::make_shared<Image>(atlas);
+ // Divide image into four quadrants.
+ Scalar half_width = size.width / 2;
+ Scalar half_height = size.height / 2;
+ std::vector<Rect> texture_coordinates = {
+ Rect::MakeLTRB(0, 0, half_width, half_height),
+ Rect::MakeLTRB(half_width, 0, size.width, half_height),
+ Rect::MakeLTRB(0, half_height, half_width, size.height),
+ Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
+ // Position quadrants adjacent to eachother.
+ std::vector<Matrix> transforms = {
+ Matrix::MakeTranslation({0, 0, 0}),
+ Matrix::MakeTranslation({half_width, 0, 0}),
+ Matrix::MakeTranslation({0, half_height, 0}),
+ Matrix::MakeTranslation({half_width, half_height, 0})};
+ std::vector<Color> colors = {Color::Red(), Color::Green(), Color::Blue(),
+ Color::Yellow()};
+
+ Paint paint;
+
+ Canvas canvas;
+ canvas.Scale({0.25, 0.25, 1.0});
+ canvas.DrawAtlas(image, transforms, texture_coordinates, colors,
+ BlendMode::kModulate, {}, std::nullopt, paint);
+
+ ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
+}
+
+// Regression test for https://github.com/flutter/flutter/issues/127374.
+TEST_P(AiksTest, DrawAtlasAdvancedAndTransform) {
+ // Draws the image as four squares stiched together.
+ auto atlas = CreateTextureForFixture("bay_bridge.jpg");
+ auto size = atlas->GetSize();
+ auto image = std::make_shared<Image>(atlas);
+ // Divide image into four quadrants.
+ Scalar half_width = size.width / 2;
+ Scalar half_height = size.height / 2;
+ std::vector<Rect> texture_coordinates = {
+ Rect::MakeLTRB(0, 0, half_width, half_height),
+ Rect::MakeLTRB(half_width, 0, size.width, half_height),
+ Rect::MakeLTRB(0, half_height, half_width, size.height),
+ Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
+ // Position quadrants adjacent to eachother.
+ std::vector<Matrix> transforms = {
+ Matrix::MakeTranslation({0, 0, 0}),
+ Matrix::MakeTranslation({half_width, 0, 0}),
+ Matrix::MakeTranslation({0, half_height, 0}),
+ Matrix::MakeTranslation({half_width, half_height, 0})};
+
+ Paint paint;
+
+ Canvas canvas;
+ canvas.Scale({0.25, 0.25, 1.0});
+ canvas.DrawAtlas(image, transforms, texture_coordinates, {},
+ BlendMode::kModulate, {}, std::nullopt, paint);
+
+ ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
+}
+
TEST_P(AiksTest, CanDrawPointsWithTextureMap) {
auto texture = CreateTextureForFixture("table_mountain_nx.png",
/*enable_mipmapping=*/true);
diff --git a/impeller/entity/contents/atlas_contents.cc b/impeller/entity/contents/atlas_contents.cc
index a3a85ca..930012b 100644
--- a/impeller/entity/contents/atlas_contents.cc
+++ b/impeller/entity/contents/atlas_contents.cc
@@ -221,50 +221,25 @@
dst_contents->SetSubAtlas(sub_atlas);
dst_contents->SetCoverage(sub_coverage);
- std::shared_ptr<Texture> new_texture;
- if (renderer.GetDeviceCapabilities().SupportsFramebufferFetch()) {
- new_texture = renderer.MakeSubpass(
- "Atlas Blend", sub_atlas->size,
- [&](const ContentContext& context, RenderPass& pass) {
- Entity entity;
- entity.SetContents(dst_contents);
- entity.SetBlendMode(BlendMode::kSource);
- if (!entity.Render(context, pass)) {
- return false;
- }
- if (blend_mode_ >= Entity::kLastPipelineBlendMode) {
- auto contents = std::make_shared<FramebufferBlendContents>();
- contents->SetBlendMode(blend_mode_);
- contents->SetChildContents(src_contents);
- entity.SetContents(std::move(contents));
- entity.SetBlendMode(BlendMode::kSource);
- return entity.Render(context, pass);
- }
- entity.SetContents(src_contents);
- entity.SetBlendMode(blend_mode_);
- return entity.Render(context, pass);
- });
- } else {
- auto contents = ColorFilterContents::MakeBlend(
- blend_mode_,
- {FilterInput::Make(dst_contents), FilterInput::Make(src_contents)});
- auto snapshot =
- contents->RenderToSnapshot(renderer, // renderer
- entity, // entity
- std::nullopt, // coverage_limit
- std::nullopt, // sampler_descriptor
- true, // msaa_enabled
- "AtlasContents Snapshot"); // label
- if (!snapshot.has_value()) {
- return false;
- }
- new_texture = snapshot.value().texture;
+ Entity untransformed_entity;
+ auto contents = ColorFilterContents::MakeBlend(
+ blend_mode_,
+ {FilterInput::Make(dst_contents), FilterInput::Make(src_contents)});
+ auto snapshot =
+ contents->RenderToSnapshot(renderer, // renderer
+ untransformed_entity, // entity
+ std::nullopt, // coverage_limit
+ std::nullopt, // sampler_descriptor
+ true, // msaa_enabled
+ "AtlasContents Snapshot"); // label
+ if (!snapshot.has_value()) {
+ return false;
}
auto child_contents = AtlasTextureContents(*this);
child_contents.SetAlpha(alpha_);
child_contents.SetCoverage(coverage);
- child_contents.SetTexture(new_texture);
+ child_contents.SetTexture(snapshot.value().texture);
child_contents.SetUseDestination(true);
child_contents.SetSubAtlas(sub_atlas);
return child_contents.Render(renderer, entity, pass);
diff --git a/impeller/entity/entity_unittests.cc b/impeller/entity/entity_unittests.cc
index c4339fc..fee275f 100644
--- a/impeller/entity/entity_unittests.cc
+++ b/impeller/entity/entity_unittests.cc
@@ -1365,8 +1365,7 @@
}
TEST_P(EntityTest, DrawAtlasWithColorAdvanced) {
- // Draws the image as four squares stiched together. Because blend modes
- // aren't implented this ends up as four solid color blocks.
+ // Draws the image as four squares stiched together.
auto atlas = CreateTextureForFixture("bay_bridge.jpg");
auto size = atlas->GetSize();
// Divide image into four quadrants.