From 8993434c39bd64efded22ed60607859239c3f3ed Mon Sep 17 00:00:00 2001 From: eschweic Date: Thu, 8 Aug 2013 15:22:02 -0700 Subject: [PATCH] Better layer resize methods --- src/components/gfx/render_task.rs | 4 +- .../main/compositing/compositor_layer.rs | 60 ++++++++++++++----- src/components/main/compositing/mod.rs | 35 ++++++++--- src/components/main/constellation.rs | 4 +- src/components/msg/compositor_msg.rs | 3 +- 5 files changed, 76 insertions(+), 30 deletions(-) diff --git a/src/components/gfx/render_task.rs b/src/components/gfx/render_task.rs index 8b3d275dbb1..3d507531145 100644 --- a/src/components/gfx/render_task.rs +++ b/src/components/gfx/render_task.rs @@ -136,7 +136,7 @@ impl RenderTask { match self.port.recv() { RenderMsg(render_layer) => { if self.paint_permission { - self.compositor.resize_layer(self.id, render_layer.size); + self.compositor.set_layer_page_size(self.id, render_layer.size); } self.render_layer = Some(render_layer); } @@ -147,7 +147,7 @@ impl RenderTask { self.paint_permission = true; match self.render_layer { Some(ref render_layer) => { - self.compositor.resize_layer(self.id, render_layer.size); + self.compositor.set_layer_page_size(self.id, render_layer.size); } None => {} } diff --git a/src/components/main/compositing/compositor_layer.rs b/src/components/main/compositing/compositor_layer.rs index 881a781eb26..cfe868bf4d4 100644 --- a/src/components/main/compositing/compositor_layer.rs +++ b/src/components/main/compositing/compositor_layer.rs @@ -62,7 +62,8 @@ enum MaybeQuadtree { } impl CompositorLayer { - /// Creates a new CompositorLayer without a page size that is initially hidden. + /// Creates a new CompositorLayer with an optional page size. If no page size is given, + /// the layer is initially hidden and initialized without a quadtree. pub fn new(pipeline: Pipeline, page_size: Option>, tile_size: uint, max_mem: Option) -> CompositorLayer { CompositorLayer { @@ -82,6 +83,7 @@ impl CompositorLayer { } } + /// Constructs a CompositorLayer tree from a frame tree. pub fn from_frame_tree(frame_tree: SendableFrameTree, tile_size: uint, max_mem: Option) -> CompositorLayer { @@ -225,6 +227,7 @@ impl CompositorLayer { // Move the sublayer to an absolute position in page coordinates relative to its parent, // and clip the layer to the specified size in page coordinates. + // If the layer is hidden and has a defined page size, unhide it. // This method returns false if the specified layer is not found. pub fn set_clipping_rect(&mut self, pipeline_id: PipelineId, new_rect: Rect) -> bool { for child_node in self.children.iter() { @@ -236,6 +239,10 @@ impl CompositorLayer { new_rect.origin.y, 0.0)); con.scissor = Some(new_rect); + // If possible, unhide child + if child_node.child.hidden && child_node.child.page_size.is_some() { + child_node.child.hidden = false; + } return true; } @@ -244,7 +251,8 @@ impl CompositorLayer { } - // Called when the layer changes size (NOT as a result of a zoom event). + // Set the layer's page size. This signals that the renderer is ready for BufferRequests. + // If the layer is hidden and has a defined clipping rect, unhide it. // This method returns false if the specified layer is not found. pub fn resize(&mut self, pipeline_id: PipelineId, new_size: Size2D, window_size: Size2D) -> bool { if self.pipeline.id == pipeline_id { @@ -257,27 +265,47 @@ impl CompositorLayer { tile_size, max_mem)), } - // Call scroll for bounds checking of the page shrunk. Use (-1, -1) as the cursor position + // 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.scroll(Point2D(0f32, 0f32), Point2D(-1f32, -1f32), window_size); + self.hidden = false; + return true; + } + self.resize_helper(pipeline_id, new_size) + } + + // A helper method to resize sublayers. + fn resize_helper(&mut self, pipeline_id: PipelineId, new_size: Size2D) -> bool { + for self.children.mut_iter().advance |child_node| { + if pipeline_id != child_node.child.pipeline.id { + loop; + } + let child = &mut child_node.child; + child.page_size = Some(new_size); + // TODO: might get buffers back here + match child.quadtree { + Tree(ref mut quadtree) => quadtree.resize(new_size.width as uint, new_size.height as uint), + NoTree(tile_size, max_mem) => child.quadtree = Tree(Quadtree::new(new_size.width as uint, + new_size.height as uint, + tile_size, + max_mem)), + } + match child_node.container.scissor { + Some(scissor) => { + // 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. + child.scroll(Point2D(0f32, 0f32), Point2D(-1f32, -1f32), scissor.size); + child.hidden = false; + } + None => {} // Nothing to do + } return true; } // ID does not match ours, so recurse on descendents (including hidden children) - let transform = |x: &mut CompositorLayerChild| -> bool { - match x.container.scissor { - Some(scissor) => { - x.child.resize(pipeline_id, new_size, scissor.size) - } - None => { - fail!("CompositorLayer: Child layer not clipped"); - } - } - }; - - self.children.mut_iter().any(transform) + self.children.mut_iter().transform(|x| &mut x.child).any(|x| x.resize_helper(pipeline_id, new_size)) } - + // Collect buffers from the quadtree. This method IS NOT recursive, so child CompositorLayers // are not rebuilt directly from this method. pub fn build_layer_tree(&mut self) { diff --git a/src/components/main/compositing/mod.rs b/src/components/main/compositing/mod.rs index fe430853567..2a17b8128ca 100644 --- a/src/components/main/compositing/mod.rs +++ b/src/components/main/compositing/mod.rs @@ -87,10 +87,18 @@ impl RenderListener for CompositorChan { let Size2D { width, height } = page_size; self.chan.send(NewLayer(id, Size2D(width as f32, height as f32))) } - fn resize_layer(&self, id: PipelineId, page_size: Size2D) { + fn set_layer_page_size(&self, id: PipelineId, page_size: Size2D) { let Size2D { width, height } = page_size; - self.chan.send(ResizeLayer(id, Size2D(width as f32, height as f32))) + self.chan.send(SetLayerPageSize(id, Size2D(width as f32, height as f32))) } + fn set_layer_clip_rect(&self, id: PipelineId, new_rect: Rect) { + let new_rect = Rect(Point2D(new_rect.origin.x as f32, + new_rect.origin.y as f32), + Size2D(new_rect.size.width as f32, + new_rect.size.height as f32)); + self.chan.send(SetLayerClipRect(id, new_rect)) + } + fn delete_layer(&self, id: PipelineId) { self.chan.send(DeleteLayer(id)) } @@ -131,8 +139,10 @@ pub enum Msg { // TODO: Attach epochs to these messages /// Alerts the compositor that there is a new layer to be rendered. NewLayer(PipelineId, Size2D), - /// Alerts the compositor that the specified layer has changed size. - ResizeLayer(PipelineId, Size2D), + /// Alerts the compositor that the specified layer's page has changed size. + SetLayerPageSize(PipelineId, Size2D), + /// Alerts the compositor that the specified layer's clipping rect has changed. + SetLayerClipRect(PipelineId, Rect), /// Alerts the compositor that the specified layer has been deleted. DeleteLayer(PipelineId), /// Invalidate a rect for a given layer @@ -288,15 +298,22 @@ impl CompositorTask { ask_for_tiles(); } - ResizeLayer(id, new_size) => { + SetLayerPageSize(id, new_size) => { match compositor_layer { Some(ref mut layer) => { let page_window = Size2D(window_size.width as f32 / world_zoom, window_size.height as f32 / world_zoom); - assert!(layer.resize(id, - Size2D(new_size.width as f32, - new_size.height as f32), - page_window)); + assert!(layer.resize(id, new_size, page_window)); + ask_for_tiles(); + } + None => {} + } + } + + SetLayerClipRect(id, new_rect) => { + match compositor_layer { + Some(ref mut layer) => { + assert!(layer.set_clipping_rect(id, new_rect)); ask_for_tiles(); } None => {} diff --git a/src/components/main/constellation.rs b/src/components/main/constellation.rs index 518a955cbc3..a9d54cfc320 100644 --- a/src/components/main/constellation.rs +++ b/src/components/main/constellation.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use compositing::{CompositorChan, SetIds, ResizeLayer}; +use compositing::{CompositorChan, SetIds, SetLayerClipRect}; use script::dom::event::ResizeEvent; use std::cell::Cell; @@ -412,7 +412,7 @@ impl Constellation { pipeline.script_chan.send(SendEventMsg(pipeline.id.clone(), ResizeEvent(width as uint, height as uint))); - self.compositor_chan.send(ResizeLayer(pipeline.id, rect.size)); + self.compositor_chan.send(SetLayerClipRect(pipeline.id, rect)); already_sent.insert(pipeline.id.clone()); break; } diff --git a/src/components/msg/compositor_msg.rs b/src/components/msg/compositor_msg.rs index f1337c94301..284b14099b1 100644 --- a/src/components/msg/compositor_msg.rs +++ b/src/components/msg/compositor_msg.rs @@ -59,7 +59,8 @@ pub enum ReadyState { pub trait RenderListener { fn get_gl_context(&self) -> AzGLContext; fn new_layer(&self, PipelineId, Size2D); - fn resize_layer(&self, PipelineId, Size2D); + fn set_layer_page_size(&self, PipelineId, Size2D); + fn set_layer_clip_rect(&self, PipelineId, Rect); fn delete_layer(&self, PipelineId); fn paint(&self, id: PipelineId, layer_buffer_set: arc::Arc); fn set_render_state(&self, render_state: RenderState);