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