Implement the render_to_surface flag in GPUSurfaceGLImpeller (flutter/engine#50669)

Without this, the EmbedderExternalViewEmbedder's call to SurfaceFrame::Submit will render an empty display list that will overwrite the output rendered by the external view embedder's layers.

See https://github.com/flutter/flutter/issues/143387
This commit is contained in:
Jason Simmons
2024-02-20 11:27:09 -08:00
committed by GitHub
parent 77cbd54c43
commit c0159abf1b
8 changed files with 34 additions and 9 deletions

View File

@@ -14,7 +14,8 @@ namespace flutter {
GPUSurfaceGLImpeller::GPUSurfaceGLImpeller(
GPUSurfaceGLDelegate* delegate,
std::shared_ptr<impeller::Context> context)
std::shared_ptr<impeller::Context> context,
bool render_to_surface)
: weak_factory_(this) {
if (delegate == nullptr) {
return;
@@ -38,6 +39,7 @@ GPUSurfaceGLImpeller::GPUSurfaceGLImpeller(
delegate_ = delegate;
impeller_context_ = std::move(context);
render_to_surface_ = render_to_surface;
impeller_renderer_ = std::move(renderer);
aiks_context_ = std::move(aiks_context);
is_valid_ = true;
@@ -82,6 +84,15 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceGLImpeller::AcquireFrame(
return nullptr;
}
if (!render_to_surface_) {
return std::make_unique<SurfaceFrame>(
nullptr, SurfaceFrame::FramebufferInfo{.supports_readback = true},
[](const SurfaceFrame& surface_frame, DlCanvas* canvas) {
return true;
},
size);
}
GLFrameInfo frame_info = {static_cast<uint32_t>(size.width()),
static_cast<uint32_t>(size.height())};
const GLFBOInfo fbo_info = delegate_->GLContextFBO(frame_info);

View File

@@ -18,7 +18,8 @@ namespace flutter {
class GPUSurfaceGLImpeller final : public Surface {
public:
explicit GPUSurfaceGLImpeller(GPUSurfaceGLDelegate* delegate,
std::shared_ptr<impeller::Context> context);
std::shared_ptr<impeller::Context> context,
bool render_to_surface);
// |Surface|
~GPUSurfaceGLImpeller() override;
@@ -29,6 +30,7 @@ class GPUSurfaceGLImpeller final : public Surface {
private:
GPUSurfaceGLDelegate* delegate_ = nullptr;
std::shared_ptr<impeller::Context> impeller_context_;
bool render_to_surface_ = true;
std::shared_ptr<impeller::Renderer> impeller_renderer_;
std::shared_ptr<impeller::AiksContext> aiks_context_;
bool is_valid_ = false;

View File

@@ -36,8 +36,9 @@ bool AndroidSurfaceGLImpeller::IsValid() const {
std::unique_ptr<Surface> AndroidSurfaceGLImpeller::CreateGPUSurface(
GrDirectContext* gr_context) {
auto surface = std::make_unique<GPUSurfaceGLImpeller>(
this, // delegate
android_context_->GetImpellerContext() // context
this, // delegate
android_context_->GetImpellerContext(), // context
true // render to surface
);
if (!surface->IsValid()) {
return nullptr;

View File

@@ -242,6 +242,7 @@ test_fixtures("fixtures") {
"fixtures/dpr_noxform.png",
"fixtures/dpr_xform.png",
"fixtures/gradient.png",
"fixtures/impeller_gl_gradient.png",
"fixtures/vk_dpr_noxform.png",
"fixtures/vk_gradient.png",
"fixtures/gradient_metal.png",
@@ -250,7 +251,6 @@ test_fixtures("fixtures") {
"fixtures/scene_without_custom_compositor.png",
"fixtures/scene_without_custom_compositor_with_xform.png",
"fixtures/snapshot_large_scene.png",
"fixtures/solid_red.png",
"fixtures/verifyb143464703.png",
"fixtures/verifyb143464703_soft_noxform.png",
]

View File

@@ -179,8 +179,9 @@ EmbedderSurfaceGLImpeller::GLContextFramebufferInfo() const {
// |EmbedderSurface|
std::unique_ptr<Surface> EmbedderSurfaceGLImpeller::CreateGPUSurface() {
return std::make_unique<GPUSurfaceGLImpeller>(
this, // GPU surface GL delegate
impeller_context_ // render to surface
this, // GPU surface GL delegate
impeller_context_, // Impeller context
!external_view_embedder_ // render to surface
);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -4704,8 +4704,14 @@ TEST_F(EmbedderTest, CanRenderWithImpellerOpenGL) {
auto& context = GetEmbedderContext(EmbedderTestContextType::kOpenGLContext);
EmbedderConfigBuilder builder(context);
bool present_called = false;
static_cast<EmbedderTestContextGL&>(context).SetGLPresentCallback(
[&present_called](FlutterPresentInfo present_info) {
present_called = true;
});
builder.AddCommandLineArgument("--enable-impeller");
builder.SetDartEntrypoint("draw_solid_red");
builder.SetDartEntrypoint("render_gradient");
builder.SetOpenGLRendererConfig(SkISize::Make(800, 600));
builder.SetCompositor();
builder.SetRenderTargetType(
@@ -4727,8 +4733,12 @@ TEST_F(EmbedderTest, CanRenderWithImpellerOpenGL) {
ASSERT_TRUE(ImageMatchesFixture(
FixtureNameForBackend(EmbedderTestContextType::kOpenGLContext,
"solid_red.png"),
"impeller_gl_gradient.png"),
rendered_scene));
// The scene will be rendered by the compositor, and the surface present
// callback should not be invoked.
ASSERT_FALSE(present_called);
}
INSTANTIATE_TEST_SUITE_P(