From fb51bc79ad4e3eef03cb1e052c8fce6f0d5b6c9a Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Fri, 25 Jul 2014 08:21:27 -0700 Subject: [PATCH] Move BufferRequest request code from CompositorData into Compositor Once we remove the integration with Servo's layer scaling, this will make it easier pull requesting buffers into rust-layers. --- src/components/compositing/compositor.rs | 45 ++++++++++++++---- src/components/compositing/compositor_data.rs | 46 ++++++------------- 2 files changed, 49 insertions(+), 42 deletions(-) diff --git a/src/components/compositing/compositor.rs b/src/components/compositing/compositor.rs index 8a357e059b4..8c9cb0b4640 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; @@ -791,17 +791,44 @@ impl IOCompositor { 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() { + 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(), + rect, + scale.get()); + + // 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)> = HashMap::new(); + for (layer, 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()) + }); + + 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..0f4072d133e 100644 --- a/src/components/compositing/compositor_data.rs +++ b/src/components/compositing/compositor_data.rs @@ -10,14 +10,13 @@ use azure::azure_hl::Color; use geom::point::TypedPoint2D; use geom::rect::Rect; 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,36 +82,20 @@ 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)>, + pub fn get_buffer_requests_recursively(requests: &mut Vec<(Rc>, + Vec)>, + unused_buffers: &mut Vec>, layer: Rc>, window_rect: Rect, - scale: f32) - -> bool { + scale: f32) { 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); - } + 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>| -> bool { + for kid in layer.children().iter() { 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; @@ -125,17 +108,14 @@ 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 + scale); } + None => {} } }; - - layer.children().iter().map(get_child_buffer_request).any(|b| b) || redisplay } pub fn update_layer(layer: Rc>, layer_properties: LayerProperties) {