servo: Merge #9756 - Flatten display list structure (from mrobinson:flat-display-lists-webrender); r=pcwalton

Instead of producing a tree of stacking contexts, display list
generation now produces a flat list of display items and a tree of
stacking contexts. This will eventually allow display list construction
to produce and modify WebRender vertex buffers directly, removing the
overhead of display list conversion.  This change also moves
layerization of the display list to the paint thread, since it isn't
currently useful for WebRender.

To accomplish this, display list generation now takes three passes of
the flow tree:

        1. Calculation of absolute positions.
        2. Collection of a tree of stacking contexts.
        3. Creation of a list of display items.

After collection of display items, they are sorted based upon the index
of their parent stacking contexts and their position in CSS 2.1
Appendeix E stacking order.

This is a big change, but it actually simplifies display list generation.

Source-Repo: https://github.com/servo/servo
Source-Revision: 62814f7cb486bc267a796b7ce58c51d59240fad0
This commit is contained in:
Martin Robinson 2016-03-02 05:52:08 +05:01
Родитель 6492a07d84
Коммит 36406cdba8
27 изменённых файлов: 1709 добавлений и 1861 удалений

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,97 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! Transforms a display list to produce a visually-equivalent, but cheaper-to-paint, one.
use app_units::Au;
use display_list::{DisplayItem, DisplayList, StackingContext};
use euclid::rect::Rect;
use euclid::{Matrix2D, Matrix4};
use std::collections::linked_list::LinkedList;
use std::sync::Arc;
use util::geometry;
/// Transforms a display list to produce a visually-equivalent, but cheaper-to-paint, one.
pub struct DisplayListOptimizer {
/// The visible rect in page coordinates.
visible_rect: Rect<Au>,
}
impl DisplayListOptimizer {
/// Creates a new display list optimizer object. `visible_rect` specifies the visible rect in
/// page coordinates.
pub fn new(visible_rect: &Rect<f32>) -> DisplayListOptimizer {
DisplayListOptimizer {
visible_rect: geometry::f32_rect_to_au_rect(*visible_rect),
}
}
/// Optimizes the given display list, returning an equivalent, but cheaper-to-paint, one.
pub fn optimize(self, display_list: &DisplayList) -> DisplayList {
let mut result = DisplayList::new();
self.add_in_bounds_display_items(&mut result.background_and_borders,
display_list.background_and_borders.iter());
self.add_in_bounds_display_items(&mut result.block_backgrounds_and_borders,
display_list.block_backgrounds_and_borders.iter());
self.add_in_bounds_display_items(&mut result.floats, display_list.floats.iter());
self.add_in_bounds_display_items(&mut result.content, display_list.content.iter());
self.add_in_bounds_display_items(&mut result.positioned_content,
display_list.positioned_content.iter());
self.add_in_bounds_display_items(&mut result.outlines,
display_list.outlines.iter());
result
}
/// Adds display items that intersect the visible rect to `result_list`.
fn add_in_bounds_display_items<'a, I>(&self,
result_list: &mut LinkedList<DisplayItem>,
display_items: I)
where I: Iterator<Item=&'a DisplayItem> {
for display_item in display_items {
if !self.should_include_display_item(display_item) {
continue;
}
result_list.push_back((*display_item).clone())
}
}
fn should_include_display_item(&self, item: &DisplayItem) -> bool {
if let &DisplayItem::StackingContextClass(ref stacking_context) = item {
return self.should_include_stacking_context(stacking_context);
}
if !self.visible_rect.intersects(&item.bounds()) {
return false;
}
if let Some(base_item) = item.base() {
if !base_item.clip.might_intersect_rect(&self.visible_rect) {
return false;
}
}
true
}
fn should_include_stacking_context(&self, stacking_context: &Arc<StackingContext>) -> bool {
// Transform this stacking context to get it into the same space as
// the parent stacking context.
let origin_x = stacking_context.bounds.origin.x.to_f32_px();
let origin_y = stacking_context.bounds.origin.y.to_f32_px();
let transform = Matrix4::identity().translate(origin_x,
origin_y,
0.0)
.mul(&stacking_context.transform);
let transform_2d = Matrix2D::new(transform.m11, transform.m12,
transform.m21, transform.m22,
transform.m41, transform.m42);
let overflow = geometry::au_rect_to_f32_rect(stacking_context.overflow);
let overflow = transform_2d.transform_rect(&overflow);
let overflow = geometry::f32_rect_to_au_rect(overflow);
self.visible_rect.intersects(&overflow)
}
}

Просмотреть файл

