LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/opts - SkBitmapProcState_opts_SSE2.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 71 327 21.7 %
Date: 2017-07-14 16:53:18 Functions: 2 7 28.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2009 The Android Open Source Project
       3             :  *
       4             :  * Use of this source code is governed by a BSD-style license that can be
       5             :  * found in the LICENSE file.
       6             :  */
       7             : 
       8             : #include <emmintrin.h>
       9             : #include "SkBitmapProcState_opts_SSE2.h"
      10             : #include "SkBitmapProcState_utils.h"
      11             : #include "SkColorPriv.h"
      12             : #include "SkPaint.h"
      13             : #include "SkUtils.h"
      14             : 
      15           0 : void S32_opaque_D32_filter_DX_SSE2(const SkBitmapProcState& s,
      16             :                                    const uint32_t* xy,
      17             :                                    int count, uint32_t* colors) {
      18           0 :     SkASSERT(count > 0 && colors != nullptr);
      19           0 :     SkASSERT(s.fFilterQuality != kNone_SkFilterQuality);
      20           0 :     SkASSERT(kN32_SkColorType == s.fPixmap.colorType());
      21           0 :     SkASSERT(s.fAlphaScale == 256);
      22             : 
      23           0 :     const char* srcAddr = static_cast<const char*>(s.fPixmap.addr());
      24           0 :     size_t rb = s.fPixmap.rowBytes();
      25           0 :     uint32_t XY = *xy++;
      26           0 :     unsigned y0 = XY >> 14;
      27           0 :     const uint32_t* row0 = reinterpret_cast<const uint32_t*>(srcAddr + (y0 >> 4) * rb);
      28           0 :     const uint32_t* row1 = reinterpret_cast<const uint32_t*>(srcAddr + (XY & 0x3FFF) * rb);
      29           0 :     unsigned subY = y0 & 0xF;
      30             : 
      31             :     // ( 0,  0,  0,  0,  0,  0,  0, 16)
      32           0 :     __m128i sixteen = _mm_cvtsi32_si128(16);
      33             : 
      34             :     // ( 0,  0,  0,  0, 16, 16, 16, 16)
      35           0 :     sixteen = _mm_shufflelo_epi16(sixteen, 0);
      36             : 
      37             :     // ( 0,  0,  0,  0,  0,  0,  0,  y)
      38           0 :     __m128i allY = _mm_cvtsi32_si128(subY);
      39             : 
      40             :     // ( 0,  0,  0,  0,  y,  y,  y,  y)
      41           0 :     allY = _mm_shufflelo_epi16(allY, 0);
      42             : 
      43             :     // ( 0,  0,  0,  0, 16-y, 16-y, 16-y, 16-y)
      44           0 :     __m128i negY = _mm_sub_epi16(sixteen, allY);
      45             : 
      46             :     // (16-y, 16-y, 16-y, 16-y, y, y, y, y)
      47           0 :     allY = _mm_unpacklo_epi64(allY, negY);
      48             : 
      49             :     // (16, 16, 16, 16, 16, 16, 16, 16 )
      50           0 :     sixteen = _mm_shuffle_epi32(sixteen, 0);
      51             : 
      52             :     // ( 0,  0,  0,  0,  0,  0,  0,  0)
      53           0 :     __m128i zero = _mm_setzero_si128();
      54           0 :     do {
      55           0 :         uint32_t XX = *xy++;    // x0:14 | 4 | x1:14
      56           0 :         unsigned x0 = XX >> 18;
      57           0 :         unsigned x1 = XX & 0x3FFF;
      58             : 
      59             :         // (0, 0, 0, 0, 0, 0, 0, x)
      60           0 :         __m128i allX = _mm_cvtsi32_si128((XX >> 14) & 0x0F);
      61             : 
      62             :         // (0, 0, 0, 0, x, x, x, x)
      63           0 :         allX = _mm_shufflelo_epi16(allX, 0);
      64             : 
      65             :         // (x, x, x, x, x, x, x, x)
      66           0 :         allX = _mm_shuffle_epi32(allX, 0);
      67             : 
      68             :         // (16-x, 16-x, 16-x, 16-x, 16-x, 16-x, 16-x)
      69           0 :         __m128i negX = _mm_sub_epi16(sixteen, allX);
      70             : 
      71             :         // Load 4 samples (pixels).
      72           0 :         __m128i a00 = _mm_cvtsi32_si128(row0[x0]);
      73           0 :         __m128i a01 = _mm_cvtsi32_si128(row0[x1]);
      74           0 :         __m128i a10 = _mm_cvtsi32_si128(row1[x0]);
      75           0 :         __m128i a11 = _mm_cvtsi32_si128(row1[x1]);
      76             : 
      77             :         // (0, 0, a00, a10)
      78           0 :         __m128i a00a10 = _mm_unpacklo_epi32(a10, a00);
      79             : 
      80             :         // Expand to 16 bits per component.
      81           0 :         a00a10 = _mm_unpacklo_epi8(a00a10, zero);
      82             : 
      83             :         // ((a00 * (16-y)), (a10 * y)).
      84           0 :         a00a10 = _mm_mullo_epi16(a00a10, allY);
      85             : 
      86             :         // (a00 * (16-y) * (16-x), a10 * y * (16-x)).
      87           0 :         a00a10 = _mm_mullo_epi16(a00a10, negX);
      88             : 
      89             :         // (0, 0, a01, a10)
      90           0 :         __m128i a01a11 = _mm_unpacklo_epi32(a11, a01);
      91             : 
      92             :         // Expand to 16 bits per component.
      93           0 :         a01a11 = _mm_unpacklo_epi8(a01a11, zero);
      94             : 
      95             :         // (a01 * (16-y)), (a11 * y)
      96           0 :         a01a11 = _mm_mullo_epi16(a01a11, allY);
      97             : 
      98             :         // (a01 * (16-y) * x), (a11 * y * x)
      99           0 :         a01a11 = _mm_mullo_epi16(a01a11, allX);
     100             : 
     101             :         // (a00*w00 + a01*w01, a10*w10 + a11*w11)
     102           0 :         __m128i sum = _mm_add_epi16(a00a10, a01a11);
     103             : 
     104             :         // (DC, a00*w00 + a01*w01)
     105           0 :         __m128i shifted = _mm_shuffle_epi32(sum, 0xEE);
     106             : 
     107             :         // (DC, a00*w00 + a01*w01 + a10*w10 + a11*w11)
     108           0 :         sum = _mm_add_epi16(sum, shifted);
     109             : 
     110             :         // Divide each 16 bit component by 256.
     111           0 :         sum = _mm_srli_epi16(sum, 8);
     112             : 
     113             :         // Pack lower 4 16 bit values of sum into lower 4 bytes.
     114           0 :         sum = _mm_packus_epi16(sum, zero);
     115             : 
     116             :         // Extract low int and store.
     117           0 :         *colors++ = _mm_cvtsi128_si32(sum);
     118             :     } while (--count > 0);
     119           0 : }
     120             : 
     121           0 : void S32_alpha_D32_filter_DX_SSE2(const SkBitmapProcState& s,
     122             :                                   const uint32_t* xy,
     123             :                                   int count, uint32_t* colors) {
     124           0 :     SkASSERT(count > 0 && colors != nullptr);
     125           0 :     SkASSERT(s.fFilterQuality != kNone_SkFilterQuality);
     126           0 :     SkASSERT(kN32_SkColorType == s.fPixmap.colorType());
     127           0 :     SkASSERT(s.fAlphaScale < 256);
     128             : 
     129           0 :     const char* srcAddr = static_cast<const char*>(s.fPixmap.addr());
     130           0 :     size_t rb = s.fPixmap.rowBytes();
     131           0 :     uint32_t XY = *xy++;
     132           0 :     unsigned y0 = XY >> 14;
     133           0 :     const uint32_t* row0 = reinterpret_cast<const uint32_t*>(srcAddr + (y0 >> 4) * rb);
     134           0 :     const uint32_t* row1 = reinterpret_cast<const uint32_t*>(srcAddr + (XY & 0x3FFF) * rb);
     135           0 :     unsigned subY = y0 & 0xF;
     136             : 
     137             :     // ( 0,  0,  0,  0,  0,  0,  0, 16)
     138           0 :     __m128i sixteen = _mm_cvtsi32_si128(16);
     139             : 
     140             :     // ( 0,  0,  0,  0, 16, 16, 16, 16)
     141           0 :     sixteen = _mm_shufflelo_epi16(sixteen, 0);
     142             : 
     143             :     // ( 0,  0,  0,  0,  0,  0,  0,  y)
     144           0 :     __m128i allY = _mm_cvtsi32_si128(subY);
     145             : 
     146             :     // ( 0,  0,  0,  0,  y,  y,  y,  y)
     147           0 :     allY = _mm_shufflelo_epi16(allY, 0);
     148             : 
     149             :     // ( 0,  0,  0,  0, 16-y, 16-y, 16-y, 16-y)
     150           0 :     __m128i negY = _mm_sub_epi16(sixteen, allY);
     151             : 
     152             :     // (16-y, 16-y, 16-y, 16-y, y, y, y, y)
     153           0 :     allY = _mm_unpacklo_epi64(allY, negY);
     154             : 
     155             :     // (16, 16, 16, 16, 16, 16, 16, 16 )
     156           0 :     sixteen = _mm_shuffle_epi32(sixteen, 0);
     157             : 
     158             :     // ( 0,  0,  0,  0,  0,  0,  0,  0)
     159           0 :     __m128i zero = _mm_setzero_si128();
     160             : 
     161             :     // ( alpha, alpha, alpha, alpha, alpha, alpha, alpha, alpha )
     162           0 :     __m128i alpha = _mm_set1_epi16(s.fAlphaScale);
     163             : 
     164           0 :     do {
     165           0 :         uint32_t XX = *xy++;    // x0:14 | 4 | x1:14
     166           0 :         unsigned x0 = XX >> 18;
     167           0 :         unsigned x1 = XX & 0x3FFF;
     168             : 
     169             :         // (0, 0, 0, 0, 0, 0, 0, x)
     170           0 :         __m128i allX = _mm_cvtsi32_si128((XX >> 14) & 0x0F);
     171             : 
     172             :         // (0, 0, 0, 0, x, x, x, x)
     173           0 :         allX = _mm_shufflelo_epi16(allX, 0);
     174             : 
     175             :         // (x, x, x, x, x, x, x, x)
     176           0 :         allX = _mm_shuffle_epi32(allX, 0);
     177             : 
     178             :         // (16-x, 16-x, 16-x, 16-x, 16-x, 16-x, 16-x)
     179           0 :         __m128i negX = _mm_sub_epi16(sixteen, allX);
     180             : 
     181             :         // Load 4 samples (pixels).
     182           0 :         __m128i a00 = _mm_cvtsi32_si128(row0[x0]);
     183           0 :         __m128i a01 = _mm_cvtsi32_si128(row0[x1]);
     184           0 :         __m128i a10 = _mm_cvtsi32_si128(row1[x0]);
     185           0 :         __m128i a11 = _mm_cvtsi32_si128(row1[x1]);
     186             : 
     187             :         // (0, 0, a00, a10)
     188           0 :         __m128i a00a10 = _mm_unpacklo_epi32(a10, a00);
     189             : 
     190             :         // Expand to 16 bits per component.
     191           0 :         a00a10 = _mm_unpacklo_epi8(a00a10, zero);
     192             : 
     193             :         // ((a00 * (16-y)), (a10 * y)).
     194           0 :         a00a10 = _mm_mullo_epi16(a00a10, allY);
     195             : 
     196             :         // (a00 * (16-y) * (16-x), a10 * y * (16-x)).
     197           0 :         a00a10 = _mm_mullo_epi16(a00a10, negX);
     198             : 
     199             :         // (0, 0, a01, a10)
     200           0 :         __m128i a01a11 = _mm_unpacklo_epi32(a11, a01);
     201             : 
     202             :         // Expand to 16 bits per component.
     203           0 :         a01a11 = _mm_unpacklo_epi8(a01a11, zero);
     204             : 
     205             :         // (a01 * (16-y)), (a11 * y)
     206           0 :         a01a11 = _mm_mullo_epi16(a01a11, allY);
     207             : 
     208             :         // (a01 * (16-y) * x), (a11 * y * x)
     209           0 :         a01a11 = _mm_mullo_epi16(a01a11, allX);
     210             : 
     211             :         // (a00*w00 + a01*w01, a10*w10 + a11*w11)
     212           0 :         __m128i sum = _mm_add_epi16(a00a10, a01a11);
     213             : 
     214             :         // (DC, a00*w00 + a01*w01)
     215           0 :         __m128i shifted = _mm_shuffle_epi32(sum, 0xEE);
     216             : 
     217             :         // (DC, a00*w00 + a01*w01 + a10*w10 + a11*w11)
     218           0 :         sum = _mm_add_epi16(sum, shifted);
     219             : 
     220             :         // Divide each 16 bit component by 256.
     221           0 :         sum = _mm_srli_epi16(sum, 8);
     222             : 
     223             :         // Multiply by alpha.
     224           0 :         sum = _mm_mullo_epi16(sum, alpha);
     225             : 
     226             :         // Divide each 16 bit component by 256.
     227           0 :         sum = _mm_srli_epi16(sum, 8);
     228             : 
     229             :         // Pack lower 4 16 bit values of sum into lower 4 bytes.
     230           0 :         sum = _mm_packus_epi16(sum, zero);
     231             : 
     232             :         // Extract low int and store.
     233           0 :         *colors++ = _mm_cvtsi128_si32(sum);
     234             :     } while (--count > 0);
     235           0 : }
     236             : 
     237        2342 : static inline uint32_t ClampX_ClampY_pack_filter(SkFixed f, unsigned max,
     238             :                                                  SkFixed one) {
     239        2342 :     unsigned i = SkClampMax(f >> 16, max);
     240        2342 :     i = (i << 4) | ((f >> 12) & 0xF);
     241        2342 :     return (i << 14) | SkClampMax((f + one) >> 16, max);
     242             : }
     243             : 
     244             : /*  SSE version of ClampX_ClampY_filter_scale()
     245             :  *  portable version is in core/SkBitmapProcState_matrix.h
     246             :  */
     247         726 : void ClampX_ClampY_filter_scale_SSE2(const SkBitmapProcState& s, uint32_t xy[],
     248             :                                      int count, int x, int y) {
     249         726 :     SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
     250             :                              SkMatrix::kScale_Mask)) == 0);
     251         726 :     SkASSERT(s.fInvKy == 0);
     252             : 
     253         726 :     const unsigned maxX = s.fPixmap.width() - 1;
     254         726 :     const SkFixed one = s.fFilterOneX;
     255         726 :     const SkFixed dx = s.fInvSx;
     256             : 
     257         726 :     const SkBitmapProcStateAutoMapper mapper(s, x, y);
     258         726 :     const SkFixed fy = mapper.fixedY();
     259         726 :     const unsigned maxY = s.fPixmap.height() - 1;
     260             :     // compute our two Y values up front
     261         726 :     *xy++ = ClampX_ClampY_pack_filter(fy, maxY, s.fFilterOneY);
     262             :     // now initialize fx
     263         726 :     SkFixed fx = mapper.fixedX();
     264             : 
     265             :     // test if we don't need to apply the tile proc
     266         726 :     if (can_truncate_to_fixed_for_decal(fx, dx, count, maxX)) {
     267         246 :         if (count >= 4) {
     268             :             // SSE version of decal_filter_scale
     269        1281 :             while ((size_t(xy) & 0x0F) != 0) {
     270         549 :                 SkASSERT((fx >> (16 + 14)) == 0);
     271         549 :                 *xy++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
     272         549 :                 fx += dx;
     273         549 :                 count--;
     274             :             }
     275             : 
     276         183 :             __m128i wide_1    = _mm_set1_epi32(1);
     277         366 :             __m128i wide_dx4  = _mm_set1_epi32(dx * 4);
     278         183 :             __m128i wide_fx   = _mm_set_epi32(fx + dx * 3, fx + dx * 2,
     279         183 :                                               fx + dx, fx);
     280             : 
     281        1311 :             while (count >= 4) {
     282             :                 __m128i wide_out;
     283             : 
     284        1128 :                 wide_out = _mm_slli_epi32(_mm_srai_epi32(wide_fx, 12), 14);
     285        1128 :                 wide_out = _mm_or_si128(wide_out, _mm_add_epi32(
     286         564 :                                         _mm_srai_epi32(wide_fx, 16), wide_1));
     287             : 
     288             :                 _mm_store_si128(reinterpret_cast<__m128i*>(xy), wide_out);
     289             : 
     290         564 :                 xy += 4;
     291         564 :                 fx += dx * 4;
     292         564 :                 wide_fx  = _mm_add_epi32(wide_fx, wide_dx4);
     293         564 :                 count -= 4;
     294             :             } // while count >= 4
     295             :         } // if count >= 4
     296             : 
     297         786 :         while (count-- > 0) {
     298         270 :             SkASSERT((fx >> (16 + 14)) == 0);
     299         270 :             *xy++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
     300         270 :             fx += dx;
     301             :         }
     302             :     } else {
     303             :         // SSE2 only support 16bit interger max & min, so only process the case
     304             :         // maxX less than the max 16bit interger. Actually maxX is the bitmap's
     305             :         // height, there should be rare bitmap whose height will be greater
     306             :         // than max 16bit interger in the real world.
     307         480 :         if ((count >= 4) && (maxX <= 0xFFFF)) {
     308        2576 :             while (((size_t)xy & 0x0F) != 0) {
     309        1104 :                 *xy++ = ClampX_ClampY_pack_filter(fx, maxX, one);
     310        1104 :                 fx += dx;
     311        1104 :                 count--;
     312             :             }
     313             : 
     314         368 :             __m128i wide_fx   = _mm_set_epi32(fx + dx * 3, fx + dx * 2,
     315         368 :                                               fx + dx, fx);
     316         736 :             __m128i wide_dx4  = _mm_set1_epi32(dx * 4);
     317         368 :             __m128i wide_one  = _mm_set1_epi32(one);
     318         736 :             __m128i wide_maxX = _mm_set1_epi32(maxX);
     319         368 :             __m128i wide_mask = _mm_set1_epi32(0xF);
     320             : 
     321        2608 :              while (count >= 4) {
     322             :                 __m128i wide_i;
     323             :                 __m128i wide_lo;
     324             :                 __m128i wide_fx1;
     325             : 
     326             :                 // i = SkClampMax(f>>16,maxX)
     327        2240 :                 wide_i = _mm_max_epi16(_mm_srli_epi32(wide_fx, 16),
     328        1120 :                                        _mm_setzero_si128());
     329        1120 :                 wide_i = _mm_min_epi16(wide_i, wide_maxX);
     330             : 
     331             :                 // i<<4 | EXTRACT_LOW_BITS(fx)
     332        1120 :                 wide_lo = _mm_srli_epi32(wide_fx, 12);
     333        1120 :                 wide_lo = _mm_and_si128(wide_lo, wide_mask);
     334        1120 :                 wide_i  = _mm_slli_epi32(wide_i, 4);
     335        1120 :                 wide_i  = _mm_or_si128(wide_i, wide_lo);
     336             : 
     337             :                 // i<<14
     338        1120 :                 wide_i = _mm_slli_epi32(wide_i, 14);
     339             : 
     340             :                 // SkClampMax(((f+one))>>16,max)
     341        1120 :                 wide_fx1 = _mm_add_epi32(wide_fx, wide_one);
     342        2240 :                 wide_fx1 = _mm_max_epi16(_mm_srli_epi32(wide_fx1, 16),
     343        1120 :                                                         _mm_setzero_si128());
     344        1120 :                 wide_fx1 = _mm_min_epi16(wide_fx1, wide_maxX);
     345             : 
     346             :                 // final combination
     347        1120 :                 wide_i = _mm_or_si128(wide_i, wide_fx1);
     348             :                 _mm_store_si128(reinterpret_cast<__m128i*>(xy), wide_i);
     349             : 
     350        1120 :                 wide_fx = _mm_add_epi32(wide_fx, wide_dx4);
     351        1120 :                 fx += dx * 4;
     352        1120 :                 xy += 4;
     353        1120 :                 count -= 4;
     354             :             } // while count >= 4
     355             :         } // if count >= 4
     356             : 
     357        1504 :         while (count-- > 0) {
     358         512 :             *xy++ = ClampX_ClampY_pack_filter(fx, maxX, one);
     359         512 :             fx += dx;
     360             :         }
     361             :     }
     362         726 : }
     363             : 
     364             : /*  SSE version of ClampX_ClampY_nofilter_scale()
     365             :  *  portable version is in core/SkBitmapProcState_matrix.h
     366             :  */
     367           0 : void ClampX_ClampY_nofilter_scale_SSE2(const SkBitmapProcState& s,
     368             :                                     uint32_t xy[], int count, int x, int y) {
     369           0 :     SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
     370             :                              SkMatrix::kScale_Mask)) == 0);
     371             : 
     372             :     // we store y, x, x, x, x, x
     373           0 :     const unsigned maxX = s.fPixmap.width() - 1;
     374           0 :     const SkBitmapProcStateAutoMapper mapper(s, x, y);
     375           0 :     const unsigned maxY = s.fPixmap.height() - 1;
     376           0 :     *xy++ = SkClampMax(mapper.intY(), maxY);
     377           0 :     SkFixed fx = mapper.fixedX();
     378             : 
     379           0 :     if (0 == maxX) {
     380             :         // all of the following X values must be 0
     381           0 :         memset(xy, 0, count * sizeof(uint16_t));
     382           0 :         return;
     383             :     }
     384             : 
     385           0 :     const SkFixed dx = s.fInvSx;
     386             : 
     387             :     // test if we don't need to apply the tile proc
     388           0 :     if ((unsigned)(fx >> 16) <= maxX &&
     389           0 :         (unsigned)((fx + dx * (count - 1)) >> 16) <= maxX) {
     390             :         // SSE version of decal_nofilter_scale
     391           0 :         if (count >= 8) {
     392           0 :             while (((size_t)xy & 0x0F) != 0) {
     393           0 :                 *xy++ = pack_two_shorts(fx >> 16, (fx + dx) >> 16);
     394           0 :                 fx += 2 * dx;
     395           0 :                 count -= 2;
     396             :             }
     397             : 
     398           0 :             __m128i wide_dx4 = _mm_set1_epi32(dx * 4);
     399           0 :             __m128i wide_dx8 = _mm_add_epi32(wide_dx4, wide_dx4);
     400             : 
     401           0 :             __m128i wide_low = _mm_set_epi32(fx + dx * 3, fx + dx * 2,
     402           0 :                                              fx + dx, fx);
     403           0 :             __m128i wide_high = _mm_add_epi32(wide_low, wide_dx4);
     404             : 
     405           0 :             while (count >= 8) {
     406           0 :                 __m128i wide_out_low = _mm_srli_epi32(wide_low, 16);
     407           0 :                 __m128i wide_out_high = _mm_srli_epi32(wide_high, 16);
     408             : 
     409             :                 __m128i wide_result = _mm_packs_epi32(wide_out_low,
     410           0 :                                                       wide_out_high);
     411             :                 _mm_store_si128(reinterpret_cast<__m128i*>(xy), wide_result);
     412             : 
     413           0 :                 wide_low = _mm_add_epi32(wide_low, wide_dx8);
     414           0 :                 wide_high = _mm_add_epi32(wide_high, wide_dx8);
     415             : 
     416           0 :                 xy += 4;
     417           0 :                 fx += dx * 8;
     418           0 :                 count -= 8;
     419             :             }
     420             :         } // if count >= 8
     421             : 
     422           0 :         uint16_t* xx = reinterpret_cast<uint16_t*>(xy);
     423           0 :         while (count-- > 0) {
     424           0 :             *xx++ = SkToU16(fx >> 16);
     425           0 :             fx += dx;
     426           0 :         }
     427             :     } else {
     428             :         // SSE2 only support 16bit interger max & min, so only process the case
     429             :         // maxX less than the max 16bit interger. Actually maxX is the bitmap's
     430             :         // height, there should be rare bitmap whose height will be greater
     431             :         // than max 16bit interger in the real world.
     432           0 :         if ((count >= 8) && (maxX <= 0xFFFF)) {
     433           0 :             while (((size_t)xy & 0x0F) != 0) {
     434           0 :                 *xy++ = pack_two_shorts(SkClampMax((fx + dx) >> 16, maxX),
     435           0 :                                         SkClampMax(fx >> 16, maxX));
     436           0 :                 fx += 2 * dx;
     437           0 :                 count -= 2;
     438             :             }
     439             : 
     440           0 :             __m128i wide_dx4 = _mm_set1_epi32(dx * 4);
     441           0 :             __m128i wide_dx8 = _mm_add_epi32(wide_dx4, wide_dx4);
     442             : 
     443           0 :             __m128i wide_low = _mm_set_epi32(fx + dx * 3, fx + dx * 2,
     444           0 :                                              fx + dx, fx);
     445           0 :             __m128i wide_high = _mm_add_epi32(wide_low, wide_dx4);
     446           0 :             __m128i wide_maxX = _mm_set1_epi32(maxX);
     447             : 
     448           0 :             while (count >= 8) {
     449           0 :                 __m128i wide_out_low = _mm_srli_epi32(wide_low, 16);
     450           0 :                 __m128i wide_out_high = _mm_srli_epi32(wide_high, 16);
     451             : 
     452           0 :                 wide_out_low  = _mm_max_epi16(wide_out_low,
     453           0 :                                               _mm_setzero_si128());
     454           0 :                 wide_out_low  = _mm_min_epi16(wide_out_low, wide_maxX);
     455           0 :                 wide_out_high = _mm_max_epi16(wide_out_high,
     456           0 :                                               _mm_setzero_si128());
     457           0 :                 wide_out_high = _mm_min_epi16(wide_out_high, wide_maxX);
     458             : 
     459             :                 __m128i wide_result = _mm_packs_epi32(wide_out_low,
     460           0 :                                                       wide_out_high);
     461             :                 _mm_store_si128(reinterpret_cast<__m128i*>(xy), wide_result);
     462             : 
     463           0 :                 wide_low  = _mm_add_epi32(wide_low, wide_dx8);
     464           0 :                 wide_high = _mm_add_epi32(wide_high, wide_dx8);
     465             : 
     466           0 :                 xy += 4;
     467           0 :                 fx += dx * 8;
     468           0 :                 count -= 8;
     469             :             }
     470             :         } // if count >= 8
     471             : 
     472           0 :         uint16_t* xx = reinterpret_cast<uint16_t*>(xy);
     473           0 :         while (count-- > 0) {
     474           0 :             *xx++ = SkClampMax(fx >> 16, maxX);
     475           0 :             fx += dx;
     476             :         }
     477             :     }
     478             : }
     479             : 
     480             : /*  SSE version of ClampX_ClampY_filter_affine()
     481             :  *  portable version is in core/SkBitmapProcState_matrix.h
     482             :  */
     483           0 : void ClampX_ClampY_filter_affine_SSE2(const SkBitmapProcState& s,
     484             :                                       uint32_t xy[], int count, int x, int y) {
     485           0 :     const SkBitmapProcStateAutoMapper mapper(s, x, y);
     486             : 
     487           0 :     SkFixed oneX = s.fFilterOneX;
     488           0 :     SkFixed oneY = s.fFilterOneY;
     489           0 :     SkFixed fx = mapper.fixedX();
     490           0 :     SkFixed fy = mapper.fixedY();
     491           0 :     SkFixed dx = s.fInvSx;
     492           0 :     SkFixed dy = s.fInvKy;
     493           0 :     unsigned maxX = s.fPixmap.width() - 1;
     494           0 :     unsigned maxY = s.fPixmap.height() - 1;
     495             : 
     496           0 :     if (count >= 2 && (maxX <= 0xFFFF)) {
     497           0 :         SkFixed dx2 = dx + dx;
     498           0 :         SkFixed dy2 = dy + dy;
     499             : 
     500           0 :         __m128i wide_f = _mm_set_epi32(fx + dx, fy + dy, fx, fy);
     501           0 :         __m128i wide_d2  = _mm_set_epi32(dx2, dy2, dx2, dy2);
     502           0 :         __m128i wide_one  = _mm_set_epi32(oneX, oneY, oneX, oneY);
     503           0 :         __m128i wide_max = _mm_set_epi32(maxX, maxY, maxX, maxY);
     504           0 :         __m128i wide_mask = _mm_set1_epi32(0xF);
     505             : 
     506           0 :         while (count >= 2) {
     507             :             // i = SkClampMax(f>>16,maxX)
     508           0 :             __m128i wide_i = _mm_max_epi16(_mm_srli_epi32(wide_f, 16),
     509           0 :                                            _mm_setzero_si128());
     510           0 :             wide_i = _mm_min_epi16(wide_i, wide_max);
     511             : 
     512             :             // i<<4 | EXTRACT_LOW_BITS(f)
     513           0 :             __m128i wide_lo = _mm_srli_epi32(wide_f, 12);
     514           0 :             wide_lo = _mm_and_si128(wide_lo, wide_mask);
     515           0 :             wide_i  = _mm_slli_epi32(wide_i, 4);
     516           0 :             wide_i  = _mm_or_si128(wide_i, wide_lo);
     517             : 
     518             :             // i<<14
     519           0 :             wide_i = _mm_slli_epi32(wide_i, 14);
     520             : 
     521             :             // SkClampMax(((f+one))>>16,max)
     522           0 :             __m128i wide_f1 = _mm_add_epi32(wide_f, wide_one);
     523           0 :             wide_f1 = _mm_max_epi16(_mm_srli_epi32(wide_f1, 16),
     524           0 :                                                    _mm_setzero_si128());
     525           0 :             wide_f1 = _mm_min_epi16(wide_f1, wide_max);
     526             : 
     527             :             // final combination
     528           0 :             wide_i = _mm_or_si128(wide_i, wide_f1);
     529             :             _mm_storeu_si128(reinterpret_cast<__m128i*>(xy), wide_i);
     530             : 
     531           0 :             wide_f = _mm_add_epi32(wide_f, wide_d2);
     532             : 
     533           0 :             fx += dx2;
     534           0 :             fy += dy2;
     535           0 :             xy += 4;
     536           0 :             count -= 2;
     537             :         } // while count >= 2
     538             :     } // if count >= 2
     539             : 
     540           0 :     while (count-- > 0) {
     541           0 :         *xy++ = ClampX_ClampY_pack_filter(fy, maxY, oneY);
     542           0 :         fy += dy;
     543           0 :         *xy++ = ClampX_ClampY_pack_filter(fx, maxX, oneX);
     544           0 :         fx += dx;
     545             :     }
     546           0 : }
     547             : 
     548             : /*  SSE version of ClampX_ClampY_nofilter_affine()
     549             :  *  portable version is in core/SkBitmapProcState_matrix.h
     550             :  */
     551           0 : void ClampX_ClampY_nofilter_affine_SSE2(const SkBitmapProcState& s,
     552             :                                       uint32_t xy[], int count, int x, int y) {
     553           0 :     SkASSERT(s.fInvType & SkMatrix::kAffine_Mask);
     554           0 :     SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
     555             :                              SkMatrix::kScale_Mask |
     556             :                              SkMatrix::kAffine_Mask)) == 0);
     557             : 
     558           0 :     const SkBitmapProcStateAutoMapper mapper(s, x, y);
     559             : 
     560           0 :     SkFixed fx = mapper.fixedX();
     561           0 :     SkFixed fy = mapper.fixedY();
     562           0 :     SkFixed dx = s.fInvSx;
     563           0 :     SkFixed dy = s.fInvKy;
     564           0 :     int maxX = s.fPixmap.width() - 1;
     565           0 :     int maxY = s.fPixmap.height() - 1;
     566             : 
     567           0 :     if (count >= 4 && (maxX <= 0xFFFF)) {
     568           0 :         while (((size_t)xy & 0x0F) != 0) {
     569           0 :             *xy++ = (SkClampMax(fy >> 16, maxY) << 16) |
     570           0 :                                   SkClampMax(fx >> 16, maxX);
     571           0 :             fx += dx;
     572           0 :             fy += dy;
     573           0 :             count--;
     574             :         }
     575             : 
     576           0 :         SkFixed dx4 = dx * 4;
     577           0 :         SkFixed dy4 = dy * 4;
     578             : 
     579           0 :         __m128i wide_fx   = _mm_set_epi32(fx + dx * 3, fx + dx * 2,
     580           0 :                                           fx + dx, fx);
     581           0 :         __m128i wide_fy   = _mm_set_epi32(fy + dy * 3, fy + dy * 2,
     582           0 :                                           fy + dy, fy);
     583           0 :         __m128i wide_dx4  = _mm_set1_epi32(dx4);
     584           0 :         __m128i wide_dy4  = _mm_set1_epi32(dy4);
     585             : 
     586           0 :         __m128i wide_maxX = _mm_set1_epi32(maxX);
     587           0 :         __m128i wide_maxY = _mm_set1_epi32(maxY);
     588             : 
     589           0 :         while (count >= 4) {
     590             :             // SkClampMax(fx>>16,maxX)
     591           0 :             __m128i wide_lo = _mm_max_epi16(_mm_srli_epi32(wide_fx, 16),
     592           0 :                                             _mm_setzero_si128());
     593           0 :             wide_lo = _mm_min_epi16(wide_lo, wide_maxX);
     594             : 
     595             :             // SkClampMax(fy>>16,maxY)
     596           0 :             __m128i wide_hi = _mm_max_epi16(_mm_srli_epi32(wide_fy, 16),
     597           0 :                                             _mm_setzero_si128());
     598           0 :             wide_hi = _mm_min_epi16(wide_hi, wide_maxY);
     599             : 
     600             :             // final combination
     601           0 :             __m128i wide_i = _mm_or_si128(_mm_slli_epi32(wide_hi, 16),
     602           0 :                                           wide_lo);
     603             :             _mm_store_si128(reinterpret_cast<__m128i*>(xy), wide_i);
     604             : 
     605           0 :             wide_fx = _mm_add_epi32(wide_fx, wide_dx4);
     606           0 :             wide_fy = _mm_add_epi32(wide_fy, wide_dy4);
     607             : 
     608           0 :             fx += dx4;
     609           0 :             fy += dy4;
     610           0 :             xy += 4;
     611           0 :             count -= 4;
     612             :         } // while count >= 4
     613             :     } // if count >= 4
     614             : 
     615           0 :     while (count-- > 0) {
     616           0 :         *xy++ = (SkClampMax(fy >> 16, maxY) << 16) |
     617           0 :                               SkClampMax(fx >> 16, maxX);
     618           0 :         fx += dx;
     619           0 :         fy += dy;
     620             :     }
     621           0 : }

Generated by: LCOV version 1.13