summaryrefslogtreecommitdiffstats
path: root/gfx/wr/webrender/res/brush_yuv_image.glsl
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/wr/webrender/res/brush_yuv_image.glsl')
-rw-r--r--gfx/wr/webrender/res/brush_yuv_image.glsl249
1 files changed, 249 insertions, 0 deletions
diff --git a/gfx/wr/webrender/res/brush_yuv_image.glsl b/gfx/wr/webrender/res/brush_yuv_image.glsl
new file mode 100644
index 0000000000..403004ff53
--- /dev/null
+++ b/gfx/wr/webrender/res/brush_yuv_image.glsl
@@ -0,0 +1,249 @@
+/* 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/. */
+
+#define VECS_PER_SPECIFIC_BRUSH 1
+
+#include shared,prim_shared,brush,yuv
+
+#ifdef WR_FEATURE_ALPHA_PASS
+varying vec2 vLocalPos;
+#endif
+
+flat varying vec3 vYuvLayers;
+
+varying vec2 vUv_Y;
+flat varying vec4 vUvBounds_Y;
+
+varying vec2 vUv_U;
+flat varying vec4 vUvBounds_U;
+
+varying vec2 vUv_V;
+flat varying vec4 vUvBounds_V;
+
+flat varying float vCoefficient;
+flat varying mat3 vYuvColorMatrix;
+flat varying vec3 vYuvOffsetVector;
+flat varying int vFormat;
+
+#ifdef SWGL
+flat varying int vYuvColorSpace;
+flat varying int vRescaleFactor;
+#endif
+
+#ifdef WR_VERTEX_SHADER
+
+struct YuvPrimitive {
+ float coefficient;
+ int color_space;
+ int yuv_format;
+};
+
+YuvPrimitive fetch_yuv_primitive(int address) {
+ vec4 data = fetch_from_gpu_cache_1(address);
+ return YuvPrimitive(data.x, int(data.y), int(data.z));
+}
+
+void brush_vs(
+ VertexInfo vi,
+ int prim_address,
+ RectWithSize local_rect,
+ RectWithSize segment_rect,
+ ivec4 prim_user_data,
+ int specific_resource_address,
+ mat4 transform,
+ PictureTask pic_task,
+ int brush_flags,
+ vec4 unused
+) {
+ vec2 f = (vi.local_pos - local_rect.p0) / local_rect.size;
+
+ YuvPrimitive prim = fetch_yuv_primitive(prim_address);
+ vCoefficient = prim.coefficient;
+
+ vYuvColorMatrix = get_yuv_color_matrix(prim.color_space);
+ vYuvOffsetVector = get_yuv_offset_vector(prim.color_space);
+ vFormat = prim.yuv_format;
+
+#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 = prim.color_space;
+ vRescaleFactor = int(log2(prim.coefficient));
+#endif
+
+#ifdef WR_FEATURE_ALPHA_PASS
+ vLocalPos = vi.local_pos;
+#endif
+
+ if (vFormat == YUV_FORMAT_PLANAR) {
+ ImageResource res_y = fetch_image_resource(prim_user_data.x);
+ ImageResource res_u = fetch_image_resource(prim_user_data.y);
+ ImageResource res_v = fetch_image_resource(prim_user_data.z);
+ write_uv_rect(res_y.uv_rect.p0, res_y.uv_rect.p1, f, TEX_SIZE(sColor0), vUv_Y, vUvBounds_Y);
+ write_uv_rect(res_u.uv_rect.p0, res_u.uv_rect.p1, f, TEX_SIZE(sColor1), vUv_U, vUvBounds_U);
+ write_uv_rect(res_v.uv_rect.p0, res_v.uv_rect.p1, f, TEX_SIZE(sColor2), vUv_V, vUvBounds_V);
+ vYuvLayers = vec3(res_y.layer, res_u.layer, res_v.layer);
+ } else if (vFormat == YUV_FORMAT_NV12) {
+ ImageResource res_y = fetch_image_resource(prim_user_data.x);
+ ImageResource res_u = fetch_image_resource(prim_user_data.y);
+ write_uv_rect(res_y.uv_rect.p0, res_y.uv_rect.p1, f, TEX_SIZE(sColor0), vUv_Y, vUvBounds_Y);
+ write_uv_rect(res_u.uv_rect.p0, res_u.uv_rect.p1, f, TEX_SIZE(sColor1), vUv_U, vUvBounds_U);
+ vYuvLayers = vec3(res_y.layer, res_u.layer, 0.0);
+ } else if (vFormat == YUV_FORMAT_INTERLEAVED) {
+ ImageResource res_y = fetch_image_resource(prim_user_data.x);
+ write_uv_rect(res_y.uv_rect.p0, res_y.uv_rect.p1, f, TEX_SIZE(sColor0), vUv_Y, vUvBounds_Y);
+ vYuvLayers = vec3(res_y.layer, 0.0, 0.0);
+ }
+}
+#endif
+
+#ifdef WR_FRAGMENT_SHADER
+
+Fragment brush_fs() {
+ vec4 color = sample_yuv(
+ vFormat,
+ vYuvColorMatrix,
+ vYuvOffsetVector,
+ vCoefficient,
+ vYuvLayers,
+ vUv_Y,
+ vUv_U,
+ vUv_V,
+ vUvBounds_Y,
+ vUvBounds_U,
+ vUvBounds_V
+ );
+
+#ifdef WR_FEATURE_ALPHA_PASS
+ color *= init_transform_fs(vLocalPos);
+#endif
+
+ return Fragment(color);
+}
+
+#ifdef SWGL
+void swgl_drawSpanRGBA8() {
+ if (vFormat == 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));
+
+ #ifdef WR_FEATURE_ALPHA_PASS
+ if (has_valid_transform_bounds()) {
+ while (swgl_SpanLength > 0) {
+ float alpha = init_transform_fs(vLocalPos);
+ vLocalPos += swgl_interpStep(vLocalPos);
+ swgl_commitTextureLinearColorYUV(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, alpha);
+ uv0 += step_uv0;
+ uv1 += step_uv1;
+ uv2 += step_uv2;
+ }
+ return;
+ }
+ #endif
+
+ 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 (vFormat == 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));
+
+ #ifdef WR_FEATURE_ALPHA_PASS
+ if (has_valid_transform_bounds()) {
+ while (swgl_SpanLength > 0) {
+ float alpha = init_transform_fs(vLocalPos);
+ vLocalPos += swgl_interpStep(vLocalPos);
+ swgl_commitTextureLinearColorYUV(sColor0, clamp(uv0, min_uv0, max_uv0), layer0,
+ sColor1, clamp(uv1, min_uv1, max_uv1), layer1,
+ vYuvColorSpace, vRescaleFactor, alpha);
+ uv0 += step_uv0;
+ uv1 += step_uv1;
+ }
+ return;
+ }
+ #endif
+
+ 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 (vFormat == YUV_FORMAT_INTERLEAVED) {
+ if (!swgl_isTextureLinear(sColor0)) {
+ 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));
+
+ #ifdef WR_FEATURE_ALPHA_PASS
+ if (has_valid_transform_bounds()) {
+ while (swgl_SpanLength > 0) {
+ float alpha = init_transform_fs(vLocalPos);
+ vLocalPos += swgl_interpStep(vLocalPos);
+ swgl_commitTextureLinearColorYUV(sColor0, clamp(uv0, min_uv0, max_uv0), layer0,
+ vYuvColorSpace, vRescaleFactor, alpha);
+ uv0 += step_uv0;
+ }
+ return;
+ }
+ #endif
+
+ while (swgl_SpanLength > 0) {
+ swgl_commitTextureLinearYUV(sColor0, clamp(uv0, min_uv0, max_uv0), layer0,
+ vYuvColorSpace, vRescaleFactor);
+ uv0 += step_uv0;
+ }
+ }
+}
+#endif
+
+#endif