mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Merge pull request #431 from pcwalton/refactor-compositor
Refactor compositor
This commit is contained in:
commit
cdc99a8572
38 changed files with 510 additions and 484 deletions
18
Makefile.in
18
Makefile.in
|
@ -168,21 +168,28 @@ DONE_servo_util = $(B)src/servo-util/libservoutil.dummy
|
||||||
|
|
||||||
DEPS_servo_util = $(CRATE_servo_util) $(SRC_servo_util) $(DONE_SUBMODULES)
|
DEPS_servo_util = $(CRATE_servo_util) $(SRC_servo_util) $(DONE_SUBMODULES)
|
||||||
|
|
||||||
RFLAGS_servo_gfx = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/servo-util
|
RFLAGS_servo_net = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/servo-util
|
||||||
|
SRC_servo_net = $(call rwildcard,$(S)src/servo-net/,*.rs)
|
||||||
|
CRATE_servo_net = $(S)src/servo-net/servo_net.rc
|
||||||
|
DONE_servo_net = $(B)src/servo-net/libservonet.dummy
|
||||||
|
|
||||||
|
DEPS_servo_net = $(CRATE_servo_net) $(SRC_servo_net) $(DONE_SUBMODULES) $(DONE_servo_util)
|
||||||
|
|
||||||
|
RFLAGS_servo_gfx = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/servo-util -L $(B)src/servo-net
|
||||||
SRC_servo_gfx = $(call rwildcard,$(S)src/servo-gfx/,*.rs)
|
SRC_servo_gfx = $(call rwildcard,$(S)src/servo-gfx/,*.rs)
|
||||||
CRATE_servo_gfx = $(S)src/servo-gfx/servo_gfx.rc
|
CRATE_servo_gfx = $(S)src/servo-gfx/servo_gfx.rc
|
||||||
DONE_servo_gfx = $(B)src/servo-gfx/libservogfx.dummy
|
DONE_servo_gfx = $(B)src/servo-gfx/libservogfx.dummy
|
||||||
|
|
||||||
DEPS_servo_gfx = $(CRATE_servo_gfx) $(SRC_servo_gfx) $(DONE_SUBMODULES) $(DONE_servo_util)
|
DEPS_servo_gfx = $(CRATE_servo_gfx) $(SRC_servo_gfx) $(DONE_SUBMODULES) $(DONE_servo_util) $(DONE_servo_net)
|
||||||
|
|
||||||
RFLAGS_servo = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/servo-gfx -L $(B)src/servo-util
|
RFLAGS_servo = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/servo-gfx -L $(B)src/servo-util -L $(B)src/servo-net
|
||||||
|
|
||||||
WEBIDL_servo = $(call rwildcard,$(S)src/servo/,*.webidl)
|
WEBIDL_servo = $(call rwildcard,$(S)src/servo/,*.webidl)
|
||||||
AUTOGEN_SRC_servo = $(patsubst %.webidl, %Binding.rs, $(WEBIDL_servo))
|
AUTOGEN_SRC_servo = $(patsubst %.webidl, %Binding.rs, $(WEBIDL_servo))
|
||||||
SRC_servo = $(call rwildcard,$(S)src/servo/,*.rs) $(AUTOGEN_SRC_servo)
|
SRC_servo = $(call rwildcard,$(S)src/servo/,*.rs) $(AUTOGEN_SRC_servo)
|
||||||
CRATE_servo = $(S)src/servo/servo.rc
|
CRATE_servo = $(S)src/servo/servo.rc
|
||||||
|
|
||||||
DEPS_servo = $(CRATE_servo) $(SRC_servo) $(DONE_SUBMODULES) $(DONE_servo_util) $(DONE_servo_gfx)
|
DEPS_servo = $(CRATE_servo) $(SRC_servo) $(DONE_SUBMODULES) $(DONE_servo_util) $(DONE_servo_gfx) $(DONE_servo_net)
|
||||||
|
|
||||||
# rules that depend on having correct meta-target vars (DEPS_CLEAN, DEPS_servo, etc)
|
# rules that depend on having correct meta-target vars (DEPS_CLEAN, DEPS_servo, etc)
|
||||||
include $(S)mk/check.mk
|
include $(S)mk/check.mk
|
||||||
|
@ -197,6 +204,9 @@ all: servo package
|
||||||
$(DONE_servo_util): $(DEPS_servo_util)
|
$(DONE_servo_util): $(DEPS_servo_util)
|
||||||
$(RUSTC) $(RFLAGS_servo_util) -o $@ $< && touch $@
|
$(RUSTC) $(RFLAGS_servo_util) -o $@ $< && touch $@
|
||||||
|
|
||||||
|
$(DONE_servo_net): $(DEPS_servo_net)
|
||||||
|
$(RUSTC) $(RFLAGS_servo_net) -o $@ $< && touch $@
|
||||||
|
|
||||||
$(DONE_servo_gfx): $(DEPS_servo_gfx)
|
$(DONE_servo_gfx): $(DEPS_servo_gfx)
|
||||||
$(RUSTC) $(RFLAGS_servo_gfx) -o $@ $< && touch $@
|
$(RUSTC) $(RFLAGS_servo_gfx) -o $@ $< && touch $@
|
||||||
|
|
||||||
|
|
1
configure
vendored
1
configure
vendored
|
@ -419,6 +419,7 @@ do
|
||||||
done
|
done
|
||||||
|
|
||||||
make_dir ${CFG_BUILD_DIR}src/servo-util
|
make_dir ${CFG_BUILD_DIR}src/servo-util
|
||||||
|
make_dir ${CFG_BUILD_DIR}src/servo-net
|
||||||
make_dir ${CFG_BUILD_DIR}src/servo-gfx
|
make_dir ${CFG_BUILD_DIR}src/servo-gfx
|
||||||
make_dir src/test/ref
|
make_dir src/test/ref
|
||||||
make_dir src/rust
|
make_dir src/rust
|
||||||
|
|
|
@ -21,10 +21,8 @@ pub struct LayerBufferSet {
|
||||||
buffers: ~[LayerBuffer]
|
buffers: ~[LayerBuffer]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// The interface used to by the renderer to acquire draw targets for each rendered frame and
|
||||||
The interface used to by the renderer to aquire draw targets for
|
/// submit them to be drawn to the display.
|
||||||
each rendered frame and submit them to be drawn to the display
|
|
||||||
*/
|
|
||||||
pub trait Compositor {
|
pub trait Compositor {
|
||||||
fn begin_drawing(&self, next_dt: comm::Chan<LayerBufferSet>);
|
fn begin_drawing(&self, next_dt: comm::Chan<LayerBufferSet>);
|
||||||
fn draw(&self, next_dt: comm::Chan<LayerBufferSet>, +draw_me: LayerBufferSet);
|
fn draw(&self, next_dt: comm::Chan<LayerBufferSet>, +draw_me: LayerBufferSet);
|
||||||
|
|
|
@ -4,15 +4,15 @@
|
||||||
|
|
||||||
use color::{Color, rgb};
|
use color::{Color, rgb};
|
||||||
use geometry::Au;
|
use geometry::Au;
|
||||||
use image::base::Image;
|
|
||||||
use render_context::RenderContext;
|
use render_context::RenderContext;
|
||||||
use text::SendableTextRun;
|
use text::SendableTextRun;
|
||||||
use servo_util::range::Range;
|
|
||||||
|
|
||||||
use clone_arc = std::arc::clone;
|
use clone_arc = std::arc::clone;
|
||||||
use geom::Rect;
|
use geom::Rect;
|
||||||
use geom::Point2D;
|
use geom::Point2D;
|
||||||
use std::arc::ARC;
|
use std::arc::ARC;
|
||||||
|
use servo_net::image::base::Image;
|
||||||
|
use servo_util::range::Range;
|
||||||
|
|
||||||
struct DisplayItemData {
|
struct DisplayItemData {
|
||||||
bounds : Rect<Au>, // TODO: whose coordinate system should this use?
|
bounds : Rect<Au>, // TODO: whose coordinate system should this use?
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
/* 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 core::io::WriterUtil;
|
|
||||||
use surface;
|
|
||||||
|
|
||||||
fn encode(writer: @io::Writer, surface: &surface::ImageSurface) {
|
|
||||||
assert!(surface.format == surface::fo_rgba_8888);
|
|
||||||
|
|
||||||
writer.write_u8(0u8); // identsize
|
|
||||||
writer.write_u8(0u8); // colourmaptype
|
|
||||||
writer.write_u8(2u8); // imagetype
|
|
||||||
|
|
||||||
writer.write_le_u16(0u16); // colourmapstart
|
|
||||||
writer.write_le_u16(0u16); // colourmaplength
|
|
||||||
writer.write_u8(16u8); // colourmapbits
|
|
||||||
|
|
||||||
writer.write_le_u16(0u16); // xstart
|
|
||||||
writer.write_le_u16(0u16); // ystart
|
|
||||||
writer.write_le_u16(surface.size.width as u16); // width
|
|
||||||
writer.write_le_u16(surface.size.height as u16); // height
|
|
||||||
writer.write_u8(32u8); // bits
|
|
||||||
writer.write_u8(0x30u8); // descriptor
|
|
||||||
|
|
||||||
writer.write(surface.buffer);
|
|
||||||
}
|
|
||||||
|
|
|
@ -10,17 +10,11 @@ use azure::azure_hl::{CoreGraphicsAcceleratedBackend, Direct2DBackend, SkiaBacke
|
||||||
|
|
||||||
pub struct Opts {
|
pub struct Opts {
|
||||||
urls: ~[~str],
|
urls: ~[~str],
|
||||||
render_mode: RenderMode,
|
|
||||||
render_backend: BackendType,
|
render_backend: BackendType,
|
||||||
n_render_threads: uint,
|
n_render_threads: uint,
|
||||||
tile_size: uint,
|
tile_size: uint,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum RenderMode {
|
|
||||||
Screen,
|
|
||||||
Png(~str)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(non_implicitly_copyable_typarams)]
|
#[allow(non_implicitly_copyable_typarams)]
|
||||||
pub fn from_cmdline_args(args: &[~str]) -> Opts {
|
pub fn from_cmdline_args(args: &[~str]) -> Opts {
|
||||||
use std::getopts;
|
use std::getopts;
|
||||||
|
@ -45,11 +39,6 @@ pub fn from_cmdline_args(args: &[~str]) -> Opts {
|
||||||
copy opt_match.free
|
copy opt_match.free
|
||||||
};
|
};
|
||||||
|
|
||||||
let render_mode = match getopts::opt_maybe_str(&opt_match, ~"o") {
|
|
||||||
Some(output_file) => Png(output_file),
|
|
||||||
None => Screen,
|
|
||||||
};
|
|
||||||
|
|
||||||
let render_backend = match getopts::opt_maybe_str(&opt_match, ~"r") {
|
let render_backend = match getopts::opt_maybe_str(&opt_match, ~"r") {
|
||||||
Some(backend_str) => {
|
Some(backend_str) => {
|
||||||
if backend_str == ~"direct2d" {
|
if backend_str == ~"direct2d" {
|
||||||
|
@ -81,7 +70,6 @@ pub fn from_cmdline_args(args: &[~str]) -> Opts {
|
||||||
|
|
||||||
Opts {
|
Opts {
|
||||||
urls: urls,
|
urls: urls,
|
||||||
render_mode: render_mode,
|
|
||||||
render_backend: render_backend,
|
render_backend: render_backend,
|
||||||
n_render_threads: n_render_threads,
|
n_render_threads: n_render_threads,
|
||||||
tile_size: tile_size,
|
tile_size: tile_size,
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
use compositor::LayerBuffer;
|
use compositor::LayerBuffer;
|
||||||
use font_context::FontContext;
|
use font_context::FontContext;
|
||||||
use geometry::Au;
|
use geometry::Au;
|
||||||
use image::base::Image;
|
|
||||||
use opts::Opts;
|
use opts::Opts;
|
||||||
|
|
||||||
use azure::azure_hl::{B8G8R8A8, Color, ColorPattern, DrawOptions};
|
use azure::azure_hl::{B8G8R8A8, Color, ColorPattern, DrawOptions};
|
||||||
|
@ -15,6 +14,7 @@ use core::libc::types::common::c99::uint16_t;
|
||||||
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 servo_net::image::base::Image;
|
||||||
use std::arc;
|
use std::arc;
|
||||||
use std::arc::ARC;
|
use std::arc::ARC;
|
||||||
|
|
||||||
|
|
|
@ -11,13 +11,13 @@ use geom::matrix2d::Matrix2D;
|
||||||
use opts::Opts;
|
use opts::Opts;
|
||||||
use render_context::RenderContext;
|
use render_context::RenderContext;
|
||||||
use render_layers::{RenderLayer, render_layers};
|
use render_layers::{RenderLayer, render_layers};
|
||||||
use resource::util::spawn_listener;
|
|
||||||
use servo_util::time::time;
|
|
||||||
|
|
||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
use core::comm::{Port, SharedChan};
|
use core::comm::{Port, SharedChan};
|
||||||
use core::task::SingleThreaded;
|
use core::task::SingleThreaded;
|
||||||
use std::task_pool::TaskPool;
|
use std::task_pool::TaskPool;
|
||||||
|
use servo_net::util::spawn_listener;
|
||||||
|
use servo_util::time::time;
|
||||||
|
|
||||||
pub enum Msg {
|
pub enum Msg {
|
||||||
RenderMsg(RenderLayer),
|
RenderMsg(RenderLayer),
|
||||||
|
|
|
@ -13,6 +13,7 @@ extern mod geom;
|
||||||
extern mod http_client;
|
extern mod http_client;
|
||||||
extern mod stb_image;
|
extern mod stb_image;
|
||||||
extern mod std;
|
extern mod std;
|
||||||
|
extern mod servo_net;
|
||||||
extern mod servo_util (name = "servo_util");
|
extern mod servo_util (name = "servo_util");
|
||||||
|
|
||||||
// Eventually we would like the shaper to be pluggable, as many operating systems have their own
|
// Eventually we would like the shaper to be pluggable, as many operating systems have their own
|
||||||
|
@ -57,22 +58,7 @@ pub mod opts;
|
||||||
#[path="platform/mod.rs"]
|
#[path="platform/mod.rs"]
|
||||||
pub mod platform;
|
pub mod platform;
|
||||||
|
|
||||||
// Images
|
|
||||||
pub mod image {
|
|
||||||
pub mod base;
|
|
||||||
pub mod holder;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Text
|
// Text
|
||||||
#[path = "text/mod.rs"]
|
#[path = "text/mod.rs"]
|
||||||
pub mod text;
|
pub mod text;
|
||||||
|
|
||||||
// FIXME: Blech. This does not belong in the GFX module.
|
|
||||||
pub mod resource {
|
|
||||||
pub mod file_loader;
|
|
||||||
pub mod http_loader;
|
|
||||||
pub mod image_cache_task;
|
|
||||||
pub mod local_image_cache;
|
|
||||||
pub mod resource_task;
|
|
||||||
pub mod util;
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,16 +2,17 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use core::task::spawn;
|
use resource_task::{Done, LoaderTask, Payload};
|
||||||
use resource::resource_task::{Payload, Done, LoaderTask};
|
|
||||||
use core::io::{file_reader, ReaderUtil};
|
use core::io::{ReaderUtil, file_reader};
|
||||||
|
use core::task;
|
||||||
|
|
||||||
static READ_SIZE: uint = 1024;
|
static READ_SIZE: uint = 1024;
|
||||||
|
|
||||||
pub fn factory() -> LoaderTask {
|
pub fn factory() -> LoaderTask {
|
||||||
let f: LoaderTask = |url, progress_chan| {
|
let f: LoaderTask = |url, progress_chan| {
|
||||||
assert!(url.scheme == ~"file");
|
assert!("file" == url.scheme);
|
||||||
do spawn {
|
do task::spawn {
|
||||||
// FIXME: Resolve bug prevents us from moving the path out of the URL.
|
// FIXME: Resolve bug prevents us from moving the path out of the URL.
|
||||||
match file_reader(&Path(url.path)) {
|
match file_reader(&Path(url.path)) {
|
||||||
Ok(reader) => {
|
Ok(reader) => {
|
|
@ -2,18 +2,19 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use resource_task::{Payload, Done, LoaderTask};
|
||||||
|
|
||||||
use core::comm::SharedChan;
|
use core::comm::SharedChan;
|
||||||
use core::task::spawn;
|
use core::task;
|
||||||
use resource::resource_task::{Payload, Done, LoaderTask};
|
use http_client::uv_http_request;
|
||||||
use http_client;
|
use http_client;
|
||||||
use http_client::{uv_http_request};
|
|
||||||
|
|
||||||
pub fn factory() -> LoaderTask {
|
pub fn factory() -> LoaderTask {
|
||||||
let f: LoaderTask = |url, progress_chan| {
|
let f: LoaderTask = |url, progress_chan| {
|
||||||
assert!(url.scheme == ~"http");
|
assert!(url.scheme == ~"http");
|
||||||
|
|
||||||
let progress_chan = SharedChan::new(progress_chan);
|
let progress_chan = SharedChan::new(progress_chan);
|
||||||
do spawn {
|
do task::spawn {
|
||||||
debug!("http_loader: requesting via http: %?", url.clone());
|
debug!("http_loader: requesting via http: %?", url.clone());
|
||||||
let mut request = uv_http_request(url.clone());
|
let mut request = uv_http_request(url.clone());
|
||||||
let errored = @mut false;
|
let errored = @mut false;
|
|
@ -20,7 +20,6 @@ pub fn test_image_bin() -> ~[u8] {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_from_memory(buffer: &[u8]) -> Option<Image> {
|
pub fn load_from_memory(buffer: &[u8]) -> Option<Image> {
|
||||||
|
|
||||||
// Can't remember why we do this. Maybe it's what cairo wants
|
// Can't remember why we do this. Maybe it's what cairo wants
|
||||||
static FORCE_DEPTH: uint = 4;
|
static FORCE_DEPTH: uint = 4;
|
||||||
|
|
|
@ -3,21 +3,20 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use image::base::Image;
|
use image::base::Image;
|
||||||
use resource::image_cache_task::{ImageReady, ImageNotReady, ImageFailed};
|
use image_cache_task::{ImageReady, ImageNotReady, ImageFailed};
|
||||||
use resource::local_image_cache::LocalImageCache;
|
use local_image_cache::LocalImageCache;
|
||||||
|
|
||||||
use core::util::replace;
|
use core::util::replace;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
use std::net::url::Url;
|
use std::net::url::Url;
|
||||||
use std::arc::{ARC, clone, get};
|
use std::arc::{ARC, clone, get};
|
||||||
|
|
||||||
// FIXME: Nasty coupling to resource here. This should probably be factored out into an interface
|
// FIXME: Nasty coupling here This will be a problem if we want to factor out image handling from
|
||||||
// and use dependency injection.
|
// the network stack. This should probably be factored out into an interface and use dependency
|
||||||
|
// injection.
|
||||||
|
|
||||||
/** A struct to store image data. The image will be loaded once, the
|
/// A struct to store image data. The image will be loaded once the first time it is requested,
|
||||||
first time it is requested, and an arc will be stored. Clones of
|
/// and an ARC will be stored. Clones of this ARC are given out on demand.
|
||||||
this arc are given out on demand.
|
|
||||||
*/
|
|
||||||
pub struct ImageHolder {
|
pub struct ImageHolder {
|
||||||
url: Url,
|
url: Url,
|
||||||
image: Option<ARC<~Image>>,
|
image: Option<ARC<~Image>>,
|
||||||
|
@ -46,18 +45,16 @@ pub impl ImageHolder {
|
||||||
holder
|
holder
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// This version doesn't perform any computation, but may be stale w.r.t. newly-available image
|
||||||
This version doesn't perform any computation, but may be stale w.r.t.
|
/// data that determines size.
|
||||||
newly-available image data that determines size.
|
///
|
||||||
|
/// The intent is that the impure version is used during layout when dimensions are used for
|
||||||
The intent is that the impure version is used during layout when
|
/// computing layout.
|
||||||
dimensions are used for computing layout.
|
|
||||||
*/
|
|
||||||
fn size(&self) -> Size2D<int> {
|
fn size(&self) -> Size2D<int> {
|
||||||
self.cached_size
|
self.cached_size
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Query and update current image size */
|
/// Query and update the current image size.
|
||||||
fn get_size(&mut self) -> Option<Size2D<int>> {
|
fn get_size(&mut self) -> Option<Size2D<int>> {
|
||||||
debug!("get_size() %?", self.url);
|
debug!("get_size() %?", self.url);
|
||||||
match self.get_image() {
|
match self.get_image() {
|
||||||
|
@ -103,3 +100,4 @@ pub impl ImageHolder {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
|
@ -3,46 +3,46 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use image::base::{Image, load_from_memory};
|
use image::base::{Image, load_from_memory};
|
||||||
use resource::resource_task;
|
use resource_task;
|
||||||
use resource::resource_task::ResourceTask;
|
use resource_task::ResourceTask;
|
||||||
use servo_util::url::{UrlMap, url_map};
|
use servo_util::url::{UrlMap, url_map};
|
||||||
|
|
||||||
use clone_arc = std::arc::clone;
|
use clone_arc = std::arc::clone;
|
||||||
|
use core::cell::Cell;
|
||||||
use core::comm::{Chan, Port, SharedChan, stream};
|
use core::comm::{Chan, Port, SharedChan, stream};
|
||||||
use core::task::spawn;
|
use core::task::spawn;
|
||||||
use core::to_str::ToStr;
|
use core::to_str::ToStr;
|
||||||
use core::util::replace;
|
use core::util::replace;
|
||||||
use std::arc::ARC;
|
use std::arc::ARC;
|
||||||
use std::net::url::Url;
|
use std::net::url::Url;
|
||||||
use core::cell::Cell;
|
|
||||||
|
|
||||||
pub enum Msg {
|
pub enum Msg {
|
||||||
/// Tell the cache that we may need a particular image soon. Must be posted
|
/// Tell the cache that we may need a particular image soon. Must be posted
|
||||||
/// before Decode
|
/// before Decode
|
||||||
pub Prefetch(Url),
|
Prefetch(Url),
|
||||||
|
|
||||||
// FIXME: We can probably get rid of this Cell now
|
// FIXME: We can probably get rid of this Cell now
|
||||||
/// Used be the prefetch tasks to post back image binaries
|
/// Used be the prefetch tasks to post back image binaries
|
||||||
priv StorePrefetchedImageData(Url, Result<Cell<~[u8]>, ()>),
|
priv StorePrefetchedImageData(Url, Result<Cell<~[u8]>, ()>),
|
||||||
|
|
||||||
/// Tell the cache to decode an image. Must be posted before GetImage/WaitForImage
|
/// Tell the cache to decode an image. Must be posted before GetImage/WaitForImage
|
||||||
pub Decode(Url),
|
Decode(Url),
|
||||||
|
|
||||||
/// Used by the decoder tasks to post decoded images back to the cache
|
/// Used by the decoder tasks to post decoded images back to the cache
|
||||||
priv StoreImage(Url, Option<ARC<~Image>>),
|
priv StoreImage(Url, Option<ARC<~Image>>),
|
||||||
|
|
||||||
/// Request an Image object for a URL. If the image is not is not immediately
|
/// Request an Image object for a URL. If the image is not is not immediately
|
||||||
/// available then ImageNotReady is returned.
|
/// available then ImageNotReady is returned.
|
||||||
pub GetImage(Url, Chan<ImageResponseMsg>),
|
GetImage(Url, Chan<ImageResponseMsg>),
|
||||||
|
|
||||||
/// Wait for an image to become available (or fail to load).
|
/// Wait for an image to become available (or fail to load).
|
||||||
pub WaitForImage(Url, Chan<ImageResponseMsg>),
|
WaitForImage(Url, Chan<ImageResponseMsg>),
|
||||||
|
|
||||||
/// For testing
|
/// For testing
|
||||||
priv OnMsg(~fn(msg: &Msg)),
|
priv OnMsg(~fn(msg: &Msg)),
|
||||||
|
|
||||||
/// Clients must wait for a response before shutting down the ResourceTask
|
/// Clients must wait for a response before shutting down the ResourceTask
|
||||||
pub Exit(Chan<()>)
|
Exit(Chan<()>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum ImageResponseMsg {
|
pub enum ImageResponseMsg {
|
||||||
|
@ -54,9 +54,9 @@ pub enum ImageResponseMsg {
|
||||||
impl ImageResponseMsg {
|
impl ImageResponseMsg {
|
||||||
fn clone(&self) -> ImageResponseMsg {
|
fn clone(&self) -> ImageResponseMsg {
|
||||||
match *self {
|
match *self {
|
||||||
ImageReady(ref img) => ImageReady(clone_arc(img)),
|
ImageReady(ref img) => ImageReady(clone_arc(img)),
|
||||||
ImageNotReady => ImageNotReady,
|
ImageNotReady => ImageNotReady,
|
||||||
ImageFailed => ImageFailed
|
ImageFailed => ImageFailed,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,17 +65,16 @@ impl Eq for ImageResponseMsg {
|
||||||
fn eq(&self, other: &ImageResponseMsg) -> bool {
|
fn eq(&self, other: &ImageResponseMsg) -> bool {
|
||||||
// FIXME: Bad copies
|
// FIXME: Bad copies
|
||||||
match (self.clone(), other.clone()) {
|
match (self.clone(), other.clone()) {
|
||||||
(ImageReady(*), ImageReady(*)) => fail!(~"unimplemented comparison"),
|
(ImageReady(*), ImageReady(*)) => fail!(~"unimplemented comparison"),
|
||||||
(ImageNotReady, ImageNotReady) => true,
|
(ImageNotReady, ImageNotReady) => true,
|
||||||
(ImageFailed, ImageFailed) => true,
|
(ImageFailed, ImageFailed) => true,
|
||||||
|
|
||||||
(ImageReady(*), _)
|
(ImageReady(*), _) | (ImageNotReady, _) | (ImageFailed, _) => false
|
||||||
| (ImageNotReady, _)
|
|
||||||
| (ImageFailed, _) => false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ne(&self, other: &ImageResponseMsg) -> bool {
|
fn ne(&self, other: &ImageResponseMsg) -> bool {
|
||||||
return !(*self).eq(other);
|
!(*self).eq(other)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,9 +86,8 @@ pub fn ImageCacheTask(resource_task: ResourceTask) -> ImageCacheTask {
|
||||||
ImageCacheTask_(resource_task, default_decoder_factory)
|
ImageCacheTask_(resource_task, default_decoder_factory)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ImageCacheTask_(resource_task: ResourceTask,
|
pub fn ImageCacheTask_(resource_task: ResourceTask, decoder_factory: DecoderFactory)
|
||||||
decoder_factory: DecoderFactory)
|
-> ImageCacheTask {
|
||||||
-> ImageCacheTask {
|
|
||||||
// FIXME: Doing some dancing to avoid copying decoder_factory, our test
|
// FIXME: Doing some dancing to avoid copying decoder_factory, our test
|
||||||
// version of which contains an uncopyable type which rust will currently
|
// version of which contains an uncopyable type which rust will currently
|
||||||
// copy unsoundly
|
// copy unsoundly
|
||||||
|
@ -140,7 +138,7 @@ fn SyncImageCacheTask(resource_task: ResourceTask) -> ImageCacheTask {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return SharedChan::new(chan);
|
SharedChan::new(chan)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ImageCache {
|
struct ImageCache {
|
||||||
|
@ -175,9 +173,7 @@ enum AfterPrefetch {
|
||||||
|
|
||||||
#[allow(non_implicitly_copyable_typarams)]
|
#[allow(non_implicitly_copyable_typarams)]
|
||||||
impl ImageCache {
|
impl ImageCache {
|
||||||
|
|
||||||
pub fn run(&mut self) {
|
pub fn run(&mut self) {
|
||||||
|
|
||||||
let mut msg_handlers: ~[~fn(msg: &Msg)] = ~[];
|
let mut msg_handlers: ~[~fn(msg: &Msg)] = ~[];
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
@ -397,26 +393,12 @@ impl ImageCache {
|
||||||
|
|
||||||
priv fn get_image(&self, url: Url, response: Chan<ImageResponseMsg>) {
|
priv fn get_image(&self, url: Url, response: Chan<ImageResponseMsg>) {
|
||||||
match self.get_state(copy url) {
|
match self.get_state(copy url) {
|
||||||
Init => fail!(~"request for image before prefetch"),
|
Init => fail!(~"request for image before prefetch"),
|
||||||
|
Prefetching(DoDecode) => response.send(ImageNotReady),
|
||||||
Prefetching(DoDecode) => {
|
Prefetching(DoNotDecode) | Prefetched(*) => fail!(~"request for image before decode"),
|
||||||
response.send(ImageNotReady);
|
Decoding => response.send(ImageNotReady),
|
||||||
}
|
Decoded(image) => response.send(ImageReady(clone_arc(image))),
|
||||||
|
Failed => response.send(ImageFailed),
|
||||||
Prefetching(DoNotDecode)
|
|
||||||
| Prefetched(*) => fail!(~"request for image before decode"),
|
|
||||||
|
|
||||||
Decoding => {
|
|
||||||
response.send(ImageNotReady)
|
|
||||||
}
|
|
||||||
|
|
||||||
Decoded(image) => {
|
|
||||||
response.send(ImageReady(clone_arc(image)));
|
|
||||||
}
|
|
||||||
|
|
||||||
Failed => {
|
|
||||||
response.send(ImageFailed);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,7 +487,6 @@ fn mock_resource_task(on_load: ~fn(resource: Chan<resource_task::ProgressMsg>))
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_exit_on_request() {
|
fn should_exit_on_request() {
|
||||||
|
|
||||||
let mock_resource_task = mock_resource_task(|_response| () );
|
let mock_resource_task = mock_resource_task(|_response| () );
|
||||||
|
|
||||||
let image_cache_task = ImageCacheTask(mock_resource_task);
|
let image_cache_task = ImageCacheTask(mock_resource_task);
|
||||||
|
@ -518,7 +499,6 @@ fn should_exit_on_request() {
|
||||||
#[test]
|
#[test]
|
||||||
#[should_fail]
|
#[should_fail]
|
||||||
fn should_fail_if_unprefetched_image_is_requested() {
|
fn should_fail_if_unprefetched_image_is_requested() {
|
||||||
|
|
||||||
let mock_resource_task = mock_resource_task(|_response| () );
|
let mock_resource_task = mock_resource_task(|_response| () );
|
||||||
|
|
||||||
let image_cache_task = ImageCacheTask(mock_resource_task);
|
let image_cache_task = ImageCacheTask(mock_resource_task);
|
||||||
|
@ -552,7 +532,6 @@ fn should_request_url_from_resource_task_on_prefetch() {
|
||||||
#[test]
|
#[test]
|
||||||
#[should_fail]
|
#[should_fail]
|
||||||
fn should_fail_if_requesting_decode_of_an_unprefetched_image() {
|
fn should_fail_if_requesting_decode_of_an_unprefetched_image() {
|
||||||
|
|
||||||
let mock_resource_task = mock_resource_task(|_response| () );
|
let mock_resource_task = mock_resource_task(|_response| () );
|
||||||
|
|
||||||
let image_cache_task = ImageCacheTask(mock_resource_task);
|
let image_cache_task = ImageCacheTask(mock_resource_task);
|
||||||
|
@ -565,7 +544,6 @@ fn should_fail_if_requesting_decode_of_an_unprefetched_image() {
|
||||||
#[test]
|
#[test]
|
||||||
#[should_fail]
|
#[should_fail]
|
||||||
fn should_fail_if_requesting_image_before_requesting_decode() {
|
fn should_fail_if_requesting_image_before_requesting_decode() {
|
||||||
|
|
||||||
let mock_resource_task = do mock_resource_task |response| {
|
let mock_resource_task = do mock_resource_task |response| {
|
||||||
response.send(resource_task::Done(result::Ok(())));
|
response.send(resource_task::Done(result::Ok(())));
|
||||||
};
|
};
|
||||||
|
@ -606,7 +584,6 @@ fn should_not_request_url_from_resource_task_on_multiple_prefetches() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_image_not_ready_if_data_has_not_arrived() {
|
fn should_return_image_not_ready_if_data_has_not_arrived() {
|
||||||
|
|
||||||
let (wait_chan, wait_port) = pipes::stream();
|
let (wait_chan, wait_port) = pipes::stream();
|
||||||
|
|
||||||
let mock_resource_task = do mock_resource_task |response| {
|
let mock_resource_task = do mock_resource_task |response| {
|
||||||
|
@ -632,7 +609,6 @@ fn should_return_image_not_ready_if_data_has_not_arrived() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_decoded_image_data_if_data_has_arrived() {
|
fn should_return_decoded_image_data_if_data_has_arrived() {
|
||||||
|
|
||||||
let mock_resource_task = do mock_resource_task |response| {
|
let mock_resource_task = do mock_resource_task |response| {
|
||||||
response.send(resource_task::Payload(test_image_bin()));
|
response.send(resource_task::Payload(test_image_bin()));
|
||||||
response.send(resource_task::Done(result::Ok(())));
|
response.send(resource_task::Done(result::Ok(())));
|
||||||
|
@ -670,7 +646,6 @@ fn should_return_decoded_image_data_if_data_has_arrived() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_decoded_image_data_for_multiple_requests() {
|
fn should_return_decoded_image_data_for_multiple_requests() {
|
||||||
|
|
||||||
let mock_resource_task = do mock_resource_task |response| {
|
let mock_resource_task = do mock_resource_task |response| {
|
||||||
response.send(resource_task::Payload(test_image_bin()));
|
response.send(resource_task::Payload(test_image_bin()));
|
||||||
response.send(resource_task::Done(result::Ok(())));
|
response.send(resource_task::Done(result::Ok(())));
|
||||||
|
@ -710,7 +685,6 @@ fn should_return_decoded_image_data_for_multiple_requests() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_not_request_image_from_resource_task_if_image_is_already_available() {
|
fn should_not_request_image_from_resource_task_if_image_is_already_available() {
|
||||||
|
|
||||||
let image_bin_sent = comm::Port();
|
let image_bin_sent = comm::Port();
|
||||||
let image_bin_sent_chan = image_bin_sent.chan();
|
let image_bin_sent_chan = image_bin_sent.chan();
|
||||||
|
|
||||||
|
@ -755,7 +729,6 @@ fn should_not_request_image_from_resource_task_if_image_is_already_available() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_not_request_image_from_resource_task_if_image_fetch_already_failed() {
|
fn should_not_request_image_from_resource_task_if_image_fetch_already_failed() {
|
||||||
|
|
||||||
let image_bin_sent = comm::Port();
|
let image_bin_sent = comm::Port();
|
||||||
let image_bin_sent_chan = image_bin_sent.chan();
|
let image_bin_sent_chan = image_bin_sent.chan();
|
||||||
|
|
||||||
|
@ -802,7 +775,6 @@ fn should_not_request_image_from_resource_task_if_image_fetch_already_failed() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_failed_if_image_bin_cannot_be_fetched() {
|
fn should_return_failed_if_image_bin_cannot_be_fetched() {
|
||||||
|
|
||||||
let mock_resource_task = do mock_resource_task |response| {
|
let mock_resource_task = do mock_resource_task |response| {
|
||||||
response.send(resource_task::Payload(test_image_bin()));
|
response.send(resource_task::Payload(test_image_bin()));
|
||||||
// ERROR fetching image
|
// ERROR fetching image
|
||||||
|
@ -841,7 +813,6 @@ fn should_return_failed_if_image_bin_cannot_be_fetched() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_failed_for_multiple_get_image_requests_if_image_bin_cannot_be_fetched() {
|
fn should_return_failed_for_multiple_get_image_requests_if_image_bin_cannot_be_fetched() {
|
||||||
|
|
||||||
let mock_resource_task = do mock_resource_task |response | {
|
let mock_resource_task = do mock_resource_task |response | {
|
||||||
response.send(resource_task::Payload(test_image_bin()));
|
response.send(resource_task::Payload(test_image_bin()));
|
||||||
// ERROR fetching image
|
// ERROR fetching image
|
||||||
|
@ -888,7 +859,6 @@ fn should_return_failed_for_multiple_get_image_requests_if_image_bin_cannot_be_f
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_not_ready_if_image_is_still_decoding() {
|
fn should_return_not_ready_if_image_is_still_decoding() {
|
||||||
|
|
||||||
let (wait_to_decode_chan, wait_to_decode_port) = pipes::stream();
|
let (wait_to_decode_chan, wait_to_decode_port) = pipes::stream();
|
||||||
|
|
||||||
let mock_resource_task = do mock_resource_task |response| {
|
let mock_resource_task = do mock_resource_task |response| {
|
||||||
|
@ -943,7 +913,6 @@ fn should_return_not_ready_if_image_is_still_decoding() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_failed_if_image_decode_fails() {
|
fn should_return_failed_if_image_decode_fails() {
|
||||||
|
|
||||||
let mock_resource_task = do mock_resource_task |response| {
|
let mock_resource_task = do mock_resource_task |response| {
|
||||||
// Bogus data
|
// Bogus data
|
||||||
response.send(resource_task::Payload(~[]));
|
response.send(resource_task::Payload(~[]));
|
||||||
|
@ -984,7 +953,6 @@ fn should_return_failed_if_image_decode_fails() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_image_on_wait_if_image_is_already_loaded() {
|
fn should_return_image_on_wait_if_image_is_already_loaded() {
|
||||||
|
|
||||||
let mock_resource_task = do mock_resource_task |response| {
|
let mock_resource_task = do mock_resource_task |response| {
|
||||||
response.send(resource_task::Payload(test_image_bin()));
|
response.send(resource_task::Payload(test_image_bin()));
|
||||||
response.send(resource_task::Done(result::Ok(())));
|
response.send(resource_task::Done(result::Ok(())));
|
||||||
|
@ -1022,7 +990,6 @@ fn should_return_image_on_wait_if_image_is_already_loaded() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_image_on_wait_if_image_is_not_yet_loaded() {
|
fn should_return_image_on_wait_if_image_is_not_yet_loaded() {
|
||||||
|
|
||||||
let (wait_chan, wait_port) = pipes::stream();
|
let (wait_chan, wait_port) = pipes::stream();
|
||||||
|
|
||||||
let mock_resource_task = do mock_resource_task |response| {
|
let mock_resource_task = do mock_resource_task |response| {
|
||||||
|
@ -1053,7 +1020,6 @@ fn should_return_image_on_wait_if_image_is_not_yet_loaded() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_image_failed_on_wait_if_image_fails_to_load() {
|
fn should_return_image_failed_on_wait_if_image_fails_to_load() {
|
||||||
|
|
||||||
let (wait_chan, wait_port) = pipes::stream();
|
let (wait_chan, wait_port) = pipes::stream();
|
||||||
|
|
||||||
let mock_resource_task = do mock_resource_task |response| {
|
let mock_resource_task = do mock_resource_task |response| {
|
||||||
|
@ -1105,3 +1071,4 @@ fn sync_cache_should_wait_for_images() {
|
||||||
image_cache_task.exit();
|
image_cache_task.exit();
|
||||||
mock_resource_task.send(resource_task::Exit);
|
mock_resource_task.send(resource_task::Exit);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,13 @@ extra message traffic, it also avoids waiting on the same image
|
||||||
multiple times and thus triggering reflows multiple times.
|
multiple times and thus triggering reflows multiple times.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use image_cache_task::{Decode, GetImage, ImageCacheTask, ImageFailed, ImageNotReady, ImageReady};
|
||||||
|
use image_cache_task::{ImageResponseMsg, Prefetch, WaitForImage};
|
||||||
|
|
||||||
use clone_arc = std::arc::clone;
|
use clone_arc = std::arc::clone;
|
||||||
use std::net::url::Url;
|
|
||||||
use core::comm::Port;
|
use core::comm::Port;
|
||||||
use resource::image_cache_task::{ImageCacheTask, ImageResponseMsg, Prefetch, Decode, GetImage};
|
|
||||||
use resource::image_cache_task::{ WaitForImage, ImageReady, ImageNotReady, ImageFailed};
|
|
||||||
use servo_util::url::{UrlMap, url_map};
|
use servo_util::url::{UrlMap, url_map};
|
||||||
|
use std::net::url::Url;
|
||||||
|
|
||||||
pub fn LocalImageCache(image_cache_task: ImageCacheTask) -> LocalImageCache {
|
pub fn LocalImageCache(image_cache_task: ImageCacheTask) -> LocalImageCache {
|
||||||
LocalImageCache {
|
LocalImageCache {
|
|
@ -2,17 +2,15 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
/*!
|
//! A task that takes a URL and streams back the binary data.
|
||||||
|
|
||||||
A task that takes a URL and streams back the binary data
|
use file_loader;
|
||||||
|
use http_loader;
|
||||||
*/
|
|
||||||
|
|
||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
use core::comm::{Chan, Port, SharedChan};
|
use core::comm::{Chan, Port, SharedChan};
|
||||||
use resource::util::spawn_listener;
|
|
||||||
use std::net::url::{Url, to_str};
|
use std::net::url::{Url, to_str};
|
||||||
use super::{file_loader, http_loader};
|
use util::spawn_listener;
|
||||||
|
|
||||||
pub enum ControlMsg {
|
pub enum ControlMsg {
|
||||||
/// Request the data associated with a particular URL
|
/// Request the data associated with a particular URL
|
33
src/servo-net/servo_net.rc
Normal file
33
src/servo-net/servo_net.rc
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
#[link(name = "servo_net",
|
||||||
|
vers = "0.1",
|
||||||
|
uuid = "69c2b7b7-0d7d-4514-a48a-0eed61476039",
|
||||||
|
url = "http://servo.org/")];
|
||||||
|
#[crate_type = "lib"];
|
||||||
|
|
||||||
|
extern mod geom;
|
||||||
|
extern mod http_client;
|
||||||
|
extern mod servo_util;
|
||||||
|
extern mod stb_image;
|
||||||
|
extern mod std;
|
||||||
|
|
||||||
|
/// Image handling.
|
||||||
|
///
|
||||||
|
/// It may be surprising that this goes in the network crate as opposed to the graphics crate.
|
||||||
|
/// However, image handling is generally very integrated with the network stack (especially where
|
||||||
|
/// caching is involved) and as a result it must live in here.
|
||||||
|
pub mod image {
|
||||||
|
pub mod base;
|
||||||
|
pub mod holder;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod file_loader;
|
||||||
|
pub mod http_loader;
|
||||||
|
pub mod image_cache_task;
|
||||||
|
pub mod local_image_cache;
|
||||||
|
pub mod resource_task;
|
||||||
|
pub mod util;
|
||||||
|
|
|
@ -2,11 +2,13 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use ShareGlContext = sharegl::platform::Context;
|
use compositing::resize_rate_limiter::ResizeRateLimiter;
|
||||||
use dom::event::Event;
|
use dom::event::Event;
|
||||||
use platform::resize_rate_limiter::ResizeRateLimiter;
|
use platform::{Application, Window};
|
||||||
|
use windowing::{ApplicationMethods, WindowMethods};
|
||||||
|
|
||||||
use azure::azure_hl::{BackendType, B8G8R8A8, DataSourceSurface, DrawTarget, SourceSurfaceMethods};
|
use azure::azure_hl::{BackendType, B8G8R8A8, DataSourceSurface, DrawTarget, SourceSurfaceMethods};
|
||||||
|
use core::cell::Cell;
|
||||||
use core::comm::{Chan, SharedChan, Port};
|
use core::comm::{Chan, SharedChan, Port};
|
||||||
use core::util;
|
use core::util;
|
||||||
use geom::matrix::identity;
|
use geom::matrix::identity;
|
||||||
|
@ -15,65 +17,40 @@ use geom::rect::Rect;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
use gfx::compositor::{Compositor, LayerBuffer, LayerBufferSet};
|
use gfx::compositor::{Compositor, LayerBuffer, LayerBufferSet};
|
||||||
use gfx::opts::Opts;
|
use gfx::opts::Opts;
|
||||||
use servo_util::time;
|
|
||||||
use core::cell::Cell;
|
|
||||||
use glut::glut;
|
|
||||||
use layers;
|
use layers;
|
||||||
use sharegl;
|
use servo_util::time;
|
||||||
use sharegl::ShareGlContext;
|
|
||||||
use sharegl::base::ShareContext;
|
|
||||||
|
|
||||||
pub struct OSMain {
|
mod resize_rate_limiter;
|
||||||
|
|
||||||
|
/// The implementation of the layers-based compositor.
|
||||||
|
#[deriving(Clone)]
|
||||||
|
pub struct CompositorImpl {
|
||||||
chan: SharedChan<Msg>
|
chan: SharedChan<Msg>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for OSMain {
|
impl CompositorImpl {
|
||||||
fn clone(&self) -> OSMain {
|
/// Creates a new compositor instance.
|
||||||
OSMain {
|
pub fn new(dom_event_chan: SharedChan<Event>, opts: Opts) -> CompositorImpl {
|
||||||
chan: self.chan.clone()
|
let dom_event_chan = Cell(dom_event_chan);
|
||||||
|
let chan: Chan<Msg> = do on_osmain |port| {
|
||||||
|
debug!("preparing to enter main loop");
|
||||||
|
mainloop(port, dom_event_chan.take(), &opts);
|
||||||
|
};
|
||||||
|
|
||||||
|
CompositorImpl {
|
||||||
|
chan: SharedChan::new(chan)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Move me over to opts.rs.
|
/// Messages to the compositor.
|
||||||
enum Mode {
|
|
||||||
GlutMode,
|
|
||||||
ShareMode
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Window {
|
|
||||||
GlutWindow(glut::Window),
|
|
||||||
ShareWindow(ShareGlContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum Msg {
|
pub enum Msg {
|
||||||
BeginDrawing(comm::Chan<LayerBufferSet>),
|
BeginDrawing(Chan<LayerBufferSet>),
|
||||||
Draw(comm::Chan<LayerBufferSet>, LayerBufferSet),
|
Draw(Chan<LayerBufferSet>, LayerBufferSet),
|
||||||
AddKeyHandler(comm::Chan<()>),
|
AddKeyHandler(Chan<()>),
|
||||||
Exit
|
Exit
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn OSMain(dom_event_chan: comm::SharedChan<Event>, opts: Opts) -> OSMain {
|
|
||||||
let dom_event_chan = Cell(dom_event_chan);
|
|
||||||
OSMain {
|
|
||||||
chan: SharedChan::new(on_osmain::<Msg>(|po| {
|
|
||||||
let po = Cell(po);
|
|
||||||
do platform::runmain {
|
|
||||||
debug!("preparing to enter main loop");
|
|
||||||
|
|
||||||
// FIXME: Use the servo options.
|
|
||||||
let mode;
|
|
||||||
match os::getenv("SERVO_SHARE") {
|
|
||||||
Some(_) => mode = ShareMode,
|
|
||||||
None => mode = GlutMode
|
|
||||||
}
|
|
||||||
|
|
||||||
mainloop(mode, po.take(), dom_event_chan.take(), &opts);
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Azure surface wrapping to work with the layers infrastructure.
|
/// Azure surface wrapping to work with the layers infrastructure.
|
||||||
struct AzureDrawTargetImageData {
|
struct AzureDrawTargetImageData {
|
||||||
draw_target: DrawTarget,
|
draw_target: DrawTarget,
|
||||||
|
@ -82,8 +59,12 @@ struct AzureDrawTargetImageData {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl layers::layers::ImageData for AzureDrawTargetImageData {
|
impl layers::layers::ImageData for AzureDrawTargetImageData {
|
||||||
fn size(&self) -> Size2D<uint> { self.size }
|
fn size(&self) -> Size2D<uint> {
|
||||||
fn stride(&self) -> uint { self.data_source_surface.stride() as uint }
|
self.size
|
||||||
|
}
|
||||||
|
fn stride(&self) -> uint {
|
||||||
|
self.data_source_surface.stride() as uint
|
||||||
|
}
|
||||||
fn format(&self) -> layers::layers::Format {
|
fn format(&self) -> layers::layers::Format {
|
||||||
// FIXME: This is not always correct. We should query the Azure draw target for the format.
|
// FIXME: This is not always correct. We should query the Azure draw target for the format.
|
||||||
layers::layers::ARGB32Format
|
layers::layers::ARGB32Format
|
||||||
|
@ -95,33 +76,20 @@ impl layers::layers::ImageData for AzureDrawTargetImageData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mainloop(mode: Mode,
|
fn mainloop(po: Port<Msg>, dom_event_chan: SharedChan<Event>, opts: &Opts) {
|
||||||
po: Port<Msg>,
|
|
||||||
dom_event_chan: SharedChan<Event>,
|
|
||||||
opts: &Opts) {
|
|
||||||
let key_handlers: @mut ~[Chan<()>] = @mut ~[];
|
let key_handlers: @mut ~[Chan<()>] = @mut ~[];
|
||||||
|
|
||||||
let window;
|
let app: Application = ApplicationMethods::new();
|
||||||
match mode {
|
let window: @mut Window = WindowMethods::new(&app);
|
||||||
GlutMode => {
|
|
||||||
glut::init();
|
|
||||||
glut::init_display_mode(glut::DOUBLE);
|
|
||||||
let glut_window = glut::create_window(~"Servo");
|
|
||||||
glut::reshape_window(glut_window, 800, 600);
|
|
||||||
window = GlutWindow(glut_window);
|
|
||||||
}
|
|
||||||
ShareMode => {
|
|
||||||
let size = Size2D(800, 600);
|
|
||||||
let share_context: ShareGlContext = sharegl::base::ShareContext::new(size);
|
|
||||||
io::println(fmt!("Sharing ID is %d", share_context.id()));
|
|
||||||
window = ShareWindow(share_context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let surfaces = @mut SurfaceSet(opts.render_backend);
|
let surfaces = @mut SurfaceSet(opts.render_backend);
|
||||||
|
|
||||||
let context = layers::rendergl::init_render_context();
|
let context = layers::rendergl::init_render_context();
|
||||||
|
|
||||||
|
// Create an initial layer tree.
|
||||||
|
//
|
||||||
|
// TODO: There should be no initial layer tree until the renderer creates one from the display
|
||||||
|
// list. This is only here because we don't have that logic in the renderer yet.
|
||||||
let root_layer = @mut layers::layers::ContainerLayer();
|
let root_layer = @mut layers::layers::ContainerLayer();
|
||||||
let original_layer_transform;
|
let original_layer_transform;
|
||||||
{
|
{
|
||||||
|
@ -137,19 +105,17 @@ fn mainloop(mode: Mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let scene = @layers::scene::Scene(layers::layers::ContainerLayerKind(root_layer),
|
let scene = @mut layers::scene::Scene(layers::layers::ContainerLayerKind(root_layer),
|
||||||
Size2D(800.0, 600.0),
|
Size2D(800.0, 600.0),
|
||||||
identity());
|
identity());
|
||||||
|
|
||||||
let done = @mut false;
|
let done = @mut false;
|
||||||
let resize_rate_limiter = @mut ResizeRateLimiter(dom_event_chan);
|
let resize_rate_limiter = @mut ResizeRateLimiter(dom_event_chan);
|
||||||
let check_for_messages: @fn() = || {
|
let check_for_messages: @fn() = || {
|
||||||
|
|
||||||
// Periodically check if content responded to our last resize event
|
// Periodically check if content responded to our last resize event
|
||||||
resize_rate_limiter.check_resize_response();
|
resize_rate_limiter.check_resize_response();
|
||||||
|
|
||||||
// Handle messages
|
// Handle messages
|
||||||
//#debug("osmain: peeking");
|
|
||||||
while po.peek() {
|
while po.peek() {
|
||||||
match po.recv() {
|
match po.recv() {
|
||||||
AddKeyHandler(key_ch) => key_handlers.push(key_ch),
|
AddKeyHandler(key_ch) => key_handlers.push(key_ch),
|
||||||
|
@ -195,9 +161,7 @@ fn mainloop(mode: Mode,
|
||||||
common.next_sibling
|
common.next_sibling
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(_) => {
|
Some(_) => fail!(~"found unexpected layer kind"),
|
||||||
fail!(~"found unexpected layer kind")
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set the layer's transform.
|
// Set the layer's transform.
|
||||||
|
@ -216,70 +180,39 @@ fn mainloop(mode: Mode,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let adjust_for_window_resizing: @fn() = || {
|
do window.set_composite_callback {
|
||||||
let window_width = glut::get(glut::WindowWidth) as uint;
|
|
||||||
let window_height = glut::get(glut::WindowHeight) as uint;
|
|
||||||
|
|
||||||
// FIXME: Cross-crate struct mutability is broken.
|
|
||||||
let size: &mut Size2D<f32>;
|
|
||||||
unsafe { size = cast::transmute(&scene.size); }
|
|
||||||
*size = Size2D(window_width as f32, window_height as f32);
|
|
||||||
};
|
|
||||||
|
|
||||||
let composite: @fn() = || {
|
|
||||||
//#debug("osmain: drawing to screen");
|
|
||||||
|
|
||||||
do time::time(~"compositing") {
|
do time::time(~"compositing") {
|
||||||
adjust_for_window_resizing();
|
// Adjust the layer dimensions as necessary to correspond to the size of the window.
|
||||||
|
scene.size = window.size();
|
||||||
|
|
||||||
|
// Render the scene.
|
||||||
layers::rendergl::render_scene(context, scene);
|
layers::rendergl::render_scene(context, scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
glut::swap_buffers();
|
window.present();
|
||||||
glut::post_redisplay();
|
}
|
||||||
};
|
|
||||||
|
|
||||||
match window {
|
do window.set_resize_callback |width, height| {
|
||||||
GlutWindow(window) => {
|
debug!("osmain: window resized to %ux%u", width, height);
|
||||||
do glut::reshape_func(window) |width, height| {
|
resize_rate_limiter.window_resized(width, height);
|
||||||
debug!("osmain: window resized to %d,%d", width as int, height as int);
|
}
|
||||||
check_for_messages();
|
|
||||||
resize_rate_limiter.window_resized(width as uint, height as uint);
|
|
||||||
//composite();
|
|
||||||
}
|
|
||||||
|
|
||||||
do glut::display_func() {
|
// Enter the main event loop.
|
||||||
//debug!("osmain: display func");
|
while !*done {
|
||||||
check_for_messages();
|
// Check for new messages coming from the rendering task.
|
||||||
composite();
|
check_for_messages();
|
||||||
}
|
|
||||||
|
|
||||||
while !*done {
|
// Check for messages coming from the windowing system.
|
||||||
//#debug("osmain: running GLUT check loop");
|
window.check_loop();
|
||||||
glut::check_loop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ShareWindow(share_context) => {
|
|
||||||
loop {
|
|
||||||
check_for_messages();
|
|
||||||
do time::time(~"compositing") {
|
|
||||||
layers::rendergl::render_scene(context, scene);
|
|
||||||
}
|
|
||||||
|
|
||||||
share_context.flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/// Implementation of the abstract `Compositor` interface.
|
||||||
Implementation to allow the osmain channel to be used as a graphics
|
impl Compositor for CompositorImpl {
|
||||||
compositor for the renderer
|
fn begin_drawing(&self, next_dt: Chan<LayerBufferSet>) {
|
||||||
*/
|
|
||||||
impl Compositor for OSMain {
|
|
||||||
fn begin_drawing(&self, next_dt: comm::Chan<LayerBufferSet>) {
|
|
||||||
self.chan.send(BeginDrawing(next_dt))
|
self.chan.send(BeginDrawing(next_dt))
|
||||||
}
|
}
|
||||||
fn draw(&self, next_dt: comm::Chan<LayerBufferSet>, draw_me: LayerBufferSet) {
|
fn draw(&self, next_dt: Chan<LayerBufferSet>, draw_me: LayerBufferSet) {
|
||||||
self.chan.send(Draw(next_dt, draw_me))
|
self.chan.send(Draw(next_dt, draw_me))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -289,7 +222,7 @@ struct SurfaceSet {
|
||||||
back: Surface,
|
back: Surface,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lend_surface(surfaces: &mut SurfaceSet, receiver: comm::Chan<LayerBufferSet>) {
|
fn lend_surface(surfaces: &mut SurfaceSet, receiver: Chan<LayerBufferSet>) {
|
||||||
// We are in a position to lend out the surface?
|
// We are in a position to lend out the surface?
|
||||||
assert!(surfaces.front.have);
|
assert!(surfaces.front.have);
|
||||||
// Ok then take it
|
// Ok then take it
|
||||||
|
@ -343,11 +276,16 @@ fn Surface(backend: BackendType) -> Surface {
|
||||||
rect: Rect(Point2D(0u, 0u), Size2D(800u, 600u)),
|
rect: Rect(Point2D(0u, 0u), Size2D(800u, 600u)),
|
||||||
stride: 800 * 4
|
stride: 800 * 4
|
||||||
};
|
};
|
||||||
let layer_buffer_set = LayerBufferSet { buffers: ~[ layer_buffer ] };
|
let layer_buffer_set = LayerBufferSet {
|
||||||
Surface { layer_buffer_set: layer_buffer_set, have: true }
|
buffers: ~[ layer_buffer ]
|
||||||
|
};
|
||||||
|
Surface {
|
||||||
|
layer_buffer_set: layer_buffer_set,
|
||||||
|
have: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A function for spawning into the platform's main thread
|
/// A function for spawning into the platform's main thread.
|
||||||
fn on_osmain<T: Owned>(f: ~fn(po: Port<T>)) -> Chan<T> {
|
fn on_osmain<T: Owned>(f: ~fn(po: Port<T>)) -> Chan<T> {
|
||||||
let (setup_po, setup_ch) = comm::stream();
|
let (setup_po, setup_ch) = comm::stream();
|
||||||
do task::task().sched_mode(task::PlatformThread).spawn {
|
do task::task().sched_mode(task::PlatformThread).spawn {
|
||||||
|
@ -358,10 +296,3 @@ fn on_osmain<T: Owned>(f: ~fn(po: Port<T>)) -> Chan<T> {
|
||||||
setup_po.recv()
|
setup_po.recv()
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[cfg(target_os = "linux")]
|
|
||||||
mod platform {
|
|
||||||
pub fn runmain(f: &fn()) {
|
|
||||||
f()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -17,15 +17,13 @@ use layout::layout_task;
|
||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
use core::comm::{Port, SharedChan};
|
use core::comm::{Port, SharedChan};
|
||||||
use core::either;
|
use core::either;
|
||||||
use core::io::{println, read_whole_file};
|
use core::io::read_whole_file;
|
||||||
use core::pipes::select2i;
|
use core::pipes::select2i;
|
||||||
use core::ptr::null;
|
use core::ptr::null;
|
||||||
use core::task::{SingleThreaded, task};
|
use core::task::{SingleThreaded, task};
|
||||||
use core::util::replace;
|
use core::util::replace;
|
||||||
use dom;
|
use dom;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
use gfx::resource::image_cache_task::ImageCacheTask;
|
|
||||||
use gfx::resource::resource_task::ResourceTask;
|
|
||||||
use html;
|
use html;
|
||||||
use js::JSVAL_NULL;
|
use js::JSVAL_NULL;
|
||||||
use js::global::{global_class, debug_fns};
|
use js::global::{global_class, debug_fns};
|
||||||
|
@ -34,6 +32,8 @@ use js::jsapi::JSContext;
|
||||||
use js::jsapi::bindgen::{JS_CallFunctionValue, JS_GetContextPrivate};
|
use js::jsapi::bindgen::{JS_CallFunctionValue, JS_GetContextPrivate};
|
||||||
use js::rust::{Compartment, Cx};
|
use js::rust::{Compartment, Cx};
|
||||||
use jsrt = js::rust::rt;
|
use jsrt = js::rust::rt;
|
||||||
|
use servo_net::image_cache_task::ImageCacheTask;
|
||||||
|
use servo_net::resource_task::ResourceTask;
|
||||||
use servo_util::tree::TreeNodeRef;
|
use servo_util::tree::TreeNodeRef;
|
||||||
use std::net::url::Url;
|
use std::net::url::Url;
|
||||||
use url_to_str = std::net::url::to_str;
|
use url_to_str = std::net::url::to_str;
|
||||||
|
|
|
@ -68,7 +68,7 @@ pub fn create(cx: *JSContext, node: &mut AbstractNode) -> jsobj {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn unwrap(obj: *JSObject) -> AbstractNode {
|
pub unsafe fn unwrap(obj: *JSObject) -> AbstractNode {
|
||||||
let raw = unsafe { utils::unwrap::<*mut Node>(obj) };
|
let raw = utils::unwrap::<*mut Node>(obj);
|
||||||
AbstractNode::from_raw(raw)
|
AbstractNode::from_raw(raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,34 +2,34 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use compositing::CompositorImpl;
|
||||||
use content::content_task::{ContentTask, ExecuteMsg, ParseMsg};
|
use content::content_task::{ContentTask, ExecuteMsg, ParseMsg};
|
||||||
use content::content_task;
|
use content::content_task;
|
||||||
use dom::event::Event;
|
use dom::event::Event;
|
||||||
use layout::layout_task;
|
use layout::layout_task;
|
||||||
use layout::layout_task::LayoutTask;
|
use layout::layout_task::LayoutTask;
|
||||||
use resource::image_cache_task::{ImageCacheTask, ImageCacheTaskClient};
|
|
||||||
use resource::resource_task::ResourceTask;
|
|
||||||
use resource::resource_task;
|
|
||||||
use util::task::spawn_listener;
|
use util::task::spawn_listener;
|
||||||
|
|
||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
use core::comm::{Port, Chan};
|
use core::comm::{Chan, Port, SharedChan};
|
||||||
use gfx::compositor::Compositor;
|
|
||||||
use gfx::opts::Opts;
|
use gfx::opts::Opts;
|
||||||
use gfx::render_task::RenderTask;
|
use gfx::render_task::RenderTask;
|
||||||
use gfx::render_task;
|
use gfx::render_task;
|
||||||
|
use servo_net::image_cache_task::{ImageCacheTask, ImageCacheTaskClient};
|
||||||
|
use servo_net::resource_task::ResourceTask;
|
||||||
|
use servo_net::resource_task;
|
||||||
use std::net::url::Url;
|
use std::net::url::Url;
|
||||||
|
|
||||||
pub type EngineTask = Chan<Msg>;
|
pub type EngineTask = Chan<Msg>;
|
||||||
|
|
||||||
pub enum Msg {
|
pub enum Msg {
|
||||||
LoadURLMsg(Url),
|
LoadUrlMsg(Url),
|
||||||
ExitMsg(Chan<()>)
|
ExitMsg(Chan<()>)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Engine<C> {
|
pub struct Engine {
|
||||||
request_port: Port<Msg>,
|
request_port: Port<Msg>,
|
||||||
compositor: C,
|
compositor: CompositorImpl,
|
||||||
render_task: RenderTask,
|
render_task: RenderTask,
|
||||||
resource_task: ResourceTask,
|
resource_task: ResourceTask,
|
||||||
image_cache_task: ImageCacheTask,
|
image_cache_task: ImageCacheTask,
|
||||||
|
@ -37,39 +37,42 @@ pub struct Engine<C> {
|
||||||
content_task: ContentTask
|
content_task: ContentTask
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn Engine<C:Compositor + Owned + Clone>(compositor: C,
|
impl Engine {
|
||||||
opts: &Opts,
|
pub fn start(compositor: CompositorImpl,
|
||||||
dom_event_port: comm::Port<Event>,
|
opts: &Opts,
|
||||||
dom_event_chan: comm::SharedChan<Event>,
|
dom_event_port: Port<Event>,
|
||||||
resource_task: ResourceTask,
|
dom_event_chan: SharedChan<Event>,
|
||||||
image_cache_task: ImageCacheTask)
|
resource_task: ResourceTask,
|
||||||
-> EngineTask {
|
image_cache_task: ImageCacheTask)
|
||||||
let dom_event_port = Cell(dom_event_port);
|
-> EngineTask {
|
||||||
let dom_event_chan = Cell(dom_event_chan);
|
let dom_event_port = Cell(dom_event_port);
|
||||||
|
let dom_event_chan = Cell(dom_event_chan);
|
||||||
|
|
||||||
let opts = Cell(copy *opts);
|
let opts = Cell(copy *opts);
|
||||||
do spawn_listener::<Msg> |request| {
|
do spawn_listener::<Msg> |request| {
|
||||||
let render_task = RenderTask(compositor.clone(), opts.with_ref(|o| copy *o));
|
let render_task = RenderTask(compositor.clone(), opts.with_ref(|o| copy *o));
|
||||||
let layout_task = LayoutTask(render_task.clone(), image_cache_task.clone(), opts.take());
|
|
||||||
let content_task = ContentTask(layout_task.clone(),
|
|
||||||
dom_event_port.take(),
|
|
||||||
dom_event_chan.take(),
|
|
||||||
resource_task.clone(),
|
|
||||||
image_cache_task.clone());
|
|
||||||
|
|
||||||
Engine {
|
let opts = opts.take();
|
||||||
request_port: request,
|
let layout_task = LayoutTask(render_task.clone(), image_cache_task.clone(), opts);
|
||||||
compositor: compositor.clone(),
|
|
||||||
render_task: render_task,
|
let content_task = ContentTask(layout_task.clone(),
|
||||||
resource_task: resource_task.clone(),
|
dom_event_port.take(),
|
||||||
image_cache_task: image_cache_task.clone(),
|
dom_event_chan.take(),
|
||||||
layout_task: layout_task,
|
resource_task.clone(),
|
||||||
content_task: content_task
|
image_cache_task.clone());
|
||||||
}.run();
|
|
||||||
|
Engine {
|
||||||
|
request_port: request,
|
||||||
|
compositor: compositor.clone(),
|
||||||
|
render_task: render_task,
|
||||||
|
resource_task: resource_task.clone(),
|
||||||
|
image_cache_task: image_cache_task.clone(),
|
||||||
|
layout_task: layout_task,
|
||||||
|
content_task: content_task,
|
||||||
|
}.run()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<C:Compositor + Owned + Clone> Engine<C> {
|
|
||||||
fn run(&self) {
|
fn run(&self) {
|
||||||
while self.handle_request(self.request_port.recv()) {
|
while self.handle_request(self.request_port.recv()) {
|
||||||
// Go on...
|
// Go on...
|
||||||
|
@ -78,30 +81,30 @@ impl<C:Compositor + Owned + Clone> Engine<C> {
|
||||||
|
|
||||||
fn handle_request(&self, request: Msg) -> bool {
|
fn handle_request(&self, request: Msg) -> bool {
|
||||||
match request {
|
match request {
|
||||||
LoadURLMsg(url) => {
|
LoadUrlMsg(url) => {
|
||||||
if url.path.ends_with(".js") {
|
if url.path.ends_with(".js") {
|
||||||
self.content_task.send(ExecuteMsg(url))
|
self.content_task.send(ExecuteMsg(url))
|
||||||
} else {
|
} else {
|
||||||
self.content_task.send(ParseMsg(url))
|
self.content_task.send(ParseMsg(url))
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ExitMsg(sender) => {
|
ExitMsg(sender) => {
|
||||||
self.content_task.send(content_task::ExitMsg);
|
self.content_task.send(content_task::ExitMsg);
|
||||||
self.layout_task.send(layout_task::ExitMsg);
|
self.layout_task.send(layout_task::ExitMsg);
|
||||||
|
|
||||||
let (response_port, response_chan) = comm::stream();
|
let (response_port, response_chan) = comm::stream();
|
||||||
|
|
||||||
self.render_task.send(render_task::ExitMsg(response_chan));
|
self.render_task.send(render_task::ExitMsg(response_chan));
|
||||||
response_port.recv();
|
response_port.recv();
|
||||||
|
|
||||||
self.image_cache_task.exit();
|
self.image_cache_task.exit();
|
||||||
self.resource_task.send(resource_task::Exit);
|
self.resource_task.send(resource_task::Exit);
|
||||||
|
|
||||||
sender.send(());
|
sender.send(());
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,17 +2,14 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
/*!
|
/// Some little helpers for hooking up the HTML parser with the CSS parser.
|
||||||
Some little helpers for hooking up the HTML parser with the CSS parser
|
|
||||||
*/
|
|
||||||
|
|
||||||
use resource::resource_task::{ResourceTask, ProgressMsg, Load, Payload, Done};
|
|
||||||
|
|
||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
use core::comm::Port;
|
use core::comm::Port;
|
||||||
use core::str;
|
use core::str;
|
||||||
use newcss::stylesheet::Stylesheet;
|
use newcss::stylesheet::Stylesheet;
|
||||||
use newcss::util::DataStream;
|
use newcss::util::DataStream;
|
||||||
|
use servo_net::resource_task::{ResourceTask, ProgressMsg, Load, Payload, Done};
|
||||||
use std::net::url::Url;
|
use std::net::url::Url;
|
||||||
|
|
||||||
/// Where a style sheet comes from.
|
/// Where a style sheet comes from.
|
||||||
|
|
|
@ -6,15 +6,15 @@ use dom::element::*;
|
||||||
use dom::node::{AbstractNode, Comment, Doctype, Element, ElementNodeTypeId, Node, Text};
|
use dom::node::{AbstractNode, Comment, Doctype, Element, ElementNodeTypeId, Node, Text};
|
||||||
use html::cssparse::{InlineProvenance, StylesheetProvenance, UrlProvenance, spawn_css_parser};
|
use html::cssparse::{InlineProvenance, StylesheetProvenance, UrlProvenance, spawn_css_parser};
|
||||||
use newcss::stylesheet::Stylesheet;
|
use newcss::stylesheet::Stylesheet;
|
||||||
use resource::image_cache_task::ImageCacheTask;
|
|
||||||
use resource::image_cache_task;
|
|
||||||
use resource::resource_task::{Done, Load, Payload, ResourceTask};
|
|
||||||
use util::task::spawn_conversation;
|
use util::task::spawn_conversation;
|
||||||
|
|
||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
use core::comm::{Chan, Port, SharedChan};
|
use core::comm::{Chan, Port, SharedChan};
|
||||||
use core::str::eq_slice;
|
use core::str::eq_slice;
|
||||||
use hubbub::hubbub;
|
use hubbub::hubbub;
|
||||||
|
use servo_net::image_cache_task::ImageCacheTask;
|
||||||
|
use servo_net::image_cache_task;
|
||||||
|
use servo_net::resource_task::{Done, Load, Payload, ResourceTask};
|
||||||
use servo_util::tree::TreeUtils;
|
use servo_util::tree::TreeUtils;
|
||||||
use servo_util::url::make_url;
|
use servo_util::url::make_url;
|
||||||
use std::net::url::Url;
|
use std::net::url::Url;
|
||||||
|
|
|
@ -127,8 +127,7 @@ impl BlockLayout for FlowContext {
|
||||||
assert!(self.starts_block_flow());
|
assert!(self.starts_block_flow());
|
||||||
|
|
||||||
let mut remaining_width = self.with_imm_node(|this| this.position.size.width);
|
let mut remaining_width = self.with_imm_node(|this| this.position.size.width);
|
||||||
let mut _right_used = Au(0);
|
let left_used = Au(0);
|
||||||
let mut left_used = Au(0);
|
|
||||||
|
|
||||||
// Let the box consume some width. It will return the amount remaining for its children.
|
// Let the box consume some width. It will return the amount remaining for its children.
|
||||||
do self.with_block_box |box| {
|
do self.with_block_box |box| {
|
||||||
|
|
|
@ -19,16 +19,15 @@ use geom::{Point2D, Rect, Size2D};
|
||||||
use gfx::display_list::{DisplayItem, DisplayList};
|
use gfx::display_list::{DisplayItem, DisplayList};
|
||||||
use gfx::font::{FontStyle, FontWeight300};
|
use gfx::font::{FontStyle, FontWeight300};
|
||||||
use gfx::geometry::Au;
|
use gfx::geometry::Au;
|
||||||
use gfx::image::holder::ImageHolder;
|
use newcss::color::rgb;
|
||||||
use gfx::resource::local_image_cache::LocalImageCache;
|
|
||||||
use gfx;
|
|
||||||
use newcss::color::{Color, rgb};
|
|
||||||
use newcss::complete::CompleteStyle;
|
use newcss::complete::CompleteStyle;
|
||||||
use newcss::units::{Cursive, Em, Fantasy, Length, Monospace, Pt, Px, SansSerif, Serif};
|
use newcss::units::{Cursive, Em, Fantasy, Length, Monospace, Pt, Px, SansSerif, Serif};
|
||||||
use newcss::values::{CSSBorderWidthLength, CSSBorderWidthMedium};
|
use newcss::values::{CSSBorderWidthLength, CSSBorderWidthMedium};
|
||||||
use newcss::values::{CSSFontFamilyFamilyName, CSSFontFamilyGenericFamily};
|
use newcss::values::{CSSFontFamilyFamilyName, CSSFontFamilyGenericFamily};
|
||||||
use newcss::values::{CSSFontSizeLength, CSSFontStyleItalic, CSSFontStyleNormal};
|
use newcss::values::{CSSFontSizeLength, CSSFontStyleItalic, CSSFontStyleNormal};
|
||||||
use newcss::values::{CSSFontStyleOblique, CSSTextAlign};
|
use newcss::values::{CSSFontStyleOblique, CSSTextAlign};
|
||||||
|
use servo_net::image::holder::ImageHolder;
|
||||||
|
use servo_net::local_image_cache::LocalImageCache;
|
||||||
use servo_util::range::*;
|
use servo_util::range::*;
|
||||||
use std::arc;
|
use std::arc;
|
||||||
use std::cmp::FuzzyEq;
|
use std::cmp::FuzzyEq;
|
||||||
|
|
|
@ -10,8 +10,7 @@ use dom::node::{ElementNodeTypeId, TextNodeTypeId};
|
||||||
use layout::block::BlockFlowData;
|
use layout::block::BlockFlowData;
|
||||||
use layout::box::{GenericRenderBoxClass, ImageRenderBox, ImageRenderBoxClass, RenderBox};
|
use layout::box::{GenericRenderBoxClass, ImageRenderBox, ImageRenderBoxClass, RenderBox};
|
||||||
use layout::box::{RenderBoxBase, RenderBoxType, RenderBox_Generic, RenderBox_Image};
|
use layout::box::{RenderBoxBase, RenderBoxType, RenderBox_Generic, RenderBox_Image};
|
||||||
use layout::box::{RenderBox_Text, TextRenderBox, UnscannedTextRenderBox};
|
use layout::box::{RenderBox_Text, UnscannedTextRenderBox, UnscannedTextRenderBoxClass};
|
||||||
use layout::box::{UnscannedTextRenderBoxClass};
|
|
||||||
use layout::context::LayoutContext;
|
use layout::context::LayoutContext;
|
||||||
use layout::debug::{BoxedMutDebugMethods, DebugMethods};
|
use layout::debug::{BoxedMutDebugMethods, DebugMethods};
|
||||||
use layout::flow::{AbsoluteFlow, BlockFlow, FloatFlow, Flow_Absolute, Flow_Block, Flow_Float};
|
use layout::flow::{AbsoluteFlow, BlockFlow, FloatFlow, Flow_Absolute, Flow_Block, Flow_Float};
|
||||||
|
@ -20,7 +19,6 @@ use layout::flow::{FlowContextType, FlowData, InlineBlockFlow, InlineFlow, RootF
|
||||||
use layout::inline::{InlineFlowData, InlineLayout};
|
use layout::inline::{InlineFlowData, InlineLayout};
|
||||||
use layout::root::RootFlowData;
|
use layout::root::RootFlowData;
|
||||||
|
|
||||||
use gfx::image::holder::ImageHolder;
|
|
||||||
use newcss::values::{CSSDisplay, CSSDisplayBlock, CSSDisplayInline, CSSDisplayInlineBlock};
|
use newcss::values::{CSSDisplay, CSSDisplayBlock, CSSDisplayInline, CSSDisplayInlineBlock};
|
||||||
use newcss::values::{CSSDisplayNone};
|
use newcss::values::{CSSDisplayNone};
|
||||||
use servo_util::range::Range;
|
use servo_util::range::Range;
|
||||||
|
@ -461,7 +459,7 @@ pub impl LayoutTreeBuilder {
|
||||||
let result = match ty {
|
let result = match ty {
|
||||||
RenderBox_Generic => GenericRenderBoxClass(@mut base),
|
RenderBox_Generic => GenericRenderBoxClass(@mut base),
|
||||||
RenderBox_Text => UnscannedTextRenderBoxClass(@mut UnscannedTextRenderBox::new(base)),
|
RenderBox_Text => UnscannedTextRenderBoxClass(@mut UnscannedTextRenderBox::new(base)),
|
||||||
RenderBox_Image => self.make_image_box(layout_ctx, node, flow_context, base),
|
RenderBox_Image => self.make_image_box(layout_ctx, node, base),
|
||||||
};
|
};
|
||||||
debug!("LayoutTreeBuilder: created box: %s", result.debug_str());
|
debug!("LayoutTreeBuilder: created box: %s", result.debug_str());
|
||||||
result
|
result
|
||||||
|
@ -470,7 +468,6 @@ pub impl LayoutTreeBuilder {
|
||||||
fn make_image_box(&mut self,
|
fn make_image_box(&mut self,
|
||||||
layout_ctx: &LayoutContext,
|
layout_ctx: &LayoutContext,
|
||||||
node: AbstractNode,
|
node: AbstractNode,
|
||||||
flow_context: FlowContext,
|
|
||||||
base: RenderBoxBase)
|
base: RenderBoxBase)
|
||||||
-> RenderBox {
|
-> RenderBox {
|
||||||
assert!(node.is_image_element());
|
assert!(node.is_image_element());
|
||||||
|
|
|
@ -2,14 +2,15 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
//! Data needed by the layout task.
|
||||||
|
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use gfx::font_context::FontContext;
|
use gfx::font_context::FontContext;
|
||||||
use gfx::geometry::Au;
|
use gfx::geometry::Au;
|
||||||
use gfx::resource::local_image_cache::LocalImageCache;
|
use servo_net::local_image_cache::LocalImageCache;
|
||||||
use std::net::url::Url;
|
use std::net::url::Url;
|
||||||
|
|
||||||
/* Represents layout task context. */
|
/// Data needed by the layout task.
|
||||||
|
|
||||||
pub struct LayoutContext {
|
pub struct LayoutContext {
|
||||||
font_ctx: @mut FontContext,
|
font_ctx: @mut FontContext,
|
||||||
image_cache: @mut LocalImageCache,
|
image_cache: @mut LocalImageCache,
|
||||||
|
|
|
@ -17,7 +17,6 @@ use core::util;
|
||||||
use geom::{Point2D, Rect, Size2D};
|
use geom::{Point2D, Rect, Size2D};
|
||||||
use gfx::display_list::DisplayList;
|
use gfx::display_list::DisplayList;
|
||||||
use gfx::geometry::Au;
|
use gfx::geometry::Au;
|
||||||
use gfx::image::holder;
|
|
||||||
use gfx::text::text_run::TextRun;
|
use gfx::text::text_run::TextRun;
|
||||||
use gfx::text::util::*;
|
use gfx::text::util::*;
|
||||||
use newcss::values::{CSSTextAlignCenter, CSSTextAlignJustify, CSSTextAlignLeft};
|
use newcss::values::{CSSTextAlignCenter, CSSTextAlignJustify, CSSTextAlignLeft};
|
||||||
|
@ -674,7 +673,7 @@ impl InlineFlowData {
|
||||||
let width = Au::from_px(size.get_or_default(Size2D(0, 0)).width);
|
let width = Au::from_px(size.get_or_default(Size2D(0, 0)).width);
|
||||||
image_box.base.position.size.width = width;
|
image_box.base.position.size.width = width;
|
||||||
}
|
}
|
||||||
TextRenderBoxClass(text_box) => {
|
TextRenderBoxClass(_) => {
|
||||||
// Text boxes are preinitialized.
|
// Text boxes are preinitialized.
|
||||||
}
|
}
|
||||||
GenericRenderBoxClass(generic_box) => {
|
GenericRenderBoxClass(generic_box) => {
|
||||||
|
|
|
@ -15,8 +15,6 @@ use layout::context::LayoutContext;
|
||||||
use layout::debug::{BoxedMutDebugMethods, DebugMethods};
|
use layout::debug::{BoxedMutDebugMethods, DebugMethods};
|
||||||
use layout::display_list_builder::{DisplayListBuilder, FlowDisplayListBuilderMethods};
|
use layout::display_list_builder::{DisplayListBuilder, FlowDisplayListBuilderMethods};
|
||||||
use layout::flow::FlowContext;
|
use layout::flow::FlowContext;
|
||||||
use resource::image_cache_task::{ImageCacheTask, ImageResponseMsg};
|
|
||||||
use resource::local_image_cache::LocalImageCache;
|
|
||||||
use util::task::spawn_listener;
|
use util::task::spawn_listener;
|
||||||
use util::time::time;
|
use util::time::time;
|
||||||
|
|
||||||
|
@ -34,6 +32,8 @@ use gfx::render_task::{RenderMsg, RenderTask};
|
||||||
use newcss::select::SelectCtx;
|
use newcss::select::SelectCtx;
|
||||||
use newcss::stylesheet::Stylesheet;
|
use newcss::stylesheet::Stylesheet;
|
||||||
use newcss::types::OriginAuthor;
|
use newcss::types::OriginAuthor;
|
||||||
|
use servo_net::image_cache_task::{ImageCacheTask, ImageResponseMsg};
|
||||||
|
use servo_net::local_image_cache::LocalImageCache;
|
||||||
use servo_util::tree::TreeUtils;
|
use servo_util::tree::TreeUtils;
|
||||||
use std::net::url::Url;
|
use std::net::url::Url;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
|
|
92
src/servo/platform/common/glut_windowing.rs
Normal file
92
src/servo/platform/common/glut_windowing.rs
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
//! A windowing implementation using GLUT.
|
||||||
|
///
|
||||||
|
/// GLUT is a very old and bare-bones toolkit. However, it has good cross-platform support, at
|
||||||
|
/// least on desktops. It is designed for testing Servo without the need of a UI.
|
||||||
|
|
||||||
|
use windowing::{ApplicationMethods, CompositeCallback, ResizeCallback, WindowMethods};
|
||||||
|
|
||||||
|
use geom::size::Size2D;
|
||||||
|
use glut::glut::{DOUBLE, WindowHeight, WindowWidth};
|
||||||
|
use glut::glut;
|
||||||
|
|
||||||
|
/// A structure responsible for setting up and tearing down the entire windowing system.
|
||||||
|
pub struct Application;
|
||||||
|
|
||||||
|
impl ApplicationMethods for Application {
|
||||||
|
pub fn new() -> Application {
|
||||||
|
glut::init();
|
||||||
|
glut::init_display_mode(DOUBLE);
|
||||||
|
Application
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The type of a window.
|
||||||
|
pub struct Window {
|
||||||
|
glut_window: glut::Window,
|
||||||
|
composite_callback: Option<CompositeCallback>,
|
||||||
|
resize_callback: Option<ResizeCallback>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WindowMethods<Application> for Window {
|
||||||
|
/// Creates a new window.
|
||||||
|
pub fn new(_: &Application) -> @mut Window {
|
||||||
|
// Create the GLUT window.
|
||||||
|
let glut_window = glut::create_window(~"Servo");
|
||||||
|
glut::reshape_window(glut_window, 800, 600);
|
||||||
|
|
||||||
|
// Create our window object.
|
||||||
|
let window = @mut Window {
|
||||||
|
glut_window: glut_window,
|
||||||
|
composite_callback: None,
|
||||||
|
resize_callback: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Register event handlers.
|
||||||
|
do glut::reshape_func(window.glut_window) |width, height| {
|
||||||
|
match window.resize_callback {
|
||||||
|
None => {}
|
||||||
|
Some(callback) => callback(width as uint, height as uint),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
do glut::display_func {
|
||||||
|
// FIXME(pcwalton): This will not work with multiple windows.
|
||||||
|
match window.composite_callback {
|
||||||
|
None => {}
|
||||||
|
Some(callback) => callback(),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the size of the window.
|
||||||
|
pub fn size(&self) -> Size2D<f32> {
|
||||||
|
Size2D(glut::get(WindowWidth) as f32, glut::get(WindowHeight) as f32)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Presents the window to the screen (perhaps by page flipping).
|
||||||
|
pub fn present(&mut self) {
|
||||||
|
glut::swap_buffers();
|
||||||
|
glut::post_redisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Registers a callback to run when a composite event occurs.
|
||||||
|
pub fn set_composite_callback(&mut self, new_composite_callback: CompositeCallback) {
|
||||||
|
self.composite_callback = Some(new_composite_callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Registers a callback to run when a resize event occurs.
|
||||||
|
pub fn set_resize_callback(&mut self, new_resize_callback: ResizeCallback) {
|
||||||
|
self.resize_callback = Some(new_resize_callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Spins the event loop.
|
||||||
|
pub fn check_loop(@mut self) {
|
||||||
|
glut::check_loop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
59
src/servo/platform/common/shared_gl_windowing.rs
Normal file
59
src/servo/platform/common/shared_gl_windowing.rs
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
//! A windowing implementation using shared OpenGL textures.
|
||||||
|
///
|
||||||
|
/// In this setup, Servo renders to an OpenGL texture and uses IPC to share that texture with
|
||||||
|
/// another application. It also uses IPC to handle events.
|
||||||
|
///
|
||||||
|
/// This is designed for sandboxing scenarios which the OpenGL graphics driver is either sandboxed
|
||||||
|
/// along with the Servo process or trusted. If the OpenGL driver itself is untrusted, then this
|
||||||
|
/// windowing implementation is not appropriate.
|
||||||
|
|
||||||
|
use windowing::{CompositeCallback, ResizeCallback};
|
||||||
|
|
||||||
|
use geom::size::Size2D;
|
||||||
|
use sharegl::base::ShareContext;
|
||||||
|
use sharegl::platform::Context;
|
||||||
|
|
||||||
|
/// A structure responsible for setting up and tearing down the entire windowing system.
|
||||||
|
pub struct Application;
|
||||||
|
|
||||||
|
impl ApplicationMethods for Application {
|
||||||
|
pub fn new() -> Application {
|
||||||
|
Application
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The type of a window.
|
||||||
|
pub struct Window(Context);
|
||||||
|
|
||||||
|
impl WindowingMethods<Application> for Window {
|
||||||
|
/// Creates a new window.
|
||||||
|
pub fn new(_: &Application) -> @mut Window {
|
||||||
|
let share_context: Context = ShareContext::new(Size2D(800, 600));
|
||||||
|
println(fmt!("Sharing ID is %d", share_context.id()));
|
||||||
|
@mut Window(share_context)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the size of the window.
|
||||||
|
pub fn size(&mut self) -> Size2D<f32> {
|
||||||
|
Size2D(800.0, 600.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Presents the window to the screen (perhaps by page flipping).
|
||||||
|
pub fn present(&mut self) {
|
||||||
|
(*self).flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Registers a callback to run when a composite event occurs.
|
||||||
|
pub fn set_composite_callback(&mut self, _: CompositeCallback) {}
|
||||||
|
|
||||||
|
/// Registers a callback to run when a resize event occurs.
|
||||||
|
pub fn set_resize_callback(&mut self, _: ResizeCallback) {}
|
||||||
|
|
||||||
|
/// Returns the next event.
|
||||||
|
pub fn check_loop(@mut self) {}
|
||||||
|
}
|
||||||
|
|
18
src/servo/platform/mod.rs
Normal file
18
src/servo/platform/mod.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
//! Platform-specific functionality for Servo.
|
||||||
|
|
||||||
|
#[cfg(not(shared_gl_windowing))]
|
||||||
|
pub use platform::common::glut_windowing::{Application, Window};
|
||||||
|
#[cfg(shared_gl_windowing)]
|
||||||
|
pub use platform::common::shared_gl_windowing::{Application, Window};
|
||||||
|
|
||||||
|
pub mod common {
|
||||||
|
#[cfg(not(shared_gl_windowing))]
|
||||||
|
pub mod glut_windowing;
|
||||||
|
#[cfg(shared_gl_windowing)]
|
||||||
|
pub mod shared_gl_windowing;
|
||||||
|
}
|
||||||
|
|
|
@ -11,19 +11,18 @@
|
||||||
#[license = "MPL"];
|
#[license = "MPL"];
|
||||||
#[crate_type = "lib"];
|
#[crate_type = "lib"];
|
||||||
|
|
||||||
#[legacy_records];
|
|
||||||
|
|
||||||
extern mod azure;
|
extern mod azure;
|
||||||
extern mod geom;
|
extern mod geom;
|
||||||
extern mod gfx (name = "servo_gfx");
|
extern mod gfx (name = "servo_gfx");
|
||||||
extern mod servo_util (name = "servo_util");
|
|
||||||
extern mod glut;
|
extern mod glut;
|
||||||
extern mod http_client;
|
extern mod http_client;
|
||||||
extern mod hubbub;
|
extern mod hubbub;
|
||||||
extern mod js;
|
extern mod js;
|
||||||
extern mod layers;
|
extern mod layers;
|
||||||
extern mod opengles;
|
|
||||||
extern mod newcss (name = "css");
|
extern mod newcss (name = "css");
|
||||||
|
extern mod opengles;
|
||||||
|
extern mod servo_net;
|
||||||
|
extern mod servo_util (name = "servo_util");
|
||||||
extern mod sharegl;
|
extern mod sharegl;
|
||||||
extern mod stb_image;
|
extern mod stb_image;
|
||||||
extern mod std;
|
extern mod std;
|
||||||
|
@ -33,16 +32,21 @@ extern mod core_graphics;
|
||||||
#[cfg(target_os="macos")]
|
#[cfg(target_os="macos")]
|
||||||
extern mod core_text;
|
extern mod core_text;
|
||||||
|
|
||||||
use engine::{Engine, LoadURLMsg};
|
use compositing::{AddKeyHandler, CompositorImpl};
|
||||||
use platform::osmain::{AddKeyHandler, OSMain};
|
use engine::{Engine, LoadUrlMsg};
|
||||||
|
|
||||||
pub use gfx::opts::{Opts, Png, Screen}; // FIXME: Do we really want "Screen" and "Png" visible?
|
use core::comm::SharedChan;
|
||||||
pub use gfx::resource;
|
use gfx::opts;
|
||||||
pub use gfx::resource::image_cache_task::ImageCacheTask;
|
use servo_net::image_cache_task::ImageCacheTask;
|
||||||
pub use gfx::resource::resource_task::ResourceTask;
|
use servo_net::resource_task::ResourceTask;
|
||||||
|
|
||||||
|
pub use gfx::opts::Opts;
|
||||||
pub use gfx::text;
|
pub use gfx::text;
|
||||||
pub use servo_util::url::make_url;
|
pub use servo_util::url::make_url;
|
||||||
|
|
||||||
|
#[path="compositing/mod.rs"]
|
||||||
|
pub mod compositing;
|
||||||
|
|
||||||
pub mod content {
|
pub mod content {
|
||||||
pub mod content_task;
|
pub mod content_task;
|
||||||
}
|
}
|
||||||
|
@ -117,65 +121,50 @@ pub mod html {
|
||||||
pub mod hubbub_html_parser;
|
pub mod hubbub_html_parser;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod platform {
|
pub mod windowing;
|
||||||
pub mod base;
|
|
||||||
pub mod osmain;
|
#[path="platform/mod.rs"]
|
||||||
priv mod resize_rate_limiter;
|
pub mod platform;
|
||||||
}
|
|
||||||
|
|
||||||
#[path = "util/mod.rs"]
|
#[path = "util/mod.rs"]
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let args = os::args();
|
run(&opts::from_cmdline_args(os::args()))
|
||||||
run(&gfx::opts::from_cmdline_args(args))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_implicitly_copyable_typarams)]
|
|
||||||
fn run(opts: &Opts) {
|
fn run(opts: &Opts) {
|
||||||
match &opts.render_mode {
|
|
||||||
&Screen => run_pipeline_screen(opts),
|
|
||||||
&Png(ref outfile) => {
|
|
||||||
assert!(!opts.urls.is_empty());
|
|
||||||
if opts.urls.len() > 1u {
|
|
||||||
fail!(~"servo asks that you stick to a single URL in PNG output mode")
|
|
||||||
}
|
|
||||||
run_pipeline_png(opts, *outfile)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run_pipeline_screen(opts: &Opts) {
|
|
||||||
let (dom_event_port, dom_event_chan) = comm::stream();
|
let (dom_event_port, dom_event_chan) = comm::stream();
|
||||||
let dom_event_chan = comm::SharedChan::new(dom_event_chan);
|
let dom_event_chan = SharedChan::new(dom_event_chan);
|
||||||
|
|
||||||
// The platform event handler thread
|
// The platform event handler thread
|
||||||
let osmain = OSMain(dom_event_chan.clone(), copy *opts);
|
let compositor = CompositorImpl::new(dom_event_chan.clone(), copy *opts);
|
||||||
|
|
||||||
// Send each file to render then wait for keypress
|
// Send each file to render then wait for keypress
|
||||||
let (keypress_from_osmain, keypress_to_engine) = comm::stream();
|
let (keypress_from_compositor, keypress_to_engine) = comm::stream();
|
||||||
osmain.chan.send(AddKeyHandler(keypress_to_engine));
|
compositor.chan.send(AddKeyHandler(keypress_to_engine));
|
||||||
|
|
||||||
// Create a servo instance
|
// Create a servo instance
|
||||||
let resource_task = ResourceTask();
|
let resource_task = ResourceTask();
|
||||||
let image_cache_task = ImageCacheTask(resource_task.clone());
|
let image_cache_task = ImageCacheTask(resource_task.clone());
|
||||||
let engine_task = Engine(osmain.clone(),
|
let engine_task = Engine::start(compositor.clone(),
|
||||||
opts,
|
opts,
|
||||||
dom_event_port,
|
dom_event_port,
|
||||||
dom_event_chan,
|
dom_event_chan,
|
||||||
resource_task,
|
resource_task,
|
||||||
image_cache_task);
|
image_cache_task);
|
||||||
|
|
||||||
for opts.urls.each |filename| {
|
for opts.urls.each |filename| {
|
||||||
let url = make_url(copy *filename, None);
|
let url = make_url(copy *filename, None);
|
||||||
debug!("master: Sending url `%s`", url.to_str());
|
|
||||||
engine_task.send(LoadURLMsg(url));
|
|
||||||
debug!("master: Waiting for keypress");
|
|
||||||
|
|
||||||
match keypress_from_osmain.try_recv() {
|
debug!("master: Sending url `%s`", url.to_str());
|
||||||
Some(*) => { }
|
engine_task.send(LoadUrlMsg(url));
|
||||||
None => { error!("keypress stream closed unexpectedly") }
|
|
||||||
};
|
debug!("master: Waiting for keypress");
|
||||||
|
match keypress_from_compositor.try_recv() {
|
||||||
|
Some(*) => {}
|
||||||
|
None => error!("keypress stream closed unexpectedly"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shut everything down
|
// Shut everything down
|
||||||
|
@ -184,46 +173,6 @@ fn run_pipeline_screen(opts: &Opts) {
|
||||||
engine_task.send(engine::ExitMsg(exit_chan));
|
engine_task.send(engine::ExitMsg(exit_chan));
|
||||||
exit_response_from_engine.recv();
|
exit_response_from_engine.recv();
|
||||||
|
|
||||||
osmain.chan.send(platform::osmain::Exit);
|
compositor.chan.send(compositing::Exit);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_pipeline_png(_opts: &Opts, _outfile: &str) {
|
|
||||||
fail!(~"PNG compositor is broken");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(broken)]
|
|
||||||
fn run_pipeline_png(url: ~str, outfile: &str) {
|
|
||||||
// Use a PNG encoder as the graphics compositor
|
|
||||||
use gfx::png_compositor;
|
|
||||||
use png_compositor::PngCompositor;
|
|
||||||
use io::{Writer, buffered_file_writer};
|
|
||||||
use resource::resource_task::ResourceTask;
|
|
||||||
use resource::image_cache_task::SyncImageCacheTask;
|
|
||||||
|
|
||||||
listen(|pngdata_from_compositor| {
|
|
||||||
let (dom_event_port, dom_event_chan) = comm::stream();
|
|
||||||
let dom_event_chan = comm::SharedChan(dom_event_chan);
|
|
||||||
|
|
||||||
let compositor = PngCompositor(pngdata_from_compositor);
|
|
||||||
let resource_task = ResourceTask();
|
|
||||||
// For the PNG pipeline we are using a synchronous image task so that all images will be
|
|
||||||
// fulfilled before the first paint.
|
|
||||||
let image_cache_task = SyncImageCacheTask(resource_task);
|
|
||||||
let engine_task = Engine(copy compositor,
|
|
||||||
dom_event_port,
|
|
||||||
dom_event_chan,
|
|
||||||
resource_task,
|
|
||||||
image_cache_task);
|
|
||||||
engine_task.send(LoadURLMsg(make_url(copy url, None)));
|
|
||||||
|
|
||||||
match buffered_file_writer(&Path(outfile)) {
|
|
||||||
Ok(writer) => writer.write(pngdata_from_compositor.recv()),
|
|
||||||
Err(e) => fail!(e)
|
|
||||||
}
|
|
||||||
|
|
||||||
let (exit_chan, exit_response_from_engine) = comm::stream();
|
|
||||||
engine_task.send(engine::ExitMsg(exit_chan));
|
|
||||||
exit_response_from_engine.recv();
|
|
||||||
compositor.send(png_compositor::Exit);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
34
src/servo/windowing.rs
Normal file
34
src/servo/windowing.rs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
//! Abstract windowing methods. The concrete implementations of these can be found in `platform/`.
|
||||||
|
|
||||||
|
use geom::size::Size2D;
|
||||||
|
|
||||||
|
/// Type of the function that is called when the screen is to be redisplayed.
|
||||||
|
pub type CompositeCallback = @fn();
|
||||||
|
|
||||||
|
/// Type of the function that is called when the window is resized.
|
||||||
|
pub type ResizeCallback = @fn(uint, uint);
|
||||||
|
|
||||||
|
/// Methods for an abstract Application.
|
||||||
|
pub trait ApplicationMethods {
|
||||||
|
fn new() -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait WindowMethods<A> {
|
||||||
|
/// Creates a new window.
|
||||||
|
pub fn new(app: &A) -> @mut Self;
|
||||||
|
/// Returns the size of the window.
|
||||||
|
pub fn size(&self) -> Size2D<f32>;
|
||||||
|
/// Presents the window to the screen (perhaps by page flipping).
|
||||||
|
pub fn present(&mut self);
|
||||||
|
/// Registers a callback to run when a composite event occurs.
|
||||||
|
pub fn set_composite_callback(&mut self, new_composite_callback: CompositeCallback);
|
||||||
|
/// Registers a callback to run when a resize event occurs.
|
||||||
|
pub fn set_resize_callback(&mut self, new_resize_callback: ResizeCallback);
|
||||||
|
/// Spins the event loop.
|
||||||
|
pub fn check_loop(@mut self);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue