diff --git a/src/layers.rs b/src/layers.rs index 4a55219..e3896ed 100644 --- a/src/layers.rs +++ b/src/layers.rs @@ -51,6 +51,10 @@ pub struct Layer { /// The content offset for this layer in unscaled layer pixels. pub content_offset: RefCell>, + + /// Whether this layer clips its children to its boundaries. + pub masks_to_bounds: RefCell, + } impl Layer { @@ -64,6 +68,7 @@ impl Layer { tile_grid: RefCell::new(TileGrid::new(tile_size)), content_age: RefCell::new(ContentAge::new()), content_offset: RefCell::new(Point2D(0f32, 0f32)), + masks_to_bounds: RefCell::new(false), } } diff --git a/src/rendergl.rs b/src/rendergl.rs index 29e875e..be592e6 100755 --- a/src/rendergl.rs +++ b/src/rendergl.rs @@ -17,6 +17,8 @@ use tiling::Tile; use platform::surface::NativeCompositingGraphicsContext; use geom::matrix::{Matrix4, identity, ortho}; +use geom::point::Point2D; +use geom::rect::Rect; use geom::size::Size2D; use libc::c_int; use opengles::gl2::{ARRAY_BUFFER, BLEND, COLOR_BUFFER_BIT, COMPILE_STATUS, FRAGMENT_SHADER}; @@ -169,12 +171,20 @@ impl TextureProgram { transform: &Matrix4, projection_matrix: &Matrix4, texture_space_transform: &Matrix4, - buffers: &Buffers) { + buffers: &Buffers, + unit_rect: Rect) { uniform_1i(self.sampler_uniform, 0); uniform_matrix_4fv(self.modelview_uniform, false, transform.to_array()); uniform_matrix_4fv(self.projection_uniform, false, projection_matrix.to_array()); + let new_coords: [f32, ..8] = [ + unit_rect.origin.x, unit_rect.origin.y, + unit_rect.origin.x, unit_rect.size.height, + unit_rect.size.width, unit_rect.origin.y, + unit_rect.size.width, unit_rect.size.height, + ]; bind_buffer(ARRAY_BUFFER, buffers.textured_quad_vertex_buffer); + buffer_data(ARRAY_BUFFER, new_coords, STATIC_DRAW); vertex_attrib_pointer_f32(self.vertex_position_attr as GLuint, 2, false, 0, 0); uniform_matrix_4fv(self.texture_space_transform_uniform, @@ -313,7 +323,8 @@ impl RenderContext { pub fn bind_and_render_quad(render_context: RenderContext, texture: &Texture, transform: &Matrix4, - scene_size: Size2D) { + scene_size: Size2D, + unit_rect: Rect) { let mut texture_coordinates_need_to_be_scaled_by_size = false; let program = match texture.target { TextureTarget2D => render_context.texture_2d_program, @@ -365,8 +376,8 @@ pub fn bind_and_render_quad(render_context: RenderContext, program.bind_uniforms_and_attributes(transform, &projection_matrix, &texture_transform, - &render_context.buffers); - + &render_context.buffers, + unit_rect); // Draw! draw_arrays(TRIANGLE_STRIP, 0, 4); @@ -393,27 +404,64 @@ pub fn bind_and_render_quad_lines(render_context: RenderContext, solid_line_program.disable_attribute_arrays(); } -// Layer rendering +fn map_clip_to_unit_rectangle(rect: Rect, + clip_rect: Option>) + -> Rect { + match clip_rect { + Some(clip_rect) => { + match clip_rect.intersection(&rect) { + Some(intersected_rect) => { + let point = intersected_rect.origin - rect.origin; + Rect(Point2D(point.x / rect.size.width, point.y / rect.size.height), + Size2D(intersected_rect.size.width / rect.size.width, + intersected_rect.size.height / rect.size.height)) + + } + None => Rect(Point2D(0., 0.), Size2D(1., 1.)), + } + }, + None => Rect(Point2D(0., 0.), Size2D(1., 1.)) + } +} +// Layer rendering pub trait Render { fn render(&self, render_context: RenderContext, transform: Matrix4, - scene_size: Size2D); + scene_size: Size2D, + mut clip_rect: Option>); } impl Render for layers::Layer { fn render(&self, render_context: RenderContext, transform: Matrix4, - scene_size: Size2D) { + scene_size: Size2D, + mut clip_rect: Option>) { let bounds = self.bounds.borrow().to_untyped(); let cumulative_transform = transform.translate(bounds.origin.x, bounds.origin.y, 0.0); let tile_transform = cumulative_transform.mul(&*self.transform.borrow()); + if *self.masks_to_bounds.borrow() { + clip_rect = match clip_rect { + Some(clip_rect) => clip_rect.intersection(&bounds), + None => Some(bounds), + }; + + if clip_rect.is_none() { + return; + } + } + + match clip_rect { + Some(ref mut clip_rect) => clip_rect.origin = clip_rect.origin - bounds.origin, + None => {}, + } + self.create_textures(&render_context.compositing_context); self.do_for_all_tiles(|tile: &Tile| { - tile.render(render_context, tile_transform, scene_size) + tile.render(render_context, tile_transform, scene_size, clip_rect) }); if render_context.show_debug_borders { @@ -426,7 +474,7 @@ impl Render for layers::Layer { } for child in self.children().iter() { - child.render(render_context, cumulative_transform, scene_size) + child.render(render_context, cumulative_transform, scene_size, clip_rect) } } @@ -436,13 +484,18 @@ impl Render for Tile { fn render(&self, render_context: RenderContext, transform: Matrix4, - scene_size: Size2D) { + scene_size: Size2D, + mut clip_rect: Option>) { if self.texture.is_zero() { return; } let transform = transform.mul(&self.transform); - bind_and_render_quad(render_context, &self.texture, &transform, scene_size); + bind_and_render_quad(render_context, + &self.texture, + &transform, + scene_size, + map_clip_to_unit_rectangle(self.bounds, clip_rect)); if render_context.show_debug_borders { bind_and_render_quad_lines(render_context, @@ -471,5 +524,5 @@ pub fn render_scene(root_layer: Rc>, let transform = identity().scale(scene.scale, scene.scale, 1.0); // Render the root layer. - root_layer.render(render_context, transform, scene.size); + root_layer.render(render_context, transform, scene.size, None); } diff --git a/src/scene.rs b/src/scene.rs index 5e6647d..5b05a7b 100755 --- a/src/scene.rs +++ b/src/scene.rs @@ -11,10 +11,11 @@ use color::Color; use geom::matrix::Matrix4; use geom::point::Point2D; use geom::rect::{Rect, TypedRect}; -use geom::size::Size2D; +use geom::size::{Size2D, TypedSize2D}; use geometry::DevicePixel; use layers::{BufferRequest, Layer, LayerBuffer}; use std::mem; +use std::num::Zero; use std::rc::Rc; pub struct Scene { @@ -113,5 +114,12 @@ impl Scene { }; self.mark_layer_contents_as_changed_recursively_for_layer(root_layer); } + + pub fn set_root_layer_size(&self, new_size: TypedSize2D) { + match self.root { + Some(ref root_layer) => *root_layer.bounds.borrow_mut() = Rect(Zero::zero(), new_size), + None => {}, + } + } } diff --git a/src/tiling.rs b/src/tiling.rs index f43aa77..c297f0a 100644 --- a/src/tiling.rs +++ b/src/tiling.rs @@ -35,15 +35,19 @@ pub struct Tile { /// The transformation applied to this tiles texture. pub transform: Matrix4, + + /// The tile boundaries in the parent layer. + pub bounds: Rect, } impl Tile { - fn new() -> Tile { + fn new(bounds: Rect) -> Tile { Tile { buffer: None, texture: Zero::zero(), transform: identity(), content_age_of_pending_buffer: None, + bounds: bounds, } } @@ -189,7 +193,8 @@ impl TileGrid { current_content_age: ContentAge) -> Option { let tile_rect = self.get_rect_for_tile_index(tile_index); - let tile = self.tiles.find_or_insert_with(tile_index, |_| Tile::new()); + let untyped_tile_rect = tile_rect.as_f32().to_untyped(); + let tile = self.tiles.find_or_insert_with(tile_index, |_| Tile::new(untyped_tile_rect)); if !tile.should_request_buffer(current_content_age) { return None; } @@ -197,7 +202,7 @@ impl TileGrid { tile.content_age_of_pending_buffer = Some(current_content_age); return Some(BufferRequest::new(tile_rect.to_untyped(), - tile_rect.as_f32().to_untyped(), + untyped_tile_rect, current_content_age)); }