mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +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;
|
use extra::arc::Arc;
|
||||||
|
|
||||||
pub struct RenderContext<'self> {
|
pub struct RenderContext<'self> {
|
||||||
canvas: &'self LayerBuffer,
|
canvas: &'self ~LayerBuffer,
|
||||||
font_ctx: @mut FontContext,
|
font_ctx: @mut FontContext,
|
||||||
opts: &'self Opts
|
opts: &'self Opts
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ pub struct RenderLayer<T> {
|
||||||
|
|
||||||
pub enum Msg<T> {
|
pub enum Msg<T> {
|
||||||
RenderMsg(RenderLayer<T>),
|
RenderMsg(RenderLayer<T>),
|
||||||
ReRenderMsg(~[BufferRequest], f32, PipelineId, Epoch),
|
ReRenderMsg(~[BufferRequest], f32, Epoch),
|
||||||
PaintPermissionGranted,
|
PaintPermissionGranted,
|
||||||
PaintPermissionRevoked,
|
PaintPermissionRevoked,
|
||||||
ExitMsg(Chan<()>),
|
ExitMsg(Chan<()>),
|
||||||
|
@ -91,7 +91,7 @@ struct RenderTask<C,T> {
|
||||||
/// Permission to send paint messages to the compositor
|
/// Permission to send paint messages to the compositor
|
||||||
paint_permission: bool,
|
paint_permission: bool,
|
||||||
/// Cached copy of last layers rendered
|
/// 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
|
/// A counter for epoch messages
|
||||||
epoch: Epoch,
|
epoch: Epoch,
|
||||||
}
|
}
|
||||||
|
@ -147,9 +147,9 @@ impl<C: RenderListener + Send,T:Send+Freeze> RenderTask<C,T> {
|
||||||
}
|
}
|
||||||
self.render_layer = Some(render_layer);
|
self.render_layer = Some(render_layer);
|
||||||
}
|
}
|
||||||
ReRenderMsg(tiles, scale, id, epoch) => {
|
ReRenderMsg(tiles, scale, epoch) => {
|
||||||
if self.epoch == epoch {
|
if self.epoch == epoch {
|
||||||
self.render(tiles, scale, id);
|
self.render(tiles, scale);
|
||||||
} else {
|
} else {
|
||||||
debug!("renderer epoch mismatch: %? != %?", self.epoch, epoch);
|
debug!("renderer epoch mismatch: %? != %?", self.epoch, epoch);
|
||||||
}
|
}
|
||||||
|
@ -163,6 +163,16 @@ impl<C: RenderListener + Send,T:Send+Freeze> RenderTask<C,T> {
|
||||||
}
|
}
|
||||||
None => {}
|
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 => {
|
PaintPermissionRevoked => {
|
||||||
self.paint_permission = false;
|
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;
|
let render_layer;
|
||||||
match self.render_layer {
|
match self.render_layer {
|
||||||
Some(ref r_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 width = tile.screen_rect.size.width;
|
||||||
let height = tile.screen_rect.size.height;
|
let height = tile.screen_rect.size.height;
|
||||||
|
|
||||||
let buffer = LayerBuffer {
|
let buffer = ~LayerBuffer {
|
||||||
draw_target: DrawTarget::new_with_fbo(self.opts.render_backend,
|
draw_target: DrawTarget::new_with_fbo(self.opts.render_backend,
|
||||||
self.share_gl_context,
|
self.share_gl_context,
|
||||||
Size2D(width as i32, height as i32),
|
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,
|
buffers: new_buffers,
|
||||||
};
|
};
|
||||||
let layer_buffer_set = arc::Arc::new(layer_buffer_set);
|
|
||||||
|
|
||||||
debug!("render_task: returning surface");
|
debug!("render_task: returning surface");
|
||||||
if self.paint_permission {
|
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");
|
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);
|
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
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use std::cell::Cell;
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
|
@ -210,7 +211,7 @@ impl CompositorLayer {
|
||||||
let (request, r) = quadtree.get_tile_rects_page(rect, scale);
|
let (request, r) = quadtree.get_tile_rects_page(rect, scale);
|
||||||
redisplay = r; // workaround to make redisplay visible outside block
|
redisplay = r; // workaround to make redisplay visible outside block
|
||||||
if !request.is_empty() {
|
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 {
|
if redisplay {
|
||||||
|
@ -399,7 +400,8 @@ impl CompositorLayer {
|
||||||
|
|
||||||
// Add LayerBuffers to the specified layer. Returns false if the layer is not found.
|
// 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.
|
// 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.pipeline.id == pipeline_id {
|
||||||
if self.epoch != epoch {
|
if self.epoch != epoch {
|
||||||
debug!("compositor epoch mismatch: %? != %?, id: %?", self.epoch, epoch, self.pipeline.id);
|
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
|
{ // block here to prevent double mutable borrow of self
|
||||||
let quadtree = match self.quadtree {
|
let quadtree = match self.quadtree {
|
||||||
NoTree(_, _) => fail!("CompositorLayer: cannot get buffer request for %?,
|
NoTree(_, _) => fail!("CompositorLayer: cannot add buffers, no quadtree initialized"),
|
||||||
no quadtree initialized", self.pipeline.id),
|
|
||||||
Tree(ref mut quadtree) => quadtree,
|
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.
|
// 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,
|
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();
|
self.build_layer_tree();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// ID does not match ours, so recurse on descendents (including hidden children).
|
// 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.
|
// 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::future::from_value;
|
||||||
use extra::time::precise_time_s;
|
use extra::time::precise_time_s;
|
||||||
use extra::arc;
|
|
||||||
|
|
||||||
use constellation::SendableFrameTree;
|
use constellation::SendableFrameTree;
|
||||||
use compositing::compositor_layer::CompositorLayer;
|
use compositing::compositor_layer::CompositorLayer;
|
||||||
|
@ -79,7 +78,7 @@ impl RenderListener for CompositorChan {
|
||||||
port.recv()
|
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))
|
self.chan.send(Paint(id, layer_buffer_set, epoch))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,7 +147,7 @@ pub enum Msg {
|
||||||
InvalidateRect(PipelineId, Rect<uint>),
|
InvalidateRect(PipelineId, Rect<uint>),
|
||||||
|
|
||||||
/// Requests that the compositor paint the given layer buffer set for the given page size.
|
/// 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.
|
/// Alerts the compositor to the current status of page loading.
|
||||||
ChangeReadyState(ReadyState),
|
ChangeReadyState(ReadyState),
|
||||||
/// Alerts the compositor to the current status of rendering.
|
/// Alerts the compositor to the current status of rendering.
|
||||||
|
@ -338,7 +337,7 @@ impl CompositorTask {
|
||||||
|
|
||||||
match compositor_layer {
|
match compositor_layer {
|
||||||
Some(ref mut 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;
|
recomposite = true;
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
|
|
@ -8,8 +8,6 @@ use geom::rect::Rect;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
|
|
||||||
use constellation_msg::PipelineId;
|
use constellation_msg::PipelineId;
|
||||||
use extra::arc;
|
|
||||||
|
|
||||||
|
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
pub struct LayerBuffer {
|
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
|
/// A set of layer buffers. This is an atomic unit used to switch between the front and back
|
||||||
/// buffers.
|
/// buffers.
|
||||||
|
#[deriving(Clone)]
|
||||||
pub struct LayerBufferSet {
|
pub struct LayerBufferSet {
|
||||||
buffers: ~[LayerBuffer]
|
buffers: ~[~LayerBuffer]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The status of the renderer.
|
/// 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_page_size(&self, PipelineId, Size2D<uint>, Epoch);
|
||||||
fn set_layer_clip_rect(&self, PipelineId, Rect<uint>);
|
fn set_layer_clip_rect(&self, PipelineId, Rect<uint>);
|
||||||
fn delete_layer(&self, PipelineId);
|
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);
|
fn set_render_state(&self, render_state: RenderState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue