diff --git a/Cargo.lock b/Cargo.lock index 8b8d751d90..537737c51f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,8 +6,8 @@ dependencies = [ "euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "gleam 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", "glutin 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender 0.8.1", - "webrender_traits 0.8.1", + "webrender 0.9.0", + "webrender_traits 0.9.0", ] [[package]] @@ -789,7 +789,7 @@ dependencies = [ [[package]] name = "webrender" -version = "0.8.1" +version = "0.9.0" dependencies = [ "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -810,12 +810,12 @@ dependencies = [ "offscreen_gl_context 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_traits 0.8.1", + "webrender_traits 0.9.0", ] [[package]] name = "webrender_traits" -version = "0.8.1" +version = "0.9.0" dependencies = [ "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -850,8 +850,8 @@ dependencies = [ "euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "gleam 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", "glutin 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender 0.8.1", - "webrender_traits 0.8.1", + "webrender 0.9.0", + "webrender_traits 0.9.0", ] [[package]] diff --git a/sample/src/main.rs b/sample/src/main.rs index 39849a2b1e..24d18c40db 100644 --- a/sample/src/main.rs +++ b/sample/src/main.rs @@ -1,4 +1,3 @@ -extern crate app_units; extern crate webrender; extern crate glutin; extern crate gleam; @@ -9,9 +8,8 @@ use euclid::{Size2D, Point2D, Rect, Matrix4D}; use gleam::gl; use std::path::PathBuf; use std::ffi::CStr; -use webrender_traits::{PipelineId, StackingContextId, DisplayListId}; -use webrender_traits::{AuxiliaryListsBuilder, Epoch, ColorF, GlyphInstance}; -use webrender_traits::{ImageFormat, RendererKind}; +use webrender_traits::{AuxiliaryListsBuilder, ColorF, Epoch, GlyphInstance}; +use webrender_traits::{ImageFormat, PipelineId, RendererKind}; use std::fs::File; use std::io::Read; use std::env; @@ -36,54 +34,10 @@ impl Notifier { } pub struct WebRenderFrameBuilder { - pub stacking_contexts: Vec<(StackingContextId, webrender_traits::StackingContext)>, - pub display_lists: Vec<(DisplayListId, webrender_traits::BuiltDisplayList)>, - pub auxiliary_lists_builder: AuxiliaryListsBuilder, pub root_pipeline_id: PipelineId, pub next_scroll_layer_id: usize, } -impl WebRenderFrameBuilder { - pub fn new(root_pipeline_id: PipelineId) -> WebRenderFrameBuilder { - WebRenderFrameBuilder { - stacking_contexts: vec![], - display_lists: vec![], - auxiliary_lists_builder: AuxiliaryListsBuilder::new(), - root_pipeline_id: root_pipeline_id, - next_scroll_layer_id: 0, - } - } - - pub fn add_stacking_context(&mut self, - api: &mut webrender_traits::RenderApi, - pipeline_id: PipelineId, - stacking_context: webrender_traits::StackingContext) - -> StackingContextId { - assert!(pipeline_id == self.root_pipeline_id); - let id = api.next_stacking_context_id(); - self.stacking_contexts.push((id, stacking_context)); - id - } - - pub fn add_display_list(&mut self, - api: &mut webrender_traits::RenderApi, - display_list: webrender_traits::BuiltDisplayList, - stacking_context: &mut webrender_traits::StackingContext) - -> DisplayListId { - let id = api.next_display_list_id(); - stacking_context.display_lists.push(id); - self.display_lists.push((id, display_list)); - id - } - - pub fn next_scroll_layer_id(&mut self) -> webrender_traits::ScrollLayerId { - let scroll_layer_id = webrender_traits::ServoScrollRootId(self.next_scroll_layer_id); - self.next_scroll_layer_id += 1; - webrender_traits::ScrollLayerId::new(self.root_pipeline_id, 0, scroll_layer_id) - } - -} - impl webrender_traits::RenderNotifier for Notifier { fn new_frame_ready(&mut self) { self.window_proxy.wakeup_event_loop(); @@ -144,7 +98,7 @@ fn main() { }; let (mut renderer, sender) = webrender::renderer::Renderer::new(opts); - let mut api = sender.create_api(); + let api = sender.create_api(); // let font_path = "/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf"; // let font_bytes = load_file(font_path); @@ -157,11 +111,15 @@ fn main() { let epoch = Epoch(0); let root_background_color = ColorF::new(0.3, 0.0, 0.0, 1.0); - let mut frame_builder = WebRenderFrameBuilder::new(pipeline_id); - let root_scroll_layer_id = frame_builder.next_scroll_layer_id(); + let mut auxiliary_lists_builder = AuxiliaryListsBuilder::new(); + let mut builder = webrender_traits::DisplayListBuilder::new(); + + let root_scroll_layer_id = + webrender_traits::ScrollLayerId::new(pipeline_id, 0, + webrender_traits::ServoScrollRootId(0)); let bounds = Rect::new(Point2D::new(0.0, 0.0), Size2D::new(width as f32, height as f32)); - let mut sc = + builder.push_stacking_context( webrender_traits::StackingContext::new(Some(root_scroll_layer_id), webrender_traits::ScrollPolicy::Scrollable, bounds, @@ -172,9 +130,7 @@ fn main() { true, webrender_traits::MixBlendMode::Normal, Vec::new(), - &mut frame_builder.auxiliary_lists_builder); - - let mut builder = webrender_traits::DisplayListBuilder::new(); + &mut auxiliary_lists_builder)); let clip_region = { let rect = Rect::new(Point2D::new(100.0, 100.0), Size2D::new(100.0, 100.0)); @@ -189,7 +145,7 @@ fn main() { webrender_traits::ClipRegion::new(&bounds, vec![complex], Some(mask), - &mut frame_builder.auxiliary_lists_builder) + &mut auxiliary_lists_builder) }; builder.push_rect(Rect::new(Point2D::new(100.0, 100.0), Size2D::new(100.0, 100.0)), @@ -270,19 +226,15 @@ fn main() { // Au::from_px(0), // &mut frame_builder.auxiliary_lists_builder); - frame_builder.add_display_list(&mut api, builder.finalize(), &mut sc); - let sc_id = frame_builder.add_stacking_context(&mut api, pipeline_id, sc); - - api.set_root_stacking_context(sc_id, - root_background_color, - epoch, - pipeline_id, - Size2D::new(width as f32, height as f32), - frame_builder.stacking_contexts, - frame_builder.display_lists, - frame_builder.auxiliary_lists_builder - .finalize()); + builder.pop_stacking_context(); + api.set_root_display_list( + root_background_color, + epoch, + pipeline_id, + Size2D::new(width as f32, height as f32), + builder.finalize(), + auxiliary_lists_builder.finalize()); api.set_root_pipeline(pipeline_id); for event in window.wait_events() { diff --git a/webrender/Cargo.toml b/webrender/Cargo.toml index 456ab82eb7..9f3e11e8a2 100644 --- a/webrender/Cargo.toml +++ b/webrender/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "webrender" -version = "0.8.1" +version = "0.9.0" authors = ["Glenn Watson "] license = "MPL-2.0" repository = "https://github.com/servo/webrender" diff --git a/webrender/src/frame.rs b/webrender/src/frame.rs index 24f25a2925..4e087abf65 100644 --- a/webrender/src/frame.rs +++ b/webrender/src/frame.rs @@ -12,13 +12,13 @@ use internal_types::{LowLevelFilterOp}; use internal_types::{RendererFrame}; use layer::{Layer, ScrollingState}; use resource_cache::{DummyResources, ResourceCache}; -use scene::{SceneStackingContext, ScenePipeline, Scene, SceneItem, SpecificSceneItem}; +use scene::Scene; use std::collections::{HashMap, HashSet}; use std::hash::BuildHasherDefault; use tiling::{AuxiliaryListsMap, FrameBuilder, FrameBuilderConfig, PrimitiveFlags}; use util::MatrixHelpers; use webrender_traits::{AuxiliaryLists, PipelineId, Epoch, ScrollPolicy, ScrollLayerId}; -use webrender_traits::{ClipRegion, ColorF, StackingContext, FilterOp, MixBlendMode}; +use webrender_traits::{ClipRegion, ColorF, DisplayItem, StackingContext, FilterOp, MixBlendMode}; use webrender_traits::{ScrollEventPhase, ScrollLayerInfo, SpecificDisplayItem, ScrollLayerState}; #[cfg(target_os = "macos")] @@ -33,23 +33,11 @@ pub struct FrameId(pub u32); static DEFAULT_SCROLLBAR_COLOR: ColorF = ColorF { r: 0.3, g: 0.3, b: 0.3, a: 0.6 }; struct FlattenContext<'a> { - resource_cache: &'a mut ResourceCache, scene: &'a Scene, pipeline_sizes: &'a mut HashMap>, builder: &'a mut FrameBuilder, } -#[derive(Debug)] -struct FlattenInfo { - // Pipeline this part of the tree belongs to. - pipeline_id: PipelineId, - - current_scroll_layer_id: ScrollLayerId, - current_fixed_layer_id: ScrollLayerId, - - layer_relative_transform: Matrix4D, -} - pub type LayerMap = HashMap>; // TODO: doc @@ -66,45 +54,16 @@ pub struct Frame { frame_builder: Option, } -enum SceneItemKind<'a> { - StackingContext(&'a SceneStackingContext, PipelineId), - Pipeline(&'a ScenePipeline) +trait DisplayListHelpers { + fn starting_stacking_context<'a>(&'a self) -> Option<&'a StackingContext>; } -#[derive(Clone)] -struct SceneItemWithZOrder { - item: SceneItem, - z_index: i32, -} - -impl<'a> SceneItemKind<'a> { - fn collect_scene_items(&self, scene: &Scene) -> Vec { - let mut result = Vec::new(); - let stacking_context = match *self { - SceneItemKind::StackingContext(stacking_context, _) => { - &stacking_context.stacking_context - } - SceneItemKind::Pipeline(pipeline) => { - if let Some(background_draw_list) = pipeline.background_draw_list { - result.push(SceneItem { - specific: SpecificSceneItem::DrawList(background_draw_list), - }); - } - - &scene.stacking_context_map - .get(&pipeline.root_stacking_context_id) - .unwrap() - .stacking_context - } - }; - - for display_list_id in &stacking_context.display_lists { - let display_list = &scene.display_list_map[display_list_id]; - for item in &display_list.items { - result.push(item.clone()); - } - } - result +impl DisplayListHelpers for Vec { + fn starting_stacking_context<'a>(&'a self) -> Option<&'a StackingContext> { + self.first().and_then(|item| match item.item { + SpecificDisplayItem::PushStackingContext(ref item) => Some(&item.stacking_context), + _ => None, + }) } } @@ -190,6 +149,56 @@ impl StackingContextHelpers for StackingContext { } } +struct DisplayListTraversal<'a> { + pub display_list: &'a [DisplayItem], + pub next_item_index: usize, +} + +impl<'a> DisplayListTraversal<'a> { + pub fn new_skipping_first(display_list: &'a Vec) -> DisplayListTraversal { + DisplayListTraversal { + display_list: display_list, + next_item_index: 1, + } + } + + pub fn skip_current_stacking_context(&mut self) { + for item in self { + if item.item == SpecificDisplayItem::PopStackingContext { + return; + } + } + } + + pub fn current_stacking_context_empty(&self) -> bool { + match self.peek() { + Some(item) => item.item == SpecificDisplayItem::PopStackingContext, + None => true, + } + } + + fn peek(&self) -> Option<&'a DisplayItem> { + if self.next_item_index >= self.display_list.len() { + return None + } + Some(&self.display_list[self.next_item_index]) + } +} + +impl<'a> Iterator for DisplayListTraversal<'a> { + type Item = &'a DisplayItem; + + fn next(&mut self) -> Option<&'a DisplayItem> { + if self.next_item_index >= self.display_list.len() { + return None + } + + let item = &self.display_list[self.next_item_index]; + self.next_item_index += 1; + Some(item) + } +} + impl Frame { pub fn new(debug: bool, config: FrameBuilderConfig) -> Frame { Frame { @@ -388,115 +397,127 @@ impl Frame { pub fn create(&mut self, scene: &Scene, - resource_cache: &mut ResourceCache, dummy_resources: &DummyResources, pipeline_sizes: &mut HashMap>, device_pixel_ratio: f32) { - if let Some(root_pipeline_id) = scene.root_pipeline_id { - if let Some(root_pipeline) = scene.pipeline_map.get(&root_pipeline_id) { - let old_layer_scrolling_states = self.reset(); - - self.pipeline_auxiliary_lists = scene.pipeline_auxiliary_lists.clone(); - - let root_stacking_context = scene.stacking_context_map - .get(&root_pipeline.root_stacking_context_id) - .unwrap(); - - let root_scroll_layer_id = root_stacking_context.stacking_context - .scroll_layer_id - .expect("root layer must be a scroll layer!"); - self.root_scroll_layer_id = Some(root_scroll_layer_id); - - // Insert global position: fixed elements layer - debug_assert!(self.layers.is_empty()); - let root_fixed_layer_id = ScrollLayerId::create_fixed(root_pipeline_id); - let root_viewport = Rect::new(Point2D::zero(), root_pipeline.viewport_size); - self.layers.insert( - root_fixed_layer_id, - Layer::new(&root_viewport, - root_stacking_context.stacking_context.overflow.size, - &Matrix4D::identity(), - root_pipeline_id)); + let root_pipeline_id = match scene.root_pipeline_id { + Some(root_pipeline_id) => root_pipeline_id, + None => return, + }; - self.layers.insert( - root_scroll_layer_id, - Layer::new(&root_viewport, - root_stacking_context.stacking_context.overflow.size, - &Matrix4D::identity(), - root_pipeline_id)); - - // Work around borrow check on resource cache - { - let mut frame_builder = FrameBuilder::new(root_pipeline.viewport_size, - device_pixel_ratio, - dummy_resources.clone(), - self.debug, - self.frame_builder_config); - - { - let mut context = FlattenContext { - resource_cache: resource_cache, - scene: scene, - pipeline_sizes: pipeline_sizes, - builder: &mut frame_builder, - }; - - let parent_info = FlattenInfo { - pipeline_id: root_pipeline_id, - current_fixed_layer_id: root_fixed_layer_id, - current_scroll_layer_id: root_scroll_layer_id, - layer_relative_transform: Matrix4D::identity(), - }; - - let root_pipeline = SceneItemKind::Pipeline(root_pipeline); - self.flatten(root_pipeline, - &parent_info, - &mut context, - 0); - } + let root_pipeline = match scene.pipeline_map.get(&root_pipeline_id) { + Some(root_pipeline) => root_pipeline, + None => return, + }; - self.frame_builder = Some(frame_builder); - } + let display_list = scene.display_lists.get(&root_pipeline_id); + let display_list = match display_list { + Some(display_list) => display_list, + None => return, + }; - // TODO(gw): These are all independent - can be run through thread pool if it shows up in the profile! - for (scroll_layer_id, layer) in &mut self.layers { - let scrolling_state = match old_layer_scrolling_states.get(&scroll_layer_id) { - Some(old_scrolling_state) => *old_scrolling_state, - None => ScrollingState::new(), - }; + let old_layer_scrolling_states = self.reset(); + self.pipeline_auxiliary_lists = scene.pipeline_auxiliary_lists.clone(); - layer.finalize(&scrolling_state); - } + self.pipeline_epoch_map.insert(root_pipeline_id, root_pipeline.epoch); + + let root_stacking_context = match display_list.starting_stacking_context() { + Some(stacking_context) => stacking_context, + None => { + warn!("Pipeline display list does not start with a stacking context."); + return; } + }; + + let root_scroll_layer_id = + root_stacking_context.scroll_layer_id + .expect("root layer must be a scroll layer!"); + self.root_scroll_layer_id = Some(root_scroll_layer_id); + + // Insert global position: fixed elements layer + debug_assert!(self.layers.is_empty()); + let root_fixed_layer_id = ScrollLayerId::create_fixed(root_pipeline_id); + let root_viewport = Rect::new(Point2D::zero(), root_pipeline.viewport_size); + let layer = Layer::new(&root_viewport, + root_stacking_context.overflow.size, + &Matrix4D::identity(), + root_pipeline_id); + self.layers.insert(root_fixed_layer_id, layer.clone()); + self.layers.insert(root_scroll_layer_id, layer); + + let mut frame_builder = FrameBuilder::new(root_pipeline.viewport_size, + device_pixel_ratio, + dummy_resources.clone(), + self.debug, + self.frame_builder_config); + + { + let mut context = FlattenContext { + scene: scene, + pipeline_sizes: pipeline_sizes, + builder: &mut frame_builder, + }; + + let mut traversal = DisplayListTraversal::new_skipping_first(display_list); + self.flatten_stacking_context(&mut traversal, + root_pipeline_id, + &mut context, + root_fixed_layer_id, + root_scroll_layer_id, + Matrix4D::identity(), + 0, + &root_stacking_context); + } + + self.frame_builder = Some(frame_builder); + + // TODO(gw): These are all independent - can be run through thread pool if it shows up + // in the profile! + for (scroll_layer_id, layer) in &mut self.layers { + let scrolling_state = match old_layer_scrolling_states.get(&scroll_layer_id) { + Some(old_scrolling_state) => *old_scrolling_state, + None => ScrollingState::new(), + }; + + layer.finalize(&scrolling_state); } } - fn flatten(&mut self, - scene_item: SceneItemKind, - parent_info: &FlattenInfo, - context: &mut FlattenContext, - level: i32) { - //let _pf = util::ProfileScope::new(" flatten"); + fn flatten_stacking_context<'a>(&mut self, + traversal: &mut DisplayListTraversal<'a>, + pipeline_id: PipelineId, + context: &mut FlattenContext, + current_fixed_layer_id: ScrollLayerId, + mut current_scroll_layer_id: ScrollLayerId, + mut layer_relative_transform: Matrix4D, + level: i32, + stacking_context: &StackingContext) { + // Avoid doing unnecessary work for empty stacking contexts. + if traversal.current_stacking_context_empty() { + traversal.skip_current_stacking_context(); + return; + } - let (stacking_context, pipeline_id) = match scene_item { - SceneItemKind::StackingContext(stacking_context, pipeline_id) => { - (&stacking_context.stacking_context, pipeline_id) - } - SceneItemKind::Pipeline(pipeline) => { - self.pipeline_epoch_map.insert(pipeline.pipeline_id, pipeline.epoch); + match (stacking_context.scroll_policy, stacking_context.scroll_layer_id) { + (ScrollPolicy::Scrollable, Some(inner_scroll_layer_id)) if level != 0 => { + debug_assert!(!self.layers.contains_key(&inner_scroll_layer_id)); - let stacking_context = &context.scene.stacking_context_map - .get(&pipeline.root_stacking_context_id) - .unwrap() - .stacking_context; + let layer = Layer::new(&stacking_context.bounds, + stacking_context.overflow.size, + &layer_relative_transform, + pipeline_id); - (stacking_context, pipeline.pipeline_id) - } - }; + debug_assert!(current_scroll_layer_id != inner_scroll_layer_id); + self.layers + .get_mut(¤t_scroll_layer_id) + .unwrap() + .add_child(inner_scroll_layer_id); - let scene_items = scene_item.collect_scene_items(&context.scene); - if scene_items.is_empty() { - return; + self.layers.insert(inner_scroll_layer_id, layer); + current_scroll_layer_id = inner_scroll_layer_id; + layer_relative_transform = Matrix4D::identity(); + } + _ => {} } let composition_operations = { @@ -509,7 +530,10 @@ impl Frame { // Detect composition operations that will make us invisible. for composition_operation in &composition_operations { match *composition_operation { - CompositionOp::Filter(LowLevelFilterOp::Opacity(Au(0))) => return, + CompositionOp::Filter(LowLevelFilterOp::Opacity(Au(0))) => { + traversal.skip_current_stacking_context(); + return; + } _ => {} } } @@ -520,32 +544,27 @@ impl Frame { // to account for them and we expand the overflow region to include the area above // their origin in the parent context. let (transform, overflow) = if stacking_context.scroll_layer_id.is_none() { - (parent_info.layer_relative_transform.pre_translated(stacking_context.bounds.origin.x, - stacking_context.bounds.origin.y, - 0.0) - .pre_mul(&stacking_context.transform) - .pre_mul(&stacking_context.perspective), + (layer_relative_transform.pre_translated(stacking_context.bounds.origin.x, + stacking_context.bounds.origin.y, + 0.0) + .pre_mul(&stacking_context.transform) + .pre_mul(&stacking_context.perspective), stacking_context.overflow) } else { let mut overflow = stacking_context.overflow; overflow.size.width += stacking_context.bounds.origin.x; overflow.size.height += stacking_context.bounds.origin.y; - (parent_info.layer_relative_transform, overflow) + (layer_relative_transform, overflow) }; // Build world space transform - let scroll_layer_id = match (stacking_context.scroll_policy, stacking_context.scroll_layer_id) { + let scroll_layer_id = match (stacking_context.scroll_policy, + stacking_context.scroll_layer_id) { (ScrollPolicy::Fixed, _scroll_layer_id) => { debug_assert!(_scroll_layer_id.is_none()); - parent_info.current_fixed_layer_id - } - (ScrollPolicy::Scrollable, Some(scroll_layer_id)) => { - debug_assert!(self.layers.contains_key(&scroll_layer_id)); - scroll_layer_id - } - (ScrollPolicy::Scrollable, None) => { - parent_info.current_scroll_layer_id + current_fixed_layer_id } + (ScrollPolicy::Scrollable, _) => current_scroll_layer_id }; // TODO(gw): Int with overflow etc @@ -557,196 +576,40 @@ impl Frame { &composition_operations); if level == 0 { - // Add a large white rectangle as the root display item. This is removed - // by the occlusion culling for most tiles, and means that it's no longer - // necessary to clear the framebuffer. + // Add a large white rectangle as the root display item if there is no root stacking + // context background color. This is removed by the occlusion culling for most tiles, + // and means that it's no longer necessary to clear the framebuffer. // - // TODO(nical) Should this be optional? - // on deferred GPUs we probably still want to clear the framebuffer and - // Gecko currently supports semit-transparent windows. - // Also, this is not needed if the root stacking context has an opaque - // background (specified in set_root_stacking_context). + // TODO(nical) Should painting a white background be optional if there is no stacking + // context background color? On deferred GPUs we probably still want to clear the + // framebuffer and Gecko currently supports semi-transparent windows. // // If we do need this, does it make sense to keep Frame::clear_tiles? + let mut root_background_color = match context.scene.pipeline_map.get(&pipeline_id) { + Some(pipeline) => pipeline.background_color, + None => ColorF::new(1.0, 1.0, 1.0, 1.0), + }; + + if root_background_color.a == 0.0 { + root_background_color = ColorF::new(1.0, 1.0, 1.0, 1.0); + } + context.builder.add_solid_rectangle(&stacking_context.bounds, &ClipRegion::simple(&stacking_context.bounds), - &ColorF::new(1.0, 1.0, 1.0, 1.0), + &root_background_color, PrimitiveFlags::None); } - for item in scene_items { - match item.specific { - SpecificSceneItem::DrawList(draw_list_id) => { - let draw_list = context.resource_cache.get_draw_list(draw_list_id); - let builder = &mut context.builder; - - for item in &draw_list.items { - match item.item { - SpecificDisplayItem::WebGL(ref info) => { - builder.add_webgl_rectangle(item.rect, - &item.clip, - info.context_id); - } - SpecificDisplayItem::Image(ref info) => { - builder.add_image(item.rect, - &item.clip, - &info.stretch_size, - &info.tile_spacing, - info.image_key, - info.image_rendering); - } - SpecificDisplayItem::Text(ref text_info) => { - builder.add_text(item.rect, - &item.clip, - text_info.font_key, - text_info.size, - text_info.blur_radius, - &text_info.color, - text_info.glyphs); - } - SpecificDisplayItem::Rectangle(ref info) => { - builder.add_solid_rectangle(&item.rect, - &item.clip, - &info.color, - PrimitiveFlags::None); - } - SpecificDisplayItem::Gradient(ref info) => { - builder.add_gradient(item.rect, - &item.clip, - info.start_point, - info.end_point, - info.stops); - } - SpecificDisplayItem::BoxShadow(ref box_shadow_info) => { - builder.add_box_shadow(&box_shadow_info.box_bounds, - &item.clip, - &box_shadow_info.offset, - &box_shadow_info.color, - box_shadow_info.blur_radius, - box_shadow_info.spread_radius, - box_shadow_info.border_radius, - box_shadow_info.clip_mode); - } - SpecificDisplayItem::Border(ref info) => { - builder.add_border(item.rect, - &item.clip, - info); - } - } - } - } - SpecificSceneItem::StackingContext(id, pipeline_id) => { - let child_stacking_context = context.scene - .stacking_context_map - .get(&id) - .unwrap(); - - let inner_stacking_context = &child_stacking_context.stacking_context; - - let mut next_scroll_layer_id = parent_info.current_scroll_layer_id; - let mut layer_relative_transform = transform; - - match (inner_stacking_context.scroll_policy, inner_stacking_context.scroll_layer_id) { - (ScrollPolicy::Scrollable, Some(inner_scroll_layer_id)) => { - debug_assert!(!self.layers.contains_key(&inner_scroll_layer_id)); - - let layer = Layer::new(&inner_stacking_context.bounds, - inner_stacking_context.overflow.size, - &transform, - parent_info.pipeline_id); - - debug_assert!(parent_info.current_scroll_layer_id != inner_scroll_layer_id); - self.layers - .get_mut(&scroll_layer_id) - .unwrap() - .add_child(inner_scroll_layer_id); - - self.layers.insert(inner_scroll_layer_id, layer); - next_scroll_layer_id = inner_scroll_layer_id; - layer_relative_transform = Matrix4D::identity(); - } - (ScrollPolicy::Fixed, _) | - (ScrollPolicy::Scrollable, None) => {} - } - - let child_info = FlattenInfo { - pipeline_id: parent_info.pipeline_id, - current_scroll_layer_id: next_scroll_layer_id, - current_fixed_layer_id: parent_info.current_fixed_layer_id, - layer_relative_transform: layer_relative_transform, - }; - - let child = SceneItemKind::StackingContext(child_stacking_context, - pipeline_id); - - self.flatten(child, - &child_info, - context, - level+1); - } - SpecificSceneItem::Iframe(ref iframe_info) => { - let pipeline = context.scene - .pipeline_map - .get(&iframe_info.id); - - context.pipeline_sizes.insert(iframe_info.id, - iframe_info.bounds.size); - - if let Some(pipeline) = pipeline { - let iframe = SceneItemKind::Pipeline(pipeline); - - let transform = transform.pre_translated(iframe_info.bounds.origin.x, - iframe_info.bounds.origin.y, - 0.0); - - let iframe_stacking_context = context.scene - .stacking_context_map - .get(&pipeline.root_stacking_context_id) - .unwrap(); - let iframe_stacking_context = &iframe_stacking_context.stacking_context; - let iframe_fixed_layer_id = ScrollLayerId::create_fixed(pipeline.pipeline_id); - let iframe_rect = &Rect::new(Point2D::zero(), iframe_info.bounds.size); - - self.layers - .insert(iframe_fixed_layer_id, - Layer::new(&iframe_rect, - iframe_stacking_context.overflow.size, - &transform, - pipeline.pipeline_id)); - - let iframe_scroll_layer_id = iframe_stacking_context.scroll_layer_id.unwrap(); - - self.layers - .insert(iframe_scroll_layer_id, - Layer::new(&iframe_rect, - iframe_stacking_context.overflow.size, - &transform, - pipeline.pipeline_id)); - - self.layers - .get_mut(&scroll_layer_id) - .unwrap() - .add_child(iframe_scroll_layer_id); - - let child_info = FlattenInfo { - pipeline_id: pipeline.pipeline_id, - current_scroll_layer_id: iframe_scroll_layer_id, - current_fixed_layer_id: iframe_fixed_layer_id, - layer_relative_transform: Matrix4D::identity(), - }; - - self.flatten(iframe, - &child_info, - context, - level+1); - } - } - } - } + self.flatten_items(traversal, + pipeline_id, + context, + current_fixed_layer_id, + current_scroll_layer_id, + transform, + level); if level == 0 && self.frame_builder_config.enable_scrollbars { - let scrollbar_rect = Rect::new(Point2D::zero(), - Size2D::new(10.0, 70.0)); + let scrollbar_rect = Rect::new(Point2D::zero(), Size2D::new(10.0, 70.0)); context.builder.add_solid_rectangle(&scrollbar_rect, &ClipRegion::simple(&scrollbar_rect), &DEFAULT_SCROLLBAR_COLOR, @@ -757,6 +620,141 @@ impl Frame { context.builder.pop_layer(); } + fn flatten_iframe<'a>(&mut self, + pipeline_id: PipelineId, + bounds: &Rect, + context: &mut FlattenContext, + current_scroll_layer_id: ScrollLayerId, + layer_relative_transform: Matrix4D) { + context.pipeline_sizes.insert(pipeline_id, bounds.size); + + let pipeline = match context.scene.pipeline_map.get(&pipeline_id) { + Some(pipeline) => pipeline, + None => return, + }; + + let display_list = context.scene.display_lists.get(&pipeline_id); + let display_list = match display_list { + Some(display_list) => display_list, + None => return, + }; + + let iframe_stacking_context = match display_list.starting_stacking_context() { + Some(stacking_context) => stacking_context, + None => { + warn!("Pipeline display list does not start with a stacking context."); + return; + } + }; + + self.pipeline_epoch_map.insert(pipeline_id, pipeline.epoch); + + let iframe_rect = &Rect::new(Point2D::zero(), bounds.size); + let transform = layer_relative_transform.pre_translated(bounds.origin.x, + bounds.origin.y, + 0.0); + + let iframe_fixed_layer_id = ScrollLayerId::create_fixed(pipeline_id); + let iframe_scroll_layer_id = iframe_stacking_context.scroll_layer_id.unwrap(); + + let layer = Layer::new(&iframe_rect, + iframe_stacking_context.overflow.size, + &transform, + pipeline_id); + self.layers.insert(iframe_fixed_layer_id, layer.clone()); + self.layers.insert(iframe_scroll_layer_id, layer); + self.layers.get_mut(¤t_scroll_layer_id).unwrap().add_child(iframe_scroll_layer_id); + + let mut traversal = DisplayListTraversal::new_skipping_first(display_list); + + self.flatten_stacking_context(&mut traversal, + pipeline_id, + context, + iframe_fixed_layer_id, + iframe_scroll_layer_id, + Matrix4D::identity(), + 0, + &iframe_stacking_context); + } + + fn flatten_items<'a>(&mut self, + traversal: &mut DisplayListTraversal<'a>, + pipeline_id: PipelineId, + context: &mut FlattenContext, + current_fixed_layer_id: ScrollLayerId, + current_scroll_layer_id: ScrollLayerId, + layer_relative_transform: Matrix4D, + level: i32) { + while let Some(item) = traversal.next() { + match item.item { + SpecificDisplayItem::WebGL(ref info) => { + context.builder.add_webgl_rectangle(item.rect, &item.clip, info.context_id); + } + SpecificDisplayItem::Image(ref info) => { + context.builder.add_image(item.rect, + &item.clip, + &info.stretch_size, + &info.tile_spacing, + info.image_key, + info.image_rendering); + } + SpecificDisplayItem::Text(ref text_info) => { + context.builder.add_text(item.rect, + &item.clip, + text_info.font_key, + text_info.size, + text_info.blur_radius, + &text_info.color, + text_info.glyphs); + } + SpecificDisplayItem::Rectangle(ref info) => { + context.builder.add_solid_rectangle(&item.rect, + &item.clip, + &info.color, + PrimitiveFlags::None); + } + SpecificDisplayItem::Gradient(ref info) => { + context.builder.add_gradient(item.rect, + &item.clip, + info.start_point, + info.end_point, + info.stops); + } + SpecificDisplayItem::BoxShadow(ref box_shadow_info) => { + context.builder.add_box_shadow(&box_shadow_info.box_bounds, + &item.clip, + &box_shadow_info.offset, + &box_shadow_info.color, + box_shadow_info.blur_radius, + box_shadow_info.spread_radius, + box_shadow_info.border_radius, + box_shadow_info.clip_mode); + } + SpecificDisplayItem::Border(ref info) => { + context.builder.add_border(item.rect, &item.clip, info); + } + SpecificDisplayItem::PushStackingContext(ref info) => { + self.flatten_stacking_context(traversal, + pipeline_id, + context, + current_fixed_layer_id, + current_scroll_layer_id, + layer_relative_transform, + level + 1, + &info.stacking_context); + } + SpecificDisplayItem::Iframe(ref info) => { + self.flatten_iframe(info.pipeline_id, + &item.rect, + context, + current_scroll_layer_id, + layer_relative_transform); + } + SpecificDisplayItem::PopStackingContext => return, + } + } + } + pub fn build(&mut self, resource_cache: &mut ResourceCache, auxiliary_lists_map: &AuxiliaryListsMap, diff --git a/webrender/src/internal_types.rs b/webrender/src/internal_types.rs index 1a606d535a..02be2ba110 100644 --- a/webrender/src/internal_types.rs +++ b/webrender/src/internal_types.rs @@ -6,7 +6,6 @@ use app_units::Au; use device::{TextureId, TextureFilter}; use euclid::{Point2D, Rect, Size2D, TypedRect, TypedPoint2D, TypedSize2D, Length, UnknownUnit}; use fnv::FnvHasher; -use freelist::{FreeListItem, FreeListItemId}; use offscreen_gl_context::{NativeGLContext, NativeGLContextHandle}; use offscreen_gl_context::{GLContext, NativeGLContextMethods, GLContextDispatcher}; use offscreen_gl_context::{OSMesaContext, OSMesaContextHandle}; @@ -20,7 +19,7 @@ use std::path::PathBuf; use std::sync::Arc; use tiling; use webrender_traits::{Epoch, ColorF, PipelineId}; -use webrender_traits::{ImageFormat, MixBlendMode, NativeFontHandle, DisplayItem}; +use webrender_traits::{ImageFormat, MixBlendMode, NativeFontHandle}; use webrender_traits::{ScrollLayerId, WebGLCommand}; pub enum GLContextHandleWrapper { @@ -162,8 +161,6 @@ pub enum FontTemplate { Native(NativeFontHandle), } -pub type DrawListId = FreeListItemId; - #[derive(Debug, PartialEq, Eq)] pub enum TextureSampler { Color0, @@ -418,36 +415,6 @@ pub enum AxisDirection { #[derive(Debug, Clone, Copy)] pub struct StackingContextIndex(pub usize); -#[derive(Debug)] -pub struct DrawList { - pub items: Vec, - pub stacking_context_index: Option, - pub pipeline_id: PipelineId, - // TODO(gw): Structure squat to remove this field. - next_free_id: Option, -} - -impl DrawList { - pub fn new(items: Vec, pipeline_id: PipelineId) -> DrawList { - DrawList { - items: items, - stacking_context_index: None, - pipeline_id: pipeline_id, - next_free_id: None, - } - } -} - -impl FreeListItem for DrawList { - fn next_free_id(&self) -> Option { - self.next_free_id - } - - fn set_next_free_id(&mut self, id: Option) { - self.next_free_id = id; - } -} - #[derive(Clone, Copy, Debug)] pub struct RectUv { pub top_left: TypedPoint2D, diff --git a/webrender/src/layer.rs b/webrender/src/layer.rs index f36ef7599a..0257214250 100644 --- a/webrender/src/layer.rs +++ b/webrender/src/layer.rs @@ -7,6 +7,7 @@ use spring::{DAMPING, STIFFNESS, Spring}; use webrender_traits::{PipelineId, ScrollLayerId}; /// Contains scroll and transform information for scrollable and root stacking contexts. +#[derive(Clone)] pub struct Layer { /// Manages scrolling offset, overscroll state etc. pub scrolling: ScrollingState, diff --git a/webrender/src/record.rs b/webrender/src/record.rs index 18fa2f4251..bf2f712542 100644 --- a/webrender/src/record.rs +++ b/webrender/src/record.rs @@ -19,9 +19,9 @@ pub fn write_msg(frame: u32, msg: &ApiMsg) { &ApiMsg::AddImage(..) | &ApiMsg::UpdateImage(..) | &ApiMsg::DeleteImage(..)| - &ApiMsg::SetRootStackingContext(..) | + &ApiMsg::SetRootDisplayList(..) | &ApiMsg::SetRootPipeline(..) | - &ApiMsg::Scroll(..)| + &ApiMsg::Scroll(..) | &ApiMsg::TickScrollingBounce | &ApiMsg::WebGLCommand(..) => { let buff = serialize(msg, bincode::SizeLimit::Infinite).unwrap(); diff --git a/webrender/src/render_backend.rs b/webrender/src/render_backend.rs index c7a02dcda3..2f8618dc8e 100644 --- a/webrender/src/render_backend.rs +++ b/webrender/src/render_backend.rs @@ -150,33 +150,21 @@ impl RenderBackend { sender.send(result).unwrap(); } - ApiMsg::SetRootStackingContext(stacking_context_id, - background_color, - epoch, - pipeline_id, - viewport_size, - stacking_contexts, - display_lists, - auxiliary_lists_descriptor) => { - for (id, stacking_context) in stacking_contexts.into_iter() { - self.scene.add_stacking_context(id, - pipeline_id, - epoch, - stacking_context); - } - + ApiMsg::SetRootDisplayList(background_color, + epoch, + pipeline_id, + viewport_size, + display_list_descriptor, + auxiliary_lists_descriptor) => { let mut leftover_auxiliary_data = vec![]; let mut auxiliary_data; loop { auxiliary_data = self.payload_rx.recv().unwrap(); { let mut payload_reader = Cursor::new(&auxiliary_data[..]); - let payload_stacking_context_id = - payload_reader.read_u32::().unwrap(); let payload_epoch = payload_reader.read_u32::().unwrap(); - if payload_epoch == epoch.0 && - payload_stacking_context_id == stacking_context_id.0 { + if payload_epoch == epoch.0 { break } } @@ -188,22 +176,14 @@ impl RenderBackend { if self.enable_recording { record::write_payload(frame_counter, &auxiliary_data); } - let mut auxiliary_data = Cursor::new(&mut auxiliary_data[8..]); - for (display_list_id, - display_list_descriptor) in display_lists.into_iter() { - let mut built_display_list_data = - vec![0; display_list_descriptor.size()]; - auxiliary_data.read_exact(&mut built_display_list_data[..]) - .unwrap(); - let built_display_list = - BuiltDisplayList::from_data(built_display_list_data, - display_list_descriptor); - self.scene.add_display_list(display_list_id, - pipeline_id, - epoch, - built_display_list, - &mut self.resource_cache); - } + + let mut auxiliary_data = Cursor::new(&mut auxiliary_data[4..]); + let mut built_display_list_data = + vec![0; display_list_descriptor.size()]; + auxiliary_data.read_exact(&mut built_display_list_data[..]).unwrap(); + let built_display_list = + BuiltDisplayList::from_data(built_display_list_data, + display_list_descriptor); let mut auxiliary_lists_data = vec![0; auxiliary_lists_descriptor.size()]; @@ -211,14 +191,14 @@ impl RenderBackend { let auxiliary_lists = AuxiliaryLists::from_data(auxiliary_lists_data, auxiliary_lists_descriptor); + let frame = profile_counters.total_time.profile(|| { - self.scene.set_root_stacking_context(pipeline_id, - epoch, - stacking_context_id, - background_color, - viewport_size, - &mut self.resource_cache, - auxiliary_lists); + self.scene.set_root_display_list(pipeline_id, + epoch, + built_display_list, + background_color, + viewport_size, + auxiliary_lists); self.build_scene(); self.render() @@ -362,7 +342,6 @@ impl RenderBackend { } self.frame.create(&self.scene, - &mut self.resource_cache, &self.dummy_resources, &mut new_pipeline_sizes, self.device_pixel_ratio); diff --git a/webrender/src/resource_cache.rs b/webrender/src/resource_cache.rs index 506fbdd424..57fc25f526 100644 --- a/webrender/src/resource_cache.rs +++ b/webrender/src/resource_cache.rs @@ -7,9 +7,7 @@ use device::{TextureFilter, TextureId}; use euclid::{Point2D, Size2D}; use fnv::FnvHasher; use frame::FrameId; -use freelist::FreeList; -use internal_types::FontTemplate; -use internal_types::{TextureUpdateList, DrawListId, DrawList}; +use internal_types::{FontTemplate, TextureUpdateList}; use platform::font::{FontContext, RasterizedGlyph}; use rayon::prelude::*; use std::cell::RefCell; @@ -19,8 +17,8 @@ use std::fmt::Debug; use std::hash::BuildHasherDefault; use std::hash::Hash; use texture_cache::{TextureCache, TextureCacheItem, TextureCacheItemId}; -use webrender_traits::{Epoch, FontKey, GlyphKey, ImageKey, ImageFormat, DisplayItem, ImageRendering}; -use webrender_traits::{FontRenderMode, GlyphDimensions, PipelineId, WebGLContextId}; +use webrender_traits::{Epoch, FontKey, GlyphKey, ImageKey, ImageFormat, ImageRendering}; +use webrender_traits::{FontRenderMode, GlyphDimensions, WebGLContextId}; thread_local!(pub static FONT_CONTEXT: RefCell = RefCell::new(FontContext::new())); @@ -180,7 +178,6 @@ pub struct ResourceCache { // TODO(pcwalton): Figure out the lifecycle of these. webgl_textures: HashMap>, - draw_lists: FreeList, font_templates: HashMap>, image_templates: HashMap>, device_pixel_ratio: f32, @@ -204,7 +201,6 @@ impl ResourceCache { cached_glyphs: ResourceClassCache::new(), cached_images: ResourceClassCache::new(), webgl_textures: HashMap::with_hasher(Default::default()), - draw_lists: FreeList::new(), font_templates: HashMap::with_hasher(Default::default()), image_templates: HashMap::with_hasher(Default::default()), cached_glyph_dimensions: HashMap::with_hasher(Default::default()), @@ -347,19 +343,6 @@ impl ResourceCache { } } - pub fn add_draw_list(&mut self, items: Vec, pipeline_id: PipelineId) - -> DrawListId { - self.draw_lists.insert(DrawList::new(items, pipeline_id)) - } - - pub fn get_draw_list(&self, draw_list_id: DrawListId) -> &DrawList { - self.draw_lists.get(draw_list_id) - } - - pub fn remove_draw_list(&mut self, draw_list_id: DrawListId) { - self.draw_lists.free(draw_list_id); - } - pub fn pending_updates(&mut self) -> TextureUpdateList { self.texture_cache.pending_updates() } diff --git a/webrender/src/scene.rs b/webrender/src/scene.rs index 0f42254d6c..d1fa515144 100644 --- a/webrender/src/scene.rs +++ b/webrender/src/scene.rs @@ -4,25 +4,32 @@ use euclid::Size2D; use fnv::FnvHasher; -use internal_types::DrawListId; -use resource_cache::ResourceCache; use std::collections::HashMap; use std::hash::BuildHasherDefault; use tiling::AuxiliaryListsMap; -use webrender_traits::{AuxiliaryLists, BuiltDisplayList, PipelineId, Epoch}; -use webrender_traits::{ColorF, DisplayListId, StackingContext, StackingContextId}; -use webrender_traits::{SpecificDisplayListItem}; -use webrender_traits::{IframeInfo}; -use webrender_traits::{RectangleDisplayItem, ClipRegion, DisplayItem, SpecificDisplayItem}; +use webrender_traits::{AuxiliaryLists, BuiltDisplayList, PipelineId, Epoch, ColorF}; +use webrender_traits::{DisplayItem, SpecificDisplayItem, StackingContext}; + +trait DisplayListHelpers { + fn starting_stacking_context<'a>(&'a self) -> Option<&'a StackingContext>; +} + +impl DisplayListHelpers for Vec { + fn starting_stacking_context<'a>(&'a self) -> Option<&'a StackingContext> { + self.first().and_then(|item| match item.item { + SpecificDisplayItem::PushStackingContext(ref item) => Some(&item.stacking_context), + _ => None, + }) + } +} /// A representation of the layout within the display port for a given document or iframe. #[derive(Debug)] pub struct ScenePipeline { pub pipeline_id: PipelineId, pub epoch: Epoch, - pub background_draw_list: Option, - pub root_stacking_context_id: StackingContextId, pub viewport_size: Size2D, + pub background_color: ColorF, } /// A complete representation of the layout bundling visible pipelines together. @@ -31,34 +38,7 @@ pub struct Scene { pub pipeline_map: HashMap>, pub pipeline_sizes: HashMap>, pub pipeline_auxiliary_lists: AuxiliaryListsMap, - pub display_list_map: HashMap>, - pub stacking_context_map: HashMap>, -} - -#[derive(Clone, Debug)] -pub enum SpecificSceneItem { - DrawList(DrawListId), - StackingContext(StackingContextId, PipelineId), - Iframe(IframeInfo), -} - -#[derive(Clone, Debug)] -pub struct SceneItem { - pub specific: SpecificSceneItem, -} - -/// Similar to webrender_traits::DisplayList internal to WebRender. -pub struct SceneDisplayList { - pub pipeline_id: PipelineId, - pub epoch: Epoch, - pub items: Vec, -} - -pub struct SceneStackingContext { - pub pipeline_id: PipelineId, - pub epoch: Epoch, - pub stacking_context: StackingContext, - pub stacking_context_id: StackingContextId, + pub display_lists: HashMap, BuildHasherDefault>, } impl Scene { @@ -68,146 +48,31 @@ impl Scene { pipeline_sizes: HashMap::new(), pipeline_map: HashMap::with_hasher(Default::default()), pipeline_auxiliary_lists: HashMap::with_hasher(Default::default()), - display_list_map: HashMap::with_hasher(Default::default()), - stacking_context_map: HashMap::with_hasher(Default::default()), + display_lists: HashMap::with_hasher(Default::default()), } } - pub fn add_display_list(&mut self, - id: DisplayListId, - pipeline_id: PipelineId, - epoch: Epoch, - built_display_list: BuiltDisplayList, - resource_cache: &mut ResourceCache) { - let items = built_display_list.display_list_items().iter().map(|item| { - match item.specific { - SpecificDisplayListItem::DrawList(ref info) => { - let draw_list_id = resource_cache.add_draw_list( - built_display_list.display_items(&info.items).to_vec(), - pipeline_id); - SceneItem { - specific: SpecificSceneItem::DrawList(draw_list_id) - } - } - SpecificDisplayListItem::StackingContext(ref info) => { - SceneItem { - specific: SpecificSceneItem::StackingContext(info.id, pipeline_id) - } - } - SpecificDisplayListItem::Iframe(ref info) => { - SceneItem { - specific: SpecificSceneItem::Iframe(*info) - } - } - } - }).collect(); - - let display_list = SceneDisplayList { - pipeline_id: pipeline_id, - epoch: epoch, - items: items, - }; - - self.display_list_map.insert(id, display_list); - } - - pub fn add_stacking_context(&mut self, - id: StackingContextId, - pipeline_id: PipelineId, - epoch: Epoch, - stacking_context: StackingContext) { - let stacking_context = SceneStackingContext { - pipeline_id: pipeline_id, - epoch: epoch, - stacking_context: stacking_context, - stacking_context_id: id, - }; - - self.stacking_context_map.insert(id, stacking_context); - } - pub fn set_root_pipeline_id(&mut self, pipeline_id: PipelineId) { self.root_pipeline_id = Some(pipeline_id); } - pub fn set_root_stacking_context(&mut self, - pipeline_id: PipelineId, - epoch: Epoch, - stacking_context_id: StackingContextId, - background_color: ColorF, - viewport_size: Size2D, - resource_cache: &mut ResourceCache, - auxiliary_lists: AuxiliaryLists) { + pub fn set_root_display_list(&mut self, + pipeline_id: PipelineId, + epoch: Epoch, + built_display_list: BuiltDisplayList, + background_color: ColorF, + viewport_size: Size2D, + auxiliary_lists: AuxiliaryLists) { self.pipeline_auxiliary_lists.insert(pipeline_id, auxiliary_lists); - - let old_display_list_keys: Vec<_> = self.display_list_map.iter() - .filter(|&(_, ref v)| { - v.pipeline_id == pipeline_id && - v.epoch < epoch - }) - .map(|(k, _)| k.clone()) - .collect(); - - // Remove any old draw lists and display lists for this pipeline - for key in old_display_list_keys { - let display_list = self.display_list_map.remove(&key).unwrap(); - for item in display_list.items { - match item.specific { - SpecificSceneItem::DrawList(draw_list_id) => { - resource_cache.remove_draw_list(draw_list_id); - } - SpecificSceneItem::StackingContext(..) | - SpecificSceneItem::Iframe(..) => {} - } - } - } - - let old_stacking_context_keys: Vec<_> = self.stacking_context_map.iter() - .filter(|&(_, ref v)| { - v.pipeline_id == pipeline_id && - v.epoch < epoch - }) - .map(|(k, _)| k.clone()) - .collect(); - - // Remove any old draw lists and display lists for this pipeline - for key in old_stacking_context_keys { - self.stacking_context_map.remove(&key).unwrap(); - - // TODO: Could remove all associated DLs here, - // and then the above code could just be a debug assert check... - } - - let background_draw_list = if background_color.a > 0.0 { - let overflow = self.stacking_context_map[&stacking_context_id].stacking_context.overflow; - - let rectangle_item = RectangleDisplayItem { - color: background_color, - }; - let root_bg_color_item = DisplayItem { - item: SpecificDisplayItem::Rectangle(rectangle_item), - rect: overflow, - clip: ClipRegion::simple(&overflow), - }; - - let draw_list_id = resource_cache.add_draw_list(vec![root_bg_color_item], pipeline_id); - Some(draw_list_id) - } else { - None - }; + self.display_lists.insert(pipeline_id, built_display_list.all_display_items().to_vec()); let new_pipeline = ScenePipeline { pipeline_id: pipeline_id, epoch: epoch, - background_draw_list: background_draw_list, - root_stacking_context_id: stacking_context_id, viewport_size: viewport_size, + background_color: background_color, }; - if let Some(old_pipeline) = self.pipeline_map.insert(pipeline_id, new_pipeline) { - if let Some(background_draw_list) = old_pipeline.background_draw_list { - resource_cache.remove_draw_list(background_draw_list); - } - } + self.pipeline_map.insert(pipeline_id, new_pipeline); } } diff --git a/webrender_traits/Cargo.toml b/webrender_traits/Cargo.toml index 294954bfb6..604031dee5 100644 --- a/webrender_traits/Cargo.toml +++ b/webrender_traits/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "webrender_traits" -version = "0.8.1" +version = "0.9.0" authors = ["Glenn Watson "] license = "MPL-2.0" repository = "https://github.com/servo/webrender" diff --git a/webrender_traits/src/api.rs b/webrender_traits/src/api.rs index 306f79c328..338e63c602 100644 --- a/webrender_traits/src/api.rs +++ b/webrender_traits/src/api.rs @@ -7,10 +7,9 @@ use euclid::{Point2D, Size2D}; use ipc_channel::ipc::{self, IpcBytesSender, IpcSender}; use offscreen_gl_context::{GLContextAttributes, GLLimits}; use std::cell::Cell; -use {ApiMsg, AuxiliaryLists, BuiltDisplayList, ColorF, DisplayListId, Epoch}; +use {ApiMsg, AuxiliaryLists, BuiltDisplayList, ColorF, Epoch}; use {FontKey, IdNamespace, ImageFormat, ImageKey, NativeFontHandle, PipelineId}; -use {RenderApiSender, ResourceId, ScrollEventPhase, ScrollLayerState}; -use {StackingContext, StackingContextId, WebGLContextId, WebGLCommand}; +use {RenderApiSender, ResourceId, ScrollEventPhase, ScrollLayerState, WebGLContextId, WebGLCommand}; use {GlyphKey, GlyphDimensions}; impl RenderApiSender { @@ -157,38 +156,25 @@ impl RenderApi { /// * `auxiliary_lists`: Various items that the display lists and stacking contexts reference. /// /// [notifier]: trait.RenderNotifier.html#tymethod.new_frame_ready - pub fn set_root_stacking_context(&self, - stacking_context_id: StackingContextId, - background_color: ColorF, - epoch: Epoch, - pipeline_id: PipelineId, - viewport_size: Size2D, - stacking_contexts: Vec<(StackingContextId, StackingContext)>, - display_lists: Vec<(DisplayListId, BuiltDisplayList)>, - auxiliary_lists: AuxiliaryLists) { - let display_list_descriptors = display_lists.iter().map(|&(display_list_id, - ref built_display_list)| { - (display_list_id, (*built_display_list.descriptor()).clone()) - }).collect(); - let msg = ApiMsg::SetRootStackingContext(stacking_context_id, - background_color, - epoch, - pipeline_id, - viewport_size, - stacking_contexts, - display_list_descriptors, - *auxiliary_lists.descriptor()); + pub fn set_root_display_list(&self, + background_color: ColorF, + epoch: Epoch, + pipeline_id: PipelineId, + viewport_size: Size2D, + display_list: BuiltDisplayList, + auxiliary_lists: AuxiliaryLists) { + let msg = ApiMsg::SetRootDisplayList(background_color, + epoch, + pipeline_id, + viewport_size, + display_list.descriptor().clone(), + *auxiliary_lists.descriptor()); self.api_sender.send(msg).unwrap(); let mut payload = vec![]; - payload.write_u32::(stacking_context_id.0).unwrap(); payload.write_u32::(epoch.0).unwrap(); - - for &(_, ref built_display_list) in &display_lists { - payload.extend_from_slice(built_display_list.data()); - } + payload.extend_from_slice(display_list.data()); payload.extend_from_slice(auxiliary_lists.data()); - self.payload_sender.send(&payload[..]).unwrap(); } @@ -240,18 +226,6 @@ impl RenderApi { self.api_sender.send(msg).unwrap(); } - #[inline] - pub fn next_stacking_context_id(&self) -> StackingContextId { - let new_id = self.next_unique_id(); - StackingContextId(new_id.0, new_id.1) - } - - #[inline] - pub fn next_display_list_id(&self) -> DisplayListId { - let new_id = self.next_unique_id(); - DisplayListId(new_id.0, new_id.1) - } - #[inline] fn next_unique_id(&self) -> (u32, u32) { let IdNamespace(namespace) = self.id_namespace; diff --git a/webrender_traits/src/display_list.rs b/webrender_traits/src/display_list.rs index 28a6443064..1afbd89838 100644 --- a/webrender_traits/src/display_list.rs +++ b/webrender_traits/src/display_list.rs @@ -9,12 +9,11 @@ use std::slice; use {AuxiliaryLists, AuxiliaryListsDescriptor, BorderDisplayItem, BorderRadius}; use {BorderSide, BoxShadowClipMode, BoxShadowDisplayItem, BuiltDisplayList}; use {BuiltDisplayListDescriptor, ClipRegion, ComplexClipRegion, ColorF}; -use {DisplayItem, DisplayListItem, DisplayListMode, DrawListInfo, FilterOp}; -use {FontKey, GlyphInstance, GradientDisplayItem, GradientStop, IframeInfo}; -use {ImageDisplayItem, ImageKey, ImageRendering, ItemRange, PipelineId}; -use {RectangleDisplayItem, SpecificDisplayItem, SpecificDisplayListItem}; -use {StackingContextId, StackingContextInfo, TextDisplayItem}; -use {WebGLContextId, WebGLDisplayItem}; +use {DisplayItem, DisplayListMode, FilterOp}; +use {FontKey, GlyphInstance, GradientDisplayItem, GradientStop, IframeDisplayItem}; +use {ImageDisplayItem, ImageKey, ImageRendering, ItemRange, PipelineId,}; +use {PushStackingContextDisplayItem, RectangleDisplayItem, SpecificDisplayItem}; +use {StackingContext, TextDisplayItem, WebGLContextId, WebGLDisplayItem}; impl BuiltDisplayListDescriptor { pub fn size(&self) -> usize { @@ -38,35 +37,23 @@ impl BuiltDisplayList { &self.descriptor } - pub fn display_list_items<'a>(&'a self) -> &'a [DisplayListItem] { + pub fn all_display_items<'a>(&'a self) -> &'a [DisplayItem] { unsafe { convert_blob_to_pod(&self.data[0..self.descriptor.display_list_items_size]) } } - - pub fn display_items<'a>(&'a self, range: &ItemRange) -> &'a [DisplayItem] { - unsafe { - range.get(convert_blob_to_pod(&self.data[self.descriptor.display_list_items_size..])) - } - } } pub struct DisplayListBuilder { pub mode: DisplayListMode, - - pub work_list: Vec, - - pub display_list_items: Vec, - pub display_items: Vec, + pub list: Vec, } impl DisplayListBuilder { pub fn new() -> DisplayListBuilder { DisplayListBuilder { mode: DisplayListMode::Default, - work_list: Vec::new(), - display_list_items: Vec::new(), - display_items: Vec::new(), + list: Vec::new(), } } @@ -84,7 +71,7 @@ impl DisplayListBuilder { clip: clip, }; - self.push_item(display_item); + self.list.push(display_item); } pub fn push_image(&mut self, @@ -107,7 +94,7 @@ impl DisplayListBuilder { clip: clip, }; - self.push_item(display_item); + self.list.push(display_item); } pub fn push_webgl_canvas(&mut self, @@ -124,7 +111,7 @@ impl DisplayListBuilder { clip: clip, }; - self.push_item(display_item); + self.list.push(display_item); } pub fn push_text(&mut self, @@ -157,7 +144,7 @@ impl DisplayListBuilder { clip: clip, }; - self.push_item(display_item); + self.list.push(display_item); } } @@ -183,7 +170,7 @@ impl DisplayListBuilder { clip: clip, }; - self.push_item(display_item); + self.list.push(display_item); } pub fn push_box_shadow(&mut self, @@ -212,18 +199,7 @@ impl DisplayListBuilder { clip: clip, }; - self.push_item(display_item); - } - - pub fn push_stacking_context(&mut self, stacking_context_id: StackingContextId) { - self.flush(); - let info = StackingContextInfo { - id: stacking_context_id, - }; - let item = DisplayListItem { - specific: SpecificDisplayListItem::StackingContext(info), - }; - self.display_list_items.push(item); + self.list.push(display_item); } pub fn push_gradient(&mut self, @@ -245,69 +221,53 @@ impl DisplayListBuilder { clip: clip, }; - self.push_item(display_item); + self.list.push(display_item); } - pub fn push_iframe(&mut self, - rect: Rect, - clip: ClipRegion, - iframe: PipelineId) { - self.flush(); - let info = IframeInfo { - id: iframe, - bounds: rect, - clip: clip, + pub fn push_stacking_context(&mut self, stacking_context: StackingContext) { + let item = DisplayItem { + item: SpecificDisplayItem::PushStackingContext(PushStackingContextDisplayItem { + stacking_context: stacking_context + }), + rect: Rect::zero(), + clip: ClipRegion::simple(&Rect::zero()), }; - let item = DisplayListItem { - specific: SpecificDisplayListItem::Iframe(info), - }; - self.display_list_items.push(item); + self.list.push(item); } - fn push_item(&mut self, item: DisplayItem) { - self.work_list.push(item); + pub fn pop_stacking_context(&mut self) { + let item = DisplayItem { + item: SpecificDisplayItem::PopStackingContext, + rect: Rect::zero(), + clip: ClipRegion::simple(&Rect::zero()), + }; + self.list.push(item); } - fn flush(&mut self) { - let items = mem::replace(&mut self.work_list, Vec::new()); - if items.is_empty() { - return - } - - let draw_list = DrawListInfo { - items: ItemRange::new(&mut self.display_items, &items), + pub fn push_iframe(&mut self, rect: Rect, clip: ClipRegion, pipeline_id: PipelineId) { + let item = DisplayItem { + item: SpecificDisplayItem::Iframe(IframeDisplayItem { pipeline_id: pipeline_id }), + rect: rect, + clip: clip, }; - self.display_list_items.push(DisplayListItem { - specific: SpecificDisplayListItem::DrawList(draw_list), - }); + self.list.push(item); } - pub fn finalize(mut self) -> BuiltDisplayList { - self.flush(); - + pub fn finalize(self) -> BuiltDisplayList { unsafe { - let mut blob = convert_pod_to_blob(&self.display_list_items).to_vec(); + let blob = convert_pod_to_blob(&self.list).to_vec(); let display_list_items_size = blob.len(); - blob.extend_from_slice(convert_pod_to_blob(&self.display_items)); - let display_items_size = blob.len() - display_list_items_size; + BuiltDisplayList { descriptor: BuiltDisplayListDescriptor { mode: self.mode, display_list_items_size: display_list_items_size, - display_items_size: display_items_size, + display_items_size: 0, }, data: blob, } } } - - pub fn display_items<'a>(&'a self, range: &ItemRange) -> &'a [DisplayItem] { - range.get(&self.display_items) - } - - pub fn display_items_mut<'a>(&'a mut self, range: &ItemRange) -> &'a mut [DisplayItem] { - range.get_mut(&mut self.display_items) - } } impl ItemRange { diff --git a/webrender_traits/src/stacking_context.rs b/webrender_traits/src/stacking_context.rs index 4c07fbcbc3..235c92767c 100644 --- a/webrender_traits/src/stacking_context.rs +++ b/webrender_traits/src/stacking_context.rs @@ -25,7 +25,6 @@ impl StackingContext { bounds: bounds, overflow: overflow, z_index: z_index, - display_lists: Vec::new(), transform: transform.clone(), perspective: perspective.clone(), establishes_3d_context: establishes_3d_context, diff --git a/webrender_traits/src/types.rs b/webrender_traits/src/types.rs index 9d81afb99d..81784882d2 100644 --- a/webrender_traits/src/types.rs +++ b/webrender_traits/src/types.rs @@ -36,20 +36,14 @@ pub enum ApiMsg { CloneApi(IpcSender), /// Supplies a new frame to WebRender. /// - /// The first `StackingContextId` describes the root stacking context. The actual stacking - /// contexts are supplied as the sixth parameter, while the display lists that make up those - /// stacking contexts are supplied as the seventh parameter. - /// - /// After receiving this message, WebRender will read the display lists, followed by the + /// After receiving this message, WebRender will read the display list, followed by the /// auxiliary lists, from the payload channel. - SetRootStackingContext(StackingContextId, - ColorF, - Epoch, - PipelineId, - Size2D, - Vec<(StackingContextId, StackingContext)>, - Vec<(DisplayListId, BuiltDisplayListDescriptor)>, - AuxiliaryListsDescriptor), + SetRootDisplayList(ColorF, + Epoch, + PipelineId, + Size2D, + BuiltDisplayListDescriptor, + AuxiliaryListsDescriptor), SetRootPipeline(PipelineId), Scroll(Point2D, Point2D, ScrollEventPhase), TickScrollingBounce, @@ -209,14 +203,6 @@ pub struct DisplayItem { pub clip: ClipRegion, } -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] -pub struct DisplayListId(pub u32, pub u32); - -#[derive(Clone, Copy, Deserialize, Serialize)] -pub struct DisplayListItem { - pub specific: SpecificDisplayListItem, -} - #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] pub enum DisplayListMode { Default, @@ -224,11 +210,6 @@ pub enum DisplayListMode { PseudoPositionedContent, } -#[derive(Clone, Copy, Deserialize, Serialize)] -pub struct DrawListInfo { - pub items: ItemRange, -} - #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] pub struct Epoch(pub u32); @@ -302,16 +283,20 @@ pub struct GradientStop { } known_heap_size!(0, GradientStop); -#[derive(Clone, Copy, Debug, Deserialize, Serialize)] -pub struct IdNamespace(pub u32); -#[derive(Clone, Copy, Debug, Deserialize, Serialize)] -pub struct IframeInfo { - pub id: PipelineId, - pub bounds: Rect, - pub clip: ClipRegion, +#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] +pub struct PushStackingContextDisplayItem { + pub stacking_context: StackingContext, +} + +#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] +pub struct IframeDisplayItem { + pub pipeline_id: PipelineId, } +#[derive(Clone, Copy, Debug, Deserialize, Serialize)] +pub struct IdNamespace(pub u32); + #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] pub struct ImageDisplayItem { pub image_key: ImageKey, @@ -452,23 +437,18 @@ pub enum SpecificDisplayItem { Border(BorderDisplayItem), BoxShadow(BoxShadowDisplayItem), Gradient(GradientDisplayItem), + Iframe(IframeDisplayItem), + PushStackingContext(PushStackingContextDisplayItem), + PopStackingContext, } -#[derive(Clone, Copy, Deserialize, Serialize)] -pub enum SpecificDisplayListItem { - DrawList(DrawListInfo), - StackingContext(StackingContextInfo), - Iframe(IframeInfo), -} - -#[derive(Clone, Deserialize, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] pub struct StackingContext { pub scroll_layer_id: Option, pub scroll_policy: ScrollPolicy, pub bounds: Rect, pub overflow: Rect, pub z_index: i32, - pub display_lists: Vec, pub transform: Matrix4D, pub perspective: Matrix4D, pub establishes_3d_context: bool, @@ -476,14 +456,6 @@ pub struct StackingContext { pub filters: ItemRange, } -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] -pub struct StackingContextId(pub u32, pub u32); - -#[derive(Clone, Copy, Deserialize, Serialize)] -pub struct StackingContextInfo { - pub id: StackingContextId, -} - #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] pub struct TextDisplayItem { pub glyphs: ItemRange,