mirror of
https://github.com/servo/servo.git
synced 2025-09-30 08:39:16 +01:00
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:
parent
4700149fcb
commit
8beef6c21f
36 changed files with 452 additions and 100 deletions
|
@ -6,6 +6,7 @@ use std::borrow::Cow;
|
|||
use std::cell::RefCell;
|
||||
|
||||
use arrayvec::ArrayVec;
|
||||
use base::Epoch;
|
||||
use dom_struct::dom_struct;
|
||||
use ipc_channel::ipc::{self};
|
||||
use pixels::Snapshot;
|
||||
|
@ -183,19 +184,29 @@ impl GPUCanvasContext {
|
|||
}
|
||||
|
||||
/// <https://gpuweb.github.io/gpuweb/#abstract-opdef-expire-the-current-texture>
|
||||
fn expire_current_texture(&self) {
|
||||
if let Some(current_texture) = self.current_texture.take() {
|
||||
// Make copy of texture content
|
||||
self.send_swap_chain_present(current_texture.id());
|
||||
// Step 1
|
||||
current_texture.Destroy()
|
||||
}
|
||||
fn expire_current_texture(&self, canvas_epoch: Option<Epoch>) -> bool {
|
||||
// Step 1: If context.[[currentTexture]] is not null:
|
||||
let Some(current_texture) = self.current_texture.take() else {
|
||||
return false;
|
||||
};
|
||||
|
||||
// Make copy of texture content
|
||||
let did_swap = self.send_swap_chain_present(current_texture.id(), canvas_epoch);
|
||||
|
||||
// Step 1.1: Call context.currentTexture.destroy() (without destroying
|
||||
// context.drawingBuffer) to terminate write access to the image.
|
||||
current_texture.Destroy();
|
||||
|
||||
// Step 1.2: Set context.[[currentTexture]] to null.
|
||||
// This is handled by the call to `.take()` above.
|
||||
|
||||
did_swap
|
||||
}
|
||||
|
||||
/// <https://gpuweb.github.io/gpuweb/#abstract-opdef-replace-the-drawing-buffer>
|
||||
fn replace_drawing_buffer(&self) {
|
||||
// Step 1
|
||||
self.expire_current_texture();
|
||||
self.expire_current_texture(None);
|
||||
// Step 2
|
||||
let configuration = self.configuration.borrow();
|
||||
// Step 3
|
||||
|
@ -234,19 +245,28 @@ impl GPUCanvasContext {
|
|||
}
|
||||
}
|
||||
|
||||
fn send_swap_chain_present(&self, texture_id: WebGPUTexture) {
|
||||
fn send_swap_chain_present(
|
||||
&self,
|
||||
texture_id: WebGPUTexture,
|
||||
canvas_epoch: Option<Epoch>,
|
||||
) -> bool {
|
||||
self.drawing_buffer.borrow_mut().cleared = false;
|
||||
let encoder_id = self.global().wgpu_id_hub().create_command_encoder_id();
|
||||
if let Err(e) = self.channel.0.send(WebGPURequest::SwapChainPresent {
|
||||
let send_result = self.channel.0.send(WebGPURequest::SwapChainPresent {
|
||||
context_id: self.context_id,
|
||||
texture_id: texture_id.0,
|
||||
encoder_id,
|
||||
}) {
|
||||
canvas_epoch,
|
||||
});
|
||||
|
||||
if let Err(error) = &send_result {
|
||||
warn!(
|
||||
"Failed to send UpdateWebrenderData({:?}) ({})",
|
||||
self.context_id, e
|
||||
"Failed to send UpdateWebrenderData({:?}) ({error})",
|
||||
self.context_id,
|
||||
);
|
||||
}
|
||||
|
||||
send_result.is_ok()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -258,9 +278,19 @@ impl CanvasContext for GPUCanvasContext {
|
|||
}
|
||||
|
||||
/// <https://gpuweb.github.io/gpuweb/#abstract-opdef-updating-the-rendering-of-a-webgpu-canvas>
|
||||
fn update_rendering(&self) {
|
||||
// Step 1
|
||||
self.expire_current_texture();
|
||||
fn update_rendering(&self, canvas_epoch: Option<Epoch>) -> bool {
|
||||
if !self.onscreen() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 1: Expire the current texture of context.
|
||||
self.expire_current_texture(canvas_epoch)
|
||||
// Step 2: Set context.[[lastPresentedImage]] to context.[[drawingBuffer]].
|
||||
// TODO: Implement this.
|
||||
}
|
||||
|
||||
fn image_key(&self) -> Option<ImageKey> {
|
||||
Some(self.webrender_image)
|
||||
}
|
||||
|
||||
/// <https://gpuweb.github.io/gpuweb/#abstract-opdef-update-the-canvas-size>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue