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 shared,clip_shared
6
7varying vec3 vLocalPos;
8varying vec2 vUv;
9flat varying vec4 vUvBounds;
10flat varying float vLayer;
11flat varying vec4 vEdge;
12flat varying vec4 vUvBounds_NoClamp;
13flat varying float vClipMode;
14
15#define MODE_STRETCH        0
16#define MODE_SIMPLE         1
17
18#ifdef WR_VERTEX_SHADER
19
20struct BoxShadowData {
21    vec2 src_rect_size;
22    float clip_mode;
23    int stretch_mode_x;
24    int stretch_mode_y;
25    RectWithSize dest_rect;
26};
27
28BoxShadowData fetch_data(ivec2 address) {
29    vec4 data[3] = fetch_from_gpu_cache_3_direct(address);
30    RectWithSize dest_rect = RectWithSize(data[2].xy, data[2].zw);
31    BoxShadowData bs_data = BoxShadowData(
32        data[0].xy,
33        data[0].z,
34        int(data[1].x),
35        int(data[1].y),
36        dest_rect
37    );
38    return bs_data;
39}
40
41void main(void) {
42    ClipMaskInstance cmi = fetch_clip_item();
43    ClipArea area = fetch_clip_area(cmi.render_task_address);
44    Transform clip_transform = fetch_transform(cmi.clip_transform_id);
45    Transform prim_transform = fetch_transform(cmi.prim_transform_id);
46    BoxShadowData bs_data = fetch_data(cmi.clip_data_address);
47    ImageResource res = fetch_image_resource_direct(cmi.resource_address);
48
49    RectWithSize dest_rect = bs_data.dest_rect;
50    dest_rect.p0 += cmi.local_pos;
51
52    ClipVertexInfo vi = write_clip_tile_vertex(
53        dest_rect,
54        prim_transform,
55        clip_transform,
56        area,
57        cmi.sub_rect,
58        cmi.snap_offsets
59    );
60    vLocalPos = vi.local_pos;
61    vLayer = res.layer;
62    vClipMode = bs_data.clip_mode;
63
64    vec2 uv0 = res.uv_rect.p0;
65    vec2 uv1 = res.uv_rect.p1;
66
67    vec2 texture_size = vec2(textureSize(sColor0, 0));
68    vec2 local_pos = vLocalPos.xy / vLocalPos.z;
69
70    switch (bs_data.stretch_mode_x) {
71        case MODE_STRETCH: {
72            vEdge.x = 0.5;
73            vEdge.z = (dest_rect.size.x / bs_data.src_rect_size.x) - 0.5;
74            vUv.x = (local_pos.x - dest_rect.p0.x) / bs_data.src_rect_size.x;
75            break;
76        }
77        case MODE_SIMPLE:
78        default: {
79            vEdge.xz = vec2(1.0);
80            vUv.x = (local_pos.x - dest_rect.p0.x) / dest_rect.size.x;
81            break;
82        }
83    }
84
85    switch (bs_data.stretch_mode_y) {
86        case MODE_STRETCH: {
87            vEdge.y = 0.5;
88            vEdge.w = (dest_rect.size.y / bs_data.src_rect_size.y) - 0.5;
89            vUv.y = (local_pos.y - dest_rect.p0.y) / bs_data.src_rect_size.y;
90            break;
91        }
92        case MODE_SIMPLE:
93        default: {
94            vEdge.yw = vec2(1.0);
95            vUv.y = (local_pos.y - dest_rect.p0.y) / dest_rect.size.y;
96            break;
97        }
98    }
99
100    vUvBounds = vec4(uv0 + vec2(0.5), uv1 - vec2(0.5)) / texture_size.xyxy;
101    vUvBounds_NoClamp = vec4(uv0, uv1) / texture_size.xyxy;
102}
103#endif
104
105#ifdef WR_FRAGMENT_SHADER
106void main(void) {
107    vec2 local_pos = vLocalPos.xy / vLocalPos.z;
108
109    vec2 uv = clamp(vUv.xy, vec2(0.0), vEdge.xy);
110    uv += max(vec2(0.0), vUv.xy - vEdge.zw);
111    uv = mix(vUvBounds_NoClamp.xy, vUvBounds_NoClamp.zw, uv);
112    uv = clamp(uv, vUvBounds.xy, vUvBounds.zw);
113
114    float in_shadow_rect = init_transform_rough_fs(local_pos);
115
116    float texel = TEX_SAMPLE(sColor0, vec3(uv, vLayer)).r;
117
118    float alpha = mix(texel, 1.0 - texel, vClipMode);
119
120    oFragColor = vec4(mix(vClipMode, alpha, in_shadow_rect));
121}
122#endif
123