compositor: Allow canvas to upload rendered contents asynchronously (#37776)

Adds epoch to each WR image op command that is sent to compositor. The
renderer now has a `FrameDelayer` data structure that is responsible for
tracking when a frame is ready to be displayed. When asking canvases to
update their rendering, they are given an optional `Epoch` which denotes
the `Document`'s canvas epoch. When all image updates for that `Epoch`
are seen in the renderer, the frame can be displayed.

Testing: Existing WPT tests
Fixes: #35733

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
Sam 2025-08-29 12:04:41 +02:00 committed by GitHub
parent 4700149fcb
commit 8beef6c21f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
36 changed files with 452 additions and 100 deletions

View file

@ -1458,6 +1458,9 @@ where
EmbedderToConstellationMessage::TickAnimation(webview_ids) => {
self.handle_tick_animation(webview_ids)
},
EmbedderToConstellationMessage::NoLongerWaitingOnAsynchronousImageUpdates(
pipeline_ids,
) => self.handle_no_longer_waiting_on_asynchronous_image_updates(pipeline_ids),
EmbedderToConstellationMessage::WebDriverCommand(command) => {
self.handle_webdriver_msg(command);
},
@ -3498,6 +3501,20 @@ where
}
}
#[servo_tracing::instrument(skip_all)]
fn handle_no_longer_waiting_on_asynchronous_image_updates(
&mut self,
pipeline_ids: Vec<PipelineId>,
) {
for pipeline_id in pipeline_ids.into_iter() {
if let Some(pipeline) = self.pipelines.get(&pipeline_id) {
let _ = pipeline.event_loop.send(
ScriptThreadMessage::NoLongerWaitingOnAsychronousImageUpdates(pipeline_id),
);
}
}
}
/// Schedule a navigation(via load_url).
/// 1: Ask the embedder for permission.
/// 2: Store the details of the navigation, pending approval from the embedder.

View file

@ -79,6 +79,9 @@ mod from_compositor {
Self::SendImageKeysForPipeline(..) => target!("SendImageKeysForPipeline"),
Self::SetWebDriverResponseSender(..) => target!("SetWebDriverResponseSender"),
Self::PreferencesUpdated(..) => target!("PreferencesUpdated"),
Self::NoLongerWaitingOnAsynchronousImageUpdates(..) => {
target!("NoLongerWaitingOnCanvas")
},
}
}
}