[Impeller] don't use glFramebufferBlit for onscreen restore. (#163327)

With the OpenGLES backend, we use the MSAA render to texture extension.
This means that the offscreen textures are multisample and implicitly
resolved when sampled from. This implicit resolve does not occur in the
blit command used to restore to the onscreen, which can trigger a crash
in the GLES driver.

In other backends, the onscreen is also multisample and the blit is OK.

Fixes https://github.com/flutter/flutter/issues/163304
This commit is contained in:
Jonah Williams 2025-02-14 11:59:39 -08:00 committed by GitHub
parent 9393aae393
commit 3e219d1cd8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 32 additions and 3 deletions

View File

@ -1681,6 +1681,14 @@ std::shared_ptr<Texture> Canvas::FlipBackdrop(Point global_pass_position,
return input_texture;
}
bool Canvas::SupportsBlitToOnscreen() const {
return renderer_.GetContext()
->GetCapabilities()
->SupportsTextureToTextureBlits() &&
renderer_.GetContext()->GetBackendType() !=
Context::BackendType::kOpenGLES;
}
bool Canvas::BlitToOnscreen(bool is_onscreen) {
auto command_buffer = renderer_.GetContext()->CreateCommandBuffer();
command_buffer->SetLabel("EntityPass Root Command Buffer");
@ -1688,9 +1696,7 @@ bool Canvas::BlitToOnscreen(bool is_onscreen) {
.inline_pass_context->GetPassTarget()
.GetRenderTarget();
if (renderer_.GetContext()
->GetCapabilities()
->SupportsTextureToTextureBlits()) {
if (SupportsBlitToOnscreen()) {
auto blit_pass = command_buffer->CreateBlitPass();
blit_pass->AddCopy(offscreen_target.GetRenderTargetTexture(),
render_target_.GetRenderTargetTexture());

View File

@ -251,6 +251,16 @@ class Canvas {
// Visible for testing.
bool RequiresReadback() const { return requires_readback_; }
// Whether the current device has the capabilities to blit an offscreen
// texture into the onscreen.
//
// This requires the availibility of the blit framebuffer command, but is
// disabled for GLES. A simple glBlitFramebuffer does not support resolving
// different sample counts which may be present in GLES when using MSAA.
//
// Visible for testing.
bool SupportsBlitToOnscreen() const;
private:
ContentContext& renderer_;
RenderTarget render_target_;

View File

@ -15,6 +15,7 @@
#include "impeller/display_list/canvas.h"
#include "impeller/display_list/dl_vertices_geometry.h"
#include "impeller/geometry/geometry_asserts.h"
#include "impeller/playground/playground.h"
#include "impeller/renderer/render_target.h"
namespace impeller {
@ -372,5 +373,17 @@ TEST_P(AiksTest, DrawVerticesWithEmptyTextureCoordinates) {
ASSERT_TRUE(Playground::OpenPlaygroundHere(callback));
}
TEST_P(AiksTest, SupportsBlitToOnscreen) {
ContentContext context(GetContext(), nullptr);
auto canvas = CreateTestCanvas(context, Rect::MakeLTRB(0, 0, 100, 100),
/*requires_readback=*/true);
if (GetBackend() == PlaygroundBackend::kOpenGLES) {
EXPECT_FALSE(canvas->SupportsBlitToOnscreen());
} else {
EXPECT_TRUE(canvas->SupportsBlitToOnscreen());
}
}
} // namespace testing
} // namespace impeller