summaryrefslogtreecommitdiffstats
path: root/gfx/wr/webrender/res/composite.glsl
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/wr/webrender/res/composite.glsl')
-rw-r--r--gfx/wr/webrender/res/composite.glsl272
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