-
Notifications
You must be signed in to change notification settings - Fork 6k
[Windows] Set swap interval on raster thread after startup #47787
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -36,6 +36,38 @@ bool SurfaceWillUpdate(size_t cur_width, | |
| (cur_height != target_height) || (cur_width != target_width); | ||
| return non_zero_target_dims && not_same_size; | ||
| } | ||
|
|
||
| /// Update the surface's swap interval to block until the v-blank iff | ||
| /// the system compositor is disabled. | ||
| void UpdateVsync(const FlutterWindowsEngine& engine, | ||
| const WindowBindingHandler& window) { | ||
| AngleSurfaceManager* surface_manager = engine.surface_manager(); | ||
| if (!surface_manager) { | ||
| return; | ||
| } | ||
|
|
||
| // Updating the vsync makes the EGL context and render surface current. | ||
| // If the engine is running, the render surface should only be made current on | ||
| // the raster thread. If the engine is initializing, the raster thread doesn't | ||
| // exist yet and the render surface can be made current on the platform | ||
| // thread. | ||
|
Comment on lines
+49
to
+53
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this operation safe/effective on either the raster or platform thread? Or in other words, should we expect it to work both before and after the engine initializes? And if so, what is the reasoning for posting it as a task only when it is possible to do so?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
No. The EGL context cannot be current on multiple threads. Since the raster thread uses the EGL context without any synchronization, other threads shouldn't use the EGL context at all while the raster thread exists. In other words, this operation must not run on the platform thread while the engine is running and the raster thread exists. However, the EGL context is unused before the engine is initialized. Thus, this operation is safe on the platform thread during startup.
Yup
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is achieved by running it on the platform thread when the engine is not initialized? Do we want to make the EGL context current at all on the platform thread in the case where there is not yet any raster thread?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Our end goal is to set the surface's swap interval to To update the swap interval, you first must first make the EGL context current. Ideally, only the raster thread would make the EGL context current. However, doing so would require us to update the swap intervals in 3 locations:
Using the platform thread allows us to remove that 2nd location by allowing us to update the swap interval whenever a view is created. |
||
| auto needs_vsync = window.NeedsVSync(); | ||
| if (engine.running()) { | ||
| engine.PostRasterThreadTask([surface_manager, needs_vsync]() { | ||
| surface_manager->SetVSyncEnabled(needs_vsync); | ||
| }); | ||
| } else { | ||
| surface_manager->SetVSyncEnabled(needs_vsync); | ||
|
|
||
| // Release the EGL context so that the raster thread can use it. | ||
| if (!surface_manager->ClearCurrent()) { | ||
| FML_LOG(ERROR) | ||
| << "Unable to clear current surface after updating the swap interval"; | ||
| return; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| } // namespace | ||
|
|
||
| FlutterWindowsView::FlutterWindowsView( | ||
|
|
@@ -580,15 +612,10 @@ bool FlutterWindowsView::PresentSoftwareBitmap(const void* allocation, | |
| void FlutterWindowsView::CreateRenderSurface() { | ||
| if (engine_ && engine_->surface_manager()) { | ||
| PhysicalWindowBounds bounds = binding_handler_->GetPhysicalWindowBounds(); | ||
| bool enable_vsync = binding_handler_->NeedsVSync(); | ||
| engine_->surface_manager()->CreateSurface(GetRenderTarget(), bounds.width, | ||
| bounds.height, enable_vsync); | ||
| bounds.height); | ||
|
|
||
| // The EGL context cannot be current on multiple threads. | ||
| // Creating the render surface runs on the platform thread and | ||
| // makes the EGL context current. Thus, the EGL context must be | ||
| // released so that the raster thread can use it for rendering. | ||
| engine_->surface_manager()->ClearCurrent(); | ||
| UpdateVsync(*engine_, *binding_handler_); | ||
|
|
||
| resize_target_width_ = bounds.width; | ||
| resize_target_height_ = bounds.height; | ||
|
|
@@ -660,24 +687,7 @@ void FlutterWindowsView::UpdateSemanticsEnabled(bool enabled) { | |
| } | ||
|
|
||
| void FlutterWindowsView::OnDwmCompositionChanged() { | ||
| AngleSurfaceManager* surface_manager = engine_->surface_manager(); | ||
| if (!surface_manager) { | ||
| return; | ||
| } | ||
|
|
||
| // Update the surface with the new composition state. | ||
| // Switch to the raster thread as the render EGL context can only be | ||
| // current on a single thread a time. | ||
| auto needs_vsync = binding_handler_->NeedsVSync(); | ||
| engine_->PostRasterThreadTask([surface_manager, needs_vsync]() { | ||
| if (!surface_manager->MakeCurrent()) { | ||
| FML_LOG(ERROR) | ||
| << "Unable to make surface current to update the swap interval"; | ||
| return; | ||
| } | ||
|
|
||
| surface_manager->SetVSyncEnabled(needs_vsync); | ||
| }); | ||
| UpdateVsync(*engine_, *binding_handler_); | ||
| } | ||
|
|
||
| void FlutterWindowsView::OnWindowStateEvent(HWND hwnd, WindowStateEvent event) { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.