Home | History | Annotate | Download | only in core
      1 
      2 /*
      3  * Copyright 2011 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 #include "SkBitmapProcState.h"
      9 #include "SkColorPriv.h"
     10 #include "SkFilterProc.h"
     11 #include "SkPaint.h"
     12 #include "SkShader.h"   // for tilemodes
     13 #include "SkUtilsArm.h"
     14 
     15 #if !SK_ARM_NEON_IS_NONE
     16 // These are defined in src/opts/SkBitmapProcState_arm_neon.cpp
     17 extern const SkBitmapProcState::SampleProc16 gSkBitmapProcStateSample16_neon[];
     18 extern const SkBitmapProcState::SampleProc32 gSkBitmapProcStateSample32_neon[];
     19 extern void  S16_D16_filter_DX_neon(const SkBitmapProcState&, const uint32_t*, int, uint16_t*);
     20 extern void  Clamp_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint16_t*, int);
     21 extern void  Repeat_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint16_t*, int);
     22 extern void  SI8_opaque_D32_filter_DX_neon(const SkBitmapProcState&, const uint32_t*, int, SkPMColor*);
     23 extern void  SI8_opaque_D32_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint32_t*, int);
     24 extern void  Clamp_SI8_opaque_D32_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint32_t*, int);
     25 #endif
     26 
     27 #define   NAME_WRAP(x)  x
     28 #include "SkBitmapProcState_filter.h"
     29 #include "SkBitmapProcState_procs.h"
     30 
     31 ///////////////////////////////////////////////////////////////////////////////
     32 
     33 /**
     34  *  For the purposes of drawing bitmaps, if a matrix is "almost" translate
     35  *  go ahead and treat it as if it were, so that subsequent code can go fast.
     36  */
     37 static bool just_trans_clamp(const SkMatrix& matrix, const SkBitmap& bitmap) {
     38     SkMatrix::TypeMask mask = matrix.getType();
     39 
     40     if (mask & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) {
     41         return false;
     42     }
     43     if (mask & SkMatrix::kScale_Mask) {
     44         SkScalar sx = matrix[SkMatrix::kMScaleX];
     45         SkScalar sy = matrix[SkMatrix::kMScaleY];
     46         int w = bitmap.width();
     47         int h = bitmap.height();
     48         int sw = SkScalarRound(SkScalarMul(sx, SkIntToScalar(w)));
     49         int sh = SkScalarRound(SkScalarMul(sy, SkIntToScalar(h)));
     50         return sw == w && sh == h;
     51     }
     52     // if we got here, we're either kTranslate_Mask or identity
     53     return true;
     54 }
     55 
     56 static bool just_trans_general(const SkMatrix& matrix) {
     57     SkMatrix::TypeMask mask = matrix.getType();
     58 
     59     if (mask & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) {
     60         return false;
     61     }
     62     if (mask & SkMatrix::kScale_Mask) {
     63         const SkScalar tol = SK_Scalar1 / 32768;
     64 
     65         if (!SkScalarNearlyZero(matrix[SkMatrix::kMScaleX] - SK_Scalar1, tol)) {
     66             return false;
     67         }
     68         if (!SkScalarNearlyZero(matrix[SkMatrix::kMScaleY] - SK_Scalar1, tol)) {
     69             return false;
     70         }
     71     }
     72     // if we got here, treat us as either kTranslate_Mask or identity
     73     return true;
     74 }
     75 
     76 ///////////////////////////////////////////////////////////////////////////////
     77 
     78 static bool valid_for_filtering(unsigned dimension) {
     79     // for filtering, width and height must fit in 14bits, since we use steal
     80     // 2 bits from each to store our 4bit subpixel data
     81     return (dimension & ~0x3FFF) == 0;
     82 }
     83 
     84 bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
     85     if (fOrigBitmap.width() == 0 || fOrigBitmap.height() == 0) {
     86         return false;
     87     }
     88 
     89     const SkMatrix* m;
     90     bool trivial_matrix = (inv.getType() & ~SkMatrix::kTranslate_Mask) == 0;
     91     bool clamp_clamp = SkShader::kClamp_TileMode == fTileModeX &&
     92                        SkShader::kClamp_TileMode == fTileModeY;
     93 
     94     if (clamp_clamp || trivial_matrix) {
     95         m = &inv;
     96     } else {
     97         fUnitInvMatrix = inv;
     98         fUnitInvMatrix.postIDiv(fOrigBitmap.width(), fOrigBitmap.height());
     99         m = &fUnitInvMatrix;
    100     }
    101 
    102     fBitmap = &fOrigBitmap;
    103     if (fOrigBitmap.hasMipMap()) {
    104         int shift = fOrigBitmap.extractMipLevel(&fMipBitmap,
    105                                                 SkScalarToFixed(m->getScaleX()),
    106                                                 SkScalarToFixed(m->getSkewY()));
    107 
    108         if (shift > 0) {
    109             if (m != &fUnitInvMatrix) {
    110                 fUnitInvMatrix = *m;
    111                 m = &fUnitInvMatrix;
    112             }
    113 
    114             SkScalar scale = SkFixedToScalar(SK_Fixed1 >> shift);
    115             fUnitInvMatrix.postScale(scale, scale);
    116 
    117             // now point here instead of fOrigBitmap
    118             fBitmap = &fMipBitmap;
    119         }
    120     }
    121 
    122     // wack our matrix to exactly no-scale, if we're really close to begin with
    123     {
    124         bool fixupMatrix = clamp_clamp ?
    125         just_trans_clamp(*m, *fBitmap) : just_trans_general(*m);
    126         if (fixupMatrix) {
    127 #ifdef SK_IGNORE_TRANS_CLAMP_FIX
    128             if (m != &fUnitInvMatrix) {    // can't mutate the original
    129                 fUnitInvMatrix = inv;
    130                 m = &fUnitInvMatrix;
    131             }
    132             fUnitInvMatrix.set(SkMatrix::kMScaleX, SK_Scalar1);
    133             fUnitInvMatrix.set(SkMatrix::kMScaleY, SK_Scalar1);
    134 #else
    135             // If we can be treated just like translate, construct that inverse
    136             // such that we landed in the proper place. Given that m may have
    137             // some slight scale, we have to invert it to compute this new
    138             // matrix.
    139             SkMatrix forward;
    140             if (m->invert(&forward)) {
    141                 SkScalar tx = -SkScalarRoundToScalar(forward.getTranslateX());
    142                 SkScalar ty = -SkScalarRoundToScalar(forward.getTranslateY());
    143                 fUnitInvMatrix.setTranslate(tx, ty);
    144                 m = &fUnitInvMatrix;
    145                 // now the following code will sniff m, and decide to take the
    146                 // fast case (since m is purely translate).
    147             }
    148 #endif
    149         }
    150     }
    151 
    152     // Below this point, we should never refer to the inv parameter, since we
    153     // may be using a munged version for "our" inverse.
    154 
    155     fInvMatrix      = m;
    156     fInvProc        = m->getMapXYProc();
    157     fInvType        = m->getType();
    158     fInvSx          = SkScalarToFixed(m->getScaleX());
    159     fInvSxFractionalInt = SkScalarToFractionalInt(m->getScaleX());
    160     fInvKy          = SkScalarToFixed(m->getSkewY());
    161     fInvKyFractionalInt = SkScalarToFractionalInt(m->getSkewY());
    162 
    163     fAlphaScale = SkAlpha255To256(paint.getAlpha());
    164 
    165     // pick-up filtering from the paint, but only if the matrix is
    166     // more complex than identity/translate (i.e. no need to pay the cost
    167     // of filtering if we're not scaled etc.).
    168     // note: we explicitly check inv, since m might be scaled due to unitinv
    169     //       trickery, but we don't want to see that for this test
    170     fDoFilter = paint.isFilterBitmap() &&
    171                 (fInvType > SkMatrix::kTranslate_Mask &&
    172                  valid_for_filtering(fBitmap->width() | fBitmap->height()));
    173 
    174     fShaderProc32 = NULL;
    175     fShaderProc16 = NULL;
    176     fSampleProc32 = NULL;
    177     fSampleProc16 = NULL;
    178 
    179     fMatrixProc = this->chooseMatrixProc(trivial_matrix);
    180     if (NULL == fMatrixProc) {
    181         return false;
    182     }
    183 
    184     ///////////////////////////////////////////////////////////////////////
    185 
    186     int index = 0;
    187     if (fAlphaScale < 256) {  // note: this distinction is not used for D16
    188         index |= 1;
    189     }
    190     if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
    191         index |= 2;
    192     }
    193     if (fDoFilter) {
    194         index |= 4;
    195     }
    196     // bits 3,4,5 encoding the source bitmap format
    197     switch (fBitmap->config()) {
    198         case SkBitmap::kARGB_8888_Config:
    199             index |= 0;
    200             break;
    201         case SkBitmap::kRGB_565_Config:
    202             index |= 8;
    203             break;
    204         case SkBitmap::kIndex8_Config:
    205             index |= 16;
    206             break;
    207         case SkBitmap::kARGB_4444_Config:
    208             index |= 24;
    209             break;
    210         case SkBitmap::kA8_Config:
    211             index |= 32;
    212             fPaintPMColor = SkPreMultiplyColor(paint.getColor());
    213             break;
    214         default:
    215             return false;
    216     }
    217 
    218 #if !SK_ARM_NEON_IS_ALWAYS
    219     static const SampleProc32 gSkBitmapProcStateSample32[] = {
    220         S32_opaque_D32_nofilter_DXDY,
    221         S32_alpha_D32_nofilter_DXDY,
    222         S32_opaque_D32_nofilter_DX,
    223         S32_alpha_D32_nofilter_DX,
    224         S32_opaque_D32_filter_DXDY,
    225         S32_alpha_D32_filter_DXDY,
    226         S32_opaque_D32_filter_DX,
    227         S32_alpha_D32_filter_DX,
    228 
    229         S16_opaque_D32_nofilter_DXDY,
    230         S16_alpha_D32_nofilter_DXDY,
    231         S16_opaque_D32_nofilter_DX,
    232         S16_alpha_D32_nofilter_DX,
    233         S16_opaque_D32_filter_DXDY,
    234         S16_alpha_D32_filter_DXDY,
    235         S16_opaque_D32_filter_DX,
    236         S16_alpha_D32_filter_DX,
    237 
    238         SI8_opaque_D32_nofilter_DXDY,
    239         SI8_alpha_D32_nofilter_DXDY,
    240         SI8_opaque_D32_nofilter_DX,
    241         SI8_alpha_D32_nofilter_DX,
    242         SI8_opaque_D32_filter_DXDY,
    243         SI8_alpha_D32_filter_DXDY,
    244         SI8_opaque_D32_filter_DX,
    245         SI8_alpha_D32_filter_DX,
    246 
    247         S4444_opaque_D32_nofilter_DXDY,
    248         S4444_alpha_D32_nofilter_DXDY,
    249         S4444_opaque_D32_nofilter_DX,
    250         S4444_alpha_D32_nofilter_DX,
    251         S4444_opaque_D32_filter_DXDY,
    252         S4444_alpha_D32_filter_DXDY,
    253         S4444_opaque_D32_filter_DX,
    254         S4444_alpha_D32_filter_DX,
    255 
    256         // A8 treats alpha/opaque the same (equally efficient)
    257         SA8_alpha_D32_nofilter_DXDY,
    258         SA8_alpha_D32_nofilter_DXDY,
    259         SA8_alpha_D32_nofilter_DX,
    260         SA8_alpha_D32_nofilter_DX,
    261         SA8_alpha_D32_filter_DXDY,
    262         SA8_alpha_D32_filter_DXDY,
    263         SA8_alpha_D32_filter_DX,
    264         SA8_alpha_D32_filter_DX
    265     };
    266 
    267     static const SampleProc16 gSkBitmapProcStateSample16[] = {
    268         S32_D16_nofilter_DXDY,
    269         S32_D16_nofilter_DX,
    270         S32_D16_filter_DXDY,
    271         S32_D16_filter_DX,
    272 
    273         S16_D16_nofilter_DXDY,
    274         S16_D16_nofilter_DX,
    275         S16_D16_filter_DXDY,
    276         S16_D16_filter_DX,
    277 
    278         SI8_D16_nofilter_DXDY,
    279         SI8_D16_nofilter_DX,
    280         SI8_D16_filter_DXDY,
    281         SI8_D16_filter_DX,
    282 
    283         // Don't support 4444 -> 565
    284         NULL, NULL, NULL, NULL,
    285         // Don't support A8 -> 565
    286         NULL, NULL, NULL, NULL
    287     };
    288 #endif
    289 
    290     fSampleProc32 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample32)[index];
    291     index >>= 1;    // shift away any opaque/alpha distinction
    292     fSampleProc16 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample16)[index];
    293 
    294     // our special-case shaderprocs
    295     if (SK_ARM_NEON_WRAP(S16_D16_filter_DX) == fSampleProc16) {
    296         if (clamp_clamp) {
    297             fShaderProc16 = SK_ARM_NEON_WRAP(Clamp_S16_D16_filter_DX_shaderproc);
    298         } else if (SkShader::kRepeat_TileMode == fTileModeX &&
    299                    SkShader::kRepeat_TileMode == fTileModeY) {
    300             fShaderProc16 = SK_ARM_NEON_WRAP(Repeat_S16_D16_filter_DX_shaderproc);
    301         }
    302     } else if (SK_ARM_NEON_WRAP(SI8_opaque_D32_filter_DX) == fSampleProc32 && clamp_clamp) {
    303         fShaderProc32 = SK_ARM_NEON_WRAP(Clamp_SI8_opaque_D32_filter_DX_shaderproc);
    304     }
    305 
    306     if (NULL == fShaderProc32) {
    307         fShaderProc32 = this->chooseShaderProc32();
    308     }
    309 
    310     // see if our platform has any accelerated overrides
    311     this->platformProcs();
    312     return true;
    313 }
    314 
    315 static void Clamp_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s,
    316                                                     int x, int y,
    317                                                     SkPMColor* SK_RESTRICT colors,
    318                                                     int count) {
    319     SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0);
    320     SkASSERT(s.fInvKy == 0);
    321     SkASSERT(count > 0 && colors != NULL);
    322     SkASSERT(!s.fDoFilter);
    323 
    324     const int maxX = s.fBitmap->width() - 1;
    325     const int maxY = s.fBitmap->height() - 1;
    326     int ix = s.fFilterOneX + x;
    327     int iy = SkClampMax(s.fFilterOneY + y, maxY);
    328 #ifdef SK_DEBUG
    329     {
    330         SkPoint pt;
    331         s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
    332                    SkIntToScalar(y) + SK_ScalarHalf, &pt);
    333         int iy2 = SkClampMax(SkScalarFloorToInt(pt.fY), maxY);
    334         int ix2 = SkScalarFloorToInt(pt.fX);
    335 
    336         SkASSERT(iy == iy2);
    337         SkASSERT(ix == ix2);
    338     }
    339 #endif
    340     const SkPMColor* row = s.fBitmap->getAddr32(0, iy);
    341 
    342     // clamp to the left
    343     if (ix < 0) {
    344         int n = SkMin32(-ix, count);
    345         sk_memset32(colors, row[0], n);
    346         count -= n;
    347         if (0 == count) {
    348             return;
    349         }
    350         colors += n;
    351         SkASSERT(-ix == n);
    352         ix = 0;
    353     }
    354     // copy the middle
    355     if (ix <= maxX) {
    356         int n = SkMin32(maxX - ix + 1, count);
    357         memcpy(colors, row + ix, n * sizeof(SkPMColor));
    358         count -= n;
    359         if (0 == count) {
    360             return;
    361         }
    362         colors += n;
    363     }
    364     SkASSERT(count > 0);
    365     // clamp to the right
    366     sk_memset32(colors, row[maxX], count);
    367 }
    368 
    369 static inline int sk_int_mod(int x, int n) {
    370     SkASSERT(n > 0);
    371     if ((unsigned)x >= (unsigned)n) {
    372         if (x < 0) {
    373             x = n + ~(~x % n);
    374         } else {
    375             x = x % n;
    376         }
    377     }
    378     return x;
    379 }
    380 
    381 static inline int sk_int_mirror(int x, int n) {
    382     x = sk_int_mod(x, 2 * n);
    383     if (x >= n) {
    384         x = n + ~(x - n);
    385     }
    386     return x;
    387 }
    388 
    389 static void Repeat_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s,
    390                                                      int x, int y,
    391                                                      SkPMColor* SK_RESTRICT colors,
    392                                                      int count) {
    393     SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0);
    394     SkASSERT(s.fInvKy == 0);
    395     SkASSERT(count > 0 && colors != NULL);
    396     SkASSERT(!s.fDoFilter);
    397 
    398     const int stopX = s.fBitmap->width();
    399     const int stopY = s.fBitmap->height();
    400     int ix = s.fFilterOneX + x;
    401     int iy = sk_int_mod(s.fFilterOneY + y, stopY);
    402 #ifdef SK_DEBUG
    403     {
    404         SkPoint pt;
    405         s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
    406                    SkIntToScalar(y) + SK_ScalarHalf, &pt);
    407         int iy2 = sk_int_mod(SkScalarFloorToInt(pt.fY), stopY);
    408         int ix2 = SkScalarFloorToInt(pt.fX);
    409 
    410         SkASSERT(iy == iy2);
    411         SkASSERT(ix == ix2);
    412     }
    413 #endif
    414     const SkPMColor* row = s.fBitmap->getAddr32(0, iy);
    415 
    416     ix = sk_int_mod(ix, stopX);
    417     for (;;) {
    418         int n = SkMin32(stopX - ix, count);
    419         memcpy(colors, row + ix, n * sizeof(SkPMColor));
    420         count -= n;
    421         if (0 == count) {
    422             return;
    423         }
    424         colors += n;
    425         ix = 0;
    426     }
    427 }
    428 
    429 static void S32_D32_constX_shaderproc(const SkBitmapProcState& s,
    430                                       int x, int y,
    431                                       SkPMColor* SK_RESTRICT colors,
    432                                       int count) {
    433     SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) == 0);
    434     SkASSERT(s.fInvKy == 0);
    435     SkASSERT(count > 0 && colors != NULL);
    436     SkASSERT(1 == s.fBitmap->width());
    437 
    438     int iY0, iY1, iSubY;
    439 
    440     if (s.fDoFilter) {
    441         SkBitmapProcState::MatrixProc mproc = s.getMatrixProc();
    442         uint32_t xy[2];
    443 
    444         mproc(s, xy, 1, x, y);
    445 
    446         iY0 = xy[0] >> 18;
    447         iY1 = xy[0] & 0x3FFF;
    448         iSubY = (xy[0] >> 14) & 0xF;
    449     } else {
    450         int yTemp;
    451 
    452         if (s.fInvType > SkMatrix::kTranslate_Mask) {
    453             SkPoint pt;
    454             s.fInvProc(*s.fInvMatrix,
    455                        SkIntToScalar(x) + SK_ScalarHalf,
    456                        SkIntToScalar(y) + SK_ScalarHalf,
    457                        &pt);
    458             // When the matrix has a scale component the setup code in
    459             // chooseProcs multiples the inverse matrix by the inverse of the
    460             // bitmap's width and height. Since this method is going to do
    461             // its own tiling and sampling we need to undo that here.
    462             if (SkShader::kClamp_TileMode != s.fTileModeX ||
    463                 SkShader::kClamp_TileMode != s.fTileModeY) {
    464                 yTemp = SkScalarFloorToInt(pt.fY * s.fBitmap->height());
    465             } else {
    466                 yTemp = SkScalarFloorToInt(pt.fY);
    467             }
    468         } else {
    469             yTemp = s.fFilterOneY + y;
    470         }
    471 
    472         const int stopY = s.fBitmap->height();
    473         switch (s.fTileModeY) {
    474             case SkShader::kClamp_TileMode:
    475                 iY0 = SkClampMax(yTemp, stopY-1);
    476                 break;
    477             case SkShader::kRepeat_TileMode:
    478                 iY0 = sk_int_mod(yTemp, stopY);
    479                 break;
    480             case SkShader::kMirror_TileMode:
    481             default:
    482                 iY0 = sk_int_mirror(yTemp, stopY);
    483                 break;
    484         }
    485 
    486 #ifdef SK_DEBUG
    487         {
    488             SkPoint pt;
    489             s.fInvProc(*s.fInvMatrix,
    490                        SkIntToScalar(x) + SK_ScalarHalf,
    491                        SkIntToScalar(y) + SK_ScalarHalf,
    492                        &pt);
    493             if (s.fInvType > SkMatrix::kTranslate_Mask &&
    494                 (SkShader::kClamp_TileMode != s.fTileModeX ||
    495                  SkShader::kClamp_TileMode != s.fTileModeY)) {
    496                 pt.fY *= s.fBitmap->height();
    497             }
    498             int iY2;
    499 
    500             switch (s.fTileModeY) {
    501             case SkShader::kClamp_TileMode:
    502                 iY2 = SkClampMax(SkScalarFloorToInt(pt.fY), stopY-1);
    503                 break;
    504             case SkShader::kRepeat_TileMode:
    505                 iY2 = sk_int_mod(SkScalarFloorToInt(pt.fY), stopY);
    506                 break;
    507             case SkShader::kMirror_TileMode:
    508             default:
    509                 iY2 = sk_int_mirror(SkScalarFloorToInt(pt.fY), stopY);
    510                 break;
    511             }
    512 
    513             SkASSERT(iY0 == iY2);
    514         }
    515 #endif
    516     }
    517 
    518     const SkPMColor* row0 = s.fBitmap->getAddr32(0, iY0);
    519     SkPMColor color;
    520 
    521     if (s.fDoFilter) {
    522         const SkPMColor* row1 = s.fBitmap->getAddr32(0, iY1);
    523 
    524         if (s.fAlphaScale < 256) {
    525             Filter_32_alpha(iSubY, *row0, *row1, &color, s.fAlphaScale);
    526         } else {
    527             Filter_32_opaque(iSubY, *row0, *row1, &color);
    528         }
    529     } else {
    530         if (s.fAlphaScale < 256) {
    531             color = SkAlphaMulQ(*row0, s.fAlphaScale);
    532         } else {
    533             color = *row0;
    534         }
    535     }
    536 
    537     sk_memset32(colors, color, count);
    538 }
    539 
    540 static void DoNothing_shaderproc(const SkBitmapProcState&, int x, int y,
    541                                  SkPMColor* SK_RESTRICT colors, int count) {
    542     // if we get called, the matrix is too tricky, so we just draw nothing
    543     sk_memset32(colors, 0, count);
    544 }
    545 
    546 bool SkBitmapProcState::setupForTranslate() {
    547     SkPoint pt;
    548     fInvProc(*fInvMatrix, SK_ScalarHalf, SK_ScalarHalf, &pt);
    549 
    550     /*
    551      *  if the translate is larger than our ints, we can get random results, or
    552      *  worse, we might get 0x80000000, which wreaks havoc on us, since we can't
    553      *  negate it.
    554      */
    555     const SkScalar too_big = SkIntToScalar(1 << 30);
    556     if (SkScalarAbs(pt.fX) > too_big || SkScalarAbs(pt.fY) > too_big) {
    557         return false;
    558     }
    559 
    560     // Since we know we're not filtered, we re-purpose these fields allow
    561     // us to go from device -> src coordinates w/ just an integer add,
    562     // rather than running through the inverse-matrix
    563     fFilterOneX = SkScalarFloorToInt(pt.fX);
    564     fFilterOneY = SkScalarFloorToInt(pt.fY);
    565     return true;
    566 }
    567 
    568 SkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() {
    569 
    570     if (SkBitmap::kARGB_8888_Config != fBitmap->config()) {
    571         return NULL;
    572     }
    573 
    574 #ifndef SK_IGNORE_1XN_BITMAP_OPT
    575     static const unsigned kMask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
    576 
    577     if (1 == fBitmap->width() && 0 == (fInvType & ~kMask)) {
    578         if (!fDoFilter && fInvType <= SkMatrix::kTranslate_Mask && !this->setupForTranslate()) {
    579             return DoNothing_shaderproc;
    580         }
    581         return S32_D32_constX_shaderproc;
    582     }
    583 #endif
    584 
    585     if (fAlphaScale < 256) {
    586         return NULL;
    587     }
    588     if (fInvType > SkMatrix::kTranslate_Mask) {
    589         return NULL;
    590     }
    591     if (fDoFilter) {
    592         return NULL;
    593     }
    594 
    595     SkShader::TileMode tx = (SkShader::TileMode)fTileModeX;
    596     SkShader::TileMode ty = (SkShader::TileMode)fTileModeY;
    597 
    598     if (SkShader::kClamp_TileMode == tx && SkShader::kClamp_TileMode == ty) {
    599         if (this->setupForTranslate()) {
    600             return Clamp_S32_D32_nofilter_trans_shaderproc;
    601         }
    602         return DoNothing_shaderproc;
    603     }
    604     if (SkShader::kRepeat_TileMode == tx && SkShader::kRepeat_TileMode == ty) {
    605         if (this->setupForTranslate()) {
    606             return Repeat_S32_D32_nofilter_trans_shaderproc;
    607         }
    608         return DoNothing_shaderproc;
    609     }
    610     return NULL;
    611 }
    612 
    613 ///////////////////////////////////////////////////////////////////////////////
    614 
    615 #ifdef SK_DEBUG
    616 
    617 static void check_scale_nofilter(uint32_t bitmapXY[], int count,
    618                                  unsigned mx, unsigned my) {
    619     unsigned y = *bitmapXY++;
    620     SkASSERT(y < my);
    621 
    622     const uint16_t* xptr = reinterpret_cast<const uint16_t*>(bitmapXY);
    623     for (int i = 0; i < count; ++i) {
    624         SkASSERT(xptr[i] < mx);
    625     }
    626 }
    627 
    628 static void check_scale_filter(uint32_t bitmapXY[], int count,
    629                                  unsigned mx, unsigned my) {
    630     uint32_t YY = *bitmapXY++;
    631     unsigned y0 = YY >> 18;
    632     unsigned y1 = YY & 0x3FFF;
    633     SkASSERT(y0 < my);
    634     SkASSERT(y1 < my);
    635 
    636     for (int i = 0; i < count; ++i) {
    637         uint32_t XX = bitmapXY[i];
    638         unsigned x0 = XX >> 18;
    639         unsigned x1 = XX & 0x3FFF;
    640         SkASSERT(x0 < mx);
    641         SkASSERT(x1 < mx);
    642     }
    643 }
    644 
    645 static void check_affine_nofilter(uint32_t bitmapXY[], int count,
    646                                  unsigned mx, unsigned my) {
    647     for (int i = 0; i < count; ++i) {
    648         uint32_t XY = bitmapXY[i];
    649         unsigned x = XY & 0xFFFF;
    650         unsigned y = XY >> 16;
    651         SkASSERT(x < mx);
    652         SkASSERT(y < my);
    653     }
    654 }
    655 
    656 static void check_affine_filter(uint32_t bitmapXY[], int count,
    657                                  unsigned mx, unsigned my) {
    658     for (int i = 0; i < count; ++i) {
    659         uint32_t YY = *bitmapXY++;
    660         unsigned y0 = YY >> 18;
    661         unsigned y1 = YY & 0x3FFF;
    662         SkASSERT(y0 < my);
    663         SkASSERT(y1 < my);
    664 
    665         uint32_t XX = *bitmapXY++;
    666         unsigned x0 = XX >> 18;
    667         unsigned x1 = XX & 0x3FFF;
    668         SkASSERT(x0 < mx);
    669         SkASSERT(x1 < mx);
    670     }
    671 }
    672 
    673 void SkBitmapProcState::DebugMatrixProc(const SkBitmapProcState& state,
    674                                         uint32_t bitmapXY[], int count,
    675                                         int x, int y) {
    676     SkASSERT(bitmapXY);
    677     SkASSERT(count > 0);
    678 
    679     state.fMatrixProc(state, bitmapXY, count, x, y);
    680 
    681     void (*proc)(uint32_t bitmapXY[], int count, unsigned mx, unsigned my);
    682 
    683     // There are four formats possible:
    684     //  scale -vs- affine
    685     //  filter -vs- nofilter
    686     if (state.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
    687         proc = state.fDoFilter ? check_scale_filter : check_scale_nofilter;
    688     } else {
    689         proc = state.fDoFilter ? check_affine_filter : check_affine_nofilter;
    690     }
    691     proc(bitmapXY, count, state.fBitmap->width(), state.fBitmap->height());
    692 }
    693 
    694 SkBitmapProcState::MatrixProc SkBitmapProcState::getMatrixProc() const {
    695     return DebugMatrixProc;
    696 }
    697 
    698 #endif
    699 
    700 ///////////////////////////////////////////////////////////////////////////////
    701 /*
    702     The storage requirements for the different matrix procs are as follows,
    703     where each X or Y is 2 bytes, and N is the number of pixels/elements:
    704 
    705     scale/translate     nofilter      Y(4bytes) + N * X
    706     affine/perspective  nofilter      N * (X Y)
    707     scale/translate     filter        Y Y + N * (X X)
    708     affine/perspective  filter        N * (Y Y X X)
    709  */
    710 int SkBitmapProcState::maxCountForBufferSize(size_t bufferSize) const {
    711     int32_t size = static_cast<int32_t>(bufferSize);
    712 
    713     size &= ~3; // only care about 4-byte aligned chunks
    714     if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
    715         size -= 4;   // the shared Y (or YY) coordinate
    716         if (size < 0) {
    717             size = 0;
    718         }
    719         size >>= 1;
    720     } else {
    721         size >>= 2;
    722     }
    723 
    724     if (fDoFilter) {
    725         size >>= 1;
    726     }
    727 
    728     return size;
    729 }
    730