diff options
author | eschweic <eschweickart@mozilla.com> | 2013-06-20 17:37:47 -0700 |
---|---|---|
committer | eschweic <eschweickart@mozilla.com> | 2013-06-20 17:37:47 -0700 |
commit | d95988da80f3bbd9df65d245c5324fd8035fc2a6 (patch) | |
tree | c5a12d8d398c2a3c2119a1852adb57d429ba6bf9 | |
parent | 0bb3fbdde0b59a5d3df38a7fd7b970633300585c (diff) | |
download | servo-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.rs | 41 | ||||
-rw-r--r-- | src/components/main/compositing/mod.rs | 85 | ||||
-rw-r--r-- | src/components/main/engine.rs | 4 | ||||
-rw-r--r-- | src/components/msg/compositor.rs | 3 | ||||
m--------- | src/support/layers/rust-layers | 0 |
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 |