summaryrefslogtreecommitdiffstats
path: root/gfx/wr/webrender/res/cs_clip_image.glsl
blob: 248af6dbddaf4f1fbef7042108ba76513a79b8de (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
/* 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