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