mirror of
https://github.com/servo/servo.git
synced 2025-06-24 17:14:33 +01:00
Fix quadtree zoom and request flood bugs
This commit is contained in:
parent
783e898c60
commit
dd061cfdc0
2 changed files with 67 additions and 90 deletions
|
@ -240,12 +240,21 @@ impl CompositorTask {
|
|||
// Iterate over the children of the container layer.
|
||||
let mut current_layer_child = root_layer.first_child;
|
||||
|
||||
// Delete old layer
|
||||
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);
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -275,17 +284,9 @@ impl CompositorTask {
|
|||
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,
|
||||
|
@ -438,7 +439,7 @@ impl CompositorTask {
|
|||
for new_layer_buffer_set.buffers.iter().advance |buffer| {
|
||||
// FIXME: Don't copy the buffers here
|
||||
quad.add_tile(buffer.screen_pos.origin.x, buffer.screen_pos.origin.y,
|
||||
*world_zoom, ~buffer.clone());
|
||||
buffer.resolution, ~buffer.clone());
|
||||
}
|
||||
|
||||
*page_size = Size2D(new_size.width as f32, new_size.height as f32);
|
||||
|
@ -493,9 +494,6 @@ impl CompositorTask {
|
|||
|
||||
root_layer.common.set_transform(scroll_transform);
|
||||
|
||||
// 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();
|
||||
|
||||
*recomposite = true;
|
||||
|
|
|
@ -86,7 +86,7 @@ impl<T> Quadtree<T> {
|
|||
pub fn remove_tile(&mut self, x: uint, y: uint, scale: f32) {
|
||||
self.root.remove_tile(x as f32 / scale, y as f32 / scale);
|
||||
}
|
||||
/// Given a window rect in page coordinates and a function to check if an existing tile is "valid"
|
||||
/// Given a window rect in pixel coordinates and a function to check if an existing tile is "valid"
|
||||
/// (i.e. is the correct resolution), this function returns a list of BufferRequests for tiles that
|
||||
/// need to be rendered. It also returns a boolean if the window needs to be redisplayed, i.e. if
|
||||
/// no tiles need to be rendered, but the display tree needs to be rebuilt. This can occur when the
|
||||
|
@ -97,6 +97,7 @@ impl<T> Quadtree<T> {
|
|||
self.root.get_tile_rects(Rect(Point2D(window.origin.x as f32 / scale, window.origin.y as f32 / scale),
|
||||
Size2D(window.size.width as f32 / scale, window.size.height as f32 / scale)),
|
||||
valid, scale, self.max_tile_size as f32 / scale)
|
||||
|
||||
}
|
||||
|
||||
/// Generate html to visualize the tree. For debugging purposes only.
|
||||
|
@ -148,14 +149,9 @@ impl<T> QuadtreeNode<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get all tiles in the tree, parents first.
|
||||
/// Get all tiles in the tree, parents last.
|
||||
fn get_all_tiles<'r>(&'r self) -> ~[&'r T] {
|
||||
let mut ret = ~[];
|
||||
|
||||
match self.tile {
|
||||
Some(ref tile) => ret = ~[tile],
|
||||
None => {}
|
||||
}
|
||||
|
||||
for self.quadrants.iter().advance |quad| {
|
||||
match *quad {
|
||||
|
@ -163,6 +159,12 @@ impl<T> QuadtreeNode<T> {
|
|||
None => {}
|
||||
}
|
||||
}
|
||||
|
||||
match self.tile {
|
||||
Some(ref tile) => ret = ret + ~[tile],
|
||||
None => {}
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -231,6 +233,7 @@ impl<T> QuadtreeNode<T> {
|
|||
let self_x = (self.origin.x * scale).ceil() as uint;
|
||||
let self_y = (self.origin.y * scale).ceil() as uint;
|
||||
let self_size = (self.size * scale).ceil() as uint;
|
||||
self.render_flag = true;
|
||||
return BufferRequest(Rect(Point2D(self_x, self_y), Size2D(self_size, self_size)),
|
||||
Rect(Point2D(self.origin.x, self.origin.y), Size2D(self.size, self.size)));
|
||||
}
|
||||
|
@ -248,7 +251,6 @@ impl<T> QuadtreeNode<T> {
|
|||
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
|
||||
|
@ -340,12 +342,14 @@ impl<T> QuadtreeNode<T> {
|
|||
|
||||
if w_x < s_x || w_x + w_width > s_x + s_size
|
||||
|| w_y < s_y || w_y + w_height > s_y + s_size {
|
||||
println(fmt!("window: %?, %?, %?, %?; self: %?, %?, %?", w_x, w_y, w_width, w_height, s_x, s_y, s_size));
|
||||
println(fmt!("window: %?, %?, %?, %?; self: %?, %?, %?",
|
||||
w_x, w_y, w_width, w_height, s_x, s_y, s_size));
|
||||
fail!("Quadtree: tried to query an invalid tile rect");
|
||||
}
|
||||
|
||||
if s_size <= tile_size { // We are the child
|
||||
match self.tile {
|
||||
return match self.tile {
|
||||
_ if self.render_flag => (~[], false),
|
||||
Some(ref tile) if valid(tile) => {
|
||||
let redisplay = match self.quadrants {
|
||||
[None, None, None, None] => false,
|
||||
|
@ -358,14 +362,9 @@ impl<T> QuadtreeNode<T> {
|
|||
self.quadrants[*quad as int] = None;
|
||||
}
|
||||
}
|
||||
return (~[], redisplay);
|
||||
}
|
||||
None if self.render_flag => {
|
||||
return(~[], false);
|
||||
}
|
||||
_ => {
|
||||
return (~[self.get_tile_rect(s_x, s_y, scale, tile_size)], false);
|
||||
(~[], redisplay)
|
||||
}
|
||||
_ => (~[self.get_tile_rect(s_x, s_y, scale, tile_size)], false),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -403,68 +402,48 @@ impl<T> QuadtreeNode<T> {
|
|||
let mut redisplay = false;
|
||||
|
||||
for quads_to_check.iter().advance |quad| {
|
||||
match self.quadrants[*quad as int] {
|
||||
Some(ref mut child) => {
|
||||
// Recurse into child
|
||||
let new_window = match *quad {
|
||||
TL => Rect(window.origin,
|
||||
Size2D(w_width.min(&(s_x + s_size / 2.0 - w_x)),
|
||||
w_height.min(&(s_y + s_size / 2.0 - w_y)))),
|
||||
TR => Rect(Point2D(w_x.max(&(s_x + s_size / 2.0)),
|
||||
w_y),
|
||||
Size2D(w_width.min(&(w_x + w_width - (s_x + s_size / 2.0))),
|
||||
w_height.min(&(s_y + s_size / 2.0 - w_y)))),
|
||||
BL => Rect(Point2D(w_x,
|
||||
w_y.max(&(s_y + s_size / 2.0))),
|
||||
Size2D(w_width.min(&(s_x + s_size / 2.0 - w_x)),
|
||||
w_height.min(&(w_y + w_height - (s_y + s_size / 2.0))))),
|
||||
BR => Rect(Point2D(w_x.max(&(s_x + s_size / 2.0)),
|
||||
w_y.max(&(s_y + s_size / 2.0))),
|
||||
Size2D(w_width.min(&(w_x + w_width - (s_x + s_size / 2.0))),
|
||||
w_height.min(&(w_y + w_height - (s_y + s_size / 2.0))))),
|
||||
|
||||
};
|
||||
let (c_ret, c_redisplay) = child.get_tile_rects(new_window, |x| valid(x), scale, tile_size);
|
||||
ret = ret + c_ret;
|
||||
redisplay = redisplay || c_redisplay;
|
||||
}
|
||||
None => {
|
||||
// Figure out locations of future children
|
||||
let (x_start, y_start, x_end, y_end) = match *quad {
|
||||
TL => (w_x,
|
||||
w_y,
|
||||
(w_x + w_width).min(&(s_x + s_size / 2.0)),
|
||||
(w_y + w_height).min(&(s_y + s_size / 2.0))),
|
||||
TR => (w_x.max(&(s_x + s_size / 2.0)),
|
||||
w_y,
|
||||
(w_x + w_width + tile_size).min(&(s_x + s_size)),
|
||||
(w_y + w_height).min(&(s_y + s_size / 2.0))),
|
||||
BL => (w_x,
|
||||
w_y.max(&(s_y + s_size / 2.0)),
|
||||
(w_x + w_width).min(&(s_x + s_size / 2.0)),
|
||||
(w_y + w_height + tile_size).min(&(s_y + s_size))),
|
||||
BR => (w_x.max(&(s_x + s_size / 2.0)),
|
||||
w_y.max(&(s_y + s_size / 2.0)),
|
||||
(w_x + w_width + tile_size).min(&(s_x + s_size)),
|
||||
(w_y + w_height + tile_size).min(&(s_y + s_size))),
|
||||
};
|
||||
let size = (((x_end - x_start) / tile_size).ceil() *
|
||||
((y_end - y_start) / tile_size).ceil()) as uint;
|
||||
// Recurse into child
|
||||
let new_window = match *quad {
|
||||
TL => Rect(window.origin,
|
||||
Size2D(w_width.min(&(s_x + s_size / 2.0 - w_x)),
|
||||
w_height.min(&(s_y + s_size / 2.0 - w_y)))),
|
||||
TR => Rect(Point2D(w_x.max(&(s_x + s_size / 2.0)),
|
||||
w_y),
|
||||
Size2D(w_width.min(&(w_x + w_width - (s_x + s_size / 2.0))),
|
||||
w_height.min(&(s_y + s_size / 2.0 - w_y)))),
|
||||
BL => Rect(Point2D(w_x,
|
||||
w_y.max(&(s_y + s_size / 2.0))),
|
||||
Size2D(w_width.min(&(s_x + s_size / 2.0 - w_x)),
|
||||
w_height.min(&(w_y + w_height - (s_y + s_size / 2.0))))),
|
||||
BR => Rect(Point2D(w_x.max(&(s_x + s_size / 2.0)),
|
||||
w_y.max(&(s_y + s_size / 2.0))),
|
||||
Size2D(w_width.min(&(w_x + w_width - (s_x + s_size / 2.0))),
|
||||
w_height.min(&(w_y + w_height - (s_y + s_size / 2.0))))),
|
||||
|
||||
};
|
||||
|
||||
let builder = |push: &fn(BufferRequest)| {
|
||||
let mut y = y_start;
|
||||
while y < y_end {
|
||||
let mut x = x_start;
|
||||
while x < x_end {
|
||||
push(self.get_tile_rect(x, y, scale, tile_size));
|
||||
x = x + tile_size;
|
||||
}
|
||||
y = y + tile_size;
|
||||
}
|
||||
let (c_ret, c_redisplay) = match self.quadrants[*quad as int] {
|
||||
Some(ref mut child) => child.get_tile_rects(new_window, |x| valid(x), scale, tile_size),
|
||||
None => {
|
||||
// Create new child
|
||||
let new_size = self.size / 2.0;
|
||||
let new_x = match *quad {
|
||||
TL | BL => self.origin.x,
|
||||
TR | BR => self.origin.x + new_size,
|
||||
};
|
||||
ret = ret + build_sized(size, builder);
|
||||
let new_y = match *quad {
|
||||
TL | TR => self.origin.y,
|
||||
BL | BR => self.origin.y + new_size,
|
||||
};
|
||||
let mut child = ~QuadtreeNode::new_child(new_x, new_y, new_size);
|
||||
let (a, b) = child.get_tile_rects(new_window, |x| valid(x), scale, tile_size);
|
||||
self.quadrants[*quad as int] = Some(child);
|
||||
(a, b)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ret = ret + c_ret;
|
||||
redisplay = redisplay || c_redisplay;
|
||||
}
|
||||
|
||||
(ret, redisplay)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue