mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
Proxy all WR interactions for layout/font/script/canvas threads to the compositor
thread. There is now a single RenderApi that is used, and all transactions are serialized through the compositor.
This commit is contained in:
parent
a6016b3a62
commit
75efaa95f5
16 changed files with 344 additions and 261 deletions
|
@ -2,7 +2,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use crate::canvas_paint_thread::AntialiasMode;
|
||||
use crate::canvas_paint_thread::{AntialiasMode, ImageUpdate, WebrenderApi};
|
||||
use crate::raqote_backend::Repetition;
|
||||
use canvas_traits::canvas::*;
|
||||
use cssparser::RGBA;
|
||||
|
@ -13,7 +13,6 @@ use num_traits::ToPrimitive;
|
|||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::sync::Arc;
|
||||
use webrender::api::DirtyRect;
|
||||
use webrender_api::units::RectExt as RectExt_;
|
||||
|
||||
/// The canvas data stores a state machine for the current status of
|
||||
|
@ -367,8 +366,7 @@ pub struct CanvasData<'a> {
|
|||
path_state: Option<PathState>,
|
||||
state: CanvasPaintState<'a>,
|
||||
saved_states: Vec<CanvasPaintState<'a>>,
|
||||
webrender_api: webrender_api::RenderApi,
|
||||
webrender_doc: webrender_api::DocumentId,
|
||||
webrender_api: Box<dyn WebrenderApi>,
|
||||
image_key: Option<webrender_api::ImageKey>,
|
||||
/// An old webrender image key that can be deleted when the next epoch ends.
|
||||
old_image_key: Option<webrender_api::ImageKey>,
|
||||
|
@ -384,22 +382,19 @@ fn create_backend() -> Box<dyn Backend> {
|
|||
impl<'a> CanvasData<'a> {
|
||||
pub fn new(
|
||||
size: Size2D<u64>,
|
||||
webrender_api_sender: webrender_api::RenderApiSender,
|
||||
webrender_doc: webrender_api::DocumentId,
|
||||
webrender_api: Box<dyn WebrenderApi>,
|
||||
antialias: AntialiasMode,
|
||||
canvas_id: CanvasId,
|
||||
) -> CanvasData<'a> {
|
||||
let backend = create_backend();
|
||||
let draw_target = backend.create_drawtarget(size);
|
||||
let webrender_api = webrender_api_sender.create_api();
|
||||
CanvasData {
|
||||
backend,
|
||||
drawtarget: draw_target,
|
||||
path_state: None,
|
||||
state: CanvasPaintState::new(antialias),
|
||||
saved_states: vec![],
|
||||
webrender_api: webrender_api,
|
||||
webrender_doc,
|
||||
webrender_api,
|
||||
image_key: None,
|
||||
old_image_key: None,
|
||||
very_old_image_key: None,
|
||||
|
@ -979,27 +974,28 @@ impl<'a> CanvasData<'a> {
|
|||
let data = self.drawtarget.snapshot_data_owned();
|
||||
let data = webrender_api::ImageData::Raw(Arc::new(data));
|
||||
|
||||
let mut txn = webrender_api::Transaction::new();
|
||||
let mut updates = vec![];
|
||||
|
||||
match self.image_key {
|
||||
Some(image_key) => {
|
||||
debug!("Updating image {:?}.", image_key);
|
||||
txn.update_image(image_key, descriptor, data, &DirtyRect::All);
|
||||
updates.push(ImageUpdate::Update(image_key, descriptor, data));
|
||||
},
|
||||
None => {
|
||||
self.image_key = Some(self.webrender_api.generate_image_key());
|
||||
let key = self.webrender_api.generate_key();
|
||||
updates.push(ImageUpdate::Add(key, descriptor, data));
|
||||
self.image_key = Some(key);
|
||||
debug!("New image {:?}.", self.image_key);
|
||||
txn.add_image(self.image_key.unwrap(), descriptor, data, None);
|
||||
},
|
||||
}
|
||||
|
||||
if let Some(image_key) =
|
||||
mem::replace(&mut self.very_old_image_key, self.old_image_key.take())
|
||||
{
|
||||
txn.delete_image(image_key);
|
||||
updates.push(ImageUpdate::Delete(image_key));
|
||||
}
|
||||
|
||||
self.webrender_api.send_transaction(self.webrender_doc, txn);
|
||||
self.webrender_api.update_images(updates);
|
||||
|
||||
let data = CanvasImageData {
|
||||
image_key: self.image_key.unwrap(),
|
||||
|
@ -1110,16 +1106,15 @@ impl<'a> CanvasData<'a> {
|
|||
|
||||
impl<'a> Drop for CanvasData<'a> {
|
||||
fn drop(&mut self) {
|
||||
let mut txn = webrender_api::Transaction::new();
|
||||
|
||||
let mut updates = vec![];
|
||||
if let Some(image_key) = self.old_image_key.take() {
|
||||
txn.delete_image(image_key);
|
||||
updates.push(ImageUpdate::Delete(image_key));
|
||||
}
|
||||
if let Some(image_key) = self.very_old_image_key.take() {
|
||||
txn.delete_image(image_key);
|
||||
updates.push(ImageUpdate::Delete(image_key));
|
||||
}
|
||||
|
||||
self.webrender_api.send_transaction(self.webrender_doc, txn);
|
||||
self.webrender_api.update_images(updates);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,35 +12,52 @@ use ipc_channel::router::ROUTER;
|
|||
use std::borrow::ToOwned;
|
||||
use std::collections::HashMap;
|
||||
use std::thread;
|
||||
use webrender_api::{ImageData, ImageDescriptor, ImageKey};
|
||||
|
||||
pub enum AntialiasMode {
|
||||
Default,
|
||||
None,
|
||||
}
|
||||
|
||||
pub enum ImageUpdate {
|
||||
Add(ImageKey, ImageDescriptor, ImageData),
|
||||
Update(ImageKey, ImageDescriptor, ImageData),
|
||||
Delete(ImageKey),
|
||||
}
|
||||
|
||||
pub trait WebrenderApi {
|
||||
fn generate_key(&self) -> webrender_api::ImageKey;
|
||||
fn update_images(&self, updates: Vec<ImageUpdate>);
|
||||
fn clone(&self) -> Box<dyn WebrenderApi>;
|
||||
}
|
||||
|
||||
pub struct CanvasPaintThread<'a> {
|
||||
canvases: HashMap<CanvasId, CanvasData<'a>>,
|
||||
next_canvas_id: CanvasId,
|
||||
webrender_api: Box<dyn WebrenderApi>,
|
||||
}
|
||||
|
||||
impl<'a> CanvasPaintThread<'a> {
|
||||
fn new() -> CanvasPaintThread<'a> {
|
||||
fn new(webrender_api: Box<dyn WebrenderApi>) -> CanvasPaintThread<'a> {
|
||||
CanvasPaintThread {
|
||||
canvases: HashMap::new(),
|
||||
next_canvas_id: CanvasId(0),
|
||||
webrender_api,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new `CanvasPaintThread` and returns an `IpcSender` to
|
||||
/// communicate with it.
|
||||
pub fn start() -> (Sender<ConstellationCanvasMsg>, IpcSender<CanvasMsg>) {
|
||||
pub fn start(
|
||||
webrender_api: Box<dyn WebrenderApi + Send>,
|
||||
) -> (Sender<ConstellationCanvasMsg>, IpcSender<CanvasMsg>) {
|
||||
let (ipc_sender, ipc_receiver) = ipc::channel::<CanvasMsg>().unwrap();
|
||||
let msg_receiver = ROUTER.route_ipc_receiver_to_new_crossbeam_receiver(ipc_receiver);
|
||||
let (create_sender, create_receiver) = unbounded();
|
||||
thread::Builder::new()
|
||||
.name("CanvasThread".to_owned())
|
||||
.spawn(move || {
|
||||
let mut canvas_paint_thread = CanvasPaintThread::new();
|
||||
let mut canvas_paint_thread = CanvasPaintThread::new(webrender_api);
|
||||
loop {
|
||||
select! {
|
||||
recv(msg_receiver) -> msg => {
|
||||
|
@ -74,16 +91,9 @@ impl<'a> CanvasPaintThread<'a> {
|
|||
Ok(ConstellationCanvasMsg::Create {
|
||||
id_sender: creator,
|
||||
size,
|
||||
webrender_sender: webrenderer_api_sender,
|
||||
webrender_doc,
|
||||
antialias
|
||||
}) => {
|
||||
let canvas_id = canvas_paint_thread.create_canvas(
|
||||
size,
|
||||
webrenderer_api_sender,
|
||||
webrender_doc,
|
||||
antialias,
|
||||
);
|
||||
let canvas_id = canvas_paint_thread.create_canvas(size, antialias);
|
||||
creator.send(canvas_id).unwrap();
|
||||
},
|
||||
Ok(ConstellationCanvasMsg::Exit) => break,
|
||||
|
@ -101,13 +111,7 @@ impl<'a> CanvasPaintThread<'a> {
|
|||
(create_sender, ipc_sender)
|
||||
}
|
||||
|
||||
pub fn create_canvas(
|
||||
&mut self,
|
||||
size: Size2D<u64>,
|
||||
webrender_api_sender: webrender_api::RenderApiSender,
|
||||
webrender_doc: webrender_api::DocumentId,
|
||||
antialias: bool,
|
||||
) -> CanvasId {
|
||||
pub fn create_canvas(&mut self, size: Size2D<u64>, antialias: bool) -> CanvasId {
|
||||
let antialias = if antialias {
|
||||
AntialiasMode::Default
|
||||
} else {
|
||||
|
@ -119,8 +123,7 @@ impl<'a> CanvasPaintThread<'a> {
|
|||
|
||||
let canvas_data = CanvasData::new(
|
||||
size,
|
||||
webrender_api_sender,
|
||||
webrender_doc,
|
||||
self.webrender_api.clone(),
|
||||
antialias,
|
||||
canvas_id.clone(),
|
||||
);
|
||||
|
|
|
@ -655,7 +655,7 @@ impl WebGLThread {
|
|||
);
|
||||
|
||||
let image_key = Self::create_wr_external_image(
|
||||
&self.webrender_api,
|
||||
&mut self.webrender_api,
|
||||
self.webrender_doc,
|
||||
size.to_i32(),
|
||||
has_alpha,
|
||||
|
@ -718,7 +718,7 @@ impl WebGLThread {
|
|||
.contains(ContextAttributeFlags::ALPHA);
|
||||
let texture_target = current_wr_texture_target(&self.device);
|
||||
Self::update_wr_external_image(
|
||||
&self.webrender_api,
|
||||
&mut self.webrender_api,
|
||||
self.webrender_doc,
|
||||
size.to_i32(),
|
||||
has_alpha,
|
||||
|
@ -1021,7 +1021,7 @@ impl WebGLThread {
|
|||
|
||||
/// Creates a `webrender_api::ImageKey` that uses shared textures.
|
||||
fn create_wr_external_image(
|
||||
webrender_api: &webrender_api::RenderApi,
|
||||
webrender_api: &mut webrender_api::RenderApi,
|
||||
webrender_doc: webrender_api::DocumentId,
|
||||
size: Size2D<i32>,
|
||||
alpha: bool,
|
||||
|
@ -1041,7 +1041,7 @@ impl WebGLThread {
|
|||
|
||||
/// Updates a `webrender_api::ImageKey` that uses shared textures.
|
||||
fn update_wr_external_image(
|
||||
webrender_api: &webrender_api::RenderApi,
|
||||
webrender_api: &mut webrender_api::RenderApi,
|
||||
webrender_doc: webrender_api::DocumentId,
|
||||
size: Size2D<i32>,
|
||||
alpha: bool,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue