diff options
author | Glenn Watson <github@intuitionlibrary.com> | 2016-10-12 10:13:27 +1000 |
---|---|---|
committer | Glenn Watson <github@intuitionlibrary.com> | 2016-10-18 10:21:27 +1000 |
commit | acfdfd2fa98562c9f891fbee2dbc3424803c1a3c (patch) | |
tree | bc66667bab89db2ab6a1c4d4113525190fb82d3a | |
parent | 4af21e3ae1676f943a9a01688fef854487bcddfc (diff) | |
download | servo-acfdfd2fa98562c9f891fbee2dbc3424803c1a3c.tar.gz servo-acfdfd2fa98562c9f891fbee2dbc3424803c1a3c.zip |
Remove old rendering backend.
This removes paint threads, rust-layers dependency, and changes
optional webrender types to be required.
The use_webrender option has been removed, however I've left
the "-w" command line option in place so that wpt
runner can continue to pass that. Once it's removed from there
we can also remove the -w option.
Once this stage is complete, it should be fine to change the
display list building code to generate webrender display
lists directly and avoid the conversion step.
55 files changed, 426 insertions, 3615 deletions
diff --git a/components/canvas/canvas_paint_thread.rs b/components/canvas/canvas_paint_thread.rs index ef084dde9d9..238ff9c06db 100644 --- a/components/canvas/canvas_paint_thread.rs +++ b/components/canvas/canvas_paint_thread.rs @@ -58,8 +58,8 @@ pub struct CanvasPaintThread<'a> { path_builder: PathBuilder, state: CanvasPaintState<'a>, saved_states: Vec<CanvasPaintState<'a>>, - webrender_api: Option<webrender_traits::RenderApi>, - webrender_image_key: Option<webrender_traits::ImageKey>, + webrender_api: webrender_traits::RenderApi, + webrender_image_key: webrender_traits::ImageKey, } #[derive(Clone)] @@ -100,12 +100,12 @@ impl<'a> CanvasPaintState<'a> { impl<'a> CanvasPaintThread<'a> { fn new(size: Size2D<i32>, - webrender_api_sender: Option<webrender_traits::RenderApiSender>, + webrender_api_sender: webrender_traits::RenderApiSender, antialias: bool) -> CanvasPaintThread<'a> { let draw_target = CanvasPaintThread::create(size); let path_builder = draw_target.create_path_builder(); - let webrender_api = webrender_api_sender.map(|wr| wr.create_api()); - let webrender_image_key = webrender_api.as_ref().map(|wr| wr.alloc_image()); + let webrender_api = webrender_api_sender.create_api(); + let webrender_image_key = webrender_api.alloc_image(); CanvasPaintThread { drawtarget: draw_target, path_builder: path_builder, @@ -119,7 +119,7 @@ impl<'a> CanvasPaintThread<'a> { /// Creates a new `CanvasPaintThread` and returns an `IpcSender` to /// communicate with it. pub fn start(size: Size2D<i32>, - webrender_api_sender: Option<webrender_traits::RenderApiSender>, + webrender_api_sender: webrender_traits::RenderApiSender, antialias: bool) -> IpcSender<CanvasMsg> { let (sender, receiver) = ipc::channel::<CanvasMsg>().unwrap(); @@ -542,14 +542,12 @@ impl<'a> CanvasPaintThread<'a> { fn send_data(&mut self, chan: IpcSender<CanvasData>) { self.drawtarget.snapshot().get_data_surface().with_data(|element| { - if let Some(ref webrender_api) = self.webrender_api { - let size = self.drawtarget.get_size(); - webrender_api.update_image(self.webrender_image_key.unwrap(), - size.width as u32, - size.height as u32, - webrender_traits::ImageFormat::RGBA8, - element.into()); - } + let size = self.drawtarget.get_size(); + self.webrender_api.update_image(self.webrender_image_key, + size.width as u32, + size.height as u32, + webrender_traits::ImageFormat::RGBA8, + element.into()); let pixel_data = CanvasPixelData { image_data: IpcSharedMemory::from_bytes(element), @@ -710,9 +708,7 @@ impl<'a> CanvasPaintThread<'a> { impl<'a> Drop for CanvasPaintThread<'a> { fn drop(&mut self) { - if let Some(ref mut wr) = self.webrender_api { - wr.delete_image(self.webrender_image_key.unwrap()); - } + self.webrender_api.delete_image(self.webrender_image_key); } } diff --git a/components/canvas/webgl_paint_thread.rs b/components/canvas/webgl_paint_thread.rs index a7a0859276c..88ab2080a81 100644 --- a/components/canvas/webgl_paint_thread.rs +++ b/components/canvas/webgl_paint_thread.rs @@ -87,7 +87,7 @@ impl GLContextWrapper { enum WebGLPaintTaskData { WebRender(webrender_traits::RenderApi, webrender_traits::WebGLContextId), - Readback(GLContextWrapper, (Option<(webrender_traits::RenderApi, webrender_traits::ImageKey)>)), + Readback(GLContextWrapper, webrender_traits::RenderApi, webrender_traits::ImageKey), } pub struct WebGLPaintThread { @@ -97,17 +97,14 @@ pub struct WebGLPaintThread { fn create_readback_painter(size: Size2D<i32>, attrs: GLContextAttributes, - webrender_api: Option<webrender_traits::RenderApi>) + webrender_api: webrender_traits::RenderApi) -> Result<(WebGLPaintThread, GLLimits), String> { let context = try!(GLContextWrapper::new(size, attrs)); let limits = context.get_limits(); - let webrender_api_and_image_key = webrender_api.map(|wr| { - let key = wr.alloc_image(); - (wr, key) - }); + let image_key = webrender_api.alloc_image(); let painter = WebGLPaintThread { size: size, - data: WebGLPaintTaskData::Readback(context, webrender_api_and_image_key) + data: WebGLPaintTaskData::Readback(context, webrender_api, image_key) }; Ok((painter, limits)) @@ -116,25 +113,21 @@ fn create_readback_painter(size: Size2D<i32>, impl WebGLPaintThread { fn new(size: Size2D<i32>, attrs: GLContextAttributes, - webrender_api_sender: Option<webrender_traits::RenderApiSender>) + webrender_api_sender: webrender_traits::RenderApiSender) -> Result<(WebGLPaintThread, GLLimits), String> { - if let Some(sender) = webrender_api_sender { - let wr_api = sender.create_api(); - match wr_api.request_webgl_context(&size, attrs) { - Ok((id, limits)) => { - let painter = WebGLPaintThread { - data: WebGLPaintTaskData::WebRender(wr_api, id), - size: size - }; - Ok((painter, limits)) - }, - Err(msg) => { - warn!("Initial context creation failed, falling back to readback: {}", msg); - create_readback_painter(size, attrs, Some(wr_api)) - } + let wr_api = webrender_api_sender.create_api(); + match wr_api.request_webgl_context(&size, attrs) { + Ok((id, limits)) => { + let painter = WebGLPaintThread { + data: WebGLPaintTaskData::WebRender(wr_api, id), + size: size + }; + Ok((painter, limits)) + }, + Err(msg) => { + warn!("Initial context creation failed, falling back to readback: {}", msg); + create_readback_painter(size, attrs, wr_api) } - } else { - create_readback_painter(size, attrs, None) } } @@ -144,7 +137,7 @@ impl WebGLPaintThread { WebGLPaintTaskData::WebRender(ref api, id) => { api.send_webgl_command(id, message); } - WebGLPaintTaskData::Readback(ref ctx, _) => { + WebGLPaintTaskData::Readback(ref ctx, _, _) => { ctx.apply_command(message); } } @@ -154,7 +147,7 @@ impl WebGLPaintThread { /// communicate with it. pub fn start(size: Size2D<i32>, attrs: GLContextAttributes, - webrender_api_sender: Option<webrender_traits::RenderApiSender>) + webrender_api_sender: webrender_traits::RenderApiSender) -> Result<(IpcSender<CanvasMsg>, GLLimits), String> { let (sender, receiver) = ipc::channel::<CanvasMsg>().unwrap(); let (result_chan, result_port) = channel(); @@ -196,7 +189,7 @@ impl WebGLPaintThread { fn send_data(&mut self, chan: IpcSender<CanvasData>) { match self.data { - WebGLPaintTaskData::Readback(_, ref webrender_api_and_image_key) => { + WebGLPaintTaskData::Readback(_, ref webrender_api, image_key) => { let width = self.size.width as usize; let height = self.size.height as usize; @@ -217,19 +210,17 @@ impl WebGLPaintThread { // rgba -> bgra byte_swap(&mut pixels); - if let Some((ref wr, wr_image_key)) = *webrender_api_and_image_key { - // TODO: This shouldn't be a common path, but try to avoid - // the spurious clone(). - wr.update_image(wr_image_key, - width as u32, - height as u32, - webrender_traits::ImageFormat::RGBA8, - pixels.clone()); - } + // TODO: This shouldn't be a common path, but try to avoid + // the spurious clone(). + webrender_api.update_image(image_key, + width as u32, + height as u32, + webrender_traits::ImageFormat::RGBA8, + pixels.clone()); let pixel_data = CanvasPixelData { image_data: IpcSharedMemory::from_bytes(&pixels[..]), - image_key: webrender_api_and_image_key.as_ref().map(|&(_, key)| key), + image_key: image_key, }; chan.send(CanvasData::Pixels(pixel_data)).unwrap(); @@ -243,7 +234,7 @@ impl WebGLPaintThread { #[allow(unsafe_code)] fn recreate(&mut self, size: Size2D<i32>) -> Result<(), &'static str> { match self.data { - WebGLPaintTaskData::Readback(ref mut context, _) => { + WebGLPaintTaskData::Readback(ref mut context, _, _) => { if size.width > self.size.width || size.height > self.size.height { self.size = try!(context.resize(size)); @@ -261,7 +252,7 @@ impl WebGLPaintThread { } fn init(&mut self) { - if let WebGLPaintTaskData::Readback(ref context, _) = self.data { + if let WebGLPaintTaskData::Readback(ref context, _, _) = self.data { context.make_current(); } } @@ -269,7 +260,7 @@ impl WebGLPaintThread { impl Drop for WebGLPaintThread { fn drop(&mut self) { - if let WebGLPaintTaskData::Readback(_, Some((ref mut wr, image_key))) = self.data { + if let WebGLPaintTaskData::Readback(_, ref mut wr, image_key) = self.data { wr.delete_image(image_key); } } diff --git a/components/canvas_traits/lib.rs b/components/canvas_traits/lib.rs index bdd29fd8e97..2fa18937c17 100644 --- a/components/canvas_traits/lib.rs +++ b/components/canvas_traits/lib.rs @@ -69,7 +69,7 @@ pub enum CanvasData { #[derive(Clone, Deserialize, Serialize)] pub struct CanvasPixelData { pub image_data: IpcSharedMemory, - pub image_key: Option<webrender_traits::ImageKey>, + pub image_key: webrender_traits::ImageKey, } #[derive(Clone, Deserialize, Serialize)] diff --git a/components/compositing/Cargo.toml b/components/compositing/Cargo.toml index 299999abf07..27124a4484f 100644 --- a/components/compositing/Cargo.toml +++ b/components/compositing/Cargo.toml @@ -10,14 +10,11 @@ name = "compositing" path = "lib.rs" [dependencies] -app_units = "0.3" -azure = {git = "https://github.com/servo/rust-azure", features = ["plugins"]} euclid = "0.10.1" gfx_traits = {path = "../gfx_traits"} gleam = "0.2.8" image = "0.10" ipc-channel = "0.5" -layers = {git = "https://github.com/servo/rust-layers", features = ["plugins"]} log = "0.3.5" msg = {path = "../msg"} net_traits = {path = "../net_traits"} diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index ddf9b069188..0a9ad22de68 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -4,49 +4,36 @@ use CompositionPipeline; use SendableFrameTree; -use app_units::Au; -use compositor_layer::{CompositorData, CompositorLayer, RcCompositorLayer, WantsScrollEventsFlag}; use compositor_thread::{CompositorProxy, CompositorReceiver}; use compositor_thread::{InitialCompositorState, Msg, RenderListener}; use delayed_composition::DelayedCompositionTimerProxy; -use euclid::{Matrix4D, Point2D, Rect, Size2D}; +use euclid::{Point2D, Size2D}; use euclid::point::TypedPoint2D; -use euclid::rect::TypedRect; use euclid::scale_factor::ScaleFactor; use euclid::size::TypedSize2D; -use gfx_traits::{ChromeToPaintMsg, PaintRequest, ScrollPolicy, StackingContextId}; -use gfx_traits::{color, Epoch, FrameTreeId, FragmentType, LayerId, LayerKind, LayerProperties}; -use gfx_traits::print_tree::PrintTree; +use gfx_traits::{DevicePixel, LayerPixel, StackingContextId}; +use gfx_traits::{Epoch, FrameTreeId, FragmentType, LayerId}; use gleam::gl; use gleam::gl::types::{GLint, GLsizei}; use image::{DynamicImage, ImageFormat, RgbImage}; use ipc_channel::ipc::{self, IpcSender, IpcSharedMemory}; use ipc_channel::router::ROUTER; -use layers::geometry::{DevicePixel, LayerPixel}; -use layers::layers::{BufferRequest, Layer, LayerBuffer, LayerBufferSet}; -use layers::platform::surface::NativeDisplay; -use layers::rendergl; -use layers::rendergl::RenderContext; -use layers::scene::Scene; use msg::constellation_msg::{Image, PixelFormat, Key, KeyModifiers, KeyState}; use msg::constellation_msg::{LoadData, TraversalDirection, PipelineId}; use msg::constellation_msg::{PipelineIndex, PipelineNamespaceId, WindowSizeType}; -use profile_traits::mem::{self, ReportKind, Reporter, ReporterRequest}; +use profile_traits::mem::{self, Reporter, ReporterRequest}; use profile_traits::time::{self, ProfilerCategory, profile}; use script_traits::{AnimationState, AnimationTickType, ConstellationControlMsg}; use script_traits::{ConstellationMsg, LayoutControlMsg, MouseButton, MouseEventType}; use script_traits::{StackingContextScrollState, TouchpadPressurePhase, TouchEventType}; use script_traits::{TouchId, WindowSizeData}; use script_traits::CompositorEvent::{self, MouseMoveEvent, MouseButtonEvent, TouchEvent, TouchpadPressureEvent}; -use std::collections::{HashMap, HashSet}; -use std::collections::hash_map::Entry::{Occupied, Vacant}; +use std::collections::HashMap; use std::fs::File; -use std::mem as std_mem; use std::rc::Rc; use std::sync::mpsc::Sender; use style_traits::{PagePx, ViewportPx}; use style_traits::viewport::ViewportConstraints; -use surface_map::SurfaceMap; use time::{precise_time_ns, precise_time_s}; use touch::{TouchHandler, TouchAction}; use url::Url; @@ -59,23 +46,17 @@ use windowing::{self, MouseWindowEvent, WindowEvent, WindowMethods, WindowNaviga #[derive(Debug, PartialEq)] enum UnableToComposite { - NoContext, WindowUnprepared, NotReadyToPaintImage(NotReadyToPaint), } #[derive(Debug, PartialEq)] enum NotReadyToPaint { - LayerHasOutstandingPaintMessages, - MissingRoot, - PendingSubpages(usize), AnimationsActive, JustNotifiedConstellation, WaitingOnConstellation, } -const BUFFER_MAP_SIZE: usize = 10000000; - // Default viewport constraints const MAX_ZOOM: f32 = 8.0; const MIN_ZOOM: f32 = 0.1; @@ -133,24 +114,17 @@ pub struct IOCompositor<Window: WindowMethods> { /// The application window. window: Rc<Window>, - /// The display this compositor targets. Will be None when using webrender. - native_display: Option<NativeDisplay>, - /// The port on which we receive messages. port: Box<CompositorReceiver>, - /// The render context. This will be `None` if the windowing system has not yet sent us a - /// `PrepareRenderingEvent`. - context: Option<RenderContext>, - /// The root pipeline. root_pipeline: Option<CompositionPipeline>, /// Tracks details about each active pipeline that the compositor knows about. pipeline_details: HashMap<PipelineId, PipelineDetails>, - /// The canvas to paint a page. - scene: Scene<CompositorData>, + /// The scene scale, to allow for zooming and high-resolution painting. + scale: ScaleFactor<f32, LayerPixel, DevicePixel>, /// The application window size. window_size: TypedSize2D<u32, DevicePixel>, @@ -213,9 +187,6 @@ pub struct IOCompositor<Window: WindowMethods> { /// The channel on which messages can be sent to the memory profiler. mem_profiler_chan: mem::ProfilerChan, - /// Pending scroll to fragment event, if any - fragment_point: Option<Point2D<f32>>, - /// Touch input state machine touch_handler: TouchHandler, @@ -229,24 +200,14 @@ pub struct IOCompositor<Window: WindowMethods> { /// image for the reftest framework. ready_to_save_state: ReadyState, - /// A data structure to cache unused NativeSurfaces. - surface_map: SurfaceMap, - - /// Pipeline IDs of subpages that the compositor has seen in a layer tree but which have not - /// yet been painted. - pending_subpages: HashSet<PipelineId>, - - /// The id of the pipeline that was last sent a mouse move event, if any. - last_mouse_move_recipient: Option<PipelineId>, - /// Whether a scroll is in progress; i.e. whether the user's fingers are down. scroll_in_progress: bool, - /// The webrender renderer, if enabled. - webrender: Option<webrender::Renderer>, + /// The webrender renderer. + webrender: webrender::Renderer, /// The webrender interface, if enabled. - webrender_api: Option<webrender_traits::RenderApi>, + webrender_api: webrender_traits::RenderApi, } #[derive(Copy, Clone)] @@ -277,20 +238,10 @@ enum ShutdownState { FinishedShuttingDown, } -struct HitTestResult { - /// The topmost layer containing the requested point - layer: Rc<Layer<CompositorData>>, - /// The point in client coordinates of the innermost window or frame containing `layer` - point: TypedPoint2D<f32, LayerPixel>, -} - struct PipelineDetails { /// The pipeline associated with this PipelineDetails object. pipeline: Option<CompositionPipeline>, - /// The current layout epoch that this pipeline wants to draw. - current_epoch: Epoch, - /// Whether animations are running animations_running: bool, @@ -305,7 +256,6 @@ impl PipelineDetails { fn new() -> PipelineDetails { PipelineDetails { pipeline: None, - current_epoch: Epoch(0), animations_running: false, animation_callbacks_running: false, visible: true, @@ -328,7 +278,6 @@ enum CompositeTarget { struct RenderTargetInfo { framebuffer_ids: Vec<gl::GLuint>, texture_ids: Vec<gl::GLuint>, - renderbuffer_ids: Vec<gl::GLuint>, } impl RenderTargetInfo { @@ -336,7 +285,6 @@ impl RenderTargetInfo { RenderTargetInfo { framebuffer_ids: Vec::new(), texture_ids: Vec::new(), - renderbuffer_ids: Vec::new() } } } @@ -358,26 +306,9 @@ fn initialize_png(width: usize, height: usize) -> RenderTargetInfo { gl::bind_texture(gl::TEXTURE_2D, 0); - let renderbuffer_ids = if opts::get().use_webrender { - let renderbuffer_ids = gl::gen_renderbuffers(1); - gl::bind_renderbuffer(gl::RENDERBUFFER, renderbuffer_ids[0]); - gl::renderbuffer_storage(gl::RENDERBUFFER, - gl::STENCIL_INDEX8, - width as GLsizei, - height as GLsizei); - gl::framebuffer_renderbuffer(gl::FRAMEBUFFER, - gl::STENCIL_ATTACHMENT, - gl::RENDERBUFFER, - renderbuffer_ids[0]); - renderbuffer_ids - } else { - Vec::new() - }; - RenderTargetInfo { framebuffer_ids: framebuffer_ids, texture_ids: texture_ids, - renderbuffer_ids: renderbuffer_ids } } @@ -450,25 +381,13 @@ impl<Window: WindowMethods> IOCompositor<Window> { None => CompositeTarget::Window }; - let webrender_api = state.webrender_api_sender.map(|sender| { - sender.create_api() - }); - - let native_display = if state.webrender.is_some() { - None - } else { - Some(window.native_display()) - }; - IOCompositor { window: window, - native_display: native_display, port: state.receiver, - context: None, root_pipeline: None, pipeline_details: HashMap::new(), - scene: Scene::new(TypedRect::new(TypedPoint2D::zero(), window_size.to_f32())), window_size: window_size, + scale: ScaleFactor::new(1.0), viewport: None, scale_factor: scale_factor, channel_to_self: state.sender.clone_compositor_proxy(), @@ -490,28 +409,22 @@ impl<Window: WindowMethods> IOCompositor<Window> { constellation_chan: state.constellation_chan, time_profiler_chan: state.time_profiler_chan, mem_profiler_chan: state.mem_profiler_chan, - fragment_point: None, last_composite_time: 0, ready_to_save_state: ReadyState::Unknown, - surface_map: SurfaceMap::new(BUFFER_MAP_SIZE), - pending_subpages: HashSet::new(), - last_mouse_move_recipient: None, scroll_in_progress: false, webrender: state.webrender, - webrender_api: webrender_api, + webrender_api: state.webrender_api_sender.create_api(), } } pub fn create(window: Rc<Window>, state: InitialCompositorState) -> IOCompositor<Window> { let mut compositor = IOCompositor::new(window, state); - if let Some(ref mut webrender) = compositor.webrender { - let compositor_proxy_for_webrender = compositor.channel_to_self - .clone_compositor_proxy(); - let render_notifier = RenderNotifier::new(compositor_proxy_for_webrender, - compositor.constellation_chan.clone()); - webrender.set_render_notifier(Box::new(render_notifier)); - } + let compositor_proxy_for_webrender = compositor.channel_to_self + .clone_compositor_proxy(); + let render_notifier = RenderNotifier::new(compositor_proxy_for_webrender, + compositor.constellation_chan.clone()); + compositor.webrender.set_render_notifier(Box::new(render_notifier)); // Set the size of the root layer. compositor.update_zoom_transform(); @@ -536,11 +449,6 @@ impl<Window: WindowMethods> IOCompositor<Window> { fn finish_shutting_down(&mut self) { debug!("Compositor received message that constellation shutdown is complete"); - // Clear out the compositor layers so that painting threads can destroy the buffers. - if let Some(ref root_layer) = self.scene.root { - root_layer.forget_all_tiles(); - } - // Drain compositor port, sometimes messages contain channels that are blocking // another thread from finishing (i.e. SetFrameTree). while self.port.try_recv_compositor_msg().is_some() {} @@ -591,55 +499,10 @@ impl<Window: WindowMethods> IOCompositor<Window> { (Msg::SetFrameTree(frame_tree, response_chan), ShutdownState::NotShuttingDown) => { self.set_frame_tree(&frame_tree, response_chan); - self.send_viewport_rects_for_all_layers(); + self.send_viewport_rects(); self.title_for_main_frame(); } - (Msg::InitializeLayersForPipeline(pipeline_id, epoch, properties), - ShutdownState::NotShuttingDown) => { - debug!("initializing layers for pipeline: {:?}", pipeline_id); - self.pipeline_details(pipeline_id).current_epoch = epoch; - - self.collect_old_layers(pipeline_id, &properties); - for (index, layer_properties) in properties.iter().enumerate() { - if index == 0 { - self.create_or_update_base_layer(pipeline_id, *layer_properties); - } else { - self.create_or_update_descendant_layer(pipeline_id, *layer_properties); - } - } - - self.send_buffer_requests_for_all_layers(); - self.dump_layer_tree(); - } - - (Msg::GetNativeDisplay(chan), - ShutdownState::NotShuttingDown) => { - if let Err(e) = chan.send(self.native_display.clone()) { - warn!("Sending response to get native display failed ({}).", e); - } - } - - (Msg::AssignPaintedBuffers(pipeline_id, epoch, replies, frame_tree_id), - ShutdownState::NotShuttingDown) => { - self.pending_subpages.remove(&pipeline_id); - - for (layer_id, new_layer_buffer_set) in replies { - self.assign_painted_buffers(pipeline_id, - layer_id, - new_layer_buffer_set, - epoch, - frame_tree_id); - } - } - - (Msg::ReturnUnusedNativeSurfaces(native_surfaces), - ShutdownState::NotShuttingDown) => { - if let Some(ref native_display) = self.native_display { - self.surface_map.insert_surfaces(native_display, native_surfaces); - } - } - (Msg::ScrollFragmentPoint(pipeline_id, layer_id, point, _), ShutdownState::NotShuttingDown) => { self.scroll_fragment_to_point(pipeline_id, layer_id, point); @@ -721,11 +584,6 @@ impl<Window: WindowMethods> IOCompositor<Window> { } } - (Msg::PaintThreadExited(pipeline_id), _) => { - debug!("compositor learned about paint thread exiting: {:?}", pipeline_id); - self.remove_pipeline_root_layer(pipeline_id); - } - (Msg::ViewportConstrained(pipeline_id, constraints), ShutdownState::NotShuttingDown) => { self.constrain_viewport(pipeline_id, constraints); @@ -756,18 +614,7 @@ impl<Window: WindowMethods> IOCompositor<Window> { } (Msg::CollectMemoryReports(reports_chan), ShutdownState::NotShuttingDown) => { - let name = "compositor-thread"; - // These are both `ExplicitUnknownLocationSize` because the memory might be in the - // GPU or on the heap. - let reports = vec![mem::Report { - path: path![name, "surface-map"], - kind: ReportKind::ExplicitUnknownLocationSize, - size: self.surface_map.mem(), - }, mem::Report { - path: path![name, "layer-tree"], - kind: ReportKind::ExplicitUnknownLocationSize, - size: self.scene.get_memory_usage(), - }]; + let reports = vec![]; reports_chan.send(reports); } @@ -780,23 +627,10 @@ impl<Window: WindowMethods> IOCompositor<Window> { (Msg::PipelineExited(pipeline_id, sender), _) => { debug!("Compositor got pipeline exited: {:?}", pipeline_id); - self.pending_subpages.remove(&pipeline_id); self.remove_pipeline_root_layer(pipeline_id); let _ = sender.send(()); } - (Msg::GetScrollOffset(pipeline_id, layer_id, sender), ShutdownState::NotShuttingDown) => { - match self.find_layer_with_pipeline_and_layer_id(pipeline_id, layer_id) { - Some(ref layer) => { - let typed = layer.extra_data.borrow().scroll_offset; - let _ = sender.send(Point2D::new(typed.x, typed.y)); - }, - None => { - warn!("Can't find requested layer in handling Msg::GetScrollOffset"); - }, - } - } - (Msg::NewScrollFrameReady(recomposite_needed), ShutdownState::NotShuttingDown) => { self.waiting_for_results_of_scroll = false; if recomposite_needed { @@ -880,67 +714,16 @@ impl<Window: WindowMethods> IOCompositor<Window> { warn!("Sending reponse to set frame tree failed ({}).", e); } - // There are now no more pending iframes. - self.pending_subpages.clear(); - self.root_pipeline = Some(frame_tree.pipeline.clone()); - if let Some(ref webrender_api) = self.webrender_api { - let pipeline_id = frame_tree.pipeline.id.to_webrender(); - webrender_api.set_root_pipeline(pipeline_id); - } - - // If we have an old root layer, release all old tiles before replacing it. - let old_root_layer = self.scene.root.take(); - if let Some(ref old_root_layer) = old_root_layer { - old_root_layer.clear_all_tiles(self) - } - - self.scene.root = Some(self.create_root_layer_for_pipeline_and_size(&frame_tree.pipeline, - None)); - self.scene.set_root_layer_size(self.window_size.to_f32()); + let pipeline_id = frame_tree.pipeline.id.to_webrender(); + self.webrender_api.set_root_pipeline(pipeline_id); self.create_pipeline_details_for_frame_tree(&frame_tree); self.send_window_size(WindowSizeType::Initial); self.frame_tree_id.next(); - self.composite_if_necessary_if_not_using_webrender(CompositingReason::NewFrameTree); - } - - fn create_root_layer_for_pipeline_and_size(&mut self, - pipeline: &CompositionPipeline, - frame_size: Option<TypedSize2D<f32, PagePx>>) - -> Rc<Layer<CompositorData>> { - let layer_properties = LayerProperties { - id: LayerId::null(), - parent_id: None, - rect: Rect::zero(), - background_color: color::transparent(), - scroll_policy: ScrollPolicy::Scrollable, - transform: Matrix4D::identity(), - perspective: Matrix4D::identity(), - subpage_pipeline_id: None, - establishes_3d_context: true, - scrolls_overflow_area: false, - }; - - let root_layer = CompositorData::new_layer(pipeline.id, - layer_properties, - WantsScrollEventsFlag::WantsScrollEvents, - opts::get().tile_size); - - self.pipeline_details(pipeline.id).pipeline = Some(pipeline.clone()); - - // All root layers mask to bounds. - *root_layer.masks_to_bounds.borrow_mut() = true; - - if let Some(ref frame_size) = frame_size { - root_layer.bounds.borrow_mut().size = - TypedSize2D::new(frame_size.width, frame_size.height); - } - - root_layer } fn create_pipeline_details_for_frame_tree(&mut self, frame_tree: &SendableFrameTree) { @@ -951,199 +734,10 @@ impl<Window: WindowMethods> IOCompositor<Window> { } } - fn find_pipeline_root_layer(&self, pipeline_id: PipelineId) - -> Option<Rc<Layer<CompositorData>>> { - if !self.pipeline_details.contains_key(&pipeline_id) { - warn!("Tried to create or update layer for unknown pipeline"); - return None; - } - self.find_layer_with_pipeline_and_layer_id(pipeline_id, LayerId::null()) - } - - fn collect_old_layers(&mut self, - pipeline_id: PipelineId, - new_layers: &[LayerProperties]) { - let root_layer = match self.scene.root { - Some(ref root_layer) => root_layer.clone(), - None => return, - }; - - let mut pipelines_removed = Vec::new(); - root_layer.collect_old_layers(self, pipeline_id, new_layers, &mut pipelines_removed); - - for pipeline_removed in pipelines_removed.into_iter() { - self.pending_subpages.remove(&pipeline_removed); - } - } - fn remove_pipeline_root_layer(&mut self, pipeline_id: PipelineId) { - let root_layer = match self.scene.root { - Some(ref root_layer) => root_layer.clone(), - None => return, - }; - - // Remove all the compositor layers for this pipeline and recache - // any buffers that they owned. - root_layer.remove_root_layer_with_pipeline_id(self, pipeline_id); self.pipeline_details.remove(&pipeline_id); } - fn update_layer_if_exists(&mut self, - pipeline_id: PipelineId, - properties: LayerProperties) - -> bool { - if let Some(subpage_id) = properties.subpage_pipeline_id { - match self.find_layer_with_pipeline_and_layer_id(subpage_id, LayerId::null()) { - Some(layer) => { - *layer.bounds.borrow_mut() = - TypedRect::new(TypedPoint2D::zero(), - TypedSize2D::from_untyped(&properties.rect.size)); - } - None => warn!("Tried to update non-existent subpage root layer: {:?}", subpage_id), - } - } - - match self.find_layer_with_pipeline_and_layer_id(pipeline_id, properties.id) { - Some(existing_layer) => { - // If this layer contains a subpage, then create the root layer for that subpage - // now. - if properties.subpage_pipeline_id.is_some() { - self.create_root_layer_for_subpage_if_necessary(properties, - existing_layer.clone()) - } - - existing_layer.update_layer(properties); - true - } - None => false, - } - } - - fn create_or_update_base_layer(&mut self, - pipeline_id: PipelineId, - layer_properties: LayerProperties) { - debug_assert!(layer_properties.parent_id.is_none()); - - let root_layer = match self.find_pipeline_root_layer(pipeline_id) { - Some(root_layer) => root_layer, - None => { - debug!("Ignoring CreateOrUpdateBaseLayer message for pipeline \ - ({:?}) shutting down.", - pipeline_id); - return; - } - }; - - let need_new_base_layer = !self.update_layer_if_exists(pipeline_id, layer_properties); - if need_new_base_layer { - root_layer.update_layer_except_bounds(layer_properties); - - let base_layer = CompositorData::new_layer( - pipeline_id, - layer_properties, - WantsScrollEventsFlag::DoesntWantScrollEvents, - opts::get().tile_size); - - // Add the base layer to the front of the child list, so that child - // iframe layers are painted on top of the base layer. These iframe - // layers were added previously when creating the layer tree - // skeleton in create_frame_tree_root_layers. - root_layer.children().insert(0, base_layer); - } - - self.scroll_layer_to_fragment_point_if_necessary(pipeline_id, - layer_properties.id); - } - - fn create_or_update_descendant_layer(&mut self, - pipeline_id: PipelineId, - layer_properties: LayerProperties) { - debug_assert!(layer_properties.parent_id.is_some()); - - if !self.update_layer_if_exists(pipeline_id, layer_properties) { - self.create_descendant_layer(pipeline_id, layer_properties); - } - self.update_subpage_size_if_necessary(&layer_properties); - self.scroll_layer_to_fragment_point_if_necessary(pipeline_id, - layer_properties.id); - } - - fn create_descendant_layer(&mut self, - pipeline_id: PipelineId, - layer_properties: LayerProperties) { - let parent_id = match layer_properties.parent_id { - None => return error!("Creating descendent layer without a parent id."), - Some(parent_id) => parent_id, - }; - if let Some(parent_layer) = self.find_layer_with_pipeline_and_layer_id(pipeline_id, - parent_id) { - let wants_scroll_events = if layer_properties.scrolls_overflow_area { - WantsScrollEventsFlag::WantsScrollEvents - } else { - WantsScrollEventsFlag::DoesntWantScrollEvents - }; - - let new_layer = CompositorData::new_layer(pipeline_id, - layer_properties, - wants_scroll_events, - parent_layer.tile_size); - - if layer_properties.scrolls_overflow_area { - *new_layer.masks_to_bounds.borrow_mut() = true - } - - // If this layer contains a subpage, then create the root layer for that subpage now. - if layer_properties.subpage_pipeline_id.is_some() { - self.create_root_layer_for_subpage_if_necessary(layer_properties, - new_layer.clone()) - } - - parent_layer.add_child(new_layer.clone()); - } - - self.dump_layer_tree(); - } - - fn create_root_layer_for_subpage_if_necessary(&mut self, - layer_properties: LayerProperties, - parent_layer: Rc<Layer<CompositorData>>) { - if parent_layer.children - .borrow() - .iter() - .any(|child| child.extra_data.borrow().subpage_info.is_some()) { - return - } - - let subpage_pipeline_id = - layer_properties.subpage_pipeline_id - .expect("create_root_layer_for_subpage() called for non-subpage?!"); - let subpage_layer_properties = LayerProperties { - id: LayerId::null(), - parent_id: None, - rect: Rect::new(Point2D::zero(), layer_properties.rect.size), - background_color: layer_properties.background_color, - scroll_policy: ScrollPolicy::Scrollable, - transform: Matrix4D::identity(), - perspective: Matrix4D::identity(), - subpage_pipeline_id: Some(subpage_pipeline_id), - establishes_3d_context: true, - scrolls_overflow_area: true, - }; - - let wants_scroll_events = if subpage_layer_properties.scrolls_overflow_area { - WantsScrollEventsFlag::WantsScrollEvents - } else { - WantsScrollEventsFlag::DoesntWantScrollEvents - }; - let subpage_layer = CompositorData::new_layer(subpage_pipeline_id, - subpage_layer_properties, - wants_scroll_events, - parent_layer.tile_size); - *subpage_layer.masks_to_bounds.borrow_mut() = true; - parent_layer.add_child(subpage_layer); - self.pending_subpages.insert(subpage_pipeline_id); - } - fn send_window_size(&self, size_type: WindowSizeType) { let dppx = self.page_zoom * self.device_pixels_per_screen_px(); let initial_viewport = self.window_size.to_f32() / dppx; @@ -1159,48 +753,6 @@ impl<Window: WindowMethods> IOCompositor<Window> { } } - /// Sends the size of the given subpage up to the constellation. This will often trigger a - /// reflow of that subpage. - fn update_subpage_size_if_necessary(&self, layer_properties: &LayerProperties) { - let subpage_pipeline_id = match layer_properties.subpage_pipeline_id { - Some(ref subpage_pipeline_id) => subpage_pipeline_id, - None => return, - }; - - let msg = ConstellationMsg::FrameSize(*subpage_pipeline_id, layer_properties.rect.size); - if let Err(e) = self.constellation_chan.send(msg) { - warn!("Sending subpage resize to constellation failed ({}).", e); - } - } - - fn move_layer(&self, - pipeline_id: PipelineId, - layer_id: LayerId, - origin: TypedPoint2D<f32, LayerPixel>) - -> bool { - match self.find_layer_with_pipeline_and_layer_id(pipeline_id, layer_id) { - Some(ref layer) => { - if layer.wants_scroll_events() == WantsScrollEventsFlag::WantsScrollEvents { - layer.clamp_scroll_offset_and_scroll_layer(TypedPoint2D::zero() - origin); - } - true - } - None => false, - } - } - - fn scroll_layer_to_fragment_point_if_necessary(&mut self, - pipeline_id: PipelineId, - layer_id: LayerId) { - if let Some(point) = self.fragment_point.take() { - if !self.move_layer(pipeline_id, layer_id, TypedPoint2D::from_untyped(&point)) { - return warn!("Compositor: Tried to scroll to fragment with unknown layer."); - } - - self.perform_updates_after_scroll(); - } - } - fn schedule_delayed_composite_if_necessary(&mut self) { match self.composition_request { CompositionRequest::CompositeNow(_) => return, @@ -1213,65 +765,11 @@ impl<Window: WindowMethods> IOCompositor<Window> { self.composition_request = CompositionRequest::DelayedComposite(timestamp); } - fn assign_painted_buffers(&mut self, - pipeline_id: PipelineId, - layer_id: LayerId, - new_layer_buffer_set: Box<LayerBufferSet>, - epoch: Epoch, - frame_tree_id: FrameTreeId) { - // If the frame tree id has changed since this paint request was sent, - // reject the buffers and send them back to the paint thread. If this isn't handled - // correctly, the content_age in the tile grid can get out of sync when iframes are - // loaded and the frame tree changes. This can result in the compositor thinking it - // has already drawn the most recently painted buffer, and missing a frame. - if frame_tree_id == self.frame_tree_id { - if let Some(layer) = self.find_layer_with_pipeline_and_layer_id(pipeline_id, - layer_id) { - let requested_epoch = layer.extra_data.borrow().requested_epoch; - if requested_epoch == epoch { - self.assign_painted_buffers_to_layer(layer, new_layer_buffer_set, epoch); - return - } else { - debug!("assign_painted_buffers epoch mismatch {:?} {:?} req={:?} actual={:?}", - pipeline_id, - layer_id, - requested_epoch, - epoch); - } - } - } - - self.cache_unused_buffers(new_layer_buffer_set.buffers); - } - - fn assign_painted_buffers_to_layer(&mut self, - layer: Rc<Layer<CompositorData>>, - new_layer_buffer_set: Box<LayerBufferSet>, - epoch: Epoch) { - debug!("compositor received new frame at size {:?}x{:?}", - self.window_size.width, - self.window_size.height); - - // From now on, if we destroy the buffers, they will leak. - let mut new_layer_buffer_set = new_layer_buffer_set; - new_layer_buffer_set.mark_will_leak(); - - // FIXME(pcwalton): This is going to cause problems with inconsistent frames since - // we only composite one layer at a time. - layer.add_buffers(self, new_layer_buffer_set, epoch); - self.composite_if_necessary_if_not_using_webrender(CompositingReason::NewPaintedBuffers); - } - fn scroll_fragment_to_point(&mut self, - pipeline_id: PipelineId, - layer_id: LayerId, - point: Point2D<f32>) { - if self.move_layer(pipeline_id, layer_id, TypedPoint2D::from_untyped(&point)) { - self.perform_updates_after_scroll(); - self.send_viewport_rects_for_all_layers() - } else { - self.fragment_point = Some(point) - } + _pipeline_id: PipelineId, + _layer_id: LayerId, + _point: Point2D<f32>) { + println!("TODO: Support scroll_fragment_to_point again"); } fn handle_window_message(&mut self, event: WindowEvent) { @@ -1383,7 +881,6 @@ impl<Window: WindowMethods> IOCompositor<Window> { self.window_size = new_size; - self.scene.set_root_layer_size(new_size.to_f32()); self.send_window_size(WindowSizeType::Resize); } @@ -1393,8 +890,8 @@ impl<Window: WindowMethods> IOCompositor<Window> { match Url::parse(&url_string) { Ok(url) => { self.window.set_page_url(url.clone()); - let msg = match self.scene.root { - Some(ref layer) => ConstellationMsg::LoadUrl(layer.pipeline_id(), LoadData::new(url, None, None)), + let msg = match self.root_pipeline { + Some(ref pipeline) => ConstellationMsg::LoadUrl(pipeline.id, LoadData::new(url, None, None)), None => ConstellationMsg::InitLoadUrl(url) }; if let Err(e) = self.constellation_chan.send(msg) { @@ -1425,37 +922,29 @@ impl<Window: WindowMethods> IOCompositor<Window> { MouseWindowEvent::MouseUp(_, p) => p, }; - if self.webrender_api.is_some() { - let root_pipeline_id = match self.get_root_pipeline_id() { - Some(root_pipeline_id) => root_pipeline_id, - None => return, - }; + let root_pipeline_id = match self.get_root_pipeline_id() { + Some(root_pipeline_id) => root_pipeline_id, + None => return, + }; - if let Some(pipeline) = self.pipeline(root_pipeline_id) { - let dppx = self.page_zoom * self.device_pixels_per_screen_px(); - let translated_point = (point / dppx).to_untyped(); - let event_to_send = match mouse_window_event { - MouseWindowEvent::Click(button, _) => { - MouseButtonEvent(MouseEventType::Click, button, translated_point) - } - MouseWindowEvent::MouseDown(button, _) => { - MouseButtonEvent(MouseEventType::MouseDown, button, translated_point) - } - MouseWindowEvent::MouseUp(button, _) => { - MouseButtonEvent(MouseEventType::MouseUp, button, translated_point) - } - }; - let msg = ConstellationControlMsg::SendEvent(root_pipeline_id, event_to_send); - if let Err(e) = pipeline.script_chan.send(msg) { - warn!("Sending control event to script failed ({}).", e); + if let Some(pipeline) = self.pipeline(root_pipeline_id) { + let dppx = self.page_zoom * self.device_pixels_per_screen_px(); + let translated_point = (point / dppx).to_untyped(); + let event_to_send = match mouse_window_event { + MouseWindowEvent::Click(button, _) => { + MouseButtonEvent(MouseEventType::Click, button, translated_point) + } + MouseWindowEvent::MouseDown(button, _) => { + MouseButtonEvent(MouseEventType::MouseDown, button, translated_point) } + MouseWindowEvent::MouseUp(button, _) => { + MouseButtonEvent(MouseEventType::MouseUp, button, translated_point) + } + }; + let msg = ConstellationControlMsg::SendEvent(root_pipeline_id, event_to_send); + if let Err(e) = pipeline.script_chan.send(msg) { + warn!("Sending control event to script failed ({}).", e); } - return - } - - match self.find_topmost_layer_at_point(point / self.scene.scale) { - Some(result) => result.layer.send_mouse_event(self, mouse_window_event, result.point), - None => {}, } } @@ -1469,45 +958,21 @@ impl<Window: WindowMethods> IOCompositor<Window> { } fn dispatch_mouse_window_move_event_class(&mut self, cursor: TypedPoint2D<f32, DevicePixel>) { - if self.webrender_api.is_some() { - let root_pipeline_id = match self.get_root_pipeline_id() { - Some(root_pipeline_id) => root_pipeline_id, - None => return, - }; - if self.pipeline(root_pipeline_id).is_none() { - return; - } - - let dppx = self.page_zoom * self.device_pixels_per_screen_px(); - let event_to_send = MouseMoveEvent(Some((cursor / dppx).to_untyped())); - let msg = ConstellationControlMsg::SendEvent(root_pipeline_id, event_to_send); - if let Some(pipeline) = self.pipeline(root_pipeline_id) { - if let Err(e) = pipeline.script_chan.send(msg) { - warn!("Sending mouse control event to script failed ({}).", e); - } - } - return + let root_pipeline_id = match self.get_root_pipeline_id() { + Some(root_pipeline_id) => root_pipeline_id, + None => return, + }; + if self.pipeline(root_pipeline_id).is_none() { + return; } - match self.find_topmost_layer_at_point(cursor / self.scene.scale) { - Some(result) => { - // In the case that the mouse was previously over a different layer, - // that layer must update its state. - if let Some(last_pipeline_id) = self.last_mouse_move_recipient { - if last_pipeline_id != result.layer.pipeline_id() { - if let Some(pipeline) = self.pipeline(last_pipeline_id) { - let _ = pipeline.script_chan - .send(ConstellationControlMsg::SendEvent( - last_pipeline_id.clone(), - MouseMoveEvent(None))); - } - } - } - - self.last_mouse_move_recipient = Some(result.layer.pipeline_id()); - result.layer.send_mouse_move_event(self, result.point); + let dppx = self.page_zoom * self.device_pixels_per_screen_px(); + let event_to_send = MouseMoveEvent(Some((cursor / dppx).to_untyped())); + let msg = ConstellationControlMsg::SendEvent(root_pipeline_id, event_to_send); + if let Some(pipeline) = self.pipeline(root_pipeline_id) { + if let Err(e) = pipeline.script_chan.send(msg) { + warn!("Sending mouse control event to script failed ({}).", e); } - None => {} } } @@ -1551,7 +1016,6 @@ impl<Window: WindowMethods> IOCompositor<Window> { phase: ScrollEventPhase::Move(true), event_count: 1, }); - self.composite_if_necessary_if_not_using_webrender(CompositingReason::Zoom); } TouchAction::DispatchEvent => { let dppx = self.page_zoom * self.device_pixels_per_screen_px(); @@ -1617,7 +1081,6 @@ impl<Window: WindowMethods> IOCompositor<Window> { phase: ScrollEventPhase::Move(self.scroll_in_progress), event_count: 1, }); - self.composite_if_necessary_if_not_using_webrender(CompositingReason::Scroll); } fn on_scroll_start_window_event(&mut self, @@ -1631,7 +1094,6 @@ impl<Window: WindowMethods> IOCompositor<Window> { phase: ScrollEventPhase::Start, event_count: 1, }); - self.composite_if_necessary_if_not_using_webrender(CompositingReason::Scroll); } fn on_scroll_end_window_event(&mut self, @@ -1645,160 +1107,68 @@ impl<Window: WindowMethods> IOCompositor<Window> { phase: ScrollEventPhase::End, event_count: 1, }); - self.composite_if_necessary_if_not_using_webrender(CompositingReason::Scroll); } fn process_pending_scroll_events(&mut self) { let had_events = self.pending_scroll_zoom_events.len() > 0; - match self.webrender_api { - Some(ref webrender_api) => { - // Batch up all scroll events into one, or else we'll do way too much painting. - let mut last_combined_event: Option<ScrollZoomEvent> = None; - for scroll_event in self.pending_scroll_zoom_events.drain(..) { - let this_delta = scroll_event.delta; - let this_cursor = scroll_event.cursor; - if let Some(combined_event) = last_combined_event { - if combined_event.phase != scroll_event.phase { - let delta = (combined_event.delta / self.scene.scale).to_untyped(); - let cursor = - (combined_event.cursor.to_f32() / self.scene.scale).to_untyped(); - webrender_api.scroll(delta, cursor, combined_event.phase); - last_combined_event = None - } - } - - match (&mut last_combined_event, scroll_event.phase) { - (last_combined_event @ &mut None, _) => { - *last_combined_event = Some(ScrollZoomEvent { - magnification: scroll_event.magnification, - delta: this_delta, - cursor: this_cursor, - phase: scroll_event.phase, - event_count: 1, - }) - } - (&mut Some(ref mut last_combined_event), - ScrollEventPhase::Move(false)) => { - // Mac OS X sometimes delivers scroll events out of vsync during a - // fling. This causes events to get bunched up occasionally, causing - // nasty-looking "pops". To mitigate this, during a fling we average - // deltas instead of summing them. - let old_event_count = - ScaleFactor::new(last_combined_event.event_count as f32); - last_combined_event.event_count += 1; - let new_event_count = - ScaleFactor::new(last_combined_event.event_count as f32); - last_combined_event.delta = - (last_combined_event.delta * old_event_count + this_delta) / - new_event_count; - } - (&mut Some(ref mut last_combined_event), _) => { - last_combined_event.delta = last_combined_event.delta + this_delta; - last_combined_event.event_count += 1 - } - } - } - - // TODO(gw): Support zoom (WR issue #28). - if let Some(combined_event) = last_combined_event { - let delta = (combined_event.delta / self.scene.scale).to_untyped(); - let cursor = (combined_event.cursor.to_f32() / self.scene.scale).to_untyped(); - webrender_api.scroll(delta, cursor, combined_event.phase); - self.waiting_for_results_of_scroll = true + // Batch up all scroll events into one, or else we'll do way too much painting. + let mut last_combined_event: Option<ScrollZoomEvent> = None; + for scroll_event in self.pending_scroll_zoom_events.drain(..) { + let this_delta = scroll_event.delta; + let this_cursor = scroll_event.cursor; + if let Some(combined_event) = last_combined_event { + if combined_event.phase != scroll_event.phase { + let delta = (combined_event.delta / self.scale).to_untyped(); + let cursor = + (combined_event.cursor.to_f32() / self.scale).to_untyped(); + self.webrender_api.scroll(delta, cursor, combined_event.phase); + last_combined_event = None } } - None => { - for event in std_mem::replace(&mut self.pending_scroll_zoom_events, - Vec::new()) { - let delta = event.delta / self.scene.scale; - let cursor = event.cursor.to_f32() / self.scene.scale; - if let Some(ref mut layer) = self.scene.root { - layer.handle_scroll_event(delta, cursor); - } - - if event.magnification != 1.0 { - self.zoom_action = true; - self.zoom_time = precise_time_s(); - self.viewport_zoom = ScaleFactor::new( - (self.viewport_zoom.get() * event.magnification) - .min(self.max_viewport_zoom.as_ref().map_or(MAX_ZOOM, ScaleFactor::get)) - .max(self.min_viewport_zoom.as_ref().map_or(MIN_ZOOM, ScaleFactor::get))); - self.update_zoom_transform(); - } - - self.perform_updates_after_scroll(); + match (&mut last_combined_event, scroll_event.phase) { + (last_combined_event @ &mut None, _) => { + *last_combined_event = Some(ScrollZoomEvent { + magnification: scroll_event.magnification, + delta: this_delta, + cursor: this_cursor, + phase: scroll_event.phase, + event_count: 1, + }) } - } - } - - if had_events { - self.send_viewport_rects_for_all_layers(); - } - } - - /// Computes new display ports for each layer, taking the scroll position into account, and - /// sends them to layout as necessary. This ultimately triggers a rerender of the content. - fn send_updated_display_ports_to_layout(&mut self) { - fn process_layer(layer: &Layer<CompositorData>, - window_size: &TypedSize2D<f32, LayerPixel>, - new_display_ports: &mut HashMap<PipelineId, Vec<(LayerId, Rect<Au>)>>) { - let visible_rect = - TypedRect::new(TypedPoint2D::zero(), *window_size) - .translate(&-*layer.content_offset.borrow()) - .intersection(&*layer.bounds.borrow()) - .unwrap_or(TypedRect::zero()) - .to_untyped(); - let visible_rect = TypedRect::new( - TypedPoint2D::new(Au::from_f32_px(visible_rect.origin.x), - Au::from_f32_px(visible_rect.origin.y)), - TypedSize2D::new(Au::from_f32_px(visible_rect.size.width), - Au::from_f32_px(visible_rect.size.height))); - - let extra_layer_data = layer.extra_data.borrow(); - if !new_display_ports.contains_key(&extra_layer_data.pipeline_id) { - new_display_ports.insert(extra_layer_data.pipeline_id, Vec::new()); - } - if let Some(new_display_port) = new_display_ports.get_mut(&extra_layer_data.pipeline_id) { - new_display_port.push((extra_layer_data.id, visible_rect)); - } - - for kid in &*layer.children.borrow() { - process_layer(&*kid, window_size, new_display_ports) - } - } - - let dppx = self.page_zoom * self.device_pixels_per_screen_px(); - let window_size = self.window_size.to_f32() / dppx * ScaleFactor::new(1.0); - let mut new_visible_rects = HashMap::new(); - if let Some(ref layer) = self.scene.root { - process_layer(&**layer, &window_size, &mut new_visible_rects) - } - - for (pipeline_id, new_visible_rects) in &new_visible_rects { - if let Some(pipeline_details) = self.pipeline_details.get(&pipeline_id) { - if let Some(ref pipeline) = pipeline_details.pipeline { - let msg = LayoutControlMsg::SetVisibleRects((*new_visible_rects).clone()); - if let Err(e) = pipeline.layout_chan.send(msg) { - warn!("Sending layout control message failed ({}).", e); - } + (&mut Some(ref mut last_combined_event), + ScrollEventPhase::Move(false)) => { + // Mac OS X sometimes delivers scroll events out of vsync during a + // fling. This causes events to get bunched up occasionally, causing + // nasty-looking "pops". To mitigate this, during a fling we average + // deltas instead of summing them. + let old_event_count = + ScaleFactor::new(last_combined_event.event_count as f32); + last_combined_event.event_count += 1; + let new_event_count = + ScaleFactor::new(last_combined_event.event_count as f32); + last_combined_event.delta = + (last_combined_event.delta * old_event_count + this_delta) / + new_event_count; + } + (&mut Some(ref mut last_combined_event), _) => { + last_combined_event.delta = last_combined_event.delta + this_delta; + last_combined_event.event_count += 1 } } } - } - /// Performs buffer requests and starts the scrolling timer or schedules a recomposite as - /// necessary. - fn perform_updates_after_scroll(&mut self) { - self.send_updated_display_ports_to_layout(); - if opts::get().use_webrender { - return + // TODO(gw): Support zoom (WR issue #28). + if let Some(combined_event) = last_combined_event { + let delta = (combined_event.delta / self.scale).to_untyped(); + let cursor = (combined_event.cursor.to_f32() / self.scale).to_untyped(); + self.webrender_api.scroll(delta, cursor, combined_event.phase); + self.waiting_for_results_of_scroll = true } - if self.send_buffer_requests_for_all_layers() { - self.schedule_delayed_composite_if_necessary(); - } else { - self.channel_to_self.send(Msg::Recomposite(CompositingReason::ContinueScroll)); + + if had_events { + self.send_viewport_rects(); } } @@ -1865,11 +1235,7 @@ impl<Window: WindowMethods> IOCompositor<Window> { fn update_zoom_transform(&mut self) { let scale = self.device_pixels_per_page_px(); - self.scene.scale = ScaleFactor::new(scale.get()); - - // We need to set the size of the root layer again, since the window size - // has changed in unscaled layer pixels. - self.scene.set_root_layer_size(self.window_size.to_f32()); + self.scale = ScaleFactor::new(scale.get()); } fn on_zoom_reset_window_event(&mut self) { @@ -1894,7 +1260,6 @@ impl<Window: WindowMethods> IOCompositor<Window> { phase: ScrollEventPhase::Move(true), event_count: 1, }); - self.composite_if_necessary_if_not_using_webrender(CompositingReason::Zoom); } fn on_navigation_window_event(&self, direction: WindowNavigateMsg) { @@ -1915,191 +1280,28 @@ impl<Window: WindowMethods> IOCompositor<Window> { } } - fn fill_paint_request_with_cached_layer_buffers(&mut self, paint_request: &mut PaintRequest) { - for buffer_request in &mut paint_request.buffer_requests { - if self.surface_map.mem() == 0 { - return; - } - - let size = Size2D::new(buffer_request.screen_rect.size.width as i32, - buffer_request.screen_rect.size.height as i32); - if let Some(mut native_surface) = self.surface_map.find(size) { - native_surface.mark_wont_leak(); - buffer_request.native_surface = Some(native_surface); - } - } - } - - fn convert_buffer_requests_to_pipeline_requests_map(&mut self, - requests: Vec<(Rc<Layer<CompositorData>>, - Vec<BufferRequest>)>) - -> HashMap<PipelineId, Vec<PaintRequest>> { - let scale = self.device_pixels_per_page_px(); - let mut results: HashMap<PipelineId, Vec<PaintRequest>> = HashMap::new(); - - for (layer, mut layer_requests) in requests { - let pipeline_id = layer.pipeline_id(); - let current_epoch = self.pipeline_details(pipeline_id).current_epoch; - layer.extra_data.borrow_mut().requested_epoch = current_epoch; - let vec = match results.entry(pipeline_id) { - Occupied(entry) => { - entry.into_mut() - } - Vacant(entry) => { - entry.insert(Vec::new()) - } - }; - - // All the BufferRequests are in layer/device coordinates, but the paint thread - // wants to know the page coordinates. We scale them before sending them. - for request in &mut layer_requests { - request.page_rect = request.page_rect / scale.get(); - } - - let layer_kind = if layer.transform_state.borrow().has_transform { - LayerKind::HasTransform - } else { - LayerKind::NoTransform - }; - - let mut paint_request = PaintRequest { - buffer_requests: layer_requests, - scale: scale.get(), - layer_id: layer.extra_data.borrow().id, - epoch: layer.extra_data.borrow().requested_epoch, - layer_kind: layer_kind, - }; - self.fill_paint_request_with_cached_layer_buffers(&mut paint_request); - vec.push(paint_request); - } - - results - } - - fn send_viewport_rect_for_layer(&self, layer: Rc<Layer<CompositorData>>) { - if layer.extra_data.borrow().id == LayerId::null() { - let layer_rect = Rect::new(-layer.extra_data.borrow().scroll_offset.to_untyped(), - layer.bounds.borrow().size.to_untyped()); - if let Some(pipeline) = self.pipeline(layer.pipeline_id()) { - let msg = ConstellationControlMsg::Viewport(pipeline.id.clone(), layer_rect); - if let Err(e) = pipeline.script_chan.send(msg) { - warn!("Send viewport to script failed ({})", e); - } - } - } - - for kid in &*layer.children() { - self.send_viewport_rect_for_layer(kid.clone()); - } - } - - fn send_viewport_rects_for_all_layers(&self) { - if opts::get().use_webrender { - return self.send_webrender_viewport_rects() - } - - if let Some(ref root) = self.scene.root { - self.send_viewport_rect_for_layer(root.clone()) - } - } - - fn send_webrender_viewport_rects(&self) { + fn send_viewport_rects(&self) { let mut stacking_context_scroll_states_per_pipeline = HashMap::new(); - if let Some(ref webrender_api) = self.webrender_api { - for scroll_layer_state in webrender_api.get_scroll_layer_state() { - let stacking_context_scroll_state = StackingContextScrollState { - stacking_context_id: scroll_layer_state.stacking_context_id.from_webrender(), - scroll_offset: scroll_layer_state.scroll_offset, - }; - let pipeline_id = scroll_layer_state.pipeline_id; - stacking_context_scroll_states_per_pipeline - .entry(pipeline_id) - .or_insert(vec![]) - .push(stacking_context_scroll_state); - } - - for (pipeline_id, stacking_context_scroll_states) in - stacking_context_scroll_states_per_pipeline { - if let Some(pipeline) = self.pipeline(pipeline_id.from_webrender()) { - let msg = LayoutControlMsg::SetStackingContextScrollStates( - stacking_context_scroll_states); - let _ = pipeline.layout_chan.send(msg); - } - } - } - } - - /// Returns true if any buffer requests were sent or false otherwise. - fn send_buffer_requests_for_all_layers(&mut self) -> bool { - if self.webrender.is_some() { - return false; - } - - if let Some(ref root_layer) = self.scene.root { - root_layer.update_transform_state(&Matrix4D::identity(), - &Matrix4D::identity(), - &Point2D::zero()); - } - - let mut layers_and_requests = Vec::new(); - let mut unused_buffers = Vec::new(); - self.scene.get_buffer_requests(&mut layers_and_requests, &mut unused_buffers); - - // Return unused tiles first, so that they can be reused by any new BufferRequests. - self.cache_unused_buffers(unused_buffers); - - if layers_and_requests.is_empty() { - return false; - } - - // We want to batch requests for each pipeline to avoid race conditions - // when handling the resulting BufferRequest responses. - let pipeline_requests = - self.convert_buffer_requests_to_pipeline_requests_map(layers_and_requests); - - for (pipeline_id, requests) in pipeline_requests { - let msg = ChromeToPaintMsg::Paint(requests, self.frame_tree_id); - if let Some(pipeline) = self.pipeline(pipeline_id) { - if let Err(e) = pipeline.chrome_to_paint_chan.send(msg) { - warn!("Sending paint message failed ({}).", e); - } - } - } - - true - } - - /// Check if a layer (or its children) have any outstanding paint - /// results to arrive yet. - fn does_layer_have_outstanding_paint_messages(&self, layer: &Rc<Layer<CompositorData>>) - -> bool { - let layer_data = layer.extra_data.borrow(); - let current_epoch = match self.pipeline_details.get(&layer_data.pipeline_id) { - None => return false, - Some(ref details) => details.current_epoch, - }; - - // Only check layers that have requested the current epoch, as there may be - // layers that are not visible in the current viewport, and therefore - // have not requested a paint of the current epoch. - // If a layer has sent a request for the current epoch, but it hasn't - // arrived yet then this layer is waiting for a paint message. - // - // Also don't check the root layer, because the paint thread won't paint - // anything for it after first layout. - if layer_data.id != LayerId::null() && - layer_data.requested_epoch == current_epoch && - layer_data.painted_epoch != current_epoch { - return true; + for scroll_layer_state in self.webrender_api.get_scroll_layer_state() { + let stacking_context_scroll_state = StackingContextScrollState { + stacking_context_id: scroll_layer_state.stacking_context_id.from_webrender(), + scroll_offset: scroll_layer_state.scroll_offset, + }; + let pipeline_id = scroll_layer_state.pipeline_id; + stacking_context_scroll_states_per_pipeline + .entry(pipeline_id) + .or_insert(vec![]) + .push(stacking_context_scroll_state); } - for child in &*layer.children() { - if self.does_layer_have_outstanding_paint_messages(child) { - return true; + for (pipeline_id, stacking_context_scroll_states) in + stacking_context_scroll_states_per_pipeline { + if let Some(pipeline) = self.pipeline(pipeline_id.from_webrender()) { + let msg = LayoutControlMsg::SetStackingContextScrollStates( + stacking_context_scroll_states); + let _ = pipeline.layout_chan.send(msg); } } - - false } // Check if any pipelines currently have active animations or animation callbacks. @@ -2126,39 +1328,17 @@ impl<Window: WindowMethods> IOCompositor<Window> { ReadyState::Unknown => { // Unsure if the output image is stable. - // Check if any layers are waiting for paints to complete - // of their current epoch request. If so, early exit - // from this check. - match self.scene.root { - Some(ref root_layer) => { - if self.does_layer_have_outstanding_paint_messages(root_layer) { - return Err(NotReadyToPaint::LayerHasOutstandingPaintMessages); - } - } - None => { - return Err(NotReadyToPaint::MissingRoot); - } - } - - // Check if there are any pending frames. If so, the image is not stable yet. - if !self.pending_subpages.is_empty() { - return Err(NotReadyToPaint::PendingSubpages(self.pending_subpages.len())); - } - // Collect the currently painted epoch of each pipeline that is // complete (i.e. has *all* layers painted to the requested epoch). // This gets sent to the constellation for comparison with the current // frame tree. let mut pipeline_epochs = HashMap::new(); - for (id, details) in &self.pipeline_details { - if let Some(ref webrender) = self.webrender { - let webrender_pipeline_id = id.to_webrender(); - if let Some(webrender_traits::Epoch(epoch)) = webrender.current_epoch(webrender_pipeline_id) { - let epoch = Epoch(epoch); - pipeline_epochs.insert(*id, epoch); - } - } else { - pipeline_epochs.insert(*id, details.current_epoch); + for (id, _) in &self.pipeline_details { + let webrender_pipeline_id = id.to_webrender(); + if let Some(webrender_traits::Epoch(epoch)) = self.webrender + .current_epoch(webrender_pipeline_id) { + let epoch = Epoch(epoch); + pipeline_epochs.insert(*id, epoch); } } @@ -2214,19 +1394,13 @@ impl<Window: WindowMethods> IOCompositor<Window> { fn composite_specific_target(&mut self, target: CompositeTarget) -> Result<Option<Image>, UnableToComposite> { - if self.context.is_none() && self.webrender.is_none() { - return Err(UnableToComposite::NoContext) - } let (width, height) = (self.window_size.width as usize, self.window_size.height as usize); if !self.window.prepare_for_composite(width, height) { return Err(UnableToComposite::WindowUnprepared) } - if let Some(ref mut webrender) = self.webrender { - assert!(self.context.is_none()); - webrender.update(); - } + self.webrender.update(); let wait_for_stable_image = match target { CompositeTarget::WindowAndPng | CompositeTarget::PngFile => true, @@ -2257,39 +1431,9 @@ impl<Window: WindowMethods> IOCompositor<Window> { profile(ProfilerCategory::Compositing, None, self.time_profiler_chan.clone(), || { debug!("compositor: compositing"); - self.dump_layer_tree(); - // Adjust the layer dimensions as necessary to correspond to the size of the window. - self.scene.viewport = match self.viewport { - Some((point, size)) => TypedRect::new(point.to_f32(), size.to_f32()), - None => TypedRect::new(TypedPoint2D::zero(), self.window_size.to_f32()), - }; // Paint the scene. - if let Some(ref mut webrender) = self.webrender { - assert!(self.context.is_none()); - webrender.render(self.window_size.to_untyped()); - } else if let Some(ref layer) = self.scene.root { - match self.context { - Some(context) => { - if let Some((point, size)) = self.viewport { - let point = point.to_untyped(); let size = size.to_untyped(); - - gl::scissor(point.x as GLint, point.y as GLint, size.width as GLsizei, - size.height as GLsizei); - - gl::enable(gl::SCISSOR_TEST); rendergl::render_scene(layer.clone(), - context, &self.scene); gl::disable(gl::SCISSOR_TEST); - - } else { - rendergl::render_scene(layer.clone(), context, &self.scene); - } - } - - None => { - debug!("compositor: not compositing because context not yet set up") - } - } - } + self.webrender.render(self.window_size.to_untyped()); }); let rv = match target { @@ -2333,10 +1477,6 @@ impl<Window: WindowMethods> IOCompositor<Window> { self.composition_request = CompositionRequest::NoCompositingNecessary; - if !opts::get().use_webrender { - self.process_pending_scroll_events(); - } - self.process_animations(); self.start_scrolling_bounce_if_necessary(); self.waiting_for_results_of_scroll = false; @@ -2358,9 +1498,6 @@ impl<Window: WindowMethods> IOCompositor<Window> { gl::delete_buffers(&render_target_info.texture_ids); gl::delete_frame_buffers(&render_target_info.framebuffer_ids); - if opts::get().use_webrender { - gl::delete_renderbuffers(&render_target_info.renderbuffer_ids); - } // flip image vertically (texture is upside down) let orig_pixels = pixels.clone(); @@ -2385,175 +1522,11 @@ impl<Window: WindowMethods> IOCompositor<Window> { } } - fn composite_if_necessary_if_not_using_webrender(&mut self, reason: CompositingReason) { - if !opts::get().use_webrender { - self.composite_if_necessary(reason) - } - } - fn initialize_compositing(&mut self) { - if self.webrender.is_none() { - let show_debug_borders = opts::get().show_debug_borders; - // We can unwrap native_display because it's only None when using webrender. - self.context = Some(rendergl::RenderContext::new(self.native_display - .expect("n_d should be Some when not using wr").clone(), - show_debug_borders, - opts::get().output_file.is_some())) - } - } - - fn find_topmost_layer_at_point_for_layer(&self, - layer: Rc<Layer<CompositorData>>, - point_in_parent_layer: TypedPoint2D<f32, LayerPixel>, - clip_rect_in_parent_layer: &TypedRect<f32, LayerPixel>) - -> Option<HitTestResult> { - let layer_bounds = *layer.bounds.borrow(); - let masks_to_bounds = *layer.masks_to_bounds.borrow(); - if layer_bounds.is_empty() && masks_to_bounds { - return None; - } - let scroll_offset = layer.extra_data.borrow().scroll_offset; - - // Total offset from parent coordinates to this layer's coordinates. - // FIXME: This offset is incorrect for fixed-position layers. - let layer_offset = scroll_offset + layer_bounds.origin; - - let clipped_layer_bounds = match clip_rect_in_parent_layer.intersection(&layer_bounds) { - Some(rect) => rect, - None => return None, - }; - - let clip_rect_for_children = if masks_to_bounds { - &clipped_layer_bounds - } else { - clip_rect_in_parent_layer - }.translate(&-layer_offset); - - let child_point = point_in_parent_layer - layer_offset; - for child in layer.children().iter().rev() { - // Translate the clip rect into the child's coordinate system. - let result = self.find_topmost_layer_at_point_for_layer(child.clone(), - child_point, - &clip_rect_for_children); - if let Some(mut result) = result { - // Return the point in layer coordinates of the topmost frame containing the point. - let pipeline_id = layer.extra_data.borrow().pipeline_id; - let child_pipeline_id = result.layer.extra_data.borrow().pipeline_id; - if pipeline_id == child_pipeline_id { - result.point = result.point + layer_offset; - } - return Some(result); - } - } - - if !clipped_layer_bounds.contains(&point_in_parent_layer) { - return None; - } - - Some(HitTestResult { layer: layer, point: point_in_parent_layer }) - } - - fn find_topmost_layer_at_point(&self, - point: TypedPoint2D<f32, LayerPixel>) - -> Option<HitTestResult> { - match self.scene.root { - Some(ref layer) => { - self.find_topmost_layer_at_point_for_layer(layer.clone(), - point, - &*layer.bounds.borrow()) - } - - None => None, - } - } - - fn find_layer_with_pipeline_and_layer_id(&self, - pipeline_id: PipelineId, - layer_id: LayerId) - -> Option<Rc<Layer<CompositorData>>> { - match self.scene.root { - Some(ref layer) => - find_layer_with_pipeline_and_layer_id_for_layer(layer.clone(), - pipeline_id, - layer_id), - - None => None, - } - } - - pub fn cache_unused_buffers<B>(&mut self, buffers: B) - where B: IntoIterator<Item=Box<LayerBuffer>> - { - let surfaces = buffers.into_iter().map(|buffer| buffer.native_surface); - if let Some(ref native_display) = self.native_display { - self.surface_map.insert_surfaces(native_display, surfaces); - } } fn get_root_pipeline_id(&self) -> Option<PipelineId> { - self.scene.root.as_ref().map(|root_layer| root_layer.extra_data.borrow().pipeline_id) - } - - #[allow(dead_code)] - fn dump_layer_tree(&self) { - if !opts::get().dump_layer_tree { - return; - } - - let mut print_tree = PrintTree::new("Layer tree".to_owned()); - if let Some(ref layer) = self.scene.root { - self.dump_layer_tree_layer(&**layer, &mut print_tree); - } - } - - #[allow(dead_code)] - fn dump_layer_tree_layer(&self, layer: &Layer<CompositorData>, print_tree: &mut PrintTree) { - let data = layer.extra_data.borrow(); - let layer_string = if data.id == LayerId::null() { - format!("Root Layer (pipeline={})", data.pipeline_id) - } else { - "Layer".to_owned() - }; - - let masks_string = if *layer.masks_to_bounds.borrow() { - " (masks children)" - } else { - "" - }; - - let establishes_3d_context_string = if layer.establishes_3d_context { - " (3D context)" - } else { - "" - }; - - let fixed_string = if data.scroll_policy == ScrollPolicy::FixedPosition { - " (fixed)" - } else { - "" - }; - - let layer_string = format!("{} ({:?}) ({},{} at {},{}){}{}{}", - layer_string, - layer.extra_data.borrow().id, - (*layer.bounds.borrow()).size.to_untyped().width, - (*layer.bounds.borrow()).size.to_untyped().height, - (*layer.bounds.borrow()).origin.to_untyped().x, - (*layer.bounds.borrow()).origin.to_untyped().y, - masks_string, - establishes_3d_context_string, - fixed_string); - - let children = layer.children(); - if !children.is_empty() { - print_tree.new_level(layer_string); - for kid in &*children { - self.dump_layer_tree_layer(&**kid, print_tree); - } - print_tree.end_level(); - } else { - print_tree.add_item(layer_string); - } + self.root_pipeline.as_ref().map(|pipeline| pipeline.id) } fn start_scrolling_bounce_if_necessary(&mut self) { @@ -2561,14 +1534,9 @@ impl<Window: WindowMethods> IOCompositor<Window> { return } - match self.webrender { - Some(ref webrender) if webrender.layers_are_bouncing_back() => {} - _ => return, - } - - if let Some(ref webrender_api) = self.webrender_api { - webrender_api.tick_scrolling_bounce_animations(); - self.send_webrender_viewport_rects() + if self.webrender.layers_are_bouncing_back() { + self.webrender_api.tick_scrolling_bounce_animations(); + self.send_viewport_rects() } } @@ -2612,8 +1580,6 @@ impl<Window: WindowMethods> IOCompositor<Window> { // If a pinch-zoom happened recently, ask for tiles at the new resolution if self.zoom_action && precise_time_s() - self.zoom_time > 0.3 { self.zoom_action = false; - self.scene.mark_layer_contents_as_changed_recursively(); - self.send_buffer_requests_for_all_layers(); } match self.composition_request { @@ -2624,8 +1590,7 @@ impl<Window: WindowMethods> IOCompositor<Window> { } } - if !self.pending_scroll_zoom_events.is_empty() && !self.waiting_for_results_of_scroll && - opts::get().use_webrender { + if !self.pending_scroll_zoom_events.is_empty() && !self.waiting_for_results_of_scroll { self.process_pending_scroll_events() } @@ -2637,37 +1602,19 @@ impl<Window: WindowMethods> IOCompositor<Window> { /// /// This is used when resizing the window. pub fn repaint_synchronously(&mut self) { - if self.webrender.is_none() { - while self.shutdown_state != ShutdownState::ShuttingDown { - let msg = self.port.recv_compositor_msg(); - let received_new_buffers = match msg { - Msg::AssignPaintedBuffers(..) => true, - _ => false, - }; - let keep_going = self.handle_browser_message(msg); - if received_new_buffers { - self.composite(); - break - } - if !keep_going { - break - } + while self.shutdown_state != ShutdownState::ShuttingDown { + let msg = self.port.recv_compositor_msg(); + let need_recomposite = match msg { + Msg::Recomposite(_) => true, + _ => false, + }; + let keep_going = self.handle_browser_message(msg); + if need_recomposite { + self.composite(); + break } - } else { - while self.shutdown_state != ShutdownState::ShuttingDown { - let msg = self.port.recv_compositor_msg(); - let need_recomposite = match msg { - Msg::Recomposite(_) => true, - _ => false, - }; - let keep_going = self.handle_browser_message(msg); - if need_recomposite { - self.composite(); - break - } - if !keep_going { - break - } + if !keep_going { + break } } } @@ -2688,27 +1635,6 @@ impl<Window: WindowMethods> IOCompositor<Window> { } } -fn find_layer_with_pipeline_and_layer_id_for_layer(layer: Rc<Layer<CompositorData>>, - pipeline_id: PipelineId, - layer_id: LayerId) - -> Option<Rc<Layer<CompositorData>>> { - if layer.extra_data.borrow().pipeline_id == pipeline_id && - layer.extra_data.borrow().id == layer_id { - return Some(layer); - } - - for kid in &*layer.children() { - let result = find_layer_with_pipeline_and_layer_id_for_layer(kid.clone(), - pipeline_id, - layer_id); - if result.is_some() { - return result; - } - } - - None -} - /// Why we performed a composite. This is used for debugging. #[derive(Copy, Clone, PartialEq, Debug)] pub enum CompositingReason { diff --git a/components/compositing/compositor_layer.rs b/components/compositing/compositor_layer.rs deleted file mode 100644 index 745da90f2d3..00000000000 --- a/components/compositing/compositor_layer.rs +++ /dev/null @@ -1,542 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use azure::azure_hl; -use compositor::IOCompositor; -use euclid::point::TypedPoint2D; -use euclid::rect::TypedRect; -use euclid::size::TypedSize2D; -use gfx_traits::{Epoch, LayerId, LayerProperties, ScrollPolicy}; -use layers::color::Color; -use layers::geometry::LayerPixel; -use layers::layers::{Layer, LayerBufferSet}; -use msg::constellation_msg::PipelineId; -use script_traits::CompositorEvent; -use script_traits::CompositorEvent::{MouseButtonEvent, MouseMoveEvent, TouchpadPressureEvent}; -use script_traits::ConstellationControlMsg; -use script_traits::MouseEventType; -use script_traits::TouchpadPressurePhase; -use std::rc::Rc; -use windowing::{MouseWindowEvent, WindowMethods}; - -#[derive(Debug)] -pub struct CompositorData { - /// This layer's pipeline id. The compositor can associate this id with an - /// actual CompositionPipeline. - pub pipeline_id: PipelineId, - - /// The ID of this layer within the pipeline. - pub id: LayerId, - - /// The behavior of this layer when a scroll message is received. - pub wants_scroll_events: WantsScrollEventsFlag, - - /// Whether an ancestor layer that receives scroll events moves this layer. - pub scroll_policy: ScrollPolicy, - - /// The epoch that has been requested for this layer (via send_buffer_requests). - pub requested_epoch: Epoch, - - /// The last accepted painted buffer for this layer (via assign_pained_buffers). - pub painted_epoch: Epoch, - - /// The scroll offset originating from this scrolling root. This allows scrolling roots - /// to track their current scroll position even while their content_offset does not change. - pub scroll_offset: TypedPoint2D<f32, LayerPixel>, - - /// The pipeline ID of this layer, if it represents a subpage. - pub subpage_info: Option<PipelineId>, -} - -impl CompositorData { - pub fn new_layer(pipeline_id: PipelineId, - layer_properties: LayerProperties, - wants_scroll_events: WantsScrollEventsFlag, - tile_size: usize) - -> Rc<Layer<CompositorData>> { - let new_compositor_data = CompositorData { - pipeline_id: pipeline_id, - id: layer_properties.id, - wants_scroll_events: wants_scroll_events, - scroll_policy: layer_properties.scroll_policy, - requested_epoch: Epoch(0), - painted_epoch: Epoch(0), - scroll_offset: TypedPoint2D::zero(), - subpage_info: layer_properties.subpage_pipeline_id, - }; - - Rc::new(Layer::new(TypedRect::from_untyped(&layer_properties.rect), - tile_size, - to_layers_color(&layer_properties.background_color), - 1.0, - layer_properties.establishes_3d_context, - new_compositor_data)) - } -} - -pub trait CompositorLayer { - fn update_layer_except_bounds(&self, layer_properties: LayerProperties); - - fn update_layer(&self, layer_properties: LayerProperties); - - fn add_buffers<Window>(&self, - compositor: &mut IOCompositor<Window>, - new_buffers: Box<LayerBufferSet>, - epoch: Epoch) - where Window: WindowMethods; - - /// Destroys all layer tiles, sending the buffers back to the painter to be destroyed or - /// reused. - fn clear<Window>(&self, compositor: &mut IOCompositor<Window>) where Window: WindowMethods; - - /// Destroys tiles for this layer and all descendent layers, sending the buffers back to the - /// painter to be destroyed or reused. - fn clear_all_tiles<Window>(&self, compositor: &mut IOCompositor<Window>) - where Window: WindowMethods; - - /// Removes the root layer (and any children) for a given pipeline from the - /// compositor. Buffers that the compositor is holding are returned to the - /// owning paint thread. - fn remove_root_layer_with_pipeline_id<Window>(&self, - compositor: &mut IOCompositor<Window>, - pipeline_id: PipelineId) - where Window: WindowMethods; - - /// Destroys all tiles of all layers, including children, *without* sending them back to the - /// painter. You must call this only when the paint thread is destined to be going down; - /// otherwise, you will leak tiles. - /// - /// This is used during shutdown, when we know the paint thread is going away. - fn forget_all_tiles(&self); - - /// Move the layer's descendants that don't want scroll events and scroll by a relative - /// specified amount in page coordinates. This also takes in a cursor position to see if the - /// mouse is over child layers first. If a layer successfully scrolled returns either - /// ScrollPositionUnchanged or ScrollPositionChanged. If no layer was targeted by the event - /// returns ScrollEventUnhandled. - fn handle_scroll_event(&self, - delta: TypedPoint2D<f32, LayerPixel>, - cursor: TypedPoint2D<f32, LayerPixel>) - -> ScrollEventResult; - - // Takes in a MouseWindowEvent, determines if it should be passed to children, and - // sends the event off to the appropriate pipeline. NB: the cursor position is in - // client coordinates. - fn send_mouse_event<Window>(&self, - compositor: &IOCompositor<Window>, - event: MouseWindowEvent, - cursor: TypedPoint2D<f32, LayerPixel>) - where Window: WindowMethods; - - fn send_mouse_move_event<Window>(&self, - compositor: &IOCompositor<Window>, - cursor: TypedPoint2D<f32, LayerPixel>) - where Window: WindowMethods; - - fn send_event<Window>(&self, - compositor: &IOCompositor<Window>, - event: CompositorEvent) - where Window: WindowMethods; - - fn send_touchpad_pressure_event<Window>(&self, - compositor: &IOCompositor<Window>, - cursor: TypedPoint2D<f32, LayerPixel>, - pressure: f32, - phase: TouchpadPressurePhase) - where Window: WindowMethods; - - fn clamp_scroll_offset_and_scroll_layer(&self, - new_offset: TypedPoint2D<f32, LayerPixel>) - -> ScrollEventResult; - - fn scroll_layer_and_all_child_layers(&self, - new_offset: TypedPoint2D<f32, LayerPixel>) - -> bool; - - /// Return a flag describing how this layer deals with scroll events. - fn wants_scroll_events(&self) -> WantsScrollEventsFlag; - - /// Return the pipeline id associated with this layer. - fn pipeline_id(&self) -> PipelineId; -} - -pub trait RcCompositorLayer { - /// Traverses the existing layer hierarchy and removes any layers that - /// currently exist but which are no longer required. - fn collect_old_layers<Window>(&self, - compositor: &mut IOCompositor<Window>, - pipeline_id: PipelineId, - new_layers: &[LayerProperties], - pipelines_removed: &mut Vec<PipelineId>) - where Window: WindowMethods; -} - -#[derive(Copy, PartialEq, Clone, Debug)] -pub enum WantsScrollEventsFlag { - WantsScrollEvents, - DoesntWantScrollEvents, -} - -fn to_layers_color(color: &azure_hl::Color) -> Color { - Color { r: color.r, g: color.g, b: color.b, a: color.a } -} - -trait Clampable { - fn clamp(&self, mn: &Self, mx: &Self) -> Self; -} - -impl Clampable for f32 { - /// Returns the number constrained within the range `mn <= self <= mx`. - /// If any of the numbers are `NAN` then `NAN` is returned. - #[inline] - fn clamp(&self, mn: &f32, mx: &f32) -> f32 { - match () { - _ if self.is_nan() => *self, - _ if !(*self <= *mx) => *mx, - _ if !(*self >= *mn) => *mn, - _ => *self, - } - } -} - -fn calculate_content_size_for_layer(layer: &Layer<CompositorData>) - -> TypedSize2D<f32, LayerPixel> { - layer.children().iter().fold(TypedRect::zero(), - |unioned_rect, child_rect| { - unioned_rect.union(&*child_rect.bounds.borrow()) - }).size -} - -#[derive(PartialEq)] -pub enum ScrollEventResult { - ScrollEventUnhandled, - ScrollPositionChanged, - ScrollPositionUnchanged, -} - -impl CompositorLayer for Layer<CompositorData> { - fn update_layer_except_bounds(&self, layer_properties: LayerProperties) { - self.extra_data.borrow_mut().scroll_policy = layer_properties.scroll_policy; - self.extra_data.borrow_mut().subpage_info = layer_properties.subpage_pipeline_id; - *self.transform.borrow_mut() = layer_properties.transform; - *self.perspective.borrow_mut() = layer_properties.perspective; - - *self.background_color.borrow_mut() = to_layers_color(&layer_properties.background_color); - - self.contents_changed(); - } - - fn update_layer(&self, layer_properties: LayerProperties) { - *self.bounds.borrow_mut() = TypedRect::from_untyped(&layer_properties.rect); - - // Call scroll for bounds checking if the page shrunk. Use (-1, -1) as the - // cursor position to make sure the scroll isn't propagated downwards. - self.handle_scroll_event(TypedPoint2D::zero(), TypedPoint2D::new(-1f32, -1f32)); - self.update_layer_except_bounds(layer_properties); - } - - // Add LayerBuffers to the specified layer. Returns the layer buffer set back if the layer that - // matches the given pipeline ID was not found; otherwise returns None and consumes the layer - // buffer set. - // - // If the epoch of the message does not match the layer's epoch, the message is ignored, the - // layer buffer set is consumed, and None is returned. - fn add_buffers<Window>(&self, - compositor: &mut IOCompositor<Window>, - new_buffers: Box<LayerBufferSet>, - epoch: Epoch) - where Window: WindowMethods { - self.extra_data.borrow_mut().painted_epoch = epoch; - assert!(self.extra_data.borrow().painted_epoch == self.extra_data.borrow().requested_epoch); - - for buffer in new_buffers.buffers.into_iter().rev() { - self.add_buffer(buffer); - } - - compositor.cache_unused_buffers(self.collect_unused_buffers()) - } - - fn clear<Window>(&self, compositor: &mut IOCompositor<Window>) where Window: WindowMethods { - let buffers = self.collect_buffers(); - - if !buffers.is_empty() { - compositor.cache_unused_buffers(buffers); - } - } - - /// Destroys tiles for this layer and all descendent layers, sending the buffers back to the - /// painter to be destroyed or reused. - fn clear_all_tiles<Window>(&self, - compositor: &mut IOCompositor<Window>) - where Window: WindowMethods { - self.clear(compositor); - for kid in &*self.children() { - kid.clear_all_tiles(compositor); - } - } - - fn remove_root_layer_with_pipeline_id<Window>(&self, - compositor: &mut IOCompositor<Window>, - pipeline_id: PipelineId) - where Window: WindowMethods { - // Find the child that is the root layer for this pipeline. - let index = self.children().iter().position(|kid| { - let extra_data = kid.extra_data.borrow(); - extra_data.pipeline_id == pipeline_id && extra_data.id == LayerId::null() - }); - - match index { - Some(index) => { - // Remove the root layer, and return buffers to the paint thread - let child = self.children().remove(index); - child.clear_all_tiles(compositor); - } - None => { - // Wasn't found, recurse into child layers - for kid in &*self.children() { - kid.remove_root_layer_with_pipeline_id(compositor, pipeline_id); - } - } - } - } - - /// Destroys all tiles of all layers, including children, *without* sending them back to the - /// painter. You must call this only when the paint thread is destined to be going down; - /// otherwise, you will leak tiles. - /// - /// This is used during shutdown, when we know the paint thread is going away. - fn forget_all_tiles(&self) { - let tiles = self.collect_buffers(); - for tile in tiles { - let mut tile = tile; - tile.mark_wont_leak() - } - - for kid in &*self.children() { - kid.forget_all_tiles(); - } - } - - fn handle_scroll_event(&self, - delta: TypedPoint2D<f32, LayerPixel>, - cursor: TypedPoint2D<f32, LayerPixel>) - -> ScrollEventResult { - // Allow children to scroll. - let scroll_offset = self.extra_data.borrow().scroll_offset; - let new_cursor = cursor - scroll_offset; - for child in self.children().iter().rev() { - let child_bounds = child.bounds.borrow(); - if child_bounds.contains(&new_cursor) { - let result = child.handle_scroll_event(delta, new_cursor - child_bounds.origin); - if result != ScrollEventResult::ScrollEventUnhandled { - return result; - } - } - } - - // If this layer doesn't want scroll events, it can't handle scroll events. - if self.wants_scroll_events() != WantsScrollEventsFlag::WantsScrollEvents { - return ScrollEventResult::ScrollEventUnhandled; - } - - self.clamp_scroll_offset_and_scroll_layer(scroll_offset + delta) - } - - fn clamp_scroll_offset_and_scroll_layer(&self, new_offset: TypedPoint2D<f32, LayerPixel>) - -> ScrollEventResult { - let layer_size = self.bounds.borrow().size; - let content_size = calculate_content_size_for_layer(self); - let min_x = (layer_size.width - content_size.width).min(0.0); - let min_y = (layer_size.height - content_size.height).min(0.0); - let new_offset: TypedPoint2D<f32, LayerPixel> = - TypedPoint2D::new(new_offset.x.clamp(&min_x, &0.0), - new_offset.y.clamp(&min_y, &0.0)); - - if self.extra_data.borrow().scroll_offset == new_offset { - return ScrollEventResult::ScrollPositionUnchanged; - } - - // The scroll offset is just a record of the scroll position of this scrolling root, - // but scroll_layer_and_all_child_layers actually moves the child layers. - self.extra_data.borrow_mut().scroll_offset = new_offset; - - let mut result = false; - for child in &*self.children() { - result |= child.scroll_layer_and_all_child_layers(new_offset); - } - - if result { - ScrollEventResult::ScrollPositionChanged - } else { - ScrollEventResult::ScrollPositionUnchanged - } - } - - fn send_mouse_event<Window>(&self, - compositor: &IOCompositor<Window>, - event: MouseWindowEvent, - cursor: TypedPoint2D<f32, LayerPixel>) - where Window: WindowMethods { - let event_point = cursor.to_untyped(); - let message = match event { - MouseWindowEvent::Click(button, _) => - MouseButtonEvent(MouseEventType::Click, button, event_point), - MouseWindowEvent::MouseDown(button, _) => - MouseButtonEvent(MouseEventType::MouseDown, button, event_point), - MouseWindowEvent::MouseUp(button, _) => - MouseButtonEvent(MouseEventType::MouseUp, button, event_point), - }; - self.send_event(compositor, message); - } - - fn send_mouse_move_event<Window>(&self, - compositor: &IOCompositor<Window>, - cursor: TypedPoint2D<f32, LayerPixel>) - where Window: WindowMethods { - self.send_event(compositor, MouseMoveEvent(Some(cursor.to_untyped()))); - } - - fn send_event<Window>(&self, - compositor: &IOCompositor<Window>, - event: CompositorEvent) where Window: WindowMethods { - if let Some(pipeline) = compositor.pipeline(self.pipeline_id()) { - let _ = pipeline.script_chan - .send(ConstellationControlMsg::SendEvent(pipeline.id.clone(), event)); - } - } - - fn send_touchpad_pressure_event<Window>(&self, - compositor: &IOCompositor<Window>, - cursor: TypedPoint2D<f32, LayerPixel>, - pressure: f32, - phase: TouchpadPressurePhase) - where Window: WindowMethods { - if let Some(pipeline) = compositor.pipeline(self.pipeline_id()) { - let message = TouchpadPressureEvent(cursor.to_untyped(), pressure, phase); - let _ = pipeline.script_chan.send(ConstellationControlMsg::SendEvent(pipeline.id.clone(), message)); - } - } - - fn scroll_layer_and_all_child_layers(&self, new_offset: TypedPoint2D<f32, LayerPixel>) - -> bool { - let mut result = false; - - // Only scroll this layer if it's not fixed-positioned. - if self.extra_data.borrow().scroll_policy != ScrollPolicy::FixedPosition { - let new_offset = new_offset.to_untyped(); - *self.content_offset.borrow_mut() = TypedPoint2D::from_untyped(&new_offset); - result = true - } - - let offset_for_children = new_offset + self.extra_data.borrow().scroll_offset; - for child in &*self.children() { - result |= child.scroll_layer_and_all_child_layers(offset_for_children); - } - - result - } - - fn wants_scroll_events(&self) -> WantsScrollEventsFlag { - self.extra_data.borrow().wants_scroll_events - } - - fn pipeline_id(&self) -> PipelineId { - self.extra_data.borrow().pipeline_id - } -} - -impl RcCompositorLayer for Rc<Layer<CompositorData>> { - fn collect_old_layers<Window>(&self, - compositor: &mut IOCompositor<Window>, - pipeline_id: PipelineId, - new_layers: &[LayerProperties], - pipelines_removed: &mut Vec<PipelineId>) - where Window: WindowMethods { - fn find_root_layer_for_pipeline(layer: &Rc<Layer<CompositorData>>, pipeline_id: PipelineId) - -> Option<Rc<Layer<CompositorData>>> { - let extra_data = layer.extra_data.borrow(); - if extra_data.pipeline_id == pipeline_id { - return Some((*layer).clone()) - } - - for kid in &*layer.children() { - if let Some(layer) = find_root_layer_for_pipeline(kid, pipeline_id) { - return Some(layer.clone()) - } - } - None - } - - fn collect_old_layers_for_pipeline<Window>( - layer: &Layer<CompositorData>, - compositor: &mut IOCompositor<Window>, - pipeline_id: PipelineId, - new_layers: &[LayerProperties], - pipelines_removed: &mut Vec<PipelineId>, - layer_pipeline_id: Option<PipelineId>) - where Window: WindowMethods { - // Traverse children first so that layers are removed - // bottom up - allowing each layer being removed to properly - // clean up any tiles it owns. - for kid in &*layer.children() { - let extra_data = kid.extra_data.borrow(); - let layer_pipeline_id = extra_data.subpage_info.or(layer_pipeline_id); - - collect_old_layers_for_pipeline(kid, - compositor, - pipeline_id, - new_layers, - pipelines_removed, - layer_pipeline_id); - } - - // Retain child layers that also exist in the new layer list. - layer.children().retain(|child| { - let extra_data = child.extra_data.borrow(); - if pipeline_id == extra_data.pipeline_id { - // Never remove our own root layer. - if extra_data.id == LayerId::null() { - return true - } - - // Keep this layer if it exists in the new layer list. - if new_layers.iter().any(|properties| properties.id == extra_data.id) { - return true - } - } - - if let Some(layer_pipeline_id) = layer_pipeline_id { - for layer_properties in new_layers.iter() { - // Keep this layer if a reference to it exists. - if let Some(ref subpage_pipeline_id) = layer_properties.subpage_pipeline_id { - if *subpage_pipeline_id == layer_pipeline_id { - return true - } - } - } - - pipelines_removed.push(extra_data.pipeline_id); - } - - // When removing a layer, clear any tiles and surfaces associated with the layer. - child.clear_all_tiles(compositor); - false - }); - } - - // First, find the root layer with the given pipeline ID. - let root_layer = match find_root_layer_for_pipeline(self, pipeline_id) { - Some(root_layer) => root_layer, - None => return, - }; - - // Then collect all old layers underneath that layer. - collect_old_layers_for_pipeline(&root_layer, - compositor, - pipeline_id, - new_layers, - pipelines_removed, - None); - } -} diff --git a/components/compositing/compositor_thread.rs b/components/compositing/compositor_thread.rs index 49d0692e6c8..3ff92b5129e 100644 --- a/components/compositing/compositor_thread.rs +++ b/components/compositing/compositor_thread.rs @@ -8,16 +8,14 @@ use SendableFrameTree; use compositor::CompositingReason; use euclid::point::Point2D; use euclid::size::Size2D; -use gfx_traits::{Epoch, FrameTreeId, LayerId, LayerProperties, PaintListener}; +use gfx_traits::LayerId; use ipc_channel::ipc::IpcSender; -use layers::layers::{BufferRequest, LayerBufferSet}; -use layers::platform::surface::{NativeDisplay, NativeSurface}; use msg::constellation_msg::{Image, Key, KeyModifiers, KeyState, PipelineId}; use profile_traits::mem; use profile_traits::time; use script_traits::{AnimationState, ConstellationMsg, EventResult}; use std::fmt::{Debug, Error, Formatter}; -use std::sync::mpsc::{Receiver, Sender, channel}; +use std::sync::mpsc::{Receiver, Sender}; use style_traits::cursor::Cursor; use style_traits::viewport::ViewportConstraints; use url::Url; @@ -63,55 +61,6 @@ impl RenderListener for Box<CompositorProxy + 'static> { } } -/// Implementation of the abstract `PaintListener` interface. -impl PaintListener for Box<CompositorProxy + 'static + Send> { - fn native_display(&mut self) -> Option<NativeDisplay> { - let (chan, port) = channel(); - self.send(Msg::GetNativeDisplay(chan)); - // If the compositor is shutting down when a paint thread - // is being created, the compositor won't respond to - // this message, resulting in an eventual panic. Instead, - // just return None in this case, since the paint thread - // will exit shortly and never actually be requested - // to paint buffers by the compositor. - port.recv().unwrap_or(None) - } - - fn assign_painted_buffers(&mut self, - pipeline_id: PipelineId, - epoch: Epoch, - replies: Vec<(LayerId, Box<LayerBufferSet>)>, - frame_tree_id: FrameTreeId) { - self.send(Msg::AssignPaintedBuffers(pipeline_id, epoch, replies, frame_tree_id)); - } - - fn ignore_buffer_requests(&mut self, buffer_requests: Vec<BufferRequest>) { - let mut native_surfaces = Vec::new(); - for request in buffer_requests.into_iter() { - if let Some(native_surface) = request.native_surface { - native_surfaces.push(native_surface); - } - } - if !native_surfaces.is_empty() { - self.send(Msg::ReturnUnusedNativeSurfaces(native_surfaces)); - } - } - - fn initialize_layers_for_pipeline(&mut self, - pipeline_id: PipelineId, - properties: Vec<LayerProperties>, - epoch: Epoch) { - // FIXME(#2004, pcwalton): This assumes that the first layer determines the page size, and - // that all other layers are immediate children of it. This is sufficient to handle - // `position: fixed` but will not be sufficient to handle `overflow: scroll` or transforms. - self.send(Msg::InitializeLayersForPipeline(pipeline_id, epoch, properties)); - } - - fn notify_paint_thread_exiting(&mut self, pipeline_id: PipelineId) { - self.send(Msg::PaintThreadExited(pipeline_id)) - } -} - /// Messages from the painting thread and the constellation thread to the compositor thread. pub enum Msg { /// Requests that the compositor shut down. @@ -122,18 +71,8 @@ pub enum Msg { /// (e.g. SetFrameTree) at the time that we send it an ExitMsg. ShutdownComplete, - /// Requests the compositor's graphics metadata. Graphics metadata is what the painter needs - /// to create surfaces that the compositor can see. On Linux this is the X display; on Mac this - /// is the pixel format. - GetNativeDisplay(Sender<Option<NativeDisplay>>), - - /// Tells the compositor to create or update the layers for a pipeline if necessary - /// (i.e. if no layer with that ID exists). - InitializeLayersForPipeline(PipelineId, Epoch, Vec<LayerProperties>), /// Scroll a page in a window ScrollFragmentPoint(PipelineId, LayerId, Point2D<f32>, bool), - /// Requests that the compositor assign the painted buffers to the given layers. - AssignPaintedBuffers(PipelineId, Epoch, Vec<(LayerId, Box<LayerBufferSet>)>, FrameTreeId), /// Alerts the compositor that the current page has changed its title. ChangePageTitle(PipelineId, Option<String>), /// Alerts the compositor that the current page has changed its URL. @@ -158,8 +97,6 @@ pub enum Msg { SetCursor(Cursor), /// Composite to a PNG file and return the Image over a passed channel. CreatePng(IpcSender<Option<Image>>), - /// Informs the compositor that the paint thread for the given pipeline has exited. - PaintThreadExited(PipelineId), /// Alerts the compositor that the viewport has been constrained in some manner ViewportConstrained(PipelineId, ViewportConstraints), /// A reply to the compositor asking if the output image is stable. @@ -168,9 +105,6 @@ pub enum Msg { NewFavicon(Url), /// <head> tag finished parsing HeadParsed, - /// Signal that the paint thread ignored the paint requests that carried - /// these native surfaces, so that they can be re-added to the surface cache. - ReturnUnusedNativeSurfaces(Vec<NativeSurface>), /// Collect memory reports and send them back to the given mem::ReportsChan. CollectMemoryReports(mem::ReportsChan), /// A status message to be displayed by the browser chrome. @@ -181,8 +115,6 @@ pub enum Msg { MoveTo(Point2D<i32>), /// Resize the window to size ResizeTo(Size2D<u32>), - /// Get scroll offset of a layer - GetScrollOffset(PipelineId, LayerId, IpcSender<Point2D<f32>>), /// Pipeline visibility changed PipelineVisibilityChanged(PipelineId, bool), /// WebRender has successfully processed a scroll. The boolean specifies whether a composite is @@ -201,10 +133,7 @@ impl Debug for Msg { match *self { Msg::Exit => write!(f, "Exit"), Msg::ShutdownComplete => write!(f, "ShutdownComplete"), - Msg::GetNativeDisplay(..) => write!(f, "GetNativeDisplay"), - Msg::InitializeLayersForPipeline(..) => write!(f, "InitializeLayersForPipeline"), Msg::ScrollFragmentPoint(..) => write!(f, "ScrollFragmentPoint"), - Msg::AssignPaintedBuffers(..) => write!(f, "AssignPaintedBuffers"), Msg::ChangeRunningAnimationsState(..) => write!(f, "ChangeRunningAnimationsState"), Msg::ChangePageTitle(..) => write!(f, "ChangePageTitle"), Msg::ChangePageUrl(..) => write!(f, "ChangePageUrl"), @@ -217,12 +146,10 @@ impl Debug for Msg { Msg::TouchEventProcessed(..) => write!(f, "TouchEventProcessed"), Msg::SetCursor(..) => write!(f, "SetCursor"), Msg::CreatePng(..) => write!(f, "CreatePng"), - Msg::PaintThreadExited(..) => write!(f, "PaintThreadExited"), Msg::ViewportConstrained(..) => write!(f, "ViewportConstrained"), Msg::IsReadyToSaveImageReply(..) => write!(f, "IsReadyToSaveImageReply"), Msg::NewFavicon(..) => write!(f, "NewFavicon"), Msg::HeadParsed => write!(f, "HeadParsed"), - Msg::ReturnUnusedNativeSurfaces(..) => write!(f, "ReturnUnusedNativeSurfaces"), Msg::CollectMemoryReports(..) => write!(f, "CollectMemoryReports"), Msg::Status(..) => write!(f, "Status"), Msg::GetClientWindow(..) => write!(f, "GetClientWindow"), @@ -230,7 +157,6 @@ impl Debug for Msg { Msg::ResizeTo(..) => write!(f, "ResizeTo"), Msg::PipelineVisibilityChanged(..) => write!(f, "PipelineVisibilityChanged"), Msg::PipelineExited(..) => write!(f, "PipelineExited"), - Msg::GetScrollOffset(..) => write!(f, "GetScrollOffset"), Msg::NewScrollFrameReady(..) => write!(f, "NewScrollFrameReady"), } } @@ -248,7 +174,7 @@ pub struct InitialCompositorState { pub time_profiler_chan: time::ProfilerChan, /// A channel to the memory profiler thread. pub mem_profiler_chan: mem::ProfilerChan, - /// Instance of webrender API if enabled - pub webrender: Option<webrender::Renderer>, - pub webrender_api_sender: Option<webrender_traits::RenderApiSender>, + /// Instance of webrender API + pub webrender: webrender::Renderer, + pub webrender_api_sender: webrender_traits::RenderApiSender, } diff --git a/components/compositing/lib.rs b/components/compositing/lib.rs index c51fb23ee3e..e976b52f09e 100644 --- a/components/compositing/lib.rs +++ b/components/compositing/lib.rs @@ -10,15 +10,11 @@ #![deny(unsafe_code)] -extern crate app_units; - -extern crate azure; extern crate euclid; extern crate gfx_traits; extern crate gleam; extern crate image; extern crate ipc_channel; -extern crate layers; #[macro_use] extern crate log; extern crate msg; @@ -39,18 +35,14 @@ extern crate webrender_traits; pub use compositor_thread::CompositorProxy; pub use compositor::IOCompositor; use euclid::size::TypedSize2D; -use gfx_traits::ChromeToPaintMsg; use ipc_channel::ipc::IpcSender; use msg::constellation_msg::PipelineId; use script_traits::{ConstellationControlMsg, LayoutControlMsg}; -use std::sync::mpsc::Sender; use style_traits::PagePx; mod compositor; -mod compositor_layer; pub mod compositor_thread; mod delayed_composition; -mod surface_map; mod touch; pub mod windowing; @@ -66,5 +58,4 @@ pub struct CompositionPipeline { pub id: PipelineId, pub script_chan: IpcSender<ConstellationControlMsg>, pub layout_chan: IpcSender<LayoutControlMsg>, - pub chrome_to_paint_chan: Sender<ChromeToPaintMsg>, } diff --git a/components/compositing/surface_map.rs b/components/compositing/surface_map.rs deleted file mode 100644 index 97b10a0677e..00000000000 --- a/components/compositing/surface_map.rs +++ /dev/null @@ -1,164 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use euclid::size::Size2D; -use layers::platform::surface::{NativeDisplay, NativeSurface}; -use std::collections::HashMap; -use std::collections::hash_map::Entry::{Occupied, Vacant}; -use std::hash::{Hash, Hasher}; - -/// This is a struct used to store surfaces when they are not in use. -/// The paint thread can quickly query for a particular size of surface when it -/// needs it. -pub struct SurfaceMap { - /// A HashMap that stores the Buffers. - map: HashMap<SurfaceKey, SurfaceValue>, - /// The current amount of memory stored by the SurfaceMap's surfaces. - mem: usize, - /// The maximum allowed memory. Unused surfaces will be deleted - /// when this threshold is exceeded. - max_mem: usize, - /// A monotonically increasing counter to track how recently tile sizes were used. - counter: usize, -} - -/// A key with which to store surfaces. It is based on the size of the surface. -#[derive(Eq, Copy, Clone)] -struct SurfaceKey([i32; 2]); - -impl Hash for SurfaceKey { - fn hash<H: Hasher>(&self, state: &mut H) { - self.0.hash(state); - } -} - -impl PartialEq for SurfaceKey { - fn eq(&self, other: &SurfaceKey) -> bool { - let SurfaceKey(s) = *self; - let SurfaceKey(o) = *other; - s[0] == o[0] && s[1] == o[1] - } -} - -/// Create a key from a given size -impl SurfaceKey { - fn get(input: Size2D<i32>) -> SurfaceKey { - SurfaceKey([input.width, input.height]) - } -} - -/// A helper struct to keep track of surfaces in the HashMap -struct SurfaceValue { - /// An array of surfaces, all the same size - surfaces: Vec<NativeSurface>, - /// The counter when this size was last requested - last_action: usize, -} - -impl SurfaceMap { - // Creates a new SurfaceMap with a given surface limit. - pub fn new(max_mem: usize) -> SurfaceMap { - SurfaceMap { - map: HashMap::new(), - mem: 0, - max_mem: max_mem, - counter: 0, - } - } - - pub fn insert_surfaces<I>(&mut self, display: &NativeDisplay, surfaces: I) - where I: IntoIterator<Item=NativeSurface> - { - for surface in surfaces { - self.insert(display, surface); - } - } - - /// Insert a new buffer into the map. - pub fn insert(&mut self, display: &NativeDisplay, mut new_surface: NativeSurface) { - let new_key = SurfaceKey::get(new_surface.get_size()); - - // If all our surfaces are the same size and we're already at our - // memory limit, no need to store this new buffer; just let it drop. - let new_total_memory_usage = self.mem + new_surface.get_memory_usage(); - if new_total_memory_usage > self.max_mem && self.map.len() == 1 && - self.map.contains_key(&new_key) { - new_surface.destroy(display); - return; - } - - self.mem = new_total_memory_usage; - new_surface.mark_wont_leak(); - - // use lazy insertion function to prevent unnecessary allocation - let counter = &self.counter; - match self.map.entry(new_key) { - Occupied(entry) => { - entry.into_mut().surfaces.push(new_surface); - } - Vacant(entry) => { - entry.insert(SurfaceValue { - surfaces: vec!(new_surface), - last_action: *counter, - }); - } - } - - let mut opt_key: Option<SurfaceKey> = None; - while self.mem > self.max_mem { - let old_key = match opt_key { - Some(key) => key, - None => { - match self.map.iter().min_by_key(|&(_, x)| x.last_action) { - Some((k, _)) => *k, - None => panic!("SurfaceMap: tried to delete with no elements in map"), - } - } - }; - if { - let list = &mut self.map.get_mut(&old_key).unwrap().surfaces; - let mut condemned_surface = list.pop().take().unwrap(); - self.mem -= condemned_surface.get_memory_usage(); - condemned_surface.destroy(display); - list.is_empty() - } - { // then - self.map.remove(&old_key); // Don't store empty vectors! - opt_key = None; - } else { - opt_key = Some(old_key); - } - } - } - - // Try to find a buffer for the given size. - pub fn find(&mut self, size: Size2D<i32>) -> Option<NativeSurface> { - let mut flag = false; // True if key needs to be popped after retrieval. - let key = SurfaceKey::get(size); - let ret = match self.map.get_mut(&key) { - Some(ref mut surface_val) => { - surface_val.last_action = self.counter; - self.counter += 1; - - let surface = surface_val.surfaces.pop().take().unwrap(); - self.mem -= surface.get_memory_usage(); - if surface_val.surfaces.is_empty() { - flag = true; - } - Some(surface) - } - None => None, - }; - - if flag { - self.map.remove(&key); // Don't store empty vectors! - } - - ret - } - - pub fn mem(&self) -> usize { - self.mem - } -} diff --git a/components/compositing/touch.rs b/components/compositing/touch.rs index 3bc22440994..24d3e5cf0e5 100644 --- a/components/compositing/touch.rs +++ b/components/compositing/touch.rs @@ -4,7 +4,7 @@ use euclid::point::TypedPoint2D; use euclid::scale_factor::ScaleFactor; -use layers::geometry::DevicePixel; +use gfx_traits::DevicePixel; use script_traits::{EventResult, TouchId}; use self::TouchState::*; diff --git a/components/compositing/windowing.rs b/components/compositing/windowing.rs index 85b03dd7e9a..7ac9c999aa0 100644 --- a/components/compositing/windowing.rs +++ b/components/compositing/windowing.rs @@ -9,8 +9,7 @@ use euclid::{Point2D, Size2D}; use euclid::point::TypedPoint2D; use euclid::scale_factor::ScaleFactor; use euclid::size::TypedSize2D; -use layers::geometry::DevicePixel; -use layers::platform::surface::NativeDisplay; +use gfx_traits::DevicePixel; use msg::constellation_msg::{Key, KeyModifiers, KeyState}; use net_traits::net_error_list::NetError; use script_traits::{MouseButton, TouchEventType, TouchId, TouchpadPressurePhase}; @@ -139,9 +138,6 @@ pub trait WindowMethods { /// Returns the scale factor of the system (device pixels / screen pixels). fn scale_factor(&self) -> ScaleFactor<f32, ScreenPx, DevicePixel>; - /// Gets the OS native graphics display for this window. - fn native_display(&self) -> NativeDisplay; - /// Creates a channel to the compositor. The dummy parameter is needed because we don't have /// UFCS in Rust yet. /// diff --git a/components/constellation/Cargo.toml b/components/constellation/Cargo.toml index 62d76de999a..6b3a864c88a 100644 --- a/components/constellation/Cargo.toml +++ b/components/constellation/Cargo.toml @@ -19,7 +19,6 @@ euclid = "0.10.1" gfx = {path = "../gfx"} gfx_traits = {path = "../gfx_traits"} ipc-channel = "0.5" -layers = {git = "https://github.com/servo/rust-layers", features = ["plugins"]} layout_traits = {path = "../layout_traits"} log = "0.3.5" msg = {path = "../msg"} diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index 35d57bbf0e0..804eb8e96c2 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -172,8 +172,8 @@ pub struct Constellation<Message, LTF, STF> { /// Document states for loaded pipelines (used only when writing screenshots). document_states: HashMap<PipelineId, DocumentState>, - // Webrender interface, if enabled. - webrender_api_sender: Option<webrender_traits::RenderApiSender>, + // Webrender interface. + webrender_api_sender: webrender_traits::RenderApiSender, /// Are we shutting down? shutting_down: bool, @@ -209,8 +209,8 @@ pub struct InitialConstellationState { pub mem_profiler_chan: mem::ProfilerChan, /// Whether the constellation supports the clipboard. pub supports_clipboard: bool, - /// Optional webrender API reference (if enabled). - pub webrender_api_sender: Option<webrender_traits::RenderApiSender>, + /// Webrender API. + pub webrender_api_sender: webrender_traits::RenderApiSender, } #[derive(Debug, Clone)] @@ -971,9 +971,6 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF> self.compositor_proxy.send(ToCompositorMsg::TouchEventProcessed(result)) } - FromScriptMsg::GetScrollOffset(pid, lid, send) => { - self.compositor_proxy.send(ToCompositorMsg::GetScrollOffset(pid, lid, send)); - } FromScriptMsg::RegisterServiceWorker(scope_things, scope) => { debug!("constellation got store registration scope message"); self.handle_register_serviceworker(scope_things, scope); @@ -1852,8 +1849,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF> } // Set paint permissions correctly for the compositor layers. - self.revoke_paint_permission(prev_pipeline_id); - self.send_frame_tree_and_grant_paint_permission(); + self.send_frame_tree(); // Update the owning iframe to point to the new pipeline id. // This makes things like contentDocument work correctly. @@ -1910,12 +1906,6 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF> } } - if let Some(old_pipeline_id) = frame_change.old_pipeline_id { - // The new pipeline is replacing an old one. - // Remove paint permissions for the pipeline being replaced. - self.revoke_paint_permission(old_pipeline_id); - }; - if self.frames.contains_key(&frame_change.frame_id) { // Mature the new pipeline, and return frames evicted from history. if let Some(ref mut pipeline) = self.pipelines.get_mut(&frame_change.new_pipeline_id) { @@ -1958,8 +1948,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF> self.clear_joint_session_future(top_level_frame_id); } - // Build frame tree and send permission - self.send_frame_tree_and_grant_paint_permission(); + // Build frame tree + self.send_frame_tree(); } fn handle_activate_document_msg(&mut self, pipeline_id: PipelineId) { @@ -2339,20 +2329,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF> }) } - // Revoke paint permission from a pipeline, and all children. - fn revoke_paint_permission(&self, pipeline_id: PipelineId) { - if let Some(pipeline) = self.pipelines.get(&pipeline_id) { - for frame in self.current_frame_tree_iter(pipeline.frame_id) { - if let Some(pipeline) = self.pipelines.get(&frame.current.pipeline_id) { - pipeline.revoke_paint_permission(); - } - } - } - } - - // Send the current frame tree to compositor, and grant paint - // permission to each pipeline in the current frame tree. - fn send_frame_tree_and_grant_paint_permission(&mut self) { + // Send the current frame tree to compositor + fn send_frame_tree(&mut self) { // Note that this function can panic, due to ipc-channel creation failure. // avoiding this panic would require a mechanism for dealing // with low-resource scenarios. @@ -2365,10 +2343,6 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF> return; // Our message has been discarded, probably shutting down. } } - - for frame in self.current_frame_tree_iter(self.root_frame_id) { - self.pipelines.get(&frame.current.pipeline_id).map(|pipeline| pipeline.grant_paint_permission()); - } } /// For a given pipeline, determine the mozbrowser iframe that transitively contains diff --git a/components/constellation/lib.rs b/components/constellation/lib.rs index 0ac6ecb947d..072d8605712 100644 --- a/components/constellation/lib.rs +++ b/components/constellation/lib.rs @@ -22,7 +22,6 @@ extern crate gaol; extern crate gfx; extern crate gfx_traits; extern crate ipc_channel; -extern crate layers; extern crate layout_traits; #[macro_use] extern crate log; diff --git a/components/constellation/pipeline.rs b/components/constellation/pipeline.rs index 377fa4c0c20..6f755489392 100644 --- a/components/constellation/pipeline.rs +++ b/components/constellation/pipeline.rs @@ -11,11 +11,9 @@ use euclid::size::TypedSize2D; #[cfg(not(target_os = "windows"))] use gaol; use gfx::font_cache_thread::FontCacheThread; -use gfx::paint_thread::{LayoutToPaintMsg, PaintThread}; -use gfx_traits::ChromeToPaintMsg; +use gfx_traits::DevicePixel; use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; use ipc_channel::router::ROUTER; -use layers::geometry::DevicePixel; use layout_traits::LayoutThreadFactory; use msg::constellation_msg::{FrameId, FrameType, LoadData, PipelineId, PipelineNamespaceId}; use net_traits::{IpcSend, ResourceThreads}; @@ -31,11 +29,9 @@ use std::env; use std::ffi::OsStr; use std::io::Error as IOError; use std::process; -use std::sync::mpsc::{Sender, channel}; +use std::sync::mpsc::Sender; use style_traits::{PagePx, ViewportPx}; use url::Url; -use util; -use util::ipc::OptionalIpcSender; use util::opts::{self, Opts}; use util::prefs::{PREFS, Pref}; use webrender_traits; @@ -58,7 +54,6 @@ pub struct Pipeline { pub layout_chan: IpcSender<LayoutControlMsg>, /// A channel to the compositor. pub compositor_proxy: Box<CompositorProxy + 'static + Send>, - pub chrome_to_paint_chan: Sender<ChromeToPaintMsg>, /// URL corresponding to the most recently-loaded page. pub url: Url, /// The title of the most recently-loaded page. @@ -127,8 +122,8 @@ pub struct InitialPipelineState { pub pipeline_namespace_id: PipelineNamespaceId, /// Pipeline visibility to be inherited pub prev_visibility: Option<bool>, - /// Optional webrender api (if enabled). - pub webrender_api_sender: Option<webrender_traits::RenderApiSender>, + /// Webrender api. + pub webrender_api_sender: webrender_traits::RenderApiSender, /// Whether this pipeline is considered private. pub is_private: bool, } @@ -143,8 +138,6 @@ impl Pipeline { { // Note: we allow channel creation to panic, since recovering from this // probably requires a general low-memory strategy. - let (layout_to_paint_chan, layout_to_paint_port) = util::ipc::optional_ipc_channel(); - let (chrome_to_paint_chan, chrome_to_paint_port) = channel(); let (pipeline_chan, pipeline_port) = ipc::channel() .expect("Pipeline main chan");; @@ -160,7 +153,6 @@ impl Pipeline { new_pipeline_id: state.id, frame_type: frame_type, load_data: state.load_data.clone(), - paint_chan: layout_to_paint_chan.clone().to_opaque(), pipeline_port: pipeline_port, layout_to_constellation_chan: state.layout_to_constellation_chan.clone(), content_process_shutdown_chan: layout_content_process_shutdown_chan.clone(), @@ -178,16 +170,6 @@ impl Pipeline { } }; - PaintThread::create(state.id, - state.load_data.url.clone(), - chrome_to_paint_chan.clone(), - layout_to_paint_port, - chrome_to_paint_port, - state.compositor_proxy.clone_compositor_proxy(), - state.font_cache_thread.clone(), - state.time_profiler_chan.clone(), - state.mem_profiler_chan.clone()); - let mut child_process = None; if let Some((script_port, pipeline_port)) = content_ports { // Route messages coming from content to devtools as appropriate. @@ -238,7 +220,6 @@ impl Pipeline { script_port: script_port, opts: (*opts::get()).clone(), prefs: PREFS.cloned(), - layout_to_paint_chan: layout_to_paint_chan, pipeline_port: pipeline_port, pipeline_namespace_id: state.pipeline_namespace_id, layout_content_process_shutdown_chan: layout_content_process_shutdown_chan, @@ -264,7 +245,6 @@ impl Pipeline { script_chan, pipeline_chan, state.compositor_proxy, - chrome_to_paint_chan, state.is_private, state.load_data.url, state.window_size, @@ -281,7 +261,6 @@ impl Pipeline { script_chan: IpcSender<ConstellationControlMsg>, layout_chan: IpcSender<LayoutControlMsg>, compositor_proxy: Box<CompositorProxy + 'static + Send>, - chrome_to_paint_chan: Sender<ChromeToPaintMsg>, is_private: bool, url: Url, size: Option<TypedSize2D<f32, PagePx>>, @@ -294,7 +273,6 @@ impl Pipeline { script_chan: script_chan, layout_chan: layout_chan, compositor_proxy: compositor_proxy, - chrome_to_paint_chan: chrome_to_paint_chan, url: url, title: None, children: vec!(), @@ -306,15 +284,6 @@ impl Pipeline { } } - pub fn grant_paint_permission(&self) { - let _ = self.chrome_to_paint_chan.send(ChromeToPaintMsg::PaintPermissionGranted); - } - - pub fn revoke_paint_permission(&self) { - debug!("pipeline revoking paint channel paint permission"); - let _ = self.chrome_to_paint_chan.send(ChromeToPaintMsg::PaintPermissionRevoked); - } - pub fn exit(&self) { debug!("pipeline {:?} exiting", self.id); @@ -353,9 +322,6 @@ impl Pipeline { if let Err(e) = self.script_chan.send(ConstellationControlMsg::ExitPipeline(self.id)) { warn!("Sending script exit message failed ({}).", e); } - if let Err(e) = self.chrome_to_paint_chan.send(ChromeToPaintMsg::Exit) { - warn!("Sending paint exit message failed ({}).", e); - } if let Err(e) = self.layout_chan.send(LayoutControlMsg::ExitNow) { warn!("Sending layout exit message failed ({}).", e); } @@ -366,7 +332,6 @@ impl Pipeline { id: self.id.clone(), script_chan: self.script_chan.clone(), layout_chan: self.layout_chan.clone(), - chrome_to_paint_chan: self.chrome_to_paint_chan.clone(), } } @@ -430,7 +395,6 @@ pub struct UnprivilegedPipelineContent { script_chan: IpcSender<ConstellationControlMsg>, load_data: LoadData, script_port: IpcReceiver<ConstellationControlMsg>, - layout_to_paint_chan: OptionalIpcSender<LayoutToPaintMsg>, opts: Opts, prefs: HashMap<String, Pref>, pipeline_port: IpcReceiver<LayoutControlMsg>, @@ -439,7 +403,7 @@ pub struct UnprivilegedPipelineContent { layout_content_process_shutdown_port: IpcReceiver<()>, script_content_process_shutdown_chan: IpcSender<()>, script_content_process_shutdown_port: IpcReceiver<()>, - webrender_api_sender: Option<webrender_traits::RenderApiSender>, + webrender_api_sender: webrender_traits::RenderApiSender, } impl UnprivilegedPipelineContent { @@ -472,7 +436,6 @@ impl UnprivilegedPipelineContent { self.pipeline_port, self.layout_to_constellation_chan, self.script_chan, - self.layout_to_paint_chan, self.image_cache_thread, self.font_cache_thread, self.time_profiler_chan, diff --git a/components/gfx/Cargo.toml b/components/gfx/Cargo.toml index 4bd27945b3f..cc008dc6e87 100644 --- a/components/gfx/Cargo.toml +++ b/components/gfx/Cargo.toml @@ -22,7 +22,6 @@ harfbuzz-sys = "0.1" heapsize = "0.3.0" heapsize_plugin = "0.1.2" ipc-channel = "0.5" -layers = {git = "https://github.com/servo/rust-layers", features = ["plugins"]} lazy_static = "0.2" libc = "0.2" log = "0.3.5" @@ -31,8 +30,6 @@ msg = {path = "../msg"} net_traits = {path = "../net_traits"} ordered-float = "0.2.2" plugins = {path = "../plugins"} -profile_traits = {path = "../profile_traits"} -rand = "0.3" range = {path = "../range"} rustc-serialize = "0.3" serde = "0.8" diff --git a/components/gfx/font.rs b/components/gfx/font.rs index c955c042eff..8a0377cd2b0 100644 --- a/components/gfx/font.rs +++ b/components/gfx/font.rs @@ -112,7 +112,7 @@ pub struct Font { shaper: Option<Shaper>, shape_cache: RefCell<HashMap<ShapeCacheEntry, Arc<GlyphStore>>>, glyph_advance_cache: RefCell<HashMap<u32, FractionalPixel>>, - pub font_key: Option<webrender_traits::FontKey>, + pub font_key: webrender_traits::FontKey, } impl Font { @@ -121,7 +121,7 @@ impl Font { descriptor: FontTemplateDescriptor, requested_pt_size: Au, actual_pt_size: Au, - font_key: Option<webrender_traits::FontKey>) -> Font { + font_key: webrender_traits::FontKey) -> Font { let metrics = handle.metrics(); Font { handle: handle, diff --git a/components/gfx/font_cache_thread.rs b/components/gfx/font_cache_thread.rs index c3fcf7dfc07..e921f41fcf9 100644 --- a/components/gfx/font_cache_thread.rs +++ b/components/gfx/font_cache_thread.rs @@ -349,16 +349,18 @@ impl FontCache { } fn get_font_template_info(&mut self, template: Arc<FontTemplateData>) -> FontTemplateInfo { - let webrender_fonts = &mut self.webrender_fonts; - let font_key = self.webrender_api.as_ref().map(|webrender_api| { - *webrender_fonts.entry(template.identifier.clone()).or_insert_with(|| { + let mut font_key = None; + + if let Some(ref webrender_api) = self.webrender_api { + let webrender_fonts = &mut self.webrender_fonts; + font_key = Some(*webrender_fonts.entry(template.identifier.clone()).or_insert_with(|| { match (template.bytes_if_in_memory(), template.native_font()) { (Some(bytes), _) => webrender_api.add_raw_font(bytes), (None, Some(native_font)) => webrender_api.add_native_font(native_font), (None, None) => webrender_api.add_raw_font(template.bytes().clone()), } - }) - }); + })); + } FontTemplateInfo { font_template: template, diff --git a/components/gfx/font_context.rs b/components/gfx/font_context.rs index d89962b869a..1ffa1b32c21 100644 --- a/components/gfx/font_context.rs +++ b/components/gfx/font_context.rs @@ -109,7 +109,7 @@ impl FontContext { descriptor: FontTemplateDescriptor, pt_size: Au, variant: font_variant::T, - font_key: Option<webrender_traits::FontKey>) -> Result<Font, ()> { + font_key: webrender_traits::FontKey) -> Result<Font, ()> { // TODO: (Bug #3463): Currently we only support fake small-caps // painting. We should also support true small-caps (where the // font supports it) in the future. @@ -197,7 +197,8 @@ impl FontContext { desc.clone(), style.font_size, style.font_variant, - template_info.font_key); + template_info.font_key + .expect("No font key present!")); let font = match layout_font { Ok(layout_font) => { let layout_font = Rc::new(RefCell::new(layout_font)); @@ -242,7 +243,7 @@ impl FontContext { desc.clone(), style.font_size, style.font_variant, - template_info.font_key); + template_info.font_key.expect("No font key present!")); match layout_font { Ok(layout_font) => { let layout_font = Rc::new(RefCell::new(layout_font)); diff --git a/components/gfx/lib.rs b/components/gfx/lib.rs index 59045550660..763f55096c6 100644 --- a/components/gfx/lib.rs +++ b/components/gfx/lib.rs @@ -9,7 +9,6 @@ #![feature(box_syntax)] #![feature(custom_attribute)] #![feature(custom_derive)] -#![feature(mpsc_select)] #![feature(plugin)] #![feature(proc_macro)] #![feature(range_contains)] @@ -57,7 +56,6 @@ extern crate harfbuzz_sys as harfbuzz; extern crate heapsize; extern crate ipc_channel; -extern crate layers; #[allow(unused_extern_crates)] #[macro_use] extern crate lazy_static; @@ -69,9 +67,6 @@ extern crate msg; extern crate net_traits; extern crate ordered_float; #[macro_use] -extern crate profile_traits; -extern crate rand; -#[macro_use] extern crate range; extern crate rustc_serialize; extern crate serde; @@ -110,8 +105,6 @@ pub mod font_cache_thread; pub mod font_context; pub mod font_template; -pub mod paint_thread; - // Platform-specific implementations. #[allow(unsafe_code)] mod platform; diff --git a/components/gfx/paint_thread.rs b/components/gfx/paint_thread.rs deleted file mode 100644 index a17a0ee2bb7..00000000000 --- a/components/gfx/paint_thread.rs +++ /dev/null @@ -1,779 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -//! The thread that handles all painting. - -use app_units::Au; -use azure::AzFloat; -use azure::azure_hl::{BackendType, Color, DrawTarget, SurfaceFormat}; -use display_list::{DisplayItem, DisplayList, DisplayListTraversal}; -use display_list::{LayerInfo, StackingContext, StackingContextType}; -use euclid::Matrix4D; -use euclid::point::Point2D; -use euclid::rect::{Rect, TypedRect}; -use euclid::size::Size2D; -use font_cache_thread::FontCacheThread; -use font_context::FontContext; -use gfx_traits::{ChromeToPaintMsg, Epoch, LayerId, LayerKind, LayerProperties}; -use gfx_traits::{PaintListener, PaintRequest, StackingContextId}; -use layers::layers::{BufferRequest, LayerBuffer, LayerBufferSet}; -use layers::platform::surface::{NativeDisplay, NativeSurface}; -use msg::constellation_msg::PipelineId; -use paint_context::PaintContext; -use profile_traits::mem; -use profile_traits::time; -use rand::{self, Rng}; -use std::borrow::ToOwned; -use std::collections::HashMap; -use std::mem as std_mem; -use std::sync::Arc; -use std::sync::mpsc::{Receiver, Sender, channel}; -use style::thread_state; -use url::Url; -use util::geometry::ExpandToPixelBoundaries; -use util::opts; -use util::thread; - -#[derive(Clone, HeapSizeOf)] -struct PaintLayer { - /// The LayerProperties, which describe the layer in a way that the Compositor - /// can consume. - pub layer_properties: LayerProperties, - - /// The StackingContextId of the StackingContext that is the immediate - /// parent of this layer. This is used to ensure applying the proper transform - /// when painting. - pub starting_stacking_context_id: StackingContextId, - - /// The indices (in the DisplayList) to the first and last display item - /// that are the contents of this layer. - pub display_list_indices: Option<(usize, usize)>, - - /// When painting, whether to draw the start by entering the surrounding StackingContext - /// or simply to draw the single item this PaintLayer contains. - pub single_item: bool, - - /// The layer's bounds start at the overflow origin, but display items are - /// positioned relative to the stacking context bounds, so we need to - /// offset by the overflow rect (which will be in the coordinate system of - /// the stacking context bounds). - pub display_list_origin: Point2D<f32> -} - -impl PaintLayer { - fn new_from_stacking_context(layer_info: &LayerInfo, - stacking_context: &StackingContext, - parent_origin: &Point2D<Au>, - transform: &Matrix4D<f32>, - perspective: &Matrix4D<f32>, - parent_id: Option<LayerId>) - -> PaintLayer { - let bounds = Rect::new(stacking_context.bounds.origin + stacking_context.overflow.origin, - stacking_context.overflow.size); - let layer_boundaries = Rect::new( - Point2D::new((parent_origin.x + bounds.min_x()).to_nearest_px() as f32, - (parent_origin.y + bounds.min_y()).to_nearest_px() as f32), - Size2D::new(bounds.size.width.to_nearest_px() as f32, - bounds.size.height.to_nearest_px() as f32)); - - let transform = transform.pre_mul(&stacking_context.transform); - let perspective = perspective.pre_mul(&stacking_context.perspective); - let establishes_3d_context = stacking_context.establishes_3d_context; - let scrolls_overflow_area = stacking_context.scrolls_overflow_area; - - PaintLayer { - layer_properties: LayerProperties { - id: layer_info.layer_id, - parent_id: parent_id, - rect: layer_boundaries, - background_color: layer_info.background_color, - scroll_policy: layer_info.scroll_policy, - transform: transform, - perspective: perspective, - establishes_3d_context: establishes_3d_context, - scrolls_overflow_area: scrolls_overflow_area, - subpage_pipeline_id: layer_info.subpage_pipeline_id, - }, - starting_stacking_context_id: stacking_context.id, - display_list_indices: None, - single_item: false, - display_list_origin: Point2D::new(stacking_context.overflow.origin.x.to_f32_px(), - stacking_context.overflow.origin.y.to_f32_px()), - } - } - - fn new_for_display_item(layer_info: &LayerInfo, - item_bounds: &Rect<Au>, - parent_origin: &Point2D<Au>, - transform: &Matrix4D<f32>, - perspective: &Matrix4D<f32>, - parent_id: Option<LayerId>, - stacking_context_id: StackingContextId, - item_index: usize) - -> PaintLayer { - let bounds = item_bounds.expand_to_px_boundaries(); - let layer_boundaries = Rect::new( - Point2D::new((parent_origin.x + bounds.min_x()).to_nearest_px() as f32, - (parent_origin.y + bounds.min_y()).to_nearest_px() as f32), - Size2D::new(bounds.size.width.to_nearest_px() as f32, - bounds.size.height.to_nearest_px() as f32)); - - PaintLayer { - layer_properties: LayerProperties { - id: layer_info.layer_id, - parent_id: parent_id, - rect: layer_boundaries, - background_color: layer_info.background_color, - scroll_policy: layer_info.scroll_policy, - transform: *transform, - perspective: *perspective, - establishes_3d_context: false, - scrolls_overflow_area: false, - subpage_pipeline_id: layer_info.subpage_pipeline_id, - }, - starting_stacking_context_id: stacking_context_id, - display_list_indices: Some((item_index, item_index)), - single_item: true, - display_list_origin: Point2D::new(bounds.origin.x.to_f32_px(), - bounds.origin.y.to_f32_px()), - } - } - - fn add_item(&mut self, index: usize) { - let indices = match self.display_list_indices { - Some((first, _)) => (first, index), - None => (index, index), - }; - self.display_list_indices = Some(indices); - } - - fn make_companion_layer(&mut self) { - self.layer_properties.id = self.layer_properties.id.companion_layer_id(); - self.display_list_indices = None; - } -} - -struct LayerCreator { - layers: Vec<PaintLayer>, - layer_details_stack: Vec<PaintLayer>, - current_layer: Option<PaintLayer>, -} - -impl LayerCreator { - fn create_layers_with_display_list<'a>(display_list: &'a DisplayList) -> Vec<PaintLayer> { - let mut layer_creator = LayerCreator { - layers: Vec::new(), - layer_details_stack: Vec::new(), - current_layer: None, - }; - let mut traversal = DisplayListTraversal::new(display_list); - layer_creator.process_stacking_context_items(&mut traversal, - &Point2D::zero(), - &Matrix4D::identity(), - &Matrix4D::identity()); - layer_creator.layers - } - - fn finalize_current_layer(&mut self) { - if let Some(current_layer) = self.current_layer.take() { - self.layers.push(current_layer); - } - } - - fn current_parent_layer_id(&self) -> Option<LayerId> { - self.layer_details_stack.last().as_ref().map(|layer| - layer.layer_properties.id - ) - } - - fn current_parent_stacking_context_id(&self) -> StackingContextId { - self.layer_details_stack.last().unwrap().starting_stacking_context_id - } - - fn create_layers_for_stacking_context<'a>(&mut self, - stacking_context: &StackingContext, - traversal: &mut DisplayListTraversal<'a>, - parent_origin: &Point2D<Au>, - transform: &Matrix4D<f32>, - perspective: &Matrix4D<f32>) { - if let Some(ref layer_info) = stacking_context.layer_info { - self.finalize_current_layer(); - let new_layer = PaintLayer::new_from_stacking_context( - layer_info, - stacking_context, - parent_origin, - transform, - perspective, - self.current_parent_layer_id()); - self.layer_details_stack.push(new_layer.clone()); - self.current_layer = Some(new_layer); - - // When there is a new layer, the transforms and origin are handled by - // the compositor, so the new transform and perspective matrices are - // just the identity. - // - // The origin for child layers which might be somewhere other than the - // layer origin, since layer boundaries are expanded to include overflow. - self.process_stacking_context_items(traversal, - &-stacking_context.overflow.origin, - &Matrix4D::identity(), - &Matrix4D::identity()); - self.finalize_current_layer(); - self.layer_details_stack.pop(); - return; - } - - debug_assert!(stacking_context.context_type == StackingContextType::Real); - self.process_stacking_context_items(traversal, - &(stacking_context.bounds.origin + *parent_origin), - &transform.pre_mul(&stacking_context.transform), - &perspective.pre_mul(&stacking_context.perspective)); - } - - fn process_stacking_context_items<'a>(&mut self, - traversal: &mut DisplayListTraversal<'a>, - parent_origin: &Point2D<Au>, - transform: &Matrix4D<f32>, - perspective: &Matrix4D<f32>) { - while let Some(item) = traversal.next() { - match item { - &DisplayItem::PushStackingContextClass(ref stacking_context_item) => { - self.create_layers_for_stacking_context(&stacking_context_item.stacking_context, - traversal, - parent_origin, - transform, - perspective); - } - &DisplayItem::PopStackingContextClass(_) => return, - _ => { - self.create_layers_for_item(traversal.previous_item_id(), - item, - parent_origin, - transform, - perspective); - } - } - } - } - - - fn create_layers_for_item<'a>(&mut self, - current_item_index: usize, - item: &DisplayItem, - parent_origin: &Point2D<Au>, - transform: &Matrix4D<f32>, - perspective: &Matrix4D<f32>) { - if let &DisplayItem::LayeredItemClass(ref layered_item) = item { - // We need to finalize the last layer here before incrementing the item - // index, otherwise this item will be placed into the parent layer. - self.finalize_current_layer(); - let layer = PaintLayer::new_for_display_item( - &layered_item.layer_info, - &layered_item.item.bounds(), - parent_origin, - transform, - perspective, - self.current_parent_layer_id(), - self.current_parent_stacking_context_id(), - current_item_index); - self.layers.push(layer); - return; - } - - // If we don't have a current layer, we are an item that belonged to a - // previous layer that was finalized by a child layer. We need to - // resurrect a copy of the original ancestor layer to ensure that this - // item is ordered on top of the child layers when painted. - if self.current_layer.is_none() { - let mut new_layer = self.layer_details_stack.pop().unwrap(); - new_layer.make_companion_layer(); - - if new_layer.layer_properties.parent_id == None { - new_layer.layer_properties.parent_id = - Some(new_layer.layer_properties.id.original()); - } - - self.layer_details_stack.push(new_layer.clone()); - self.current_layer = Some(new_layer); - } - - if let Some(ref mut current_layer) = self.current_layer { - current_layer.add_item(current_item_index); - } - } -} - -pub enum Msg { - FromLayout(LayoutToPaintMsg), - FromChrome(ChromeToPaintMsg), -} - -#[derive(Deserialize, Serialize)] -pub enum LayoutToPaintMsg { - PaintInit(Epoch, Arc<DisplayList>), - Exit, -} - -pub struct PaintThread<C> { - id: PipelineId, - _url: Url, - layout_to_paint_port: Receiver<LayoutToPaintMsg>, - chrome_to_paint_port: Receiver<ChromeToPaintMsg>, - compositor: C, - - /// A channel to the time profiler. - time_profiler_chan: time::ProfilerChan, - - /// The root paint layer sent to us by the layout thread. - root_display_list: Option<Arc<DisplayList>>, - - /// A map that associates LayerIds with their corresponding layers. - layer_map: HashMap<LayerId, Arc<PaintLayer>>, - - /// Permission to send paint messages to the compositor - paint_permission: bool, - - /// The current epoch counter is passed by the layout thread - current_epoch: Option<Epoch>, - - /// Communication handles to each of the worker threads. - worker_threads: Vec<WorkerThreadProxy>, -} - -// If we implement this as a function, we get borrowck errors from borrowing -// the whole PaintThread struct. -macro_rules! native_display( - ($thread:expr) => ( - $thread.native_display.as_ref().expect("Need a graphics context to do painting") - ) -); - -impl<C> PaintThread<C> where C: PaintListener + Send + 'static { - pub fn create(id: PipelineId, - url: Url, - chrome_to_paint_chan: Sender<ChromeToPaintMsg>, - layout_to_paint_port: Receiver<LayoutToPaintMsg>, - chrome_to_paint_port: Receiver<ChromeToPaintMsg>, - mut compositor: C, - font_cache_thread: FontCacheThread, - time_profiler_chan: time::ProfilerChan, - mem_profiler_chan: mem::ProfilerChan) { - thread::spawn_named(format!("PaintThread {:?}", id), move || { - thread_state::initialize(thread_state::PAINT); - PipelineId::install(id); - - let native_display = compositor.native_display(); - let worker_threads = WorkerThreadProxy::spawn(native_display, - font_cache_thread, - time_profiler_chan.clone()); - - let mut paint_thread = PaintThread { - id: id, - _url: url, - layout_to_paint_port: layout_to_paint_port, - chrome_to_paint_port: chrome_to_paint_port, - compositor: compositor, - time_profiler_chan: time_profiler_chan, - root_display_list: None, - layer_map: HashMap::new(), - paint_permission: false, - current_epoch: None, - worker_threads: worker_threads, - }; - - let reporter_name = format!("paint-reporter-{}", id); - mem_profiler_chan.run_with_memory_reporting(|| { - paint_thread.start(); - }, reporter_name, chrome_to_paint_chan, ChromeToPaintMsg::CollectReports); - - // Tell all the worker threads to shut down. - for worker_thread in &mut paint_thread.worker_threads { - worker_thread.exit() - } - }); - } - - #[allow(unsafe_code)] - fn start(&mut self) { - debug!("PaintThread: beginning painting loop"); - - loop { - let message = { - let layout_to_paint = &self.layout_to_paint_port; - let chrome_to_paint = &self.chrome_to_paint_port; - select! { - msg = layout_to_paint.recv() => - Msg::FromLayout(msg.expect("expected message from layout")), - msg = chrome_to_paint.recv() => - Msg::FromChrome(msg.expect("expected message from chrome")) - } - }; - - match message { - Msg::FromLayout(LayoutToPaintMsg::PaintInit(epoch, display_list)) => { - self.current_epoch = Some(epoch); - self.root_display_list = Some(display_list); - - if self.paint_permission { - self.initialize_layers(); - } - } - Msg::FromChrome(ChromeToPaintMsg::Paint(requests, frame_tree_id)) => { - if self.paint_permission && self.root_display_list.is_some() { - let mut replies = Vec::new(); - for PaintRequest { buffer_requests, scale, layer_id, epoch, layer_kind } - in requests { - if self.current_epoch == Some(epoch) { - self.paint(&mut replies, buffer_requests, scale, layer_id, layer_kind); - } else { - debug!("PaintThread: Ignoring requests with epoch mismatch: {:?} != {:?}", - self.current_epoch, - epoch); - self.compositor.ignore_buffer_requests(buffer_requests); - } - } - - debug!("PaintThread: returning surfaces"); - self.compositor.assign_painted_buffers(self.id, - self.current_epoch.unwrap(), - replies, - frame_tree_id); - } - } - Msg::FromChrome(ChromeToPaintMsg::PaintPermissionGranted) => { - self.paint_permission = true; - - if self.root_display_list.is_some() { - self.initialize_layers(); - } - } - Msg::FromChrome(ChromeToPaintMsg::PaintPermissionRevoked) => { - self.paint_permission = false; - } - Msg::FromChrome(ChromeToPaintMsg::CollectReports(ref channel)) => { - // FIXME(njn): should eventually measure the paint thread. - channel.send(Vec::new()) - } - Msg::FromLayout(LayoutToPaintMsg::Exit) => { - // Ask the compositor to remove any layers it is holding for this paint thread. - // FIXME(mrobinson): This can probably move back to the constellation now. - debug!("PaintThread: Exiting."); - self.compositor.notify_paint_thread_exiting(self.id); - - break; - } - Msg::FromChrome(ChromeToPaintMsg::Exit) => { - // Ask the compositor to remove any layers it is holding for this paint thread. - // FIXME(mrobinson): This can probably move back to the constellation now. - debug!("PaintThread: Exiting."); - self.compositor.notify_paint_thread_exiting(self.id); - - break; - } - } - } - } - - /// Paints one layer and places the painted tiles in `replies`. - fn paint(&mut self, - replies: &mut Vec<(LayerId, Box<LayerBufferSet>)>, - mut tiles: Vec<BufferRequest>, - scale: f32, - layer_id: LayerId, - layer_kind: LayerKind) { - time::profile(time::ProfilerCategory::Painting, None, self.time_profiler_chan.clone(), || { - let display_list = match self.root_display_list { - Some(ref display_list) => display_list.clone(), - None => return, - }; - - // Bail out if there is no appropriate layer. - let layer = match self.layer_map.get(&layer_id) { - Some(layer) => layer.clone(), - None => return, - }; - - // Divide up the layer into tiles and distribute them to workers via a simple round- - // robin strategy. - let tiles = std_mem::replace(&mut tiles, Vec::new()); - let tile_count = tiles.len(); - for (i, tile) in tiles.into_iter().enumerate() { - let thread_id = i % self.worker_threads.len(); - self.worker_threads[thread_id].paint_tile(thread_id, - tile, - display_list.clone(), - layer.clone(), - scale, - layer_kind); - } - let new_buffers = (0..tile_count).map(|i| { - let thread_id = i % self.worker_threads.len(); - self.worker_threads[thread_id].painted_tile_buffer() - }).collect(); - - let layer_buffer_set = box LayerBufferSet { - buffers: new_buffers, - }; - replies.push((layer_id, layer_buffer_set)); - }) - } - - fn initialize_layers(&mut self) { - let root_display_list = match self.root_display_list { - None => return, - Some(ref root_display_list) => root_display_list, - }; - let layers = LayerCreator::create_layers_with_display_list(&root_display_list); - let properties = layers.iter().map(|layer| layer.layer_properties.clone()).collect(); - self.compositor.initialize_layers_for_pipeline(self.id, - properties, - self.current_epoch.unwrap()); - self.layer_map.clear(); - for layer in layers.into_iter() { - self.layer_map.insert(layer.layer_properties.id, Arc::new(layer)); - } - } -} - -struct WorkerThreadProxy { - sender: Sender<MsgToWorkerThread>, - receiver: Receiver<MsgFromWorkerThread>, -} - -impl WorkerThreadProxy { - fn spawn(native_display: Option<NativeDisplay>, - font_cache_thread: FontCacheThread, - time_profiler_chan: time::ProfilerChan) - -> Vec<WorkerThreadProxy> { - // Don't make any paint threads if we're using WebRender. They're just a waste of - // resources. - if opts::get().use_webrender { - return vec![] - } - - let thread_count = opts::get().paint_threads; - (0..thread_count).map(|_| { - let (from_worker_sender, from_worker_receiver) = channel(); - let (to_worker_sender, to_worker_receiver) = channel(); - let font_cache_thread = font_cache_thread.clone(); - let time_profiler_chan = time_profiler_chan.clone(); - thread::spawn_named("PaintWorker".to_owned(), move || { - let mut worker_thread = WorkerThread::new(from_worker_sender, - to_worker_receiver, - native_display, - font_cache_thread, - time_profiler_chan); - worker_thread.main(); - }); - WorkerThreadProxy { - receiver: from_worker_receiver, - sender: to_worker_sender, - } - }).collect() - } - - fn paint_tile(&mut self, - thread_id: usize, - tile: BufferRequest, - display_list: Arc<DisplayList>, - paint_layer: Arc<PaintLayer>, - scale: f32, - layer_kind: LayerKind) { - let msg = MsgToWorkerThread::PaintTile(thread_id, - tile, - display_list, - paint_layer, - scale, - layer_kind); - self.sender.send(msg).unwrap() - } - - fn painted_tile_buffer(&mut self) -> Box<LayerBuffer> { - match self.receiver.recv().unwrap() { - MsgFromWorkerThread::PaintedTile(layer_buffer) => layer_buffer, - } - } - - fn exit(&mut self) { - self.sender.send(MsgToWorkerThread::Exit).unwrap() - } -} - -struct WorkerThread { - sender: Sender<MsgFromWorkerThread>, - receiver: Receiver<MsgToWorkerThread>, - native_display: Option<NativeDisplay>, - font_context: Box<FontContext>, - time_profiler_sender: time::ProfilerChan, -} - -impl WorkerThread { - fn new(sender: Sender<MsgFromWorkerThread>, - receiver: Receiver<MsgToWorkerThread>, - native_display: Option<NativeDisplay>, - font_cache_thread: FontCacheThread, - time_profiler_sender: time::ProfilerChan) - -> WorkerThread { - WorkerThread { - sender: sender, - receiver: receiver, - native_display: native_display, - font_context: box FontContext::new(font_cache_thread.clone()), - time_profiler_sender: time_profiler_sender, - } - } - - fn main(&mut self) { - loop { - match self.receiver.recv().unwrap() { - MsgToWorkerThread::Exit => break, - MsgToWorkerThread::PaintTile(thread_id, - tile, - display_list, - paint_layer, - scale, - layer_kind) => { - let buffer = self.optimize_and_paint_tile(thread_id, - tile, - display_list, - paint_layer, - scale, - layer_kind); - self.sender.send(MsgFromWorkerThread::PaintedTile(buffer)).unwrap() - } - } - } - } - - fn optimize_and_paint_tile(&mut self, - thread_id: usize, - mut tile: BufferRequest, - display_list: Arc<DisplayList>, - paint_layer: Arc<PaintLayer>, - scale: f32, - layer_kind: LayerKind) - -> Box<LayerBuffer> { - let size = Size2D::new(tile.screen_rect.size.width as i32, - tile.screen_rect.size.height as i32); - let mut buffer = self.create_layer_buffer(&mut tile, scale); - let draw_target = DrawTarget::new(BackendType::Skia, size, SurfaceFormat::B8G8R8A8); - - { - // Build the paint context. - let mut paint_context = PaintContext { - draw_target: draw_target.clone(), - font_context: &mut self.font_context, - page_rect: TypedRect::from_untyped(&tile.page_rect.translate(&paint_layer.display_list_origin)), - screen_rect: TypedRect::from_untyped(&tile.screen_rect), - clip_rect: None, - transient_clip: None, - layer_kind: layer_kind, - subpixel_offset: Point2D::zero(), - }; - - // Apply the translation to paint the tile we want. - let matrix = Matrix4D::identity(); - let matrix = matrix.pre_scaled(scale as AzFloat, scale as AzFloat, 1.0); - let tile_bounds = tile.page_rect.translate(&paint_layer.display_list_origin); - let matrix = matrix.pre_translated(-tile_bounds.origin.x as AzFloat, - -tile_bounds.origin.y as AzFloat, - 0.0); - - // Clear the buffer. - paint_context.clear(); - - // Draw the display list. - time::profile(time::ProfilerCategory::PaintingPerTile, - None, - self.time_profiler_sender.clone(), || { - if let Some((start, end)) = paint_layer.display_list_indices { - if paint_layer.single_item { - display_list.draw_item_at_index_into_context( - &mut paint_context, &matrix, start); - } else { - display_list.draw_into_context( - &mut paint_context, - &matrix, - paint_layer.starting_stacking_context_id, - start, - end); - } - } - paint_context.draw_target.flush(); - }); - - if opts::get().show_debug_parallel_paint { - // Overlay a transparent solid color to identify the thread that - // painted this tile. - let color = THREAD_TINT_COLORS[thread_id % THREAD_TINT_COLORS.len()]; - paint_context.draw_solid_color(&Rect::new(Point2D::new(Au(0), Au(0)), - Size2D::new(Au::from_px(size.width), - Au::from_px(size.height))), - color); - } - if opts::get().paint_flashing { - // Overlay a random transparent color. - let color = *rand::thread_rng().choose(&THREAD_TINT_COLORS[..]).unwrap(); - paint_context.draw_solid_color(&Rect::new(Point2D::new(Au(0), Au(0)), - Size2D::new(Au::from_px(size.width), - Au::from_px(size.height))), - color); - } - } - - // Extract the texture from the draw target and place it into its slot in the buffer. - // Upload it first. - draw_target.snapshot().get_data_surface().with_data(|data| { - buffer.native_surface.upload(native_display!(self), data); - debug!("painting worker thread uploading to native surface {}", - buffer.native_surface.get_id()); - }); - - draw_target.finish(); - buffer - } - - fn create_layer_buffer(&mut self, - tile: &mut BufferRequest, - scale: f32) - -> Box<LayerBuffer> { - // Create an empty native surface. We mark it as not leaking - // in case it dies in transit to the compositor thread. - let width = tile.screen_rect.size.width; - let height = tile.screen_rect.size.height; - let mut native_surface = tile.native_surface.take().unwrap_or_else(|| { - NativeSurface::new(native_display!(self), Size2D::new(width as i32, height as i32)) - }); - native_surface.mark_wont_leak(); - - box LayerBuffer { - native_surface: native_surface, - rect: tile.page_rect, - screen_pos: tile.screen_rect, - resolution: scale, - painted_with_cpu: true, - content_age: tile.content_age, - } - } -} - -enum MsgToWorkerThread { - Exit, - PaintTile(usize, BufferRequest, Arc<DisplayList>, Arc<PaintLayer>, f32, LayerKind), -} - -enum MsgFromWorkerThread { - PaintedTile(Box<LayerBuffer>), -} - -pub static THREAD_TINT_COLORS: [Color; 8] = [ - Color { r: 6.0 / 255.0, g: 153.0 / 255.0, b: 198.0 / 255.0, a: 0.7 }, - Color { r: 255.0 / 255.0, g: 212.0 / 255.0, b: 83.0 / 255.0, a: 0.7 }, - Color { r: 116.0 / 255.0, g: 29.0 / 255.0, b: 109.0 / 255.0, a: 0.7 }, - Color { r: 204.0 / 255.0, g: 158.0 / 255.0, b: 199.0 / 255.0, a: 0.7 }, - Color { r: 242.0 / 255.0, g: 46.0 / 255.0, b: 121.0 / 255.0, a: 0.7 }, - Color { r: 116.0 / 255.0, g: 203.0 / 255.0, b: 196.0 / 255.0, a: 0.7 }, - Color { r: 255.0 / 255.0, g: 249.0 / 255.0, b: 201.0 / 255.0, a: 0.7 }, - Color { r: 137.0 / 255.0, g: 196.0 / 255.0, b: 78.0 / 255.0, a: 0.7 }, -]; diff --git a/components/gfx/text/text_run.rs b/components/gfx/text/text_run.rs index 7ab8f4a870f..db65dc49142 100644 --- a/components/gfx/text/text_run.rs +++ b/components/gfx/text/text_run.rs @@ -29,7 +29,7 @@ pub struct TextRun { pub font_template: Arc<FontTemplateData>, pub actual_pt_size: Au, pub font_metrics: FontMetrics, - pub font_key: Option<webrender_traits::FontKey>, + pub font_key: webrender_traits::FontKey, /// The glyph runs that make up this text run. pub glyphs: Arc<Vec<GlyphRun>>, pub bidi_level: u8, diff --git a/components/gfx_traits/Cargo.toml b/components/gfx_traits/Cargo.toml index 65baa8d3791..83a3845d7fc 100644 --- a/components/gfx_traits/Cargo.toml +++ b/components/gfx_traits/Cargo.toml @@ -11,13 +11,9 @@ path = "lib.rs" [dependencies] azure = {git = "https://github.com/servo/rust-azure", features = ["plugins"]} -euclid = "0.10.1" heapsize = "0.3.0" heapsize_plugin = "0.1.2" -layers = {git = "https://github.com/servo/rust-layers", features = ["plugins"]} -msg = {path = "../msg"} plugins = {path = "../plugins"} -profile_traits = {path = "../profile_traits"} range = {path = "../range"} rustc-serialize = "0.3" serde = "0.8" diff --git a/components/gfx_traits/lib.rs b/components/gfx_traits/lib.rs index 674eb42c55d..0f21cc9c890 100644 --- a/components/gfx_traits/lib.rs +++ b/components/gfx_traits/lib.rs @@ -11,11 +11,7 @@ #![deny(unsafe_code)] extern crate azure; -extern crate euclid; extern crate heapsize; -extern crate layers; -extern crate msg; -extern crate profile_traits; #[macro_use] extern crate range; extern crate rustc_serialize; @@ -24,16 +20,8 @@ extern crate serde; extern crate serde_derive; pub mod color; -mod paint_listener; pub mod print_tree; -pub use paint_listener::PaintListener; -use azure::azure_hl::Color; -use euclid::Matrix4D; -use euclid::rect::Rect; -use layers::layers::BufferRequest; -use msg::constellation_msg::PipelineId; -use profile_traits::mem::ReportsChan; use range::RangeIndex; use std::fmt::{self, Debug, Formatter}; use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering}; @@ -50,6 +38,20 @@ static NEXT_SPECIAL_STACKING_CONTEXT_ID: AtomicUsize = ATOMIC_USIZE_INIT; /// Note that we assume that the top 16 bits of the address space are unused on the platform. const SPECIAL_STACKING_CONTEXT_ID_MASK: usize = 0xffff; +// Units for use with euclid::length and euclid::scale_factor. + +/// One hardware pixel. +/// +/// This unit corresponds to the smallest addressable element of the display hardware. +#[derive(Copy, Clone, RustcEncodable, Debug)] +pub enum DevicePixel {} + +/// One pixel in layer coordinate space. +/// +/// This unit corresponds to a "pixel" in layer coordinate space, which after scaling and +/// transformation becomes a device pixel. +#[derive(Copy, Clone, RustcEncodable, Debug)] +pub enum LayerPixel {} #[derive(Clone, Copy, Debug, PartialEq)] pub enum LayerKind { @@ -128,33 +130,6 @@ impl LayerId { } } -/// All layer-specific information that the painting task sends to the compositor other than the -/// buffer contents of the layer itself. -#[derive(Copy, Clone, HeapSizeOf)] -pub struct LayerProperties { - /// An opaque ID. This is usually the address of the flow and index of the box within it. - pub id: LayerId, - /// The id of the parent layer. - pub parent_id: Option<LayerId>, - /// The position and size of the layer in pixels. - pub rect: Rect<f32>, - /// The background color of the layer. - pub background_color: Color, - /// The scrolling policy of this layer. - pub scroll_policy: ScrollPolicy, - /// The transform for this layer - pub transform: Matrix4D<f32>, - /// The perspective transform for this layer - pub perspective: Matrix4D<f32>, - /// The subpage that this layer represents. If this is `Some`, this layer represents an - /// iframe. - pub subpage_pipeline_id: Option<PipelineId>, - /// Whether this layer establishes a new 3d rendering context. - pub establishes_3d_context: bool, - /// Whether this layer scrolls its overflow area. - pub scrolls_overflow_area: bool, -} - /// A newtype struct for denoting the age of messages; prevents race conditions. #[derive(PartialEq, Eq, Debug, Copy, Clone, PartialOrd, Ord, Deserialize, Serialize)] pub struct Epoch(pub u32); @@ -272,19 +247,3 @@ int_range_index! { #[derive(HeapSizeOf)] struct ByteIndex(isize) } - -pub struct PaintRequest { - pub buffer_requests: Vec<BufferRequest>, - pub scale: f32, - pub layer_id: LayerId, - pub epoch: Epoch, - pub layer_kind: LayerKind, -} - -pub enum ChromeToPaintMsg { - Paint(Vec<PaintRequest>, FrameTreeId), - PaintPermissionGranted, - PaintPermissionRevoked, - CollectReports(ReportsChan), - Exit, -} diff --git a/components/gfx_traits/paint_listener.rs b/components/gfx_traits/paint_listener.rs deleted file mode 100644 index f47b442dead..00000000000 --- a/components/gfx_traits/paint_listener.rs +++ /dev/null @@ -1,37 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use Epoch; -use FrameTreeId; -use LayerId; -use LayerProperties; -use layers::layers::{BufferRequest, LayerBufferSet}; -use layers::platform::surface::NativeDisplay; -use msg::constellation_msg::PipelineId; - -/// The interface used by the painter to acquire draw targets for each paint frame and -/// submit them to be drawn to the display. -pub trait PaintListener { - fn native_display(&mut self) -> Option<NativeDisplay>; - - /// Informs the compositor of the layers for the given pipeline. The compositor responds by - /// creating and/or destroying paint layers as necessary. - fn initialize_layers_for_pipeline(&mut self, - pipeline_id: PipelineId, - properties: Vec<LayerProperties>, - epoch: Epoch); - - /// Sends new buffers for the given layers to the compositor. - fn assign_painted_buffers(&mut self, - pipeline_id: PipelineId, - epoch: Epoch, - replies: Vec<(LayerId, Box<LayerBufferSet>)>, - frame_tree_id: FrameTreeId); - - /// Inform the compositor that these buffer requests will be ignored. - fn ignore_buffer_requests(&mut self, buffer_requests: Vec<BufferRequest>); - - // Notification that the paint task wants to exit. - fn notify_paint_thread_exiting(&mut self, pipeline_id: PipelineId); -} diff --git a/components/layout/block.rs b/components/layout/block.rs index 4df73666a27..2011c50c181 100644 --- a/components/layout/block.rs +++ b/components/layout/block.rs @@ -31,7 +31,7 @@ use app_units::{Au, MAX_AU}; use context::{LayoutContext, SharedLayoutContext}; use display_list_builder::{BorderPaintingMode, DisplayListBuildState, FragmentDisplayListBuilding}; use display_list_builder::BlockFlowDisplayListBuilding; -use euclid::{Point2D, Rect, Size2D}; +use euclid::{Point2D, Size2D}; use floats::{ClearType, FloatKind, Floats, PlacementInfo}; use flow::{self, BaseFlow, EarlyAbsolutePositionInfo, Flow, FlowClass, ForceNonfloatedFlag}; use flow::{BLOCK_POSITION_IS_STATIC, CLEARS_LEFT, CLEARS_RIGHT}; @@ -64,10 +64,6 @@ use style::properties::ServoComputedValues; use style::values::computed::{LengthOrNone, LengthOrPercentageOrNone}; use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto}; use util::clamp; -use util::geometry::max_rect; - -/// The number of screens of data we're allowed to generate display lists for in each direction. -const DISPLAY_PORT_SIZE_FACTOR: i32 = 8; /// Information specific to floated blocks. #[derive(Clone, RustcEncodable)] @@ -1959,7 +1955,7 @@ impl Flow for BlockFlow { } } - fn compute_absolute_position(&mut self, layout_context: &SharedLayoutContext) { + fn compute_absolute_position(&mut self, _layout_context: &SharedLayoutContext) { if self.base.flags.contains(NEEDS_LAYER) { self.fragment.flags.insert(HAS_LAYER) } @@ -1970,7 +1966,6 @@ impl Flow for BlockFlow { if self.is_root() { self.base.clip = ClippingRegion::max(); - self.base.stacking_relative_position_of_display_port = max_rect(); } let transform_style = self.fragment.style().get_used_transform_style(); @@ -1983,7 +1978,6 @@ impl Flow for BlockFlow { (overflow_x::T::auto, _) | (overflow_x::T::scroll, _) | (_, overflow_x::T::auto) | (_, overflow_x::T::scroll) => { self.base.clip = ClippingRegion::max(); - self.base.stacking_relative_position_of_display_port = max_rect(); } _ => {} } @@ -2085,25 +2079,6 @@ impl Flow for BlockFlow { self.base.stacking_relative_position + relative_offset }; - let stacking_relative_position_of_display_port_for_children = - if is_stacking_context || self.is_root() { - let visible_rect = - match layout_context.visible_rects.get(&self.layer_id()) { - Some(visible_rect) => *visible_rect, - None => Rect::new(Point2D::zero(), layout_context.style_context.viewport_size), - }; - - let viewport_size = layout_context.style_context.viewport_size; - visible_rect.inflate(viewport_size.width * DISPLAY_PORT_SIZE_FACTOR, - viewport_size.height * DISPLAY_PORT_SIZE_FACTOR) - } else if is_stacking_context { - self.base - .stacking_relative_position_of_display_port - .translate(&-self.base.stacking_relative_position) - } else { - self.base.stacking_relative_position_of_display_port - }; - let stacking_relative_border_box = self.fragment .stacking_relative_border_box(&self.base.stacking_relative_position, @@ -2168,8 +2143,6 @@ impl Flow for BlockFlow { flow::mut_base(kid).late_absolute_position_info = late_absolute_position_info_for_children; - flow::mut_base(kid).stacking_relative_position_of_display_port = - stacking_relative_position_of_display_port_for_children; // This clipping region is in our coordinate system. The child will fix it up to be in // its own coordinate system by itself if necessary. diff --git a/components/layout/context.rs b/components/layout/context.rs index eb9024c2c5b..7125c6ab44d 100644 --- a/components/layout/context.rs +++ b/components/layout/context.rs @@ -15,7 +15,7 @@ use gfx::font_cache_thread::FontCacheThread; use gfx::font_context::FontContext; use gfx_traits::LayerId; use heapsize::HeapSizeOf; -use ipc_channel::ipc::{self, IpcSharedMemory}; +use ipc_channel::ipc; use net_traits::image::base::Image; use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheThread, ImageResponse, ImageState}; use net_traits::image_cache_thread::{ImageOrMetadataAvailable, UsePlaceholder}; @@ -196,36 +196,27 @@ impl SharedLayoutContext { pub fn get_webrender_image_for_url(&self, url: &Url, - use_placeholder: UsePlaceholder, - fetch_image_data_as_well: bool) - -> Option<(WebRenderImageInfo, Option<IpcSharedMemory>)> { - if !fetch_image_data_as_well { - let webrender_image_cache = self.webrender_image_cache.read().unwrap(); - if let Some(existing_webrender_image) = - webrender_image_cache.get(&((*url).clone(), use_placeholder)) { - return Some(((*existing_webrender_image).clone(), None)) - } + use_placeholder: UsePlaceholder) + -> Option<WebRenderImageInfo> { + if let Some(existing_webrender_image) = self.webrender_image_cache + .read() + .unwrap() + .get(&((*url).clone(), use_placeholder)) { + return Some((*existing_webrender_image).clone()) } match self.get_or_request_image_or_meta((*url).clone(), use_placeholder) { Some(ImageOrMetadataAvailable::ImageAvailable(image)) => { let image_info = WebRenderImageInfo::from_image(&*image); if image_info.key.is_none() { - let bytes = if !fetch_image_data_as_well { - None - } else { - Some(image.bytes.clone()) - }; - Some((image_info, bytes)) - } else if !fetch_image_data_as_well { + Some(image_info) + } else { let mut webrender_image_cache = self.webrender_image_cache .write() .unwrap(); webrender_image_cache.insert(((*url).clone(), use_placeholder), image_info); - Some((image_info, None)) - } else { - Some((image_info, Some(image.bytes.clone()))) + Some(image_info) } } None | Some(ImageOrMetadataAvailable::MetadataAvailable(_)) => None, diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index 33d44a82278..827f8ce2b4c 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -25,10 +25,9 @@ use gfx::display_list::{BLUR_INFLATION_FACTOR, BaseDisplayItem, BorderDisplayIte use gfx::display_list::{BorderRadii, BoxShadowClipMode, BoxShadowDisplayItem, ClippingRegion}; use gfx::display_list::{DisplayItem, DisplayItemMetadata, DisplayListSection, GradientDisplayItem}; use gfx::display_list::{GradientStop, IframeDisplayItem, ImageDisplayItem, WebGLDisplayItem}; -use gfx::display_list::{LayerInfo, LayeredItem, LineDisplayItem, OpaqueNode}; +use gfx::display_list::{LayerInfo, LineDisplayItem, OpaqueNode}; use gfx::display_list::{SolidColorDisplayItem, StackingContext, StackingContextType}; use gfx::display_list::{TextDisplayItem, TextOrientation, WebRenderImageInfo}; -use gfx::paint_thread::THREAD_TINT_COLORS; use gfx_traits::{ScrollPolicy, StackingContextId, color}; use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, LAST_FRAGMENT_OF_ELEMENT}; use ipc_channel::ipc; @@ -60,6 +59,17 @@ use table_cell::CollapsedBordersForCell; use url::Url; use util::opts; +static THREAD_TINT_COLORS: [Color; 8] = [ + Color { r: 6.0 / 255.0, g: 153.0 / 255.0, b: 198.0 / 255.0, a: 0.7 }, + Color { r: 255.0 / 255.0, g: 212.0 / 255.0, b: 83.0 / 255.0, a: 0.7 }, + Color { r: 116.0 / 255.0, g: 29.0 / 255.0, b: 109.0 / 255.0, a: 0.7 }, + Color { r: 204.0 / 255.0, g: 158.0 / 255.0, b: 199.0 / 255.0, a: 0.7 }, + Color { r: 242.0 / 255.0, g: 46.0 / 255.0, b: 121.0 / 255.0, a: 0.7 }, + Color { r: 116.0 / 255.0, g: 203.0 / 255.0, b: 196.0 / 255.0, a: 0.7 }, + Color { r: 255.0 / 255.0, g: 249.0 / 255.0, b: 201.0 / 255.0, a: 0.7 }, + Color { r: 137.0 / 255.0, g: 196.0 / 255.0, b: 78.0 / 255.0, a: 0.7 }, +]; + fn get_cyclic<T>(arr: &[T], index: usize) -> &T { &arr[index % arr.len()] } @@ -230,8 +240,6 @@ pub trait FragmentDisplayListBuilding { /// * `relative_containing_block_size`: The size of the containing block that /// `position: relative` makes use of. /// * `clip`: The region to clip the display items to. - /// * `stacking_relative_display_port`: The position and size of the display port with respect - /// to the nearest ancestor stacking context. fn build_display_list(&mut self, state: &mut DisplayListBuildState, stacking_relative_flow_origin: &Point2D<Au>, @@ -239,8 +247,7 @@ pub trait FragmentDisplayListBuilding { relative_containing_block_mode: WritingMode, border_painting_mode: BorderPaintingMode, display_list_section: DisplayListSection, - clip: &ClippingRegion, - stacking_relative_display_port: &Rect<Au>); + clip: &ClippingRegion); /// Adjusts the clipping region for all descendants of this fragment as appropriate. fn adjust_clipping_region_for_children(&self, @@ -497,13 +504,11 @@ impl FragmentDisplayListBuilding for Fragment { image_url: &Url, index: usize) { let background = style.get_background(); - let fetch_image_data_as_well = !opts::get().use_webrender; let webrender_image = state.shared_layout_context .get_webrender_image_for_url(image_url, - UsePlaceholder::No, - fetch_image_data_as_well); + UsePlaceholder::No); - if let Some((webrender_image, image_data)) = webrender_image { + if let Some(webrender_image) = webrender_image { debug!("(building display list) building background image"); // Use `background-size` to get the size. @@ -633,7 +638,7 @@ impl FragmentDisplayListBuilding for Fragment { state.add_display_item(DisplayItem::ImageClass(box ImageDisplayItem { base: base, webrender_image: webrender_image, - image_data: image_data.map(Arc::new), + image_data: None, stretch_size: stretch_size, tile_spacing: tile_spacing, image_rendering: style.get_inheritedbox().image_rendering.clone(), @@ -1080,8 +1085,7 @@ impl FragmentDisplayListBuilding for Fragment { relative_containing_block_mode: WritingMode, border_painting_mode: BorderPaintingMode, display_list_section: DisplayListSection, - clip: &ClippingRegion, - stacking_relative_display_port: &Rect<Au>) { + clip: &ClippingRegion) { self.restyle_damage.remove(REPAINT); if self.style().get_inheritedbox().visibility != visibility::T::visible { return @@ -1102,14 +1106,6 @@ impl FragmentDisplayListBuilding for Fragment { stacking_relative_flow_origin, self); - // webrender deals with all culling via aabb - if !opts::get().use_webrender { - if !stacking_relative_border_box.intersects(stacking_relative_display_port) { - debug!("Fragment::build_display_list: outside display port"); - return - } - } - // Check the clip rect. If there's nothing to render at all, don't even construct display // list items. let empty_rect = !clip.might_intersect_rect(&stacking_relative_border_box); @@ -1270,17 +1266,7 @@ impl FragmentDisplayListBuilding for Fragment { iframe: fragment_info.pipeline_id, }); - if opts::get().use_webrender { - state.add_display_item(item); - } else { - state.add_display_item(DisplayItem::LayeredItemClass(box LayeredItem { - item: item, - layer_info: LayerInfo::new(self.layer_id(), - ScrollPolicy::Scrollable, - Some(fragment_info.pipeline_id), - color::transparent()), - })); - } + state.add_display_item(item); } } SpecificFragmentInfo::Image(ref mut image_fragment) => { @@ -1311,7 +1297,6 @@ impl FragmentDisplayListBuilding for Fragment { let computed_width = canvas_fragment_info.canvas_inline_size().to_px(); let computed_height = canvas_fragment_info.canvas_block_size().to_px(); - let layer_id = self.layer_id(); let canvas_data = match canvas_fragment_info.ipc_renderer { Some(ref ipc_renderer) => { let ipc_renderer = ipc_renderer.lock().unwrap(); @@ -1338,7 +1323,7 @@ impl FragmentDisplayListBuilding for Fragment { width: computed_width as u32, height: computed_height as u32, format: PixelFormat::RGBA8, - key: canvas_data.image_key, + key: Some(canvas_data.image_key), }, stretch_size: stacking_relative_content_box.size, tile_spacing: Size2D::zero(), @@ -1353,17 +1338,7 @@ impl FragmentDisplayListBuilding for Fragment { } }; - if opts::get().use_webrender { - state.add_display_item(display_item); - } else { - state.add_display_item(DisplayItem::LayeredItemClass(box LayeredItem { - item: display_item, - layer_info: LayerInfo::new(layer_id, - ScrollPolicy::Scrollable, - None, - color::transparent()), - })); - } + state.add_display_item(display_item); } } SpecificFragmentInfo::UnscannedText(_) => { @@ -1381,7 +1356,6 @@ impl FragmentDisplayListBuilding for Fragment { scroll_policy: ScrollPolicy, mode: StackingContextCreationMode) -> StackingContext { - let use_webrender = opts::get().use_webrender; let border_box = match mode { StackingContextCreationMode::InnerScrollWrapper => { Rect::new(Point2D::zero(), base_flow.overflow.scroll.size) @@ -1396,10 +1370,7 @@ impl FragmentDisplayListBuilding for Fragment { } }; let overflow = match mode { - StackingContextCreationMode::InnerScrollWrapper if !use_webrender => { - Rect::new(Point2D::zero(), base_flow.overflow.paint.size) - } - StackingContextCreationMode::InnerScrollWrapper if use_webrender => { + StackingContextCreationMode::InnerScrollWrapper => { Rect::new(Point2D::zero(), base_flow.overflow.scroll.size) } StackingContextCreationMode::OuterScrollWrapper => { @@ -1874,8 +1845,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow { .relative_containing_block_mode, border_painting_mode, background_border_section, - &self.base.clip, - &self.base.stacking_relative_position_of_display_port); + &self.base.clip); self.base.build_display_items_for_debugging_tint(state, self.fragment.node); } @@ -1982,8 +1952,7 @@ impl InlineFlowDisplayListBuilding for InlineFlow { .relative_containing_block_mode, BorderPaintingMode::Separate, DisplayListSection::Content, - &self.base.clip, - &self.base.stacking_relative_position_of_display_port); + &self.base.clip); } fn build_display_list_for_inline(&mut self, state: &mut DisplayListBuildState) { @@ -2039,10 +2008,7 @@ impl ListItemFlowDisplayListBuilding for ListItemFlow { .relative_containing_block_mode, BorderPaintingMode::Separate, DisplayListSection::Content, - &self.block_flow.base.clip, - &self.block_flow - .base - .stacking_relative_position_of_display_port); + &self.block_flow.base.clip); } // Draw the rest of the block. diff --git a/components/layout/flow.rs b/components/layout/flow.rs index 8e68250a80d..ea5d61e4cf0 100644 --- a/components/layout/flow.rs +++ b/components/layout/flow.rs @@ -29,7 +29,7 @@ use app_units::Au; use block::{BlockFlow, FormattingContextType}; use context::{LayoutContext, SharedLayoutContext}; use display_list_builder::DisplayListBuildState; -use euclid::{Point2D, Rect, Size2D}; +use euclid::{Point2D, Size2D}; use floats::{Floats, SpeculatedFloatPlacement}; use flow_list::{FlowList, MutFlowListIterator}; use flow_ref::{self, FlowRef, WeakFlowRef}; @@ -940,12 +940,6 @@ pub struct BaseFlow { /// this is in the flow's own coordinate system. pub clip: ClippingRegion, - /// The stacking-relative position of the display port. - /// - /// FIXME(pcwalton): This might be faster as an Arc, since this varies only - /// per-stacking-context. - pub stacking_relative_position_of_display_port: Rect<Au>, - /// The writing mode for this flow. pub writing_mode: WritingMode, @@ -1124,7 +1118,6 @@ impl BaseFlow { early_absolute_position_info: EarlyAbsolutePositionInfo::new(writing_mode), late_absolute_position_info: LateAbsolutePositionInfo::new(), clip: ClippingRegion::max(), - stacking_relative_position_of_display_port: Rect::zero(), flags: flags, writing_mode: writing_mode, thread_id: 0, diff --git a/components/layout/inline.rs b/components/layout/inline.rs index 18bb1ad54a3..055fbeb4a0b 100644 --- a/components/layout/inline.rs +++ b/components/layout/inline.rs @@ -1566,8 +1566,6 @@ impl Flow for InlineFlow { block_flow.base.stacking_relative_position = stacking_relative_content_box.origin; - block_flow.base.stacking_relative_position_of_display_port = - self.base.stacking_relative_position_of_display_port; // Write the clip in our coordinate system into the child flow. (The kid will // fix it up to be in its own coordinate system if necessary.) @@ -1581,8 +1579,6 @@ impl Flow for InlineFlow { block_flow.base.stacking_relative_position = stacking_relative_border_box.origin; - block_flow.base.stacking_relative_position_of_display_port = - self.base.stacking_relative_position_of_display_port; // As above, this is in our coordinate system for now. block_flow.base.clip = self.base.clip.clone() @@ -1602,8 +1598,6 @@ impl Flow for InlineFlow { block_flow.base.stacking_relative_position = stacking_relative_border_box.origin; - block_flow.base.stacking_relative_position_of_display_port = - self.base.stacking_relative_position_of_display_port; // As above, this is in our coordinate system for now. block_flow.base.clip = self.base.clip.clone() diff --git a/components/layout/webrender_helpers.rs b/components/layout/webrender_helpers.rs index ff79f9b6ba7..bcc185e5882 100644 --- a/components/layout/webrender_helpers.rs +++ b/components/layout/webrender_helpers.rs @@ -411,7 +411,7 @@ impl WebRenderDisplayItemConverter for DisplayItem { builder.push_text(item.base.bounds.to_rectf(), item.base.clip.to_clip_region(frame_builder), glyphs, - item.text_run.font_key.expect("Font not added to webrender!"), + item.text_run.font_key, item.text_color.to_colorf(), item.text_run.actual_pt_size, item.blur_radius, diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index 026e9796883..f7d4bd05fde 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -56,7 +56,6 @@ use gfx::display_list::{StackingContext, StackingContextType, WebRenderImageInfo use gfx::font; use gfx::font_cache_thread::FontCacheThread; use gfx::font_context; -use gfx::paint_thread::LayoutToPaintMsg; use gfx_traits::{Epoch, FragmentType, LayerId, ScrollPolicy, StackingContextId, color}; use heapsize::HeapSizeOf; use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; @@ -120,7 +119,6 @@ use style::timer::Timer; use style::workqueue::WorkQueue; use url::Url; use util::geometry::max_rect; -use util::ipc::OptionalIpcSender; use util::opts; use util::prefs::PREFS; use util::resource_files::read_resource_file; @@ -164,9 +162,6 @@ pub struct LayoutThread { /// The channel on which messages can be sent to the script thread. script_chan: IpcSender<ConstellationControlMsg>, - /// The channel on which messages can be sent to the painting thread. - paint_chan: OptionalIpcSender<LayoutToPaintMsg>, - /// The channel on which messages can be sent to the time profiler. time_profiler_chan: time::ProfilerChan, @@ -232,8 +227,8 @@ pub struct LayoutThread { WebRenderImageInfo, BuildHasherDefault<FnvHasher>>>>, - // Webrender interface, if enabled. - webrender_api: Option<webrender_traits::RenderApi>, + // Webrender interface. + webrender_api: webrender_traits::RenderApi, /// The timer object to control the timing of the animations. This should /// only be a test-mode timer during testing for animations. @@ -255,13 +250,12 @@ impl LayoutThreadFactory for LayoutThread { pipeline_port: IpcReceiver<LayoutControlMsg>, constellation_chan: IpcSender<ConstellationMsg>, script_chan: IpcSender<ConstellationControlMsg>, - paint_chan: OptionalIpcSender<LayoutToPaintMsg>, image_cache_thread: ImageCacheThread, font_cache_thread: FontCacheThread, time_profiler_chan: time::ProfilerChan, mem_profiler_chan: mem::ProfilerChan, content_process_shutdown_chan: IpcSender<()>, - webrender_api_sender: Option<webrender_traits::RenderApiSender>, + webrender_api_sender: webrender_traits::RenderApiSender, layout_threads: usize) { thread::spawn_named(format!("LayoutThread {:?}", id), move || { @@ -276,7 +270,6 @@ impl LayoutThreadFactory for LayoutThread { pipeline_port, constellation_chan, script_chan, - paint_chan, image_cache_thread, font_cache_thread, time_profiler_chan, @@ -388,12 +381,11 @@ impl LayoutThread { pipeline_port: IpcReceiver<LayoutControlMsg>, constellation_chan: IpcSender<ConstellationMsg>, script_chan: IpcSender<ConstellationControlMsg>, - paint_chan: OptionalIpcSender<LayoutToPaintMsg>, image_cache_thread: ImageCacheThread, font_cache_thread: FontCacheThread, time_profiler_chan: time::ProfilerChan, mem_profiler_chan: mem::ProfilerChan, - webrender_api_sender: Option<webrender_traits::RenderApiSender>, + webrender_api_sender: webrender_traits::RenderApiSender, layout_threads: usize) -> LayoutThread { let device = Device::new( @@ -439,7 +431,6 @@ impl LayoutThread { pipeline_port: pipeline_receiver, script_chan: script_chan.clone(), constellation_chan: constellation_chan.clone(), - paint_chan: paint_chan, time_profiler_chan: time_profiler_chan, mem_profiler_chan: mem_profiler_chan, image_cache_thread: image_cache_thread, @@ -460,7 +451,7 @@ impl LayoutThread { expired_animations: Arc::new(RwLock::new(HashMap::new())), epoch: Epoch(0), viewport_size: Size2D::new(Au(0), Au(0)), - webrender_api: webrender_api_sender.map(|wr| wr.create_api()), + webrender_api: webrender_api_sender.create_api(), rw_data: Arc::new(Mutex::new( LayoutThreadData { constellation_chan: constellation_chan, @@ -763,13 +754,12 @@ impl LayoutThread { info.pipeline_port, info.constellation_chan, info.script_chan.clone(), - info.paint_chan.to::<LayoutToPaintMsg>(), self.image_cache_thread.clone(), self.font_cache_thread.clone(), self.time_profiler_chan.clone(), self.mem_profiler_chan.clone(), info.content_process_shutdown_chan, - self.webrender_api.as_ref().map(|wr| wr.clone_sender()), + self.webrender_api.clone_sender(), info.layout_threads); } @@ -805,8 +795,6 @@ impl LayoutThread { if let Some(ref mut traversal) = self.parallel_traversal { traversal.shutdown() } - - let _ = self.paint_chan.send(LayoutToPaintMsg::Exit); } fn handle_add_stylesheet<'a, 'b>(&self, @@ -1009,45 +997,38 @@ impl LayoutThread { self.epoch.next(); - if let Some(ref mut webrender_api) = self.webrender_api { - // TODO: Avoid the temporary conversion and build webrender sc/dl directly! - let Epoch(epoch_number) = self.epoch; - let epoch = webrender_traits::Epoch(epoch_number); - let pipeline_id = self.id.to_webrender(); - - // TODO(gw) For now only create a root scrolling layer! - let mut frame_builder = WebRenderFrameBuilder::new(pipeline_id); - let root_scroll_layer_id = frame_builder.next_scroll_layer_id(); - let sc_id = rw_data.display_list.as_ref().unwrap().convert_to_webrender( - webrender_api, - pipeline_id, - epoch, - Some(root_scroll_layer_id), - &mut frame_builder); - let root_background_color = get_root_flow_background_color(layout_root); - let root_background_color = - webrender_traits::ColorF::new(root_background_color.r, - root_background_color.g, - root_background_color.b, - root_background_color.a); - - let viewport_size = Size2D::new(self.viewport_size.width.to_f32_px(), - self.viewport_size.height.to_f32_px()); - - webrender_api.set_root_stacking_context( - sc_id, - root_background_color, - epoch, - pipeline_id, - viewport_size, - frame_builder.stacking_contexts, - frame_builder.display_lists, - frame_builder.auxiliary_lists_builder.finalize()); - } else { - self.paint_chan - .send(LayoutToPaintMsg::PaintInit(self.epoch, display_list)) - .unwrap(); - } + // TODO: Avoid the temporary conversion and build webrender sc/dl directly! + let Epoch(epoch_number) = self.epoch; + let epoch = webrender_traits::Epoch(epoch_number); + let pipeline_id = self.id.to_webrender(); + + // TODO(gw) For now only create a root scrolling layer! + let mut frame_builder = WebRenderFrameBuilder::new(pipeline_id); + let root_scroll_layer_id = frame_builder.next_scroll_layer_id(); + let sc_id = rw_data.display_list.as_ref().unwrap().convert_to_webrender( + &mut self.webrender_api, + pipeline_id, + epoch, + Some(root_scroll_layer_id), + &mut frame_builder); + let root_background_color = get_root_flow_background_color(layout_root); + let root_background_color = + webrender_traits::ColorF::new(root_background_color.r, + root_background_color.g, + root_background_color.b, + root_background_color.a); + + let viewport_size = Size2D::new(self.viewport_size.width.to_f32_px(), + self.viewport_size.height.to_f32_px()); + + self.webrender_api.set_root_stacking_context(sc_id, + root_background_color, + epoch, + pipeline_id, + viewport_size, + frame_builder.stacking_contexts, + frame_builder.display_lists, + frame_builder.auxiliary_lists_builder.finalize()); }); } diff --git a/components/layout_traits/Cargo.toml b/components/layout_traits/Cargo.toml index dcb58d8a902..e286a52b940 100644 --- a/components/layout_traits/Cargo.toml +++ b/components/layout_traits/Cargo.toml @@ -15,7 +15,6 @@ script_traits = {path = "../script_traits"} msg = {path = "../msg"} net_traits = {path = "../net_traits"} profile_traits = {path = "../profile_traits"} -util = {path = "../util"} ipc-channel = "0.5" url = {version = "1.2", features = ["heap_size"]} diff --git a/components/layout_traits/lib.rs b/components/layout_traits/lib.rs index 7f8f0f2e64c..aeeae1bdb26 100644 --- a/components/layout_traits/lib.rs +++ b/components/layout_traits/lib.rs @@ -11,7 +11,6 @@ extern crate net_traits; extern crate profile_traits; extern crate script_traits; extern crate url; -extern crate util; extern crate webrender_traits; // This module contains traits in layout used generically @@ -20,7 +19,6 @@ extern crate webrender_traits; // that these modules won't have to depend on layout. use gfx::font_cache_thread::FontCacheThread; -use gfx::paint_thread::LayoutToPaintMsg; use ipc_channel::ipc::{IpcReceiver, IpcSender}; use msg::constellation_msg::PipelineId; use net_traits::image_cache_thread::ImageCacheThread; @@ -29,7 +27,6 @@ use script_traits::{ConstellationControlMsg, LayoutControlMsg}; use script_traits::LayoutMsg as ConstellationMsg; use std::sync::mpsc::{Receiver, Sender}; use url::Url; -use util::ipc::OptionalIpcSender; // A static method creating a layout thread // Here to remove the compositor -> layout dependency @@ -42,12 +39,11 @@ pub trait LayoutThreadFactory { pipeline_port: IpcReceiver<LayoutControlMsg>, constellation_chan: IpcSender<ConstellationMsg>, script_chan: IpcSender<ConstellationControlMsg>, - layout_to_paint_chan: OptionalIpcSender<LayoutToPaintMsg>, image_cache_thread: ImageCacheThread, font_cache_thread: FontCacheThread, time_profiler_chan: time::ProfilerChan, mem_profiler_chan: mem::ProfilerChan, content_process_shutdown_chan: IpcSender<()>, - webrender_api_sender: Option<webrender_traits::RenderApiSender>, + webrender_api_sender: webrender_traits::RenderApiSender, layout_threads: usize); } diff --git a/components/net/image_cache_thread.rs b/components/net/image_cache_thread.rs index 92c0aa0fd83..8925e6198ca 100644 --- a/components/net/image_cache_thread.rs +++ b/components/net/image_cache_thread.rs @@ -252,8 +252,8 @@ struct ImageCache { // The placeholder image used when an image fails to load placeholder_image: Option<Arc<Image>>, - // Webrender API instance, if enabled. - webrender_api: Option<webrender_traits::RenderApi>, + // Webrender API instance. + webrender_api: webrender_traits::RenderApi, } /// Message that the decoder worker threads send to main image cache thread. @@ -318,24 +318,23 @@ impl LoadOrigin for ImageCacheOrigin { } } -fn get_placeholder_image(webrender_api: &Option<webrender_traits::RenderApi>) -> io::Result<Arc<Image>> { +fn get_placeholder_image(webrender_api: &webrender_traits::RenderApi) -> io::Result<Arc<Image>> { let mut placeholder_path = try!(resources_dir_path()); placeholder_path.push("rippy.png"); let mut file = try!(File::open(&placeholder_path)); let mut image_data = vec![]; try!(file.read_to_end(&mut image_data)); let mut image = load_from_memory(&image_data).unwrap(); - if let Some(ref webrender_api) = *webrender_api { - let format = convert_format(image.format); - let mut bytes = Vec::new(); - bytes.extend_from_slice(&*image.bytes); - image.id = Some(webrender_api.add_image(image.width, image.height, format, bytes)); - } + let format = convert_format(image.format); + let mut bytes = Vec::new(); + bytes.extend_from_slice(&*image.bytes); + image.id = Some(webrender_api.add_image(image.width, image.height, format, bytes)); Ok(Arc::new(image)) } + impl ImageCache { fn run(core_resource_thread: CoreResourceThread, - webrender_api: Option<webrender_traits::RenderApi>, + webrender_api: webrender_traits::RenderApi, ipc_command_receiver: IpcReceiver<ImageCacheCommand>) { // Preload the placeholder image, used when images fail to load. let placeholder_image = get_placeholder_image(&webrender_api).ok(); @@ -479,16 +478,14 @@ impl ImageCache { fn complete_load(&mut self, key: LoadKey, mut load_result: LoadResult) { let pending_load = self.pending_loads.remove(&key).unwrap(); - if let Some(ref webrender_api) = self.webrender_api { - match load_result { - LoadResult::Loaded(ref mut image) => { - let format = convert_format(image.format); - let mut bytes = Vec::new(); - bytes.extend_from_slice(&*image.bytes); - image.id = Some(webrender_api.add_image(image.width, image.height, format, bytes)); - } - LoadResult::PlaceholderLoaded(..) | LoadResult::None => {} + match load_result { + LoadResult::Loaded(ref mut image) => { + let format = convert_format(image.format); + let mut bytes = Vec::new(); + bytes.extend_from_slice(&*image.bytes); + image.id = Some(self.webrender_api.add_image(image.width, image.height, format, bytes)); } + LoadResult::PlaceholderLoaded(..) | LoadResult::None => {} } let image_response = match load_result { @@ -627,7 +624,7 @@ impl ImageCache { /// Create a new image cache. pub fn new_image_cache_thread(core_resource_thread: CoreResourceThread, - webrender_api: Option<webrender_traits::RenderApi>) -> ImageCacheThread { + webrender_api: webrender_traits::RenderApi) -> ImageCacheThread { let (ipc_command_sender, ipc_command_receiver) = ipc::channel().unwrap(); spawn_named("ImageCacheThread".to_owned(), move || { diff --git a/components/net_traits/image/base.rs b/components/net_traits/image/base.rs index 9c72413d320..cc604a1dc62 100644 --- a/components/net_traits/image/base.rs +++ b/components/net_traits/image/base.rs @@ -4,7 +4,6 @@ use ipc_channel::ipc::IpcSharedMemory; use piston_image::{self, DynamicImage, ImageFormat}; -use util::opts; pub use msg::constellation_msg::{Image, PixelFormat}; @@ -21,24 +20,14 @@ pub struct ImageMetadata { fn byte_swap_and_premultiply(data: &mut [u8]) { let length = data.len(); - // No need to pre-multiply alpha when using direct GPU rendering. - let premultiply_alpha = !opts::get().use_webrender; - for i in (0..length).step_by(4) { let r = data[i + 2]; let g = data[i + 1]; let b = data[i + 0]; - let a = data[i + 3]; - - if premultiply_alpha { - data[i + 0] = ((r as u32) * (a as u32) / 255) as u8; - data[i + 1] = ((g as u32) * (a as u32) / 255) as u8; - data[i + 2] = ((b as u32) * (a as u32) / 255) as u8; - } else { - data[i + 0] = r; - data[i + 1] = g; - data[i + 2] = b; - } + + data[i + 0] = r; + data[i + 1] = g; + data[i + 2] = b; } } diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 5ddf6cda2ea..5b36249be59 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -5,7 +5,7 @@ use canvas_traits::{Canvas2dMsg, CanvasCommonMsg, CanvasMsg}; use canvas_traits::{CompositionOrBlending, FillOrStrokeStyle, FillRule}; use canvas_traits::{LineCapStyle, LineJoinStyle, LinearGradientStyle}; -use canvas_traits::{RadialGradientStyle, RepetitionStyle, byte_swap, byte_swap_and_premultiply}; +use canvas_traits::{RadialGradientStyle, RepetitionStyle, byte_swap_and_premultiply}; use cssparser::{Parser, RGBA}; use cssparser::Color as CSSColor; use dom::bindings::cell::DOMRefCell; @@ -47,7 +47,6 @@ use std::cell::Cell; use std::str::FromStr; use unpremultiplytable::UNPREMULTIPLY_TABLE; use url::Url; -use util::opts; #[must_root] #[derive(JSTraceable, Clone, HeapSizeOf)] @@ -297,14 +296,7 @@ impl CanvasRenderingContext2D { Some((mut data, size)) => { // Pixels come from cache in BGRA order and drawImage expects RGBA so we // have to swap the color values - if opts::get().use_webrender { - // Webrender doesn't pre-multiply alpha when decoding - // images, but canvas expects the images to be - // pre-multiplied alpha. - byte_swap_and_premultiply(&mut data); - } else { - byte_swap(&mut data); - } + byte_swap_and_premultiply(&mut data); let size = Size2D::new(size.width as f64, size.height as f64); (data, size) }, diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 9a836b6d845..5ee70b8b068 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -1220,42 +1220,20 @@ impl Window { } pub fn scroll_offset_query(&self, node: &Node) -> Point2D<f32> { - // WebRender always keeps the scroll offsets up to date and stored here in the window. So, - // if WR is in use, all we need to do is to check our list of scroll offsets and return the - // result. - if opts::get().use_webrender { - let mut node = Root::from_ref(node); - loop { - if let Some(scroll_offset) = self.scroll_offsets - .borrow() - .get(&node.to_untrusted_node_address()) { - return *scroll_offset - } - node = match node.GetParentNode() { - Some(node) => node, - None => break, - } + let mut node = Root::from_ref(node); + loop { + if let Some(scroll_offset) = self.scroll_offsets + .borrow() + .get(&node.to_untrusted_node_address()) { + return *scroll_offset + } + node = match node.GetParentNode() { + Some(node) => node, + None => break, } - let offset = self.current_viewport.get().origin; - return Point2D::new(offset.x.to_f32_px(), offset.y.to_f32_px()) - } - - let node = node.to_trusted_node_address(); - if !self.reflow(ReflowGoal::ForScriptQuery, - ReflowQueryType::NodeLayerIdQuery(node), - ReflowReason::Query) { - return Point2D::zero(); } - - let layer_id = self.layout_rpc.node_layer_id().layer_id; - - let (send, recv) = ipc::channel::<Point2D<f32>>().unwrap(); - let global_scope = self.upcast::<GlobalScope>(); - global_scope - .constellation_chan() - .send(ConstellationMsg::GetScrollOffset(global_scope.pipeline_id(), layer_id, send)) - .unwrap(); - recv.recv().unwrap_or(Point2D::zero()) + let offset = self.current_viewport.get().origin; + Point2D::new(offset.x.to_f32_px(), offset.y.to_f32_px()) } // https://drafts.csswg.org/cssom-view/#dom-element-scroll diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 335e65f2abf..73a3d1458d8 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -1143,7 +1143,6 @@ impl ScriptThread { new_pipeline_id, frame_type, load_data, - paint_chan, pipeline_port, layout_to_constellation_chan, content_process_shutdown_chan, @@ -1160,7 +1159,6 @@ impl ScriptThread { layout_pair: layout_pair, pipeline_port: pipeline_port, constellation_chan: layout_to_constellation_chan, - paint_chan: paint_chan, script_chan: self.control_chan.clone(), image_cache_thread: self.image_cache_thread.clone(), content_process_shutdown_chan: content_process_shutdown_chan, diff --git a/components/script_layout_interface/Cargo.toml b/components/script_layout_interface/Cargo.toml index 970c74aa515..9edbd41c8f4 100644 --- a/components/script_layout_interface/Cargo.toml +++ b/components/script_layout_interface/Cargo.toml @@ -31,4 +31,3 @@ selectors = "0.13" string_cache = {version = "0.2.26", features = ["heap_size"]} style = {path = "../style"} url = {version = "1.2", features = ["heap_size"]} -util = {path = "../util"} diff --git a/components/script_layout_interface/lib.rs b/components/script_layout_interface/lib.rs index ee2a2a8b75f..31d4334cb6d 100644 --- a/components/script_layout_interface/lib.rs +++ b/components/script_layout_interface/lib.rs @@ -39,7 +39,6 @@ extern crate selectors; extern crate string_cache; extern crate style; extern crate url; -extern crate util; pub mod message; pub mod reporter; diff --git a/components/script_layout_interface/message.rs b/components/script_layout_interface/message.rs index 35583bc2dfe..5d41b6df660 100644 --- a/components/script_layout_interface/message.rs +++ b/components/script_layout_interface/message.rs @@ -21,7 +21,6 @@ use style::context::ReflowGoal; use style::selector_impl::PseudoElement; use style::stylesheets::Stylesheet; use url::Url; -use util::ipc::OptionalOpaqueIpcSender; /// Asynchronous messages that script can send to layout. pub enum Msg { @@ -148,7 +147,6 @@ pub struct NewLayoutThreadInfo { pub constellation_chan: IpcSender<ConstellationMsg>, pub script_chan: IpcSender<ConstellationControlMsg>, pub image_cache_thread: ImageCacheThread, - pub paint_chan: OptionalOpaqueIpcSender, pub content_process_shutdown_chan: IpcSender<()>, pub layout_threads: usize, } diff --git a/components/script_traits/Cargo.toml b/components/script_traits/Cargo.toml index 8a51d5bd6b7..5fb33f27625 100644 --- a/components/script_traits/Cargo.toml +++ b/components/script_traits/Cargo.toml @@ -20,7 +20,6 @@ heapsize = "0.3.0" heapsize_plugin = "0.1.2" hyper_serde = "0.1.4" ipc-channel = "0.5" -layers = {git = "https://github.com/servo/rust-layers", features = ["plugins"]} libc = "0.2" msg = {path = "../msg"} net_traits = {path = "../net_traits"} @@ -33,4 +32,3 @@ serde_derive = "0.8" style_traits = {path = "../style_traits", features = ["servo"]} time = "0.1.12" url = {version = "1.2", features = ["heap_size"]} -util = {path = "../util"} diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs index c5fa8fee4e6..73eee3bccea 100644 --- a/components/script_traits/lib.rs +++ b/components/script_traits/lib.rs @@ -20,7 +20,6 @@ extern crate gfx_traits; extern crate heapsize; extern crate hyper_serde; extern crate ipc_channel; -extern crate layers; extern crate libc; extern crate msg; extern crate net_traits; @@ -33,7 +32,6 @@ extern crate serde_derive; extern crate style_traits; extern crate time; extern crate url; -extern crate util; mod script_msg; pub mod webdriver_msg; @@ -46,12 +44,12 @@ use euclid::point::Point2D; use euclid::rect::Rect; use euclid::scale_factor::ScaleFactor; use euclid::size::TypedSize2D; +use gfx_traits::DevicePixel; use gfx_traits::Epoch; use gfx_traits::LayerId; use gfx_traits::StackingContextId; use heapsize::HeapSizeOf; use ipc_channel::ipc::{IpcReceiver, IpcSender}; -use layers::geometry::DevicePixel; use libc::c_void; use msg::constellation_msg::{FrameId, FrameType, Image, Key, KeyModifiers, KeyState, LoadData}; use msg::constellation_msg::{PipelineId, PipelineNamespaceId, ReferrerPolicy}; @@ -68,7 +66,6 @@ use std::fmt; use std::sync::mpsc::{Receiver, Sender}; use style_traits::{PagePx, UnsafeNode, ViewportPx}; use url::Url; -use util::ipc::OptionalOpaqueIpcSender; use webdriver_msg::{LoadStatus, WebDriverScriptCommand}; pub use script_msg::{LayoutMsg, ScriptMsg, EventResult, LogEntry}; @@ -138,9 +135,6 @@ pub struct NewLayoutInfo { pub frame_type: FrameType, /// Network request data which will be initiated by the script thread. pub load_data: LoadData, - /// The paint channel, cast to `OptionalOpaqueIpcSender`. This is really an - /// `Sender<LayoutToPaintMsg>`. - pub paint_chan: OptionalOpaqueIpcSender, /// A port on which layout can receive messages from the pipeline. pub pipeline_port: IpcReceiver<LayoutControlMsg>, /// A sender for the layout thread to communicate to the constellation. diff --git a/components/script_traits/script_msg.rs b/components/script_traits/script_msg.rs index 8b3283800df..d12ec99abef 100644 --- a/components/script_traits/script_msg.rs +++ b/components/script_traits/script_msg.rs @@ -128,8 +128,6 @@ pub enum ScriptMsg { ResizeTo(Size2D<u32>), /// Script has handled a touch event, and either prevented or allowed default actions. TouchEventProcessed(EventResult), - /// Get Scroll Offset - GetScrollOffset(PipelineId, LayerId, IpcSender<Point2D<f32>>), /// A log entry, with the pipeline id and thread name LogEntry(Option<PipelineId>, Option<String>, LogEntry), /// Notifies the constellation that this pipeline has exited. diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index 2b6ccfc0e7b..80ea989dc82 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -321,14 +321,11 @@ dependencies = [ name = "compositing" version = "0.0.1" dependencies = [ - "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "azure 0.9.0 (git+https://github.com/servo/rust-azure)", "euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "gfx_traits 0.0.1", "gleam 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "image 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "layers 0.5.3 (git+https://github.com/servo/rust-layers)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", "net_traits 0.0.1", @@ -359,7 +356,6 @@ dependencies = [ "gfx 0.0.1", "gfx_traits 0.0.1", "ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "layers 0.5.3 (git+https://github.com/servo/rust-layers)", "layout_traits 0.0.1", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", @@ -797,7 +793,6 @@ dependencies = [ "heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize_plugin 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "layers 0.5.3 (git+https://github.com/servo/rust-layers)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -806,8 +801,6 @@ dependencies = [ "net_traits 0.0.1", "ordered-float 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "plugins 0.0.1", - "profile_traits 0.0.1", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "range 0.0.1", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -841,13 +834,9 @@ name = "gfx_traits" version = "0.0.1" dependencies = [ "azure 0.9.0 (git+https://github.com/servo/rust-azure)", - "euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize_plugin 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "layers 0.5.3 (git+https://github.com/servo/rust-layers)", - "msg 0.0.1", "plugins 0.0.1", - "profile_traits 0.0.1", "range 0.0.1", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -894,8 +883,8 @@ dependencies = [ "compositing 0.0.1", "euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gfx_traits 0.0.1", "gleam 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "layers 0.5.3 (git+https://github.com/servo/rust-layers)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", "net_traits 0.0.1", @@ -1142,26 +1131,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "layers" -version = "0.5.3" -source = "git+https://github.com/servo/rust-layers#b064de859b2cf3f4e07b29ee11a34543f1671ac0" -dependencies = [ - "cgl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "gleam 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "glx 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "io-surface 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "servo-skia 0.20130412.24 (registry+https://github.com/rust-lang/crates.io-index)", - "x11 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] name = "layout" version = "0.0.1" dependencies = [ @@ -1251,7 +1220,6 @@ dependencies = [ "profile_traits 0.0.1", "script_traits 0.0.1", "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "util 0.0.1", "webrender_traits 0.6.0 (git+https://github.com/servo/webrender)", ] @@ -2050,7 +2018,6 @@ dependencies = [ "string_cache 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "util 0.0.1", ] [[package]] @@ -2077,7 +2044,6 @@ dependencies = [ "heapsize_plugin 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "hyper_serde 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "layers 0.5.3 (git+https://github.com/servo/rust-layers)", "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", "net_traits 0.0.1", @@ -2090,7 +2056,6 @@ dependencies = [ "style_traits 0.0.1", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "util 0.0.1", ] [[package]] @@ -2917,7 +2882,6 @@ dependencies = [ "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum khronos_api 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "09c9d3760673c427d46f91a0350f0a84a52e6bc5a84adf26dc610b6c52436630" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" -"checksum layers 0.5.3 (git+https://github.com/servo/rust-layers)" = "<none>" "checksum lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "cf186d1a8aa5f5bee5fd662bc9c1b949e0259e1bcc379d1f006847b0080c7417" "checksum lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "49247ec2a285bb3dcb23cbd9c35193c025e7251bfce77c1d5da97e6362dffe7f" "checksum leak 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd100e01f1154f2908dfa7d02219aeab25d0b9c7fa955164192e3245255a0c73" diff --git a/components/servo/lib.rs b/components/servo/lib.rs index bd43ff2064d..b715a9ebc35 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -133,57 +133,50 @@ impl<Window> Browser<Window> where Window: WindowMethods + 'static { devtools::start_server(port) }); - let (webrender, webrender_api_sender) = if opts::get().use_webrender { - if let Ok(mut resource_path) = resources_dir_path() { - resource_path.push("shaders"); - - // TODO(gw): Duplicates device_pixels_per_screen_px from compositor. Tidy up! - let scale_factor = window.scale_factor().get(); - let device_pixel_ratio = match opts.device_pixels_per_px { - Some(device_pixels_per_px) => device_pixels_per_px, - None => match opts.output_file { - Some(_) => 1.0, - None => scale_factor, - } - }; - - let renderer_kind = if opts::get().should_use_osmesa() { - webrender_traits::RendererKind::OSMesa - } else { - webrender_traits::RendererKind::Native - }; - - let (webrender, webrender_sender) = - webrender::Renderer::new(webrender::RendererOptions { - device_pixel_ratio: device_pixel_ratio, - resource_path: resource_path, - enable_aa: opts.enable_text_antialiasing, - enable_msaa: opts.use_msaa, - enable_profiler: opts.webrender_stats, - debug: opts.webrender_debug, - enable_recording: false, - precache_shaders: opts.precache_shaders, - enable_scrollbars: opts.output_file.is_none(), - renderer_kind: renderer_kind, - }); - (Some(webrender), Some(webrender_sender)) + let mut resource_path = resources_dir_path().unwrap(); + resource_path.push("shaders"); + + let (webrender, webrender_api_sender) = { + // TODO(gw): Duplicates device_pixels_per_screen_px from compositor. Tidy up! + let scale_factor = window.scale_factor().get(); + let device_pixel_ratio = match opts.device_pixels_per_px { + Some(device_pixels_per_px) => device_pixels_per_px, + None => match opts.output_file { + Some(_) => 1.0, + None => scale_factor, + } + }; + + let renderer_kind = if opts::get().should_use_osmesa() { + webrender_traits::RendererKind::OSMesa } else { - (None, None) - } - } else { - (None, None) + webrender_traits::RendererKind::Native + }; + + webrender::Renderer::new(webrender::RendererOptions { + device_pixel_ratio: device_pixel_ratio, + resource_path: resource_path, + enable_aa: opts.enable_text_antialiasing, + enable_msaa: opts.use_msaa, + enable_profiler: opts.webrender_stats, + debug: opts.webrender_debug, + enable_recording: false, + precache_shaders: opts.precache_shaders, + enable_scrollbars: opts.output_file.is_none(), + renderer_kind: renderer_kind, + }) }; // Create the constellation, which maintains the engine // pipelines, including the script and layout threads, as well // as the navigation context. let (constellation_chan, sw_senders) = create_constellation(opts.clone(), - compositor_proxy.clone_compositor_proxy(), - time_profiler_chan.clone(), - mem_profiler_chan.clone(), - devtools_chan, - supports_clipboard, - webrender_api_sender.clone()); + compositor_proxy.clone_compositor_proxy(), + time_profiler_chan.clone(), + mem_profiler_chan.clone(), + devtools_chan, + supports_clipboard, + webrender_api_sender.clone()); // Send the constellation's swmanager sender to service worker manager thread script::init(sw_senders); @@ -247,7 +240,7 @@ fn create_constellation(opts: opts::Opts, mem_profiler_chan: mem::ProfilerChan, devtools_chan: Option<Sender<devtools_traits::DevtoolsControlMsg>>, supports_clipboard: bool, - webrender_api_sender: Option<webrender_traits::RenderApiSender>) + webrender_api_sender: webrender_traits::RenderApiSender) -> (Sender<ConstellationMsg>, SWManagerSenders) { let bluetooth_thread: IpcSender<BluetoothMethodMsg> = BluetoothThreadFactory::new(); @@ -257,9 +250,9 @@ fn create_constellation(opts: opts::Opts, time_profiler_chan.clone(), opts.config_dir.map(Into::into)); let image_cache_thread = new_image_cache_thread(public_resource_threads.sender(), - webrender_api_sender.as_ref().map(|wr| wr.create_api())); + webrender_api_sender.create_api()); let font_cache_thread = FontCacheThread::new(public_resource_threads.sender(), - webrender_api_sender.as_ref().map(|wr| wr.create_api())); + Some(webrender_api_sender.create_api())); let resource_sender = public_resource_threads.sender(); diff --git a/components/util/opts.rs b/components/util/opts.rs index 148a1dfc6a7..242cd569bec 100644 --- a/components/util/opts.rs +++ b/components/util/opts.rs @@ -192,9 +192,6 @@ pub struct Opts { /// Enable vsync in the compositor pub enable_vsync: bool, - /// True to enable the webrender painting/compositing backend. - pub use_webrender: bool, - /// True to show webrender profiling stats on screen. pub webrender_stats: bool, @@ -212,9 +209,6 @@ pub struct Opts { /// Directory for a default config directory pub config_dir: Option<String>, - // Which rendering API to use. - pub render_api: RenderApi, - // don't skip any backtraces on panic pub full_backtraces: bool, @@ -452,15 +446,6 @@ enum UserAgent { Android, } -#[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -pub enum RenderApi { - GL, - ES2, -} - -const DEFAULT_RENDER_API: RenderApi = RenderApi::GL; - fn default_user_agent_string(agent: UserAgent) -> &'static str { #[cfg(all(target_os = "linux", target_arch = "x86_64"))] const DESKTOP_UA_STRING: &'static str = @@ -549,10 +534,8 @@ pub fn default_opts() -> Opts { exit_after_load: false, no_native_titlebar: false, enable_vsync: true, - use_webrender: true, webrender_stats: false, use_msaa: false, - render_api: DEFAULT_RENDER_API, config_dir: None, full_backtraces: false, is_printing_version: false, @@ -800,15 +783,6 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult { opt_match.opt_present("b") || !PREFS.get("shell.native-titlebar.enabled").as_boolean().unwrap(); - let use_webrender = !opt_match.opt_present("c"); - - let render_api = match opt_match.opt_str("G") { - Some(ref ga) if ga == "gl" => RenderApi::GL, - Some(ref ga) if ga == "es2" => RenderApi::ES2, - None => DEFAULT_RENDER_API, - _ => args_fail(&format!("error: graphics option must be gl or es2:")), - }; - let is_printing_version = opt_match.opt_present("v") || opt_match.opt_present("version"); let opts = Opts { @@ -842,7 +816,6 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult { sandbox: opt_match.opt_present("S"), random_pipeline_closure_probability: random_pipeline_closure_probability, random_pipeline_closure_seed: random_pipeline_closure_seed, - render_api: render_api, show_debug_borders: debug_options.show_compositor_borders, show_debug_fragment_borders: debug_options.show_fragment_borders, show_debug_parallel_paint: debug_options.show_parallel_paint, @@ -862,7 +835,6 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult { exit_after_load: opt_match.opt_present("x"), no_native_titlebar: do_not_use_native_titlebar, enable_vsync: !debug_options.disable_vsync, - use_webrender: use_webrender, webrender_stats: debug_options.webrender_stats, use_msaa: debug_options.use_msaa, config_dir: opt_match.opt_str("config-dir"), diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock index ce9c6084174..3fbfa944b31 100644 --- a/ports/cef/Cargo.lock +++ b/ports/cef/Cargo.lock @@ -6,9 +6,9 @@ dependencies = [ "compositing 0.0.1", "devtools 0.0.1", "euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "gfx_traits 0.0.1", "gleam 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "glutin_app 0.0.1", - "layers 0.5.3 (git+https://github.com/servo/rust-layers)", "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", @@ -278,14 +278,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "compositing" version = "0.0.1" dependencies = [ - "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "azure 0.9.0 (git+https://github.com/servo/rust-azure)", "euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "gfx_traits 0.0.1", "gleam 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "image 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "layers 0.5.3 (git+https://github.com/servo/rust-layers)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", "net_traits 0.0.1", @@ -316,7 +313,6 @@ dependencies = [ "gfx 0.0.1", "gfx_traits 0.0.1", "ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "layers 0.5.3 (git+https://github.com/servo/rust-layers)", "layout_traits 0.0.1", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", @@ -713,7 +709,6 @@ dependencies = [ "heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize_plugin 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "layers 0.5.3 (git+https://github.com/servo/rust-layers)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -722,8 +717,6 @@ dependencies = [ "net_traits 0.0.1", "ordered-float 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "plugins 0.0.1", - "profile_traits 0.0.1", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "range 0.0.1", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -748,13 +741,9 @@ name = "gfx_traits" version = "0.0.1" dependencies = [ "azure 0.9.0 (git+https://github.com/servo/rust-azure)", - "euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize_plugin 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "layers 0.5.3 (git+https://github.com/servo/rust-layers)", - "msg 0.0.1", "plugins 0.0.1", - "profile_traits 0.0.1", "range 0.0.1", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -801,8 +790,8 @@ dependencies = [ "compositing 0.0.1", "euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gfx_traits 0.0.1", "gleam 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "layers 0.5.3 (git+https://github.com/servo/rust-layers)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", "net_traits 0.0.1", @@ -1049,26 +1038,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "layers" -version = "0.5.3" -source = "git+https://github.com/servo/rust-layers#b064de859b2cf3f4e07b29ee11a34543f1671ac0" -dependencies = [ - "cgl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "gleam 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "glx 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "io-surface 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "servo-skia 0.20130412.24 (registry+https://github.com/rust-lang/crates.io-index)", - "x11 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] name = "layout" version = "0.0.1" dependencies = [ @@ -1151,7 +1120,6 @@ dependencies = [ "profile_traits 0.0.1", "script_traits 0.0.1", "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "util 0.0.1", "webrender_traits 0.6.0 (git+https://github.com/servo/webrender)", ] @@ -1901,7 +1869,6 @@ dependencies = [ "string_cache 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "util 0.0.1", ] [[package]] @@ -1918,7 +1885,6 @@ dependencies = [ "heapsize_plugin 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "hyper_serde 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "layers 0.5.3 (git+https://github.com/servo/rust-layers)", "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", "net_traits 0.0.1", @@ -1931,7 +1897,6 @@ dependencies = [ "style_traits 0.0.1", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "util 0.0.1", ] [[package]] @@ -2769,7 +2734,6 @@ dependencies = [ "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum khronos_api 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "09c9d3760673c427d46f91a0350f0a84a52e6bc5a84adf26dc610b6c52436630" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" -"checksum layers 0.5.3 (git+https://github.com/servo/rust-layers)" = "<none>" "checksum lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "cf186d1a8aa5f5bee5fd662bc9c1b949e0259e1bcc379d1f006847b0080c7417" "checksum lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "49247ec2a285bb3dcb23cbd9c35193c025e7251bfce77c1d5da97e6362dffe7f" "checksum leak 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd100e01f1154f2908dfa7d02219aeab25d0b9c7fa955164192e3245255a0c73" diff --git a/ports/cef/Cargo.toml b/ports/cef/Cargo.toml index dd2525410c5..8e0d4383121 100644 --- a/ports/cef/Cargo.toml +++ b/ports/cef/Cargo.toml @@ -18,9 +18,9 @@ opt-level = 3 compositing = {path = "../../components/compositing"} devtools = {path = "../../components/devtools"} euclid = "0.10.1" +gfx_traits = {path = "../../components/gfx_traits"} gleam = "0.2.8" glutin_app = {path = "../glutin"} -layers = {git = "https://github.com/servo/rust-layers"} libc = "0.2" log = {version = "0.3.5", features = ["release_max_level_info"]} msg = {path = "../../components/msg"} diff --git a/ports/cef/lib.rs b/ports/cef/lib.rs index c0b7fc6375d..02a39d901fe 100644 --- a/ports/cef/lib.rs +++ b/ports/cef/lib.rs @@ -19,9 +19,9 @@ extern crate servo; extern crate compositing; extern crate euclid; +extern crate gfx_traits; extern crate gleam; extern crate glutin_app; -extern crate layers; extern crate rustc_unicode; extern crate script_traits; diff --git a/ports/cef/window.rs b/ports/cef/window.rs index 062f239bcdd..8a3b1d9d2ce 100644 --- a/ports/cef/window.rs +++ b/ports/cef/window.rs @@ -23,9 +23,8 @@ use compositing::windowing::{WindowEvent, WindowMethods}; use euclid::point::Point2D; use euclid::scale_factor::ScaleFactor; use euclid::size::{Size2D, TypedSize2D}; +use gfx_traits::DevicePixel; use gleam::gl; -use layers::geometry::DevicePixel; -use layers::platform::surface::NativeDisplay; use msg::constellation_msg::{Key, KeyModifiers}; use net_traits::net_error_list::NetError; use std::cell::RefCell; @@ -284,19 +283,6 @@ impl WindowMethods for Window { } } - #[cfg(target_os="linux")] - fn native_display(&self) -> NativeDisplay { - use x11::xlib; - unsafe { - NativeDisplay::new(DISPLAY as *mut xlib::Display) - } - } - - #[cfg(not(target_os="linux"))] - fn native_display(&self) -> NativeDisplay { - NativeDisplay::new() - } - fn create_compositor_channel(&self) -> (Box<CompositorProxy+Send>, Box<CompositorReceiver>) { let (sender, receiver) = channel(); diff --git a/ports/glutin/Cargo.toml b/ports/glutin/Cargo.toml index b5d90e499bf..015468b8260 100644 --- a/ports/glutin/Cargo.toml +++ b/ports/glutin/Cargo.toml @@ -12,8 +12,8 @@ path = "lib.rs" bitflags = "0.7" compositing = {path = "../../components/compositing"} euclid = "0.10.1" +gfx_traits = {path = "../../components/gfx_traits"} gleam = "0.2.8" -layers = {git = "https://github.com/servo/rust-layers", features = ["plugins"]} log = "0.3.5" msg = {path = "../../components/msg"} net_traits = {path = "../../components/net_traits"} diff --git a/ports/glutin/lib.rs b/ports/glutin/lib.rs index 6e3c64691c2..99e57439b24 100644 --- a/ports/glutin/lib.rs +++ b/ports/glutin/lib.rs @@ -11,9 +11,9 @@ extern crate compositing; #[allow(unused_extern_crates)] #[cfg(target_os = "android")] extern crate egl; extern crate euclid; +extern crate gfx_traits; extern crate gleam; extern crate glutin; -extern crate layers; #[macro_use] extern crate log; extern crate msg; extern crate net_traits; @@ -22,7 +22,6 @@ extern crate script_traits; extern crate style_traits; extern crate url; extern crate util; -#[cfg(target_os = "linux")] extern crate x11; #[cfg(target_os = "windows")] extern crate winapi; #[cfg(target_os = "windows")] extern crate user32; #[cfg(target_os = "windows")] extern crate gdi32; diff --git a/ports/glutin/window.rs b/ports/glutin/window.rs index 1bb7af2fef2..5a8b811aff4 100644 --- a/ports/glutin/window.rs +++ b/ports/glutin/window.rs @@ -13,14 +13,13 @@ use euclid::scale_factor::ScaleFactor; use euclid::size::TypedSize2D; #[cfg(target_os = "windows")] use gdi32; +use gfx_traits::DevicePixel; use gleam::gl; use glutin; use glutin::{Api, ElementState, Event, GlRequest, MouseButton, MouseScrollDelta, VirtualKeyCode}; use glutin::{ScanCode, TouchPhase}; #[cfg(target_os = "macos")] use glutin::os::macos::{ActivationPolicy, WindowBuilderExt}; -use layers::geometry::DevicePixel; -use layers::platform::surface::NativeDisplay; use msg::constellation_msg::{self, Key}; use msg::constellation_msg::{ALT, CONTROL, KeyState, NONE, SHIFT, SUPER}; use net_traits::net_error_list::NetError; @@ -42,8 +41,6 @@ use url::Url; use user32; use util::geometry::ScreenPx; use util::opts; -#[cfg(not(target_os = "android"))] -use util::opts::RenderApi; use util::prefs::PREFS; use util::resource_files; #[cfg(target_os = "windows")] @@ -318,17 +315,7 @@ impl Window { #[cfg(not(any(target_arch = "arm", target_arch = "aarch64")))] fn gl_version() -> GlRequest { - if opts::get().use_webrender { - return GlRequest::Specific(Api::OpenGl, (3, 2)); - } - match opts::get().render_api { - RenderApi::GL => { - GlRequest::Specific(Api::OpenGl, (2, 1)) - } - RenderApi::ES2 => { - GlRequest::Specific(Api::OpenGlEs, (2, 0)) - } - } + return GlRequest::Specific(Api::OpenGl, (3, 2)); } #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] @@ -558,72 +545,28 @@ impl Window { #[cfg(any(target_os = "linux", target_os = "android"))] fn handle_next_event(&self) -> bool { - use std::thread; - use std::time::Duration; - - // WebRender can use the normal blocking event check and proper vsync, - // because it doesn't call X11 functions from another thread, so doesn't - // hit the same issues explained below. - if opts::get().use_webrender { - match self.kind { - WindowKind::Window(ref window) => { - let event = match window.wait_events().next() { - None => { - warn!("Window event stream closed."); - return false; - }, - Some(event) => event, - }; - let mut close = self.handle_window_event(event); - if !close { - while let Some(event) = window.poll_events().next() { - if self.handle_window_event(event) { - close = true; - break - } + match self.kind { + WindowKind::Window(ref window) => { + let event = match window.wait_events().next() { + None => { + warn!("Window event stream closed."); + return false; + }, + Some(event) => event, + }; + let mut close = self.handle_window_event(event); + if !close { + while let Some(event) = window.poll_events().next() { + if self.handle_window_event(event) { + close = true; + break } } - close - } - WindowKind::Headless(..) => { - false } + close } - } else { - // TODO(gw): This is an awful hack to work around the - // broken way we currently call X11 from multiple threads. - // - // On some (most?) X11 implementations, blocking here - // with XPeekEvent results in the paint thread getting stuck - // in XGetGeometry randomly. When this happens the result - // is that until you trigger the XPeekEvent to return - // (by moving the mouse over the window) the paint thread - // never completes and you don't see the most recent - // results. - // - // For now, poll events and sleep for ~1 frame if there - // are no events. This means we don't spin the CPU at - // 100% usage, but is far from ideal! - // - // See https://github.com/servo/servo/issues/5780 - // - match self.kind { - WindowKind::Window(ref window) => { - let first_event = window.poll_events().next(); - - match first_event { - Some(event) => { - self.handle_window_event(event) - } - None => { - thread::sleep(Duration::from_millis(16)); - false - } - } - } - WindowKind::Headless(..) => { - false - } + WindowKind::Headless(..) => { + false } } } @@ -1031,33 +974,6 @@ impl WindowMethods for Window { true } - #[cfg(target_os = "linux")] - fn native_display(&self) -> NativeDisplay { - use x11::xlib; - unsafe { - match opts::get().render_api { - RenderApi::GL => { - match self.kind { - WindowKind::Window(ref window) => { - NativeDisplay::new(window.platform_display() as *mut xlib::Display) - } - WindowKind::Headless(..) => { - unreachable!() - } - } - }, - RenderApi::ES2 => { - NativeDisplay::new_egl_display() - } - } - } - } - - #[cfg(not(target_os = "linux"))] - fn native_display(&self) -> NativeDisplay { - NativeDisplay::new() - } - /// Helper function to handle keyboard events. fn handle_key(&self, ch: Option<char>, key: Key, mods: constellation_msg::KeyModifiers) { match (mods, ch, key) { |