Skip to content

Off-screen clip mask generation #556

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

Merged
merged 1 commit into from
Nov 16, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions replay/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ fn main() {
let resource_path = &args[1];
let ref dir = args[2];
let window = glutin::WindowBuilder::new()
.with_title("WebRender Replay")
.with_gl(glutin::GlRequest::Specific(glutin::Api::OpenGl, (3,2)))
.build()
.unwrap();
Expand Down
8 changes: 5 additions & 3 deletions sample/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ fn main() {
let res_path = &args[1];

let window = glutin::WindowBuilder::new()
.with_title("WebRender Sample")
.with_gl(glutin::GlRequest::Specific(glutin::Api::OpenGl, (3, 2)))
.build()
.unwrap();
Expand Down Expand Up @@ -133,14 +134,15 @@ fn main() {
&mut auxiliary_lists_builder));

let clip_region = {
let rect = Rect::new(Point2D::new(100.0, 100.0), Size2D::new(100.0, 100.0));
let mask = webrender_traits::ImageMask {
image: api.add_image(2, 2, None, ImageFormat::A8, vec![0,80, 180, 255]),
rect: rect,
rect: Rect::new(Point2D::new(75.0, 75.0), Size2D::new(100.0, 100.0)),
repeat: false,
};
let radius = webrender_traits::BorderRadius::uniform(20.0);
let complex = webrender_traits::ComplexClipRegion::new(rect, radius);
let complex = webrender_traits::ComplexClipRegion::new(
Rect::new(Point2D::new(50.0, 50.0), Size2D::new(100.0, 100.0)),
radius);

webrender_traits::ClipRegion::new(&bounds,
vec![complex],
Expand Down
84 changes: 35 additions & 49 deletions webrender/res/clip_shared.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,63 +3,49 @@
* 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/. */

flat varying vec4 vClipRect;
flat varying vec4 vClipRadius;
flat varying vec4 vClipMaskUvRect;
flat varying vec4 vClipMaskLocalRect;

#ifdef WR_VERTEX_SHADER
void write_clip(ClipData clip) {
vClipRect = vec4(clip.rect.rect.xy, clip.rect.rect.xy + clip.rect.rect.zw);
vClipRadius = vec4(clip.top_left.outer_inner_radius.x,
clip.top_right.outer_inner_radius.x,
clip.bottom_right.outer_inner_radius.x,
clip.bottom_left.outer_inner_radius.x);
//TODO: interpolate the final mask UV
vec2 texture_size = textureSize(sMask, 0);
vClipMaskUvRect = clip.mask_data.uv_rect / texture_size.xyxy;
vClipMaskLocalRect = clip.mask_data.local_rect; //TODO: transform
}
#endif

#ifdef WR_FRAGMENT_SHADER
float do_clip(vec2 pos) {
vec2 ref_tl = vClipRect.xy + vec2( vClipRadius.x, vClipRadius.x);
vec2 ref_tr = vClipRect.zy + vec2(-vClipRadius.y, vClipRadius.y);
vec2 ref_br = vClipRect.zw + vec2(-vClipRadius.z, -vClipRadius.z);
vec2 ref_bl = vClipRect.xw + vec2( vClipRadius.w, -vClipRadius.w);
struct CacheClipInstance {
int render_task_index;
int layer_index;
int data_index;
};

float d_tl = distance(pos, ref_tl);
float d_tr = distance(pos, ref_tr);
float d_br = distance(pos, ref_br);
float d_bl = distance(pos, ref_bl);
CacheClipInstance fetch_clip_item(int index) {
CacheClipInstance cci;

float pixels_per_fragment = length(fwidth(pos.xy));
float nudge = 0.5 * pixels_per_fragment;
vec4 distances = vec4(d_tl, d_tr, d_br, d_bl) - vClipRadius + nudge;
int offset = index * 1;

bvec4 is_out = bvec4(pos.x < ref_tl.x && pos.y < ref_tl.y,
pos.x > ref_tr.x && pos.y < ref_tr.y,
pos.x > ref_br.x && pos.y > ref_br.y,
pos.x < ref_bl.x && pos.y > ref_bl.y);
ivec4 data0 = int_data[offset + 0];

float distance_from_border = dot(vec4(is_out),
max(vec4(0.0, 0.0, 0.0, 0.0), distances));
cci.render_task_index = data0.x;
cci.layer_index = data0.y;
cci.data_index = data0.z;

return cci;
}

// Move the distance back into pixels.
distance_from_border /= pixels_per_fragment;
// Apply a more gradual fade out to transparent.
//distance_from_border -= 0.5;
// The transformed vertex function that always covers the whole whole clip area,
// which is the intersection of all clip instances of a given primitive
TransformVertexInfo write_clip_tile_vertex(vec4 local_clip_rect,
Layer layer,
ClipArea area) {
vec2 lp0_base = local_clip_rect.xy;
vec2 lp1_base = local_clip_rect.xy + local_clip_rect.zw;

float border_alpha = 1.0 - smoothstep(0.0, 1.0, distance_from_border);
vec2 lp0 = clamp_rect(lp0_base, layer.local_clip_rect);
vec2 lp1 = clamp_rect(lp1_base, layer.local_clip_rect);
vec4 clipped_local_rect = vec4(lp0, lp1 - lp0);

bool repeat_mask = false; //TODO
vec2 vMaskUv = (pos - vClipMaskLocalRect.xy) / vClipMaskLocalRect.zw;
vec2 clamped_mask_uv = repeat_mask ? fract(vMaskUv) :
clamp(vMaskUv, vec2(0.0, 0.0), vec2(1.0, 1.0));
vec2 source_uv = clamped_mask_uv * vClipMaskUvRect.zw + vClipMaskUvRect.xy;
float mask_alpha = texture(sMask, source_uv).r; //careful: texture has type A8
vec2 final_pos = mix(area.task_bounds.xy, area.task_bounds.zw, aPosition.xy);

return border_alpha * mask_alpha;
// compute the point position in side the layer, in CSS space
vec2 clamped_pos = final_pos + area.screen_origin_target_index.xy - area.task_bounds.xy;
vec4 layer_pos = get_layer_pos(clamped_pos / uDevicePixelRatio, layer);

gl_Position = uTransform * vec4(final_pos, 0.0, 1);

return TransformVertexInfo(layer_pos.xyw, clamped_pos, clipped_local_rect);
}
#endif

#endif //WR_VERTEX_SHADER
7 changes: 7 additions & 0 deletions webrender/res/cs_clip_clear.fs.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */

void main(void) {
oFragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
13 changes: 13 additions & 0 deletions webrender/res/cs_clip_clear.vs.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#line 1
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */

void main(void) {
CacheClipInstance cci = fetch_clip_item(gl_InstanceID);
ClipArea area = fetch_clip_area(cci.render_task_index);

vec2 final_pos = mix(area.task_bounds.xy, area.task_bounds.zw, aPosition.xy);

gl_Position = uTransform * vec4(final_pos, 0.0, 1.0);
}
16 changes: 16 additions & 0 deletions webrender/res/cs_clip_image.fs.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */

void main(void) {
float alpha = 1.f;
vec2 local_pos = init_transform_fs(vPos, vLocalRect, alpha);

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

oFragColor = vec4(1.0, 1.0, 1.0, min(alpha, clip_alpha));
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,6 @@
* 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/. */

varying vec4 vColor;

#ifdef WR_FEATURE_TRANSFORM
varying vec3 vPos;
flat varying vec4 vLocalRect;
#else
varying vec2 vPos;
#endif
flat varying vec4 vClipMaskUvRect;
38 changes: 38 additions & 0 deletions webrender/res/cs_clip_image.vs.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#line 1
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */

struct ImageMaskData {
vec4 uv_rect;
vec4 local_rect;
};

ImageMaskData fetch_mask_data(int index) {
ImageMaskData info;

ivec2 uv = get_fetch_uv_2(index);

info.uv_rect = texelFetchOffset(sData32, uv, 0, ivec2(0, 0));
info.local_rect = texelFetchOffset(sData32, uv, 0, ivec2(1, 0));

return info;
}

void main(void) {
CacheClipInstance cci = fetch_clip_item(gl_InstanceID);
ClipArea area = fetch_clip_area(cci.render_task_index);
Layer layer = fetch_layer(cci.layer_index);
ImageMaskData mask = fetch_mask_data(cci.data_index);
vec4 local_rect = mask.local_rect;

TransformVertexInfo vi = write_clip_tile_vertex(local_rect,
layer,
area);
vLocalRect = vi.clipped_local_rect;
vPos = vi.local_pos;

vClipMaskUv = vec3((vPos.xy / vPos.z - local_rect.xy) / local_rect.zw, 0.0);
vec2 texture_size = textureSize(sMask, 0);
vClipMaskUvRect = mask.uv_rect / texture_size.xyxy;
}
44 changes: 44 additions & 0 deletions webrender/res/cs_clip_rectangle.fs.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */

float rounded_rect(vec2 pos) {
vec2 ref_tl = vClipRect.xy + vec2( vClipRadius.x, vClipRadius.x);
vec2 ref_tr = vClipRect.zy + vec2(-vClipRadius.y, vClipRadius.y);
vec2 ref_br = vClipRect.zw + vec2(-vClipRadius.z, -vClipRadius.z);
vec2 ref_bl = vClipRect.xw + vec2( vClipRadius.w, -vClipRadius.w);

float d_tl = distance(pos, ref_tl);
float d_tr = distance(pos, ref_tr);
float d_br = distance(pos, ref_br);
float d_bl = distance(pos, ref_bl);

float pixels_per_fragment = length(fwidth(pos.xy));
float nudge = 0.5 * pixels_per_fragment;
vec4 distances = vec4(d_tl, d_tr, d_br, d_bl) - vClipRadius + nudge;

bvec4 is_out = bvec4(pos.x < ref_tl.x && pos.y < ref_tl.y,
pos.x > ref_tr.x && pos.y < ref_tr.y,
pos.x > ref_br.x && pos.y > ref_br.y,
pos.x < ref_bl.x && pos.y > ref_bl.y);

float distance_from_border = dot(vec4(is_out),
max(vec4(0.0, 0.0, 0.0, 0.0), distances));

// Move the distance back into pixels.
distance_from_border /= pixels_per_fragment;
// Apply a more gradual fade out to transparent.
//distance_from_border -= 0.5;

return 1.0 - smoothstep(0.0, 1.0, distance_from_border);
}


void main(void) {
float alpha = 1.f;
vec2 local_pos = init_transform_fs(vPos, vLocalRect, alpha);

float clip_alpha = rounded_rect(local_pos);

oFragColor = vec4(1.0, 1.0, 1.0, min(alpha, clip_alpha));
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
#line 1

/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */

varying vec4 vColor;

#ifdef WR_FEATURE_TRANSFORM
varying vec3 vLocalPos;
varying vec3 vPos;
flat varying vec4 vLocalRect;
#else
varying vec2 vPos;
#endif
flat varying vec4 vClipRect;
flat varying vec4 vClipRadius;
77 changes: 77 additions & 0 deletions webrender/res/cs_clip_rectangle.vs.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#line 1
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */

struct ClipRect {
vec4 rect;
vec4 dummy;
};

ClipRect fetch_clip_rect(int index) {
ClipRect rect;

ivec2 uv = get_fetch_uv_2(index);

rect.rect = texelFetchOffset(sData32, uv, 0, ivec2(0, 0));
//rect.dummy = texelFetchOffset(sData32, uv, 0, ivec2(1, 0));
rect.dummy = vec4(0.0, 0.0, 0.0, 0.0);

return rect;
}

struct ClipCorner {
vec4 rect;
vec4 outer_inner_radius;
};

ClipCorner fetch_clip_corner(int index) {
ClipCorner corner;

ivec2 uv = get_fetch_uv_2(index);

corner.rect = texelFetchOffset(sData32, uv, 0, ivec2(0, 0));
corner.outer_inner_radius = texelFetchOffset(sData32, uv, 0, ivec2(1, 0));

return corner;
}

struct ClipData {
ClipRect rect;
ClipCorner top_left;
ClipCorner top_right;
ClipCorner bottom_left;
ClipCorner bottom_right;
};

ClipData fetch_clip(int index) {
ClipData clip;

clip.rect = fetch_clip_rect(index + 0);
clip.top_left = fetch_clip_corner(index + 1);
clip.top_right = fetch_clip_corner(index + 2);
clip.bottom_left = fetch_clip_corner(index + 3);
clip.bottom_right = fetch_clip_corner(index + 4);

return clip;
}

void main(void) {
CacheClipInstance cci = fetch_clip_item(gl_InstanceID);
ClipArea area = fetch_clip_area(cci.render_task_index);
Layer layer = fetch_layer(cci.layer_index);
ClipData clip = fetch_clip(cci.data_index);
vec4 local_rect = clip.rect.rect;

TransformVertexInfo vi = write_clip_tile_vertex(local_rect,
layer,
area);
vLocalRect = vi.clipped_local_rect;
vPos = vi.local_pos;

vClipRect = vec4(local_rect.xy, local_rect.xy + local_rect.zw);
vClipRadius = vec4(clip.top_left.outer_inner_radius.x,
clip.top_right.outer_inner_radius.x,
clip.bottom_right.outer_inner_radius.x,
clip.bottom_left.outer_inner_radius.x);
}
Loading