Files
sousa-gecko/gfx/2d
Tom Ritter 73160a2005 Bug 2046791 - Make Unpremultiply_SSE2 bit-exact to the scalar/NEON un-premultiply r=gfx-reviewers,lsalzman
getImageData() on a canvas with non-opaque pixels returned
CPU-architecture-dependent bytes: Unpremultiply_SSE2 used a 16-bit *scaled*
reciprocal (UNPREMULQ_SSE2 + _mm_mulhi_epu16) that rounds down by 1 LSB on a
subset of anti-aliased / alpha pixels, whereas the scalar fallback and NEON
paths use the full 8.16 reciprocal and agree with each other. The result was a
100%-clean x86-vs-ARM split in canvas readback.

Use the full 0xFF00FF/alpha reciprocal (same table as the scalar fallback) and
compute an exact (channel * reciprocal) >> 16 in 16-bit lanes by splitting the
reciprocal into high/low halves:
  (channel*Q)>>16 = mullo(channel, Q>>16) + mulhi(channel, Q&0xFFFF).
This is bit-identical to the scalar/NEON output for all 256x256 (channel,alpha)
pairs (verified exhaustively) and keeps the SIMD path (two 16-bit multiplies +
an add per channel group). Both UnpremultiplyData and UnpremultiplyRow go
through UnpremultiplyVector_SSE2, so this fixes every getImageData caller.

Differential Revision: https://phabricator.services.mozilla.com/D306170
2026-07-13 11:06:27 +00:00
..
…
…
…
…
…
…
…
…
…