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 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<DisplayItem>,
|
||||
}
|
||||
|
@ -331,6 +334,7 @@ impl DisplayList {
|
|||
}
|
||||
|
||||
/// One drawing command in the list.
|
||||
#[deriving(Clone)]
|
||||
pub enum DisplayItem {
|
||||
SolidColorDisplayItemClass(Box<SolidColorDisplayItem>),
|
||||
TextDisplayItemClass(Box<TextDisplayItem>),
|
||||
|
@ -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<Color>,
|
||||
|
@ -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<Box<Image>>,
|
||||
|
@ -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,
|
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
|
||||
pub mod color;
|
||||
#[path="display_list/mod.rs"]
|
||||
pub mod display_list;
|
||||
pub mod render_task;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -294,6 +294,12 @@ impl<C: RenderListener + Send> RenderTask<C> {
|
|||
|
||||
// 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<C: RenderListener + Send> RenderTask<C> {
|
|||
|
||||
// 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();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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<T:Ord + Add<T,T>>(rect: Rect<T>, point: Point2D<T>) -
|
|||
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