diff --git a/src/components/gfx/display_list.rs b/src/components/gfx/display_list/mod.rs similarity index 99% rename from src/components/gfx/display_list.rs rename to src/components/gfx/display_list/mod.rs index 3cff59b52d8..a0695e98d3a 100644 --- a/src/components/gfx/display_list.rs +++ b/src/components/gfx/display_list/mod.rs @@ -33,6 +33,8 @@ use std::slice::Items; use style::computed_values::border_style; use sync::Arc; +pub mod optimizer; + /// An opaque handle to a node. The only safe operation that can be performed on this node is to /// compare it to another opaque handle or to another node. /// @@ -51,7 +53,7 @@ impl OpaqueNode { } /// "Steps" as defined by CSS 2.1 ยง E.2. -#[deriving(Eq)] +#[deriving(Clone, Eq)] pub enum StackingLevel { /// The border and backgrounds for the root of this stacking context: steps 1 and 2. BackgroundAndBordersStackingLevel, @@ -207,6 +209,7 @@ pub enum BackgroundAndBorderLevel { } /// A list of rendering operations to be performed. +#[deriving(Clone)] pub struct DisplayList { pub list: DList, } @@ -331,6 +334,7 @@ impl DisplayList { } /// One drawing command in the list. +#[deriving(Clone)] pub enum DisplayItem { SolidColorDisplayItemClass(Box), TextDisplayItemClass(Box), @@ -348,6 +352,7 @@ pub enum DisplayItem { } /// Information common to all display items. +#[deriving(Clone)] pub struct BaseDisplayItem { /// The boundaries of the display item. /// @@ -372,12 +377,14 @@ impl BaseDisplayItem { } /// Renders a solid color. +#[deriving(Clone)] pub struct SolidColorDisplayItem { pub base: BaseDisplayItem, pub color: Color, } /// Text decoration information. +#[deriving(Clone)] pub struct TextDecorations { /// The color to use for underlining, if any. pub underline: Option, @@ -388,6 +395,7 @@ pub struct TextDecorations { } /// Renders text. +#[deriving(Clone)] pub struct TextDisplayItem { /// Fields common to all display items. pub base: BaseDisplayItem, @@ -406,6 +414,7 @@ pub struct TextDisplayItem { } /// Renders an image. +#[deriving(Clone)] pub struct ImageDisplayItem { pub base: BaseDisplayItem, pub image: Arc>, @@ -417,6 +426,7 @@ pub struct ImageDisplayItem { } /// Renders a border. +#[deriving(Clone)] pub struct BorderDisplayItem { pub base: BaseDisplayItem, @@ -431,6 +441,7 @@ pub struct BorderDisplayItem { } /// Renders a line segment. +#[deriving(Clone)] pub struct LineDisplayItem { pub base: BaseDisplayItem, @@ -442,6 +453,7 @@ pub struct LineDisplayItem { } /// Clips a list of child display items to this display item's boundaries. +#[deriving(Clone)] pub struct ClipDisplayItem { /// The base information. pub base: BaseDisplayItem, diff --git a/src/components/gfx/display_list/optimizer.rs b/src/components/gfx/display_list/optimizer.rs new file mode 100644 index 00000000000..82484bb5738 --- /dev/null +++ b/src/components/gfx/display_list/optimizer.rs @@ -0,0 +1,74 @@ +/* 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/. */ + +use display_list::{BorderDisplayItemClass, ClipDisplayItem, ClipDisplayItemClass, DisplayItem}; +use display_list::{DisplayList, ImageDisplayItemClass, LineDisplayItemClass}; +use display_list::{PseudoDisplayItemClass, SolidColorDisplayItemClass, TextDisplayItemClass}; + +use collections::deque::Deque; +use collections::dlist::DList; +use geom::rect::Rect; +use servo_util::geometry::Au; +use sync::Arc; + +pub struct DisplayListOptimizer { + display_list: Arc, + /// The visible rect in page coordinates. + visible_rect: Rect, +} + +impl DisplayListOptimizer { + /// `visible_rect` specifies the visible rect in page coordinates. + pub fn new(display_list: Arc, visible_rect: Rect) -> DisplayListOptimizer { + DisplayListOptimizer { + display_list: display_list, + visible_rect: visible_rect, + } + } + + pub fn optimize(self) -> DisplayList { + self.process_display_list(&*self.display_list) + } + + fn process_display_list(&self, display_list: &DisplayList) -> DisplayList { + let mut result = DList::new(); + for item in display_list.iter() { + match self.process_display_item(item) { + None => {} + Some(display_item) => result.push_back(display_item), + } + } + DisplayList { + list: result, + } + } + + fn process_display_item(&self, display_item: &DisplayItem) -> Option { + // Eliminate display items outside the visible region. + if !self.visible_rect.intersects(&display_item.base().bounds) { + return None + } + + // Recur. + match *display_item { + ClipDisplayItemClass(ref clip) => { + let new_children = self.process_display_list(&clip.children); + if new_children.is_empty() { + return None + } + Some(ClipDisplayItemClass(box ClipDisplayItem { + base: clip.base.clone(), + children: new_children, + })) + } + + BorderDisplayItemClass(_) | ImageDisplayItemClass(_) | LineDisplayItemClass(_) | + PseudoDisplayItemClass(_) | SolidColorDisplayItemClass(_) | + TextDisplayItemClass(_) => { + Some((*display_item).clone()) + } + } + } +} + diff --git a/src/components/gfx/gfx.rs b/src/components/gfx/gfx.rs index 4a44f77f350..f5b2229ce00 100644 --- a/src/components/gfx/gfx.rs +++ b/src/components/gfx/gfx.rs @@ -56,6 +56,7 @@ mod render_context; // Rendering pub mod color; +#[path="display_list/mod.rs"] pub mod display_list; pub mod render_task; diff --git a/src/components/gfx/render_task.rs b/src/components/gfx/render_task.rs index a828adeddb0..f8411e3714a 100644 --- a/src/components/gfx/render_task.rs +++ b/src/components/gfx/render_task.rs @@ -5,6 +5,7 @@ //! The task that handles all rendering/painting. use buffer_map::BufferMap; +use display_list::optimizer::DisplayListOptimizer; use display_list::DisplayList; use font_context::{FontContext, FontContextInfo}; use render_context::RenderContext; @@ -17,19 +18,18 @@ use geom::size::Size2D; use layers::platform::surface::{NativePaintingGraphicsContext, NativeSurface}; use layers::platform::surface::{NativeSurfaceMethods}; use layers; -use servo_msg::compositor_msg::{Epoch, IdleRenderState, LayerBuffer}; -use servo_msg::compositor_msg::{LayerBufferSet, LayerId, LayerMetadata, RenderListener}; -use servo_msg::compositor_msg::{RenderingRenderState, ScrollPolicy}; -use servo_msg::constellation_msg::{ConstellationChan, PipelineId, RendererReadyMsg}; -use servo_msg::constellation_msg::{Failure, FailureMsg}; +use servo_msg::compositor_msg::{Epoch, IdleRenderState, LayerBuffer, LayerBufferSet, LayerId}; +use servo_msg::compositor_msg::{LayerMetadata, RenderListener, RenderingRenderState, ScrollPolicy}; +use servo_msg::constellation_msg::{ConstellationChan, Failure, FailureMsg, PipelineId}; +use servo_msg::constellation_msg::{RendererReadyMsg}; use servo_msg::platform::surface::NativeSurfaceAzureMethods; +use servo_util::geometry; use servo_util::opts::Opts; use servo_util::smallvec::{SmallVec, SmallVec1}; +use servo_util::task::send_on_failure; use servo_util::time::{ProfilerChan, profile}; use servo_util::time; -use servo_util::task::send_on_failure; - -use std::comm::{channel, Receiver, Sender}; +use std::comm::{Receiver, Sender, channel}; use std::task::TaskBuilder; use sync::Arc; @@ -154,7 +154,7 @@ fn initialize_layers( compositor.initialize_layers_for_pipeline(pipeline_id, metadata, epoch); } -impl RenderTask { +impl RenderTask { pub fn create(id: PipelineId, port: Receiver, compositor: C, @@ -294,6 +294,12 @@ impl RenderTask { // Divide up the layer into tiles. for tile in tiles.iter() { + // Optimize the display list for this tile. + let page_rect_au = geometry::f32_rect_to_au_rect(tile.page_rect); + let optimizer = DisplayListOptimizer::new(render_layer.display_list.clone(), + page_rect_au); + let display_list = optimizer.optimize(); + let width = tile.screen_rect.size.width; let height = tile.screen_rect.size.height; @@ -340,7 +346,7 @@ impl RenderTask { // Draw the display list. profile(time::RenderingDrawingCategory, self.profiler_chan.clone(), || { - render_layer.display_list.draw_into_context(&mut ctx); + display_list.draw_into_context(&mut ctx); ctx.draw_target.flush(); }); } diff --git a/src/components/util/geometry.rs b/src/components/util/geometry.rs index c72dd03bd23..0e6fd2acf8c 100644 --- a/src/components/util/geometry.rs +++ b/src/components/util/geometry.rs @@ -4,6 +4,7 @@ use geom::point::Point2D; use geom::rect::Rect; +use geom::size::Size2D; use std::default::Default; use std::num::{NumCast, One, Zero}; @@ -159,6 +160,11 @@ impl Au { else { return Au(s - res) }; } + #[inline] + pub fn from_frac32_px(px: f32) -> Au { + Au((px * 60f32) as i32) + } + #[inline] pub fn from_pt(pt: f64) -> Au { from_px(pt_to_px(pt) as int) @@ -231,3 +237,9 @@ pub fn rect_contains_point>(rect: Rect, point: Point2D) - point.y >= rect.origin.y && point.y < rect.origin.y + rect.size.height } +/// A helper function to convert a rect of `f32` pixels to a rect of app units. +pub fn f32_rect_to_au_rect(rect: Rect) -> Rect { + Rect(Point2D(Au::from_frac32_px(rect.origin.x), Au::from_frac32_px(rect.origin.y)), + Size2D(Au::from_frac32_px(rect.size.width), Au::from_frac32_px(rect.size.height))) +} +