Make the GL context current in EmbedderSurfaceGLImpeller before creating the GPU surface (flutter/engine#50807)

The GPUSurfaceGLImpeller ctor creates an AiksContext/ContentContext, which loads the shader pipelines.  If the current thread does not have a GL context and can not execute ReactorGLES operations, then the pipeline futures will not complete.  This can cause the raster thread to hang if the reactor has not run and the futures are still incomplete when a rendering task later needs to obtain the pipeline.
This commit is contained in:
Jason Simmons 2024-02-21 10:37:21 -08:00 committed by GitHub
parent 9a26927508
commit 55da4fb37d
6 changed files with 26 additions and 3 deletions

View File

@ -242,7 +242,7 @@ test_fixtures("fixtures") {
"fixtures/dpr_noxform.png",
"fixtures/dpr_xform.png",
"fixtures/gradient.png",
"fixtures/impeller_gl_gradient.png",
"fixtures/impeller_gl_test.png",
"fixtures/vk_dpr_noxform.png",
"fixtures/vk_gradient.png",
"fixtures/gradient_metal.png",

View File

@ -178,6 +178,11 @@ EmbedderSurfaceGLImpeller::GLContextFramebufferInfo() const {
// |EmbedderSurface|
std::unique_ptr<Surface> EmbedderSurfaceGLImpeller::CreateGPUSurface() {
// Ensure that the GL context is current before creating the GPU surface.
// GPUSurfaceGLImpeller initialization will set up shader pipelines, and the
// current thread needs to be able to execute reactor operations.
GLContextMakeCurrent();
return std::make_unique<GPUSurfaceGLImpeller>(
this, // GPU surface GL delegate
impeller_context_, // Impeller context

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -1364,3 +1364,21 @@ void render_gradient_retained() {
};
PlatformDispatcher.instance.scheduleFrame();
}
@pragma('vm:entry-point')
void render_impeller_gl_test() {
PlatformDispatcher.instance.onBeginFrame = (Duration duration) {
final SceneBuilder builder = SceneBuilder();
builder.pushOffset(0.0, 0.0);
final Paint paint = Paint();
paint.color = Color.fromARGB(255, 0, 0, 255);
final PictureRecorder baseRecorder = PictureRecorder();
final Canvas canvas = Canvas(baseRecorder);
canvas.drawPaint(Paint()..color = Color.fromARGB(255, 255, 0, 0));
canvas.drawRect(Rect.fromLTRB(20.0, 20.0, 200.0, 150.0), paint);
builder.addPicture(Offset.zero, baseRecorder.endRecording());
builder.pop();
PlatformDispatcher.instance.views.first.render(builder.build());
};
PlatformDispatcher.instance.scheduleFrame();
}

View File

@ -4711,7 +4711,7 @@ TEST_F(EmbedderTest, CanRenderWithImpellerOpenGL) {
});
builder.AddCommandLineArgument("--enable-impeller");
builder.SetDartEntrypoint("render_gradient");
builder.SetDartEntrypoint("render_impeller_gl_test");
builder.SetOpenGLRendererConfig(SkISize::Make(800, 600));
builder.SetCompositor();
builder.SetRenderTargetType(
@ -4733,7 +4733,7 @@ TEST_F(EmbedderTest, CanRenderWithImpellerOpenGL) {
ASSERT_TRUE(ImageMatchesFixture(
FixtureNameForBackend(EmbedderTestContextType::kOpenGLContext,
"impeller_gl_gradient.png"),
"impeller_gl_test.png"),
rendered_scene));
// The scene will be rendered by the compositor, and the surface present