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