diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index c2b07397610a1..3858ff0dca914 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -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 cache = + std::make_shared(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 diff --git a/impeller/entity/entity_pass.cc b/impeller/entity/entity_pass.cc index 576c3a97a6ff9..dec9a98b15ed7 100644 --- a/impeller/entity/entity_pass.cc +++ b/impeller/entity/entity_pass.cc @@ -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(&element)) { - if (const auto& contents = entity->GetContents()) { - contents->PopulateGlyphAtlas(lazy_glyph_atlas, - entity->DeriveTextScale()); - } - } - if (auto subpass = std::get_if>(&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>(&element)) { + result = std::max(result, subpass->get()->GetRequiredMipCount()); + } + } + return result; +} + EntityPassClipRecorder::EntityPassClipRecorder() {} void EntityPassClipRecorder::RecordEntity(const Entity& entity, diff --git a/impeller/entity/entity_pass.h b/impeller/entity/entity_pass.h index 7de68d0d9ad11..cacf45776c029 100644 --- a/impeller/entity/entity_pass.h +++ b/impeller/entity/entity_pass.h @@ -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