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

Properly support tiling clip mask images. #3220

Merged
merged 11 commits into from Oct 23, 2018
@@ -4,22 +4,24 @@

#include shared,clip_shared

varying vec3 vLocalPos;
varying vec3 vClipMaskImageUv;
varying vec2 vLocalPos;
varying vec2 vClipMaskImageUv;

flat varying vec4 vClipMaskUvRect;
flat varying vec4 vClipMaskUvInnerRect;
flat varying float vLayer;

#ifdef WR_VERTEX_SHADER
struct ImageMaskData {
RectWithSize local_rect;
RectWithSize local_mask_rect;
RectWithSize local_tile_rect;
};

ImageMaskData fetch_mask_data(ivec2 address) {
vec4 data = fetch_from_gpu_cache_1_direct(address);
RectWithSize local_rect = RectWithSize(data.xy, data.zw);
ImageMaskData mask_data = ImageMaskData(local_rect);
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);
return mask_data;
}

@@ -29,7 +31,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_rect;
RectWithSize local_rect = mask.local_mask_rect;
ImageResource res = fetch_image_resource_direct(cmi.resource_address);

ClipVertexInfo vi = write_clip_tile_vertex(
@@ -38,12 +40,9 @@ void main(void) {
clip_transform,
area
);
vLocalPos = vi.local_pos;
vLocalPos = vi.local_pos.xy / vi.local_pos.z;
vLayer = res.layer;

vec2 local_pos = vLocalPos.xy / vLocalPos.z;

vClipMaskImageUv = vec3((local_pos - local_rect.p0) / local_rect.size, 0.0);
vClipMaskImageUv = (vLocalPos - mask.local_tile_rect.p0) / mask.local_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
@@ -54,17 +53,19 @@ void main(void) {

#ifdef WR_FRAGMENT_SHADER
void main(void) {
vec2 local_pos = vLocalPos.xy / vLocalPos.z;
float alpha = init_transform_fs(vLocalPos);

float alpha = init_transform_fs(local_pos);
// TODO: Handle repeating masks?
vec2 clamped_mask_uv = clamp(vClipMaskImageUv, vec2(0.0, 0.0), vec2(1.0, 1.0));

// Ensure we don't draw outside of our tile.
// FIXME(emilio): Can we do this earlier?
if (clamped_mask_uv != vClipMaskImageUv)
discard;

bool repeat_mask = false; //TODO
vec2 clamped_mask_uv = repeat_mask ? fract(vClipMaskImageUv.xy) :
clamp(vClipMaskImageUv.xy, vec2(0.0, 0.0), vec2(1.0, 1.0));
vec2 source_uv = clamp(clamped_mask_uv * vClipMaskUvRect.zw + vClipMaskUvRect.xy,
vClipMaskUvInnerRect.xy, vClipMaskUvInnerRect.zw);
float clip_alpha = texture(sColor0, vec3(source_uv, vLayer)).r; //careful: texture has type A8

oFragColor = vec4(alpha * clip_alpha, 1.0, 1.0, 1.0);
}
#endif
@@ -1949,37 +1949,51 @@ impl ClipBatcher {
resource_address: GpuCacheAddress::invalid(),
};

let gpu_address = gpu_cache.get_address(&clip_node.gpu_cache_handle);

match clip_node.item {
ClipItem::Image(ref mask, is_valid) => {
if is_valid {
if let Ok(cache_item) = resource_cache.get_cached_image(
ImageRequest {
key: mask.image,
rendering: ImageRendering::Auto,
tile: None,
ClipItem::Image { ref mask, ref visible_tiles } => {
let request = ImageRequest {
key: mask.image,
rendering: ImageRendering::Auto,
tile: None,
};
let mut add_image = |request: ImageRequest, clip_data_address: GpuCacheAddress| {
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);
return;
}
};
self.images
.entry(cache_item.texture_id)
.or_insert(Vec::new())
.push(ClipMaskInstance {
clip_data_address,
resource_address: gpu_cache.get_address(&cache_item.uv_rect_handle),
..instance
});
};

match *visible_tiles {
Some(ref tiles) => {
for tile in tiles {
add_image(
request.with_tile(tile.tile_offset),
gpu_cache.get_address(&tile.handle),
)
}
) {
self.images
.entry(cache_item.texture_id)
.or_insert(Vec::new())
.push(ClipMaskInstance {
clip_data_address: gpu_address,
resource_address: gpu_cache.get_address(&cache_item.uv_rect_handle),
..instance
});
} else {
warn!("Warnings: skip a image mask");
debug!("Key:{:?} Rect::{:?}", mask.image, mask.rect);
continue;
}
} else {
warn!("Warnings: clip masks that are tiled blobs are not yet supported (#2852)");
continue;
None => {
let gpu_address =
gpu_cache.get_address(&clip_node.gpu_cache_handle);
add_image(request, gpu_address)
}
}
}
ClipItem::BoxShadow(ref info) => {
let gpu_address =
gpu_cache.get_address(&clip_node.gpu_cache_handle);
let rt_handle = info
.cache_handle
.as_ref()
@@ -2002,13 +2016,17 @@ impl ClipBatcher {
ClipItem::Rectangle(_, mode) => {
if !clip_instance.flags.contains(ClipNodeFlags::SAME_COORD_SYSTEM) ||
mode == ClipMode::ClipOut {
let gpu_address =
gpu_cache.get_address(&clip_node.gpu_cache_handle);
self.rectangles.push(ClipMaskInstance {
clip_data_address: gpu_address,
..instance
});
}
}
ClipItem::RoundedRectangle(..) => {
let gpu_address =
gpu_cache.get_address(&clip_node.gpu_cache_handle);
self.rectangles.push(ClipMaskInstance {
clip_data_address: gpu_address,
..instance
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.