mirror of
https://github.com/servo/servo.git
synced 2025-06-25 09:34:32 +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,6 +240,15 @@ impl CompositorTask {
|
||||||
// Iterate over the children of the container layer.
|
// Iterate over the children of the container layer.
|
||||||
let mut current_layer_child = root_layer.first_child;
|
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();
|
let all_tiles = quad.get_all_tiles();
|
||||||
for all_tiles.iter().advance |buffer| {
|
for all_tiles.iter().advance |buffer| {
|
||||||
let width = buffer.screen_pos.size.width as uint;
|
let width = buffer.screen_pos.size.width as uint;
|
||||||
|
@ -278,14 +287,6 @@ impl CompositorTask {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
// Reset zoom
|
||||||
*local_zoom = 1f32;
|
*local_zoom = 1f32;
|
||||||
root_layer.common.set_transform(identity().translate(-world_offset.x,
|
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| {
|
for new_layer_buffer_set.buffers.iter().advance |buffer| {
|
||||||
// FIXME: Don't copy the buffers here
|
// FIXME: Don't copy the buffers here
|
||||||
quad.add_tile(buffer.screen_pos.origin.x, buffer.screen_pos.origin.y,
|
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);
|
*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);
|
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();
|
ask_for_tiles();
|
||||||
|
|
||||||
*recomposite = true;
|
*recomposite = true;
|
||||||
|
|
|
@ -86,7 +86,7 @@ impl<T> Quadtree<T> {
|
||||||
pub fn remove_tile(&mut self, x: uint, y: uint, scale: f32) {
|
pub fn remove_tile(&mut self, x: uint, y: uint, scale: f32) {
|
||||||
self.root.remove_tile(x as f32 / scale, y as f32 / scale);
|
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
|
/// (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
|
/// 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
|
/// 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),
|
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)),
|
Size2D(window.size.width as f32 / scale, window.size.height as f32 / scale)),
|
||||||
valid, scale, self.max_tile_size as f32 / scale)
|
valid, scale, self.max_tile_size as f32 / scale)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate html to visualize the tree. For debugging purposes only.
|
/// Generate html to visualize the tree. For debugging purposes only.
|
||||||
|
@ -148,15 +149,10 @@ 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] {
|
fn get_all_tiles<'r>(&'r self) -> ~[&'r T] {
|
||||||
let mut ret = ~[];
|
let mut ret = ~[];
|
||||||
|
|
||||||
match self.tile {
|
|
||||||
Some(ref tile) => ret = ~[tile],
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
for self.quadrants.iter().advance |quad| {
|
for self.quadrants.iter().advance |quad| {
|
||||||
match *quad {
|
match *quad {
|
||||||
Some(ref child) => ret = ret + child.get_all_tiles(),
|
Some(ref child) => ret = ret + child.get_all_tiles(),
|
||||||
|
@ -164,6 +160,12 @@ impl<T> QuadtreeNode<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match self.tile {
|
||||||
|
Some(ref tile) => ret = ret + ~[tile],
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,6 +233,7 @@ impl<T> QuadtreeNode<T> {
|
||||||
let self_x = (self.origin.x * scale).ceil() as uint;
|
let self_x = (self.origin.x * scale).ceil() as uint;
|
||||||
let self_y = (self.origin.y * scale).ceil() as uint;
|
let self_y = (self.origin.y * scale).ceil() as uint;
|
||||||
let self_size = (self.size * 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)),
|
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)));
|
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,
|
BL | BR => self.origin.y + new_size,
|
||||||
};
|
};
|
||||||
let mut c = ~QuadtreeNode::new_child(new_x, new_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);
|
let result = c.get_tile_rect(x, y, scale, tile_size);
|
||||||
self.quadrants[quad as int] = Some(c);
|
self.quadrants[quad as int] = Some(c);
|
||||||
result
|
result
|
||||||
|
@ -340,12 +342,14 @@ impl<T> QuadtreeNode<T> {
|
||||||
|
|
||||||
if w_x < s_x || w_x + w_width > s_x + s_size
|
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 {
|
|| 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");
|
fail!("Quadtree: tried to query an invalid tile rect");
|
||||||
}
|
}
|
||||||
|
|
||||||
if s_size <= tile_size { // We are the child
|
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) => {
|
Some(ref tile) if valid(tile) => {
|
||||||
let redisplay = match self.quadrants {
|
let redisplay = match self.quadrants {
|
||||||
[None, None, None, None] => false,
|
[None, None, None, None] => false,
|
||||||
|
@ -358,14 +362,9 @@ impl<T> QuadtreeNode<T> {
|
||||||
self.quadrants[*quad as int] = None;
|
self.quadrants[*quad as int] = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (~[], redisplay);
|
(~[], redisplay)
|
||||||
}
|
|
||||||
None if self.render_flag => {
|
|
||||||
return(~[], false);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
return (~[self.get_tile_rect(s_x, s_y, scale, tile_size)], false);
|
|
||||||
}
|
}
|
||||||
|
_ => (~[self.get_tile_rect(s_x, s_y, scale, tile_size)], false),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,8 +402,6 @@ impl<T> QuadtreeNode<T> {
|
||||||
let mut redisplay = false;
|
let mut redisplay = false;
|
||||||
|
|
||||||
for quads_to_check.iter().advance |quad| {
|
for quads_to_check.iter().advance |quad| {
|
||||||
match self.quadrants[*quad as int] {
|
|
||||||
Some(ref mut child) => {
|
|
||||||
// Recurse into child
|
// Recurse into child
|
||||||
let new_window = match *quad {
|
let new_window = match *quad {
|
||||||
TL => Rect(window.origin,
|
TL => Rect(window.origin,
|
||||||
|
@ -424,48 +421,30 @@ impl<T> QuadtreeNode<T> {
|
||||||
w_height.min(&(w_y + w_height - (s_y + 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);
|
|
||||||
|
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,
|
||||||
|
};
|
||||||
|
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;
|
ret = ret + c_ret;
|
||||||
redisplay = redisplay || c_redisplay;
|
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;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
ret = ret + build_sized(size, builder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(ret, redisplay)
|
(ret, redisplay)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue