mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
Add a spinner for layout
This commit is contained in:
parent
96b9be6c33
commit
204c5b663a
9 changed files with 77 additions and 23 deletions
|
@ -24,9 +24,17 @@ pub struct LayerBufferSet {
|
|||
buffers: ~[LayerBuffer]
|
||||
}
|
||||
|
||||
/// The status of the renderer.
|
||||
#[deriving(Eq)]
|
||||
pub enum RenderState {
|
||||
IdleRenderState,
|
||||
RenderingRenderState,
|
||||
}
|
||||
|
||||
/// 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 paint(&self, layer_buffer_set: LayerBufferSet, new_size: Size2D<uint>);
|
||||
fn set_render_state(&self, render_state: RenderState);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// The task that handles all rendering/painting.
|
||||
|
||||
use azure::AzFloat;
|
||||
use compositor::Compositor;
|
||||
use compositor::{Compositor, IdleRenderState, RenderingRenderState};
|
||||
use font_context::FontContext;
|
||||
use geom::matrix2d::Matrix2D;
|
||||
use opts::Opts;
|
||||
|
@ -122,6 +122,7 @@ impl<C: Compositor + Owned> Renderer<C> {
|
|||
|
||||
fn render(&mut self, render_layer: RenderLayer) {
|
||||
debug!("renderer: rendering");
|
||||
self.compositor.set_render_state(RenderingRenderState);
|
||||
do profile(time::RenderingCategory, self.profiler_chan.clone()) {
|
||||
let layer_buffer_set = do render_layers(&render_layer,
|
||||
&self.opts,
|
||||
|
@ -168,6 +169,7 @@ impl<C: Compositor + Owned> Renderer<C> {
|
|||
|
||||
debug!("renderer: returning surface");
|
||||
self.compositor.paint(layer_buffer_set, render_layer.size);
|
||||
self.compositor.set_render_state(IdleRenderState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ use script::script_task::{LoadMsg, ScriptMsg, SendEventMsg};
|
|||
use windowing::{ApplicationMethods, WindowMethods, WindowMouseEvent, WindowClickEvent};
|
||||
use windowing::{WindowMouseDownEvent, WindowMouseUpEvent};
|
||||
|
||||
use gfx::compositor::RenderState;
|
||||
use script::dom::event::{Event, ClickEvent, MouseDownEvent, MouseUpEvent};
|
||||
use script::compositor_interface::{ReadyState, CompositorInterface};
|
||||
use script::compositor_interface;
|
||||
|
@ -20,7 +21,7 @@ use core::util;
|
|||
use geom::matrix::identity;
|
||||
use geom::point::Point2D;
|
||||
use geom::size::Size2D;
|
||||
use gfx::compositor::{Compositor, LayerBufferSet};
|
||||
use gfx::compositor::{Compositor, LayerBufferSet, RenderState};
|
||||
use layers::layers::{ARGB32Format, BasicImageData, ContainerLayer, ContainerLayerKind, Format};
|
||||
use layers::layers::{Image, ImageData, ImageLayer, ImageLayerKind, RGB24Format, WithDataFn};
|
||||
use layers::rendergl;
|
||||
|
@ -39,8 +40,8 @@ pub struct CompositorTask {
|
|||
}
|
||||
|
||||
impl CompositorInterface for CompositorTask {
|
||||
fn send_compositor_msg(&self, msg: ReadyState) {
|
||||
let msg = ChangeReadyState(msg);
|
||||
fn set_ready_state(&self, ready_state: ReadyState) {
|
||||
let msg = ChangeReadyState(ready_state);
|
||||
self.chan.send(msg);
|
||||
}
|
||||
}
|
||||
|
@ -48,8 +49,7 @@ impl CompositorInterface for CompositorTask {
|
|||
impl CompositorTask {
|
||||
/// Starts the compositor. Returns an interface that can be used to communicate with the
|
||||
/// compositor and a port which allows notification when the compositor shuts down.
|
||||
pub fn new(script_chan: SharedChan<ScriptMsg>,
|
||||
profiler_chan: ProfilerChan)
|
||||
pub fn new(script_chan: SharedChan<ScriptMsg>, profiler_chan: ProfilerChan)
|
||||
-> (CompositorTask, Port<()>) {
|
||||
let script_chan = Cell(script_chan);
|
||||
let (shutdown_port, shutdown_chan) = stream();
|
||||
|
@ -76,8 +76,10 @@ pub enum Msg {
|
|||
Exit,
|
||||
/// Requests that the compositor paint the given layer buffer set for the given page size.
|
||||
Paint(LayerBufferSet, Size2D<uint>),
|
||||
/// Alerts the compositor to the current status of page loading
|
||||
/// Alerts the compositor to the current status of page loading.
|
||||
ChangeReadyState(ReadyState),
|
||||
/// Alerts the compositor to the current status of rendering.
|
||||
ChangeRenderState(RenderState),
|
||||
}
|
||||
|
||||
/// Azure surface wrapping to work with the layers infrastructure.
|
||||
|
@ -151,6 +153,7 @@ fn run_main_loop(port: Port<Msg>,
|
|||
Exit => *done = true,
|
||||
|
||||
ChangeReadyState(ready_state) => window.set_ready_state(ready_state),
|
||||
ChangeRenderState(render_state) => window.set_render_state(render_state),
|
||||
|
||||
Paint(new_layer_buffer_set, new_size) => {
|
||||
debug!("osmain: received new frame");
|
||||
|
@ -356,6 +359,9 @@ impl Compositor for CompositorTask {
|
|||
fn paint(&self, layer_buffer_set: LayerBufferSet, new_size: Size2D<uint>) {
|
||||
self.chan.send(Paint(layer_buffer_set, new_size))
|
||||
}
|
||||
fn set_render_state(&self, render_state: RenderState) {
|
||||
self.chan.send(ChangeRenderState(render_state))
|
||||
}
|
||||
}
|
||||
|
||||
/// A function for spawning into the platform's main thread.
|
||||
|
|
|
@ -78,7 +78,7 @@ impl Engine {
|
|||
script_chan.take(),
|
||||
engine_chan_clone.clone(),
|
||||
|msg: ReadyState| {
|
||||
compositor_clone.send_compositor_msg(msg)
|
||||
compositor_clone.set_ready_state(msg)
|
||||
},
|
||||
layout_task.clone(),
|
||||
resource_task.clone(),
|
||||
|
|
|
@ -38,7 +38,7 @@ use script::layout_interface::{ContentBoxesQuery, ContentBoxesResponse, ExitMsg,
|
|||
use script::layout_interface::{LayoutResponse, LayoutTask, MatchSelectorsDocumentDamage, Msg};
|
||||
use script::layout_interface::{QueryMsg, Reflow, ReflowDocumentDamage, ReflowForDisplay};
|
||||
use script::layout_interface::{ReflowMsg};
|
||||
use script::script_task::{ScriptMsg, SendEventMsg};
|
||||
use script::script_task::{ReflowCompleteMsg, ScriptMsg, SendEventMsg};
|
||||
use servo_net::image_cache_task::{ImageCacheTask, ImageResponseMsg};
|
||||
use servo_net::local_image_cache::LocalImageCache;
|
||||
use servo_util::tree::{TreeNodeRef, TreeUtils};
|
||||
|
@ -255,7 +255,11 @@ impl Layout {
|
|||
debug!("%?", layout_root.dump());
|
||||
|
||||
// Tell script that we're done.
|
||||
//
|
||||
// FIXME(pcwalton): This should probably be *one* channel, but we can't fix this without
|
||||
// either select or a filtered recv() that only looks for messages of a given type.
|
||||
data.script_join_chan.send(());
|
||||
data.script_chan.send(ReflowCompleteMsg);
|
||||
}
|
||||
|
||||
/// Handles a query from the script task. This is the main routine that DOM functions like
|
||||
|
|
|
@ -16,10 +16,11 @@ use core::cell::Cell;
|
|||
use core::libc::c_int;
|
||||
use geom::point::Point2D;
|
||||
use geom::size::Size2D;
|
||||
use gfx::compositor::{IdleRenderState, RenderState, RenderingRenderState};
|
||||
use glut::glut::{ACTIVE_CTRL, DOUBLE, HAVE_PRECISE_MOUSE_WHEEL, WindowHeight, WindowWidth};
|
||||
use glut::glut;
|
||||
use glut::machack;
|
||||
use script::compositor_interface::{FinishedLoading, Loading, Rendering, ReadyState};
|
||||
use script::compositor_interface::{FinishedLoading, Loading, PerformingLayout, ReadyState};
|
||||
|
||||
static THROBBER: [char, ..8] = [ '⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷' ];
|
||||
|
||||
|
@ -51,6 +52,7 @@ pub struct Window {
|
|||
mouse_down_point: @mut Point2D<c_int>,
|
||||
|
||||
ready_state: ReadyState,
|
||||
render_state: RenderState,
|
||||
throbber_frame: u8,
|
||||
}
|
||||
|
||||
|
@ -78,6 +80,7 @@ impl WindowMethods<Application> for Window {
|
|||
mouse_down_point: @mut Point2D(0, 0),
|
||||
|
||||
ready_state: FinishedLoading,
|
||||
render_state: IdleRenderState,
|
||||
throbber_frame: 0,
|
||||
};
|
||||
|
||||
|
@ -190,6 +193,12 @@ impl WindowMethods<Application> for Window {
|
|||
self.ready_state = ready_state;
|
||||
self.update_window_title()
|
||||
}
|
||||
|
||||
/// Sets the render state.
|
||||
pub fn set_render_state(@mut self, render_state: RenderState) {
|
||||
self.render_state = render_state;
|
||||
self.update_window_title()
|
||||
}
|
||||
}
|
||||
|
||||
impl Window {
|
||||
|
@ -200,10 +209,19 @@ impl Window {
|
|||
Loading => {
|
||||
glut::set_window_title(self.glut_window, fmt!("%c Loading — Servo", throbber))
|
||||
}
|
||||
Rendering => {
|
||||
glut::set_window_title(self.glut_window, fmt!("%c Rendering — Servo", throbber))
|
||||
PerformingLayout => {
|
||||
glut::set_window_title(self.glut_window,
|
||||
fmt!("%c Performing Layout — Servo", throbber))
|
||||
}
|
||||
FinishedLoading => {
|
||||
match self.render_state {
|
||||
RenderingRenderState => {
|
||||
glut::set_window_title(self.glut_window,
|
||||
fmt!("%c Rendering — Servo", throbber))
|
||||
}
|
||||
IdleRenderState => glut::set_window_title(self.glut_window, "Servo"),
|
||||
}
|
||||
}
|
||||
FinishedLoading => glut::set_window_title(self.glut_window, "Servo"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
use geom::point::Point2D;
|
||||
use geom::size::Size2D;
|
||||
use gfx::compositor::RenderState;
|
||||
use script::compositor_interface::ReadyState;
|
||||
|
||||
pub enum WindowMouseEvent {
|
||||
|
@ -64,5 +65,7 @@ pub trait WindowMethods<A> {
|
|||
pub fn set_needs_display(@mut self);
|
||||
/// Sets the ready state of the current page.
|
||||
pub fn set_ready_state(@mut self, ready_state: ReadyState);
|
||||
/// Sets the render state of the current page.
|
||||
pub fn set_render_state(@mut self, render_state: RenderState);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
pub enum ReadyState {
|
||||
/// Informs the compositor that a page is loading. Used for setting status
|
||||
Loading,
|
||||
/// Informs the compositor that a page is rendering. Used for setting status
|
||||
Rendering,
|
||||
/// Informs the compositor that a page is performing layout. Used for setting status
|
||||
PerformingLayout,
|
||||
/// Informs the compositor that a page is finished loading. Used for setting status
|
||||
FinishedLoading,
|
||||
}
|
||||
|
||||
pub trait CompositorInterface : Clone {
|
||||
fn send_compositor_msg(&self, ReadyState);
|
||||
fn set_ready_state(&self, ReadyState);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
/// The script task is the task that owns the DOM in memory, runs JavaScript, and spawns parsing
|
||||
/// and layout tasks.
|
||||
|
||||
use compositor_interface::{ReadyState, Loading, Rendering, FinishedLoading};
|
||||
use compositor_interface::{ReadyState, Loading, PerformingLayout, FinishedLoading};
|
||||
use dom::bindings::utils::GlobalStaticData;
|
||||
use dom::document::Document;
|
||||
use dom::element::Element;
|
||||
|
@ -54,6 +54,8 @@ pub enum ScriptMsg {
|
|||
SendEventMsg(Event),
|
||||
/// Fires a JavaScript timeout.
|
||||
FireTimerMsg(~TimerData),
|
||||
/// Notifies script that reflow is finished.
|
||||
ReflowCompleteMsg,
|
||||
/// Exits the engine.
|
||||
ExitMsg,
|
||||
}
|
||||
|
@ -262,6 +264,10 @@ impl ScriptContext {
|
|||
self.handle_fire_timer_msg(timer_data);
|
||||
true
|
||||
}
|
||||
ReflowCompleteMsg => {
|
||||
self.handle_reflow_complete_msg();
|
||||
true
|
||||
}
|
||||
ExitMsg => {
|
||||
self.handle_exit_msg();
|
||||
false
|
||||
|
@ -306,6 +312,12 @@ impl ScriptContext {
|
|||
self.reflow(ReflowForScriptQuery)
|
||||
}
|
||||
|
||||
/// Handles a notification that reflow completed.
|
||||
fn handle_reflow_complete_msg(&mut self) {
|
||||
self.layout_join_port = None;
|
||||
self.set_ready_state(FinishedLoading)
|
||||
}
|
||||
|
||||
/// Handles a request to exit the script task and shut down layout.
|
||||
fn handle_exit_msg(&mut self) {
|
||||
self.join_layout();
|
||||
|
@ -318,7 +330,7 @@ impl ScriptContext {
|
|||
|
||||
// tells the compositor when loading starts and finishes
|
||||
// FIXME ~compositor_interface doesn't work right now, which is why this is necessary
|
||||
fn send_compositor_msg(&self, msg: ReadyState) {
|
||||
fn set_ready_state(&self, msg: ReadyState) {
|
||||
(self.compositor_task)(msg);
|
||||
}
|
||||
|
||||
|
@ -333,7 +345,7 @@ impl ScriptContext {
|
|||
self.bindings_initialized = true
|
||||
}
|
||||
|
||||
self.send_compositor_msg(Loading);
|
||||
self.set_ready_state(Loading);
|
||||
// Parse HTML.
|
||||
//
|
||||
// Note: We can parse the next document in parallel with any previous documents.
|
||||
|
@ -374,7 +386,6 @@ impl ScriptContext {
|
|||
url: url
|
||||
});
|
||||
|
||||
self.send_compositor_msg(Rendering);
|
||||
// Perform the initial reflow.
|
||||
self.damage = Some(DocumentDamage {
|
||||
root: root_node,
|
||||
|
@ -392,7 +403,6 @@ impl ScriptContext {
|
|||
~"???",
|
||||
1);
|
||||
}
|
||||
self.send_compositor_msg(FinishedLoading);
|
||||
}
|
||||
|
||||
/// Sends a ping to layout and waits for the response. The response will arrive when the
|
||||
|
@ -426,6 +436,9 @@ impl ScriptContext {
|
|||
// Now, join the layout so that they will see the latest changes we have made.
|
||||
self.join_layout();
|
||||
|
||||
// Tell the user that we're performing layout.
|
||||
self.set_ready_state(PerformingLayout);
|
||||
|
||||
// Layout will let us know when it's done.
|
||||
let (join_port, join_chan) = comm::stream();
|
||||
self.layout_join_port = Some(join_port);
|
||||
|
@ -438,8 +451,8 @@ impl ScriptContext {
|
|||
document_root: root_frame.document.root,
|
||||
url: copy root_frame.url,
|
||||
goal: goal,
|
||||
script_chan: self.script_chan.clone(),
|
||||
window_size: self.window_size,
|
||||
script_chan: self.script_chan.clone(),
|
||||
script_join_chan: join_chan,
|
||||
damage: replace(&mut self.damage, None).unwrap(),
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue