From 9a38e6bfc48d75a91fa871c6b8c7e2436a8a6d60 Mon Sep 17 00:00:00 2001 From: Glenn Watson Date: Fri, 15 Jan 2016 10:54:30 +1000 Subject: [PATCH] Support clipping scroll areas with non-rectangular transforms. (This unfortunately loses the batch -> arc optimization temporarily). Fixes #136. --- src/batch.rs | 5 ++--- src/frame.rs | 46 ++++++++++++++++++++++--------------------- src/internal_types.rs | 16 ++++++++------- src/renderer.rs | 46 +++++++++++-------------------------------- 4 files changed, 47 insertions(+), 66 deletions(-) diff --git a/src/batch.rs b/src/batch.rs index f2c263fe62..4f15e88c01 100644 --- a/src/batch.rs +++ b/src/batch.rs @@ -3,7 +3,6 @@ use euclid::{Point2D, Rect, Size2D}; use internal_types::{MAX_RECT, AxisDirection, PackedVertex, PackedVertexForTextureCacheUpdate, Primitive}; use std::sync::atomic::Ordering::SeqCst; use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT}; -use std::sync::Arc; use std::u16; use webrender_traits::{ComplexClipRegion}; @@ -237,8 +236,8 @@ impl<'a> BatchBuilder<'a> { } } - pub fn finalize(self) -> Vec> { - self.batches.into_iter().map(|batch| Arc::new(batch)).collect() + pub fn finalize(self) -> Vec { + self.batches } pub fn next_draw_list(&mut self) { diff --git a/src/frame.rs b/src/frame.rs index 2bdf90da72..1177569064 100644 --- a/src/frame.rs +++ b/src/frame.rs @@ -104,21 +104,17 @@ pub struct RenderTarget { child_texture_id: Option, size: Size2D, - - apply_mask: bool, } impl RenderTarget { fn new(id: RenderTargetId, - size: Size2D, - apply_mask: bool) -> RenderTarget { + size: Size2D) -> RenderTarget { RenderTarget { id: id, children: Vec::new(), items: Vec::new(), child_texture_id: None, size: size, - apply_mask: apply_mask, } } @@ -161,18 +157,7 @@ impl RenderTarget { offset_palette[index].stacking_context_y0 = context.offset_from_layer.y; } - let mut clip_rect = None; - - if self.apply_mask { - clip_rect = Some(Rect::new(Point2D::new(layer.world_origin.x as u32, - layer.world_origin.y as u32), - Size2D::new(layer.viewport_size.width as u32, - layer.viewport_size.height as u32))); - } - - let mut batch_info = BatchInfo::new(matrix_palette, - offset_palette, - clip_rect); + let mut batch_info = BatchInfo::new(matrix_palette, offset_palette); // Collect relevant draws from each node in the tree. for node in &layer.aabb_tree.nodes { @@ -187,10 +172,29 @@ impl RenderTarget { if let Some(batch_list) = batch_list { let vertex_buffer_id = compiled_node.vertex_buffer_id.unwrap(); + let scroll_clip_rect = Rect::new(-layer.scroll_offset, + layer.viewport_size); + for batch in &batch_list.batches { + let mut clip_rects = batch.clip_rects.clone(); + + // Intersect all local clips for this layer with the viewport + // size. This clips out content outside iframes, scroll layers etc. + for clip_rect in &mut clip_rects { + *clip_rect = match clip_rect.intersection(&scroll_clip_rect) { + Some(clip_rect) => clip_rect, + None => Rect::new(Point2D::zero(), Size2D::zero()), + }; + } + batch_info.draw_calls.push(DrawCall { - batch: (*batch).clone(), + tile_params: batch.tile_params.clone(), // TODO(gw): Move this instead? + clip_rects: clip_rects, vertex_buffer_id: vertex_buffer_id, + color_texture_id: batch.color_texture_id, + mask_texture_id: batch.mask_texture_id, + first_vertex: batch.first_vertex, + index_count: batch.index_count, }); } } @@ -611,8 +615,7 @@ impl Frame { let root_target_id = self.next_render_target_id(); let mut root_target = RenderTarget::new(root_target_id, - viewport_size, - true); + viewport_size); // Insert global position: fixed elements layer debug_assert!(self.layers.is_empty()); @@ -896,8 +899,7 @@ impl Frame { target_rect.size.height as u32); let render_target_id = self.next_render_target_id(); let mut new_target = RenderTarget::new(render_target_id, - render_target_size, - false); + render_target_size); // TODO(gw): Handle transforms + composition ops... for composition_operation in composition_operations { diff --git a/src/internal_types.rs b/src/internal_types.rs index 793bcd5c24..b9a6bc6128 100644 --- a/src/internal_types.rs +++ b/src/internal_types.rs @@ -1,5 +1,5 @@ use app_units::Au; -use batch::{VertexBuffer, Batch, VertexBufferId, OffsetParams}; +use batch::{VertexBuffer, Batch, VertexBufferId, OffsetParams, TileParams}; use device::{TextureId, TextureFilter}; use euclid::{Matrix4, Point2D, Rect, Size2D}; use fnv::FnvHasher; @@ -324,26 +324,28 @@ pub struct ClearInfo { #[derive(Clone, Debug)] pub struct DrawCall { - pub batch: Arc, + pub tile_params: Vec, + pub clip_rects: Vec>, pub vertex_buffer_id: VertexBufferId, + pub color_texture_id: TextureId, + pub mask_texture_id: TextureId, + pub first_vertex: u32, + pub index_count: u16, } #[derive(Clone, Debug)] pub struct BatchInfo { pub matrix_palette: Vec, pub offset_palette: Vec, - pub clip_rect: Option>, pub draw_calls: Vec, } impl BatchInfo { pub fn new(matrix_palette: Vec, - offset_palette: Vec, - clip_rect: Option>) -> BatchInfo { + offset_palette: Vec) -> BatchInfo { BatchInfo { matrix_palette: matrix_palette, offset_palette: offset_palette, - clip_rect: clip_rect, draw_calls: Vec::new(), } } @@ -488,7 +490,7 @@ pub enum Primitive { #[derive(Debug)] pub struct BatchList { - pub batches: Vec>, + pub batches: Vec, pub draw_list_group_id: DrawListGroupId, } diff --git a/src/renderer.rs b/src/renderer.rs index 527cac47d1..efb83cc9af 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -967,36 +967,14 @@ impl Renderer { self.device.set_uniform_mat4_array(self.u_quad_transform_array, &info.matrix_palette); - if let Some(clip_rect) = info.clip_rect { - let layer_rect = Rect::new(Point2D::zero(), - Size2D::new(layer.layer_size.width as i32, - layer.layer_size.height as i32)); - - let clip_y0 = layer.layer_size.height as i32 - - clip_rect.size.height as i32 - - clip_rect.origin.y as i32; - - let clip_rect = Rect::new(Point2D::new(clip_rect.origin.x as i32, - clip_y0), - Size2D::new(clip_rect.size.width as i32, - clip_rect.size.height as i32)); - - // TODO(gw): Can this unwrap ever fail!? - let scissor_rect = layer_rect.intersection(&clip_rect).unwrap(); - gl::scissor(self.device_pixel_ratio as gl::GLint * scissor_rect.origin.x as gl::GLint, - self.device_pixel_ratio as gl::GLint * scissor_rect.origin.y as gl::GLint, - self.device_pixel_ratio as gl::GLint * scissor_rect.size.width as gl::GLint, - self.device_pixel_ratio as gl::GLint * scissor_rect.size.height as gl::GLint); - } - for draw_call in &info.draw_calls { let vao_id = self.vertex_buffers[&draw_call.vertex_buffer_id].vao_id; self.device.bind_vao(vao_id); - if draw_call.batch.tile_params.len() > 0 { + if draw_call.tile_params.len() > 0 { // TODO(gw): Avoid alloc here... let mut floats = Vec::new(); - for vec in &draw_call.batch.tile_params { + for vec in &draw_call.tile_params { floats.push(vec.u0); floats.push(vec.v0); floats.push(vec.u_size); @@ -1007,10 +985,10 @@ impl Renderer { &floats); } - if draw_call.batch.clip_rects.len() > 0 { + if draw_call.clip_rects.len() > 0 { // TODO(gw): Avoid alloc here... let mut floats = Vec::new(); - for rect in &draw_call.batch.clip_rects { + for rect in &draw_call.clip_rects { floats.push(rect.origin.x); floats.push(rect.origin.y); floats.push(rect.origin.x + rect.size.width); @@ -1021,27 +999,27 @@ impl Renderer { &floats); } - self.device.bind_mask_texture(draw_call.batch.mask_texture_id); - self.device.bind_color_texture(draw_call.batch.color_texture_id); + self.device.bind_mask_texture(draw_call.mask_texture_id); + self.device.bind_color_texture(draw_call.color_texture_id); // TODO(gw): Although a minor cost, this is an extra hashtable lookup for every // draw call, when the batch textures are (almost) always the same. // This could probably be cached or provided elsewhere. - let color_size = - self.device.get_texture_dimensions(draw_call.batch.color_texture_id); - let mask_size = - self.device.get_texture_dimensions(draw_call.batch.mask_texture_id); + let color_size = self.device + .get_texture_dimensions(draw_call.color_texture_id); + let mask_size = self.device + .get_texture_dimensions(draw_call.mask_texture_id); self.device.set_uniform_4f(self.u_atlas_params, color_size.0 as f32, color_size.1 as f32, mask_size.0 as f32, mask_size.1 as f32); - let index_count = draw_call.batch.index_count as i32; + let index_count = draw_call.index_count as i32; self.profile_counters.draw_calls.inc(); - self.device.draw_triangles_u16(draw_call.batch.first_vertex as i32, + self.device.draw_triangles_u16(draw_call.first_vertex as i32, index_count); } }