summaryrefslogtreecommitdiffstats
path: root/gfx/wr/webrender/res/composite.glsl
blob: 4d30685ea1e2bd8f43afbef01d5f9a74ca855045 (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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
/* 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/. */

// Composite a picture cache tile into the framebuffer.

// This shader must remain compatible with ESSL 1, at least for the
// WR_FEATURE_TEXTURE_EXTERNAL_ESSL1 feature, so that it can be used to render
// video on GLES devices without GL_OES_EGL_image_external_essl3 support.
// This means we cannot use textureSize(), int inputs/outputs, etc.

#include shared

#ifdef WR_FEATURE_YUV
#include yuv
#endif

#ifdef WR_FEATURE_YUV
flat varying YUV_PRECISION vec3 vYcbcrBias;
flat varying YUV_PRECISION mat3 vRgbFromDebiasedYcbcr;
// YUV format. Packed in to vector to avoid bug 1630356.
flat varying mediump ivec2 vYuvFormat;

#ifdef SWGL_DRAW_SPAN
flat varying mediump int vRescaleFactor;
#endif
varying highp vec2 vUV_y;
varying highp vec2 vUV_u;
varying highp vec2 vUV_v;
flat varying highp vec4 vUVBounds_y;
flat varying highp vec4 vUVBounds_u;
flat varying highp vec4 vUVBounds_v;
#else
varying highp vec2 vUv;
#ifndef WR_FEATURE_FAST_PATH
flat varying mediump vec4 vColor;
flat varying highp vec4 vUVBounds;
#endif
#ifdef WR_FEATURE_TEXTURE_EXTERNAL_ESSL1
uniform mediump vec2 uTextureSize;
#endif
#endif

#ifdef WR_VERTEX_SHADER
// CPU side data is in CompositeInstance (gpu_types.rs) and is
// converted to GPU data using desc::COMPOSITE (renderer.rs) by
// filling vaos.composite_vao with VertexArrayKind::Composite.
PER_INSTANCE attribute vec4 aLocalRect;
PER_INSTANCE attribute vec4 aDeviceClipRect;
PER_INSTANCE attribute vec4 aColor;
PER_INSTANCE attribute vec4 aParams;
PER_INSTANCE attribute vec4 aTransform;

#ifdef WR_FEATURE_YUV
// YUV treats these as a UV clip rect (clamp)
PER_INSTANCE attribute vec4 aUvRect0;
PER_INSTANCE attribute vec4 aUvRect1;
PER_INSTANCE attribute vec4 aUvRect2;
#else
PER_INSTANCE attribute vec4 aUvRect0;
#endif

vec2 apply_transform(vec2 p, vec4 transform) {
    return p * transform.xy + transform.zw;
}

#ifdef WR_FEATURE_YUV
YuvPrimitive fetch_yuv_primitive() {
    // From ExternalSurfaceDependency::Yuv:
    int color_space = int(aParams.y);
    int yuv_format = int(aParams.z);
    int channel_bit_depth = int(aParams.w);
    return YuvPrimitive(channel_bit_depth, color_space, yuv_format);
}
#endif

void main(void) {
	// Get world position
    vec2 world_p0 = apply_transform(aLocalRect.xy, aTransform);
    vec2 world_p1 = apply_transform(aLocalRect.zw, aTransform);
    vec2 world_pos = mix(world_p0, world_p1, aPosition.xy);

    // Clip the position to the world space clip rect
    vec2 clipped_world_pos = clamp(world_pos, aDeviceClipRect.xy, aDeviceClipRect.zw);

    // Derive the normalized UV from the clipped vertex position
    vec2 uv = (clipped_world_pos - world_p0) / (world_p1 - world_p0);

#ifdef WR_FEATURE_YUV
    YuvPrimitive prim = fetch_yuv_primitive();

#ifdef SWGL_DRAW_SPAN
    // swgl_commitTextureLinearYUV needs to know the color space specifier and
    // also needs to know how many bits of scaling are required to normalize
    // HDR textures. Note that MSB HDR formats don't need renormalization.
    vRescaleFactor = 0;
    if (prim.channel_bit_depth > 8 && prim.yuv_format != YUV_FORMAT_P010) {
        vRescaleFactor = 16 - prim.channel_bit_depth;
    }
#endif

    YuvColorMatrixInfo mat_info = get_rgb_from_ycbcr_info(prim);
    vYcbcrBias = mat_info.ycbcr_bias;
    vRgbFromDebiasedYcbcr = mat_info.rgb_from_debiased_ycbrc;

    vYuvFormat.x = prim.yuv_format;

    write_uv_rect(
        aUvRect0.xy,
        aUvRect0.zw,
        uv,
        TEX_SIZE_YUV(sColor0),
        vUV_y,
        vUVBounds_y
    );
    write_uv_rect(
        aUvRect1.xy,
        aUvRect1.zw,
        uv,
        TEX_SIZE_YUV(sColor1),
        vUV_u,
        vUVBounds_u
    );
    write_uv_rect(
        aUvRect2.xy,
        aUvRect2.zw,
        uv,
        TEX_SIZE_YUV(sColor2),
        vUV_v,
        vUVBounds_v
    );
#else
    uv = mix(aUvRect0.xy, aUvRect0.zw, uv);
    // The uvs may be inverted, so use the min and max for the bounds
    vec4 uvBounds = vec4(min(aUvRect0.xy, aUvRect0.zw), max(aUvRect0.xy, aUvRect0.zw));
    int rescale_uv = int(aParams.y);
    if (rescale_uv == 1)
    {
        // using an atlas, so UVs are in pixels, and need to be
        // normalized and clamped.
#if defined(WR_FEATURE_TEXTURE_RECT)
        vec2 texture_size = vec2(1.0, 1.0);
#elif defined(WR_FEATURE_TEXTURE_EXTERNAL_ESSL1)
        vec2 texture_size = uTextureSize;
#else
        vec2 texture_size = vec2(TEX_SIZE(sColor0));
#endif
        uvBounds += vec4(0.5, 0.5, -0.5, -0.5);
    #ifndef WR_FEATURE_TEXTURE_RECT
        uv /= texture_size;
        uvBounds /= texture_size.xyxy;
    #endif
    }

    vUv = uv;
#ifndef WR_FEATURE_FAST_PATH
    vUVBounds = uvBounds;
    // Pass through color
    vColor = aColor;
#endif
#endif

    gl_Position = uTransform * vec4(clipped_world_pos, 0.0, 1.0);
}
#endif

#ifdef WR_FRAGMENT_SHADER
void main(void) {
#ifdef WR_FEATURE_YUV
    vec4 color = sample_yuv(
        vYuvFormat.x,
        vYcbcrBias,
        vRgbFromDebiasedYcbcr,
        vUV_y,
        vUV_u,
        vUV_v,
        vUVBounds_y,
        vUVBounds_u,
        vUVBounds_v
    );
#else
    // The color is just the texture sample modulated by a supplied color.
    // In the fast path we avoid clamping the UV coordinates and modulating by the color.
#ifdef WR_FEATURE_FAST_PATH
    vec2 uv = vUv;
#else
    vec2 uv = clamp(vUv, vUVBounds.xy, vUVBounds.zw);
#endif
    vec4 texel = TEX_SAMPLE(sColor0, uv);
#ifdef WR_FEATURE_FAST_PATH
    vec4 color = texel;
#else
    vec4 color = vColor * texel;
#endif
#endif
    write_output(color);
}

#ifdef SWGL_DRAW_SPAN
void swgl_drawSpanRGBA8() {
#ifdef WR_FEATURE_YUV
    if (vYuvFormat.x == YUV_FORMAT_PLANAR) {
        swgl_commitTextureLinearYUV(sColor0, vUV_y, vUVBounds_y,
                                    sColor1, vUV_u, vUVBounds_u,
                                    sColor2, vUV_v, vUVBounds_v,
                                    vYcbcrBias,
                                    vRgbFromDebiasedYcbcr,
                                    vRescaleFactor);
    } else if (vYuvFormat.x == YUV_FORMAT_NV12 || vYuvFormat.x == YUV_FORMAT_P010) {
        swgl_commitTextureLinearYUV(sColor0, vUV_y, vUVBounds_y,
                                    sColor1, vUV_u, vUVBounds_u,
                                    vYcbcrBias,
                                    vRgbFromDebiasedYcbcr,
                                    vRescaleFactor);
    } else if (vYuvFormat.x == YUV_FORMAT_INTERLEAVED) {
        swgl_commitTextureLinearYUV(sColor0, vUV_y, vUVBounds_y,
                                    vYcbcrBias,
                                    vRgbFromDebiasedYcbcr,
                                    vRescaleFactor);
    }
#else
#ifdef WR_FEATURE_FAST_PATH
    vec4 color = vec4(1.0);
#ifdef WR_FEATURE_TEXTURE_RECT
    vec4 uvBounds = vec4(vec2(0.0), vec2(textureSize(sColor0)));
#else
    vec4 uvBounds = vec4(0.0, 0.0, 1.0, 1.0);
#endif
#else
    vec4 color = vColor;
    vec4 uvBounds = vUVBounds;
#endif
    if (color != vec4(1.0)) {
        swgl_commitTextureColorRGBA8(sColor0, vUv, uvBounds, color);
    } else {
        swgl_commitTextureRGBA8(sColor0, vUv, uvBounds);
    }
#endif
}
#endif

#endif