diff options
Diffstat (limited to 'gfx/wr/webrender/res/cs_clip_image.glsl')
-rw-r--r-- | gfx/wr/webrender/res/cs_clip_image.glsl | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/gfx/wr/webrender/res/cs_clip_image.glsl b/gfx/wr/webrender/res/cs_clip_image.glsl new file mode 100644 index 0000000000..248af6dbdd --- /dev/null +++ b/gfx/wr/webrender/res/cs_clip_image.glsl @@ -0,0 +1,83 @@ +/* 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/. */ + +#include shared,clip_shared + +varying vec4 vLocalPos; +varying vec2 vClipMaskImageUv; + +flat varying vec4 vClipMaskUvRect; +flat varying vec4 vClipMaskUvInnerRect; + +#ifdef WR_VERTEX_SHADER + +PER_INSTANCE in vec4 aClipTileRect; +PER_INSTANCE in ivec2 aClipDataResourceAddress; +PER_INSTANCE in vec4 aClipLocalRect; + +struct ClipMaskInstanceImage { + ClipMaskInstanceCommon shared; + RectWithSize tile_rect; + ivec2 resource_address; + RectWithSize local_rect; +}; + +ClipMaskInstanceImage fetch_clip_item() { + ClipMaskInstanceImage cmi; + + cmi.shared = fetch_clip_item_common(); + + cmi.tile_rect = RectWithSize(aClipTileRect.xy, aClipTileRect.zw); + cmi.resource_address = aClipDataResourceAddress; + cmi.local_rect = RectWithSize(aClipLocalRect.xy, aClipLocalRect.zw); + + return cmi; +} + +void main(void) { + ClipMaskInstanceImage cmi = fetch_clip_item(); + Transform clip_transform = fetch_transform(cmi.shared.clip_transform_id); + Transform prim_transform = fetch_transform(cmi.shared.prim_transform_id); + ImageResource res = fetch_image_resource_direct(cmi.resource_address); + + ClipVertexInfo vi = write_clip_tile_vertex( + cmi.local_rect, + prim_transform, + clip_transform, + cmi.shared.sub_rect, + cmi.shared.task_origin, + cmi.shared.screen_origin, + cmi.shared.device_pixel_scale + ); + vLocalPos = vi.local_pos; + vClipMaskImageUv = (vi.local_pos.xy - cmi.tile_rect.p0 * vi.local_pos.w) / 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 + vec4 inner_rect = vec4(res.uv_rect.p0, res.uv_rect.p1); + vClipMaskUvInnerRect = (inner_rect + vec4(0.5, 0.5, -0.5, -0.5)) / texture_size.xyxy; +} +#endif + +#ifdef WR_FRAGMENT_SHADER +void main(void) { + vec2 local_pos = vLocalPos.xy / vLocalPos.w; + float alpha = vLocalPos.w > 0.0 ? init_transform_fs(local_pos) : 0.0; + + // TODO: Handle repeating masks? + vec2 clamped_mask_uv = clamp(vClipMaskImageUv, vec2(0.0, 0.0), vLocalPos.ww); + + // Ensure we don't draw outside of our tile. + // FIXME(emilio): Can we do this earlier? + if (clamped_mask_uv != vClipMaskImageUv) + discard; + + vec2 source_uv = clamp( + clamped_mask_uv / vLocalPos.w * vClipMaskUvRect.zw + vClipMaskUvRect.xy, + vClipMaskUvInnerRect.xy, vClipMaskUvInnerRect.zw); + float clip_alpha = texture(sColor0, source_uv).r; //careful: texture has type A8 + oFragColor = vec4(alpha * clip_alpha, 1.0, 1.0, 1.0); +} +#endif |