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 #include "SkBitmapScaler.h"
     15 #include "SkMipMap.h"
     16 #include "SkPixelRef.h"
     17 #include "SkScaledImageCache.h"
     18 #include "SkImageEncoder.h"
     19 
     20 #if !SK_ARM_NEON_IS_NONE
     21 // These are defined in src/opts/SkBitmapProcState_arm_neon.cpp
     22 extern const SkBitmapProcState::SampleProc16 gSkBitmapProcStateSample16_neon[];
     23 extern const SkBitmapProcState::SampleProc32 gSkBitmapProcStateSample32_neon[];
     24 extern void  S16_D16_filter_DX_neon(const SkBitmapProcState&, const uint32_t*, int, uint16_t*);
     25 extern void  Clamp_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint16_t*, int);
     26 extern void  Repeat_S16_D16_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint16_t*, int);
     27 extern void  SI8_opaque_D32_filter_DX_neon(const SkBitmapProcState&, const uint32_t*, int, SkPMColor*);
     28 extern void  SI8_opaque_D32_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint32_t*, int);
     29 extern void  Clamp_SI8_opaque_D32_filter_DX_shaderproc_neon(const SkBitmapProcState&, int, int, uint32_t*, int);
     30 #endif
     31 
     32 #define   NAME_WRAP(x)  x
     33 #include "SkBitmapProcState_filter.h"
     34 #include "SkBitmapProcState_procs.h"
     35 
     36 ///////////////////////////////////////////////////////////////////////////////
     37 
     38 // true iff the matrix contains, at most, scale and translate elements
     39 static bool matrix_only_scale_translate(const SkMatrix& m) {
     40     return m.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask);
     41 }
     42 
     43 /**
     44  *  For the purposes of drawing bitmaps, if a matrix is "almost" translate
     45  *  go ahead and treat it as if it were, so that subsequent code can go fast.
     46  */
     47 static bool just_trans_clamp(const SkMatrix& matrix, const SkBitmap& bitmap) {
     48     SkASSERT(matrix_only_scale_translate(matrix));
     49 
     50     if (matrix.getType() & SkMatrix::kScale_Mask) {
     51         SkRect src, dst;
     52         bitmap.getBounds(&src);
     53 
     54         // Can't call mapRect(), since that will fix up inverted rectangles,
     55         // e.g. when scale is negative, and we don't want to return true for
     56         // those.
     57         matrix.mapPoints(SkTCast<SkPoint*>(&dst),
     58                          SkTCast<const SkPoint*>(&src),
     59                          2);
     60 
     61         // Now round all 4 edges to device space, and then compare the device
     62         // width/height to the original. Note: we must map all 4 and subtract
     63         // rather than map the "width" and compare, since we care about the
     64         // phase (in pixel space) that any translate in the matrix might impart.
     65         SkIRect idst;
     66         dst.round(&idst);
     67         return idst.width() == bitmap.width() && idst.height() == bitmap.height();
     68     }
     69     // if we got here, we're either kTranslate_Mask or identity
     70     return true;
     71 }
     72 
     73 static bool just_trans_general(const SkMatrix& matrix) {
     74     SkASSERT(matrix_only_scale_translate(matrix));
     75 
     76     if (matrix.getType() & SkMatrix::kScale_Mask) {
     77         const SkScalar tol = SK_Scalar1 / 32768;
     78 
     79         if (!SkScalarNearlyZero(matrix[SkMatrix::kMScaleX] - SK_Scalar1, tol)) {
     80             return false;
     81         }
     82         if (!SkScalarNearlyZero(matrix[SkMatrix::kMScaleY] - SK_Scalar1, tol)) {
     83             return false;
     84         }
     85     }
     86     // if we got here, treat us as either kTranslate_Mask or identity
     87     return true;
     88 }
     89 
     90 ///////////////////////////////////////////////////////////////////////////////
     91 
     92 static bool valid_for_filtering(unsigned dimension) {
     93     // for filtering, width and height must fit in 14bits, since we use steal
     94     // 2 bits from each to store our 4bit subpixel data
     95     return (dimension & ~0x3FFF) == 0;
     96 }
     97 
     98 static SkScalar effective_matrix_scale_sqrd(const SkMatrix& mat) {
     99     SkPoint v1, v2;
    100 
    101     v1.fX = mat.getScaleX();
    102     v1.fY = mat.getSkewY();
    103 
    104     v2.fX = mat.getSkewX();
    105     v2.fY = mat.getScaleY();
    106 
    107     return SkMaxScalar(v1.lengthSqd(), v2.lengthSqd());
    108 }
    109 
    110 class AutoScaledCacheUnlocker {
    111 public:
    112     AutoScaledCacheUnlocker(SkScaledImageCache::ID** idPtr) : fIDPtr(idPtr) {}
    113     ~AutoScaledCacheUnlocker() {
    114         if (fIDPtr && *fIDPtr) {
    115             SkScaledImageCache::Unlock(*fIDPtr);
    116             *fIDPtr = NULL;
    117         }
    118     }
    119 
    120     // forgets the ID, so it won't call Unlock
    121     void release() {
    122         fIDPtr = NULL;
    123     }
    124 
    125 private:
    126     SkScaledImageCache::ID** fIDPtr;
    127 };
    128 #define AutoScaledCacheUnlocker(...) SK_REQUIRE_LOCAL_VAR(AutoScaledCacheUnlocker)
    129 
    130 // Check to see that the size of the bitmap that would be produced by
    131 // scaling by the given inverted matrix is less than the maximum allowed.
    132 static inline bool cache_size_okay(const SkBitmap& bm, const SkMatrix& invMat) {
    133     size_t maximumAllocation
    134         = SkScaledImageCache::GetSingleAllocationByteLimit();
    135     if (0 == maximumAllocation) {
    136         return true;
    137     }
    138     // float matrixScaleFactor = 1.0 / (invMat.scaleX * invMat.scaleY);
    139     // return ((origBitmapSize * matrixScaleFactor) < maximumAllocationSize);
    140     // Skip the division step:
    141     return bm.info().getSafeSize(bm.info().minRowBytes())
    142         < (maximumAllocation * invMat.getScaleX() * invMat.getScaleY());
    143 }
    144 
    145 // TODO -- we may want to pass the clip into this function so we only scale
    146 // the portion of the image that we're going to need.  This will complicate
    147 // the interface to the cache, but might be well worth it.
    148 
    149 bool SkBitmapProcState::possiblyScaleImage() {
    150     AutoScaledCacheUnlocker unlocker(&fScaledCacheID);
    151 
    152     SkASSERT(NULL == fBitmap);
    153     SkASSERT(NULL == fScaledCacheID);
    154 
    155     if (fFilterLevel <= SkPaint::kLow_FilterLevel) {
    156         return false;
    157     }
    158     // Check to see if the transformation matrix is simple, and if we're
    159     // doing high quality scaling.  If so, do the bitmap scale here and
    160     // remove the scaling component from the matrix.
    161 
    162     if (SkPaint::kHigh_FilterLevel == fFilterLevel &&
    163         fInvMatrix.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask) &&
    164         kN32_SkColorType == fOrigBitmap.colorType() &&
    165         cache_size_okay(fOrigBitmap, fInvMatrix)) {
    166 
    167         SkScalar invScaleX = fInvMatrix.getScaleX();
    168         SkScalar invScaleY = fInvMatrix.getScaleY();
    169 
    170         fScaledCacheID = SkScaledImageCache::FindAndLock(fOrigBitmap,
    171                                                          invScaleX, invScaleY,
    172                                                          &fScaledBitmap);
    173         if (fScaledCacheID) {
    174             fScaledBitmap.lockPixels();
    175             if (!fScaledBitmap.getPixels()) {
    176                 fScaledBitmap.unlockPixels();
    177                 // found a purged entry (discardablememory?), release it
    178                 SkScaledImageCache::Unlock(fScaledCacheID);
    179                 fScaledCacheID = NULL;
    180                 // fall through to rebuild
    181             }
    182         }
    183 
    184         if (NULL == fScaledCacheID) {
    185             float dest_width  = fOrigBitmap.width() / invScaleX;
    186             float dest_height = fOrigBitmap.height() / invScaleY;
    187 
    188             // All the criteria are met; let's make a new bitmap.
    189 
    190             SkConvolutionProcs simd;
    191             sk_bzero(&simd, sizeof(simd));
    192             this->platformConvolutionProcs(&simd);
    193 
    194             if (!SkBitmapScaler::Resize(&fScaledBitmap,
    195                                         fOrigBitmap,
    196                                         SkBitmapScaler::RESIZE_BEST,
    197                                         dest_width,
    198                                         dest_height,
    199                                         simd,
    200                                         SkScaledImageCache::GetAllocator())) {
    201                 // we failed to create fScaledBitmap, so just return and let
    202                 // the scanline proc handle it.
    203                 return false;
    204 
    205             }
    206 
    207             SkASSERT(NULL != fScaledBitmap.getPixels());
    208             fScaledCacheID = SkScaledImageCache::AddAndLock(fOrigBitmap,
    209                                                             invScaleX,
    210                                                             invScaleY,
    211                                                             fScaledBitmap);
    212             if (!fScaledCacheID) {
    213                 fScaledBitmap.reset();
    214                 return false;
    215             }
    216             SkASSERT(NULL != fScaledBitmap.getPixels());
    217         }
    218 
    219         SkASSERT(NULL != fScaledBitmap.getPixels());
    220         fBitmap = &fScaledBitmap;
    221 
    222         // set the inv matrix type to translate-only;
    223         fInvMatrix.setTranslate(fInvMatrix.getTranslateX() / fInvMatrix.getScaleX(),
    224                                 fInvMatrix.getTranslateY() / fInvMatrix.getScaleY());
    225 
    226         // no need for any further filtering; we just did it!
    227         fFilterLevel = SkPaint::kNone_FilterLevel;
    228         unlocker.release();
    229         return true;
    230     }
    231 
    232     /*
    233      *  If High, then our special-case for scale-only did not take, and so we
    234      *  have to make a choice:
    235      *      1. fall back on mipmaps + bilerp
    236      *      2. fall back on scanline bicubic filter
    237      *  For now, we compute the "scale" value from the matrix, and have a
    238      *  threshold to decide when bicubic is better, and when mips are better.
    239      *  No doubt a fancier decision tree could be used uere.
    240      *
    241      *  If Medium, then we just try to build a mipmap and select a level,
    242      *  setting the filter-level to kLow to signal that we just need bilerp
    243      *  to process the selected level.
    244      */
    245 
    246     SkScalar scaleSqd = effective_matrix_scale_sqrd(fInvMatrix);
    247 
    248     if (SkPaint::kHigh_FilterLevel == fFilterLevel) {
    249         // Set the limit at 0.25 for the CTM... if the CTM is scaling smaller
    250         // than this, then the mipmaps quality may be greater (certainly faster)
    251         // so we only keep High quality if the scale is greater than this.
    252         //
    253         // Since we're dealing with the inverse, we compare against its inverse.
    254         const SkScalar bicubicLimit = 4.0f;
    255         const SkScalar bicubicLimitSqd = bicubicLimit * bicubicLimit;
    256         if (scaleSqd < bicubicLimitSqd) {  // use bicubic scanline
    257             return false;
    258         }
    259 
    260         // else set the filter-level to Medium, since we're scaling down and
    261         // want to reqeust mipmaps
    262         fFilterLevel = SkPaint::kMedium_FilterLevel;
    263     }
    264 
    265     SkASSERT(SkPaint::kMedium_FilterLevel == fFilterLevel);
    266 
    267     /**
    268      *  Medium quality means use a mipmap for down-scaling, and just bilper
    269      *  for upscaling. Since we're examining the inverse matrix, we look for
    270      *  a scale > 1 to indicate down scaling by the CTM.
    271      */
    272     if (scaleSqd > SK_Scalar1) {
    273         const SkMipMap* mip = NULL;
    274 
    275         SkASSERT(NULL == fScaledCacheID);
    276         fScaledCacheID = SkScaledImageCache::FindAndLockMip(fOrigBitmap, &mip);
    277         if (!fScaledCacheID) {
    278             SkASSERT(NULL == mip);
    279             mip = SkMipMap::Build(fOrigBitmap);
    280             if (mip) {
    281                 fScaledCacheID = SkScaledImageCache::AddAndLockMip(fOrigBitmap,
    282                                                                    mip);
    283                 SkASSERT(mip->getRefCnt() > 1);
    284                 mip->unref();   // the cache took a ref
    285                 SkASSERT(fScaledCacheID);
    286             }
    287         } else {
    288             SkASSERT(mip);
    289         }
    290 
    291         if (mip) {
    292             SkScalar levelScale = SkScalarInvert(SkScalarSqrt(scaleSqd));
    293             SkMipMap::Level level;
    294             if (mip->extractLevel(levelScale, &level)) {
    295                 SkScalar invScaleFixup = level.fScale;
    296                 fInvMatrix.postScale(invScaleFixup, invScaleFixup);
    297 
    298                 SkImageInfo info = fOrigBitmap.info();
    299                 info.fWidth = level.fWidth;
    300                 info.fHeight = level.fHeight;
    301                 fScaledBitmap.installPixels(info, level.fPixels, level.fRowBytes);
    302                 fBitmap = &fScaledBitmap;
    303                 fFilterLevel = SkPaint::kLow_FilterLevel;
    304                 unlocker.release();
    305                 return true;
    306             }
    307         }
    308     }
    309 
    310     return false;
    311 }
    312 
    313 static bool get_locked_pixels(const SkBitmap& src, int pow2, SkBitmap* dst) {
    314     SkPixelRef* pr = src.pixelRef();
    315     if (pr && pr->decodeInto(pow2, dst)) {
    316         return true;
    317     }
    318 
    319     /*
    320      *  If decodeInto() fails, it is possibe that we have an old subclass that
    321      *  does not, or cannot, implement that. In that case we fall back to the
    322      *  older protocol of having the pixelRef handle the caching for us.
    323      */
    324     *dst = src;
    325     dst->lockPixels();
    326     return SkToBool(dst->getPixels());
    327 }
    328 
    329 bool SkBitmapProcState::lockBaseBitmap() {
    330     AutoScaledCacheUnlocker unlocker(&fScaledCacheID);
    331 
    332     SkPixelRef* pr = fOrigBitmap.pixelRef();
    333 
    334     SkASSERT(NULL == fScaledCacheID);
    335 
    336     if (pr->isLocked() || !pr->implementsDecodeInto()) {
    337         // fast-case, no need to look in our cache
    338         fScaledBitmap = fOrigBitmap;
    339         fScaledBitmap.lockPixels();
    340         if (NULL == fScaledBitmap.getPixels()) {
    341             return false;
    342         }
    343     } else {
    344         fScaledCacheID = SkScaledImageCache::FindAndLock(fOrigBitmap,
    345                                                          SK_Scalar1, SK_Scalar1,
    346                                                          &fScaledBitmap);
    347         if (fScaledCacheID) {
    348             fScaledBitmap.lockPixels();
    349             if (!fScaledBitmap.getPixels()) {
    350                 fScaledBitmap.unlockPixels();
    351                 // found a purged entry (discardablememory?), release it
    352                 SkScaledImageCache::Unlock(fScaledCacheID);
    353                 fScaledCacheID = NULL;
    354                 // fall through to rebuild
    355             }
    356         }
    357 
    358         if (NULL == fScaledCacheID) {
    359             if (!get_locked_pixels(fOrigBitmap, 0, &fScaledBitmap)) {
    360                 return false;
    361             }
    362 
    363             // TODO: if fScaled comes back at a different width/height than fOrig,
    364             // we need to update the matrix we are using to sample from this guy.
    365 
    366             fScaledCacheID = SkScaledImageCache::AddAndLock(fOrigBitmap,
    367                                                             SK_Scalar1, SK_Scalar1,
    368                                                             fScaledBitmap);
    369             if (!fScaledCacheID) {
    370                 fScaledBitmap.reset();
    371                 return false;
    372             }
    373         }
    374     }
    375     fBitmap = &fScaledBitmap;
    376     unlocker.release();
    377     return true;
    378 }
    379 
    380 SkBitmapProcState::~SkBitmapProcState() {
    381     if (fScaledCacheID) {
    382         SkScaledImageCache::Unlock(fScaledCacheID);
    383     }
    384     SkDELETE(fBitmapFilter);
    385 }
    386 
    387 bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
    388     SkASSERT(fOrigBitmap.width() && fOrigBitmap.height());
    389 
    390     fBitmap = NULL;
    391     fInvMatrix = inv;
    392     fFilterLevel = paint.getFilterLevel();
    393 
    394     SkASSERT(NULL == fScaledCacheID);
    395 
    396     // possiblyScaleImage will look to see if it can rescale the image as a
    397     // preprocess; either by scaling up to the target size, or by selecting
    398     // a nearby mipmap level.  If it does, it will adjust the working
    399     // matrix as well as the working bitmap.  It may also adjust the filter
    400     // quality to avoid re-filtering an already perfectly scaled image.
    401     if (!this->possiblyScaleImage()) {
    402         if (!this->lockBaseBitmap()) {
    403             return false;
    404         }
    405     }
    406     // The above logic should have always assigned fBitmap, but in case it
    407     // didn't, we check for that now...
    408     // TODO(dominikg): Ask humper@ if we can just use an SkASSERT(fBitmap)?
    409     if (NULL == fBitmap) {
    410         return false;
    411     }
    412 
    413     // If we are "still" kMedium_FilterLevel, then the request was not fulfilled by possiblyScale,
    414     // so we downgrade to kLow (so the rest of the sniffing code can assume that)
    415     if (SkPaint::kMedium_FilterLevel == fFilterLevel) {
    416         fFilterLevel = SkPaint::kLow_FilterLevel;
    417     }
    418 
    419     bool trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0;
    420     bool clampClamp = SkShader::kClamp_TileMode == fTileModeX &&
    421                       SkShader::kClamp_TileMode == fTileModeY;
    422 
    423     if (!(clampClamp || trivialMatrix)) {
    424         fInvMatrix.postIDiv(fOrigBitmap.width(), fOrigBitmap.height());
    425     }
    426 
    427     // Now that all possible changes to the matrix have taken place, check
    428     // to see if we're really close to a no-scale matrix.  If so, explicitly
    429     // set it to be so.  Subsequent code may inspect this matrix to choose
    430     // a faster path in this case.
    431 
    432     // This code will only execute if the matrix has some scale component;
    433     // if it's already pure translate then we won't do this inversion.
    434 
    435     if (matrix_only_scale_translate(fInvMatrix)) {
    436         SkMatrix forward;
    437         if (fInvMatrix.invert(&forward)) {
    438             if (clampClamp ? just_trans_clamp(forward, *fBitmap)
    439                             : just_trans_general(forward)) {
    440                 SkScalar tx = -SkScalarRoundToScalar(forward.getTranslateX());
    441                 SkScalar ty = -SkScalarRoundToScalar(forward.getTranslateY());
    442                 fInvMatrix.setTranslate(tx, ty);
    443             }
    444         }
    445     }
    446 
    447     fInvProc        = fInvMatrix.getMapXYProc();
    448     fInvType        = fInvMatrix.getType();
    449     fInvSx          = SkScalarToFixed(fInvMatrix.getScaleX());
    450     fInvSxFractionalInt = SkScalarToFractionalInt(fInvMatrix.getScaleX());
    451     fInvKy          = SkScalarToFixed(fInvMatrix.getSkewY());
    452     fInvKyFractionalInt = SkScalarToFractionalInt(fInvMatrix.getSkewY());
    453 
    454     fAlphaScale = SkAlpha255To256(paint.getAlpha());
    455 
    456     fShaderProc32 = NULL;
    457     fShaderProc16 = NULL;
    458     fSampleProc32 = NULL;
    459     fSampleProc16 = NULL;
    460 
    461     // recompute the triviality of the matrix here because we may have
    462     // changed it!
    463 
    464     trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0;
    465 
    466     if (SkPaint::kHigh_FilterLevel == fFilterLevel) {
    467         // If this is still set, that means we wanted HQ sampling
    468         // but couldn't do it as a preprocess.  Let's try to install
    469         // the scanline version of the HQ sampler.  If that process fails,
    470         // downgrade to bilerp.
    471 
    472         // NOTE: Might need to be careful here in the future when we want
    473         // to have the platform proc have a shot at this; it's possible that
    474         // the chooseBitmapFilterProc will fail to install a shader but a
    475         // platform-specific one might succeed, so it might be premature here
    476         // to fall back to bilerp.  This needs thought.
    477 
    478         if (!this->setBitmapFilterProcs()) {
    479             fFilterLevel = SkPaint::kLow_FilterLevel;
    480         }
    481     }
    482 
    483     if (SkPaint::kLow_FilterLevel == fFilterLevel) {
    484         // Only try bilerp if the matrix is "interesting" and
    485         // the image has a suitable size.
    486 
    487         if (fInvType <= SkMatrix::kTranslate_Mask ||
    488                 !valid_for_filtering(fBitmap->width() | fBitmap->height())) {
    489             fFilterLevel = SkPaint::kNone_FilterLevel;
    490         }
    491     }
    492 
    493     // At this point, we know exactly what kind of sampling the per-scanline
    494     // shader will perform.
    495 
    496     fMatrixProc = this->chooseMatrixProc(trivialMatrix);
    497     // TODO(dominikg): SkASSERT(fMatrixProc) instead? chooseMatrixProc never returns NULL.
    498     if (NULL == fMatrixProc) {
    499         return false;
    500     }
    501 
    502     ///////////////////////////////////////////////////////////////////////
    503 
    504     // No need to do this if we're doing HQ sampling; if filter quality is
    505     // still set to HQ by the time we get here, then we must have installed
    506     // the shader procs above and can skip all this.
    507 
    508     if (fFilterLevel < SkPaint::kHigh_FilterLevel) {
    509 
    510         int index = 0;
    511         if (fAlphaScale < 256) {  // note: this distinction is not used for D16
    512             index |= 1;
    513         }
    514         if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
    515             index |= 2;
    516         }
    517         if (fFilterLevel > SkPaint::kNone_FilterLevel) {
    518             index |= 4;
    519         }
    520         // bits 3,4,5 encoding the source bitmap format
    521         switch (fBitmap->colorType()) {
    522             case kN32_SkColorType:
    523                 index |= 0;
    524                 break;
    525             case kRGB_565_SkColorType:
    526                 index |= 8;
    527                 break;
    528             case kIndex_8_SkColorType:
    529                 index |= 16;
    530                 break;
    531             case kARGB_4444_SkColorType:
    532                 index |= 24;
    533                 break;
    534             case kAlpha_8_SkColorType:
    535                 index |= 32;
    536                 fPaintPMColor = SkPreMultiplyColor(paint.getColor());
    537                 break;
    538             default:
    539                 // TODO(dominikg): Should we ever get here? SkASSERT(false) instead?
    540                 return false;
    541         }
    542 
    543     #if !SK_ARM_NEON_IS_ALWAYS
    544         static const SampleProc32 gSkBitmapProcStateSample32[] = {
    545             S32_opaque_D32_nofilter_DXDY,
    546             S32_alpha_D32_nofilter_DXDY,
    547             S32_opaque_D32_nofilter_DX,
    548             S32_alpha_D32_nofilter_DX,
    549             S32_opaque_D32_filter_DXDY,
    550             S32_alpha_D32_filter_DXDY,
    551             S32_opaque_D32_filter_DX,
    552             S32_alpha_D32_filter_DX,
    553 
    554             S16_opaque_D32_nofilter_DXDY,
    555             S16_alpha_D32_nofilter_DXDY,
    556             S16_opaque_D32_nofilter_DX,
    557             S16_alpha_D32_nofilter_DX,
    558             S16_opaque_D32_filter_DXDY,
    559             S16_alpha_D32_filter_DXDY,
    560             S16_opaque_D32_filter_DX,
    561             S16_alpha_D32_filter_DX,
    562 
    563             SI8_opaque_D32_nofilter_DXDY,
    564             SI8_alpha_D32_nofilter_DXDY,
    565             SI8_opaque_D32_nofilter_DX,
    566             SI8_alpha_D32_nofilter_DX,
    567             SI8_opaque_D32_filter_DXDY,
    568             SI8_alpha_D32_filter_DXDY,
    569             SI8_opaque_D32_filter_DX,
    570             SI8_alpha_D32_filter_DX,
    571 
    572             S4444_opaque_D32_nofilter_DXDY,
    573             S4444_alpha_D32_nofilter_DXDY,
    574             S4444_opaque_D32_nofilter_DX,
    575             S4444_alpha_D32_nofilter_DX,
    576             S4444_opaque_D32_filter_DXDY,
    577             S4444_alpha_D32_filter_DXDY,
    578             S4444_opaque_D32_filter_DX,
    579             S4444_alpha_D32_filter_DX,
    580 
    581             // A8 treats alpha/opaque the same (equally efficient)
    582             SA8_alpha_D32_nofilter_DXDY,
    583             SA8_alpha_D32_nofilter_DXDY,
    584             SA8_alpha_D32_nofilter_DX,
    585             SA8_alpha_D32_nofilter_DX,
    586             SA8_alpha_D32_filter_DXDY,
    587             SA8_alpha_D32_filter_DXDY,
    588             SA8_alpha_D32_filter_DX,
    589             SA8_alpha_D32_filter_DX
    590         };
    591 
    592         static const SampleProc16 gSkBitmapProcStateSample16[] = {
    593             S32_D16_nofilter_DXDY,
    594             S32_D16_nofilter_DX,
    595             S32_D16_filter_DXDY,
    596             S32_D16_filter_DX,
    597 
    598             S16_D16_nofilter_DXDY,
    599             S16_D16_nofilter_DX,
    600             S16_D16_filter_DXDY,
    601             S16_D16_filter_DX,
    602 
    603             SI8_D16_nofilter_DXDY,
    604             SI8_D16_nofilter_DX,
    605             SI8_D16_filter_DXDY,
    606             SI8_D16_filter_DX,
    607 
    608             // Don't support 4444 -> 565
    609             NULL, NULL, NULL, NULL,
    610             // Don't support A8 -> 565
    611             NULL, NULL, NULL, NULL
    612         };
    613     #endif
    614 
    615         fSampleProc32 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample32)[index];
    616         index >>= 1;    // shift away any opaque/alpha distinction
    617         fSampleProc16 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample16)[index];
    618 
    619         // our special-case shaderprocs
    620         if (SK_ARM_NEON_WRAP(S16_D16_filter_DX) == fSampleProc16) {
    621             if (clampClamp) {
    622                 fShaderProc16 = SK_ARM_NEON_WRAP(Clamp_S16_D16_filter_DX_shaderproc);
    623             } else if (SkShader::kRepeat_TileMode == fTileModeX &&
    624                        SkShader::kRepeat_TileMode == fTileModeY) {
    625                 fShaderProc16 = SK_ARM_NEON_WRAP(Repeat_S16_D16_filter_DX_shaderproc);
    626             }
    627         } else if (SK_ARM_NEON_WRAP(SI8_opaque_D32_filter_DX) == fSampleProc32 && clampClamp) {
    628             fShaderProc32 = SK_ARM_NEON_WRAP(Clamp_SI8_opaque_D32_filter_DX_shaderproc);
    629         }
    630 
    631         if (NULL == fShaderProc32) {
    632             fShaderProc32 = this->chooseShaderProc32();
    633         }
    634     }
    635 
    636     // see if our platform has any accelerated overrides
    637     this->platformProcs();
    638 
    639     return true;
    640 }
    641 
    642 static void Clamp_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s,
    643                                                     int x, int y,
    644                                                     SkPMColor* SK_RESTRICT colors,
    645                                                     int count) {
    646     SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0);
    647     SkASSERT(s.fInvKy == 0);
    648     SkASSERT(count > 0 && colors != NULL);
    649     SkASSERT(SkPaint::kNone_FilterLevel == s.fFilterLevel);
    650 
    651     const int maxX = s.fBitmap->width() - 1;
    652     const int maxY = s.fBitmap->height() - 1;
    653     int ix = s.fFilterOneX + x;
    654     int iy = SkClampMax(s.fFilterOneY + y, maxY);
    655 #ifdef SK_DEBUG
    656     {
    657         SkPoint pt;
    658         s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
    659                    SkIntToScalar(y) + SK_ScalarHalf, &pt);
    660         int iy2 = SkClampMax(SkScalarFloorToInt(pt.fY), maxY);
    661         int ix2 = SkScalarFloorToInt(pt.fX);
    662 
    663         SkASSERT(iy == iy2);
    664         SkASSERT(ix == ix2);
    665     }
    666 #endif
    667     const SkPMColor* row = s.fBitmap->getAddr32(0, iy);
    668 
    669     // clamp to the left
    670     if (ix < 0) {
    671         int n = SkMin32(-ix, count);
    672         sk_memset32(colors, row[0], n);
    673         count -= n;
    674         if (0 == count) {
    675             return;
    676         }
    677         colors += n;
    678         SkASSERT(-ix == n);
    679         ix = 0;
    680     }
    681     // copy the middle
    682     if (ix <= maxX) {
    683         int n = SkMin32(maxX - ix + 1, count);
    684         memcpy(colors, row + ix, n * sizeof(SkPMColor));
    685         count -= n;
    686         if (0 == count) {
    687             return;
    688         }
    689         colors += n;
    690     }
    691     SkASSERT(count > 0);
    692     // clamp to the right
    693     sk_memset32(colors, row[maxX], count);
    694 }
    695 
    696 static inline int sk_int_mod(int x, int n) {
    697     SkASSERT(n > 0);
    698     if ((unsigned)x >= (unsigned)n) {
    699         if (x < 0) {
    700             x = n + ~(~x % n);
    701         } else {
    702             x = x % n;
    703         }
    704     }
    705     return x;
    706 }
    707 
    708 static inline int sk_int_mirror(int x, int n) {
    709     x = sk_int_mod(x, 2 * n);
    710     if (x >= n) {
    711         x = n + ~(x - n);
    712     }
    713     return x;
    714 }
    715 
    716 static void Repeat_S32_D32_nofilter_trans_shaderproc(const SkBitmapProcState& s,
    717                                                      int x, int y,
    718                                                      SkPMColor* SK_RESTRICT colors,
    719                                                      int count) {
    720     SkASSERT(((s.fInvType & ~SkMatrix::kTranslate_Mask)) == 0);
    721     SkASSERT(s.fInvKy == 0);
    722     SkASSERT(count > 0 && colors != NULL);
    723     SkASSERT(SkPaint::kNone_FilterLevel == s.fFilterLevel);
    724 
    725     const int stopX = s.fBitmap->width();
    726     const int stopY = s.fBitmap->height();
    727     int ix = s.fFilterOneX + x;
    728     int iy = sk_int_mod(s.fFilterOneY + y, stopY);
    729 #ifdef SK_DEBUG
    730     {
    731         SkPoint pt;
    732         s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
    733                    SkIntToScalar(y) + SK_ScalarHalf, &pt);
    734         int iy2 = sk_int_mod(SkScalarFloorToInt(pt.fY), stopY);
    735         int ix2 = SkScalarFloorToInt(pt.fX);
    736 
    737         SkASSERT(iy == iy2);
    738         SkASSERT(ix == ix2);
    739     }
    740 #endif
    741     const SkPMColor* row = s.fBitmap->getAddr32(0, iy);
    742 
    743     ix = sk_int_mod(ix, stopX);
    744     for (;;) {
    745         int n = SkMin32(stopX - ix, count);
    746         memcpy(colors, row + ix, n * sizeof(SkPMColor));
    747         count -= n;
    748         if (0 == count) {
    749             return;
    750         }
    751         colors += n;
    752         ix = 0;
    753     }
    754 }
    755 
    756 static void S32_D32_constX_shaderproc(const SkBitmapProcState& s,
    757                                       int x, int y,
    758                                       SkPMColor* SK_RESTRICT colors,
    759                                       int count) {
    760     SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) == 0);
    761     SkASSERT(s.fInvKy == 0);
    762     SkASSERT(count > 0 && colors != NULL);
    763     SkASSERT(1 == s.fBitmap->width());
    764 
    765     int iY0;
    766     int iY1   SK_INIT_TO_AVOID_WARNING;
    767     int iSubY SK_INIT_TO_AVOID_WARNING;
    768 
    769     if (SkPaint::kNone_FilterLevel != s.fFilterLevel) {
    770         SkBitmapProcState::MatrixProc mproc = s.getMatrixProc();
    771         uint32_t xy[2];
    772 
    773         mproc(s, xy, 1, x, y);
    774 
    775         iY0 = xy[0] >> 18;
    776         iY1 = xy[0] & 0x3FFF;
    777         iSubY = (xy[0] >> 14) & 0xF;
    778     } else {
    779         int yTemp;
    780 
    781         if (s.fInvType > SkMatrix::kTranslate_Mask) {
    782             SkPoint pt;
    783             s.fInvProc(s.fInvMatrix,
    784                        SkIntToScalar(x) + SK_ScalarHalf,
    785                        SkIntToScalar(y) + SK_ScalarHalf,
    786                        &pt);
    787             // When the matrix has a scale component the setup code in
    788             // chooseProcs multiples the inverse matrix by the inverse of the
    789             // bitmap's width and height. Since this method is going to do
    790             // its own tiling and sampling we need to undo that here.
    791             if (SkShader::kClamp_TileMode != s.fTileModeX ||
    792                 SkShader::kClamp_TileMode != s.fTileModeY) {
    793                 yTemp = SkScalarFloorToInt(pt.fY * s.fBitmap->height());
    794             } else {
    795                 yTemp = SkScalarFloorToInt(pt.fY);
    796             }
    797         } else {
    798             yTemp = s.fFilterOneY + y;
    799         }
    800 
    801         const int stopY = s.fBitmap->height();
    802         switch (s.fTileModeY) {
    803             case SkShader::kClamp_TileMode:
    804                 iY0 = SkClampMax(yTemp, stopY-1);
    805                 break;
    806             case SkShader::kRepeat_TileMode:
    807                 iY0 = sk_int_mod(yTemp, stopY);
    808                 break;
    809             case SkShader::kMirror_TileMode:
    810             default:
    811                 iY0 = sk_int_mirror(yTemp, stopY);
    812                 break;
    813         }
    814 
    815 #ifdef SK_DEBUG
    816         {
    817             SkPoint pt;
    818             s.fInvProc(s.fInvMatrix,
    819                        SkIntToScalar(x) + SK_ScalarHalf,
    820                        SkIntToScalar(y) + SK_ScalarHalf,
    821                        &pt);
    822             if (s.fInvType > SkMatrix::kTranslate_Mask &&
    823                 (SkShader::kClamp_TileMode != s.fTileModeX ||
    824                  SkShader::kClamp_TileMode != s.fTileModeY)) {
    825                 pt.fY *= s.fBitmap->height();
    826             }
    827             int iY2;
    828 
    829             switch (s.fTileModeY) {
    830             case SkShader::kClamp_TileMode:
    831                 iY2 = SkClampMax(SkScalarFloorToInt(pt.fY), stopY-1);
    832                 break;
    833             case SkShader::kRepeat_TileMode:
    834                 iY2 = sk_int_mod(SkScalarFloorToInt(pt.fY), stopY);
    835                 break;
    836             case SkShader::kMirror_TileMode:
    837             default:
    838                 iY2 = sk_int_mirror(SkScalarFloorToInt(pt.fY), stopY);
    839                 break;
    840             }
    841 
    842             SkASSERT(iY0 == iY2);
    843         }
    844 #endif
    845     }
    846 
    847     const SkPMColor* row0 = s.fBitmap->getAddr32(0, iY0);
    848     SkPMColor color;
    849 
    850     if (SkPaint::kNone_FilterLevel != s.fFilterLevel) {
    851         const SkPMColor* row1 = s.fBitmap->getAddr32(0, iY1);
    852 
    853         if (s.fAlphaScale < 256) {
    854             Filter_32_alpha(iSubY, *row0, *row1, &color, s.fAlphaScale);
    855         } else {
    856             Filter_32_opaque(iSubY, *row0, *row1, &color);
    857         }
    858     } else {
    859         if (s.fAlphaScale < 256) {
    860             color = SkAlphaMulQ(*row0, s.fAlphaScale);
    861         } else {
    862             color = *row0;
    863         }
    864     }
    865 
    866     sk_memset32(colors, color, count);
    867 }
    868 
    869 static void DoNothing_shaderproc(const SkBitmapProcState&, int x, int y,
    870                                  SkPMColor* SK_RESTRICT colors, int count) {
    871     // if we get called, the matrix is too tricky, so we just draw nothing
    872     sk_memset32(colors, 0, count);
    873 }
    874 
    875 bool SkBitmapProcState::setupForTranslate() {
    876     SkPoint pt;
    877     fInvProc(fInvMatrix, SK_ScalarHalf, SK_ScalarHalf, &pt);
    878 
    879     /*
    880      *  if the translate is larger than our ints, we can get random results, or
    881      *  worse, we might get 0x80000000, which wreaks havoc on us, since we can't
    882      *  negate it.
    883      */
    884     const SkScalar too_big = SkIntToScalar(1 << 30);
    885     if (SkScalarAbs(pt.fX) > too_big || SkScalarAbs(pt.fY) > too_big) {
    886         return false;
    887     }
    888 
    889     // Since we know we're not filtered, we re-purpose these fields allow
    890     // us to go from device -> src coordinates w/ just an integer add,
    891     // rather than running through the inverse-matrix
    892     fFilterOneX = SkScalarFloorToInt(pt.fX);
    893     fFilterOneY = SkScalarFloorToInt(pt.fY);
    894     return true;
    895 }
    896 
    897 SkBitmapProcState::ShaderProc32 SkBitmapProcState::chooseShaderProc32() {
    898 
    899     if (kN32_SkColorType != fBitmap->colorType()) {
    900         return NULL;
    901     }
    902 
    903     static const unsigned kMask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
    904 
    905     if (1 == fBitmap->width() && 0 == (fInvType & ~kMask)) {
    906         if (SkPaint::kNone_FilterLevel == fFilterLevel &&
    907             fInvType <= SkMatrix::kTranslate_Mask &&
    908             !this->setupForTranslate()) {
    909             return DoNothing_shaderproc;
    910         }
    911         return S32_D32_constX_shaderproc;
    912     }
    913 
    914     if (fAlphaScale < 256) {
    915         return NULL;
    916     }
    917     if (fInvType > SkMatrix::kTranslate_Mask) {
    918         return NULL;
    919     }
    920     if (SkPaint::kNone_FilterLevel != fFilterLevel) {
    921         return NULL;
    922     }
    923 
    924     SkShader::TileMode tx = (SkShader::TileMode)fTileModeX;
    925     SkShader::TileMode ty = (SkShader::TileMode)fTileModeY;
    926 
    927     if (SkShader::kClamp_TileMode == tx && SkShader::kClamp_TileMode == ty) {
    928         if (this->setupForTranslate()) {
    929             return Clamp_S32_D32_nofilter_trans_shaderproc;
    930         }
    931         return DoNothing_shaderproc;
    932     }
    933     if (SkShader::kRepeat_TileMode == tx && SkShader::kRepeat_TileMode == ty) {
    934         if (this->setupForTranslate()) {
    935             return Repeat_S32_D32_nofilter_trans_shaderproc;
    936         }
    937         return DoNothing_shaderproc;
    938     }
    939     return NULL;
    940 }
    941 
    942 ///////////////////////////////////////////////////////////////////////////////
    943 
    944 #ifdef SK_DEBUG
    945 
    946 static void check_scale_nofilter(uint32_t bitmapXY[], int count,
    947                                  unsigned mx, unsigned my) {
    948     unsigned y = *bitmapXY++;
    949     SkASSERT(y < my);
    950 
    951     const uint16_t* xptr = reinterpret_cast<const uint16_t*>(bitmapXY);
    952     for (int i = 0; i < count; ++i) {
    953         SkASSERT(xptr[i] < mx);
    954     }
    955 }
    956 
    957 static void check_scale_filter(uint32_t bitmapXY[], int count,
    958                                  unsigned mx, unsigned my) {
    959     uint32_t YY = *bitmapXY++;
    960     unsigned y0 = YY >> 18;
    961     unsigned y1 = YY & 0x3FFF;
    962     SkASSERT(y0 < my);
    963     SkASSERT(y1 < my);
    964 
    965     for (int i = 0; i < count; ++i) {
    966         uint32_t XX = bitmapXY[i];
    967         unsigned x0 = XX >> 18;
    968         unsigned x1 = XX & 0x3FFF;
    969         SkASSERT(x0 < mx);
    970         SkASSERT(x1 < mx);
    971     }
    972 }
    973 
    974 static void check_affine_nofilter(uint32_t bitmapXY[], int count,
    975                                  unsigned mx, unsigned my) {
    976     for (int i = 0; i < count; ++i) {
    977         uint32_t XY = bitmapXY[i];
    978         unsigned x = XY & 0xFFFF;
    979         unsigned y = XY >> 16;
    980         SkASSERT(x < mx);
    981         SkASSERT(y < my);
    982     }
    983 }
    984 
    985 static void check_affine_filter(uint32_t bitmapXY[], int count,
    986                                  unsigned mx, unsigned my) {
    987     for (int i = 0; i < count; ++i) {
    988         uint32_t YY = *bitmapXY++;
    989         unsigned y0 = YY >> 18;
    990         unsigned y1 = YY & 0x3FFF;
    991         SkASSERT(y0 < my);
    992         SkASSERT(y1 < my);
    993 
    994         uint32_t XX = *bitmapXY++;
    995         unsigned x0 = XX >> 18;
    996         unsigned x1 = XX & 0x3FFF;
    997         SkASSERT(x0 < mx);
    998         SkASSERT(x1 < mx);
    999     }
   1000 }
   1001 
   1002 void SkBitmapProcState::DebugMatrixProc(const SkBitmapProcState& state,
   1003                                         uint32_t bitmapXY[], int count,
   1004                                         int x, int y) {
   1005     SkASSERT(bitmapXY);
   1006     SkASSERT(count > 0);
   1007 
   1008     state.fMatrixProc(state, bitmapXY, count, x, y);
   1009 
   1010     void (*proc)(uint32_t bitmapXY[], int count, unsigned mx, unsigned my);
   1011 
   1012     // There are four formats possible:
   1013     //  scale -vs- affine
   1014     //  filter -vs- nofilter
   1015     if (state.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
   1016         proc = state.fFilterLevel != SkPaint::kNone_FilterLevel ? check_scale_filter : check_scale_nofilter;
   1017     } else {
   1018         proc = state.fFilterLevel != SkPaint::kNone_FilterLevel ? check_affine_filter : check_affine_nofilter;
   1019     }
   1020     proc(bitmapXY, count, state.fBitmap->width(), state.fBitmap->height());
   1021 }
   1022 
   1023 SkBitmapProcState::MatrixProc SkBitmapProcState::getMatrixProc() const {
   1024     return DebugMatrixProc;
   1025 }
   1026 
   1027 #endif
   1028 
   1029 ///////////////////////////////////////////////////////////////////////////////
   1030 /*
   1031     The storage requirements for the different matrix procs are as follows,
   1032     where each X or Y is 2 bytes, and N is the number of pixels/elements:
   1033 
   1034     scale/translate     nofilter      Y(4bytes) + N * X
   1035     affine/perspective  nofilter      N * (X Y)
   1036     scale/translate     filter        Y Y + N * (X X)
   1037     affine/perspective  filter        N * (Y Y X X)
   1038  */
   1039 int SkBitmapProcState::maxCountForBufferSize(size_t bufferSize) const {
   1040     int32_t size = static_cast<int32_t>(bufferSize);
   1041 
   1042     size &= ~3; // only care about 4-byte aligned chunks
   1043     if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
   1044         size -= 4;   // the shared Y (or YY) coordinate
   1045         if (size < 0) {
   1046             size = 0;
   1047         }
   1048         size >>= 1;
   1049     } else {
   1050         size >>= 2;
   1051     }
   1052 
   1053     if (fFilterLevel != SkPaint::kNone_FilterLevel) {
   1054         size >>= 1;
   1055     }
   1056 
   1057     return size;
   1058 }
   1059