Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor display lists to use less memory. #476

Merged
merged 10 commits into from May 30, 2013
@@ -171,35 +171,42 @@ $(eval $(call DEF_SUBMODULE_RULES,$(submodule))))

DONE_SUBMODULES = $(foreach submodule,$(SUBMODULES),$(DONE_$(submodule)))

RFLAGS_servo_util = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES))
SRC_servo_util = $(call rwildcard,$(S)src/components/servo-util/,*.rs)
CRATE_servo_util = $(S)src/components/servo-util/servo_util.rc
DONE_servo_util = $(B)src/components/servo-util/libservoutil.dummy
RFLAGS_util = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES))
SRC_util = $(call rwildcard,$(S)src/components/util/,*.rs)
CRATE_util = $(S)src/components/util/util.rc
DONE_util = $(B)src/components/util/libutil.dummy

DEPS_servo_util = $(CRATE_servo_util) $(SRC_servo_util) $(DONE_SUBMODULES)
DEPS_util = $(CRATE_util) $(SRC_util) $(DONE_SUBMODULES)

RFLAGS_servo_net = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/servo-util
SRC_servo_net = $(call rwildcard,$(S)src/components/servo-net/,*.rs)
CRATE_servo_net = $(S)src/components/servo-net/servo_net.rc
DONE_servo_net = $(B)src/components/servo-net/libservonet.dummy
RFLAGS_net = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/util
SRC_net = $(call rwildcard,$(S)src/components/net/,*.rs)
CRATE_net = $(S)src/components/net/net.rc
DONE_net = $(B)src/components/net/libnet.dummy

DEPS_servo_net = $(CRATE_servo_net) $(SRC_servo_net) $(DONE_SUBMODULES) $(DONE_servo_util)
DEPS_net = $(CRATE_net) $(SRC_net) $(DONE_SUBMODULES) $(DONE_util)

RFLAGS_servo_gfx = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/servo-util -L $(B)src/components/servo-net
SRC_servo_gfx = $(call rwildcard,$(S)src/components/servo-gfx/,*.rs)
CRATE_servo_gfx = $(S)src/components/servo-gfx/servo_gfx.rc
DONE_servo_gfx = $(B)src/components/servo-gfx/libservogfx.dummy
RFLAGS_gfx = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/util -L $(B)src/components/net
SRC_gfx = $(call rwildcard,$(S)src/components/gfx/,*.rs)
CRATE_gfx = $(S)src/components/gfx/gfx.rc
DONE_gfx = $(B)src/components/gfx/libgfx.dummy

DEPS_servo_gfx = $(CRATE_servo_gfx) $(SRC_servo_gfx) $(DONE_SUBMODULES) $(DONE_servo_util) $(DONE_servo_net)
DEPS_gfx = $(CRATE_gfx) $(SRC_gfx) $(DONE_SUBMODULES) $(DONE_util) $(DONE_net)

RFLAGS_servo = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/servo-gfx -L $(B)src/components/servo-util -L $(B)src/components/servo-net
RFLAGS_script = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/util -L $(B)src/components/net -L $(B)src/components/gfx
WEBIDL_script = $(call rwildcard,$(S)src/components/script/,*.webidl)
AUTOGEN_SRC_script = $(patsubst %.webidl, %Binding.rs, $(WEBIDL_script))
SRC_script = $(call rwildcard,$(S)src/components/script/,*.rs) $(AUTOGEN_SRC_script)
CRATE_script = $(S)src/components/script/script.rc
DONE_script = $(B)src/components/script/libscript.dummy

WEBIDL_servo = $(call rwildcard,$(S)src/components/servo/,*.webidl)
AUTOGEN_SRC_servo = $(patsubst %.webidl, %Binding.rs, $(WEBIDL_servo))
SRC_servo = $(call rwildcard,$(S)src/components/servo/,*.rs) $(AUTOGEN_SRC_servo)
CRATE_servo = $(S)src/components/servo/servo.rc
DEPS_script = $(CRATE_script) $(SRC_script) $(DONE_SUBMODULES) $(DONE_util) $(DONE_net)

DEPS_servo = $(CRATE_servo) $(SRC_servo) $(DONE_SUBMODULES) $(DONE_servo_util) $(DONE_servo_gfx) $(DONE_servo_net)
RFLAGS_servo = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/components/gfx -L $(B)src/components/util -L $(B)src/components/net -L $(B)src/components/script

SRC_servo = $(call rwildcard,$(S)src/components/main/,*.rs)
CRATE_servo = $(S)src/components/main/servo.rc

