firefox: add a real fix for the swizzlerow BE crash

This commit is contained in:
q66 2020-03-07 05:18:29 +01:00
parent c48cf123ba
commit 892146e923
2 changed files with 115 additions and 73 deletions

View file

@ -0,0 +1,115 @@
https://phabricator.services.mozilla.com/D65797
https://bugzilla.mozilla.org/show_bug.cgi?id=1616030
diff --git a/gfx/2d/Swizzle.cpp b/gfx/2d/Swizzle.cpp
--- gfx/2d/Swizzle.cpp
+++ gfx/2d/Swizzle.cpp
@@ -892,7 +892,11 @@
uint8_t r = src[aSwapRB ? 2 : 0];
uint8_t g = src[1];
uint8_t b = src[aSwapRB ? 0 : 2];
+#if MOZ_LITTLE_ENDIAN()
*--dst = 0xFF000000 | (b << 16) | (g << 8) | r;
+#else
+ *--dst = 0x000000FF | (b << 8) | (g << 16) | (r << 24);
+#endif
src -= 3;
}
}
@@ -906,6 +910,28 @@
SurfaceFormat::R8G8B8, aDstFormat, \
UnpackRowRGB24<ShouldSwapRB(SurfaceFormat::R8G8B8, aDstFormat)>)
+static void UnpackRowRGB24_To_ARGB(const uint8_t* aSrc, uint8_t* aDst,
+ int32_t aLength) {
+ // Because we are expanding, we can only process the data back to front in
+ // case we are performing this in place.
+ const uint8_t* src = aSrc + 3 * (aLength - 1);
+ uint32_t* dst = reinterpret_cast<uint32_t*>(aDst + 4 * aLength);
+ while (src >= aSrc) {
+ uint8_t r = src[0];
+ uint8_t g = src[1];
+ uint8_t b = src[2];
+#if MOZ_LITTLE_ENDIAN()
+ *--dst = 0x000000FF | (r << 8) | (g << 16) | (b << 24);
+#else
+ *--dst = 0xFF000000 | (r << 24) | (g << 16) | b;
+#endif
+ src -= 3;
+ }
+}
+
+#define UNPACK_ROW_RGB_TO_ARGB(aDstFormat) \
+ FORMAT_CASE_ROW(SurfaceFormat::R8G8B8, aDstFormat, UnpackRowRGB24_To_ARGB)
+
bool SwizzleData(const uint8_t* aSrc, int32_t aSrcStride,
SurfaceFormat aSrcFormat, uint8_t* aDst, int32_t aDstStride,
SurfaceFormat aDstFormat, const IntSize& aSize) {
@@ -1071,16 +1097,36 @@
SWIZZLE_ROW_FALLBACK(SurfaceFormat::R8G8B8X8, SurfaceFormat::B8G8R8X8)
SWIZZLE_ROW_FALLBACK(SurfaceFormat::R8G8B8A8, SurfaceFormat::B8G8R8X8)
SWIZZLE_ROW_FALLBACK(SurfaceFormat::R8G8B8X8, SurfaceFormat::B8G8R8A8)
+ SWIZZLE_ROW_FALLBACK(SurfaceFormat::R8G8B8A8, SurfaceFormat::A8R8G8B8)
+ SWIZZLE_ROW_FALLBACK(SurfaceFormat::R8G8B8X8, SurfaceFormat::X8R8G8B8)
+
+ SWIZZLE_ROW_FALLBACK(SurfaceFormat::A8R8G8B8, SurfaceFormat::R8G8B8A8)
+ SWIZZLE_ROW_FALLBACK(SurfaceFormat::X8R8G8B8, SurfaceFormat::R8G8B8X8)
+ SWIZZLE_ROW_FALLBACK(SurfaceFormat::A8R8G8B8, SurfaceFormat::R8G8B8X8)
+ SWIZZLE_ROW_FALLBACK(SurfaceFormat::X8R8G8B8, SurfaceFormat::R8G8B8A8)
SWIZZLE_ROW_OPAQUE(SurfaceFormat::B8G8R8A8, SurfaceFormat::B8G8R8X8)
SWIZZLE_ROW_OPAQUE(SurfaceFormat::B8G8R8X8, SurfaceFormat::B8G8R8A8)
SWIZZLE_ROW_OPAQUE(SurfaceFormat::R8G8B8A8, SurfaceFormat::R8G8B8X8)
SWIZZLE_ROW_OPAQUE(SurfaceFormat::R8G8B8X8, SurfaceFormat::R8G8B8A8)
+ SWIZZLE_ROW_OPAQUE(SurfaceFormat::A8R8G8B8, SurfaceFormat::X8R8G8B8)
+ SWIZZLE_ROW_OPAQUE(SurfaceFormat::X8R8G8B8, SurfaceFormat::A8R8G8B8)
+
+ SWIZZLE_ROW_SWAP(SurfaceFormat::B8G8R8A8, SurfaceFormat::A8R8G8B8)
+ SWIZZLE_ROW_SWAP(SurfaceFormat::B8G8R8A8, SurfaceFormat::X8R8G8B8)
+ SWIZZLE_ROW_SWAP(SurfaceFormat::B8G8R8X8, SurfaceFormat::X8R8G8B8)
+ SWIZZLE_ROW_SWAP(SurfaceFormat::B8G8R8X8, SurfaceFormat::A8R8G8B8)
+ SWIZZLE_ROW_SWAP(SurfaceFormat::A8R8G8B8, SurfaceFormat::B8G8R8A8)
+ SWIZZLE_ROW_SWAP(SurfaceFormat::A8R8G8B8, SurfaceFormat::B8G8R8X8)
+ SWIZZLE_ROW_SWAP(SurfaceFormat::X8R8G8B8, SurfaceFormat::B8G8R8X8)
+ SWIZZLE_ROW_SWAP(SurfaceFormat::X8R8G8B8, SurfaceFormat::B8G8R8A8)
UNPACK_ROW_RGB(SurfaceFormat::R8G8B8X8)
UNPACK_ROW_RGB(SurfaceFormat::R8G8B8A8)
UNPACK_ROW_RGB(SurfaceFormat::B8G8R8X8)
UNPACK_ROW_RGB(SurfaceFormat::B8G8R8A8)
+ UNPACK_ROW_RGB_TO_ARGB(SurfaceFormat::A8R8G8B8)
+ UNPACK_ROW_RGB_TO_ARGB(SurfaceFormat::X8R8G8B8)
default:
break;
diff --git a/gfx/tests/gtest/TestSwizzle.cpp b/gfx/tests/gtest/TestSwizzle.cpp
--- gfx/tests/gtest/TestSwizzle.cpp
+++ gfx/tests/gtest/TestSwizzle.cpp
@@ -219,6 +219,12 @@
15, 14, 13, 255, 18, 17, 16, 255, 21, 20, 19, 255, 24, 23, 22, 255,
27, 26, 25, 255, 30, 29, 28, 255, 33, 32, 31, 255, 36, 35, 34, 255,
};
+ const uint8_t check_unpack_xrgb[16 * 4] = {
+ 255, 0, 254, 253, 255, 255, 0, 0, 255, 0, 0, 0, 255, 3, 2, 1,
+ 255, 9, 0, 127, 255, 4, 5, 6, 255, 9, 8, 7, 255, 10, 11, 12,
+ 255, 13, 14, 15, 255, 16, 17, 18, 255, 19, 20, 21, 255, 22, 23, 24,
+ 255, 25, 26, 27, 255, 28, 29, 30, 255, 31, 32, 33, 255, 34, 35, 36,
+ };
SwizzleRowFn func =
SwizzleRow(SurfaceFormat::B8G8R8A8, SurfaceFormat::R8G8B8A8);
@@ -246,4 +252,13 @@
memcpy(out_unpack, in_rgb, sizeof(in_rgb));
func(out_unpack, out_unpack, 16);
EXPECT_TRUE(ArrayEqual(out_unpack, check_unpack_rgbx));
+
+ func = SwizzleRow(SurfaceFormat::R8G8B8, SurfaceFormat::X8R8G8B8);
+ func(in_rgb, out_unpack, 16);
+ EXPECT_TRUE(ArrayEqual(out_unpack, check_unpack_xrgb));
+
+ memset(out_unpack, 0xE5, sizeof(out_unpack));
+ memcpy(out_unpack, in_rgb, sizeof(in_rgb));
+ func(out_unpack, out_unpack, 16);
+ EXPECT_TRUE(ArrayEqual(out_unpack, check_unpack_xrgb));
}

View file

@ -1,73 +0,0 @@
Since this code is broken on BE at this point (OS_RGBA resolves to an
unhandled thing), temporarily revert to the code present in firefox-esr
Upstream issue: https://bugzilla.mozilla.org/show_bug.cgi?id=1616030
--- image/decoders/nsGIFDecoder2.cpp
+++ image/decoders/nsGIFDecoder2.cpp
@@ -418,10 +418,65 @@ void nsGIFDecoder2::ConvertColormap(uint32_t* aColormap, uint32_t aColors) {
}
}
+ // since SwizzleRow is broken on BE right now for OS_RGBA, temporarily
+ // restore this code to whatever it was before the rework...
+#if MOZ_BIG_ENDIAN()
+
+#define BLOCK_RGB_TO_FRGB(from, to) \
+do { \
+ uint32_t m0 = ((uint32_t*)from)[0], m1 = ((uint32_t*)from)[1], \
+ m2 = ((uint32_t*)from)[2], \
+ p0, p1, p2, p3; \
+ p0 = 0xFF000000 | ((m0) >> 8); \
+ p1 = 0xFF000000 | ((m0) << 16) | ((m1) >> 16); \
+ p2 = 0xFF000000 | ((m1) << 8) | ((m2) >> 24); \
+ p3 = 0xFF000000 | (m2); \
+ to[0] = p0; \
+ to[1] = p1; \
+ to[2] = p2; \
+ to[3] = p3; \
+} while(0)
+
+ // Convert from the GIF's RGB format to the Cairo format.
+ // Work from end to begin, because of the in-place expansion
+ uint8_t* from = ((uint8_t*)aColormap) + 3 * aColors;
+ uint32_t* to = aColormap + aColors;
+
+ // Convert color entries to Cairo format
+
+ // set up for loops below
+ if (!aColors) {
+ return;
+ }
+ uint32_t c = aColors;
+
+ // copy as bytes until source pointer is 32-bit-aligned
+ // NB: can't use 32-bit reads, they might read off the end of the buffer
+ for (; (NS_PTR_TO_UINT32(from) & 0x3) && c; --c) {
+ from -= 3;
+ *--to = gfxPackedPixel(0xFF, from[0], from[1], from[2]);
+ }
+
+ // bulk copy of pixels.
+ while (c >= 4) {
+ from -= 12;
+ to -= 4;
+ c -= 4;
+ BLOCK_RGB_TO_FRGB(from, to);
+ }
+
+ // copy remaining pixel(s)
+ // NB: can't use 32-bit reads, they might read off the end of the buffer
+ while (c--) {
+ from -= 3;
+ *--to = gfxPackedPixel(0xFF, from[0], from[1], from[2]);
+ }
+#else
// Expand color table from RGB to BGRA.
MOZ_ASSERT(mSwizzleFn);
uint8_t* data = reinterpret_cast<uint8_t*>(aColormap);
mSwizzleFn(data, data, aColors);
+#endif
}
LexerResult nsGIFDecoder2::DoDecode(SourceBufferIterator& aIterator,