@ -8,15 +8,16 @@ use app_units::Au;
use azure::AzFloat;
use azure::azure_hl::{BackendType, Color, DrawTarget, SurfaceFormat};
use canvas_traits::CanvasMsg;
use display_list::{DisplayItem, DisplayList, LayerInfo, StackingContext};
use display_list::{DisplayItem, DisplayList, DisplayListEntry, DisplayListTraversal};
use display_list::{LayerInfo, StackingContext, StackingContextId, StackingContextType};
use euclid::Matrix4;
use euclid::point::Point2D;
use euclid::rect::Rect;
use euclid::size::Size2D;
use font_cache_thread::FontCacheThread;
use font_context::FontContext;
use gfx_traits::{Epoch, FrameTreeId, LayerId, LayerKind, LayerProperties};
use gfx_traits::{PaintListener, PaintMsg as ConstellationMsg, ScrollPolicy, color};
use gfx_traits::PaintMsg as ConstellationMsg;
use gfx_traits::{Epoch, FrameTreeId, LayerId, LayerKind, LayerProperties, PaintListener};
use ipc_channel::ipc::IpcSender;
use layers::layers::{BufferRequest, LayerBuffer, LayerBufferSet};
use layers::platform::surface::{NativeDisplay, NativeSurface};
@ -37,143 +38,292 @@ use util::opts;
use util::thread;
use util::thread_state;
#[derive(Clone, Deserialize, Serialize, HeapSizeOf)]
pub enum PaintLayerContents {
StackingContext(Arc<StackingContext>),
DisplayList(Arc<DisplayList>),
}
#[derive(Clone, HeapSizeOf)]
struct PaintLayer {
/// The LayerProperties, which describe the layer in a way that the Compositor
/// can consume.
pub layer_properties: LayerProperties,
/// Information about a hardware graphics layer that layout sends to the painting thread.
#[derive(Clone, Deserialize, Serialize, HeapSizeOf)]
pub struct PaintLayer {
/// A per-pipeline ID describing this layer that should be stable across reflows.
pub id: LayerId,
/// The color of the background in this layer. Used for unpainted content.
pub background_color: Color,
/// The content of this layer, which is either a stacking context or a display list.
pub contents: PaintLayerContents,
/// The layer's boundaries in the parent layer's coordinate system.
pub bounds: Rect<Au>,
/// The scrolling policy of this layer.
pub scroll_policy: ScrollPolicy,
/// The pipeline of the subpage that this layer represents, if there is one.
pub subpage_pipeline_id: Option<PipelineId>,
/// The StackingContextId of the StackingContext that is the immediate
/// parent of this layer. This is used to ensure applying the proper transform
/// when painting.
pub starting_stacking_context_id: StackingContextId,
/// The indices (in the DisplayList) to the first and last display item
/// that are the contents of this layer.
pub display_list_indices: Option<(usize, usize)>,
/// When painting, whether to draw the start by entering the surrounding StackingContext
/// or simply to draw the single item this PaintLayer contains.
pub single_item: bool,
/// The layer's bounds start at the overflow origin, but display items are
/// positioned relative to the stacking context bounds, so we need to
/// offset by the overflow rect (which will be in the coordinate system of
/// the stacking context bounds).
pub display_list_origin: Point2D<f32>
}
impl PaintLayer {
/// Creates a new `PaintLayer` with a stacking context.
pub fn new_with_stacking_context(layer_info: LayerInfo,
stacking_context: Arc<StackingContext>,
background_color: Color)
-> PaintLayer {
fn new_from_stacking_context(layer_info: &LayerInfo,
stacking_context: &StackingContext,
parent_origin: &Point2D<Au>,
transform: &Matrix4,
perspective: &Matrix4,
parent_id: Option<LayerId>)
-> PaintLayer {
let bounds = Rect::new(stacking_context.bounds.origin + stacking_context.overflow.origin,
stacking_context.overflow.size);
PaintLayer {
id: layer_info.layer_id,
background_color: background_color,
contents: PaintLayerContents::StackingContext(stacking_context),
bounds: bounds,
scroll_policy: layer_info.scroll_policy,
subpage_pipeline_id: layer_info.subpage_pipeline_id,
}
}
/// Creates a new `PaintLayer` with a display list.
pub fn new_with_display_list(layer_info: LayerInfo,
display_list: DisplayList)
-> PaintLayer {
let bounds = display_list.calculate_bounding_rect().expand_to_px_boundaries();
PaintLayer {
id: layer_info.layer_id,
background_color: color::transparent(),
contents: PaintLayerContents::DisplayList(Arc::new(display_list)),
bounds: bounds,
scroll_policy: layer_info.scroll_policy,
subpage_pipeline_id: layer_info.subpage_pipeline_id,
}
}
pub fn find_layer_with_layer_id(this: &Arc<PaintLayer>,
layer_id: LayerId)
-> Option<Arc<PaintLayer>> {
if this.id == layer_id {
return Some(this.clone());
}
match this.contents {
PaintLayerContents::StackingContext(ref stacking_context) =>
stacking_context.display_list.find_layer_with_layer_id(layer_id),
PaintLayerContents::DisplayList(ref display_list) =>
display_list.find_layer_with_layer_id(layer_id),
}
}
fn build_layer_properties(&self,
parent_origin: &Point2D<Au>,
transform: &Matrix4,
perspective: &Matrix4,
parent_id: Option<LayerId>)
-> LayerProperties {
let layer_boundaries = Rect::new(
Point2D::new((parent_origin.x + self.bounds.min_x()).to_nearest_px() as f32,
(parent_origin.y + self.bounds.min_y()).to_nearest_px() as f32),
Size2D::new(self.bounds.size.width.to_nearest_px() as f32,
self.bounds.size.height.to_nearest_px() as f32));
Point2D::new((parent_origin.x + bounds.min_x()).to_nearest_px() as f32,
(parent_origin.y + bounds.min_y()).to_nearest_px() as f32),
Size2D::new(bounds.size.width.to_nearest_px() as f32,
bounds.size.height.to_nearest_px() as f32));
let (transform,
perspective,
establishes_3d_context,
scrolls_overflow_area) = match self.contents {
PaintLayerContents::StackingContext(ref stacking_context) => {
(transform.mul(&stacking_context.transform),
perspective.mul(&stacking_context.perspective),
stacking_context.establishes_3d_context,
stacking_context.scrolls_overflow_area)
let transform = transform.mul(&stacking_context.transform);
let perspective = perspective.mul(&stacking_context.perspective);
let establishes_3d_context = stacking_context.establishes_3d_context;
let scrolls_overflow_area = stacking_context.scrolls_overflow_area;
PaintLayer {
layer_properties: LayerProperties {
id: layer_info.layer_id,
parent_id: parent_id,
rect: layer_boundaries,
background_color: layer_info.background_color,
scroll_policy: layer_info.scroll_policy,
transform: transform,
perspective: perspective,
establishes_3d_context: establishes_3d_context,
scrolls_overflow_area: scrolls_overflow_area,
subpage_pipeline_id: layer_info.subpage_pipeline_id,
},
PaintLayerContents::DisplayList(_) => {
(*transform, *perspective, false, false)
}
starting_stacking_context_id: stacking_context.id,
display_list_indices: None,
single_item: false,
display_list_origin: Point2D::new(stacking_context.overflow.origin.x.to_f32_px(),
stacking_context.overflow.origin.y.to_f32_px()),
}
}
fn new_for_display_item(layer_info: &LayerInfo,
item_bounds: &Rect<Au>,
parent_origin: &Point2D<Au>,
transform: &Matrix4,
perspective: &Matrix4,
parent_id: Option<LayerId>,
stacking_context_id: StackingContextId,
item_index: usize)
-> PaintLayer {
let bounds = item_bounds.expand_to_px_boundaries();
let layer_boundaries = Rect::new(
Point2D::new((parent_origin.x + bounds.min_x()).to_nearest_px() as f32,
(parent_origin.y + bounds.min_y()).to_nearest_px() as f32),
Size2D::new(bounds.size.width.to_nearest_px() as f32,
bounds.size.height.to_nearest_px() as f32));
PaintLayer {
layer_properties: LayerProperties {
id: layer_info.layer_id,
parent_id: parent_id,
rect: layer_boundaries,
background_color: layer_info.background_color,
scroll_policy: layer_info.scroll_policy,
transform: *transform,
perspective: *perspective,
establishes_3d_context: false,
scrolls_overflow_area: false,
subpage_pipeline_id: layer_info.subpage_pipeline_id,
},
starting_stacking_context_id: stacking_context_id,
display_list_indices: Some((item_index, item_index)),
single_item: true,
display_list_origin: Point2D::new(bounds.origin.x.to_f32_px(),
bounds.origin.y.to_f32_px()),
}
}
fn add_item(&mut self, index: usize) {
let indices = match self.display_list_indices {
Some((first, _)) => (first, index),
None => (index, index),
};
self.display_list_indices = Some(indices);
}
LayerProperties {
id: self.id,
parent_id: parent_id,
rect: layer_boundaries,
background_color: self.background_color,
scroll_policy: self.scroll_policy,
transform: transform,
perspective: perspective,
establishes_3d_context: establishes_3d_context,
scrolls_overflow_area: scrolls_overflow_area,
subpage_pipeline_id: self.subpage_pipeline_id,
fn make_companion_layer(&mut self) {
self.layer_properties.id = self.layer_properties.id.companion_layer_id();
self.display_list_indices = None;
}
}
struct LayerCreator {
layers: Vec<PaintLayer>,
layer_details_stack: Vec<PaintLayer>,
current_layer: Option<PaintLayer>,
current_entry_index: usize,
}
impl LayerCreator {
fn create_layers_with_display_list(display_list: &DisplayList) -> Vec<PaintLayer> {
let mut layer_creator = LayerCreator {
layers: Vec::new(),
layer_details_stack: Vec::new(),
current_layer: None,
current_entry_index: 0,
};
let mut traversal = DisplayListTraversal {
display_list: display_list,
current_item_index: 0,
last_item_index: display_list.list.len(),
};
layer_creator.create_layers_for_stacking_context(&display_list.root_stacking_context,
&mut traversal,
&Point2D::zero(),
&Matrix4::identity(),
&Matrix4::identity());
layer_creator.layers
}
fn finalize_current_layer(&mut self) {
if let Some(current_layer) = self.current_layer.take() {
self.layers.push(current_layer);
}
}
// The origin for child layers might be somewhere other than the layer origin,
// since layer boundaries are expanded to include overflow.
pub fn origin_for_child_layers(&self) -> Point2D<Au> {
match self.contents {
PaintLayerContents::StackingContext(ref stacking_context) =>
-stacking_context.overflow.origin,
PaintLayerContents::DisplayList(_) => Point2D::zero(),
}
fn current_parent_layer_id(&self) -> Option<LayerId> {
self.layer_details_stack.last().as_ref().map(|layer|
layer.layer_properties.id
)
}
pub fn display_list_origin(&self) -> Point2D<f32> {
// The layer's bounds start at the overflow origin, but display items are
// positioned relative to the stacking context counds, so we need to
// offset by the overflow rect (which will be in the coordinate system of
// the stacking context bounds).
match self.contents {
PaintLayerContents::StackingContext(ref stacking_context) => {
Point2D::new(stacking_context.overflow.origin.x.to_f32_px(),
stacking_context.overflow.origin.y.to_f32_px())
fn current_parent_stacking_context_id(&self) -> StackingContextId {
self.layer_details_stack.last().unwrap().starting_stacking_context_id
}
},
PaintLayerContents::DisplayList(_) => {
Point2D::new(self.bounds.origin.x.to_f32_px(), self.bounds.origin.y.to_f32_px())
fn create_layers_for_stacking_context<'a>(&mut self,
stacking_context: &StackingContext,
traversal: &mut DisplayListTraversal<'a>,
parent_origin: &Point2D<Au>,
transform: &Matrix4,
perspective: &Matrix4) {
if let Some(ref layer_info) = stacking_context.layer_info {
self.finalize_current_layer();
let new_layer = PaintLayer::new_from_stacking_context(
layer_info,
stacking_context,
parent_origin,
transform,
perspective,
self.current_parent_layer_id());
self.layer_details_stack.push(new_layer.clone());
self.current_layer = Some(new_layer);
// When there is a new layer, the transforms and origin are handled by
// the compositor, so the new transform and perspective matrices are
// just the identity.
//
// The origin for child layers which might be somewhere other than the
// layer origin, since layer boundaries are expanded to include overflow.
self.process_stacking_context_items(stacking_context,
traversal,
&-stacking_context.overflow.origin,
&Matrix4::identity(),
&Matrix4::identity());
self.finalize_current_layer();
self.layer_details_stack.pop();
return;
}
if stacking_context.context_type != StackingContextType::Real {
self.process_stacking_context_items(stacking_context,
traversal,
parent_origin,
transform,
perspective);
return;
}
self.process_stacking_context_items(stacking_context,
traversal,
&(stacking_context.bounds.origin + *parent_origin),
&transform.mul(&stacking_context.transform),
&perspective.mul(&stacking_context.perspective));
}
fn process_stacking_context_items<'a>(&mut self,
stacking_context: &StackingContext,
traversal: &mut DisplayListTraversal<'a>,
parent_origin: &Point2D<Au>,
transform: &Matrix4,
perspective: &Matrix4) {
for kid in stacking_context.children.iter() {
while let Some(item) = traversal.advance(stacking_context) {
self.create_layers_for_item(item,
parent_origin,
transform,
perspective);
}
self.create_layers_for_stacking_context(kid,
traversal,
parent_origin,
transform,
perspective);
}
while let Some(item) = traversal.advance(stacking_context) {
self.create_layers_for_item(item,
parent_origin,
transform,
perspective);
}
}
fn create_layers_for_item<'a>(&mut self,
item: &DisplayListEntry,
parent_origin: &Point2D<Au>,
transform: &Matrix4,
perspective: &Matrix4) {
if let DisplayItem::LayeredItemClass(ref layered_item) = item.item {
// We need to finalize the last layer here before incrementing the entry
// index, otherwise this item will be placed into the parent layer.
self.finalize_current_layer();
let layer = PaintLayer::new_for_display_item(
&layered_item.layer_info,
&layered_item.item.bounds(),
parent_origin,
transform,
perspective,
self.current_parent_layer_id(),
self.current_parent_stacking_context_id(),
self.current_entry_index);
self.layers.push(layer);
self.current_entry_index += 1;
return;
}
// If we don't have a current layer, we are an item that belonged to a
// previous layer that was finalized by a child layer. We need to
// resurrect a copy of the original ancestor layer to ensure that this
// item is ordered on top of the child layers when painted.
if self.current_layer.is_none() {
let mut new_layer = self.layer_details_stack.pop().unwrap();
new_layer.make_companion_layer();
if new_layer.layer_properties.parent_id == None {
new_layer.layer_properties.parent_id =
Some(new_layer.layer_properties.id.original());
}
self.layer_details_stack.push(new_layer.clone());
self.current_layer = Some(new_layer);
}
if let Some(ref mut current_layer) = self.current_layer {
current_layer.add_item(self.current_entry_index);
}
self.current_entry_index += 1;
}
}
@ -192,7 +342,7 @@ pub enum Msg {
#[derive(Deserialize, Serialize)]
pub enum LayoutToPaintMsg {
PaintInit(Epoch, PaintLayer),
PaintInit(Epoch, Arc<DisplayList>),
CanvasLayer(LayerId, IpcSender<CanvasMsg>),
Exit(IpcSender<()>),
}
@ -216,7 +366,10 @@ pub struct PaintThread<C> {
time_profiler_chan: time::ProfilerChan,
/// The root paint layer sent to us by the layout thread.
root_paint_layer: Option<Arc<PaintLayer>>,
root_display_list: Option<Arc<DisplayList>>,
/// A map that associates LayerIds with their corresponding layers.
layer_map: HashMap<LayerId, Arc<PaintLayer>>,
/// Permission to send paint messages to the compositor
paint_permission: bool,
@ -273,7 +426,8 @@ impl<C> PaintThread<C> where C: PaintListener + Send + 'static {
chrome_to_paint_port: chrome_to_paint_port,
compositor: compositor,
time_profiler_chan: time_profiler_chan,
root_paint_layer: None,
root_display_list: None,
layer_map: HashMap::new(),
paint_permission: false,
current_epoch: None,
worker_threads: worker_threads,
@ -312,9 +466,9 @@ impl<C> PaintThread<C> where C: PaintListener + Send + 'static {
};
match message {
Msg::FromLayout(LayoutToPaintMsg::PaintInit(epoch, paint_layer)) => {
Msg::FromLayout(LayoutToPaintMsg::PaintInit(epoch, display_list)) => {
self.current_epoch = Some(epoch);
self.root_paint_layer = Some(Arc::new(paint_layer));
self.root_display_list = Some(display_list);
if self.paint_permission {
self.initialize_layers();
@ -326,7 +480,7 @@ impl<C> PaintThread<C> where C: PaintListener + Send + 'static {
self.canvas_map.insert(layer_id, canvas_renderer);
}
Msg::FromChrome(ChromeToPaintMsg::Paint(requests, frame_tree_id)) => {
if self.paint_permission && self.root_paint_layer.is_some() {
if self.paint_permission && self.root_display_list.is_some() {
let mut replies = Vec::new();
for PaintRequest { buffer_requests, scale, layer_id, epoch, layer_kind }
in requests {
@ -350,7 +504,7 @@ impl<C> PaintThread<C> where C: PaintListener + Send + 'static {
Msg::FromChrome(ChromeToPaintMsg::PaintPermissionGranted) => {
self.paint_permission = true;
if self.root_paint_layer.is_some() {
if self.root_display_list.is_some() {
self.initialize_layers();
}
}
@ -390,14 +544,15 @@ impl<C> PaintThread<C> where C: PaintListener + Send + 'static {
layer_id: LayerId,
layer_kind: LayerKind) {
time::profile(time::ProfilerCategory::Painting, None, self.time_profiler_chan.clone(), || {
let display_list = match self.root_display_list {
Some(ref display_list) => display_list.clone(),
None => return,
};
// Bail out if there is no appropriate layer.
let paint_layer = if let Some(ref root_paint_layer) = self.root_paint_layer {
match PaintLayer::find_layer_with_layer_id(root_paint_layer, layer_id) {
Some(paint_layer) => paint_layer,
None => return,
}
} else {
return
let layer = match self.layer_map.get(&layer_id) {
Some(layer) => layer.clone(),
None => return,
};
// Divide up the layer into tiles and distribute them to workers via a simple round-
@ -408,7 +563,8 @@ impl<C> PaintThread<C> where C: PaintListener + Send + 'static {
let thread_id = i % self.worker_threads.len();
self.worker_threads[thread_id].paint_tile(thread_id,
tile,
paint_layer.clone(),
display_list.clone(),
layer.clone(),
scale,
layer_kind);
}
@ -425,109 +581,18 @@ impl<C> PaintThread<C> where C: PaintListener + Send + 'static {
}
fn initialize_layers(&mut self) {
let root_paint_layer = match self.root_paint_layer {
let root_display_list = match self.root_display_list {
None => return,
Some(ref root_paint_layer) => root_paint_layer,
Some(ref root_display_list) => root_display_list,
};
let mut properties = Vec::new();
build_from_paint_layer(&mut properties,
root_paint_layer,
&Point2D::zero(),
&Matrix4::identity(),
&Matrix4::identity(),
None);
let layers = LayerCreator::create_layers_with_display_list(&root_display_list);
let properties = layers.iter().map(|layer| layer.layer_properties.clone()).collect();
self.compositor.initialize_layers_for_pipeline(self.id,
properties,
self.current_epoch.unwrap());
fn build_from_paint_layer(properties: &mut Vec<LayerProperties>,
paint_layer: &Arc<PaintLayer>,
parent_origin: &Point2D<Au>,
transform: &Matrix4,
perspective: &Matrix4,
parent_id: Option<LayerId>) {
properties.push(paint_layer.build_layer_properties(parent_origin,
transform,
perspective,
parent_id));
match paint_layer.contents {
PaintLayerContents::StackingContext(ref context) => {
// When there is a new layer, the transforms and origin are handled by the compositor,
// so the new transform and perspective matrices are just the identity.
continue_walking_stacking_context(properties,
&context,
&paint_layer.origin_for_child_layers(),
&Matrix4::identity(),
&Matrix4::identity(),
Some(paint_layer.id));
},
PaintLayerContents::DisplayList(ref display_list) => {
for kid in display_list.positioned_content.iter() {
if let &DisplayItem::StackingContextClass(ref stacking_context) = kid {
build_from_stacking_context(properties,
&stacking_context,
&parent_origin,
&transform,
&perspective,
parent_id)
}
}
for kid in display_list.layered_children.iter() {
build_from_paint_layer(properties,
&kid,
&parent_origin,
&transform,
&perspective,
parent_id)
}
},
}
}
fn build_from_stacking_context(properties: &mut Vec<LayerProperties>,
stacking_context: &Arc<StackingContext>,
parent_origin: &Point2D<Au>,
transform: &Matrix4,
perspective: &Matrix4,
parent_id: Option<LayerId>) {
continue_walking_stacking_context(properties,
stacking_context,
&(stacking_context.bounds.origin + *parent_origin),
&transform.mul(&stacking_context.transform),
&perspective.mul(&stacking_context.perspective),
parent_id);
}
fn continue_walking_stacking_context(properties: &mut Vec<LayerProperties>,
stacking_context: &Arc<StackingContext>,
parent_origin: &Point2D<Au>,
transform: &Matrix4,
perspective: &Matrix4,
parent_id: Option<LayerId>) {
for kid in stacking_context.display_list.positioned_content.iter() {
if let &DisplayItem::StackingContextClass(ref stacking_context) = kid {
build_from_stacking_context(properties,
&stacking_context,
&parent_origin,
&transform,
&perspective,
parent_id)
}
}
for kid in stacking_context.display_list.layered_children.iter() {
build_from_paint_layer(properties,
&kid,
&parent_origin,
&transform,
&perspective,
parent_id)
}
self.layer_map.clear();
for layer in layers.into_iter() {
self.layer_map.insert(layer.layer_properties.id, Arc::new(layer));
}
}
}
@ -570,11 +635,13 @@ impl WorkerThreadProxy {
fn paint_tile(&mut self,
thread_id: usize,
tile: BufferRequest,
display_list: Arc<DisplayList>,
paint_layer: Arc<PaintLayer>,
scale: f32,
layer_kind: LayerKind) {
let msg = MsgToWorkerThread::PaintTile(thread_id,
tile,
display_list,
paint_layer,
scale,
layer_kind);
@ -640,9 +707,15 @@ impl WorkerThread {
loop {
match self.receiver.recv().unwrap() {
MsgToWorkerThread::Exit => break,
MsgToWorkerThread::PaintTile(thread_id, tile, paint_layer, scale, layer_kind) => {
MsgToWorkerThread::PaintTile(thread_id,
tile,
display_list,
paint_layer,
scale,
layer_kind) => {
let buffer = self.optimize_and_paint_tile(thread_id,
tile,
display_list,
paint_layer,
scale,
layer_kind);
@ -676,6 +749,7 @@ impl WorkerThread {
fn optimize_and_paint_tile(&mut self,
thread_id: usize,
mut tile: BufferRequest,
display_list: Arc<DisplayList>,
paint_layer: Arc<PaintLayer>,
scale: f32,
layer_kind: LayerKind)
@ -700,7 +774,7 @@ impl WorkerThread {
// Apply the translation to paint the tile we want.
let matrix = Matrix4::identity();
let matrix = matrix.scale(scale as AzFloat, scale as AzFloat, 1.0);
let tile_bounds = tile.page_rect.translate(&paint_layer.display_list_origin());
let tile_bounds = tile.page_rect.translate(&paint_layer.display_list_origin);
let matrix = matrix.translate(-tile_bounds.origin.x as AzFloat,
-tile_bounds.origin.y as AzFloat,
0.0);
@ -711,26 +785,22 @@ impl WorkerThread {
// Draw the display list.
time::profile(time::ProfilerCategory::PaintingPerTile,
None,
self.time_profiler_sender.clone(),
|| {
match paint_layer.contents {
PaintLayerContents::StackingContext(ref stacking_context) => {
stacking_context.optimize_and_draw_into_context(&mut paint_context,
&matrix,
None);
}
PaintLayerContents::DisplayList(ref display_list) => {
paint_context.remove_transient_clip_if_applicable();
let draw_target = paint_context.draw_target.clone();
display_list.draw_into_context(&draw_target,
&mut paint_context,
&matrix,
None);
}
}
paint_context.draw_target.flush();
});
self.time_profiler_sender.clone(), || {
if let Some((start, end)) = paint_layer.display_list_indices {
if paint_layer.single_item {
display_list.draw_item_at_index_into_context(
&mut paint_context, &matrix, start);
} else {
display_list.draw_into_context(
&mut paint_context,
&matrix,
paint_layer.starting_stacking_context_id,
start,
end);
}
}
paint_context.draw_target.flush();
});
if opts::get().show_debug_parallel_paint {
// Overlay a transparent solid color to identify the thread that
@ -791,7 +861,7 @@ impl WorkerThread {
enum MsgToWorkerThread {
Exit,
PaintTile(usize, BufferRequest, Arc<PaintLayer>, f32, LayerKind),
PaintTile(usize, BufferRequest, Arc<DisplayList>, Arc<PaintLayer>, f32, LayerKind),
}
enum MsgFromWorkerThread {

Просмотреть файл

@ -98,11 +98,16 @@ impl LayerId {
let LayerId(layer_type, id, companion) = *self;
LayerId(layer_type, id, companion + 1)
}
pub fn original(&self) -> LayerId {
let LayerId(layer_type, id, _) = *self;
LayerId(layer_type, id, 0)
}
}
/// All layer-specific information that the painting task sends to the compositor other than the
/// buffer contents of the layer itself.
#[derive(Copy, Clone)]
#[derive(Copy, Clone, HeapSizeOf)]
pub struct LayerProperties {
/// An opaque ID. This is usually the address of the flow and index of the box within it.
pub id: LayerId,

Просмотреть файл

@ -29,8 +29,8 @@
use app_units::{Au, MAX_AU};
use context::LayoutContext;
use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode};
use display_list_builder::{FragmentDisplayListBuilding};
use display_list_builder::BlockFlowDisplayListBuilding;
use display_list_builder::{BorderPaintingMode, DisplayListBuildState, FragmentDisplayListBuilding};
use euclid::{Point2D, Rect, Size2D};
use floats::{ClearType, FloatKind, Floats, PlacementInfo};
use flow::{BLOCK_POSITION_IS_STATIC};
@ -45,7 +45,7 @@ use flow_list::FlowList;
use flow_ref::FlowRef;
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, HAS_LAYER, Overflow};
use fragment::{SpecificFragmentInfo};
use gfx::display_list::{ClippingRegion, DisplayList};
use gfx::display_list::{ClippingRegion, StackingContext, StackingContextId};
use gfx_traits::LayerId;
use incremental::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT};
use layout_debug;
@ -1622,6 +1622,29 @@ impl BlockFlow {
}
}
pub fn establishes_pseudo_stacking_context(&self) -> bool {
if self.fragment.establishes_stacking_context() {
return false;
}
self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) ||
self.fragment.style.get_box().position != position::T::static_ ||
self.base.flags.is_float()
}
pub fn has_scrolling_overflow(&self) -> bool {
if !self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) {
return false;
}
match (self.fragment.style().get_box().overflow_x,
self.fragment.style().get_box().overflow_y.0) {
(overflow_x::T::auto, _) | (overflow_x::T::scroll, _) |
(_, overflow_x::T::auto) | (_, overflow_x::T::scroll) => true,
(_, _) => false,
}
}
pub fn compute_inline_sizes(&mut self, layout_context: &LayoutContext) {
if !self.base.restyle_damage.intersects(REFLOW_OUT_OF_FLOW | REFLOW) {
return
@ -2084,10 +2107,15 @@ impl Flow for BlockFlow {
}
}
fn build_display_list(&mut self, layout_context: &LayoutContext) {
self.build_display_list_for_block(box DisplayList::new(),
layout_context,
BorderPaintingMode::Separate);
fn collect_stacking_contexts(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>)
-> StackingContextId {
self.collect_stacking_contexts_for_block(parent_id, contexts)
}
fn build_display_list(&mut self, state: &mut DisplayListBuildState) {
self.build_display_list_for_block(state, BorderPaintingMode::Separate);
self.fragment.restyle_damage.remove(REPAINT);
if opts::get().validate_display_list_geometry {
self.base.validate_display_list_geometry();

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -9,7 +9,7 @@
use app_units::Au;
use block::BlockFlow;
use context::LayoutContext;
use display_list_builder::FlexFlowDisplayListBuilding;
use display_list_builder::{DisplayListBuildState, FlexFlowDisplayListBuilding};
use euclid::Point2D;
use floats::FloatKind;
use flow;
@ -19,7 +19,7 @@ use flow::ImmutableFlowUtils;
use flow::{Flow, FlowClass, OpaqueFlow};
use flow::{HAS_LEFT_FLOATED_DESCENDANTS, HAS_RIGHT_FLOATED_DESCENDANTS};
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
use gfx::display_list::DisplayList;
use gfx::display_list::{StackingContext, StackingContextId};
use incremental::{REFLOW, REFLOW_OUT_OF_FLOW};
use layout_debug;
use model::MaybeAuto;
@ -420,14 +420,21 @@ impl Flow for FlexFlow {
self.block_flow.update_late_computed_block_position_if_necessary(block_position)
}
fn build_display_list(&mut self, layout_context: &LayoutContext) {
self.build_display_list_for_flex(Box::new(DisplayList::new()), layout_context);
fn build_display_list(&mut self, state: &mut DisplayListBuildState) {
self.build_display_list_for_flex(state);
if opts::get().validate_display_list_geometry {
self.block_flow.base.validate_display_list_geometry();
}
}
fn collect_stacking_contexts(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>)
-> StackingContextId {
self.block_flow.collect_stacking_contexts(parent_id, contexts)
}
fn repair_style(&mut self, new_style: &Arc<ComputedValues>) {
self.block_flow.repair_style(new_style)
}

Просмотреть файл

@ -28,12 +28,13 @@
use app_units::Au;
use block::BlockFlow;
use context::LayoutContext;
use display_list_builder::DisplayListBuildState;
use euclid::{Point2D, Rect, Size2D};
use floats::Floats;
use flow_list::{FlowList, FlowListIterator, MutFlowListIterator};
use flow_ref::{self, FlowRef, WeakFlowRef};
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow, SpecificFragmentInfo};
use gfx::display_list::{ClippingRegion, DisplayList};
use gfx::display_list::{ClippingRegion, DisplayListEntry, StackingContext, StackingContextId};
use gfx_traits::{LayerId, LayerType};
use incremental::{RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RestyleDamage};
use inline::InlineFlow;
@ -221,6 +222,11 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static {
None
}
fn collect_stacking_contexts(&mut self,
_parent_id: StackingContextId,
_: &mut Vec<StackingContext>)
-> StackingContextId;
/// If this is a float, places it. The default implementation does nothing.
fn place_float_if_applicable<'a>(&mut self, _: &'a LayoutContext<'a>) {}
@ -284,7 +290,7 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static {
}
/// Phase 5 of reflow: builds display lists.
fn build_display_list(&mut self, layout_context: &LayoutContext);
fn build_display_list(&mut self, state: &mut DisplayListBuildState);
/// Returns the union of all overflow rects of all of this flow's fragments.
fn compute_overflow(&self) -> Overflow;
@ -361,17 +367,13 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static {
fn generated_containing_block_size(&self, _: OpaqueFlow) -> LogicalSize<Au>;
/// Returns a layer ID for the given fragment.
#[allow(unsafe_code)]
fn layer_id(&self) -> LayerId {
let obj = unsafe { mem::transmute::<&&Self, &raw::TraitObject>(&self) };
LayerId::new_of_type(LayerType::FragmentBody, obj.data as usize)
LayerId::new_of_type(LayerType::FragmentBody, base(self).flow_id())
}
/// Returns a layer ID for the given fragment.
#[allow(unsafe_code)]
fn layer_id_for_overflow_scroll(&self) -> LayerId {
let obj = unsafe { mem::transmute::<&&Self, &raw::TraitObject>(&self) };
LayerId::new_of_type(LayerType::OverflowScroll, obj.data as usize)
LayerId::new_of_type(LayerType::OverflowScroll, base(self).flow_id())
}
/// Attempts to perform incremental fixup of this flow by replacing its fragment's style with
@ -924,7 +926,7 @@ pub struct BaseFlow {
pub stacking_relative_position_of_display_port: Rect<Au>,
/// The results of display list building for this flow.
pub display_list_building_result: Option<Box<DisplayList>>,
pub display_list_building_result: Option<Vec<DisplayListEntry>>,
/// The writing mode for this flow.
pub writing_mode: WritingMode,
@ -934,6 +936,11 @@ pub struct BaseFlow {
/// Various flags for flows, tightly packed to save space.
pub flags: FlowFlags,
/// The ID of the StackingContext that contains this flow. This is initialized
/// to 0, but it assigned during the collect_stacking_contexts phase of display
/// list construction.
pub stacking_context_id: StackingContextId,
}
impl fmt::Debug for BaseFlow {
@ -958,7 +965,8 @@ impl fmt::Debug for BaseFlow {
};
write!(f,
"pos={:?}, overflow={:?}{}{}{}",
"sc={:?} pos={:?}, overflow={:?}{}{}{}",
self.stacking_context_id,
self.position,
self.overflow,
child_count_string,
@ -1097,6 +1105,7 @@ impl BaseFlow {
flags: flags,
writing_mode: writing_mode,
thread_id: 0,
stacking_context_id: StackingContextId::new(0),
}
}
@ -1136,22 +1145,35 @@ impl BaseFlow {
.union(&self.overflow.paint);
let bounds = Rect::new(self.stacking_relative_position, position_with_overflow.size);
let all_items = match self.display_list_building_result {
Some(ref display_list) => display_list.flatten(),
None => Vec::new(),
let items = match self.display_list_building_result {
Some(ref items) => items,
None => return,
};
for item in &all_items {
if let Some(base_item) = item.base() {
let paint_bounds = base_item.clip.clone().intersect_rect(&base_item.bounds);
if !paint_bounds.might_be_nonempty() {
continue;
}
if bounds.union(&paint_bounds.bounding_rect()) != bounds {
error!("DisplayList item {:?} outside of Flow overflow ({:?})", item, paint_bounds);
}
for item in items.iter() {
let base_item = item.item.base();
let paint_bounds = base_item.clip.clone().intersect_rect(&base_item.bounds);
if !paint_bounds.might_be_nonempty() {
continue;
}
if bounds.union(&paint_bounds.bounding_rect()) != bounds {
error!("DisplayList item {:?} outside of Flow overflow ({:?})",
item.item,
paint_bounds);
}
}
}
pub fn flow_id(&self) -> usize {
return self as *const BaseFlow as usize;
}
pub fn collect_stacking_contexts_for_children(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>) {
for kid in self.children.iter_mut() {
kid.collect_stacking_contexts(parent_id, contexts);
}
}
}

Просмотреть файл

@ -14,7 +14,7 @@ use floats::ClearType;
use flow::{self, Flow};
use flow_ref::{self, FlowRef};
use gfx;
use gfx::display_list::{BLUR_INFLATION_FACTOR, OpaqueNode};
use gfx::display_list::{BLUR_INFLATION_FACTOR, FragmentType, OpaqueNode, StackingContextId};
use gfx::text::glyph::CharIndex;
use gfx::text::text_run::{TextRun, TextRunSlice};
use gfx_traits::{LayerId, LayerType};
@ -117,6 +117,11 @@ pub struct Fragment {
/// A debug ID that is consistent for the life of this fragment (via transform etc).
pub debug_id: u16,
/// The ID of the StackingContext that contains this fragment. This is initialized
/// to 0, but it assigned during the collect_stacking_contexts phase of display
/// list construction.
pub stacking_context_id: StackingContextId,
}
impl Encodable for Fragment {
@ -790,6 +795,7 @@ impl Fragment {
pseudo: node.get_pseudo_element_type().strip(),
flags: FragmentFlags::empty(),
debug_id: layout_debug::generate_unique_debug_id(),
stacking_context_id: StackingContextId::new(0),
}
}
@ -816,6 +822,7 @@ impl Fragment {
pseudo: pseudo,
flags: FragmentFlags::empty(),
debug_id: layout_debug::generate_unique_debug_id(),
stacking_context_id: StackingContextId::new(0),
}
}
@ -848,6 +855,7 @@ impl Fragment {
pseudo: self.pseudo.clone(),
flags: FragmentFlags::empty(),
debug_id: self.debug_id,
stacking_context_id: StackingContextId::new(0),
}
}
@ -2139,10 +2147,12 @@ impl Fragment {
overflow_x::T::visible) => false,
(position::T::absolute, _, _, _) |
(position::T::fixed, _, _, _) |
(position::T::relative, _, _, _) => true,
(position::T::static_, _, _, _) => {
false
}
(position::T::relative, _, _, _) |
(_, _, overflow_x::T::auto, _) |
(_, _, overflow_x::T::scroll, _) |
(_, _, _, overflow_x::T::auto) |
(_, _, _, overflow_x::T::scroll) => true,
(position::T::static_, _, _, _) => false
}
}
@ -2424,6 +2434,18 @@ impl Fragment {
}
}
pub fn fragment_id(&self) -> usize {
return self as *const Fragment as usize;
}
pub fn fragment_type(&self) -> FragmentType {
match self.pseudo {
PseudoElementType::Normal => FragmentType::FragmentBody,
PseudoElementType::Before(_) => FragmentType::BeforePseudoContent,
PseudoElementType::After(_) => FragmentType::AfterPseudoContent
}
}
pub fn layer_id(&self) -> LayerId {
let layer_type = match self.pseudo {
PseudoElementType::Normal => LayerType::FragmentBody,

Просмотреть файл

@ -7,6 +7,7 @@
use app_units::Au;
use block::AbsoluteAssignBSizesTraversal;
use context::LayoutContext;
use display_list_builder::DisplayListBuildState;
use display_list_builder::{FragmentDisplayListBuilding, InlineFlowDisplayListBuilding};
use euclid::{Point2D, Size2D};
use floats::{FloatKind, Floats, PlacementInfo};
@ -15,7 +16,7 @@ use flow::{self, BaseFlow, Flow, FlowClass, ForceNonfloatedFlag, IS_ABSOLUTELY_P
use flow_ref;
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, Overflow};
use fragment::{SpecificFragmentInfo};
use gfx::display_list::OpaqueNode;
use gfx::display_list::{OpaqueNode, StackingContext, StackingContextId};
use gfx::font::FontMetrics;
use gfx::font_context::FontContext;
use incremental::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RESOLVE_GENERATED_CONTENT};
@ -1747,8 +1748,15 @@ impl Flow for InlineFlow {
fn update_late_computed_block_position_if_necessary(&mut self, _: Au) {}
fn build_display_list(&mut self, layout_context: &LayoutContext) {
self.build_display_list_for_inline(layout_context);
fn collect_stacking_contexts(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>)
-> StackingContextId {
self.collect_stacking_contexts_for_inline(parent_id, contexts)
}
fn build_display_list(&mut self, state: &mut DisplayListBuildState) {
self.build_display_list_for_inline(state);
for fragment in &mut self.fragments.fragments {
fragment.restyle_damage.remove(REPAINT);

Просмотреть файл

@ -22,11 +22,12 @@ use euclid::size::Size2D;
use flow::{self, Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils};
use flow_ref::{self, FlowRef};
use fnv::FnvHasher;
use gfx::display_list::{ClippingRegion, DisplayList, LayerInfo, OpaqueNode, StackingContext};
use gfx::display_list::{ClippingRegion, DisplayList, LayerInfo};
use gfx::display_list::{OpaqueNode, StackingContext, StackingContextId, StackingContextType};
use gfx::font;
use gfx::font_cache_thread::FontCacheThread;
use gfx::font_context;
use gfx::paint_thread::{LayoutToPaintMsg, PaintLayer};
use gfx::paint_thread::LayoutToPaintMsg;
use gfx_traits::{color, Epoch, LayerId, ScrollPolicy};
use heapsize::HeapSizeOf;
use incremental::{LayoutDamageComputation, REFLOW, REFLOW_ENTIRE_DOCUMENT, REPAINT};
@ -81,7 +82,7 @@ use util::opts;
use util::thread;
use util::thread_state;
use util::workqueue::WorkQueue;
use webrender_helpers::WebRenderStackingContextConverter;
use webrender_helpers::WebRenderDisplayListConverter;
use webrender_traits;
use wrapper::{LayoutNode, NonOpaqueStyleAndLayoutData, ServoLayoutNode, ThreadSafeLayoutNode};
@ -99,7 +100,7 @@ pub struct LayoutThreadData {
pub constellation_chan: ConstellationChan<ConstellationMsg>,
/// The root stacking context.
pub stacking_context: Option<Arc<StackingContext>>,
pub display_list: Option<Arc<DisplayList>>,
/// Performs CSS selector matching and style resolution.
pub stylist: Box<Stylist>,
@ -452,7 +453,7 @@ impl LayoutThread {
rw_data: Arc::new(Mutex::new(
LayoutThreadData {
constellation_chan: constellation_chan,
stacking_context: None,
display_list: None,
stylist: stylist,
content_box_response: Rect::zero(),
content_boxes_response: Vec::new(),
@ -671,12 +672,12 @@ impl LayoutThread {
// FIXME(njn): Just measuring the display tree for now.
let rw_data = possibly_locked_rw_data.lock();
let stacking_context = rw_data.stacking_context.as_ref();
let display_list = rw_data.display_list.as_ref();
let formatted_url = &format!("url({})", *self.url.borrow());
reports.push(Report {
path: path![formatted_url, "layout-thread", "display-list"],
kind: ReportKind::ExplicitJemallocHeapSize,
size: stacking_context.map_or(0, |sc| sc.heap_size_of_children()),
size: display_list.map_or(0, |sc| sc.heap_size_of_children()),
});
// The LayoutThread has a context in TLS...
@ -860,7 +861,23 @@ impl LayoutThread {
flow::mut_base(flow_ref::deref_mut(layout_root)).clip =
ClippingRegion::from_rect(&data.page_clip_rect);
sequential::build_display_list_for_subtree(layout_root, shared_layout_context);
let mut root_stacking_context =
StackingContext::new(StackingContextId::new(0),
StackingContextType::Real,
&Rect::zero(),
&Rect::zero(),
0,
filter::T::new(Vec::new()),
mix_blend_mode::T::normal,
Matrix4::identity(),
Matrix4::identity(),
true,
false,
None);
sequential::build_display_list_for_subtree(layout_root,
&mut root_stacking_context,
shared_layout_context);
if data.goal == ReflowGoal::ForDisplay {
debug!("Done building display list.");
@ -875,37 +892,28 @@ impl LayoutThread {
root_flow.overflow.scroll.size
}
};
let mut display_list = box DisplayList::new();
display_list.append_from(&mut flow::mut_base(flow_ref::deref_mut(layout_root))
.display_list_building_result);
let origin = Rect::new(Point2D::new(Au(0), Au(0)), root_size);
let stacking_context = Arc::new(StackingContext::new(display_list,
&origin,
&origin,
0,
filter::T::new(Vec::new()),
mix_blend_mode::T::normal,
Matrix4::identity(),
Matrix4::identity(),
true,
false,
None));
root_stacking_context.bounds = origin;
root_stacking_context.overflow = origin;
root_stacking_context.layer_info = Some(LayerInfo::new(layout_root.layer_id(),
ScrollPolicy::Scrollable,
None,
root_background_color));
let display_list = DisplayList::new(
root_stacking_context,
&mut flow::mut_base(flow_ref::deref_mut(layout_root))
.display_list_building_result);
if opts::get().dump_display_list {
stacking_context.print("DisplayList".to_owned());
display_list.print();
}
if opts::get().dump_display_list_json {
println!("{}", serde_json::to_string_pretty(&stacking_context).unwrap());
println!("{}", serde_json::to_string_pretty(&display_list).unwrap());
}
rw_data.stacking_context = Some(stacking_context.clone());
let layer_info = LayerInfo::new(layout_root.layer_id(),
ScrollPolicy::Scrollable,
None);
let paint_layer = PaintLayer::new_with_stacking_context(layer_info,
stacking_context,
root_background_color);
let display_list = Arc::new(display_list);
rw_data.display_list = Some(display_list.clone());
debug!("Layout done!");
@ -920,12 +928,12 @@ impl LayoutThread {
// TODO(gw) For now only create a root scrolling layer!
let root_scroll_layer_id = webrender_traits::ScrollLayerId::new(pipeline_id, 0);
let sc_id = rw_data.stacking_context.as_ref()
.unwrap()
.convert_to_webrender(&self.webrender_api.as_ref().unwrap(),
pipeline_id,
epoch,
Some(root_scroll_layer_id));
let sc_id = rw_data.display_list.as_ref()
.unwrap()
.convert_to_webrender(&self.webrender_api.as_ref().unwrap(),
pipeline_id,
epoch,
Some(root_scroll_layer_id));
let root_background_color = webrender_traits::ColorF::new(root_background_color.r,
root_background_color.g,
root_background_color.b,
@ -941,7 +949,7 @@ impl LayoutThread {
viewport_size);
} else {
self.paint_chan
.send(LayoutToPaintMsg::PaintInit(self.epoch, paint_layer))
.send(LayoutToPaintMsg::PaintInit(self.epoch, display_list))
.unwrap();
}
}

Просмотреть файл

@ -10,14 +10,14 @@
use app_units::Au;
use block::BlockFlow;
use context::LayoutContext;
use display_list_builder::ListItemFlowDisplayListBuilding;
use display_list_builder::{DisplayListBuildState, ListItemFlowDisplayListBuilding};
use euclid::Point2D;
use floats::FloatKind;
use flow::{Flow, FlowClass, OpaqueFlow};
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, GeneratedContentInfo};
use fragment::{Overflow};
use generated_content;
use gfx::display_list::DisplayList;
use gfx::display_list::{StackingContext, StackingContextId};
use incremental::RESOLVE_GENERATED_CONTENT;
use inline::InlineMetrics;
use std::sync::Arc;
@ -142,13 +142,20 @@ impl Flow for ListItemFlow {
self.block_flow.update_late_computed_block_position_if_necessary(block_position)
}
fn build_display_list(&mut self, layout_context: &LayoutContext) {
self.build_display_list_for_list_item(box DisplayList::new(), layout_context);
fn build_display_list(&mut self, state: &mut DisplayListBuildState) {
self.build_display_list_for_list_item(state);
if opts::get().validate_display_list_geometry {
self.block_flow.base.validate_display_list_geometry();
}
}
fn collect_stacking_contexts(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>)
-> StackingContextId {
self.block_flow.collect_stacking_contexts(parent_id, contexts)
}
fn repair_style(&mut self, new_style: &Arc<ComputedValues>) {
self.block_flow.repair_style(new_style)
}

Просмотреть файл

@ -9,11 +9,13 @@
use app_units::Au;
use block::BlockFlow;
use context::LayoutContext;
use display_list_builder::DisplayListBuildState;
use euclid::Point2D;
use floats::FloatKind;
use flow::{Flow, FlowClass, OpaqueFlow, mut_base, FragmentationContext};
use flow_ref::{self, FlowRef};
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
use gfx::display_list::{StackingContext, StackingContextId};
use std::cmp::{min, max};
use std::fmt;
use std::sync::Arc;
@ -177,9 +179,16 @@ impl Flow for MulticolFlow {
self.block_flow.update_late_computed_block_position_if_necessary(block_position)
}
fn build_display_list(&mut self, layout_context: &LayoutContext) {
fn build_display_list(&mut self, state: &mut DisplayListBuildState) {
debug!("build_display_list_multicol");
self.block_flow.build_display_list(layout_context);
self.block_flow.build_display_list(state);
}
fn collect_stacking_contexts(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>)
-> StackingContextId {
self.block_flow.collect_stacking_contexts(parent_id, contexts)
}
fn repair_style(&mut self, new_style: &Arc<ComputedValues>) {
@ -255,9 +264,16 @@ impl Flow for MulticolColumnFlow {
self.block_flow.update_late_computed_block_position_if_necessary(block_position)
}
fn build_display_list(&mut self, layout_context: &LayoutContext) {
fn build_display_list(&mut self, state: &mut DisplayListBuildState) {
debug!("build_display_list_multicol column");
self.block_flow.build_display_list(layout_context);
self.block_flow.build_display_list(state);
}
fn collect_stacking_contexts(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>)
-> StackingContextId {
self.block_flow.collect_stacking_contexts(parent_id, contexts)
}
fn repair_style(&mut self, new_style: &Arc<ComputedValues>) {

Просмотреть файл

@ -11,7 +11,7 @@ use euclid::rect::Rect;
use flow;
use flow_ref::FlowRef;
use fragment::{Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo};
use gfx::display_list::{DisplayItemMetadata, OpaqueNode};
use gfx::display_list::OpaqueNode;
use layout_thread::LayoutThreadData;
use msg::constellation_msg::ConstellationChan;
use opaque_node::OpaqueNodeMethods;
@ -69,51 +69,40 @@ impl LayoutRPC for LayoutRPCImpl {
/// Requests the node containing the point of interest.
fn hit_test(&self, point: Point2D<f32>) -> Result<HitTestResponse, ()> {
let point = Point2D::new(Au::from_f32_px(point.x), Au::from_f32_px(point.y));
let resp = {
let &LayoutRPCImpl(ref rw_data) = self;
let rw_data = rw_data.lock().unwrap();
match rw_data.stacking_context {
None => panic!("no root stacking context!"),
Some(ref stacking_context) => {
let mut result = Vec::new();
stacking_context.hit_test(point, &mut result, true);
if !result.is_empty() {
Some(HitTestResponse(result[0].node.to_untrusted_node_address()))
} else {
None
}
}
}
let &LayoutRPCImpl(ref rw_data) = self;
let rw_data = rw_data.lock().unwrap();
let result = match rw_data.display_list {
None => panic!("Tried to hit test without a DisplayList"),
Some(ref display_list) => display_list.hit_test(point),
};
if resp.is_some() {
return Ok(resp.unwrap());
if result.is_empty() {
return Err(());
}
Err(())
Ok(HitTestResponse(result[0].node.to_untrusted_node_address()))
}
fn mouse_over(&self, point: Point2D<f32>) -> Result<MouseOverResponse, ()> {
let mut mouse_over_list: Vec<DisplayItemMetadata> = vec!();
let point = Point2D::new(Au::from_f32_px(point.x), Au::from_f32_px(point.y));
{
let mouse_over_list = {
let &LayoutRPCImpl(ref rw_data) = self;
let rw_data = rw_data.lock().unwrap();
match rw_data.stacking_context {
None => panic!("no root stacking context!"),
Some(ref stacking_context) => {
stacking_context.hit_test(point, &mut mouse_over_list, false);
}
}
let result = match rw_data.display_list {
None => panic!("Tried to hit test without a DisplayList"),
Some(ref display_list) => display_list.hit_test(point),
};
// Compute the new cursor.
let cursor = if !mouse_over_list.is_empty() {
mouse_over_list[0].pointing.unwrap()
let cursor = if !result.is_empty() {
result[0].pointing.unwrap()
} else {
Cursor::DefaultCursor
};
let ConstellationChan(ref constellation_chan) = rw_data.constellation_chan;
constellation_chan.send(ConstellationMsg::SetCursor(cursor)).unwrap();
}
result
};
if mouse_over_list.is_empty() {
Err(())

Просмотреть файл

@ -12,6 +12,7 @@ use flow::{self, Flow, ImmutableFlowUtils, InorderFlowTraversal, MutableFlowUtil
use flow_ref::{self, FlowRef};
use fragment::FragmentBorderBoxIterator;
use generated_content::ResolveGeneratedContent;
use gfx::display_list::StackingContext;
use style::dom::TNode;
use style::traversal::DomTraversalContext;
use traversal::{AssignBSizesAndStoreOverflow, AssignISizes};
@ -75,28 +76,14 @@ pub fn traverse_flow_tree_preorder(root: &mut FlowRef,
}
pub fn build_display_list_for_subtree(root: &mut FlowRef,
root_stacking_context: &mut StackingContext,
shared_layout_context: &SharedLayoutContext) {
fn doit(flow: &mut Flow,
compute_absolute_positions: ComputeAbsolutePositions,
build_display_list: BuildDisplayList) {
if compute_absolute_positions.should_process(flow) {
compute_absolute_positions.process(flow);
}
for kid in flow::mut_base(flow).child_iter() {
doit(kid, compute_absolute_positions, build_display_list);
}
if build_display_list.should_process(flow) {
build_display_list.process(flow);
}
}
let flow_root = flow_ref::deref_mut(root);
let layout_context = LayoutContext::new(shared_layout_context);
let compute_absolute_positions = ComputeAbsolutePositions { layout_context: &layout_context };
let build_display_list = BuildDisplayList { layout_context: &layout_context };
doit(flow_ref::deref_mut(root), compute_absolute_positions, build_display_list);
flow_root.traverse_preorder(&ComputeAbsolutePositions { layout_context: &layout_context });
flow_root.collect_stacking_contexts(root_stacking_context.id,
&mut root_stacking_context.children);
flow_root.traverse_postorder(&BuildDisplayList { layout_context: &layout_context });
}
pub fn iterate_through_flow_tree_fragment_border_boxes(root: &mut FlowRef,

Просмотреть файл

@ -10,13 +10,13 @@ use app_units::Au;
use block::{BlockFlow, CandidateBSizeIterator, ISizeAndMarginsComputer};
use block::{ISizeConstraintInput, ISizeConstraintSolution};
use context::LayoutContext;
use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode};
use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode, DisplayListBuildState};
use euclid::Point2D;
use flow::{BaseFlow, IMPACTED_BY_RIGHT_FLOATS, ImmutableFlowUtils, OpaqueFlow};
use flow::{self, EarlyAbsolutePositionInfo, Flow, FlowClass, IMPACTED_BY_LEFT_FLOATS};
use flow_list::MutFlowListIterator;
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
use gfx::display_list::DisplayList;
use gfx::display_list::{StackingContext, StackingContextId};
use incremental::{REFLOW, REFLOW_OUT_OF_FLOW};
use layout_debug;
use model::{IntrinsicISizes, IntrinsicISizesContribution, MaybeAuto};
@ -452,7 +452,7 @@ impl Flow for TableFlow {
self.block_flow.update_late_computed_block_position_if_necessary(block_position)
}
fn build_display_list(&mut self, layout_context: &LayoutContext) {
fn build_display_list(&mut self, state: &mut DisplayListBuildState) {
let border_painting_mode = match self.block_flow
.fragment
.style
@ -462,9 +462,14 @@ impl Flow for TableFlow {
border_collapse::T::collapse => BorderPaintingMode::Hidden,
};
self.block_flow.build_display_list_for_block(box DisplayList::new(),
layout_context,
border_painting_mode);
self.block_flow.build_display_list_for_block(state, border_painting_mode);
}
fn collect_stacking_contexts(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>)
-> StackingContextId {
self.block_flow.collect_stacking_contexts(parent_id, contexts)
}
fn repair_style(&mut self, new_style: &Arc<ComputedValues>) {

Просмотреть файл

@ -9,9 +9,11 @@
use app_units::Au;
use block::BlockFlow;
use context::LayoutContext;
use display_list_builder::DisplayListBuildState;
use euclid::Point2D;
use flow::{Flow, FlowClass, OpaqueFlow};
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
use gfx::display_list::{StackingContext, StackingContextId};
use std::fmt;
use std::sync::Arc;
use style::logical_geometry::LogicalSize;
@ -74,9 +76,16 @@ impl Flow for TableCaptionFlow {
self.block_flow.update_late_computed_block_position_if_necessary(block_position)
}
fn build_display_list(&mut self, layout_context: &LayoutContext) {
fn build_display_list(&mut self, state: &mut DisplayListBuildState) {
debug!("build_display_list_table_caption: same process as block flow");
self.block_flow.build_display_list(layout_context)
self.block_flow.build_display_list(state);
}
fn collect_stacking_contexts(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>)
-> StackingContextId {
self.block_flow.collect_stacking_contexts(parent_id, contexts)
}
fn repair_style(&mut self, new_style: &Arc<ComputedValues>) {

Просмотреть файл

@ -10,11 +10,11 @@ use app_units::Au;
use block::{BlockFlow, ISizeAndMarginsComputer, MarginsMayCollapseFlag};
use context::LayoutContext;
use cssparser::Color;
use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode};
use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode, DisplayListBuildState};
use euclid::{Point2D, Rect, SideOffsets2D, Size2D};
use flow::{Flow, FlowClass, OpaqueFlow};
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
use gfx::display_list::DisplayList;
use gfx::display_list::{StackingContext, StackingContextId};
use layout_debug;
use model::MaybeAuto;
use std::fmt;
@ -174,7 +174,7 @@ impl Flow for TableCellFlow {
self.block_flow.update_late_computed_block_position_if_necessary(block_position)
}
fn build_display_list(&mut self, layout_context: &LayoutContext) {
fn build_display_list(&mut self, state: &mut DisplayListBuildState) {
if !self.visible {
return
}
@ -188,9 +188,14 @@ impl Flow for TableCellFlow {
border_collapse::T::collapse => BorderPaintingMode::Collapse(&self.collapsed_borders),
};
self.block_flow.build_display_list_for_block(box DisplayList::new(),
layout_context,
border_painting_mode)
self.block_flow.build_display_list_for_block(state, border_painting_mode)
}
fn collect_stacking_contexts(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>)
-> StackingContextId {
self.block_flow.collect_stacking_contexts(parent_id, contexts)
}
fn repair_style(&mut self, new_style: &Arc<ComputedValues>) {

Просмотреть файл

@ -8,9 +8,11 @@
use app_units::Au;
use context::LayoutContext;
use display_list_builder::DisplayListBuildState;
use euclid::Point2D;
use flow::{BaseFlow, Flow, FlowClass, ForceNonfloatedFlag, OpaqueFlow};
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow, SpecificFragmentInfo};
use gfx::display_list::{StackingContext, StackingContextId};
use layout_debug;
use std::cmp::max;
use std::fmt;
@ -90,7 +92,14 @@ impl Flow for TableColGroupFlow {
fn update_late_computed_block_position_if_necessary(&mut self, _: Au) {}
// Table columns are invisible.
fn build_display_list(&mut self, _: &LayoutContext) {}
fn build_display_list(&mut self, _: &mut DisplayListBuildState) { }
fn collect_stacking_contexts(&mut self,
parent_id: StackingContextId,
_: &mut Vec<StackingContext>)
-> StackingContextId {
parent_id
}
fn repair_style(&mut self, _: &Arc<ComputedValues>) {}

Просмотреть файл

@ -10,12 +10,12 @@ use app_units::Au;
use block::{BlockFlow, ISizeAndMarginsComputer};
use context::LayoutContext;
use cssparser::{Color, RGBA};
use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode};
use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode, DisplayListBuildState};
use euclid::Point2D;
use flow::{self, EarlyAbsolutePositionInfo, Flow, FlowClass, ImmutableFlowUtils, OpaqueFlow};
use flow_list::MutFlowListIterator;
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
use gfx::display_list::DisplayList;
use gfx::display_list::{StackingContext, StackingContextId};
use layout_debug;
use model::MaybeAuto;
use rustc_serialize::{Encodable, Encoder};
@ -420,7 +420,7 @@ impl Flow for TableRowFlow {
self.block_flow.update_late_computed_block_position_if_necessary(block_position)
}
fn build_display_list(&mut self, layout_context: &LayoutContext) {
fn build_display_list(&mut self, state: &mut DisplayListBuildState) {
let border_painting_mode = match self.block_flow
.fragment
.style
@ -430,9 +430,14 @@ impl Flow for TableRowFlow {
border_collapse::T::collapse => BorderPaintingMode::Hidden,
};
self.block_flow.build_display_list_for_block(box DisplayList::new(),
layout_context,
border_painting_mode);
self.block_flow.build_display_list_for_block(state, border_painting_mode);
}
fn collect_stacking_contexts(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>)
-> StackingContextId {
self.block_flow.collect_stacking_contexts(parent_id, contexts)
}
fn repair_style(&mut self, new_style: &Arc<ComputedValues>) {

Просмотреть файл

@ -9,9 +9,11 @@
use app_units::Au;
use block::{BlockFlow, ISizeAndMarginsComputer};
use context::LayoutContext;
use display_list_builder::DisplayListBuildState;
use euclid::Point2D;
use flow::{Flow, FlowClass, OpaqueFlow};
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
use gfx::display_list::{StackingContext, StackingContextId};
use layout_debug;
use rustc_serialize::{Encodable, Encoder};
use std::fmt;
@ -203,9 +205,16 @@ impl Flow for TableRowGroupFlow {
self.block_flow.update_late_computed_block_position_if_necessary(block_position)
}
fn build_display_list(&mut self, layout_context: &LayoutContext) {
fn build_display_list(&mut self, state: &mut DisplayListBuildState) {
debug!("build_display_list_table_rowgroup: same process as block flow");
self.block_flow.build_display_list(layout_context)
self.block_flow.build_display_list(state);
}
fn collect_stacking_contexts(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>)
-> StackingContextId {
self.block_flow.collect_stacking_contexts(parent_id, contexts)
}
fn repair_style(&mut self, new_style: &Arc<ComputedValues>) {

Просмотреть файл

@ -17,11 +17,13 @@ use app_units::Au;
use block::{AbsoluteNonReplaced, BlockFlow, FloatNonReplaced, ISizeAndMarginsComputer, ISizeConstraintInput};
use block::{ISizeConstraintSolution, MarginsMayCollapseFlag};
use context::LayoutContext;
use display_list_builder::DisplayListBuildState;
use euclid::Point2D;
use floats::FloatKind;
use flow::{Flow, FlowClass, ImmutableFlowUtils};
use flow::{IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS, INLINE_POSITION_IS_STATIC, OpaqueFlow};
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
use gfx::display_list::{StackingContext, StackingContextId};
use model::MaybeAuto;
use std::cmp::{max, min};
use std::fmt;
@ -443,8 +445,15 @@ impl Flow for TableWrapperFlow {
self.block_flow.generated_containing_block_size(flow)
}
fn build_display_list(&mut self, layout_context: &LayoutContext) {
self.block_flow.build_display_list(layout_context)
fn build_display_list(&mut self, state: &mut DisplayListBuildState) {
self.block_flow.build_display_list(state);
}
fn collect_stacking_contexts(&mut self,
parent_id: StackingContextId,
contexts: &mut Vec<StackingContext>)
-> StackingContextId {
self.block_flow.collect_stacking_contexts(parent_id, contexts)
}
fn repair_style(&mut self, new_style: &Arc<ComputedValues>) {

Просмотреть файл

@ -9,6 +9,7 @@
use construct::FlowConstructor;
use context::{LayoutContext, SharedLayoutContext};
use display_list_builder::DisplayListBuildState;
use flow::{PostorderFlowTraversal, PreorderFlowTraversal};
use flow::{self, Flow, CAN_BE_FRAGMENTED};
use gfx::display_list::OpaqueNode;
@ -222,7 +223,10 @@ pub struct BuildDisplayList<'a> {
impl<'a> PostorderFlowTraversal for BuildDisplayList<'a> {
#[inline]
fn process(&self, flow: &mut Flow) {
flow.build_display_list(self.layout_context);
let mut state = DisplayListBuildState::new(
self.layout_context, flow::base(flow).stacking_context_id);
flow.build_display_list(&mut state);
flow::mut_base(flow).display_list_building_result = Some(state.items);
flow::mut_base(flow).restyle_damage.remove(REPAINT);
}

Просмотреть файл

@ -12,8 +12,8 @@ use azure::azure_hl::Color;
use euclid::num::Zero;
use euclid::{Point2D, Rect, Size2D};
use gfx::display_list::{BorderRadii, BoxShadowClipMode, ClippingRegion};
use gfx::display_list::{DisplayItem, DisplayList};
use gfx::display_list::{GradientStop, StackingContext};
use gfx::display_list::{DisplayItem, DisplayList, DisplayListEntry, DisplayListSection};
use gfx::display_list::{DisplayListTraversal, GradientStop, StackingContext, StackingContextType};
use gfx_traits::ScrollPolicy;
use msg::constellation_msg::ConvertPipelineIdToWebRender;
use style::computed_values::filter::{self, Filter};
@ -21,31 +21,59 @@ use style::computed_values::{image_rendering, mix_blend_mode};
use style::values::computed::BorderStyle;
use webrender_traits;
pub trait WebRenderStackingContextConverter {
trait WebRenderStackingContextConverter {
fn convert_to_webrender<'a>(&self,
traversal: &mut DisplayListTraversal<'a>,
api: &webrender_traits::RenderApi,
pipeline_id: webrender_traits::PipelineId,
epoch: webrender_traits::Epoch,
scroll_layer_id: Option<webrender_traits::ScrollLayerId>)
-> webrender_traits::StackingContextId;
fn convert_children_to_webrender<'a>(&self,
traversal: &mut DisplayListTraversal<'a>,
api: &webrender_traits::RenderApi,
pipeline_id: webrender_traits::PipelineId,
epoch: webrender_traits::Epoch,
scroll_layer_id: Option<webrender_traits::ScrollLayerId>,
builder: &mut webrender_traits::DisplayListBuilder,
force_positioned_stacking_level: bool);
fn web_render_stacking_level(&self) -> webrender_traits::StackingLevel;
}
pub trait WebRenderDisplayListConverter {
fn convert_to_webrender(&self,
api: &webrender_traits::RenderApi,
pipeline_id: webrender_traits::PipelineId,
epoch: webrender_traits::Epoch,
scroll_layer_id: Option<webrender_traits::ScrollLayerId>)
-> webrender_traits::StackingContextId;
}
trait WebRenderDisplayListConverter {
fn convert_to_webrender(&self,
api: &webrender_traits::RenderApi,
pipeline_id: webrender_traits::PipelineId,
epoch: webrender_traits::Epoch) -> webrender_traits::DisplayListBuilder;
-> webrender_traits::StackingContextId;
}
trait WebRenderDisplayItemConverter {
fn convert_to_webrender(&self,
api: &webrender_traits::RenderApi,
pipeline_id: webrender_traits::PipelineId,
epoch: webrender_traits::Epoch,
level: webrender_traits::StackingLevel,
builder: &mut webrender_traits::DisplayListBuilder);
}
trait WebRenderDisplayListEntryConverter {
fn web_render_stacking_level(&self) -> webrender_traits::StackingLevel;
}
impl WebRenderDisplayListEntryConverter for DisplayListEntry {
fn web_render_stacking_level(&self) -> webrender_traits::StackingLevel {
match self.section {
DisplayListSection::BackgroundAndBorders =>
webrender_traits::StackingLevel::BackgroundAndBorders,
DisplayListSection::BlockBackgroundsAndBorders =>
webrender_traits::StackingLevel::BlockBackgroundAndBorders,
DisplayListSection::Content => webrender_traits::StackingLevel::Content,
DisplayListSection::Outlines => webrender_traits::StackingLevel::Outlines,
}
}
}
trait ToBorderStyle {
fn to_border_style(&self) -> webrender_traits::BorderStyle;
}
@ -235,11 +263,55 @@ impl ToFilterOps for filter::T {
}
impl WebRenderStackingContextConverter for StackingContext {
fn convert_to_webrender(&self,
api: &webrender_traits::RenderApi,
pipeline_id: webrender_traits::PipelineId,
epoch: webrender_traits::Epoch,
scroll_layer_id: Option<webrender_traits::ScrollLayerId>)
fn convert_children_to_webrender<'a>(&self,
traversal: &mut DisplayListTraversal<'a>,
api: &webrender_traits::RenderApi,
pipeline_id: webrender_traits::PipelineId,
epoch: webrender_traits::Epoch,
scroll_layer_id: Option<webrender_traits::ScrollLayerId>,
builder: &mut webrender_traits::DisplayListBuilder,
force_positioned_stacking_level: bool) {
for child in self.children.iter() {
while let Some(item) = traversal.advance(self) {
let stacking_level = if force_positioned_stacking_level {
webrender_traits::StackingLevel::PositionedContent
} else {
item.web_render_stacking_level()
};
item.item.convert_to_webrender(stacking_level, builder);
}
if child.context_type == StackingContextType::Real {
let stacking_context_id = child.convert_to_webrender(traversal,
api,
pipeline_id,
epoch,
None);
builder.push_stacking_context(child.web_render_stacking_level(),
stacking_context_id);
} else {
child.convert_children_to_webrender(traversal,
api,
pipeline_id,
epoch,
scroll_layer_id,
builder,
true);
}
}
while let Some(item) = traversal.advance(self) {
item.item.convert_to_webrender(webrender_traits::StackingLevel::PositionedContent,
builder);
}
}
fn convert_to_webrender<'a>(&self,
traversal: &mut DisplayListTraversal<'a>,
api: &webrender_traits::RenderApi,
pipeline_id: webrender_traits::PipelineId,
epoch: webrender_traits::Epoch,
scroll_layer_id: Option<webrender_traits::ScrollLayerId>)
-> webrender_traits::StackingContextId {
let scroll_policy = self.layer_info
.map_or(webrender_traits::ScrollPolicy::Scrollable, |info| {
@ -259,80 +331,50 @@ impl WebRenderStackingContextConverter for StackingContext {
self.establishes_3d_context,
self.blend_mode.to_blend_mode(),
self.filters.to_filter_ops());
let dl_builder = self.display_list.convert_to_webrender(api,
pipeline_id,
epoch);
api.add_display_list(dl_builder, &mut sc, pipeline_id, epoch);
let mut builder = webrender_traits::DisplayListBuilder::new();
self.convert_children_to_webrender(traversal,
api,
pipeline_id,
epoch,
scroll_layer_id,
&mut builder,
false);
api.add_display_list(builder, &mut sc, pipeline_id, epoch);
api.add_stacking_context(sc, pipeline_id, epoch)
}
fn web_render_stacking_level(&self) -> webrender_traits::StackingLevel {
match self.context_type {
StackingContextType::Real | StackingContextType::PseudoPositioned =>
webrender_traits::StackingLevel::PositionedContent,
StackingContextType::PseudoFloat => webrender_traits::StackingLevel::Floats,
}
}
}
impl WebRenderDisplayListConverter for Box<DisplayList> {
impl WebRenderDisplayListConverter for DisplayList {
fn convert_to_webrender(&self,
api: &webrender_traits::RenderApi,
pipeline_id: webrender_traits::PipelineId,
epoch: webrender_traits::Epoch) -> webrender_traits::DisplayListBuilder {
let mut builder = webrender_traits::DisplayListBuilder::new();
epoch: webrender_traits::Epoch,
scroll_layer_id: Option<webrender_traits::ScrollLayerId>)
-> webrender_traits::StackingContextId {
let mut traversal = DisplayListTraversal {
display_list: self,
current_item_index: 0,
last_item_index: self.list.len() - 1,
};
for item in &self.background_and_borders {
item.convert_to_webrender(api,
pipeline_id,
epoch,
webrender_traits::StackingLevel::BackgroundAndBorders,
&mut builder);
}
for item in &self.block_backgrounds_and_borders {
item.convert_to_webrender(api,
pipeline_id,
epoch,
webrender_traits::StackingLevel::BlockBackgroundAndBorders,
&mut builder);
}
for item in &self.floats {
item.convert_to_webrender(api,
pipeline_id,
epoch,
webrender_traits::StackingLevel::Floats,
&mut builder);
}
for item in &self.content {
item.convert_to_webrender(api,
pipeline_id,
epoch,
webrender_traits::StackingLevel::Content,
&mut builder);
}
for item in &self.positioned_content {
item.convert_to_webrender(api,
pipeline_id,
epoch,
webrender_traits::StackingLevel::PositionedContent,
&mut builder);
}
for item in &self.outlines {
item.convert_to_webrender(api,
pipeline_id,
epoch,
webrender_traits::StackingLevel::Outlines,
&mut builder);
}
builder
self.root_stacking_context.convert_to_webrender(&mut traversal,
api,
pipeline_id,
epoch,
scroll_layer_id)
}
}
impl WebRenderDisplayItemConverter for DisplayItem {
fn convert_to_webrender(&self,
api: &webrender_traits::RenderApi,
pipeline_id: webrender_traits::PipelineId,
epoch: webrender_traits::Epoch,
level: webrender_traits::StackingLevel,
builder: &mut webrender_traits::DisplayListBuilder) {
match *self {
@ -469,13 +511,6 @@ impl WebRenderDisplayItemConverter for DisplayItem {
item.base.clip.to_clip_region(),
pipeline_id);
}
DisplayItem::StackingContextClass(ref item) => {
let stacking_context_id = item.convert_to_webrender(api,
pipeline_id,
epoch,
None);
builder.push_stacking_context(level, stacking_context_id);
}
}
}
}

Просмотреть файл

@ -58,6 +58,7 @@ impl Formattable for ProfilerCategory {
ProfilerCategory::LayoutRestyleDamagePropagation |
ProfilerCategory::LayoutNonIncrementalReset |
ProfilerCategory::LayoutGeneratedContent |
ProfilerCategory::LayoutDisplayListSorting |
ProfilerCategory::LayoutMain |
ProfilerCategory::LayoutDispListBuild |
ProfilerCategory::LayoutDamagePropagate |
@ -79,6 +80,7 @@ impl Formattable for ProfilerCategory {
ProfilerCategory::LayoutSelectorMatch => "Selector Matching",
ProfilerCategory::LayoutTreeBuilder => "Tree Building",
ProfilerCategory::LayoutDamagePropagate => "Damage Propagation",
ProfilerCategory::LayoutDisplayListSorting => "Sorting Display List",
ProfilerCategory::LayoutGeneratedContent => "Generated Content Resolution",
ProfilerCategory::LayoutMain => "Primary Layout Pass",
ProfilerCategory::LayoutParallelWarmup => "Parallel Warmup",

Просмотреть файл

@ -48,6 +48,7 @@ pub enum ProfilerCategory {
LayoutTreeBuilder,
LayoutDamagePropagate,
LayoutGeneratedContent,
LayoutDisplayListSorting,
LayoutMain,
LayoutParallelWarmup,
LayoutDispListBuild,

Просмотреть файл

@ -57,3 +57,9 @@ impl PrintTree {
}
}
}
impl Drop for PrintTree {
fn drop(&mut self) {
self.flush_queued_item("└─");
}
}