Source code

Revision control

Copy as Markdown

Other Tools

/* 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
#ifndef WR_FEATURE_FAST_PATH
// Parameters for compositor clip
varying highp vec2 vNormalizedWorldPos;
flat varying highp vec2 vRoundedClipParams;
flat varying highp vec4 vRoundedClipRadii;
#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 aDeviceRect;
PER_INSTANCE attribute vec4 aDeviceClipRect;
PER_INSTANCE attribute vec4 aColor;
PER_INSTANCE attribute vec4 aParams;
PER_INSTANCE attribute vec2 aFlip;
#ifndef WR_FEATURE_FAST_PATH
PER_INSTANCE attribute vec4 aDeviceRoundedClipRect;
PER_INSTANCE attribute vec4 aDeviceRoundedClipRadii;
#endif
#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
#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) {
// Flip device rect if required
vec4 device_rect = mix(aDeviceRect.xyzw, aDeviceRect.zwxy, aFlip.xyxy);
// Get world position
vec2 world_pos = mix(device_rect.xy, device_rect.zw, aPosition.xy);
// Clip the position to the world space clip rect
vec2 clipped_world_pos = clamp(world_pos, aDeviceClipRect.xy, aDeviceClipRect.zw);
#ifndef WR_FEATURE_FAST_PATH
vec2 half_clip_box_size = 0.5 * (aDeviceRoundedClipRect.zw - aDeviceRoundedClipRect.xy);
vNormalizedWorldPos = aDeviceRoundedClipRect.xy + half_clip_box_size - clipped_world_pos;
vRoundedClipParams = half_clip_box_size;
vRoundedClipRadii = aDeviceRoundedClipRadii;
#endif
// Derive the normalized UV from the clipped vertex position
vec2 uv = (clipped_world_pos - device_rect.xy) / (device_rect.zw - device_rect.xy);
#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));
if (int(aParams.y) == UV_TYPE_UNNORMALIZED) {
// 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
#ifndef WR_FEATURE_FAST_PATH
// Notes:
// * pos is centered in the origin (so 0,0 is the center of the box).
// * The border radii must not be larger than half_box_size.
float sd_round_box(in vec2 pos, in vec2 half_box_size, in vec4 radii) {
radii.xy = (pos.x > 0.0) ? radii.xy : radii.zw;
radii.x = (pos.y > 0.0) ? radii.x : radii.y;
vec2 q = abs(pos) - half_box_size + radii.x;
return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - radii.x;
}
#endif
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
// TODO(gw): Do we need to support this on ESSL1?
#ifndef WR_FEATURE_TEXTURE_EXTERNAL_ESSL1
#ifndef WR_FEATURE_FAST_PATH
// Apply compositor clip
float aa_range = compute_aa_range(vNormalizedWorldPos);
float dist = sd_round_box(
vNormalizedWorldPos,
vRoundedClipParams,
vRoundedClipRadii
);
// Compute AA for the given dist and range.
float clip_alpha = distance_aa(aa_range, dist);
// Apply clip alpha
color *= clip_alpha;
#endif
#endif
write_output(color);
}
#ifdef SWGL_DRAW_SPAN
void swgl_drawSpanRGBA8() {
#ifndef WR_FEATURE_FAST_PATH
// If there is per-fragment clipping to do, we need to bail
// out of the span shader.
if (any(greaterThan(vRoundedClipRadii, vec4(0.0)))) {
return;
}
#endif // WR_FEATURE_FAST_PATH
#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 // SWGL_DRAW_SPAN
#endif