layout: Flatten display list transfer into a separately-transferred byte

array, and consolidate the multitude of display list messages into one.

Improves display list building performance by 50%-100% for small display
lists.
This commit is contained in:
Patrick Walton 2016-03-09 18:22:18 -08:00
parent 805aa3a3ab
commit 9fcf9215d0
5 changed files with 106 additions and 59 deletions

View file

@ -19,26 +19,26 @@ use msg::constellation_msg::ConvertPipelineIdToWebRender;
use style::computed_values::filter::{self, Filter};
use style::computed_values::{image_rendering, mix_blend_mode};
use style::values::computed::BorderStyle;
use webrender_traits::{self, AuxiliaryListsBuilder};
use webrender_traits::{self, AuxiliaryListsBuilder, DisplayListId, PipelineId, StackingContextId};
trait WebRenderStackingContextConverter {
fn convert_to_webrender<'a>(&self,
traversal: &mut DisplayListTraversal<'a>,
api: &webrender_traits::RenderApi,
api: &mut webrender_traits::RenderApi,
pipeline_id: webrender_traits::PipelineId,
epoch: webrender_traits::Epoch,
scroll_layer_id: Option<webrender_traits::ScrollLayerId>,
auxiliary_lists_builder: &mut AuxiliaryListsBuilder)
frame_builder: &mut WebRenderFrameBuilder)
-> webrender_traits::StackingContextId;
fn convert_children_to_webrender<'a>(&self,
traversal: &mut DisplayListTraversal<'a>,
api: &webrender_traits::RenderApi,
api: &mut webrender_traits::RenderApi,
pipeline_id: webrender_traits::PipelineId,
epoch: webrender_traits::Epoch,
scroll_layer_id: Option<webrender_traits::ScrollLayerId>,
builder: &mut webrender_traits::DisplayListBuilder,
auxiliary_lists_builder: &mut AuxiliaryListsBuilder,
frame_builder: &mut WebRenderFrameBuilder,
force_positioned_stacking_level: bool);
fn web_render_stacking_level(&self) -> webrender_traits::StackingLevel;
@ -46,11 +46,11 @@ trait WebRenderStackingContextConverter {
pub trait WebRenderDisplayListConverter {
fn convert_to_webrender(&self,
api: &webrender_traits::RenderApi,
api: &mut webrender_traits::RenderApi,
pipeline_id: webrender_traits::PipelineId,
epoch: webrender_traits::Epoch,
scroll_layer_id: Option<webrender_traits::ScrollLayerId>,
auxiliary_lists_builder: &mut AuxiliaryListsBuilder)
frame_builder: &mut WebRenderFrameBuilder)
-> webrender_traits::StackingContextId;
}
@ -58,7 +58,7 @@ trait WebRenderDisplayItemConverter {
fn convert_to_webrender(&self,
level: webrender_traits::StackingLevel,
builder: &mut webrender_traits::DisplayListBuilder,
auxiliary_lists_builder: &mut AuxiliaryListsBuilder);
frame_builder: &mut WebRenderFrameBuilder);
}
trait WebRenderDisplayListEntryConverter {
@ -171,12 +171,12 @@ impl ToGradientStop for GradientStop {
}
trait ToClipRegion {
fn to_clip_region(&self, auxiliary_lists_builder: &mut AuxiliaryListsBuilder)
fn to_clip_region(&self, frame_builder: &mut WebRenderFrameBuilder)
-> webrender_traits::ClipRegion;
}
impl ToClipRegion for ClippingRegion {
fn to_clip_region(&self, auxiliary_lists_builder: &mut AuxiliaryListsBuilder)
fn to_clip_region(&self, frame_builder: &mut WebRenderFrameBuilder)
-> webrender_traits::ClipRegion {
webrender_traits::ClipRegion::new(&self.main.to_rectf(),
self.complex.iter().map(|complex_clipping_region| {
@ -185,7 +185,7 @@ impl ToClipRegion for ClippingRegion {
complex_clipping_region.radii.to_border_radius(),
)
}).collect(),
auxiliary_lists_builder)
&mut frame_builder.auxiliary_lists_builder)
}
}
@ -272,12 +272,12 @@ impl ToFilterOps for filter::T {
impl WebRenderStackingContextConverter for StackingContext {
fn convert_children_to_webrender<'a>(&self,
traversal: &mut DisplayListTraversal<'a>,
api: &webrender_traits::RenderApi,
api: &mut webrender_traits::RenderApi,
pipeline_id: webrender_traits::PipelineId,
epoch: webrender_traits::Epoch,
scroll_layer_id: Option<webrender_traits::ScrollLayerId>,
builder: &mut webrender_traits::DisplayListBuilder,
auxiliary_lists_builder: &mut AuxiliaryListsBuilder,
frame_builder: &mut WebRenderFrameBuilder,
force_positioned_stacking_level: bool) {
for child in self.children.iter() {
while let Some(item) = traversal.advance(self) {
@ -286,7 +286,7 @@ impl WebRenderStackingContextConverter for StackingContext {
} else {
item.web_render_stacking_level()
};
item.item.convert_to_webrender(stacking_level, builder, auxiliary_lists_builder);
item.item.convert_to_webrender(stacking_level, builder, frame_builder);
}
if child.context_type == StackingContextType::Real {
@ -295,7 +295,7 @@ impl WebRenderStackingContextConverter for StackingContext {
pipeline_id,
epoch,
None,
auxiliary_lists_builder);
frame_builder);
builder.push_stacking_context(child.web_render_stacking_level(),
stacking_context_id);
} else {
@ -305,7 +305,7 @@ impl WebRenderStackingContextConverter for StackingContext {
epoch,
scroll_layer_id,
builder,
auxiliary_lists_builder,
frame_builder,
true);
}
}
@ -313,17 +313,17 @@ impl WebRenderStackingContextConverter for StackingContext {
while let Some(item) = traversal.advance(self) {
item.item.convert_to_webrender(webrender_traits::StackingLevel::PositionedContent,
builder,
auxiliary_lists_builder);
frame_builder);
}
}
fn convert_to_webrender<'a>(&self,
traversal: &mut DisplayListTraversal<'a>,
api: &webrender_traits::RenderApi,
api: &mut webrender_traits::RenderApi,
pipeline_id: webrender_traits::PipelineId,
epoch: webrender_traits::Epoch,
scroll_layer_id: Option<webrender_traits::ScrollLayerId>,
auxiliary_lists_builder: &mut AuxiliaryListsBuilder)
frame_builder: &mut WebRenderFrameBuilder)
-> webrender_traits::StackingContextId {
let scroll_policy = self.layer_info
.map_or(webrender_traits::ScrollPolicy::Scrollable, |info| {
@ -333,17 +333,18 @@ impl WebRenderStackingContextConverter for StackingContext {
}
});
let mut sc = webrender_traits::StackingContext::new(scroll_layer_id,
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(),
auxiliary_lists_builder);
let mut sc =
webrender_traits::StackingContext::new(scroll_layer_id,
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,
@ -351,10 +352,10 @@ impl WebRenderStackingContextConverter for StackingContext {
epoch,
scroll_layer_id,
&mut builder,
auxiliary_lists_builder,
frame_builder,
false);
api.add_display_list(builder.finalize(), &mut sc, pipeline_id, epoch);
api.add_stacking_context(sc, pipeline_id, epoch)
frame_builder.add_display_list(api, builder.finalize(), &mut sc);
frame_builder.add_stacking_context(api, pipeline_id, sc)
}
fn web_render_stacking_level(&self) -> webrender_traits::StackingLevel {
@ -368,11 +369,11 @@ impl WebRenderStackingContextConverter for StackingContext {
impl WebRenderDisplayListConverter for DisplayList {
fn convert_to_webrender(&self,
api: &webrender_traits::RenderApi,
api: &mut webrender_traits::RenderApi,
pipeline_id: webrender_traits::PipelineId,
epoch: webrender_traits::Epoch,
scroll_layer_id: Option<webrender_traits::ScrollLayerId>,
auxiliary_lists_builder: &mut AuxiliaryListsBuilder)
frame_builder: &mut WebRenderFrameBuilder)
-> webrender_traits::StackingContextId {
let mut traversal = DisplayListTraversal {
display_list: self,
@ -385,7 +386,7 @@ impl WebRenderDisplayListConverter for DisplayList {
pipeline_id,
epoch,
scroll_layer_id,
auxiliary_lists_builder)
frame_builder)
}
}
@ -393,14 +394,14 @@ impl WebRenderDisplayItemConverter for DisplayItem {
fn convert_to_webrender(&self,
level: webrender_traits::StackingLevel,
builder: &mut webrender_traits::DisplayListBuilder,
auxiliary_lists_builder: &mut AuxiliaryListsBuilder) {
frame_builder: &mut WebRenderFrameBuilder) {
match *self {
DisplayItem::SolidColorClass(ref item) => {
let color = item.color.to_colorf();
if color.a > 0.0 {
builder.push_rect(level,
item.base.bounds.to_rectf(),
item.base.clip.to_clip_region(auxiliary_lists_builder),
item.base.clip.to_clip_region(frame_builder),
color);
}
}
@ -425,13 +426,13 @@ impl WebRenderDisplayItemConverter for DisplayItem {
if glyphs.len() > 0 {
builder.push_text(level,
item.base.bounds.to_rectf(),
item.base.clip.to_clip_region(auxiliary_lists_builder),
item.base.clip.to_clip_region(frame_builder),
glyphs,
item.text_run.font_key.expect("Font not added to webrender!"),
item.text_color.to_colorf(),
item.text_run.actual_pt_size,
item.blur_radius,
auxiliary_lists_builder);
&mut frame_builder.auxiliary_lists_builder);
}
}
DisplayItem::ImageClass(ref item) => {
@ -440,7 +441,7 @@ impl WebRenderDisplayItemConverter for DisplayItem {
item.stretch_size.height > Au(0) {
builder.push_image(level,
item.base.bounds.to_rectf(),
item.base.clip.to_clip_region(auxiliary_lists_builder),
item.base.clip.to_clip_region(frame_builder),
item.stretch_size.to_sizef(),
item.image_rendering.to_image_rendering(),
id);
@ -450,7 +451,7 @@ impl WebRenderDisplayItemConverter for DisplayItem {
DisplayItem::WebGLClass(ref item) => {
builder.push_webgl_canvas(level,
item.base.bounds.to_rectf(),
item.base.clip.to_clip_region(auxiliary_lists_builder),
item.base.clip.to_clip_region(frame_builder),
item.context_id);
}
DisplayItem::BorderClass(ref item) => {
@ -478,7 +479,7 @@ impl WebRenderDisplayItemConverter for DisplayItem {
let radius = item.radius.to_border_radius();
builder.push_border(level,
rect,
item.base.clip.to_clip_region(auxiliary_lists_builder),
item.base.clip.to_clip_region(frame_builder),
left,
top,
right,
@ -495,11 +496,11 @@ impl WebRenderDisplayItemConverter for DisplayItem {
}
builder.push_gradient(level,
rect,
item.base.clip.to_clip_region(auxiliary_lists_builder),
item.base.clip.to_clip_region(frame_builder),
start_point,
end_point,
stops,
auxiliary_lists_builder);
&mut frame_builder.auxiliary_lists_builder);
}
DisplayItem::LineClass(..) => {
println!("TODO DisplayItem::LineClass");
@ -512,7 +513,7 @@ impl WebRenderDisplayItemConverter for DisplayItem {
let box_bounds = item.box_bounds.to_rectf();
builder.push_box_shadow(level,
rect,
item.base.clip.to_clip_region(auxiliary_lists_builder),
item.base.clip.to_clip_region(frame_builder),
box_bounds,
item.offset.to_pointf(),
item.color.to_colorf(),
@ -526,9 +527,52 @@ impl WebRenderDisplayItemConverter for DisplayItem {
let pipeline_id = item.iframe.to_webrender();
builder.push_iframe(level,
rect,
item.base.clip.to_clip_region(auxiliary_lists_builder),
item.base.clip.to_clip_region(frame_builder),
pipeline_id);
}
}
}
}
pub struct WebRenderFrameBuilder {
pub stacking_contexts: Vec<(StackingContextId, webrender_traits::StackingContext)>,
pub display_lists: Vec<(DisplayListId, webrender_traits::BuiltDisplayList)>,
pub auxiliary_lists_builder: AuxiliaryListsBuilder,
pub root_pipeline_id: PipelineId
}
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,
}
}
pub fn add_stacking_context(&mut self,
api: &mut webrender_traits::RenderApi,
pipeline_id: PipelineId,
stacking_context: webrender_traits::StackingContext)
-> 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.has_stacking_contexts = stacking_context.has_stacking_contexts ||
display_list.descriptor().has_stacking_contexts;
stacking_context.display_lists.push(id);
self.display_lists.push((id, display_list));
id
}
}