Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store clip node templates in local space. #3383

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

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.
  • Loading branch information
gw3583 committed Dec 4, 2018
commit 05e657ea9d0e64c46a4ce315c21fd7fd741965bc
@@ -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;
}
@@ -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,29 +68,29 @@ 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;
}
}

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;
}
}
@@ -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
@@ -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,
@@ -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)
}
}
}
@@ -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,
@@ -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.
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.