Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

layout_2020: Add support for transform-style #26485

Merged
merged 1 commit into from May 11, 2020
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

layout_2020: Add support for transform-style

This requires creating a matching stacking context for every reference
frame and also properly placing those stacking contexts inside them.
  • Loading branch information
mrobinson committed May 11, 2020
commit a637810df39b05dd46c521ffdfba5ab66483520c
@@ -126,6 +126,10 @@ pub(crate) enum StackingContextType {
}

pub(crate) struct StackingContext {
/// The spatial id of this fragment. This is used to properly handle
/// things like preserve-3d.
spatial_id: wr::SpatialId,

/// The fragment that established this stacking context.
initializing_fragment_style: Option<ServoArc<ComputedValues>>,

@@ -145,10 +149,12 @@ pub(crate) struct StackingContext {

impl StackingContext {
pub(crate) fn new(
spatial_id: wr::SpatialId,
initializing_fragment_style: ServoArc<ComputedValues>,
context_type: StackingContextType,
) -> Self {
Self {
spatial_id,
initializing_fragment_style: Some(initializing_fragment_style),
context_type,
fragments: vec![],
@@ -157,8 +163,9 @@ impl StackingContext {
}
}

pub(crate) fn create_root() -> Self {
pub(crate) fn create_root(wr: &wr::DisplayListBuilder) -> Self {
Self {
spatial_id: wr::SpaceAndClipInfo::root_scroll(wr.pipeline_id).spatial_id,
initializing_fragment_style: None,
context_type: StackingContextType::Real,
fragments: vec![],
@@ -198,16 +205,18 @@ impl StackingContext {
&self,
builder: &'a mut DisplayListBuilder,
) -> bool {
let effects = match self.initializing_fragment_style.as_ref() {
Some(style) => style.get_effects(),
let style = match self.initializing_fragment_style.as_ref() {
Some(style) => style,
None => return false,
};

// WebRender only uses the stacking context to apply certain effects. If we don't
// actually need to create a stacking context, just avoid creating one.
let effects = style.get_effects();
if effects.filter.0.is_empty() &&
effects.opacity == 1.0 &&
effects.mix_blend_mode == ComputedMixBlendMode::Normal
effects.mix_blend_mode == ComputedMixBlendMode::Normal &&
!style.has_transform_or_perspective()
{
return false;
}
@@ -227,11 +236,11 @@ impl StackingContext {
}

builder.wr.push_stacking_context(
LayoutPoint::zero(), // origin
builder.current_space_and_clip.spatial_id, // spatial_id
LayoutPoint::zero(), // origin
self.spatial_id,
wr::PrimitiveFlags::default(),
None, // clip_id
wr::TransformStyle::Flat,
style.get_used_transform_style().to_webrender(),
effects.mix_blend_mode.to_webrender(),
&filters,
&vec![], // filter_datas
@@ -423,52 +432,38 @@ impl BoxFragment {
builder.clipping_and_scrolling_scope(|builder| {
self.adjust_spatial_id_for_positioning(builder);

let context_type = match self.get_stacking_context_type() {
Some(context_type) => context_type,
match self.get_stacking_context_type() {
Some(context_type) => {
self.build_stacking_context_tree_creating_stacking_context(
fragment,
builder,
containing_block_info,
stacking_context,
context_type,
);
},
None => {
self.build_stacking_context_tree_for_children(
fragment,
builder,
containing_block_info,
stacking_context,
);
return;
},
};

let mut child_stacking_context = StackingContext::new(self.style.clone(), context_type);
self.build_stacking_context_tree_for_children(
fragment,
builder,
containing_block_info,
&mut child_stacking_context,
);

let mut stolen_children = vec![];
if context_type != StackingContextType::Real {
stolen_children = mem::replace(
&mut child_stacking_context.stacking_contexts,
stolen_children,
);
}

child_stacking_context.sort();
stacking_context
.stacking_contexts
.push(child_stacking_context);
stacking_context
.stacking_contexts
.append(&mut stolen_children);
});
}

fn build_stacking_context_tree_for_children<'a>(
&'a self,
fn build_stacking_context_tree_creating_stacking_context(
&self,
fragment: &ArcRefCell<Fragment>,
builder: &mut StackingContextBuilder,
containing_block_info: &ContainingBlockInfo,
stacking_context: &mut StackingContext,
parent_stacking_context: &mut StackingContext,
context_type: StackingContextType,
) {
// 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);
@@ -477,32 +472,72 @@ impl BoxFragment {
let established_reference_frame =
self.build_reference_frame_if_necessary(builder, &border_rect);

let mut new_containing_block_info = containing_block_info.clone();

// 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();
}

let mut child_stacking_context = StackingContext::new(
builder.current_space_and_clip.spatial_id,
self.style.clone(),
context_type,
);
self.build_stacking_context_tree_for_children(
fragment,
builder,
&new_containing_block_info,
&mut child_stacking_context,
);

let mut stolen_children = vec![];
if context_type != StackingContextType::Real {
stolen_children = mem::replace(
&mut child_stacking_context.stacking_contexts,
stolen_children,
);
}

child_stacking_context.sort();
parent_stacking_context
.stacking_contexts
.push(child_stacking_context);
parent_stacking_context
.stacking_contexts
.append(&mut stolen_children);

if established_reference_frame {
builder.wr.pop_reference_frame();
}
}

fn build_stacking_context_tree_for_children<'a>(
&'a self,
fragment: &ArcRefCell<Fragment>,
builder: &mut StackingContextBuilder,
containing_block_info: &ContainingBlockInfo,
stacking_context: &mut StackingContext,
) {
stacking_context.fragments.push(StackingContextFragment {
space_and_clip: builder.current_space_and_clip,
section: self.get_stacking_context_section(),
containing_block: new_containing_block_info.rect,
containing_block: containing_block_info.rect,
fragment: fragment.clone(),
});

// We want to build the scroll frame after the background and border, because
// they shouldn't scroll with the rest of the box content.
self.build_scroll_frame_if_necessary(builder, &new_containing_block_info);
self.build_scroll_frame_if_necessary(builder, containing_block_info);

let padding_rect = self
.padding_rect()
.to_physical(self.style.writing_mode, &new_containing_block_info.rect)
.translate(new_containing_block_info.rect.origin.to_vector());
.to_physical(self.style.writing_mode, &containing_block_info.rect)
.translate(containing_block_info.rect.origin.to_vector());
let mut new_containing_block_info = containing_block_info.clone();
new_containing_block_info.rect = self
.content_rect
.to_physical(self.style.writing_mode, &new_containing_block_info.rect)
@@ -522,10 +557,6 @@ impl BoxFragment {
StackingContextBuildMode::SkipHoisted,
);
}

if established_reference_frame {
builder.wr.pop_reference_frame();
}
}

fn adjust_spatial_id_for_positioning(&self, builder: &mut StackingContextBuilder) {
@@ -196,7 +196,7 @@ impl BoxTreeRoot {

impl FragmentTreeRoot {
pub fn build_display_list(&self, builder: &mut crate::display_list::DisplayListBuilder) {
let mut stacking_context = StackingContext::create_root();
let mut stacking_context = StackingContext::create_root(&builder.wr);
{
let mut stacking_context_builder = StackingContextBuilder::new(&mut builder.wr);
let containing_block_info = ContainingBlockInfo {

This file was deleted.

This file was deleted.

ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.