[Impeller] blur: removed ability to request out of bounds mip_counts (#50290)
b/323402168
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc
index ca5ba3c..c8c5a47 100644
--- a/impeller/aiks/aiks_unittests.cc
+++ b/impeller/aiks/aiks_unittests.cc
@@ -3968,5 +3968,61 @@
}
}
+// This addresses a bug where tiny blurs could result in mip maps that beyond
+// the limits for the textures used for blurring.
+// See also: b/323402168
+TEST_P(AiksTest, GaussianBlurSolidColorTinyMipMap) {
+ for (int32_t i = 1; i < 5; ++i) {
+ Canvas canvas;
+ Scalar fi = i;
+ canvas.DrawPath(
+ PathBuilder{}
+ .MoveTo({100, 100})
+ .LineTo({100.f + fi, 100.f + fi})
+ .TakePath(),
+ {.color = Color::Chartreuse(),
+ .image_filter = ImageFilter::MakeBlur(
+ Sigma(0.1), Sigma(0.1), FilterContents::BlurStyle::kNormal,
+ Entity::TileMode::kClamp)});
+
+ Picture picture = canvas.EndRecordingAsPicture();
+ std::shared_ptr<RenderTargetCache> cache =
+ std::make_shared<RenderTargetCache>(
+ GetContext()->GetResourceAllocator());
+ AiksContext aiks_context(GetContext(), nullptr, cache);
+ std::shared_ptr<Image> image = picture.ToImage(aiks_context, {1024, 768});
+ EXPECT_TRUE(image) << " length " << i;
+ }
+}
+
+// This addresses a bug where tiny blurs could result in mip maps that beyond
+// the limits for the textures used for blurring.
+// See also: b/323402168
+TEST_P(AiksTest, GaussianBlurBackdropTinyMipMap) {
+ for (int32_t i = 0; i < 5; ++i) {
+ Canvas canvas;
+ ISize clip_size = ISize(i, i);
+ canvas.ClipRect(
+ Rect::MakeXYWH(400, 400, clip_size.width, clip_size.height));
+ canvas.DrawCircle(
+ {400, 400}, 200,
+ {
+ .color = Color::Green(),
+ .image_filter = ImageFilter::MakeBlur(
+ Sigma(0.1), Sigma(0.1), FilterContents::BlurStyle::kNormal,
+ Entity::TileMode::kDecal),
+ });
+ canvas.Restore();
+
+ Picture picture = canvas.EndRecordingAsPicture();
+ std::shared_ptr<RenderTargetCache> cache =
+ std::make_shared<RenderTargetCache>(
+ GetContext()->GetResourceAllocator());
+ AiksContext aiks_context(GetContext(), nullptr, cache);
+ std::shared_ptr<Image> image = picture.ToImage(aiks_context, {1024, 768});
+ EXPECT_TRUE(image) << " clip rect " << i;
+ }
+}
+
} // namespace testing
} // namespace impeller
diff --git a/impeller/core/allocator.cc b/impeller/core/allocator.cc
index d9cedbe..19314c5 100644
--- a/impeller/core/allocator.cc
+++ b/impeller/core/allocator.cc
@@ -55,6 +55,14 @@
return nullptr;
}
+ if (desc.mip_count > desc.size.MipCount()) {
+ VALIDATION_LOG << "Requested mip_count " << desc.mip_count
+ << " exceeds maximum supported for size " << desc.size;
+ TextureDescriptor corrected_desc = desc;
+ corrected_desc.mip_count = desc.size.MipCount();
+ return OnCreateTexture(corrected_desc);
+ }
+
return OnCreateTexture(desc);
}
diff --git a/impeller/entity/contents/contents.cc b/impeller/entity/contents/contents.cc
index bbef829..b8bfcc3 100644
--- a/impeller/entity/contents/contents.cc
+++ b/impeller/entity/contents/contents.cc
@@ -80,8 +80,9 @@
}
}
+ ISize subpass_size = ISize::Ceil(coverage->GetSize());
fml::StatusOr<RenderTarget> render_target = renderer.MakeSubpass(
- label, ISize::Ceil(coverage->GetSize()),
+ label, subpass_size,
[&contents = *this, &entity, &coverage](const ContentContext& renderer,
RenderPass& pass) -> bool {
Entity sub_entity;
@@ -91,7 +92,8 @@
entity.GetTransform());
return contents.Render(renderer, sub_entity, pass);
},
- msaa_enabled, mip_count);
+ msaa_enabled,
+ std::min(mip_count, static_cast<int32_t>(subpass_size.MipCount())));
if (!render_target.ok()) {
return std::nullopt;