summaryrefslogtreecommitdiffstats
path: root/gfx/wr/webrender/res/cs_clip_box_shadow.glsl
blob: cc8252fdb9cf9c4a91e0b4a4832644dbf1ccea3f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/* 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 vUv;
flat varying vec4 vUvBounds;
flat varying float vLayer;
flat varying vec4 vEdge;
flat varying vec4 vUvBounds_NoClamp;
flat varying float vClipMode;

#define MODE_STRETCH        0
#define MODE_SIMPLE         1

#ifdef WR_VERTEX_SHADER

PER_INSTANCE in ivec2 aClipDataResourceAddress;
PER_INSTANCE in vec2 aClipSrcRectSize;
PER_INSTANCE in int aClipMode;
PER_INSTANCE in ivec2 aStretchMode;
PER_INSTANCE in vec4 aClipDestRect;

struct ClipMaskInstanceBoxShadow {
    ClipMaskInstanceCommon shared;
    ivec2 resource_address;
};

ClipMaskInstanceBoxShadow fetch_clip_item() {
    ClipMaskInstanceBoxShadow cmi;

    cmi.shared = fetch_clip_item_common();
    cmi.resource_address = aClipDataResourceAddress;

    return cmi;
}

struct BoxShadowData {
    vec2 src_rect_size;
    int clip_mode;
    int stretch_mode_x;
    int stretch_mode_y;
    RectWithSize dest_rect;
};

BoxShadowData fetch_data() {
    BoxShadowData bs_data = BoxShadowData(
        aClipSrcRectSize,
        aClipMode,
        aStretchMode.x,
        aStretchMode.y,
        RectWithSize(aClipDestRect.xy, aClipDestRect.zw)
    );
    return bs_data;
}

void main(void) {
    ClipMaskInstanceBoxShadow cmi = fetch_clip_item();
    Transform clip_transform = fetch_transform(cmi.shared.clip_transform_id);
    Transform prim_transform = fetch_transform(cmi.shared.prim_transform_id);
    BoxShadowData bs_data = fetch_data();
    ImageResource res = fetch_image_resource_direct(cmi.resource_address);

    RectWithSize dest_rect = bs_data.dest_rect;

    ClipVertexInfo vi = write_clip_tile_vertex(
        dest_rect,
        prim_transform,
        clip_transform,
        cmi.shared.sub_rect,
        cmi.shared.task_origin,
        cmi.shared.screen_origin,
        cmi.shared.device_pixel_scale
    );
    vLayer = res.layer;
    vClipMode = float(bs_data.clip_mode);

    vec2 texture_size = vec2(textureSize(sColor0, 0));
    vec2 local_pos = vi.local_pos.xy / vi.local_pos.w;
    vLocalPos = vi.local_pos;

    switch (bs_data.stretch_mode_x) {
        case MODE_STRETCH: {
            vEdge.x = 0.5;
            vEdge.z = (dest_rect.size.x / bs_data.src_rect_size.x) - 0.5;
            vUv.x = (local_pos.x - dest_rect.p0.x) / bs_data.src_rect_size.x;
            break;
        }
        case MODE_SIMPLE:
        default: {
            vEdge.xz = vec2(1.0);
            vUv.x = (local_pos.x - dest_rect.p0.x) / dest_rect.size.x;
            break;
        }
    }

    switch (bs_data.stretch_mode_y) {
        case MODE_STRETCH: {
            vEdge.y = 0.5;
            vEdge.w = (dest_rect.size.y / bs_data.src_rect_size.y) - 0.5;
            vUv.y = (local_pos.y - dest_rect.p0.y) / bs_data.src_rect_size.y;
            break;
        }
        case MODE_SIMPLE:
        default: {
            vEdge.yw = vec2(1.0);
            vUv.y = (local_pos.y - dest_rect.p0.y) / dest_rect.size.y;
            break;
        }
    }

    vUv *= vi.local_pos.w;
    vec2 uv0 = res.uv_rect.p0;
    vec2 uv1 = res.uv_rect.p1;
    vUvBounds = vec4(uv0 + vec2(0.5), uv1 - vec2(0.5)) / texture_size.xyxy;
    vUvBounds_NoClamp = vec4(uv0, uv1) / texture_size.xyxy;
}
#endif

#ifdef WR_FRAGMENT_SHADER
void main(void) {
    vec2 uv_linear = vUv / vLocalPos.w;
    vec2 uv = clamp(uv_linear, vec2(0.0), vEdge.xy);
    uv += max(vec2(0.0), uv_linear - vEdge.zw);
    uv = mix(vUvBounds_NoClamp.xy, vUvBounds_NoClamp.zw, uv);
    uv = clamp(uv, vUvBounds.xy, vUvBounds.zw);

    float in_shadow_rect = init_transform_rough_fs(vLocalPos.xy / vLocalPos.w);

    float texel = TEX_SAMPLE(sColor0, vec3(uv, vLayer)).r;

    float alpha = mix(texel, 1.0 - texel, vClipMode);
    float result = vLocalPos.w > 0.0 ? mix(vClipMode, alpha, in_shadow_rect) : 0.0;

    oFragColor = vec4(result);
}
#endif