LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/core - SkBitmapProcState_matrixProcs.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 93 224 41.5 %
Date: 2017-07-14 16:53:18 Functions: 8 26 30.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2008 Google Inc.
       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             : // The copyright below was added in 2009, but I see no record of moto contributions...?
       9             : 
      10             : /* NEON optimized code (C) COPYRIGHT 2009 Motorola
      11             :  *
      12             :  * Use of this source code is governed by a BSD-style license that can be
      13             :  * found in the LICENSE file.
      14             :  */
      15             : 
      16             : #include "SkBitmapProcState.h"
      17             : #include "SkPerspIter.h"
      18             : #include "SkShader.h"
      19             : #include "SkUtils.h"
      20             : #include "SkUtilsArm.h"
      21             : #include "SkBitmapProcState_utils.h"
      22             : 
      23             : /*  returns 0...(n-1) given any x (positive or negative).
      24             : 
      25             :     As an example, if n (which is always positive) is 5...
      26             : 
      27             :           x: -8 -7 -6 -5 -4 -3 -2 -1  0  1  2  3  4  5  6  7  8
      28             :     returns:  2  3  4  0  1  2  3  4  0  1  2  3  4  0  1  2  3
      29             :  */
      30         680 : static inline int sk_int_mod(int x, int n) {
      31         680 :     SkASSERT(n > 0);
      32         680 :     if ((unsigned)x >= (unsigned)n) {
      33         306 :         if (x < 0) {
      34           0 :             x = n + ~(~x % n);
      35             :         } else {
      36         306 :             x = x % n;
      37             :         }
      38             :     }
      39         680 :     return x;
      40             : }
      41             : 
      42             : void decal_nofilter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count);
      43             : void decal_filter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count);
      44             : 
      45             : #include "SkBitmapProcState_matrix_template.h"
      46             : 
      47             : ///////////////////////////////////////////////////////////////////////////////
      48             : 
      49             : // Compile neon code paths if needed
      50             : #if defined(SK_ARM_HAS_NEON)
      51             : 
      52             : // These are defined in src/opts/SkBitmapProcState_matrixProcs_neon.cpp
      53             : extern const SkBitmapProcState::MatrixProc ClampX_ClampY_Procs_neon[];
      54             : extern const SkBitmapProcState::MatrixProc RepeatX_RepeatY_Procs_neon[];
      55             : 
      56             : #endif // defined(SK_ARM_HAS_NEON)
      57             : 
      58             : // Compile non-neon code path if needed
      59             : #if !defined(SK_ARM_HAS_NEON)
      60             : #define MAKENAME(suffix)         ClampX_ClampY ## suffix
      61             : #define TILEX_PROCF(fx, max)     SkClampMax((fx) >> 16, max)
      62             : #define TILEY_PROCF(fy, max)     SkClampMax((fy) >> 16, max)
      63             : #define EXTRACT_LOW_BITS(v, max) (((v) >> 12) & 0xF)
      64             : #define CHECK_FOR_DECAL
      65             : #include "SkBitmapProcState_matrix.h"
      66             : 
      67             : struct ClampTileProcs {
      68           0 :     static unsigned X(const SkBitmapProcState&, SkFixed fx, int max) {
      69           0 :         return SkClampMax(fx >> 16, max);
      70             :     }
      71           0 :     static unsigned Y(const SkBitmapProcState&, SkFixed fy, int max) {
      72           0 :         return SkClampMax(fy >> 16, max);
      73             :     }
      74             : };
      75             : 
      76             : // Referenced in opts_check_x86.cpp
      77           0 : void ClampX_ClampY_nofilter_scale(const SkBitmapProcState& s, uint32_t xy[],
      78             :                                   int count, int x, int y) {
      79           0 :     return NoFilterProc_Scale<ClampTileProcs, true>(s, xy, count, x, y);
      80             : }
      81           0 : void ClampX_ClampY_nofilter_affine(const SkBitmapProcState& s, uint32_t xy[],
      82             :                                   int count, int x, int y) {
      83           0 :     return NoFilterProc_Affine<ClampTileProcs>(s, xy, count, x, y);
      84             : }
      85             : 
      86             : static SkBitmapProcState::MatrixProc ClampX_ClampY_Procs[] = {
      87             :     // only clamp lives in the right coord space to check for decal
      88             :     ClampX_ClampY_nofilter_scale,
      89             :     ClampX_ClampY_filter_scale,
      90             :     ClampX_ClampY_nofilter_affine,
      91             :     ClampX_ClampY_filter_affine,
      92             :     NoFilterProc_Persp<ClampTileProcs>,
      93             :     ClampX_ClampY_filter_persp
      94             : };
      95             : 
      96             : #define MAKENAME(suffix)         RepeatX_RepeatY ## suffix
      97             : #define TILEX_PROCF(fx, max)     SK_USHIFT16((unsigned)((fx) & 0xFFFF) * ((max) + 1))
      98             : #define TILEY_PROCF(fy, max)     SK_USHIFT16((unsigned)((fy) & 0xFFFF) * ((max) + 1))
      99             : #define EXTRACT_LOW_BITS(v, max) (((unsigned)((v) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
     100             : #include "SkBitmapProcState_matrix.h"
     101             : 
     102             : struct RepeatTileProcs {
     103           0 :     static unsigned X(const SkBitmapProcState&, SkFixed fx, int max) {
     104           0 :         SkASSERT(max < 65535);
     105           0 :         return SK_USHIFT16((unsigned)((fx) & 0xFFFF) * ((max) + 1));
     106             :     }
     107           0 :     static unsigned Y(const SkBitmapProcState&, SkFixed fy, int max) {
     108           0 :         SkASSERT(max < 65535);
     109           0 :         return SK_USHIFT16((unsigned)((fy) & 0xFFFF) * ((max) + 1));
     110             :     }
     111             : };
     112             : 
     113             : static SkBitmapProcState::MatrixProc RepeatX_RepeatY_Procs[] = {
     114             :     NoFilterProc_Scale<RepeatTileProcs, false>,
     115             :     RepeatX_RepeatY_filter_scale,
     116             :     NoFilterProc_Affine<RepeatTileProcs>,
     117             :     RepeatX_RepeatY_filter_affine,
     118             :     NoFilterProc_Persp<RepeatTileProcs>,
     119             :     RepeatX_RepeatY_filter_persp
     120             : };
     121             : #endif
     122             : 
     123             : #define MAKENAME(suffix)        GeneralXY ## suffix
     124             : #define PREAMBLE(state)         SkBitmapProcState::FixedTileProc tileProcX = (state).fTileProcX; (void) tileProcX; \
     125             :                                 SkBitmapProcState::FixedTileProc tileProcY = (state).fTileProcY; (void) tileProcY;
     126             : #define PREAMBLE_PARAM_X        , SkBitmapProcState::FixedTileProc tileProcX
     127             : #define PREAMBLE_PARAM_Y        , SkBitmapProcState::FixedTileProc tileProcY
     128             : #define PREAMBLE_ARG_X          , tileProcX
     129             : #define PREAMBLE_ARG_Y          , tileProcY
     130             : #define TILEX_PROCF(fx, max)    SK_USHIFT16(tileProcX(fx) * ((max) + 1))
     131             : #define TILEY_PROCF(fy, max)    SK_USHIFT16(tileProcY(fy) * ((max) + 1))
     132             : #define EXTRACT_LOW_BITS(v, max) (((v * (max + 1)) >> 12) & 0xF)
     133             : #include "SkBitmapProcState_matrix.h"
     134             : 
     135             : struct GeneralTileProcs {
     136           0 :     static unsigned X(const SkBitmapProcState& s, SkFixed fx, int max) {
     137           0 :         return SK_USHIFT16(s.fTileProcX(fx) * ((max) + 1));
     138             :     }
     139           0 :     static unsigned Y(const SkBitmapProcState& s, SkFixed fy, int max) {
     140           0 :         return SK_USHIFT16(s.fTileProcY(fy) * ((max) + 1));
     141             :     }
     142             : };
     143             : 
     144             : static SkBitmapProcState::MatrixProc GeneralXY_Procs[] = {
     145             :     NoFilterProc_Scale<GeneralTileProcs, false>,
     146             :     GeneralXY_filter_scale,
     147             :     NoFilterProc_Affine<GeneralTileProcs>,
     148             :     GeneralXY_filter_affine,
     149             :     NoFilterProc_Persp<GeneralTileProcs>,
     150             :     GeneralXY_filter_persp
     151             : };
     152             : 
     153             : ///////////////////////////////////////////////////////////////////////////////
     154             : 
     155           0 : static inline U16CPU fixed_clamp(SkFixed x) {
     156           0 :     if (x < 0) {
     157           0 :         x = 0;
     158             :     }
     159           0 :     if (x >> 16) {
     160           0 :         x = 0xFFFF;
     161             :     }
     162           0 :     return x;
     163             : }
     164             : 
     165           0 : static inline U16CPU fixed_repeat(SkFixed x) {
     166           0 :     return x & 0xFFFF;
     167             : }
     168             : 
     169           0 : static inline U16CPU fixed_mirror(SkFixed x) {
     170           0 :     SkFixed s = SkLeftShift(x, 15) >> 31;
     171             :     // s is FFFFFFFF if we're on an odd interval, or 0 if an even interval
     172           0 :     return (x ^ s) & 0xFFFF;
     173             : }
     174             : 
     175           0 : static SkBitmapProcState::FixedTileProc choose_tile_proc(unsigned m) {
     176           0 :     if (SkShader::kClamp_TileMode == m) {
     177           0 :         return fixed_clamp;
     178             :     }
     179           0 :     if (SkShader::kRepeat_TileMode == m) {
     180           0 :         return fixed_repeat;
     181             :     }
     182           0 :     SkASSERT(SkShader::kMirror_TileMode == m);
     183           0 :     return fixed_mirror;
     184             : }
     185             : 
     186        1104 : static inline U16CPU int_clamp(int x, int n) {
     187        1104 :     if (x >= n) {
     188           0 :         x = n - 1;
     189             :     }
     190        1104 :     if (x < 0) {
     191           0 :         x = 0;
     192             :     }
     193        1104 :     return x;
     194             : }
     195             : 
     196           0 : static inline U16CPU int_repeat(int x, int n) {
     197           0 :     return sk_int_mod(x, n);
     198             : }
     199             : 
     200           0 : static inline U16CPU int_mirror(int x, int n) {
     201           0 :     x = sk_int_mod(x, 2 * n);
     202           0 :     if (x >= n) {
     203           0 :         x = n + ~(x - n);
     204             :     }
     205           0 :     return x;
     206             : }
     207             : 
     208             : #if 0
     209             : static void test_int_tileprocs() {
     210             :     for (int i = -8; i <= 8; i++) {
     211             :         SkDebugf(" int_mirror(%2d, 3) = %d\n", i, int_mirror(i, 3));
     212             :     }
     213             : }
     214             : #endif
     215             : 
     216          99 : static SkBitmapProcState::IntTileProc choose_int_tile_proc(unsigned tm) {
     217          99 :     if (SkShader::kClamp_TileMode == tm)
     218          81 :         return int_clamp;
     219          18 :     if (SkShader::kRepeat_TileMode == tm)
     220          18 :         return int_repeat;
     221           0 :     SkASSERT(SkShader::kMirror_TileMode == tm);
     222           0 :     return int_mirror;
     223             : }
     224             : 
     225             : //////////////////////////////////////////////////////////////////////////////
     226             : 
     227           0 : void decal_nofilter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count) {
     228             :     int i;
     229             : 
     230           0 :     for (i = (count >> 2); i > 0; --i) {
     231           0 :         *dst++ = pack_two_shorts(fx >> 16, (fx + dx) >> 16);
     232           0 :         fx += dx+dx;
     233           0 :         *dst++ = pack_two_shorts(fx >> 16, (fx + dx) >> 16);
     234           0 :         fx += dx+dx;
     235             :     }
     236           0 :     count &= 3;
     237             : 
     238           0 :     uint16_t* xx = (uint16_t*)dst;
     239           0 :     for (i = count; i > 0; --i) {
     240           0 :         *xx++ = SkToU16(fx >> 16); fx += dx;
     241             :     }
     242           0 : }
     243             : 
     244           0 : void decal_filter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count) {
     245           0 :     if (count & 1) {
     246           0 :         SkASSERT((fx >> (16 + 14)) == 0);
     247           0 :         *dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
     248           0 :         fx += dx;
     249             :     }
     250           0 :     while ((count -= 2) >= 0) {
     251           0 :         SkASSERT((fx >> (16 + 14)) == 0);
     252           0 :         *dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
     253           0 :         fx += dx;
     254             : 
     255           0 :         *dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
     256           0 :         fx += dx;
     257             :     }
     258           0 : }
     259             : 
     260             : ///////////////////////////////////////////////////////////////////////////////
     261             : // stores the same as SCALE, but is cheaper to compute. Also since there is no
     262             : // scale, we don't need/have a FILTER version
     263             : 
     264        9222 : static void fill_sequential(uint16_t xptr[], int start, int count) {
     265             : #if 1
     266        9222 :     if (reinterpret_cast<intptr_t>(xptr) & 0x2) {
     267        1018 :         *xptr++ = start++;
     268        1018 :         count -= 1;
     269             :     }
     270        9222 :     if (count > 3) {
     271        8912 :         uint32_t* xxptr = reinterpret_cast<uint32_t*>(xptr);
     272        8912 :         uint32_t pattern0 = PACK_TWO_SHORTS(start + 0, start + 1);
     273        8912 :         uint32_t pattern1 = PACK_TWO_SHORTS(start + 2, start + 3);
     274        8912 :         start += count & ~3;
     275        8912 :         int qcount = count >> 2;
     276       28968 :         do {
     277       28968 :             *xxptr++ = pattern0;
     278       28968 :             pattern0 += 0x40004;
     279       28968 :             *xxptr++ = pattern1;
     280       28968 :             pattern1 += 0x40004;
     281             :         } while (--qcount != 0);
     282        8912 :         xptr = reinterpret_cast<uint16_t*>(xxptr);
     283        8912 :         count &= 3;
     284             :     }
     285       17746 :     while (--count >= 0) {
     286        4262 :         *xptr++ = start++;
     287             :     }
     288             : #else
     289             :     for (int i = 0; i < count; i++) {
     290             :         *xptr++ = start++;
     291             :     }
     292             : #endif
     293        9222 : }
     294             : 
     295        1104 : static int nofilter_trans_preamble(const SkBitmapProcState& s, uint32_t** xy,
     296             :                                    int x, int y) {
     297        1104 :     const SkBitmapProcStateAutoMapper mapper(s, x, y);
     298        1104 :     **xy = s.fIntTileProcY(mapper.intY(), s.fPixmap.height());
     299        1104 :     *xy += 1;   // bump the ptr
     300             :     // return our starting X position
     301        1104 :     return mapper.intX();
     302             : }
     303             : 
     304         424 : static void clampx_nofilter_trans(const SkBitmapProcState& s,
     305             :                                   uint32_t xy[], int count, int x, int y) {
     306         424 :     SkASSERT((s.fInvType & ~SkMatrix::kTranslate_Mask) == 0);
     307             : 
     308         424 :     int xpos = nofilter_trans_preamble(s, &xy, x, y);
     309         424 :     const int width = s.fPixmap.width();
     310         424 :     if (1 == width) {
     311             :         // all of the following X values must be 0
     312           0 :         memset(xy, 0, count * sizeof(uint16_t));
     313           0 :         return;
     314             :     }
     315             : 
     316         424 :     uint16_t* xptr = reinterpret_cast<uint16_t*>(xy);
     317             :     int n;
     318             : 
     319             :     // fill before 0 as needed
     320         424 :     if (xpos < 0) {
     321           0 :         n = -xpos;
     322           0 :         if (n > count) {
     323           0 :             n = count;
     324             :         }
     325           0 :         memset(xptr, 0, n * sizeof(uint16_t));
     326           0 :         count -= n;
     327           0 :         if (0 == count) {
     328           0 :             return;
     329             :         }
     330           0 :         xptr += n;
     331           0 :         xpos = 0;
     332             :     }
     333             : 
     334             :     // fill in 0..width-1 if needed
     335         424 :     if (xpos < width) {
     336         424 :         n = width - xpos;
     337         424 :         if (n > count) {
     338          32 :             n = count;
     339             :         }
     340         424 :         fill_sequential(xptr, xpos, n);
     341         424 :         count -= n;
     342         424 :         if (0 == count) {
     343         424 :             return;
     344             :         }
     345           0 :         xptr += n;
     346             :     }
     347             : 
     348             :     // fill the remaining with the max value
     349           0 :     sk_memset16(xptr, width - 1, count);
     350             : }
     351             : 
     352         680 : static void repeatx_nofilter_trans(const SkBitmapProcState& s,
     353             :                                    uint32_t xy[], int count, int x, int y) {
     354         680 :     SkASSERT((s.fInvType & ~SkMatrix::kTranslate_Mask) == 0);
     355             : 
     356         680 :     int xpos = nofilter_trans_preamble(s, &xy, x, y);
     357         680 :     const int width = s.fPixmap.width();
     358         680 :     if (1 == width) {
     359             :         // all of the following X values must be 0
     360           0 :         memset(xy, 0, count * sizeof(uint16_t));
     361           0 :         return;
     362             :     }
     363             : 
     364         680 :     uint16_t* xptr = reinterpret_cast<uint16_t*>(xy);
     365         680 :     int start = sk_int_mod(xpos, width);
     366         680 :     int n = width - start;
     367         680 :     if (n > count) {
     368          30 :         n = count;
     369             :     }
     370         680 :     fill_sequential(xptr, start, n);
     371         680 :     xptr += n;
     372         680 :     count -= n;
     373             : 
     374       16052 :     while (count >= width) {
     375        7686 :         fill_sequential(xptr, 0, width);
     376        7686 :         xptr += width;
     377        7686 :         count -= width;
     378             :     }
     379             : 
     380         680 :     if (count > 0) {
     381         432 :         fill_sequential(xptr, 0, count);
     382             :     }
     383             : }
     384             : 
     385           0 : static void fill_backwards(uint16_t xptr[], int pos, int count) {
     386           0 :     for (int i = 0; i < count; i++) {
     387           0 :         SkASSERT(pos >= 0);
     388           0 :         xptr[i] = pos--;
     389             :     }
     390           0 : }
     391             : 
     392           0 : static void mirrorx_nofilter_trans(const SkBitmapProcState& s,
     393             :                                    uint32_t xy[], int count, int x, int y) {
     394           0 :     SkASSERT((s.fInvType & ~SkMatrix::kTranslate_Mask) == 0);
     395             : 
     396           0 :     int xpos = nofilter_trans_preamble(s, &xy, x, y);
     397           0 :     const int width = s.fPixmap.width();
     398           0 :     if (1 == width) {
     399             :         // all of the following X values must be 0
     400           0 :         memset(xy, 0, count * sizeof(uint16_t));
     401           0 :         return;
     402             :     }
     403             : 
     404           0 :     uint16_t* xptr = reinterpret_cast<uint16_t*>(xy);
     405             :     // need to know our start, and our initial phase (forward or backward)
     406             :     bool forward;
     407             :     int n;
     408           0 :     int start = sk_int_mod(xpos, 2 * width);
     409           0 :     if (start >= width) {
     410           0 :         start = width + ~(start - width);
     411           0 :         forward = false;
     412           0 :         n = start + 1;  // [start .. 0]
     413             :     } else {
     414           0 :         forward = true;
     415           0 :         n = width - start;  // [start .. width)
     416             :     }
     417           0 :     if (n > count) {
     418           0 :         n = count;
     419             :     }
     420           0 :     if (forward) {
     421           0 :         fill_sequential(xptr, start, n);
     422             :     } else {
     423           0 :         fill_backwards(xptr, start, n);
     424             :     }
     425           0 :     forward = !forward;
     426           0 :     xptr += n;
     427           0 :     count -= n;
     428             : 
     429           0 :     while (count >= width) {
     430           0 :         if (forward) {
     431           0 :             fill_sequential(xptr, 0, width);
     432             :         } else {
     433           0 :             fill_backwards(xptr, width - 1, width);
     434             :         }
     435           0 :         forward = !forward;
     436           0 :         xptr += width;
     437           0 :         count -= width;
     438             :     }
     439             : 
     440           0 :     if (count > 0) {
     441           0 :         if (forward) {
     442           0 :             fill_sequential(xptr, 0, count);
     443             :         } else {
     444           0 :             fill_backwards(xptr, width - 1, count);
     445             :         }
     446             :     }
     447             : }
     448             : 
     449             : ///////////////////////////////////////////////////////////////////////////////
     450             : 
     451         141 : SkBitmapProcState::MatrixProc SkBitmapProcState::chooseMatrixProc(bool trivial_matrix) {
     452             : //    test_int_tileprocs();
     453             :     // check for our special case when there is no scale/affine/perspective
     454         141 :     if (trivial_matrix && kNone_SkFilterQuality == fFilterQuality) {
     455          99 :         fIntTileProcY = choose_int_tile_proc(fTileModeY);
     456          99 :         switch (fTileModeX) {
     457             :             case SkShader::kClamp_TileMode:
     458          73 :                 return clampx_nofilter_trans;
     459             :             case SkShader::kRepeat_TileMode:
     460          26 :                 return repeatx_nofilter_trans;
     461             :             case SkShader::kMirror_TileMode:
     462           0 :                 return mirrorx_nofilter_trans;
     463             :         }
     464             :     }
     465             : 
     466          42 :     int index = 0;
     467          42 :     if (fFilterQuality != kNone_SkFilterQuality) {
     468          42 :         index = 1;
     469             :     }
     470          42 :     if (fInvType & SkMatrix::kPerspective_Mask) {
     471           0 :         index += 4;
     472          42 :     } else if (fInvType & SkMatrix::kAffine_Mask) {
     473           0 :         index += 2;
     474             :     }
     475             : 
     476          42 :     if (SkShader::kClamp_TileMode == fTileModeX && SkShader::kClamp_TileMode == fTileModeY) {
     477             :         // clamp gets special version of filterOne
     478          25 :         fFilterOneX = SK_Fixed1;
     479          25 :         fFilterOneY = SK_Fixed1;
     480          25 :         return SK_ARM_NEON_WRAP(ClampX_ClampY_Procs)[index];
     481             :     }
     482             : 
     483             :     // all remaining procs use this form for filterOne
     484          17 :     fFilterOneX = SK_Fixed1 / fPixmap.width();
     485          17 :     fFilterOneY = SK_Fixed1 / fPixmap.height();
     486             : 
     487          17 :     if (SkShader::kRepeat_TileMode == fTileModeX && SkShader::kRepeat_TileMode == fTileModeY) {
     488          17 :         return SK_ARM_NEON_WRAP(RepeatX_RepeatY_Procs)[index];
     489             :     }
     490             : 
     491           0 :     fTileProcX = choose_tile_proc(fTileModeX);
     492           0 :     fTileProcY = choose_tile_proc(fTileModeY);
     493           0 :     return GeneralXY_Procs[index];
     494             : }

Generated by: LCOV version 1.13