diff --git a/servo/components/compositing/compositor.rs b/servo/components/compositing/compositor.rs index 3eadc3dd33d5..55127bd64fe0 100644 --- a/servo/components/compositing/compositor.rs +++ b/servo/components/compositing/compositor.rs @@ -11,7 +11,7 @@ use euclid::{Point2D, Size2D}; use euclid::point::TypedPoint2D; use euclid::scale_factor::ScaleFactor; use euclid::size::TypedSize2D; -use gfx_traits::{DevicePixel, LayerPixel, StackingContextId}; +use gfx_traits::{DevicePixel, LayerPixel, ScrollRootId}; use gfx_traits::{Epoch, FrameTreeId, FragmentType}; use gleam::gl; use gleam::gl::types::{GLint, GLsizei}; @@ -74,13 +74,13 @@ impl ConvertPipelineIdFromWebRender for webrender_traits::PipelineId { } } -trait ConvertStackingContextFromWebRender { - fn from_webrender(&self) -> StackingContextId; +trait ConvertScrollRootIdFromWebRender { + fn from_webrender(&self) -> ScrollRootId; } -impl ConvertStackingContextFromWebRender for webrender_traits::ServoStackingContextId { - fn from_webrender(&self) -> StackingContextId { - StackingContextId::new_of_type(self.1, self.0.from_webrender()) +impl ConvertScrollRootIdFromWebRender for webrender_traits::ServoScrollRootId { + fn from_webrender(&self) -> ScrollRootId { + ScrollRootId(self.0) } } @@ -1312,7 +1312,7 @@ impl IOCompositor { let mut stacking_context_scroll_states_per_pipeline = HashMap::new(); for scroll_layer_state in self.webrender_api.get_scroll_layer_state() { let stacking_context_scroll_state = StackingContextScrollState { - stacking_context_id: scroll_layer_state.stacking_context_id.from_webrender(), + scroll_root_id: scroll_layer_state.scroll_root_id.from_webrender(), scroll_offset: scroll_layer_state.scroll_offset, }; let pipeline_id = scroll_layer_state.pipeline_id; diff --git a/servo/components/gfx/display_list/mod.rs b/servo/components/gfx/display_list/mod.rs index 5a3795fec096..36a09aff4a7a 100644 --- a/servo/components/gfx/display_list/mod.rs +++ b/servo/components/gfx/display_list/mod.rs @@ -20,7 +20,7 @@ use euclid::{Matrix4D, Point2D, Rect, Size2D}; use euclid::num::{One, Zero}; use euclid::rect::TypedRect; use euclid::side_offsets::SideOffsets2D; -use gfx_traits::{ScrollPolicy, StackingContextId}; +use gfx_traits::{ScrollPolicy, ScrollRootId, StackingContextId}; use gfx_traits::print_tree::PrintTree; use ipc_channel::ipc::IpcSharedMemory; use msg::constellation_msg::PipelineId; @@ -215,9 +215,11 @@ impl DisplayList { // the DOM-side code has already translated the point for us (e.g. in // `Window::hit_test_query()`) by now. if !is_fixed && stacking_context.id != StackingContextId::root() { - if let Some(scroll_offset) = scroll_offsets.get(&stacking_context.id) { - translated_point.x -= Au::from_f32_px(scroll_offset.x); - translated_point.y -= Au::from_f32_px(scroll_offset.y); + if let Some(scroll_root_id) = stacking_context.overflow_scroll_id { + if let Some(scroll_offset) = scroll_offsets.get(&scroll_root_id) { + translated_point.x -= Au::from_f32_px(scroll_offset.x); + translated_point.y -= Au::from_f32_px(scroll_offset.y); + } } } @@ -386,7 +388,7 @@ pub struct StackingContext { pub children: Vec, /// If this StackingContext scrolls its overflow area, this will contain the id. - pub overflow_scroll_id: Option, + pub overflow_scroll_id: Option, } impl StackingContext { @@ -403,7 +405,7 @@ impl StackingContext { perspective: Matrix4D, establishes_3d_context: bool, scroll_policy: ScrollPolicy, - scroll_id: Option) + scroll_root_id: Option) -> StackingContext { StackingContext { id: id, @@ -418,7 +420,7 @@ impl StackingContext { establishes_3d_context: establishes_3d_context, scroll_policy: scroll_policy, children: Vec::new(), - overflow_scroll_id: scroll_id, + overflow_scroll_id: scroll_root_id, } } @@ -1194,7 +1196,7 @@ impl WebRenderImageInfo { } /// The type of the scroll offset list. This is only populated if WebRender is in use. -pub type ScrollOffsetMap = HashMap>; +pub type ScrollOffsetMap = HashMap>; pub trait SimpleMatrixDetection { diff --git a/servo/components/gfx_traits/lib.rs b/servo/components/gfx_traits/lib.rs index b1530aef29b8..bdf1a7591eb6 100644 --- a/servo/components/gfx_traits/lib.rs +++ b/servo/components/gfx_traits/lib.rs @@ -162,6 +162,58 @@ impl StackingContextId { } } +/// A unique ID for every scrolling root. +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, HeapSizeOf, PartialEq, Serialize)] +pub struct ScrollRootId( + /// The identifier for this StackingContext, derived from the Flow's memory address + /// and fragment type. As a space optimization, these are combined into a single word. + pub usize +); + +impl ScrollRootId { + /// Returns a new stacking context ID for a special stacking context. + fn next_special_id() -> usize { + // We shift this left by 2 to make room for the fragment type ID. + ((NEXT_SPECIAL_STACKING_CONTEXT_ID.fetch_add(1, Ordering::SeqCst) + 1) << 2) & + SPECIAL_STACKING_CONTEXT_ID_MASK + } + + #[inline] + pub fn new_of_type(id: usize, fragment_type: FragmentType) -> ScrollRootId { + debug_assert_eq!(id & (fragment_type as usize), 0); + if fragment_type == FragmentType::FragmentBody { + ScrollRootId(id) + } else { + ScrollRootId(ScrollRootId::next_special_id() | (fragment_type as usize)) + } + } + + /// Returns the stacking context ID for the outer document/layout root. + #[inline] + pub fn root() -> ScrollRootId { + ScrollRootId(0) + } + + /// Returns true if this is a special stacking context. + /// + /// A special stacking context is a stacking context that is one of (a) the outer stacking + /// context of an element with `overflow: scroll`; (b) generated content; (c) both (a) and (b). + #[inline] + pub fn is_special(&self) -> bool { + (self.0 & !SPECIAL_STACKING_CONTEXT_ID_MASK) == 0 + } + + #[inline] + pub fn id(&self) -> usize { + self.0 & !3 + } + + #[inline] + pub fn fragment_type(&self) -> FragmentType { + FragmentType::from_usize(self.0 & 3) + } +} + /// The type of fragment that a stacking context represents. /// /// This can only ever grow to maximum 4 entries. That's because we cram the value of this enum diff --git a/servo/components/layout/block.rs b/servo/components/layout/block.rs index 356b1aaf6b3d..91383c12e280 100644 --- a/servo/components/layout/block.rs +++ b/servo/components/layout/block.rs @@ -44,6 +44,7 @@ use flow_ref::FlowRef; use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, Overflow}; use fragment::SpecificFragmentInfo; use gfx::display_list::{ClippingRegion, StackingContext}; +use gfx_traits::ScrollRootId; use gfx_traits::print_tree::PrintTree; use layout_debug; use model::{CollapsibleMargins, IntrinsicISizes, MarginCollapseInfo, MaybeAuto}; @@ -2162,8 +2163,10 @@ impl Flow for BlockFlow { } } - fn collect_stacking_contexts(&mut self, parent: &mut StackingContext) { - self.collect_stacking_contexts_for_block(parent); + fn collect_stacking_contexts(&mut self, + parent: &mut StackingContext, + parent_scroll_root_id: ScrollRootId) { + self.collect_stacking_contexts_for_block(parent, parent_scroll_root_id); } fn build_display_list(&mut self, state: &mut DisplayListBuildState) { diff --git a/servo/components/layout/display_list_builder.rs b/servo/components/layout/display_list_builder.rs index e714df23314c..d665734f947c 100644 --- a/servo/components/layout/display_list_builder.rs +++ b/servo/components/layout/display_list_builder.rs @@ -28,7 +28,7 @@ use gfx::display_list::{GradientStop, IframeDisplayItem, ImageDisplayItem, WebGL use gfx::display_list::{LineDisplayItem, OpaqueNode}; use gfx::display_list::{SolidColorDisplayItem, StackingContext, StackingContextType}; use gfx::display_list::{TextDisplayItem, TextOrientation, WebRenderImageInfo}; -use gfx_traits::{ScrollPolicy, StackingContextId, color}; +use gfx_traits::{ScrollPolicy, ScrollRootId, StackingContextId, color}; use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, LAST_FRAGMENT_OF_ELEMENT}; use ipc_channel::ipc; use list_item::ListItemFlow; @@ -78,6 +78,7 @@ pub struct DisplayListBuildState<'a> { pub shared_layout_context: &'a SharedLayoutContext, pub items: Vec, pub stacking_context_id_stack: Vec, + pub scroll_root_id_stack: Vec, } impl<'a> DisplayListBuildState<'a> { @@ -88,6 +89,7 @@ impl<'a> DisplayListBuildState<'a> { shared_layout_context: shared_layout_context, items: Vec::new(), stacking_context_id_stack: vec!(stacking_context_id), + scroll_root_id_stack: vec!(ScrollRootId::root()), } } @@ -95,7 +97,7 @@ impl<'a> DisplayListBuildState<'a> { self.items.push(display_item); } - fn stacking_context_id(&self) -> StackingContextId { + pub fn stacking_context_id(&self) -> StackingContextId { self.stacking_context_id_stack.last().unwrap().clone() } @@ -108,6 +110,19 @@ impl<'a> DisplayListBuildState<'a> { assert!(!self.stacking_context_id_stack.is_empty()); } + pub fn scroll_root_id(&mut self) -> ScrollRootId { + self.scroll_root_id_stack.last().unwrap().clone() + } + + pub fn push_scroll_root_id(&mut self, id: ScrollRootId) { + self.scroll_root_id_stack.push(id); + } + + pub fn pop_scroll_root_id(&mut self) { + self.scroll_root_id_stack.pop(); + assert!(!self.scroll_root_id_stack.is_empty()); + } + fn create_base_display_item(&self, bounds: &Rect, clip: &ClippingRegion, @@ -299,7 +314,7 @@ pub trait FragmentDisplayListBuilding { base_flow: &BaseFlow, scroll_policy: ScrollPolicy, mode: StackingContextCreationMode, - scroll_id: Option) + scroll_root_id: Option) -> StackingContext; /// Returns the 4D matrix representing this fragment's transform. @@ -1356,7 +1371,7 @@ impl FragmentDisplayListBuilding for Fragment { base_flow: &BaseFlow, scroll_policy: ScrollPolicy, mode: StackingContextCreationMode, - scroll_id: Option) + scroll_root_id: Option) -> StackingContext { let scrolls_overflow_area = mode == StackingContextCreationMode::ScrollWrapper; let border_box = @@ -1431,7 +1446,7 @@ impl FragmentDisplayListBuilding for Fragment { perspective, establishes_3d_context, scroll_policy, - scroll_id) + scroll_root_id) } fn adjust_clipping_region_for_children(&self, @@ -1687,7 +1702,9 @@ impl FragmentDisplayListBuilding for Fragment { } pub trait BlockFlowDisplayListBuilding { - fn collect_stacking_contexts_for_block(&mut self, parent: &mut StackingContext); + fn collect_stacking_contexts_for_block(&mut self, + parent: &mut StackingContext, + parent_scroll_root_id: ScrollRootId); fn build_display_list_for_block(&mut self, state: &mut DisplayListBuildState, border_painting_mode: BorderPaintingMode); @@ -1704,17 +1721,29 @@ pub trait BlockFlowDisplayListBuilding { } impl BlockFlowDisplayListBuilding for BlockFlow { - fn collect_stacking_contexts_for_block(&mut self, parent: &mut StackingContext) { + fn collect_stacking_contexts_for_block(&mut self, + parent: &mut StackingContext, + parent_scroll_root_id: ScrollRootId) { let block_stacking_context_type = self.block_stacking_context_type(); if block_stacking_context_type == BlockStackingContextType::NonstackingContext { self.base.stacking_context_id = parent.id; - self.base.collect_stacking_contexts_for_children(parent); + self.base.collect_stacking_contexts_for_children(parent, parent_scroll_root_id); return; } - let has_scrolling_overflow = self.has_scrolling_overflow(); let stacking_context_id = StackingContextId::new_of_type(self.fragment.node.id() as usize, self.fragment.fragment_type()); + + let has_scrolling_overflow = self.has_scrolling_overflow(); + let scroll_root_id = if has_scrolling_overflow { + ScrollRootId::new_of_type(self.fragment.node.id() as usize, + self.fragment.fragment_type()) + } else { + parent_scroll_root_id + }; + self.base.scroll_root_id = scroll_root_id; + + self.base.stacking_context_id = stacking_context_id; if block_stacking_context_type == BlockStackingContextType::PseudoStackingContext { @@ -1731,7 +1760,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow { ScrollPolicy::Scrollable, creation_mode, None); - self.base.collect_stacking_contexts_for_children(&mut new_context); + self.base.collect_stacking_contexts_for_children(&mut new_context, scroll_root_id); let new_children: Vec = new_context.children.drain(..).collect(); let mut non_floating_children = Vec::new(); @@ -1755,10 +1784,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow { }; let (creation_mode, internal_id) = if has_scrolling_overflow { - (StackingContextCreationMode::ScrollWrapper, - Some(StackingContextId::new_of_type(self.fragment.node.id() as usize, - self.fragment.fragment_type()))) - + (StackingContextCreationMode::ScrollWrapper, Some(self.base.scroll_root_id)) } else { (StackingContextCreationMode::Normal, None) }; @@ -1769,7 +1795,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow { scroll_policy, creation_mode, internal_id); - self.base.collect_stacking_contexts_for_children(&mut stacking_context); + self.base.collect_stacking_contexts_for_children(&mut stacking_context, scroll_root_id); parent.add_child(stacking_context); } @@ -1859,7 +1885,9 @@ impl BlockFlowDisplayListBuilding for BlockFlow { } pub trait InlineFlowDisplayListBuilding { - fn collect_stacking_contexts_for_inline(&mut self, parent: &mut StackingContext); + fn collect_stacking_contexts_for_inline(&mut self, + parent: &mut StackingContext, + parent_scroll_root_id: ScrollRootId); fn build_display_list_for_inline_fragment_at_index(&mut self, state: &mut DisplayListBuildState, index: usize); @@ -1867,18 +1895,21 @@ pub trait InlineFlowDisplayListBuilding { } impl InlineFlowDisplayListBuilding for InlineFlow { - fn collect_stacking_contexts_for_inline(&mut self, parent: &mut StackingContext) { + fn collect_stacking_contexts_for_inline(&mut self, + parent: &mut StackingContext, + parent_scroll_root_id: ScrollRootId) { self.base.stacking_context_id = parent.id; + self.base.scroll_root_id = parent_scroll_root_id; for mut fragment in self.fragments.fragments.iter_mut() { match fragment.specific { SpecificFragmentInfo::InlineBlock(ref mut block_flow) => { let block_flow = flow_ref::deref_mut(&mut block_flow.flow_ref); - block_flow.collect_stacking_contexts(parent); + block_flow.collect_stacking_contexts(parent, parent_scroll_root_id); } SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut block_flow) => { let block_flow = flow_ref::deref_mut(&mut block_flow.flow_ref); - block_flow.collect_stacking_contexts(parent); + block_flow.collect_stacking_contexts(parent, parent_scroll_root_id); } _ if fragment.establishes_stacking_context() => { fragment.stacking_context_id = diff --git a/servo/components/layout/flex.rs b/servo/components/layout/flex.rs index 69ae5a7bf49c..0fca93fb5f3f 100644 --- a/servo/components/layout/flex.rs +++ b/servo/components/layout/flex.rs @@ -17,6 +17,7 @@ use flow::{Flow, FlowClass, ImmutableFlowUtils, OpaqueFlow}; use flow::{INLINE_POSITION_IS_STATIC, IS_ABSOLUTELY_POSITIONED}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; use gfx::display_list::StackingContext; +use gfx_traits::ScrollRootId; use layout_debug; use model::{Direction, IntrinsicISizes, MaybeAuto, MinMaxConstraint}; use model::{specified, specified_or_none}; @@ -956,8 +957,10 @@ impl Flow for FlexFlow { self.build_display_list_for_flex(state); } - fn collect_stacking_contexts(&mut self, parent: &mut StackingContext) { - self.block_flow.collect_stacking_contexts(parent); + fn collect_stacking_contexts(&mut self, + parent: &mut StackingContext, + parent_scroll_root_id: ScrollRootId) { + self.block_flow.collect_stacking_contexts(parent, parent_scroll_root_id); } fn repair_style(&mut self, new_style: &Arc) { diff --git a/servo/components/layout/flow.rs b/servo/components/layout/flow.rs index 2c85febaf2c3..f68ea3f35fdc 100644 --- a/servo/components/layout/flow.rs +++ b/servo/components/layout/flow.rs @@ -35,7 +35,7 @@ use flow_list::{FlowList, MutFlowListIterator}; use flow_ref::{self, FlowRef, WeakFlowRef}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; use gfx::display_list::{ClippingRegion, StackingContext}; -use gfx_traits::StackingContextId; +use gfx_traits::{ScrollRootId, StackingContextId}; use gfx_traits::print_tree::PrintTree; use inline::InlineFlow; use model::{CollapsibleMargins, IntrinsicISizes, MarginCollapseInfo}; @@ -223,7 +223,9 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static { None } - fn collect_stacking_contexts(&mut self, _parent: &mut StackingContext); + fn collect_stacking_contexts(&mut self, + _parent: &mut StackingContext, + parent_scroll_root_id: ScrollRootId); /// If this is a float, places it. The default implementation does nothing. fn place_float_if_applicable<'a>(&mut self) {} @@ -935,6 +937,8 @@ pub struct BaseFlow { /// to 0, but it assigned during the collect_stacking_contexts phase of display /// list construction. pub stacking_context_id: StackingContextId, + + pub scroll_root_id: ScrollRootId, } impl fmt::Debug for BaseFlow { @@ -1105,6 +1109,7 @@ impl BaseFlow { writing_mode: writing_mode, thread_id: 0, stacking_context_id: StackingContextId::new(0), + scroll_root_id: ScrollRootId::root(), } } @@ -1136,9 +1141,11 @@ impl BaseFlow { return self as *const BaseFlow as usize; } - pub fn collect_stacking_contexts_for_children(&mut self, parent: &mut StackingContext) { + pub fn collect_stacking_contexts_for_children(&mut self, + parent: &mut StackingContext, + parent_scroll_root_id: ScrollRootId) { for kid in self.children.iter_mut() { - kid.collect_stacking_contexts(parent); + kid.collect_stacking_contexts(parent, parent_scroll_root_id); } } diff --git a/servo/components/layout/inline.rs b/servo/components/layout/inline.rs index 055fbeb4a0b3..96901638b4ce 100644 --- a/servo/components/layout/inline.rs +++ b/servo/components/layout/inline.rs @@ -19,6 +19,7 @@ use fragment::SpecificFragmentInfo; use gfx::display_list::{OpaqueNode, StackingContext}; use gfx::font::FontMetrics; use gfx::font_context::FontContext; +use gfx_traits::ScrollRootId; use gfx_traits::print_tree::PrintTree; use layout_debug; use model::IntrinsicISizesContribution; @@ -1613,8 +1614,10 @@ impl Flow for InlineFlow { fn update_late_computed_block_position_if_necessary(&mut self, _: Au) {} - fn collect_stacking_contexts(&mut self, parent: &mut StackingContext) { - self.collect_stacking_contexts_for_inline(parent); + fn collect_stacking_contexts(&mut self, + parent: &mut StackingContext, + parent_scroll_root_id: ScrollRootId) { + self.collect_stacking_contexts_for_inline(parent, parent_scroll_root_id); } fn build_display_list(&mut self, state: &mut DisplayListBuildState) { diff --git a/servo/components/layout/list_item.rs b/servo/components/layout/list_item.rs index 50318f65457d..2a925acd8837 100644 --- a/servo/components/layout/list_item.rs +++ b/servo/components/layout/list_item.rs @@ -18,6 +18,7 @@ use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, GeneratedC use fragment::Overflow; use generated_content; use gfx::display_list::StackingContext; +use gfx_traits::ScrollRootId; use inline::InlineFlow; use script_layout_interface::restyle_damage::RESOLVE_GENERATED_CONTENT; use std::sync::Arc; @@ -145,8 +146,10 @@ impl Flow for ListItemFlow { self.build_display_list_for_list_item(state); } - fn collect_stacking_contexts(&mut self, parent: &mut StackingContext) { - self.block_flow.collect_stacking_contexts(parent); + fn collect_stacking_contexts(&mut self, + parent: &mut StackingContext, + parent_scroll_root_id: ScrollRootId) { + self.block_flow.collect_stacking_contexts(parent, parent_scroll_root_id); } fn repair_style(&mut self, new_style: &Arc) { diff --git a/servo/components/layout/multicol.rs b/servo/components/layout/multicol.rs index 669f3a595302..14d03c3bd851 100644 --- a/servo/components/layout/multicol.rs +++ b/servo/components/layout/multicol.rs @@ -17,6 +17,7 @@ use flow::{Flow, FlowClass, OpaqueFlow, mut_base, FragmentationContext}; use flow_ref::{self, FlowRef}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; use gfx::display_list::StackingContext; +use gfx_traits::ScrollRootId; use gfx_traits::print_tree::PrintTree; use std::cmp::{min, max}; use std::fmt; @@ -185,8 +186,10 @@ impl Flow for MulticolFlow { self.block_flow.build_display_list(state); } - fn collect_stacking_contexts(&mut self, parent: &mut StackingContext) { - self.block_flow.collect_stacking_contexts(parent); + fn collect_stacking_contexts(&mut self, + parent: &mut StackingContext, + parent_scroll_root_id: ScrollRootId) { + self.block_flow.collect_stacking_contexts(parent, parent_scroll_root_id); } fn repair_style(&mut self, new_style: &Arc) { @@ -267,8 +270,10 @@ impl Flow for MulticolColumnFlow { self.block_flow.build_display_list(state); } - fn collect_stacking_contexts(&mut self, parent: &mut StackingContext) { - self.block_flow.collect_stacking_contexts(parent); + fn collect_stacking_contexts(&mut self, + parent: &mut StackingContext, + parent_scroll_root_id: ScrollRootId) { + self.block_flow.collect_stacking_contexts(parent, parent_scroll_root_id); } fn repair_style(&mut self, new_style: &Arc) { diff --git a/servo/components/layout/sequential.rs b/servo/components/layout/sequential.rs index f2964976ed3e..51f2ac874a01 100644 --- a/servo/components/layout/sequential.rs +++ b/servo/components/layout/sequential.rs @@ -15,6 +15,7 @@ use flow::IS_ABSOLUTELY_POSITIONED; use fragment::FragmentBorderBoxIterator; use generated_content::ResolveGeneratedContent; use gfx::display_list::{DisplayItem, StackingContext}; +use gfx_traits::ScrollRootId; use script_layout_interface::restyle_damage::{REFLOW, STORE_OVERFLOW}; use style::context::StyleContext; use traversal::{AssignBSizes, AssignISizes, BubbleISizes, BuildDisplayList}; @@ -78,7 +79,7 @@ pub fn build_display_list_for_subtree(flow_root: &mut Flow, root_stacking_context: &mut StackingContext, shared_layout_context: &SharedLayoutContext) -> Vec { - flow_root.collect_stacking_contexts(root_stacking_context); + flow_root.collect_stacking_contexts(root_stacking_context, ScrollRootId::root()); let mut build_display_list = BuildDisplayList { state: DisplayListBuildState::new(shared_layout_context, flow::base(flow_root).stacking_context_id), diff --git a/servo/components/layout/table.rs b/servo/components/layout/table.rs index 9abd030f68b6..1d904e00b23f 100644 --- a/servo/components/layout/table.rs +++ b/servo/components/layout/table.rs @@ -17,6 +17,7 @@ use flow::{BaseFlow, EarlyAbsolutePositionInfo, Flow, FlowClass, ImmutableFlowUt use flow_list::MutFlowListIterator; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; use gfx::display_list::StackingContext; +use gfx_traits::ScrollRootId; use gfx_traits::print_tree::PrintTree; use layout_debug; use model::{IntrinsicISizes, IntrinsicISizesContribution, MaybeAuto}; @@ -489,8 +490,10 @@ impl Flow for TableFlow { self.block_flow.build_display_list_for_block(state, border_painting_mode); } - fn collect_stacking_contexts(&mut self, parent: &mut StackingContext) { - self.block_flow.collect_stacking_contexts(parent); + fn collect_stacking_contexts(&mut self, + parent: &mut StackingContext, + parent_scroll_root_id: ScrollRootId) { + self.block_flow.collect_stacking_contexts(parent, parent_scroll_root_id); } fn repair_style(&mut self, new_style: &Arc) { diff --git a/servo/components/layout/table_caption.rs b/servo/components/layout/table_caption.rs index 3487aac0f5ef..523a1f0e0711 100644 --- a/servo/components/layout/table_caption.rs +++ b/servo/components/layout/table_caption.rs @@ -14,6 +14,7 @@ use euclid::Point2D; use flow::{Flow, FlowClass, OpaqueFlow}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; use gfx::display_list::StackingContext; +use gfx_traits::ScrollRootId; use gfx_traits::print_tree::PrintTree; use std::fmt; use std::sync::Arc; @@ -82,8 +83,10 @@ impl Flow for TableCaptionFlow { self.block_flow.build_display_list(state); } - fn collect_stacking_contexts(&mut self, parent: &mut StackingContext) { - self.block_flow.collect_stacking_contexts(parent); + fn collect_stacking_contexts(&mut self, + parent: &mut StackingContext, + parent_scroll_root_id: ScrollRootId) { + self.block_flow.collect_stacking_contexts(parent, parent_scroll_root_id); } fn repair_style(&mut self, new_style: &Arc) { diff --git a/servo/components/layout/table_cell.rs b/servo/components/layout/table_cell.rs index 8e6394b9a755..ca2af6a48978 100644 --- a/servo/components/layout/table_cell.rs +++ b/servo/components/layout/table_cell.rs @@ -15,6 +15,7 @@ use euclid::{Point2D, Rect, SideOffsets2D, Size2D}; use flow::{self, Flow, FlowClass, IS_ABSOLUTELY_POSITIONED, OpaqueFlow}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; use gfx::display_list::StackingContext; +use gfx_traits::ScrollRootId; use gfx_traits::print_tree::PrintTree; use layout_debug; use model::MaybeAuto; @@ -256,8 +257,10 @@ impl Flow for TableCellFlow { self.block_flow.build_display_list_for_block(state, border_painting_mode) } - fn collect_stacking_contexts(&mut self, parent: &mut StackingContext) { - self.block_flow.collect_stacking_contexts(parent); + fn collect_stacking_contexts(&mut self, + parent: &mut StackingContext, + parent_scroll_root_id: ScrollRootId) { + self.block_flow.collect_stacking_contexts(parent, parent_scroll_root_id); } fn repair_style(&mut self, new_style: &Arc) { diff --git a/servo/components/layout/table_colgroup.rs b/servo/components/layout/table_colgroup.rs index 795f24693b71..468e0ffb285a 100644 --- a/servo/components/layout/table_colgroup.rs +++ b/servo/components/layout/table_colgroup.rs @@ -13,6 +13,7 @@ use euclid::Point2D; use flow::{BaseFlow, Flow, FlowClass, ForceNonfloatedFlag, OpaqueFlow}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow, SpecificFragmentInfo}; use gfx::display_list::StackingContext; +use gfx_traits::ScrollRootId; use layout_debug; use std::cmp::max; use std::fmt; @@ -95,7 +96,9 @@ impl Flow for TableColGroupFlow { // Table columns are invisible. fn build_display_list(&mut self, _: &mut DisplayListBuildState) { } - fn collect_stacking_contexts(&mut self, _parent: &mut StackingContext) { } + fn collect_stacking_contexts(&mut self, + _parent: &mut StackingContext, + _parent_scroll_root_id: ScrollRootId) {} fn repair_style(&mut self, _: &Arc) {} diff --git a/servo/components/layout/table_row.rs b/servo/components/layout/table_row.rs index eb0b575cfa7f..19f423a576c3 100644 --- a/servo/components/layout/table_row.rs +++ b/servo/components/layout/table_row.rs @@ -16,6 +16,7 @@ use flow::{self, EarlyAbsolutePositionInfo, Flow, FlowClass, ImmutableFlowUtils, use flow_list::MutFlowListIterator; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; use gfx::display_list::StackingContext; +use gfx_traits::ScrollRootId; use gfx_traits::print_tree::PrintTree; use layout_debug; use model::MaybeAuto; @@ -458,8 +459,10 @@ impl Flow for TableRowFlow { self.block_flow.build_display_list_for_block(state, border_painting_mode); } - fn collect_stacking_contexts(&mut self, parent: &mut StackingContext) { - self.block_flow.collect_stacking_contexts(parent); + fn collect_stacking_contexts(&mut self, + parent: &mut StackingContext, + parent_scroll_root_id: ScrollRootId) { + self.block_flow.collect_stacking_contexts(parent, parent_scroll_root_id); } fn repair_style(&mut self, new_style: &Arc) { diff --git a/servo/components/layout/table_rowgroup.rs b/servo/components/layout/table_rowgroup.rs index 00a31a6bafe4..d1f3e1754a44 100644 --- a/servo/components/layout/table_rowgroup.rs +++ b/servo/components/layout/table_rowgroup.rs @@ -14,6 +14,7 @@ use euclid::Point2D; use flow::{Flow, FlowClass, OpaqueFlow}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; use gfx::display_list::StackingContext; +use gfx_traits::ScrollRootId; use gfx_traits::print_tree::PrintTree; use layout_debug; use rustc_serialize::{Encodable, Encoder}; @@ -211,8 +212,10 @@ impl Flow for TableRowGroupFlow { self.block_flow.build_display_list(state); } - fn collect_stacking_contexts(&mut self, parent: &mut StackingContext) { - self.block_flow.collect_stacking_contexts(parent); + fn collect_stacking_contexts(&mut self, + parent: &mut StackingContext, + parent_scroll_root_id: ScrollRootId) { + self.block_flow.collect_stacking_contexts(parent, parent_scroll_root_id); } fn repair_style(&mut self, new_style: &Arc) { diff --git a/servo/components/layout/table_wrapper.rs b/servo/components/layout/table_wrapper.rs index ec029f8d06fa..1fcf08b249b3 100644 --- a/servo/components/layout/table_wrapper.rs +++ b/servo/components/layout/table_wrapper.rs @@ -23,6 +23,7 @@ use floats::FloatKind; use flow::{Flow, FlowClass, ImmutableFlowUtils, INLINE_POSITION_IS_STATIC, OpaqueFlow}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; use gfx::display_list::StackingContext; +use gfx_traits::ScrollRootId; use gfx_traits::print_tree::PrintTree; use model::MaybeAuto; use std::cmp::{max, min}; @@ -468,8 +469,10 @@ impl Flow for TableWrapperFlow { self.block_flow.build_display_list(state); } - fn collect_stacking_contexts(&mut self, parent: &mut StackingContext) { - self.block_flow.collect_stacking_contexts(parent); + fn collect_stacking_contexts(&mut self, + parent: &mut StackingContext, + parent_scroll_root_id: ScrollRootId) { + self.block_flow.collect_stacking_contexts(parent, parent_scroll_root_id); } fn repair_style(&mut self, new_style: &Arc) { diff --git a/servo/components/layout/traversal.rs b/servo/components/layout/traversal.rs index d80264bb34f5..49b8f1a32c6e 100644 --- a/servo/components/layout/traversal.rs +++ b/servo/components/layout/traversal.rs @@ -264,10 +264,28 @@ impl<'a> BuildDisplayList<'a> { #[inline] pub fn traverse(&mut self, flow: &mut Flow) { if self.should_process() { - self.state.push_stacking_context_id(flow::base(flow).stacking_context_id); + let new_stacking_context = + flow::base(flow).stacking_context_id != self.state.stacking_context_id(); + if new_stacking_context { + self.state.push_stacking_context_id(flow::base(flow).stacking_context_id); + } + + let new_scroll_root = + flow::base(flow).scroll_root_id != self.state.scroll_root_id(); + if new_scroll_root { + self.state.push_scroll_root_id(flow::base(flow).scroll_root_id); + } + flow.build_display_list(&mut self.state); flow::mut_base(flow).restyle_damage.remove(REPAINT); - self.state.pop_stacking_context_id(); + + if new_stacking_context { + self.state.pop_stacking_context_id(); + } + + if new_scroll_root { + self.state.pop_scroll_root_id(); + } } for kid in flow::child_iter_mut(flow) { diff --git a/servo/components/layout/webrender_helpers.rs b/servo/components/layout/webrender_helpers.rs index 91402a315e50..d58a346867c1 100644 --- a/servo/components/layout/webrender_helpers.rs +++ b/servo/components/layout/webrender_helpers.rs @@ -13,7 +13,7 @@ use euclid::{Point2D, Rect, Size2D}; use gfx::display_list::{BorderRadii, BoxShadowClipMode, ClippingRegion}; use gfx::display_list::{DisplayItem, DisplayList, DisplayListTraversal}; use gfx::display_list::{GradientStop, StackingContext, StackingContextType}; -use gfx_traits::{FragmentType, ScrollPolicy, StackingContextId}; +use gfx_traits::{FragmentType, ScrollPolicy, StackingContextId, ScrollRootId}; use style::computed_values::{image_rendering, mix_blend_mode}; use style::computed_values::filter::{self, Filter}; use style::values::computed::BorderStyle; @@ -287,18 +287,16 @@ impl WebRenderStackingContextConverter for StackingContext { ScrollPolicy::FixedPosition => webrender_traits::ScrollPolicy::Fixed, }; - let webrender_stacking_context_id = self.id.convert_to_webrender(); - - let scroll_layer_id = if self.overflow_scroll_id.is_some() || - self.id == StackingContextId::root() { - Some(frame_builder.next_scroll_layer_id()) + let scroll_layer_id = if let Some(scroll_root_id) = self.overflow_scroll_id { + Some(frame_builder.next_scroll_layer_id(scroll_root_id)) + } else if self.id == StackingContextId::root() { + Some(frame_builder.next_scroll_layer_id(ScrollRootId::root())) } else { None }; let mut sc = - webrender_traits::StackingContext::new(webrender_stacking_context_id, - scroll_layer_id, + webrender_traits::StackingContext::new(scroll_layer_id, webrender_scroll_policy, self.bounds.to_rectf(), self.overflow.to_rectf(), @@ -532,21 +530,25 @@ impl WebRenderFrameBuilder { id } - pub fn next_scroll_layer_id(&mut self) -> webrender_traits::ScrollLayerId { + pub fn next_scroll_layer_id(&mut self, + scroll_root_id: ScrollRootId) + -> webrender_traits::ScrollLayerId { let scroll_layer_id = self.next_scroll_layer_id; self.next_scroll_layer_id += 1; - webrender_traits::ScrollLayerId::new(self.root_pipeline_id, scroll_layer_id) + webrender_traits::ScrollLayerId::new(self.root_pipeline_id, + scroll_layer_id, + scroll_root_id.convert_to_webrender()) + } } -trait WebRenderStackingContextIdConverter { - fn convert_to_webrender(&self) -> webrender_traits::ServoStackingContextId; +trait WebRenderScrollRootIdConverter { + fn convert_to_webrender(&self) -> webrender_traits::ServoScrollRootId; } -impl WebRenderStackingContextIdConverter for StackingContextId { - fn convert_to_webrender(&self) -> webrender_traits::ServoStackingContextId { - webrender_traits::ServoStackingContextId(self.fragment_type().convert_to_webrender(), - self.id()) +impl WebRenderScrollRootIdConverter for ScrollRootId { + fn convert_to_webrender(&self) -> webrender_traits::ServoScrollRootId { + webrender_traits::ServoScrollRootId(self.0) } } diff --git a/servo/components/layout_thread/lib.rs b/servo/components/layout_thread/lib.rs index a2ad05025a6b..71d98a21e4f5 100644 --- a/servo/components/layout_thread/lib.rs +++ b/servo/components/layout_thread/lib.rs @@ -57,7 +57,7 @@ use gfx::display_list::{StackingContext, StackingContextType, WebRenderImageInfo use gfx::font; use gfx::font_cache_thread::FontCacheThread; use gfx::font_context; -use gfx_traits::{Epoch, FragmentType, ScrollPolicy, StackingContextId, color}; +use gfx_traits::{Epoch, FragmentType, ScrollPolicy, ScrollRootId, StackingContextId, color}; use heapsize::HeapSizeOf; use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; use ipc_channel::router::ROUTER; @@ -1285,14 +1285,13 @@ impl LayoutThread { let mut layout_scroll_states = HashMap::new(); for new_scroll_state in &new_scroll_states { let offset = new_scroll_state.scroll_offset; - layout_scroll_states.insert(new_scroll_state.stacking_context_id, offset); + layout_scroll_states.insert(new_scroll_state.scroll_root_id, offset); - if new_scroll_state.stacking_context_id == StackingContextId::root() { + if new_scroll_state.scroll_root_id == ScrollRootId::root() { script_scroll_states.push((UntrustedNodeAddress::from_id(0), offset)) - } else if !new_scroll_state.stacking_context_id.is_special() && - new_scroll_state.stacking_context_id.fragment_type() == - FragmentType::FragmentBody { - let id = new_scroll_state.stacking_context_id.id(); + } else if !new_scroll_state.scroll_root_id.is_special() && + new_scroll_state.scroll_root_id.fragment_type() == FragmentType::FragmentBody { + let id = new_scroll_state.scroll_root_id.id(); script_scroll_states.push((UntrustedNodeAddress::from_id(id), offset)) } } diff --git a/servo/components/script_traits/lib.rs b/servo/components/script_traits/lib.rs index e700c47ae476..62b6ef55ec56 100644 --- a/servo/components/script_traits/lib.rs +++ b/servo/components/script_traits/lib.rs @@ -45,7 +45,7 @@ use euclid::scale_factor::ScaleFactor; use euclid::size::TypedSize2D; use gfx_traits::DevicePixel; use gfx_traits::Epoch; -use gfx_traits::StackingContextId; +use gfx_traits::ScrollRootId; use heapsize::HeapSizeOf; use hyper::header::Headers; use hyper::method::Method; @@ -600,8 +600,8 @@ pub enum AnimationTickType { /// The scroll state of a stacking context. #[derive(Copy, Clone, Debug, Deserialize, Serialize)] pub struct StackingContextScrollState { - /// The ID of the stacking context. - pub stacking_context_id: StackingContextId, + /// The ID of the scroll root. + pub scroll_root_id: ScrollRootId, /// The scrolling offset of this stacking context. pub scroll_offset: Point2D, } diff --git a/servo/components/servo/Cargo.lock b/servo/components/servo/Cargo.lock index cca7d499f746..3ced06b6f79c 100644 --- a/servo/components/servo/Cargo.lock +++ b/servo/components/servo/Cargo.lock @@ -46,8 +46,8 @@ dependencies = [ "util 0.0.1", "util_tests 0.0.1", "webdriver_server 0.0.1", - "webrender 0.7.0 (git+https://github.com/servo/webrender)", - "webrender_traits 0.7.0 (git+https://github.com/servo/webrender)", + "webrender 0.8.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -233,7 +233,7 @@ dependencies = [ "offscreen_gl_context 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "plugins 0.0.1", "util 0.0.1", - "webrender_traits 0.7.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -250,7 +250,7 @@ dependencies = [ "plugins 0.0.1", "serde 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 0.8.12 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_traits 0.7.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -338,8 +338,8 @@ dependencies = [ "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", - "webrender 0.7.0 (git+https://github.com/servo/webrender)", - "webrender_traits 0.7.0 (git+https://github.com/servo/webrender)", + "webrender 0.8.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -370,7 +370,7 @@ dependencies = [ "style_traits 0.0.1", "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", - "webrender_traits 0.7.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -815,7 +815,7 @@ dependencies = [ "unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", - "webrender_traits 0.7.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "xi-unicode 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1167,7 +1167,7 @@ dependencies = [ "unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", - "webrender_traits 0.7.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -1207,7 +1207,7 @@ dependencies = [ "style 0.0.1", "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", - "webrender_traits 0.7.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -1221,7 +1221,7 @@ dependencies = [ "profile_traits 0.0.1", "script_traits 0.0.1", "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_traits 0.7.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -1390,7 +1390,7 @@ dependencies = [ "plugins 0.0.1", "serde 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 0.8.12 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_traits 0.7.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -1428,7 +1428,7 @@ dependencies = [ "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", "uuid 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_traits 0.7.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)", "websocket 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1486,7 +1486,7 @@ dependencies = [ "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", "uuid 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_traits 0.7.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)", "websocket 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1983,7 +1983,7 @@ dependencies = [ "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", "uuid 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_traits 0.7.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)", "websocket 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", "xml5ever 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2659,8 +2659,8 @@ dependencies = [ [[package]] name = "webrender" -version = "0.7.0" -source = "git+https://github.com/servo/webrender#4440d1daa3d6e9630d4b164f7bae644b9dc4cb8a" +version = "0.8.0" +source = "git+https://github.com/servo/webrender#d44b1ffd3ea9e9e97ef7a70c1ac0f53bbd626850" 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)", @@ -2679,13 +2679,13 @@ dependencies = [ "offscreen_gl_context 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 0.4.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.7.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)", ] [[package]] name = "webrender_traits" -version = "0.7.0" -source = "git+https://github.com/servo/webrender#4440d1daa3d6e9630d4b164f7bae644b9dc4cb8a" +version = "0.8.0" +source = "git+https://github.com/servo/webrender#d44b1ffd3ea9e9e97ef7a70c1ac0f53bbd626850" 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)", @@ -3001,8 +3001,8 @@ dependencies = [ "checksum wayland-sys 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9633f7fe5de56544215f82eaf1b76bf1b584becf7f08b58cbef4c2c7d10e803a" "checksum wayland-window 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "309b69d3a863c9c21422d889fb7d98cf02f8a2ca054960a49243ce5b67ad884c" "checksum webdriver 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee2d66e90672022ced375134329c57be4db228b19b120b97b744a469c381be06" -"checksum webrender 0.7.0 (git+https://github.com/servo/webrender)" = "" -"checksum webrender_traits 0.7.0 (git+https://github.com/servo/webrender)" = "" +"checksum webrender 0.8.0 (git+https://github.com/servo/webrender)" = "" +"checksum webrender_traits 0.8.0 (git+https://github.com/servo/webrender)" = "" "checksum websocket 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a1a6ea5ed0367f32eb3d94dcc58859ef4294b5f75ba983dbf56ac314af45d" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/servo/ports/cef/Cargo.lock b/servo/ports/cef/Cargo.lock index 7f29f8e48765..af719ba3928c 100644 --- a/servo/ports/cef/Cargo.lock +++ b/servo/ports/cef/Cargo.lock @@ -206,7 +206,7 @@ dependencies = [ "offscreen_gl_context 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "plugins 0.0.1", "util 0.0.1", - "webrender_traits 0.7.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -223,7 +223,7 @@ dependencies = [ "plugins 0.0.1", "serde 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 0.8.12 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_traits 0.7.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -295,8 +295,8 @@ dependencies = [ "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", - "webrender 0.7.0 (git+https://github.com/servo/webrender)", - "webrender_traits 0.7.0 (git+https://github.com/servo/webrender)", + "webrender 0.8.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -327,7 +327,7 @@ dependencies = [ "style_traits 0.0.1", "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", - "webrender_traits 0.7.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -731,7 +731,7 @@ dependencies = [ "unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", - "webrender_traits 0.7.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "xi-unicode 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1074,7 +1074,7 @@ dependencies = [ "unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", - "webrender_traits 0.7.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -1107,7 +1107,7 @@ dependencies = [ "style 0.0.1", "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", - "webrender_traits 0.7.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -1121,7 +1121,7 @@ dependencies = [ "profile_traits 0.0.1", "script_traits 0.0.1", "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_traits 0.7.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -1290,7 +1290,7 @@ dependencies = [ "plugins 0.0.1", "serde 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 0.8.12 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_traits 0.7.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -1328,7 +1328,7 @@ dependencies = [ "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", "uuid 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_traits 0.7.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)", "websocket 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1364,7 +1364,7 @@ dependencies = [ "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", "uuid 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_traits 0.7.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)", "websocket 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1834,7 +1834,7 @@ dependencies = [ "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", "uuid 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_traits 0.7.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)", "websocket 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", "xml5ever 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1991,8 +1991,8 @@ dependencies = [ "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", "webdriver_server 0.0.1", - "webrender 0.7.0 (git+https://github.com/servo/webrender)", - "webrender_traits 0.7.0 (git+https://github.com/servo/webrender)", + "webrender 0.8.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)", ] [[package]] @@ -2517,8 +2517,8 @@ dependencies = [ [[package]] name = "webrender" -version = "0.7.0" -source = "git+https://github.com/servo/webrender#4440d1daa3d6e9630d4b164f7bae644b9dc4cb8a" +version = "0.8.0" +source = "git+https://github.com/servo/webrender#d44b1ffd3ea9e9e97ef7a70c1ac0f53bbd626850" 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)", @@ -2537,13 +2537,13 @@ dependencies = [ "offscreen_gl_context 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 0.4.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.7.0 (git+https://github.com/servo/webrender)", + "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)", ] [[package]] name = "webrender_traits" -version = "0.7.0" -source = "git+https://github.com/servo/webrender#4440d1daa3d6e9630d4b164f7bae644b9dc4cb8a" +version = "0.8.0" +source = "git+https://github.com/servo/webrender#d44b1ffd3ea9e9e97ef7a70c1ac0f53bbd626850" 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)", @@ -2853,8 +2853,8 @@ dependencies = [ "checksum wayland-sys 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9633f7fe5de56544215f82eaf1b76bf1b584becf7f08b58cbef4c2c7d10e803a" "checksum wayland-window 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "309b69d3a863c9c21422d889fb7d98cf02f8a2ca054960a49243ce5b67ad884c" "checksum webdriver 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee2d66e90672022ced375134329c57be4db228b19b120b97b744a469c381be06" -"checksum webrender 0.7.0 (git+https://github.com/servo/webrender)" = "" -"checksum webrender_traits 0.7.0 (git+https://github.com/servo/webrender)" = "" +"checksum webrender 0.8.0 (git+https://github.com/servo/webrender)" = "" +"checksum webrender_traits 0.8.0 (git+https://github.com/servo/webrender)" = "" "checksum websocket 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a1a6ea5ed0367f32eb3d94dcc58859ef4294b5f75ba983dbf56ac314af45d" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/servo/resources/shaders/cs_box_shadow.fs.glsl b/servo/resources/shaders/cs_box_shadow.fs.glsl new file mode 100644 index 000000000000..3243dc6d6284 --- /dev/null +++ b/servo/resources/shaders/cs_box_shadow.fs.glsl @@ -0,0 +1,148 @@ +#line 1 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// See http://asciimath.org to render the equations here. + +// The Gaussian function used for blurring: +// +// G_sigma(x) = 1/sqrt(2 pi sigma^2) e^(-x^2/(2 sigma^2)) +float gauss(float x, float sigma) { + float sigmaPow2 = sigma * sigma; + return 1.0 / sqrt(6.283185307179586 * sigmaPow2) * exp(-(x * x) / (2.0 * sigmaPow2)); +} + +// An approximation of the error function, which is related to the integral of the Gaussian +// function: +// +// "erf"(x) = 2/sqrt(pi) int_0^x e^(-t^2) dt +// ~~ 1 - 1 / (1 + a_1 x + a_2 x^2 + a_3 x^3 + a_4 x^4)^4 +// +// where: +// +// a_1 = 0.278393, a_2 = 0.230389, a_3 = 0.000972, a_4 = 0.078108 +// +// This approximation is accurate to `5 xx 10^-4`, more than accurate enough for our purposes. +// +// See: https://en.wikipedia.org/wiki/Error_function#Approximation_with_elementary_functions +float erf(float x) { + bool negative = x < 0.0; + if (negative) + x = -x; + float x2 = x * x; + float x3 = x2 * x; + float x4 = x2 * x2; + float denom = 1.0 + 0.278393 * x + 0.230389 * x2 + 0.000972 * x3 + 0.078108 * x4; + float result = 1.0 - 1.0 / (denom * denom * denom * denom); + return negative ? -result : result; +} + +// A useful helper for calculating integrals of the Gaussian function via the error function: +// +// "erf"_sigma(x) = 2 int 1/sqrt(2 pi sigma^2) e^(-x^2/(2 sigma^2)) dx +// = "erf"(x/(sigma sqrt(2))) +float erfSigma(float x, float sigma) { + return erf(x / (sigma * 1.4142135623730951)); +} + +// Returns the blurred color value from the box itself (not counting any rounded corners). `p_0` is +// the vector distance to the top left corner of the box; `p_1` is the vector distance to its +// bottom right corner. +// +// "colorFromRect"_sigma(p_0, p_1) +// = int_{p_{0_y}}^{p_{1_y}} int_{p_{1_x}}^{p_{0_x}} G_sigma(y) G_sigma(x) dx dy +// = 1/4 ("erf"_sigma(p_{1_x}) - "erf"_sigma(p_{0_x})) +// ("erf"_sigma(p_{1_y}) - "erf"_sigma(p_{0_y})) +float colorFromRect(vec2 p0, vec2 p1, float sigma) { + return (erfSigma(p1.x, sigma) - erfSigma(p0.x, sigma)) * + (erfSigma(p1.y, sigma) - erfSigma(p0.y, sigma)) / 4.0; +} + +// Returns the `x` coordinate on the ellipse with the given radii for the given `y` coordinate: +// +// "ellipsePoint"(y, y_0, a, b) = a sqrt(1 - ((y - y_0) / b)^2) +float ellipsePoint(float y, float y0, vec2 radii) { + float bStep = (y - y0) / radii.y; + return radii.x * sqrt(1.0 - bStep * bStep); +} + +// A helper function to compute the value that needs to be subtracted to accommodate the border +// corners. +// +// "colorCutout"_sigma(x_{0_l}, x_{0_r}, y_0, y_{min}, y_{max}, a, b) +// = int_{y_{min}}^{y_{max}} +// int_{x_{0_r} + "ellipsePoint"(y, y_0, a, b)}^{x_{0_r} + a} G_sigma(y) G_sigma(x) dx +// + int_{x_{0_l} - a}^{x_{0_l} - "ellipsePoint"(y, y_0, a, b)} G_sigma(y) G_sigma(x) +// dx dy +// = int_{y_{min}}^{y_{max}} 1/2 G_sigma(y) +// ("erf"_sigma(x_{0_r} + a) - "erf"_sigma(x_{0_r} + "ellipsePoint"(y, y_0, a, b)) + +// "erf"_sigma(x_{0_l} - "ellipsePoint"(y, y_0, a, b)) - "erf"_sigma(x_{0_l} - a)) +// +// with the outer integral evaluated numerically. +float colorCutoutGeneral(float x0l, + float x0r, + float y0, + float yMin, + float yMax, + vec2 radii, + float sigma) { + float sum = 0.0; + for (float y = yMin; y <= yMax; y += 1.0) { + float xEllipsePoint = ellipsePoint(y, y0, radii); + sum += gauss(y, sigma) * + (erfSigma(x0r + radii.x, sigma) - erfSigma(x0r + xEllipsePoint, sigma) + + erfSigma(x0l - xEllipsePoint, sigma) - erfSigma(x0l - radii.x, sigma)); + } + return sum / 2.0; +} + +// The value that needs to be subtracted to accommodate the top border corners. +float colorCutoutTop(float x0l, float x0r, float y0, vec2 radii, float sigma) { + return colorCutoutGeneral(x0l, x0r, y0, y0, y0 + radii.y, radii, sigma); +} + +// The value that needs to be subtracted to accommodate the bottom border corners. +float colorCutoutBottom(float x0l, float x0r, float y0, vec2 radii, float sigma) { + return colorCutoutGeneral(x0l, x0r, y0, y0 - radii.y, y0, radii, sigma); +} + +// The blurred color value for the point at `pos` with the top left corner of the box at +// `p_{0_"rect"}` and the bottom right corner of the box at `p_{1_"rect"}`. +float color(vec2 pos, vec2 p0Rect, vec2 p1Rect, vec2 radii, float sigma) { + // Compute the vector distances `p_0` and `p_1`. + vec2 p0 = p0Rect - pos, p1 = p1Rect - pos; + + // Compute the basic color `"colorFromRect"_sigma(p_0, p_1)`. This is all we have to do if + // the box is unrounded. + float cRect = colorFromRect(p0, p1, sigma); + if (radii.x == 0.0 || radii.y == 0.0) + return cRect; + + // Compute the inner corners of the box, taking border radii into account: `x_{0_l}`, + // `y_{0_t}`, `x_{0_r}`, and `y_{0_b}`. + float x0l = p0.x + radii.x; + float y0t = p1.y - radii.y; + float x0r = p1.x - radii.x; + float y0b = p0.y + radii.y; + + // Compute the final color: + // + // "colorFromRect"_sigma(p_0, p_1) - + // ("colorCutoutTop"_sigma(x_{0_l}, x_{0_r}, y_{0_t}, a, b) + + // "colorCutoutBottom"_sigma(x_{0_l}, x_{0_r}, y_{0_b}, a, b)) + float cCutoutTop = colorCutoutTop(x0l, x0r, y0t, radii, sigma); + float cCutoutBottom = colorCutoutBottom(x0l, x0r, y0b, radii, sigma); + return cRect - (cCutoutTop + cCutoutBottom); +} + +void main(void) { + vec2 pos = vPos.xy; + vec2 p0Rect = vBoxShadowRect.xy, p1Rect = vBoxShadowRect.zw; + vec2 radii = vBorderRadii.xy; + float sigma = vBlurRadius / 2.0; + float value = color(pos, p0Rect, p1Rect, radii, sigma); + + value = max(value, 0.0); + oFragColor = vec4(1.0, 1.0, 1.0, vInverted == 1.0 ? 1.0 - value : value); +} diff --git a/servo/resources/shaders/cs_box_shadow.glsl b/servo/resources/shaders/cs_box_shadow.glsl new file mode 100644 index 000000000000..9e5dd036c542 --- /dev/null +++ b/servo/resources/shaders/cs_box_shadow.glsl @@ -0,0 +1,10 @@ +#line 1 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +varying vec2 vPos; +flat varying vec2 vBorderRadii; +flat varying float vBlurRadius; +flat varying vec4 vBoxShadowRect; +flat varying float vInverted; diff --git a/servo/resources/shaders/cs_box_shadow.vs.glsl b/servo/resources/shaders/cs_box_shadow.vs.glsl new file mode 100644 index 000000000000..fce6e53af1d6 --- /dev/null +++ b/servo/resources/shaders/cs_box_shadow.vs.glsl @@ -0,0 +1,31 @@ +#line 1 +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +void main(void) { + CachePrimitiveInstance cpi = fetch_cache_instance(gl_InstanceID); + RenderTaskData task = fetch_render_task(cpi.render_task_index); + BoxShadow bs = fetch_boxshadow(cpi.specific_prim_index); + + vec2 p0 = task.data0.xy; + vec2 p1 = p0 + task.data0.zw; + + vec2 pos = mix(p0, p1, aPosition.xy); + + vBorderRadii = bs.border_radius_edge_size_blur_radius_inverted.xx; + vBlurRadius = bs.border_radius_edge_size_blur_radius_inverted.z; + vInverted = bs.border_radius_edge_size_blur_radius_inverted.w; + vBoxShadowRect = vec4(bs.bs_rect.xy, bs.bs_rect.xy + bs.bs_rect.zw); + + // The fragment shader expects logical units, beginning at where the + // blur radius begins. + // The first path of the equation gets the virtual position in + // logical pixels within the patch rectangle (accounting for + // bilinear offset). Then we add the start position of the + // box shadow rect and subtract the blur radius to get the + // virtual coordinates that the FS expects. + vPos = (pos - 1.0 - p0) / uDevicePixelRatio + bs.bs_rect.xy - vec2(2.0 * vBlurRadius); + + gl_Position = uTransform * vec4(pos, 0.0, 1.0); +} diff --git a/servo/resources/shaders/prim_shared.glsl b/servo/resources/shaders/prim_shared.glsl index d25b7152540b..6d6b04e58148 100644 --- a/servo/resources/shaders/prim_shared.glsl +++ b/servo/resources/shaders/prim_shared.glsl @@ -39,7 +39,7 @@ uniform sampler2DArray sCache; #ifdef WR_VERTEX_SHADER #define VECS_PER_LAYER 13 -#define VECS_PER_TILE 2 +#define VECS_PER_RENDER_TASK 2 #define VECS_PER_PRIM_GEOM 2 #define GRADIENT_HORIZONTAL 0 @@ -121,18 +121,33 @@ Layer fetch_layer(int index) { return layer; } +struct RenderTaskData { + vec4 data0; + vec4 data1; +}; + +RenderTaskData fetch_render_task(int index) { + RenderTaskData task; + + ivec2 uv = get_fetch_uv(index, VECS_PER_RENDER_TASK); + + task.data0 = texelFetchOffset(sRenderTasks, uv, 0, ivec2(0, 0)); + task.data1 = texelFetchOffset(sRenderTasks, uv, 0, ivec2(1, 0)); + + return task; +} + struct Tile { vec4 screen_origin_task_origin; vec4 size_target_index; }; Tile fetch_tile(int index) { + RenderTaskData task = fetch_render_task(index); + Tile tile; - - ivec2 uv = get_fetch_uv(index, VECS_PER_TILE); - - tile.screen_origin_task_origin = texelFetchOffset(sRenderTasks, uv, 0, ivec2(0, 0)); - tile.size_target_index = texelFetchOffset(sRenderTasks, uv, 0, ivec2(1, 0)); + tile.screen_origin_task_origin = task.data0; + tile.size_target_index = task.data1; return tile; } @@ -259,6 +274,27 @@ PrimitiveInstance fetch_instance(int index) { return pi; } + +struct CachePrimitiveInstance { + int global_prim_index; + int specific_prim_index; + int render_task_index; +}; + +CachePrimitiveInstance fetch_cache_instance(int index) { + CachePrimitiveInstance cpi; + + int offset = index * 1; + + ivec4 data0 = int_data[offset + 0]; + + cpi.global_prim_index = data0.x; + cpi.specific_prim_index = data0.y; + cpi.render_task_index = data0.z; + + return cpi; +} + struct Primitive { Layer layer; Tile tile; @@ -553,7 +589,7 @@ struct BoxShadow { vec4 src_rect; vec4 bs_rect; vec4 color; - vec4 border_radii_blur_radius_inverted; + vec4 border_radius_edge_size_blur_radius_inverted; }; BoxShadow fetch_boxshadow(int index) { @@ -564,7 +600,7 @@ BoxShadow fetch_boxshadow(int index) { bs.src_rect = texelFetchOffset(sData64, uv, 0, ivec2(0, 0)); bs.bs_rect = texelFetchOffset(sData64, uv, 0, ivec2(1, 0)); bs.color = texelFetchOffset(sData64, uv, 0, ivec2(2, 0)); - bs.border_radii_blur_radius_inverted = texelFetchOffset(sData64, uv, 0, ivec2(3, 0)); + bs.border_radius_edge_size_blur_radius_inverted = texelFetchOffset(sData64, uv, 0, ivec2(3, 0)); return bs; } diff --git a/servo/resources/shaders/ps_box_shadow.fs.glsl b/servo/resources/shaders/ps_box_shadow.fs.glsl index 9c485cba9fed..8392ab698beb 100644 --- a/servo/resources/shaders/ps_box_shadow.fs.glsl +++ b/servo/resources/shaders/ps_box_shadow.fs.glsl @@ -2,150 +2,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -// See http://asciimath.org to render the equations here. - -// The Gaussian function used for blurring: -// -// G_sigma(x) = 1/sqrt(2 pi sigma^2) e^(-x^2/(2 sigma^2)) -float gauss(float x, float sigma) { - float sigmaPow2 = sigma * sigma; - return 1.0 / sqrt(6.283185307179586 * sigmaPow2) * exp(-(x * x) / (2.0 * sigmaPow2)); -} - -// An approximation of the error function, which is related to the integral of the Gaussian -// function: -// -// "erf"(x) = 2/sqrt(pi) int_0^x e^(-t^2) dt -// ~~ 1 - 1 / (1 + a_1 x + a_2 x^2 + a_3 x^3 + a_4 x^4)^4 -// -// where: -// -// a_1 = 0.278393, a_2 = 0.230389, a_3 = 0.000972, a_4 = 0.078108 -// -// This approximation is accurate to `5 xx 10^-4`, more than accurate enough for our purposes. -// -// See: https://en.wikipedia.org/wiki/Error_function#Approximation_with_elementary_functions -float erf(float x) { - bool negative = x < 0.0; - if (negative) - x = -x; - float x2 = x * x; - float x3 = x2 * x; - float x4 = x2 * x2; - float denom = 1.0 + 0.278393 * x + 0.230389 * x2 + 0.000972 * x3 + 0.078108 * x4; - float result = 1.0 - 1.0 / (denom * denom * denom * denom); - return negative ? -result : result; -} - -// A useful helper for calculating integrals of the Gaussian function via the error function: -// -// "erf"_sigma(x) = 2 int 1/sqrt(2 pi sigma^2) e^(-x^2/(2 sigma^2)) dx -// = "erf"(x/(sigma sqrt(2))) -float erfSigma(float x, float sigma) { - return erf(x / (sigma * 1.4142135623730951)); -} - -// Returns the blurred color value from the box itself (not counting any rounded corners). `p_0` is -// the vector distance to the top left corner of the box; `p_1` is the vector distance to its -// bottom right corner. -// -// "colorFromRect"_sigma(p_0, p_1) -// = int_{p_{0_y}}^{p_{1_y}} int_{p_{1_x}}^{p_{0_x}} G_sigma(y) G_sigma(x) dx dy -// = 1/4 ("erf"_sigma(p_{1_x}) - "erf"_sigma(p_{0_x})) -// ("erf"_sigma(p_{1_y}) - "erf"_sigma(p_{0_y})) -float colorFromRect(vec2 p0, vec2 p1, float sigma) { - return (erfSigma(p1.x, sigma) - erfSigma(p0.x, sigma)) * - (erfSigma(p1.y, sigma) - erfSigma(p0.y, sigma)) / 4.0; -} - -// Returns the `x` coordinate on the ellipse with the given radii for the given `y` coordinate: -// -// "ellipsePoint"(y, y_0, a, b) = a sqrt(1 - ((y - y_0) / b)^2) -float ellipsePoint(float y, float y0, vec2 radii) { - float bStep = (y - y0) / radii.y; - return radii.x * sqrt(1.0 - bStep * bStep); -} - -// A helper function to compute the value that needs to be subtracted to accommodate the border -// corners. -// -// "colorCutout"_sigma(x_{0_l}, x_{0_r}, y_0, y_{min}, y_{max}, a, b) -// = int_{y_{min}}^{y_{max}} -// int_{x_{0_r} + "ellipsePoint"(y, y_0, a, b)}^{x_{0_r} + a} G_sigma(y) G_sigma(x) dx -// + int_{x_{0_l} - a}^{x_{0_l} - "ellipsePoint"(y, y_0, a, b)} G_sigma(y) G_sigma(x) -// dx dy -// = int_{y_{min}}^{y_{max}} 1/2 G_sigma(y) -// ("erf"_sigma(x_{0_r} + a) - "erf"_sigma(x_{0_r} + "ellipsePoint"(y, y_0, a, b)) + -// "erf"_sigma(x_{0_l} - "ellipsePoint"(y, y_0, a, b)) - "erf"_sigma(x_{0_l} - a)) -// -// with the outer integral evaluated numerically. -float colorCutoutGeneral(float x0l, - float x0r, - float y0, - float yMin, - float yMax, - vec2 radii, - float sigma) { - float sum = 0.0; - for (float y = yMin; y <= yMax; y += 1.0) { - float xEllipsePoint = ellipsePoint(y, y0, radii); - sum += gauss(y, sigma) * - (erfSigma(x0r + radii.x, sigma) - erfSigma(x0r + xEllipsePoint, sigma) + - erfSigma(x0l - xEllipsePoint, sigma) - erfSigma(x0l - radii.x, sigma)); - } - return sum / 2.0; -} - -// The value that needs to be subtracted to accommodate the top border corners. -float colorCutoutTop(float x0l, float x0r, float y0, vec2 radii, float sigma) { - return colorCutoutGeneral(x0l, x0r, y0, y0, y0 + radii.y, radii, sigma); -} - -// The value that needs to be subtracted to accommodate the bottom border corners. -float colorCutoutBottom(float x0l, float x0r, float y0, vec2 radii, float sigma) { - return colorCutoutGeneral(x0l, x0r, y0, y0 - radii.y, y0, radii, sigma); -} - -// The blurred color value for the point at `pos` with the top left corner of the box at -// `p_{0_"rect"}` and the bottom right corner of the box at `p_{1_"rect"}`. -float color(vec2 pos, vec2 p0Rect, vec2 p1Rect, vec2 radii, float sigma) { - // Compute the vector distances `p_0` and `p_1`. - vec2 p0 = p0Rect - pos, p1 = p1Rect - pos; - - // Compute the basic color `"colorFromRect"_sigma(p_0, p_1)`. This is all we have to do if - // the box is unrounded. - float cRect = colorFromRect(p0, p1, sigma); - if (radii.x == 0.0 || radii.y == 0.0) - return cRect; - - // Compute the inner corners of the box, taking border radii into account: `x_{0_l}`, - // `y_{0_t}`, `x_{0_r}`, and `y_{0_b}`. - float x0l = p0.x + radii.x; - float y0t = p1.y - radii.y; - float x0r = p1.x - radii.x; - float y0b = p0.y + radii.y; - - // Compute the final color: - // - // "colorFromRect"_sigma(p_0, p_1) - - // ("colorCutoutTop"_sigma(x_{0_l}, x_{0_r}, y_{0_t}, a, b) + - // "colorCutoutBottom"_sigma(x_{0_l}, x_{0_r}, y_{0_b}, a, b)) - float cCutoutTop = colorCutoutTop(x0l, x0r, y0t, radii, sigma); - float cCutoutBottom = colorCutoutBottom(x0l, x0r, y0b, radii, sigma); - return cRect - (cCutoutTop + cCutoutBottom); -} - void main(void) { - vec2 pos = vPos.xy; - vec2 p0Rect = vBoxShadowRect.xy, p1Rect = vBoxShadowRect.zw; - vec2 radii = vBorderRadii.xy; - float sigma = vBlurRadius / 2.0; - float value = color(pos, p0Rect, p1Rect, radii, sigma); - - value = max(value, 0.0); - oFragColor = vColor * vec4(1.0, 1.0, 1.0, vInverted == 1.0 ? 1.0 - value : value); + vec2 uv = min(vec2(1.0), vMirrorPoint - abs(vUv.xy - vMirrorPoint)); + uv = mix(vCacheUvRectCoords.xy, vCacheUvRectCoords.zw, uv); + oFragColor = vColor * texture(sCache, vec3(uv, vUv.z)); } diff --git a/servo/resources/shaders/ps_box_shadow.glsl b/servo/resources/shaders/ps_box_shadow.glsl index 26fdba588f36..40faee87f583 100644 --- a/servo/resources/shaders/ps_box_shadow.glsl +++ b/servo/resources/shaders/ps_box_shadow.glsl @@ -2,10 +2,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -varying vec2 vPos; flat varying vec4 vColor; -flat varying vec2 vBorderRadii; -flat varying float vBlurRadius; -flat varying vec4 vBoxShadowRect; -flat varying vec4 vSrcRect; -flat varying float vInverted; + +varying vec3 vUv; +flat varying vec2 vMirrorPoint; +flat varying vec4 vCacheUvRectCoords; diff --git a/servo/resources/shaders/ps_box_shadow.vs.glsl b/servo/resources/shaders/ps_box_shadow.vs.glsl index e863ab0a8fc3..930aef9062e3 100644 --- a/servo/resources/shaders/ps_box_shadow.vs.glsl +++ b/servo/resources/shaders/ps_box_shadow.vs.glsl @@ -13,11 +13,19 @@ void main(void) { prim.layer, prim.tile); - vPos = vi.local_clamped_pos; + RenderTaskData child_task = fetch_render_task(prim.user_data.z); + vUv.z = child_task.data1.x; + + // Constant offsets to inset from bilinear filtering border. + vec2 patch_origin = child_task.data0.xy + vec2(1.0); + vec2 patch_size_device_pixels = child_task.data0.zw - vec2(2.0); + vec2 patch_size = patch_size_device_pixels / uDevicePixelRatio; + + vUv.xy = (vi.local_clamped_pos - prim.local_rect.xy) / patch_size; + vMirrorPoint = 0.5 * prim.local_rect.zw / patch_size; + + vec2 texture_size = vec2(textureSize(sCache, 0)); + vCacheUvRectCoords = vec4(patch_origin, patch_origin + patch_size_device_pixels) / texture_size.xyxy; + vColor = bs.color; - vBorderRadii = bs.border_radii_blur_radius_inverted.xy; - vBlurRadius = bs.border_radii_blur_radius_inverted.z; - vBoxShadowRect = vec4(bs.bs_rect.xy, bs.bs_rect.xy + bs.bs_rect.zw); - vSrcRect = vec4(bs.src_rect.xy, bs.src_rect.xy + bs.src_rect.zw); - vInverted = bs.border_radii_blur_radius_inverted.w; }