aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreschweic <eschweickart@mozilla.com>2013-06-20 17:37:47 -0700
committereschweic <eschweickart@mozilla.com>2013-06-20 17:37:47 -0700
commitd95988da80f3bbd9df65d245c5324fd8035fc2a6 (patch)
treec5a12d8d398c2a3c2119a1852adb57d429ba6bf9
parent0bb3fbdde0b59a5d3df38a7fd7b970633300585c (diff)
downloadservo-d95988da80f3bbd9df65d245c5324fd8035fc2a6.tar.gz
servo-d95988da80f3bbd9df65d245c5324fd8035fc2a6.zip
Implement dynamic resolution, messaging from compositor to renderer, delete unused texture layers
-rw-r--r--src/components/gfx/render_task.rs41
-rw-r--r--src/components/main/compositing/mod.rs85
-rw-r--r--src/components/main/engine.rs4
-rw-r--r--src/components/msg/compositor.rs3
m---------src/support/layers/rust-layers0
5 files changed, 97 insertions, 36 deletions
diff --git a/src/components/gfx/render_task.rs b/src/components/gfx/render_task.rs
index a0b54d8dd9e..32368265deb 100644
--- a/src/components/gfx/render_task.rs
+++ b/src/components/gfx/render_task.rs
@@ -31,6 +31,7 @@ pub struct RenderLayer {
pub enum Msg<C> {
AttachCompositorMsg(C),
RenderMsg(RenderLayer),
+ ReRenderMsg(f32),
ExitMsg(Chan<()>),
}
@@ -82,6 +83,7 @@ pub fn create_render_task<C: RenderListener + Owned>(port: Port<Msg<C>>,
opts: opts_cell.take(),
profiler_chan: profiler_chan_copy,
share_gl_context: share_gl_context,
+ render_layer: None,
};
renderer.start();
@@ -98,6 +100,9 @@ priv struct Renderer<C> {
profiler_chan: ProfilerChan,
share_gl_context: AzGLContext,
+
+ /// The layer to be rendered
+ render_layer: Option<RenderLayer>,
}
impl<C: RenderListener + Owned> Renderer<C> {
@@ -107,7 +112,13 @@ impl<C: RenderListener + Owned> Renderer<C> {
loop {
match self.port.recv() {
AttachCompositorMsg(compositor) => self.compositor = compositor,
- RenderMsg(render_layer) => self.render(render_layer),
+ RenderMsg(render_layer) => {
+ self.render_layer = Some(render_layer);
+ self.render(1.0);
+ }
+ ReRenderMsg(scale) => {
+ self.render(scale);
+ }
ExitMsg(response_ch) => {
response_ch.send(());
break;
@@ -116,12 +127,20 @@ impl<C: RenderListener + Owned> Renderer<C> {
}
}
- fn render(&mut self, render_layer: RenderLayer) {
+ fn render(&mut self, scale: f32) {
debug!("renderer: rendering");
+
+ let render_layer;
+ match (self.render_layer) {
+ None => return,
+ Some(ref r_layer) => {
+ render_layer = r_layer;
+ }
+ }
+
self.compositor.set_render_state(RenderingRenderState);
do profile(time::RenderingCategory, self.profiler_chan.clone()) {
let tile_size = self.opts.tile_size;
- let scale = self.opts.zoom;
// FIXME: Try not to create a new array here.
let mut new_buffers = ~[];
@@ -129,17 +148,17 @@ impl<C: RenderListener + Owned> Renderer<C> {
// Divide up the layer into tiles.
do time::profile(time::RenderingPrepBuffCategory, self.profiler_chan.clone()) {
let mut y = 0;
- while y < render_layer.size.height * scale {
+ while y < (render_layer.size.height as f32 * scale).ceil() as uint {
let mut x = 0;
- while x < render_layer.size.width * scale {
+ while x < (render_layer.size.width as f32 * scale).ceil() as uint {
// Figure out the dimension of this tile.
- let right = uint::min(x + tile_size, render_layer.size.width * scale);
- let bottom = uint::min(y + tile_size, render_layer.size.height * scale);
+ let right = uint::min(x + tile_size, (render_layer.size.width as f32 * scale).ceil() as uint);
+ let bottom = uint::min(y + tile_size, (render_layer.size.height as f32 * scale).ceil() as uint);
let width = right - x;
let height = bottom - y;
- let tile_rect = Rect(Point2D(x / scale, y / scale), Size2D(width, height)); //change this
- let screen_rect = Rect(Point2D(x, y), Size2D(width, height)); //change this
+ let tile_rect = Rect(Point2D(x as f32 / scale, y as f32 / scale), Size2D(width as f32, height as f32));
+ let screen_rect = Rect(Point2D(x, y), Size2D(width, height));
let buffer = LayerBuffer {
draw_target: DrawTarget::new_with_fbo(self.opts.render_backend,
@@ -162,8 +181,8 @@ impl<C: RenderListener + Owned> Renderer<C> {
// Apply the translation to render the tile we want.
let matrix: Matrix2D<AzFloat> = Matrix2D::identity();
let matrix = matrix.scale(scale as AzFloat, scale as AzFloat);
- let matrix = matrix.translate(-(buffer.rect.origin.x as f32) as AzFloat,
- -(buffer.rect.origin.y as f32) as AzFloat);
+ let matrix = matrix.translate(-(buffer.rect.origin.x) as AzFloat,
+ -(buffer.rect.origin.y) as AzFloat);
ctx.canvas.draw_target.set_transform(&matrix);
diff --git a/src/components/main/compositing/mod.rs b/src/components/main/compositing/mod.rs
index 5eb82234e0b..c56c179707d 100644
--- a/src/components/main/compositing/mod.rs
+++ b/src/components/main/compositing/mod.rs
@@ -10,6 +10,7 @@ use windowing::{ApplicationMethods, WindowMethods, WindowMouseEvent, WindowClick
use windowing::{WindowMouseDownEvent, WindowMouseUpEvent};
use servo_msg::compositor::{RenderListener, LayerBufferSet, RenderState};
use servo_msg::compositor::{ReadyState, ScriptListener};
+use gfx::render_task::{RenderChan, ReRenderMsg};
use azure::azure_hl::{DataSourceSurface, DrawTarget, SourceSurfaceMethods, current_gl_context};
use azure::azure::AzGLContext;
@@ -29,6 +30,7 @@ use servo_util::{time, url};
use servo_util::time::profile;
use servo_util::time::ProfilerChan;
+
/// The implementation of the layers-based compositor.
#[deriving(Clone)]
pub struct CompositorChan {
@@ -84,6 +86,8 @@ pub enum Msg {
ChangeRenderState(RenderState),
/// Sets the channel to the current layout task
SetLayoutChan(LayoutChan),
+ /// Sets the channel to the current renderer
+ SetRenderChan(RenderChan<CompositorChan>),
}
/// Azure surface wrapping to work with the layers infrastructure.
@@ -166,6 +170,11 @@ impl CompositorTask {
// Keeps track of the current zoom factor
let world_zoom = @mut 1f32;
+ // Keeps track of local zoom factor. Reset to 1 after a rerender event.
+ let local_zoom = @mut 1f32;
+ // Channel to the current renderer.
+ // FIXME: This probably shouldn't be stored like this.
+ let render_chan: @mut Option<RenderChan<CompositorChan>> = @mut None;
let update_layout_callbacks: @fn(LayoutChan) = |layout_chan: LayoutChan| {
let layout_chan_clone = layout_chan.clone();
@@ -200,6 +209,16 @@ impl CompositorTask {
event = MouseDownEvent(button, world_mouse_point(layer_mouse_point));
}
WindowMouseUpEvent(button, layer_mouse_point) => {
+
+ // rerender layer at new zoom level
+ // FIXME: this should happen when the user stops zooming, definitely not here
+ match *render_chan {
+ Some(ref r_chan) => {
+ r_chan.send(ReRenderMsg(*world_zoom));
+ }
+ None => {} // Nothing to do
+ }
+
event = MouseUpEvent(button, world_mouse_point(layer_mouse_point));
}
}
@@ -220,6 +239,10 @@ impl CompositorTask {
update_layout_callbacks(layout_chan);
}
+ SetRenderChan(new_render_chan) => {
+ *render_chan = Some(new_render_chan);
+ }
+
GetGLContext(chan) => chan.send(current_gl_context()),
Paint(new_layer_buffer_set, new_size) => {
@@ -248,7 +271,7 @@ impl CompositorTask {
None => {
debug!("osmain: adding new texture layer");
texture_layer = @mut TextureLayer::new(@buffer.draw_target.clone() as @TextureManager,
- buffer.rect.size);
+ buffer.screen_pos.size);
root_layer.add_child(TextureLayerKind(texture_layer));
None
}
@@ -273,6 +296,21 @@ impl CompositorTask {
texture_layer.common.set_transform(transform);
}
+ // Delete leftover layers
+ while current_layer_child.is_some() {
+ let trash = current_layer_child.get();
+ do current_layer_child.get().with_common |common| {
+ current_layer_child = common.next_sibling;
+ }
+ root_layer.remove_child(trash);
+ }
+
+ // Reset zoom
+ *local_zoom = 1f32;
+ root_layer.common.set_transform(identity().translate(-world_offset.x,
+ -world_offset.y,
+ 0.0));
+
// TODO: Recycle the old buffers; send them back to the renderer to reuse if
// it wishes.
@@ -304,24 +342,25 @@ impl CompositorTask {
// 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);
+ world_offset.x = world_offset.x.clamp(&0.0, &max_x).round();
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);
-
+ world_offset.y = world_offset.y.clamp(&0.0, &max_y).round();
+
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 * *local_zoom - world_offset.x,
+ window_size.height as f32 / 2f32 * *local_zoom - world_offset.y,
+ 0.0);
+ scroll_transform = scroll_transform.scale(*local_zoom, *local_zoom, 1f32);
scroll_transform = scroll_transform.translate(window_size.width as f32 / -2f32,
- window_size.height as f32 / -2f32,
- 0.0);
-
+ window_size.height as f32 / -2f32,
+ 0.0);
+
root_layer.common.set_transform(scroll_transform);
-
+
window.set_needs_display()
}
@@ -333,6 +372,7 @@ impl CompositorTask {
// Determine zoom amount
*world_zoom = (*world_zoom * magnification).max(&1.0);
+ *local_zoom = *local_zoom * *world_zoom/old_world_zoom;
// Update world offset
let corner_to_center_x = world_offset.x + window_size.width as f32 / 2f32;
@@ -345,23 +385,22 @@ impl CompositorTask {
// 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);
+ world_offset.x = world_offset.x.clamp(&0.0, &max_x).round();
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);
-
-
+ world_offset.y = world_offset.y.clamp(&0.0, &max_y).round();
+
// 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,
+ zoom_transform = zoom_transform.translate(window_size.width as f32 / 2f32 * *local_zoom - world_offset.x,
+ window_size.height as f32 / 2f32 * *local_zoom - world_offset.y,
0.0);
- zoom_transform = zoom_transform.scale(*world_zoom, *world_zoom, 1f32);
+ zoom_transform = zoom_transform.scale(*local_zoom, *local_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.
diff --git a/src/components/main/engine.rs b/src/components/main/engine.rs
index 3da355a08c7..0538e252e53 100644
--- a/src/components/main/engine.rs
+++ b/src/components/main/engine.rs
@@ -2,7 +2,7 @@
* 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 compositing::{CompositorChan, SetLayoutChan};
+use compositing::{CompositorChan, SetLayoutChan, SetRenderChan};
use layout::layout_task;
use core::cell::Cell;
@@ -62,6 +62,8 @@ impl Engine {
compositor_chan.send(SetLayoutChan(layout_chan.clone()));
+ compositor_chan.send(SetRenderChan(render_chan.clone()));
+
let compositor_chan = Cell(compositor_chan);
let opts = Cell(copy *opts);
diff --git a/src/components/msg/compositor.rs b/src/components/msg/compositor.rs
index 1cd50843449..6b6311fd1ba 100644
--- a/src/components/msg/compositor.rs
+++ b/src/components/msg/compositor.rs
@@ -11,8 +11,9 @@ pub struct LayerBuffer {
draw_target: DrawTarget,
// The rect in the containing RenderLayer that this represents.
- rect: Rect<uint>,
+ rect: Rect<f32>,
+ // The rect in pixels that will be drawn to the screen.
screen_pos: Rect<uint>,
// NB: stride is in pixels, like OpenGL GL_UNPACK_ROW_LENGTH.
diff --git a/src/support/layers/rust-layers b/src/support/layers/rust-layers
-Subproject e0898b8555261dc01485883486df13afbcbd4dd
+Subproject 1e1e359da32c9d0ddb4f93b505a658d66900842