diff --git a/src/components/main/compositing/mod.rs b/src/components/main/compositing/mod.rs index 3033afbb56d..5b388b5a0dd 100644 --- a/src/components/main/compositing/mod.rs +++ b/src/components/main/compositing/mod.rs @@ -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; diff --git a/src/components/main/compositing/quadtree.rs b/src/components/main/compositing/quadtree.rs index 0a86b39f6dc..fc6274e9b96 100644 --- a/src/components/main/compositing/quadtree.rs +++ b/src/components/main/compositing/quadtree.rs @@ -86,7 +86,7 @@ impl Quadtree { 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 Quadtree { 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 QuadtreeNode { } } - /// 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 QuadtreeNode { None => {} } } + + match self.tile { + Some(ref tile) => ret = ret + ~[tile], + None => {} + } + return ret; } @@ -231,6 +233,7 @@ impl QuadtreeNode { 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 QuadtreeNode { 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 QuadtreeNode { 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 QuadtreeNode { 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 QuadtreeNode { 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)