forked from mirrors/gecko-dev
		
	servo: Merge #758 - Compositor clean up (from eschweic:comp-clean-up); r=metajack
Reorder layer tree construction, implement layer occlusion, and general clean up. Source-Repo: https://github.com/servo/servo Source-Revision: 0c50d4374f77a7d3b7a8a549859e537faae36b5e
This commit is contained in:
		
							parent
							
								
									e01584a3fb
								
							
						
					
					
						commit
						1894465ec9
					
				
					 3 changed files with 178 additions and 99 deletions
				
			
		| 
						 | 
					@ -13,7 +13,7 @@ use servo_msg::constellation_msg::PipelineId;
 | 
				
			||||||
use script::dom::event::{ClickEvent, MouseDownEvent, MouseUpEvent};
 | 
					use script::dom::event::{ClickEvent, MouseDownEvent, MouseUpEvent};
 | 
				
			||||||
use script::script_task::SendEventMsg;
 | 
					use script::script_task::SendEventMsg;
 | 
				
			||||||
use windowing::{MouseWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEvent, MouseWindowMouseUpEvent};
 | 
					use windowing::{MouseWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEvent, MouseWindowMouseUpEvent};
 | 
				
			||||||
use compositing::quadtree::{Quadtree, Invalid};
 | 
					use compositing::quadtree::{Quadtree, Normal, Invalid, Hidden};
 | 
				
			||||||
use layers::layers::{ContainerLayerKind, ContainerLayer, TextureLayerKind, TextureLayer, TextureManager};
 | 
					use layers::layers::{ContainerLayerKind, ContainerLayer, TextureLayerKind, TextureLayer, TextureManager};
 | 
				
			||||||
use pipeline::Pipeline;
 | 
					use pipeline::Pipeline;
 | 
				
			||||||
use constellation::{SendableChildFrameTree, SendableFrameTree};
 | 
					use constellation::{SendableChildFrameTree, SendableFrameTree};
 | 
				
			||||||
