Home | History | Annotate | Download | only in core
      1 #include "SkBitmapProcState.h"
      2 #include "SkBitmapProcState_filter.h"
      3 #include "SkColorPriv.h"
      4 #include "SkFilterProc.h"
      5 #include "SkPaint.h"
      6 #include "SkShader.h"   // for tilemodes
      7 
      8 // returns expanded * 5bits
      9 static inline uint32_t Filter_565_Expanded(unsigned x, unsigned y,
     10                                            uint32_t a00, uint32_t a01,
     11                                            uint32_t a10, uint32_t a11) {
     12     SkASSERT((unsigned)x <= 0xF);
     13     SkASSERT((unsigned)y <= 0xF);
     14 
     15     a00 = SkExpand_rgb_16(a00);
     16     a01 = SkExpand_rgb_16(a01);
     17     a10 = SkExpand_rgb_16(a10);
     18     a11 = SkExpand_rgb_16(a11);
     19 
     20     int xy = x * y >> 3;
     21     return  a00 * (32 - 2*y - 2*x + xy) +
     22             a01 * (2*x - xy) +
     23             a10 * (2*y - xy) +
     24             a11 * xy;
     25 }
     26 
     27 // turn an expanded 565 * 5bits into SkPMColor
     28 // g:11 | r:10 | x:1 | b:10
     29 static inline SkPMColor SkExpanded_565_To_PMColor(uint32_t c) {
     30     unsigned r = (c >> 13) & 0xFF;
     31     unsigned g = (c >> 24);
     32     unsigned b = (c >> 2) & 0xFF;
     33     return SkPackARGB32(0xFF, r, g, b);
     34 }
     35 
     36 // returns answer in SkPMColor format
     37 static inline SkPMColor Filter_4444_D32(unsigned x, unsigned y,
     38                                         uint32_t a00, uint32_t a01,
     39                                         uint32_t a10, uint32_t a11) {
     40     SkASSERT((unsigned)x <= 0xF);
     41     SkASSERT((unsigned)y <= 0xF);
     42 
     43     a00 = SkExpand_4444(a00);
     44     a01 = SkExpand_4444(a01);
     45     a10 = SkExpand_4444(a10);
     46     a11 = SkExpand_4444(a11);
     47 
     48     int xy = x * y >> 4;
     49     uint32_t result =   a00 * (16 - y - x + xy) +
     50                         a01 * (x - xy) +
     51                         a10 * (y - xy) +
     52                         a11 * xy;
     53 
     54     return SkCompact_8888(result);
     55 }
     56 
     57 static inline U8CPU Filter_8(unsigned x, unsigned y,
     58                              U8CPU a00, U8CPU a01,
     59                              U8CPU a10, U8CPU a11) {
     60     SkASSERT((unsigned)x <= 0xF);
     61     SkASSERT((unsigned)y <= 0xF);
     62 
     63     int xy = x * y;
     64     unsigned result =   a00 * (256 - 16*y - 16*x + xy) +
     65                         a01 * (16*x - xy) +
     66                         a10 * (16*y - xy) +
     67                         a11 * xy;
     68 
     69     return result >> 8;
     70 }
     71 
     72 /*****************************************************************************
     73  *
     74  *  D32 functions
     75  *
     76  */
     77 
     78 // SRC == 8888
     79 
     80 #define FILTER_PROC(x, y, a, b, c, d, dst)   Filter_32_opaque(x, y, a, b, c, d, dst)
     81 
     82 #define MAKENAME(suffix)        S32_opaque_D32 ## suffix
     83 #define DSTSIZE                 32
     84 #define SRCTYPE                 SkPMColor
     85 #define CHECKSTATE(state)       SkASSERT(state.fBitmap->config() == SkBitmap::kARGB_8888_Config); \
     86                                 SkASSERT(state.fAlphaScale == 256)
     87 #define RETURNDST(src)          src
     88 #define SRC_TO_FILTER(src)      src
     89 #include "SkBitmapProcState_sample.h"
     90 
     91 #undef FILTER_PROC
     92 #define FILTER_PROC(x, y, a, b, c, d, dst)   Filter_32_alpha(x, y, a, b, c, d, dst, alphaScale)
     93 
     94 #define MAKENAME(suffix)        S32_alpha_D32 ## suffix
     95 #define DSTSIZE                 32
     96 #define SRCTYPE                 SkPMColor
     97 #define CHECKSTATE(state)       SkASSERT(state.fBitmap->config() == SkBitmap::kARGB_8888_Config); \
     98                                 SkASSERT(state.fAlphaScale < 256)
     99 #define PREAMBLE(state)         unsigned alphaScale = state.fAlphaScale
    100 #define RETURNDST(src)          SkAlphaMulQ(src, alphaScale)
    101 #define SRC_TO_FILTER(src)      src
    102 #include "SkBitmapProcState_sample.h"
    103 
    104 // SRC == 565
    105 
    106 #undef FILTER_PROC
    107 #define FILTER_PROC(x, y, a, b, c, d, dst) \
    108     do {                                                        \
    109         uint32_t tmp = Filter_565_Expanded(x, y, a, b, c, d);   \
    110         *(dst) = SkExpanded_565_To_PMColor(tmp);                \
    111     } while (0)
    112 
    113 #define MAKENAME(suffix)        S16_opaque_D32 ## suffix
    114 #define DSTSIZE                 32
    115 #define SRCTYPE                 uint16_t
    116 #define CHECKSTATE(state)       SkASSERT(state.fBitmap->config() == SkBitmap::kRGB_565_Config); \
    117                                 SkASSERT(state.fAlphaScale == 256)
    118 #define RETURNDST(src)          SkPixel16ToPixel32(src)
    119 #define SRC_TO_FILTER(src)      src
    120 #include "SkBitmapProcState_sample.h"
    121 
    122 #undef FILTER_PROC
    123 #define FILTER_PROC(x, y, a, b, c, d, dst) \
    124     do {                                                                    \
    125         uint32_t tmp = Filter_565_Expanded(x, y, a, b, c, d);               \
    126         *(dst) = SkAlphaMulQ(SkExpanded_565_To_PMColor(tmp), alphaScale);   \
    127     } while (0)
    128 
    129 #define MAKENAME(suffix)        S16_alpha_D32 ## suffix
    130 #define DSTSIZE                 32
    131 #define SRCTYPE                 uint16_t
    132 #define CHECKSTATE(state)       SkASSERT(state.fBitmap->config() == SkBitmap::kRGB_565_Config); \
    133                                 SkASSERT(state.fAlphaScale < 256)
    134 #define PREAMBLE(state)         unsigned alphaScale = state.fAlphaScale
    135 #define RETURNDST(src)          SkAlphaMulQ(SkPixel16ToPixel32(src), alphaScale)
    136 #define SRC_TO_FILTER(src)      src
    137 #include "SkBitmapProcState_sample.h"
    138 
    139 // SRC == Index8
    140 
    141 #undef FILTER_PROC
    142 #define FILTER_PROC(x, y, a, b, c, d, dst)   Filter_32_opaque(x, y, a, b, c, d, dst)
    143 
    144 #define MAKENAME(suffix)        SI8_opaque_D32 ## suffix
    145 #define DSTSIZE                 32
    146 #define SRCTYPE                 uint8_t
    147 #define CHECKSTATE(state)       SkASSERT(state.fBitmap->config() == SkBitmap::kIndex8_Config); \
    148                                 SkASSERT(state.fAlphaScale == 256)
    149 #define PREAMBLE(state)         const SkPMColor* SK_RESTRICT table = state.fBitmap->getColorTable()->lockColors()
    150 #define RETURNDST(src)          table[src]
    151 #define SRC_TO_FILTER(src)      table[src]
    152 #define POSTAMBLE(state)        state.fBitmap->getColorTable()->unlockColors(false)
    153 #include "SkBitmapProcState_sample.h"
    154 
    155 #undef FILTER_PROC
    156 #define FILTER_PROC(x, y, a, b, c, d, dst)   Filter_32_alpha(x, y, a, b, c, d, dst, alphaScale)
    157 
    158 #define MAKENAME(suffix)        SI8_alpha_D32 ## suffix
    159 #define DSTSIZE                 32
    160 #define SRCTYPE                 uint8_t
    161 #define CHECKSTATE(state)       SkASSERT(state.fBitmap->config() == SkBitmap::kIndex8_Config); \
    162                                 SkASSERT(state.fAlphaScale < 256)
    163 #define PREAMBLE(state)         unsigned alphaScale = state.fAlphaScale; \
    164                                 const SkPMColor* SK_RESTRICT table = state.fBitmap->getColorTable()->lockColors()
    165 #define RETURNDST(src)          SkAlphaMulQ(table[src], alphaScale)
    166 #define SRC_TO_FILTER(src)      table[src]
    167 #define POSTAMBLE(state)        state.fBitmap->getColorTable()->unlockColors(false)
    168 #include "SkBitmapProcState_sample.h"
    169 
    170 // SRC == 4444
    171 
    172 #undef FILTER_PROC
    173 #define FILTER_PROC(x, y, a, b, c, d, dst)  *(dst) = Filter_4444_D32(x, y, a, b, c, d)
    174 
    175 #define MAKENAME(suffix)        S4444_opaque_D32 ## suffix
    176 #define DSTSIZE                 32
    177 #define SRCTYPE                 SkPMColor16
    178 #define CHECKSTATE(state)       SkASSERT(state.fBitmap->config() == SkBitmap::kARGB_4444_Config); \
    179                                 SkASSERT(state.fAlphaScale == 256)
    180 #define RETURNDST(src)          SkPixel4444ToPixel32(src)
    181 #define SRC_TO_FILTER(src)      src
    182 #include "SkBitmapProcState_sample.h"
    183 
    184 #undef FILTER_PROC
    185 #define FILTER_PROC(x, y, a, b, c, d, dst)  \
    186     do {                                                    \
    187         uint32_t tmp = Filter_4444_D32(x, y, a, b, c, d);   \
    188         *(dst) = SkAlphaMulQ(tmp, alphaScale);              \
    189     } while (0)
    190 
    191 #define MAKENAME(suffix)        S4444_alpha_D32 ## suffix
    192 #define DSTSIZE                 32
    193 #define SRCTYPE                 SkPMColor16
    194 #define CHECKSTATE(state)       SkASSERT(state.fBitmap->config() == SkBitmap::kARGB_4444_Config); \
    195                                 SkASSERT(state.fAlphaScale < 256)
    196 #define PREAMBLE(state)         unsigned alphaScale = state.fAlphaScale
    197 #define RETURNDST(src)          SkAlphaMulQ(SkPixel4444ToPixel32(src), alphaScale)
    198 #define SRC_TO_FILTER(src)      src
    199 #include "SkBitmapProcState_sample.h"
    200 
    201 // SRC == A8
    202 
    203 #undef FILTER_PROC
    204 #define FILTER_PROC(x, y, a, b, c, d, dst) \
    205     do {                                                        \
    206         unsigned tmp = Filter_8(x, y, a, b, c, d);              \
    207         *(dst) = SkAlphaMulQ(pmColor, SkAlpha255To256(tmp));    \
    208     } while (0)
    209 
    210 #define MAKENAME(suffix)        SA8_alpha_D32 ## suffix
    211 #define DSTSIZE                 32
    212 #define SRCTYPE                 uint8_t
    213 #define CHECKSTATE(state)       SkASSERT(state.fBitmap->config() == SkBitmap::kA8_Config); \
    214                                 SkASSERT(state.fAlphaScale == 256)
    215 #define PREAMBLE(state)         const SkPMColor pmColor = state.fPaintPMColor;
    216 #define RETURNDST(src)          SkAlphaMulQ(pmColor, SkAlpha255To256(src))
    217 #define SRC_TO_FILTER(src)      src
    218 #include "SkBitmapProcState_sample.h"
    219 
    220 /*****************************************************************************
    221  *
    222  *  D16 functions
    223  *
    224  */
    225 
    226 // SRC == 8888
    227 
    228 #undef FILTER_PROC
    229 #define FILTER_PROC(x, y, a, b, c, d, dst) \
    230     do {                                                \
    231         SkPMColor dstColor;                             \
    232         Filter_32_opaque(x, y, a, b, c, d, &dstColor);  \
    233         (*dst) = SkPixel32ToPixel16(dstColor);          \
    234     } while (0)
    235 
    236 #define MAKENAME(suffix)        S32_D16 ## suffix
    237 #define DSTSIZE                 16
    238 #define SRCTYPE                 SkPMColor
    239 #define CHECKSTATE(state)       SkASSERT(state.fBitmap->config() == SkBitmap::kARGB_8888_Config); \
    240                                 SkASSERT(state.fBitmap->isOpaque())
    241 #define RETURNDST(src)          SkPixel32ToPixel16(src)
    242 #define SRC_TO_FILTER(src)      src
    243 #include "SkBitmapProcState_sample.h"
    244 
    245 // SRC == 565
    246 
    247 #undef FILTER_PROC
    248 #define FILTER_PROC(x, y, a, b, c, d, dst) \
    249     do {                                                        \
    250         uint32_t tmp = Filter_565_Expanded(x, y, a, b, c, d);   \
    251         *(dst) = SkCompact_rgb_16((tmp) >> 5);                  \
    252     } while (0)
    253 
    254 #define MAKENAME(suffix)        S16_D16 ## suffix
    255 #define DSTSIZE                 16
    256 #define SRCTYPE                 uint16_t
    257 #define CHECKSTATE(state)       SkASSERT(state.fBitmap->config() == SkBitmap::kRGB_565_Config)
    258 #define RETURNDST(src)          src
    259 #define SRC_TO_FILTER(src)      src
    260 #include "SkBitmapProcState_sample.h"
    261 
    262 // SRC == Index8
    263 
    264 #undef FILTER_PROC
    265 #define FILTER_PROC(x, y, a, b, c, d, dst) \
    266     do {                                                        \
    267         uint32_t tmp = Filter_565_Expanded(x, y, a, b, c, d);   \
    268         *(dst) = SkCompact_rgb_16((tmp) >> 5);                  \
    269     } while (0)
    270 
    271 #define MAKENAME(suffix)        SI8_D16 ## suffix
    272 #define DSTSIZE                 16
    273 #define SRCTYPE                 uint8_t
    274 #define CHECKSTATE(state)       SkASSERT(state.fBitmap->config() == SkBitmap::kIndex8_Config); \
    275                                 SkASSERT(state.fBitmap->isOpaque())
    276 #define PREAMBLE(state)         const uint16_t* SK_RESTRICT table = state.fBitmap->getColorTable()->lock16BitCache()
    277 #define RETURNDST(src)          table[src]
    278 #define SRC_TO_FILTER(src)      table[src]
    279 #define POSTAMBLE(state)        state.fBitmap->getColorTable()->unlock16BitCache()
    280 #include "SkBitmapProcState_sample.h"
    281 
    282 ///////////////////////////////////////////////////////////////////////////////
    283 
    284 #undef FILTER_PROC
    285 #define FILTER_PROC(x, y, a, b, c, d, dst) \
    286     do {                                                        \
    287         uint32_t tmp = Filter_565_Expanded(x, y, a, b, c, d);   \
    288         *(dst) = SkCompact_rgb_16((tmp) >> 5);                  \
    289     } while (0)
    290 
    291 
    292 // clamp
    293 
    294 #define TILEX_PROCF(fx, max)    SkClampMax((fx) >> 16, max)
    295 #define TILEY_PROCF(fy, max)    SkClampMax((fy) >> 16, max)
    296 #define TILEX_LOW_BITS(fx, max) (((fx) >> 12) & 0xF)
    297 #define TILEY_LOW_BITS(fy, max) (((fy) >> 12) & 0xF)
    298 
    299 #define MAKENAME(suffix)        Clamp_S16_D16 ## suffix
    300 #define SRCTYPE                 uint16_t
    301 #define DSTTYPE                 uint16_t
    302 #define CHECKSTATE(state)       SkASSERT(state.fBitmap->config() == SkBitmap::kRGB_565_Config)
    303 #define SRC_TO_FILTER(src)      src
    304 #include "SkBitmapProcState_shaderproc.h"
    305 
    306 
    307 #define TILEX_PROCF(fx, max)    (((fx) & 0xFFFF) * ((max) + 1) >> 16)
    308 #define TILEY_PROCF(fy, max)    (((fy) & 0xFFFF) * ((max) + 1) >> 16)
    309 #define TILEX_LOW_BITS(fx, max) ((((fx) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
    310 #define TILEY_LOW_BITS(fy, max) ((((fy) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
    311 
    312 #define MAKENAME(suffix)        Repeat_S16_D16 ## suffix
    313 #define SRCTYPE                 uint16_t
    314 #define DSTTYPE                 uint16_t
    315 #define CHECKSTATE(state)       SkASSERT(state.fBitmap->config() == SkBitmap::kRGB_565_Config)
    316 #define SRC_TO_FILTER(src)      src
    317 #include "SkBitmapProcState_shaderproc.h"
    318 
    319 
    320 #define TILEX_PROCF(fx, max)    SkClampMax((fx) >> 16, max)
    321 #define TILEY_PROCF(fy, max)    SkClampMax((fy) >> 16, max)
    322 #define TILEX_LOW_BITS(fx, max) (((fx) >> 12) & 0xF)
    323 #define TILEY_LOW_BITS(fy, max) (((fy) >> 12) & 0xF)
    324 
    325 #undef FILTER_PROC
    326 #define FILTER_PROC(x, y, a, b, c, d, dst)   Filter_32_opaque(x, y, a, b, c, d, dst)
    327 #define MAKENAME(suffix)        Clamp_SI8_opaque_D32 ## suffix
    328 #define SRCTYPE                 uint8_t
    329 #define DSTTYPE                 uint32_t
    330 #define CHECKSTATE(state)       SkASSERT(state.fBitmap->config() == SkBitmap::kIndex8_Config)
    331 #define PREAMBLE(state)         const SkPMColor* SK_RESTRICT table = state.fBitmap->getColorTable()->lockColors()
    332 #define SRC_TO_FILTER(src)      table[src]
    333 #define POSTAMBLE(state)        state.fBitmap->getColorTable()->unlockColors(false)
    334 #include "SkBitmapProcState_shaderproc.h"
    335 
    336 ///////////////////////////////////////////////////////////////////////////////
    337 
    338 static bool valid_for_filtering(unsigned dimension) {
    339     // for filtering, width and height must fit in 14bits, since we use steal
    340     // 2 bits from each to store our 4bit subpixel data
    341     return (dimension & ~0x3FFF) == 0;
    342 }
    343 
    344 bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
    345     if (fOrigBitmap.width() == 0 || fOrigBitmap.height() == 0) {
    346         return false;
    347     }
    348 
    349     const SkMatrix* m;
    350     bool trivial_matrix = (inv.getType() & ~SkMatrix::kTranslate_Mask) == 0;
    351     bool clamp_clamp = SkShader::kClamp_TileMode == fTileModeX &&
    352                        SkShader::kClamp_TileMode == fTileModeY;
    353 
    354     if (clamp_clamp || trivial_matrix) {
    355         m = &inv;
    356     } else {
    357         fUnitInvMatrix = inv;
    358         fUnitInvMatrix.postIDiv(fOrigBitmap.width(), fOrigBitmap.height());
    359         m = &fUnitInvMatrix;
    360     }
    361 
    362     fBitmap = &fOrigBitmap;
    363     if (fOrigBitmap.hasMipMap()) {
    364         int shift = fOrigBitmap.extractMipLevel(&fMipBitmap,
    365                                                 SkScalarToFixed(m->getScaleX()),
    366                                                 SkScalarToFixed(m->getSkewY()));
    367 
    368         if (shift > 0) {
    369             if (m != &fUnitInvMatrix) {
    370                 fUnitInvMatrix = *m;
    371                 m = &fUnitInvMatrix;
    372             }
    373 
    374             SkScalar scale = SkFixedToScalar(SK_Fixed1 >> shift);
    375             fUnitInvMatrix.postScale(scale, scale);
    376 
    377             // now point here instead of fOrigBitmap
    378             fBitmap = &fMipBitmap;
    379         }
    380     }
    381 
    382     fInvMatrix      = m;
    383     fInvProc        = m->getMapXYProc();
    384     fInvType        = m->getType();
    385     fInvSx          = SkScalarToFixed(m->getScaleX());
    386     fInvKy          = SkScalarToFixed(m->getSkewY());
    387 
    388     fAlphaScale = SkAlpha255To256(paint.getAlpha());
    389 
    390     // pick-up filtering from the paint, but only if the matrix is
    391     // more complex than identity/translate (i.e. no need to pay the cost
    392     // of filtering if we're not scaled etc.).
    393     // note: we explicitly check inv, since m might be scaled due to unitinv
    394     //       trickery, but we don't want to see that for this test
    395     fDoFilter = paint.isFilterBitmap() &&
    396                 (inv.getType() > SkMatrix::kTranslate_Mask &&
    397                  valid_for_filtering(fBitmap->width() | fBitmap->height()));
    398 
    399     fShaderProc32 = NULL;
    400     fShaderProc16 = NULL;
    401     fSampleProc32 = NULL;
    402     fSampleProc16 = NULL;
    403 
    404     fMatrixProc = this->chooseMatrixProc(trivial_matrix);
    405     if (NULL == fMatrixProc) {
    406         return false;
    407     }
    408 
    409     ///////////////////////////////////////////////////////////////////////
    410 
    411     int index = 0;
    412     if (fAlphaScale < 256) {  // note: this distinction is not used for D16
    413         index |= 1;
    414     }
    415     if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
    416         index |= 2;
    417     }
    418     if (fDoFilter) {
    419         index |= 4;
    420     }
    421     // bits 3,4,5 encoding the source bitmap format
    422     switch (fBitmap->config()) {
    423         case SkBitmap::kARGB_8888_Config:
    424             index |= 0;
    425             break;
    426         case SkBitmap::kRGB_565_Config:
    427             index |= 8;
    428             break;
    429         case SkBitmap::kIndex8_Config:
    430             index |= 16;
    431             break;
    432         case SkBitmap::kARGB_4444_Config:
    433             index |= 24;
    434             break;
    435         case SkBitmap::kA8_Config:
    436             index |= 32;
    437             fPaintPMColor = SkPreMultiplyColor(paint.getColor());
    438             break;
    439         default:
    440             return false;
    441     }
    442 
    443     static const SampleProc32 gSample32[] = {
    444         S32_opaque_D32_nofilter_DXDY,
    445         S32_alpha_D32_nofilter_DXDY,
    446         S32_opaque_D32_nofilter_DX,
    447         S32_alpha_D32_nofilter_DX,
    448         S32_opaque_D32_filter_DXDY,
    449         S32_alpha_D32_filter_DXDY,
    450         S32_opaque_D32_filter_DX,
    451         S32_alpha_D32_filter_DX,
    452 
    453         S16_opaque_D32_nofilter_DXDY,
    454         S16_alpha_D32_nofilter_DXDY,
    455         S16_opaque_D32_nofilter_DX,
    456         S16_alpha_D32_nofilter_DX,
    457         S16_opaque_D32_filter_DXDY,
    458         S16_alpha_D32_filter_DXDY,
    459         S16_opaque_D32_filter_DX,
    460         S16_alpha_D32_filter_DX,
    461 
    462         SI8_opaque_D32_nofilter_DXDY,
    463         SI8_alpha_D32_nofilter_DXDY,
    464         SI8_opaque_D32_nofilter_DX,
    465         SI8_alpha_D32_nofilter_DX,
    466         SI8_opaque_D32_filter_DXDY,
    467         SI8_alpha_D32_filter_DXDY,
    468         SI8_opaque_D32_filter_DX,
    469         SI8_alpha_D32_filter_DX,
    470 
    471         S4444_opaque_D32_nofilter_DXDY,
    472         S4444_alpha_D32_nofilter_DXDY,
    473         S4444_opaque_D32_nofilter_DX,
    474         S4444_alpha_D32_nofilter_DX,
    475         S4444_opaque_D32_filter_DXDY,
    476         S4444_alpha_D32_filter_DXDY,
    477         S4444_opaque_D32_filter_DX,
    478         S4444_alpha_D32_filter_DX,
    479 
    480         // A8 treats alpha/opauqe the same (equally efficient)
    481         SA8_alpha_D32_nofilter_DXDY,
    482         SA8_alpha_D32_nofilter_DXDY,
    483         SA8_alpha_D32_nofilter_DX,
    484         SA8_alpha_D32_nofilter_DX,
    485         SA8_alpha_D32_filter_DXDY,
    486         SA8_alpha_D32_filter_DXDY,
    487         SA8_alpha_D32_filter_DX,
    488         SA8_alpha_D32_filter_DX
    489     };
    490 
    491     static const SampleProc16 gSample16[] = {
    492         S32_D16_nofilter_DXDY,
    493         S32_D16_nofilter_DX,
    494         S32_D16_filter_DXDY,
    495         S32_D16_filter_DX,
    496 
    497         S16_D16_nofilter_DXDY,
    498         S16_D16_nofilter_DX,
    499         S16_D16_filter_DXDY,
    500         S16_D16_filter_DX,
    501 
    502         SI8_D16_nofilter_DXDY,
    503         SI8_D16_nofilter_DX,
    504         SI8_D16_filter_DXDY,
    505         SI8_D16_filter_DX,
    506 
    507         // Don't support 4444 -> 565
    508         NULL, NULL, NULL, NULL,
    509         // Don't support A8 -> 565
    510         NULL, NULL, NULL, NULL
    511     };
    512 
    513     fSampleProc32 = gSample32[index];
    514     index >>= 1;    // shift away any opaque/alpha distinction
    515     fSampleProc16 = gSample16[index];
    516 
    517     // our special-case shaderprocs
    518     if (S16_D16_filter_DX == fSampleProc16) {
    519         if (clamp_clamp) {
    520             fShaderProc16 = Clamp_S16_D16_filter_DX_shaderproc;
    521         } else if (SkShader::kRepeat_TileMode == fTileModeX &&
    522                    SkShader::kRepeat_TileMode == fTileModeY) {
    523             fShaderProc16 = Repeat_S16_D16_filter_DX_shaderproc;
    524         }
    525     } else if (SI8_opaque_D32_filter_DX == fSampleProc32 && clamp_clamp) {
    526         fShaderProc32 = Clamp_SI8_opaque_D32_filter_DX_shaderproc;
    527     }
    528 
    529     // see if our platform has any accelerated overrides
    530     this->platformProcs();
    531     return true;
    532 }
    533 
    534 ///////////////////////////////////////////////////////////////////////////////
    535 /*
    536     The storage requirements for the different matrix procs are as follows,
    537     where each X or Y is 2 bytes, and N is the number of pixels/elements:
    538 
    539     scale/translate     nofilter      Y(4bytes) + N * X
    540     affine/perspective  nofilter      N * (X Y)
    541     scale/translate     filter        Y Y + N * (X X)
    542     affine/perspective  filter        N * (Y Y X X)
    543  */
    544 int SkBitmapProcState::maxCountForBufferSize(size_t bufferSize) const {
    545     int32_t size = static_cast<int32_t>(bufferSize);
    546     int perElemShift;
    547 
    548     size &= ~3; // only care about 4-byte aligned chunks
    549     if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
    550         size -= 4;   // the shared Y (or YY) coordinate
    551         if (size < 0) {
    552             size = 0;
    553         }
    554         perElemShift = fDoFilter ? 2 : 1;
    555     } else {
    556         perElemShift = fDoFilter ? 3 : 2;
    557     }
    558 
    559     return size >> perElemShift;
    560 }
    561 
    562