aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Sapin <simon.sapin@exyr.org>2020-05-13 17:45:57 +0200
committerSimon Sapin <simon.sapin@exyr.org>2020-05-15 13:25:35 +0200
commitc7acfc37ed774cbec0bc3be7722c11facbbf8ac8 (patch)
treeea5d8045eeb1cb7a844ee3ef0dff78fb74dd46b7
parent3e8623332bf0613f700c7883be33bbb4dee43c87 (diff)
downloadservo-c7acfc37ed774cbec0bc3be7722c11facbbf8ac8.tar.gz
servo-c7acfc37ed774cbec0bc3be7722c11facbbf8ac8.zip
Separate computing a WR reference frame from adding it to the display list
-rw-r--r--components/layout_2020/display_list/stacking_context.rs63
1 files changed, 36 insertions, 27 deletions
diff --git a/components/layout_2020/display_list/stacking_context.rs b/components/layout_2020/display_list/stacking_context.rs
index 1b0644e9d91..953ef188459 100644
--- a/components/layout_2020/display_list/stacking_context.rs
+++ b/components/layout_2020/display_list/stacking_context.rs
@@ -364,6 +364,12 @@ impl Fragment {
}
}
+struct ReferenceFrameData {
+ origin: crate::geom::PhysicalPoint<Length>,
+ transform: LayoutTransform,
+ kind: wr::ReferenceFrameKind,
+}
+
impl BoxFragment {
fn get_stacking_context_type(&self) -> Option<StackingContextType> {
if self.style.establishes_stacking_context() {
@@ -464,22 +470,24 @@ impl BoxFragment {
) {
// If we are creating a stacking context, we may also need to create a reference
// frame first.
- let relative_border_rect = self
- .border_rect()
- .to_physical(self.style.writing_mode, &containing_block_info.rect);
- let border_rect =
- relative_border_rect.translate(containing_block_info.rect.origin.to_vector());
- let established_reference_frame =
- self.build_reference_frame_if_necessary(builder, &border_rect);
+ let reference_frame_data = self.reference_frame_data_if_necessary(containing_block_info);
// WebRender reference frames establish a new coordinate system at their origin
// (the border box of the fragment). We need to ensure that any coordinates we
// give to WebRender in this reference frame are relative to the fragment border
// box. We do this by adjusting the containing block origin.
let mut new_containing_block_info = containing_block_info.clone();
- if established_reference_frame {
- new_containing_block_info.rect.origin =
- (-relative_border_rect.origin.to_vector()).to_point();
+
+ if let Some(reference_frame_data) = &reference_frame_data {
+ new_containing_block_info.rect.origin -= reference_frame_data.origin.to_vector();
+ builder.current_space_and_clip.spatial_id = builder.wr.push_reference_frame(
+ reference_frame_data.origin.to_webrender(),
+ builder.current_space_and_clip.spatial_id,
+ self.style.get_box().transform_style.to_webrender(),
+ wr::PropertyBinding::Value(reference_frame_data.transform),
+ reference_frame_data.kind,
+ );
+ builder.nearest_reference_frame = builder.current_space_and_clip.spatial_id;
}
let mut child_stacking_context = StackingContext::new(
@@ -510,7 +518,7 @@ impl BoxFragment {
.stacking_contexts
.append(&mut stolen_children);
- if established_reference_frame {
+ if reference_frame_data.is_some() {
builder.wr.pop_reference_frame();
}
}
@@ -611,17 +619,22 @@ impl BoxFragment {
}
}
- /// Build a reference frame for this fragment if it is necessary. Returns `true` if
- /// a reference was built and `false` otherwise.
- fn build_reference_frame_if_necessary(
+ /// Optionally returns the data for building a reference frame, without yet building it.
+ fn reference_frame_data_if_necessary(
&self,
- builder: &mut StackingContextBuilder,
- border_rect: &PhysicalRect<Length>,
- ) -> bool {
+ containing_block_info: &ContainingBlockInfo,
+ ) -> Option<ReferenceFrameData> {
if !self.style.has_transform_or_perspective() {
- return false;
+ return None;
}
+
+ let relative_border_rect = self
+ .border_rect()
+ .to_physical(self.style.writing_mode, &containing_block_info.rect);
+ let border_rect = relative_border_rect
+ .translate(containing_block_info.rect.origin.to_vector());
let untyped_border_rect = border_rect.to_untyped();
+
let transform = self.calculate_transform_matrix(&untyped_border_rect);
let perspective = self.calculate_perspective_matrix(&untyped_border_rect);
let (reference_frame_transform, reference_frame_kind) = match (transform, perspective) {
@@ -641,15 +654,11 @@ impl BoxFragment {
(None, None) => unreachable!(),
};
- builder.current_space_and_clip.spatial_id = builder.wr.push_reference_frame(
- border_rect.origin.to_webrender(),
- builder.current_space_and_clip.spatial_id,
- self.style.get_box().transform_style.to_webrender(),
- wr::PropertyBinding::Value(reference_frame_transform),
- reference_frame_kind,
- );
- builder.nearest_reference_frame = builder.current_space_and_clip.spatial_id;
- true
+ Some(ReferenceFrameData {
+ origin: border_rect.origin,
+ transform: reference_frame_transform,
+ kind: reference_frame_kind,
+ })
}
/// Returns the 4D matrix representing this fragment's transform.