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,prim_shared
6
7// interpolated UV coordinates to sample.
8varying vec2 vUv;
9// X = layer index to sample, Y = flag to allow perspective interpolation of UV.
10flat varying vec2 vLayerAndPerspective;
11flat varying vec4 vUvSampleBounds;
12
13#ifdef WR_VERTEX_SHADER
14struct SplitGeometry {
15    vec2 local[4];
16};
17
18SplitGeometry fetch_split_geometry(int address) {
19    ivec2 uv = get_gpu_cache_uv(address);
20
21    vec4 data0 = TEXEL_FETCH(sGpuCache, uv, 0, ivec2(0, 0));
22    vec4 data1 = TEXEL_FETCH(sGpuCache, uv, 0, ivec2(1, 0));
23
24    SplitGeometry geo;
25    geo.local = vec2[4](
26        data0.xy,
27        data0.zw,
28        data1.xy,
29        data1.zw
30    );
31
32    return geo;
33}
34
35vec2 bilerp(vec2 a, vec2 b, vec2 c, vec2 d, float s, float t) {
36    vec2 x = mix(a, b, t);
37    vec2 y = mix(c, d, t);
38    return mix(x, y, s);
39}
40
41struct SplitCompositeInstance {
42    int prim_header_index;
43    int polygons_address;
44    float z;
45};
46
47SplitCompositeInstance fetch_composite_instance() {
48    SplitCompositeInstance ci;
49
50    ci.prim_header_index = aData.x;
51    ci.polygons_address = aData.y;
52    ci.z = float(aData.z);
53
54    return ci;
55}
56
57void main(void) {
58    SplitCompositeInstance ci = fetch_composite_instance();
59    SplitGeometry geometry = fetch_split_geometry(ci.polygons_address);
60    PrimitiveHeader ph = fetch_prim_header(ci.prim_header_index);
61    PictureTask dest_task = fetch_picture_task(ph.render_task_index);
62    Transform transform = fetch_transform(ph.transform_id);
63    ImageResource res = fetch_image_resource(ph.user_data.x);
64    ClipArea clip_area = fetch_clip_area(ph.clip_task_index);
65
66    vec2 dest_origin = dest_task.common_data.task_rect.p0 -
67                       dest_task.content_origin;
68
69    vec2 local_pos = bilerp(geometry.local[0], geometry.local[1],
70                            geometry.local[3], geometry.local[2],
71                            aPosition.y, aPosition.x);
72    vec4 world_pos = transform.m * vec4(local_pos, 0.0, 1.0);
73
74    vec4 final_pos = vec4(
75        dest_origin * world_pos.w + world_pos.xy * dest_task.common_data.device_pixel_scale,
76        world_pos.w * ci.z,
77        world_pos.w
78    );
79
80    write_clip(
81        world_pos,
82        vec2(0.0),
83        clip_area
84    );
85
86    gl_Position = uTransform * final_pos;
87
88    vec2 texture_size = vec2(textureSize(sPrevPassColor, 0));
89    vec2 uv0 = res.uv_rect.p0;
90    vec2 uv1 = res.uv_rect.p1;
91
92    vec2 min_uv = min(uv0, uv1);
93    vec2 max_uv = max(uv0, uv1);
94
95    vUvSampleBounds = vec4(
96        min_uv + vec2(0.5),
97        max_uv - vec2(0.5)
98    ) / texture_size.xyxy;
99
100    vec2 f = (local_pos - ph.local_rect.p0) / ph.local_rect.size;
101    f = get_image_quad_uv(ph.user_data.x, f);
102    vec2 uv = mix(uv0, uv1, f);
103    float perspective_interpolate = float(ph.user_data.y);
104
105    vUv = uv / texture_size * mix(gl_Position.w, 1.0, perspective_interpolate);
106    vLayerAndPerspective = vec2(res.layer, perspective_interpolate);
107}
108#endif
109
110#ifdef WR_FRAGMENT_SHADER
111void main(void) {
112    float alpha = do_clip();
113    float perspective_divisor = mix(gl_FragCoord.w, 1.0, vLayerAndPerspective.y);
114    vec2 uv = clamp(vUv * perspective_divisor, vUvSampleBounds.xy, vUvSampleBounds.zw);
115    oFragColor = alpha * textureLod(sPrevPassColor, vec3(uv, vLayerAndPerspective.x), 0.0);
116}
117#endif
118