diff options
Diffstat (limited to 'gfx/wr/webrender/res/composite.glsl')
-rw-r--r-- | gfx/wr/webrender/res/composite.glsl | 272 |
1 files changed, 272 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..8f612e2a92 --- /dev/null +++ b/gfx/wr/webrender/res/composite.glsl @@ -0,0 +1,272 @@ +/* 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. + +#include shared,yuv + +#ifdef WR_FEATURE_YUV +flat varying mat3 vYuvColorMatrix; +flat varying vec3 vYuvOffsetVector; +flat varying float vYuvCoefficient; +flat varying int vYuvFormat; +flat varying vec3 vYuvLayers; +#ifdef SWGL +flat varying int vYuvColorSpace; +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 +flat varying vec4 vColor; +flat varying float vLayer; +varying vec2 vUv; +flat varying vec4 vUVBounds; +#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 in vec4 aDeviceRect; +PER_INSTANCE in vec4 aDeviceClipRect; +PER_INSTANCE in vec4 aColor; +PER_INSTANCE in vec4 aParams; +PER_INSTANCE in vec3 aTextureLayers; + +#ifdef WR_FEATURE_YUV +// YUV treats these as a UV clip rect (clamp) +PER_INSTANCE in vec4 aUvRect0; +PER_INSTANCE in vec4 aUvRect1; +PER_INSTANCE in vec4 aUvRect2; +#else +PER_INSTANCE in vec4 aUvRect0; +#endif + +void main(void) { + // Get world position + vec2 world_pos = aDeviceRect.xy + aPosition.xy * aDeviceRect.zw; + + // Clip the position to the world space clip rect + vec2 clipped_world_pos = clamp(world_pos, aDeviceClipRect.xy, aDeviceClipRect.xy + aDeviceClipRect.zw); + + // Derive the normalized UV from the clipped vertex position + vec2 uv = (clipped_world_pos - aDeviceRect.xy) / aDeviceRect.zw; + +#ifdef WR_FEATURE_YUV + int yuv_color_space = int(aParams.y); + int yuv_format = int(aParams.z); + float yuv_coefficient = aParams.w; + + vYuvColorMatrix = get_yuv_color_matrix(yuv_color_space); + vYuvOffsetVector = get_yuv_offset_vector(yuv_color_space); + vYuvCoefficient = yuv_coefficient; + vYuvFormat = yuv_format; + vYuvLayers = aTextureLayers.xyz; + +#ifdef SWGL + // 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. + vYuvColorSpace = yuv_color_space; + vRescaleFactor = int(log2(yuv_coefficient)); +#endif + + write_uv_rect( + aUvRect0.xy, + aUvRect0.zw, + uv, + TEX_SIZE(sColor0), + vUV_y, + vUVBounds_y + ); + write_uv_rect( + aUvRect1.xy, + aUvRect1.zw, + uv, + TEX_SIZE(sColor1), + vUV_u, + vUVBounds_u + ); + write_uv_rect( + aUvRect2.xy, + aUvRect2.zw, + uv, + TEX_SIZE(sColor2), + vUV_v, + vUVBounds_v + ); +#else + vUv = mix(aUvRect0.xy, aUvRect0.zw, uv); + // flip_y might have the UV rect "upside down", make sure + // clamp works correctly: + vUVBounds = vec4(aUvRect0.x, min(aUvRect0.y, aUvRect0.w), + aUvRect0.z, max(aUvRect0.y, aUvRect0.w)); + 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. + vec2 texture_size = TEX_SIZE(sColor0); + vUVBounds += vec4(0.5, 0.5, -0.5, -0.5); + #ifndef WR_FEATURE_TEXTURE_RECT + vUv /= texture_size; + vUVBounds /= texture_size.xyxy; + #endif + } + // Pass through color and texture array layer + vColor = aColor; + vLayer = aTextureLayers.x; +#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, + vYuvColorMatrix, + vYuvOffsetVector, + vYuvCoefficient, + vYuvLayers, + 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 + vec2 uv = clamp(vUv.xy, vUVBounds.xy, vUVBounds.zw); +# if defined(WR_FEATURE_TEXTURE_EXTERNAL) || defined(WR_FEATURE_TEXTURE_2D) || defined(WR_FEATURE_TEXTURE_RECT) + vec4 texel = TEX_SAMPLE(sColor0, vec3(uv, vLayer)); +# else + vec4 texel = textureLod(sColor0, vec3(uv, vLayer), 0.0); +# endif + vec4 color = vColor * texel; +#endif + write_output(color); +} + +#ifdef SWGL +void swgl_drawSpanRGBA8() { +#ifdef WR_FEATURE_YUV + if (vYuvFormat == YUV_FORMAT_PLANAR) { + if (!swgl_isTextureLinear(sColor0) || !swgl_isTextureLinear(sColor1) || !swgl_isTextureLinear(sColor2)) { + return; + } + + int layer0 = swgl_textureLayerOffset(sColor0, vYuvLayers.x); + vec2 uv0 = swgl_linearQuantize(sColor0, vUV_y); + vec2 min_uv0 = swgl_linearQuantize(sColor0, vUVBounds_y.xy); + vec2 max_uv0 = swgl_linearQuantize(sColor0, vUVBounds_y.zw); + vec2 step_uv0 = swgl_linearQuantizeStep(sColor0, swgl_interpStep(vUV_y)); + + int layer1 = swgl_textureLayerOffset(sColor1, vYuvLayers.y); + vec2 uv1 = swgl_linearQuantize(sColor1, vUV_u); + vec2 min_uv1 = swgl_linearQuantize(sColor1, vUVBounds_u.xy); + vec2 max_uv1 = swgl_linearQuantize(sColor1, vUVBounds_u.zw); + vec2 step_uv1 = swgl_linearQuantizeStep(sColor1, swgl_interpStep(vUV_u)); + + int layer2 = swgl_textureLayerOffset(sColor2, vYuvLayers.z); + vec2 uv2 = swgl_linearQuantize(sColor2, vUV_v); + vec2 min_uv2 = swgl_linearQuantize(sColor2, vUVBounds_v.xy); + vec2 max_uv2 = swgl_linearQuantize(sColor2, vUVBounds_v.zw); + vec2 step_uv2 = swgl_linearQuantizeStep(sColor2, swgl_interpStep(vUV_v)); + + while (swgl_SpanLength > 0) { + swgl_commitTextureLinearYUV(sColor0, clamp(uv0, min_uv0, max_uv0), layer0, + sColor1, clamp(uv1, min_uv1, max_uv1), layer1, + sColor2, clamp(uv2, min_uv2, max_uv2), layer2, + vYuvColorSpace, vRescaleFactor); + uv0 += step_uv0; + uv1 += step_uv1; + uv2 += step_uv2; + } + } else if (vYuvFormat == YUV_FORMAT_NV12) { + if (!swgl_isTextureLinear(sColor0) || !swgl_isTextureLinear(sColor1)) { + return; + } + + int layer0 = swgl_textureLayerOffset(sColor0, vYuvLayers.x); + vec2 uv0 = swgl_linearQuantize(sColor0, vUV_y); + vec2 min_uv0 = swgl_linearQuantize(sColor0, vUVBounds_y.xy); + vec2 max_uv0 = swgl_linearQuantize(sColor0, vUVBounds_y.zw); + vec2 step_uv0 = swgl_linearQuantizeStep(sColor0, swgl_interpStep(vUV_y)); + + int layer1 = swgl_textureLayerOffset(sColor1, vYuvLayers.y); + vec2 uv1 = swgl_linearQuantize(sColor1, vUV_u); + vec2 min_uv1 = swgl_linearQuantize(sColor1, vUVBounds_u.xy); + vec2 max_uv1 = swgl_linearQuantize(sColor1, vUVBounds_u.zw); + vec2 step_uv1 = swgl_linearQuantizeStep(sColor1, swgl_interpStep(vUV_u)); + + while (swgl_SpanLength > 0) { + swgl_commitTextureLinearYUV(sColor0, clamp(uv0, min_uv0, max_uv0), layer0, + sColor1, clamp(uv1, min_uv1, max_uv1), layer1, + vYuvColorSpace, vRescaleFactor); + uv0 += step_uv0; + uv1 += step_uv1; + } + } else if (vYuvFormat == YUV_FORMAT_INTERLEAVED) { + if (!swgl_isTextureLinear(sColor0) || !swgl_isTextureLinear(sColor1)) { + return; + } + + int layer0 = swgl_textureLayerOffset(sColor0, vYuvLayers.x); + vec2 uv0 = swgl_linearQuantize(sColor0, vUV_y); + vec2 min_uv0 = swgl_linearQuantize(sColor0, vUVBounds_y.xy); + vec2 max_uv0 = swgl_linearQuantize(sColor0, vUVBounds_y.zw); + vec2 step_uv0 = swgl_linearQuantizeStep(sColor0, swgl_interpStep(vUV_y)); + + while (swgl_SpanLength > 0) { + swgl_commitTextureLinearYUV(sColor0, clamp(uv0, min_uv0, max_uv0), layer0, + vYuvColorSpace, vRescaleFactor); + uv0 += step_uv0; + } + } +#else + if (!swgl_isTextureRGBA8(sColor0) || !swgl_isTextureLinear(sColor0)) { + return; + } + + int layer = swgl_textureLayerOffset(sColor0, vLayer); + + if (swgl_allowTextureNearest(sColor0, vUv)) { + if (vColor != vec4(1.0)) { + swgl_commitTextureNearestColorRGBA8(sColor0, vUv, vUVBounds, vColor, layer); + } else { + swgl_commitTextureNearestRGBA8(sColor0, vUv, vUVBounds, layer); + } + return; + } + + vec2 uv = swgl_linearQuantize(sColor0, vUv); + vec2 min_uv = swgl_linearQuantize(sColor0, vUVBounds.xy); + vec2 max_uv = swgl_linearQuantize(sColor0, vUVBounds.zw); + vec2 step_uv = swgl_linearQuantizeStep(sColor0, swgl_interpStep(vUv)); + + if (vColor != vec4(1.0)) { + while (swgl_SpanLength > 0) { + swgl_commitTextureLinearColorRGBA8(sColor0, clamp(uv, min_uv, max_uv), vColor, layer); + uv += step_uv; + } + } else { + while (swgl_SpanLength > 0) { + swgl_commitTextureLinearRGBA8(sColor0, clamp(uv, min_uv, max_uv), layer); + uv += step_uv; + } + } +#endif +} +#endif + +#endif |