Skip to content

Removes the tiling and render task stack from clipping, draws clips in regions of interest. #685

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

Closed
wants to merge 5 commits into from
Closed
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
31 changes: 30 additions & 1 deletion sample/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,22 @@ fn main() {
let mut builder = webrender_traits::DisplayListBuilder::new(pipeline_id);

let bounds = LayoutRect::new(LayoutPoint::new(0.0, 0.0), LayoutSize::new(width as f32, height as f32));

// Push outer stacking context.
// No (effective) clip on the stacking context
let clip_region = {
builder.new_clip_region(&bounds, vec![], None)
};
builder.push_stacking_context(webrender_traits::ScrollPolicy::Scrollable,
bounds,
clip_region,
0,
&LayoutTransform::identity(),
&LayoutTransform::identity(),
webrender_traits::MixBlendMode::Normal,
Vec::new());


let clip_region = {
let complex = webrender_traits::ComplexClipRegion::new(
LayoutRect::new(LayoutPoint::new(50.0, 50.0), LayoutSize::new(100.0, 100.0)),
Expand Down Expand Up @@ -151,7 +167,6 @@ fn main() {
border_side,
webrender_traits::BorderRadius::uniform(20.0));


if false { // draw text?
let font_bytes = load_file("res/FreeSans.ttf");
let font_key = api.add_raw_font(font_bytes);
Expand Down Expand Up @@ -232,6 +247,20 @@ fn main() {

builder.pop_stacking_context();

let two_clips = {
let complex1 = webrender_traits::ComplexClipRegion::new(
LayoutRect::new(LayoutPoint::new(400.0, 100.0), LayoutSize::new(50.0, 100.0)),
webrender_traits::BorderRadius::uniform(10.0));
let complex2 = webrender_traits::ComplexClipRegion::new(
LayoutRect::new(LayoutPoint::new(400.0, 100.0), LayoutSize::new(100.0, 50.0)),
webrender_traits::BorderRadius::uniform(20.0));
builder.new_clip_region(&bounds, vec![complex1, complex2], None)
};
builder.push_rect(LayoutRect::new(LayoutPoint::new(400.0, 100.0), LayoutSize::new(100.0, 100.0)),
two_clips,
ColorF::new(1.0, 1.0, 0.0, 1.0));
builder.pop_stacking_context();

api.set_root_display_list(
Some(root_background_color),
epoch,
Expand Down
48 changes: 39 additions & 9 deletions webrender/res/clip_shared.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,11 @@
in int aClipRenderTaskIndex;
in int aClipLayerIndex;
in int aClipDataIndex;
in int aClipBaseTaskIndex;

struct CacheClipInstance {
int render_task_index;
int layer_index;
int data_index;
int base_task_index;
};

CacheClipInstance fetch_clip_item(int index) {
Expand All @@ -23,30 +21,62 @@ CacheClipInstance fetch_clip_item(int index) {
cci.render_task_index = aClipRenderTaskIndex;
cci.layer_index = aClipLayerIndex;
cci.data_index = aClipDataIndex;
cci.base_task_index = aClipBaseTaskIndex;

return cci;
}

// The transformed vertex function that always covers the whole clip area,
// which is the intersection of all clip instances of a given primitive
TransformVertexInfo write_clip_tile_vertex(vec4 local_clip_rect,
TransformVertexInfo write_clip_tile_vertex(vec4 local_rect,
Layer layer,
ClipArea area) {
vec2 lp0_base = local_clip_rect.xy;
vec2 lp1_base = local_clip_rect.xy + local_clip_rect.zw;
vec2 lp0_base = local_rect.xy;
vec2 lp1_base = local_rect.xy + local_rect.zw;

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);

vec2 final_pos = mix(area.task_bounds.xy, area.task_bounds.zw, aPosition.xy);
vec2 p0 = lp0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand why we need all the transform logic back here. I assume it's related to this quote:

The 2nd commit makes the clip shader only run in the regions of interest for a clip mask. This makes clip mask generation time negligible on any sites I've tried (e.g. GH.com drops from 9ms to ~3ms on my test setup).

If a clip instance is only going to touch the pixels related to it, then it would not mark pixels outside of it as transparent, some of those pixels might have been written by the previous clip instances in the stack. Unless... we do something very clever with the depth/stencil buffer for the clip masks. (unfinished idea here)

vec2 p1 = vec2(lp1.x, lp0.y);
vec2 p2 = vec2(lp0.x, lp1.y);
vec2 p3 = lp1;

vec4 t0 = layer.transform * vec4(p0, 0, 1);
vec4 t1 = layer.transform * vec4(p1, 0, 1);
vec4 t2 = layer.transform * vec4(p2, 0, 1);
vec4 t3 = layer.transform * vec4(p3, 0, 1);

vec2 tp0 = t0.xy / t0.w;
vec2 tp1 = t1.xy / t1.w;
vec2 tp2 = t2.xy / t2.w;
vec2 tp3 = t3.xy / t3.w;

// compute a CSS space aligned bounding box
vec2 min_pos = min(min(tp0.xy, tp1.xy), min(tp2.xy, tp3.xy));
vec2 max_pos = max(max(tp0.xy, tp1.xy), max(tp2.xy, tp3.xy));

// clamp to the tile boundaries, in device space
vec2 min_pos_clamped = clamp(min_pos * uDevicePixelRatio,
area.screen_origin_target_index.xy,
area.screen_origin_target_index.xy + area.task_bounds.zw - area.task_bounds.xy);

vec2 max_pos_clamped = clamp(max_pos * uDevicePixelRatio,
area.screen_origin_target_index.xy,
area.screen_origin_target_index.xy + area.task_bounds.zw - area.task_bounds.xy);

// compute the device space position of this vertex
vec2 clamped_pos = mix(min_pos_clamped,
max_pos_clamped,
aPosition.xy);

// 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);
// apply the task offset
vec2 final_pos = clamped_pos - area.screen_origin_target_index.xy + area.task_bounds.xy;

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

return TransformVertexInfo(layer_pos.xyw, clamped_pos, clipped_local_rect);
}
Expand Down
8 changes: 0 additions & 8 deletions webrender/res/cs_clip_copy.fs.glsl

This file was deleted.

19 changes: 0 additions & 19 deletions webrender/res/cs_clip_copy.vs.glsl

This file was deleted.

29 changes: 4 additions & 25 deletions webrender/res/cs_clip_rectangle.fs.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,16 @@
* 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));
// TODO(gw): Support ellipse clip!
float d = max(0.0, distance(pos, vClipRefPoint_Radius.xy));
d = (d - vClipRefPoint_Radius.z + nudge) / pixels_per_fragment;

// 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);
return 1.0 - smoothstep(0.0, 1.0, d);
}


void main(void) {
float alpha = 1.f;
vec2 local_pos = init_transform_fs(vPos, vLocalRect, alpha);
Expand Down
2 changes: 1 addition & 1 deletion webrender/res/cs_clip_rectangle.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@
varying vec3 vPos;
flat varying vec4 vLocalRect;
flat varying vec4 vClipRect;
flat varying vec4 vClipRadius;
flat varying vec4 vClipRefPoint_Radius;
50 changes: 5 additions & 45 deletions webrender/res/cs_clip_rectangle.vs.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,9 @@
* 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;
vec4 clip_ref_radius;
};

ClipCorner fetch_clip_corner(int index) {
Expand All @@ -31,37 +14,17 @@ ClipCorner fetch_clip_corner(int index) {
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));
corner.clip_ref_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;
ClipCorner clip = fetch_clip_corner(cci.data_index);
vec4 local_rect = clip.rect;

TransformVertexInfo vi = write_clip_tile_vertex(local_rect,
layer,
Expand All @@ -70,8 +33,5 @@ void main(void) {
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);
vClipRefPoint_Radius = clip.clip_ref_radius;
}
2 changes: 0 additions & 2 deletions webrender/src/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,6 @@ impl VertexFormat {
for (i, &attrib) in [ClipAttribute::RenderTaskIndex,
ClipAttribute::LayerIndex,
ClipAttribute::DataIndex,
ClipAttribute::BaseTaskIndex,
].into_iter().enumerate() {
gl::enable_vertex_attrib_array(attrib as gl::GLuint);
gl::vertex_attrib_divisor(attrib as gl::GLuint, 1);
Expand Down Expand Up @@ -401,7 +400,6 @@ impl Program {
gl::bind_attrib_location(self.id, ClipAttribute::RenderTaskIndex as gl::GLuint, "aClipRenderTaskIndex");
gl::bind_attrib_location(self.id, ClipAttribute::LayerIndex as gl::GLuint, "aClipLayerIndex");
gl::bind_attrib_location(self.id, ClipAttribute::DataIndex as gl::GLuint, "aClipDataIndex");
gl::bind_attrib_location(self.id, ClipAttribute::BaseTaskIndex as gl::GLuint, "aClipBaseTaskIndex");

gl::link_program(self.id);
if gl::get_program_iv(self.id, gl::LINK_STATUS) == (0 as gl::GLint) {
Expand Down
1 change: 0 additions & 1 deletion webrender/src/internal_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,6 @@ pub enum ClipAttribute {
RenderTaskIndex,
LayerIndex,
DataIndex,
BaseTaskIndex,
}

#[derive(Debug, Clone, Copy)]
Expand Down
Loading