| 
						 | 
					@ -109,13 +109,14 @@ impl CompositorLayer {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            let child_layer = ~CompositorLayer::from_frame_tree(frame_tree, tile_size, max_mem);
 | 
					            let child_layer = ~CompositorLayer::from_frame_tree(frame_tree, tile_size, max_mem);
 | 
				
			||||||
            container.add_child(ContainerLayerKind(child_layer.root_layer));
 | 
					            container.add_child_start(ContainerLayerKind(child_layer.root_layer));
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            CompositorLayerChild {
 | 
					            CompositorLayerChild {
 | 
				
			||||||
                child: child_layer,
 | 
					                child: child_layer,
 | 
				
			||||||
                container: container,
 | 
					                container: container,
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }).collect();
 | 
					        }).collect();
 | 
				
			||||||
 | 
					        layer.set_occlusions();
 | 
				
			||||||
        layer
 | 
					        layer
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -140,6 +141,7 @@ impl CompositorLayer {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Scroll this layer!
 | 
				
			||||||
        let old_origin = self.scroll_offset;
 | 
					        let old_origin = self.scroll_offset;
 | 
				
			||||||
        self.scroll_offset = self.scroll_offset + delta;
 | 
					        self.scroll_offset = self.scroll_offset + delta;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
| 
						 | 
					@ -204,7 +206,7 @@ impl CompositorLayer {
 | 
				
			||||||
        let mut redisplay: bool;
 | 
					        let mut redisplay: bool;
 | 
				
			||||||
        { // block here to prevent double mutable borrow of self
 | 
					        { // block here to prevent double mutable borrow of self
 | 
				
			||||||
            let quadtree = match self.quadtree {
 | 
					            let quadtree = match self.quadtree {
 | 
				
			||||||
                NoTree(_, _) => fail!("CompositorLayer: cannot get buffer request for %?,
 | 
					                NoTree(*) => fail!("CompositorLayer: cannot get buffer request for %?,
 | 
				
			||||||
                                   no quadtree initialized", self.pipeline.id),
 | 
					                                   no quadtree initialized", self.pipeline.id),
 | 
				
			||||||
                Tree(ref mut quadtree) => quadtree,
 | 
					                Tree(ref mut quadtree) => quadtree,
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
| 
						 | 
					@ -249,25 +251,40 @@ impl CompositorLayer {
 | 
				
			||||||
    // If the layer is hidden and has a defined page size, unhide it.
 | 
					    // If the layer is hidden and has a defined page size, unhide it.
 | 
				
			||||||
    // This method returns false if the specified layer is not found.
 | 
					    // This method returns false if the specified layer is not found.
 | 
				
			||||||
    pub fn set_clipping_rect(&mut self, pipeline_id: PipelineId, new_rect: Rect<f32>) -> bool {
 | 
					    pub fn set_clipping_rect(&mut self, pipeline_id: PipelineId, new_rect: Rect<f32>) -> bool {
 | 
				
			||||||
        for child_node in self.children.mut_iter() {
 | 
					        match self.children.iter().position(|x| pipeline_id == x.child.pipeline.id) {
 | 
				
			||||||
            if pipeline_id != child_node.child.pipeline.id {
 | 
					            Some(i) => {
 | 
				
			||||||
                loop;
 | 
					                let child_node = &mut self.children[i];
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
                let con = child_node.container;
 | 
					                let con = child_node.container;
 | 
				
			||||||
                con.common.set_transform(identity().translate(new_rect.origin.x,
 | 
					                con.common.set_transform(identity().translate(new_rect.origin.x,
 | 
				
			||||||
                                                              new_rect.origin.y,
 | 
					                                                              new_rect.origin.y,
 | 
				
			||||||
                                                              0.0));
 | 
					                                                              0.0));
 | 
				
			||||||
 | 
					                let old_rect = con.scissor;
 | 
				
			||||||
                con.scissor = Some(new_rect);
 | 
					                con.scissor = Some(new_rect);
 | 
				
			||||||
 | 
					                match self.quadtree {
 | 
				
			||||||
 | 
					                    NoTree(*) => {} // Nothing to do
 | 
				
			||||||
 | 
					                        Tree(ref mut quadtree) => {
 | 
				
			||||||
 | 
					                        match old_rect {
 | 
				
			||||||
 | 
					                            Some(old_rect) => {
 | 
				
			||||||
 | 
					                                quadtree.set_status_page(old_rect, Normal, false); // Rect is unhidden
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                            None => {} // Nothing to do
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        quadtree.set_status_page(new_rect, Hidden, false); // Hide the new rect
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
                // If possible, unhide child
 | 
					                // If possible, unhide child
 | 
				
			||||||
                if child_node.child.hidden && child_node.child.page_size.is_some() {
 | 
					                if child_node.child.hidden && child_node.child.page_size.is_some() {
 | 
				
			||||||
                    child_node.child.hidden = false;
 | 
					                    child_node.child.hidden = false;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            return true;
 | 
					                true
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        
 | 
					            None => {
 | 
				
			||||||
        // ID does not match any of our immediate children, so recurse on descendents (including hidden children)
 | 
					                // ID does not match any of our immediate children, so recurse on 
 | 
				
			||||||
 | 
					                // descendents (including hidden children)
 | 
				
			||||||
                self.children.mut_iter().map(|x| &mut x.child).any(|x| x.set_clipping_rect(pipeline_id, new_rect))
 | 
					                self.children.mut_iter().map(|x| &mut x.child).any(|x| x.set_clipping_rect(pipeline_id, new_rect))
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Set the layer's page size. This signals that the renderer is ready for BufferRequests.
 | 
					    // Set the layer's page size. This signals that the renderer is ready for BufferRequests.
 | 
				
			||||||
| 
						 | 
					@ -277,39 +294,48 @@ impl CompositorLayer {
 | 
				
			||||||
        if self.pipeline.id == pipeline_id {
 | 
					        if self.pipeline.id == pipeline_id {
 | 
				
			||||||
            self.epoch = epoch;
 | 
					            self.epoch = epoch;
 | 
				
			||||||
            self.page_size = Some(new_size);
 | 
					            self.page_size = Some(new_size);
 | 
				
			||||||
            // TODO: might get buffers back here
 | 
					 | 
				
			||||||
            match self.quadtree {
 | 
					            match self.quadtree {
 | 
				
			||||||
                Tree(ref mut quadtree) => quadtree.resize(new_size.width as uint, new_size.height as uint),
 | 
					                Tree(ref mut quadtree) => {
 | 
				
			||||||
                NoTree(tile_size, max_mem) => self.quadtree = Tree(Quadtree::new(new_size.width as uint,
 | 
					                    self.pipeline.render_chan.send(UnusedBufferMsg(quadtree.resize(new_size.width as uint,
 | 
				
			||||||
 | 
					                                                                                   new_size.height as uint)));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                NoTree(tile_size, max_mem) => {
 | 
				
			||||||
 | 
					                    self.quadtree = Tree(Quadtree::new(new_size.width as uint,
 | 
				
			||||||
                                                       new_size.height as uint,
 | 
					                                                       new_size.height as uint,
 | 
				
			||||||
                                                       tile_size,
 | 
					                                                       tile_size,
 | 
				
			||||||
                                                                                 max_mem)),
 | 
					                                                       max_mem));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            // Call scroll for bounds checking if the page shrunk. Use (-1, -1) as the cursor position
 | 
					            // Call scroll for bounds checking if the page shrunk. Use (-1, -1) as the cursor position
 | 
				
			||||||
            // to make sure the scroll isn't propagated downwards.
 | 
					            // to make sure the scroll isn't propagated downwards.
 | 
				
			||||||
            self.scroll(Point2D(0f32, 0f32), Point2D(-1f32, -1f32), window_size);
 | 
					            self.scroll(Point2D(0f32, 0f32), Point2D(-1f32, -1f32), window_size);
 | 
				
			||||||
            self.hidden = false;
 | 
					            self.hidden = false;
 | 
				
			||||||
            return true;
 | 
					            self.set_occlusions();
 | 
				
			||||||
        }
 | 
					            true
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
            self.resize_helper(pipeline_id, new_size, epoch)
 | 
					            self.resize_helper(pipeline_id, new_size, epoch)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // A helper method to resize sublayers.
 | 
					    // A helper method to resize sublayers.
 | 
				
			||||||
    fn resize_helper(&mut self, pipeline_id: PipelineId, new_size: Size2D<f32>, epoch: Epoch) -> bool {
 | 
					    fn resize_helper(&mut self, pipeline_id: PipelineId, new_size: Size2D<f32>, epoch: Epoch) -> bool {
 | 
				
			||||||
        for child_node in self.children.mut_iter() {
 | 
					        let found = match self.children.iter().position(|x| pipeline_id == x.child.pipeline.id) {
 | 
				
			||||||
            if pipeline_id != child_node.child.pipeline.id {
 | 
					            Some(i) => {
 | 
				
			||||||
                loop;
 | 
					                let child_node = &mut self.children[i];
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
                let child = &mut child_node.child;
 | 
					                let child = &mut child_node.child;
 | 
				
			||||||
                child.epoch = epoch;
 | 
					                child.epoch = epoch;
 | 
				
			||||||
                child.page_size = Some(new_size);
 | 
					                child.page_size = Some(new_size);
 | 
				
			||||||
            // TODO: might get buffers back here
 | 
					 | 
				
			||||||
                match child.quadtree {
 | 
					                match child.quadtree {
 | 
				
			||||||
                Tree(ref mut quadtree) => quadtree.resize(new_size.width as uint, new_size.height as uint),
 | 
					                    Tree(ref mut quadtree) => {
 | 
				
			||||||
                NoTree(tile_size, max_mem) => child.quadtree = Tree(Quadtree::new(new_size.width as uint,
 | 
					                        child.pipeline.render_chan.send(UnusedBufferMsg(quadtree.resize(new_size.width as uint,
 | 
				
			||||||
 | 
					                                                                                        new_size.height as uint)));
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    NoTree(tile_size, max_mem) => {
 | 
				
			||||||
 | 
					                        child.quadtree = Tree(Quadtree::new(new_size.width as uint,
 | 
				
			||||||
                                                            new_size.height as uint,
 | 
					                                                            new_size.height as uint,
 | 
				
			||||||
                                                            tile_size,
 | 
					                                                            tile_size,
 | 
				
			||||||
                                                                                  max_mem)),
 | 
					                                                            max_mem));
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                match child_node.container.scissor {
 | 
					                match child_node.container.scissor {
 | 
				
			||||||
                    Some(scissor) => {
 | 
					                    Some(scissor) => {
 | 
				
			||||||
| 
						 | 
					@ -320,12 +346,19 @@ impl CompositorLayer {
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    None => {} // Nothing to do
 | 
					                    None => {} // Nothing to do
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            return true;
 | 
					                true
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            None => false,
 | 
				
			||||||
 | 
					        }; 
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
 | 
					        if found { // Boolean flag to get around double borrow of self
 | 
				
			||||||
 | 
					            self.set_occlusions();
 | 
				
			||||||
 | 
					            true
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
            // ID does not match ours, so recurse on descendents (including hidden children)
 | 
					            // ID does not match ours, so recurse on descendents (including hidden children)
 | 
				
			||||||
            self.children.mut_iter().map(|x| &mut x.child).any(|x| x.resize_helper(pipeline_id, new_size, epoch))
 | 
					            self.children.mut_iter().map(|x| &mut x.child).any(|x| x.resize_helper(pipeline_id, new_size, epoch))
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Collect buffers from the quadtree. This method IS NOT recursive, so child CompositorLayers
 | 
					    // Collect buffers from the quadtree. This method IS NOT recursive, so child CompositorLayers
 | 
				
			||||||
    // are not rebuilt directly from this method.
 | 
					    // are not rebuilt directly from this method.
 | 
				
			||||||
| 
						 | 
					@ -342,25 +375,9 @@ impl CompositorLayer {
 | 
				
			||||||
            self.root_layer.remove_child(trash);
 | 
					            self.root_layer.remove_child(trash);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Add child layers.
 | 
					 | 
				
			||||||
        for child in self.children.mut_iter().filter(|x| !x.child.hidden) {
 | 
					 | 
				
			||||||
            current_layer_child = match current_layer_child {
 | 
					 | 
				
			||||||
                None => {
 | 
					 | 
				
			||||||
                    child.container.common.parent = None;
 | 
					 | 
				
			||||||
                    child.container.common.prev_sibling = None;
 | 
					 | 
				
			||||||
                    child.container.common.next_sibling = None;
 | 
					 | 
				
			||||||
                    self.root_layer.add_child(ContainerLayerKind(child.container));
 | 
					 | 
				
			||||||
                    None
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                Some(_) => {
 | 
					 | 
				
			||||||
                    fail!("CompositorLayer: Layer tree failed to delete");
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Add new tiles.
 | 
					        // Add new tiles.
 | 
				
			||||||
        let quadtree = match self.quadtree {
 | 
					        let quadtree = match self.quadtree {
 | 
				
			||||||
            NoTree(_, _) => fail!("CompositorLayer: cannot get buffer request for %?,
 | 
					            NoTree(*) => fail!("CompositorLayer: cannot build layer tree for %?,
 | 
				
			||||||
                               no quadtree initialized", self.pipeline.id),
 | 
					                               no quadtree initialized", self.pipeline.id),
 | 
				
			||||||
            Tree(ref mut quadtree) => quadtree,
 | 
					            Tree(ref mut quadtree) => quadtree,
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
| 
						 | 
					@ -376,7 +393,7 @@ impl CompositorLayer {
 | 
				
			||||||
                    debug!("osmain: adding new texture layer");
 | 
					                    debug!("osmain: adding new texture layer");
 | 
				
			||||||
                    texture_layer = @mut TextureLayer::new(@buffer.draw_target.clone() as @TextureManager,
 | 
					                    texture_layer = @mut TextureLayer::new(@buffer.draw_target.clone() as @TextureManager,
 | 
				
			||||||
                                                           buffer.screen_pos.size);
 | 
					                                                           buffer.screen_pos.size);
 | 
				
			||||||
                    self.root_layer.add_child(TextureLayerKind(texture_layer));
 | 
					                    self.root_layer.add_child_end(TextureLayerKind(texture_layer));
 | 
				
			||||||
                    None
 | 
					                    None
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                Some(TextureLayerKind(existing_texture_layer)) => {
 | 
					                Some(TextureLayerKind(existing_texture_layer)) => {
 | 
				
			||||||
| 
						 | 
					@ -399,6 +416,23 @@ impl CompositorLayer {
 | 
				
			||||||
            texture_layer.common.set_transform(transform);
 | 
					            texture_layer.common.set_transform(transform);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Add child layers.
 | 
				
			||||||
 | 
					        for child in self.children.mut_iter().filter(|x| !x.child.hidden) {
 | 
				
			||||||
 | 
					            current_layer_child = match current_layer_child {
 | 
				
			||||||
 | 
					                None => {
 | 
				
			||||||
 | 
					                    child.container.common.parent = None;
 | 
				
			||||||
 | 
					                    child.container.common.prev_sibling = None;
 | 
				
			||||||
 | 
					                    child.container.common.next_sibling = None;
 | 
				
			||||||
 | 
					                    self.root_layer.add_child_end(ContainerLayerKind(child.container));
 | 
				
			||||||
 | 
					                    None
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                Some(_) => {
 | 
				
			||||||
 | 
					                    fail!("CompositorLayer: Layer tree failed to delete");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Add LayerBuffers to the specified layer. Returns false if the layer is not found.
 | 
					    // Add LayerBuffers to the specified layer. Returns false if the layer is not found.
 | 
				
			||||||
| 
						 | 
					@ -408,12 +442,12 @@ impl CompositorLayer {
 | 
				
			||||||
        if self.pipeline.id == pipeline_id {
 | 
					        if self.pipeline.id == pipeline_id {
 | 
				
			||||||
            if self.epoch != epoch {
 | 
					            if self.epoch != epoch {
 | 
				
			||||||
                debug!("compositor epoch mismatch: %? != %?, id: %?", self.epoch, epoch, self.pipeline.id);
 | 
					                debug!("compositor epoch mismatch: %? != %?, id: %?", self.epoch, epoch, self.pipeline.id);
 | 
				
			||||||
                // TODO: send buffers back
 | 
					                self.pipeline.render_chan.send(UnusedBufferMsg(cell.take().buffers));
 | 
				
			||||||
                return true;
 | 
					                return true;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            { // block here to prevent double mutable borrow of self
 | 
					            { // block here to prevent double mutable borrow of self
 | 
				
			||||||
                let quadtree = match self.quadtree {
 | 
					                let quadtree = match self.quadtree {
 | 
				
			||||||
                    NoTree(_, _) => fail!("CompositorLayer: cannot add buffers, no quadtree initialized"),
 | 
					                    NoTree(*) => fail!("CompositorLayer: cannot add buffers, no quadtree initialized"),
 | 
				
			||||||
                    Tree(ref mut quadtree) => quadtree,
 | 
					                    Tree(ref mut quadtree) => quadtree,
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
| 
						 | 
					@ -429,18 +463,37 @@ impl CompositorLayer {
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            self.build_layer_tree();
 | 
					            self.build_layer_tree();
 | 
				
			||||||
            return true;
 | 
					            true
 | 
				
			||||||
        }
 | 
					        } else { 
 | 
				
			||||||
                // ID does not match ours, so recurse on descendents (including hidden children).
 | 
					                // ID does not match ours, so recurse on descendents (including hidden children).
 | 
				
			||||||
        self.children.mut_iter().map(|x| &mut x.child).any(|x| x.add_buffers(pipeline_id, cell.take(), epoch))
 | 
					                self.children.mut_iter().map(|x| &mut x.child)
 | 
				
			||||||
 | 
					                    .any(|x| x.add_buffers(pipeline_id, cell.take(), epoch))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Deletes a specified sublayer, including hidden children. Returns false if the layer is not found.
 | 
					    // Deletes a specified sublayer, including hidden children. Returns false if the layer is not found.
 | 
				
			||||||
    pub fn delete(&mut self, pipeline_id: PipelineId) -> bool {
 | 
					    pub fn delete(&mut self, pipeline_id: PipelineId) -> bool {
 | 
				
			||||||
        match self.children.rposition(|x| x.child.pipeline.id == pipeline_id) {
 | 
					        match self.children.iter().position(|x| x.child.pipeline.id == pipeline_id) {
 | 
				
			||||||
            Some(index) => {
 | 
					            Some(i) => {
 | 
				
			||||||
                // TODO: send buffers back to renderer when layer is deleted
 | 
					                let mut child = self.children.remove(i);
 | 
				
			||||||
                self.children.remove(index);
 | 
					                match self.quadtree {
 | 
				
			||||||
 | 
					                    NoTree(*) => {} // Nothing to do
 | 
				
			||||||
 | 
					                    Tree(ref mut quadtree) => {
 | 
				
			||||||
 | 
					                        match child.container.scissor {
 | 
				
			||||||
 | 
					                            Some(rect) => {
 | 
				
			||||||
 | 
					                                quadtree.set_status_page(rect, Normal, false); // Unhide this rect
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                            None => {} // Nothing to do
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                match child.child.quadtree {
 | 
				
			||||||
 | 
					                    NoTree(*) => {} // Nothing to do
 | 
				
			||||||
 | 
					                    Tree(ref mut quadtree) => {
 | 
				
			||||||
 | 
					                        // Send back all tiles to renderer.
 | 
				
			||||||
 | 
					                        child.child.pipeline.render_chan.send(UnusedBufferMsg(quadtree.collect_tiles()));
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
                self.build_layer_tree();
 | 
					                self.build_layer_tree();
 | 
				
			||||||
                true
 | 
					                true
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -453,15 +506,16 @@ impl CompositorLayer {
 | 
				
			||||||
    pub fn invalidate_rect(&mut self, pipeline_id: PipelineId, rect: Rect<f32>) -> bool {
 | 
					    pub fn invalidate_rect(&mut self, pipeline_id: PipelineId, rect: Rect<f32>) -> bool {
 | 
				
			||||||
        if self.pipeline.id == pipeline_id {
 | 
					        if self.pipeline.id == pipeline_id {
 | 
				
			||||||
            let quadtree = match self.quadtree {
 | 
					            let quadtree = match self.quadtree {
 | 
				
			||||||
                NoTree(_, _) => return true, // Nothing to do
 | 
					                NoTree(*) => return true, // Nothing to do
 | 
				
			||||||
                Tree(ref mut quadtree) => quadtree,
 | 
					                Tree(ref mut quadtree) => quadtree,
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
            quadtree.set_status_page(rect, Invalid, true);
 | 
					            quadtree.set_status_page(rect, Invalid, true);
 | 
				
			||||||
            return true;
 | 
					            true
 | 
				
			||||||
        }
 | 
					        } else {
 | 
				
			||||||
            // ID does not match ours, so recurse on descendents (including hidden children).
 | 
					            // ID does not match ours, so recurse on descendents (including hidden children).
 | 
				
			||||||
            self.children.mut_iter().map(|x| &mut x.child).any(|x| x.invalidate_rect(pipeline_id, rect))
 | 
					            self.children.mut_iter().map(|x| &mut x.child).any(|x| x.invalidate_rect(pipeline_id, rect))
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Adds a child.
 | 
					    // Adds a child.
 | 
				
			||||||
    pub fn add_child(&mut self, pipeline: Pipeline, page_size: Option<Size2D<f32>>, tile_size: uint,
 | 
					    pub fn add_child(&mut self, pipeline: Pipeline, page_size: Option<Size2D<f32>>, tile_size: uint,
 | 
				
			||||||
| 
						 | 
					@ -472,11 +526,31 @@ impl CompositorLayer {
 | 
				
			||||||
                                                            clipping_rect.origin.y,
 | 
					                                                            clipping_rect.origin.y,
 | 
				
			||||||
                                                            0.0));
 | 
					                                                            0.0));
 | 
				
			||||||
        let child = ~CompositorLayer::new(pipeline, page_size, tile_size, max_mem);
 | 
					        let child = ~CompositorLayer::new(pipeline, page_size, tile_size, max_mem);
 | 
				
			||||||
        container.add_child(ContainerLayerKind(child.root_layer));
 | 
					        container.add_child_start(ContainerLayerKind(child.root_layer));
 | 
				
			||||||
        self.children.push(CompositorLayerChild {
 | 
					        self.children.push(CompositorLayerChild {
 | 
				
			||||||
            child: child,
 | 
					            child: child,
 | 
				
			||||||
            container: container,
 | 
					            container: container,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					        self.set_occlusions();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Recursively sets occluded portions of quadtrees to Hidden, so that they do not ask for
 | 
				
			||||||
 | 
					    // tile requests. If layers are moved, resized, or deleted, these portions may be updated.
 | 
				
			||||||
 | 
					    fn set_occlusions(&mut self) {
 | 
				
			||||||
 | 
					        let quadtree = match self.quadtree {
 | 
				
			||||||
 | 
					            NoTree(*) => return, // Cannot calculate occlusions
 | 
				
			||||||
 | 
					            Tree(ref mut quadtree) => quadtree,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        for child in self.children.iter().filter(|x| !x.child.hidden) {
 | 
				
			||||||
 | 
					            match child.container.scissor {
 | 
				
			||||||
 | 
					                None => {} // Nothing to do
 | 
				
			||||||
 | 
					                Some(rect) => {
 | 
				
			||||||
 | 
					                    quadtree.set_status_page(rect, Hidden, false);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        for child in self.children.mut_iter().filter(|x| !x.child.hidden) {
 | 
				
			||||||
 | 
					            child.child.set_occlusions();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -263,7 +263,7 @@ impl CompositorTask {
 | 
				
			||||||
                        let layer = CompositorLayer::from_frame_tree(frame_tree,
 | 
					                        let layer = CompositorLayer::from_frame_tree(frame_tree,
 | 
				
			||||||
                                                                     self.opts.tile_size,
 | 
					                                                                     self.opts.tile_size,
 | 
				
			||||||
                                                                     Some(10000000u));
 | 
					                                                                     Some(10000000u));
 | 
				
			||||||
                        root_layer.add_child(ContainerLayerKind(layer.root_layer));
 | 
					                        root_layer.add_child_start(ContainerLayerKind(layer.root_layer));
 | 
				
			||||||
                        compositor_layer = Some(layer);
 | 
					                        compositor_layer = Some(layer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        constellation_chan = Some(new_constellation_chan);
 | 
					                        constellation_chan = Some(new_constellation_chan);
 | 
				
			||||||
| 
						 | 
					@ -294,7 +294,7 @@ impl CompositorTask {
 | 
				
			||||||
                            Some(old_layer) => root_layer.remove_child(old_layer),
 | 
					                            Some(old_layer) => root_layer.remove_child(old_layer),
 | 
				
			||||||
                            None => {}
 | 
					                            None => {}
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        root_layer.add_child(ContainerLayerKind(new_layer.root_layer));
 | 
					                        root_layer.add_child_start(ContainerLayerKind(new_layer.root_layer));
 | 
				
			||||||
                        compositor_layer = Some(new_layer);
 | 
					                        compositor_layer = Some(new_layer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        ask_for_tiles();
 | 
					                        ask_for_tiles();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -217,14 +217,13 @@ impl<T: Tile> Quadtree<T> {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Creates a new quadtree at the specified size. This should be called when the window changes size.
 | 
					    /// Creates a new quadtree at the specified size. This should be called when the window changes size.
 | 
				
			||||||
    /// TODO: return old tiles.
 | 
					    pub fn resize(&mut self, width: uint, height: uint) -> ~[T] {
 | 
				
			||||||
    pub fn resize(&mut self, width: uint, height: uint) {
 | 
					 | 
				
			||||||
        // Spaces must be squares and powers of 2, so expand the space until it is
 | 
					        // Spaces must be squares and powers of 2, so expand the space until it is
 | 
				
			||||||
        let longer = width.max(&height);
 | 
					        let longer = width.max(&height);
 | 
				
			||||||
        let num_tiles = div_ceil(longer, self.max_tile_size);
 | 
					        let num_tiles = div_ceil(longer, self.max_tile_size);
 | 
				
			||||||
        let power_of_two = next_power_of_two(num_tiles);
 | 
					        let power_of_two = next_power_of_two(num_tiles);
 | 
				
			||||||
        let size = power_of_two * self.max_tile_size;
 | 
					        let size = power_of_two * self.max_tile_size;
 | 
				
			||||||
        
 | 
					        let ret = self.root.collect_tiles();
 | 
				
			||||||
        self.root = ~QuadtreeNode {
 | 
					        self.root = ~QuadtreeNode {
 | 
				
			||||||
            tile: None,
 | 
					            tile: None,
 | 
				
			||||||
            origin: Point2D(0f32, 0f32),
 | 
					            origin: Point2D(0f32, 0f32),
 | 
				
			||||||
| 
						 | 
					@ -234,6 +233,7 @@ impl<T: Tile> Quadtree<T> {
 | 
				
			||||||
            tile_mem: 0,
 | 
					            tile_mem: 0,
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        self.clip_size = Size2D(width, height);
 | 
					        self.clip_size = Size2D(width, height);
 | 
				
			||||||
 | 
					        ret
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Resize the underlying quadtree without removing tiles already in place.
 | 
					    /// Resize the underlying quadtree without removing tiles already in place.
 | 
				
			||||||
| 
						 | 
					@ -290,6 +290,12 @@ impl<T: Tile> Quadtree<T> {
 | 
				
			||||||
        self.root.set_status(rect, status, include_border);
 | 
					        self.root.set_status(rect, status, include_border);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Remove and return all tiles in the tree. Use this before deleting the quadtree to prevent
 | 
				
			||||||
 | 
					    /// a GC pause.
 | 
				
			||||||
 | 
					    pub fn collect_tiles(&mut self) -> ~[T] {
 | 
				
			||||||
 | 
					        self.root.collect_tiles()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Generate html to visualize the tree. For debugging purposes only.
 | 
					    /// Generate html to visualize the tree. For debugging purposes only.
 | 
				
			||||||
    pub fn get_html(&self) -> ~str {
 | 
					    pub fn get_html(&self) -> ~str {
 | 
				
			||||||
        static HEADER: &'static str = "<!DOCTYPE html><html>";
 | 
					        static HEADER: &'static str = "<!DOCTYPE html><html>";
 | 
				
			||||||
| 
						 | 
					@ -340,10 +346,15 @@ impl<T: Tile> QuadtreeNode<T> {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Get all tiles in the tree, parents last.
 | 
					    /// Get all tiles in the tree, parents first.
 | 
				
			||||||
    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 = ret + ~[tile],
 | 
				
			||||||
 | 
					            None => {}
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for quad in self.quadrants.iter() {
 | 
					        for quad in self.quadrants.iter() {
 | 
				
			||||||
            match *quad {
 | 
					            match *quad {
 | 
				
			||||||
                Some(ref child) => ret = ret + child.get_all_tiles(),
 | 
					                Some(ref child) => ret = ret + child.get_all_tiles(),
 | 
				
			||||||
| 
						 | 
					@ -351,12 +362,6 @@ impl<T: Tile> QuadtreeNode<T> {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        match self.tile {
 | 
					 | 
				
			||||||
            Some(ref tile) => ret = ret + ~[tile],
 | 
					 | 
				
			||||||
            None => {}
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return ret;
 | 
					        return ret;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue