Cleanup of SSE optimization files.
authorcommit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Wed, 30 Apr 2014 14:58:46 +0000 (14:58 +0000)
committercommit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Wed, 30 Apr 2014 14:58:46 +0000 (14:58 +0000)
General cleanup of optimization files for x86/SSEx.
Renamed the opts_check_SSE2.cpp file to _x86, since it's not specific
to SSE2. Commented out the ColorRect32 optimization, since it's
disabled anyway, to make it more visible.
Also fixed a lot of indentation, inclusion guards, spelling,
copyright headers, braces, whitespace, and sorting of includes.

Author: henrik.smiding@intel.com

Signed-off-by: Henrik Smiding <henrik.smiding@intel.com>
R=reed@google.com, mtklein@google.com, tomhudson@google.com, djsollen@google.com, joakim.landberg@intel.com

Author: henrik.smiding@intel.com

Review URL: https://codereview.chromium.org/264603002

git-svn-id: http://skia.googlecode.com/svn/trunk@14464 2bbb7eff-a529-9590-31e7-b0007b416f81

23 files changed:
gyp/opts.gyp
src/core/SkBitmapProcState_matrixProcs.cpp
src/opts/SkBitmapFilter_opts_SSE2.cpp
src/opts/SkBitmapFilter_opts_SSE2.h
src/opts/SkBitmapProcState_opts_SSE2.cpp
src/opts/SkBitmapProcState_opts_SSE2.h
src/opts/SkBitmapProcState_opts_SSSE3.cpp
src/opts/SkBitmapProcState_opts_SSSE3.h
src/opts/SkBlitRect_opts_SSE2.cpp
src/opts/SkBlitRect_opts_SSE2.h
src/opts/SkBlitRow_opts_SSE2.cpp
src/opts/SkBlitRow_opts_SSE2.h
src/opts/SkBlurImage_opts_SSE2.cpp
src/opts/SkBlurImage_opts_SSE2.h
src/opts/SkMorphology_opts_SSE2.cpp
src/opts/SkMorphology_opts_SSE2.h
src/opts/SkUtils_opts_SSE2.cpp
src/opts/SkUtils_opts_SSE2.h
src/opts/SkXfermode_opts_SSE2.cpp
src/opts/SkXfermode_opts_SSE2.h
src/opts/opts_check_SSE2.cpp [deleted file]
src/opts/opts_check_x86.cpp [new file with mode: 0644]
tools/chromium/chrome_changes

index 36af0c49da4c0a2c20b86062ac43f6a5a603d89f..6ca602ca2c801bc70d4561354cddd661a26aca5e 100644 (file)
@@ -48,7 +48,7 @@
             'opts_ssse3',
           ],
           'sources': [
-            '../src/opts/opts_check_SSE2.cpp',
+            '../src/opts/opts_check_x86.cpp',
             '../src/opts/SkBitmapProcState_opts_SSE2.cpp',
             '../src/opts/SkBitmapFilter_opts_SSE2.cpp',
             '../src/opts/SkBlitRow_opts_SSE2.cpp',
index a05c13ed283c847edf24f04f07b55b60d8ef6806..02204b676b2fc6945a86acb0adbbcdea4a2fd8d3 100644 (file)
@@ -65,7 +65,7 @@ struct ClampTileProcs {
     }
 };
 
-// Referenced in opts_check_SSE2.cpp
+// Referenced in opts_check_x86.cpp
 void ClampX_ClampY_nofilter_scale(const SkBitmapProcState& s, uint32_t xy[],
                                   int count, int x, int y) {
     return NoFilterProc_Scale<ClampTileProcs, true>(s, xy, count, x, y);
index 259e2efc0ecdd83a9cbc89b2ab691f2e42a7d47a..b0405669218ba635017e36d308374235eae44953 100644 (file)
@@ -5,17 +5,15 @@
  * found in the LICENSE file.
  */
 
-#include "SkBitmapProcState.h"
+#include <emmintrin.h>
 #include "SkBitmap.h"
+#include "SkBitmapFilter_opts_SSE2.h"
+#include "SkBitmapProcState.h"
 #include "SkColor.h"
 #include "SkColorPriv.h"
-#include "SkUnPreMultiply.h"
-#include "SkShader.h"
 #include "SkConvolver.h"
-
-#include "SkBitmapFilter_opts_SSE2.h"
-
-#include <emmintrin.h>
+#include "SkShader.h"
+#include "SkUnPreMultiply.h"
 
 #if 0
 static inline void print128i(__m128i value) {
@@ -175,7 +173,6 @@ void highQualityFilter_ScaleOnly_SSE2(const SkBitmapProcState &s, int x, int y,
 
         s.fInvProc(s.fInvMatrix, SkIntToScalar(x),
                     SkIntToScalar(y), &srcPt);
-
     }
 }
 
@@ -185,126 +182,126 @@ void convolveHorizontally_SSE2(const unsigned char* src_data,
                                const SkConvolutionFilter1D& filter,
                                unsigned char* out_row,
                                bool /*has_alpha*/) {
-  int num_values = filter.numValues();
-
-  int filter_offset, filter_length;
-  __m128i zero = _mm_setzero_si128();
-  __m128i mask[4];
-  // |mask| will be used to decimate all extra filter coefficients that are
-  // loaded by SIMD when |filter_length| is not divisible by 4.
-  // mask[0] is not used in following algorithm.
-  mask[1] = _mm_set_epi16(0, 0, 0, 0, 0, 0, 0, -1);
-  mask[2] = _mm_set_epi16(0, 0, 0, 0, 0, 0, -1, -1);
-  mask[3] = _mm_set_epi16(0, 0, 0, 0, 0, -1, -1, -1);
-
-  // Output one pixel each iteration, calculating all channels (RGBA) together.
-  for (int out_x = 0; out_x < num_values; out_x++) {
-    const SkConvolutionFilter1D::ConvolutionFixed* filter_values =
-        filter.FilterForValue(out_x, &filter_offset, &filter_length);
-
-    __m128i accum = _mm_setzero_si128();
-
-    // Compute the first pixel in this row that the filter affects. It will
-    // touch |filter_length| pixels (4 bytes each) after this.
-    const __m128i* row_to_filter =
-        reinterpret_cast<const __m128i*>(&src_data[filter_offset << 2]);
-
-    // We will load and accumulate with four coefficients per iteration.
-    for (int filter_x = 0; filter_x < filter_length >> 2; filter_x++) {
-
-      // Load 4 coefficients => duplicate 1st and 2nd of them for all channels.
-      __m128i coeff, coeff16;
-      // [16] xx xx xx xx c3 c2 c1 c0
-      coeff = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(filter_values));
-      // [16] xx xx xx xx c1 c1 c0 c0
-      coeff16 = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(1, 1, 0, 0));
-      // [16] c1 c1 c1 c1 c0 c0 c0 c0
-      coeff16 = _mm_unpacklo_epi16(coeff16, coeff16);
-
-      // Load four pixels => unpack the first two pixels to 16 bits =>
-      // multiply with coefficients => accumulate the convolution result.
-      // [8] a3 b3 g3 r3 a2 b2 g2 r2 a1 b1 g1 r1 a0 b0 g0 r0
-      __m128i src8 = _mm_loadu_si128(row_to_filter);
-      // [16] a1 b1 g1 r1 a0 b0 g0 r0
-      __m128i src16 = _mm_unpacklo_epi8(src8, zero);
-      __m128i mul_hi = _mm_mulhi_epi16(src16, coeff16);
-      __m128i mul_lo = _mm_mullo_epi16(src16, coeff16);
-      // [32]  a0*c0 b0*c0 g0*c0 r0*c0
-      __m128i t = _mm_unpacklo_epi16(mul_lo, mul_hi);
-      accum = _mm_add_epi32(accum, t);
-      // [32]  a1*c1 b1*c1 g1*c1 r1*c1
-      t = _mm_unpackhi_epi16(mul_lo, mul_hi);
-      accum = _mm_add_epi32(accum, t);
-
-      // Duplicate 3rd and 4th coefficients for all channels =>
-      // unpack the 3rd and 4th pixels to 16 bits => multiply with coefficients
-      // => accumulate the convolution results.
-      // [16] xx xx xx xx c3 c3 c2 c2
-      coeff16 = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(3, 3, 2, 2));
-      // [16] c3 c3 c3 c3 c2 c2 c2 c2
-      coeff16 = _mm_unpacklo_epi16(coeff16, coeff16);
-      // [16] a3 g3 b3 r3 a2 g2 b2 r2
-      src16 = _mm_unpackhi_epi8(src8, zero);
-      mul_hi = _mm_mulhi_epi16(src16, coeff16);
-      mul_lo = _mm_mullo_epi16(src16, coeff16);
-      // [32]  a2*c2 b2*c2 g2*c2 r2*c2
-      t = _mm_unpacklo_epi16(mul_lo, mul_hi);
-      accum = _mm_add_epi32(accum, t);
-      // [32]  a3*c3 b3*c3 g3*c3 r3*c3
-      t = _mm_unpackhi_epi16(mul_lo, mul_hi);
-      accum = _mm_add_epi32(accum, t);
-
-      // Advance the pixel and coefficients pointers.
-      row_to_filter += 1;
-      filter_values += 4;
-    }
+    int num_values = filter.numValues();
+
+    int filter_offset, filter_length;
+    __m128i zero = _mm_setzero_si128();
+    __m128i mask[4];
+    // |mask| will be used to decimate all extra filter coefficients that are
+    // loaded by SIMD when |filter_length| is not divisible by 4.
+    // mask[0] is not used in following algorithm.
+    mask[1] = _mm_set_epi16(0, 0, 0, 0, 0, 0, 0, -1);
+    mask[2] = _mm_set_epi16(0, 0, 0, 0, 0, 0, -1, -1);
+    mask[3] = _mm_set_epi16(0, 0, 0, 0, 0, -1, -1, -1);
+
+    // Output one pixel each iteration, calculating all channels (RGBA) together.
+    for (int out_x = 0; out_x < num_values; out_x++) {
+        const SkConvolutionFilter1D::ConvolutionFixed* filter_values =
+            filter.FilterForValue(out_x, &filter_offset, &filter_length);
+
+        __m128i accum = _mm_setzero_si128();
+
+        // Compute the first pixel in this row that the filter affects. It will
+        // touch |filter_length| pixels (4 bytes each) after this.
+        const __m128i* row_to_filter =
+            reinterpret_cast<const __m128i*>(&src_data[filter_offset << 2]);
+
+        // We will load and accumulate with four coefficients per iteration.
+        for (int filter_x = 0; filter_x < filter_length >> 2; filter_x++) {
+
+            // Load 4 coefficients => duplicate 1st and 2nd of them for all channels.
+            __m128i coeff, coeff16;
+            // [16] xx xx xx xx c3 c2 c1 c0
+            coeff = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(filter_values));
+            // [16] xx xx xx xx c1 c1 c0 c0
+            coeff16 = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(1, 1, 0, 0));
+            // [16] c1 c1 c1 c1 c0 c0 c0 c0
+            coeff16 = _mm_unpacklo_epi16(coeff16, coeff16);
+
+            // Load four pixels => unpack the first two pixels to 16 bits =>
+            // multiply with coefficients => accumulate the convolution result.
+            // [8] a3 b3 g3 r3 a2 b2 g2 r2 a1 b1 g1 r1 a0 b0 g0 r0
+            __m128i src8 = _mm_loadu_si128(row_to_filter);
+            // [16] a1 b1 g1 r1 a0 b0 g0 r0
+            __m128i src16 = _mm_unpacklo_epi8(src8, zero);
+            __m128i mul_hi = _mm_mulhi_epi16(src16, coeff16);
+            __m128i mul_lo = _mm_mullo_epi16(src16, coeff16);
+            // [32]  a0*c0 b0*c0 g0*c0 r0*c0
+            __m128i t = _mm_unpacklo_epi16(mul_lo, mul_hi);
+            accum = _mm_add_epi32(accum, t);
+            // [32]  a1*c1 b1*c1 g1*c1 r1*c1
+            t = _mm_unpackhi_epi16(mul_lo, mul_hi);
+            accum = _mm_add_epi32(accum, t);
+
+            // Duplicate 3rd and 4th coefficients for all channels =>
+            // unpack the 3rd and 4th pixels to 16 bits => multiply with coefficients
+            // => accumulate the convolution results.
+            // [16] xx xx xx xx c3 c3 c2 c2
+            coeff16 = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(3, 3, 2, 2));
+            // [16] c3 c3 c3 c3 c2 c2 c2 c2
+            coeff16 = _mm_unpacklo_epi16(coeff16, coeff16);
+            // [16] a3 g3 b3 r3 a2 g2 b2 r2
+            src16 = _mm_unpackhi_epi8(src8, zero);
+            mul_hi = _mm_mulhi_epi16(src16, coeff16);
+            mul_lo = _mm_mullo_epi16(src16, coeff16);
+            // [32]  a2*c2 b2*c2 g2*c2 r2*c2
+            t = _mm_unpacklo_epi16(mul_lo, mul_hi);
+            accum = _mm_add_epi32(accum, t);
+            // [32]  a3*c3 b3*c3 g3*c3 r3*c3
+            t = _mm_unpackhi_epi16(mul_lo, mul_hi);
+            accum = _mm_add_epi32(accum, t);
+
+            // Advance the pixel and coefficients pointers.
+            row_to_filter += 1;
+            filter_values += 4;
+        }
 
-    // When |filter_length| is not divisible by 4, we need to decimate some of
-    // the filter coefficient that was loaded incorrectly to zero; Other than
-    // that the algorithm is same with above, exceot that the 4th pixel will be
-    // always absent.
-    int r = filter_length&3;
-    if (r) {
-      // Note: filter_values must be padded to align_up(filter_offset, 8).
-      __m128i coeff, coeff16;
-      coeff = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(filter_values));
-      // Mask out extra filter taps.
-      coeff = _mm_and_si128(coeff, mask[r]);
-      coeff16 = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(1, 1, 0, 0));
-      coeff16 = _mm_unpacklo_epi16(coeff16, coeff16);
-
-      // Note: line buffer must be padded to align_up(filter_offset, 16).
-      // We resolve this by use C-version for the last horizontal line.
-      __m128i src8 = _mm_loadu_si128(row_to_filter);
-      __m128i src16 = _mm_unpacklo_epi8(src8, zero);
-      __m128i mul_hi = _mm_mulhi_epi16(src16, coeff16);
-      __m128i mul_lo = _mm_mullo_epi16(src16, coeff16);
-      __m128i t = _mm_unpacklo_epi16(mul_lo, mul_hi);
-      accum = _mm_add_epi32(accum, t);
-      t = _mm_unpackhi_epi16(mul_lo, mul_hi);
-      accum = _mm_add_epi32(accum, t);
-
-      src16 = _mm_unpackhi_epi8(src8, zero);
-      coeff16 = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(3, 3, 2, 2));
-      coeff16 = _mm_unpacklo_epi16(coeff16, coeff16);
-      mul_hi = _mm_mulhi_epi16(src16, coeff16);
-      mul_lo = _mm_mullo_epi16(src16, coeff16);
-      t = _mm_unpacklo_epi16(mul_lo, mul_hi);
-      accum = _mm_add_epi32(accum, t);
-    }
+        // When |filter_length| is not divisible by 4, we need to decimate some of
+        // the filter coefficient that was loaded incorrectly to zero; Other than
+        // that the algorithm is same with above, exceot that the 4th pixel will be
+        // always absent.
+        int r = filter_length&3;
+        if (r) {
+            // Note: filter_values must be padded to align_up(filter_offset, 8).
+            __m128i coeff, coeff16;
+            coeff = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(filter_values));
+            // Mask out extra filter taps.
+            coeff = _mm_and_si128(coeff, mask[r]);
+            coeff16 = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(1, 1, 0, 0));
+            coeff16 = _mm_unpacklo_epi16(coeff16, coeff16);
+
+            // Note: line buffer must be padded to align_up(filter_offset, 16).
+            // We resolve this by use C-version for the last horizontal line.
+            __m128i src8 = _mm_loadu_si128(row_to_filter);
+            __m128i src16 = _mm_unpacklo_epi8(src8, zero);
+            __m128i mul_hi = _mm_mulhi_epi16(src16, coeff16);
+            __m128i mul_lo = _mm_mullo_epi16(src16, coeff16);
+            __m128i t = _mm_unpacklo_epi16(mul_lo, mul_hi);
+            accum = _mm_add_epi32(accum, t);
+            t = _mm_unpackhi_epi16(mul_lo, mul_hi);
+            accum = _mm_add_epi32(accum, t);
+
+            src16 = _mm_unpackhi_epi8(src8, zero);
+            coeff16 = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(3, 3, 2, 2));
+            coeff16 = _mm_unpacklo_epi16(coeff16, coeff16);
+            mul_hi = _mm_mulhi_epi16(src16, coeff16);
+            mul_lo = _mm_mullo_epi16(src16, coeff16);
+            t = _mm_unpacklo_epi16(mul_lo, mul_hi);
+            accum = _mm_add_epi32(accum, t);
+        }
 
-    // Shift right for fixed point implementation.
-    accum = _mm_srai_epi32(accum, SkConvolutionFilter1D::kShiftBits);
+        // Shift right for fixed point implementation.
+        accum = _mm_srai_epi32(accum, SkConvolutionFilter1D::kShiftBits);
 
-    // Packing 32 bits |accum| to 16 bits per channel (signed saturation).
-    accum = _mm_packs_epi32(accum, zero);
-    // Packing 16 bits |accum| to 8 bits per channel (unsigned saturation).
-    accum = _mm_packus_epi16(accum, zero);
+        // Packing 32 bits |accum| to 16 bits per channel (signed saturation).
+        accum = _mm_packs_epi32(accum, zero);
+        // Packing 16 bits |accum| to 8 bits per channel (unsigned saturation).
+        accum = _mm_packus_epi16(accum, zero);
 
-    // Store the pixel value of 32 bits.
-    *(reinterpret_cast<int*>(out_row)) = _mm_cvtsi128_si32(accum);
-    out_row += 4;
-  }
+        // Store the pixel value of 32 bits.
+        *(reinterpret_cast<int*>(out_row)) = _mm_cvtsi128_si32(accum);
+        out_row += 4;
+    }
 }
 
 // Convolves horizontally along four rows. The row data is given in
@@ -314,116 +311,116 @@ void convolveHorizontally_SSE2(const unsigned char* src_data,
 void convolve4RowsHorizontally_SSE2(const unsigned char* src_data[4],
                                     const SkConvolutionFilter1D& filter,
                                     unsigned char* out_row[4]) {
-  int num_values = filter.numValues();
-
-  int filter_offset, filter_length;
-  __m128i zero = _mm_setzero_si128();
-  __m128i mask[4];
-  // |mask| will be used to decimate all extra filter coefficients that are
-  // loaded by SIMD when |filter_length| is not divisible by 4.
-  // mask[0] is not used in following algorithm.
-  mask[1] = _mm_set_epi16(0, 0, 0, 0, 0, 0, 0, -1);
-  mask[2] = _mm_set_epi16(0, 0, 0, 0, 0, 0, -1, -1);
-  mask[3] = _mm_set_epi16(0, 0, 0, 0, 0, -1, -1, -1);
-
-  // Output one pixel each iteration, calculating all channels (RGBA) together.
-  for (int out_x = 0; out_x < num_values; out_x++) {
-    const SkConvolutionFilter1D::ConvolutionFixed* filter_values =
-        filter.FilterForValue(out_x, &filter_offset, &filter_length);
-
-    // four pixels in a column per iteration.
-    __m128i accum0 = _mm_setzero_si128();
-    __m128i accum1 = _mm_setzero_si128();
-    __m128i accum2 = _mm_setzero_si128();
-    __m128i accum3 = _mm_setzero_si128();
-    int start = (filter_offset<<2);
-    // We will load and accumulate with four coefficients per iteration.
-    for (int filter_x = 0; filter_x < (filter_length >> 2); filter_x++) {
-      __m128i coeff, coeff16lo, coeff16hi;
-      // [16] xx xx xx xx c3 c2 c1 c0
-      coeff = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(filter_values));
-      // [16] xx xx xx xx c1 c1 c0 c0
-      coeff16lo = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(1, 1, 0, 0));
-      // [16] c1 c1 c1 c1 c0 c0 c0 c0
-      coeff16lo = _mm_unpacklo_epi16(coeff16lo, coeff16lo);
-      // [16] xx xx xx xx c3 c3 c2 c2
-      coeff16hi = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(3, 3, 2, 2));
-      // [16] c3 c3 c3 c3 c2 c2 c2 c2
-      coeff16hi = _mm_unpacklo_epi16(coeff16hi, coeff16hi);
-
-      __m128i src8, src16, mul_hi, mul_lo, t;
-
-#define ITERATION(src, accum)                                          \
-      src8 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(src));   \
-      src16 = _mm_unpacklo_epi8(src8, zero);                           \
-      mul_hi = _mm_mulhi_epi16(src16, coeff16lo);                      \
-      mul_lo = _mm_mullo_epi16(src16, coeff16lo);                      \
-      t = _mm_unpacklo_epi16(mul_lo, mul_hi);                          \
-      accum = _mm_add_epi32(accum, t);                                 \
-      t = _mm_unpackhi_epi16(mul_lo, mul_hi);                          \
-      accum = _mm_add_epi32(accum, t);                                 \
-      src16 = _mm_unpackhi_epi8(src8, zero);                           \
-      mul_hi = _mm_mulhi_epi16(src16, coeff16hi);                      \
-      mul_lo = _mm_mullo_epi16(src16, coeff16hi);                      \
-      t = _mm_unpacklo_epi16(mul_lo, mul_hi);                          \
-      accum = _mm_add_epi32(accum, t);                                 \
-      t = _mm_unpackhi_epi16(mul_lo, mul_hi);                          \
-      accum = _mm_add_epi32(accum, t)
-
-      ITERATION(src_data[0] + start, accum0);
-      ITERATION(src_data[1] + start, accum1);
-      ITERATION(src_data[2] + start, accum2);
-      ITERATION(src_data[3] + start, accum3);
-
-      start += 16;
-      filter_values += 4;
-    }
+    int num_values = filter.numValues();
+
+    int filter_offset, filter_length;
+    __m128i zero = _mm_setzero_si128();
+    __m128i mask[4];
+    // |mask| will be used to decimate all extra filter coefficients that are
+    // loaded by SIMD when |filter_length| is not divisible by 4.
+    // mask[0] is not used in following algorithm.
+    mask[1] = _mm_set_epi16(0, 0, 0, 0, 0, 0, 0, -1);
+    mask[2] = _mm_set_epi16(0, 0, 0, 0, 0, 0, -1, -1);
+    mask[3] = _mm_set_epi16(0, 0, 0, 0, 0, -1, -1, -1);
+
+    // Output one pixel each iteration, calculating all channels (RGBA) together.
+    for (int out_x = 0; out_x < num_values; out_x++) {
+        const SkConvolutionFilter1D::ConvolutionFixed* filter_values =
+            filter.FilterForValue(out_x, &filter_offset, &filter_length);
+
+        // four pixels in a column per iteration.
+        __m128i accum0 = _mm_setzero_si128();
+        __m128i accum1 = _mm_setzero_si128();
+        __m128i accum2 = _mm_setzero_si128();
+        __m128i accum3 = _mm_setzero_si128();
+        int start = (filter_offset<<2);
+        // We will load and accumulate with four coefficients per iteration.
+        for (int filter_x = 0; filter_x < (filter_length >> 2); filter_x++) {
+            __m128i coeff, coeff16lo, coeff16hi;
+            // [16] xx xx xx xx c3 c2 c1 c0
+            coeff = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(filter_values));
+            // [16] xx xx xx xx c1 c1 c0 c0
+            coeff16lo = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(1, 1, 0, 0));
+            // [16] c1 c1 c1 c1 c0 c0 c0 c0
+            coeff16lo = _mm_unpacklo_epi16(coeff16lo, coeff16lo);
+            // [16] xx xx xx xx c3 c3 c2 c2
+            coeff16hi = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(3, 3, 2, 2));
+            // [16] c3 c3 c3 c3 c2 c2 c2 c2
+            coeff16hi = _mm_unpacklo_epi16(coeff16hi, coeff16hi);
+
+            __m128i src8, src16, mul_hi, mul_lo, t;
+
+#define ITERATION(src, accum)                                                \
+            src8 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(src));   \
+            src16 = _mm_unpacklo_epi8(src8, zero);                           \
+            mul_hi = _mm_mulhi_epi16(src16, coeff16lo);                      \
+            mul_lo = _mm_mullo_epi16(src16, coeff16lo);                      \
+            t = _mm_unpacklo_epi16(mul_lo, mul_hi);                          \
+            accum = _mm_add_epi32(accum, t);                                 \
+            t = _mm_unpackhi_epi16(mul_lo, mul_hi);                          \
+            accum = _mm_add_epi32(accum, t);                                 \
+            src16 = _mm_unpackhi_epi8(src8, zero);                           \
+            mul_hi = _mm_mulhi_epi16(src16, coeff16hi);                      \
+            mul_lo = _mm_mullo_epi16(src16, coeff16hi);                      \
+            t = _mm_unpacklo_epi16(mul_lo, mul_hi);                          \
+            accum = _mm_add_epi32(accum, t);                                 \
+            t = _mm_unpackhi_epi16(mul_lo, mul_hi);                          \
+            accum = _mm_add_epi32(accum, t)
+
+            ITERATION(src_data[0] + start, accum0);
+            ITERATION(src_data[1] + start, accum1);
+            ITERATION(src_data[2] + start, accum2);
+            ITERATION(src_data[3] + start, accum3);
+
+            start += 16;
+            filter_values += 4;
+        }
 
