From 237a7e688aaedc3c6c4d787fc67a7d4eeadf68da Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Tue, 15 Jul 2014 14:43:26 -0700 Subject: [PATCH 1/4] Remove the Tile trait It's unclear whether LayerBuffers will always represent the contents of one Tile and there's only one implementation of this trait. --- layers.rs | 67 +++++++++++++++++++++++-------------------------------- 1 file changed, 28 insertions(+), 39 deletions(-) diff --git a/layers.rs b/layers.rs index 7b9b98d..518cf52 100644 --- a/layers.rs +++ b/layers.rs @@ -155,58 +155,47 @@ pub struct LayerBuffer { pub stride: uint, } -/// A set of layer buffers. This is an atomic unit used to switch between the front and back -/// buffers. -pub struct LayerBufferSet { - pub buffers: Vec> -} - -impl LayerBufferSet { - /// Notes all buffer surfaces will leak if not destroyed via a call to `destroy`. - pub fn mark_will_leak(&mut self) { - for buffer in self.buffers.mut_iter() { - buffer.native_surface.mark_will_leak() - } - } -} - -/// The interface used by the BufferMap to get info about layer buffers. -pub trait Tile { +impl LayerBuffer { /// Returns the amount of memory used by the tile - fn get_mem(&self) -> uint; - - /// Returns true if the tile is displayable at the given scale - fn is_valid(&self, f32) -> bool; - - /// Returns the Size2D of the tile - fn get_size_2d(&self) -> Size2D; - - /// Marks the layer buffer as not leaking. See comments on - /// `NativeSurfaceMethods::mark_wont_leak` for how this is used. - fn mark_wont_leak(&mut self); - - /// Destroys the layer buffer. Painting task only. - fn destroy(self, graphics_context: &NativePaintingGraphicsContext); -} - -impl Tile for Box { - fn get_mem(&self) -> uint { + pub fn get_mem(&self) -> uint { // This works for now, but in the future we may want a better heuristic self.screen_pos.size.width * self.screen_pos.size.height } - fn is_valid(&self, scale: f32) -> bool { + + /// Returns true if the tile is displayable at the given scale + pub fn is_valid(&self, scale: f32) -> bool { (self.resolution - scale).abs() < 1.0e-6 } - fn get_size_2d(&self) -> Size2D { + + /// Returns the Size2D of the tile + pub fn get_size_2d(&self) -> Size2D { self.screen_pos.size } - fn mark_wont_leak(&mut self) { + + /// Marks the layer buffer as not leaking. See comments on + /// `NativeSurfaceMethods::mark_wont_leak` for how this is used. + pub fn mark_wont_leak(&mut self) { self.native_surface.mark_wont_leak() } - fn destroy(self, graphics_context: &NativePaintingGraphicsContext) { + + /// Destroys the layer buffer. Painting task only. + pub fn destroy(self, graphics_context: &NativePaintingGraphicsContext) { let mut this = self; this.native_surface.destroy(graphics_context) } } +/// A set of layer buffers. This is an atomic unit used to switch between the front and back +/// buffers. +pub struct LayerBufferSet { + pub buffers: Vec> +} +impl LayerBufferSet { + /// Notes all buffer surfaces will leak if not destroyed via a call to `destroy`. + pub fn mark_will_leak(&mut self) { + for buffer in self.buffers.mut_iter() { + buffer.native_surface.mark_will_leak() + } + } +} From ce7f615302af1527aadf537b7019ba5d75375a6a Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Tue, 15 Jul 2014 16:03:47 -0700 Subject: [PATCH 2/4] TileGrid keeps a grid of Tiles instead of Buffers This will allow the TileGrid to better track the state of each Tile. --- layers.rs | 18 +++++------ tiling.rs | 90 ++++++++++++++++++++++++++++++++++++------------------- 2 files changed, 69 insertions(+), 39 deletions(-) diff --git a/layers.rs b/layers.rs index 518cf52..fad95e1 100644 --- a/layers.rs +++ b/layers.rs @@ -55,27 +55,27 @@ impl Layer { pub fn get_tile_rects_page(&self, window: Rect, scale: f32) -> (Vec, Vec>) { let mut tile_grid = self.tile_grid.borrow_mut(); - (tile_grid.get_buffer_requests_in_rect(window, scale), tile_grid.take_unused_tiles()) + (tile_grid.get_buffer_requests_in_rect(window, scale), tile_grid.take_unused_buffers()) } pub fn resize(&self, new_size: Size2D) { self.bounds.borrow_mut().size = new_size; } - pub fn do_for_all_tiles(&self, f: |&Box|) { - self.tile_grid.borrow().do_for_all_tiles(f); + pub fn do_for_all_buffers(&self, f: |&Box|) { + self.tile_grid.borrow().do_for_all_buffers(f); } - pub fn add_tile_pixel(&self, tile: Box) { - self.tile_grid.borrow_mut().add_tile(tile); + pub fn add_buffer(&self, tile: Box) { + self.tile_grid.borrow_mut().add_buffer(tile); } - pub fn collect_unused_tiles(&self) -> Vec> { - self.tile_grid.borrow_mut().take_unused_tiles() + pub fn collect_unused_buffers(&self) -> Vec> { + self.tile_grid.borrow_mut().take_unused_buffers() } - pub fn collect_tiles(&self) -> Vec> { - self.tile_grid.borrow_mut().collect_tiles() + pub fn collect_buffers(&self) -> Vec> { + self.tile_grid.borrow_mut().collect_buffers() } pub fn flush_pending_buffer_requests(&self) -> (Vec, f32) { diff --git a/tiling.rs b/tiling.rs index 760e673..693599c 100644 --- a/tiling.rs +++ b/tiling.rs @@ -16,19 +16,37 @@ use std::collections::hashmap::HashMap; use std::iter::range_inclusive; use std::mem; +pub struct Tile { + buffer: Option>, +} + +impl Tile { + fn new() -> Tile { + Tile { + buffer: None, + } + } + + fn replace_buffer(&mut self, buffer: Box) -> Option> { + let old_buffer = self.buffer.take(); + self.buffer = Some(buffer); + return old_buffer; + } +} + pub struct TileGrid { - pub tiles: HashMap, Box>, + pub tiles: HashMap, Tile>, // The size of tiles in this grid in device pixels. tile_size: uint, - // Tiles that are currently unused or outside the last-known visible rectangle. - unused_tiles: Vec>, + // Buffers that are currently unused. + unused_buffers: Vec>, // Whether or not there are pending buffer requests. - waiting_on_tiles : bool, + waiting_on_buffers : bool, - // Once we know that we are waiting for tiles, track any later buffer requests. + // Once we know that we are waiting for buffers, track any later buffer requests. // FIXME: Replace with a per-tile state which better tracks epoch transitions. pending_buffer_request: Option<(Rect, f32)>, } @@ -43,8 +61,8 @@ impl TileGrid { TileGrid { tiles: HashMap::new(), tile_size: tile_size, - unused_tiles: Vec::new(), - waiting_on_tiles: false, + unused_buffers: Vec::new(), + waiting_on_buffers: false, pending_buffer_request: None, } } @@ -61,10 +79,17 @@ impl TileGrid { Size2D(self.tile_size, self.tile_size)) } - pub fn take_unused_tiles(&mut self) -> Vec> { - let mut unused_tiles = Vec::new(); - mem::swap(&mut unused_tiles, &mut self.unused_tiles); - return unused_tiles; + pub fn take_unused_buffers(&mut self) -> Vec> { + let mut unused_buffers = Vec::new(); + mem::swap(&mut unused_buffers, &mut self.unused_buffers); + return unused_buffers; + } + + pub fn add_unused_buffer(&mut self, buffer: Option>) { + match buffer { + Some(buffer) => self.unused_buffers.push(buffer), + None => {}, + } } pub fn mark_tiles_outside_of_rect_as_unused(&mut self, rect: Rect) { @@ -77,14 +102,14 @@ impl TileGrid { for tile_index in tile_indexes_to_take.iter() { match self.tiles.pop(tile_index) { - Some(tile) => self.unused_tiles.push(tile), + Some(ref mut tile) => self.add_unused_buffer(tile.buffer.take()), None => {}, } } } pub fn get_buffer_requests_in_rect(&mut self, screen_rect: Rect, scale: f32) -> Vec { - if self.waiting_on_tiles { + if self.waiting_on_buffers { self.pending_buffer_request = Some((screen_rect, scale)); return Vec::new(); } @@ -103,7 +128,7 @@ impl TileGrid { } self.mark_tiles_outside_of_rect_as_unused(rect_in_layer_pixels); - self.waiting_on_tiles = !buffer_requests.is_empty(); + self.waiting_on_buffers = !buffer_requests.is_empty(); return buffer_requests; } @@ -114,35 +139,40 @@ impl TileGrid { (point.y / self.tile_size) as uint) } - pub fn add_tile(&mut self, tile: Box) { - self.waiting_on_tiles = false; - let index = self.get_tile_index_for_point(tile.screen_pos.origin.clone()); - match self.tiles.swap(index, tile) { - Some(tile) => self.unused_tiles.push(tile), - None => {}, - } + pub fn add_buffer(&mut self, buffer: Box) { + self.waiting_on_buffers = false; + let index = self.get_tile_index_for_point(buffer.screen_pos.origin.clone()); + let replaced_buffer = + self.tiles.find_or_insert_with(index, |_| Tile::new()).replace_buffer(buffer); + self.add_unused_buffer(replaced_buffer); } - pub fn do_for_all_tiles(&self, f: |&Box|) { + pub fn do_for_all_buffers(&self, f: |&Box|) { for tile in self.tiles.values() { - f(tile); + match tile.buffer { + Some(ref buffer) => f(buffer), + None => {}, + } } } - pub fn collect_tiles(&mut self) -> Vec> { - let mut collected_tiles = Vec::new(); + pub fn collect_buffers(&mut self) -> Vec> { + let mut collected_buffers = Vec::new(); - collected_tiles.push_all_move(self.take_unused_tiles()); + collected_buffers.push_all_move(self.take_unused_buffers()); // We need to replace the HashMap since it cannot be used again after move_iter(). let mut tile_map = HashMap::new(); mem::swap(&mut tile_map, &mut self.tiles); - for (_, tile) in tile_map.move_iter() { - collected_tiles.push(tile); + for (_, mut tile) in tile_map.move_iter() { + match tile.buffer.take() { + Some(buffer) => collected_buffers.push(buffer), + None => {}, + } } - return collected_tiles; + return collected_buffers; } pub fn flush_pending_buffer_requests(&mut self) -> (Vec, f32) { @@ -154,6 +184,6 @@ impl TileGrid { pub fn contents_changed(&mut self) { self.pending_buffer_request = None; - self.waiting_on_tiles = false; + self.waiting_on_buffers = false; } } From 09e62f1993652dc1bcb3c7320d51ce7ccabbdc6c Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Wed, 16 Jul 2014 11:26:34 -0700 Subject: [PATCH 3/4] Move texture creation to Layer This allows Layers to create their own textures instead of relying on Servo to do the job. Textures now track whether or not they should be flipped by passing the buffer to the factory method. --- layers.rs | 50 ++++++++++++++++++++++++++++++++++------------- rendergl.rs | 10 +++++----- texturegl.rs | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 96 insertions(+), 19 deletions(-) diff --git a/layers.rs b/layers.rs index fad95e1..f6953e8 100644 --- a/layers.rs +++ b/layers.rs @@ -13,7 +13,8 @@ use tiling::TileGrid; use geom::matrix::{Matrix4, identity}; use geom::size::Size2D; use geom::rect::Rect; -use platform::surface::{NativePaintingGraphicsContext, NativeSurfaceMethods, NativeSurface}; +use platform::surface::{NativeSurfaceMethods, NativeSurface}; +use platform::surface::{NativeCompositingGraphicsContext, NativePaintingGraphicsContext}; use std::cell::{RefCell, RefMut}; use std::rc::Rc; @@ -85,34 +86,54 @@ impl Layer { pub fn contents_changed(&self) { self.tile_grid.borrow_mut().contents_changed() } -} -/// Whether a texture should be flipped. -#[deriving(PartialEq)] -pub enum Flip { - /// The texture should not be flipped. - NoFlip, - /// The texture should be flipped vertically. - VerticalFlip, + pub fn create_textures(&self, graphics_context: &NativeCompositingGraphicsContext) { + // Clear all old textures. + self.tiles.borrow_mut().clear(); + + self.do_for_all_buffers(|buffer: &Box| { + debug!("osmain: compositing buffer rect {}", buffer.rect); + + let size = Size2D(buffer.screen_pos.size.width as int, + buffer.screen_pos.size.height as int); + + debug!("osmain: adding new texture layer"); + + // Make a new texture and bind the layer buffer's surface to it. + let texture = Texture::new_with_buffer(buffer); + debug!("COMPOSITOR binding to native surface {:d}", + buffer.native_surface.get_id() as int); + buffer.native_surface.bind_to_texture(graphics_context, &texture, size); + + // Set the layer's transform. + let rect = buffer.rect; + let transform = identity().translate(rect.origin.x, rect.origin.y, 0.0); + let transform = transform.scale(rect.size.width, rect.size.height, 1.0); + + // Make a texture layer and add it. + let texture_layer = Rc::new(TextureLayer::new(texture, + buffer.screen_pos.size, + transform)); + self.tiles.borrow_mut().push(texture_layer); + }); + } } pub struct TextureLayer { /// A handle to the GPU texture. pub texture: Texture, + /// The size of the texture in pixels. size: Size2D, - /// Whether this texture is flipped vertically. - pub flip: Flip, pub transform: Matrix4, } impl TextureLayer { - pub fn new(texture: Texture, size: Size2D, flip: Flip, transform: Matrix4) -> TextureLayer { + pub fn new(texture: Texture, size: Size2D, transform: Matrix4) -> TextureLayer { TextureLayer { texture: texture, size: size, - flip: flip, transform: transform, } } @@ -153,6 +174,9 @@ pub struct LayerBuffer { /// NB: stride is in pixels, like OpenGL GL_UNPACK_ROW_LENGTH. pub stride: uint, + + /// Whether or not this buffer was painted with the CPU rasterization. + pub painted_with_cpu: bool, } impl LayerBuffer { diff --git a/rendergl.rs b/rendergl.rs index 29932f0..ba0ba43 100755 --- a/rendergl.rs +++ b/rendergl.rs @@ -7,9 +7,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use layers::{Layer, TextureLayer, Flip, NoFlip, VerticalFlip}; +use layers::{Layer, TextureLayer}; use layers; use scene::Scene; +use texturegl::{Flip, NoFlip, VerticalFlip}; use texturegl::{Texture, TextureTarget2D, TextureTargetRectangle}; use geom::matrix::{Matrix4, ortho}; @@ -272,7 +273,6 @@ fn bind_texture_coordinate_buffer(render_context: RenderContext, flip: Flip) { pub fn bind_and_render_quad(render_context: RenderContext, texture: &Texture, - flip: Flip, transform: &Matrix4, scene_size: Size2D) { let program_id = match texture.target { @@ -311,7 +311,7 @@ pub fn bind_and_render_quad(render_context: RenderContext, 0, 0); - bind_texture_coordinate_buffer(render_context, flip); + bind_texture_coordinate_buffer(render_context, texture.flip); vertex_attrib_pointer_f32(render_context.program_2d.unwrap().texture_coord_attr as GLuint, 2, false, @@ -338,7 +338,7 @@ pub fn bind_and_render_quad(render_context: RenderContext, 0, 0); - bind_texture_coordinate_buffer(render_context, flip); + bind_texture_coordinate_buffer(render_context, texture.flip); vertex_attrib_pointer_f32(render_context.program_rectangle.unwrap().texture_coord_attr as GLuint, 2, @@ -384,7 +384,7 @@ impl Render for layers::TextureLayer { transform: Matrix4, scene_size: Size2D) { let transform = transform.mul(&self.transform); - bind_and_render_quad(render_context, &self.texture, self.flip, &transform, scene_size); + bind_and_render_quad(render_context, &self.texture, &transform, scene_size); } } diff --git a/texturegl.rs b/texturegl.rs index 53c779b..faf5a6a 100644 --- a/texturegl.rs +++ b/texturegl.rs @@ -9,7 +9,7 @@ //! OpenGL-specific implementation of texturing. -use layers::{ARGB32Format, Format, RGB24Format}; +use layers::{ARGB32Format, Format, RGB24Format, LayerBuffer}; use geom::size::Size2D; use opengles::gl2::{BGRA, CLAMP_TO_EDGE, GLenum, GLint, GLsizei, GLuint, LINEAR, RGB, RGBA}; @@ -49,11 +49,16 @@ impl TextureTarget { pub struct Texture { /// The OpenGL texture ID. id: GLuint, + /// The texture target. pub target: TextureTarget, + /// Whether this texture is weak. Weak textures will not be cleaned up by /// the destructor. weak: bool, + + // Whether or not this texture needs to be flipped upon display. + pub flip: Flip, } impl Drop for Texture { @@ -78,6 +83,7 @@ impl Zero for Texture { id: 0, target: TextureTarget2D, weak: true, + flip: NoFlip, } } fn is_zero(&self) -> bool { @@ -104,11 +110,48 @@ impl Texture { id: *gl2::gen_textures(1).get(0), target: target, weak: false, + flip: NoFlip, }; this.set_default_params(); this } + pub fn new_with_buffer(buffer: &Box) -> Texture { + let (flip, target) = + Texture::texture_flip_and_target(buffer.painted_with_cpu, buffer.screen_pos.size); + let mut texture = Texture::new(target); + texture.flip = flip; + return texture; + } + + // Returns whether the layer should be vertically flipped. + #[cfg(target_os="macos")] + fn texture_flip_and_target(cpu_painting: bool, size: Size2D) -> (Flip, TextureTarget) { + let flip = if cpu_painting { + NoFlip + } else { + VerticalFlip + }; + + (flip, TextureTargetRectangle(size)) + } + + #[cfg(target_os="android")] + fn texture_flip_and_target(cpu_painting: bool, _: Size2D) -> (Flip, TextureTarget) { + let flip = if cpu_painting { + NoFlip + } else { + VerticalFlip + }; + + (flip, TextureTarget2D) + } + + #[cfg(target_os="linux")] + fn texture_flip_and_target(_: bool, _: Size2D) -> (Flip, TextureTarget) { + (NoFlip, TextureTarget2D) + } + /// Creates a texture from an existing OpenGL texture. The texture will be deleted when this /// `Texture` object goes out of scope. pub fn adopt_native_texture(native_texture_id: GLuint, target: TextureTarget) -> Texture { @@ -116,6 +159,7 @@ impl Texture { id: native_texture_id, target: target, weak: false, + flip: NoFlip, }; this } @@ -127,6 +171,7 @@ impl Texture { id: native_texture_id, target: target, weak: true, + flip: NoFlip, }; this.set_default_params(); this @@ -186,3 +231,11 @@ impl Texture { } } +/// Whether a texture should be flipped. +#[deriving(PartialEq)] +pub enum Flip { + /// The texture should not be flipped. + NoFlip, + /// The texture should be flipped vertically. + VerticalFlip, +} From ca8fc1ceef245d5174be7a8c1fd7609de76a3e83 Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Wed, 16 Jul 2014 12:47:31 -0700 Subject: [PATCH 4/4] Move Texture creation to the TileGrid This way each Tile can be responsible for creating its own Textures. --- layers.rs | 63 ++++------------------------------------------------ rendergl.rs | 11 +++++---- texturegl.rs | 7 +++++- tiling.rs | 52 +++++++++++++++++++++++++++++++++++++------ 4 files changed, 62 insertions(+), 71 deletions(-) diff --git a/layers.rs b/layers.rs index f6953e8..8a51180 100644 --- a/layers.rs +++ b/layers.rs @@ -7,8 +7,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use texturegl::Texture; -use tiling::TileGrid; +use tiling::{Tile, TileGrid}; use geom::matrix::{Matrix4, identity}; use geom::size::Size2D; @@ -18,14 +17,8 @@ use platform::surface::{NativeCompositingGraphicsContext, NativePaintingGraphics use std::cell::{RefCell, RefMut}; use std::rc::Rc; -pub enum Format { - ARGB32Format, - RGB24Format -} - pub struct Layer { pub children: RefCell>>>, - pub tiles: RefCell>>, pub transform: RefCell>, pub bounds: RefCell>, pub tile_size: uint, @@ -37,7 +30,6 @@ impl Layer { pub fn new(bounds: Rect, tile_size: uint, data: T) -> Layer { Layer { children: RefCell::new(vec!()), - tiles: RefCell::new(vec!()), transform: RefCell::new(identity()), bounds: RefCell::new(bounds), tile_size: tile_size, @@ -63,10 +55,6 @@ impl Layer { self.bounds.borrow_mut().size = new_size; } - pub fn do_for_all_buffers(&self, f: |&Box|) { - self.tile_grid.borrow().do_for_all_buffers(f); - } - pub fn add_buffer(&self, tile: Box) { self.tile_grid.borrow_mut().add_buffer(tile); } @@ -88,54 +76,11 @@ impl Layer { } pub fn create_textures(&self, graphics_context: &NativeCompositingGraphicsContext) { - // Clear all old textures. - self.tiles.borrow_mut().clear(); - - self.do_for_all_buffers(|buffer: &Box| { - debug!("osmain: compositing buffer rect {}", buffer.rect); - - let size = Size2D(buffer.screen_pos.size.width as int, - buffer.screen_pos.size.height as int); - - debug!("osmain: adding new texture layer"); - - // Make a new texture and bind the layer buffer's surface to it. - let texture = Texture::new_with_buffer(buffer); - debug!("COMPOSITOR binding to native surface {:d}", - buffer.native_surface.get_id() as int); - buffer.native_surface.bind_to_texture(graphics_context, &texture, size); - - // Set the layer's transform. - let rect = buffer.rect; - let transform = identity().translate(rect.origin.x, rect.origin.y, 0.0); - let transform = transform.scale(rect.size.width, rect.size.height, 1.0); - - // Make a texture layer and add it. - let texture_layer = Rc::new(TextureLayer::new(texture, - buffer.screen_pos.size, - transform)); - self.tiles.borrow_mut().push(texture_layer); - }); + self.tile_grid.borrow_mut().create_textures(graphics_context); } -} - -pub struct TextureLayer { - /// A handle to the GPU texture. - pub texture: Texture, - /// The size of the texture in pixels. - size: Size2D, - - pub transform: Matrix4, -} - -impl TextureLayer { - pub fn new(texture: Texture, size: Size2D, transform: Matrix4) -> TextureLayer { - TextureLayer { - texture: texture, - size: size, - transform: transform, - } + pub fn do_for_all_tiles(&self, f: |&Tile|) { + self.tile_grid.borrow().do_for_all_tiles(f); } } diff --git a/rendergl.rs b/rendergl.rs index ba0ba43..dcf9c5a 100755 --- a/rendergl.rs +++ b/rendergl.rs @@ -7,11 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use layers::{Layer, TextureLayer}; +use layers::Layer; use layers; use scene::Scene; use texturegl::{Flip, NoFlip, VerticalFlip}; use texturegl::{Texture, TextureTarget2D, TextureTargetRectangle}; +use tiling::Tile; use geom::matrix::{Matrix4, ortho}; use geom::size::Size2D; @@ -369,16 +370,18 @@ impl Render for layers::Layer { scene_size: Size2D) { let origin = self.bounds.borrow().origin; let transform = transform.translate(origin.x, origin.y, 0.0).mul(&*self.transform.borrow()); - for tile in self.tiles.borrow().iter() { + + self.do_for_all_tiles(|tile: &Tile| { tile.render(render_context, transform, scene_size) - } + }); + for child in self.children().iter() { child.render(render_context, transform, scene_size) } } } -impl Render for layers::TextureLayer { +impl Render for Tile { fn render(&self, render_context: RenderContext, transform: Matrix4, diff --git a/texturegl.rs b/texturegl.rs index faf5a6a..e7fd6d9 100644 --- a/texturegl.rs +++ b/texturegl.rs @@ -9,7 +9,7 @@ //! OpenGL-specific implementation of texturing. -use layers::{ARGB32Format, Format, RGB24Format, LayerBuffer}; +use layers::LayerBuffer; use geom::size::Size2D; use opengles::gl2::{BGRA, CLAMP_TO_EDGE, GLenum, GLint, GLsizei, GLuint, LINEAR, RGB, RGBA}; @@ -18,6 +18,11 @@ use opengles::gl2::{TEXTURE_WRAP_S, TEXTURE_WRAP_T, UNSIGNED_BYTE, UNSIGNED_INT_ use opengles::gl2; use std::num::Zero; +pub enum Format { + ARGB32Format, + RGB24Format +} + /// Image data used when uploading to a texture. pub struct TextureImageData<'a> { size: Size2D, diff --git a/tiling.rs b/tiling.rs index 693599c..6abe168 100644 --- a/tiling.rs +++ b/tiling.rs @@ -7,23 +7,37 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use layers::BufferRequest; +use layers::LayerBuffer; +use platform::surface::{NativeCompositingGraphicsContext, NativeSurfaceMethods}; +use texturegl::Texture; + +use geom::matrix::{Matrix4, identity}; use geom::point::Point2D; use geom::size::Size2D; use geom::rect::Rect; -use layers::BufferRequest; -use layers::LayerBuffer; use std::collections::hashmap::HashMap; use std::iter::range_inclusive; use std::mem; +use std::num::Zero; pub struct Tile { + /// The buffer displayed by this tile. buffer: Option>, + + /// A handle to the GPU texture. + pub texture: Texture, + + /// The transformation applied to this tiles texture. + pub transform: Matrix4, } impl Tile { fn new() -> Tile { Tile { buffer: None, + texture: Zero::zero(), + transform: identity(), } } @@ -32,6 +46,27 @@ impl Tile { self.buffer = Some(buffer); return old_buffer; } + + fn create_texture(&mut self, graphics_context: &NativeCompositingGraphicsContext) { + match self.buffer { + Some(ref buffer) => { + let size = Size2D(buffer.screen_pos.size.width as int, + buffer.screen_pos.size.height as int); + + // Make a new texture and bind the LayerBuffer's surface to it. + self.texture = Texture::new_with_buffer(buffer); + debug!("Tile: binding to native surface {:d}", + buffer.native_surface.get_id() as int); + buffer.native_surface.bind_to_texture(graphics_context, &self.texture, size); + + // Set the layer's transform. + let rect = buffer.rect; + let transform = identity().translate(rect.origin.x, rect.origin.y, 0.0); + self.transform = transform.scale(rect.size.width, rect.size.height, 1.0); + }, + None => {}, + } + } } pub struct TileGrid { @@ -147,12 +182,9 @@ impl TileGrid { self.add_unused_buffer(replaced_buffer); } - pub fn do_for_all_buffers(&self, f: |&Box|) { + pub fn do_for_all_tiles(&self, f: |&Tile|) { for tile in self.tiles.values() { - match tile.buffer { - Some(ref buffer) => f(buffer), - None => {}, - } + f(tile); } } @@ -186,4 +218,10 @@ impl TileGrid { self.pending_buffer_request = None; self.waiting_on_buffers = false; } + + pub fn create_textures(&mut self, graphics_context: &NativeCompositingGraphicsContext) { + for (_, ref mut tile) in self.tiles.mut_iter() { + tile.create_texture(graphics_context); + } + } }