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
|
/* 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 vec2 vLocalPos;
varying vec2 vClipMaskImageUv;
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 base;
RectWithEndpoint tile_rect;
ivec2 resource_address;
RectWithEndpoint local_rect;
};
ClipMaskInstanceImage fetch_clip_item() {
ClipMaskInstanceImage cmi;
cmi.base = fetch_clip_item_common();
cmi.tile_rect = RectWithEndpoint(aClipTileRect.xy, aClipTileRect.zw);
cmi.resource_address = aClipDataResourceAddress;
cmi.local_rect = RectWithEndpoint(aClipLocalRect.xy, aClipLocalRect.zw);
return cmi;
}
struct ClipImageVertexInfo {
vec2 local_pos;
vec4 world_pos;
};
// This differs from write_clip_tile_vertex in that we forward transform the
// primitive's local-space tile rect into the target space. We use scissoring
// to ensure that the primitive does not draw outside the target bounds.
ClipImageVertexInfo write_clip_image_vertex(RectWithEndpoint tile_rect,
RectWithEndpoint local_clip_rect,
Transform prim_transform,
Transform clip_transform,
RectWithEndpoint sub_rect,
vec2 task_origin,
vec2 screen_origin,
float device_pixel_scale) {
vec2 local_pos = rect_clamp(local_clip_rect, mix(tile_rect.p0, tile_rect.p1, aPosition.xy));
vec4 world_pos = prim_transform.m * vec4(local_pos, 0.0, 1.0);
vec4 final_pos = vec4(
world_pos.xy * device_pixel_scale + (task_origin - screen_origin) * world_pos.w,
0.0,
world_pos.w
);
gl_Position = uTransform * final_pos;
init_transform_vs(
clip_transform.is_axis_aligned
? vec4(vec2(-1.0e16), vec2(1.0e16))
: vec4(local_clip_rect.p0, local_clip_rect.p1));
ClipImageVertexInfo vi = ClipImageVertexInfo(local_pos, world_pos);
return vi;
}
void main(void) {
ClipMaskInstanceImage cmi = fetch_clip_item();
Transform clip_transform = fetch_transform(cmi.base.clip_transform_id);
Transform prim_transform = fetch_transform(cmi.base.prim_transform_id);
ImageSource res = fetch_image_source_direct(cmi.resource_address);
ClipImageVertexInfo vi = write_clip_image_vertex(
cmi.tile_rect,
cmi.local_rect,
prim_transform,
clip_transform,
cmi.base.sub_rect,
cmi.base.task_origin,
cmi.base.screen_origin,
cmi.base.device_pixel_scale
);
vLocalPos = vi.local_pos;
vec2 uv = (vi.local_pos - cmi.tile_rect.p0) / rect_size(cmi.tile_rect);
vec2 texture_size = vec2(TEX_SIZE(sColor0));
vec4 uv_rect = vec4(res.uv_rect.p0, res.uv_rect.p1);
vClipMaskImageUv = mix(uv_rect.xy, uv_rect.zw, uv) / texture_size;
// applying a half-texel offset to the UV boundaries to prevent linear samples from the outside
vClipMaskUvInnerRect = (uv_rect + vec4(0.5, 0.5, -0.5, -0.5)) / texture_size.xyxy;
}
#endif
#ifdef WR_FRAGMENT_SHADER
void main(void) {
float alpha = init_transform_rough_fs(vLocalPos);
vec2 source_uv = clamp(vClipMaskImageUv, vClipMaskUvInnerRect.xy, vClipMaskUvInnerRect.zw);
float clip_alpha = texture(sColor0, source_uv).r; //careful: texture has type A8
oFragColor = vec4(mix(1.0, clip_alpha, alpha), 0.0, 0.0, 1.0);
}
#ifdef SWGL_DRAW_SPAN
void swgl_drawSpanR8() {
if (has_valid_transform_bounds()) {
return;
}
swgl_commitTextureLinearR8(sColor0, vClipMaskImageUv, vClipMaskUvInnerRect);
}
#endif
#endif
|