Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Refactor the compositing interface to use messages instead of callbacks. #520

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Refactor the compositing interface to use messages instead of callbacks.

This will enable compositing to be cleaned up drastically and is necessary
for proper integration with the new scheduler.
  • Loading branch information
pcwalton committed Jun 15, 2013
commit f1c24a94b1d13cd06fe1c576b804f3dc7c736c1e
@@ -5,13 +5,10 @@
use compositing::resize_rate_limiter::ResizeRateLimiter;
use platform::{Application, Window};
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;
use windowing::{ApplicationMethods, CompositeWindowEvent, IdleWindowEvent, MouseWindowClickEvent};
use windowing::{MouseWindowEvent, MouseWindowEventClass, MouseWindowMouseDownEvent};
use windowing::{MouseWindowMouseUpEvent, NavigateWindowEvent, QuitWindowEvent, ResizeWindowEvent};
use windowing::{ScrollWindowEvent, WindowMethods, ZoomWindowEvent};

use azure::azure_hl::{DataSourceSurface, DrawTarget, SourceSurfaceMethods, current_gl_context};
use azure::azure::AzGLContext;
@@ -28,6 +25,9 @@ use layers::layers::{ImageData, WithDataFn};
use layers::layers::{TextureLayerKind, TextureLayer, TextureManager};
use layers::rendergl;
use layers::scene::Scene;
use script::dom::event::{Event, ClickEvent, MouseDownEvent, MouseUpEvent};
use script::compositor_interface::{ReadyState, CompositorInterface};
use script::compositor_interface;
use servo_util::{time, url};
use servo_util::time::profile;
use servo_util::time::ProfilerChan;
@@ -76,7 +76,7 @@ impl CompositorTask {
pub enum Msg {
/// Requests that the compositor shut down.
Exit,
/// Requests the compositors GL context.
/// Requests the compositor's OpenGL context.
GetGLContext(Chan<AzGLContext>),
/// Requests that the compositor paint the given layer buffer set for the given page size.
Paint(LayerBufferSet, Size2D<uint>),
@@ -211,132 +211,140 @@ fn run_main_loop(port: Port<Msg>,
}
};

do window.set_composite_callback {
do profile(time::CompositingCategory, profiler_chan.clone()) {
debug!("compositor: compositing");
// Adjust the layer dimensions as necessary to correspond to the size of the window.
scene.size = window.size();

// Render the scene.
rendergl::render_scene(context, scene);
}

window.present();
}

// Hook the windowing system's resize callback up to the resize rate limiter.
do window.set_resize_callback |width, height| {
debug!("osmain: window resized to %ux%u", width, height);
*window_size = Size2D(width, height);
resize_rate_limiter.window_resized(width, height)
}

let script_chan_clone = script_chan.clone();

// When the user enters a new URL, load it.
do window.set_load_url_callback |url_string| {
debug!("osmain: loading URL `%s`", url_string);
script_chan_clone.send(LoadMsg(url::make_url(url_string.to_str(), None)))
}
// Enter the main event loop.
while !*done {
// Check for new messages coming from the rendering task.
check_for_messages();

let script_chan_clone = script_chan.clone();
// Check for messages coming from the windowing system.
match window.recv() {
CompositeWindowEvent => {
do profile(time::CompositingCategory, profiler_chan.clone()) {
debug!("compositor: compositing");
// Adjust the layer dimensions as necessary to correspond to the size of the
// window.
scene.size = window.size();

// Render the scene.
rendergl::render_scene(context, scene);
}

// When the user triggers a mouse event, perform appropriate hit testing
do window.set_mouse_callback |window_mouse_event: WindowMouseEvent| {
let event: Event;
let world_mouse_point = |layer_mouse_point: Point2D<f32>| {
layer_mouse_point + *world_offset
};
match window_mouse_event {
WindowClickEvent(button, layer_mouse_point) => {
event = ClickEvent(button, world_mouse_point(layer_mouse_point));
}
WindowMouseDownEvent(button, layer_mouse_point) => {
event = MouseDownEvent(button, world_mouse_point(layer_mouse_point));
window.present();
}
WindowMouseUpEvent(button, layer_mouse_point) => {
event = MouseUpEvent(button, world_mouse_point(layer_mouse_point));
}
}
script_chan_clone.send(SendEventMsg(event));
}

// When the user scrolls, move the layer around.
do window.set_scroll_callback |delta| {
// FIXME (Rust #2528): Can't use `-=`.
let world_offset_copy = *world_offset;
*world_offset = world_offset_copy - delta;

// Clamp the world offset to the screen size.
let max_x = (page_size.width * *world_zoom - window_size.width as f32).max(&0.0);
world_offset.x = world_offset.x.clamp(&0.0, &max_x);
let max_y = (page_size.height * *world_zoom - window_size.height as f32).max(&0.0);
world_offset.y = world_offset.y.clamp(&0.0, &max_y);

debug!("compositor: scrolled to %?", *world_offset);

let mut scroll_transform = identity();

scroll_transform = scroll_transform.translate(window_size.width as f32 / 2f32 * *world_zoom - world_offset.x,
window_size.height as f32 / 2f32 * *world_zoom - world_offset.y,
0.0);
scroll_transform = scroll_transform.scale(*world_zoom, *world_zoom, 1f32);
scroll_transform = scroll_transform.translate(window_size.width as f32 / -2f32,
window_size.height as f32 / -2f32,
0.0);

root_layer.common.set_transform(scroll_transform);

window.set_needs_display()
}



// When the user pinch-zooms, scale the layer
do window.set_zoom_callback |magnification| {
let old_world_zoom = *world_zoom;

// Determine zoom amount
*world_zoom = (*world_zoom * magnification).max(&1.0);

// Update world offset
let corner_to_center_x = world_offset.x + window_size.width as f32 / 2f32;
let new_corner_to_center_x = corner_to_center_x * *world_zoom / old_world_zoom;
world_offset.x = world_offset.x + new_corner_to_center_x - corner_to_center_x;

let corner_to_center_y = world_offset.y + window_size.height as f32 / 2f32;
let new_corner_to_center_y = corner_to_center_y * *world_zoom / old_world_zoom;
world_offset.y = world_offset.y + new_corner_to_center_y - corner_to_center_y;

// Clamp to page bounds when zooming out
let max_x = (page_size.width * *world_zoom - window_size.width as f32).max(&0.0);
world_offset.x = world_offset.x.clamp(&0.0, &max_x);
let max_y = (page_size.height * *world_zoom - window_size.height as f32).max(&0.0);
world_offset.y = world_offset.y.clamp(&0.0, &max_y);
ResizeWindowEvent(new_window_size) => {
// Hook the windowing system's resize callback up to the resize rate limiter.
*window_size = new_window_size;
resize_rate_limiter.window_resized(new_window_size.width, new_window_size.height)
}

NavigateWindowEvent(url_string) => {
// When the user enters a new URL, load it.
debug!("osmain: loading URL `%s`", url_string);
script_chan_clone.send(LoadMsg(url::make_url(url_string.to_str(), None)))
}

// Apply transformations
let mut zoom_transform = identity();
zoom_transform = zoom_transform.translate(window_size.width as f32 / 2f32 * *world_zoom - world_offset.x,
window_size.height as f32 / 2f32 * *world_zoom - world_offset.y,
0.0);
zoom_transform = zoom_transform.scale(*world_zoom, *world_zoom, 1f32);
zoom_transform = zoom_transform.translate(window_size.width as f32 / -2f32,
window_size.height as f32 / -2f32,
0.0);
root_layer.common.set_transform(zoom_transform);
MouseWindowEventClass(window_mouse_event) => {
// When the user triggers a mouse event, perform appropriate hit testing
let event: Event;
let world_mouse_point = |layer_mouse_point: Point2D<f32>| {
layer_mouse_point + *world_offset
};
match window_mouse_event {
MouseWindowClickEvent(button, layer_mouse_point) => {
event = ClickEvent(button, world_mouse_point(layer_mouse_point));
}
MouseWindowMouseDownEvent(button, layer_mouse_point) => {
event = MouseDownEvent(button, world_mouse_point(layer_mouse_point));
}
MouseWindowMouseUpEvent(button, layer_mouse_point) => {
event = MouseUpEvent(button, world_mouse_point(layer_mouse_point));
}
}
script_chan_clone.send(SendEventMsg(event));
}

ScrollWindowEvent(delta) => {
// When the user scrolls, move the layer around.
//
// FIXME (Rust #2528): Can't use `-=`.
let world_offset_copy = *world_offset;
*world_offset = world_offset_copy - delta;

// Clamp the world offset to the screen size.
let max_x = (page_size.width * *world_zoom -
window_size.width as f32).max(&0.0);
world_offset.x = world_offset.x.clamp(&0.0, &max_x);
let max_y = (page_size.height * *world_zoom -
window_size.height as f32).max(&0.0);
world_offset.y = world_offset.y.clamp(&0.0, &max_y);

debug!("compositor: scrolled to %?", *world_offset);

let mut scroll_transform = identity();

scroll_transform = scroll_transform.translate(window_size.width as f32 / 2f32 *
*world_zoom - world_offset.x,
window_size.height as f32 / 2f32 *
*world_zoom - world_offset.y,
0.0);
scroll_transform = scroll_transform.scale(*world_zoom, *world_zoom, 1f32);
scroll_transform = scroll_transform.translate(window_size.width as f32 / -2.0,
window_size.height as f32 / -2.0,
0.0);

root_layer.common.set_transform(scroll_transform);

window.set_needs_display()
}

window.set_needs_display()
}
ZoomWindowEvent(magnification) => {
// When the user pinch-zooms, scale the layer.
let old_world_zoom = *world_zoom;

// Determine zoom amount
*world_zoom = (*world_zoom * magnification).max(&1.0);

// Update world offset.
let corner_to_center_x = world_offset.x + window_size.width as f32 / 2f32;
let new_corner_to_center_x = corner_to_center_x * *world_zoom / old_world_zoom;
world_offset.x = world_offset.x + new_corner_to_center_x - corner_to_center_x;

let corner_to_center_y = world_offset.y + window_size.height as f32 / 2f32;
let new_corner_to_center_y = corner_to_center_y * *world_zoom / old_world_zoom;
world_offset.y = world_offset.y + new_corner_to_center_y - corner_to_center_y;

// Clamp to page bounds when zooming out.
let max_x = (page_size.width * *world_zoom -
window_size.width as f32).max(&0.0);
world_offset.x = world_offset.x.clamp(&0.0, &max_x);
let max_y = (page_size.height * *world_zoom -
window_size.height as f32).max(&0.0);
world_offset.y = world_offset.y.clamp(&0.0, &max_y);


// Apply transformations.
let mut zoom_transform = identity();
zoom_transform = zoom_transform.translate(window_size.width as f32 / 2f32 *
*world_zoom - world_offset.x,
window_size.height as f32 / 2f32 *
*world_zoom - world_offset.y,
0.0);
zoom_transform = zoom_transform.scale(*world_zoom, *world_zoom, 1f32);
zoom_transform = zoom_transform.translate(window_size.width as f32 / -2f32,
window_size.height as f32 / -2f32,
0.0);
root_layer.common.set_transform(zoom_transform);

window.set_needs_display()
}

// Enter the main event loop.
while !*done {
// Check for new messages coming from the rendering task.
check_for_messages();
IdleWindowEvent => {}

// Check for messages coming from the windowing system.
window.check_loop();
QuitWindowEvent => break,
}
}

shutdown_chan.send(())
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.