mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
Use reference frames explicitly for fixed positioning
Now that WebRender gives us reference frame ClipIds, we can use those to implement fixed positioning in Servo. This will allow us to remove the feature from WebRender entirely.
This commit is contained in:
parent
11a89bcc47
commit
32f00ef821
4 changed files with 160 additions and 50 deletions
|
@ -192,12 +192,16 @@ pub struct StackingContextCollectionState {
|
|||
/// recursively building and processing the display list.
|
||||
pub current_stacking_context_id: StackingContextId,
|
||||
|
||||
/// The current stacking real context id, which doesn't include pseudo-stacking contexts.
|
||||
/// The current reference frame ClipScrollNodeIndex.
|
||||
pub current_real_stacking_context_id: StackingContextId,
|
||||
|
||||
/// The next stacking context id that we will assign to a stacking context.
|
||||
pub next_stacking_context_id: StackingContextId,
|
||||
|
||||
/// The current reference frame id. This is used to assign items to the parent
|
||||
/// reference frame when we encounter a fixed position stacking context.
|
||||
pub current_parent_reference_frame_id: ClipScrollNodeIndex,
|
||||
|
||||
/// The current clip and scroll info, used to keep track of state when
|
||||
/// recursively building and processing the display list.
|
||||
pub current_clipping_and_scrolling: ClippingAndScrolling,
|
||||
|
@ -221,19 +225,8 @@ pub struct StackingContextCollectionState {
|
|||
|
||||
impl StackingContextCollectionState {
|
||||
pub fn new(pipeline_id: PipelineId) -> StackingContextCollectionState {
|
||||
let root_clip_indices = ClippingAndScrolling::simple(ClipScrollNodeIndex(0));
|
||||
|
||||
// This is just a dummy node to take up a slot in the array. WebRender
|
||||
// takes care of adding this root node and it can be ignored during DL conversion.
|
||||
let root_node = ClipScrollNode {
|
||||
parent_index: ClipScrollNodeIndex(0),
|
||||
clip: ClippingRegion::from_rect(LayoutRect::zero()),
|
||||
content_rect: LayoutRect::zero(),
|
||||
node_type: ClipScrollNodeType::ScrollFrame(
|
||||
ScrollSensitivity::ScriptAndInputEvents,
|
||||
pipeline_id.root_scroll_id(),
|
||||
),
|
||||
};
|
||||
let root_clip_indices =
|
||||
ClippingAndScrolling::simple(ClipScrollNodeIndex::root_scroll_node());
|
||||
|
||||
let mut stacking_context_info = FnvHashMap::default();
|
||||
stacking_context_info.insert(
|
||||
|
@ -241,14 +234,22 @@ impl StackingContextCollectionState {
|
|||
StackingContextInfo::new(StackingContextId::root()),
|
||||
);
|
||||
|
||||
// We add two empty nodes to represent the WebRender root reference frame and
|
||||
// root scroll nodes. WebRender adds these automatically and we add them here
|
||||
// so that the ids in the array match up with the ones we assign during display
|
||||
// list building. We ignore these two nodes during conversion to WebRender
|
||||
// display lists.
|
||||
let clip_scroll_nodes = vec![ClipScrollNode::placeholder(), ClipScrollNode::placeholder()];
|
||||
|
||||
StackingContextCollectionState {
|
||||
pipeline_id: pipeline_id,
|
||||
root_stacking_context: StackingContext::root(),
|
||||
stacking_context_info,
|
||||
clip_scroll_nodes: vec![root_node],
|
||||
clip_scroll_nodes,
|
||||
current_stacking_context_id: StackingContextId::root(),
|
||||
current_real_stacking_context_id: StackingContextId::root(),
|
||||
next_stacking_context_id: StackingContextId::root().next(),
|
||||
current_parent_reference_frame_id: ClipScrollNodeIndex::root_reference_frame(),
|
||||
current_clipping_and_scrolling: root_clip_indices,
|
||||
containing_block_clipping_and_scrolling: root_clip_indices,
|
||||
clip_stack: Vec::new(),
|
||||
|
@ -291,17 +292,27 @@ impl StackingContextCollectionState {
|
|||
}
|
||||
|
||||
fn add_clip_scroll_node(&mut self, clip_scroll_node: ClipScrollNode) -> ClipScrollNodeIndex {
|
||||
// We want the scroll root to be defined before any possible item that could use it,
|
||||
// so we make sure that it is added to the beginning of the parent "real" (non-pseudo)
|
||||
// stacking context. This ensures that item reordering will not result in an item using
|
||||
// the scroll root before it is defined.
|
||||
let is_placeholder = clip_scroll_node.is_placeholder();
|
||||
|
||||
self.clip_scroll_nodes.push(clip_scroll_node);
|
||||
let index = ClipScrollNodeIndex(self.clip_scroll_nodes.len() - 1);
|
||||
self.stacking_context_info
|
||||
.get_mut(&self.current_real_stacking_context_id)
|
||||
.unwrap()
|
||||
.clip_scroll_nodes
|
||||
.push(index);
|
||||
let index = ClipScrollNodeIndex::new(self.clip_scroll_nodes.len() - 1);
|
||||
|
||||
// If this node is a placeholder node (currently just reference frames), then don't add
|
||||
// it to the stacking context list. Placeholder nodes are created automatically by
|
||||
// WebRender and we don't want to explicitly create them in the display list. The node
|
||||
// is just there to take up a spot in the global list of ClipScrollNodes.
|
||||
if !is_placeholder {
|
||||
// We want the scroll root to be defined before any possible item that could use it,
|
||||
// so we make sure that it is added to the beginning of the parent "real" (non-pseudo)
|
||||
// stacking context. This ensures that item reordering will not result in an item using
|
||||
// the scroll root before it is defined.
|
||||
self.stacking_context_info
|
||||
.get_mut(&self.current_real_stacking_context_id)
|
||||
.unwrap()
|
||||
.clip_scroll_nodes
|
||||
.push(index);
|
||||
}
|
||||
|
||||
index
|
||||
}
|
||||
}
|
||||
|
@ -347,7 +358,6 @@ impl<'a> DisplayListBuildState<'a> {
|
|||
layout_context: &'a LayoutContext,
|
||||
state: StackingContextCollectionState,
|
||||
) -> DisplayListBuildState<'a> {
|
||||
let root_clip_indices = ClippingAndScrolling::simple(ClipScrollNodeIndex(0));
|
||||
DisplayListBuildState {
|
||||
layout_context: layout_context,
|
||||
root_stacking_context: state.root_stacking_context,
|
||||
|
@ -356,7 +366,8 @@ impl<'a> DisplayListBuildState<'a> {
|
|||
clip_scroll_nodes: state.clip_scroll_nodes,
|
||||
processing_scrolling_overflow_element: false,
|
||||
current_stacking_context_id: StackingContextId::root(),
|
||||
current_clipping_and_scrolling: root_clip_indices,
|
||||
current_clipping_and_scrolling:
|
||||
ClippingAndScrolling::simple(ClipScrollNodeIndex::root_scroll_node()),
|
||||
iframe_sizes: Vec::new(),
|
||||
indexable_text: IndexableText::default(),
|
||||
}
|
||||
|
@ -374,7 +385,7 @@ impl<'a> DisplayListBuildState<'a> {
|
|||
return index;
|
||||
}
|
||||
|
||||
self.clip_scroll_nodes[index.0].parent_index
|
||||
self.clip_scroll_nodes[index.to_index()].parent_index
|
||||
}
|
||||
|
||||
fn is_background_or_border_of_clip_scroll_node(&self, section: DisplayListSection) -> bool {
|
||||
|
@ -429,7 +440,7 @@ impl<'a> DisplayListBuildState<'a> {
|
|||
// stacking context. This ensures that item reordering will not result in an item using
|
||||
// the scroll root before it is defined.
|
||||
self.clip_scroll_nodes.push(node);
|
||||
let index = ClipScrollNodeIndex(self.clip_scroll_nodes.len() - 1);
|
||||
let index = ClipScrollNodeIndex::new(self.clip_scroll_nodes.len() - 1);
|
||||
let real_stacking_context_id =
|
||||
self.stacking_context_info[&self.current_stacking_context_id].real_stacking_context_id;
|
||||
self.stacking_context_info
|
||||
|
@ -751,6 +762,7 @@ pub trait FragmentDisplayListBuilding {
|
|||
base_flow: &BaseFlow,
|
||||
scroll_policy: ScrollPolicy,
|
||||
context_type: StackingContextType,
|
||||
established_reference_frame: Option<ClipScrollNodeIndex>,
|
||||
parent_clipping_and_scrolling: ClippingAndScrolling,
|
||||
) -> StackingContext;
|
||||
|
||||
|
@ -1873,6 +1885,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
base_flow: &BaseFlow,
|
||||
scroll_policy: ScrollPolicy,
|
||||
context_type: StackingContextType,
|
||||
established_reference_frame: Option<ClipScrollNodeIndex>,
|
||||
parent_clipping_and_scrolling: ClippingAndScrolling,
|
||||
) -> StackingContext {
|
||||
let border_box = self.stacking_relative_border_box(
|
||||
|
@ -1916,6 +1929,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
self.perspective_matrix(&border_box),
|
||||
scroll_policy,
|
||||
parent_clipping_and_scrolling,
|
||||
established_reference_frame,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -2135,6 +2149,7 @@ pub trait BlockFlowDisplayListBuilding {
|
|||
state: &mut StackingContextCollectionState,
|
||||
preserved_state: &mut SavedStackingContextCollectionState,
|
||||
stacking_context_type: Option<StackingContextType>,
|
||||
established_reference_frame: Option<ClipScrollNodeIndex>,
|
||||
flags: StackingContextCollectionFlags,
|
||||
) -> ClippingAndScrolling;
|
||||
fn setup_clip_scroll_node_for_position(
|
||||
|
@ -2164,6 +2179,7 @@ pub trait BlockFlowDisplayListBuilding {
|
|||
&mut self,
|
||||
parent_stacking_context_id: StackingContextId,
|
||||
parent_clipping_and_scrolling: ClippingAndScrolling,
|
||||
established_reference_frame: Option<ClipScrollNodeIndex>,
|
||||
state: &mut StackingContextCollectionState,
|
||||
);
|
||||
fn build_display_list_for_block(
|
||||
|
@ -2187,6 +2203,8 @@ pub trait BlockFlowDisplayListBuilding {
|
|||
&self,
|
||||
flags: StackingContextCollectionFlags,
|
||||
) -> Option<StackingContextType>;
|
||||
|
||||
fn is_reference_frame(&self, context_type: Option<StackingContextType>) -> bool;
|
||||
}
|
||||
|
||||
/// This structure manages ensuring that modification to StackingContextCollectionState is
|
||||
|
@ -2197,6 +2215,7 @@ pub trait BlockFlowDisplayListBuilding {
|
|||
pub struct SavedStackingContextCollectionState {
|
||||
stacking_context_id: StackingContextId,
|
||||
real_stacking_context_id: StackingContextId,
|
||||
parent_reference_frame_id: ClipScrollNodeIndex,
|
||||
clipping_and_scrolling: ClippingAndScrolling,
|
||||
containing_block_clipping_and_scrolling: ClippingAndScrolling,
|
||||
clips_pushed: usize,
|
||||
|
@ -2209,6 +2228,7 @@ impl SavedStackingContextCollectionState {
|
|||
SavedStackingContextCollectionState {
|
||||
stacking_context_id: state.current_stacking_context_id,
|
||||
real_stacking_context_id: state.current_real_stacking_context_id,
|
||||
parent_reference_frame_id: state.current_parent_reference_frame_id,
|
||||
clipping_and_scrolling: state.current_clipping_and_scrolling,
|
||||
containing_block_clipping_and_scrolling: state.containing_block_clipping_and_scrolling,
|
||||
clips_pushed: 0,
|
||||
|
@ -2230,6 +2250,7 @@ impl SavedStackingContextCollectionState {
|
|||
fn restore(self, state: &mut StackingContextCollectionState) {
|
||||
state.current_stacking_context_id = self.stacking_context_id;
|
||||
state.current_real_stacking_context_id = self.real_stacking_context_id;
|
||||
state.current_parent_reference_frame_id = self.parent_reference_frame_id;
|
||||
state.current_clipping_and_scrolling = self.clipping_and_scrolling;
|
||||
state.containing_block_clipping_and_scrolling =
|
||||
self.containing_block_clipping_and_scrolling;
|
||||
|
@ -2332,6 +2353,16 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns true if this fragment may establish a reference frame and this block
|
||||
/// creates a stacking context. Both are necessary in order to establish a reference
|
||||
/// frame.
|
||||
fn is_reference_frame(&self, context_type: Option<StackingContextType>) -> bool {
|
||||
match context_type {
|
||||
Some(StackingContextType::Real) => self.fragment.can_establish_reference_frame(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_stacking_contexts_for_block(
|
||||
&mut self,
|
||||
state: &mut StackingContextCollectionState,
|
||||
|
@ -2348,8 +2379,17 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
|
||||
if stacking_context_type == Some(StackingContextType::Real) {
|
||||
state.current_real_stacking_context_id = self.base.stacking_context_id;
|
||||
|
||||
}
|
||||
|
||||
let established_reference_frame = if self.is_reference_frame(stacking_context_type) {
|
||||
// WebRender currently creates reference frames automatically, so just add
|
||||
// a placeholder node to allocate a ClipScrollNodeIndex for this reference frame.
|
||||
Some(state.add_clip_scroll_node(ClipScrollNode::placeholder()))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// We are getting the id of the scroll root that contains us here, not the id of
|
||||
// any scroll root that we create. If we create a scroll root, its index will be
|
||||
// stored in state.current_clipping_and_scrolling. If we create a stacking context,
|
||||
|
@ -2358,6 +2398,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
state,
|
||||
&mut preserved_state,
|
||||
stacking_context_type,
|
||||
established_reference_frame,
|
||||
flags,
|
||||
);
|
||||
|
||||
|
@ -2371,6 +2412,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
self.create_real_stacking_context_for_block(
|
||||
preserved_state.stacking_context_id,
|
||||
containing_clipping_and_scrolling,
|
||||
established_reference_frame,
|
||||
state,
|
||||
);
|
||||
},
|
||||
|
@ -2392,6 +2434,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
state: &mut StackingContextCollectionState,
|
||||
preserved_state: &mut SavedStackingContextCollectionState,
|
||||
stacking_context_type: Option<StackingContextType>,
|
||||
established_reference_frame: Option<ClipScrollNodeIndex>,
|
||||
flags: StackingContextCollectionFlags,
|
||||
) -> ClippingAndScrolling {
|
||||
// If this block is absolutely positioned, we should be clipped and positioned by
|
||||
|
@ -2404,13 +2447,23 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
state.containing_block_clipping_and_scrolling
|
||||
},
|
||||
StylePosition::Fixed => {
|
||||
// If we are a fixed positioned stacking context, we want to be scrolled by
|
||||
// our reference frame instead of the clip scroll node that we are inside.
|
||||
preserved_state.push_clip(state, Rect::max_rect(), StylePosition::Fixed);
|
||||
state.current_clipping_and_scrolling.scrolling =
|
||||
state.current_parent_reference_frame_id;
|
||||
state.current_clipping_and_scrolling
|
||||
},
|
||||
_ => state.current_clipping_and_scrolling,
|
||||
};
|
||||
self.base.clipping_and_scrolling = Some(containing_clipping_and_scrolling);
|
||||
|
||||
if let Some(reference_frame_index) = established_reference_frame {
|
||||
let clipping_and_scrolling = ClippingAndScrolling::simple(reference_frame_index);
|
||||
state.current_clipping_and_scrolling = clipping_and_scrolling;
|
||||
self.base.clipping_and_scrolling = Some(clipping_and_scrolling);
|
||||
}
|
||||
|
||||
let stacking_relative_border_box = if self.fragment.establishes_stacking_context() {
|
||||
self.stacking_relative_border_box(CoordinateSystem::Own)
|
||||
} else {
|
||||
|
@ -2658,6 +2711,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
&self.base,
|
||||
ScrollPolicy::Scrollable,
|
||||
stacking_context_type,
|
||||
None,
|
||||
parent_clipping_and_scrolling,
|
||||
);
|
||||
state.add_stacking_context(parent_stacking_context_id, new_context);
|
||||
|
@ -2683,19 +2737,15 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
&mut self,
|
||||
parent_stacking_context_id: StackingContextId,
|
||||
parent_clipping_and_scrolling: ClippingAndScrolling,
|
||||
established_reference_frame: Option<ClipScrollNodeIndex>,
|
||||
state: &mut StackingContextCollectionState,
|
||||
) {
|
||||
let scroll_policy = if self.is_fixed() {
|
||||
ScrollPolicy::Fixed
|
||||
} else {
|
||||
ScrollPolicy::Scrollable
|
||||
};
|
||||
|
||||
let stacking_context = self.fragment.create_stacking_context(
|
||||
self.base.stacking_context_id,
|
||||
&self.base,
|
||||
scroll_policy,
|
||||
ScrollPolicy::Scrollable,
|
||||
StackingContextType::Real,
|
||||
established_reference_frame,
|
||||
parent_clipping_and_scrolling,
|
||||
);
|
||||
|
||||
|
@ -2833,6 +2883,7 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
|
|||
&self.base,
|
||||
ScrollPolicy::Scrollable,
|
||||
StackingContextType::Real,
|
||||
None,
|
||||
state.current_clipping_and_scrolling,
|
||||
);
|
||||
|
||||
|
|
|
@ -38,14 +38,25 @@ pub static BLUR_INFLATION_FACTOR: i32 = 3;
|
|||
/// An index into the vector of ClipScrollNodes. During WebRender conversion these nodes
|
||||
/// are given ClipIds.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize)]
|
||||
pub struct ClipScrollNodeIndex(pub usize);
|
||||
pub struct ClipScrollNodeIndex(usize);
|
||||
|
||||
impl ClipScrollNodeIndex {
|
||||
pub fn root_scroll_node() -> ClipScrollNodeIndex {
|
||||
ClipScrollNodeIndex(1)
|
||||
}
|
||||
|
||||
pub fn root_reference_frame() -> ClipScrollNodeIndex {
|
||||
ClipScrollNodeIndex(0)
|
||||
}
|
||||
|
||||
pub fn new(index: usize) -> ClipScrollNodeIndex {
|
||||
assert_ne!(index, 0, "Use the root_reference_frame constructor");
|
||||
assert_ne!(index, 1, "Use the root_scroll_node constructor");
|
||||
ClipScrollNodeIndex(index)
|
||||
}
|
||||
|
||||
pub fn is_root_scroll_node(&self) -> bool {
|
||||
match *self {
|
||||
ClipScrollNodeIndex(0) => true,
|
||||
_ => false,
|
||||
}
|
||||
*self == Self::root_scroll_node()
|
||||
}
|
||||
|
||||
pub fn to_define_item(&self) -> DisplayItem {
|
||||
|
@ -54,6 +65,10 @@ impl ClipScrollNodeIndex {
|
|||
node_index: *self,
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn to_index(self) -> usize {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// A set of indices into the clip scroll node vector for a given item.
|
||||
|
@ -193,6 +208,9 @@ pub struct StackingContext {
|
|||
|
||||
/// The clip and scroll info for this StackingContext.
|
||||
pub parent_clipping_and_scrolling: ClippingAndScrolling,
|
||||
|
||||
/// The index of the reference frame that this stacking context estalishes.
|
||||
pub established_reference_frame: Option<ClipScrollNodeIndex>,
|
||||
}
|
||||
|
||||
impl StackingContext {
|
||||
|
@ -211,6 +229,7 @@ impl StackingContext {
|
|||
perspective: Option<LayoutTransform>,
|
||||
scroll_policy: ScrollPolicy,
|
||||
parent_clipping_and_scrolling: ClippingAndScrolling,
|
||||
established_reference_frame: Option<ClipScrollNodeIndex>,
|
||||
) -> StackingContext {
|
||||
StackingContext {
|
||||
id,
|
||||
|
@ -225,6 +244,7 @@ impl StackingContext {
|
|||
perspective,
|
||||
scroll_policy,
|
||||
parent_clipping_and_scrolling,
|
||||
established_reference_frame,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -242,7 +262,8 @@ impl StackingContext {
|
|||
TransformStyle::Flat,
|
||||
None,
|
||||
ScrollPolicy::Scrollable,
|
||||
ClippingAndScrolling::simple(ClipScrollNodeIndex(0)),
|
||||
ClippingAndScrolling::simple(ClipScrollNodeIndex::root_scroll_node()),
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -309,15 +330,16 @@ impl fmt::Debug for StackingContext {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize)]
|
||||
pub struct StickyFrameData {
|
||||
pub margins: SideOffsets2D<Option<f32>>,
|
||||
pub vertical_offset_bounds: StickyOffsetBounds,
|
||||
pub horizontal_offset_bounds: StickyOffsetBounds,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize)]
|
||||
pub enum ClipScrollNodeType {
|
||||
Placeholder,
|
||||
ScrollFrame(ScrollSensitivity, ExternalScrollId),
|
||||
StickyFrame(StickyFrameData),
|
||||
Clip,
|
||||
|
@ -339,6 +361,21 @@ pub struct ClipScrollNode {
|
|||
pub node_type: ClipScrollNodeType,
|
||||
}
|
||||
|
||||
impl ClipScrollNode {
|
||||
pub fn placeholder() -> ClipScrollNode {
|
||||
ClipScrollNode {
|
||||
parent_index: ClipScrollNodeIndex(0),
|
||||
clip: ClippingRegion::from_rect(LayoutRect::zero()),
|
||||
content_rect: LayoutRect::zero(),
|
||||
node_type: ClipScrollNodeType::Placeholder,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_placeholder(&self) -> bool {
|
||||
self.node_type == ClipScrollNodeType::Placeholder
|
||||
}
|
||||
}
|
||||
|
||||
/// One drawing command in the list.
|
||||
#[derive(Clone, Serialize)]
|
||||
pub enum DisplayItem {
|
||||
|
@ -412,7 +449,8 @@ impl BaseDisplayItem {
|
|||
clip_rect: LayoutRect::max_rect(),
|
||||
section: DisplayListSection::Content,
|
||||
stacking_context_id: StackingContextId::root(),
|
||||
clipping_and_scrolling: ClippingAndScrolling::simple(ClipScrollNodeIndex(0)),
|
||||
clipping_and_scrolling:
|
||||
ClippingAndScrolling::simple(ClipScrollNodeIndex::root_scroll_node()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,12 @@ impl WebRenderDisplayListConverter for DisplayList {
|
|||
|
||||
let mut clip_ids = Vec::with_capacity(self.clip_scroll_nodes.len());
|
||||
clip_ids.resize(self.clip_scroll_nodes.len(), None);
|
||||
clip_ids[0] = Some(ClipId::root_scroll_node(pipeline_id.to_webrender()));
|
||||
|
||||
// We need to add the WebRender root reference frame and root scroll node ids
|
||||
// here manually, because WebRender creates these automatically.
|
||||
let webrender_pipeline = pipeline_id.to_webrender();
|
||||
clip_ids[0] = Some(ClipId::root_reference_frame(webrender_pipeline));
|
||||
clip_ids[1] = Some(ClipId::root_scroll_node(webrender_pipeline));
|
||||
|
||||
for item in &self.list {
|
||||
item.convert_to_webrender(
|
||||
|
@ -78,7 +83,7 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
|||
current_clip_and_scroll_info: &mut ClipAndScrollInfo,
|
||||
) {
|
||||
let get_id = |clip_ids: &[Option<ClipId>], index: ClipScrollNodeIndex| -> ClipId {
|
||||
match clip_ids[index.0] {
|
||||
match clip_ids[index.to_index()] {
|
||||
Some(id) => id,
|
||||
None => unreachable!("Tried to use WebRender ClipId before it was defined."),
|
||||
}
|
||||
|
@ -214,7 +219,7 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
|||
let stacking_context = &item.stacking_context;
|
||||
debug_assert_eq!(stacking_context.context_type, StackingContextType::Real);
|
||||
|
||||
builder.push_stacking_context(
|
||||
let reference_frame_clip_id = builder.push_stacking_context(
|
||||
&webrender_api::LayoutPrimitiveInfo::new(stacking_context.bounds),
|
||||
None,
|
||||
stacking_context.scroll_policy,
|
||||
|
@ -225,10 +230,17 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
|||
stacking_context.filters.clone(),
|
||||
GlyphRasterSpace::Screen,
|
||||
);
|
||||
|
||||
match (reference_frame_clip_id, stacking_context.established_reference_frame) {
|
||||
(Some(webrender_id), Some(frame_index)) =>
|
||||
clip_ids[frame_index.to_index()] = Some(webrender_id),
|
||||
(None, None) => {},
|
||||
_ => warn!("Mismatch between reference frame establishment!"),
|
||||
}
|
||||
},
|
||||
DisplayItem::PopStackingContext(_) => builder.pop_stacking_context(),
|
||||
DisplayItem::DefineClipScrollNode(ref item) => {
|
||||
let node = &clip_scroll_nodes[item.node_index.0];
|
||||
let node = &clip_scroll_nodes[item.node_index.to_index()];
|
||||
let parent_id = get_id(clip_ids, node.parent_index);
|
||||
let item_rect = node.clip.main;
|
||||
|
||||
|
@ -262,9 +274,12 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
|||
builder.pop_clip_id();
|
||||
id
|
||||
},
|
||||
ClipScrollNodeType::Placeholder => {
|
||||
unreachable!("Found DefineClipScrollNode for Placeholder type node.");
|
||||
}
|
||||
};
|
||||
|
||||
clip_ids[item.node_index.0] = Some(webrender_id);
|
||||
clip_ids[item.node_index.to_index()] = Some(webrender_id);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2474,6 +2474,12 @@ impl Fragment {
|
|||
stacking_relative_border_box.size.height - border_padding.vertical()))
|
||||
}
|
||||
|
||||
/// Returns true if this fragment may establish a reference frame.
|
||||
pub fn can_establish_reference_frame(&self) -> bool {
|
||||
!self.style().get_box().transform.0.is_empty() ||
|
||||
self.style().get_box().perspective != Perspective::None
|
||||
}
|
||||
|
||||
/// Returns true if this fragment has a filter, transform, or perspective property set.
|
||||
pub fn has_filter_transform_or_perspective(&self) -> bool {
|
||||
!self.style().get_box().transform.0.is_empty() ||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue