[Windows] Move EGL surface creation (#51920) _This is a refactoring with no semantic changes._ The engine can start rendering into a view once it's received the view's initial window metrics. In a multi-view world, the initial window metrics will be sent by `FlutterEngineAddView`, which will be called by `FlutterWindowsEngine::CreateView`. This change creates the view's EGL surface earlier, in `FlutterWindowsEngine::CreateView`, to prepare for multi-view rendering. Prepares for https://github.com/flutter/flutter/issues/144810 Part of https://github.com/flutter/flutter/issues/142845 [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
diff --git a/shell/platform/windows/flutter_windows.cc b/shell/platform/windows/flutter_windows.cc index d25d3f9..39aac3f 100644 --- a/shell/platform/windows/flutter_windows.cc +++ b/shell/platform/windows/flutter_windows.cc
@@ -96,7 +96,7 @@ auto controller = std::make_unique<flutter::FlutterWindowsViewController>( std::move(engine), std::move(view)); - controller->view()->CreateRenderSurface(); + // Launch the engine if it is not running already. if (!controller->engine()->running()) { if (!controller->engine()->Run()) { return nullptr;
diff --git a/shell/platform/windows/flutter_windows_engine.cc b/shell/platform/windows/flutter_windows_engine.cc index 4884752..a92be61 100644 --- a/shell/platform/windows/flutter_windows_engine.cc +++ b/shell/platform/windows/flutter_windows_engine.cc
@@ -497,6 +497,8 @@ auto view = std::make_unique<FlutterWindowsView>( kImplicitViewId, this, std::move(window), windows_proc_table_); + view->CreateRenderSurface(); + views_[kImplicitViewId] = view.get(); return std::move(view);
diff --git a/shell/platform/windows/flutter_windows_view_unittests.cc b/shell/platform/windows/flutter_windows_view_unittests.cc index c22459f..61ae1b6 100644 --- a/shell/platform/windows/flutter_windows_view_unittests.cc +++ b/shell/platform/windows/flutter_windows_view_unittests.cc
@@ -87,6 +87,7 @@ GetTestProject(), std::move(windows_proc_table)); EngineModifier modifier(engine.get()); + modifier.SetEGLManager(nullptr); auto key_response_controller = std::make_shared<MockKeyResponseController>(); key_response_controller->SetChannelResponse( @@ -243,25 +244,38 @@ std::make_unique<NiceMock<MockWindowBindingHandler>>(); auto egl_manager = std::make_unique<egl::MockManager>(); auto surface = std::make_unique<egl::MockWindowSurface>(); + egl::MockContext render_context; auto engine_ptr = engine.get(); auto surface_ptr = surface.get(); + auto egl_manager_ptr = egl_manager.get(); EngineModifier modifier{engine.get()}; modifier.SetEGLManager(std::move(egl_manager)); + InSequence s; + std::unique_ptr<FlutterWindowsView> view; + + // Mock render surface initialization. { - std::unique_ptr<FlutterWindowsView> view = - engine->CreateView(std::move(window_binding_handler)); + EXPECT_CALL(*egl_manager_ptr, CreateWindowSurface) + .WillOnce(Return(std::move(surface))); + EXPECT_CALL(*engine_ptr, running).WillOnce(Return(false)); + EXPECT_CALL(*surface_ptr, IsValid).WillOnce(Return(true)); + EXPECT_CALL(*surface_ptr, MakeCurrent).WillOnce(Return(true)); + EXPECT_CALL(*surface_ptr, SetVSyncEnabled).WillOnce(Return(true)); + EXPECT_CALL(*egl_manager_ptr, render_context) + .WillOnce(Return(&render_context)); + EXPECT_CALL(render_context, ClearCurrent).WillOnce(Return(true)); + view = engine->CreateView(std::move(window_binding_handler)); + } + + // The view must be removed before the surface can be destroyed. + { auto view_id = view->view_id(); - ViewModifier view_modifier{view.get()}; - view_modifier.SetSurface(std::move(surface)); - FlutterWindowsViewController controller{std::move(engine), std::move(view)}; - // The view must be removed before the surface can be destroyed. - InSequence s; EXPECT_CALL(*engine_ptr, running).WillOnce(Return(true)); EXPECT_CALL(*engine_ptr, RemoveView(view_id)).Times(1); EXPECT_CALL(*engine_ptr, running).WillOnce(Return(true)); @@ -843,11 +857,22 @@ auto egl_manager = std::make_unique<egl::MockManager>(); auto surface = std::make_unique<egl::MockWindowSurface>(); auto resized_surface = std::make_unique<egl::MockWindowSurface>(); + egl::MockContext render_context; + + auto surface_ptr = surface.get(); auto resized_surface_ptr = resized_surface.get(); - EXPECT_CALL(*surface.get(), IsValid).WillRepeatedly(Return(true)); - EXPECT_CALL(*surface.get(), Destroy).WillOnce(Return(true)); + // Mock render surface creation + EXPECT_CALL(*egl_manager, CreateWindowSurface) + .WillOnce(Return(std::move(surface))); + EXPECT_CALL(*surface_ptr, IsValid).WillRepeatedly(Return(true)); + EXPECT_CALL(*surface_ptr, MakeCurrent).WillOnce(Return(true)); + EXPECT_CALL(*surface_ptr, SetVSyncEnabled).WillOnce(Return(true)); + EXPECT_CALL(*egl_manager, render_context).WillOnce(Return(&render_context)); + EXPECT_CALL(render_context, ClearCurrent).WillOnce(Return(true)); + // Mock render surface resize + EXPECT_CALL(*surface_ptr, Destroy).WillOnce(Return(true)); EXPECT_CALL(*egl_manager.get(), CreateWindowSurface(_, /*width=*/500, /*height=*/500)) .WillOnce(Return(std::move((resized_surface)))); @@ -862,9 +887,6 @@ std::unique_ptr<FlutterWindowsView> view = engine->CreateView( std::make_unique<NiceMock<MockWindowBindingHandler>>()); - ViewModifier view_modifier{view.get()}; - view_modifier.SetSurface(std::move(surface)); - fml::AutoResetWaitableEvent metrics_sent_latch; engine_modifier.embedder_api().SendWindowMetricsEvent = MOCK_ENGINE_PROC( SendWindowMetricsEvent, @@ -1441,8 +1463,6 @@ std::unique_ptr<FlutterWindowsView> view = engine->CreateView( std::make_unique<NiceMock<MockWindowBindingHandler>>()); - - view->CreateRenderSurface(); } // Blocks until the v-blank if it is enabled by the window. @@ -1478,8 +1498,6 @@ std::unique_ptr<FlutterWindowsView> view = engine->CreateView( std::make_unique<NiceMock<MockWindowBindingHandler>>()); - - view->CreateRenderSurface(); } // Don't block until the v-blank if it is disabled by the window. @@ -1523,8 +1541,6 @@ std::unique_ptr<FlutterWindowsView> view = engine->CreateView( std::make_unique<NiceMock<MockWindowBindingHandler>>()); - - view->CreateRenderSurface(); } // Blocks until the v-blank if it is enabled by the window. @@ -1571,8 +1587,6 @@ std::unique_ptr<FlutterWindowsView> view = engine->CreateView( std::make_unique<NiceMock<MockWindowBindingHandler>>()); - - view->CreateRenderSurface(); } // Desktop Window Manager composition can be disabled on Windows 7. @@ -1594,36 +1608,49 @@ return true; }); - EXPECT_CALL(*windows_proc_table.get(), DwmIsCompositionEnabled) - .WillOnce(Return(false)) - .WillOnce(Return(true)); - EXPECT_CALL(*egl_manager.get(), render_context) .WillRepeatedly(Return(&render_context)); EXPECT_CALL(*surface_ptr, IsValid).WillRepeatedly(Return(true)); + EXPECT_CALL(*surface_ptr, MakeCurrent).WillRepeatedly(Return(true)); + EXPECT_CALL(*surface_ptr, Destroy).Times(1); + EXPECT_CALL(render_context, ClearCurrent).WillRepeatedly(Return(true)); InSequence s; - EXPECT_CALL(*surface_ptr, MakeCurrent).WillOnce(Return(true)); - EXPECT_CALL(*surface_ptr, SetVSyncEnabled(true)).WillOnce(Return(true)); - EXPECT_CALL(render_context, ClearCurrent).WillOnce(Return(true)); - EXPECT_CALL(*surface_ptr, MakeCurrent).WillOnce(Return(true)); - EXPECT_CALL(*surface_ptr, SetVSyncEnabled(false)).WillOnce(Return(true)); - EXPECT_CALL(render_context, ClearCurrent).WillOnce(Return(true)); + // Mock render surface initialization. + std::unique_ptr<FlutterWindowsView> view; + { + EXPECT_CALL(*egl_manager, CreateWindowSurface) + .WillOnce(Return(std::move(surface))); + EXPECT_CALL(*windows_proc_table.get(), DwmIsCompositionEnabled) + .WillOnce(Return(true)); + EXPECT_CALL(*surface_ptr, SetVSyncEnabled).WillOnce(Return(true)); - EXPECT_CALL(*surface_ptr, Destroy).Times(1); + EngineModifier engine_modifier{engine.get()}; + engine_modifier.SetEGLManager(std::move(egl_manager)); - EngineModifier engine_modifier{engine.get()}; - engine_modifier.SetEGLManager(std::move(egl_manager)); + view = engine->CreateView( + std::make_unique<NiceMock<MockWindowBindingHandler>>()); + } - std::unique_ptr<FlutterWindowsView> view = engine->CreateView( - std::make_unique<NiceMock<MockWindowBindingHandler>>()); - ViewModifier view_modifier{view.get()}; - view_modifier.SetSurface(std::move(surface)); + // Disabling DWM composition should enable vsync blocking on the surface. + { + EXPECT_CALL(*windows_proc_table.get(), DwmIsCompositionEnabled) + .WillOnce(Return(false)); + EXPECT_CALL(*surface_ptr, SetVSyncEnabled(true)).WillOnce(Return(true)); - engine->OnDwmCompositionChanged(); - engine->OnDwmCompositionChanged(); + engine->OnDwmCompositionChanged(); + } + + // Enabling DWM composition should disable vsync blocking on the surface. + { + EXPECT_CALL(*windows_proc_table.get(), DwmIsCompositionEnabled) + .WillOnce(Return(true)); + EXPECT_CALL(*surface_ptr, SetVSyncEnabled(false)).WillOnce(Return(true)); + + engine->OnDwmCompositionChanged(); + } } } // namespace testing