diff options
author | Patrick Walton <pcwalton@mimiga.net> | 2012-10-25 16:20:39 -0700 |
---|---|---|
committer | Patrick Walton <pcwalton@mimiga.net> | 2012-10-25 16:20:39 -0700 |
commit | 5c373c21d83cfb537c79e854d72544c0835cec2e (patch) | |
tree | f51ad45c250d3eb64a3ca9e38e5fd29ae9799298 | |
parent | 467c79953277971854604ea53f50b2b0766b50c5 (diff) | |
download | servo-5c373c21d83cfb537c79e854d72544c0835cec2e.tar.gz servo-5c373c21d83cfb537c79e854d72544c0835cec2e.zip |
gfx: Use layer buffer sets instead of a single layer buffer
-rw-r--r-- | src/servo/gfx/compositor.rs | 10 | ||||
-rw-r--r-- | src/servo/gfx/png_compositor.rs | 29 | ||||
-rw-r--r-- | src/servo/gfx/render_layers.rs | 11 | ||||
-rw-r--r-- | src/servo/gfx/render_task.rs | 30 | ||||
-rw-r--r-- | src/servo/platform/osmain.rs | 78 |
5 files changed, 87 insertions, 71 deletions
diff --git a/src/servo/gfx/compositor.rs b/src/servo/gfx/compositor.rs index f434564dd41..f704132dddf 100644 --- a/src/servo/gfx/compositor.rs +++ b/src/servo/gfx/compositor.rs @@ -16,12 +16,18 @@ struct LayerBuffer { stride: uint } +/// A set of layer buffers. This is an atomic unit used to switch between the front and back +/// buffers. +struct LayerBufferSet { + buffers: ~[LayerBuffer] +} + /** The interface used to by the renderer to aquire draw targets for each rendered frame and submit them to be drawn to the display */ trait Compositor { - fn begin_drawing(next_dt: pipes::Chan<LayerBuffer>); - fn draw(next_dt: pipes::Chan<LayerBuffer>, +draw_me: LayerBuffer); + fn begin_drawing(next_dt: pipes::Chan<LayerBufferSet>); + fn draw(next_dt: pipes::Chan<LayerBufferSet>, +draw_me: LayerBufferSet); } diff --git a/src/servo/gfx/png_compositor.rs b/src/servo/gfx/png_compositor.rs index 094a4181479..bd0f108feb2 100644 --- a/src/servo/gfx/png_compositor.rs +++ b/src/servo/gfx/png_compositor.rs @@ -12,8 +12,8 @@ use azure::azure_hl::DrawTarget; use cairo::cairo_hl::ImageSurface; use cairo::{CAIRO_FORMAT_ARGB32, cairo_surface_t, cairo_status_t, CAIRO_STATUS_SUCCESS}; use cairo_bg = cairo::bindgen; -use cairo_bg::{cairo_image_surface_create, cairo_surface_destroy, - cairo_surface_write_to_png_stream}; +use cairo_bg::{cairo_image_surface_create, cairo_surface_destroy}; +use cairo_bg::{cairo_surface_write_to_png_stream}; use compositor::Compositor; use render_task::{RenderTask, RenderMsg}; use task::spawn_listener; @@ -25,23 +25,23 @@ use dvec::DVec; use display_list::DisplayList; use std::cell::Cell; use core::io::BytesWriter; -use gfx::compositor::LayerBuffer; +use gfx::compositor::{LayerBuffer, LayerBufferSet}; use geom::size::Size2D; use gfx::render_layers::RenderLayer; pub type PngCompositor = Chan<Msg>; pub enum Msg { - BeginDrawing(pipes::Chan<LayerBuffer>), - Draw(pipes::Chan<LayerBuffer>, LayerBuffer), + BeginDrawing(pipes::Chan<LayerBufferSet>), + Draw(pipes::Chan<LayerBufferSet>, LayerBufferSet), Exit } impl Chan<Msg> : Compositor { - fn begin_drawing(next_dt: pipes::Chan<LayerBuffer>) { + fn begin_drawing(next_dt: pipes::Chan<LayerBufferSet>) { self.send(BeginDrawing(move next_dt)) } - fn draw(next_dt: pipes::Chan<LayerBuffer>, draw_me: LayerBuffer) { + fn draw(next_dt: pipes::Chan<LayerBufferSet>, draw_me: LayerBufferSet) { self.send(Draw(move next_dt, move draw_me)) } } @@ -56,17 +56,18 @@ pub fn PngCompositor(output: Chan<~[u8]>) -> PngCompositor { size: Size2D(800u, 600u), stride: 800 }; - let layer_buffer = Cell(move layer_buffer); + let layer_buffer_set = LayerBufferSet { buffers: ~[ move layer_buffer ] }; + let layer_buffer_set = Cell(move layer_buffer_set); loop { match po.recv() { BeginDrawing(sender) => { debug!("png_compositor: begin_drawing"); - sender.send(layer_buffer.take()); + sender.send(layer_buffer_set.take()); } - Draw(move sender, move layer_buffer) => { + Draw(move sender, move layer_buffer_set) => { debug!("png_compositor: draw"); - do_draw(move sender, move layer_buffer, output, &cairo_surface); + do_draw(move sender, move layer_buffer_set, output, &cairo_surface); } Exit => break } @@ -74,8 +75,8 @@ pub fn PngCompositor(output: Chan<~[u8]>) -> PngCompositor { } } -fn do_draw(sender: pipes::Chan<LayerBuffer>, - layer_buffer: LayerBuffer, +fn do_draw(sender: pipes::Chan<LayerBufferSet>, + layer_buffer_set: LayerBufferSet, output: Chan<~[u8]>, cairo_surface: &ImageSurface) { let buffer = BytesWriter(); @@ -83,7 +84,7 @@ fn do_draw(sender: pipes::Chan<LayerBuffer>, output.send(buffer.bytes.get()); // Send the next draw target to the renderer - sender.send(move layer_buffer); + sender.send(move layer_buffer_set); } #[test] diff --git a/src/servo/gfx/render_layers.rs b/src/servo/gfx/render_layers.rs index bd24bcd813c..8d155a23cea 100644 --- a/src/servo/gfx/render_layers.rs +++ b/src/servo/gfx/render_layers.rs @@ -1,5 +1,5 @@ use gfx::display_list::DisplayList; -use gfx::compositor::LayerBuffer; +use gfx::compositor::{LayerBuffer, LayerBufferSet}; use azure::azure_hl::DrawTarget; use cairo::CAIRO_FORMAT_RGB24; @@ -17,9 +17,10 @@ pub struct RenderLayer { /// given callback with the render layer and the buffer. Returns the resulting layer buffer (which /// might be the old layer buffer if it had the appropriate size and format). pub fn render_layers(layer: &RenderLayer, - buffer: LayerBuffer, - f: &fn(layer: &RenderLayer, buffer: &LayerBuffer) -> bool) -> LayerBuffer { - let mut buffer = move buffer; + buffer_set: LayerBufferSet, + f: &fn(layer: &RenderLayer, buffer: &LayerBuffer) -> bool) -> LayerBufferSet { + let mut buffers = match move buffer_set { LayerBufferSet { buffers: move b } => move b }; + let mut buffer = buffers.pop(); if buffer.size != layer.size { // Create a new buffer. @@ -44,6 +45,6 @@ pub fn render_layers(layer: &RenderLayer, } let _ = f(layer, &buffer); - return move buffer; + return LayerBufferSet { buffers: ~[ move buffer ] }; } diff --git a/src/servo/gfx/render_task.rs b/src/servo/gfx/render_task.rs index d762ffbf2ce..52ab43717e4 100644 --- a/src/servo/gfx/render_task.rs +++ b/src/servo/gfx/render_task.rs @@ -1,7 +1,7 @@ use au = gfx::geometry; use au::Au; use comm::*; -use compositor::{Compositor, LayerBuffer}; +use compositor::{Compositor, LayerBufferSet}; use dl = display_list; use mod gfx::render_layers; use render_layers::render_layers; @@ -24,7 +24,7 @@ pub type RenderTask = comm::Chan<Msg>; pub fn RenderTask<C: Compositor Send>(compositor: C) -> RenderTask { let compositor_cell = Cell(move compositor); do task::spawn_listener |po: comm::Port<Msg>, move compositor_cell| { - let (layer_buffer_channel, layer_buffer_port) = pipes::stream(); + let (layer_buffer_channel, layer_buffer_set_port) = pipes::stream(); let compositor = compositor_cell.take(); compositor.begin_drawing(move layer_buffer_channel); @@ -32,7 +32,7 @@ pub fn RenderTask<C: Compositor Send>(compositor: C) -> RenderTask { Renderer { port: po, compositor: move compositor, - mut layer_buffer_port: Cell(move layer_buffer_port), + mut layer_buffer_set_port: Cell(move layer_buffer_set_port), font_cache: FontCache(), }.start(); } @@ -41,7 +41,7 @@ pub fn RenderTask<C: Compositor Send>(compositor: C) -> RenderTask { priv struct Renderer<C: Compositor Send> { port: comm::Port<Msg>, compositor: C, - layer_buffer_port: Cell<pipes::Port<LayerBuffer>>, + layer_buffer_set_port: Cell<pipes::Port<LayerBufferSet>>, font_cache: @FontCache } @@ -63,28 +63,28 @@ impl<C: Compositor Send> Renderer<C> { fn render(render_layer: RenderLayer) { debug!("renderer: got render request"); - let layer_buffer_port = self.layer_buffer_port.take(); + let layer_buffer_set_port = self.layer_buffer_set_port.take(); - if !layer_buffer_port.peek() { + if !layer_buffer_set_port.peek() { warn!("renderer: waiting on layer buffer"); } - let layer_buffer = layer_buffer_port.recv(); - let (layer_buffer_channel, new_layer_buffer_port) = pipes::stream(); - self.layer_buffer_port.put_back(move new_layer_buffer_port); + let layer_buffer_set = layer_buffer_set_port.recv(); + let (layer_buffer_set_channel, new_layer_buffer_set_port) = pipes::stream(); + self.layer_buffer_set_port.put_back(move new_layer_buffer_set_port); let render_layer_cell = Cell(move render_layer); - let layer_buffer_cell = Cell(move layer_buffer); - let layer_buffer_channel_cell = Cell(move layer_buffer_channel); + let layer_buffer_set_cell = Cell(move layer_buffer_set); + let layer_buffer_set_channel_cell = Cell(move layer_buffer_set_channel); #debug("renderer: rendering"); do util::time::time(~"rendering") { let render_layer = render_layer_cell.take(); - let layer_buffer = layer_buffer_cell.take(); - let layer_buffer_channel = layer_buffer_channel_cell.take(); + let layer_buffer_set = layer_buffer_set_cell.take(); + let layer_buffer_set_channel = layer_buffer_set_channel_cell.take(); - let layer_buffer = for render_layers(&render_layer, move layer_buffer) + let layer_buffer_set = for render_layers(&render_layer, move layer_buffer_set) |render_layer, layer_buffer| { let ctx = RenderContext { canvas: layer_buffer, @@ -96,7 +96,7 @@ impl<C: Compositor Send> Renderer<C> { }; #debug("renderer: returning surface"); - self.compositor.draw(move layer_buffer_channel, move layer_buffer); + self.compositor.draw(move layer_buffer_set_channel, move layer_buffer_set); } } } diff --git a/src/servo/platform/osmain.rs b/src/servo/platform/osmain.rs index 167d51d4def..0db894cdf05 100644 --- a/src/servo/platform/osmain.rs +++ b/src/servo/platform/osmain.rs @@ -1,20 +1,21 @@ -use mod azure::azure_hl; +use ShareGlContext = sharegl::platform::Context; +use azure::azure_hl; use azure::azure_hl::DrawTarget; -use cairo::cairo_surface_t; use cairo::cairo_hl::ImageSurface; -use dvec::DVec; -use gfx::compositor::{LayerBuffer, Compositor}; +use cairo::cairo_surface_t; +use core::util::replace; use dom::event::{Event, ResizeEvent}; -use layers::ImageLayer; +use dvec::DVec; use geom::matrix::{Matrix4, identity}; use geom::size::Size2D; -use ShareGlContext = sharegl::platform::Context; +use gfx::compositor::{Compositor, LayerBuffer, LayerBufferSet}; +use layers::ImageLayer; +use pipes::Chan; +use resize_rate_limiter::ResizeRateLimiter; +use std::cell::Cell; use std::cmp::FuzzyEq; use task::TaskBuilder; use vec::push; -use pipes::Chan; -use std::cell::Cell; -use resize_rate_limiter::ResizeRateLimiter; pub type OSMain = comm::Chan<Msg>; @@ -30,8 +31,8 @@ enum Window { } pub enum Msg { - BeginDrawing(pipes::Chan<LayerBuffer>), - Draw(pipes::Chan<LayerBuffer>, LayerBuffer), + BeginDrawing(pipes::Chan<LayerBufferSet>), + Draw(pipes::Chan<LayerBufferSet>, LayerBufferSet), AddKeyHandler(pipes::Chan<()>), Exit } @@ -120,11 +121,12 @@ fn mainloop(mode: Mode, po: comm::Port<Msg>, dom_event_chan: pipes::SharedChan<E return_surface(surfaces, move dt); lend_surface(surfaces, move sender); - let width = surfaces.front.layer_buffer.size.width as uint; - let height = surfaces.front.layer_buffer.size.height as uint; + let buffers = &mut surfaces.front.layer_buffer_set.buffers; + let width = buffers[0].size.width as uint; + let height = buffers[0].size.height as uint; let image_data = @CairoSurfaceImageData { - cairo_surface: surfaces.front.layer_buffer.cairo_surface.clone(), + cairo_surface: buffers[0].cairo_surface.clone(), size: Size2D(width, height) }; let image = @layers::layers::Image::new( @@ -142,7 +144,6 @@ fn mainloop(mode: Mode, po: comm::Port<Msg>, dom_event_chan: pipes::SharedChan<E }; let adjust_for_window_resizing: fn@() = || { - let height = surfaces.front.layer_buffer.size.height as uint; let window_width = glut::get(glut::WindowWidth) as uint; let window_height = glut::get(glut::WindowHeight) as uint; @@ -167,15 +168,14 @@ fn mainloop(mode: Mode, po: comm::Port<Msg>, dom_event_chan: pipes::SharedChan<E match window { GlutWindow(window) => { do glut::reshape_func(window) |width, height| { - check_for_messages(); - #debug("osmain: window resized to %d,%d", width as int, height as int); + check_for_messages(); resize_rate_limiter.window_resized(width as uint, height as uint); - - composite(); + //composite(); } do glut::display_func() { + debug!("osmain: display func"); check_for_messages(); composite(); } @@ -203,10 +203,10 @@ Implementation to allow the osmain channel to be used as a graphics compositor for the renderer */ impl OSMain : Compositor { - fn begin_drawing(next_dt: pipes::Chan<LayerBuffer>) { + fn begin_drawing(next_dt: pipes::Chan<LayerBufferSet>) { self.send(BeginDrawing(move next_dt)) } - fn draw(next_dt: pipes::Chan<LayerBuffer>, draw_me: LayerBuffer) { + fn draw(next_dt: pipes::Chan<LayerBufferSet>, draw_me: LayerBufferSet) { self.send(Draw(move next_dt, move draw_me)) } } @@ -216,19 +216,26 @@ struct SurfaceSet { mut back: Surface, } -fn lend_surface(surfaces: &SurfaceSet, receiver: pipes::Chan<LayerBuffer>) { +fn lend_surface(surfaces: &SurfaceSet, receiver: pipes::Chan<LayerBufferSet>) { // We are in a position to lend out the surface? assert surfaces.front.have; // Ok then take it - let draw_target_ref = &mut surfaces.front.layer_buffer.draw_target; - let layer_buffer = LayerBuffer { - cairo_surface: surfaces.front.layer_buffer.cairo_surface.clone(), - draw_target: azure_hl::clone_mutable_draw_target(draw_target_ref), - size: copy surfaces.front.layer_buffer.size, - stride: surfaces.front.layer_buffer.stride + let old_layer_buffers = replace(&mut surfaces.front.layer_buffer_set.buffers, ~[]); + let new_layer_buffers = do old_layer_buffers.map |layer_buffer| { + let draw_target_ref = &layer_buffer.draw_target; + let layer_buffer = LayerBuffer { + cairo_surface: layer_buffer.cairo_surface.clone(), + draw_target: draw_target_ref.clone(), + size: copy layer_buffer.size, + stride: layer_buffer.stride + }; + #debug("osmain: lending surface %?", layer_buffer); + move layer_buffer }; - #debug("osmain: lending surface %?", layer_buffer); - receiver.send(move layer_buffer); + surfaces.front.layer_buffer_set.buffers = move old_layer_buffers; + + let new_layer_buffer_set = LayerBufferSet { buffers: move new_layer_buffers }; + receiver.send(move new_layer_buffer_set); // Now we don't have it surfaces.front.have = false; // But we (hopefully) have another! @@ -237,13 +244,13 @@ fn lend_surface(surfaces: &SurfaceSet, receiver: pipes::Chan<LayerBuffer>) { assert surfaces.front.have; } -fn return_surface(surfaces: &SurfaceSet, layer_buffer: LayerBuffer) { - #debug("osmain: returning surface %?", layer_buffer); +fn return_surface(surfaces: &SurfaceSet, layer_buffer_set: LayerBufferSet) { + #debug("osmain: returning surface %?", layer_buffer_set); // We have room for a return assert surfaces.front.have; assert !surfaces.back.have; - surfaces.back.layer_buffer = move layer_buffer; + surfaces.back.layer_buffer_set = move layer_buffer_set; // Now we have it again surfaces.back.have = true; @@ -254,7 +261,7 @@ fn SurfaceSet() -> SurfaceSet { } struct Surface { - layer_buffer: LayerBuffer, + layer_buffer_set: LayerBufferSet, mut have: bool, } @@ -267,7 +274,8 @@ fn Surface() -> Surface { size: Size2D(800u, 600u), stride: 800 }; - Surface { layer_buffer: move layer_buffer, have: true } + let layer_buffer_set = LayerBufferSet { buffers: ~[ move layer_buffer ] }; + Surface { layer_buffer_set: move layer_buffer_set, have: true } } /// A function for spawning into the platform's main thread |