mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
Implement dynamic resolution, messaging from compositor to renderer, delete unused texture layers
This commit is contained in:
parent
0bb3fbdde0
commit
d95988da80
5 changed files with 98 additions and 37 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,21 +342,22 @@ 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);
|
||||
|
||||
|
@ -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,17 +385,16 @@ 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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit e0898b8555261dc01485883486df13afbcbd4dd0
|
||||
Subproject commit 1e1e359da32c9d0ddb4f93b505a658d669008426
|
Loading…
Add table
Add a link
Reference in a new issue