dd1d2c
# HG changeset patch
dd1d2c
# Parent  36563351309ddbc6c29559ba50a41d005f925abb
dd1d2c
Skia does not support big endian. The places to fix are too numerous and upstream (skia, not Mozilla)
dd1d2c
has no interest in maintaining big endian.
dd1d2c
So here we try to swizzle the input for skia, so that skia always works on LE, and when it comes
dd1d2c
out again, we transform back to BE.
dd1d2c
dd1d2c
diff -r 36563351309d gfx/2d/ConvolutionFilter.cpp
dd1d2c
--- a/gfx/2d/ConvolutionFilter.cpp	Mon Sep 09 17:59:28 2019 +0200
dd1d2c
+++ b/gfx/2d/ConvolutionFilter.cpp	Tue Sep 10 08:25:13 2019 +0200
dd1d2c
@@ -35,9 +35,38 @@
dd1d2c
   return true;
dd1d2c
 }
dd1d2c
 
dd1d2c
+static void ByteSwapArray(uint8_t *u8Array, int32_t size) {
dd1d2c
+    uint32_t *array = reinterpret_cast<uint32_t*>(u8Array);
dd1d2c
+    for (int pxl = 0; pxl < size; ++pxl) {
dd1d2c
+        // Use an endian swap to move the bytes, i.e. BGRA -> ARGB.
dd1d2c
+        uint32_t rgba = array[pxl];
dd1d2c
+        array[pxl] = NativeEndian::swapToLittleEndian(rgba);
dd1d2c
+    }
dd1d2c
+}
dd1d2c
+
dd1d2c
 void ConvolutionFilter::ConvolveHorizontally(const uint8_t* aSrc, uint8_t* aDst,
dd1d2c
                                              bool aHasAlpha) {
dd1d2c
+#if MOZ_BIG_ENDIAN
dd1d2c
+    int outputSize = mFilter->numValues();
dd1d2c
+
dd1d2c
+    // Input size isn't handed in, so we have to calculate it quickly
dd1d2c
+    int inputSize = 0;
dd1d2c
+    for (int xx = 0; xx < outputSize; ++xx) {
dd1d2c
+        // Get the filter that determines the current output pixel.
dd1d2c
+        int filterOffset, filterLength;
dd1d2c
+        mFilter->FilterForValue(xx, &filterOffset, &filterLength);
dd1d2c
+        inputSize = std::max(inputSize, filterOffset + filterLength);
dd1d2c
+    }
dd1d2c
+
dd1d2c
+    ByteSwapArray((uint8_t*)aSrc, inputSize);
dd1d2c
+#endif
dd1d2c
+
dd1d2c
   SkOpts::convolve_horizontally(aSrc, *mFilter, aDst, aHasAlpha);
dd1d2c
+
dd1d2c
+#if MOZ_BIG_ENDIAN
dd1d2c
+    ByteSwapArray((uint8_t*)aSrc, inputSize);
dd1d2c
+    ByteSwapArray(aDst, outputSize);
dd1d2c
+#endif
dd1d2c
 }
dd1d2c
 
dd1d2c
 void ConvolutionFilter::ConvolveVertically(uint8_t* const* aSrc, uint8_t* aDst,
dd1d2c
@@ -49,8 +78,26 @@
dd1d2c
   int32_t filterLength;
dd1d2c
   auto filterValues =
dd1d2c
       mFilter->FilterForValue(aRowIndex, &filterOffset, &filterLength);
dd1d2c
+
dd1d2c
+#if MOZ_BIG_ENDIAN
dd1d2c
+  for (int filterY = 0; filterY < filterLength; filterY++) {
dd1d2c
+      // Skia only knows LE, so we have to swizzle the input
dd1d2c
+    ByteSwapArray(aSrc[filterY], aRowSize);
dd1d2c
+  }
dd1d2c
+#endif
dd1d2c
+
dd1d2c
   SkOpts::convolve_vertically(filterValues, filterLength, aSrc, aRowSize, aDst,
dd1d2c
                               aHasAlpha);
dd1d2c
+
dd1d2c
+#if MOZ_BIG_ENDIAN
dd1d2c
+  // After skia is finished, we swizzle back to BE, in case
dd1d2c
+  // the input is used again somewhere else
dd1d2c
+  for (int filterY = 0; filterY < filterLength; filterY++) {
dd1d2c
+    ByteSwapArray(aSrc[filterY], aRowSize);
dd1d2c
+  }
dd1d2c
+  // The destination array as well
dd1d2c
+  ByteSwapArray(aDst, aRowSize);
dd1d2c
+#endif
dd1d2c
 }
dd1d2c
 
dd1d2c
 /* ConvolutionFilter::ComputeResizeFactor is derived from Skia's
dd1d2c
diff -r 36563351309d gfx/skia/skia/include/core/SkPreConfig.h
dd1d2c
--- a/gfx/skia/skia/include/core/SkPreConfig.h	Mon Sep 09 17:59:28 2019 +0200
dd1d2c
+++ b/gfx/skia/skia/include/core/SkPreConfig.h	Tue Sep 10 08:25:13 2019 +0200
dd1d2c
@@ -73,7 +73,7 @@
dd1d2c
       defined(__ppc__) || defined(__hppa) || \
dd1d2c
       defined(__PPC__) || defined(__PPC64__) || \
dd1d2c
       defined(_MIPSEB) || defined(__ARMEB__) || \
dd1d2c
-      defined(__s390__) || \
dd1d2c
+      defined(__s390__) || defined(__s390x__) || \
dd1d2c
       (defined(__sh__) && defined(__BIG_ENDIAN__)) || \
dd1d2c
       (defined(__ia64) && defined(__BIG_ENDIAN__))
dd1d2c
          #define SK_CPU_BENDIAN