mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Address pcwalton's nits; automatic rendering after scrolling
This commit is contained in:
parent
cc816c04b9
commit
8a0878a41c
2 changed files with 99 additions and 93 deletions
|
@ -235,6 +235,64 @@ impl CompositorTask {
|
|||
let zoom_action = @mut false;
|
||||
let zoom_time = @mut 0f;
|
||||
|
||||
// Extract tiles from the given quadtree and build and display the render tree.
|
||||
let build_layer_tree: @fn(&Quadtree<~LayerBuffer>) = |quad: &Quadtree<~LayerBuffer>| {
|
||||
// Iterate over the children of the container layer.
|
||||
let mut current_layer_child = root_layer.first_child;
|
||||
|
||||
let all_tiles = quad.get_all_tiles();
|
||||
for all_tiles.iter().advance |buffer| {
|
||||
let width = buffer.screen_pos.size.width as uint;
|
||||
let height = buffer.screen_pos.size.height as uint;
|
||||
debug!("osmain: compositing buffer rect %?", &buffer.rect);
|
||||
|
||||
// Find or create a texture layer.
|
||||
let texture_layer;
|
||||
current_layer_child = match current_layer_child {
|
||||
None => {
|
||||
debug!("osmain: adding new texture layer");
|
||||
texture_layer = @mut TextureLayer::new(@buffer.draw_target.clone() as @TextureManager,
|
||||
buffer.screen_pos.size);
|
||||
root_layer.add_child(TextureLayerKind(texture_layer));
|
||||
None
|
||||
}
|
||||
Some(TextureLayerKind(existing_texture_layer)) => {
|
||||
texture_layer = existing_texture_layer;
|
||||
texture_layer.manager = @buffer.draw_target.clone() as @TextureManager;
|
||||
|
||||
// Move on to the next sibling.
|
||||
do current_layer_child.get().with_common |common| {
|
||||
common.next_sibling
|
||||
}
|
||||
}
|
||||
Some(_) => fail!(~"found unexpected layer kind"),
|
||||
};
|
||||
|
||||
let origin = buffer.rect.origin;
|
||||
let origin = Point2D(origin.x as f32, origin.y as f32);
|
||||
|
||||
// Set the layer's transform.
|
||||
let transform = identity().translate(origin.x * *world_zoom, origin.y * *world_zoom, 0.0);
|
||||
let transform = transform.scale(width as f32 * *world_zoom / buffer.resolution, height as f32 * *world_zoom / buffer.resolution, 1.0);
|
||||
texture_layer.common.set_transform(transform);
|
||||
|
||||
}
|
||||
|
||||
// Delete leftover layers
|
||||
while current_layer_child.is_some() {
|
||||
let trash = current_layer_child.get();
|
||||
do current_layer_child.get().with_common |common| {
|
||||
current_layer_child = common.next_sibling;
|
||||
}
|
||||
root_layer.remove_child(trash);
|
||||
}
|
||||
// Reset zoom
|
||||
*local_zoom = 1f32;
|
||||
root_layer.common.set_transform(identity().translate(-world_offset.x,
|
||||
-world_offset.y,
|
||||
0.0));
|
||||
*recomposite = true;
|
||||
};
|
||||
|
||||
let ask_for_tiles: @fn() = || {
|
||||
match *quadtree {
|
||||
|
@ -256,7 +314,7 @@ impl CompositorTask {
|
|||
}
|
||||
}
|
||||
} else if redisplay {
|
||||
// TODO: move display code to its own closure and call that here
|
||||
build_layer_tree(quad);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
|
@ -313,11 +371,6 @@ impl CompositorTask {
|
|||
|
||||
}
|
||||
WindowMouseUpEvent(button, layer_mouse_point) => {
|
||||
|
||||
// FIXME: this should happen on a scroll/zoom event instead,
|
||||
// but is here temporarily to prevent request floods to the renderer
|
||||
ask_for_tiles();
|
||||
|
||||
event = MouseUpEvent(button, world_mouse_point(layer_mouse_point));
|
||||
}
|
||||
}
|
||||
|
@ -371,17 +424,16 @@ impl CompositorTask {
|
|||
Some(pipeline_id) => if id != pipeline_id { loop; },
|
||||
None => { loop; },
|
||||
}
|
||||
|
||||
debug!("osmain: received new frame");
|
||||
|
||||
debug!("osmain: received new frame");
|
||||
|
||||
|
||||
let quad;
|
||||
match *quadtree {
|
||||
Some(ref mut q) => quad = q,
|
||||
None => fail!("Compositor: given paint command with no quadtree initialized"),
|
||||
}
|
||||
|
||||
*page_size = Size2D(new_size.width as f32, new_size.height as f32);
|
||||
|
||||
|
||||
let new_layer_buffer_set = new_layer_buffer_set.get();
|
||||
for new_layer_buffer_set.buffers.iter().advance |buffer| {
|
||||
// FIXME: Don't copy the buffers here
|
||||
|
@ -389,67 +441,12 @@ impl CompositorTask {
|
|||
*world_zoom, ~buffer.clone());
|
||||
}
|
||||
|
||||
|
||||
// Iterate over the children of the container layer.
|
||||
let mut current_layer_child = root_layer.first_child;
|
||||
*page_size = Size2D(new_size.width as f32, new_size.height as f32);
|
||||
|
||||
let all_tiles = quad.get_all_tiles();
|
||||
for all_tiles.iter().advance |buffer| {
|
||||
let width = buffer.screen_pos.size.width as uint;
|
||||
let height = buffer.screen_pos.size.height as uint;
|
||||
debug!("osmain: compositing buffer rect %?", &buffer.rect);
|
||||
|
||||
// Find or create a texture layer.
|
||||
let texture_layer;
|
||||
current_layer_child = match current_layer_child {
|
||||
None => {
|
||||
debug!("osmain: adding new texture layer");
|
||||
texture_layer = @mut TextureLayer::new(@buffer.draw_target.clone() as @TextureManager,
|
||||
buffer.screen_pos.size);
|
||||
root_layer.add_child(TextureLayerKind(texture_layer));
|
||||
None
|
||||
}
|
||||
Some(TextureLayerKind(existing_texture_layer)) => {
|
||||
texture_layer = existing_texture_layer;
|
||||
texture_layer.manager = @buffer.draw_target.clone() as @TextureManager;
|
||||
|
||||
// Move on to the next sibling.
|
||||
do current_layer_child.get().with_common |common| {
|
||||
common.next_sibling
|
||||
}
|
||||
}
|
||||
Some(_) => fail!(~"found unexpected layer kind"),
|
||||
};
|
||||
|
||||
let origin = buffer.rect.origin;
|
||||
let origin = Point2D(origin.x as f32, origin.y as f32);
|
||||
|
||||
// Set the layer's transform.
|
||||
let transform = identity().translate(origin.x * *world_zoom, origin.y * *world_zoom, 0.0);
|
||||
let transform = transform.scale(width as f32 * *world_zoom / buffer.resolution, height as f32 * *world_zoom / buffer.resolution, 1.0);
|
||||
texture_layer.common.set_transform(transform);
|
||||
|
||||
}
|
||||
|
||||
// Delete leftover layers
|
||||
while current_layer_child.is_some() {
|
||||
let trash = current_layer_child.get();
|
||||
do current_layer_child.get().with_common |common| {
|
||||
current_layer_child = common.next_sibling;
|
||||
}
|
||||
root_layer.remove_child(trash);
|
||||
}
|
||||
|
||||
// Reset zoom
|
||||
*local_zoom = 1f32;
|
||||
root_layer.common.set_transform(identity().translate(-world_offset.x,
|
||||
-world_offset.y,
|
||||
0.0));
|
||||
build_layer_tree(quad);
|
||||
|
||||
// TODO: Recycle the old buffers; send them back to the renderer to reuse if
|
||||
// it wishes.
|
||||
|
||||
*recomposite = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -499,7 +496,7 @@ impl CompositorTask {
|
|||
// FIXME: ask_for_tiles() should be called here, but currently this sends a flood of requests
|
||||
// to the renderer, which slows the application dramatically. Instead, ask_for_tiles() is only
|
||||
// called on a click event.
|
||||
// ask_for_tiles();
|
||||
ask_for_tiles();
|
||||
|
||||
*recomposite = true;
|
||||
}
|
||||
|
|
|
@ -23,12 +23,14 @@ pub struct Quadtree<T> {
|
|||
struct QuadtreeNode<T> {
|
||||
/// The tile belonging to this node. Note that parent nodes can have tiles.
|
||||
tile: Option<T>,
|
||||
/// The positiong of the node in page coordinates.
|
||||
/// The position of the node in page coordinates.
|
||||
origin: Point2D<f32>,
|
||||
/// The width and hight of the node in page coordinates.
|
||||
/// The width and height of the node in page coordinates.
|
||||
size: f32,
|
||||
/// The node's children.
|
||||
quadrants: [Option<~QuadtreeNode<T>>, ..4],
|
||||
/// If this node is marked for rendering
|
||||
render_flag: bool,
|
||||
}
|
||||
|
||||
priv enum Quadrant {
|
||||
|
@ -53,6 +55,7 @@ impl<T> Quadtree<T> {
|
|||
origin: Point2D(x as f32, y as f32),
|
||||
size: size as f32,
|
||||
quadrants: [None, None, None, None],
|
||||
render_flag: false,
|
||||
},
|
||||
max_tile_size: tile_size,
|
||||
}
|
||||
|
@ -71,7 +74,7 @@ impl<T> Quadtree<T> {
|
|||
self.root.add_tile(x as f32 / scale, y as f32 / scale, tile, self.max_tile_size as f32 / scale);
|
||||
}
|
||||
/// Get the tile rect in screen and page coordinates for a given pixel position
|
||||
pub fn get_tile_rect(&self, x: uint, y: uint, scale: f32) -> BufferRequest {
|
||||
pub fn get_tile_rect(&mut self, x: uint, y: uint, scale: f32) -> BufferRequest {
|
||||
self.root.get_tile_rect(x as f32 / scale, y as f32 / scale, scale, self.max_tile_size as f32 / scale)
|
||||
}
|
||||
/// Get all the tiles in the tree
|
||||
|
@ -96,10 +99,10 @@ impl<T> Quadtree<T> {
|
|||
valid, scale, self.max_tile_size as f32 / scale)
|
||||
}
|
||||
|
||||
/// Generate html to visualize the tree
|
||||
/// Generate html to visualize the tree. For debugging purposes only.
|
||||
pub fn get_html(&self) -> ~str {
|
||||
let header = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"> <html xmlns=\"http://www.w3.org/1999/xhtml\">";
|
||||
fmt!("%s<body>%s</body></html>", header, self.root.get_html())
|
||||
static HEADER: &'static str = "<!DOCTYPE html><html>";
|
||||
fmt!("%s<body>%s</body></html>", HEADER, self.root.get_html())
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -112,6 +115,7 @@ impl<T> QuadtreeNode<T> {
|
|||
origin: Point2D(x, y),
|
||||
size: size,
|
||||
quadrants: [None, None, None, None],
|
||||
render_flag: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,7 +153,7 @@ impl<T> QuadtreeNode<T> {
|
|||
let mut ret = ~[];
|
||||
|
||||
match self.tile {
|
||||
Some (ref tile) => ret = ~[tile],
|
||||
Some(ref tile) => ret = ~[tile],
|
||||
None => {}
|
||||
}
|
||||
|
||||
|
@ -180,6 +184,7 @@ impl<T> QuadtreeNode<T> {
|
|||
for quads.iter().advance |quad| {
|
||||
self.quadrants[*quad as int] = None;
|
||||
}
|
||||
self.render_flag = false;
|
||||
} else { // Send tile to children
|
||||
let quad = self.get_quadrant(x, y);
|
||||
match self.quadrants[quad as int] {
|
||||
|
@ -216,7 +221,7 @@ impl<T> QuadtreeNode<T> {
|
|||
}
|
||||
|
||||
/// Get a tile rect in screen and page coords for a given position in page coords
|
||||
fn get_tile_rect(&self, x: f32, y: f32, scale: f32, tile_size: f32) -> BufferRequest {
|
||||
fn get_tile_rect(&mut self, x: f32, y: f32, scale: f32, tile_size: f32) -> BufferRequest {
|
||||
if x >= self.origin.x + self.size || x < self.origin.x
|
||||
|| y >= self.origin.y + self.size || y < self.origin.y {
|
||||
fail!("Quadtree: Tried to query a tile rect outside of range");
|
||||
|
@ -230,24 +235,25 @@ impl<T> QuadtreeNode<T> {
|
|||
Rect(Point2D(self.origin.x, self.origin.y), Size2D(self.size, self.size)));
|
||||
}
|
||||
|
||||
let index = self.get_quadrant(x,y) as int;
|
||||
match self.quadrants[index] {
|
||||
let quad = self.get_quadrant(x,y);
|
||||
match self.quadrants[quad as int] {
|
||||
None => {
|
||||
// Calculate where the new tile should go
|
||||
let factor = self.size / tile_size;
|
||||
let divisor = next_power_of_two(factor.ceil() as uint);
|
||||
let new_size_page = self.size / (divisor as f32);
|
||||
let new_size_pixel = (new_size_page * scale).ceil() as uint;
|
||||
|
||||
let new_x_page = self.origin.x + new_size_page * ((x - self.origin.x) / new_size_page).floor();
|
||||
let new_y_page = self.origin.y + new_size_page * ((y - self.origin.y) / new_size_page).floor();
|
||||
let new_x_pixel = (new_x_page * scale).ceil() as uint;
|
||||
let new_y_pixel = (new_y_page * scale).ceil() as uint;
|
||||
|
||||
BufferRequest(Rect(Point2D(new_x_pixel, new_y_pixel), Size2D(new_size_pixel, new_size_pixel)),
|
||||
Rect(Point2D(new_x_page, new_y_page), Size2D(new_size_page, new_size_page)))
|
||||
let new_size = self.size / 2.0;
|
||||
let new_x = match quad {
|
||||
TL | BL => self.origin.x,
|
||||
TR | BR => self.origin.x + new_size,
|
||||
};
|
||||
let new_y = match quad {
|
||||
TL | TR => self.origin.y,
|
||||
BL | BR => self.origin.y + new_size,
|
||||
};
|
||||
let mut c = ~QuadtreeNode::new_child(new_x, new_y, new_size);
|
||||
c.render_flag = true;
|
||||
let result = c.get_tile_rect(x, y, scale, tile_size);
|
||||
self.quadrants[quad as int] = Some(c);
|
||||
result
|
||||
}
|
||||
Some(ref child) => child.get_tile_rect(x, y, scale, tile_size),
|
||||
Some(ref mut child) => child.get_tile_rect(x, y, scale, tile_size),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -354,6 +360,9 @@ impl<T> QuadtreeNode<T> {
|
|||
}
|
||||
return (~[], redisplay);
|
||||
}
|
||||
None if self.render_flag => {
|
||||
return(~[], false);
|
||||
}
|
||||
_ => {
|
||||
return (~[self.get_tile_rect(s_x, s_y, scale, tile_size)], false);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue