gfx: Implement tiled rendering

This commit is contained in:
Patrick Walton 2012-10-25 20:36:34 -07:00
parent 01e9c30b80
commit 7c029a322d
4 changed files with 79 additions and 37 deletions

View file

@ -78,7 +78,8 @@ impl RenderContext {
fn clear(&self) {
let pattern = ColorPattern(Color(1f as AzFloat, 1f as AzFloat, 1f as AzFloat, 1f as AzFloat));
let rect = Rect(Point2D(0 as AzFloat, 0 as AzFloat),
let rect = Rect(Point2D(self.canvas.rect.origin.x as AzFloat,
self.canvas.rect.origin.y as AzFloat),
Size2D(self.canvas.rect.size.width as AzFloat,
self.canvas.rect.size.height as AzFloat));
self.canvas.draw_target.fill_rect(&rect, &pattern);

View file

@ -11,6 +11,8 @@ use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;
const TILE_SIZE: uint = 512;
pub struct RenderLayer {
display_list: DisplayList,
size: Size2D<uint>
@ -24,36 +26,61 @@ pub fn render_layers(layer: &RenderLayer,
buffer_set: LayerBufferSet,
f: &fn(layer: &RenderLayer, buffer: &LayerBuffer) -> bool) -> LayerBufferSet {
let mut buffers = match move buffer_set { LayerBufferSet { buffers: move b } => move b };
let mut buffer = buffers.pop();
if buffer.rect.size != layer.size {
// Create a new buffer.
// Round the width up the nearest 32 pixels for DMA on the Mac.
let mut stride = layer.size.width;
if stride % 32 != 0 {
stride = (stride & !(32 - 1)) + 32;
// FIXME: Try not to create a new array here.
let new_buffers = dvec::DVec();
// Divide up the layer into tiles.
let mut y = 0;
while y < layer.size.height {
let mut x = 0;
while x < layer.size.width {
// Figure out the dimension of this tile.
let right = uint::min(x + TILE_SIZE, layer.size.width);
let bottom = uint::min(y + TILE_SIZE, layer.size.height);
let width = right - x;
let height = bottom - y;
// Round the width up the nearest 32 pixels for DMA on the Mac.
let mut stride = width;
if stride % 32 != 0 {
stride = (stride & !(32 - 1)) + 32;
}
assert stride % 32 == 0;
assert stride >= width;
let tile_rect = Rect(Point2D(x, y), Size2D(width, height));
let buffer;
// FIXME: Try harder to search for a matching tile.
// FIXME: Don't use shift; it's bad for perf. Maybe reverse and pop.
if buffers.len() != 0 && buffers[0].rect == tile_rect {
debug!("reusing tile, (%u, %u)", x, y);
buffer = buffers.shift();
} else {
// Create a new buffer.
debug!("creating tile, (%u, %u)", x, y);
let cairo_surface = ImageSurface(
CAIRO_FORMAT_RGB24, stride as c_int, height as c_int);
let draw_target = DrawTarget(&cairo_surface);
buffer = LayerBuffer {
cairo_surface: move cairo_surface,
draw_target: move draw_target,
rect: tile_rect,
stride: stride
};
}
let _ = f(layer, &buffer);
new_buffers.push(move buffer);
x += TILE_SIZE;
}
assert stride % 32 == 0;
assert stride >= layer.size.width;
let cairo_surface = ImageSurface(CAIRO_FORMAT_RGB24,
stride as c_int,
layer.size.height as c_int);
let draw_target = DrawTarget(&cairo_surface);
/*let matrix: Matrix2D<AzFloat> = Matrix2D::identity();
let matrix = matrix.translate(&(-32 as AzFloat), &(0 as AzFloat));
draw_target.set_transform(&matrix);*/
buffer = LayerBuffer {
cairo_surface: move cairo_surface,
draw_target: move draw_target,
rect: Rect(Point2D(0u, 0u), copy layer.size),
stride: stride
};
y += TILE_SIZE;
}
let _ = f(layer, &buffer);
return LayerBufferSet { buffers: ~[ move buffer ] };
return LayerBufferSet { buffers: move dvec::unwrap(move new_buffers) };
}

View file

@ -1,18 +1,20 @@
use au = gfx::geometry;
use au::Au;
use azure::AzFloat;
use comm::*;
use compositor::{Compositor, LayerBufferSet};
use dl = display_list;
use mod gfx::render_layers;
use render_layers::render_layers;
use geom::matrix2d::Matrix2D;
use gfx::render_layers::RenderLayer;
use libc::size_t;
use libc::types::common::c99::uint16_t;
use mod gfx::render_layers;
use pipes::{Port, Chan};
use platform::osmain;
use render_context::RenderContext;
use render_layers::render_layers;
use std::cell::Cell;
use text::font_cache::FontCache;
use render_context::RenderContext;
pub enum Msg {
RenderMsg(RenderLayer),
@ -91,7 +93,14 @@ impl<C: Compositor Send> Renderer<C> {
font_cache: self.font_cache
};
// Apply the translation to render the tile we want.
let matrix: Matrix2D<AzFloat> = Matrix2D::identity();
let matrix = matrix.translate(&-(layer_buffer.rect.origin.x as AzFloat),
&-(layer_buffer.rect.origin.y as AzFloat));
layer_buffer.draw_target.set_transform(&matrix);
ctx.clear();
render_layer.display_list.draw_into_context(&ctx);
};

View file

@ -116,7 +116,7 @@ fn mainloop(mode: Mode, po: comm::Port<Msg>, dom_event_chan: pipes::SharedChan<E
resize_rate_limiter.check_resize_response();
// Handle messages
#debug("osmain: peeking");
//#debug("osmain: peeking");
while po.peek() {
match po.recv() {
AddKeyHandler(move key_ch) => key_handlers.push(move key_ch),
@ -135,8 +135,12 @@ fn mainloop(mode: Mode, po: comm::Port<Msg>, dom_event_chan: pipes::SharedChan<E
let width = buffer.rect.size.width as uint;
let height = buffer.rect.size.height as uint;
debug!("osmain: compositing buffer rect %?, cairo surface %?",
&buffer.rect,
&buffer.cairo_surface);
let image_data = @CairoSurfaceImageData {
cairo_surface: buffers[0].cairo_surface.clone(),
cairo_surface: buffer.cairo_surface.clone(),
size: Size2D(width, height)
};
let image = @layers::layers::Image::new(
@ -146,6 +150,7 @@ fn mainloop(mode: Mode, po: comm::Port<Msg>, dom_event_chan: pipes::SharedChan<E
let image_layer;
current_layer_child = match current_layer_child {
None => {
debug!("osmain: adding new image layer");
image_layer = @layers::layers::ImageLayer(image);
root_layer.add_child(layers::layers::ImageLayerKind(image_layer));
None
@ -191,7 +196,7 @@ fn mainloop(mode: Mode, po: comm::Port<Msg>, dom_event_chan: pipes::SharedChan<E
};
let composite: fn@() = || {
#debug("osmain: drawing to screen");
//#debug("osmain: drawing to screen");
do util::time::time(~"compositing") {
adjust_for_window_resizing();
@ -212,13 +217,13 @@ fn mainloop(mode: Mode, po: comm::Port<Msg>, dom_event_chan: pipes::SharedChan<E
}
do glut::display_func() {
debug!("osmain: display func");
//debug!("osmain: display func");
check_for_messages();
composite();
}
while !*done {
#debug("osmain: running GLUT check loop");
//#debug("osmain: running GLUT check loop");
glut::check_loop();
}
}
@ -282,7 +287,7 @@ fn lend_surface(surfaces: &SurfaceSet, receiver: pipes::Chan<LayerBufferSet>) {
}
fn return_surface(surfaces: &SurfaceSet, layer_buffer_set: LayerBufferSet) {
#debug("osmain: returning surface %?", layer_buffer_set);
//#debug("osmain: returning surface %?", layer_buffer_set);
// We have room for a return
assert surfaces.front.have;
assert !surfaces.back.have;