From 71d285af800c874e5bc9d302d3e45e14de1fb7bb Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Fri, 21 Oct 2016 08:03:01 +0200 Subject: [PATCH 1/2] Use a new id type for tracking scrolling areas This is a step in disassociating scrolling areas from stacking contexts. Now scroll areas are defined by unique ids, which means that in the future stacking context will be able to contain more than one. --- components/compositing/compositor.rs | 14 ++--- components/gfx/display_list/mod.rs | 18 +++--- components/gfx_traits/lib.rs | 52 +++++++++++++++++ components/layout/block.rs | 7 ++- components/layout/display_list_builder.rs | 69 ++++++++++++++++------- components/layout/flex.rs | 7 ++- components/layout/flow.rs | 15 +++-- components/layout/inline.rs | 7 ++- components/layout/list_item.rs | 7 ++- components/layout/multicol.rs | 13 +++-- components/layout/sequential.rs | 3 +- components/layout/table.rs | 7 ++- components/layout/table_caption.rs | 7 ++- components/layout/table_cell.rs | 7 ++- components/layout/table_colgroup.rs | 5 +- components/layout/table_row.rs | 7 ++- components/layout/table_rowgroup.rs | 7 ++- components/layout/table_wrapper.rs | 7 ++- components/layout/traversal.rs | 22 +++++++- components/layout/webrender_helpers.rs | 34 +++++------ components/layout_thread/lib.rs | 13 ++--- components/script_traits/lib.rs | 6 +- 22 files changed, 242 insertions(+), 92 deletions(-) diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index 3eadc3dd33d..55127bd64fe 100644 --- a/components/compositing/compositor.rs +++ b/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/components/gfx/display_list/mod.rs b/components/gfx/display_list/mod.rs index 5a3795fec09..36a09aff4a7 100644 --- a/components/gfx/display_list/mod.rs +++ b/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/components/gfx_traits/lib.rs b/components/gfx_traits/lib.rs index b1530aef29b..bdf1a7591eb 100644 --- a/components/gfx_traits/lib.rs +++ b/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/components/layout/block.rs b/components/layout/block.rs index 356b1aaf6b3..91383c12e28 100644 --- a/components/layout/block.rs +++ b/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/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index e714df23314..d665734f947 100644 --- a/components/layout/display_list_builder.rs +++ b/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/components/layout/flex.rs b/components/layout/flex.rs index 69ae5a7bf49..0fca93fb5f3 100644 --- a/components/layout/flex.rs +++ b/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/components/layout/flow.rs b/components/layout/flow.rs index 2c85febaf2c..f68ea3f35fd 100644 --- a/components/layout/flow.rs +++ b/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/components/layout/inline.rs b/components/layout/inline.rs index 055fbeb4a0b..96901638b4c 100644 --- a/components/layout/inline.rs +++ b/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/components/layout/list_item.rs b/components/layout/list_item.rs index 50318f65457..2a925acd883 100644 --- a/components/layout/list_item.rs +++ b/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/components/layout/multicol.rs b/components/layout/multicol.rs index 669f3a59530..14d03c3bd85 100644 --- a/components/layout/multicol.rs +++ b/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/components/layout/sequential.rs b/components/layout/sequential.rs index f2964976ed3..51f2ac874a0 100644 --- a/components/layout/sequential.rs +++ b/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/components/layout/table.rs b/components/layout/table.rs index 9abd030f68b..1d904e00b23 100644 --- a/components/layout/table.rs +++ b/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/components/layout/table_caption.rs b/components/layout/table_caption.rs index 3487aac0f5e..523a1f0e071 100644 --- a/components/layout/table_caption.rs +++ b/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/components/layout/table_cell.rs b/components/layout/table_cell.rs index 8e6394b9a75..ca2af6a4897 100644 --- a/components/layout/table_cell.rs +++ b/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/components/layout/table_colgroup.rs b/components/layout/table_colgroup.rs index 795f24693b7..468e0ffb285 100644 --- a/components/layout/table_colgroup.rs +++ b/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/components/layout/table_row.rs b/components/layout/table_row.rs index eb0b575cfa7..19f423a576c 100644 --- a/components/layout/table_row.rs +++ b/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/components/layout/table_rowgroup.rs b/components/layout/table_rowgroup.rs index 00a31a6bafe..d1f3e1754a4 100644 --- a/components/layout/table_rowgroup.rs +++ b/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/components/layout/table_wrapper.rs b/components/layout/table_wrapper.rs index ec029f8d06f..1fcf08b249b 100644 --- a/components/layout/table_wrapper.rs +++ b/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/components/layout/traversal.rs b/components/layout/traversal.rs index 2ab1e21cebe..983fe76a384 100644 --- a/components/layout/traversal.rs +++ b/components/layout/traversal.rs @@ -247,10 +247,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/components/layout/webrender_helpers.rs b/components/layout/webrender_helpers.rs index 91402a315e5..d58a346867c 100644 --- a/components/layout/webrender_helpers.rs +++ b/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/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index 51ec52cb0d0..2c7e918d67d 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -56,7 +56,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; @@ -1282,14 +1282,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/components/script_traits/lib.rs b/components/script_traits/lib.rs index e700c47ae47..62b6ef55ec5 100644 --- a/components/script_traits/lib.rs +++ b/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, } From 05beb59f474b902b3160b3323f79403efb8f6f3b Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Thu, 27 Oct 2016 09:52:12 +0200 Subject: [PATCH 2/2] Update WebRender This is necessary because the API has changed for scrolling ids. --- components/servo/Cargo.lock | 44 +++---- ports/cef/Cargo.lock | 44 +++---- resources/shaders/cs_box_shadow.fs.glsl | 148 ++++++++++++++++++++++++ resources/shaders/cs_box_shadow.glsl | 10 ++ resources/shaders/cs_box_shadow.vs.glsl | 31 +++++ resources/shaders/prim_shared.glsl | 52 +++++++-- resources/shaders/ps_box_shadow.fs.glsl | 148 +----------------------- resources/shaders/ps_box_shadow.glsl | 10 +- resources/shaders/ps_box_shadow.vs.glsl | 20 +++- 9 files changed, 298 insertions(+), 209 deletions(-) create mode 100644 resources/shaders/cs_box_shadow.fs.glsl create mode 100644 resources/shaders/cs_box_shadow.glsl create mode 100644 resources/shaders/cs_box_shadow.vs.glsl diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index 211f46106ee..6b99146dee0 100644 --- a/components/servo/Cargo.lock +++ b/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)", ] @@ -1166,7 +1166,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]] @@ -1205,7 +1205,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]] @@ -1219,7 +1219,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]] @@ -1388,7 +1388,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]] @@ -1426,7 +1426,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)", ] @@ -1484,7 +1484,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)", ] @@ -1989,7 +1989,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)", ] @@ -2666,8 +2666,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)", @@ -2686,13 +2686,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)", @@ -3009,8 +3009,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/ports/cef/Cargo.lock b/ports/cef/Cargo.lock index 1e44021bfbf..835d008f4f3 100644 --- a/ports/cef/Cargo.lock +++ b/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)", ] @@ -1073,7 +1073,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]] @@ -1105,7 +1105,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]] @@ -1119,7 +1119,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]] @@ -1288,7 +1288,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]] @@ -1326,7 +1326,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)", ] @@ -1362,7 +1362,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)", ] @@ -1840,7 +1840,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)", ] @@ -1998,8 +1998,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]] @@ -2524,8 +2524,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)", @@ -2544,13 +2544,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)", @@ -2861,8 +2861,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/resources/shaders/cs_box_shadow.fs.glsl b/resources/shaders/cs_box_shadow.fs.glsl new file mode 100644 index 00000000000..3243dc6d628 --- /dev/null +++ b/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/resources/shaders/cs_box_shadow.glsl b/resources/shaders/cs_box_shadow.glsl new file mode 100644 index 00000000000..9e5dd036c54 --- /dev/null +++ b/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/resources/shaders/cs_box_shadow.vs.glsl b/resources/shaders/cs_box_shadow.vs.glsl new file mode 100644 index 00000000000..fce6e53af1d --- /dev/null +++ b/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/resources/shaders/prim_shared.glsl b/resources/shaders/prim_shared.glsl index d25b7152540..6d6b04e5814 100644 --- a/resources/shaders/prim_shared.glsl +++ b/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/resources/shaders/ps_box_shadow.fs.glsl b/resources/shaders/ps_box_shadow.fs.glsl index 9c485cba9fe..8392ab698be 100644 --- a/resources/shaders/ps_box_shadow.fs.glsl +++ b/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/resources/shaders/ps_box_shadow.glsl b/resources/shaders/ps_box_shadow.glsl index 26fdba588f3..40faee87f58 100644 --- a/resources/shaders/ps_box_shadow.glsl +++ b/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/resources/shaders/ps_box_shadow.vs.glsl b/resources/shaders/ps_box_shadow.vs.glsl index e863ab0a8fc..930aef9062e 100644 --- a/resources/shaders/ps_box_shadow.vs.glsl +++ b/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; }