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