mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
Stop copying buffers when sending them to quadtrees
This commit is contained in:
parent
abccd82eba
commit
02ae7bdd34
5 changed files with 34 additions and 26 deletions
|
@ -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
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ pub struct RenderLayer<T> {
|
|||
|
||||
pub enum Msg<T> {
|
||||
RenderMsg(RenderLayer<T>),
|
||||
ReRenderMsg(~[BufferRequest], f32, PipelineId, Epoch),
|
||||
ReRenderMsg(~[BufferRequest], f32, Epoch),
|
||||
PaintPermissionGranted,
|
||||
PaintPermissionRevoked,
|
||||
ExitMsg(Chan<()>),
|
||||
|
@ -91,7 +91,7 @@ struct RenderTask<C,T> {
|
|||
/// Permission to send paint messages to the compositor
|
||||
paint_permission: bool,
|
||||
/// Cached copy of last layers rendered
|
||||
last_paint_msg: Option<(arc::Arc<LayerBufferSet>, Size2D<uint>)>,
|
||||
last_paint_msg: Option<~LayerBufferSet>,
|
||||
/// A counter for epoch messages
|
||||
epoch: Epoch,
|
||||
}
|
||||
|
@ -147,9 +147,9 @@ impl<C: RenderListener + Send,T:Send+Freeze> RenderTask<C,T> {
|
|||
}
|
||||
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<C: RenderListener + Send,T:Send+Freeze> RenderTask<C,T> {
|
|||
}
|
||||
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<C: RenderListener + Send,T:Send+Freeze> RenderTask<C,T> {
|
|||
}
|
||||
}
|
||||
|
||||
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<C: RenderListener + Send,T:Send+Freeze> RenderTask<C,T> {
|
|||
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<C: RenderListener + Send,T:Send+Freeze> RenderTask<C,T> {
|
|||
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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<LayerBufferSet>, 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<uint>),
|
||||
|
||||
/// Requests that the compositor paint the given layer buffer set for the given page size.
|
||||
Paint(PipelineId, arc::Arc<LayerBufferSet>, 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 => {
|
||||
|
|
|
@ -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<uint>, Epoch);
|
||||
fn set_layer_clip_rect(&self, PipelineId, Rect<uint>);
|
||||
fn delete_layer(&self, PipelineId);
|
||||
fn paint(&self, id: PipelineId, layer_buffer_set: arc::Arc<LayerBufferSet>, Epoch);
|
||||
fn paint(&self, id: PipelineId, layer_buffer_set: ~LayerBufferSet, Epoch);
|
||||
fn set_render_state(&self, render_state: RenderState);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue