gfx: Use pipes to transfer layer buffers between the render supervisor function and the render callback

This commit is contained in:
Patrick Walton 2012-11-09 16:35:43 -08:00
parent dbcb85b724
commit a338c76bc6
2 changed files with 43 additions and 20 deletions

View file

@ -5,6 +5,7 @@ use opts::Opts;
use azure::AzFloat; use azure::AzFloat;
use azure::azure_hl::{B8G8R8A8, DrawTarget}; use azure::azure_hl::{B8G8R8A8, DrawTarget};
use core::libc::c_int; use core::libc::c_int;
use core::pipes::Chan;
use geom::matrix2d::Matrix2D; use geom::matrix2d::Matrix2D;
use geom::point::Point2D; use geom::point::Point2D;
use geom::rect::Rect; use geom::rect::Rect;
@ -17,6 +18,8 @@ pub struct RenderLayer {
size: Size2D<uint> size: Size2D<uint>
} }
type RenderFn = &fn(layer: &RenderLayer, buffer: LayerBuffer, return_buffer: Chan<LayerBuffer>);
/// Given a layer and a buffer, either reuses the buffer (if it's of the right size and format) /// Given a layer and a buffer, either reuses the buffer (if it's of the right size and format)
/// or creates a new buffer (if it's not of the appropriate size and format) and invokes the /// or creates a new buffer (if it's not of the appropriate size and format) and invokes the
/// given callback with the render layer and the buffer. Returns the resulting layer buffer (which /// given callback with the render layer and the buffer. Returns the resulting layer buffer (which
@ -24,11 +27,11 @@ pub struct RenderLayer {
pub fn render_layers(layer: &RenderLayer, pub fn render_layers(layer: &RenderLayer,
buffer_set: LayerBufferSet, buffer_set: LayerBufferSet,
opts: &Opts, opts: &Opts,
f: &fn(layer: &RenderLayer, buffer: &LayerBuffer) -> bool) -> LayerBufferSet { f: RenderFn) -> LayerBufferSet {
let mut buffers = match move buffer_set { LayerBufferSet { buffers: move b } => move b }; let mut buffers = match move buffer_set { LayerBufferSet { buffers: move b } => move b };
// FIXME: Try not to create a new array here. // FIXME: Try not to create a new array here.
let new_buffers = dvec::DVec(); let new_buffer_ports = dvec::DVec();
// Divide up the layer into tiles. // Divide up the layer into tiles.
let mut y = 0; let mut y = 0;
@ -100,14 +103,26 @@ pub fn render_layers(layer: &RenderLayer,
}; };
//} //}
let _ = f(layer, &buffer); // Create a port and channel pair to receive the new buffer.
new_buffers.push(move buffer); let (new_buffer_chan, new_buffer_port) = pipes::stream();
// Send the buffer to the child.
f(layer, move buffer, move new_buffer_chan);
// Enqueue the port.
new_buffer_ports.push(move new_buffer_port);
x += TILE_SIZE; x += TILE_SIZE;
} }
y += TILE_SIZE; y += TILE_SIZE;
} }
debug!("servo::gfx::render_layers: waiting on ports...");
let new_buffers = dvec::DVec();
for new_buffer_ports.each |new_buffer_port| {
new_buffers.push(new_buffer_port.recv());
}
return LayerBufferSet { buffers: move dvec::unwrap(move new_buffers) }; return LayerBufferSet { buffers: move dvec::unwrap(move new_buffers) };
} }

View file

@ -87,25 +87,33 @@ impl<C: Compositor Send> Renderer<C> {
let layer_buffer_set = layer_buffer_set_cell.take(); let layer_buffer_set = layer_buffer_set_cell.take();
let layer_buffer_set_channel = layer_buffer_set_channel_cell.take(); let layer_buffer_set_channel = layer_buffer_set_channel_cell.take();
let layer_buffer_set = for render_layers(&render_layer, let layer_buffer_set = do render_layers(&render_layer,
move layer_buffer_set, move layer_buffer_set,
&self.opts) &self.opts)
|render_layer, layer_buffer| { |render_layer, layer_buffer, buffer_chan| {
let ctx = RenderContext { {
canvas: layer_buffer, // Build the render context.
font_ctx: self.font_ctx, let ctx = RenderContext {
opts: &self.opts canvas: &layer_buffer,
}; font_ctx: self.font_ctx,
opts: &self.opts
};
// Apply the translation to render the tile we want. // Apply the translation to render the tile we want.
let matrix: Matrix2D<AzFloat> = Matrix2D::identity(); let matrix: Matrix2D<AzFloat> = Matrix2D::identity();
let matrix = matrix.translate(&-(layer_buffer.rect.origin.x as AzFloat), let matrix = matrix.translate(&-(layer_buffer.rect.origin.x as AzFloat),
&-(layer_buffer.rect.origin.y as AzFloat)); &-(layer_buffer.rect.origin.y as AzFloat));
layer_buffer.draw_target.set_transform(&matrix); layer_buffer.draw_target.set_transform(&matrix);
ctx.clear(); // Clear the buffer.
ctx.clear();
render_layer.display_list.draw_into_context(&ctx); // Draw the display list.
render_layer.display_list.draw_into_context(&ctx);
}
// Send back the buffer.
buffer_chan.send(move layer_buffer);
}; };
#debug("renderer: returning surface"); #debug("renderer: returning surface");