diff --git a/src/components/main/compositing/mod.rs b/src/components/main/compositing/mod.rs index f794446e299..3033afbb56d 100644 --- a/src/components/main/compositing/mod.rs +++ b/src/components/main/compositing/mod.rs @@ -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; } diff --git a/src/components/main/compositing/quadtree.rs b/src/components/main/compositing/quadtree.rs index 300c3ccff09..0a86b39f6dc 100644 --- a/src/components/main/compositing/quadtree.rs +++ b/src/components/main/compositing/quadtree.rs @@ -23,12 +23,14 @@ pub struct Quadtree { struct QuadtreeNode { /// The tile belonging to this node. Note that parent nodes can have tiles. tile: Option, - /// The positiong of the node in page coordinates. + /// The position of the node in page coordinates. origin: Point2D, - /// 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>, ..4], + /// If this node is marked for rendering + render_flag: bool, } priv enum Quadrant { @@ -53,6 +55,7 @@ impl Quadtree { 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 Quadtree { 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 Quadtree { 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 = " "; - fmt!("%s%s", header, self.root.get_html()) + static HEADER: &'static str = ""; + fmt!("%s%s", HEADER, self.root.get_html()) } } @@ -112,6 +115,7 @@ impl QuadtreeNode { origin: Point2D(x, y), size: size, quadrants: [None, None, None, None], + render_flag: false, } } @@ -149,7 +153,7 @@ impl QuadtreeNode { let mut ret = ~[]; match self.tile { - Some (ref tile) => ret = ~[tile], + Some(ref tile) => ret = ~[tile], None => {} } @@ -180,6 +184,7 @@ impl QuadtreeNode { 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 QuadtreeNode { } /// 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 QuadtreeNode { 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 QuadtreeNode { } return (~[], redisplay); } + None if self.render_flag => { + return(~[], false); + } _ => { return (~[self.get_tile_rect(s_x, s_y, scale, tile_size)], false); }