[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:
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user