From 5d632c41b03d10ffe172e8859d1ca1f4c7b24d15 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 26 Jan 2016 13:42:19 -0800 Subject: [PATCH] Add support for transformed render targets. --- src/frame.rs | 20 +++++++++++++++----- src/internal_types.rs | 1 + src/renderer.rs | 37 ++++++++++++++++++++----------------- 3 files changed, 36 insertions(+), 22 deletions(-) diff --git a/src/frame.rs b/src/frame.rs index 7ad445bb32..dbe96b0400 100644 --- a/src/frame.rs +++ b/src/frame.rs @@ -278,6 +278,7 @@ impl RenderTarget { fn push_composite(&mut self, op: CompositionOp, target: Rect, + transform: &Matrix4, render_target_index: RenderTargetIndex) { // TODO(gw): Relax the restriction on batch breaks for FB reads // once the proper render target allocation code is done! @@ -304,6 +305,7 @@ impl RenderTarget { &mut FrameRenderItem::CompositeBatch(ref mut batch) => { let job = CompositeBatchJob { rect: target, + transform: *transform, render_target_index: render_target_index }; batch.jobs.push(job); @@ -867,12 +869,17 @@ impl Frame { if let Some(local_clip_rect) = local_clip_rect { let scene_items = scene_item.collect_scene_items(&context.scene); if !scene_items.is_empty() { + let composition_operations = stacking_context.composition_operations(); // Build world space transform let origin = parent_info.offset_from_current_layer + stacking_context.bounds.origin; - let local_transform = Matrix4::identity().translate(origin.x, origin.y, 0.0) - .mul(&stacking_context.transform) - .translate(-origin.x, -origin.y, 0.0); + let local_transform = if composition_operations.is_empty() { + Matrix4::identity().translate(origin.x, origin.y, 0.0) + .mul(&stacking_context.transform) + .translate(-origin.x, -origin.y, 0.0) + } else { + Matrix4::identity() + }; let transform = parent_info.perspective.mul(&parent_info.transform) .mul(&local_transform); @@ -931,7 +938,6 @@ impl Frame { } // TODO: Account for scroll offset with transforms! - let composition_operations = stacking_context.composition_operations(); if composition_operations.is_empty() { self.add_items_to_target(&scene_items, &info, @@ -957,10 +963,14 @@ impl Frame { let mut new_target = RenderTarget::new(render_target_id, render_target_size); - // TODO(gw): Handle transforms + composition ops... + let local_transform = + Matrix4::identity().translate(origin.x, origin.y, 0.0) + .mul(&stacking_context.transform) + .translate(-origin.x, -origin.y, 0.0); for composition_operation in composition_operations { target.push_composite(composition_operation, target_rect, + &local_transform, render_target_index); } diff --git a/src/internal_types.rs b/src/internal_types.rs index a58074c35f..de36bc5e07 100644 --- a/src/internal_types.rs +++ b/src/internal_types.rs @@ -487,6 +487,7 @@ impl BatchInfo { #[derive(Debug, Clone)] pub struct CompositeBatchJob { pub rect: Rect, + pub transform: Matrix4, pub render_target_index: RenderTargetIndex, } diff --git a/src/renderer.rs b/src/renderer.rs index faf9925dfb..26109a97b6 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -1218,10 +1218,8 @@ impl Renderer { let (mut indices, mut vertices) = (vec![], vec![]); for job in &info.jobs { - let x0 = job.rect.origin.x; - let y0 = job.rect.origin.y; - let x1 = job.rect.max_x(); - let y1 = job.rect.max_y(); + let p0 = Point2D::new(job.rect.origin.x as f32, job.rect.origin.y as f32); + let p1 = Point2D::new(job.rect.max_x() as f32, job.rect.max_y() as f32); // TODO(glennw): No need to re-init this FB working copy texture // every time... @@ -1229,11 +1227,12 @@ impl Renderer { let fb_rect_size = Size2D::new(job.rect.size.width as f32 * render_context.device_pixel_ratio, job.rect.size.height as f32 * render_context.device_pixel_ratio); - let inverted_y0 = layer.layer_size.height as i32 - - job.rect.size.height - - y0; - let fb_rect_origin = Point2D::new(x0 as f32 * render_context.device_pixel_ratio, - inverted_y0 as f32 * render_context.device_pixel_ratio); + let inverted_y0 = layer.layer_size.height as f32 - + job.rect.size.height as f32 - + p0.y; + let fb_rect_origin = Point2D::new( + p0.x * render_context.device_pixel_ratio, + inverted_y0 * render_context.device_pixel_ratio); self.device.init_texture(render_context.temporary_fb_texture, fb_rect_size.width as u32, @@ -1279,26 +1278,30 @@ impl Renderer { Size2D::new(pixel_uv.size.width as f32 / texture_width, pixel_uv.size.height as f32 / texture_height)); + let tl = job.transform.transform_point(&p0); + let tr = job.transform.transform_point(&Point2D::new(p1.x, p0.y)); + let br = job.transform.transform_point(&p1); + let bl = job.transform.transform_point(&Point2D::new(p0.x, p1.y)); if needs_fb { vertices.extend_from_slice(&[ PackedVertex::from_components( - x0 as f32, y0 as f32, + tl.x, tl.y, &color, texture_uv.origin.x, texture_uv.max_y(), 0.0, 1.0), PackedVertex::from_components( - x1 as f32, y0 as f32, + tr.x, tr.y, &color, texture_uv.max_x(), texture_uv.max_y(), 1.0, 1.0), PackedVertex::from_components( - x0 as f32, y1 as f32, + bl.x, bl.y, &color, texture_uv.origin.x, texture_uv.origin.y, 0.0, 0.0), PackedVertex::from_components( - x1 as f32, y1 as f32, + br.x, br.y, &color, texture_uv.max_x(), texture_uv.origin.y, 1.0, 0.0), @@ -1306,22 +1309,22 @@ impl Renderer { } else { vertices.extend_from_slice(&[ PackedVertex::from_components_unscaled_muv( - x0 as f32, y0 as f32, + tl.x, tl.y, &color, texture_uv.origin.x, texture_uv.max_y(), texture_width as u16, texture_height as u16), PackedVertex::from_components_unscaled_muv( - x1 as f32, y0 as f32, + tr.x, tr.y, &color, texture_uv.max_x(), texture_uv.max_y(), texture_width as u16, texture_height as u16), PackedVertex::from_components_unscaled_muv( - x0 as f32, y1 as f32, + bl.x, bl.y, &color, texture_uv.origin.x, texture_uv.origin.y, texture_width as u16, texture_height as u16), PackedVertex::from_components_unscaled_muv( - x1 as f32, y1 as f32, + br.x, br.y, &color, texture_uv.max_x(), texture_uv.origin.y, texture_width as u16, texture_height as u16),