mozilla-bmo1504834-part2.patch
author Wolfgang Rosenauer <wr@rosenauer.org>
Mon, 25 Nov 2019 08:30:26 +0100
changeset 1115 ed3548a16248
parent 1109 972f68ac6b1a
child 1119 4c5d44d40a03
permissions -rw-r--r--
fix reference

# HG changeset patch
# Parent  6fa4b62427433e8f445d05c557e5db096667d880
Skia does not support big endian. The places to fix are too numerous and upstream (skia, not Mozilla)
has no interest in maintaining big endian.
So here we try to swizzle the input for skia, so that skia always works on LE, and when it comes
out again, we transform back to BE.

diff --git a/gfx/2d/ConvolutionFilter.cpp b/gfx/2d/ConvolutionFilter.cpp
--- a/gfx/2d/ConvolutionFilter.cpp
+++ b/gfx/2d/ConvolutionFilter.cpp
@@ -30,32 +30,79 @@ bool ConvolutionFilter::GetFilterOffsetA
                                                  int32_t* aResultLength) {
   if (aRowIndex >= mFilter->numValues()) {
     return false;
   }
   mFilter->FilterForValue(aRowIndex, aResultOffset, aResultLength);
   return true;
 }
 
+static void ByteSwapArray(uint8_t *u8Array, int32_t size) {
+    uint32_t *array = reinterpret_cast<uint32_t*>(u8Array);
+    for (int pxl = 0; pxl < size; ++pxl) {
+        // Use an endian swap to move the bytes, i.e. BGRA -> ARGB.
+        uint32_t rgba = array[pxl];
+        array[pxl] = NativeEndian::swapToLittleEndian(rgba);
+    }
+}
+
 void ConvolutionFilter::ConvolveHorizontally(const uint8_t* aSrc, uint8_t* aDst,
                                              bool aHasAlpha) {
+#if MOZ_BIG_ENDIAN
+    int outputSize = mFilter->numValues();
+
+    // Input size isn't handed in, so we have to calculate it quickly
+    int inputSize = 0;
+    for (int xx = 0; xx < outputSize; ++xx) {
+        // Get the filter that determines the current output pixel.
+        int filterOffset, filterLength;
+        mFilter->FilterForValue(xx, &filterOffset, &filterLength);
+        inputSize = std::max(inputSize, filterOffset + filterLength);
+    }
+
+    ByteSwapArray((uint8_t*)aSrc, inputSize);
+#endif
+
   SkOpts::convolve_horizontally(aSrc, *mFilter, aDst, aHasAlpha);
+
+#if MOZ_BIG_ENDIAN
+    ByteSwapArray((uint8_t*)aSrc, inputSize);
+    ByteSwapArray(aDst, outputSize);
+#endif
 }
 
 void ConvolutionFilter::ConvolveVertically(uint8_t* const* aSrc, uint8_t* aDst,
                                            int32_t aRowIndex, int32_t aRowSize,
                                            bool aHasAlpha) {
   MOZ_ASSERT(aRowIndex < mFilter->numValues());
 
   int32_t filterOffset;
   int32_t filterLength;
   auto filterValues =
       mFilter->FilterForValue(aRowIndex, &filterOffset, &filterLength);
+
+#if MOZ_BIG_ENDIAN
+  for (int filterY = 0; filterY < filterLength; filterY++) {
+      // Skia only knows LE, so we have to swizzle the input
+    ByteSwapArray(aSrc[filterY], aRowSize);
+  }
+#endif
+
   SkOpts::convolve_vertically(filterValues, filterLength, aSrc, aRowSize, aDst,
                               aHasAlpha);
+
+#if MOZ_BIG_ENDIAN
+  // After skia is finished, we swizzle back to BE, in case
+  // the input is used again somewhere else
+  for (int filterY = 0; filterY < filterLength; filterY++) {
+    ByteSwapArray(aSrc[filterY], aRowSize);
+  }
+  // The destination array as well
+  ByteSwapArray(aDst, aRowSize);
+#endif
 }
 
 /* ConvolutionFilter::ComputeResizeFactor is derived from Skia's
  * SkBitmapScaler/SkResizeFilter::computeFactors. It is governed by Skia's
  * BSD-style license (see gfx/skia/LICENSE) and the following copyright:
  * Copyright (c) 2015 Google Inc.
  */
 bool ConvolutionFilter::ComputeResizeFilter(ResizeMethod aResizeMethod,
diff --git a/gfx/skia/skia/include/core/SkPreConfig.h b/gfx/skia/skia/include/core/SkPreConfig.h
--- a/gfx/skia/skia/include/core/SkPreConfig.h
+++ b/gfx/skia/skia/include/core/SkPreConfig.h
@@ -68,17 +68,17 @@
         #define SK_CPU_BENDIAN
     #elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
         #define SK_CPU_LENDIAN
     #elif defined(__sparc) || defined(__sparc__) || \
       defined(_POWER) || defined(__powerpc__) || \
       defined(__ppc__) || defined(__hppa) || \
       defined(__PPC__) || defined(__PPC64__) || \
       defined(_MIPSEB) || defined(__ARMEB__) || \
-      defined(__s390__) || \
+      defined(__s390__) || defined(__s390x__) || \
       (defined(__sh__) && defined(__BIG_ENDIAN__)) || \
       (defined(__ia64) && defined(__BIG_ENDIAN__))
          #define SK_CPU_BENDIAN
     #else
         #define SK_CPU_LENDIAN
     #endif
 #endif