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

Send display lists over IPC in multiprocess mode. #6795

Merged
merged 6 commits into from Jul 31, 2015

gfx: Split the paint messages into layout and chrome messages, and make

the layout messages serializable.
  • Loading branch information
pcwalton committed Jul 31, 2015
commit 3be5bbbaa312fc9b83610d03c1a9807408230679
@@ -4,8 +4,7 @@

use surface_map::SurfaceMap;
use compositor_layer::{CompositorData, CompositorLayer, WantsScrollEventsFlag};
use compositor_task::{CompositorEventListener, CompositorProxy, CompositorReceiver};
use compositor_task::Msg;
use compositor_task::{CompositorEventListener, CompositorProxy, CompositorReceiver, Msg};
use constellation::SendableFrameTree;
use pipeline::CompositionPipeline;
use scrolling::ScrollingTimerProxy;
@@ -18,8 +17,7 @@ use euclid::rect::{Rect, TypedRect};
use euclid::scale_factor::ScaleFactor;
use euclid::size::{Size2D, TypedSize2D};
use gfx_traits::color;
use gfx::paint_task::Msg as PaintMsg;
use gfx::paint_task::PaintRequest;
use gfx::paint_task::{ChromeToPaintMsg, PaintRequest};
use gleam::gl::types::{GLint, GLsizei};
use gleam::gl;
use ipc_channel::ipc;
@@ -1306,8 +1304,8 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.convert_buffer_requests_to_pipeline_requests_map(layers_and_requests);

for (pipeline_id, requests) in pipeline_requests.into_iter() {
let msg = PaintMsg::Paint(requests, self.frame_tree_id);
let _ = self.get_pipeline(pipeline_id).paint_chan.send(msg);
let msg = ChromeToPaintMsg::Paint(requests, self.frame_tree_id);
let _ = self.get_pipeline(pipeline_id).chrome_to_paint_chan.send(msg);
}

