Skip to content

Commit c38f0b7

Browse files
author
Jonah Williams
authored
[Impeller] fix validation check when restoring to onscreen with BDF and mips. (#165098)
Fixes flutter/flutter#163421 If we restore to the onscreen but need to generate mips (because its a toImage call) then we could miss the mip map generation. This will primarily happen on Android emulators as they do not support framebuffer fetch.
1 parent 2b8aea7 commit c38f0b7

File tree

3 files changed

+48
-2
lines changed

3 files changed

+48
-2
lines changed

engine/src/flutter/impeller/display_list/aiks_dl_unittests.cc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "flutter/display_list/dl_paint.h"
2121
#include "flutter/testing/testing.h"
2222
#include "fml/synchronization/count_down_latch.h"
23+
#include "gtest/gtest.h"
2324
#include "imgui.h"
2425
#include "impeller/base/validation.h"
2526
#include "impeller/core/device_buffer.h"
@@ -30,6 +31,7 @@
3031
#include "impeller/display_list/dl_dispatcher.h"
3132
#include "impeller/display_list/dl_image_impeller.h"
3233
#include "impeller/geometry/scalar.h"
34+
#include "impeller/playground/playground.h"
3335

3436
namespace impeller {
3537
namespace testing {
@@ -1119,5 +1121,26 @@ TEST_P(AiksTest, DisplayListToTextureAllocationFailure) {
11191121
EXPECT_EQ(texture, nullptr);
11201122
}
11211123

1124+
TEST_P(AiksTest, DisplayListToTextureWithMipGenerationOnGLES) {
1125+
if (GetBackend() != PlaygroundBackend::kOpenGLES) {
1126+
GTEST_SKIP() << "Only relevant for GLES";
1127+
}
1128+
DisplayListBuilder builder;
1129+
1130+
std::shared_ptr<DlImageFilter> filter =
1131+
DlImageFilter::MakeBlur(8, 8, DlTileMode::kClamp);
1132+
builder.SaveLayer(std::nullopt, nullptr, filter.get());
1133+
builder.Restore();
1134+
1135+
AiksContext aiks_context(GetContext(), nullptr);
1136+
// Use intentionally invalid dimensions that would trigger an allocation
1137+
// failure.
1138+
auto texture =
1139+
DisplayListToTexture(builder.Build(), ISize{10, 10}, aiks_context,
1140+
/*reset_host_buffer=*/true, /*generate_mips=*/true);
1141+
1142+
EXPECT_FALSE(texture->NeedsMipmapGeneration());
1143+
}
1144+
11221145
} // namespace testing
11231146
} // namespace impeller

engine/src/flutter/impeller/display_list/canvas.cc

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1718,7 +1718,6 @@ bool Canvas::BlitToOnscreen(bool is_onscreen) {
17181718
auto offscreen_target = render_passes_.back()
17191719
.inline_pass_context->GetPassTarget()
17201720
.GetRenderTarget();
1721-
17221721
if (SupportsBlitToOnscreen()) {
17231722
auto blit_pass = command_buffer->CreateBlitPass();
17241723
blit_pass->AddCopy(offscreen_target.GetRenderTargetTexture(),
@@ -1762,6 +1761,24 @@ bool Canvas::BlitToOnscreen(bool is_onscreen) {
17621761
}
17631762
}
17641763

1764+
bool Canvas::EnsureFinalMipmapGeneration() const {
1765+
if (!render_target_.GetRenderTargetTexture()->NeedsMipmapGeneration()) {
1766+
return true;
1767+
}
1768+
std::shared_ptr<CommandBuffer> cmd_buffer =
1769+
renderer_.GetContext()->CreateCommandBuffer();
1770+
if (!cmd_buffer) {
1771+
return false;
1772+
}
1773+
std::shared_ptr<BlitPass> blit_pass = cmd_buffer->CreateBlitPass();
1774+
if (!blit_pass) {
1775+
return false;
1776+
}
1777+
blit_pass->GenerateMipmap(render_target_.GetRenderTargetTexture());
1778+
blit_pass->EncodeCommands();
1779+
return renderer_.GetContext()->EnqueueCommandBuffer(std::move(cmd_buffer));
1780+
}
1781+
17651782
void Canvas::EndReplay() {
17661783
FML_DCHECK(render_passes_.size() == 1u);
17671784
render_passes_.back().inline_pass_context->GetRenderPass();
@@ -1775,7 +1792,9 @@ void Canvas::EndReplay() {
17751792
if (requires_readback_) {
17761793
BlitToOnscreen(/*is_onscreen_=*/is_onscreen_);
17771794
}
1778-
1795+
if (!EnsureFinalMipmapGeneration()) {
1796+
VALIDATION_LOG << "Failed to generate onscreen mipmaps.";
1797+
}
17791798
if (!renderer_.GetContext()->FlushCommandBuffers()) {
17801799
// Not much we can do.
17811800
VALIDATION_LOG << "Failed to submit command buffers";

engine/src/flutter/impeller/display_list/canvas.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,10 @@ class Canvas {
263263
// Visible for testing.
264264
bool SupportsBlitToOnscreen() const;
265265

266+
/// For picture snapshots we need addition steps to verify that final mipmaps
267+
/// are generated.
268+
bool EnsureFinalMipmapGeneration() const;
269+
266270
private:
267271
ContentContext& renderer_;
268272
RenderTarget render_target_;

0 commit comments

Comments
 (0)