This is an automated email from the git hooks/post-receive script.
richard pushed a commit to branch tor-browser-91.9esr-11.0-1 in repository tor-browser.
commit 330014207d6fcecd96060169c8e88a1b28a00afb Author: Lee Salzman lsalzman@mozilla.com AuthorDate: Sat Apr 23 16:48:20 2022 +0000
Bug 1766056 - Fix YUV color matrix for SWGL slow and fast paths. r=jrmuizel, a=RyanVM
The brush_yuv_image slow path expected a YUV color matrix that applies scaling, whereas we set up a matrix for SWGL that had no scaling to support the fast path. To work around the fact that both paths have different scaling requirements, we pass the matrix with scaling down to the fast path and undo the scaling later when constructing SWGL's internal YUVMatrix from it. This allows both paths to just use the same matrix and avoids the footgun.
Differential Revision: https://phabricator.services.mozilla.com/D144479 --- gfx/wr/swgl/src/composite.h | 54 +++++++++++++++++++------------ gfx/wr/swgl/src/swgl_ext.h | 8 ++--- gfx/wr/webrender/res/brush_yuv_image.glsl | 3 -- gfx/wr/webrender/res/composite.glsl | 3 -- 4 files changed, 37 insertions(+), 31 deletions(-)
diff --git a/gfx/wr/swgl/src/composite.h b/gfx/wr/swgl/src/composite.h index 1a74d6aef5441..050dd8a2b43d6 100644 --- a/gfx/wr/swgl/src/composite.h +++ b/gfx/wr/swgl/src/composite.h @@ -518,7 +518,8 @@ struct YUVMatrix { // [ yScale, g_from_u, g_from_v ] x ([cb] - ycbcr_bias ) // [ yScale, b_from_u, 0 ] ([cr] ) static YUVMatrix From(const vec3_scalar& ycbcr_bias, - const mat3_scalar& rgb_from_debiased_ycbcr) { + const mat3_scalar& rgb_from_debiased_ycbcr, + int rescale_factor = 0) { assert(ycbcr_bias.z == ycbcr_bias.y);
const auto rgb_from_y = rgb_from_debiased_ycbcr[0].y; @@ -528,14 +529,14 @@ struct YUVMatrix { if (rgb_from_debiased_ycbcr[0].x == 0.0) { // gbr-identity matrix? assert(rgb_from_debiased_ycbcr[0].x == 0); - assert(rgb_from_debiased_ycbcr[0].y == 1); + assert(rgb_from_debiased_ycbcr[0].y >= 1); assert(rgb_from_debiased_ycbcr[0].z == 0);
assert(rgb_from_debiased_ycbcr[1].x == 0); assert(rgb_from_debiased_ycbcr[1].y == 0); - assert(rgb_from_debiased_ycbcr[1].z == 1); + assert(rgb_from_debiased_ycbcr[1].z >= 1);
- assert(rgb_from_debiased_ycbcr[2].x == 1); + assert(rgb_from_debiased_ycbcr[2].x >= 1); assert(rgb_from_debiased_ycbcr[2].y == 0); assert(rgb_from_debiased_ycbcr[2].z == 0);
@@ -557,24 +558,30 @@ struct YUVMatrix { assert(rgb_from_debiased_ycbcr[2].z == 0.0);
return YUVMatrix({ycbcr_bias.x, ycbcr_bias.y}, rgb_from_y, br_from_y_mask, - r_from_v, g_from_u, g_from_v, b_from_u); + r_from_v, g_from_u, g_from_v, b_from_u, rescale_factor); }
- // Convert matrix coefficients to fixed-point representation. + // Convert matrix coefficients to fixed-point representation. If the matrix + // has a rescaling applied to it, then we need to take care to undo the + // scaling so that we can convert the coefficients to fixed-point range. The + // bias still requires shifting to apply the rescaling. The rescaling will be + // applied to the actual YCbCr sample data later by manually shifting it + // before applying this matrix. YUVMatrix(vec2_scalar yuv_bias, double yCoeff, int16_t br_yMask_, double rv, - double gu, double gv, double bu) - : br_uvCoeffs(zip(I16(int16_t(bu * (1 << 6) + 0.5)), - I16(int16_t(rv * (1 << 6) + 0.5)))), - gg_uvCoeffs(zip(I16(-int16_t(-gu * (1 << 6) + - 0.5)), // These are negative coeffs, so - // round them away from zero - I16(-int16_t(-gv * (1 << 6) + 0.5)))), - yCoeffs(uint16_t(yCoeff * (1 << (6 + 1)) + 0.5)), + double gu, double gv, double bu, int rescale_factor = 0) + : br_uvCoeffs(zip(I16(int16_t(bu * (1 << (6 - rescale_factor)) + 0.5)), + I16(int16_t(rv * (1 << (6 - rescale_factor)) + 0.5)))), + gg_uvCoeffs( + zip(I16(-int16_t(-gu * (1 << (6 - rescale_factor)) + + 0.5)), // These are negative coeffs, so + // round them away from zero + I16(-int16_t(-gv * (1 << (6 - rescale_factor)) + 0.5)))), + yCoeffs(uint16_t(yCoeff * (1 << (6 + 1 - rescale_factor)) + 0.5)), // We have a +0.5 fudge-factor for -ybias. // Without this, we get white=254 not 255. // This approximates rounding rather than truncation during `gg >>= 6`. - yBias(int16_t( ((yuv_bias.x * 255 * yCoeff) - 0.5 ) * (1<<6) )), - uvBias(int16_t(yuv_bias.y * 255 + 0.5)), + yBias(int16_t(((yuv_bias.x * 255 * yCoeff) - 0.5) * (1 << 6))), + uvBias(int16_t(yuv_bias.y * (255 << rescale_factor) + 0.5)), br_yMask(br_yMask_) { assert(yuv_bias.x >= 0); assert(yuv_bias.y >= 0); @@ -584,6 +591,7 @@ struct YUVMatrix { assert(rv > 0); assert(gu <= 0); assert(gv <= 0); + assert(rescale_factor <= 6); }
ALWAYS_INLINE PackedRGBA8 convert(V8<int16_t> yy, V8<int16_t> uv) const { @@ -865,11 +873,15 @@ static void linear_row_yuv(uint32_t* dest, int span, sampler2DRect samplerY, // If the source row has less than 2 pixels, it's not safe to use a linear // filter because it may overread the row. Just convert the single pixel // with nearest filtering and fill the row with it. - I16 yuv = CONVERT( - round_pixel((Float){texelFetch(samplerY, ivec2(srcUV)).x.x, - texelFetch(samplerU, ivec2(chromaUV)).x.x, - texelFetch(samplerV, ivec2(chromaUV)).x.x, 1.0f}), - I16); + Float yuvF = {texelFetch(samplerY, ivec2(srcUV)).x.x, + texelFetch(samplerU, ivec2(chromaUV)).x.x, + texelFetch(samplerV, ivec2(chromaUV)).x.x, 1.0f}; + // If this is an HDR LSB format, we need to renormalize the result. + if (colorDepth > 8) { + int rescaleFactor = 16 - colorDepth; + yuvF *= float(1 << rescaleFactor); + } + I16 yuv = CONVERT(round_pixel(yuvF), I16); commit_solid_span<BLEND>( dest, unpack(colorSpace.convert(V8<int16_t>(yuv.x), diff --git a/gfx/wr/swgl/src/swgl_ext.h b/gfx/wr/swgl/src/swgl_ext.h index b5cf845ed0a68..2cad7307a5b8f 100644 --- a/gfx/wr/swgl/src/swgl_ext.h +++ b/gfx/wr/swgl/src/swgl_ext.h @@ -1029,7 +1029,7 @@ static int blendYUV(P* buf, int span, S0 sampler0, vec2 uv0, } LINEAR_QUANTIZE_UV(sampler0, uv0, uv_step0, uv_rect0, min_uv0, max_uv0); const auto rgb_from_ycbcr = - YUVMatrix::From(ycbcr_bias, rgb_from_debiased_ycbcr); + YUVMatrix::From(ycbcr_bias, rgb_from_debiased_ycbcr, rescaleFactor); auto c = packColor(buf, color); auto* end = buf + span; for (; buf < end; buf += swgl_StepSize, uv0 += uv_step0) { @@ -1080,7 +1080,7 @@ static int blendYUV(P* buf, int span, S0 sampler0, vec2 uv0, LINEAR_QUANTIZE_UV(sampler0, uv0, uv_step0, uv_rect0, min_uv0, max_uv0); LINEAR_QUANTIZE_UV(sampler1, uv1, uv_step1, uv_rect1, min_uv1, max_uv1); const auto rgb_from_ycbcr = - YUVMatrix::From(ycbcr_bias, rgb_from_debiased_ycbcr); + YUVMatrix::From(ycbcr_bias, rgb_from_debiased_ycbcr, rescaleFactor); auto c = packColor(buf, color); auto* end = buf + span; for (; buf < end; buf += swgl_StepSize, uv0 += uv_step0, uv1 += uv_step1) { @@ -1142,7 +1142,7 @@ static void blendYUVFallback(P* buf, int span, S0 sampler0, vec2 uv0, const mat3_scalar& rgb_from_debiased_ycbcr, int rescaleFactor, C color) { const auto rgb_from_ycbcr = - YUVMatrix::From(ycbcr_bias, rgb_from_debiased_ycbcr); + YUVMatrix::From(ycbcr_bias, rgb_from_debiased_ycbcr, rescaleFactor); for (auto* end = buf + span; buf < end; buf += swgl_StepSize, uv0 += uv_step0, uv1 += uv_step1, uv2 += uv_step2) { commit_blend_span<BLEND>( @@ -1240,7 +1240,7 @@ static int blendYUV(uint32_t* buf, int span, sampler2DRect sampler0, vec2 uv0, (sampler0->format == TextureFormat::R16 ? 16 : 8) - rescaleFactor; // Finally, call the inner loop of CompositeYUV. const auto rgb_from_ycbcr = - YUVMatrix::From(ycbcr_bias, rgb_from_debiased_ycbcr); + YUVMatrix::From(ycbcr_bias, rgb_from_debiased_ycbcr, rescaleFactor); linear_row_yuv<BLEND>( buf, inside * swgl_StepSize, sampler0, force_scalar(uv0), uv_step0.x / swgl_StepSize, sampler1, sampler2, force_scalar(uv1), diff --git a/gfx/wr/webrender/res/brush_yuv_image.glsl b/gfx/wr/webrender/res/brush_yuv_image.glsl index a02bf30a7c3fb..628e52c0b61c7 100644 --- a/gfx/wr/webrender/res/brush_yuv_image.glsl +++ b/gfx/wr/webrender/res/brush_yuv_image.glsl @@ -58,9 +58,6 @@ void brush_vs( if (prim.channel_bit_depth > 8) { vRescaleFactor = 16 - prim.channel_bit_depth; } - // Since SWGL rescales filtered YUV values to 8bpc before yuv->rgb - // conversion, don't embed a 10bpc channel multiplier into the yuv matrix. - prim.channel_bit_depth = 8; #endif
YuvColorMatrixInfo mat_info = get_rgb_from_ycbcr_info(prim); diff --git a/gfx/wr/webrender/res/composite.glsl b/gfx/wr/webrender/res/composite.glsl index 017e933e7f8bf..79c4e8560c65e 100644 --- a/gfx/wr/webrender/res/composite.glsl +++ b/gfx/wr/webrender/res/composite.glsl @@ -96,9 +96,6 @@ void main(void) { if (prim.channel_bit_depth > 8) { vRescaleFactor = 16 - prim.channel_bit_depth; } - // Since SWGL rescales filtered YUV values to 8bpc before yuv->rgb - // conversion, don't embed a 10bpc channel multiplier into the yuv matrix. - prim.channel_bit_depth = 8; #endif
YuvColorMatrixInfo mat_info = get_rgb_from_ycbcr_info(prim);