-    int r = filter_length & 3;
-    if (r) {
-      // Note: filter_values must be padded to align_up(filter_offset, 8);
-      __m128i coeff;
-      coeff = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(filter_values));
-      // Mask out extra filter taps.
-      coeff = _mm_and_si128(coeff, mask[r]);
-
-      __m128i coeff16lo = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(1, 1, 0, 0));
-      /* c1 c1 c1 c1 c0 c0 c0 c0 */
-      coeff16lo = _mm_unpacklo_epi16(coeff16lo, coeff16lo);
-      __m128i coeff16hi = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(3, 3, 2, 2));
-      coeff16hi = _mm_unpacklo_epi16(coeff16hi, coeff16hi);
-
-      __m128i src8, src16, mul_hi, mul_lo, t;
-
-      ITERATION(src_data[0] + start, accum0);
-      ITERATION(src_data[1] + start, accum1);
-      ITERATION(src_data[2] + start, accum2);
-      ITERATION(src_data[3] + start, accum3);
-    }
+        int r = filter_length & 3;
+        if (r) {
+            // Note: filter_values must be padded to align_up(filter_offset, 8);
+            __m128i coeff;
+            coeff = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(filter_values));
+            // Mask out extra filter taps.
+            coeff = _mm_and_si128(coeff, mask[r]);
+
+            __m128i coeff16lo = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(1, 1, 0, 0));
+            /* c1 c1 c1 c1 c0 c0 c0 c0 */
+            coeff16lo = _mm_unpacklo_epi16(coeff16lo, coeff16lo);
+            __m128i coeff16hi = _mm_shufflelo_epi16(coeff, _MM_SHUFFLE(3, 3, 2, 2));
+            coeff16hi = _mm_unpacklo_epi16(coeff16hi, coeff16hi);
+
+            __m128i src8, src16, mul_hi, mul_lo, t;
+
+            ITERATION(src_data[0] + start, accum0);
+            ITERATION(src_data[1] + start, accum1);
+            ITERATION(src_data[2] + start, accum2);
+            ITERATION(src_data[3] + start, accum3);
+        }
 
-    accum0 = _mm_srai_epi32(accum0, SkConvolutionFilter1D::kShiftBits);
-    accum0 = _mm_packs_epi32(accum0, zero);
-    accum0 = _mm_packus_epi16(accum0, zero);
-    accum1 = _mm_srai_epi32(accum1, SkConvolutionFilter1D::kShiftBits);
-    accum1 = _mm_packs_epi32(accum1, zero);
-    accum1 = _mm_packus_epi16(accum1, zero);
-    accum2 = _mm_srai_epi32(accum2, SkConvolutionFilter1D::kShiftBits);
-    accum2 = _mm_packs_epi32(accum2, zero);
-    accum2 = _mm_packus_epi16(accum2, zero);
-    accum3 = _mm_srai_epi32(accum3, SkConvolutionFilter1D::kShiftBits);
-    accum3 = _mm_packs_epi32(accum3, zero);
-    accum3 = _mm_packus_epi16(accum3, zero);
-
-    *(reinterpret_cast<int*>(out_row[0])) = _mm_cvtsi128_si32(accum0);
-    *(reinterpret_cast<int*>(out_row[1])) = _mm_cvtsi128_si32(accum1);
-    *(reinterpret_cast<int*>(out_row[2])) = _mm_cvtsi128_si32(accum2);
-    *(reinterpret_cast<int*>(out_row[3])) = _mm_cvtsi128_si32(accum3);
-
-    out_row[0] += 4;
-    out_row[1] += 4;
-    out_row[2] += 4;
-    out_row[3] += 4;
-  }
+        accum0 = _mm_srai_epi32(accum0, SkConvolutionFilter1D::kShiftBits);
+        accum0 = _mm_packs_epi32(accum0, zero);
+        accum0 = _mm_packus_epi16(accum0, zero);
+        accum1 = _mm_srai_epi32(accum1, SkConvolutionFilter1D::kShiftBits);
+        accum1 = _mm_packs_epi32(accum1, zero);
+        accum1 = _mm_packus_epi16(accum1, zero);
+        accum2 = _mm_srai_epi32(accum2, SkConvolutionFilter1D::kShiftBits);
+        accum2 = _mm_packs_epi32(accum2, zero);
+        accum2 = _mm_packus_epi16(accum2, zero);
+        accum3 = _mm_srai_epi32(accum3, SkConvolutionFilter1D::kShiftBits);
+        accum3 = _mm_packs_epi32(accum3, zero);
+        accum3 = _mm_packus_epi16(accum3, zero);
+
+        *(reinterpret_cast<int*>(out_row[0])) = _mm_cvtsi128_si32(accum0);
+        *(reinterpret_cast<int*>(out_row[1])) = _mm_cvtsi128_si32(accum1);
+        *(reinterpret_cast<int*>(out_row[2])) = _mm_cvtsi128_si32(accum2);
+        *(reinterpret_cast<int*>(out_row[3])) = _mm_cvtsi128_si32(accum3);
+
+        out_row[0] += 4;
+        out_row[1] += 4;
+        out_row[2] += 4;
+        out_row[3] += 4;
+    }
 }
 
 // Does vertical convolution to produce one output row. The filter values and
