diff options
Diffstat (limited to 'gfx/wr/webrender/res/composite.glsl')
-rw-r--r-- | gfx/wr/webrender/res/composite.glsl | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/gfx/wr/webrender/res/composite.glsl b/gfx/wr/webrender/res/composite.glsl new file mode 100644 index 0000000000..dbd799f129 --- /dev/null +++ b/gfx/wr/webrender/res/composite.glsl @@ -0,0 +1,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 +YUV_PRECISION flat varying vec3 vYcbcrBias; +YUV_PRECISION flat varying mat3 vRgbFromDebiasedYcbcr; +// YUV format. Packed in to vector to avoid bug 1630356. +flat varying ivec2 vYuvFormat; + +#ifdef SWGL_DRAW_SPAN +flat varying int vRescaleFactor; +#endif +varying vec2 vUV_y; +varying vec2 vUV_u; +varying vec2 vUV_v; +flat varying vec4 vUVBounds_y; +flat varying vec4 vUVBounds_u; +flat varying vec4 vUVBounds_v; +#else +varying vec2 vUv; +#ifndef WR_FEATURE_FAST_PATH +flat varying vec4 vColor; +flat varying vec4 vUVBounds; +#endif +#ifdef WR_FEATURE_TEXTURE_EXTERNAL_ESSL1 +uniform 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, aParams.x /* z_id */, 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 |