DEPS_servo = $(CRATE_servo) $(SRC_servo) $(DONE_SUBMODULES) $(DONE_util) $(DONE_gfx) $(DONE_script) $(DONE_net)

# rules that depend on having correct meta-target vars (DEPS_CLEAN, DEPS_servo, etc)
include $(S)mk/check.mk
@@ -211,22 +218,25 @@ all: servo package

# Servo helper libraries

$(DONE_servo_util): $(DEPS_servo_util)
$(RUSTC) $(RFLAGS_servo_util) -o $@ $< && touch $@
$(DONE_util): $(DEPS_util)
$(RUSTC) $(RFLAGS_util) -o $@ $< && touch $@

$(DONE_net): $(DEPS_net)
$(RUSTC) $(RFLAGS_net) -o $@ $< && touch $@

$(DONE_servo_net): $(DEPS_servo_net)
$(RUSTC) $(RFLAGS_servo_net) -o $@ $< && touch $@
$(DONE_gfx): $(DEPS_gfx)
$(RUSTC) $(RFLAGS_gfx) -o $@ $< && touch $@

$(DONE_servo_gfx): $(DEPS_servo_gfx)
$(RUSTC) $(RFLAGS_servo_gfx) -o $@ $< && touch $@
$(DONE_script): $(DEPS_script)
$(RUSTC) $(RFLAGS_script) -o $@ $< && touch $@

BINDINGS_SRC = $(S)/src/components/servo/dom/bindings/codegen
BINDINGS_SRC = $(S)/src/components/script/dom/bindings/codegen

CACHE_DIR = $(BINDINGS_SRC)/_cache

bindinggen_dependencies := $(addprefix $(BINDINGS_SRC)/, BindingGen.py Bindings.conf Configuration.py CodegenRust.py parser/WebIDL.py ParserResults.pkl)

$(AUTOGEN_SRC_servo): %Binding.rs: $(bindinggen_dependencies) \
$(AUTOGEN_SRC_script): %Binding.rs: $(bindinggen_dependencies) \
%.webidl
PYTHONDONTWRITEBYTECODE=1 $(CFG_PYTHON2) $(BINDINGS_SRC)/pythonpath.py \
-I$(BINDINGS_SRC)/parser -I$(BINDINGS_SRC)/ply \
@@ -241,13 +251,13 @@ $(CACHE_DIR)/.done:
@touch $@

$(BINDINGS_SRC)/ParserResults.pkl: $(globalgen_dependencies) \
$(WEBIDL_servo)
$(WEBIDL_script)
PYTHONDONTWRITEBYTECODE=1 $(CFG_PYTHON2) $(BINDINGS_SRC)/pythonpath.py \
-I$(BINDINGS_SRC)/parser -I$(BINDINGS_SRC)/ply \
-D$(BINDINGS_SRC) \
$(BINDINGS_SRC)/GlobalGen.py $(BINDINGS_SRC)/Bindings.conf . \
--cachedir=$(CACHE_DIR) \
$(WEBIDL_servo)
$(WEBIDL_script)

# Servo binaries

@@ -268,7 +278,7 @@ package: servo

else

bindings: $(AUTOGEN_SRC_servo)
bindings: $(AUTOGEN_SRC_script)

.PHONY: package
package:
@@ -1,4 +1,4 @@
# The Servo Parallel Browser Project
zRThe Servo Parallel Browser Project

