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