From 05e657ea9d0e64c46a4ce315c21fd7fd741965bc Mon Sep 17 00:00:00 2001 From: Glenn Watson Date: Wed, 5 Dec 2018 02:29:32 +1000 Subject: [PATCH 1/2] Store clip node templates in local space. This change makes clip item keys independent of the local space origin of the node. This ensures that even when Gecko sends a new display list with clip nodes that have different scroll offsets the interning logic results in the same uid for the clip node, avoiding unnecessary invalidations of cached picture tiles. --- webrender/res/clip_shared.glsl | 6 + webrender/res/cs_clip_box_shadow.glsl | 17 +- webrender/res/cs_clip_image.glsl | 13 +- webrender/res/cs_clip_rectangle.glsl | 2 + webrender/src/batch.rs | 27 +- webrender/src/border.rs | 20 +- webrender/src/box_shadow.rs | 76 +++- webrender/src/clip.rs | 395 ++++++++++-------- webrender/src/display_list_flattener.rs | 19 +- webrender/src/gpu_types.rs | 4 +- webrender/src/hit_test.rs | 21 +- webrender/src/prim_store.rs | 57 ++- webrender/src/render_task.rs | 6 +- webrender/src/renderer.rs | 10 + webrender/src/tiling.rs | 1 + .../boxshadow/box-shadow-huge-radius.png | Bin 16745 -> 16127 bytes .../box-shadow-large-blur-radius-3.png | Bin 63886 -> 63665 bytes 17 files changed, 415 insertions(+), 259 deletions(-) diff --git a/webrender/res/clip_shared.glsl b/webrender/res/clip_shared.glsl index 05074295c6..8fd0afd42c 100644 --- a/webrender/res/clip_shared.glsl +++ b/webrender/res/clip_shared.glsl @@ -17,6 +17,8 @@ in int aClipTransformId; in int aPrimTransformId; in int aClipSegment; in ivec4 aClipDataResourceAddress; +in vec2 aClipLocalPos; +in vec4 aClipTileRect; struct ClipMaskInstance { int render_task_address; @@ -25,6 +27,8 @@ struct ClipMaskInstance { int segment; ivec2 clip_data_address; ivec2 resource_address; + vec2 local_pos; + RectWithSize tile_rect; }; ClipMaskInstance fetch_clip_item() { @@ -36,6 +40,8 @@ ClipMaskInstance fetch_clip_item() { cmi.segment = aClipSegment; cmi.clip_data_address = aClipDataResourceAddress.xy; cmi.resource_address = aClipDataResourceAddress.zw; + cmi.local_pos = aClipLocalPos; + cmi.tile_rect = RectWithSize(aClipTileRect.xy, aClipTileRect.zw); return cmi; } diff --git a/webrender/res/cs_clip_box_shadow.glsl b/webrender/res/cs_clip_box_shadow.glsl index 4419241313..c8c98f7147 100644 --- a/webrender/res/cs_clip_box_shadow.glsl +++ b/webrender/res/cs_clip_box_shadow.glsl @@ -46,8 +46,11 @@ void main(void) { BoxShadowData bs_data = fetch_data(cmi.clip_data_address); ImageResource res = fetch_image_resource_direct(cmi.resource_address); + RectWithSize dest_rect = bs_data.dest_rect; + dest_rect.p0 += cmi.local_pos; + ClipVertexInfo vi = write_clip_tile_vertex( - bs_data.dest_rect, + dest_rect, prim_transform, clip_transform, area @@ -65,14 +68,14 @@ void main(void) { switch (bs_data.stretch_mode_x) { case MODE_STRETCH: { vEdge.x = 0.5; - vEdge.z = (bs_data.dest_rect.size.x / bs_data.src_rect_size.x) - 0.5; - vUv.x = (local_pos.x - bs_data.dest_rect.p0.x) / bs_data.src_rect_size.x; + vEdge.z = (dest_rect.size.x / bs_data.src_rect_size.x) - 0.5; + vUv.x = (local_pos.x - dest_rect.p0.x) / bs_data.src_rect_size.x; break; } case MODE_SIMPLE: default: { vEdge.xz = vec2(1.0); - vUv.x = (local_pos.x - bs_data.dest_rect.p0.x) / bs_data.dest_rect.size.x; + vUv.x = (local_pos.x - dest_rect.p0.x) / dest_rect.size.x; break; } } @@ -80,14 +83,14 @@ void main(void) { switch (bs_data.stretch_mode_y) { case MODE_STRETCH: { vEdge.y = 0.5; - vEdge.w = (bs_data.dest_rect.size.y / bs_data.src_rect_size.y) - 0.5; - vUv.y = (local_pos.y - bs_data.dest_rect.p0.y) / bs_data.src_rect_size.y; + vEdge.w = (dest_rect.size.y / bs_data.src_rect_size.y) - 0.5; + vUv.y = (local_pos.y - dest_rect.p0.y) / bs_data.src_rect_size.y; break; } case MODE_SIMPLE: default: { vEdge.yw = vec2(1.0); - vUv.y = (local_pos.y - bs_data.dest_rect.p0.y) / bs_data.dest_rect.size.y; + vUv.y = (local_pos.y - dest_rect.p0.y) / dest_rect.size.y; break; } } diff --git a/webrender/res/cs_clip_image.glsl b/webrender/res/cs_clip_image.glsl index a150344fbd..30640d4504 100644 --- a/webrender/res/cs_clip_image.glsl +++ b/webrender/res/cs_clip_image.glsl @@ -13,15 +13,12 @@ flat varying float vLayer; #ifdef WR_VERTEX_SHADER struct ImageMaskData { - RectWithSize local_mask_rect; - RectWithSize local_tile_rect; + vec2 local_mask_size; }; ImageMaskData fetch_mask_data(ivec2 address) { - vec4 data[2] = fetch_from_gpu_cache_2_direct(address); - RectWithSize mask_rect = RectWithSize(data[0].xy, data[0].zw); - RectWithSize tile_rect = RectWithSize(data[1].xy, data[1].zw); - ImageMaskData mask_data = ImageMaskData(mask_rect, tile_rect); + vec4 data = fetch_from_gpu_cache_1_direct(address); + ImageMaskData mask_data = ImageMaskData(data.xy); return mask_data; } @@ -31,7 +28,7 @@ void main(void) { Transform clip_transform = fetch_transform(cmi.clip_transform_id); Transform prim_transform = fetch_transform(cmi.prim_transform_id); ImageMaskData mask = fetch_mask_data(cmi.clip_data_address); - RectWithSize local_rect = mask.local_mask_rect; + RectWithSize local_rect = RectWithSize(cmi.local_pos, mask.local_mask_size); ImageResource res = fetch_image_resource_direct(cmi.resource_address); ClipVertexInfo vi = write_clip_tile_vertex( @@ -42,7 +39,7 @@ void main(void) { ); vLocalPos = vi.local_pos.xy / vi.local_pos.z; vLayer = res.layer; - vClipMaskImageUv = (vLocalPos - mask.local_tile_rect.p0) / mask.local_tile_rect.size; + vClipMaskImageUv = (vLocalPos - cmi.tile_rect.p0) / cmi.tile_rect.size; vec2 texture_size = vec2(textureSize(sColor0, 0)); vClipMaskUvRect = vec4(res.uv_rect.p0, res.uv_rect.p1 - res.uv_rect.p0) / texture_size.xyxy; // applying a half-texel offset to the UV boundaries to prevent linear samples from the outside diff --git a/webrender/res/cs_clip_rectangle.glsl b/webrender/res/cs_clip_rectangle.glsl index 3918c86346..468c5f353d 100644 --- a/webrender/res/cs_clip_rectangle.glsl +++ b/webrender/res/cs_clip_rectangle.glsl @@ -63,7 +63,9 @@ void main(void) { Transform clip_transform = fetch_transform(cmi.clip_transform_id); Transform prim_transform = fetch_transform(cmi.prim_transform_id); ClipData clip = fetch_clip(cmi.clip_data_address); + RectWithSize local_rect = clip.rect.rect; + local_rect.p0 = cmi.local_pos; ClipVertexInfo vi = write_clip_tile_vertex( local_rect, diff --git a/webrender/src/batch.rs b/webrender/src/batch.rs index aae0cf8a65..867eb13a92 100644 --- a/webrender/src/batch.rs +++ b/webrender/src/batch.rs @@ -2442,6 +2442,7 @@ impl ClipBatcher { &mut self, task_address: RenderTaskAddress, clip_data_address: GpuCacheAddress, + local_pos: LayoutPoint, ) { let instance = ClipMaskInstance { render_task_address: task_address, @@ -2450,6 +2451,8 @@ impl ClipBatcher { segment: 0, clip_data_address, resource_address: GpuCacheAddress::invalid(), + local_pos, + tile_rect: LayoutRect::zero(), }; self.rectangles.push(instance); @@ -2490,21 +2493,27 @@ impl ClipBatcher { segment: 0, clip_data_address: GpuCacheAddress::invalid(), resource_address: GpuCacheAddress::invalid(), + local_pos: clip_instance.local_pos, + tile_rect: LayoutRect::zero(), }; match clip_node.item { - ClipItem::Image { ref mask, ref visible_tiles } => { + ClipItem::Image { image, size, .. } => { let request = ImageRequest { - key: mask.image, + key: image, rendering: ImageRendering::Auto, tile: None, }; - let mut add_image = |request: ImageRequest, clip_data_address: GpuCacheAddress| { + + let clip_data_address = + gpu_cache.get_address(&clip_node.gpu_cache_handle); + + let mut add_image = |request: ImageRequest, local_tile_rect: LayoutRect| { let cache_item = match resource_cache.get_cached_image(request) { Ok(item) => item, Err(..) => { warn!("Warnings: skip a image mask"); - debug!("Mask: {:?}, request: {:?}", mask, request); + debug!("request: {:?}", request); return; } }; @@ -2514,23 +2523,23 @@ impl ClipBatcher { .push(ClipMaskInstance { clip_data_address, resource_address: gpu_cache.get_address(&cache_item.uv_rect_handle), + tile_rect: local_tile_rect, ..instance }); }; - match *visible_tiles { + match clip_instance.visible_tiles { Some(ref tiles) => { for tile in tiles { add_image( request.with_tile(tile.tile_offset), - gpu_cache.get_address(&tile.handle), + tile.tile_rect, ) } } None => { - let gpu_address = - gpu_cache.get_address(&clip_node.gpu_cache_handle); - add_image(request, gpu_address) + let mask_rect = LayoutRect::new(clip_instance.local_pos, size); + add_image(request, mask_rect) } } } diff --git a/webrender/src/border.rs b/webrender/src/border.rs index c22a428f6f..b575122de6 100644 --- a/webrender/src/border.rs +++ b/webrender/src/border.rs @@ -171,7 +171,7 @@ pub struct BorderSegmentCacheKey { pub fn ensure_no_corner_overlap( radius: &mut BorderRadius, - rect: &LayoutRect, + size: LayoutSize, ) { let mut ratio = 1.0; let top_left_radius = &mut radius.top_left; @@ -180,23 +180,23 @@ pub fn ensure_no_corner_overlap( let bottom_left_radius = &mut radius.bottom_left; let sum = top_left_radius.width + top_right_radius.width; - if rect.size.width < sum { - ratio = f32::min(ratio, rect.size.width / sum); + if size.width < sum { + ratio = f32::min(ratio, size.width / sum); } let sum = bottom_left_radius.width + bottom_right_radius.width; - if rect.size.width < sum { - ratio = f32::min(ratio, rect.size.width / sum); + if size.width < sum { + ratio = f32::min(ratio, size.width / sum); } let sum = top_left_radius.height + bottom_left_radius.height; - if rect.size.height < sum { - ratio = f32::min(ratio, rect.size.height / sum); + if size.height < sum { + ratio = f32::min(ratio, size.height / sum); } let sum = top_right_radius.height + bottom_right_radius.height; - if rect.size.height < sum { - ratio = f32::min(ratio, rect.size.height / sum); + if size.height < sum { + ratio = f32::min(ratio, size.height / sum); } if ratio < 1. { @@ -223,7 +223,7 @@ impl<'a> DisplayListFlattener<'a> { clip_and_scroll: ScrollNodeAndClipChain, ) { let mut border = *border; - ensure_no_corner_overlap(&mut border.radius, &info.rect); + ensure_no_corner_overlap(&mut border.radius, info.rect.size); self.add_primitive( clip_and_scroll, diff --git a/webrender/src/box_shadow.rs b/webrender/src/box_shadow.rs index eaaa4fd71b..f14a526423 100644 --- a/webrender/src/box_shadow.rs +++ b/webrender/src/box_shadow.rs @@ -117,32 +117,47 @@ impl<'a> DisplayListFlattener<'a> { } // TODO(gw): Add a fast path for ClipOut + zero border radius! - clips.push(ClipItemKey::rounded_rect( - prim_info.rect, - border_radius, - ClipMode::ClipOut, - )); + clips.push( + ( + prim_info.rect.origin, + ClipItemKey::rounded_rect( + prim_info.rect.size, + border_radius, + ClipMode::ClipOut, + ), + ) + ); (shadow_rect, shadow_radius) } BoxShadowClipMode::Inset => { if shadow_rect.is_well_formed_and_nonempty() { - clips.push(ClipItemKey::rounded_rect( - shadow_rect, - shadow_radius, - ClipMode::ClipOut, - )); + clips.push( + ( + shadow_rect.origin, + ClipItemKey::rounded_rect( + shadow_rect.size, + shadow_radius, + ClipMode::ClipOut, + ), + ) + ); } (prim_info.rect, border_radius) } }; - clips.push(ClipItemKey::rounded_rect( - final_prim_rect, - clip_radius, - ClipMode::Clip, - )); + clips.push( + ( + final_prim_rect.origin, + ClipItemKey::rounded_rect( + final_prim_rect.size, + clip_radius, + ClipMode::Clip, + ), + ) + ); self.add_primitive( clip_and_scroll, @@ -159,11 +174,16 @@ impl<'a> DisplayListFlattener<'a> { // Add a normal clip mask to clip out the contents // of the surrounding primitive. - extra_clips.push(ClipItemKey::rounded_rect( - prim_info.rect, - border_radius, - prim_clip_mode, - )); + extra_clips.push( + ( + prim_info.rect.origin, + ClipItemKey::rounded_rect( + prim_info.rect.size, + border_radius, + prim_clip_mode, + ), + ) + ); // Get the local rect of where the shadow will be drawn, // expanded to include room for the blurred region. @@ -179,7 +199,7 @@ impl<'a> DisplayListFlattener<'a> { let shadow_clip_source = ClipItemKey::box_shadow( shadow_rect, shadow_radius, - dest_rect, + dest_rect.translate(&LayoutVector2D::new(-prim_info.rect.origin.x, -prim_info.rect.origin.y)), blur_radius, clip_mode, ); @@ -192,7 +212,12 @@ impl<'a> DisplayListFlattener<'a> { } // Add the box-shadow clip source. - extra_clips.push(shadow_clip_source); + extra_clips.push( + ( + prim_info.rect.origin, + shadow_clip_source, + ), + ); // Outset shadows are expanded by the shadow // region from the original primitive. @@ -212,7 +237,12 @@ impl<'a> DisplayListFlattener<'a> { // inset shadow rect becomes invalid (they will // just look like a solid rectangle). if shadow_rect.is_well_formed_and_nonempty() { - extra_clips.push(shadow_clip_source); + extra_clips.push( + ( + prim_info.rect.origin, + shadow_clip_source, + ), + ); } // Inset shadows draw inside the original primitive. diff --git a/webrender/src/clip.rs b/webrender/src/clip.rs index c5b8041ad6..2f3a4ae592 100644 --- a/webrender/src/clip.rs +++ b/webrender/src/clip.rs @@ -6,7 +6,7 @@ use api::{BorderRadius, ClipMode, ComplexClipRegion, DeviceIntRect, DevicePixelS use api::{ImageRendering, LayoutRect, LayoutSize, LayoutPoint, LayoutVector2D}; use api::{BoxShadowClipMode, LayoutToWorldScale, PicturePixel, WorldPixel}; use api::{PictureRect, LayoutPixel, WorldPoint, WorldSize, WorldRect, LayoutToWorldTransform}; -use api::{VoidPtrToSizeFn, LayoutRectAu, ImageKey, AuHelpers}; +use api::{VoidPtrToSizeFn, ImageKey}; use app_units::Au; use border::{ensure_no_corner_overlap, BorderRadiusAu}; use box_shadow::{BLUR_SAMPLE_SCALE, BoxShadowClipSource, BoxShadowCacheKey}; @@ -18,6 +18,7 @@ use image::{self, Repetition}; use intern; use internal_types::FastHashSet; use prim_store::{ClipData, ImageMaskData, SpaceMapper, VisibleMaskImageTile}; +use prim_store::{PointKey, SizeKey, RectangleKey}; use render_task::to_cache_size; use resource_cache::{ImageRequest, ResourceCache}; use std::{cmp, u32}; @@ -136,31 +137,29 @@ pub struct ClipNode { impl From for ClipNode { fn from(item: ClipItemKey) -> Self { let item = match item { - ClipItemKey::Rectangle(rect, mode) => { - ClipItem::Rectangle(LayoutRect::from_au(rect), mode) + ClipItemKey::Rectangle(size, mode) => { + ClipItem::Rectangle(size.into(), mode) } - ClipItemKey::RoundedRectangle(rect, radius, mode) => { + ClipItemKey::RoundedRectangle(size, radius, mode) => { ClipItem::RoundedRectangle( - LayoutRect::from_au(rect), + size.into(), radius.into(), mode, ) } - ClipItemKey::ImageMask(rect, image, repeat) => { + ClipItemKey::ImageMask(size, image, repeat) => { ClipItem::Image { - mask: ImageMask { - image, - rect: LayoutRect::from_au(rect), - repeat, - }, - visible_tiles: None, + image, + size: size.into(), + repeat, } } - ClipItemKey::BoxShadow(shadow_rect, shadow_radius, prim_shadow_rect, blur_radius, clip_mode) => { + ClipItemKey::BoxShadow(shadow_rect_fract_offset, shadow_rect_size, shadow_radius, prim_shadow_rect, blur_radius, clip_mode) => { ClipItem::new_box_shadow( - LayoutRect::from_au(shadow_rect), + shadow_rect_fract_offset.into(), + shadow_rect_size.into(), shadow_radius.into(), - LayoutRect::from_au(prim_shadow_rect), + prim_shadow_rect.into(), blur_radius.to_f32_px(), clip_mode, ) @@ -203,6 +202,7 @@ impl ClipChainId { #[derive(Clone)] pub struct ClipChainNode { pub handle: ClipDataHandle, + pub local_pos: LayoutPoint, pub spatial_node_index: SpatialNodeIndex, pub parent_clip_chain_id: ClipChainId, } @@ -219,13 +219,16 @@ pub struct ClipNodeIndex(pub u32); // an index to the node data itself, as well as // some flags describing how this clip node instance // is positioned. -#[derive(Clone, Copy, Debug)] +#[derive(Debug)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct ClipNodeInstance { pub handle: ClipDataHandle, pub flags: ClipNodeFlags, pub spatial_node_index: SpatialNodeIndex, + pub local_pos: LayoutPoint, + + pub visible_tiles: Option>, } // A range of clip node instances that were found by @@ -255,84 +258,111 @@ enum ClipSpaceConversion { struct ClipNodeInfo { conversion: ClipSpaceConversion, handle: ClipDataHandle, + local_pos: LayoutPoint, spatial_node_index: SpatialNodeIndex, } -impl ClipNode { - pub fn update( - &mut self, +impl ClipNodeInfo { + fn create_instance( + &self, + node: &ClipNode, + clipped_rect: &LayoutRect, gpu_cache: &mut GpuCache, resource_cache: &mut ResourceCache, - device_pixel_scale: DevicePixelScale, - clipped_rect: &LayoutRect, - ) { - match self.item { - ClipItem::Image { ref mask, ref mut visible_tiles } => { - let request = ImageRequest { - key: mask.image, - rendering: ImageRendering::Auto, - tile: None, - }; - *visible_tiles = None; - if let Some(props) = resource_cache.get_image_properties(mask.image) { - if let Some(tile_size) = props.tiling { - let mut mask_tiles = Vec::new(); - - let device_image_size = props.descriptor.size; - let visible_rect = if mask.repeat { - *clipped_rect - } else { - clipped_rect.intersection(&mask.rect).unwrap() - }; + ) -> ClipNodeInstance { + // Calculate some flags that are required for the segment + // building logic. + let flags = match self.conversion { + ClipSpaceConversion::Local => { + ClipNodeFlags::SAME_SPATIAL_NODE | ClipNodeFlags::SAME_COORD_SYSTEM + } + ClipSpaceConversion::ScaleOffset(..) => { + ClipNodeFlags::SAME_COORD_SYSTEM + } + ClipSpaceConversion::Transform(..) => { + ClipNodeFlags::empty() + } + }; + + let mut visible_tiles = None; + + if let ClipItem::Image { size, image, repeat } = node.item { + let request = ImageRequest { + key: image, + rendering: ImageRendering::Auto, + tile: None, + }; + + if let Some(props) = resource_cache.get_image_properties(image) { + if let Some(tile_size) = props.tiling { + let mut mask_tiles = Vec::new(); + let mask_rect = LayoutRect::new(self.local_pos, size); + + let device_image_size = props.descriptor.size; + let visible_rect = if repeat { + *clipped_rect + } else { + clipped_rect.intersection(&mask_rect).unwrap() + }; - let repetitions = image::repetitions( - &mask.rect, + let repetitions = image::repetitions( + &mask_rect, + &visible_rect, + size, + ); + + for Repetition { origin, .. } in repetitions { + let image_rect = LayoutRect { + origin, + size, + }; + let tiles = image::tiles( + &image_rect, &visible_rect, - mask.rect.size, + &device_image_size, + tile_size as i32, ); - - for Repetition { origin, .. } in repetitions { - let image_rect = LayoutRect { - origin, - size: mask.rect.size, - }; - let tiles = image::tiles( - &image_rect, - &visible_rect, - &device_image_size, - tile_size as i32, + for tile in tiles { + resource_cache.request_image( + request.with_tile(tile.offset), + gpu_cache, ); - for tile in tiles { - resource_cache.request_image( - request.with_tile(tile.offset), - gpu_cache, - ); - let mut handle = GpuCacheHandle::new(); - if let Some(request) = gpu_cache.request(&mut handle) { - let data = ImageMaskData { - local_mask_rect: mask.rect, - local_tile_rect: tile.rect, - }; - data.write_gpu_blocks(request); - } - - mask_tiles.push(VisibleMaskImageTile { - tile_offset: tile.offset, - handle, - }); - } + mask_tiles.push(VisibleMaskImageTile { + tile_offset: tile.offset, + tile_rect: tile.rect, + }); } - *visible_tiles = Some(mask_tiles); - } else { - if let Some(request) = gpu_cache.request(&mut self.gpu_cache_handle) { - let data = ImageMaskData { - local_mask_rect: mask.rect, - local_tile_rect: mask.rect, - }; - data.write_gpu_blocks(request); - } - resource_cache.request_image(request, gpu_cache); } + visible_tiles = Some(mask_tiles); + } else { + resource_cache.request_image(request, gpu_cache); + } + } + } + + ClipNodeInstance { + handle: self.handle, + flags, + spatial_node_index: self.spatial_node_index, + local_pos: self.local_pos, + visible_tiles, + } + } +} + +impl ClipNode { + pub fn update( + &mut self, + gpu_cache: &mut GpuCache, + device_pixel_scale: DevicePixelScale, + ) { + match self.item { + ClipItem::Image { size, .. } => { + if let Some(request) = gpu_cache.request(&mut self.gpu_cache_handle) { + let data = ImageMaskData { + local_mask_size: size, + }; + data.write_gpu_blocks(request); } } ClipItem::BoxShadow(ref mut info) => { @@ -376,7 +406,7 @@ impl ClipNode { if let Some(mut request) = gpu_cache.request(&mut info.clip_data_handle) { let data = ClipData::rounded_rect( - &info.minimal_shadow_rect, + info.minimal_shadow_rect.size, &info.shadow_radius, ClipMode::Clip, ); @@ -384,15 +414,15 @@ impl ClipNode { data.write(&mut request); } } - ClipItem::Rectangle(rect, mode) => { + ClipItem::Rectangle(size, mode) => { if let Some(mut request) = gpu_cache.request(&mut self.gpu_cache_handle) { - let data = ClipData::uniform(rect, 0.0, mode); + let data = ClipData::uniform(size, 0.0, mode); data.write(&mut request); } } - ClipItem::RoundedRectangle(ref rect, ref radius, mode) => { + ClipItem::RoundedRectangle(size, ref radius, mode) => { if let Some(mut request) = gpu_cache.request(&mut self.gpu_cache_handle) { - let data = ClipData::rounded_rect(rect, radius, mode); + let data = ClipData::rounded_rect(size, radius, mode); data.write(&mut request); } } @@ -442,6 +472,7 @@ impl ClipStore { pub fn add_clip_chain_node( &mut self, handle: ClipDataHandle, + local_pos: LayoutPoint, spatial_node_index: SpatialNodeIndex, parent_clip_chain_id: ClipChainId, ) -> ClipChainId { @@ -449,6 +480,7 @@ impl ClipStore { self.clip_chain_nodes.push(ClipChainNode { handle, spatial_node_index, + local_pos, parent_clip_chain_id, }); id @@ -523,6 +555,7 @@ impl ClipStore { if !add_clip_node_to_current_chain( clip_chain_node.handle, clip_chain_node.spatial_node_index, + clip_chain_node.local_pos, spatial_node_index, &mut local_clip_rect, &mut self.clip_node_info, @@ -541,14 +574,15 @@ impl ClipStore { // handled as part of this rasterization root. if let Some(clip_node_collector) = clip_node_collector { for clip_chain_id in &clip_node_collector.clips { - let (handle, clip_spatial_node_index) = { + let (handle, clip_spatial_node_index, local_pos) = { let clip_chain_node = &self.clip_chain_nodes[clip_chain_id.0 as usize]; - (clip_chain_node.handle, clip_chain_node.spatial_node_index) + (clip_chain_node.handle, clip_chain_node.spatial_node_index, clip_chain_node.local_pos) }; if !add_clip_node_to_current_chain( handle, clip_spatial_node_index, + local_pos, spatial_node_index, &mut local_clip_rect, &mut self.clip_node_info, @@ -580,15 +614,16 @@ impl ClipStore { // See how this clip affects the prim region. let clip_result = match node_info.conversion { ClipSpaceConversion::Local => { - node.item.get_clip_result(&local_bounding_rect) + node.item.get_clip_result(node_info.local_pos, &local_bounding_rect) } ClipSpaceConversion::ScaleOffset(ref scale_offset) => { has_non_local_clips = true; - node.item.get_clip_result(&scale_offset.unmap_rect(&local_bounding_rect)) + node.item.get_clip_result(node_info.local_pos, &scale_offset.unmap_rect(&local_bounding_rect)) } ClipSpaceConversion::Transform(ref transform) => { has_non_local_clips = true; node.item.get_clip_result_complex( + node_info.local_pos, transform, &world_clip_rect, world_rect, @@ -610,24 +645,16 @@ impl ClipStore { // TODO(gw): Ensure this only runs once on each node per frame? node.update( gpu_cache, - resource_cache, device_pixel_scale, - &local_bounding_rect, ); - // Calculate some flags that are required for the segment - // building logic. - let flags = match node_info.conversion { - ClipSpaceConversion::Local => { - ClipNodeFlags::SAME_SPATIAL_NODE | ClipNodeFlags::SAME_COORD_SYSTEM - } - ClipSpaceConversion::ScaleOffset(..) => { - ClipNodeFlags::SAME_COORD_SYSTEM - } - ClipSpaceConversion::Transform(..) => { - ClipNodeFlags::empty() - } - }; + // Create the clip node instance for this clip node + let instance = node_info.create_instance( + node, + &local_bounding_rect, + gpu_cache, + resource_cache, + ); // As a special case, a partial accept of a clip rect that is // in the same coordinate system as the primitive doesn't need @@ -644,16 +671,11 @@ impl ClipStore { } ClipItem::Rectangle(_, ClipMode::Clip) => { - !flags.contains(ClipNodeFlags::SAME_COORD_SYSTEM) + !instance.flags.contains(ClipNodeFlags::SAME_COORD_SYSTEM) } }; // Store this in the index buffer for this clip chain instance. - let instance = ClipNodeInstance { - handle: node_info.handle, - flags, - spatial_node_index: node_info.spatial_node_index, - }; self.clip_node_instances.push(instance); } } @@ -815,24 +837,24 @@ pub struct ClipItemSceneData { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub enum ClipItemKey { - Rectangle(LayoutRectAu, ClipMode), - RoundedRectangle(LayoutRectAu, BorderRadiusAu, ClipMode), - ImageMask(LayoutRectAu, ImageKey, bool), - BoxShadow(LayoutRectAu, BorderRadiusAu, LayoutRectAu, Au, BoxShadowClipMode), + Rectangle(SizeKey, ClipMode), + RoundedRectangle(SizeKey, BorderRadiusAu, ClipMode), + ImageMask(SizeKey, ImageKey, bool), + BoxShadow(PointKey, SizeKey, BorderRadiusAu, RectangleKey, Au, BoxShadowClipMode), } impl ClipItemKey { - pub fn rectangle(rect: LayoutRect, mode: ClipMode) -> Self { - ClipItemKey::Rectangle(rect.to_au(), mode) + pub fn rectangle(size: LayoutSize, mode: ClipMode) -> Self { + ClipItemKey::Rectangle(size.into(), mode) } - pub fn rounded_rect(rect: LayoutRect, mut radii: BorderRadius, mode: ClipMode) -> Self { + pub fn rounded_rect(size: LayoutSize, mut radii: BorderRadius, mode: ClipMode) -> Self { if radii.is_zero() { - ClipItemKey::rectangle(rect, mode) + ClipItemKey::rectangle(size, mode) } else { - ensure_no_corner_overlap(&mut radii, &rect); + ensure_no_corner_overlap(&mut radii, size); ClipItemKey::RoundedRectangle( - rect.to_au(), + size.into(), radii.into(), mode, ) @@ -841,7 +863,7 @@ impl ClipItemKey { pub fn image_mask(image_mask: &ImageMask) -> Self { ClipItemKey::ImageMask( - image_mask.rect.to_au(), + image_mask.rect.size.into(), image_mask.image, image_mask.repeat, ) @@ -854,10 +876,18 @@ impl ClipItemKey { blur_radius: f32, clip_mode: BoxShadowClipMode, ) -> Self { + // Get the fractional offsets required to match the + // source rect with a minimal rect. + let fract_offset = LayoutPoint::new( + shadow_rect.origin.x.fract().abs(), + shadow_rect.origin.y.fract().abs(), + ); + ClipItemKey::BoxShadow( - shadow_rect.to_au(), + fract_offset.into(), + shadow_rect.size.into(), shadow_radius.into(), - prim_shadow_rect.to_au(), + prim_shadow_rect.into(), Au::from_f32_px(blur_radius), clip_mode, ) @@ -868,31 +898,30 @@ impl ClipItemKey { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub enum ClipItem { - Rectangle(LayoutRect, ClipMode), - RoundedRectangle(LayoutRect, BorderRadius, ClipMode), - Image { mask: ImageMask, visible_tiles: Option> }, + Rectangle(LayoutSize, ClipMode), + RoundedRectangle(LayoutSize, BorderRadius, ClipMode), + Image { + image: ImageKey, + size: LayoutSize, + repeat: bool, + }, BoxShadow(BoxShadowClipSource), } fn compute_box_shadow_parameters( - shadow_rect: LayoutRect, + shadow_rect_fract_offset: LayoutPoint, + shadow_rect_size: LayoutSize, mut shadow_radius: BorderRadius, prim_shadow_rect: LayoutRect, blur_radius: f32, clip_mode: BoxShadowClipMode, ) -> BoxShadowClipSource { // Make sure corners don't overlap. - ensure_no_corner_overlap(&mut shadow_radius, &shadow_rect); + ensure_no_corner_overlap(&mut shadow_radius, shadow_rect_size); - // Get the fractional offsets required to match the - // source rect with a minimal rect. - let fract_offset = LayoutPoint::new( - shadow_rect.origin.x.fract().abs(), - shadow_rect.origin.y.fract().abs(), - ); let fract_size = LayoutSize::new( - shadow_rect.size.width.fract().abs(), - shadow_rect.size.height.fract().abs(), + shadow_rect_size.width.fract().abs(), + shadow_rect_size.height.fract().abs(), ); // Create a minimal size primitive mask to blur. In this @@ -925,8 +954,8 @@ fn compute_box_shadow_parameters( // The minimal rect to blur. let mut minimal_shadow_rect = LayoutRect::new( LayoutPoint::new( - blur_region + fract_offset.x, - blur_region + fract_offset.y, + blur_region + shadow_rect_fract_offset.x, + blur_region + shadow_rect_fract_offset.y, ), LayoutSize::new( min_shadow_rect_size.width + fract_size.width, @@ -940,14 +969,14 @@ fn compute_box_shadow_parameters( // correctness, since the blur of one corner may affect the blur // in another corner. let mut stretch_mode_x = BoxShadowStretchMode::Stretch; - if shadow_rect.size.width < minimal_shadow_rect.size.width { - minimal_shadow_rect.size.width = shadow_rect.size.width; + if shadow_rect_size.width < minimal_shadow_rect.size.width { + minimal_shadow_rect.size.width = shadow_rect_size.width; stretch_mode_x = BoxShadowStretchMode::Simple; } let mut stretch_mode_y = BoxShadowStretchMode::Stretch; - if shadow_rect.size.height < minimal_shadow_rect.size.height { - minimal_shadow_rect.size.height = shadow_rect.size.height; + if shadow_rect_size.height < minimal_shadow_rect.size.height { + minimal_shadow_rect.size.height = shadow_rect_size.height; stretch_mode_y = BoxShadowStretchMode::Simple; } @@ -975,14 +1004,16 @@ fn compute_box_shadow_parameters( impl ClipItem { pub fn new_box_shadow( - shadow_rect: LayoutRect, + shadow_rect_fract_offset: LayoutPoint, + shadow_rect_size: LayoutSize, mut shadow_radius: BorderRadius, prim_shadow_rect: LayoutRect, blur_radius: f32, clip_mode: BoxShadowClipMode, ) -> Self { let mut source = compute_box_shadow_parameters( - shadow_rect, + shadow_rect_fract_offset, + shadow_rect_size, shadow_radius, prim_shadow_rect, blur_radius, @@ -1019,8 +1050,10 @@ impl ClipItem { shadow_radius.top_right.width *= downscale; let original_alloc_size = source.shadow_rect_alloc_size; + source = compute_box_shadow_parameters( - shadow_rect.scale(downscale, downscale), + shadow_rect_fract_offset * downscale, + shadow_rect_size * downscale, shadow_radius, prim_shadow_rect, blur_radius * downscale, @@ -1035,31 +1068,43 @@ impl ClipItem { // reduce the size of a primitive region. This is typically // used to eliminate redundant clips, and reduce the size of // any clip mask that eventually gets drawn. - fn get_local_clip_rect(&self) -> Option { - match *self { - ClipItem::Rectangle(clip_rect, ClipMode::Clip) => Some(clip_rect), + fn get_local_clip_rect(&self, local_pos: LayoutPoint) -> Option { + let size = match *self { + ClipItem::Rectangle(size, ClipMode::Clip) => Some(size), ClipItem::Rectangle(_, ClipMode::ClipOut) => None, - ClipItem::RoundedRectangle(clip_rect, _, ClipMode::Clip) => Some(clip_rect), + ClipItem::RoundedRectangle(size, _, ClipMode::Clip) => Some(size), ClipItem::RoundedRectangle(_, _, ClipMode::ClipOut) => None, - ClipItem::Image { ref mask, .. } if mask.repeat => None, - ClipItem::Image { ref mask, .. } => Some(mask.rect), + ClipItem::Image { repeat, size, .. } => { + if repeat { + None + } else { + Some(size) + } + } ClipItem::BoxShadow(..) => None, - } + }; + + size.map(|size| { + LayoutRect::new(local_pos, size) + }) } fn get_clip_result_complex( &self, + local_pos: LayoutPoint, transform: &LayoutToWorldTransform, prim_world_rect: &WorldRect, world_rect: &WorldRect, ) -> ClipResult { let (clip_rect, inner_rect) = match *self { - ClipItem::Rectangle(clip_rect, ClipMode::Clip) => { + ClipItem::Rectangle(size, ClipMode::Clip) => { + let clip_rect = LayoutRect::new(local_pos, size); (clip_rect, Some(clip_rect)) } - ClipItem::RoundedRectangle(ref clip_rect, ref radius, ClipMode::Clip) => { - let inner_clip_rect = extract_inner_rect_safe(clip_rect, radius); - (*clip_rect, inner_clip_rect) + ClipItem::RoundedRectangle(size, ref radius, ClipMode::Clip) => { + let clip_rect = LayoutRect::new(local_pos, size); + let inner_clip_rect = extract_inner_rect_safe(&clip_rect, radius); + (clip_rect, inner_clip_rect) } ClipItem::Rectangle(_, ClipMode::ClipOut) | ClipItem::RoundedRectangle(_, _, ClipMode::ClipOut) | @@ -1101,10 +1146,13 @@ impl ClipItem { // Check how a given clip source affects a local primitive region. fn get_clip_result( &self, + local_pos: LayoutPoint, prim_rect: &LayoutRect, ) -> ClipResult { match *self { - ClipItem::Rectangle(ref clip_rect, ClipMode::Clip) => { + ClipItem::Rectangle(size, ClipMode::Clip) => { + let clip_rect = LayoutRect::new(local_pos, size); + if clip_rect.contains_rect(prim_rect) { return ClipResult::Accept; } @@ -1118,7 +1166,9 @@ impl ClipItem { } } } - ClipItem::Rectangle(ref clip_rect, ClipMode::ClipOut) => { + ClipItem::Rectangle(size, ClipMode::ClipOut) => { + let clip_rect = LayoutRect::new(local_pos, size); + if clip_rect.contains_rect(prim_rect) { return ClipResult::Reject; } @@ -1132,12 +1182,14 @@ impl ClipItem { } } } - ClipItem::RoundedRectangle(ref clip_rect, ref radius, ClipMode::Clip) => { + ClipItem::RoundedRectangle(size, ref radius, ClipMode::Clip) => { + let clip_rect = LayoutRect::new(local_pos, size); + // TODO(gw): Consider caching this in the ClipNode // if it ever shows in profiles. // TODO(gw): extract_inner_rect_safe is overly // conservative for this code! - let inner_clip_rect = extract_inner_rect_safe(clip_rect, radius); + let inner_clip_rect = extract_inner_rect_safe(&clip_rect, radius); if let Some(inner_clip_rect) = inner_clip_rect { if inner_clip_rect.contains_rect(prim_rect) { return ClipResult::Accept; @@ -1153,12 +1205,14 @@ impl ClipItem { } } } - ClipItem::RoundedRectangle(ref clip_rect, ref radius, ClipMode::ClipOut) => { + ClipItem::RoundedRectangle(size, ref radius, ClipMode::ClipOut) => { + let clip_rect = LayoutRect::new(local_pos, size); + // TODO(gw): Consider caching this in the ClipNode // if it ever shows in profiles. // TODO(gw): extract_inner_rect_safe is overly // conservative for this code! - let inner_clip_rect = extract_inner_rect_safe(clip_rect, radius); + let inner_clip_rect = extract_inner_rect_safe(&clip_rect, radius); if let Some(inner_clip_rect) = inner_clip_rect { if inner_clip_rect.contains_rect(prim_rect) { return ClipResult::Reject; @@ -1174,11 +1228,12 @@ impl ClipItem { } } } - ClipItem::Image { ref mask, .. } => { - if mask.repeat { + ClipItem::Image { size, repeat, .. } => { + if repeat { ClipResult::Partial } else { - match mask.rect.intersection(prim_rect) { + let mask_rect = LayoutRect::new(local_pos, size); + match mask_rect.intersection(prim_rect) { Some(..) => { ClipResult::Partial } @@ -1303,6 +1358,7 @@ impl ClipNodeCollector { fn add_clip_node_to_current_chain( handle: ClipDataHandle, clip_spatial_node_index: SpatialNodeIndex, + local_pos: LayoutPoint, spatial_node_index: SpatialNodeIndex, local_clip_rect: &mut LayoutRect, clip_node_info: &mut Vec, @@ -1336,7 +1392,7 @@ fn add_clip_node_to_current_chain( // If we can convert spaces, try to reduce the size of the region // requested, and cache the conversion information for the next step. if let Some(conversion) = conversion { - if let Some(clip_rect) = clip_node.item.get_local_clip_rect() { + if let Some(clip_rect) = clip_node.item.get_local_clip_rect(local_pos) { match conversion { ClipSpaceConversion::Local => { *local_clip_rect = match local_clip_rect.intersection(&clip_rect) { @@ -1366,6 +1422,7 @@ fn add_clip_node_to_current_chain( } clip_node_info.push(ClipNodeInfo { conversion, + local_pos, handle, spatial_node_index: clip_spatial_node_index, }) diff --git a/webrender/src/display_list_flattener.rs b/webrender/src/display_list_flattener.rs index d7218f0c0c..698fc653b2 100644 --- a/webrender/src/display_list_flattener.rs +++ b/webrender/src/display_list_flattener.rs @@ -917,14 +917,14 @@ impl<'a> DisplayListFlattener<'a> { for _ in 0 .. item_clip_node.count { // Get the id of the clip sources entry for that clip chain node. - let (handle, spatial_node_index) = { + let (handle, spatial_node_index, local_pos) = { let clip_chain = self .clip_store .get_clip_chain(clip_node_clip_chain_id); clip_node_clip_chain_id = clip_chain.parent_clip_chain_id; - (clip_chain.handle, clip_chain.spatial_node_index) + (clip_chain.handle, clip_chain.spatial_node_index, clip_chain.local_pos) }; // Add a new clip chain node, which references the same clip sources, and @@ -933,6 +933,7 @@ impl<'a> DisplayListFlattener<'a> { .clip_store .add_clip_chain_node( handle, + local_pos, spatial_node_index, clip_chain_id, ); @@ -984,7 +985,7 @@ impl<'a> DisplayListFlattener<'a> { // just return the parent clip chain id directly. fn build_clip_chain( &mut self, - clip_items: Vec, + clip_items: Vec<(LayoutPoint, ClipItemKey)>, spatial_node_index: SpatialNodeIndex, parent_clip_chain_id: ClipChainId, ) -> ClipChainId { @@ -993,7 +994,7 @@ impl<'a> DisplayListFlattener<'a> { } else { let mut clip_chain_id = parent_clip_chain_id; - for item in clip_items { + for (local_pos, item) in clip_items { // Intern this clip item, and store the handle // in the clip chain node. let handle = self.resources @@ -1012,6 +1013,7 @@ impl<'a> DisplayListFlattener<'a> { clip_chain_id = self.clip_store .add_clip_chain_node( handle, + local_pos, spatial_node_index, clip_chain_id, ); @@ -1107,7 +1109,7 @@ impl<'a> DisplayListFlattener<'a> { &mut self, clip_and_scroll: ScrollNodeAndClipChain, info: &LayoutPrimitiveInfo, - clip_items: Vec, + clip_items: Vec<(LayoutPoint, ClipItemKey)>, key_kind: PrimitiveKeyKind, ) { // If a shadow context is not active, then add the primitive @@ -1587,7 +1589,7 @@ impl<'a> DisplayListFlattener<'a> { let handle = self .resources .clip_interner - .intern(&ClipItemKey::rectangle(clip_region.main, ClipMode::Clip), || { + .intern(&ClipItemKey::rectangle(clip_region.main.size, ClipMode::Clip), || { ClipItemSceneData { clip_rect: clip_region.main, } @@ -1597,6 +1599,7 @@ impl<'a> DisplayListFlattener<'a> { .clip_store .add_clip_chain_node( handle, + clip_region.main.origin, spatial_node, parent_clip_chain_index, ); @@ -1616,6 +1619,7 @@ impl<'a> DisplayListFlattener<'a> { .clip_store .add_clip_chain_node( handle, + image_mask.rect.origin, spatial_node, parent_clip_chain_index, ); @@ -1626,7 +1630,7 @@ impl<'a> DisplayListFlattener<'a> { let handle = self .resources .clip_interner - .intern(&ClipItemKey::rounded_rect(region.rect, region.radii, region.mode), || { + .intern(&ClipItemKey::rounded_rect(region.rect.size, region.radii, region.mode), || { ClipItemSceneData { clip_rect: region.get_local_clip_rect().unwrap_or(LayoutRect::max_rect()), } @@ -1636,6 +1640,7 @@ impl<'a> DisplayListFlattener<'a> { .clip_store .add_clip_chain_node( handle, + region.rect.origin, spatial_node, parent_clip_chain_index, ); diff --git a/webrender/src/gpu_types.rs b/webrender/src/gpu_types.rs index 64afd556a7..f1f2c93908 100644 --- a/webrender/src/gpu_types.rs +++ b/webrender/src/gpu_types.rs @@ -5,7 +5,7 @@ use api::{ DevicePoint, DeviceSize, DeviceRect, LayoutRect, LayoutToWorldTransform, LayoutTransform, PremultipliedColorF, LayoutToPictureTransform, PictureToLayoutTransform, PicturePixel, - WorldPixel, WorldToLayoutTransform, + WorldPixel, WorldToLayoutTransform, LayoutPoint, }; use clip_scroll_tree::{ClipScrollTree, ROOT_SPATIAL_NODE_INDEX, SpatialNodeIndex}; use gpu_cache::{GpuCacheAddress, GpuDataRequest}; @@ -140,6 +140,8 @@ pub struct ClipMaskInstance { pub segment: i32, pub clip_data_address: GpuCacheAddress, pub resource_address: GpuCacheAddress, + pub local_pos: LayoutPoint, + pub tile_rect: LayoutRect, } /// A border corner dot or dash drawn into the clipping mask. diff --git a/webrender/src/hit_test.rs b/webrender/src/hit_test.rs index fd7f3901c8..98ec34c860 100644 --- a/webrender/src/hit_test.rs +++ b/webrender/src/hit_test.rs @@ -34,13 +34,20 @@ pub struct HitTestClipNode { } impl HitTestClipNode { - fn new(node: &ClipNode) -> Self { + fn new(local_pos: LayoutPoint, node: &ClipNode) -> Self { let region = match node.item { - ClipItem::Rectangle(ref rect, mode) => HitTestRegion::Rectangle(*rect, mode), - ClipItem::RoundedRectangle(ref rect, ref radii, ref mode) => - HitTestRegion::RoundedRectangle(*rect, *radii, *mode), - ClipItem::Image { ref mask, .. } => - HitTestRegion::Rectangle(mask.rect, ClipMode::Clip), + ClipItem::Rectangle(size, mode) => { + let rect = LayoutRect::new(local_pos, size); + HitTestRegion::Rectangle(rect, mode) + } + ClipItem::RoundedRectangle(size, radii, mode) => { + let rect = LayoutRect::new(local_pos, size); + HitTestRegion::RoundedRectangle(rect, radii, mode) + } + ClipItem::Image { size, .. } => { + let rect = LayoutRect::new(local_pos, size); + HitTestRegion::Rectangle(rect, ClipMode::Clip) + } ClipItem::BoxShadow(_) => HitTestRegion::Invalid, }; @@ -170,7 +177,7 @@ impl HitTester { for node in &clip_store.clip_chain_nodes { let clip_node = &clip_data_store[node.handle]; self.clip_chains.push(HitTestClipChainNode { - region: HitTestClipNode::new(clip_node), + region: HitTestClipNode::new(node.local_pos, clip_node), spatial_node_index: node.spatial_node_index, parent_clip_chain_id: HitTestClipChainId(node.parent_clip_chain_id.0), }); diff --git a/webrender/src/prim_store.rs b/webrender/src/prim_store.rs index fd27c55d60..617f670d60 100644 --- a/webrender/src/prim_store.rs +++ b/webrender/src/prim_store.rs @@ -2,7 +2,7 @@ * 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::{AlphaType, BorderRadius, ClipMode, ColorF, PictureRect, ColorU}; +use api::{AlphaType, BorderRadius, ClipMode, ColorF, PictureRect, ColorU, LayoutVector2D}; use api::{DeviceIntRect, DeviceIntSize, DevicePixelScale, ExtendMode, DeviceRect, LayoutSideOffsetsAu}; use api::{FilterOp, GlyphInstance, GradientStop, ImageKey, ImageRendering, TileOffset, RepeatMode}; use api::{RasterSpace, LayoutPoint, LayoutRect, LayoutSideOffsets, LayoutSize, LayoutToWorldTransform}; @@ -1528,7 +1528,7 @@ pub struct VisibleImageTile { #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct VisibleMaskImageTile { pub tile_offset: TileOffset, - pub handle: GpuCacheHandle, + pub tile_rect: LayoutRect, } #[derive(Debug)] @@ -2057,16 +2057,18 @@ impl ClipCorner { #[derive(Debug)] #[repr(C)] pub struct ImageMaskData { - /// The local rect of the whole masked area. - pub local_mask_rect: LayoutRect, - /// The local rect of an individual tile. - pub local_tile_rect: LayoutRect, + /// The local size of the whole masked area. + pub local_mask_size: LayoutSize, } impl ToGpuBlocks for ImageMaskData { fn write_gpu_blocks(&self, mut request: GpuDataRequest) { - request.push(self.local_mask_rect); - request.push(self.local_tile_rect); + request.push([ + self.local_mask_size.width, + self.local_mask_size.height, + 0.0, + 0.0, + ]); } } @@ -2080,10 +2082,19 @@ pub struct ClipData { } impl ClipData { - pub fn rounded_rect(rect: &LayoutRect, radii: &BorderRadius, mode: ClipMode) -> ClipData { + pub fn rounded_rect(size: LayoutSize, radii: &BorderRadius, mode: ClipMode) -> ClipData { + // TODO(gw): For simplicity, keep most of the clip GPU structs the + // same as they were, even though the origin is now always + // zero, since they are in the clip's local space. In future, + // we could reduce the GPU cache size of ClipData. + let rect = LayoutRect::new( + LayoutPoint::zero(), + size, + ); + ClipData { rect: ClipRect { - rect: *rect, + rect, mode: mode as u32 as f32, }, top_left: ClipCorner { @@ -2138,7 +2149,16 @@ impl ClipData { } } - pub fn uniform(rect: LayoutRect, radius: f32, mode: ClipMode) -> ClipData { + pub fn uniform(size: LayoutSize, radius: f32, mode: ClipMode) -> ClipData { + // TODO(gw): For simplicity, keep most of the clip GPU structs the + // same as they were, even though the origin is now always + // zero, since they are in the clip's local space. In future, + // we could reduce the GPU cache size of ClipData. + let rect = LayoutRect::new( + LayoutPoint::zero(), + size, + ); + ClipData { rect: ClipRect { rect, @@ -3752,12 +3772,12 @@ impl<'a> GpuDataRequest<'a> { local_clip_count += 1; let (local_clip_rect, radius, mode) = match clip_node.item { - ClipItem::RoundedRectangle(rect, radii, clip_mode) => { + ClipItem::RoundedRectangle(size, radii, clip_mode) => { rect_clips_only = false; - (rect, Some(radii), clip_mode) + (LayoutRect::new(clip_instance.local_pos, size), Some(radii), clip_mode) } - ClipItem::Rectangle(rect, mode) => { - (rect, None, mode) + ClipItem::Rectangle(size, mode) => { + (LayoutRect::new(clip_instance.local_pos, size), None, mode) } ClipItem::BoxShadow(ref info) => { rect_clips_only = false; @@ -3775,9 +3795,12 @@ impl<'a> GpuDataRequest<'a> { // box-shadow can have an effect on the result. This // ensures clip-mask tasks get allocated for these // pixel regions, even if no other clips affect them. + let prim_shadow_rect = info.prim_shadow_rect.translate( + &LayoutVector2D::new(clip_instance.local_pos.x, clip_instance.local_pos.y), + ); segment_builder.push_mask_region( - info.prim_shadow_rect, - info.prim_shadow_rect.inflate( + prim_shadow_rect, + prim_shadow_rect.inflate( -0.5 * info.original_alloc_size.width, -0.5 * info.original_alloc_size.height, ), diff --git a/webrender/src/render_task.rs b/webrender/src/render_task.rs index 28a8eaca90..433fc4ea0b 100644 --- a/webrender/src/render_task.rs +++ b/webrender/src/render_task.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DeviceSize, DeviceIntSideOffsets}; -use api::{DevicePixelScale, ImageDescriptor, ImageFormat}; +use api::{DevicePixelScale, ImageDescriptor, ImageFormat, LayoutPoint}; use api::{LineStyle, LineOrientation, LayoutSize, ColorF, DirtyRect}; #[cfg(feature = "pathfinder")] use api::FontRenderMode; @@ -253,6 +253,7 @@ pub struct CacheMaskTask { #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct ClipRegionTask { pub clip_data_address: GpuCacheAddress, + pub local_pos: LayoutPoint, } #[derive(Debug)] @@ -587,6 +588,7 @@ impl RenderTask { let mask_task = RenderTask::new_rounded_rect_mask( cache_size, clip_data_address, + info.minimal_shadow_rect.origin, ); let mask_task_id = render_tasks.add(mask_task); @@ -628,12 +630,14 @@ impl RenderTask { pub fn new_rounded_rect_mask( size: DeviceIntSize, clip_data_address: GpuCacheAddress, + local_pos: LayoutPoint, ) -> Self { RenderTask::with_dynamic_location( size, Vec::new(), RenderTaskKind::ClipRegion(ClipRegionTask { clip_data_address, + local_pos, }), ClearMode::One, ) diff --git a/webrender/src/renderer.rs b/webrender/src/renderer.rs index a5ed9fc607..f5e20a048d 100644 --- a/webrender/src/renderer.rs +++ b/webrender/src/renderer.rs @@ -534,6 +534,16 @@ pub(crate) mod desc { count: 4, kind: VertexAttributeKind::U16, }, + VertexAttribute { + name: "aClipLocalPos", + count: 2, + kind: VertexAttributeKind::F32, + }, + VertexAttribute { + name: "aClipTileRect", + count: 4, + kind: VertexAttributeKind::F32, + } ], }; diff --git a/webrender/src/tiling.rs b/webrender/src/tiling.rs index b480f4724f..97eccc8cc8 100644 --- a/webrender/src/tiling.rs +++ b/webrender/src/tiling.rs @@ -652,6 +652,7 @@ impl RenderTarget for AlphaRenderTarget { self.clip_batcher.add_clip_region( task_address, task.clip_data_address, + task.local_pos, ); } RenderTaskKind::Scaling(ref info) => { diff --git a/wrench/reftests/boxshadow/box-shadow-huge-radius.png b/wrench/reftests/boxshadow/box-shadow-huge-radius.png index c40699001cd93f31498fec59ee8fa1277213ed74..f10110eae371b4480aacd3fd25b453fc569aa64d 100644 GIT binary patch literal 16127 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 literal 16745 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 PMu(k`eaHFc diff --git a/wrench/reftests/boxshadow/box-shadow-large-blur-radius-3.png b/wrench/reftests/boxshadow/box-shadow-large-blur-radius-3.png index b801b193ab1d0304ccf5caca0695d9cd50c54ffc..0616288708474d539471d9bc6b4f9e84754634ea 100644 GIT binary patch literal 63665 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 wtf%3@zJEG^g3=LX!Ww_kNxvpzqB3 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�jn06+rE@3I6Unk2 zmIvJkv;zSzF1pxnjYV-6=6-CM2z57#YdRm3-A7cJ9?z2v~2wYI(-9Gp8oc7rG)Jl}~4f&y37T zBGY~n5M#e)@f3s0=4WO;?(r9so3j^ly2Zp6&6 z=eo6>g>^Rh&u5*ksmg}PfSSKq{M8)O{@JD;`sxh6+B&*$NjB%cps9d;4Rg8m50VY} z6}RmQhelN0f#)ha+{Ys`J~&wcR9bj^ur}W&p+IMYGUsnADva6nD}P=@aUHu`ttFyUu*K+dVeGyQ5fkTp!Htm znVj0+J~FrY=)^aVL`Xf)dRaR<`ZrI`@WcL^zv}*R?*+OKEcxXZw=K=Tib(t8l34G} zl5#H7_a7fU?wfPZ6EyG1dVlzLD<)*A|Gp&l_A4A!>f=+pG~k7Q`KsaYEBIVMjracM ziT7x+Pv3dP4@>a;?MUN~{vK<+`wsy%m-AP7{xTyp;+_BelYDtTEj8`oQh)Hn|H-9Z zDV?}EzpSsA2~T{mBz9uyyb0e4iV)Je5_0ZciF{~p=k4A{&P-Ilg#ey;_~G0CnsbTl zb!+0AeNWF{;`TpsyRaGJ+~kIiQfq!hi07$&0`@Igm+_Us{mrt-iFVIZ`&{x5(A@v5 z)O~zo-b6149DRKD`bMPo{7ufipUrv-9BjTMK(qI!aCEt6YkYjV^OwY4`Y{|>&i%X~ z+{fAbtluis_sgZ;>%Zs5`g}(b17hzw-ieGz>v=in-lH>5dH?F>L0k%ZwCGZ={Qpb& z{14bFb>{hbv*#a-x%5jgmNT3@0e^q#nE=iCAAl8|+2H-urN{ACKMAObnz-TptG&+z zTsr^MeC+x7-2dHt%;KkcJ&PFje$?k6Vt@XB*8S}N!7p8(TT&x&s>+wX^AGf(8(!V~ Lf68Be=TH9^1 Date: Wed, 5 Dec 2018 09:17:17 +1000 Subject: [PATCH 2/2] Switch segments to be defined relative to the local primitive position. --- webrender/res/brush.glsl | 1 + webrender/src/batch.rs | 4 ++-- webrender/src/border.rs | 14 ++++++++++++-- webrender/src/prim_store.rs | 21 ++++++++++----------- 4 files changed, 25 insertions(+), 15 deletions(-) diff --git a/webrender/res/brush.glsl b/webrender/res/brush.glsl index 48f5e18a43..547204443d 100644 --- a/webrender/res/brush.glsl +++ b/webrender/res/brush.glsl @@ -49,6 +49,7 @@ void main(void) { vec4[2] segment_info = fetch_from_gpu_cache_2(segment_address); segment_rect = RectWithSize(segment_info[0].xy, segment_info[0].zw); + segment_rect.p0 += ph.local_rect.p0; segment_data = segment_info[1]; } diff --git a/webrender/src/batch.rs b/webrender/src/batch.rs index 867eb13a92..6db9410f79 100644 --- a/webrender/src/batch.rs +++ b/webrender/src/batch.rs @@ -1971,7 +1971,7 @@ impl AlphaBatchBuilder { let base_instance = BrushInstance { prim_header_index, clip_task_address, - segment_index: 0, + segment_index: INVALID_SEGMENT_INDEX, edge_flags, brush_flags: BrushFlags::PERSPECTIVE_INTERPOLATION, user_data: uv_rect_address.as_int(), @@ -2188,7 +2188,7 @@ fn add_gradient_tiles( BrushInstance { prim_header_index, clip_task_address, - segment_index: 0, + segment_index: INVALID_SEGMENT_INDEX, edge_flags: EdgeAaSegmentMask::all(), brush_flags: BrushFlags::PERSPECTIVE_INTERPOLATION, user_data: 0, diff --git a/webrender/src/border.rs b/webrender/src/border.rs index b575122de6..13aa052629 100644 --- a/webrender/src/border.rs +++ b/webrender/src/border.rs @@ -649,12 +649,17 @@ fn get_edge_info( /// Create the set of border segments and render task /// cache keys for a given CSS border. pub fn create_border_segments( - rect: &LayoutRect, + size: LayoutSize, border: &NormalBorder, widths: &LayoutSideOffsets, border_segments: &mut Vec, brush_segments: &mut Vec, ) { + let rect = LayoutRect::new( + LayoutPoint::zero(), + size, + ); + let local_size_tl = LayoutSize::new( border.radius.top_left.width.max(widths.left), border.radius.top_left.height.max(widths.top), @@ -1143,8 +1148,13 @@ pub fn build_border_instances( impl NinePatchDescriptor { pub fn create_segments( &self, - rect: &LayoutRect, + size: LayoutSize, ) -> Vec { + let rect = LayoutRect::new( + LayoutPoint::zero(), + size, + ); + // Calculate the modified rect as specific by border-image-outset let origin = LayoutPoint::new( rect.origin.x - self.outset.left, diff --git a/webrender/src/prim_store.rs b/webrender/src/prim_store.rs index 617f670d60..f493d0667d 100644 --- a/webrender/src/prim_store.rs +++ b/webrender/src/prim_store.rs @@ -833,7 +833,7 @@ impl PrimitiveKeyKind { let mut border_segments = Vec::new(); create_border_segments( - rect, + rect.size, &border, &widths, &mut border_segments, @@ -854,7 +854,7 @@ impl PrimitiveKeyKind { ref nine_patch, .. } => { - let brush_segments = nine_patch.create_segments(rect); + let brush_segments = nine_patch.create_segments(rect.size); PrimitiveTemplateKind::ImageBorder { request, @@ -921,7 +921,7 @@ impl PrimitiveKeyKind { let mut brush_segments = Vec::new(); if let Some(ref nine_patch) = nine_patch { - brush_segments = nine_patch.create_segments(rect); + brush_segments = nine_patch.create_segments(rect.size); } // Save opacity of the stops for use in @@ -955,7 +955,7 @@ impl PrimitiveKeyKind { let mut brush_segments = Vec::new(); if let Some(ref nine_patch) = nine_patch { - brush_segments = nine_patch.create_segments(rect); + brush_segments = nine_patch.create_segments(rect.size); } let stops = stops.iter().map(|stop| { @@ -3494,7 +3494,6 @@ impl PrimitiveStore { request.push(PremultipliedColorF::WHITE); request.push(PremultipliedColorF::WHITE); request.push([tile.rect.size.width, tile.rect.size.height, 0.0, 0.0]); - request.write_segment(tile.rect, [0.0; 4]); } image_instance.visible_tiles.push(VisibleImageTile { @@ -3534,7 +3533,7 @@ impl PrimitiveStore { frame_state, &pic_context.dirty_world_rect, &mut scratch.gradient_tiles, - &mut |rect, mut request| { + &mut |_, mut request| { request.push([ start_point.x, start_point.y, @@ -3547,7 +3546,6 @@ impl PrimitiveStore { stretch_size.height, 0.0, ]); - request.write_segment(*rect, [0.0; 4]); } ); @@ -3574,7 +3572,7 @@ impl PrimitiveStore { frame_state, &pic_context.dirty_world_rect, &mut scratch.gradient_tiles, - &mut |rect, mut request| { + &mut |_, mut request| { request.push([ center.x, center.y, @@ -3587,7 +3585,6 @@ impl PrimitiveStore { stretch_size.width, stretch_size.height, ]); - request.write_segment(*rect, [0.0; 4]); }, ); @@ -3919,7 +3916,7 @@ impl PrimitiveInstance { frame_state.segment_builder.build(|segment| { segments.push( BrushSegment::new( - segment.rect, + segment.rect.translate(&LayoutVector2D::new(-prim_local_rect.origin.x, -prim_local_rect.origin.y)), segment.has_mask, segment.edge_flags, [0.0; 4], @@ -3950,6 +3947,7 @@ impl PrimitiveInstance { fn update_clip_task_for_brush( &mut self, + prim_origin: LayoutPoint, prim_local_clip_rect: LayoutRect, root_spatial_node_index: SpatialNodeIndex, prim_bounding_rect: WorldRect, @@ -4098,7 +4096,7 @@ impl PrimitiveInstance { .clip_store .build_clip_chain_instance( self.clip_chain_id, - segment.local_rect, + segment.local_rect.translate(&LayoutVector2D::new(prim_origin.x, prim_origin.y)), prim_local_clip_rect, prim_context.spatial_node_index, &pic_state.map_local_to_pic, @@ -4165,6 +4163,7 @@ impl PrimitiveInstance { // First try to render this primitive's mask using optimized brush rendering. if self.update_clip_task_for_brush( + prim_local_rect.origin, prim_local_clip_rect, root_spatial_node_index, prim_bounding_rect,