Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2011 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 #include "SkBitmapCache.h"
      9 #include "SkBitmapController.h"
     10 #include "SkBitmapProcState.h"
     11 #include "SkColorPriv.h"
     12 #include "SkFilterProc.h"
     13 #include "SkPaint.h"
     14 #include "SkShader.h"   // for tilemodes
     15 #include "SkUtilsArm.h"
     16 #include "SkBitmapScaler.h"
     17 #include "SkMipMap.h"
     18 #include "SkPixelRef.h"
     19 #include "SkImageEncoder.h"
     20 #include "SkResourceCache.h"
     21 
     22 #if !SK_ARM_NEON_IS_NONE
     23 // These are defined in src/opts/SkBitmapProcState_arm_neon.cpp
     24 extern const SkBitmapProcState::SampleProc32 gSkBitmapProcStateSample32_neon[];
     25 extern void  S16_D16_filter_DX_neon(const SkBitmapProcState&, const uint32_t*, int, uint16_t*);
     26 extern void  Clamp_S16_D16_filter_DX_shaderproc_neon(const void *, int, int, uint16_t*, int);
     27 extern void  Repeat_S16_D16_filter_DX_shaderproc_neon(const void *, int, int, uint16_t*, int);
     28 extern void  SI8_opaque_D32_filter_DX_neon(const SkBitmapProcState&, const uint32_t*, int, SkPMColor*);
     29 extern void  SI8_opaque_D32_filter_DX_shaderproc_neon(const void *, int, int, uint32_t*, int);
     30 extern void  Clamp_SI8_opaque_D32_filter_DX_shaderproc_neon(const void*, int, int, uint32_t*, int);
     31 #endif
     32 
     33 extern void Clamp_S32_opaque_D32_nofilter_DX_shaderproc(const void*, int, int, uint32_t*, int);
     34 
     35 #define   NAME_WRAP(x)  x
     36 #include "SkBitmapProcState_filter.h"
     37 #include "SkBitmapProcState_procs.h"
     38 
     39 SkBitmapProcState::SkBitmapProcState(const SkBitmapProvider& provider,
     40                                      SkShader::TileMode tmx, SkShader::TileMode tmy)
     41     : fProvider(provider)
     42     , fBMState(nullptr)
     43 {
     44     fTileModeX = tmx;
     45     fTileModeY = tmy;
     46 }
     47 
     48 SkBitmapProcState::SkBitmapProcState(const SkBitmap& bm,
     49                                      SkShader::TileMode tmx, SkShader::TileMode tmy)
     50     : fProvider(SkBitmapProvider(bm))
     51     , fBMState(nullptr)
     52 {
     53     fTileModeX = tmx;
     54     fTileModeY = tmy;
     55 }
     56 
     57 SkBitmapProcState::~SkBitmapProcState() {
     58     SkInPlaceDeleteCheck(fBMState, fBMStateStorage.get());
     59 }
     60 
     61 ///////////////////////////////////////////////////////////////////////////////
     62 
     63 // true iff the matrix contains, at most, scale and translate elements
     64 static bool matrix_only_scale_translate(const SkMatrix& m) {
     65     return m.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask);
     66 }
     67 
     68 /**
     69  *  For the purposes of drawing bitmaps, if a matrix is "almost" translate
     70  *  go ahead and treat it as if it were, so that subsequent code can go fast.
     71  */
     72 static bool just_trans_clamp(const SkMatrix& matrix, const SkPixmap& pixmap) {
     73     SkASSERT(matrix_only_scale_translate(matrix));
     74 
     75     if (matrix.getType() & SkMatrix::kScale_Mask) {
     76         SkRect dst;
     77         SkRect src = SkRect::Make(pixmap.bounds());
     78 
     79         // Can't call mapRect(), since that will fix up inverted rectangles,
     80         // e.g. when scale is negative, and we don't want to return true for
     81         // those.
     82         matrix.mapPoints(SkTCast<SkPoint*>(&dst),
     83                          SkTCast<const SkPoint*>(&src),
     84                          2);
     85 
     86         // Now round all 4 edges to device space, and then compare the device
     87         // width/height to the original. Note: we must map all 4 and subtract
     88         // rather than map the "width" and compare, since we care about the
     89         // phase (in pixel space) that any translate in the matrix might impart.
     90         SkIRect idst;
     91         dst.round(&idst);
     92         return idst.width() == pixmap.width() && idst.height() == pixmap.height();
     93     }
     94     // if we got here, we're either kTranslate_Mask or identity
     95     return true;
     96 }
     97 
     98 static bool just_trans_general(const SkMatrix& matrix) {
     99     SkASSERT(matrix_only_scale_translate(matrix));
    100 
    101     if (matrix.getType() & SkMatrix::kScale_Mask) {
    102         const SkScalar tol = SK_Scalar1 / 32768;
    103 
    104         if (!SkScalarNearlyZero(matrix[SkMatrix::kMScaleX] - SK_Scalar1, tol)) {
    105             return false;
    106         }
    107         if (!SkScalarNearlyZero(matrix[SkMatrix::kMScaleY] - SK_Scalar1, tol)) {
    108             return false;
    109         }
    110     }
    111     // if we got here, treat us as either kTranslate_Mask or identity
    112     return true;
    113 }
    114 
    115 static bool valid_for_filtering(unsigned dimension) {
    116     // for filtering, width and height must fit in 14bits, since we use steal
    117     // 2 bits from each to store our 4bit subpixel data
    118     return (dimension & ~0x3FFF) == 0;
    119 }
    120 
    121 /*
    122  *  Analyze filter-quality and matrix, and decide how to implement that.
    123  *
    124  *  In general, we cascade down the request level [ High ... None ]
    125  *  - for a given level, if we can fulfill it, fine, else
    126  *    - else we downgrade to the next lower level and try again.
    127  *  We can always fulfill requests for Low and None
    128  *  - sometimes we will "ignore" Low and give None, but this is likely a legacy perf hack
    129  *    and may be removed.
    130  */
    131 bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
    132     fPixmap.reset();
    133     fInvMatrix = inv;
    134     fFilterLevel = paint.getFilterQuality();
    135 
    136     const int origW = fProvider.info().width();
    137     const int origH = fProvider.info().height();
    138     bool allow_ignore_fractional_translate = true;  // historical default
    139     if (kMedium_SkFilterQuality == fFilterLevel) {
    140         allow_ignore_fractional_translate = false;
    141     }
    142 
    143     SkDefaultBitmapController controller;
    144     fBMState = controller.requestBitmap(fProvider, inv, paint.getFilterQuality(),
    145                                         fBMStateStorage.get(), fBMStateStorage.size());
    146     // Note : we allow the controller to return an empty (zero-dimension) result. Should we?
    147     if (nullptr == fBMState || fBMState->pixmap().info().isEmpty()) {
    148         return false;
    149     }
    150     fPixmap = fBMState->pixmap();
    151     fInvMatrix = fBMState->invMatrix();
    152     fFilterLevel = fBMState->quality();
    153     SkASSERT(fPixmap.addr());
    154 
    155     bool trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0;
    156     bool clampClamp = SkShader::kClamp_TileMode == fTileModeX &&
    157                       SkShader::kClamp_TileMode == fTileModeY;
    158 
    159     // Most of the scanline procs deal with "unit" texture coordinates, as this
    160     // makes it easy to perform tiling modes (repeat = (x & 0xFFFF)). To generate
    161     // those, we divide the matrix by its dimensions here.
    162     //
    163     // We don't do this if we're either trivial (can ignore the matrix) or clamping
    164     // in both X and Y since clamping to width,height is just as easy as to 0xFFFF.
    165 
    166     if (!(clampClamp || trivialMatrix)) {
    167         fInvMatrix.postIDiv(fPixmap.width(), fPixmap.height());
    168     }
    169 
    170     // Now that all possible changes to the matrix have taken place, check
    171     // to see if we're really close to a no-scale matrix.  If so, explicitly
    172     // set it to be so.  Subsequent code may inspect this matrix to choose
    173     // a faster path in this case.
    174 
    175     // This code will only execute if the matrix has some scale component;
    176     // if it's already pure translate then we won't do this inversion.
    177 
    178     if (matrix_only_scale_translate(fInvMatrix)) {
    179         SkMatrix forward;
    180         if (fInvMatrix.invert(&forward)) {
    181             if ((clampClamp && allow_ignore_fractional_translate)
    182                            ? just_trans_clamp(forward, fPixmap)
    183                            : just_trans_general(forward)) {
    184                 fInvMatrix.setTranslate(-forward.getTranslateX(), -forward.getTranslateY());
    185             }
    186         }
    187     }
    188 
    189     fInvProc        = fInvMatrix.getMapXYProc();
    190     fInvType        = fInvMatrix.getType();
    191     fInvSx          = SkScalarToFixed(fInvMatrix.getScaleX());
    192     fInvSxFractionalInt = SkScalarToFractionalInt(fInvMatrix.getScaleX());
    193     fInvKy          = SkScalarToFixed(fInvMatrix.getSkewY());
    194     fInvKyFractionalInt = SkScalarToFractionalInt(fInvMatrix.getSkewY());
    195 
    196     fAlphaScale = SkAlpha255To256(paint.getAlpha());
    197 
    198     fShaderProc32 = nullptr;
    199     fShaderProc16 = nullptr;
    200     fSampleProc32 = nullptr;
    201 
    202     // recompute the triviality of the matrix here because we may have
    203     // changed it!
    204 
    205     trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0;
    206 
    207     // If our target pixmap is the same as the original, then we revert back to legacy behavior
    208     // and allow the code to ignore fractional translate.
    209     //
    210     // The width/height check allows allow_ignore_fractional_translate to stay false if we
    211     // previously set it that way (e.g. we started in kMedium).
    212     //
    213     if (fPixmap.width() == origW && fPixmap.height() == origH) {
    214         allow_ignore_fractional_translate = true;
    215     }
    216 
    217     if (kLow_SkFilterQuality == fFilterLevel && allow_ignore_fractional_translate) {
    218         // Only try bilerp if the matrix is "interesting" and
    219         // the image has a suitable size.
    220 
    221         if (fInvType <= SkMatrix::kTranslate_Mask ||
    222             !valid_for_filtering(fPixmap.width() | fPixmap.height()))
    223         {
    224             fFilterLevel = kNone_SkFilterQuality;
    225         }
    226     }
    227 
    228     return this->chooseScanlineProcs(trivialMatrix, clampClamp, paint);
    229 }
    230 
    231 bool SkBitmapProcState::chooseScanlineProcs(bool trivialMatrix, bool clampClamp,
    232                                             const SkPaint& paint) {
    233     fMatrixProc = this->chooseMatrixProc(trivialMatrix);
    234     // TODO(dominikg): SkASSERT(fMatrixProc) instead? chooseMatrixProc never returns nullptr.
    235     if (nullptr == fMatrixProc) {
    236         return false;
    237     }
    238 
    239     ///////////////////////////////////////////////////////////////////////
    240 
    241     const SkAlphaType at = fPixmap.alphaType();
    242 
    243     // No need to do this if we're doing HQ sampling; if filter quality is
    244     // still set to HQ by the time we get here, then we must have installed
    245     // the shader procs above and can skip all this.
    246 
    247     if (fFilterLevel < kHigh_SkFilterQuality) {
    248 
    249         int index = 0;
    250         if (fAlphaScale < 256) {  // note: this distinction is not used for D16
    251             index |= 1;
    252         }
    253         if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
    254             index |= 2;
    255         }
    256         if (fFilterLevel > kNone_SkFilterQuality) {
    257             index |= 4;
    258         }
    259         // bits 3,4,5 encoding the source bitmap format
    260         switch (fPixmap.colorType()) {
    261             case kN32_SkColorType:
    262                 if (kPremul_SkAlphaType != at && kOpaque_SkAlphaType != at) {
    263                     return false;
    264                 }
    265                 index |= 0;
    266                 break;
    267             case kRGB_565_SkColorType:
    268                 index |= 8;
    269                 break;
    270             case kIndex_8_SkColorType:
    271                 if (kPremul_SkAlphaType != at && kOpaque_SkAlphaType != at) {
    272                     return false;
    273                 }
    274                 index |= 16;
    275                 break;
    276             case kARGB_4444_SkColorType:
    277                 if (kPremul_SkAlphaType != at && kOpaque_SkAlphaType != at) {
    278                     return false;
    279                 }
    280                 index |= 24;
    281                 break;
    282             case kAlpha_8_SkColorType:
    283                 index |= 32;
    284                 fPaintPMColor = SkPreMultiplyColor(paint.getColor());
    285                 break;
    286             case kGray_8_SkColorType:
    287                 index |= 40;
    288                 fPaintPMColor = SkPreMultiplyColor(paint.getColor());
    289                 break;
    290             default:
    291                 // TODO(dominikg): Should we ever get here? SkASSERT(false) instead?
    292                 return false;
    293         }
    294 
    295 #if !SK_ARM_NEON_IS_ALWAYS
    296         static const SampleProc32 gSkBitmapProcStateSample32[] = {
    297             S32_opaque_D32_nofilter_DXDY,
    298             S32_alpha_D32_nofilter_DXDY,
    299             S32_opaque_D32_nofilter_DX,
    300             S32_alpha_D32_nofilter_DX,
    301             S32_opaque_D32_filter_DXDY,
    302             S32_alpha_D32_filter_DXDY,
    303             S32_opaque_D32_filter_DX,
    304             S32_alpha_D32_filter_DX,
    305 
    306             S16_opaque_D32_nofilter_DXDY,
    307             S16_alpha_D32_nofilter_DXDY,
    308             S16_opaque_D32_nofilter_DX,
    309             S16_alpha_D32_nofilter_DX,
    310             S16_opaque_D32_filter_DXDY,
    311             S16_alpha_D32_filter_DXDY,
    312             S16_opaque_D32_filter_DX,
    313             S16_alpha_D32_filter_DX,
    314 
    315             SI8_opaque_D32_nofilter_DXDY,
    316             SI8_alpha_D32_nofilter_DXDY,
    317             SI8_opaque_D32_nofilter_DX,
    318             SI8_alpha_D32_nofilter_DX,
    319             SI8_opaque_D32_filter_DXDY,
    320             SI8_alpha_D32_filter_DXDY,
    321             SI8_opaque_D32_filter_DX,
    322             SI8_alpha_D32_filter_DX,
    323 
    324             S4444_opaque_D32_nofilter_DXDY,
    325             S4444_alpha_D32_nofilter_DXDY,
    326             S4444_opaque_D32_nofilter_DX,
    327             S4444_alpha_D32_nofilter_DX,
    328             S4444_opaque_D32_filter_DXDY,
    329             S4444_alpha_D32_filter_DXDY,
    330             S4444_opaque_D32_filter_DX,
    331             S4444_alpha_D32_filter_DX,
    332 
    333             // A8 treats alpha/opaque the same (equally efficient)
    334             SA8_alpha_D32_nofilter_DXDY,
    335             SA8_alpha_D32_nofilter_DXDY,
    336             SA8_alpha_D32_nofilter_DX,
    337             SA8_alpha_D32_nofilter_DX,
    338             SA8_alpha_D32_filter_DXDY,
    339             SA8_alpha_D32_filter_DXDY,
    340             SA8_alpha_D32_filter_DX,
    341             SA8_alpha_D32_filter_DX,
    342 
    343             // todo: possibly specialize on opaqueness
    344             SG8_alpha_D32_nofilter_DXDY,
    345             SG8_alpha_D32_nofilter_DXDY,
    346             SG8_alpha_D32_nofilter_DX,
    347             SG8_alpha_D32_nofilter_DX,
    348             SG8_alpha_D32_filter_DXDY,
    349             SG8_alpha_D32_filter_DXDY,
    350             SG8_alpha_D32_filter_DX,
    351             SG8_alpha_D32_filter_DX
    352         };
    353 #endif
    354 
    355         fSampleProc32 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample32)[index];
    356         index >>= 1;    // shift away any opaque/alpha distinction
    357 
    358         // our special-case shaderprocs
    359         if (SK_ARM_NEON_WRAP(SI8_opaque_D32_filter_DX) == fSampleProc32 && clampClamp) {
    360             fShaderProc32 = SK_ARM_NEON_WRAP(Clamp_SI8_opaque_D32_filter_DX_shaderproc);
    361         } else if (S32_opaque_D32_nofilter_DX == fSampleProc32 && clampClamp) {
    362             fShaderProc32 = Clamp_S32_opaque_D32_nofilter_DX_shaderproc;
    363         }
    364 
    365         if (nullptr == fShaderProc32) {
    366             fShaderProc32 = this->chooseShaderProc32();
    367         }
    368     }
    369 
    370     // see if our platform has any accelerated overrides
    371     this->platformProcs();
    372 
    373     return true;
    374 }
    375 
    376 static void Clamp_S32_D32_nofilter_trans_shaderproc(const void* sIn,
    377                                                     int x, int y,
    378                                                     SkPMColor* SK_RESTRICT colors,
    379                                                     int count) {
    380     const SkBitmapProcState& s = *static_cast<const SkBitmapProcState*>(sIn);
    381     SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0);
    382     SkASSERT(s.fInvKy == 0);
    383     SkASSERT(count > 0 && colors != nullptr);
    384     SkASSERT(kNone_SkFilterQuality == s.fFilterLevel);
    385 
    386     const int maxX = s.fPixmap.width() - 1;
    387     const int maxY = s.fPixmap.height() - 1;
    388     int ix = s.fFilterOneX + x;
    389     int iy = SkClampMax(s.fFilterOneY + y, maxY);
    390     const SkPMColor* row = s.fPixmap.addr32(0, iy);
    391 
    392     // clamp to the left
    393     if (ix < 0) {
    394         int n = SkMin32(-ix, count);
    395         sk_memset32(colors, row[0], n);
    396         count -= n;
    397         if (0 == count) {
    398             return;
    399         }
    400         colors += n;
    401         SkASSERT(-ix == n);
    402         ix = 0;
    403     }
    404     // copy the middle
    405     if (ix <= maxX) {
    406         int n = SkMin32(maxX - ix + 1, count);
    407         memcpy(colors, row + ix, n * sizeof(SkPMColor));
    408         count -= n;
    409         if (0 == count) {
    410             return;
    411         }
    412         colors += n;
    413     }
    414     SkASSERT(count > 0);
    415     // clamp to the right
    416     sk_memset32(colors, row[maxX], count);
    417 }
    418 
    419 static inline int sk_int_mod(int x, int n) {
    420     SkASSERT(n > 0);
    421     if ((unsigned)x >= (unsigned)n) {
    422         if (x < 0) {
    423             x = n + ~(~x % n);
    424         } else {
    425             x = x % n;
    426         }
    427     }
    428     return x;
    429 }
    430 
    431 static inline int sk_int_mirror(int x, int n) {
    432     x = sk_int_mod(x, 2 * n);
    433     if (x >= n) {
    434         x = n + ~(x - n);
    435     }
    436     return x;
    437 }
    438 
    439 static void Repeat_S32_D32_nofilter_trans_shaderproc(const void* sIn,
    440                                                      int x, int y,
    441                                                      SkPMColor* SK_RESTRICT colors,
    442                                                      int count) {
    443     const SkBitmapProcState& s = *static_cast<const SkBitmapProcState*>(sIn);
    444     SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0);
    445     SkASSERT(s.fInvKy == 0);
    446     SkASSERT(count > 0 && colors != nullptr);
    447     SkASSERT(kNone_SkFilterQuality == s.fFilterLevel);
    448 
    449     const int stopX = s.fPixmap.width();
    450     const int stopY = s.fPixmap.height();
    451     int ix = s.fFilterOneX + x;
    452     int iy = sk_int_mod(s.fFilterOneY + y, stopY);
    453     const SkPMColor* row = s.fPixmap.addr32(0, iy);
    454 
    455     ix = sk_int_mod(ix, stopX);
    456     for (;;) {
    457         int n = SkMin32(stopX - ix, count);
    458         memcpy(colors, row + ix, n * sizeof(SkPMColor));
    459         count -= n;
    460         if (0 == count) {
    461             return;
    462         }
    463         colors += n;
    464         ix = 0;
    465     }
    466 }
    467 
    468 static void S32_D32_constX_shaderproc(const void* sIn,
    469                                       int x, int y,
    470                                       SkPMColor* SK_RESTRICT colors,
    471                                       int count) {
    472     const SkBitmapProcState& s = *static_cast<const SkBitmapProcState*>(sIn);
    473     SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) == 0);
    474     SkASSERT(s.fInvKy == 0);
    475     SkASSERT(count > 0 && colors != nullptr);
    476     SkASSERT(1 == s.fPixmap.width());
    477 
    478     int iY0;
    479     int iY1   SK_INIT_TO_AVOID_WARNING;
    480     int iSubY SK_INIT_TO_AVOID_WARNING;
    481 
    482     if (kNone_SkFilterQuality != s.fFilterLevel) {
    483         SkBitmapProcState::MatrixProc mproc = s.getMatrixProc();
    484         uint32_t xy[2];
    485 
    486         mproc(s, xy, 1, x, y);
    487 
    488         iY0 = xy[0] >> 18;
    489         iY1 = xy[0] & 0x3FFF;
    490         iSubY = (xy[0] >> 14) & 0xF;
    491     } else {
    492         int yTemp;
    493 
    494         if (s.fInvType > SkMatrix::kTranslate_Mask) {
    495             const SkBitmapProcStateAutoMapper mapper(s, x, y);
    496 
    497             // When the matrix has a scale component the setup code in
    498             // chooseProcs multiples the inverse matrix by the inverse of the
    499             // bitmap's width and height. Since this method is going to do
    500             // its own tiling and sampling we need to undo that here.
    501             if (SkShader::kClamp_TileMode != s.fTileModeX ||
    502                 SkShader::kClamp_TileMode != s.fTileModeY) {
    503                 yTemp = SkFractionalIntToInt(mapper.fractionalIntY() * s.fPixmap.height());
    504             } else {
    505                 yTemp = mapper.intY();
    506             }
    507         } else {
    508             yTemp = s.fFilterOneY + y;
    509         }
    510 
    511         const int stopY = s.fPixmap.height();
    512         switch (s.fTileModeY) {
    513             case SkShader::kClamp_TileMode:
    514                 iY0 = SkClampMax(yTemp, stopY-1);
    515                 break;
    516             case SkShader::kRepeat_TileMode:
    517                 iY0 = sk_int_mod(yTemp, stopY);
    518                 break;
    519             case SkShader::kMirror_TileMode:
    520             default:
    521                 iY0 = sk_int_mirror(yTemp, stopY);
    522                 break;
    523         }
    524 
    525 #ifdef SK_DEBUG
    526         {
    527             const SkBitmapProcStateAutoMapper mapper(s, x, y);
    528             int iY2;
    529 
    530             if (s.fInvType > SkMatrix::kTranslate_Mask &&
    531                 (SkShader::kClamp_TileMode != s.fTileModeX ||
    532                  SkShader::kClamp_TileMode != s.fTileModeY)) {
    533                 iY2 = SkFractionalIntToInt(mapper.fractionalIntY() * s.fPixmap.height());
    534             } else {
    535                 iY2 = mapper.intY();
    536             }
    537 
    538             switch (s.fTileModeY) {
    539             case SkShader::kClamp_TileMode:
    540                 iY2 = SkClampMax(iY2, stopY-1);
    541                 break;
    542             case SkShader::kRepeat_TileMode:
    543                 iY2 = sk_int_mod(iY2, stopY);
    544                 break;
    545             case SkShader::kMirror_TileMode:
    546             default:
    547                 iY2 = sk_int_mirror(iY2, stopY);
    548                 break;
    549             }
    550 
    551             SkASSERT(iY0 == iY2);
    552         }
    553 #endif
    554     }
    555 
    556     const SkPMColor* row0 = s.fPixmap.addr32(0, iY0);
    557     SkPMColor color;
    558 
    559     if (kNone_SkFilterQuality != s.fFilterLevel) {
    560         const SkPMColor* row1 = s.fPixmap.addr32(0, iY1);
    561 
    562         if (s.fAlphaScale < 256) {
    563             Filter_32_alpha(iSubY, *row0, *row1, &color, s.fAlphaScale);
    564         } else {
    565             Filter_32_opaque(iSubY, *row0, *row1, &color);
    566         }
    567     } else {
    568         if (s.fAlphaScale < 256) {
    569             color = SkAlphaMulQ(*row0, s.fAlphaScale);
    570         } else {
    571             color = *row0;
    572         }
    573     }
    574 
    575     sk_memset32(colors, color, count);
    576 }
    577 
    578 static void DoNothing_shaderproc(const void*, int x, int y,
    579                                  SkPMColor* SK_RESTRICT colors, int count) {
    580     // if we get called, the matrix is too tricky, so we just draw nothing
    581     sk_memset32(colors, 0, count);
    582 }
    583 
    584 bool SkBitmapProcState::setupForTranslate() {
    585     SkPoint pt;
    586     const SkBitmapProcStateAutoMapper mapper(*this, 0, 0, &pt);
    587 
    588     /*
    589      *  if the translate is larger than our ints, we can get random results, or
    590      *  worse, we might get 0x80000000, which wreaks havoc on us, since we can't
    591      *  negate it.
    592      */
    593     const SkScalar too_big = SkIntToScalar(1 << 30);
    594     if (SkScalarAbs(pt.fX) > too_big || SkScalarAbs(pt.fY) > too_big) {
    595         return false;
    596     }
    597 
    598     // Since we know we're not filtered, we re-purpose these fields allow
    599     // us to go from device -> src coordinates w/ just an integer add,
    600     // rather than running through the inverse-matrix
    601     fFilterOneX = mapper.intX();
    602     fFilterOneY = mapper.intY();
    603 
    604     return true;
    605 }
    606 
    607 SkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() {
    608 
    609     if (kN32_SkColorType != fPixmap.colorType()) {
    610         return nullptr;
    611     }
    612 
    613     static const unsigned kMask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
    614 
    615     if (1 == fPixmap.width() && 0 == (fInvType & ~kMask)) {
    616         if (kNone_SkFilterQuality == fFilterLevel &&
    617             fInvType <= SkMatrix::kTranslate_Mask &&
    618             !this->setupForTranslate()) {
    619             return DoNothing_shaderproc;
    620         }
    621         return S32_D32_constX_shaderproc;
    622     }
    623 
    624     if (fAlphaScale < 256) {
    625         return nullptr;
    626     }
    627     if (fInvType > SkMatrix::kTranslate_Mask) {
    628         return nullptr;
    629     }
    630     if (kNone_SkFilterQuality != fFilterLevel) {
    631         return nullptr;
    632     }
    633 
    634     SkShader::TileMode tx = (SkShader::TileMode)fTileModeX;
    635     SkShader::TileMode ty = (SkShader::TileMode)fTileModeY;
    636 
    637     if (SkShader::kClamp_TileMode == tx && SkShader::kClamp_TileMode == ty) {
    638         if (this->setupForTranslate()) {
    639             return Clamp_S32_D32_nofilter_trans_shaderproc;
    640         }
    641         return DoNothing_shaderproc;
    642     }
    643     if (SkShader::kRepeat_TileMode == tx && SkShader::kRepeat_TileMode == ty) {
    644         if (this->setupForTranslate()) {
    645             return Repeat_S32_D32_nofilter_trans_shaderproc;
    646         }
    647         return DoNothing_shaderproc;
    648     }
    649     return nullptr;
    650 }
    651 
    652 ///////////////////////////////////////////////////////////////////////////////
    653 
    654 #ifdef SK_DEBUG
    655 
    656 static void check_scale_nofilter(uint32_t bitmapXY[], int count,
    657                                  unsigned mx, unsigned my) {
    658     unsigned y = *bitmapXY++;
    659     SkASSERT(y < my);
    660 
    661     const uint16_t* xptr = reinterpret_cast<const uint16_t*>(bitmapXY);
    662     for (int i = 0; i < count; ++i) {
    663         SkASSERT(xptr[i] < mx);
    664     }
    665 }
    666 
    667 static void check_scale_filter(uint32_t bitmapXY[], int count,
    668                                  unsigned mx, unsigned my) {
    669     uint32_t YY = *bitmapXY++;
    670     unsigned y0 = YY >> 18;
    671     unsigned y1 = YY & 0x3FFF;
    672     SkASSERT(y0 < my);
    673     SkASSERT(y1 < my);
    674 
    675     for (int i = 0; i < count; ++i) {
    676         uint32_t XX = bitmapXY[i];
    677         unsigned x0 = XX >> 18;
    678         unsigned x1 = XX & 0x3FFF;
    679         SkASSERT(x0 < mx);
    680         SkASSERT(x1 < mx);
    681     }
    682 }
    683 
    684 static void check_affine_nofilter(uint32_t bitmapXY[], int count,
    685                                  unsigned mx, unsigned my) {
    686     for (int i = 0; i < count; ++i) {
    687         uint32_t XY = bitmapXY[i];
    688         unsigned x = XY & 0xFFFF;
    689         unsigned y = XY >> 16;
    690         SkASSERT(x < mx);
    691         SkASSERT(y < my);
    692     }
    693 }
    694 
    695 static void check_affine_filter(uint32_t bitmapXY[], int count,
    696                                  unsigned mx, unsigned my) {
    697     for (int i = 0; i < count; ++i) {
    698         uint32_t YY = *bitmapXY++;
    699         unsigned y0 = YY >> 18;
    700         unsigned y1 = YY & 0x3FFF;
    701         SkASSERT(y0 < my);
    702         SkASSERT(y1 < my);
    703 
    704         uint32_t XX = *bitmapXY++;
    705         unsigned x0 = XX >> 18;
    706         unsigned x1 = XX & 0x3FFF;
    707         SkASSERT(x0 < mx);
    708         SkASSERT(x1 < mx);
    709     }
    710 }
    711 
    712 void SkBitmapProcState::DebugMatrixProc(const SkBitmapProcState& state,
    713                                         uint32_t bitmapXY[], int count,
    714                                         int x, int y) {
    715     SkASSERT(bitmapXY);
    716     SkASSERT(count > 0);
    717 
    718     state.fMatrixProc(state, bitmapXY, count, x, y);
    719 
    720     void (*proc)(uint32_t bitmapXY[], int count, unsigned mx, unsigned my);
    721 
    722     // There are four formats possible:
    723     //  scale -vs- affine
    724     //  filter -vs- nofilter
    725     if (state.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
    726         proc = state.fFilterLevel != kNone_SkFilterQuality ? check_scale_filter : check_scale_nofilter;
    727     } else {
    728         proc = state.fFilterLevel != kNone_SkFilterQuality ? check_affine_filter : check_affine_nofilter;
    729     }
    730     proc(bitmapXY, count, state.fPixmap.width(), state.fPixmap.height());
    731 }
    732 
    733 SkBitmapProcState::MatrixProc SkBitmapProcState::getMatrixProc() const {
    734     return DebugMatrixProc;
    735 }
    736 
    737 #endif
    738 
    739 ///////////////////////////////////////////////////////////////////////////////
    740 /*
    741     The storage requirements for the different matrix procs are as follows,
    742     where each X or Y is 2 bytes, and N is the number of pixels/elements:
    743 
    744     scale/translate     nofilter      Y(4bytes) + N * X
    745     affine/perspective  nofilter      N * (X Y)
    746     scale/translate     filter        Y Y + N * (X X)
    747     affine/perspective  filter        N * (Y Y X X)
    748  */
    749 int SkBitmapProcState::maxCountForBufferSize(size_t bufferSize) const {
    750     int32_t size = static_cast<int32_t>(bufferSize);
    751 
    752     size &= ~3; // only care about 4-byte aligned chunks
    753     if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
    754         size -= 4;   // the shared Y (or YY) coordinate
    755         if (size < 0) {
    756             size = 0;
    757         }
    758         size >>= 1;
    759     } else {
    760         size >>= 2;
    761     }
    762 
    763     if (fFilterLevel != kNone_SkFilterQuality) {
    764         size >>= 1;
    765     }
    766 
    767     return size;
    768 }
    769 
    770 ///////////////////////
    771 
    772 void  Clamp_S32_opaque_D32_nofilter_DX_shaderproc(const void* sIn, int x, int y,
    773                                                   SkPMColor* SK_RESTRICT dst, int count) {
    774     const SkBitmapProcState& s = *static_cast<const SkBitmapProcState*>(sIn);
    775     SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
    776                              SkMatrix::kScale_Mask)) == 0);
    777 
    778     const unsigned maxX = s.fPixmap.width() - 1;
    779     SkFractionalInt fx;
    780     int dstY;
    781     {
    782         const SkBitmapProcStateAutoMapper mapper(s, x, y);
    783         const unsigned maxY = s.fPixmap.height() - 1;
    784         dstY = SkClampMax(mapper.intY(), maxY);
    785         fx = mapper.fractionalIntX();
    786     }
    787 
    788     const SkPMColor* SK_RESTRICT src = s.fPixmap.addr32(0, dstY);
    789     const SkFractionalInt dx = s.fInvSxFractionalInt;
    790 
    791     // Check if we're safely inside [0...maxX] so no need to clamp each computed index.
    792     //
    793     if ((uint64_t)SkFractionalIntToInt(fx) <= maxX &&
    794         (uint64_t)SkFractionalIntToInt(fx + dx * (count - 1)) <= maxX)
    795     {
    796         int count4 = count >> 2;
    797         for (int i = 0; i < count4; ++i) {
    798             SkPMColor src0 = src[SkFractionalIntToInt(fx)]; fx += dx;
    799             SkPMColor src1 = src[SkFractionalIntToInt(fx)]; fx += dx;
    800             SkPMColor src2 = src[SkFractionalIntToInt(fx)]; fx += dx;
    801             SkPMColor src3 = src[SkFractionalIntToInt(fx)]; fx += dx;
    802             dst[0] = src0;
    803             dst[1] = src1;
    804             dst[2] = src2;
    805             dst[3] = src3;
    806             dst += 4;
    807         }
    808         for (int i = (count4 << 2); i < count; ++i) {
    809             unsigned index = SkFractionalIntToInt(fx);
    810             SkASSERT(index <= maxX);
    811             *dst++ = src[index];
    812             fx += dx;
    813         }
    814     } else {
    815         for (int i = 0; i < count; ++i) {
    816             dst[i] = src[SkClampMax(SkFractionalIntToInt(fx), maxX)];
    817             fx += dx;
    818         }
    819     }
    820 }
    821 
    822