diff options
author | Glenn Watson <gw@intuitionlibrary.com> | 2015-08-13 09:46:58 +1000 |
---|---|---|
committer | Glenn Watson <gw@intuitionlibrary.com> | 2015-08-13 09:46:58 +1000 |
commit | 6506468e193be9363972ce58e70cf93755f9f8ec (patch) | |
tree | f05547cad57ec7993ef74bc9f2db09520984ad97 /components/compositing | |
parent | e44ae6404fd25ed51a543141ca8f9cc2a3443817 (diff) | |
download | servo-6506468e193be9363972ce58e70cf93755f9f8ec.tar.gz servo-6506468e193be9363972ce58e70cf93755f9f8ec.zip |
Ensure compositor layers are collected when removed from layout.
Diffstat (limited to 'components/compositing')
-rw-r--r-- | components/compositing/compositor.rs | 12 | ||||
-rw-r--r-- | components/compositing/compositor_layer.rs | 45 |
2 files changed, 57 insertions, 0 deletions
diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index c7fc95d59a7..d70956e906e 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -379,6 +379,7 @@ impl<Window: WindowMethods> IOCompositor<Window> { (Msg::InitializeLayersForPipeline(pipeline_id, epoch, properties), ShutdownState::NotShuttingDown) => { self.get_or_create_pipeline_details(pipeline_id).current_epoch = epoch; + self.collect_old_layers(pipeline_id, &properties); for (index, layer_properties) in properties.iter().enumerate() { if index == 0 { self.create_or_update_base_layer(pipeline_id, *layer_properties); @@ -671,6 +672,17 @@ impl<Window: WindowMethods> IOCompositor<Window> { self.find_layer_with_pipeline_and_layer_id(pipeline_id, LayerId::null()) } + fn collect_old_layers(&mut self, + pipeline_id: PipelineId, + new_layers: &Vec<LayerProperties>) { + let root_layer = match self.scene.root { + Some(ref root_layer) => root_layer.clone(), + None => return, + }; + + root_layer.collect_old_layers(self, pipeline_id, new_layers); + } + fn remove_pipeline_root_layer(&mut self, pipeline_id: PipelineId) { let root_layer = match self.scene.root { Some(ref root_layer) => root_layer.clone(), diff --git a/components/compositing/compositor_layer.rs b/components/compositing/compositor_layer.rs index 0d3c27ab53f..380660be6b5 100644 --- a/components/compositing/compositor_layer.rs +++ b/components/compositing/compositor_layer.rs @@ -98,6 +98,14 @@ pub trait CompositorLayer { pipeline_id: PipelineId) where Window: WindowMethods; + /// Traverses the existing layer hierarchy and removes any layers that + /// currently exist but which are no longer required. + fn collect_old_layers<Window>(&self, + compositor: &mut IOCompositor<Window>, + pipeline_id: PipelineId, + new_layers: &Vec<LayerProperties>) + where Window: WindowMethods; + /// Destroys all tiles of all layers, including children, *without* sending them back to the /// painter. You must call this only when the paint task is destined to be going down; /// otherwise, you will leak tiles. @@ -272,6 +280,43 @@ impl CompositorLayer for Layer<CompositorData> { } } + fn collect_old_layers<Window>(&self, + compositor: &mut IOCompositor<Window>, + pipeline_id: PipelineId, + new_layers: &Vec<LayerProperties>) + where Window: WindowMethods { + // Traverse children first so that layers are removed + // bottom up - allowing each layer being removed to properly + // clean up any tiles it owns. + for kid in self.children().iter() { + kid.collect_old_layers(compositor, pipeline_id, new_layers); + } + + // Retain child layers that also exist in the new layer list. + self.children().retain(|child| { + let extra_data = child.extra_data.borrow(); + + // Never remove root layers or layers from other pipelines. + if pipeline_id != extra_data.pipeline_id || + extra_data.id == LayerId::null() { + true + } else { + // Keep this layer if it exists in the new layer list. + let keep_layer = new_layers.iter().position(|properties| { + properties.id == extra_data.id + }).is_some(); + + // When removing a layer, clear any tiles and surfaces + // associated with the layer. + if !keep_layer { + child.clear_all_tiles(compositor); + } + + keep_layer + } + }); + } + /// Destroys all tiles of all layers, including children, *without* sending them back to the /// painter. You must call this only when the paint task is destined to be going down; /// otherwise, you will leak tiles. |