[Impeller] fix validation check when restoring to onscreen with BDF and mips. (#165098)
Fixes https://github.com/flutter/flutter/issues/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.
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
#include "flutter/display_list/dl_paint.h"
|
||||
#include "flutter/testing/testing.h"
|
||||
#include "fml/synchronization/count_down_latch.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "imgui.h"
|
||||
#include "impeller/base/validation.h"
|
||||
#include "impeller/core/device_buffer.h"
|
||||
@@ -30,6 +31,7 @@
|
||||
#include "impeller/display_list/dl_dispatcher.h"
|
||||
#include "impeller/display_list/dl_image_impeller.h"
|
||||
#include "impeller/geometry/scalar.h"
|
||||
#include "impeller/playground/playground.h"
|
||||
|
||||
namespace impeller {
|
||||
namespace testing {
|
||||
@@ -1119,5 +1121,26 @@ TEST_P(AiksTest, DisplayListToTextureAllocationFailure) {
|
||||
EXPECT_EQ(texture, nullptr);
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, DisplayListToTextureWithMipGenerationOnGLES) {
|
||||
if (GetBackend() != PlaygroundBackend::kOpenGLES) {
|
||||
GTEST_SKIP() << "Only relevant for GLES";
|
||||
}
|
||||
DisplayListBuilder builder;
|
||||
|
||||
std::shared_ptr<DlImageFilter> filter =
|
||||
DlImageFilter::MakeBlur(8, 8, DlTileMode::kClamp);
|
||||
builder.SaveLayer(std::nullopt, nullptr, filter.get());
|
||||
builder.Restore();
|
||||
|
||||
AiksContext aiks_context(GetContext(), nullptr);
|
||||
// Use intentionally invalid dimensions that would trigger an allocation
|
||||
// failure.
|
||||
auto texture =
|
||||
DisplayListToTexture(builder.Build(), ISize{10, 10}, aiks_context,
|
||||
/*reset_host_buffer=*/true, /*generate_mips=*/true);
|
||||
|
||||
EXPECT_FALSE(texture->NeedsMipmapGeneration());
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace impeller
|
||||
|
||||
@@ -1718,7 +1718,6 @@ bool Canvas::BlitToOnscreen(bool is_onscreen) {
|
||||
auto offscreen_target = render_passes_.back()
|
||||
.inline_pass_context->GetPassTarget()
|
||||
.GetRenderTarget();
|
||||
|
||||
if (SupportsBlitToOnscreen()) {
|
||||
auto blit_pass = command_buffer->CreateBlitPass();
|
||||
blit_pass->AddCopy(offscreen_target.GetRenderTargetTexture(),
|
||||
@@ -1762,6 +1761,24 @@ bool Canvas::BlitToOnscreen(bool is_onscreen) {
|
||||
}
|
||||
}
|
||||
|
||||
bool Canvas::EnsureFinalMipmapGeneration() const {
|
||||
if (!render_target_.GetRenderTargetTexture()->NeedsMipmapGeneration()) {
|
||||
return true;
|
||||
}
|
||||
std::shared_ptr<CommandBuffer> cmd_buffer =
|
||||
renderer_.GetContext()->CreateCommandBuffer();
|
||||
if (!cmd_buffer) {
|
||||
return false;
|
||||
}
|
||||
std::shared_ptr<BlitPass> blit_pass = cmd_buffer->CreateBlitPass();
|
||||
if (!blit_pass) {
|
||||
return false;
|
||||
}
|
||||
blit_pass->GenerateMipmap(render_target_.GetRenderTargetTexture());
|
||||
blit_pass->EncodeCommands();
|
||||
return renderer_.GetContext()->EnqueueCommandBuffer(std::move(cmd_buffer));
|
||||
}
|
||||
|
||||
void Canvas::EndReplay() {
|
||||
FML_DCHECK(render_passes_.size() == 1u);
|
||||
render_passes_.back().inline_pass_context->GetRenderPass();
|
||||
@@ -1775,7 +1792,9 @@ void Canvas::EndReplay() {
|
||||
if (requires_readback_) {
|
||||
BlitToOnscreen(/*is_onscreen_=*/is_onscreen_);
|
||||
}
|
||||
|
||||
if (!EnsureFinalMipmapGeneration()) {
|
||||
VALIDATION_LOG << "Failed to generate onscreen mipmaps.";
|
||||
}
|
||||
if (!renderer_.GetContext()->FlushCommandBuffers()) {
|
||||
// Not much we can do.
|
||||
VALIDATION_LOG << "Failed to submit command buffers";
|
||||
|
||||
@@ -263,6 +263,10 @@ class Canvas {
|
||||
// Visible for testing.
|
||||
bool SupportsBlitToOnscreen() const;
|
||||
|
||||
/// For picture snapshots we need addition steps to verify that final mipmaps
|
||||
/// are generated.
|
||||
bool EnsureFinalMipmapGeneration() const;
|
||||
|
||||
private:
|
||||
ContentContext& renderer_;
|
||||
RenderTarget render_target_;
|
||||
|
||||
Reference in New Issue
Block a user