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:
Josh Matthews 2020-06-08 13:53:33 -04:00
parent a6016b3a62
commit 75efaa95f5
16 changed files with 344 additions and 261 deletions

View file

@ -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" }

View file

@ -3,7 +3,9 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use crate::compositor_thread::CompositorReceiver;
use crate::compositor_thread::{InitialCompositorState, Msg};
use crate::compositor_thread::{
InitialCompositorState, Msg, WebrenderCanvasMsg, WebrenderFontMsg, WebrenderMsg,
};
#[cfg(feature = "gl")]
use crate::gl;
use crate::touch::{TouchAction, TouchHandler};
@ -11,10 +13,11 @@ use crate::windowing::{
self, EmbedderCoordinates, MouseWindowEvent, WebRenderDebugOption, WindowMethods,
};
use crate::{CompositionPipeline, ConstellationMsg, SendableFrameTree};
use canvas::canvas_paint_thread::ImageUpdate;
use crossbeam_channel::Sender;
use embedder_traits::Cursor;
use euclid::{Point2D, Rect, Scale, Vector2D};
use gfx_traits::Epoch;
use gfx_traits::{Epoch, FontData};
#[cfg(feature = "gl")]
use image::{DynamicImage, ImageFormat};
use ipc_channel::ipc;
@ -40,8 +43,6 @@ use std::fs::{create_dir_all, File};
use std::io::Write;
use std::num::NonZeroU32;
use std::rc::Rc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use style_traits::viewport::ViewportConstraints;
use style_traits::{CSSPixel, DevicePixel, PinchZoomFactor};
use time::{now, precise_time_ns, precise_time_s};
@ -218,7 +219,7 @@ pub struct IOCompositor<Window: WindowMethods + ?Sized> {
/// True if a WR frame render has been requested. Screenshots
/// taken before the render is complete will not reflect the
/// most up to date rendering.
waiting_on_pending_frame: Arc<AtomicBool>,
waiting_on_pending_frame: bool,
}
#[derive(Clone, Copy)]
@ -334,7 +335,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
is_running_problem_test,
exit_after_load,
convert_mouse_to_touch,
waiting_on_pending_frame: state.pending_wr_frame,
waiting_on_pending_frame: false,
}
}
@ -443,7 +444,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
},
(Msg::Recomposite(reason), ShutdownState::NotShuttingDown) => {
self.waiting_on_pending_frame.store(false, Ordering::SeqCst);
self.waiting_on_pending_frame = false;
self.composition_request = CompositionRequest::CompositeNow(reason)
},
@ -474,7 +475,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
self.ready_to_save_state,
ReadyState::WaitingForConstellationReply
);
if is_ready && !self.waiting_on_pending_frame.load(Ordering::SeqCst) {
if is_ready && !self.waiting_on_pending_frame {
self.ready_to_save_state = ReadyState::ReadyToSaveImage;
if self.is_running_problem_test {
println!("ready to save image!");
@ -569,6 +570,10 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
}
},
(Msg::Webrender(msg), ShutdownState::NotShuttingDown) => {
self.handle_webrender_message(msg);
},
// When we are shutting_down, we need to avoid performing operations
// such as Paint that may crash because we have begun tearing down
// the rest of our resources.
@ -578,6 +583,148 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
true
}
/// Accept messages from content processes that need to be relayed to the WebRender
/// instance in the parent process.
fn handle_webrender_message(&mut self, msg: WebrenderMsg) {
match msg {
WebrenderMsg::Layout(script_traits::WebrenderMsg::SendInitialTransaction(
_doc,
pipeline,
)) => {
self.waiting_on_pending_frame = true;
let mut txn = webrender_api::Transaction::new();
txn.set_display_list(
webrender_api::Epoch(0),
None,
Default::default(),
(pipeline, Default::default(), Default::default()),
false,
);
self.webrender_api
.send_transaction(self.webrender_document, txn);
},
WebrenderMsg::Layout(script_traits::WebrenderMsg::SendScrollNode(
_doc,
point,
scroll_id,
clamping,
)) => {
let mut txn = webrender_api::Transaction::new();
txn.scroll_node_with_id(point, scroll_id, clamping);
self.webrender_api
.send_transaction(self.webrender_document, txn);
},
WebrenderMsg::Layout(script_traits::WebrenderMsg::SendDisplayList(
_doc,
epoch,
size,
pipeline,
size2,
data,
descriptor,
)) => {
self.waiting_on_pending_frame = true;
let mut txn = webrender_api::Transaction::new();
txn.set_display_list(
epoch,
None,
size,
(
pipeline,
size2,
webrender_api::BuiltDisplayList::from_data(data, descriptor),
),
true,
);
txn.generate_frame();
self.webrender_api
.send_transaction(self.webrender_document, txn);
},
WebrenderMsg::Layout(script_traits::WebrenderMsg::HitTest(
_doc,
pipeline,
point,
flags,
sender,
)) => {
let result =
self.webrender_api
.hit_test(self.webrender_document, pipeline, point, flags);
let _ = sender.send(result);
},
WebrenderMsg::Layout(script_traits::WebrenderMsg::GenerateImageKey(sender)) |
WebrenderMsg::Net(net_traits::WebrenderImageMsg::GenerateImageKey(sender)) => {
let _ = sender.send(self.webrender_api.generate_image_key());
},
WebrenderMsg::Layout(script_traits::WebrenderMsg::UpdateImages(updates)) => {
let mut txn = webrender_api::Transaction::new();
for update in updates {
match update {
script_traits::ImageUpdate::AddImage(key, desc, data) => {
txn.add_image(key, desc, data, None)
},
script_traits::ImageUpdate::DeleteImage(key) => txn.delete_image(key),
script_traits::ImageUpdate::UpdateImage(key, desc, data) => {
txn.update_image(key, desc, data, &webrender_api::DirtyRect::All)
},
}
}
self.webrender_api
.send_transaction(self.webrender_document, txn);
},
WebrenderMsg::Net(net_traits::WebrenderImageMsg::AddImage(key, desc, data)) => {
let mut txn = webrender_api::Transaction::new();
txn.add_image(key, desc, data, None);
self.webrender_api
.send_transaction(self.webrender_document, txn);
},
WebrenderMsg::Font(WebrenderFontMsg::AddFontInstance(font_key, size, sender)) => {
let key = self.webrender_api.generate_font_instance_key();
let mut txn = webrender_api::Transaction::new();
txn.add_font_instance(key, font_key, size, None, None, Vec::new());
self.webrender_api
.send_transaction(self.webrender_document, txn);
let _ = sender.send(key);
},
WebrenderMsg::Font(WebrenderFontMsg::AddFont(data, sender)) => {
let font_key = self.webrender_api.generate_font_key();
let mut txn = webrender_api::Transaction::new();
match data {
FontData::Raw(bytes) => txn.add_raw_font(font_key, bytes, 0),
FontData::Native(native_font) => txn.add_native_font(font_key, native_font),
}
self.webrender_api
.send_transaction(self.webrender_document, txn);
let _ = sender.send(font_key);
},
WebrenderMsg::Canvas(WebrenderCanvasMsg::GenerateKey(sender)) => {
let _ = sender.send(self.webrender_api.generate_image_key());
},
WebrenderMsg::Canvas(WebrenderCanvasMsg::UpdateImages(updates)) => {
let mut txn = webrender_api::Transaction::new();
for update in updates {
match update {
ImageUpdate::Add(key, descriptor, data) => {
txn.add_image(key, descriptor, data, None)
},
ImageUpdate::Update(key, descriptor, data) => {
txn.update_image(key, descriptor, data, &webrender_api::DirtyRect::All)
},
ImageUpdate::Delete(key) => txn.delete_image(key),
}
}
self.webrender_api
.send_transaction(self.webrender_document, txn);
},
}
}
/// Sets or unsets the animations-running flag for the given pipeline, and schedules a
/// recomposite if necessary.
fn change_running_animations_state(

View file

@ -6,6 +6,7 @@
use crate::compositor::CompositingReason;
use crate::{ConstellationMsg, SendableFrameTree};
use canvas::canvas_paint_thread::ImageUpdate;
use crossbeam_channel::{Receiver, Sender};
use embedder_traits::EventLoopWaker;
use euclid::Rect;
@ -18,8 +19,6 @@ use profile_traits::time;
use script_traits::{AnimationState, EventResult, MouseButton, MouseEventType};
use std::fmt::{Debug, Error, Formatter};
use std::rc::Rc;
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
use style_traits::viewport::ViewportConstraints;
use style_traits::CSSPixel;
use webrender_api;
@ -122,6 +121,30 @@ pub enum Msg {
GetScreenSize(IpcSender<DeviceIntSize>),
/// Get screen available size.
GetScreenAvailSize(IpcSender<DeviceIntSize>),
/// Webrender operations requested from non-compositor threads.
Webrender(WebrenderMsg),
}
pub enum WebrenderFontMsg {
AddFontInstance(
webrender_api::FontKey,
app_units::Au,
Sender<webrender_api::FontInstanceKey>,
),
AddFont(gfx_traits::FontData, Sender<webrender_api::FontKey>),
}
pub enum WebrenderCanvasMsg {
GenerateKey(Sender<webrender_api::ImageKey>),
UpdateImages(Vec<ImageUpdate>),
}
pub enum WebrenderMsg {
Layout(script_traits::WebrenderMsg),
Net(net_traits::WebrenderImageMsg),
Font(WebrenderFontMsg),
Canvas(WebrenderCanvasMsg),
}
impl Debug for Msg {
@ -148,6 +171,7 @@ impl Debug for Msg {
Msg::GetClientWindow(..) => write!(f, "GetClientWindow"),
Msg::GetScreenSize(..) => write!(f, "GetScreenSize"),
Msg::GetScreenAvailSize(..) => write!(f, "GetScreenAvailSize"),
Msg::Webrender(..) => write!(f, "Webrender"),
}
}
}
@ -171,5 +195,4 @@ pub struct InitialCompositorState {
pub webrender_surfman: WebrenderSurfman,
pub webrender_gl: Rc<dyn gleam::gl::Gl>,
pub webxr_main_thread: webxr::MainThreadRegistry,
pub pending_wr_frame: Arc<AtomicBool>,
}