Servo is a prototype web browser engine written in the [Rust](https://github.com/mozilla/rust)
language. It is currently developed on 64bit OS X and 64bit Linux.
@@ -36,7 +36,7 @@ cd servo
mkdir -p build && cd build
../configure
make && make check
./servo ../src/test/about-mozilla.html
./servo ../src/test/html/about-mozilla.html
```

[issue]: https://github.com/mxcl/homebrew/issues/5117
@@ -449,10 +449,12 @@ do
make_dir ${CFG_BUILD_DIR}src/${i}
done

make_dir ${CFG_BUILD_DIR}src/components/servo-util
make_dir ${CFG_BUILD_DIR}src/components/servo-net
make_dir ${CFG_BUILD_DIR}src/components/servo-gfx
make_dir src/test/ref
make_dir ${CFG_BUILD_DIR}src/components/util
make_dir ${CFG_BUILD_DIR}src/components/net
make_dir ${CFG_BUILD_DIR}src/components/gfx
make_dir ${CFG_BUILD_DIR}src/components/script
make_dir ${CFG_BUILD_DIR}src/components/main
make_dir src/test/html/ref
make_dir src/compiler/rust

# TODO: don't run configure on submodules unless necessary. For an example,
@@ -20,10 +20,10 @@ $(eval $(call DEF_SUBMODULE_TEST_RULES,$(submodule))))
servo-test: $(DEPS_servo)
$(RUSTC) $(RFLAGS_servo) --test -o $@ $<

reftest: $(S)src/reftest/reftest.rs servo
reftest: $(S)src/test/harness/reftest/reftest.rs servo
$(RUSTC) $(RFLAGS_servo) -o $@ $< -L .

contenttest: $(S)src/contenttest/contenttest.rs servo
contenttest: $(S)src/test/harness/contenttest/contenttest.rs servo
$(RUSTC) $(RFLAGS_servo) -o $@ $< -L .

DEPS_CHECK_TARGETS_ALL = $(addprefix check-,$(DEPS_CHECK_ALL))
@@ -39,7 +39,7 @@ check-servo: servo-test
./servo-test $(TESTNAME)

check-ref: reftest
./reftest --source-dir=$(S)/src/test/ref --work-dir=src/test/ref $(TESTNAME)
./reftest --source-dir=$(S)/src/test/html/ref --work-dir=src/test/html/ref $(TESTNAME)

check-content: contenttest
./contenttest --source-dir=$(S)/src/test/content $(TESTNAME)
@@ -25,14 +25,17 @@ clean-fast: $(DEPS_CLEAN_TARGETS_FAST) clean-servo
$(Q)echo "Cleaning targets:"
$(Q)echo "$(filter-out $(SLOW_BUILDS),$(DEPS_CLEAN_ALL))"

clean-servo-util:
cd $(B)/src/components/servo-util/ && rm -rf libservo_util*.dylib $(DONE_servo_util)
clean-util:
cd $(B)/src/components/util/ && rm -rf libservo_util*.dylib $(DONE_servo_util)

clean-servo-net:
cd $(B)/src/components/servo-net/ && rm -rf libservo_net*.dylib $(DONE_servo_net)
clean-net:
cd $(B)/src/components/net/ && rm -rf libservo_net*.dylib $(DONE_servo_net)

clean-servo-gfx:
cd $(B)/src/components/servo-gfx/ && rm -rf libservo_gfx*.dylib $(DONE_servo_gfx)
clean-gfx:
cd $(B)/src/components/gfx/ && rm -rf libservo_gfx*.dylib $(DONE_servo_gfx)

clean-servo: clean-servo-gfx clean-servo-util clean-servo-net
clean-script:
cd $(B)/src/components/script/ && rm -rf libservo_script*.dylib $(DONE_servo_script)

clean-servo: clean-gfx clean-util clean-net clean-script
rm -f servo servo-test
@@ -3,12 +3,10 @@ crate or library.

## Servo components

* `components/contenttest`: JavaScript test runner.
* `components/reftest`: Reference (layout) test runner.
* `components/servo`: The top-level Servo crate. Contains compositing, DOM, layout, and script.
* `components/servo-gfx`: Graphics rendering, fonts, and text shaping.
* `components/servo-net`: Networking, caching, image decoding.
* `components/servo-util`: Various utility functions used by other Servo components.
* `components/gfx`: Graphics rendering, fonts, and text shaping.
* `components/main`: The top-level Servo crate. Contains compositing, DOM, layout, and script.
* `components/net`: Networking, caching, image decoding.
* `components/util`: Various utility functions used by other Servo components.

## The Rust compiler

@@ -60,9 +58,14 @@ they are designed to be useful in other Rust projects.
* `platform/macos/rust-core-text`: Bindings to Core Text.
* `platform/macos/rust-io-surface`: Bindings to the `IOSurface` library.

## Tests

* `test/harness/contenttest`: JavaScript test runner.
* `test/harness/reftest`: Reference (layout) test runner.
* `test/html`: Test cases.

## Miscellaneous

* `etc`: Various scripts and files that don't belong anywhere else.
* `etc/patches`: Patches for upstream libraries.
* `test`: Test cases.

File renamed without changes.
@@ -24,7 +24,6 @@ pub struct LayerBufferSet {
/// The interface used to by the renderer to acquire draw targets for each rendered frame and
/// submit them to be drawn to the display.
pub trait Compositor {
fn begin_drawing(&self, next_dt: comm::Chan<LayerBufferSet>);
fn draw(&self, next_dt: comm::Chan<LayerBufferSet>, draw_me: LayerBufferSet);
fn paint(&self, layer_buffer_set: LayerBufferSet);
}

@@ -0,0 +1,152 @@
/* 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/. */

//! Servo heavily uses display lists, which are retained-mode lists of rendering commands to
/// perform. Using a list instead of rendering elements in immediate mode allows transforms, hit
/// testing, and invalidation to be performed using the same primitives as painting. It also allows
/// Servo to aggressively cull invisible and out-of-bounds rendering elements, to reduce overdraw.
/// Finally, display lists allow tiles to be farmed out onto multiple CPUs and rendered in
/// parallel (although this benefit does not apply to GPU-based rendering).
///
/// Display items describe relatively high-level drawing operations (for example, entire borders
/// and shadows instead of lines and blur operations), to reduce the amount of allocation required.
/// They are therefore not exactly analogous to constructs like Skia pictures, which consist of
/// low-level drawing primitives.

use color::Color;
use geometry::Au;
use render_context::RenderContext;
use text::SendableTextRun;

use geom::{Point2D, Rect, Size2D};
use servo_net::image::base::Image;
use servo_util::range::Range;
use std::arc::ARC;
use std::arc;

/// A list of rendering operations to be performed.
pub struct DisplayList {
priv list: ~[DisplayItem]
}

impl DisplayList {
/// Creates a new display list.
pub fn new() -> DisplayList {
DisplayList {
list: ~[]
}
}

/// Appends the given item to the display list.
pub fn append_item(&mut self, item: DisplayItem) {
// FIXME(Issue #150): crashes
//debug!("Adding display item %u: %?", self.len(), item);
self.list.push(item)
}

/// Draws the display list into the given render context.
pub fn draw_into_context(&self, render_context: &RenderContext) {
debug!("Beginning display list.");
for self.list.each |item| {
// FIXME(Issue #150): crashes
//debug!("drawing %?", *item);
item.draw_into_context(render_context)
}
debug!("Ending display list.")
}
}

/// One drawing command in the list.
pub enum DisplayItem {
SolidColorDisplayItemClass(~SolidColorDisplayItem),
TextDisplayItemClass(~TextDisplayItem),
ImageDisplayItemClass(~ImageDisplayItem),
BorderDisplayItemClass(~BorderDisplayItem),
}

/// Information common to all display items.
pub struct BaseDisplayItem {
/// The boundaries of the display item.
///
/// TODO: Which coordinate system should this use?
bounds: Rect<Au>,
}

/// Renders a solid color.
pub struct SolidColorDisplayItem {
base: BaseDisplayItem,
color: Color,
}

/// Renders text.
pub struct TextDisplayItem {
base: BaseDisplayItem,
text_run: ~SendableTextRun,
range: Range,
color: Color,
}

/// Renders an image.
pub struct ImageDisplayItem {
base: BaseDisplayItem,
image: ARC<~Image>,
}

/// Renders a border.
pub struct BorderDisplayItem {
base: BaseDisplayItem,
/// The width of the border.
width: Au,
/// The color of the border.
color: Color,
}

impl DisplayItem {
/// Renders this display item into the given render context.
fn draw_into_context(&self, render_context: &RenderContext) {
match *self {
SolidColorDisplayItemClass(ref solid_color) => {
render_context.draw_solid_color(&solid_color.base.bounds, solid_color.color)
}

TextDisplayItemClass(ref text) => {
debug!("Drawing text at %?.", text.base.bounds);

// FIXME(pcwalton): Allocating? Why?
let new_run = @text.text_run.deserialize(render_context.font_ctx);

let font = new_run.font;
let origin = text.base.bounds.origin;
let baseline_origin = Point2D(origin.x, origin.y + font.metrics.ascent);

font.draw_text_into_context(render_context,
new_run,
&text.range,
baseline_origin,
text.color);

if new_run.underline {
// TODO(eatkinson): Use the font metrics to properly position the underline
// bar.
let width = text.base.bounds.size.width;
let underline_size = font.metrics.underline_size;
let underline_bounds = Rect(Point2D(baseline_origin.x, baseline_origin.y),
Size2D(width, underline_size));
render_context.draw_solid_color(&underline_bounds, text.color);
}
}

ImageDisplayItemClass(ref image_item) => {
debug!("Drawing image at %?.", image_item.base.bounds);

render_context.draw_image(image_item.base.bounds, image_item.image.clone())
}

BorderDisplayItemClass(ref border) => {
render_context.draw_border(&border.base.bounds, border.width, border.color)
}
}
}
}

File renamed without changes.
File renamed without changes.
File renamed without changes.
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.