auto merge of #1579 : ibnc/servo/multiple_display_lists, r=larsbergstrom

Fixes: #1538

Still needs to be rebased.
This commit is contained in:
bors-servo 2014-01-30 15:22:33 -08:00
commit 9352e1db00
7 changed files with 172 additions and 103 deletions

View file

@ -27,11 +27,62 @@ use std::cast::transmute_region;
use std::vec::VecIterator; use std::vec::VecIterator;
use style::computed_values::border_style; use style::computed_values::border_style;
pub struct DisplayListCollection<E> {
lists: ~[DisplayList<E>]
}
impl<E> DisplayListCollection<E> {
pub fn new() -> DisplayListCollection<E> {
DisplayListCollection {
lists: ~[]
}
}
pub fn iter<'a>(&'a self) -> DisplayListIterator<'a,E> {
ParentDisplayListIterator(self.lists.iter())
}
pub fn add_list(&mut self, list: DisplayList<E>) {
self.lists.push(list);
}
pub fn draw_lists_into_context(&self, render_context: &mut RenderContext) {
for list in self.lists.iter() {
list.draw_into_context(render_context);
}
debug!("{:?}", self.dump());
}
fn dump(&self) {
let mut index = 0;
for list in self.lists.iter() {
debug!("dumping display list {:d}:", index);
list.dump();
index = index + 1;
}
}
}
/// A list of rendering operations to be performed. /// A list of rendering operations to be performed.
pub struct DisplayList<E> { pub struct DisplayList<E> {
list: ~[DisplayItem<E>] list: ~[DisplayItem<E>]
} }
pub enum DisplayListIterator<'a,E> {
EmptyDisplayListIterator,
ParentDisplayListIterator(VecIterator<'a,DisplayList<E>>),
}
impl<'a,E> Iterator<&'a DisplayList<E>> for DisplayListIterator<'a,E> {
#[inline]
fn next(&mut self) -> Option<&'a DisplayList<E>> {
match *self {
EmptyDisplayListIterator => None,
ParentDisplayListIterator(ref mut subiterator) => subiterator.next(),
}
}
}
impl<E> DisplayList<E> { impl<E> DisplayList<E> {
/// Creates a new display list. /// Creates a new display list.
pub fn new() -> DisplayList<E> { pub fn new() -> DisplayList<E> {
@ -62,7 +113,6 @@ impl<E> DisplayList<E> {
item.draw_into_context(render_context) item.draw_into_context(render_context)
} }
debug!("Ending display list."); debug!("Ending display list.");
debug!("{:?}", self.dump());
} }
/// Returns a preorder iterator over the given display list. /// Returns a preorder iterator over the given display list.

View file

@ -24,13 +24,14 @@ use std::comm::{Chan, Port, SharedChan};
use extra::arc::Arc; use extra::arc::Arc;
use buffer_map::BufferMap; use buffer_map::BufferMap;
use display_list::DisplayList; use font_context::{FontContext, FontContextInfo};
use display_list::DisplayListCollection;
use font_context::{FontContext, FontContextInfo}; use font_context::{FontContext, FontContextInfo};
use opts::Opts; use opts::Opts;
use render_context::RenderContext; use render_context::RenderContext;
pub struct RenderLayer<T> { pub struct RenderLayer<T> {
display_list: Arc<DisplayList<T>>, display_list_collection: Arc<DisplayListCollection<T>>,
size: Size2D<uint>, size: Size2D<uint>,
color: Color color: Color
} }
@ -305,7 +306,7 @@ impl<C: RenderListener + Send,T:Send+Freeze> RenderTask<C,T> {
// Draw the display list. // Draw the display list.
profile(time::RenderingDrawingCategory, self.profiler_chan.clone(), || { profile(time::RenderingDrawingCategory, self.profiler_chan.clone(), || {
render_layer.display_list.get().draw_into_context(&mut ctx); render_layer.display_list_collection.get().draw_lists_into_context(&mut ctx);
ctx.draw_target.flush(); ctx.draw_target.flush();
}); });
} }

View file

