1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5#include rect,render_task,gpu_cache,snap,transform
6
7#ifdef WR_VERTEX_SHADER
8
9in int aClipRenderTaskAddress;
10in int aClipTransformId;
11in int aPrimTransformId;
12in int aClipSegment;
13in ivec4 aClipDataResourceAddress;
14in vec2 aClipLocalPos;
15in vec4 aClipTileRect;
16in vec4 aClipDeviceArea;
17in vec4 aClipSnapOffsets;
18
19struct ClipMaskInstance {
20    int render_task_address;
21    int clip_transform_id;
22    int prim_transform_id;
23    ivec2 clip_data_address;
24    ivec2 resource_address;
25    vec2 local_pos;
26    RectWithSize tile_rect;
27    RectWithSize sub_rect;
28    vec4 snap_offsets;
29};
30
31ClipMaskInstance fetch_clip_item() {
32    ClipMaskInstance cmi;
33
34    cmi.render_task_address = aClipRenderTaskAddress;
35    cmi.clip_transform_id = aClipTransformId;
36    cmi.prim_transform_id = aPrimTransformId;
37    cmi.clip_data_address = aClipDataResourceAddress.xy;
38    cmi.resource_address = aClipDataResourceAddress.zw;
39    cmi.local_pos = aClipLocalPos;
40    cmi.tile_rect = RectWithSize(aClipTileRect.xy, aClipTileRect.zw);
41    cmi.sub_rect = RectWithSize(aClipDeviceArea.xy, aClipDeviceArea.zw);
42    cmi.snap_offsets = aClipSnapOffsets;
43
44    return cmi;
45}
46
47struct ClipVertexInfo {
48    vec3 local_pos;
49    RectWithSize clipped_local_rect;
50};
51
52RectWithSize intersect_rect(RectWithSize a, RectWithSize b) {
53    vec4 p = clamp(vec4(a.p0, a.p0 + a.size), b.p0.xyxy, b.p0.xyxy + b.size.xyxy);
54    return RectWithSize(p.xy, max(vec2(0.0), p.zw - p.xy));
55}
56
57// The transformed vertex function that always covers the whole clip area,
58// which is the intersection of all clip instances of a given primitive
59ClipVertexInfo write_clip_tile_vertex(RectWithSize local_clip_rect,
60                                      Transform prim_transform,
61                                      Transform clip_transform,
62                                      ClipArea area,
63                                      RectWithSize sub_rect,
64                                      vec4 snap_offsets) {
65    vec2 device_pos = area.screen_origin + sub_rect.p0 +
66                      aPosition.xy * sub_rect.size;
67
68    // If the primitive we are drawing a clip mask for was snapped, then
69    // remove the effect of that snapping, so that the local position
70    // interpolation below works correctly relative to the clip item.
71    vec2 snap_offset = mix(
72        snap_offsets.xy,
73        snap_offsets.zw,
74        aPosition.xy
75    );
76
77    device_pos -= snap_offset;
78
79    vec2 world_pos = device_pos / area.common_data.device_pixel_scale;
80
81    vec4 pos = prim_transform.m * vec4(world_pos, 0.0, 1.0);
82    pos.xyz /= pos.w;
83
84    vec4 p = get_node_pos(pos.xy, clip_transform);
85    vec3 local_pos = p.xyw * pos.w;
86
87    vec4 vertex_pos = vec4(
88        area.common_data.task_rect.p0 + sub_rect.p0 + aPosition.xy * sub_rect.size,
89        0.0,
90        1.0
91    );
92
93    gl_Position = uTransform * vertex_pos;
94
95    init_transform_vs(vec4(local_clip_rect.p0, local_clip_rect.p0 + local_clip_rect.size));
96
97    ClipVertexInfo vi = ClipVertexInfo(local_pos, local_clip_rect);
98    return vi;
99}
100
101#endif //WR_VERTEX_SHADER
102