true
@@ -11,8 +11,7 @@ use compositor_task;
use devtools_traits::{DevtoolsControlChan, DevtoolsControlMsg, ScriptToDevtoolsControlMsg};
use euclid::rect::{TypedRect};
use euclid::scale_factor::ScaleFactor;
use gfx::paint_task::Msg as PaintMsg;
use gfx::paint_task::{PaintChan, PaintTask};
use gfx::paint_task::{ChromeToPaintMsg, LayoutToPaintMsg, PaintTask};
use gfx::font_cache_task::FontCacheTask;
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use ipc_channel::router::ROUTER;
@@ -40,7 +39,7 @@ pub struct Pipeline {
pub script_chan: ScriptControlChan,
/// A channel to layout, for performing reflows and shutdown.
pub layout_chan: LayoutControlChan,
pub paint_chan: PaintChan,
pub chrome_to_paint_chan: Sender<ChromeToPaintMsg>,
pub layout_shutdown_port: Receiver<()>,
pub paint_shutdown_port: Receiver<()>,
/// URL corresponding to the most recently-loaded page.
@@ -60,7 +59,7 @@ pub struct CompositionPipeline {
pub id: PipelineId,
pub script_chan: ScriptControlChan,
pub layout_chan: LayoutControlChan,
pub paint_chan: PaintChan,
pub chrome_to_paint_chan: Sender<ChromeToPaintMsg>,
}

impl Pipeline {
@@ -84,7 +83,8 @@ impl Pipeline {
device_pixel_ratio: ScaleFactor<ViewportPx, DevicePixel, f32>)
-> (Pipeline, PipelineContent)
where LTF: LayoutTaskFactory, STF:ScriptTaskFactory {
let (paint_port, paint_chan) = PaintChan::new();
let (layout_to_paint_chan, layout_to_paint_port) = channel();
let (chrome_to_paint_chan, chrome_to_paint_port) = channel();
let (paint_shutdown_chan, paint_shutdown_port) = channel();
let (layout_shutdown_chan, layout_shutdown_port) = channel();
let (pipeline_chan, pipeline_port) = ipc::channel().unwrap();
@@ -123,7 +123,7 @@ impl Pipeline {
new_pipeline_id: id,
subpage_id: subpage_id,
load_data: load_data.clone(),
paint_chan: box paint_chan.clone() as Box<Any + Send>,
paint_chan: box layout_to_paint_chan.clone() as Box<Any + Send>,
failure: failure,
pipeline_port: mem::replace(&mut pipeline_port, None).unwrap(),
layout_shutdown_chan: layout_shutdown_chan.clone(),
@@ -144,7 +144,7 @@ impl Pipeline {
parent_info,
script_chan.clone(),
LayoutControlChan(pipeline_chan),
paint_chan.clone(),
chrome_to_paint_chan.clone(),
layout_shutdown_port,
paint_shutdown_port,
load_data.url.clone(),
@@ -167,8 +167,10 @@ impl Pipeline {
load_data: load_data,
failure: failure,
script_port: script_port,
paint_chan: paint_chan,
paint_port: Some(paint_port),
layout_to_paint_chan: layout_to_paint_chan,
chrome_to_paint_chan: chrome_to_paint_chan,
layout_to_paint_port: Some(layout_to_paint_port),
chrome_to_paint_port: Some(chrome_to_paint_port),
pipeline_port: pipeline_port,
paint_shutdown_chan: paint_shutdown_chan,
layout_shutdown_chan: layout_shutdown_chan,
@@ -181,7 +183,7 @@ impl Pipeline {
parent_info: Option<(PipelineId, SubpageId)>,
script_chan: ScriptControlChan,
layout_chan: LayoutControlChan,
paint_chan: PaintChan,
chrome_to_paint_chan: Sender<ChromeToPaintMsg>,
layout_shutdown_port: Receiver<()>,
paint_shutdown_port: Receiver<()>,
url: Url,
@@ -192,7 +194,7 @@ impl Pipeline {
parent_info: parent_info,
script_chan: script_chan,
layout_chan: layout_chan,
paint_chan: paint_chan,
chrome_to_paint_chan: chrome_to_paint_chan,
layout_shutdown_port: layout_shutdown_port,
paint_shutdown_port: paint_shutdown_port,
url: url,
@@ -204,12 +206,12 @@ impl Pipeline {
}

pub fn grant_paint_permission(&self) {
let _ = self.paint_chan.send(PaintMsg::PaintPermissionGranted);
drop(self.chrome_to_paint_chan.send(ChromeToPaintMsg::PaintPermissionGranted));
}

pub fn revoke_paint_permission(&self) {
debug!("pipeline revoking paint channel paint permission");
let _ = self.paint_chan.send(PaintMsg::PaintPermissionRevoked);
drop(self.chrome_to_paint_chan.send(ChromeToPaintMsg::PaintPermissionRevoked));
}

pub fn exit(&self, exit_type: PipelineExitType) {
@@ -242,7 +244,9 @@ impl Pipeline {
let _ = script_channel.send(
ConstellationControlMsg::ExitPipeline(self.id,
PipelineExitType::PipelineOnly)).unwrap();
let _ = self.paint_chan.send(PaintMsg::Exit(None, PipelineExitType::PipelineOnly));
let _ = self.chrome_to_paint_chan.send(ChromeToPaintMsg::Exit(
None,
PipelineExitType::PipelineOnly));
let LayoutControlChan(ref layout_channel) = self.layout_chan;
let _ = layout_channel.send(
LayoutControlMsg::ExitNow(PipelineExitType::PipelineOnly)).unwrap();
@@ -253,7 +257,7 @@ impl Pipeline {
id: self.id.clone(),
script_chan: self.script_chan.clone(),
layout_chan: self.layout_chan.clone(),
paint_chan: self.paint_chan.clone(),
chrome_to_paint_chan: self.chrome_to_paint_chan.clone(),
}
}

@@ -296,8 +300,10 @@ pub struct PipelineContent {
load_data: LoadData,
failure: Failure,
script_port: Option<Receiver<ConstellationControlMsg>>,
paint_chan: PaintChan,
paint_port: Option<Receiver<PaintMsg>>,
layout_to_paint_chan: Sender<LayoutToPaintMsg>,
chrome_to_paint_chan: Sender<ChromeToPaintMsg>,
layout_to_paint_port: Option<Receiver<LayoutToPaintMsg>>,
chrome_to_paint_port: Option<Receiver<ChromeToPaintMsg>>,
paint_shutdown_chan: Sender<()>,
pipeline_port: Option<IpcReceiver<LayoutControlMsg>>,
layout_shutdown_chan: Sender<()>,
@@ -344,7 +350,7 @@ impl PipelineContent {
self.constellation_chan,
self.failure,
self.script_chan.clone(),
self.paint_chan.clone(),
self.layout_to_paint_chan.clone(),
self.image_cache_task,
self.font_cache_task,
self.time_profiler_chan,
@@ -355,8 +361,9 @@ impl PipelineContent {
pub fn start_paint_task(&mut self) {
PaintTask::create(self.id,
self.load_data.url.clone(),
self.paint_chan.clone(),
mem::replace(&mut self.paint_port, None).unwrap(),
self.chrome_to_paint_chan.clone(),
mem::replace(&mut self.layout_to_paint_port, None).unwrap(),
mem::replace(&mut self.chrome_to_paint_port, None).unwrap(),
self.compositor_proxy.clone_compositor_proxy(),
self.constellation_chan.clone(),
self.font_cache_task.clone(),
@@ -9,6 +9,7 @@
#![feature(custom_derive)]
#![feature(hashmap_hasher)]
#![cfg_attr(any(target_os="linux", target_os = "android"), feature(heap_api))]
#![feature(mpsc_select)]
#![feature(plugin)]
#![feature(str_char)]
#![feature(vec_push_all)]
@@ -32,7 +32,7 @@ use skia::gl_context::GLContext;
use std::borrow::ToOwned;
use std::mem as std_mem;
use std::sync::Arc;
use std::sync::mpsc::{Receiver, Sender, channel};
use std::sync::mpsc::{Receiver, Select, Sender, channel};
use std::collections::HashMap;
use url::Url;
use util::geometry::{Au, ZERO_POINT};
@@ -72,38 +72,30 @@ pub struct PaintRequest {
}

pub enum Msg {
FromLayout(LayoutToPaintMsg),
FromChrome(ChromeToPaintMsg),
}

#[derive(Deserialize, Serialize)]
pub enum LayoutToPaintMsg {
PaintInit(Epoch, Arc<StackingContext>),
CanvasLayer(LayerId, IpcSender<CanvasMsg>),
Exit(Option<IpcSender<()>>, PipelineExitType),
}

pub enum ChromeToPaintMsg {
Paint(Vec<PaintRequest>, FrameTreeId),
PaintPermissionGranted,
PaintPermissionRevoked,
CollectReports(ReportsChan),
Exit(Option<Sender<()>>, PipelineExitType),
}

#[derive(Clone)]
pub struct PaintChan(Sender<Msg>);

impl PaintChan {
pub fn new() -> (Receiver<Msg>, PaintChan) {
let (chan, port) = channel();
(port, PaintChan(chan))
}

pub fn send(&self, msg: Msg) {
assert!(self.send_opt(msg).is_ok(), "PaintChan.send: paint port closed")
}

pub fn send_opt(&self, msg: Msg) -> Result<(), Msg> {
let &PaintChan(ref chan) = self;
chan.send(msg).map_err(|e| e.0)
}
Exit(Option<IpcSender<()>>, PipelineExitType),
}

pub struct PaintTask<C> {
id: PipelineId,
_url: Url,
port: Receiver<Msg>,
layout_to_paint_port: Receiver<LayoutToPaintMsg>,
chrome_to_paint_port: Receiver<ChromeToPaintMsg>,
compositor: C,
constellation_chan: ConstellationChan,

@@ -137,8 +129,9 @@ macro_rules! native_display(
impl<C> PaintTask<C> where C: PaintListener + Send + 'static {
pub fn create(id: PipelineId,
url: Url,
chan: PaintChan,
port: Receiver<Msg>,
chrome_to_paint_chan: Sender<ChromeToPaintMsg>,
layout_to_paint_port: Receiver<LayoutToPaintMsg>,
chrome_to_paint_port: Receiver<ChromeToPaintMsg>,
compositor: C,
constellation_chan: ConstellationChan,
font_cache_task: FontCacheTask,
@@ -162,7 +155,8 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static {
let mut paint_task = PaintTask {
id: id,
_url: url,
port: port,
layout_to_paint_port: layout_to_paint_port,
chrome_to_paint_port: chrome_to_paint_port,
compositor: compositor,
constellation_chan: constellation_chan,
time_profiler_chan: time_profiler_chan,
@@ -177,12 +171,12 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static {
let reporter_name = format!("paint-reporter-{}", id.0);
let (reporter_sender, reporter_receiver) =
ipc::channel::<ReporterRequest>().unwrap();
let paint_chan_for_reporter = chan.clone();
let paint_chan_for_reporter = chrome_to_paint_chan.clone();
ROUTER.add_route(reporter_receiver.to_opaque(), box move |message| {
// Just injects an appropriate event into the paint task's queue.
let request: ReporterRequest = message.to().unwrap();
paint_chan_for_reporter.0.send(Msg::CollectReports(request.reports_channel))
.unwrap();
paint_chan_for_reporter.send(ChromeToPaintMsg::CollectReports(
request.reports_channel)).unwrap();
});
mem_profiler_chan.send(mem::ProfilerMsg::RegisterReporter(
reporter_name.clone(),
@@ -208,8 +202,26 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static {
debug!("PaintTask: beginning painting loop");

loop {
match self.port.recv().unwrap() {
Msg::PaintInit(epoch, stacking_context) => {
let message = {
let select = Select::new();
let mut layout_to_paint_handle = select.handle(&self.layout_to_paint_port);
let mut chrome_to_paint_handle = select.handle(&self.chrome_to_paint_port);
unsafe {
layout_to_paint_handle.add();
chrome_to_paint_handle.add();
}
let result = select.wait();
if result == layout_to_paint_handle.id() {
Msg::FromLayout(self.layout_to_paint_port.recv().unwrap())
} else if result == chrome_to_paint_handle.id() {
Msg::FromChrome(self.chrome_to_paint_port.recv().unwrap())
} else {
panic!("unexpected select result")
}
};

match message {
Msg::FromLayout(LayoutToPaintMsg::PaintInit(epoch, stacking_context)) => {
self.current_epoch = Some(epoch);
self.root_stacking_context = Some(stacking_context.clone());

@@ -223,11 +235,11 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static {
self.initialize_layers();
}
// Inserts a new canvas renderer to the layer map
Msg::CanvasLayer(layer_id, canvas_renderer) => {
Msg::FromLayout(LayoutToPaintMsg::CanvasLayer(layer_id, canvas_renderer)) => {
debug!("Renderer received for canvas with layer {:?}", layer_id);
self.canvas_map.insert(layer_id, canvas_renderer);
}
Msg::Paint(requests, frame_tree_id) => {
Msg::FromChrome(ChromeToPaintMsg::Paint(requests, frame_tree_id)) => {
if !self.paint_permission {
debug!("PaintTask: paint ready msg");
let ConstellationChan(ref mut c) = self.constellation_chan;
@@ -254,27 +266,28 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static {
replies,
frame_tree_id);
}
Msg::PaintPermissionGranted => {
Msg::FromChrome(ChromeToPaintMsg::PaintPermissionGranted) => {
self.paint_permission = true;

if self.root_stacking_context.is_some() {
self.initialize_layers();
}
}
Msg::PaintPermissionRevoked => {
Msg::FromChrome(ChromeToPaintMsg::PaintPermissionRevoked) => {
self.paint_permission = false;
}
Msg::CollectReports(ref channel) => {
Msg::FromChrome(ChromeToPaintMsg::CollectReports(ref channel)) => {
// FIXME(njn): should eventually measure the paint task.
channel.send(Vec::new())
}
Msg::Exit(response_channel, _) => {
Msg::FromLayout(LayoutToPaintMsg::Exit(ref response_channel, _)) |
Msg::FromChrome(ChromeToPaintMsg::Exit(ref response_channel, _)) => {
// Ask the compositor to remove any layers it is holding for this paint task.
// FIXME(mrobinson): This can probably move back to the constellation now.
self.compositor.notify_paint_task_exiting(self.id);

debug!("PaintTask: Exiting.");
response_channel.map(|channel| channel.send(()));
response_channel.as_ref().map(|channel| channel.send(()));
break;
}
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.