diff options
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) { |