mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
gfx: Add display list optimization to eliminate clipped items before
submitting them to Skia. 40x improvement in painting time on Wikipedia.
This commit is contained in:
parent
b2e7e67087
commit
081e054b4a
5 changed files with 116 additions and 11 deletions
|
@ -33,6 +33,8 @@ use std::slice::Items;
|
||||||
use style::computed_values::border_style;
|
use style::computed_values::border_style;
|
||||||
use sync::Arc;
|
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
|
/// 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.
|
/// 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.
|
/// "Steps" as defined by CSS 2.1 § E.2.
|
||||||
#[deriving(Eq)]
|
#[deriving(Clone, Eq)]
|
||||||
pub enum StackingLevel {
|
pub enum StackingLevel {
|
||||||
/// The border and backgrounds for the root of this stacking context: steps 1 and 2.
|
/// The border and backgrounds for the root of this stacking context: steps 1 and 2.
|
||||||
BackgroundAndBordersStackingLevel,
|
BackgroundAndBordersStackingLevel,
|
||||||
|
@ -207,6 +209,7 @@ pub enum BackgroundAndBorderLevel {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A list of rendering operations to be performed.
|
/// A list of rendering operations to be performed.
|
||||||
|
#[deriving(Clone)]
|
||||||
pub struct DisplayList {
|
pub struct DisplayList {
|
||||||
pub list: DList<DisplayItem>,
|
pub list: DList<DisplayItem>,
|
||||||
}
|
}
|
||||||
|
@ -331,6 +334,7 @@ impl DisplayList {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// One drawing command in the list.
|
/// One drawing command in the list.
|
||||||
|
#[deriving(Clone)]
|
||||||
pub enum DisplayItem {
|
pub enum DisplayItem {
|
||||||
SolidColorDisplayItemClass(Box<SolidColorDisplayItem>),
|
SolidColorDisplayItemClass(Box<SolidColorDisplayItem>),
|
||||||
TextDisplayItemClass(Box<TextDisplayItem>),
|
TextDisplayItemClass(Box<TextDisplayItem>),
|
||||||
|
@ -348,6 +352,7 @@ pub enum DisplayItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Information common to all display items.
|
/// Information common to all display items.
|
||||||
|
#[deriving(Clone)]
|
||||||
pub struct BaseDisplayItem {
|
pub struct BaseDisplayItem {
|
||||||
/// The boundaries of the display item.
|
/// The boundaries of the display item.
|
||||||
///
|
///
|
||||||
|
@ -372,12 +377,14 @@ impl BaseDisplayItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Renders a solid color.
|
/// Renders a solid color.
|
||||||
|
#[deriving(Clone)]
|
||||||
pub struct SolidColorDisplayItem {
|
pub struct SolidColorDisplayItem {
|
||||||
pub base: BaseDisplayItem,
|
pub base: BaseDisplayItem,
|
||||||
pub color: Color,
|
pub color: Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Text decoration information.
|
/// Text decoration information.
|
||||||
|
#[deriving(Clone)]
|
||||||
pub struct TextDecorations {
|
pub struct TextDecorations {
|
||||||
/// The color to use for underlining, if any.
|
/// The color to use for underlining, if any.
|
||||||
pub underline: Option<Color>,
|
pub underline: Option<Color>,
|
||||||
|
@ -388,6 +395,7 @@ pub struct TextDecorations {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Renders text.
|
/// Renders text.
|
||||||
|
#[deriving(Clone)]
|
||||||
pub struct TextDisplayItem {
|
pub struct TextDisplayItem {
|
||||||
/// Fields common to all display items.
|
/// Fields common to all display items.
|
||||||
pub base: BaseDisplayItem,
|
pub base: BaseDisplayItem,
|
||||||
|
@ -406,6 +414,7 @@ pub struct TextDisplayItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Renders an image.
|
/// Renders an image.
|
||||||
|
#[deriving(Clone)]
|
||||||
pub struct ImageDisplayItem {
|
pub struct ImageDisplayItem {
|
||||||
pub base: BaseDisplayItem,
|
pub base: BaseDisplayItem,
|
||||||
pub image: Arc<Box<Image>>,
|
pub image: Arc<Box<Image>>,
|
||||||
|
@ -417,6 +426,7 @@ pub struct ImageDisplayItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Renders a border.
|
/// Renders a border.
|
||||||
|
#[deriving(Clone)]
|
||||||
pub struct BorderDisplayItem {
|
pub struct BorderDisplayItem {
|
||||||
pub base: BaseDisplayItem,
|
pub base: BaseDisplayItem,
|
||||||
|
|
||||||
|
@ -431,6 +441,7 @@ pub struct BorderDisplayItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Renders a line segment.
|
/// Renders a line segment.
|
||||||
|
#[deriving(Clone)]
|
||||||
pub struct LineDisplayItem {
|
pub struct LineDisplayItem {
|
||||||
pub base: BaseDisplayItem,
|
pub base: BaseDisplayItem,
|
||||||
|
|
||||||
|
@ -442,6 +453,7 @@ pub struct LineDisplayItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clips a list of child display items to this display item's boundaries.
|
/// Clips a list of child display items to this display item's boundaries.
|
||||||
|
#[deriving(Clone)]
|
||||||
pub struct ClipDisplayItem {
|
pub struct ClipDisplayItem {
|
||||||
/// The base information.
|
/// The base information.
|
||||||
pub base: BaseDisplayItem,
|
pub base: BaseDisplayItem,
|
74
src/components/gfx/display_list/optimizer.rs
Normal file
74
src/components/gfx/display_list/optimizer.rs
Normal file
|
@ -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<DisplayList>,
|
||||||
|
/// The visible rect in page coordinates.
|
||||||
|
visible_rect: Rect<Au>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DisplayListOptimizer {
|
||||||
|
/// `visible_rect` specifies the visible rect in page coordinates.
|
||||||
|
pub fn new(display_list: Arc<DisplayList>, visible_rect: Rect<Au>) -> 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<DisplayItem> {
|
||||||
|
// 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())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -56,6 +56,7 @@ mod render_context;
|
||||||
|
|
||||||
// Rendering
|
// Rendering
|
||||||
pub mod color;
|
pub mod color;
|
||||||
|
#[path="display_list/mod.rs"]
|
||||||
pub mod display_list;
|
pub mod display_list;
|
||||||
pub mod render_task;
|
pub mod render_task;
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
//! The task that handles all rendering/painting.
|
//! The task that handles all rendering/painting.
|
||||||
|
|
||||||
use buffer_map::BufferMap;
|
use buffer_map::BufferMap;
|
||||||
|
use display_list::optimizer::DisplayListOptimizer;
|
||||||
use display_list::DisplayList;
|
use display_list::DisplayList;
|
||||||
use font_context::{FontContext, FontContextInfo};
|
use font_context::{FontContext, FontContextInfo};
|
||||||
use render_context::RenderContext;
|
use render_context::RenderContext;
|
||||||
|
@ -17,19 +18,18 @@ use geom::size::Size2D;
|
||||||
use layers::platform::surface::{NativePaintingGraphicsContext, NativeSurface};
|
use layers::platform::surface::{NativePaintingGraphicsContext, NativeSurface};
|
||||||
use layers::platform::surface::{NativeSurfaceMethods};
|
use layers::platform::surface::{NativeSurfaceMethods};
|
||||||
use layers;
|
use layers;
|
||||||
use servo_msg::compositor_msg::{Epoch, IdleRenderState, LayerBuffer};
|
use servo_msg::compositor_msg::{Epoch, IdleRenderState, LayerBuffer, LayerBufferSet, LayerId};
|
||||||
use servo_msg::compositor_msg::{LayerBufferSet, LayerId, LayerMetadata, RenderListener};
|
use servo_msg::compositor_msg::{LayerMetadata, RenderListener, RenderingRenderState, ScrollPolicy};
|
||||||
use servo_msg::compositor_msg::{RenderingRenderState, ScrollPolicy};
|
use servo_msg::constellation_msg::{ConstellationChan, Failure, FailureMsg, PipelineId};
|
||||||
use servo_msg::constellation_msg::{ConstellationChan, PipelineId, RendererReadyMsg};
|
use servo_msg::constellation_msg::{RendererReadyMsg};
|
||||||
use servo_msg::constellation_msg::{Failure, FailureMsg};
|
|
||||||
use servo_msg::platform::surface::NativeSurfaceAzureMethods;
|
use servo_msg::platform::surface::NativeSurfaceAzureMethods;
|
||||||
|
use servo_util::geometry;
|
||||||
use servo_util::opts::Opts;
|
use servo_util::opts::Opts;
|
||||||
use servo_util::smallvec::{SmallVec, SmallVec1};
|
use servo_util::smallvec::{SmallVec, SmallVec1};
|
||||||
|
use servo_util::task::send_on_failure;
|
||||||
use servo_util::time::{ProfilerChan, profile};
|
use servo_util::time::{ProfilerChan, profile};
|
||||||
use servo_util::time;
|
use servo_util::time;
|
||||||
use servo_util::task::send_on_failure;
|
use std::comm::{Receiver, Sender, channel};
|
||||||
|
|
||||||
use std::comm::{channel, Receiver, Sender};
|
|
||||||
use std::task::TaskBuilder;
|
use std::task::TaskBuilder;
|
||||||
use sync::Arc;
|
use sync::Arc;
|
||||||
|
|
||||||
|
@ -154,7 +154,7 @@ fn initialize_layers<C:RenderListener>(
|
||||||
compositor.initialize_layers_for_pipeline(pipeline_id, metadata, epoch);
|
compositor.initialize_layers_for_pipeline(pipeline_id, metadata, epoch);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: RenderListener + Send> RenderTask<C> {
|
impl<C:RenderListener + Send> RenderTask<C> {
|
||||||
pub fn create(id: PipelineId,
|
pub fn create(id: PipelineId,
|
||||||
port: Receiver<Msg>,
|
port: Receiver<Msg>,
|
||||||
compositor: C,
|
compositor: C,
|
||||||
|
@ -294,6 +294,12 @@ impl<C: RenderListener + Send> RenderTask<C> {
|
||||||
|
|
||||||
// Divide up the layer into tiles.
|
// Divide up the layer into tiles.
|
||||||
for tile in tiles.iter() {
|
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 width = tile.screen_rect.size.width;
|
||||||
let height = tile.screen_rect.size.height;
|
let height = tile.screen_rect.size.height;
|
||||||
|
|
||||||
|
@ -340,7 +346,7 @@ impl<C: RenderListener + Send> RenderTask<C> {
|
||||||
|
|
||||||
// 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.draw_into_context(&mut ctx);
|
display_list.draw_into_context(&mut ctx);
|
||||||
ctx.draw_target.flush();
|
ctx.draw_target.flush();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
|
use geom::size::Size2D;
|
||||||
|
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use std::num::{NumCast, One, Zero};
|
use std::num::{NumCast, One, Zero};
|
||||||
|
@ -159,6 +160,11 @@ impl Au {
|
||||||
else { return Au(s - res) };
|
else { return Au(s - res) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn from_frac32_px(px: f32) -> Au {
|
||||||
|
Au((px * 60f32) as i32)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_pt(pt: f64) -> Au {
|
pub fn from_pt(pt: f64) -> Au {
|
||||||
from_px(pt_to_px(pt) as int)
|
from_px(pt_to_px(pt) as int)
|
||||||
|
@ -231,3 +237,9 @@ pub fn rect_contains_point<T:Ord + Add<T,T>>(rect: Rect<T>, point: Point2D<T>) -
|
||||||
point.y >= rect.origin.y && point.y < rect.origin.y + rect.size.height
|
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<f32>) -> Rect<Au> {
|
||||||
|
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)))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue