Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update webrender #26823

Merged
merged 4 commits into from Jun 9, 2020
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Some generated files are not rendered by default. Learn more.

@@ -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,
@@ -26,8 +26,6 @@ pub enum ConstellationCanvasMsg {
Create {
id_sender: Sender<CanvasId>,
size: Size2D<u64>,
webrender_sender: webrender_api::RenderApiSender,
webrender_doc: webrender_api::DocumentId,
antialias: bool,
},
Exit,
@@ -16,6 +16,7 @@ default = []
gl = ["gleam", "pixels"]

[dependencies]
app_units = "0.7"
canvas = { path = "../canvas" }
crossbeam-channel = "0.4"
embedder_traits = { path = "../embedder_traits" }
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.