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

@ -8,6 +8,7 @@ use std::slice;
use std::sync::{Arc, Mutex};
use arrayvec::ArrayVec;
use base::Epoch;
use compositing_traits::{
CrossProcessCompositorApi, ExternalImageSource, SerializableImageData,
WebrenderExternalImageApi,
@ -425,6 +426,7 @@ impl crate::WGPU {
context_data.image_key,
context_data.image_desc.0,
SerializableImageData::External(context_data.image_data),
None,
);
}
}
@ -435,6 +437,7 @@ impl crate::WGPU {
context_id: WebGPUContextId,
encoder_id: id::Id<id::markers::CommandEncoder>,
texture_id: id::Id<id::markers::Texture>,
canvas_epoch: Option<Epoch>,
) -> Result<(), Box<dyn std::error::Error>> {
fn err<T: std::error::Error + 'static>(e: Option<T>) -> Result<(), T> {
if let Some(error) = e {
@ -518,6 +521,7 @@ impl crate::WGPU {
compositor_api,
image_desc,
presentation_id,
canvas_epoch,
);
})
};
@ -550,6 +554,7 @@ fn update_wr_image(
compositor_api: CrossProcessCompositorApi,
image_desc: WebGPUImageDescriptor,
presentation_id: PresentationId,
canvas_epoch: Option<Epoch>,
) {
match result {
Ok(()) => {
@ -577,6 +582,7 @@ fn update_wr_image(
context_data.image_key,
context_data.image_desc.0,
SerializableImageData::External(context_data.image_data),
canvas_epoch,
);
if let Some(old_presentation_buffer) = old_presentation_buffer {
context_data.unmap_old_buffer(old_presentation_buffer)

View file

@ -520,8 +520,14 @@ impl WGPU {
context_id,
texture_id,
encoder_id,
canvas_epoch,
} => {
let result = self.swapchain_present(context_id, encoder_id, texture_id);
let result = self.swapchain_present(
context_id,
encoder_id,
texture_id,
canvas_epoch,
);
if let Err(e) = result {
log::error!("Error occured in SwapChainPresent: {e:?}");
}