mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
gfx: Implement tiled rendering
This commit is contained in:
parent
01e9c30b80
commit
7c029a322d
4 changed files with 79 additions and 37 deletions
|
@ -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);
|
||||
|
|
|
@ -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) };
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue