Bug 1551088 - Part 2. Add unpack methods to convert from RGB to RGBX/BGRX. r=lsalzman
authorAndrew Osmond <aosmond@mozilla.com>
Tue, 24 Sep 2019 20:42:41 +0000
changeset 494818 25a5f5563e9d8acbb18ee2ff319ca755d54d35d6
parent 494817 bed9c93eeb2d6ea3a64288beffcfc098d2079c8c
child 494819 d90a571e581f04efcd642520b0911fde9421a61e
push id114131
push userdluca@mozilla.com
push dateThu, 26 Sep 2019 09:47:34 +0000
treeherdermozilla-inbound@1dc1a755079a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslsalzman
bugs1551088
milestone71.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1551088 - Part 2. Add unpack methods to convert from RGB to RGBX/BGRX. r=lsalzman Some image decoders (e.g. PNG) may have a native representation of the data as RGB, and do not have accelerated methods to transform from RGB to RGBX/BGRX. Exposing this as part of the swizzle/premultiply methods allows us to write accelerated versions ourselves in a later patch in this series. Differential Revision: https://phabricator.services.mozilla.com/D46445
gfx/2d/Swizzle.cpp
--- a/gfx/2d/Swizzle.cpp
+++ b/gfx/2d/Swizzle.cpp
@@ -853,16 +853,45 @@ static void PackToA8(const uint8_t* aSrc
 #define PACK_ALPHA_CASE(aSrcFormat, aDstFormat, aPackFunc) \
   FORMAT_CASE(aSrcFormat, aDstFormat, aPackFunc<AlphaByteIndex(aSrcFormat)>)
 
 #define PACK_ALPHA(aDstFormat, aPackFunc)                         \
   PACK_ALPHA_CASE(SurfaceFormat::B8G8R8A8, aDstFormat, aPackFunc) \
   PACK_ALPHA_CASE(SurfaceFormat::R8G8B8A8, aDstFormat, aPackFunc) \
   PACK_ALPHA_CASE(SurfaceFormat::A8R8G8B8, aDstFormat, aPackFunc)
 
+template <bool aSwapRB>
+void UnpackRowRGB24(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);
+  uint8_t* dst = aDst + 4 * (aLength - 1);
+  while (src >= aSrc) {
+    uint8_t r = src[aSwapRB ? 2 : 0];
+    uint8_t g = src[1];
+    uint8_t b = src[aSwapRB ? 0 : 2];
+
+    dst[0] = r;
+    dst[1] = g;
+    dst[2] = b;
+    dst[3] = 0xFF;
+
+    src -= 3;
+    dst -= 4;
+  }
+}
+
+// Force instantiation of swizzle variants here.
+template void UnpackRowRGB24<false>(const uint8_t*, uint8_t*, int32_t);
+template void UnpackRowRGB24<true>(const uint8_t*, uint8_t*, int32_t);
+
+#define UNPACK_ROW_RGB(aDstFormat)                   \
+  FORMAT_CASE_ROW(SurfaceFormat::R8G8B8, aDstFormat, \
+                  UnpackRowRGB24<ShouldSwapRB(SurfaceFormat::R8G8B8, aDstFormat)>)
+
 bool SwizzleData(const uint8_t* aSrc, int32_t aSrcStride,
                  SurfaceFormat aSrcFormat, uint8_t* aDst, int32_t aDstStride,
                  SurfaceFormat aDstFormat, const IntSize& aSize) {
   if (aSize.IsEmpty()) {
     return true;
   }
   IntSize size = CollapseSize(aSize, aSrcStride, aDstStride);
   // Find gap from end of row to the start of the next row.
@@ -1002,16 +1031,21 @@ SwizzleRowFn SwizzleRow(SurfaceFormat aS
     SWIZZLE_ROW_FALLBACK(SurfaceFormat::R8G8B8A8, SurfaceFormat::B8G8R8X8)
     SWIZZLE_ROW_FALLBACK(SurfaceFormat::R8G8B8X8, SurfaceFormat::B8G8R8A8)
 
     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)
 
+    UNPACK_ROW_RGB(SurfaceFormat::R8G8B8X8)
+    UNPACK_ROW_RGB(SurfaceFormat::R8G8B8A8)
+    UNPACK_ROW_RGB(SurfaceFormat::B8G8R8X8)
+    UNPACK_ROW_RGB(SurfaceFormat::B8G8R8A8)
+
     default:
       break;
   }
 
   MOZ_ASSERT_UNREACHABLE("Unsupported swizzle formats");
   return nullptr;
 }