@@ -438,166 +435,166 @@ void convolveVertically_SSE2(const SkConvolutionFilter1D::ConvolutionFixed* filt
                              unsigned char* const* source_data_rows,
                              int pixel_width,
                              unsigned char* out_row) {
-  int width = pixel_width & ~3;
-
-  __m128i zero = _mm_setzero_si128();
-  __m128i accum0, accum1, accum2, accum3, coeff16;
-  const __m128i* src;
-  // Output four pixels per iteration (16 bytes).
-  for (int out_x = 0; out_x < width; out_x += 4) {
-
-    // Accumulated result for each pixel. 32 bits per RGBA channel.
-    accum0 = _mm_setzero_si128();
-    accum1 = _mm_setzero_si128();
-    accum2 = _mm_setzero_si128();
-    accum3 = _mm_setzero_si128();
-
-    // Convolve with one filter coefficient per iteration.
-    for (int filter_y = 0; filter_y < filter_length; filter_y++) {
-
-      // Duplicate the filter coefficient 8 times.
-      // [16] cj cj cj cj cj cj cj cj
-      coeff16 = _mm_set1_epi16(filter_values[filter_y]);
-
-      // Load four pixels (16 bytes) together.
-      // [8] a3 b3 g3 r3 a2 b2 g2 r2 a1 b1 g1 r1 a0 b0 g0 r0
-      src = reinterpret_cast<const __m128i*>(
-          &source_data_rows[filter_y][out_x << 2]);
-      __m128i src8 = _mm_loadu_si128(src);
-
-      // Unpack 1st and 2nd pixels from 8 bits to 16 bits for each channels =>
-      // multiply with current coefficient => accumulate the result.
-      // [16] a1 b1 g1 r1 a0 b0 g0 r0
-      __m128i src16 = _mm_unpacklo_epi8(src8, zero);
-      __m128i mul_hi = _mm_mulhi_epi16(src16, coeff16);
-      __m128i mul_lo = _mm_mullo_epi16(src16, coeff16);
-      // [32] a0 b0 g0 r0
-      __m128i t = _mm_unpacklo_epi16(mul_lo, mul_hi);
-      accum0 = _mm_add_epi32(accum0, t);
-      // [32] a1 b1 g1 r1
-      t = _mm_unpackhi_epi16(mul_lo, mul_hi);
-      accum1 = _mm_add_epi32(accum1, t);
-
-      // Unpack 3rd and 4th pixels from 8 bits to 16 bits for each channels =>
-      // multiply with current coefficient => accumulate the result.
-      // [16] a3 b3 g3 r3 a2 b2 g2 r2
-      src16 = _mm_unpackhi_epi8(src8, zero);
-      mul_hi = _mm_mulhi_epi16(src16, coeff16);
-      mul_lo = _mm_mullo_epi16(src16, coeff16);
-      // [32] a2 b2 g2 r2
-      t = _mm_unpacklo_epi16(mul_lo, mul_hi);
-      accum2 = _mm_add_epi32(accum2, t);
-      // [32] a3 b3 g3 r3
-      t = _mm_unpackhi_epi16(mul_lo, mul_hi);
-      accum3 = _mm_add_epi32(accum3, t);
-    }
-
-    // Shift right for fixed point implementation.
-    accum0 = _mm_srai_epi32(accum0, SkConvolutionFilter1D::kShiftBits);
-    accum1 = _mm_srai_epi32(accum1, SkConvolutionFilter1D::kShiftBits);
-    accum2 = _mm_srai_epi32(accum2, SkConvolutionFilter1D::kShiftBits);
-    accum3 = _mm_srai_epi32(accum3, SkConvolutionFilter1D::kShiftBits);
-
-    // Packing 32 bits |accum| to 16 bits per channel (signed saturation).
-    // [16] a1 b1 g1 r1 a0 b0 g0 r0
-    accum0 = _mm_packs_epi32(accum0, accum1);
-    // [16] a3 b3 g3 r3 a2 b2 g2 r2
-    accum2 = _mm_packs_epi32(accum2, accum3);
+    int width = pixel_width & ~3;
+
+    __m128i zero = _mm_setzero_si128();
+    __m128i accum0, accum1, accum2, accum3, coeff16;
+    const __m128i* src;
+    // Output four pixels per iteration (16 bytes).
+    for (int out_x = 0; out_x < width; out_x += 4) {
+
+        // Accumulated result for each pixel. 32 bits per RGBA channel.
+        accum0 = _mm_setzero_si128();
+        accum1 = _mm_setzero_si128();
+        accum2 = _mm_setzero_si128();
+        accum3 = _mm_setzero_si128();
+
+        // Convolve with one filter coefficient per iteration.
+        for (int filter_y = 0; filter_y < filter_length; filter_y++) {
+
+            // Duplicate the filter coefficient 8 times.
+            // [16] cj cj cj cj cj cj cj cj
+            coeff16 = _mm_set1_epi16(filter_values[filter_y]);
+
+            // Load four pixels (16 bytes) together.
+            // [8] a3 b3 g3 r3 a2 b2 g2 r2 a1 b1 g1 r1 a0 b0 g0 r0
+            src = reinterpret_cast<const __m128i*>(
+                &source_data_rows[filter_y][out_x << 2]);
+            __m128i src8 = _mm_loadu_si128(src);
+
+            // Unpack 1st and 2nd pixels from 8 bits to 16 bits for each channels =>
+            // multiply with current coefficient => accumulate the result.
+            // [16] a1 b1 g1 r1 a0 b0 g0 r0
+            __m128i src16 = _mm_unpacklo_epi8(src8, zero);
+            __m128i mul_hi = _mm_mulhi_epi16(src16, coeff16);
+            __m128i mul_lo = _mm_mullo_epi16(src16, coeff16);
+            // [32] a0 b0 g0 r0
+            __m128i t = _mm_unpacklo_epi16(mul_lo, mul_hi);
+            accum0 = _mm_add_epi32(accum0, t);
+            // [32] a1 b1 g1 r1
+            t = _mm_unpackhi_epi16(mul_lo, mul_hi);
+            accum1 = _mm_add_epi32(accum1, t);
+
+            // Unpack 3rd and 4th pixels from 8 bits to 16 bits for each channels =>
+            // multiply with current coefficient => accumulate the result.
+            // [16] a3 b3 g3 r3 a2 b2 g2 r2
+            src16 = _mm_unpackhi_epi8(src8, zero);
+            mul_hi = _mm_mulhi_epi16(src16, coeff16);
+            mul_lo = _mm_mullo_epi16(src16, coeff16);
+            // [32] a2 b2 g2 r2
+            t = _mm_unpacklo_epi16(mul_lo, mul_hi);
+            accum2 = _mm_add_epi32(accum2, t);
+            // [32] a3 b3 g3 r3
+            t = _mm_unpackhi_epi16(mul_lo, mul_hi);
+            accum3 = _mm_add_epi32(accum3, t);
+        }
 
-    // Packing 16 bits |accum| to 8 bits per channel (unsigned saturation).
-    // [8] a3 b3 g3 r3 a2 b2 g2 r2 a1 b1 g1 r1 a0 b0 g0 r0
-    accum0 = _mm_packus_epi16(accum0, accum2);
+        // Shift right for fixed point implementation.
+        accum0 = _mm_srai_epi32(accum0, SkConvolutionFilter1D::kShiftBits);
+        accum1 = _mm_srai_epi32(accum1, SkConvolutionFilter1D::kShiftBits);
+        accum2 = _mm_srai_epi32(accum2, SkConvolutionFilter1D::kShiftBits);
+        accum3 = _mm_srai_epi32(accum3, SkConvolutionFilter1D::kShiftBits);
+
+        // Packing 32 bits |accum| to 16 bits per channel (signed saturation).
+        // [16] a1 b1 g1 r1 a0 b0 g0 r0
+        accum0 = _mm_packs_epi32(accum0, accum1);
+        // [16] a3 b3 g3 r3 a2 b2 g2 r2
+        accum2 = _mm_packs_epi32(accum2, accum3);
+
+        // Packing 16 bits |accum| to 8 bits per channel (unsigned saturation).
+        // [8] a3 b3 g3 r3 a2 b2 g2 r2 a1 b1 g1 r1 a0 b0 g0 r0
+        accum0 = _mm_packus_epi16(accum0, accum2);
+
+        if (has_alpha) {
+            // Compute the max(ri, gi, bi) for each pixel.
+            // [8] xx a3 b3 g3 xx a2 b2 g2 xx a1 b1 g1 xx a0 b0 g0
+            __m128i a = _mm_srli_epi32(accum0, 8);
+            // [8] xx xx xx max3 xx xx xx max2 xx xx xx max1 xx xx xx max0
+            __m128i b = _mm_max_epu8(a, accum0);  // Max of r and g.
+            // [8] xx xx a3 b3 xx xx a2 b2 xx xx a1 b1 xx xx a0 b0
+            a = _mm_srli_epi32(accum0, 16);
+            // [8] xx xx xx max3 xx xx xx max2 xx xx xx max1 xx xx xx max0
+            b = _mm_max_epu8(a, b);  // Max of r and g and b.
+            // [8] max3 00 00 00 max2 00 00 00 max1 00 00 00 max0 00 00 00
+            b = _mm_slli_epi32(b, 24);
+
+            // Make sure the value of alpha channel is always larger than maximum
+            // value of color channels.
+            accum0 = _mm_max_epu8(b, accum0);
+        } else {
+            // Set value of alpha channels to 0xFF.
+            __m128i mask = _mm_set1_epi32(0xff000000);
+            accum0 = _mm_or_si128(accum0, mask);
+        }
 
-    if (has_alpha) {
-      // Compute the max(ri, gi, bi) for each pixel.
-      // [8] xx a3 b3 g3 xx a2 b2 g2 xx a1 b1 g1 xx a0 b0 g0
-      __m128i a = _mm_srli_epi32(accum0, 8);
-      // [8] xx xx xx max3 xx xx xx max2 xx xx xx max1 xx xx xx max0
-      __m128i b = _mm_max_epu8(a, accum0);  // Max of r and g.
-      // [8] xx xx a3 b3 xx xx a2 b2 xx xx a1 b1 xx xx a0 b0
-      a = _mm_srli_epi32(accum0, 16);
-      // [8] xx xx xx max3 xx xx xx max2 xx xx xx max1 xx xx xx max0
-      b = _mm_max_epu8(a, b);  // Max of r and g and b.
-      // [8] max3 00 00 00 max2 00 00 00 max1 00 00 00 max0 00 00 00
-      b = _mm_slli_epi32(b, 24);
-
-      // Make sure the value of alpha channel is always larger than maximum
-      // value of color channels.
-      accum0 = _mm_max_epu8(b, accum0);
-    } else {
-      // Set value of alpha channels to 0xFF.
-      __m128i mask = _mm_set1_epi32(0xff000000);
-      accum0 = _mm_or_si128(accum0, mask);
+        // Store the convolution result (16 bytes) and advance the pixel pointers.
+        _mm_storeu_si128(reinterpret_cast<__m128i*>(out_row), accum0);
+        out_row += 16;
     }
 
-    // Store the convolution result (16 bytes) and advance the pixel pointers.
-    _mm_storeu_si128(reinterpret_cast<__m128i*>(out_row), accum0);
-    out_row += 16;
-  }
-
-  // When the width of the output is not divisible by 4, We need to save one
-  // pixel (4 bytes) each time. And also the fourth pixel is always absent.
-  if (pixel_width & 3) {
-    accum0 = _mm_setzero_si128();
-    accum1 = _mm_setzero_si128();
-    accum2 = _mm_setzero_si128();
-    for (int filter_y = 0; filter_y < filter_length; ++filter_y) {
-      coeff16 = _mm_set1_epi16(filter_values[filter_y]);
-      // [8] a3 b3 g3 r3 a2 b2 g2 r2 a1 b1 g1 r1 a0 b0 g0 r0
-      src = reinterpret_cast<const __m128i*>(
-          &source_data_rows[filter_y][width<<2]);
-      __m128i src8 = _mm_loadu_si128(src);
-      // [16] a1 b1 g1 r1 a0 b0 g0 r0
-      __m128i src16 = _mm_unpacklo_epi8(src8, zero);
-      __m128i mul_hi = _mm_mulhi_epi16(src16, coeff16);
-      __m128i mul_lo = _mm_mullo_epi16(src16, coeff16);
-      // [32] a0 b0 g0 r0
-      __m128i t = _mm_unpacklo_epi16(mul_lo, mul_hi);
-      accum0 = _mm_add_epi32(accum0, t);
-      // [32] a1 b1 g1 r1
-      t = _mm_unpackhi_epi16(mul_lo, mul_hi);
-      accum1 = _mm_add_epi32(accum1, t);
-      // [16] a3 b3 g3 r3 a2 b2 g2 r2
-      src16 = _mm_unpackhi_epi8(src8, zero);
-      mul_hi = _mm_mulhi_epi16(src16, coeff16);
-      mul_lo = _mm_mullo_epi16(src16, coeff16);
-      // [32] a2 b2 g2 r2
-      t = _mm_unpacklo_epi16(mul_lo, mul_hi);
-      accum2 = _mm_add_epi32(accum2, t);
-    }
+    // When the width of the output is not divisible by 4, We need to save one
+    // pixel (4 bytes) each time. And also the fourth pixel is always absent.
+    if (pixel_width & 3) {
+        accum0 = _mm_setzero_si128();
+        accum1 = _mm_setzero_si128();
+        accum2 = _mm_setzero_si128();
+        for (int filter_y = 0; filter_y < filter_length; ++filter_y) {
+            coeff16 = _mm_set1_epi16(filter_values[filter_y]);
+            // [8] a3 b3 g3 r3 a2 b2 g2 r2 a1 b1 g1 r1 a0 b0 g0 r0
+            src = reinterpret_cast<const __m128i*>(
+                &source_data_rows[filter_y][width<<2]);
+            __m128i src8 = _mm_loadu_si128(src);
+            // [16] a1 b1 g1 r1 a0 b0 g0 r0
+            __m128i src16 = _mm_unpacklo_epi8(src8, zero);
+            __m128i mul_hi = _mm_mulhi_epi16(src16, coeff16);
+            __m128i mul_lo = _mm_mullo_epi16(src16, coeff16);
+            // [32] a0 b0 g0 r0
+            __m128i t = _mm_unpacklo_epi16(mul_lo, mul_hi);
+            accum0 = _mm_add_epi32(accum0, t);
+            // [32] a1 b1 g1 r1
+            t = _mm_unpackhi_epi16(mul_lo, mul_hi);
+            accum1 = _mm_add_epi32(accum1, t);
+            // [16] a3 b3 g3 r3 a2 b2 g2 r2
+            src16 = _mm_unpackhi_epi8(src8, zero);
+            mul_hi = _mm_mulhi_epi16(src16, coeff16);
+            mul_lo = _mm_mullo_epi16(src16, coeff16);
+            // [32] a2 b2 g2 r2
+            t = _mm_unpacklo_epi16(mul_lo, mul_hi);
+            accum2 = _mm_add_epi32(accum2, t);
+        }
 
-    accum0 = _mm_srai_epi32(accum0, SkConvolutionFilter1D::kShiftBits);
-    accum1 = _mm_srai_epi32(accum1, SkConvolutionFilter1D::kShiftBits);
-    accum2 = _mm_srai_epi32(accum2, SkConvolutionFilter1D::kShiftBits);
-    // [16] a1 b1 g1 r1 a0 b0 g0 r0
-    accum0 = _mm_packs_epi32(accum0, accum1);
-    // [16] a3 b3 g3 r3 a2 b2 g2 r2
-    accum2 = _mm_packs_epi32(accum2, zero);
-    // [8] a3 b3 g3 r3 a2 b2 g2 r2 a1 b1 g1 r1 a0 b0 g0 r0
-    accum0 = _mm_packus_epi16(accum0, accum2);
-    if (has_alpha) {
-      // [8] xx a3 b3 g3 xx a2 b2 g2 xx a1 b1 g1 xx a0 b0 g0
-      __m128i a = _mm_srli_epi32(accum0, 8);
-      // [8] xx xx xx max3 xx xx xx max2 xx xx xx max1 xx xx xx max0
-      __m128i b = _mm_max_epu8(a, accum0);  // Max of r and g.
-      // [8] xx xx a3 b3 xx xx a2 b2 xx xx a1 b1 xx xx a0 b0
-      a = _mm_srli_epi32(accum0, 16);
-      // [8] xx xx xx max3 xx xx xx max2 xx xx xx max1 xx xx xx max0
-      b = _mm_max_epu8(a, b);  // Max of r and g and b.
-      // [8] max3 00 00 00 max2 00 00 00 max1 00 00 00 max0 00 00 00
-      b = _mm_slli_epi32(b, 24);
-      accum0 = _mm_max_epu8(b, accum0);
-    } else {
-      __m128i mask = _mm_set1_epi32(0xff000000);
-      accum0 = _mm_or_si128(accum0, mask);
-    }
+        accum0 = _mm_srai_epi32(accum0, SkConvolutionFilter1D::kShiftBits);
+        accum1 = _mm_srai_epi32(accum1, SkConvolutionFilter1D::kShiftBits);
+        accum2 = _mm_srai_epi32(accum2, SkConvolutionFilter1D::kShiftBits);
+        // [16] a1 b1 g1 r1 a0 b0 g0 r0
+        accum0 = _mm_packs_epi32(accum0, accum1);
+        // [16] a3 b3 g3 r3 a2 b2 g2 r2
+        accum2 = _mm_packs_epi32(accum2, zero);
+        // [8] a3 b3 g3 r3 a2 b2 g2 r2 a1 b1 g1 r1 a0 b0 g0 r0
+        accum0 = _mm_packus_epi16(accum0, accum2);
+        if (has_alpha) {
+            // [8] xx a3 b3 g3 xx a2 b2 g2 xx a1 b1 g1 xx a0 b0 g0
+            __m128i a = _mm_srli_epi32(accum0, 8);
+            // [8] xx xx xx max3 xx xx xx max2 xx xx xx max1 xx xx xx max0
+            __m128i b = _mm_max_epu8(a, accum0);  // Max of r and g.
+            // [8] xx xx a3 b3 xx xx a2 b2 xx xx a1 b1 xx xx a0 b0
+            a = _mm_srli_epi32(accum0, 16);
+            // [8] xx xx xx max3 xx xx xx max2 xx xx xx max1 xx xx xx max0
+            b = _mm_max_epu8(a, b);  // Max of r and g and b.
+            // [8] max3 00 00 00 max2 00 00 00 max1 00 00 00 max0 00 00 00
+            b = _mm_slli_epi32(b, 24);
+            accum0 = _mm_max_epu8(b, accum0);
+        } else {
+            __m128i mask = _mm_set1_epi32(0xff000000);
+            accum0 = _mm_or_si128(accum0, mask);
+        }
 
-    for (int out_x = width; out_x < pixel_width; out_x++) {
-      *(reinterpret_cast<int*>(out_row)) = _mm_cvtsi128_si32(accum0);
-      accum0 = _mm_srli_si128(accum0, 4);
-      out_row += 4;
+        for (int out_x = width; out_x < pixel_width; out_x++) {
+            *(reinterpret_cast<int*>(out_row)) = _mm_cvtsi128_si32(accum0);
+            accum0 = _mm_srli_si128(accum0, 4);
+            out_row += 4;
+        }
     }
-  }
 }
 
 void convolveVertically_SSE2(const SkConvolutionFilter1D::ConvolutionFixed* filter_values,
@@ -606,19 +603,19 @@ void convolveVertically_SSE2(const SkConvolutionFilter1D::ConvolutionFixed* filt
                              int pixel_width,
                              unsigned char* out_row,
                              bool has_alpha) {
-  if (has_alpha) {
-    convolveVertically_SSE2<true>(filter_values,
-                                  filter_length,
-                                  source_data_rows,
-                                  pixel_width,
-                                  out_row);
-  } else {
-    convolveVertically_SSE2<false>(filter_values,
-                                   filter_length,
-                                   source_data_rows,
-                                   pixel_width,
-                                   out_row);
-  }
+    if (has_alpha) {
+        convolveVertically_SSE2<true>(filter_values,
+                                      filter_length,
+                                      source_data_rows,
+                                      pixel_width,
+                                      out_row);
+    } else {
+        convolveVertically_SSE2<false>(filter_values,
+                                       filter_length,
+                                       source_data_rows,
+                                       pixel_width,
+                                       out_row);
+    }
 }
 
 void applySIMDPadding_SSE2(SkConvolutionFilter1D *filter) {
index 588f4ef18bbe19c71bb2ea118889f795a1dc15fe..661a824e22734eac14855a724cbb737d4816aca6 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2013 Google Inc.
  *
@@ -6,7 +5,6 @@
  * found in the LICENSE file.
  */
 
-
 #ifndef SkBitmapFilter_opts_sse2_DEFINED
 #define SkBitmapFilter_opts_sse2_DEFINED
 
@@ -14,9 +12,9 @@
 #include "SkConvolver.h"
 
 void highQualityFilter_ScaleOnly_SSE2(const SkBitmapProcState &s, int x, int y,
-                          SkPMColor *SK_RESTRICT colors, int count);
+                                      SkPMColor *SK_RESTRICT colors, int count);
 void highQualityFilter_SSE2(const SkBitmapProcState &s, int x, int y,
-                SkPMColor *SK_RESTRICT colors, int count);
+                            SkPMColor *SK_RESTRICT colors, int count);
 
 
 void convolveVertically_SSE2(const SkConvolutionFilter1D::ConvolutionFixed* filter_values,
index 54a2f2dab4b0df8df9359aa24b3d870418bad07d..2279b9d146e76f37ba73b8a6e80ae026d122517f 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2009 The Android Open Source Project
  *
@@ -6,7 +5,6 @@
  * found in the LICENSE file.
  */
 
-
 #include <emmintrin.h>
 #include "SkBitmapProcState_opts_SSE2.h"
 #include "SkColorPriv.h"
index 46e35a0f96f69bde7f09d770907296675ced050c..82c5cc8d6e1493f8efd09cba890fdfc0b27ec790 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2009 The Android Open Source Project
  *
@@ -6,6 +5,8 @@
  * found in the LICENSE file.
  */
 
+#ifndef SkBitmapProcState_opts_SSE2_DEFINED
+#define SkBitmapProcState_opts_SSE2_DEFINED
 
 #include "SkBitmapProcState.h"
 
@@ -24,7 +25,9 @@ void ClampX_ClampY_nofilter_scale_SSE2(const SkBitmapProcState& s,
 void ClampX_ClampY_filter_affine_SSE2(const SkBitmapProcState& s,
                                       uint32_t xy[], int count, int x, int y);
 void ClampX_ClampY_nofilter_affine_SSE2(const SkBitmapProcState& s,
-                                       uint32_t xy[], int count, int x, int y);
+                                        uint32_t xy[], int count, int x, int y);
 void S32_D16_filter_DX_SSE2(const SkBitmapProcState& s,
-                                  const uint32_t* xy,
-                                  int count, uint16_t* colors);
+                            const uint32_t* xy,
+                            int count, uint16_t* colors);
+
+#endif
index ddc8ccc5ab5fad5d8411c63df9e81ebae516e5c9..4622937c70cbc639970ffe9508f6b94538b2cf55 100644 (file)
@@ -425,9 +425,10 @@ void S32_generic_D32_filter_DX_SSSE3(const SkBitmapProcState& s,
     const __m128i zero = _mm_setzero_si128();
 
     __m128i alpha = _mm_setzero_si128();
-    if (has_alpha)
+    if (has_alpha) {
         // 8x(alpha)
         alpha = _mm_set1_epi16(s.fAlphaScale);
+    }
 
     if (sub_y == 0) {
         // Unroll 4x, interleave bytes, use pmaddubsw (all_x is small)
@@ -705,7 +706,7 @@ void S32_generic_D32_filter_DXDY_SSSE3(const SkBitmapProcState& s,
         *colors++ = _mm_cvtsi128_si32(sum0);
     }
 }
-}  // namepace
+}  // namespace
 
 void S32_opaque_D32_filter_DX_SSSE3(const SkBitmapProcState& s,
                                     const uint32_t* xy,
index 176f2bfbe7421e693c306f42b269123e7d55762f..9fd074aacf27a55907529097366db5dffd71b753 100644 (file)
@@ -5,6 +5,9 @@
  * found in the LICENSE file.
  */
 
+#ifndef SkBitmapProcState_opts_SSSE3_DEFINED
+#define SkBitmapProcState_opts_SSSE3_DEFINED
+
 #include "SkBitmapProcState.h"
 
 void S32_opaque_D32_filter_DX_SSSE3(const SkBitmapProcState& s,
@@ -19,3 +22,5 @@ void S32_opaque_D32_filter_DXDY_SSSE3(const SkBitmapProcState& s,
 void S32_alpha_D32_filter_DXDY_SSSE3(const SkBitmapProcState& s,
                                    const uint32_t* xy,
                                    int count, uint32_t* colors);
+
+#endif
index 3cb2b9c6d09f0c2e0b06d142ead4c3e6e7e2830d..d65a313dadf5b997c64172e272dff70ac2f16ba0 100644 (file)
@@ -5,15 +5,14 @@
  * found in the LICENSE file.
  */
 
+#include <emmintrin.h>
 #include "SkBlitRect_opts_SSE2.h"
 #include "SkBlitRow.h"
 #include "SkColorPriv.h"
 
-#include <emmintrin.h>
-
-/** Simple blitting of opaque rectangles less than 31 pixels wide:
-    inlines and merges sections of Color32_SSE2 and sk_memset32_SSE2.
-*/
+/* Simple blitting of opaque rectangles less than 31 pixels wide:
+ * inlines and merges sections of Color32_SSE2 and sk_memset32_SSE2.
+ */
 static void BlitRect32_OpaqueNarrow_SSE2(SkPMColor* SK_RESTRICT destination,
                                   int width, int height,
                                   size_t rowBytes, uint32_t color) {
@@ -42,12 +41,12 @@ static void BlitRect32_OpaqueNarrow_SSE2(SkPMColor* SK_RESTRICT destination,
     }
 }
 
-/**
-  Fast blitting of opaque rectangles at least 31 pixels wide:
-  inlines and merges sections of Color32_SSE2 and sk_memset32_SSE2.
-  A 31 pixel rectangle is guaranteed to have at least one
-  16-pixel aligned span that can take advantage of mm_store.
-*/
+/*
* Fast blitting of opaque rectangles at least 31 pixels wide:
* inlines and merges sections of Color32_SSE2 and sk_memset32_SSE2.
* A 31 pixel rectangle is guaranteed to have at least one
* 16-pixel aligned span that can take advantage of mm_store.
+ */
 static void BlitRect32_OpaqueWide_SSE2(SkPMColor* SK_RESTRICT destination,
                                 int width, int height,
                                 size_t rowBytes, uint32_t color) {
index 4d2f74a4b1bc80a45fd1af9089d22bfb50a4faa5..3d09f5c3abc86189fca70869653c3b8f18eb8195 100644 (file)
@@ -8,13 +8,11 @@
 #ifndef SkBlitRect_opts_SSE2_DEFINED
 #define SkBlitRect_opts_SSE2_DEFINED
 
-/*
-  These functions' implementations copy sections of both
-  SkBlitRow_opts_SSE2 and SkUtils_opts_SSE2.
-*/
-
 #include "SkColor.h"
 
+/* These functions' implementations copy sections of both
+ * SkBlitRow_opts_SSE2 and SkUtils_opts_SSE2.
+ */
 void ColorRect32_SSE2(SkPMColor* SK_RESTRICT dst,
                       int width, int height,
                       size_t rowBytes, uint32_t color);
index d1474f4a67c45bb37965d4a362c1cb5f79fcb496..391b24c8673809c9a40a0225be52129af2369237 100644 (file)
@@ -5,16 +5,14 @@
  * found in the LICENSE file.
  */
 
-
-#include "SkBlitRow_opts_SSE2.h"
+#include <emmintrin.h>
 #include "SkBitmapProcState_opts_SSE2.h"
+#include "SkBlitRow_opts_SSE2.h"
 #include "SkColorPriv.h"
 #include "SkColor_opts_SSE2.h"
 #include "SkDither.h"
 #include "SkUtils.h"
 
-#include <emmintrin.h>
-
 /* SSE2 version of S32_Blend_BlitRow32()
  * portable version is in core/SkBlitRow_D32.cpp
  */
@@ -179,7 +177,7 @@ void S32A_Opaque_BlitRow32_SSE2(SkPMColor* SK_RESTRICT dst,
             d++;
             count -= 4;
         }
-    #else
+#else
         __m128i rb_mask = _mm_set1_epi32(0x00FF00FF);
         __m128i c_256 = _mm_set1_epi16(0x0100);  // 8 copies of 256 (16-bit)
         while (count >= 4) {
@@ -342,7 +340,6 @@ void S32A_Blend_BlitRow32_SSE2(SkPMColor* SK_RESTRICT dst,
  */
 void Color32_SSE2(SkPMColor dst[], const SkPMColor src[], int count,
                   SkPMColor color) {
-
     if (count <= 0) {
         return;
     }
@@ -406,7 +403,7 @@ void Color32_SSE2(SkPMColor dst[], const SkPMColor src[], int count,
             }
             src = reinterpret_cast<const SkPMColor*>(s);
             dst = reinterpret_cast<SkPMColor*>(d);
-         }
+        }
 
         while (count > 0) {
             *dst = color + SkAlphaMulQ(*src, scale);
@@ -504,7 +501,7 @@ void SkARGB32_A8_BlitMask_SSE2(void* device, size_t dstRB, const void* maskPtr,
             }
             dst = reinterpret_cast<SkPMColor *>(d);
         }
-        while(count > 0) {
+        while (count > 0) {
             *dst= SkBlendARGB32(color, *dst, *mask);
             dst += 1;
             mask++;
index fcf82d08e578c09523beafc47b92d2be940a255d..29fd96e5e915da215ea763f5570eb9a446889643 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2009 The Android Open Source Project
  *
@@ -6,6 +5,8 @@
  * found in the LICENSE file.
  */
 
+#ifndef SkBlitRow_opts_SSE2_DEFINED
+#define SkBlitRow_opts_SSE2_DEFINED
 
 #include "SkBlitRow.h"
 
@@ -41,3 +42,5 @@ void S32_D565_Opaque_Dither_SSE2(uint16_t* SK_RESTRICT dst,
 void S32A_D565_Opaque_Dither_SSE2(uint16_t* SK_RESTRICT dst,
                                   const SkPMColor* SK_RESTRICT src,
                                   int count, U8CPU alpha, int x, int y);
+
+#endif
index 93830d78b46b7978ef5a7411d0631cf8de7acd81..bbc6a66462ea5bd278bcf20ef73e2f11ab80ad56 100644 (file)
@@ -5,36 +5,31 @@
  * found in the LICENSE file.
  */
 
-
+#include <emmintrin.h>
 #include "SkBitmap.h"
-#include "SkColorPriv.h"
 #include "SkBlurImage_opts_SSE2.h"
+#include "SkColorPriv.h"
 #include "SkRect.h"
 
-#include <emmintrin.h>
-
 namespace {
-
 enum BlurDirection {
     kX, kY
 };
 
-/**
- * Helper function to spread the components of a 32-bit integer into the
+/* Helper function to spread the components of a 32-bit integer into the
  * lower 8 bits of each 32-bit element of an SSE register.
  */
-
 inline __m128i expand(int a) {
-      const __m128i zero = _mm_setzero_si128();
+    const __m128i zero = _mm_setzero_si128();
 
-      // 0 0 0 0   0 0 0 0   0 0 0 0   A R G B
-      __m128i result = _mm_cvtsi32_si128(a);
+    // 0 0 0 0   0 0 0 0   0 0 0 0   A R G B
+    __m128i result = _mm_cvtsi32_si128(a);
 
-      // 0 0 0 0   0 0 0 0   0 A 0 R   0 G 0 B
-      result = _mm_unpacklo_epi8(result, zero);
+    // 0 0 0 0   0 0 0 0   0 A 0 R   0 G 0 B
+    result = _mm_unpacklo_epi8(result, zero);
 
-      // 0 0 0 A   0 0 0 R   0 0 0 G   0 0 0 B
-      return _mm_unpacklo_epi16(result, zero);
+    // 0 0 0 A   0 0 0 R   0 0 0 G   0 0 0 B
+    return _mm_unpacklo_epi16(result, zero);
 }
 
 template<BlurDirection srcDirection, BlurDirection dstDirection>
index c8deea4bb9cf5ffe91b58ed470968aa13ce13a73..db104bacf4fd1ea4beaa021cbc68be60f08b5ba5 100644 (file)
@@ -5,9 +5,14 @@
  * found in the LICENSE file.
  */
 
+#ifndef SkBlurImage_opts_SSE2_DEFINED
+#define SkBlurImage_opts_SSE2_DEFINED
+
 #include "SkBlurImage_opts.h"
 
 bool SkBoxBlurGetPlatformProcs_SSE2(SkBoxBlurProc* boxBlurX,
                                     SkBoxBlurProc* boxBlurY,
                                     SkBoxBlurProc* boxBlurXY,
                                     SkBoxBlurProc* boxBlurYX);
+
+#endif
index b58fced2c12718f8b84b42f948b8f85a6b914415..e782950956a54377637f733ed680b9fca50eae1f 100644 (file)
@@ -5,12 +5,10 @@
  * found in the LICENSE file.
  */
 
-
+#include <emmintrin.h>
 #include "SkColorPriv.h"
 #include "SkMorphology_opts_SSE2.h"
 
-#include <emmintrin.h>
-
 /* SSE2 version of dilateX, dilateY, erodeX, erodeY.
  * portable versions are in src/effects/SkMorphologyImageFilter.cpp.
  */
@@ -48,8 +46,12 @@ static void SkMorph_SSE2(const SkPMColor* src, SkPMColor* dst, int radius,
             lp += srcStrideY;
             up += srcStrideY;
         }
-        if (x >= radius) src += srcStrideX;
-        if (x + radius < width - 1) upperSrc += srcStrideX;
+        if (x >= radius) {
+            src += srcStrideX;
+        }
+        if (x + radius < width - 1) {
+            upperSrc += srcStrideX;
+        }
         dst += dstStrideX;
     }
 }
index bd103e6eba9a6261f6f59ff7e61450acfd169373..bf5aa03b092a9c39667aca2ea694cd42734092c7 100644 (file)
@@ -5,6 +5,11 @@
  * found in the LICENSE file.
  */
 
+#ifndef SkMorphology_opts_SSE2_DEFINED
+#define SkMorphology_opts_SSE2_DEFINED
+
+#include "SkColor.h"
+
 void SkDilateX_SSE2(const SkPMColor* src, SkPMColor* dst, int radius,
                     int width, int height, int srcStride, int dstStride);
 void SkDilateY_SSE2(const SkPMColor* src, SkPMColor* dst, int radius,
@@ -13,3 +18,5 @@ void SkErodeX_SSE2(const SkPMColor* src, SkPMColor* dst, int radius,
                    int width, int height, int srcStride, int dstStride);
 void SkErodeY_SSE2(const SkPMColor* src, SkPMColor* dst, int radius,
                    int width, int height, int srcStride, int dstStride);
+
+#endif
index e22044d39d36821726cb95ff3e1605e8976ec29c..a3c5aa5dfd7f1cf417abda23f10d662d80bf8045 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2009 The Android Open Source Project
  *
@@ -6,7 +5,6 @@
  * found in the LICENSE file.
  */
 
-
 #include <emmintrin.h>
 #include "SkUtils_opts_SSE2.h"
 
index ed24c1ffa40868813e98525bc7134118c72a5c0f..5f0bc329542a4de3fc8e46280e5b774def791487 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2009 The Android Open Source Project
  *
@@ -6,8 +5,12 @@
  * found in the LICENSE file.
  */
 
+#ifndef SkUtils_opts_SSE2_DEFINED
+#define SkUtils_opts_SSE2_DEFINED
 
 #include "SkTypes.h"
 
 void sk_memset16_SSE2(uint16_t *dst, uint16_t value, int count);
 void sk_memset32_SSE2(uint32_t *dst, uint32_t value, int count);
+
+#endif
index 4e4532b7bdc6475c1ea5ae9f7b170cf5e7cb407b..ec76ab3cfbb6533b4295f5a50b0867e5a700bfd5 100644 (file)
@@ -1,3 +1,10 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
 #include "SkColorPriv.h"
 #include "SkColor_opts_SSE2.h"
 #include "SkMathPriv.h"
index 9f17f8b3ebffbe6aabb71ee74e5926ea461ab883..bfc143937a82206a6c52a6b181afeb338d908e22 100644 (file)
@@ -1,3 +1,10 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
 #ifndef SkXfermode_opts_SSE2_DEFINED
 #define SkXfermode_opts_SSE2_DEFINED
 
diff --git a/src/opts/opts_check_SSE2.cpp b/src/opts/opts_check_SSE2.cpp
deleted file mode 100644 (file)
index 6c684c2..0000000
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * Copyright 2009 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkBitmapProcState_opts_SSE2.h"
-#include "SkBitmapProcState_opts_SSSE3.h"
-#include "SkBitmapFilter_opts_SSE2.h"
-#include "SkBlitMask.h"
-#include "SkBlitRow.h"
-#include "SkBlitRect_opts_SSE2.h"
-#include "SkBlitRow_opts_SSE2.h"
-#include "SkBlurImage_opts_SSE2.h"
-#include "SkUtils_opts_SSE2.h"
-#include "SkUtils.h"
-#include "SkMorphology_opts.h"
-#include "SkMorphology_opts_SSE2.h"
-#include "SkXfermode.h"
-#include "SkXfermode_proccoeff.h"
-
-#include "SkRTConf.h"
-
-#if defined(_MSC_VER) && defined(_WIN64)
-#include <intrin.h>
-#endif
-
-/* This file must *not* be compiled with -msse or -msse2, otherwise
-   gcc may generate sse2 even for scalar ops (and thus give an invalid
-   instruction on Pentium3 on the code below).  Only files named *_SSE2.cpp
-   in this directory should be compiled with -msse2. */
-
-
-#ifdef _MSC_VER
-static inline void getcpuid(int info_type, int info[4]) {
-#if defined(_WIN64)
-    __cpuid(info, info_type);
-#else
-    __asm {
-        mov    eax, [info_type]
-        cpuid
-        mov    edi, [info]
-        mov    [edi], eax
-        mov    [edi+4], ebx
-        mov    [edi+8], ecx
-        mov    [edi+12], edx
-    }
-#endif
-}
-#else
-#if defined(__x86_64__)
-static inline void getcpuid(int info_type, int info[4]) {
-    asm volatile (
-        "cpuid \n\t"
-        : "=a"(info[0]), "=b"(info[1]), "=c"(info[2]), "=d"(info[3])
-        : "a"(info_type)
-    );
-}
-#else
-static inline void getcpuid(int info_type, int info[4]) {
-    // We save and restore ebx, so this code can be compatible with -fPIC
-    asm volatile (
-        "pushl %%ebx      \n\t"
-        "cpuid            \n\t"
-        "movl %%ebx, %1   \n\t"
-        "popl %%ebx       \n\t"
-        : "=a"(info[0]), "=r"(info[1]), "=c"(info[2]), "=d"(info[3])
-        : "a"(info_type)
-    );
-}
-#endif
-#endif
-
-#if defined(__x86_64__) || defined(_WIN64) || SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
-/* All x86_64 machines have SSE2, or we know it's supported at compile time,  so don't even bother checking. */
-static inline bool hasSSE2() {
-    return true;
-}
-#else
-
-static inline bool hasSSE2() {
-    int cpu_info[4] = { 0 };
-    getcpuid(1, cpu_info);
-    return (cpu_info[3] & (1<<26)) != 0;
-}
-#endif
-
-#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSSE3
-/* If we know SSSE3 is supported at compile time, don't even bother checking. */
-static inline bool hasSSSE3() {
-    return true;
-}
-#elif defined(SK_BUILD_FOR_ANDROID_FRAMEWORK)
-/* For the Android framework we should always know at compile time if the device
- * we are building for supports SSSE3.  The one exception to this rule is on the
- * emulator where we are compiled without the -msse3 option (so we have no SSSE3
- * procs) but can be run on a host machine that supports SSSE3 instructions. So
- * for that particular case we disable our SSSE3 options.
- */
-static inline bool hasSSSE3() {
-    return false;
-}
-#else
-
-static inline bool hasSSSE3() {
-    int cpu_info[4] = { 0 };
-    getcpuid(1, cpu_info);
-    return (cpu_info[2] & 0x200) != 0;
-}
-#endif
-
-static bool cachedHasSSE2() {
-    static bool gHasSSE2 = hasSSE2();
-    return gHasSSE2;
-}
-
-static bool cachedHasSSSE3() {
-    static bool gHasSSSE3 = hasSSSE3();
-    return gHasSSSE3;
-}
-
-SK_CONF_DECLARE( bool, c_hqfilter_sse, "bitmap.filter.highQualitySSE", false, "Use SSE optimized version of high quality image filters");
-
-void SkBitmapProcState::platformConvolutionProcs(SkConvolutionProcs* procs) {
-    if (cachedHasSSE2()) {
-        procs->fExtraHorizontalReads = 3;
-        procs->fConvolveVertically = &convolveVertically_SSE2;
-        procs->fConvolve4RowsHorizontally = &convolve4RowsHorizontally_SSE2;
-        procs->fConvolveHorizontally = &convolveHorizontally_SSE2;
-        procs->fApplySIMDPadding = &applySIMDPadding_SSE2;
-    }
-}
-
-void SkBitmapProcState::platformProcs() {
-    /* Every optimization in the function requires at least SSE2 */
-    if (!cachedHasSSE2()) {
-        return;
-    }
-
-    /* Check fSampleProc32 */
-    if (fSampleProc32 == S32_opaque_D32_filter_DX) {
-        if (cachedHasSSSE3()) {
-            fSampleProc32 = S32_opaque_D32_filter_DX_SSSE3;
-        } else {
-            fSampleProc32 = S32_opaque_D32_filter_DX_SSE2;
-        }
-    } else if (fSampleProc32 == S32_opaque_D32_filter_DXDY) {
-        if (cachedHasSSSE3()) {
-            fSampleProc32 = S32_opaque_D32_filter_DXDY_SSSE3;
-        }
-    } else if (fSampleProc32 == S32_alpha_D32_filter_DX) {
-        if (cachedHasSSSE3()) {
-            fSampleProc32 = S32_alpha_D32_filter_DX_SSSE3;
-        } else {
-            fSampleProc32 = S32_alpha_D32_filter_DX_SSE2;
-        }
-    } else if (fSampleProc32 == S32_alpha_D32_filter_DXDY) {
-        if (cachedHasSSSE3()) {
-            fSampleProc32 = S32_alpha_D32_filter_DXDY_SSSE3;
-        }
-    }
-
-    /* Check fSampleProc16 */
-    if (fSampleProc16 == S32_D16_filter_DX) {
-        fSampleProc16 = S32_D16_filter_DX_SSE2;
-    }
-
-    /* Check fMatrixProc */
-    if (fMatrixProc == ClampX_ClampY_filter_scale) {
-        fMatrixProc = ClampX_ClampY_filter_scale_SSE2;
-    } else if (fMatrixProc == ClampX_ClampY_nofilter_scale) {
-        fMatrixProc = ClampX_ClampY_nofilter_scale_SSE2;
-    } else if (fMatrixProc == ClampX_ClampY_filter_affine) {
-        fMatrixProc = ClampX_ClampY_filter_affine_SSE2;
-    } else if (fMatrixProc == ClampX_ClampY_nofilter_affine) {
-        fMatrixProc = ClampX_ClampY_nofilter_affine_SSE2;
-    }
-
-    /* Check fShaderProc32 */
-    if (c_hqfilter_sse) {
-        if (fShaderProc32 == highQualityFilter32) {
-            fShaderProc32 = highQualityFilter_SSE2;
-        }
-    }
-}
-
-static SkBlitRow::Proc platform_16_procs[] = {
-    S32_D565_Opaque_SSE2,               // S32_D565_Opaque
-    NULL,                               // S32_D565_Blend
-    S32A_D565_Opaque_SSE2,              // S32A_D565_Opaque
-    NULL,                               // S32A_D565_Blend
-    S32_D565_Opaque_Dither_SSE2,        // S32_D565_Opaque_Dither
-    NULL,                               // S32_D565_Blend_Dither
-    S32A_D565_Opaque_Dither_SSE2,       // S32A_D565_Opaque_Dither
-    NULL,                               // S32A_D565_Blend_Dither
-};
-
-static SkBlitRow::Proc32 platform_32_procs[] = {
-    NULL,                               // S32_Opaque,
-    S32_Blend_BlitRow32_SSE2,           // S32_Blend,
-    S32A_Opaque_BlitRow32_SSE2,         // S32A_Opaque
-    S32A_Blend_BlitRow32_SSE2,          // S32A_Blend,
-};
-
-SkBlitRow::Proc SkBlitRow::PlatformProcs565(unsigned flags) {
-    if (cachedHasSSE2()) {
-        return platform_16_procs[flags];
-    } else {
-        return NULL;
-    }
-}
-
-SkBlitRow::ColorProc SkBlitRow::PlatformColorProc() {
-    if (cachedHasSSE2()) {
-        return Color32_SSE2;
-    } else {
-        return NULL;
-    }
-}
-
-SkBlitRow::Proc32 SkBlitRow::PlatformProcs32(unsigned flags) {
-    if (cachedHasSSE2()) {
-        return platform_32_procs[flags];
-    } else {
-        return NULL;
-    }
-}
-
-
-SkBlitMask::ColorProc SkBlitMask::PlatformColorProcs(SkBitmap::Config dstConfig,
-                                                     SkMask::Format maskFormat,
-                                                     SkColor color) {
-    if (SkMask::kA8_Format != maskFormat) {
-        return NULL;
-    }
-
-    ColorProc proc = NULL;
-    if (cachedHasSSE2()) {
-        switch (dstConfig) {
-            case SkBitmap::kARGB_8888_Config:
-                // The SSE2 version is not (yet) faster for black, so we check
-                // for that.
-                if (SK_ColorBLACK != color) {
-                    proc = SkARGB32_A8_BlitMask_SSE2;
-                }
-                break;
-            default:
-                break;
-        }
-    }
-    return proc;
-}
-
-SkBlitMask::BlitLCD16RowProc SkBlitMask::PlatformBlitRowProcs16(bool isOpaque) {
-    if (cachedHasSSE2()) {
-        if (isOpaque) {
-            return SkBlitLCD16OpaqueRow_SSE2;
-        } else {
-            return SkBlitLCD16Row_SSE2;
-        }
-    } else {
-        return NULL;
-    }
-
-}
-SkBlitMask::RowProc SkBlitMask::PlatformRowProcs(SkBitmap::Config dstConfig,
-                                                 SkMask::Format maskFormat,
-                                                 RowFlags flags) {
-    return NULL;
-}
-
-SkMemset16Proc SkMemset16GetPlatformProc() {
-    if (cachedHasSSE2()) {
-        return sk_memset16_SSE2;
-    } else {
-        return NULL;
-    }
-}
-
-SkMemset32Proc SkMemset32GetPlatformProc() {
-    if (cachedHasSSE2()) {
-        return sk_memset32_SSE2;
-    } else {
-        return NULL;
-    }
-}
-
-SkMorphologyImageFilter::Proc SkMorphologyGetPlatformProc(SkMorphologyProcType type) {
-    if (!cachedHasSSE2()) {
-        return NULL;
-    }
-    switch (type) {
-        case kDilateX_SkMorphologyProcType:
-            return SkDilateX_SSE2;
-        case kDilateY_SkMorphologyProcType:
-            return SkDilateY_SSE2;
-        case kErodeX_SkMorphologyProcType:
-            return SkErodeX_SSE2;
-        case kErodeY_SkMorphologyProcType:
-            return SkErodeY_SSE2;
-        default:
-            return NULL;
-    }
-}
-
-bool SkBoxBlurGetPlatformProcs(SkBoxBlurProc* boxBlurX,
-                               SkBoxBlurProc* boxBlurY,
-                               SkBoxBlurProc* boxBlurXY,
-                               SkBoxBlurProc* boxBlurYX) {
-#ifdef SK_DISABLE_BLUR_DIVISION_OPTIMIZATION
-    return false;
-#else
-    if (!cachedHasSSE2()) {
-        return false;
-    }
-    return SkBoxBlurGetPlatformProcs_SSE2(boxBlurX, boxBlurY, boxBlurXY, boxBlurYX);
-#endif
-}
-
-SkBlitRow::ColorRectProc PlatformColorRectProcFactory(); // suppress warning
-
-SkBlitRow::ColorRectProc PlatformColorRectProcFactory() {
-    if (cachedHasSSE2()) {
-        return ColorRect32_SSE2;
-    } else {
-        return NULL;
-    }
-}
-
-extern SkProcCoeffXfermode* SkPlatformXfermodeFactory_impl_SSE2(const ProcCoeff& rec,
-                                                                SkXfermode::Mode mode);
-
-SkProcCoeffXfermode* SkPlatformXfermodeFactory_impl(const ProcCoeff& rec,
-                                                    SkXfermode::Mode mode);
-
-SkProcCoeffXfermode* SkPlatformXfermodeFactory_impl(const ProcCoeff& rec,
-                                                    SkXfermode::Mode mode) {
-    return NULL;
-}
-
-SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec,
-                                               SkXfermode::Mode mode);
-
-SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec,
-                                               SkXfermode::Mode mode) {
-    if (cachedHasSSE2()) {
-        return SkPlatformXfermodeFactory_impl_SSE2(rec, mode);
-    } else {
-        return SkPlatformXfermodeFactory_impl(rec, mode);
-    }
-}
-
-SkXfermodeProc SkPlatformXfermodeProcFactory(SkXfermode::Mode mode);
-
-SkXfermodeProc SkPlatformXfermodeProcFactory(SkXfermode::Mode mode) {
-    return NULL;
-}
diff --git a/src/opts/opts_check_x86.cpp b/src/opts/opts_check_x86.cpp
new file mode 100644 (file)
index 0000000..0b0debb
--- /dev/null
@@ -0,0 +1,379 @@
+/*
+ * Copyright 2009 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkBitmapFilter_opts_SSE2.h"
+#include "SkBitmapProcState_opts_SSE2.h"
+#include "SkBitmapProcState_opts_SSSE3.h"
+#include "SkBlitMask.h"
+#include "SkBlitRect_opts_SSE2.h"
+#include "SkBlitRow.h"
+#include "SkBlitRow_opts_SSE2.h"
+#include "SkBlurImage_opts_SSE2.h"
+#include "SkMorphology_opts.h"
+#include "SkMorphology_opts_SSE2.h"
+#include "SkRTConf.h"
+#include "SkUtils.h"
+#include "SkUtils_opts_SSE2.h"
+#include "SkXfermode.h"
+#include "SkXfermode_proccoeff.h"
+
+#if defined(_MSC_VER) && defined(_WIN64)
+#include <intrin.h>
+#endif
+
+/* This file must *not* be compiled with -msse or -msse2, otherwise
+   gcc may generate sse2 even for scalar ops (and thus give an invalid
+   instruction on Pentium3 on the code below).  Only files named *_SSE2.cpp
+   in this directory should be compiled with -msse2. */
+
+
+/* Function to get the CPU SSE-level in runtime, for different compilers. */
+#ifdef _MSC_VER
+static inline void getcpuid(int info_type, int info[4]) {
+#if defined(_WIN64)
+    __cpuid(info, info_type);
+#else
+    __asm {
+        mov    eax, [info_type]
+        cpuid
+        mov    edi, [info]
+        mov    [edi], eax
+        mov    [edi+4], ebx
+        mov    [edi+8], ecx
+        mov    [edi+12], edx
+    }
+#endif
+}
+#else
+#if defined(__x86_64__)
+static inline void getcpuid(int info_type, int info[4]) {
+    asm volatile (
+        "cpuid \n\t"
+        : "=a"(info[0]), "=b"(info[1]), "=c"(info[2]), "=d"(info[3])
+        : "a"(info_type)
+    );
+}
+#else
+static inline void getcpuid(int info_type, int info[4]) {
+    // We save and restore ebx, so this code can be compatible with -fPIC
+    asm volatile (
+        "pushl %%ebx      \n\t"
+        "cpuid            \n\t"
+        "movl %%ebx, %1   \n\t"
+        "popl %%ebx       \n\t"
+        : "=a"(info[0]), "=r"(info[1]), "=c"(info[2]), "=d"(info[3])
+        : "a"(info_type)
+    );
+}
+#endif
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__x86_64__) || defined(_WIN64) || SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
+/* All x86_64 machines have SSE2, or we know it's supported at compile time,  so don't even bother checking. */
+static inline bool hasSSE2() {
+    return true;
+}
+#else
+
+static inline bool hasSSE2() {
+    int cpu_info[4] = { 0 };
+    getcpuid(1, cpu_info);
+    return (cpu_info[3] & (1<<26)) != 0;
+}
+#endif
+
+#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSSE3
+/* If we know SSSE3 is supported at compile time, don't even bother checking. */
+static inline bool hasSSSE3() {
+    return true;
+}
+#elif defined(SK_BUILD_FOR_ANDROID_FRAMEWORK)
+/* For the Android framework we should always know at compile time if the device
+ * we are building for supports SSSE3.  The one exception to this rule is on the
+ * emulator where we are compiled without the -msse3 option (so we have no SSSE3
+ * procs) but can be run on a host machine that supports SSSE3 instructions. So
+ * for that particular case we disable our SSSE3 options.
+ */
+static inline bool hasSSSE3() {
+    return false;
+}
+#else
+
+static inline bool hasSSSE3() {
+    int cpu_info[4] = { 0 };
+    getcpuid(1, cpu_info);
+    return (cpu_info[2] & 0x200) != 0;
+}
+#endif
+
+static bool cachedHasSSE2() {
+    static bool gHasSSE2 = hasSSE2();
+    return gHasSSE2;
+}
+
+static bool cachedHasSSSE3() {
+    static bool gHasSSSE3 = hasSSSE3();
+    return gHasSSSE3;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+SK_CONF_DECLARE( bool, c_hqfilter_sse, "bitmap.filter.highQualitySSE", false, "Use SSE optimized version of high quality image filters");
+
+void SkBitmapProcState::platformConvolutionProcs(SkConvolutionProcs* procs) {
+    if (cachedHasSSE2()) {
+        procs->fExtraHorizontalReads = 3;
+        procs->fConvolveVertically = &convolveVertically_SSE2;
+        procs->fConvolve4RowsHorizontally = &convolve4RowsHorizontally_SSE2;
+        procs->fConvolveHorizontally = &convolveHorizontally_SSE2;
+        procs->fApplySIMDPadding = &applySIMDPadding_SSE2;
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+void SkBitmapProcState::platformProcs() {
+    /* Every optimization in the function requires at least SSE2 */
+    if (!cachedHasSSE2()) {
+        return;
+    }
+
+    /* Check fSampleProc32 */
+    if (fSampleProc32 == S32_opaque_D32_filter_DX) {
+        if (cachedHasSSSE3()) {
+            fSampleProc32 = S32_opaque_D32_filter_DX_SSSE3;
+        } else {
+            fSampleProc32 = S32_opaque_D32_filter_DX_SSE2;
+        }
+    } else if (fSampleProc32 == S32_opaque_D32_filter_DXDY) {
+        if (cachedHasSSSE3()) {
+            fSampleProc32 = S32_opaque_D32_filter_DXDY_SSSE3;
+        }
+    } else if (fSampleProc32 == S32_alpha_D32_filter_DX) {
+        if (cachedHasSSSE3()) {
+            fSampleProc32 = S32_alpha_D32_filter_DX_SSSE3;
+        } else {
+            fSampleProc32 = S32_alpha_D32_filter_DX_SSE2;
+        }
+    } else if (fSampleProc32 == S32_alpha_D32_filter_DXDY) {
+        if (cachedHasSSSE3()) {
+            fSampleProc32 = S32_alpha_D32_filter_DXDY_SSSE3;
+        }
+    }
+
+    /* Check fSampleProc16 */
+    if (fSampleProc16 == S32_D16_filter_DX) {
+        fSampleProc16 = S32_D16_filter_DX_SSE2;
+    }
+
+    /* Check fMatrixProc */
+    if (fMatrixProc == ClampX_ClampY_filter_scale) {
+        fMatrixProc = ClampX_ClampY_filter_scale_SSE2;
+    } else if (fMatrixProc == ClampX_ClampY_nofilter_scale) {
+        fMatrixProc = ClampX_ClampY_nofilter_scale_SSE2;
+    } else if (fMatrixProc == ClampX_ClampY_filter_affine) {
+        fMatrixProc = ClampX_ClampY_filter_affine_SSE2;
+    } else if (fMatrixProc == ClampX_ClampY_nofilter_affine) {
+        fMatrixProc = ClampX_ClampY_nofilter_affine_SSE2;
+    }
+
+    /* Check fShaderProc32 */
+    if (c_hqfilter_sse) {
+        if (fShaderProc32 == highQualityFilter32) {
+            fShaderProc32 = highQualityFilter_SSE2;
+        }
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+static SkBlitRow::Proc platform_16_procs[] = {
+    S32_D565_Opaque_SSE2,               // S32_D565_Opaque
+    NULL,                               // S32_D565_Blend
+    S32A_D565_Opaque_SSE2,              // S32A_D565_Opaque
+    NULL,                               // S32A_D565_Blend
+    S32_D565_Opaque_Dither_SSE2,        // S32_D565_Opaque_Dither
+    NULL,                               // S32_D565_Blend_Dither
+    S32A_D565_Opaque_Dither_SSE2,       // S32A_D565_Opaque_Dither
+    NULL,                               // S32A_D565_Blend_Dither
+};
+
+SkBlitRow::Proc SkBlitRow::PlatformProcs565(unsigned flags) {
+    if (cachedHasSSE2()) {
+        return platform_16_procs[flags];
+    } else {
+        return NULL;
+    }
+}
+
+static SkBlitRow::Proc32 platform_32_procs[] = {
+    NULL,                               // S32_Opaque,
+    S32_Blend_BlitRow32_SSE2,           // S32_Blend,
+    S32A_Opaque_BlitRow32_SSE2,         // S32A_Opaque
+    S32A_Blend_BlitRow32_SSE2,          // S32A_Blend,
+};
+
+SkBlitRow::Proc32 SkBlitRow::PlatformProcs32(unsigned flags) {
+    if (cachedHasSSE2()) {
+        return platform_32_procs[flags];
+    } else {
+        return NULL;
+    }
+}
+
+SkBlitRow::ColorProc SkBlitRow::PlatformColorProc() {
+    if (cachedHasSSE2()) {
+        return Color32_SSE2;
+    } else {
+        return NULL;
+    }
+}
+
+SkBlitRow::ColorRectProc PlatformColorRectProcFactory(); // suppress warning
+
+SkBlitRow::ColorRectProc PlatformColorRectProcFactory() {
+/* Return NULL for now, since the optimized path in ColorRect32_SSE2 is disabled.
+    if (cachedHasSSE2()) {
+        return ColorRect32_SSE2;
+    } else {
+        return NULL;
+    }
+*/
+    return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+SkBlitMask::ColorProc SkBlitMask::PlatformColorProcs(SkBitmap::Config dstConfig,
+                                                     SkMask::Format maskFormat,
+                                                     SkColor color) {
+    if (SkMask::kA8_Format != maskFormat) {
+        return NULL;
+    }
+
+    ColorProc proc = NULL;
+    if (cachedHasSSE2()) {
+        switch (dstConfig) {
+            case SkBitmap::kARGB_8888_Config:
+                // The SSE2 version is not (yet) faster for black, so we check
+                // for that.
+                if (SK_ColorBLACK != color) {
+                    proc = SkARGB32_A8_BlitMask_SSE2;
+                }
+                break;
+            default:
+                break;
+        }
+    }
+    return proc;
+}
+
+SkBlitMask::BlitLCD16RowProc SkBlitMask::PlatformBlitRowProcs16(bool isOpaque) {
+    if (cachedHasSSE2()) {
+        if (isOpaque) {
+            return SkBlitLCD16OpaqueRow_SSE2;
+        } else {
+            return SkBlitLCD16Row_SSE2;
+        }
+    } else {
+        return NULL;
+    }
+
+}
+
+SkBlitMask::RowProc SkBlitMask::PlatformRowProcs(SkBitmap::Config dstConfig,
+                                                 SkMask::Format maskFormat,
+                                                 RowFlags flags) {
+    return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+SkMemset16Proc SkMemset16GetPlatformProc() {
+    if (cachedHasSSE2()) {
+        return sk_memset16_SSE2;
+    } else {
+        return NULL;
+    }
+}
+
+SkMemset32Proc SkMemset32GetPlatformProc() {
+    if (cachedHasSSE2()) {
+        return sk_memset32_SSE2;
+    } else {
+        return NULL;
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+SkMorphologyImageFilter::Proc SkMorphologyGetPlatformProc(SkMorphologyProcType type) {
+    if (!cachedHasSSE2()) {
+        return NULL;
+    }
+    switch (type) {
+        case kDilateX_SkMorphologyProcType:
+            return SkDilateX_SSE2;
+        case kDilateY_SkMorphologyProcType:
+            return SkDilateY_SSE2;
+        case kErodeX_SkMorphologyProcType:
+            return SkErodeX_SSE2;
+        case kErodeY_SkMorphologyProcType:
+            return SkErodeY_SSE2;
+        default:
+            return NULL;
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+bool SkBoxBlurGetPlatformProcs(SkBoxBlurProc* boxBlurX,
+                               SkBoxBlurProc* boxBlurY,
+                               SkBoxBlurProc* boxBlurXY,
+                               SkBoxBlurProc* boxBlurYX) {
+#ifdef SK_DISABLE_BLUR_DIVISION_OPTIMIZATION
+    return false;
+#else
+    if (!cachedHasSSE2()) {
+        return false;
+    }
+    return SkBoxBlurGetPlatformProcs_SSE2(boxBlurX, boxBlurY, boxBlurXY, boxBlurYX);
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+extern SkProcCoeffXfermode* SkPlatformXfermodeFactory_impl_SSE2(const ProcCoeff& rec,
+                                                                SkXfermode::Mode mode);
+
+SkProcCoeffXfermode* SkPlatformXfermodeFactory_impl(const ProcCoeff& rec,
+                                                    SkXfermode::Mode mode);
+
+SkProcCoeffXfermode* SkPlatformXfermodeFactory_impl(const ProcCoeff& rec,
+                                                    SkXfermode::Mode mode) {
+    return NULL;
+}
+
+SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec,
+                                               SkXfermode::Mode mode);
+
+SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec,
+                                               SkXfermode::Mode mode) {
+    if (cachedHasSSE2()) {
+        return SkPlatformXfermodeFactory_impl_SSE2(rec, mode);
+    } else {
+        return SkPlatformXfermodeFactory_impl(rec, mode);
+    }
+}
+
+SkXfermodeProc SkPlatformXfermodeProcFactory(SkXfermode::Mode mode);
+
+SkXfermodeProc SkPlatformXfermodeProcFactory(SkXfermode::Mode mode) {
+    return NULL;
+}
index 91f176c0e04b7d0641630f34592fe8f34ba28db8..18f67e7520b622f9be0c643f85574ff149d531e4 100644 (file)
@@ -4,3 +4,4 @@
 # https://codereview.chromium.org/249493003/
 # In the future, these changes will be automatically applied and committed as
 # part of the DEPS roll which contains the Skia change.
+https://codereview.chromium.org/265513005/