[Impeller] fixed nested save layer mipmap counts (flutter/engine#49778)

resolves https://github.com/flutter/engine/pull/49607#discussion_r1450982660

[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
This commit is contained in:
gaaclarke
2024-01-12 17:34:22 -08:00
committed by GitHub
parent 08e89db585
commit 6bd7574e88
3 changed files with 50 additions and 19 deletions

View File

@@ -3794,5 +3794,31 @@ TEST_P(AiksTest, GaussianBlurAllocatesCorrectMipCountRenderTarget) {
EXPECT_EQ(max_mip_count, 1lu);
}
TEST_P(AiksTest, GaussianBlurMipMapNestedLayer) {
Canvas canvas;
canvas.DrawPaint({.color = Color::Wheat()});
canvas.SaveLayer({.blend_mode = BlendMode::kMultiply});
canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()});
canvas.SaveLayer({}, std::nullopt,
ImageFilter::MakeBlur(Sigma(30), Sigma(30),
FilterContents::BlurStyle::kNormal,
Entity::TileMode::kClamp));
canvas.DrawCircle({200, 200}, 50, {.color = Color::Chartreuse()});
Picture picture = canvas.EndRecordingAsPicture();
std::shared_ptr<RenderTargetCache> cache =
std::make_shared<RenderTargetCache>(GetContext()->GetResourceAllocator());
AiksContext aiks_context(GetContext(), nullptr, cache);
picture.ToImage(aiks_context, {100, 100});
size_t max_mip_count = 0;
for (auto it = cache->GetTextureDataBegin(); it != cache->GetTextureDataEnd();
++it) {
max_mip_count =
std::max(it->texture->GetTextureDescriptor().mip_count, max_mip_count);
}
EXPECT_EQ(max_mip_count, 1lu);
}
} // namespace testing
} // namespace impeller

View File

@@ -325,23 +325,13 @@ bool EntityPass::Render(ContentContext& renderer,
Rect::MakeSize(root_render_target.GetRenderTargetSize()),
{.readonly = true});
int32_t required_mip_count = 1;
IterateAllElements(
[&required_mip_count, lazy_glyph_atlas = renderer.GetLazyGlyphAtlas()](
const Element& element) {
if (auto entity = std::get_if<Entity>(&element)) {
if (const auto& contents = entity->GetContents()) {
contents->PopulateGlyphAtlas(lazy_glyph_atlas,
entity->DeriveTextScale());
}
}
if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
const EntityPass* entity_pass = subpass->get();
required_mip_count =
std::max(required_mip_count, entity_pass->GetRequiredMipCount());
}
return true;
});
IterateAllEntities([lazy_glyph_atlas =
renderer.GetLazyGlyphAtlas()](const Entity& entity) {
if (const auto& contents = entity.GetContents()) {
contents->PopulateGlyphAtlas(lazy_glyph_atlas, entity.DeriveTextScale());
}
return true;
});
ClipCoverageStack clip_coverage_stack = {ClipCoverageLayer{
.coverage = Rect::MakeSize(root_render_target.GetRenderTargetSize()),
@@ -353,7 +343,8 @@ bool EntityPass::Render(ContentContext& renderer,
// there's no need to set up a stencil attachment on the root render target.
if (reads_from_onscreen_backdrop) {
EntityPassTarget offscreen_target = CreateRenderTarget(
renderer, root_render_target.GetRenderTargetSize(), required_mip_count,
renderer, root_render_target.GetRenderTargetSize(),
GetBackdropFilterMipCount(),
GetClearColorOrDefault(render_target.GetRenderTargetSize()));
if (!OnRender(renderer, // renderer
@@ -615,7 +606,7 @@ EntityPass::EntityResult EntityPass::GetEntityForElement(
auto subpass_target = CreateRenderTarget(
renderer, // renderer
subpass_size, // size
/*mip_count=*/1,
subpass->GetBackdropFilterMipCount(),
subpass->GetClearColorOrDefault(subpass_size)); // clear_color
if (!subpass_target.IsValid()) {
@@ -1200,6 +1191,16 @@ void EntityPass::SetEnableOffscreenCheckerboard(bool enabled) {
enable_offscreen_debug_checkerboard_ = enabled;
}
int32_t EntityPass::GetBackdropFilterMipCount() const {
int32_t result = 1;
for (auto& element : elements_) {
if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
result = std::max(result, subpass->get()->GetRequiredMipCount());
}
}
return result;
}
EntityPassClipRecorder::EntityPassClipRecorder() {}
void EntityPassClipRecorder::RecordEntity(const Entity& entity,

View File

@@ -157,6 +157,10 @@ class EntityPass {
required_mip_count_ = mip_count;
}
/// Returns the mip map count that should be required for the render target
/// receiving this EntityPass.
int32_t GetBackdropFilterMipCount() const;
//----------------------------------------------------------------------------
/// @brief Computes the coverage of a given subpass. This is used to
/// determine the texture size of a given subpass before it's rendered