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