Skip to content

Commit 3e219d1

Browse files
author
Jonah Williams
authored
[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 flutter/flutter#163304
1 parent 9393aae commit 3e219d1

3 files changed

Lines changed: 32 additions & 3 deletions

File tree

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1681,16 +1681,22 @@ std::shared_ptr<Texture> Canvas::FlipBackdrop(Point global_pass_position,
16811681
return input_texture;
16821682
}
16831683

1684+
bool Canvas::SupportsBlitToOnscreen() const {
1685+
return renderer_.GetContext()
1686+
->GetCapabilities()
1687+
->SupportsTextureToTextureBlits() &&
1688+
renderer_.GetContext()->GetBackendType() !=
1689+
Context::BackendType::kOpenGLES;
1690+
}
1691+
16841692
bool Canvas::BlitToOnscreen(bool is_onscreen) {
16851693
auto command_buffer = renderer_.GetContext()->CreateCommandBuffer();
16861694
command_buffer->SetLabel("EntityPass Root Command Buffer");
16871695
auto offscreen_target = render_passes_.back()
16881696
.inline_pass_context->GetPassTarget()
16891697
.GetRenderTarget();
16901698

1691-
if (renderer_.GetContext()
1692-
->GetCapabilities()
1693-
->SupportsTextureToTextureBlits()) {
1699+
if (SupportsBlitToOnscreen()) {
16941700
auto blit_pass = command_buffer->CreateBlitPass();
16951701
blit_pass->AddCopy(offscreen_target.GetRenderTargetTexture(),
16961702
render_target_.GetRenderTargetTexture());

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,16 @@ class Canvas {
251251
// Visible for testing.
252252
bool RequiresReadback() const { return requires_readback_; }
253253

254+
// Whether the current device has the capabilities to blit an offscreen
255+
// texture into the onscreen.
256+
//
257+
// This requires the availibility of the blit framebuffer command, but is
258+
// disabled for GLES. A simple glBlitFramebuffer does not support resolving
259+
// different sample counts which may be present in GLES when using MSAA.
260+
//
261+
// Visible for testing.
262+
bool SupportsBlitToOnscreen() const;
263+
254264
private:
255265
ContentContext& renderer_;
256266
RenderTarget render_target_;

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "impeller/display_list/canvas.h"
1616
#include "impeller/display_list/dl_vertices_geometry.h"
1717
#include "impeller/geometry/geometry_asserts.h"
18+
#include "impeller/playground/playground.h"
1819
#include "impeller/renderer/render_target.h"
1920

2021
namespace impeller {
@@ -372,5 +373,17 @@ TEST_P(AiksTest, DrawVerticesWithEmptyTextureCoordinates) {
372373
ASSERT_TRUE(Playground::OpenPlaygroundHere(callback));
373374
}
374375

376+
TEST_P(AiksTest, SupportsBlitToOnscreen) {
377+
ContentContext context(GetContext(), nullptr);
378+
auto canvas = CreateTestCanvas(context, Rect::MakeLTRB(0, 0, 100, 100),
379+
/*requires_readback=*/true);
380+
381+
if (GetBackend() == PlaygroundBackend::kOpenGLES) {
382+
EXPECT_FALSE(canvas->SupportsBlitToOnscreen());
383+
} else {
384+
EXPECT_TRUE(canvas->SupportsBlitToOnscreen());
385+
}
386+
}
387+
375388
} // namespace testing
376389
} // namespace impeller

0 commit comments

Comments
 (0)