Skip to content

Commit

Permalink
Deal with changes to the WebRender API
Browse files Browse the repository at this point in the history
The WebRender display list is now similar to the Servo display list,
which simplifies the conversion.
  • Loading branch information
mrobinson committed Nov 14, 2016
1 parent bfd4a0e commit 978f534
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 241 deletions.
238 changes: 60 additions & 178 deletions components/layout/webrender_helpers.rs
Expand Up @@ -10,46 +10,20 @@
use app_units::Au;
use euclid::{Matrix4D, Point2D, Rect, Size2D, TypedRect};
use gfx::display_list::{BorderRadii, BoxShadowClipMode, ClippingRegion};
use gfx::display_list::{DisplayItem, DisplayList, DisplayListTraversal};
use gfx::display_list::{StackingContext, StackingContextType};
use gfx::display_list::{DisplayItem, DisplayList, DisplayListTraversal, StackingContextType};
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;
use webrender_traits::{self, AuxiliaryListsBuilder, DisplayListId, PipelineId};

trait WebRenderStackingContextConverter {
fn convert_to_webrender<'a>(&self,
traversal: &mut DisplayListTraversal<'a>,
api: &mut webrender_traits::RenderApi,
pipeline_id: webrender_traits::PipelineId,
epoch: webrender_traits::Epoch,
frame_builder: &mut WebRenderFrameBuilder,
scroll_layer_id: Option<webrender_traits::ScrollLayerId>)
-> webrender_traits::StackingContextId;

fn convert_children_to_webrender<'a>(&self,
traversal: &mut DisplayListTraversal<'a>,
api: &mut webrender_traits::RenderApi,
pipeline_id: webrender_traits::PipelineId,
epoch: webrender_traits::Epoch,
builder: &mut webrender_traits::DisplayListBuilder,
frame_builder: &mut WebRenderFrameBuilder,
force_positioned_stacking_level: bool);
}
use webrender_traits::{self, AuxiliaryListsBuilder, BuiltDisplayList, DisplayListBuilder, PipelineId};

pub trait WebRenderDisplayListConverter {
fn convert_to_webrender(&self,
api: &mut webrender_traits::RenderApi,
pipeline_id: webrender_traits::PipelineId,
epoch: webrender_traits::Epoch,
frame_builder: &mut WebRenderFrameBuilder)
-> webrender_traits::StackingContextId;
fn convert_to_webrender(&self, frame_builder: &mut WebRenderFrameBuilder) -> BuiltDisplayList;
}

trait WebRenderDisplayItemConverter {
fn convert_to_webrender(&self,
builder: &mut webrender_traits::DisplayListBuilder,
builder: &mut DisplayListBuilder,
frame_builder: &mut WebRenderFrameBuilder);
}

Expand All @@ -73,7 +47,6 @@ impl ToBorderStyle for BorderStyle {
}
}
}

trait ToBoxShadowClipMode {
fn to_clip_mode(&self) -> webrender_traits::BoxShadowClipMode;
}
Expand Down Expand Up @@ -222,128 +195,20 @@ impl ToFilterOps for filter::T {
}
}

impl WebRenderStackingContextConverter for StackingContext {
fn convert_children_to_webrender<'a>(&self,
traversal: &mut DisplayListTraversal<'a>,
api: &mut webrender_traits::RenderApi,
pipeline_id: webrender_traits::PipelineId,
epoch: webrender_traits::Epoch,
builder: &mut webrender_traits::DisplayListBuilder,
frame_builder: &mut WebRenderFrameBuilder,
_force_positioned_stacking_level: bool) {
while let Some(item) = traversal.next() {
match item {
&DisplayItem::PushStackingContext(ref stacking_context_item) => {
let stacking_context = &stacking_context_item.stacking_context;
debug_assert!(stacking_context.context_type == StackingContextType::Real);
builder.push_stacking_context(
stacking_context.convert_to_webrender(traversal,
api,
pipeline_id,
epoch,
frame_builder,
None));
}
&DisplayItem::PushScrollRoot(ref item) => {
let stacking_context = StackingContext::new(
StackingContextId::new(0),
StackingContextType::Real,
&item.scroll_root.clip,
&TypedRect::new(Point2D::zero(), item.scroll_root.size),
0,
filter::T::new(Vec::new()),
mix_blend_mode::T::normal,
Matrix4D::identity(),
Matrix4D::identity(),
true,
ScrollPolicy::Scrollable,
ScrollRootId::root());
let scroll_layer_id =
Some(frame_builder.next_scroll_layer_id(item.scroll_root.id));
builder.push_stacking_context(
stacking_context.convert_to_webrender(traversal,
api,
pipeline_id,
epoch,
frame_builder,
scroll_layer_id));
}
&DisplayItem::PopStackingContext(_) | &DisplayItem::PopScrollRoot(_) => return,
_ => item.convert_to_webrender(builder, frame_builder),
}
}
}

