From 02ae7bdd34e4f0ef28fac2ae239b5d822fea4425 Mon Sep 17 00:00:00 2001 From: eschweic Date: Tue, 6 Aug 2013 16:28:35 -0700 Subject: [PATCH] Stop copying buffers when sending them to quadtrees --- src/components/gfx/render_context.rs | 2 +- src/components/gfx/render_task.rs | 29 ++++++++++++------- .../main/compositing/compositor_layer.rs | 15 +++++----- src/components/main/compositing/mod.rs | 7 ++--- src/components/msg/compositor_msg.rs | 7 ++--- 5 files changed, 34 insertions(+), 26 deletions(-) diff --git a/src/components/gfx/render_context.rs b/src/components/gfx/render_context.rs index e7b44a661e6..3468c2ede5a 100644 --- a/src/components/gfx/render_context.rs +++ b/src/components/gfx/render_context.rs @@ -19,7 +19,7 @@ use servo_net::image::base::Image; use extra::arc::Arc; pub struct RenderContext<'self> { - canvas: &'self LayerBuffer, + canvas: &'self ~LayerBuffer, font_ctx: @mut FontContext, opts: &'self Opts } diff --git a/src/components/gfx/render_task.rs b/src/components/gfx/render_task.rs index 1586c28b860..fa84bec3b73 100644 --- a/src/components/gfx/render_task.rs +++ b/src/components/gfx/render_task.rs @@ -35,7 +35,7 @@ pub struct RenderLayer { pub enum Msg { RenderMsg(RenderLayer), - ReRenderMsg(~[BufferRequest], f32, PipelineId, Epoch), + ReRenderMsg(~[BufferRequest], f32, Epoch), PaintPermissionGranted, PaintPermissionRevoked, ExitMsg(Chan<()>), @@ -91,7 +91,7 @@ struct RenderTask { /// Permission to send paint messages to the compositor paint_permission: bool, /// Cached copy of last layers rendered - last_paint_msg: Option<(arc::Arc, Size2D)>, + last_paint_msg: Option<~LayerBufferSet>, /// A counter for epoch messages epoch: Epoch, } @@ -147,9 +147,9 @@ impl RenderTask { } self.render_layer = Some(render_layer); } - ReRenderMsg(tiles, scale, id, epoch) => { + ReRenderMsg(tiles, scale, epoch) => { if self.epoch == epoch { - self.render(tiles, scale, id); + self.render(tiles, scale); } else { debug!("renderer epoch mismatch: %? != %?", self.epoch, epoch); } @@ -163,6 +163,16 @@ impl RenderTask { } None => {} } + // FIXME: This sends the last paint request, anticipating what + // the compositor will ask for. However, even if it sends the right + // tiles, the compositor still asks for them, and they will be + // re-rendered redundantly. + match self.last_paint_msg { + Some(ref layer_buffer_set) => { + self.compositor.paint(self.id, layer_buffer_set.clone()); + } + None => {} // Nothing to do + } } PaintPermissionRevoked => { self.paint_permission = false; @@ -175,7 +185,7 @@ impl RenderTask { } } - fn render(&mut self, tiles: ~[BufferRequest], scale: f32, id: PipelineId) { + fn render(&mut self, tiles: ~[BufferRequest], scale: f32) { let render_layer; match self.render_layer { Some(ref r_layer) => { @@ -196,7 +206,7 @@ impl RenderTask { let width = tile.screen_rect.size.width; let height = tile.screen_rect.size.height; - let buffer = LayerBuffer { + let buffer = ~LayerBuffer { draw_target: DrawTarget::new_with_fbo(self.opts.render_backend, self.share_gl_context, Size2D(width as i32, height as i32), @@ -240,17 +250,16 @@ impl RenderTask { } - let layer_buffer_set = LayerBufferSet { + let layer_buffer_set = ~LayerBufferSet { buffers: new_buffers, }; - let layer_buffer_set = arc::Arc::new(layer_buffer_set); debug!("render_task: returning surface"); if self.paint_permission { - self.compositor.paint(id, layer_buffer_set.clone(), self.epoch); + self.compositor.paint(self.id, layer_buffer_set.clone(), self.epoch); } debug!("caching paint msg"); - self.last_paint_msg = Some((layer_buffer_set, render_layer.size)); + self.last_paint_msg = Some(layer_buffer_set); self.compositor.set_render_state(IdleRenderState); } } diff --git a/src/components/main/compositing/compositor_layer.rs b/src/components/main/compositing/compositor_layer.rs index 5d11c5d2860..6c567994500 100644 --- a/src/components/main/compositing/compositor_layer.rs +++ b/src/components/main/compositing/compositor_layer.rs @@ -2,6 +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 std::cell::Cell; use geom::point::Point2D; use geom::size::Size2D; use geom::rect::Rect; @@ -210,7 +211,7 @@ impl CompositorLayer { let (request, r) = quadtree.get_tile_rects_page(rect, scale); redisplay = r; // workaround to make redisplay visible outside block if !request.is_empty() { - self.pipeline.render_chan.send(ReRenderMsg(request, scale, self.pipeline.id.clone(), self.epoch)); + self.pipeline.render_chan.send(ReRenderMsg(request, scale, self.epoch)); } } if redisplay { @@ -399,7 +400,8 @@ impl CompositorLayer { // Add LayerBuffers to the specified layer. Returns false if the layer is not found. // If the epoch of the message does not match the layer's epoch, the message is ignored. - pub fn add_buffers(&mut self, pipeline_id: PipelineId, new_buffers: &LayerBufferSet, epoch: Epoch) -> bool { + pub fn add_buffers(&mut self, pipeline_id: PipelineId, new_buffers: ~LayerBufferSet, epoch: Epoch) -> bool { + let cell = Cell::new(new_buffers); if self.pipeline.id == pipeline_id { if self.epoch != epoch { debug!("compositor epoch mismatch: %? != %?, id: %?", self.epoch, epoch, self.pipeline.id); @@ -408,22 +410,21 @@ impl CompositorLayer { } { // block here to prevent double mutable borrow of self let quadtree = match self.quadtree { - NoTree(_, _) => fail!("CompositorLayer: cannot get buffer request for %?, - no quadtree initialized", self.pipeline.id), + NoTree(_, _) => fail!("CompositorLayer: cannot add buffers, no quadtree initialized"), Tree(ref mut quadtree) => quadtree, }; - for buffer in new_buffers.buffers.iter() { + for buffer in cell.take().buffers.consume_rev_iter() { // TODO: This may return old buffers, which should be sent back to the renderer. quadtree.add_tile_pixel(buffer.screen_pos.origin.x, buffer.screen_pos.origin.y, - buffer.resolution, ~buffer.clone()); + buffer.resolution, buffer); } } self.build_layer_tree(); return true; } // ID does not match ours, so recurse on descendents (including hidden children). - self.children.mut_iter().map(|x| &mut x.child).any(|x| x.add_buffers(pipeline_id, new_buffers, epoch)) + self.children.mut_iter().map(|x| &mut x.child).any(|x| x.add_buffers(pipeline_id, cell.take(), epoch)) } // Deletes a specified sublayer, including hidden children. Returns false if the layer is not found. diff --git a/src/components/main/compositing/mod.rs b/src/components/main/compositing/mod.rs index a480ee76b39..4d96d9ebc82 100644 --- a/src/components/main/compositing/mod.rs +++ b/src/components/main/compositing/mod.rs @@ -40,7 +40,6 @@ use servo_util::time::ProfilerChan; use extra::future::from_value; use extra::time::precise_time_s; -use extra::arc; use constellation::SendableFrameTree; use compositing::compositor_layer::CompositorLayer; @@ -79,7 +78,7 @@ impl RenderListener for CompositorChan { port.recv() } - fn paint(&self, id: PipelineId, layer_buffer_set: arc::Arc, epoch: Epoch) { + fn paint(&self, id: PipelineId, layer_buffer_set: ~LayerBufferSet, epoch: Epoch) { self.chan.send(Paint(id, layer_buffer_set, epoch)) } @@ -148,7 +147,7 @@ pub enum Msg { InvalidateRect(PipelineId, Rect), /// Requests that the compositor paint the given layer buffer set for the given page size. - Paint(PipelineId, arc::Arc, Epoch), + Paint(PipelineId, ~LayerBufferSet, Epoch), /// Alerts the compositor to the current status of page loading. ChangeReadyState(ReadyState), /// Alerts the compositor to the current status of rendering. @@ -338,7 +337,7 @@ impl CompositorTask { match compositor_layer { Some(ref mut layer) => { - assert!(layer.add_buffers(id, new_layer_buffer_set.get(), epoch)); + assert!(layer.add_buffers(id, new_layer_buffer_set, epoch)); recomposite = true; } None => { diff --git a/src/components/msg/compositor_msg.rs b/src/components/msg/compositor_msg.rs index 949f418c317..d306dc99aa7 100644 --- a/src/components/msg/compositor_msg.rs +++ b/src/components/msg/compositor_msg.rs @@ -8,8 +8,6 @@ use geom::rect::Rect; use geom::size::Size2D; use constellation_msg::PipelineId; -use extra::arc; - #[deriving(Clone)] pub struct LayerBuffer { @@ -31,8 +29,9 @@ pub struct LayerBuffer { /// A set of layer buffers. This is an atomic unit used to switch between the front and back /// buffers. +#[deriving(Clone)] pub struct LayerBufferSet { - buffers: ~[LayerBuffer] + buffers: ~[~LayerBuffer] } /// The status of the renderer. @@ -72,7 +71,7 @@ pub trait RenderListener { fn set_layer_page_size(&self, PipelineId, Size2D, Epoch); fn set_layer_clip_rect(&self, PipelineId, Rect); fn delete_layer(&self, PipelineId); - fn paint(&self, id: PipelineId, layer_buffer_set: arc::Arc, Epoch); + fn paint(&self, id: PipelineId, layer_buffer_set: ~LayerBufferSet, Epoch); fn set_render_state(&self, render_state: RenderState); }