From 5bdcb9546fa2efd65190334c793876c3cc12939d Mon Sep 17 00:00:00 2001 From: Glenn Watson Date: Thu, 2 Nov 2017 16:34:06 +1000 Subject: [PATCH] Remove ClipScrollGroup and PackedLayer. Instead, we provide access to both the clip node and scroll node for a given primitive in the shader. The shader then calculated the appropriate local clip rect. There's a few hacks in here - for example, the way that I pack the clip/scroll IDs into a single u32 for the shaders. In the future, we'll be switching the vertex formats to work on u16 size data fields, so this will become a lot simpler then. --- webrender/res/brush.glsl | 8 +- webrender/res/clip_shared.glsl | 8 +- webrender/res/cs_clip_border.glsl | 2 +- webrender/res/cs_clip_image.glsl | 2 +- webrender/res/cs_clip_rectangle.glsl | 2 +- webrender/res/prim_shared.glsl | 73 ++++++--- webrender/src/box_shadow.rs | 2 - webrender/src/clip.rs | 26 ++-- webrender/src/clip_scroll_node.rs | 89 ++++++----- webrender/src/clip_scroll_tree.rs | 20 ++- webrender/src/frame.rs | 16 +- webrender/src/frame_builder.rs | 222 ++++----------------------- webrender/src/gpu_types.rs | 56 ++++--- webrender/src/prim_store.rs | 32 ++-- webrender/src/render_task.rs | 7 +- webrender/src/renderer.rs | 26 ++-- webrender/src/tiling.rs | 113 +++----------- webrender/src/util.rs | 9 ++ 18 files changed, 281 insertions(+), 432 deletions(-) diff --git a/webrender/res/brush.glsl b/webrender/res/brush.glsl index 4cf9e886bb..3230f56706 100644 --- a/webrender/res/brush.glsl +++ b/webrender/res/brush.glsl @@ -19,7 +19,8 @@ void brush_vs( struct BrushInstance { int picture_address; int prim_address; - int layer_address; + int clip_node_id; + int scroll_node_id; int clip_address; int z; int flags; @@ -31,7 +32,8 @@ BrushInstance load_brush() { bi.picture_address = aData0.x; bi.prim_address = aData0.y; - bi.layer_address = aData0.z; + bi.clip_node_id = aData0.z / 65536; + bi.scroll_node_id = aData0.z % 65536; bi.clip_address = aData0.w; bi.z = aData1.x; bi.flags = aData1.y; @@ -66,7 +68,7 @@ void main(void) { gl_Position = uTransform * vec4(device_pos, 0.0, 1.0); } else { AlphaBatchTask alpha_task = fetch_alpha_batch_task(brush.picture_address); - Layer layer = fetch_layer(brush.layer_address); + Layer layer = fetch_layer(brush.clip_node_id, brush.scroll_node_id); ClipArea clip_area = fetch_clip_area(brush.clip_address); // Write the normal vertex information out. diff --git a/webrender/res/clip_shared.glsl b/webrender/res/clip_shared.glsl index d2d75b4f39..4443d9038d 100644 --- a/webrender/res/clip_shared.glsl +++ b/webrender/res/clip_shared.glsl @@ -52,10 +52,6 @@ ClipVertexInfo write_clip_tile_vertex(RectWithSize local_clip_rect, Layer layer, ClipArea area, int segment) { - - RectWithSize clipped_local_rect = intersect_rect(local_clip_rect, - layer.local_clip_rect); - vec2 outer_p0 = area.screen_origin_target_index.xy; vec2 outer_p1 = outer_p0 + area.task_bounds.zw - area.task_bounds.xy; vec2 inner_p0 = area.inner_rect.xy; @@ -94,9 +90,9 @@ ClipVertexInfo write_clip_tile_vertex(RectWithSize local_clip_rect, gl_Position = uTransform * vec4(vertex_pos, 0.0, 1); - vLocalBounds = vec4(clipped_local_rect.p0, clipped_local_rect.p0 + clipped_local_rect.size); + vLocalBounds = vec4(local_clip_rect.p0, local_clip_rect.p0 + local_clip_rect.size); - ClipVertexInfo vi = ClipVertexInfo(layer_pos.xyw, actual_pos, clipped_local_rect); + ClipVertexInfo vi = ClipVertexInfo(layer_pos.xyw, actual_pos, local_clip_rect); return vi; } diff --git a/webrender/res/cs_clip_border.glsl b/webrender/res/cs_clip_border.glsl index f9f7ace448..30f1b9de57 100644 --- a/webrender/res/cs_clip_border.glsl +++ b/webrender/res/cs_clip_border.glsl @@ -64,7 +64,7 @@ BorderClipDot fetch_border_clip_dot(ivec2 address, int segment) { void main(void) { ClipMaskInstance cmi = fetch_clip_item(); ClipArea area = fetch_clip_area(cmi.render_task_address); - Layer layer = fetch_layer(cmi.layer_address); + Layer layer = fetch_layer(cmi.layer_address, cmi.layer_address); // Fetch the header information for this corner clip. BorderCorner corner = fetch_border_corner(cmi.clip_data_address); diff --git a/webrender/res/cs_clip_image.glsl b/webrender/res/cs_clip_image.glsl index fadb9451d1..4ea58b0fb1 100644 --- a/webrender/res/cs_clip_image.glsl +++ b/webrender/res/cs_clip_image.glsl @@ -24,7 +24,7 @@ ImageMaskData fetch_mask_data(ivec2 address) { void main(void) { ClipMaskInstance cmi = fetch_clip_item(); ClipArea area = fetch_clip_area(cmi.render_task_address); - Layer layer = fetch_layer(cmi.layer_address); + Layer layer = fetch_layer(cmi.layer_address, cmi.layer_address); ImageMaskData mask = fetch_mask_data(cmi.clip_data_address); RectWithSize local_rect = mask.local_rect; ImageResource res = fetch_image_resource_direct(cmi.resource_address); diff --git a/webrender/res/cs_clip_rectangle.glsl b/webrender/res/cs_clip_rectangle.glsl index 0370aeef13..239a3bf6e7 100644 --- a/webrender/res/cs_clip_rectangle.glsl +++ b/webrender/res/cs_clip_rectangle.glsl @@ -58,7 +58,7 @@ ClipData fetch_clip(ivec2 address) { void main(void) { ClipMaskInstance cmi = fetch_clip_item(); ClipArea area = fetch_clip_area(cmi.render_task_address); - Layer layer = fetch_layer(cmi.layer_address); + Layer layer = fetch_layer(cmi.layer_address, cmi.layer_address); ClipData clip = fetch_clip(cmi.clip_data_address); RectWithSize local_rect = clip.rect.rect; diff --git a/webrender/res/prim_shared.glsl b/webrender/res/prim_shared.glsl index e560fa5de5..81a4725795 100644 --- a/webrender/res/prim_shared.glsl +++ b/webrender/res/prim_shared.glsl @@ -71,14 +71,14 @@ vec4[2] fetch_from_resource_cache_2(int address) { #ifdef WR_VERTEX_SHADER -#define VECS_PER_LAYER 9 +#define VECS_PER_LAYER 10 #define VECS_PER_RENDER_TASK 3 #define VECS_PER_PRIM_HEADER 2 #define VECS_PER_TEXT_RUN 3 #define VECS_PER_GRADIENT 3 #define VECS_PER_GRADIENT_STOP 2 -uniform HIGHP_SAMPLER_FLOAT sampler2D sLayers; +uniform HIGHP_SAMPLER_FLOAT sampler2D sClipScrollNodes; uniform HIGHP_SAMPLER_FLOAT sampler2D sRenderTasks; // Instanced attributes @@ -143,14 +143,16 @@ vec4 fetch_from_resource_cache_1(int address) { return texelFetch(sResourceCache, uv, 0); } -struct Layer { +struct ClipScrollNode { mat4 transform; mat4 inv_transform; - RectWithSize local_clip_rect; + vec4 local_clip_rect; + vec2 reference_frame_relative_scroll_offset; + vec2 scroll_offset; }; -Layer fetch_layer(int index) { - Layer layer; +ClipScrollNode fetch_clip_scroll_node(int index) { + ClipScrollNode node; // Create a UV base coord for each 8 texels. // This is required because trying to use an offset @@ -160,18 +162,46 @@ Layer fetch_layer(int index) { ivec2 uv0 = ivec2(uv.x + 0, uv.y); ivec2 uv1 = ivec2(uv.x + 8, uv.y); - layer.transform[0] = TEXEL_FETCH(sLayers, uv0, 0, ivec2(0, 0)); - layer.transform[1] = TEXEL_FETCH(sLayers, uv0, 0, ivec2(1, 0)); - layer.transform[2] = TEXEL_FETCH(sLayers, uv0, 0, ivec2(2, 0)); - layer.transform[3] = TEXEL_FETCH(sLayers, uv0, 0, ivec2(3, 0)); + node.transform[0] = TEXEL_FETCH(sClipScrollNodes, uv0, 0, ivec2(0, 0)); + node.transform[1] = TEXEL_FETCH(sClipScrollNodes, uv0, 0, ivec2(1, 0)); + node.transform[2] = TEXEL_FETCH(sClipScrollNodes, uv0, 0, ivec2(2, 0)); + node.transform[3] = TEXEL_FETCH(sClipScrollNodes, uv0, 0, ivec2(3, 0)); + + node.inv_transform[0] = TEXEL_FETCH(sClipScrollNodes, uv0, 0, ivec2(4, 0)); + node.inv_transform[1] = TEXEL_FETCH(sClipScrollNodes, uv0, 0, ivec2(5, 0)); + node.inv_transform[2] = TEXEL_FETCH(sClipScrollNodes, uv0, 0, ivec2(6, 0)); + node.inv_transform[3] = TEXEL_FETCH(sClipScrollNodes, uv0, 0, ivec2(7, 0)); + + vec4 clip_rect = TEXEL_FETCH(sClipScrollNodes, uv1, 0, ivec2(0, 0)); + node.local_clip_rect = clip_rect; + + vec4 offsets = TEXEL_FETCH(sClipScrollNodes, uv1, 0, ivec2(1, 0)); + node.reference_frame_relative_scroll_offset = offsets.xy; + node.scroll_offset = offsets.zw; + + return node; +} + +struct Layer { + mat4 transform; + mat4 inv_transform; + RectWithSize local_clip_rect; +}; + +Layer fetch_layer(int clip_node_id, int scroll_node_id) { + ClipScrollNode clip_node = fetch_clip_scroll_node(clip_node_id); + ClipScrollNode scroll_node = fetch_clip_scroll_node(scroll_node_id); + + Layer layer; + layer.transform = scroll_node.transform; + layer.inv_transform = scroll_node.inv_transform; - layer.inv_transform[0] = TEXEL_FETCH(sLayers, uv0, 0, ivec2(4, 0)); - layer.inv_transform[1] = TEXEL_FETCH(sLayers, uv0, 0, ivec2(5, 0)); - layer.inv_transform[2] = TEXEL_FETCH(sLayers, uv0, 0, ivec2(6, 0)); - layer.inv_transform[3] = TEXEL_FETCH(sLayers, uv0, 0, ivec2(7, 0)); + vec4 local_clip_rect = clip_node.local_clip_rect; + local_clip_rect.xy += clip_node.reference_frame_relative_scroll_offset; + local_clip_rect.xy -= scroll_node.reference_frame_relative_scroll_offset; + local_clip_rect.xy -= scroll_node.scroll_offset; - vec4 clip_rect = TEXEL_FETCH(sLayers, uv1, 0, ivec2(0, 0)); - layer.local_clip_rect = RectWithSize(clip_rect.xy, clip_rect.zw); + layer.local_clip_rect = RectWithSize(local_clip_rect.xy, local_clip_rect.zw); return layer; } @@ -358,7 +388,8 @@ struct PrimitiveInstance { int specific_prim_address; int render_task_index; int clip_task_index; - int layer_index; + int scroll_node_id; + int clip_node_id; int z; int user_data0; int user_data1; @@ -372,7 +403,8 @@ PrimitiveInstance fetch_prim_instance() { pi.specific_prim_address = pi.prim_address + VECS_PER_PRIM_HEADER; pi.render_task_index = aData0.y; pi.clip_task_index = aData0.z; - pi.layer_index = aData0.w; + pi.clip_node_id = aData0.w / 65536; + pi.scroll_node_id = aData0.w % 65536; pi.z = aData1.x; pi.user_data0 = aData1.y; pi.user_data1 = aData1.z; @@ -437,7 +469,7 @@ Primitive load_primitive() { Primitive prim; - prim.layer = fetch_layer(pi.layer_index); + prim.layer = fetch_layer(pi.clip_node_id, pi.scroll_node_id); prim.clip_area = fetch_clip_area(pi.clip_task_index); #ifdef PRIMITIVE_HAS_PICTURE_TASK prim.task = fetch_picture_task(pi.render_task_index); @@ -546,8 +578,7 @@ VertexInfo write_vertex(RectWithSize instance_rect, vec2 local_pos = instance_rect.p0 + instance_rect.size * aPosition.xy; // Clamp to the two local clip rects. - vec2 clamped_local_pos = clamp_rect(clamp_rect(local_pos, local_clip_rect), - layer.local_clip_rect); + vec2 clamped_local_pos = clamp_rect(clamp_rect(local_pos, local_clip_rect), layer.local_clip_rect); /// Compute the snapping offset. vec2 snap_offset = compute_snap_offset(clamped_local_pos, local_clip_rect, layer, snap_rect); diff --git a/webrender/src/box_shadow.rs b/webrender/src/box_shadow.rs index c1401e7699..51356745ff 100644 --- a/webrender/src/box_shadow.rs +++ b/webrender/src/box_shadow.rs @@ -170,7 +170,6 @@ impl FrameBuilder { LayerSize::new(width, height)); let brush_info = LayerPrimitiveInfo::new(brush_rect); let brush_prim_index = self.create_primitive( - clip_and_scroll, &brush_info, Vec::new(), PrimitiveContainer::Brush(brush_prim), @@ -239,7 +238,6 @@ impl FrameBuilder { }; let brush_info = LayerPrimitiveInfo::new(brush_rect); let brush_prim_index = self.create_primitive( - clip_and_scroll, &brush_info, Vec::new(), PrimitiveContainer::Brush(brush_prim), diff --git a/webrender/src/clip.rs b/webrender/src/clip.rs index de8e20a45c..7098a2e820 100644 --- a/webrender/src/clip.rs +++ b/webrender/src/clip.rs @@ -21,7 +21,6 @@ pub type ClipSourcesWeakHandle = WeakFreeListHandle; #[derive(Clone, Debug)] pub struct ClipRegion { - pub origin: LayerPoint, pub main: LayerRect, pub image_mask: Option, pub complex_clips: Vec, @@ -32,32 +31,39 @@ impl ClipRegion { rect: LayerRect, mut complex_clips: Vec, mut image_mask: Option, + reference_frame_relative_offset: &LayoutVector2D, ) -> ClipRegion { - // All the coordinates we receive are relative to the stacking context, but we want - // to convert them to something relative to the origin of the clip. - let negative_origin = -rect.origin.to_vector(); + let rect = rect.translate(reference_frame_relative_offset); + if let Some(ref mut image_mask) = image_mask { - image_mask.rect = image_mask.rect.translate(&negative_origin); + image_mask.rect = image_mask.rect.translate(reference_frame_relative_offset); } for complex_clip in complex_clips.iter_mut() { - complex_clip.rect = complex_clip.rect.translate(&negative_origin); + complex_clip.rect = complex_clip.rect.translate(reference_frame_relative_offset); } ClipRegion { - origin: rect.origin, - main: LayerRect::new(LayerPoint::zero(), rect.size), + main: rect, image_mask, complex_clips, } } - pub fn create_for_clip_node_with_local_clip(local_clip: &LocalClip) -> ClipRegion { + pub fn create_for_clip_node_with_local_clip( + local_clip: &LocalClip, + reference_frame_relative_offset: &LayoutVector2D + ) -> ClipRegion { let complex_clips = match local_clip { &LocalClip::Rect(_) => Vec::new(), &LocalClip::RoundedRect(_, ref region) => vec![region.clone()], }; - ClipRegion::create_for_clip_node(*local_clip.clip_rect(), complex_clips, None) + ClipRegion::create_for_clip_node( + *local_clip.clip_rect(), + complex_clips, + None, + reference_frame_relative_offset + ) } } diff --git a/webrender/src/clip_scroll_node.rs b/webrender/src/clip_scroll_node.rs index a89a36c77f..98d5cf0859 100644 --- a/webrender/src/clip_scroll_node.rs +++ b/webrender/src/clip_scroll_node.rs @@ -4,18 +4,18 @@ use api::{ClipId, DeviceIntRect, LayerPixel, LayerPoint, LayerRect, LayerSize}; use api::{LayerToScrollTransform, LayerToWorldTransform, LayerVector2D, PipelineId}; -use api::{ScrollClamping, ScrollEventPhase, ScrollLocation, ScrollSensitivity, StickyOffsetBounds}; -use api::WorldPoint; +use api::{ScrollClamping, ScrollEventPhase, ScrollLocation, ScrollSensitivity}; +use api::{StickyOffsetBounds, WorldPoint}; use clip::{ClipRegion, ClipSources, ClipSourcesHandle, ClipStore}; use clip_scroll_tree::{CoordinateSystemId, TransformUpdateState}; use euclid::SideOffsets2D; use geometry::ray_intersects_rect; use gpu_cache::GpuCache; +use gpu_types::{ClipScrollNodeIndex, ClipScrollNodeData}; use render_task::{ClipChain, ClipChainNode, ClipWorkItem}; use resource_cache::ResourceCache; use spring::{DAMPING, STIFFNESS, Spring}; use std::rc::Rc; -use tiling::{PackedLayer, PackedLayerIndex}; use util::{MatrixHelpers, MaxRect}; #[cfg(target_os = "macos")] @@ -24,15 +24,13 @@ const CAN_OVERSCROLL: bool = true; #[cfg(not(target_os = "macos"))] const CAN_OVERSCROLL: bool = false; +const MAX_LOCAL_VIEWPORT: f32 = 1000000.0; + #[derive(Debug)] pub struct ClipInfo { /// The clips for this node. pub clip_sources: ClipSourcesHandle, - /// The packed layer index for this node, which is used to render a clip mask - /// for it, if necessary. - pub packed_layer_index: PackedLayerIndex, - /// Whether or not this clip node automatically creates a mask. pub is_masking: bool, } @@ -40,7 +38,6 @@ pub struct ClipInfo { impl ClipInfo { pub fn new( clip_region: ClipRegion, - packed_layer_index: PackedLayerIndex, clip_store: &mut ClipStore, ) -> ClipInfo { let clip_sources = ClipSources::from(clip_region); @@ -48,7 +45,6 @@ impl ClipInfo { ClipInfo { clip_sources: clip_store.insert(clip_sources), - packed_layer_index, is_masking, } } @@ -110,7 +106,8 @@ pub struct ClipScrollNode { /// This is in the coordinate system of the node origin. /// Precisely, it combines the local clipping rectangles of all the parent /// nodes on the way to the root, including those of `ClipRegion` rectangles. - /// The combined clip is lossy/concervative on `ReferenceFrame` nodes. + /// The combined clip is reset to maximum when an incompatible coordinate + /// system is encountered. pub combined_local_viewport_rect: LayerRect, /// World transform for the viewport rect itself. This is the parent @@ -148,6 +145,10 @@ pub struct ClipScrollNode { /// The axis-aligned coordinate system id of this node. pub coordinate_system_id: CoordinateSystemId, + + /// A linear ID / index of this clip-scroll node. Used as a reference to + /// pass to shaders, to allow them to fetch a given clip-scroll node. + pub id: ClipScrollNodeIndex, } impl ClipScrollNode { @@ -171,6 +172,7 @@ impl ClipScrollNode { clip_chain_node: None, combined_clip_outer_bounds: DeviceIntRect::max_rect(), coordinate_system_id: CoordinateSystemId(0), + id: ClipScrollNodeIndex(0), } } @@ -287,15 +289,11 @@ impl ClipScrollNode { pub fn update_clip_work_item( &mut self, state: &mut TransformUpdateState, - screen_rect: &DeviceIntRect, device_pixel_ratio: f32, - packed_layers: &mut Vec, clip_store: &mut ClipStore, resource_cache: &mut ResourceCache, gpu_cache: &mut GpuCache, ) { - self.coordinate_system_id = state.current_coordinate_system_id; - let current_clip_chain = state.parent_clip_chain.clone(); let clip_info = match self.node_type { NodeType::Clip(ref mut info) if info.is_masking => info, @@ -306,29 +304,9 @@ impl ClipScrollNode { } }; - // The coordinates of the mask are relative to the origin of the node itself, - // so we need to account for that origin in the transformation we assign to - // the packed layer. - let transform = self.world_viewport_transform - .pre_translate(self.local_viewport_rect.origin.to_vector().to_3d()); - - let packed_layer = &mut packed_layers[clip_info.packed_layer_index.0]; - if packed_layer.set_transform(transform) { - // Meanwhile, the combined viewport rect is relative to the reference frame, so - // we move it into the local coordinate system of the node. - let local_viewport_rect = self.combined_local_viewport_rect - .translate(&-self.local_viewport_rect.origin.to_vector()); - - packed_layer.set_rect( - &local_viewport_rect, - screen_rect, - device_pixel_ratio, - ); - } - let clip_sources = clip_store.get_mut(&clip_info.clip_sources); clip_sources.update( - &transform, + &self.world_viewport_transform, gpu_cache, resource_cache, device_pixel_ratio, @@ -345,7 +323,7 @@ impl ClipScrollNode { // TODO: Combine rectangles in the same axis-aligned clip space here? self.clip_chain_node = Some(Rc::new(ClipChainNode { work_item: ClipWorkItem { - layer_index: clip_info.packed_layer_index, + scroll_node_id: self.id, clip_sources: clip_info.clip_sources.weak(), coordinate_system_id: state.current_coordinate_system_id, }, @@ -356,7 +334,11 @@ impl ClipScrollNode { state.parent_clip_chain = self.clip_chain_node.clone(); } - pub fn update_transform(&mut self, state: &mut TransformUpdateState) { + pub fn update_transform( + &mut self, + state: &mut TransformUpdateState, + node_data: &mut Vec, + ) { // We calculate this here to avoid a double-borrow later. let sticky_offset = self.calculate_sticky_offset( &state.nearest_scrolling_ancestor_offset, @@ -452,6 +434,39 @@ impl ClipScrollNode { info.current_offset + state.parent_accumulated_scroll_offset; } } + + // Store coord system ID, and also the ID used for shaders to reference this node. + self.coordinate_system_id = state.current_coordinate_system_id; + self.id = ClipScrollNodeIndex(node_data.len() as u32); + + let local_clip_rect = if self.world_content_transform.has_perspective_component() { + LayerRect::new( + LayerPoint::new(-MAX_LOCAL_VIEWPORT, -MAX_LOCAL_VIEWPORT), + LayerSize::new(2.0 * MAX_LOCAL_VIEWPORT, 2.0 * MAX_LOCAL_VIEWPORT) + ) + } else { + self.combined_local_viewport_rect + }; + + let data = match self.world_content_transform.inverse() { + Some(inverse) => { + ClipScrollNodeData { + transform: self.world_content_transform, + inv_transform: inverse, + local_clip_rect, + reference_frame_relative_scroll_offset: self.reference_frame_relative_scroll_offset, + scroll_offset: self.scroll_offset(), + } + } + None => { + state.combined_outer_clip_bounds = DeviceIntRect::zero(); + + ClipScrollNodeData::invalid() + } + }; + + // Write the data that will be made available to the GPU for this node. + node_data.push(data); } fn calculate_sticky_offset( diff --git a/webrender/src/clip_scroll_tree.rs b/webrender/src/clip_scroll_tree.rs index 599717f64f..99f8fd6fcd 100644 --- a/webrender/src/clip_scroll_tree.rs +++ b/webrender/src/clip_scroll_tree.rs @@ -8,11 +8,11 @@ use api::{ScrollLayerState, ScrollLocation, WorldPoint}; use clip::ClipStore; use clip_scroll_node::{ClipScrollNode, NodeType, ScrollingState, StickyFrameInfo}; use gpu_cache::GpuCache; +use gpu_types::ClipScrollNodeData; use internal_types::{FastHashMap, FastHashSet}; use print_tree::{PrintTree, PrintTreePrinter}; use render_task::ClipChain; use resource_cache::ResourceCache; -use tiling::PackedLayer; pub type ScrollStates = FastHashMap; @@ -329,11 +329,11 @@ impl ClipScrollTree { &mut self, screen_rect: &DeviceIntRect, device_pixel_ratio: f32, - packed_layers: &mut Vec, clip_store: &mut ClipStore, resource_cache: &mut ResourceCache, gpu_cache: &mut GpuCache, pan: LayerPoint, + node_data: &mut Vec, ) { if self.nodes.is_empty() { return; @@ -360,12 +360,11 @@ impl ClipScrollTree { self.update_node_transform( root_reference_frame_id, &mut state, - &screen_rect, device_pixel_ratio, - packed_layers, clip_store, resource_cache, gpu_cache, + node_data, ); } @@ -373,12 +372,11 @@ impl ClipScrollTree { &mut self, layer_id: ClipId, state: &mut TransformUpdateState, - screen_rect: &DeviceIntRect, device_pixel_ratio: f32, - packed_layers: &mut Vec, clip_store: &mut ClipStore, resource_cache: &mut ResourceCache, gpu_cache: &mut GpuCache, + node_data: &mut Vec, ) { // TODO(gw): This is an ugly borrow check workaround to clone these. // Restructure this to avoid the clones! @@ -389,12 +387,13 @@ impl ClipScrollTree { None => return, }; - node.update_transform(&mut state); + node.update_transform( + &mut state, + node_data + ); node.update_clip_work_item( &mut state, - screen_rect, device_pixel_ratio, - packed_layers, clip_store, resource_cache, gpu_cache, @@ -407,12 +406,11 @@ impl ClipScrollTree { self.update_node_transform( child_layer_id, &mut state, - screen_rect, device_pixel_ratio, - packed_layers, clip_store, resource_cache, gpu_cache, + node_data, ); } } diff --git a/webrender/src/frame.rs b/webrender/src/frame.rs index d1e68d3cde..72c61e4521 100644 --- a/webrender/src/frame.rs +++ b/webrender/src/frame.rs @@ -322,8 +322,10 @@ impl<'a> FlattenContext<'a> { None => return, }; - let mut clip_region = ClipRegion::create_for_clip_node_with_local_clip(local_clip); - clip_region.origin += reference_frame_relative_offset; + let clip_region = ClipRegion::create_for_clip_node_with_local_clip( + local_clip, + &reference_frame_relative_offset + ); let parent_pipeline_id = parent_id.pipeline_id(); let clip_id = self.clip_scroll_tree .generate_new_clip_id(parent_pipeline_id); @@ -552,13 +554,12 @@ impl<'a> FlattenContext<'a> { } SpecificDisplayItem::Clip(ref info) => { let complex_clips = self.get_complex_clips(pipeline_id, item.complex_clip().0); - let mut clip_region = ClipRegion::create_for_clip_node( + let clip_region = ClipRegion::create_for_clip_node( *item.local_clip().clip_rect(), complex_clips, info.image_mask, + &reference_frame_relative_offset, ); - clip_region.origin += reference_frame_relative_offset; - self.flatten_clip( pipeline_id, &clip_and_scroll.scroll_node_id, @@ -568,13 +569,12 @@ impl<'a> FlattenContext<'a> { } SpecificDisplayItem::ScrollFrame(ref info) => { let complex_clips = self.get_complex_clips(pipeline_id, item.complex_clip().0); - let mut clip_region = ClipRegion::create_for_clip_node( + let clip_region = ClipRegion::create_for_clip_node( *item.local_clip().clip_rect(), complex_clips, info.image_mask, + &reference_frame_relative_offset, ); - clip_region.origin += reference_frame_relative_offset; - // Just use clip rectangle as the frame rect for this scroll frame. // This is useful when calculating scroll extents for the // ClipScrollNode::scroll(..) API as well as for properly setting sticky diff --git a/webrender/src/frame_builder.rs b/webrender/src/frame_builder.rs index 79a450c0f8..15fcd94e25 100644 --- a/webrender/src/frame_builder.rs +++ b/webrender/src/frame_builder.rs @@ -16,7 +16,7 @@ use app_units::Au; use border::ImageBorderSegment; use clip::{ClipRegion, ClipSource, ClipSources, ClipStore, Contains}; use clip_scroll_node::{ClipInfo, ClipScrollNode, NodeType}; -use clip_scroll_tree::{ClipScrollTree, CoordinateSystemId}; +use clip_scroll_tree::{ClipScrollTree}; use euclid::{SideOffsets2D, TypedTransform3D, vec2, vec3}; use frame::FrameId; use gpu_cache::GpuCache; @@ -29,14 +29,14 @@ use prim_store::{PrimitiveContainer, PrimitiveIndex}; use prim_store::{PrimitiveStore, RadialGradientPrimitiveCpu}; use prim_store::{RectangleContent, RectanglePrimitive, TextRunPrimitiveCpu}; use profiler::{FrameProfileCounters, GpuCacheProfileCounters, TextureCacheProfileCounters}; -use render_task::{AlphaRenderItem, ClearMode, ClipChain, RenderTask, RenderTaskId, RenderTaskLocation}; +use render_task::{AlphaRenderItem, ClearMode, RenderTask, RenderTaskId, RenderTaskLocation}; use render_task::RenderTaskTree; use resource_cache::ResourceCache; use scene::ScenePipeline; use std::{mem, usize, f32, i32}; -use tiling::{ClipScrollGroup, ClipScrollGroupIndex, CompositeOps, Frame}; +use tiling::{CompositeOps, Frame}; use tiling::{ContextIsolation, RenderTargetKind, StackingContextIndex}; -use tiling::{PackedLayer, PackedLayerIndex, PrimitiveFlags, PrimitiveRunCmd, RenderPass}; +use tiling::{PrimitiveFlags, PrimitiveRunCmd, RenderPass}; use tiling::{RenderTargetContext, ScrollbarPrimitive, StackingContext}; use util::{self, pack_as_float, RectHelpers, recycle_vec}; use box_shadow::BLUR_SAMPLE_SCALE; @@ -113,11 +113,6 @@ pub struct FrameBuilder { pub config: FrameBuilderConfig, stacking_context_store: Vec, - clip_scroll_group_store: Vec, - // Note: value here is meant to be `ClipScrollGroupIndex`, - // but we already have `ClipAndScrollInfo` in the key - clip_scroll_group_indices: FastHashMap, - packed_layers: Vec, // A stack of the current shadow primitives. // The sub-Vec stores a buffer of fast-path primitives to be appended on pop. @@ -141,36 +136,24 @@ pub struct FrameBuilder { } pub struct PrimitiveContext<'a> { - pub packed_layer_index: PackedLayerIndex, - pub packed_layer: &'a PackedLayer, pub device_pixel_ratio: f32, - pub clip_chain: ClipChain, - pub clip_bounds: DeviceIntRect, - pub clip_id: ClipId, - pub coordinate_system_id: CoordinateSystemId, pub display_list: &'a BuiltDisplayList, + pub clip_node: &'a ClipScrollNode, + pub scroll_node: &'a ClipScrollNode, } impl<'a> PrimitiveContext<'a> { fn new( - packed_layer_index: PackedLayerIndex, - packed_layer: &'a PackedLayer, - clip_id: ClipId, - clip_chain: ClipChain, - clip_bounds: DeviceIntRect, - coordinate_system_id: CoordinateSystemId, device_pixel_ratio: f32, display_list: &'a BuiltDisplayList, + clip_node: &'a ClipScrollNode, + scroll_node: &'a ClipScrollNode, ) -> Self { PrimitiveContext { - packed_layer_index, - packed_layer, - clip_chain, - clip_bounds, - coordinate_system_id, device_pixel_ratio, - clip_id, display_list, + clip_node, + scroll_node, } } } @@ -185,11 +168,8 @@ impl FrameBuilder { match previous { Some(prev) => FrameBuilder { stacking_context_store: recycle_vec(prev.stacking_context_store), - clip_scroll_group_store: recycle_vec(prev.clip_scroll_group_store), - clip_scroll_group_indices: FastHashMap::default(), cmds: recycle_vec(prev.cmds), hit_testing_runs: recycle_vec(prev.hit_testing_runs), - packed_layers: recycle_vec(prev.packed_layers), shadow_prim_stack: recycle_vec(prev.shadow_prim_stack), pending_shadow_contents: recycle_vec(prev.pending_shadow_contents), scrollbar_prims: recycle_vec(prev.scrollbar_prims), @@ -204,11 +184,8 @@ impl FrameBuilder { }, None => FrameBuilder { stacking_context_store: Vec::new(), - clip_scroll_group_store: Vec::new(), - clip_scroll_group_indices: FastHashMap::default(), cmds: Vec::new(), hit_testing_runs: Vec::new(), - packed_layers: Vec::new(), shadow_prim_stack: Vec::new(), pending_shadow_contents: Vec::new(), scrollbar_prims: Vec::new(), @@ -229,16 +206,10 @@ impl FrameBuilder { /// sub-primitives. pub fn create_primitive( &mut self, - clip_and_scroll: ClipAndScrollInfo, info: &LayerPrimitiveInfo, mut clip_sources: Vec, container: PrimitiveContainer, ) -> PrimitiveIndex { - if !self.clip_scroll_group_indices.contains_key(&clip_and_scroll) { - let group_id = self.create_clip_scroll_group(&clip_and_scroll); - self.clip_scroll_group_indices.insert(clip_and_scroll, group_id); - } - if let &LocalClip::RoundedRect(main, region) = &info.local_clip { clip_sources.push(ClipSource::Rectangle(main)); clip_sources.push(ClipSource::RoundedRectangle( @@ -322,28 +293,12 @@ impl FrameBuilder { container: PrimitiveContainer, ) -> PrimitiveIndex { self.add_primitive_to_hit_testing_list(info, clip_and_scroll); - let prim_index = self.create_primitive(clip_and_scroll, info, clip_sources, container); + let prim_index = self.create_primitive(info, clip_sources, container); self.add_primitive_to_draw_list(prim_index, clip_and_scroll); prim_index } - fn create_clip_scroll_group(&mut self, info: &ClipAndScrollInfo) -> usize { - let packed_layer_index = PackedLayerIndex(self.packed_layers.len()); - self.packed_layers.push(PackedLayer::empty()); - - let group_id = self.clip_scroll_group_store.len(); - self.clip_scroll_group_store.push(ClipScrollGroup { - scroll_node_id: info.scroll_node_id, - clip_node_id: info.clip_node_id(), - packed_layer_index, - screen_bounding_rect: None, - coordinate_system_id: CoordinateSystemId(0), - }); - - group_id - } - pub fn notify_waiting_for_root_stacking_context(&mut self) { self.has_root_stacking_context = false; } @@ -517,15 +472,13 @@ impl FrameBuilder { clip_region: ClipRegion, clip_scroll_tree: &mut ClipScrollTree, ) { - let clip_rect = LayerRect::new(clip_region.origin, clip_region.main.size); + let clip_rect = clip_region.main; let clip_info = ClipInfo::new( clip_region, - PackedLayerIndex(self.packed_layers.len()), &mut self.clip_store, ); let node = ClipScrollNode::new_clip_node(pipeline_id, parent_id, clip_info, clip_rect); clip_scroll_tree.add_node(node, new_node_id); - self.packed_layers.push(PackedLayer::empty()); } pub fn add_scroll_frame( @@ -566,7 +519,6 @@ impl FrameBuilder { // before any visual text elements that are added as // part of this shadow context. let prim_index = self.create_primitive( - clip_and_scroll, info, Vec::new(), PrimitiveContainer::Picture(prim), @@ -676,7 +628,6 @@ impl FrameBuilder { let mut info = info.clone(); info.rect = info.rect.translate(&shadow.offset); let prim_index = self.create_primitive( - clip_and_scroll, &info, Vec::new(), PrimitiveContainer::Line(line), @@ -685,7 +636,6 @@ impl FrameBuilder { } let prim_index = self.create_primitive( - clip_and_scroll, &info, Vec::new(), PrimitiveContainer::Line(line), @@ -1183,7 +1133,6 @@ impl FrameBuilder { let mut info = info.clone(); info.rect = rect.translate(&text_prim.offset); let prim_index = self.create_primitive( - clip_and_scroll, &info, Vec::new(), PrimitiveContainer::TextRun(text_prim), @@ -1194,7 +1143,6 @@ impl FrameBuilder { // Create (and add to primitive store) the primitive that will be // used for both the visual element and also the shadow(s). let prim_index = self.create_primitive( - clip_and_scroll, info, Vec::new(), PrimitiveContainer::TextRun(prim), @@ -1317,19 +1265,6 @@ impl FrameBuilder { stacking_context.isolated_items_bounds = LayerRect::zero(); } - pub fn get_packed_layer_index_if_visible( - &self, - clip_and_scroll: &ClipAndScrollInfo - ) -> Option { - let group_id = self.clip_scroll_group_indices[&clip_and_scroll]; - let clip_scroll_group = &self.clip_scroll_group_store[group_id]; - if clip_scroll_group.is_visible() { - Some(clip_scroll_group.packed_layer_index) - } else { - None - } - } - pub fn hit_test( &self, clip_scroll_tree: &ClipScrollTree, @@ -1414,33 +1349,13 @@ impl FrameBuilder { profile_counters: &mut FrameProfileCounters, ) -> bool { let stacking_context_index = *self.stacking_context_stack.last().unwrap(); - let packed_layer_index = - match self.get_packed_layer_index_if_visible(&clip_and_scroll) { - Some(index) => index, - None => { - debug!("{:?} of invisible {:?}", base_prim_index, stacking_context_index); - return false; - } - }; + let scroll_node = &clip_scroll_tree.nodes[&clip_and_scroll.scroll_node_id]; + let clip_node = &clip_scroll_tree.nodes[&clip_and_scroll.clip_node_id()]; - let (clip_chain, clip_bounds, coordinate_system_id) = - match clip_scroll_tree.nodes.get(&clip_and_scroll.clip_node_id()) { - Some(node) if node.combined_clip_outer_bounds != DeviceIntRect::zero() => { - let group_id = self.clip_scroll_group_indices[&clip_and_scroll]; - ( - node.clip_chain_node.clone(), - node.combined_clip_outer_bounds, - self.clip_scroll_group_store[group_id].coordinate_system_id, - ) - } - _ => { - let group_id = self.clip_scroll_group_indices[&clip_and_scroll]; - self.clip_scroll_group_store[group_id].screen_bounding_rect = None; - - debug!("{:?} of clipped out {:?}", base_prim_index, stacking_context_index); - return false; - } - }; + if clip_node.combined_clip_outer_bounds == DeviceIntRect::zero() { + debug!("{:?} of clipped out {:?}", base_prim_index, stacking_context_index); + return false; + } let stacking_context = &mut self.stacking_context_store[stacking_context_index.0]; let pipeline_id = { @@ -1455,37 +1370,25 @@ impl FrameBuilder { }; debug!( - "\t{:?} of {:?} at {:?}", + "\t{:?} of {:?}", base_prim_index, stacking_context_index, - packed_layer_index ); - let packed_layer = &self.packed_layers[packed_layer_index.0]; let display_list = &pipelines .get(&pipeline_id) .expect("No display list?") .display_list; - if !stacking_context.is_backface_visible && packed_layer.transform.is_backface_visible() { + if !stacking_context.is_backface_visible && scroll_node.world_content_transform.is_backface_visible() { return false; } let prim_context = PrimitiveContext::new( - packed_layer_index, - packed_layer, - clip_and_scroll.clip_node_id(), - clip_chain, - clip_bounds, - coordinate_system_id, device_pixel_ratio, display_list, - ); - - debug!( - "\tclip_bounds {:?}, layer_local_clip {:?}", - prim_context.clip_bounds, - packed_layer.local_clip_rect + clip_node, + scroll_node, ); for i in 0 .. prim_count { @@ -1571,55 +1474,6 @@ impl FrameBuilder { } } - fn recalculate_clip_scroll_groups( - &mut self, - clip_scroll_tree: &ClipScrollTree, - screen_rect: &DeviceIntRect, - device_pixel_ratio: f32 - ) { - debug!("recalculate_clip_scroll_groups"); - for ref mut group in &mut self.clip_scroll_group_store { - let scroll_node = &clip_scroll_tree.nodes[&group.scroll_node_id]; - let clip_node = &clip_scroll_tree.nodes[&group.clip_node_id]; - let packed_layer = &mut self.packed_layers[group.packed_layer_index.0]; - - debug!( - "\tProcessing group scroll={:?}, clip={:?}", - group.scroll_node_id, - group.clip_node_id - ); - - let transform = scroll_node.world_content_transform; - if !packed_layer.set_transform(transform) { - group.screen_bounding_rect = None; - debug!("\t\tUnable to set transform {:?}", transform); - continue; - } - - // Here we move the viewport rectangle into the coordinate system - // of the stacking context content. - let local_viewport_rect = clip_node - .combined_local_viewport_rect - .translate(&clip_node.reference_frame_relative_scroll_offset) - .translate(&-scroll_node.reference_frame_relative_scroll_offset) - .translate(&-scroll_node.scroll_offset()); - - group.screen_bounding_rect = packed_layer.set_rect( - &local_viewport_rect, - screen_rect, - device_pixel_ratio, - ); - - group.coordinate_system_id = scroll_node.coordinate_system_id; - - debug!( - "\t\tlocal viewport {:?} screen bound {:?}", - local_viewport_rect, - group.screen_bounding_rect - ); - } - } - /// Compute the contribution (bounding rectangles, and resources) of layers and their /// primitives in screen space. fn build_layer_screen_rects_and_cull_layers( @@ -1635,12 +1489,6 @@ impl FrameBuilder { ) { profile_scope!("cull"); - self.recalculate_clip_scroll_groups( - clip_scroll_tree, - screen_rect, - device_pixel_ratio - ); - debug!("processing commands..."); let commands = mem::replace(&mut self.cmds, Vec::new()); for cmd in &commands { @@ -1993,19 +1841,11 @@ impl FrameBuilder { continue; } - let group_id = self.clip_scroll_group_indices[&clip_and_scroll]; - let group_index = ClipScrollGroupIndex(group_id, clip_and_scroll); - - if self.clip_scroll_group_store[group_id] - .screen_bounding_rect - .is_none() - { - debug!("\tcs-group {:?} screen rect is None", group_index); - continue; - } - debug!("\trun of {} items", prim_count); + let scroll_node = &clip_scroll_tree.nodes[&clip_and_scroll.scroll_node_id]; + let clip_node = &clip_scroll_tree.nodes[&clip_and_scroll.clip_node_id()]; + for i in 0 .. prim_count { let prim_index = PrimitiveIndex(first_prim_index.0 + i); @@ -2013,7 +1853,7 @@ impl FrameBuilder { self.prim_store .add_render_tasks_for_prim(prim_index, &mut current_task); let item = - AlphaRenderItem::Primitive(Some(group_index), prim_index, next_z); + AlphaRenderItem::Primitive(clip_node.id, scroll_node.id, prim_index, next_z); current_task.as_alpha_batch_mut().items.push(item); next_z += 1; } @@ -2058,14 +1898,16 @@ impl FrameBuilder { ), ); + let mut node_data = Vec::new(); + clip_scroll_tree.update_all_node_transforms( &screen_rect, device_pixel_ratio, - &mut self.packed_layers, &mut self.clip_store, resource_cache, gpu_cache, - pan + pan, + &mut node_data, ); self.update_scroll_bars(clip_scroll_tree, gpu_cache); @@ -2112,9 +1954,9 @@ impl FrameBuilder { let ctx = RenderTargetContext { device_pixel_ratio, stacking_context_store: &self.stacking_context_store, - clip_scroll_group_store: &self.clip_scroll_group_store, prim_store: &self.prim_store, resource_cache, + node_data: &node_data, }; pass.build( @@ -2146,7 +1988,7 @@ impl FrameBuilder { window_size: self.screen_size, profile_counters, passes, - layer_texture_data: self.packed_layers.clone(), + node_data, render_tasks, deferred_resolves, gpu_cache_updates: Some(gpu_cache_updates), diff --git a/webrender/src/gpu_types.rs b/webrender/src/gpu_types.rs index c2ef4c6457..185d188c41 100644 --- a/webrender/src/gpu_types.rs +++ b/webrender/src/gpu_types.rs @@ -2,22 +2,12 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use api::LayerRect; +use api::{LayerVector2D, LayerRect, LayerToWorldTransform, WorldToLayerTransform}; use gpu_cache::GpuCacheAddress; use render_task::RenderTaskAddress; -use tiling::PackedLayerIndex; // Contains type that must exactly match the same structures declared in GLSL. -#[derive(Debug, Copy, Clone)] -pub struct PackedLayerAddress(i32); - -impl From for PackedLayerAddress { - fn from(index: PackedLayerIndex) -> PackedLayerAddress { - PackedLayerAddress(index.0 as i32) - } -} - #[repr(i32)] #[derive(Debug, Copy, Clone)] pub enum BlurDirection { @@ -41,7 +31,7 @@ pub struct BlurInstance { #[repr(C)] pub struct ClipMaskInstance { pub render_task_address: RenderTaskAddress, - pub layer_address: PackedLayerAddress, + pub scroll_node_id: ClipScrollNodeIndex, pub segment: i32, pub clip_data_address: GpuCacheAddress, pub resource_address: GpuCacheAddress, @@ -57,7 +47,8 @@ pub struct SimplePrimitiveInstance { pub specific_prim_address: GpuCacheAddress, pub task_address: RenderTaskAddress, pub clip_task_address: RenderTaskAddress, - pub layer_address: PackedLayerAddress, + pub clip_id: ClipScrollNodeIndex, + pub scroll_id: ClipScrollNodeIndex, pub z_sort_index: i32, } @@ -66,14 +57,16 @@ impl SimplePrimitiveInstance { specific_prim_address: GpuCacheAddress, task_address: RenderTaskAddress, clip_task_address: RenderTaskAddress, - layer_address: PackedLayerAddress, + clip_id: ClipScrollNodeIndex, + scroll_id: ClipScrollNodeIndex, z_sort_index: i32, ) -> SimplePrimitiveInstance { SimplePrimitiveInstance { specific_prim_address, task_address, clip_task_address, - layer_address, + clip_id, + scroll_id, z_sort_index, } } @@ -84,7 +77,7 @@ impl SimplePrimitiveInstance { self.specific_prim_address.as_int(), self.task_address.0 as i32, self.clip_task_address.0 as i32, - self.layer_address.0, + ((self.clip_id.0 as i32) << 16) | self.scroll_id.0 as i32, self.z_sort_index, data0, data1, @@ -156,7 +149,8 @@ pub const BRUSH_FLAG_USES_PICTURE: i32 = (1 << 0); pub struct BrushInstance { pub picture_address: RenderTaskAddress, pub prim_address: GpuCacheAddress, - pub layer_address: PackedLayerAddress, + pub clip_id: ClipScrollNodeIndex, + pub scroll_id: ClipScrollNodeIndex, pub clip_task_address: RenderTaskAddress, pub z: i32, pub flags: i32, @@ -170,7 +164,7 @@ impl From for PrimitiveInstance { data: [ instance.picture_address.0 as i32, instance.prim_address.as_int(), - instance.layer_address.0, + ((instance.clip_id.0 as i32) << 16) | instance.scroll_id.0 as i32, instance.clip_task_address.0 as i32, instance.z, instance.flags, @@ -190,3 +184,29 @@ pub enum BrushImageKind { NinePatch = 1, // A nine-patch image (stretch inside segments) Mirror = 2, // A top left corner only (mirror across x/y axes) } + +#[derive(Copy, Debug, Clone)] +#[repr(C)] +pub struct ClipScrollNodeIndex(pub u32); + +#[derive(Debug)] +#[repr(C)] +pub struct ClipScrollNodeData { + pub transform: LayerToWorldTransform, + pub inv_transform: WorldToLayerTransform, + pub local_clip_rect: LayerRect, + pub reference_frame_relative_scroll_offset: LayerVector2D, + pub scroll_offset: LayerVector2D, +} + +impl ClipScrollNodeData { + pub fn invalid() -> ClipScrollNodeData { + ClipScrollNodeData { + transform: LayerToWorldTransform::identity(), + inv_transform: WorldToLayerTransform::identity(), + local_clip_rect: LayerRect::zero(), + reference_frame_relative_scroll_offset: LayerVector2D::zero(), + scroll_offset: LayerVector2D::zero(), + } + } +} diff --git a/webrender/src/prim_store.rs b/webrender/src/prim_store.rs index 7e0f04066d..43c5fcf431 100644 --- a/webrender/src/prim_store.rs +++ b/webrender/src/prim_store.rs @@ -18,7 +18,7 @@ use renderer::MAX_VERTEX_TEXTURE_WIDTH; use resource_cache::{ImageProperties, ResourceCache}; use std::{mem, usize}; use std::rc::Rc; -use util::{MatrixHelpers, pack_as_float, recycle_vec, TransformedRect}; +use util::{pack_as_float, recycle_vec, MatrixHelpers, TransformedRect, TransformedRectKind}; #[derive(Debug, Copy, Clone)] pub struct PrimitiveOpacity { @@ -1209,8 +1209,10 @@ impl PrimitiveStore { clip_store: &mut ClipStore, ) -> bool { let metadata = &mut self.cpu_metadata[prim_index.0]; + let transform = &prim_context.scroll_node.world_content_transform; + clip_store.get_mut(&metadata.clip_sources).update( - &prim_context.packed_layer.transform, + transform, gpu_cache, resource_cache, prim_context.device_pixel_ratio, @@ -1218,8 +1220,9 @@ impl PrimitiveStore { // Try to create a mask if we may need to. let prim_clips = clip_store.get(&metadata.clip_sources); - let is_axis_aligned = prim_context.packed_layer.transform.preserves_2d_axis_alignment(); - let clip_task = if prim_context.clip_chain.is_some() || prim_clips.is_masking() { + let is_axis_aligned = transform.transform_kind() == TransformedRectKind::AxisAligned; + + let clip_task = if prim_context.clip_node.clip_chain_node.is_some() || prim_clips.is_masking() { // Take into account the actual clip info of the primitive, and // mutate the current bounds accordingly. let mask_rect = match prim_clips.bounds.outer { @@ -1236,9 +1239,9 @@ impl PrimitiveStore { let extra_clip = if prim_clips.is_masking() { Some(Rc::new(ClipChainNode { work_item: ClipWorkItem { - layer_index: prim_context.packed_layer_index, + scroll_node_id: prim_context.scroll_node.id, clip_sources: metadata.clip_sources.weak(), - coordinate_system_id: prim_context.coordinate_system_id, + coordinate_system_id: prim_context.scroll_node.coordinate_system_id, }, prev: None, })) @@ -1249,12 +1252,12 @@ impl PrimitiveStore { RenderTask::new_mask( None, mask_rect, - prim_context.clip_chain.clone(), + prim_context.clip_node.clip_chain_node.clone(), extra_clip, prim_screen_rect, clip_store, is_axis_aligned, - prim_context.coordinate_system_id, + prim_context.scroll_node.coordinate_system_id, ) } else { None @@ -1284,14 +1287,13 @@ impl PrimitiveStore { } if !metadata.is_backface_visible && - prim_context.packed_layer.transform.is_backface_visible() { + prim_context.scroll_node.world_content_transform.is_backface_visible() { return None; } let local_rect = metadata .local_rect - .intersection(&metadata.local_clip_rect) - .and_then(|rect| rect.intersection(&prim_context.packed_layer.local_clip_rect)); + .intersection(&metadata.local_clip_rect); let local_rect = match local_rect { Some(local_rect) => local_rect, @@ -1300,13 +1302,13 @@ impl PrimitiveStore { let xf_rect = TransformedRect::new( &local_rect, - &prim_context.packed_layer.transform, + &prim_context.scroll_node.world_content_transform, prim_context.device_pixel_ratio ); - metadata.screen_rect = xf_rect - .bounding_rect - .intersection(&prim_context.clip_bounds); + let clip_bounds = &prim_context.clip_node.combined_clip_outer_bounds; + metadata.screen_rect = xf_rect.bounding_rect + .intersection(clip_bounds); let geometry = match metadata.screen_rect { Some(device_rect) => Geometry { diff --git a/webrender/src/render_task.rs b/webrender/src/render_task.rs index 340aa7bd8a..2aa82fea9b 100644 --- a/webrender/src/render_task.rs +++ b/webrender/src/render_task.rs @@ -8,11 +8,12 @@ use api::{LayerRect, PipelineId}; use clip::{ClipSource, ClipSourcesWeakHandle, ClipStore}; use clip_scroll_tree::CoordinateSystemId; use gpu_cache::GpuCacheHandle; +use gpu_types::{ClipScrollNodeIndex}; use internal_types::HardwareCompositeOp; use prim_store::PrimitiveIndex; use std::{cmp, usize, f32, i32}; use std::rc::Rc; -use tiling::{ClipScrollGroupIndex, PackedLayerIndex, RenderPass, RenderTargetIndex}; +use tiling::{RenderPass, RenderTargetIndex}; use tiling::{RenderTargetKind, StackingContextIndex}; const FLOATS_PER_RENDER_TASK_INFO: usize = 12; @@ -151,7 +152,7 @@ pub enum RenderTaskLocation { #[derive(Debug)] pub enum AlphaRenderItem { - Primitive(Option, PrimitiveIndex, i32), + Primitive(ClipScrollNodeIndex, ClipScrollNodeIndex, PrimitiveIndex, i32), Blend(StackingContextIndex, RenderTaskId, FilterOp, i32), Composite( StackingContextIndex, @@ -200,7 +201,7 @@ pub enum MaskGeometryKind { #[derive(Debug, Clone)] pub struct ClipWorkItem { - pub layer_index: PackedLayerIndex, + pub scroll_node_id: ClipScrollNodeIndex, pub clip_sources: ClipSourcesWeakHandle, pub coordinate_system_id: CoordinateSystemId, } diff --git a/webrender/src/renderer.rs b/webrender/src/renderer.rs index 7a58374923..8da5c39ff7 100644 --- a/webrender/src/renderer.rs +++ b/webrender/src/renderer.rs @@ -255,7 +255,7 @@ enum TextureSampler { CacheA8, CacheRGBA8, ResourceCache, - Layers, + ClipScrollNodes, RenderTasks, Dither, // A special sampler that is bound to the A8 output of @@ -286,7 +286,7 @@ impl Into for TextureSampler { TextureSampler::CacheA8 => TextureSlot(3), TextureSampler::CacheRGBA8 => TextureSlot(4), TextureSampler::ResourceCache => TextureSlot(5), - TextureSampler::Layers => TextureSlot(6), + TextureSampler::ClipScrollNodes => TextureSlot(6), TextureSampler::RenderTasks => TextureSlot(7), TextureSampler::Dither => TextureSlot(8), TextureSampler::SharedCacheA8 => TextureSlot(9), @@ -1126,7 +1126,7 @@ fn create_prim_shader( ("sDither", TextureSampler::Dither), ("sCacheA8", TextureSampler::CacheA8), ("sCacheRGBA8", TextureSampler::CacheRGBA8), - ("sLayers", TextureSampler::Layers), + ("sClipScrollNodes", TextureSampler::ClipScrollNodes), ("sRenderTasks", TextureSampler::RenderTasks), ("sResourceCache", TextureSampler::ResourceCache), ("sSharedCacheA8", TextureSampler::SharedCacheA8), @@ -1153,7 +1153,7 @@ fn create_clip_shader(name: &'static str, device: &mut Device) -> Result { + AlphaRenderItem::Primitive(clip_id, scroll_id, prim_index, z) => { let prim_metadata = ctx.prim_store.get_metadata(prim_index); - let (transform_kind, packed_layer_index) = match clip_scroll_group_index_opt { - Some(group_index) => { - let group = &ctx.clip_scroll_group_store[group_index.0]; - let bounding_rect = group.screen_bounding_rect.as_ref().unwrap(); - (bounding_rect.0, group.packed_layer_index) - } - None => (TransformedRectKind::AxisAligned, PackedLayerIndex(0)), - }; + let scroll_node = &ctx.node_data[scroll_id.0 as usize]; + // TODO(gw): Calculating this for every primitive is a bit + // wasteful. We should probably cache this in + // the scroll node... + let transform_kind = scroll_node.transform.transform_kind(); let item_bounding_rect = prim_metadata.screen_rect.as_ref().unwrap(); let prim_cache_address = gpu_cache.get_address(&prim_metadata.gpu_location); let no_textures = BatchTextures::no_texture(); @@ -423,7 +419,8 @@ impl AlphaRenderItem { prim_cache_address, task_address, clip_task_address, - packed_layer_index.into(), + clip_id, + scroll_id, z, ); @@ -631,7 +628,8 @@ impl AlphaRenderItem { let instance = BrushInstance { picture_address: task_address, prim_address: prim_cache_address, - layer_address: packed_layer_index.into(), + clip_id, + scroll_id, clip_task_address, z, flags: 0, @@ -864,7 +862,7 @@ impl ClipBatcher { for work_item in clips.iter() { let instance = ClipMaskInstance { render_task_address: task_address, - layer_address: work_item.layer_index.into(), + scroll_node_id: work_item.scroll_node_id, segment: 0, clip_data_address: GpuCacheAddress::invalid(), resource_address: GpuCacheAddress::invalid(), @@ -956,9 +954,9 @@ impl ClipBatcher { pub struct RenderTargetContext<'a> { pub device_pixel_ratio: f32, pub stacking_context_store: &'a [StackingContext], - pub clip_scroll_group_store: &'a [ClipScrollGroup], pub prim_store: &'a PrimitiveStore, pub resource_cache: &'a ResourceCache, + pub node_data: &'a [ClipScrollNodeData], } struct TextureAllocator { @@ -1228,7 +1226,8 @@ impl RenderTarget for ColorRenderTarget { sub_prim_address, task_index, RenderTaskAddress(0), - PackedLayerIndex(0).into(), + ClipScrollNodeIndex(0), + ClipScrollNodeIndex(0), 0, ); // z is disabled for rendering cache primitives @@ -1395,7 +1394,8 @@ impl RenderTarget for AlphaRenderTarget { // tasks support clip masks and // transform primitives, these // will need to be filled out! - layer_address: PackedLayerIndex(0).into(), + clip_id: ClipScrollNodeIndex(0), + scroll_id: ClipScrollNodeIndex(0), clip_task_address: RenderTaskAddress(0), z: 0, flags: BRUSH_FLAG_USES_PICTURE, @@ -1700,9 +1700,6 @@ impl OpaquePrimitiveBatch { } } -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)] -pub struct PackedLayerIndex(pub usize); - #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)] pub struct StackingContextIndex(pub usize); @@ -1808,73 +1805,6 @@ impl StackingContext { } } -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -pub struct ClipScrollGroupIndex(pub usize, pub ClipAndScrollInfo); - -#[derive(Debug)] -pub struct ClipScrollGroup { - pub scroll_node_id: ClipId, - pub clip_node_id: ClipId, - pub packed_layer_index: PackedLayerIndex, - pub screen_bounding_rect: Option<(TransformedRectKind, DeviceIntRect)>, - pub coordinate_system_id: CoordinateSystemId, -} - -impl ClipScrollGroup { - pub fn is_visible(&self) -> bool { - self.screen_bounding_rect.is_some() - } -} - -#[derive(Debug, Clone)] -#[repr(C)] -pub struct PackedLayer { - pub transform: LayerToWorldTransform, - pub inv_transform: WorldToLayerTransform, - pub local_clip_rect: LayerRect, -} - -impl PackedLayer { - pub fn empty() -> PackedLayer { - PackedLayer { - transform: LayerToWorldTransform::identity(), - inv_transform: WorldToLayerTransform::identity(), - local_clip_rect: LayerRect::zero(), - } - } - - pub fn set_transform(&mut self, transform: LayerToWorldTransform) -> bool { - self.transform = transform; - match self.transform.inverse() { - Some(inv) => { - self.inv_transform = inv; - true - } - None => false, - } - } - - pub fn set_rect( - &mut self, - local_rect: &LayerRect, - screen_rect: &DeviceIntRect, - device_pixel_ratio: f32, - ) -> Option<(TransformedRectKind, DeviceIntRect)> { - self.local_clip_rect = if self.transform.has_perspective_component() { - // Given a very large rect which means any rect would be inside this rect. - // That is, nothing would be clipped. - rect(f32::MIN / 2.0, f32::MIN / 2.0, f32::MAX, f32::MAX) - } else { - *local_rect - }; - let xf_rect = TransformedRect::new(local_rect, &self.transform, device_pixel_ratio); - xf_rect - .bounding_rect - .intersection(screen_rect) - .map(|rect| (xf_rect.kind, rect)) - } -} - #[derive(Debug, Clone, Default)] pub struct CompositeOps { // Requires only a single texture as input (e.g. most filters) @@ -1915,8 +1845,7 @@ pub struct Frame { pub passes: Vec, pub profile_counters: FrameProfileCounters, - pub layer_texture_data: Vec, - + pub node_data: Vec, pub render_tasks: RenderTaskTree, // List of updates that need to be pushed to the diff --git a/webrender/src/util.rs b/webrender/src/util.rs index 3bbcb2591b..714f474de5 100644 --- a/webrender/src/util.rs +++ b/webrender/src/util.rs @@ -22,6 +22,7 @@ pub trait MatrixHelpers { fn has_perspective_component(&self) -> bool; fn inverse_project(&self, target: &TypedPoint2D) -> Option>; fn inverse_rect_footprint(&self, rect: &TypedRect) -> TypedRect; + fn transform_kind(&self) -> TransformedRectKind; } impl MatrixHelpers for TypedTransform3D { @@ -98,6 +99,14 @@ impl MatrixHelpers for TypedTransform3D { .unwrap_or(TypedPoint2D::zero()), ]) } + + fn transform_kind(&self) -> TransformedRectKind { + if self.preserves_2d_axis_alignment() { + TransformedRectKind::AxisAligned + } else { + TransformedRectKind::Complex + } + } } pub trait RectHelpers