fn convert_to_webrender<'a>(&self,
traversal: &mut DisplayListTraversal<'a>,
api: &mut webrender_traits::RenderApi,
pipeline_id: webrender_traits::PipelineId,
epoch: webrender_traits::Epoch,
frame_builder: &mut WebRenderFrameBuilder,
scroll_layer_id: Option<webrender_traits::ScrollLayerId>)
-> webrender_traits::StackingContextId {
let webrender_scroll_policy = match self.scroll_policy {
ScrollPolicy::Scrollable => webrender_traits::ScrollPolicy::Scrollable,
ScrollPolicy::FixedPosition => webrender_traits::ScrollPolicy::Fixed,
};

let mut sc =
webrender_traits::StackingContext::new(scroll_layer_id,
webrender_scroll_policy,
self.bounds.to_rectf(),
self.overflow.to_rectf(),
self.z_index,
&self.transform,
&self.perspective,
self.establishes_3d_context,
self.blend_mode.to_blend_mode(),
self.filters.to_filter_ops(),
&mut frame_builder.auxiliary_lists_builder);

let mut builder = webrender_traits::DisplayListBuilder::new();
self.convert_children_to_webrender(traversal,
api,
pipeline_id,
epoch,
&mut builder,
frame_builder,
false);

frame_builder.add_display_list(api, builder.finalize(), &mut sc);
frame_builder.add_stacking_context(api, pipeline_id, sc)
}
}

