diff options
author | Cameron Zwarich <zwarich@mozilla.com> | 2014-07-28 20:51:39 -0700 |
---|---|---|
committer | Cameron Zwarich <zwarich@mozilla.com> | 2014-07-28 20:51:39 -0700 |
commit | 1f04ce807dcfbea62524d4a33c8432fa2e6f018f (patch) | |
tree | d9871a3175ad0fc21eb6c37572a17bb6bd6f3cda /src | |
parent | 32740b3012928034dfbf964970c03d775b25fdea (diff) | |
parent | 2a612fd9c5b4b33e2728fb1ac3009742910aadef (diff) | |
download | servo-1f04ce807dcfbea62524d4a33c8432fa2e6f018f.tar.gz servo-1f04ce807dcfbea62524d4a33c8432fa2e6f018f.zip |
Merge pull request #2945 from mrobinson/disentangle-scale
Untangle contents scale from rust-layers
Diffstat (limited to 'src')
-rw-r--r-- | src/components/compositing/compositor.rs | 96 | ||||
-rw-r--r-- | src/components/compositing/compositor_data.rs | 71 | ||||
-rw-r--r-- | src/components/compositing/events.rs | 29 | ||||
m--------- | src/support/layers/rust-layers | 0 |
4 files changed, 123 insertions, 73 deletions
diff --git a/src/components/compositing/compositor.rs b/src/components/compositing/compositor.rs index 8a357e059b4..11173d140f8 100644 --- a/src/components/compositing/compositor.rs +++ b/src/components/compositing/compositor.rs @@ -26,7 +26,7 @@ use geom::point::{Point2D, TypedPoint2D}; use geom::rect::Rect; use geom::size::TypedSize2D; use geom::scale_factor::ScaleFactor; -use gfx::render_task::ReRenderMsg; +use gfx::render_task::{RenderChan, ReRenderMsg, ReRenderRequest, UnusedBufferMsg}; use layers::layers::LayerBufferSet; use layers::rendergl; use layers::rendergl::RenderContext; @@ -397,7 +397,15 @@ impl IOCompositor { } } - fn create_or_update_root_layer(&mut self, layer_properties: LayerProperties) { + // rust-layers keeps everything in layer coordinates, so we must convert all rectangles + // from page coordinates into layer coordinates based on our current scale. + fn convert_page_rect_to_layer_coordinates(&self, page_rect: Rect<f32>) -> Rect<f32> { + page_rect * self.device_pixels_per_page_px().get() + } + + fn create_or_update_root_layer(&mut self, mut layer_properties: LayerProperties) { + layer_properties.rect = self.convert_page_rect_to_layer_coordinates(layer_properties.rect); + let need_new_root_layer = !self.update_layer_if_exists(layer_properties); if need_new_root_layer { let root_pipeline = match self.root_pipeline { @@ -433,7 +441,8 @@ impl IOCompositor { self.ask_for_tiles(); } - fn create_or_update_descendant_layer(&mut self, layer_properties: LayerProperties) { + fn create_or_update_descendant_layer(&mut self, mut layer_properties: LayerProperties) { + layer_properties.rect = self.convert_page_rect_to_layer_coordinates(layer_properties.rect); if !self.update_layer_if_exists(layer_properties) { self.create_descendant_layer(layer_properties); } @@ -483,6 +492,7 @@ impl IOCompositor { pipeline_id: PipelineId, layer_id: LayerId) { let page_window = self.page_window(); + let device_pixels_per_page_px = self.device_pixels_per_page_px(); let needs_recomposite = match self.scene.root { Some(ref mut root_layer) => { self.fragment_point.take().map_or(false, |fragment_point| { @@ -490,7 +500,8 @@ impl IOCompositor { pipeline_id, layer_id, fragment_point, - page_window) + page_window, + device_pixels_per_page_px) }) } None => fail!("Compositor: Tried to scroll to fragment without root layer."), @@ -502,14 +513,16 @@ impl IOCompositor { fn set_layer_clip_rect(&mut self, pipeline_id: PipelineId, layer_id: LayerId, - new_rect: Rect<f32>) { + new_rect_in_page_coordinates: Rect<f32>) { + let new_rect_in_layer_coordinates = + self.convert_page_rect_to_layer_coordinates(new_rect_in_page_coordinates); let should_ask_for_tiles = match self.scene.root { Some(ref root_layer) => { match CompositorData::find_layer_with_pipeline_and_layer_id(root_layer.clone(), pipeline_id, layer_id) { Some(ref layer) => { - *layer.bounds.borrow_mut() = new_rect; + *layer.bounds.borrow_mut() = new_rect_in_layer_coordinates; true } None => { @@ -569,10 +582,16 @@ impl IOCompositor { layer_id: LayerId, point: Point2D<f32>) { let page_window = self.page_window(); + let device_pixels_per_page_px = self.device_pixels_per_page_px(); let (ask, move): (bool, bool) = match self.scene.root { Some(ref layer) if layer.extra_data.borrow().pipeline.id == pipeline_id => { (true, - events::move(layer.clone(), pipeline_id, layer_id, point, page_window)) + events::move(layer.clone(), + pipeline_id, + layer_id, + point, + page_window, + device_pixels_per_page_px)) } Some(_) | None => { self.fragment_point = Some(point); @@ -704,12 +723,14 @@ impl IOCompositor { let page_cursor = cursor.as_f32() / scale; let page_window = self.page_window(); let mut scroll = false; + let device_pixels_per_page_px = self.device_pixels_per_page_px(); match self.scene.root { Some(ref mut layer) => { scroll = events::handle_scroll_event(layer.clone(), page_delta, page_cursor, - page_window) || scroll; + page_window, + device_pixels_per_page_px) || scroll; } None => { } } @@ -761,12 +782,14 @@ impl IOCompositor { let page_cursor = TypedPoint2D(-1f32, -1f32); // Make sure this hits the base layer let page_window = self.page_window(); + let device_pixels_per_page_px = self.device_pixels_per_page_px(); match self.scene.root { Some(ref mut layer) => { events::handle_scroll_event(layer.clone(), page_delta, page_cursor, - page_window); + page_window, + device_pixels_per_page_px); } None => { } } @@ -786,22 +809,55 @@ impl IOCompositor { /// Get BufferRequests from each layer. fn ask_for_tiles(&mut self) { let scale = self.device_pixels_per_page_px(); - let page_window = self.page_window(); let mut num_rerendermsgs_sent = 0; + let window_rect_in_device_pixels = Rect(Point2D(0f32, 0f32), + self.window_size.as_f32().to_untyped()); + match self.scene.root { - Some(ref layer) => { - let rect = Rect(Point2D(0f32, 0f32), page_window.to_untyped()); - let mut request_map = HashMap::new(); - let recomposite = - CompositorData::get_buffer_requests_recursively(&mut request_map, - layer.clone(), - rect, - scale.get()); - for (_pipeline_id, (chan, requests)) in request_map.move_iter() { + Some(ref mut layer) => { + let mut layers_and_requests = Vec::new(); + let mut unused_buffers = Vec::new(); + CompositorData::get_buffer_requests_recursively(&mut layers_and_requests, + &mut unused_buffers, + layer.clone(), + window_rect_in_device_pixels); + + // Return unused tiles first, so that they can be reused by any new BufferRequests. + let have_unused_buffers = unused_buffers.len() > 0; + self.recomposite = self.recomposite || have_unused_buffers; + if have_unused_buffers { + let message = UnusedBufferMsg(unused_buffers); + let _ = layer.extra_data.borrow().pipeline.render_chan.send_opt(message); + } + + // We want to batch requests for each pipeline to avoid race conditions + // when handling the resulting BufferRequest responses. + let mut pipeline_requests: + HashMap<PipelineId, (RenderChan, Vec<ReRenderRequest>)> = HashMap::new(); + for (layer, mut requests) in layers_and_requests.move_iter() { + let pipeline_id = layer.extra_data.borrow().pipeline.id; + let &(_, ref mut vec) = pipeline_requests.find_or_insert_with(pipeline_id, |_| { + (layer.extra_data.borrow().pipeline.render_chan.clone(), Vec::new()) + }); + + // All the BufferRequests are in layer/device coordinates, but the render task + // wants to know the page coordinates. We scale them before sending them. + for request in requests.mut_iter() { + request.page_rect = request.page_rect / scale.get(); + } + + vec.push(ReRenderRequest { + buffer_requests: requests, + scale: scale.get(), + layer_id: layer.extra_data.borrow().id, + epoch: layer.extra_data.borrow().epoch, + }); + } + + for (_pipeline_id, (chan, requests)) in pipeline_requests.move_iter() { num_rerendermsgs_sent += 1; let _ = chan.send_opt(ReRenderMsg(requests)); } - self.recomposite = self.recomposite || recomposite; } None => { } } diff --git a/src/components/compositing/compositor_data.rs b/src/components/compositing/compositor_data.rs index 1432b1dd3d6..e08694443b9 100644 --- a/src/components/compositing/compositor_data.rs +++ b/src/components/compositing/compositor_data.rs @@ -9,15 +9,15 @@ use pipeline::CompositionPipeline; use azure::azure_hl::Color; use geom::point::TypedPoint2D; use geom::rect::Rect; +use geom::scale_factor::ScaleFactor; use geom::size::{Size2D, TypedSize2D}; -use gfx::render_task::{ReRenderRequest, RenderChan, UnusedBufferMsg}; -use layers::layers::{Layer, LayerBufferSet}; +use gfx::render_task::UnusedBufferMsg; +use layers::layers::{BufferRequest, Layer, LayerBuffer, LayerBufferSet}; use layers::platform::surface::NativeSurfaceMethods; use servo_msg::compositor_msg::{Epoch, LayerId}; use servo_msg::compositor_msg::ScrollPolicy; use servo_msg::constellation_msg::PipelineId; use servo_util::geometry::PagePx; -use std::collections::hashmap::HashMap; use std::rc::Rc; pub struct CompositorData { @@ -83,40 +83,24 @@ impl CompositorData { // Given the current window size, determine which tiles need to be (re-)rendered and sends them // off the the appropriate renderer. Returns true if and only if the scene should be repainted. - pub fn get_buffer_requests_recursively(requests: &mut HashMap<PipelineId, - (RenderChan, - Vec<ReRenderRequest>)>, + pub fn get_buffer_requests_recursively(requests: &mut Vec<(Rc<Layer<CompositorData>>, + Vec<BufferRequest>)>, + unused_buffers: &mut Vec<Box<LayerBuffer>>, layer: Rc<Layer<CompositorData>>, - window_rect: Rect<f32>, - scale: f32) - -> bool { - let (request, unused) = layer.get_tile_rects_page(window_rect, scale); - let redisplay = !unused.is_empty(); - if redisplay { - // Send back unused tiles. - let msg = UnusedBufferMsg(unused); - let _ = layer.extra_data.borrow().pipeline.render_chan.send_opt(msg); - } + window_rect_in_device_pixels: Rect<f32>) { + let (request, unused) = layer.get_tile_rects_page(window_rect_in_device_pixels); + unused_buffers.push_all_move(unused); + if !request.is_empty() { - // Ask for tiles. - let pipeline_id = layer.extra_data.borrow().pipeline.id; - let msg = ReRenderRequest { - buffer_requests: request, - scale: scale, - layer_id: layer.extra_data.borrow().id, - epoch: layer.extra_data.borrow().epoch, - }; - let &(_, ref mut vec) = requests.find_or_insert_with(pipeline_id, |_| { - (layer.extra_data.borrow().pipeline.render_chan.clone(), Vec::new()) - }); - vec.push(msg); + requests.push((layer.clone(), request)); } - let get_child_buffer_request = |kid: &Rc<Layer<CompositorData>>| -> bool { - let mut new_rect = window_rect; - let offset = kid.extra_data.borrow().scroll_offset.to_untyped(); - new_rect.origin.x = new_rect.origin.x - offset.x; - new_rect.origin.y = new_rect.origin.y - offset.y; + for kid in layer.children().iter() { + let mut new_rect = window_rect_in_device_pixels; + let content_offset = kid.content_offset.borrow(); + new_rect.origin.x = new_rect.origin.x - content_offset.x; + new_rect.origin.y = new_rect.origin.y - content_offset.y; + match new_rect.intersection(&*kid.bounds.borrow()) { Some(new_rect) => { // Child layers act as if they are rendered at (0,0), so we @@ -125,17 +109,13 @@ impl CompositorData { let child_rect = Rect(new_rect.origin.sub(&kid.bounds.borrow().origin), new_rect.size); CompositorData::get_buffer_requests_recursively(requests, + unused_buffers, kid.clone(), - child_rect, - scale) - } - None => { - false // Layer is offscreen + child_rect); } + None => {} } }; - - layer.children().iter().map(get_child_buffer_request).any(|b| b) || redisplay } pub fn update_layer(layer: Rc<Layer<CompositorData>>, layer_properties: LayerProperties) { @@ -146,12 +126,15 @@ impl CompositorData { layer.contents_changed(); // 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. + // cursor position to make sure the scroll isn't propagated downwards. The + // scale factor does not matter here since we are scrolling to 0 offset and + // 0 * n == 0. let size: TypedSize2D<PagePx, f32> = Size2D::from_untyped(&layer.bounds.borrow().size); events::handle_scroll_event(layer.clone(), - TypedPoint2D(0f32, 0f32), - TypedPoint2D(-1f32, -1f32), - size); + TypedPoint2D(0f32, 0f32), + TypedPoint2D(-1f32, -1f32), + size, + ScaleFactor(1.0)); } pub fn find_layer_with_pipeline_and_layer_id(layer: Rc<Layer<CompositorData>>, diff --git a/src/components/compositing/events.rs b/src/components/compositing/events.rs index 5aa202d2bf0..8ded49a5477 100644 --- a/src/components/compositing/events.rs +++ b/src/components/compositing/events.rs @@ -10,13 +10,14 @@ use geom::length::Length; use geom::matrix::identity; use geom::point::{Point2D, TypedPoint2D}; use geom::rect::{Rect, TypedRect}; +use geom::scale_factor::ScaleFactor; use geom::size::TypedSize2D; use layers::layers::Layer; use script::dom::event::{ClickEvent, MouseDownEvent, MouseMoveEvent, MouseUpEvent}; use script::script_task::{ScriptChan, SendEventMsg}; use servo_msg::compositor_msg::{FixedPosition, LayerId}; use servo_msg::constellation_msg::PipelineId; -use servo_util::geometry::PagePx; +use servo_util::geometry::{DevicePixel, PagePx}; use std::rc::Rc; trait Clampable { @@ -44,7 +45,8 @@ impl Clampable for f32 { pub fn handle_scroll_event(layer: Rc<Layer<CompositorData>>, delta: TypedPoint2D<PagePx, f32>, cursor: TypedPoint2D<PagePx, f32>, - window_size: TypedSize2D<PagePx, f32>) + window_size: TypedSize2D<PagePx, f32>, + page_to_device_pixels_scale: ScaleFactor<PagePx, DevicePixel, f32>) -> bool { // If this layer doesn't want scroll events, neither it nor its children can handle scroll // events. @@ -60,7 +62,8 @@ pub fn handle_scroll_event(layer: Rc<Layer<CompositorData>>, handle_scroll_event(child.clone(), delta, cursor - rect.origin, - rect.size) { + rect.size, + page_to_device_pixels_scale) { return true } } @@ -86,13 +89,14 @@ pub fn handle_scroll_event(layer: Rc<Layer<CompositorData>>, } let offset = layer.extra_data.borrow().scroll_offset.clone(); - scroll(layer.clone(), offset) + scroll(layer.clone(), offset, page_to_device_pixels_scale) } /// Actually scrolls the descendants of a layer that scroll. This is called by /// `handle_scroll_event` above when it determines that a layer wants to scroll. fn scroll(layer: Rc<Layer<CompositorData>>, - scroll_offset: TypedPoint2D<PagePx, f32>) + scroll_offset: TypedPoint2D<PagePx, f32>, + page_to_device_pixels_scale: ScaleFactor<PagePx, DevicePixel, f32>) -> bool { let mut result = false; @@ -103,12 +107,13 @@ fn scroll(layer: Rc<Layer<CompositorData>>, let scroll_offset = layer.extra_data.borrow().scroll_offset.clone(); *layer.transform.borrow_mut() = identity().translate(scroll_offset.x.get(), scroll_offset.y.get(), 0.0); + *layer.content_offset.borrow_mut() = (scroll_offset * page_to_device_pixels_scale).to_untyped(); result = true } for child in layer.children().iter() { - result = scroll(child.clone(), scroll_offset) || result; + result = scroll(child.clone(), scroll_offset, page_to_device_pixels_scale) || result; } result @@ -149,13 +154,19 @@ pub fn move(layer: Rc<Layer<CompositorData>>, pipeline_id: PipelineId, layer_id: LayerId, origin: Point2D<f32>, - window_size: TypedSize2D<PagePx, f32>) + window_size: TypedSize2D<PagePx, f32>, + page_to_device_pixels_scale: ScaleFactor<PagePx, DevicePixel, f32>) -> bool { // Search children for the right layer to move. if layer.extra_data.borrow().pipeline.id != pipeline_id || layer.extra_data.borrow().id != layer_id { return layer.children().iter().any(|kid| { - move(kid.clone(), pipeline_id, layer_id, origin, window_size) + move(kid.clone(), + pipeline_id, + layer_id, + origin, + window_size, + page_to_device_pixels_scale) }); } @@ -183,5 +194,5 @@ pub fn move(layer: Rc<Layer<CompositorData>>, } let offset = layer.extra_data.borrow().scroll_offset.clone(); - scroll(layer.clone(), offset) + scroll(layer.clone(), offset, page_to_device_pixels_scale) } diff --git a/src/support/layers/rust-layers b/src/support/layers/rust-layers -Subproject 10e34dbdf9b9d4a437fedc412d37f13a42182e4 +Subproject 5f3dc4cc940c0f807171e26411e18ea1ee52836 |