layout: Make the display list freezable/dual mode

This commit is contained in:
Patrick Walton 2012-10-25 22:01:52 -07:00
parent 7c029a322d
commit b101f8258e
8 changed files with 58 additions and 43 deletions

View file

@ -82,22 +82,32 @@ impl DisplayItem {
} }
} }
pub type DisplayList = DVec<~DisplayItem>; // Dual-mode/freezable.
pub struct DisplayList {
list: ~[~DisplayItem]
}
trait DisplayListMethods { trait DisplayListMethods {
fn append_item(&mut self, item: ~DisplayItem);
fn draw_into_context(ctx: &RenderContext); fn draw_into_context(ctx: &RenderContext);
} }
impl DisplayList {
static fn new() -> DisplayList {
DisplayList { list: ~[] }
}
}
impl DisplayList : DisplayListMethods { impl DisplayList : DisplayListMethods {
fn append_item(item: ~DisplayItem) { fn append_item(&mut self, item: ~DisplayItem) {
// FIXME(Issue #150): crashes // FIXME(Issue #150): crashes
//debug!("Adding display item %u: %?", self.len(), item); //debug!("Adding display item %u: %?", self.len(), item);
self.push(move item); self.list.push(move item);
} }
fn draw_into_context(ctx: &RenderContext) { fn draw_into_context(ctx: &RenderContext) {
debug!("beginning display list"); debug!("beginning display list");
for self.each |item| { for self.list.each |item| {
// FIXME(Issue #150): crashes // FIXME(Issue #150): crashes
//debug!("drawing %?", *item); //debug!("drawing %?", *item);
item.draw_into_context(ctx); item.draw_into_context(ctx);

View file

@ -1,9 +1,9 @@
use au = gfx::geometry; use au = gfx::geometry;
use css::values::*; use css::values::*;
use dl = gfx::display_list;
use geom::point::Point2D; use geom::point::Point2D;
use geom::rect::Rect; use geom::rect::Rect;
use geom::size::Size2D; use geom::size::Size2D;
use gfx::display_list::{DisplayList, DisplayListBuilder};
use gfx::geometry::Au; use gfx::geometry::Au;
use layout::box::{RenderBox}; use layout::box::{RenderBox};
use layout::context::LayoutContext; use layout::context::LayoutContext;
@ -27,8 +27,8 @@ trait BlockLayout {
fn bubble_widths_block(@self, ctx: &LayoutContext); fn bubble_widths_block(@self, ctx: &LayoutContext);
fn assign_widths_block(@self, ctx: &LayoutContext); fn assign_widths_block(@self, ctx: &LayoutContext);
fn assign_height_block(@self, ctx: &LayoutContext); fn assign_height_block(@self, ctx: &LayoutContext);
fn build_display_list_block(@self, a: &dl::DisplayListBuilder, b: &Rect<Au>, fn build_display_list_block(@self, a: &DisplayListBuilder, b: &Rect<Au>,
c: &Point2D<Au>, d: &dl::DisplayList); c: &Point2D<Au>, d: &mut DisplayList);
} }
impl FlowContext : BlockLayout { impl FlowContext : BlockLayout {
@ -141,8 +141,8 @@ impl FlowContext : BlockLayout {
} }
} }
fn build_display_list_block(@self, builder: &dl::DisplayListBuilder, dirty: &Rect<Au>, fn build_display_list_block(@self, builder: &DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &dl::DisplayList) { offset: &Point2D<Au>, list: &mut DisplayList) {
assert self.starts_block_flow(); assert self.starts_block_flow();

View file

@ -9,14 +9,14 @@ use core::dvec::DVec;
use core::to_str::ToStr; use core::to_str::ToStr;
use core::rand; use core::rand;
use css::styles::SpecifiedStyle; use css::styles::SpecifiedStyle;
use css::values::{BoxSizing, Length, Px, CSSDisplay, Specified, BgColor, BgColorTransparent, BdrColor, PosAbsolute}; use css::values::{BoxSizing, Length, Px, CSSDisplay, Specified, BgColor, BgColorTransparent};
use dl = gfx::display_list; use css::values::{BdrColor, PosAbsolute};
use dl::DisplayItem;
use dom::element::{ElementKind, HTMLDivElement, HTMLImageElement}; use dom::element::{ElementKind, HTMLDivElement, HTMLImageElement};
use dom::node::{Element, Node, NodeData, NodeKind, NodeTree}; use dom::node::{Element, Node, NodeData, NodeKind, NodeTree};
use geom::rect::Rect; use geom::rect::Rect;
use geom::size::Size2D; use geom::size::Size2D;
use geom::point::Point2D; use geom::point::Point2D;
use gfx::display_list::{DisplayItem, DisplayList, DisplayListBuilder};
use image::{Image, ImageHolder}; use image::{Image, ImageHolder};
use layout::context::LayoutContext; use layout::context::LayoutContext;
use layout::debug::BoxedDebugMethods; use layout::debug::BoxedDebugMethods;
@ -118,8 +118,8 @@ trait RenderBoxMethods {
fn get_pref_width(&LayoutContext) -> Au; fn get_pref_width(&LayoutContext) -> Au;
fn get_used_width() -> (Au, Au); fn get_used_width() -> (Au, Au);
fn get_used_height() -> (Au, Au); fn get_used_height() -> (Au, Au);
fn build_display_list(@self, &dl::DisplayListBuilder, dirty: &Rect<Au>, fn build_display_list(@self, &DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, &dl::DisplayList); offset: &Point2D<Au>, dl: &mut DisplayList);
} }
fn RenderBoxData(node: Node, ctx: @FlowContext, id: int) -> RenderBoxData { fn RenderBoxData(node: Node, ctx: @FlowContext, id: int) -> RenderBoxData {
@ -381,8 +381,8 @@ impl RenderBox : RenderBoxMethods {
* `origin` - Total offset from display list root flow to this box's owning flow * `origin` - Total offset from display list root flow to this box's owning flow
* `list` - List to which items should be appended * `list` - List to which items should be appended
*/ */
fn build_display_list(@self, builder: &dl::DisplayListBuilder, dirty: &Rect<Au>, fn build_display_list(@self, builder: &DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &dl::DisplayList) { offset: &Point2D<Au>, list: &mut DisplayList) {
let style = self.d().node.style(); let style = self.d().node.style();
let box_bounds : Rect<Au> = match style.position { let box_bounds : Rect<Au> = match style.position {
@ -441,7 +441,7 @@ impl RenderBox : RenderBoxMethods {
self.add_border_to_list(list, &abs_box_bounds); self.add_border_to_list(list, &abs_box_bounds);
} }
fn add_bgcolor_to_list(list: &dl::DisplayList, abs_bounds: &Rect<Au>) { fn add_bgcolor_to_list(list: &mut DisplayList, abs_bounds: &Rect<Au>) {
use std::cmp::FuzzyEq; use std::cmp::FuzzyEq;
// TODO: shouldn't need to unbox CSSValue by now // TODO: shouldn't need to unbox CSSValue by now
let boxed_bgcolor = self.d().node.style().background_color; let boxed_bgcolor = self.d().node.style().background_color;
@ -454,7 +454,7 @@ impl RenderBox : RenderBoxMethods {
} }
} }
fn add_border_to_list(list: &dl::DisplayList, abs_bounds: &Rect<Au>) { fn add_border_to_list(list: &mut DisplayList, abs_bounds: &Rect<Au>) {
let style = self.d().node.style(); let style = self.d().node.style();
match style.border_width { match style.border_width {
Specified(Px(px)) => { Specified(Px(px)) => {
@ -474,7 +474,8 @@ impl RenderBox : RenderBoxMethods {
Specified(BdrColor(color)) => color, Specified(BdrColor(color)) => color,
_ => rgb(0, 0, 0) // FIXME _ => rgb(0, 0, 0) // FIXME
}; };
list.push(~DisplayItem::new_Border(&abs_bounds, border_width, color.red, color.green, color.blue)); list.append_item(~DisplayItem::new_Border(&abs_bounds, border_width, color.red,
color.green, color.blue));
} }
_ => () // TODO _ => () // TODO
} }

View file

@ -3,7 +3,6 @@ export DisplayListBuilder;
use au = gfx::geometry; use au = gfx::geometry;
use au::Au; use au::Au;
use css::values::{BgColor, BgColorTransparent, Specified}; use css::values::{BgColor, BgColorTransparent, Specified};
use dl = gfx::display_list;
use dom::node::{Text, NodeScope}; use dom::node::{Text, NodeScope};
use dom::cow::Scope; use dom::cow::Scope;
use dvec::DVec; use dvec::DVec;
@ -11,6 +10,7 @@ use either::{Left, Right};
use geom::point::Point2D; use geom::point::Point2D;
use geom::rect::Rect; use geom::rect::Rect;
use geom::size::Size2D; use geom::size::Size2D;
use gfx::display_list::DisplayList;
use layout::box::{RenderBox, TextBox}; use layout::box::{RenderBox, TextBox};
use layout::context::LayoutContext; use layout::context::LayoutContext;
use layout::flow::FlowContext; use layout::flow::FlowContext;
@ -32,21 +32,24 @@ pub struct DisplayListBuilder {
trait FlowDisplayListBuilderMethods { trait FlowDisplayListBuilderMethods {
fn build_display_list(@self, a: &DisplayListBuilder, b: &Rect<Au>, c: &dl::DisplayList); fn build_display_list(@self, a: &DisplayListBuilder, b: &Rect<Au>, c: &mut DisplayList);
fn build_display_list_for_child(@self, a: &DisplayListBuilder, b: @FlowContext, fn build_display_list_for_child(@self, a: &DisplayListBuilder, b: @FlowContext,
c: &Rect<Au>, d: &Point2D<Au>, e: &dl::DisplayList); c: &Rect<Au>, d: &Point2D<Au>, e: &mut DisplayList);
} }
impl FlowContext: FlowDisplayListBuilderMethods { impl FlowContext: FlowDisplayListBuilderMethods {
fn build_display_list(@self, builder: &DisplayListBuilder, dirty: &Rect<Au>, list: &dl::DisplayList) { fn build_display_list(@self, builder: &DisplayListBuilder, dirty: &Rect<Au>,
list: &mut DisplayList) {
let zero = au::zero_point(); let zero = au::zero_point();
self.build_display_list_recurse(builder, dirty, &zero, list); self.build_display_list_recurse(builder, dirty, &zero, list);
} }
fn build_display_list_for_child(@self, builder: &DisplayListBuilder, child_flow: @FlowContext, fn build_display_list_for_child(@self,
builder: &DisplayListBuilder,
child_flow: @FlowContext,
dirty: &Rect<Au>, offset: &Point2D<Au>, dirty: &Rect<Au>, offset: &Point2D<Au>,
list: &dl::DisplayList) { list: &mut DisplayList) {
// adjust the dirty rect to child flow context coordinates // adjust the dirty rect to child flow context coordinates
let abs_flow_bounds = child_flow.d().position.translate(offset); let abs_flow_bounds = child_flow.d().position.translate(offset);

View file

@ -1,10 +1,10 @@
use au = gfx::geometry; use au = gfx::geometry;
use au::Au; use au::Au;
use core::dvec::DVec; use core::dvec::DVec;
use dl = gfx::display_list;
use dom::node::Node; use dom::node::Node;
use geom::rect::Rect; use geom::rect::Rect;
use geom::point::Point2D; use geom::point::Point2D;
use gfx::display_list::{DisplayList, DisplayListBuilder};
// TODO: pub-use these // TODO: pub-use these
use layout::block::BlockFlowData; use layout::block::BlockFlowData;
use layout::box::RenderBox; use layout::box::RenderBox;
@ -72,8 +72,8 @@ trait FlowContextMethods {
fn bubble_widths(@self, &LayoutContext); fn bubble_widths(@self, &LayoutContext);
fn assign_widths(@self, &LayoutContext); fn assign_widths(@self, &LayoutContext);
fn assign_height(@self, &LayoutContext); fn assign_height(@self, &LayoutContext);
fn build_display_list_recurse(@self, &dl::DisplayListBuilder, dirty: &Rect<Au>, fn build_display_list_recurse(@self, &DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, &dl::DisplayList); offset: &Point2D<Au>, &mut DisplayList);
pure fn foldl_boxes_for_node<B: Copy>(Node, +seed: B, cb: pure fn&(+a: B,@RenderBox) -> B) -> B; pure fn foldl_boxes_for_node<B: Copy>(Node, +seed: B, cb: pure fn&(+a: B,@RenderBox) -> B) -> B;
pure fn iter_boxes_for_node<T>(Node, cb: pure fn&(@RenderBox) -> T); pure fn iter_boxes_for_node<T>(Node, cb: pure fn&(@RenderBox) -> T);
} }
@ -168,8 +168,8 @@ impl FlowContext : FlowContextMethods {
} }
} }
fn build_display_list_recurse(@self, builder: &dl::DisplayListBuilder, dirty: &Rect<Au>, fn build_display_list_recurse(@self, builder: &DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &dl::DisplayList) { offset: &Point2D<Au>, list: &mut DisplayList) {
debug!("FlowContext::build_display_list at %?: %s", self.d().position, self.debug_str()); debug!("FlowContext::build_display_list at %?: %s", self.d().position, self.debug_str());
match self { match self {

View file

@ -2,11 +2,11 @@ use au = gfx::geometry;
use core::dlist::DList; use core::dlist::DList;
use core::dvec::DVec; use core::dvec::DVec;
use css::values::{BoxAuto, BoxLength, Px}; use css::values::{BoxAuto, BoxLength, Px};
use dl = gfx::display_list;
use dom::node::Node; use dom::node::Node;
use geom::point::Point2D; use geom::point::Point2D;
use geom::rect::Rect; use geom::rect::Rect;
use geom::size::Size2D; use geom::size::Size2D;
use gfx::display_list::{DisplayList, DisplayListBuilder};
use gfx::geometry::Au; use gfx::geometry::Au;
use layout::box::*; use layout::box::*;
use layout::context::LayoutContext; use layout::context::LayoutContext;
@ -538,7 +538,8 @@ trait InlineLayout {
fn bubble_widths_inline(@self, ctx: &LayoutContext); fn bubble_widths_inline(@self, ctx: &LayoutContext);
fn assign_widths_inline(@self, ctx: &LayoutContext); fn assign_widths_inline(@self, ctx: &LayoutContext);
fn assign_height_inline(@self, ctx: &LayoutContext); fn assign_height_inline(@self, ctx: &LayoutContext);
fn build_display_list_inline(@self, a: &dl::DisplayListBuilder, b: &Rect<Au>, c: &Point2D<Au>, d: &dl::DisplayList); fn build_display_list_inline(@self, a: &DisplayListBuilder, b: &Rect<Au>, c: &Point2D<Au>,
d: &mut DisplayList);
} }
impl FlowContext : InlineLayout { impl FlowContext : InlineLayout {
@ -648,8 +649,8 @@ impl FlowContext : InlineLayout {
self.d().position.size.height = cur_y; self.d().position.size.height = cur_y;
} }
fn build_display_list_inline(@self, builder: &dl::DisplayListBuilder, dirty: &Rect<Au>, fn build_display_list_inline(@self, builder: &DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &dl::DisplayList) { offset: &Point2D<Au>, list: &mut DisplayList) {
assert self.starts_inline_flow(); assert self.starts_inline_flow();

View file

@ -15,6 +15,7 @@ use dom::node::{Node, LayoutData};
use geom::point::Point2D; use geom::point::Point2D;
use geom::rect::Rect; use geom::rect::Rect;
use geom::size::Size2D; use geom::size::Size2D;
use gfx::display_list::DisplayList;
use gfx::render_task; use gfx::render_task;
use gfx::render_layers::RenderLayer; use gfx::render_layers::RenderLayer;
use layout::box::RenderBox; use layout::box::RenderBox;
@ -179,12 +180,11 @@ impl Layout {
} }
do time("layout: display list building") { do time("layout: display list building") {
let dlist = DVec();
let builder = dl::DisplayListBuilder { let builder = dl::DisplayListBuilder {
ctx: &layout_ctx, ctx: &layout_ctx,
}; };
let render_layer = RenderLayer { let mut render_layer = RenderLayer {
display_list: move dlist, display_list: DisplayList::new(),
size: Size2D(au::to_px(screen_size.width) as uint, size: Size2D(au::to_px(screen_size.width) as uint,
au::to_px(screen_size.height) as uint) au::to_px(screen_size.height) as uint)
}; };
@ -192,7 +192,7 @@ impl Layout {
// TODO: set options on the builder before building // TODO: set options on the builder before building
// TODO: be smarter about what needs painting // TODO: be smarter about what needs painting
layout_root.build_display_list(&builder, &copy layout_root.d().position, layout_root.build_display_list(&builder, &copy layout_root.d().position,
&render_layer.display_list); &mut render_layer.display_list);
self.render_task.send(render_task::RenderMsg(move render_layer)); self.render_task.send(render_task::RenderMsg(move render_layer));
} // time(layout: display list building) } // time(layout: display list building)

View file

@ -1,8 +1,8 @@
use au = gfx::geometry; use au = gfx::geometry;
use css::values::*; use css::values::*;
use dl = gfx::display_list;
use geom::point::Point2D; use geom::point::Point2D;
use geom::rect::Rect; use geom::rect::Rect;
use gfx::display_list::{DisplayList, DisplayListBuilder};
use gfx::geometry::Au; use gfx::geometry::Au;
use layout::box::RenderBox; use layout::box::RenderBox;
use layout::context::LayoutContext; use layout::context::LayoutContext;
@ -25,8 +25,8 @@ trait RootLayout {
fn bubble_widths_root(@self, ctx: &LayoutContext); fn bubble_widths_root(@self, ctx: &LayoutContext);
fn assign_widths_root(@self, ctx: &LayoutContext); fn assign_widths_root(@self, ctx: &LayoutContext);
fn assign_height_root(@self, ctx: &LayoutContext); fn assign_height_root(@self, ctx: &LayoutContext);
fn build_display_list_root(@self, a: &dl::DisplayListBuilder, b: &Rect<Au>, fn build_display_list_root(@self, a: &DisplayListBuilder, b: &Rect<Au>,
c: &Point2D<Au>, d: &dl::DisplayList); c: &Point2D<Au>, d: &mut DisplayList);
} }
impl FlowContext : RootLayout { impl FlowContext : RootLayout {
@ -57,8 +57,8 @@ impl FlowContext : RootLayout {
self.assign_height_block(ctx); self.assign_height_block(ctx);
} }
fn build_display_list_root(@self, builder: &dl::DisplayListBuilder, dirty: &Rect<Au>, fn build_display_list_root(@self, builder: &DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &dl::DisplayList) { offset: &Point2D<Au>, list: &mut DisplayList) {
assert self.starts_root_flow(); assert self.starts_root_flow();
self.build_display_list_block(builder, dirty, offset, list); self.build_display_list_block(builder, dirty, offset, list);