impl WebRenderDisplayListConverter for DisplayList {
fn convert_to_webrender(&self,
api: &mut webrender_traits::RenderApi,
pipeline_id: webrender_traits::PipelineId,
epoch: webrender_traits::Epoch,
frame_builder: &mut WebRenderFrameBuilder)
-> webrender_traits::StackingContextId {
let mut traversal = DisplayListTraversal::new(self);
let item = traversal.next();
match item {
Some(&DisplayItem::PushStackingContext(ref stacking_context_item)) => {
let stacking_context = &stacking_context_item.stacking_context;
let scroll_layer_id =
Some(frame_builder.next_scroll_layer_id(ScrollRootId::root()));
stacking_context.convert_to_webrender(&mut traversal,
api,
pipeline_id,
epoch,
frame_builder,
scroll_layer_id)
}
_ => unreachable!("DisplayList did not start with StackingContext."),

fn convert_to_webrender(&self, frame_builder: &mut WebRenderFrameBuilder) -> BuiltDisplayList {
let traversal = DisplayListTraversal::new(self);
let mut builder = DisplayListBuilder::new();
for item in traversal {
item.convert_to_webrender(&mut builder, frame_builder);
}
builder.finalize()
}
}

impl WebRenderDisplayItemConverter for DisplayItem {
fn convert_to_webrender(&self,
builder: &mut webrender_traits::DisplayListBuilder,
builder: &mut DisplayListBuilder,
frame_builder: &mut WebRenderFrameBuilder) {
match *self {
DisplayItem::SolidColor(ref item) => {
Expand Down Expand Up @@ -472,19 +337,60 @@ impl WebRenderDisplayItemConverter for DisplayItem {
item.base.clip.to_clip_region(frame_builder),
pipeline_id);
}
DisplayItem::PushStackingContext(_) |
DisplayItem::PopStackingContext(_) |
DisplayItem::PushScrollRoot(_) |
DisplayItem::PopScrollRoot(_) =>
unreachable!("Tried to convert a scroll root or stacking context structure item."),
DisplayItem::PushStackingContext(ref item) => {
let stacking_context = &item.stacking_context;
debug_assert!(stacking_context.context_type == StackingContextType::Real);

let webrender_scroll_policy = match stacking_context.scroll_policy {
ScrollPolicy::Scrollable => webrender_traits::ScrollPolicy::Scrollable,
ScrollPolicy::FixedPosition => webrender_traits::ScrollPolicy::Fixed,
};

let scroll_layer_id = if stacking_context.id == StackingContextId::root() {
Some(frame_builder.next_scroll_layer_id(ScrollRootId::root()))
} else {
None
};

let context =
webrender_traits::StackingContext::new(
scroll_layer_id,
webrender_scroll_policy,
stacking_context.bounds.to_rectf(),
stacking_context.overflow.to_rectf(),
stacking_context.z_index,
&stacking_context.transform,
&stacking_context.perspective,
stacking_context.establishes_3d_context,
stacking_context.blend_mode.to_blend_mode(),
stacking_context.filters.to_filter_ops(),
&mut frame_builder.auxiliary_lists_builder);
builder.push_stacking_context(context);

}
DisplayItem::PopStackingContext(_) => builder.pop_stacking_context(),
DisplayItem::PushScrollRoot(ref item) => {
let overflow = TypedRect::new(Point2D::zero(), item.scroll_root.size);
let context = webrender_traits::StackingContext::new(
Some(frame_builder.next_scroll_layer_id(item.scroll_root.id)),
webrender_traits::ScrollPolicy::Scrollable,
item.scroll_root.clip.to_rectf(),
overflow.to_rectf(),
0,
&Matrix4D::identity(),
&Matrix4D::identity(),
true,
mix_blend_mode::T::normal.to_blend_mode(),
filter::T::new(Vec::new()).to_filter_ops(),
&mut frame_builder.auxiliary_lists_builder);
builder.push_stacking_context(context);
}
DisplayItem::PopScrollRoot(_) => builder.pop_stacking_context(),
}
}
}

pub struct WebRenderFrameBuilder {
pub stacking_contexts: Vec<(webrender_traits::StackingContextId,
webrender_traits::StackingContext)>,
pub display_lists: Vec<(DisplayListId, webrender_traits::BuiltDisplayList)>,
pub auxiliary_lists_builder: AuxiliaryListsBuilder,
pub root_pipeline_id: PipelineId,
pub next_scroll_layer_id: usize,
Expand All @@ -493,36 +399,12 @@ pub struct WebRenderFrameBuilder {
impl WebRenderFrameBuilder {
pub fn new(root_pipeline_id: PipelineId) -> WebRenderFrameBuilder {
WebRenderFrameBuilder {
stacking_contexts: vec![],
display_lists: vec![],
auxiliary_lists_builder: AuxiliaryListsBuilder::new(),
root_pipeline_id: root_pipeline_id,
next_scroll_layer_id: 0,
}
}

pub fn add_stacking_context(&mut self,
api: &mut webrender_traits::RenderApi,
pipeline_id: PipelineId,
stacking_context: webrender_traits::StackingContext)
-> webrender_traits::StackingContextId {
assert!(pipeline_id == self.root_pipeline_id);
let id = api.next_stacking_context_id();
self.stacking_contexts.push((id, stacking_context));
id
}

pub fn add_display_list(&mut self,
api: &mut webrender_traits::RenderApi,
display_list: webrender_traits::BuiltDisplayList,
stacking_context: &mut webrender_traits::StackingContext)
-> DisplayListId {
let id = api.next_display_list_id();
stacking_context.display_lists.push(id);
self.display_lists.push((id, display_list));
id
}

pub fn next_scroll_layer_id(&mut self,
scroll_root_id: ScrollRootId)
-> webrender_traits::ScrollLayerId {
Expand Down
30 changes: 11 additions & 19 deletions components/layout_thread/lib.rs
Expand Up @@ -952,33 +952,25 @@ impl LayoutThread {

debug!("Layout done!");

self.epoch.next();

// TODO: Avoid the temporary conversion and build webrender sc/dl directly!
let Epoch(epoch_number) = self.epoch;
let epoch = webrender_traits::Epoch(epoch_number);
let pipeline_id = self.id.to_webrender();

// TODO(gw) For now only create a root scrolling layer!
let mut frame_builder = WebRenderFrameBuilder::new(pipeline_id);
let sc_id = rw_data.display_list.as_ref().unwrap().convert_to_webrender(
&mut self.webrender_api,
pipeline_id,
epoch,
let built_display_list = rw_data.display_list.as_ref().unwrap().convert_to_webrender(
&mut frame_builder);
let root_background_color = get_root_flow_background_color(layout_root);

let viewport_size = Size2D::new(self.viewport_size.width.to_f32_px(),
self.viewport_size.height.to_f32_px());

self.webrender_api.set_root_stacking_context(sc_id,
root_background_color,
epoch,
pipeline_id,
viewport_size,
frame_builder.stacking_contexts,
frame_builder.display_lists,
frame_builder.auxiliary_lists_builder.finalize());
self.epoch.next();
let Epoch(epoch_number) = self.epoch;

self.webrender_api.set_root_display_list(
get_root_flow_background_color(layout_root),
webrender_traits::Epoch(epoch_number),
pipeline_id,
viewport_size,
built_display_list,
frame_builder.auxiliary_lists_builder.finalize());
});
}

Expand Down

0 comments on commit 978f534

Please sign in to comment.