@ -14,7 +14,7 @@ use layout::float_context::{FloatContext, PlacementInfo, Invalid, FloatType};
use std::cell::RefCell; use std::cell::RefCell;
use geom::{Point2D, Rect, SideOffsets2D}; use geom::{Point2D, Rect, SideOffsets2D};
use gfx::display_list::DisplayList; use gfx::display_list::{DisplayList, DisplayListCollection};
use servo_util::geometry::Au; use servo_util::geometry::Au;
use servo_util::geometry; use servo_util::geometry;
@ -496,22 +496,31 @@ impl BlockFlow {
&mut self, &mut self,
builder: &DisplayListBuilder, builder: &DisplayListBuilder,
dirty: &Rect<Au>, dirty: &Rect<Au>,
list: &RefCell<DisplayList<E>>) mut index: uint,
-> bool { lists: &RefCell<DisplayListCollection<E>>)
-> uint {
if self.is_float() { if self.is_float() {
return self.build_display_list_float(builder, dirty, list); self.build_display_list_float(builder, dirty, index, lists);
return index;
}
if self.is_fixed {
lists.with_mut(|lists| {
index = lists.lists.len();
lists.add_list(DisplayList::<E>::new());
});
} }
let abs_rect = Rect(self.base.abs_position, self.base.position.size); let abs_rect = Rect(self.base.abs_position, self.base.position.size);
if !abs_rect.intersects(dirty) { if !abs_rect.intersects(dirty) {
return true; return index;
} }
debug!("build_display_list_block: adding display element"); debug!("build_display_list_block: adding display element");
// add box that starts block context // add box that starts block context
for box_ in self.box_.iter() { for box_ in self.box_.iter() {
box_.build_display_list(builder, dirty, self.base.abs_position, (&*self) as &Flow, list) box_.build_display_list(builder, dirty, self.base.abs_position, (&*self) as &Flow, index, lists);
} }
// TODO: handle any out-of-flow elements // TODO: handle any out-of-flow elements
let this_position = self.base.abs_position; let this_position = self.base.abs_position;
@ -521,24 +530,26 @@ impl BlockFlow {
child_base.abs_position = this_position + child_base.position.origin; child_base.abs_position = this_position + child_base.position.origin;
} }
false index
} }
pub fn build_display_list_float<E:ExtraDisplayListData>( pub fn build_display_list_float<E:ExtraDisplayListData>(
&mut self, &mut self,
builder: &DisplayListBuilder, builder: &DisplayListBuilder,
dirty: &Rect<Au>, dirty: &Rect<Au>,
list: &RefCell<DisplayList<E>>) index: uint,
lists: &RefCell<DisplayListCollection<E>>)
-> bool { -> bool {
let abs_rect = Rect(self.base.abs_position, self.base.position.size); let abs_rect = Rect(self.base.abs_position, self.base.position.size);
if !abs_rect.intersects(dirty) { if !abs_rect.intersects(dirty) {
return true return true;
} }
let offset = self.base.abs_position + self.float.get_ref().rel_pos; let offset = self.base.abs_position + self.float.get_ref().rel_pos;
// add box that starts block context // add box that starts block context
for box_ in self.box_.iter() { for box_ in self.box_.iter() {
box_.build_display_list(builder, dirty, offset, (&*self) as &Flow, list) box_.build_display_list(builder, dirty, offset, (&*self) as &Flow, index, lists);
} }

View file

@ -9,10 +9,10 @@ use extra::arc::{MutexArc, Arc};
use geom::{Point2D, Rect, Size2D, SideOffsets2D}; use geom::{Point2D, Rect, Size2D, SideOffsets2D};
use gfx::color::rgb; use gfx::color::rgb;
use gfx::display_list::{BaseDisplayItem, BorderDisplayItem, BorderDisplayItemClass}; use gfx::display_list::{BaseDisplayItem, BorderDisplayItem, BorderDisplayItemClass};
use gfx::display_list::{DisplayList, ImageDisplayItem, ImageDisplayItemClass}; use gfx::display_list::{ImageDisplayItem, ImageDisplayItemClass};
use gfx::display_list::{SolidColorDisplayItem, SolidColorDisplayItemClass, TextDisplayItem}; use gfx::display_list::{SolidColorDisplayItem, SolidColorDisplayItemClass, TextDisplayItem};
use gfx::display_list::{TextDisplayItemClass, TextDisplayItemFlags, ClipDisplayItem}; use gfx::display_list::{TextDisplayItemClass, TextDisplayItemFlags, ClipDisplayItem};
use gfx::display_list::{ClipDisplayItemClass}; use gfx::display_list::{ClipDisplayItemClass, DisplayListCollection};
use gfx::font::FontStyle; use gfx::font::FontStyle;
use gfx::text::text_run::TextRun; use gfx::text::text_run::TextRun;
@ -757,7 +757,8 @@ impl Box {
pub fn paint_inline_background_border_if_applicable<E:ExtraDisplayListData>( pub fn paint_inline_background_border_if_applicable<E:ExtraDisplayListData>(
&self, &self,
list: &RefCell<DisplayList<E>>, index: uint,
lists: &RefCell<DisplayListCollection<E>>,
absolute_bounds: &Rect<Au>, absolute_bounds: &Rect<Au>,
offset: &Point2D<Au>) { offset: &Point2D<Au>) {
// FIXME: This causes a lot of background colors to be displayed when they are clearly not // FIXME: This causes a lot of background colors to be displayed when they are clearly not
@ -776,7 +777,7 @@ impl Box {
info.style.get().Background.background_color); info.style.get().Background.background_color);
if !background_color.alpha.approx_eq(&0.0) { if !background_color.alpha.approx_eq(&0.0) {
list.with_mut(|list| { lists.with_mut(|lists| {
let solid_color_display_item = ~SolidColorDisplayItem { let solid_color_display_item = ~SolidColorDisplayItem {
base: BaseDisplayItem { base: BaseDisplayItem {
bounds: bg_rect.clone(), bounds: bg_rect.clone(),
@ -785,7 +786,7 @@ impl Box {
color: background_color.to_gfx_color(), color: background_color.to_gfx_color(),
}; };
list.append_item(SolidColorDisplayItemClass(solid_color_display_item)) lists.lists[index].append_item(SolidColorDisplayItemClass(solid_color_display_item))
}); });
} }
let border = &info.border; let border = &info.border;
@ -807,7 +808,7 @@ impl Box {
let left_style = style.Border.border_left_style; let left_style = style.Border.border_left_style;
list.with_mut(|list| { lists.with_mut(|lists| {
let border_display_item = ~BorderDisplayItem { let border_display_item = ~BorderDisplayItem {
base: BaseDisplayItem { base: BaseDisplayItem {
bounds: bg_rect, bounds: bg_rect,
@ -824,7 +825,7 @@ impl Box {
left_style) left_style)
}; };
list.append_item(BorderDisplayItemClass(border_display_item)) lists.lists[index].append_item(BorderDisplayItemClass(border_display_item))
}); });
bg_rect.origin.x = bg_rect.origin.x + border.left; bg_rect.origin.x = bg_rect.origin.x + border.left;
@ -838,7 +839,8 @@ impl Box {
/// necessary. /// necessary.
pub fn paint_background_if_applicable<E:ExtraDisplayListData>( pub fn paint_background_if_applicable<E:ExtraDisplayListData>(
&self, &self,
list: &RefCell<DisplayList<E>>, index: uint,
lists: &RefCell<DisplayListCollection<E>>,
absolute_bounds: &Rect<Au>) { absolute_bounds: &Rect<Au>) {
// FIXME: This causes a lot of background colors to be displayed when they are clearly not // FIXME: This causes a lot of background colors to be displayed when they are clearly not
// needed. We could use display list optimization to clean this up, but it still seems // needed. We could use display list optimization to clean this up, but it still seems
@ -847,7 +849,7 @@ impl Box {
let style = self.style(); let style = self.style();
let background_color = style.resolve_color(style.Background.background_color); let background_color = style.resolve_color(style.Background.background_color);
if !background_color.alpha.approx_eq(&0.0) { if !background_color.alpha.approx_eq(&0.0) {
list.with_mut(|list| { lists.with_mut(|lists| {
let solid_color_display_item = ~SolidColorDisplayItem { let solid_color_display_item = ~SolidColorDisplayItem {
base: BaseDisplayItem { base: BaseDisplayItem {
bounds: *absolute_bounds, bounds: *absolute_bounds,
@ -856,8 +858,8 @@ impl Box {
color: background_color.to_gfx_color(), color: background_color.to_gfx_color(),
}; };
list.append_item(SolidColorDisplayItemClass(solid_color_display_item)) lists.lists[index].append_item(SolidColorDisplayItemClass(solid_color_display_item))
}) });
} }
} }
@ -865,7 +867,8 @@ impl Box {
/// necessary. /// necessary.
pub fn paint_borders_if_applicable<E:ExtraDisplayListData>( pub fn paint_borders_if_applicable<E:ExtraDisplayListData>(
&self, &self,
list: &RefCell<DisplayList<E>>, index: uint,
lists: &RefCell<DisplayListCollection<E>>,
abs_bounds: &Rect<Au>) { abs_bounds: &Rect<Au>) {
// Fast path. // Fast path.
let border = self.border.get(); let border = self.border.get();
@ -889,7 +892,7 @@ impl Box {
- self.noncontent_inline_right(); - self.noncontent_inline_right();
// Append the border to the display list. // Append the border to the display list.
list.with_mut(|list| { lists.with_mut(|lists| {
let border_display_item = ~BorderDisplayItem { let border_display_item = ~BorderDisplayItem {
base: BaseDisplayItem { base: BaseDisplayItem {
bounds: abs_bounds, bounds: abs_bounds,
@ -906,7 +909,7 @@ impl Box {
left_style) left_style)
}; };
list.append_item(BorderDisplayItemClass(border_display_item)) lists.lists[index].append_item(BorderDisplayItemClass(border_display_item))
}); });
} }
@ -930,7 +933,8 @@ impl Box {
dirty: &Rect<Au>, dirty: &Rect<Au>,
offset: Point2D<Au>, offset: Point2D<Au>,
flow: &Flow, flow: &Flow,
list: &RefCell<DisplayList<E>>) { index: uint,
lists: &RefCell<DisplayListCollection<E>>) {
let box_bounds = self.position.get(); let box_bounds = self.position.get();
let absolute_box_bounds = box_bounds.translate(&offset); let absolute_box_bounds = box_bounds.translate(&offset);
debug!("Box::build_display_list at rel={}, abs={}: {:s}", debug!("Box::build_display_list at rel={}, abs={}: {:s}",
@ -948,14 +952,14 @@ impl Box {
return; return;
} }
self.paint_inline_background_border_if_applicable(list, &absolute_box_bounds, &offset); self.paint_inline_background_border_if_applicable(index, lists, &absolute_box_bounds, &offset);
// Add the background to the list, if applicable. // Add the background to the list, if applicable.
self.paint_background_if_applicable(list, &absolute_box_bounds); self.paint_background_if_applicable(index, lists, &absolute_box_bounds);
match self.specific { match self.specific {
UnscannedTextBox(_) => fail!("Shouldn't see unscanned boxes here."), UnscannedTextBox(_) => fail!("Shouldn't see unscanned boxes here."),
ScannedTextBox(ref text_box) => { ScannedTextBox(ref text_box) => {
list.with_mut(|list| { lists.with_mut(|lists| {
let item = ~ClipDisplayItem { let item = ~ClipDisplayItem {
base: BaseDisplayItem { base: BaseDisplayItem {
bounds: absolute_box_bounds, bounds: absolute_box_bounds,
@ -964,7 +968,7 @@ impl Box {
child_list: ~[], child_list: ~[],
need_clip: false need_clip: false
}; };
list.append_item(ClipDisplayItemClass(item)); lists.lists[index].append_item(ClipDisplayItemClass(item));
}); });
let text_color = self.style().Color.color.to_gfx_color(); let text_color = self.style().Color.color.to_gfx_color();
@ -995,7 +999,7 @@ impl Box {
- self.noncontent_inline_right(); - self.noncontent_inline_right();
// Create the text box. // Create the text box.
list.with_mut(|list| { lists.with_mut(|lists| {
let text_display_item = ~TextDisplayItem { let text_display_item = ~TextDisplayItem {
base: BaseDisplayItem { base: BaseDisplayItem {
bounds: bounds, bounds: bounds,
@ -1010,7 +1014,7 @@ impl Box {
flags: text_flags, flags: text_flags,
}; };
list.append_item(TextDisplayItemClass(text_display_item)) lists.lists[index].append_item(TextDisplayItemClass(text_display_item));
}); });
// Draw debug frames for text bounds. // Draw debug frames for text bounds.
@ -1021,7 +1025,7 @@ impl Box {
// Compute the text box bounds and draw a border surrounding them. // Compute the text box bounds and draw a border surrounding them.
let debug_border = SideOffsets2D::new_all_same(Au::from_px(1)); let debug_border = SideOffsets2D::new_all_same(Au::from_px(1));
list.with_mut(|list| { lists.with_mut(|lists| {
let border_display_item = ~BorderDisplayItem { let border_display_item = ~BorderDisplayItem {
base: BaseDisplayItem { base: BaseDisplayItem {
bounds: absolute_box_bounds, bounds: absolute_box_bounds,
@ -1032,7 +1036,7 @@ impl Box {
style: SideOffsets2D::new_all_same(border_style::solid) style: SideOffsets2D::new_all_same(border_style::solid)
}; };
list.append_item(BorderDisplayItemClass(border_display_item)) lists.lists[index].append_item(BorderDisplayItemClass(border_display_item));
}); });
// Draw a rectangle representing the baselines. // Draw a rectangle representing the baselines.
@ -1043,7 +1047,7 @@ impl Box {
let baseline = Rect(absolute_box_bounds.origin + Point2D(Au(0), ascent), let baseline = Rect(absolute_box_bounds.origin + Point2D(Au(0), ascent),
Size2D(absolute_box_bounds.size.width, Au(0))); Size2D(absolute_box_bounds.size.width, Au(0)));
list.with_mut(|list| { lists.with_mut(|lists| {
let border_display_item = ~BorderDisplayItem { let border_display_item = ~BorderDisplayItem {
base: BaseDisplayItem { base: BaseDisplayItem {
bounds: baseline, bounds: baseline,
@ -1054,12 +1058,12 @@ impl Box {
style: SideOffsets2D::new_all_same(border_style::dashed) style: SideOffsets2D::new_all_same(border_style::dashed)
}; };
list.append_item(BorderDisplayItemClass(border_display_item)) lists.lists[index].append_item(BorderDisplayItemClass(border_display_item));
}); });
}); });
}, },
GenericBox | IframeBox(..) => { GenericBox | IframeBox(..) => {
list.with_mut(|list| { lists.with_mut(|lists| {
let item = ~ClipDisplayItem { let item = ~ClipDisplayItem {
base: BaseDisplayItem { base: BaseDisplayItem {
bounds: absolute_box_bounds, bounds: absolute_box_bounds,
@ -1068,7 +1072,7 @@ impl Box {
child_list: ~[], child_list: ~[],
need_clip: self.needs_clip() need_clip: self.needs_clip()
}; };
list.append_item(ClipDisplayItemClass(item)); lists.lists[index].append_item(ClipDisplayItemClass(item));
}); });
// FIXME(pcwalton): This is a bit of an abuse of the logging infrastructure. We // FIXME(pcwalton): This is a bit of an abuse of the logging infrastructure. We
@ -1076,7 +1080,7 @@ impl Box {
debug!("{:?}", { debug!("{:?}", {
let debug_border = SideOffsets2D::new_all_same(Au::from_px(1)); let debug_border = SideOffsets2D::new_all_same(Au::from_px(1));
list.with_mut(|list| { lists.with_mut(|lists| {
let border_display_item = ~BorderDisplayItem { let border_display_item = ~BorderDisplayItem {
base: BaseDisplayItem { base: BaseDisplayItem {
bounds: absolute_box_bounds, bounds: absolute_box_bounds,
@ -1087,12 +1091,12 @@ impl Box {
style: SideOffsets2D::new_all_same(border_style::solid) style: SideOffsets2D::new_all_same(border_style::solid)
}; };
list.append_item(BorderDisplayItemClass(border_display_item)) lists.lists[index].append_item(BorderDisplayItemClass(border_display_item));
}); });
}); });
}, },
ImageBox(ref image_box) => { ImageBox(ref image_box) => {
list.with_mut(|list| { lists.with_mut(|lists| {
let item = ~ClipDisplayItem { let item = ~ClipDisplayItem {
base: BaseDisplayItem { base: BaseDisplayItem {
bounds: absolute_box_bounds, bounds: absolute_box_bounds,
@ -1101,7 +1105,7 @@ impl Box {
child_list: ~[], child_list: ~[],
need_clip: false need_clip: false
}; };
list.append_item(ClipDisplayItemClass(item)); lists.lists[index].append_item(ClipDisplayItemClass(item));
}); });
let mut image_ref = image_box.image.borrow_mut(); let mut image_ref = image_box.image.borrow_mut();
@ -1119,7 +1123,7 @@ impl Box {
debug!("(building display list) building image box"); debug!("(building display list) building image box");
// Place the image into the display list. // Place the image into the display list.
list.with_mut(|list| { lists.with_mut(|lists| {
let image_display_item = ~ImageDisplayItem { let image_display_item = ~ImageDisplayItem {
base: BaseDisplayItem { base: BaseDisplayItem {
bounds: bounds, bounds: bounds,
@ -1127,7 +1131,7 @@ impl Box {
}, },
image: image.clone(), image: image.clone(),
}; };
list.append_item(ImageDisplayItemClass(image_display_item)); lists.lists[index].append_item(ImageDisplayItemClass(image_display_item));
}); });
} }
None => { None => {
@ -1142,7 +1146,7 @@ impl Box {
debug!("{:?}", { debug!("{:?}", {
let debug_border = SideOffsets2D::new_all_same(Au::from_px(1)); let debug_border = SideOffsets2D::new_all_same(Au::from_px(1));
list.with_mut(|list| { lists.with_mut(|lists| {
let border_display_item = ~BorderDisplayItem { let border_display_item = ~BorderDisplayItem {
base: BaseDisplayItem { base: BaseDisplayItem {
bounds: absolute_box_bounds, bounds: absolute_box_bounds,
@ -1153,7 +1157,7 @@ impl Box {
style: SideOffsets2D::new_all_same(border_style::solid) style: SideOffsets2D::new_all_same(border_style::solid)
}; };
list.append_item(BorderDisplayItemClass(border_display_item)) lists.lists[index].append_item(BorderDisplayItemClass(border_display_item))
}); });
}); });
@ -1180,7 +1184,8 @@ impl Box {
// Add a border, if applicable. // Add a border, if applicable.
// //
// TODO: Outlines. // TODO: Outlines.
self.paint_borders_if_applicable(list, &absolute_box_bounds); self.paint_borders_if_applicable(index, lists, &absolute_box_bounds);
} }
/// Returns the *minimum width* and *preferred width* of this box as defined by CSS 2.1. /// Returns the *minimum width* and *preferred width* of this box as defined by CSS 2.1.

View file

@ -41,7 +41,7 @@ use extra::dlist::{DList, DListIterator, MutDListIterator};
use extra::container::Deque; use extra::container::Deque;
use geom::point::Point2D; use geom::point::Point2D;
use geom::rect::Rect; use geom::rect::Rect;
use gfx::display_list::{ClipDisplayItemClass, DisplayList}; use gfx::display_list::{ClipDisplayItemClass, DisplayListCollection, DisplayList};
use layout::display_list_builder::ToGfxColor; use layout::display_list_builder::ToGfxColor;
use gfx::color::Color; use gfx::color::Color;
use servo_util::geometry::Au; use servo_util::geometry::Au;
@ -200,12 +200,13 @@ pub trait MutableFlowUtils {
/// Computes the overflow region for this flow. /// Computes the overflow region for this flow.
fn store_overflow(self, _: &mut LayoutContext); fn store_overflow(self, _: &mut LayoutContext);
/// Builds a display list for this flow and its children. /// builds the display lists
fn build_display_list<E:ExtraDisplayListData>( fn build_display_lists<E:ExtraDisplayListData>(
self, self,
builder: &DisplayListBuilder, builder: &DisplayListBuilder,
dirty: &Rect<Au>, dirty: &Rect<Au>,
list: &RefCell<DisplayList<E>>) index: uint,
mut list: &RefCell<DisplayListCollection<E>>)
-> bool; -> bool;
} }
@ -697,33 +698,37 @@ impl<'a> MutableFlowUtils for &'a mut Flow {
mut_base(self).overflow = overflow mut_base(self).overflow = overflow
} }
fn build_display_list<E:ExtraDisplayListData>( fn build_display_lists<E:ExtraDisplayListData>(
self, self,
builder: &DisplayListBuilder, builder: &DisplayListBuilder,
dirty: &Rect<Au>, dirty: &Rect<Au>,
list: &RefCell<DisplayList<E>>) mut index: uint,
lists: &RefCell<DisplayListCollection<E>>)
-> bool { -> bool {
debug!("Flow: building display list for f{}", base(self).id); debug!("Flow: building display list for f{}", base(self).id);
match self.class() { index = match self.class() {
BlockFlowClass => self.as_block().build_display_list_block(builder, dirty, list), BlockFlowClass => self.as_block().build_display_list_block(builder, dirty, index, lists),
InlineFlowClass => self.as_inline().build_display_list_inline(builder, dirty, list), InlineFlowClass => self.as_inline().build_display_list_inline(builder, dirty, index, lists),
}; };
if list.with_mut(|list| list.list.len() == 0) { if lists.with_mut(|lists| lists.lists[index].list.len() == 0) {
return true; return true;
} }
let child_list = ~RefCell::new(DisplayList::new()); let mut child_lists = DisplayListCollection::new();
child_lists.add_list(DisplayList::new());
let child_lists = RefCell::new(child_lists);
for kid in child_iter(self) { for kid in child_iter(self) {
kid.build_display_list(builder,dirty,child_list); kid.build_display_lists(builder, dirty, 0u, &child_lists);
} }
let mut child_list = Some(child_list.unwrap()); let mut child_lists = Some(child_lists.unwrap());
list.with_mut(|list| { lists.with_mut(|lists| {
let result = list.list.mut_rev_iter().position(|item| { let mut child_lists = child_lists.take_unwrap();
let result = lists.lists[index].list.mut_rev_iter().position(|item| {
match *item { match *item {
ClipDisplayItemClass(ref mut item) => { ClipDisplayItemClass(ref mut item) => {
item.child_list.push_all_move(child_list.take_unwrap().list); item.child_list.push_all_move(child_lists.lists.shift().list);
true true
}, },
_ => false, _ => false,
@ -734,6 +739,7 @@ impl<'a> MutableFlowUtils for &'a mut Flow {
fail!("fail to find parent item"); fail!("fail to find parent item");
} }
lists.lists.push_all_move(child_lists.lists);
}); });
true true
} }

View file

@ -16,7 +16,7 @@ use layout::float_context::{PlacementInfo, FloatLeft};
use extra::container::Deque; use extra::container::Deque;
use extra::ringbuf::RingBuf; use extra::ringbuf::RingBuf;
use geom::{Point2D, Rect, Size2D}; use geom::{Point2D, Rect, Size2D};
use gfx::display_list::DisplayList; use gfx::display_list::DisplayListCollection;
use servo_util::geometry::Au; use servo_util::geometry::Au;
use servo_util::range::Range; use servo_util::range::Range;
use std::cell::RefCell; use std::cell::RefCell;
@ -495,11 +495,12 @@ impl InlineFlow {
&self, &self,
builder: &DisplayListBuilder, builder: &DisplayListBuilder,
dirty: &Rect<Au>, dirty: &Rect<Au>,
list: &RefCell<DisplayList<E>>) index: uint,
-> bool { lists: &RefCell<DisplayListCollection<E>>)
-> uint {
let abs_rect = Rect(self.base.abs_position, self.base.position.size); let abs_rect = Rect(self.base.abs_position, self.base.position.size);
if !abs_rect.intersects(dirty) { if !abs_rect.intersects(dirty) {
return true; return index;
} }
// TODO(#228): Once we form line boxes and have their cached bounds, we can be smarter and // TODO(#228): Once we form line boxes and have their cached bounds, we can be smarter and
@ -509,14 +510,14 @@ impl InlineFlow {
self.boxes.len()); self.boxes.len());
for box_ in self.boxes.iter() { for box_ in self.boxes.iter() {
box_.build_display_list(builder, dirty, self.base.abs_position, (&*self) as &Flow, list) box_.build_display_list(builder, dirty, self.base.abs_position, (&*self) as &Flow, index, lists);
} }
// TODO(#225): Should `inline-block` elements have flows as children of the inline flow or // TODO(#225): Should `inline-block` elements have flows as children of the inline flow or
// should the flow be nested inside the box somehow? // should the flow be nested inside the box somehow?
// For now, don't traverse the subtree rooted here // For now, don't traverse the subtree rooted here
true index
} }
/// Returns the relative offset from the baseline for this box, taking into account the value /// Returns the relative offset from the baseline for this box, taking into account the value

View file

@ -25,7 +25,8 @@ use layout::wrapper::{DomLeafSet, LayoutNode};
use extra::arc::{Arc, MutexArc}; use extra::arc::{Arc, MutexArc};
use geom::rect::Rect; use geom::rect::Rect;
use geom::size::Size2D; use geom::size::Size2D;
use gfx::display_list::{ClipDisplayItemClass, DisplayItem, DisplayItemIterator, DisplayList}; use gfx::display_list::{ClipDisplayItemClass, DisplayItem, DisplayItemIterator};
use gfx::display_list::{DisplayList, DisplayListCollection};
use gfx::font_context::FontContextInfo; use gfx::font_context::FontContextInfo;
use gfx::opts::Opts; use gfx::opts::Opts;
use gfx::render_task::{RenderMsg, RenderChan, RenderLayer}; use gfx::render_task::{RenderMsg, RenderChan, RenderLayer};
@ -92,7 +93,7 @@ pub struct LayoutTask {
screen_size: Size2D<Au>, screen_size: Size2D<Au>,
/// A cached display list. /// A cached display list.
display_list: Option<Arc<DisplayList<OpaqueNode>>>, display_list_collection: Option<Arc<DisplayListCollection<OpaqueNode>>>,
stylist: ~Stylist, stylist: ~Stylist,
@ -295,7 +296,7 @@ impl LayoutTask {
dom_leaf_set: MutexArc::new(DomLeafSet::new()), dom_leaf_set: MutexArc::new(DomLeafSet::new()),
flow_leaf_set: MutexArc::new(FlowLeafSet::new()), flow_leaf_set: MutexArc::new(FlowLeafSet::new()),
display_list: None, display_list_collection: None,
stylist: ~new_stylist(), stylist: ~new_stylist(),
parallel_traversal: parallel_traversal, parallel_traversal: parallel_traversal,
profiler_chan: profiler_chan, profiler_chan: profiler_chan,
@ -620,14 +621,16 @@ impl LayoutTask {
if data.goal == ReflowForDisplay { if data.goal == ReflowForDisplay {
profile(time::LayoutDispListBuildCategory, self.profiler_chan.clone(), || { profile(time::LayoutDispListBuildCategory, self.profiler_chan.clone(), || {
let root_size = flow::base(layout_root).position.size; let root_size = flow::base(layout_root).position.size;
let display_list = ~RefCell::new(DisplayList::<OpaqueNode>::new()); let mut display_list_collection = DisplayListCollection::new();
display_list_collection.add_list(DisplayList::<OpaqueNode>::new());
let display_list_collection = ~RefCell::new(display_list_collection);
let dirty = flow::base(layout_root).position.clone(); let dirty = flow::base(layout_root).position.clone();
let display_list_builder = DisplayListBuilder { let display_list_builder = DisplayListBuilder {
ctx: &layout_ctx, ctx: &layout_ctx,
}; };
layout_root.build_display_list(&display_list_builder, &dirty, display_list); layout_root.build_display_lists(&display_list_builder, &dirty, 0u, display_list_collection);
let display_list = Arc::new(display_list.unwrap()); let display_list_collection = Arc::new(display_list_collection.unwrap());
let mut color = color::rgba(255.0, 255.0, 255.0, 255.0); let mut color = color::rgba(255.0, 255.0, 255.0, 255.0);
@ -652,13 +655,13 @@ impl LayoutTask {
} }
let render_layer = RenderLayer { let render_layer = RenderLayer {
display_list: display_list.clone(), display_list_collection: display_list_collection.clone(),
size: Size2D(root_size.width.to_nearest_px() as uint, size: Size2D(root_size.width.to_nearest_px() as uint,
root_size.height.to_nearest_px() as uint), root_size.height.to_nearest_px() as uint),
color: color color: color
}; };
self.display_list = Some(display_list.clone()); self.display_list_collection = Some(display_list_collection.clone());
debug!("Layout done!"); debug!("Layout done!");
@ -701,8 +704,9 @@ impl LayoutTask {
} }
let mut rect = None; let mut rect = None;
let display_list = self.display_list.as_ref().unwrap().get(); for display_list in self.display_list_collection.as_ref().unwrap().get().iter() {
union_boxes_for_node(&mut rect, display_list.iter(), node); union_boxes_for_node(&mut rect, display_list.iter(), node);
}
reply_chan.send(ContentBoxResponse(rect.unwrap_or(Au::zero_rect()))) reply_chan.send(ContentBoxResponse(rect.unwrap_or(Au::zero_rect())))
} }
ContentBoxesQuery(node, reply_chan) => { ContentBoxesQuery(node, reply_chan) => {
@ -721,8 +725,9 @@ impl LayoutTask {
} }
let mut boxes = ~[]; let mut boxes = ~[];
let display_list = self.display_list.as_ref().unwrap().get(); for display_list in self.display_list_collection.as_ref().unwrap().get().iter() {
add_boxes_for_node(&mut boxes, display_list.iter(), node); add_boxes_for_node(&mut boxes, display_list.iter(), node);
}
reply_chan.send(ContentBoxesResponse(boxes)) reply_chan.send(ContentBoxesResponse(boxes))
} }
HitTestQuery(_, point, reply_chan) => { HitTestQuery(_, point, reply_chan) => {
@ -762,27 +767,17 @@ impl LayoutTask {
let ret: Option<HitTestResponse> = None; let ret: Option<HitTestResponse> = None;
ret ret
} }
let response = { for display_list in self.display_list_collection.as_ref().unwrap().get().lists.rev_iter() {
match self.display_list {
Some(ref list) => {
let display_list = list.get();
let (x, y) = (Au::from_frac_px(point.x as f64), let (x, y) = (Au::from_frac_px(point.x as f64),
Au::from_frac_px(point.y as f64)); Au::from_frac_px(point.y as f64));
let resp = hit_test(x,y,display_list.list); let resp = hit_test(x,y,display_list.list);
if resp.is_none() { if resp.is_some() {
Err(()) reply_chan.send(Ok(resp.unwrap()));
} else { return
Ok(resp.unwrap())
} }
} }
None => { reply_chan.send(Err(()));
error!("Can't hit test: no display list");
Err(())
},
}
};
reply_chan.send(response)
} }
} }
} }