SkSwizzler.cpp revision 80803ff615e4293e8af2dc5d094a1f4fa81ec396
1/* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "SkCodecPriv.h" 9#include "SkColorPriv.h" 10#include "SkScaledCodec.h" 11#include "SkSwizzler.h" 12#include "SkTemplates.h" 13 14SkSwizzler::ResultAlpha SkSwizzler::GetResult(uint8_t zeroAlpha, 15 uint8_t maxAlpha) { 16 // In the transparent case, this returns 0x0000 17 // In the opaque case, this returns 0xFFFF 18 // If the row is neither transparent nor opaque, returns something else 19 return (((uint16_t) maxAlpha) << 8) | zeroAlpha; 20} 21 22// samples the row. Does not do anything else but sampling 23static SkSwizzler::ResultAlpha sample565(void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, 24 int width, int bpp, int deltaSrc, int offset, const SkPMColor ctable[]){ 25 26 src += offset; 27 uint16_t* SK_RESTRICT dst = (uint16_t*) dstRow; 28 for (int x = 0; x < width; x++) { 29 dst[x] = src[1] << 8 | src[0]; 30 src += deltaSrc; 31 } 32 // 565 is always opaque 33 return SkSwizzler::kOpaque_ResultAlpha; 34} 35 36// TODO (msarett): Investigate SIMD optimizations for swizzle routines. 37 38// kBit 39// These routines exclusively choose between white and black 40 41#define GRAYSCALE_BLACK 0 42#define GRAYSCALE_WHITE 0xFF 43 44 45// same as swizzle_bit_to_index and swizzle_bit_to_n32 except for value assigned to dst[x] 46static SkSwizzler::ResultAlpha swizzle_bit_to_grayscale( 47 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 48 int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) { 49 50 uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow; 51 52 // increment src by byte offset and bitIndex by bit offset 53 src += offset / 8; 54 int bitIndex = offset % 8; 55 uint8_t currByte = *src; 56 57 dst[0] = ((currByte >> (7-bitIndex)) & 1) ? GRAYSCALE_WHITE : GRAYSCALE_BLACK; 58 59 for (int x = 1; x < dstWidth; x++) { 60 int bitOffset = bitIndex + deltaSrc; 61 bitIndex = bitOffset % 8; 62 currByte = *(src += bitOffset / 8); 63 dst[x] = ((currByte >> (7-bitIndex)) & 1) ? GRAYSCALE_WHITE : GRAYSCALE_BLACK; 64 } 65 66 return SkSwizzler::kOpaque_ResultAlpha; 67} 68 69#undef GRAYSCALE_BLACK 70#undef GRAYSCALE_WHITE 71 72// same as swizzle_bit_to_grayscale and swizzle_bit_to_n32 except for value assigned to dst[x] 73static SkSwizzler::ResultAlpha swizzle_bit_to_index( 74 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 75 int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) { 76 uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow; 77 78 // increment src by byte offset and bitIndex by bit offset 79 src += offset / 8; 80 int bitIndex = offset % 8; 81 uint8_t currByte = *src; 82 83 dst[0] = ((currByte >> (7-bitIndex)) & 1); 84 85 for (int x = 1; x < dstWidth; x++) { 86 int bitOffset = bitIndex + deltaSrc; 87 bitIndex = bitOffset % 8; 88 currByte = *(src += bitOffset / 8); 89 dst[x] = ((currByte >> (7-bitIndex)) & 1); 90 } 91 92 return SkSwizzler::kOpaque_ResultAlpha; 93} 94 95// same as swizzle_bit_to_grayscale and swizzle_bit_to_index except for value assigned to dst[x] 96static SkSwizzler::ResultAlpha swizzle_bit_to_n32( 97 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 98 int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) { 99 SkPMColor* SK_RESTRICT dst = (SkPMColor*) dstRow; 100 101 // increment src by byte offset and bitIndex by bit offset 102 src += offset / 8; 103 int bitIndex = offset % 8; 104 uint8_t currByte = *src; 105 106 dst[0] = ((currByte >> (7 - bitIndex)) & 1) ? SK_ColorWHITE : SK_ColorBLACK; 107 108 for (int x = 1; x < dstWidth; x++) { 109 int bitOffset = bitIndex + deltaSrc; 110 bitIndex = bitOffset % 8; 111 currByte = *(src += bitOffset / 8); 112 dst[x] = ((currByte >> (7 - bitIndex)) & 1) ? SK_ColorWHITE : SK_ColorBLACK; 113 } 114 115 return SkSwizzler::kOpaque_ResultAlpha; 116} 117 118#define RGB565_BLACK 0 119#define RGB565_WHITE 0xFFFF 120 121static SkSwizzler::ResultAlpha swizzle_bit_to_565( 122 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 123 int bpp, int deltaSrc, int offset, const SkPMColor* /*ctable*/) { 124 uint16_t* SK_RESTRICT dst = (uint16_t*) dstRow; 125 126 // increment src by byte offset and bitIndex by bit offset 127 src += offset / 8; 128 int bitIndex = offset % 8; 129 uint8_t currByte = *src; 130 131 dst[0] = ((currByte >> (7 - bitIndex)) & 1) ? RGB565_WHITE : RGB565_BLACK; 132 133 for (int x = 1; x < dstWidth; x++) { 134 int bitOffset = bitIndex + deltaSrc; 135 bitIndex = bitOffset % 8; 136 currByte = *(src += bitOffset / 8); 137 dst[x] = ((currByte >> (7 - bitIndex)) & 1) ? RGB565_WHITE : RGB565_BLACK; 138 } 139 140 return SkSwizzler::kOpaque_ResultAlpha; 141} 142 143#undef RGB565_BLACK 144#undef RGB565_WHITE 145 146// kIndex1, kIndex2, kIndex4 147 148static SkSwizzler::ResultAlpha swizzle_small_index_to_index( 149 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 150 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 151 152 uint8_t* dst = (uint8_t*) dstRow; 153 INIT_RESULT_ALPHA; 154 src += offset / 8; 155 int bitIndex = offset % 8; 156 uint8_t currByte = *src; 157 const uint8_t mask = (1 << bpp) - 1; 158 uint8_t index = (currByte >> (8 - bpp - bitIndex)) & mask; 159 dst[0] = index; 160 UPDATE_RESULT_ALPHA(ctable[index] >> SK_A32_SHIFT); 161 162 for (int x = 1; x < dstWidth; x++) { 163 int bitOffset = bitIndex + deltaSrc; 164 bitIndex = bitOffset % 8; 165 currByte = *(src += bitOffset / 8); 166 index = (currByte >> (8 - bpp - bitIndex)) & mask; 167 dst[x] = index; 168 UPDATE_RESULT_ALPHA(ctable[index] >> SK_A32_SHIFT); 169 } 170 return COMPUTE_RESULT_ALPHA; 171} 172 173static SkSwizzler::ResultAlpha swizzle_small_index_to_565( 174 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 175 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 176 177 uint16_t* dst = (uint16_t*) dstRow; 178 src += offset / 8; 179 int bitIndex = offset % 8; 180 uint8_t currByte = *src; 181 const uint8_t mask = (1 << bpp) - 1; 182 uint8_t index = (currByte >> (8 - bpp - bitIndex)) & mask; 183 dst[0] = SkPixel32ToPixel16(ctable[index]); 184 185 for (int x = 1; x < dstWidth; x++) { 186 int bitOffset = bitIndex + deltaSrc; 187 bitIndex = bitOffset % 8; 188 currByte = *(src += bitOffset / 8); 189 index = (currByte >> (8 - bpp - bitIndex)) & mask; 190 dst[x] = SkPixel32ToPixel16(ctable[index]); 191 } 192 return SkAlphaType::kOpaque_SkAlphaType; 193} 194 195static SkSwizzler::ResultAlpha swizzle_small_index_to_n32( 196 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 197 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 198 199 SkPMColor* dst = (SkPMColor*) dstRow; 200 INIT_RESULT_ALPHA; 201 src += offset / 8; 202 int bitIndex = offset % 8; 203 uint8_t currByte = *src; 204 const uint8_t mask = (1 << bpp) - 1; 205 uint8_t index = (currByte >> (8 - bpp - bitIndex)) & mask; 206 dst[0] = ctable[index]; 207 UPDATE_RESULT_ALPHA(ctable[index] >> SK_A32_SHIFT); 208 209 for (int x = 1; x < dstWidth; x++) { 210 int bitOffset = bitIndex + deltaSrc; 211 bitIndex = bitOffset % 8; 212 currByte = *(src += bitOffset / 8); 213 index = (currByte >> (8 - bpp - bitIndex)) & mask; 214 dst[x] = ctable[index]; 215 UPDATE_RESULT_ALPHA(ctable[index] >> SK_A32_SHIFT); 216 } 217 return COMPUTE_RESULT_ALPHA; 218} 219 220// kIndex 221 222static SkSwizzler::ResultAlpha swizzle_index_to_index( 223 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 224 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 225 226 src += offset; 227 uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow; 228 INIT_RESULT_ALPHA; 229 // TODO (msarett): Should we skip the loop here and guess that the row is opaque/not opaque? 230 // SkScaledBitmap sampler just guesses that it is opaque. This is dangerous 231 // and probably wrong since gif and bmp (rarely) may have alpha. 232 if (1 == deltaSrc) { 233 memcpy(dst, src, dstWidth); 234 for (int x = 0; x < dstWidth; x++) { 235 UPDATE_RESULT_ALPHA(ctable[src[x]] >> SK_A32_SHIFT); 236 } 237 } else { 238 for (int x = 0; x < dstWidth; x++) { 239 dst[x] = *src; 240 UPDATE_RESULT_ALPHA(ctable[*src] >> SK_A32_SHIFT); 241 src += deltaSrc; 242 } 243 } 244 return COMPUTE_RESULT_ALPHA; 245} 246 247static SkSwizzler::ResultAlpha swizzle_index_to_n32( 248 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 249 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 250 251 src += offset; 252 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 253 INIT_RESULT_ALPHA; 254 for (int x = 0; x < dstWidth; x++) { 255 SkPMColor c = ctable[*src]; 256 UPDATE_RESULT_ALPHA(c >> SK_A32_SHIFT); 257 dst[x] = c; 258 src += deltaSrc; 259 } 260 return COMPUTE_RESULT_ALPHA; 261} 262 263static SkSwizzler::ResultAlpha swizzle_index_to_n32_skipZ( 264 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 265 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 266 267 src += offset; 268 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 269 INIT_RESULT_ALPHA; 270 for (int x = 0; x < dstWidth; x++) { 271 SkPMColor c = ctable[*src]; 272 UPDATE_RESULT_ALPHA(c >> SK_A32_SHIFT); 273 if (c != 0) { 274 dst[x] = c; 275 } 276 src += deltaSrc; 277 } 278 return COMPUTE_RESULT_ALPHA; 279} 280 281static SkSwizzler::ResultAlpha swizzle_index_to_565( 282 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 283 int bytesPerPixel, int deltaSrc, int offset, const SkPMColor ctable[]) { 284 // FIXME: Support dithering? Requires knowing y, which I think is a bigger 285 // change. 286 src += offset; 287 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; 288 for (int x = 0; x < dstWidth; x++) { 289 dst[x] = SkPixel32ToPixel16(ctable[*src]); 290 src += deltaSrc; 291 } 292 return SkSwizzler::kOpaque_ResultAlpha; 293} 294 295 296#undef A32_MASK_IN_PLACE 297 298// kGray 299 300static SkSwizzler::ResultAlpha swizzle_gray_to_n32( 301 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 302 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 303 304 src += offset; 305 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 306 for (int x = 0; x < dstWidth; x++) { 307 dst[x] = SkPackARGB32NoCheck(0xFF, *src, *src, *src); 308 src += deltaSrc; 309 } 310 return SkSwizzler::kOpaque_ResultAlpha; 311} 312 313static SkSwizzler::ResultAlpha swizzle_gray_to_gray( 314 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 315 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 316 317 src += offset; 318 uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow; 319 if (1 == deltaSrc) { 320 memcpy(dstRow, src, dstWidth); 321 } else { 322 for (int x = 0; x < dstWidth; x++) { 323 dst[x] = src[0]; 324 src += deltaSrc; 325 } 326 } 327 return SkSwizzler::kOpaque_ResultAlpha; 328} 329 330static SkSwizzler::ResultAlpha swizzle_gray_to_565( 331 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 332 int bytesPerPixel, int deltaSrc, int offset, const SkPMColor ctable[]) { 333 // FIXME: Support dithering? 334 src += offset; 335 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; 336 for (int x = 0; x < dstWidth; x++) { 337 dst[x] = SkPack888ToRGB16(src[0], src[0], src[0]); 338 src += deltaSrc; 339 } 340 return SkSwizzler::kOpaque_ResultAlpha; 341} 342 343// kBGRX 344 345static SkSwizzler::ResultAlpha swizzle_bgrx_to_n32( 346 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 347 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 348 349 src += offset; 350 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 351 for (int x = 0; x < dstWidth; x++) { 352 dst[x] = SkPackARGB32NoCheck(0xFF, src[2], src[1], src[0]); 353 src += deltaSrc; 354 } 355 return SkSwizzler::kOpaque_ResultAlpha; 356} 357 358static SkSwizzler::ResultAlpha swizzle_bgrx_to_565( 359 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 360 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 361 // FIXME: Support dithering? 362 src += offset; 363 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; 364 for (int x = 0; x < dstWidth; x++) { 365 dst[x] = SkPack888ToRGB16(src[2], src[1], src[0]); 366 src += deltaSrc; 367 } 368 return SkSwizzler::kOpaque_ResultAlpha; 369} 370 371// kBGRA 372 373static SkSwizzler::ResultAlpha swizzle_bgra_to_n32_unpremul( 374 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 375 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 376 377 src += offset; 378 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 379 INIT_RESULT_ALPHA; 380 for (int x = 0; x < dstWidth; x++) { 381 uint8_t alpha = src[3]; 382 UPDATE_RESULT_ALPHA(alpha); 383 dst[x] = SkPackARGB32NoCheck(alpha, src[2], src[1], src[0]); 384 src += deltaSrc; 385 } 386 return COMPUTE_RESULT_ALPHA; 387} 388 389static SkSwizzler::ResultAlpha swizzle_bgra_to_n32_premul( 390 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 391 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 392 393 src += offset; 394 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 395 INIT_RESULT_ALPHA; 396 for (int x = 0; x < dstWidth; x++) { 397 uint8_t alpha = src[3]; 398 UPDATE_RESULT_ALPHA(alpha); 399 dst[x] = SkPreMultiplyARGB(alpha, src[2], src[1], src[0]); 400 src += deltaSrc; 401 } 402 return COMPUTE_RESULT_ALPHA; 403} 404 405// kRGBX 406static SkSwizzler::ResultAlpha swizzle_rgbx_to_n32( 407 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 408 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 409 410 src += offset; 411 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 412 for (int x = 0; x < dstWidth; x++) { 413 dst[x] = SkPackARGB32(0xFF, src[0], src[1], src[2]); 414 src += deltaSrc; 415 } 416 return SkSwizzler::kOpaque_ResultAlpha; 417} 418 419static SkSwizzler::ResultAlpha swizzle_rgbx_to_565( 420 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 421 int bytesPerPixel, int deltaSrc, int offset, const SkPMColor ctable[]) { 422 // FIXME: Support dithering? 423 src += offset; 424 uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; 425 for (int x = 0; x < dstWidth; x++) { 426 dst[x] = SkPack888ToRGB16(src[0], src[1], src[2]); 427 src += deltaSrc; 428 } 429 return SkSwizzler::kOpaque_ResultAlpha; 430} 431 432 433// kRGBA 434static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_premul( 435 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 436 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 437 438 src += offset; 439 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 440 INIT_RESULT_ALPHA; 441 for (int x = 0; x < dstWidth; x++) { 442 unsigned alpha = src[3]; 443 UPDATE_RESULT_ALPHA(alpha); 444 dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); 445 src += deltaSrc; 446 } 447 return COMPUTE_RESULT_ALPHA; 448} 449 450static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_unpremul( 451 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 452 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 453 454 src += offset; 455 uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow); 456 INIT_RESULT_ALPHA; 457 for (int x = 0; x < dstWidth; x++) { 458 unsigned alpha = src[3]; 459 UPDATE_RESULT_ALPHA(alpha); 460 dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]); 461 src += deltaSrc; 462 } 463 return COMPUTE_RESULT_ALPHA; 464} 465 466static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_premul_skipZ( 467 void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, 468 int bpp, int deltaSrc, int offset, const SkPMColor ctable[]) { 469 470 src += offset; 471 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 472 INIT_RESULT_ALPHA; 473 for (int x = 0; x < dstWidth; x++) { 474 unsigned alpha = src[3]; 475 UPDATE_RESULT_ALPHA(alpha); 476 if (0 != alpha) { 477 dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); 478 } 479 src += deltaSrc; 480 } 481 return COMPUTE_RESULT_ALPHA; 482} 483 484/** 485 FIXME: This was my idea to cheat in order to continue taking advantage of skipping zeroes. 486 This would be fine for drawing normally, but not for drawing with transfer modes. Being 487 honest means we can draw correctly with transfer modes, with the cost of not being able 488 to take advantage of Android's free unwritten pages. Something to keep in mind when we 489 decide whether to switch to unpremul default. 490static bool swizzle_rgba_to_n32_unpremul_skipZ(void* SK_RESTRICT dstRow, 491 const uint8_t* SK_RESTRICT src, 492 int dstWidth, int bitsPerPixel, int offset, 493 const SkPMColor[]) { 494 src += offset; 495 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 496 unsigned alphaMask = 0xFF; 497 for (int x = 0; x < dstWidth; x++) { 498 unsigned alpha = src[3]; 499 // NOTE: We cheat here. The caller requested unpremul and skip zeroes. It's possible 500 // the color components are not zero, but we skip them anyway, meaning they'll remain 501 // zero (implied by the request to skip zeroes). 502 if (0 != alpha) { 503 dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]); 504 } 505 src += deltaSrc; 506 alphaMask &= alpha; 507 } 508 return alphaMask != 0xFF; 509} 510*/ 511 512SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, 513 const SkPMColor* ctable, 514 const SkImageInfo& dstInfo, 515 const SkCodec::Options& options) { 516 if (dstInfo.colorType() == kUnknown_SkColorType || kUnknown == sc) { 517 return nullptr; 518 } 519 if ((kIndex == sc || kIndex4 == sc || kIndex2 == sc || kIndex1 == sc) 520 && nullptr == ctable) { 521 return nullptr; 522 } 523 RowProc proc = nullptr; 524 SkCodec::ZeroInitialized zeroInit = options.fZeroInitialized; 525 switch (sc) { 526 case kBit: 527 switch (dstInfo.colorType()) { 528 case kN32_SkColorType: 529 proc = &swizzle_bit_to_n32; 530 break; 531 case kIndex_8_SkColorType: 532 proc = &swizzle_bit_to_index; 533 break; 534 case kRGB_565_SkColorType: 535 proc = &swizzle_bit_to_565; 536 break; 537 case kGray_8_SkColorType: 538 proc = &swizzle_bit_to_grayscale; 539 break; 540 default: 541 break; 542 } 543 break; 544 case kIndex1: 545 case kIndex2: 546 case kIndex4: 547 switch (dstInfo.colorType()) { 548 case kN32_SkColorType: 549 proc = &swizzle_small_index_to_n32; 550 break; 551 case kRGB_565_SkColorType: 552 proc = &swizzle_small_index_to_565; 553 break; 554 case kIndex_8_SkColorType: 555 proc = &swizzle_small_index_to_index; 556 break; 557 default: 558 break; 559 } 560 break; 561 case kIndex: 562 switch (dstInfo.colorType()) { 563 case kN32_SkColorType: 564 // We assume the color premultiplied ctable (or not) as desired. 565 if (SkCodec::kYes_ZeroInitialized == zeroInit) { 566 proc = &swizzle_index_to_n32_skipZ; 567 break; 568 } else { 569 proc = &swizzle_index_to_n32; 570 break; 571 } 572 break; 573 case kRGB_565_SkColorType: 574 proc = &swizzle_index_to_565; 575 break; 576 case kIndex_8_SkColorType: 577 proc = &swizzle_index_to_index; 578 break; 579 default: 580 break; 581 } 582 break; 583 case kGray: 584 switch (dstInfo.colorType()) { 585 case kN32_SkColorType: 586 proc = &swizzle_gray_to_n32; 587 break; 588 case kGray_8_SkColorType: 589 proc = &swizzle_gray_to_gray; 590 break; 591 case kRGB_565_SkColorType: 592 proc = &swizzle_gray_to_565; 593 break; 594 default: 595 break; 596 } 597 break; 598 case kBGR: 599 case kBGRX: 600 switch (dstInfo.colorType()) { 601 case kN32_SkColorType: 602 proc = &swizzle_bgrx_to_n32; 603 break; 604 case kRGB_565_SkColorType: 605 proc = &swizzle_bgrx_to_565; 606 break; 607 default: 608 break; 609 } 610 break; 611 case kBGRA: 612 switch (dstInfo.colorType()) { 613 case kN32_SkColorType: 614 switch (dstInfo.alphaType()) { 615 case kUnpremul_SkAlphaType: 616 proc = &swizzle_bgra_to_n32_unpremul; 617 break; 618 case kPremul_SkAlphaType: 619 proc = &swizzle_bgra_to_n32_premul; 620 break; 621 default: 622 break; 623 } 624 break; 625 default: 626 break; 627 } 628 break; 629 case kRGBX: 630 // TODO: Support other swizzles. 631 switch (dstInfo.colorType()) { 632 case kN32_SkColorType: 633 proc = &swizzle_rgbx_to_n32; 634 break; 635 case kRGB_565_SkColorType: 636 proc = &swizzle_rgbx_to_565; 637 default: 638 break; 639 } 640 break; 641 case kRGBA: 642 switch (dstInfo.colorType()) { 643 case kN32_SkColorType: 644 if (dstInfo.alphaType() == kUnpremul_SkAlphaType) { 645 // Respect zeroInit? 646 proc = &swizzle_rgba_to_n32_unpremul; 647 } else { 648 if (SkCodec::kYes_ZeroInitialized == zeroInit) { 649 proc = &swizzle_rgba_to_n32_premul_skipZ; 650 } else { 651 proc = &swizzle_rgba_to_n32_premul; 652 } 653 } 654 break; 655 default: 656 break; 657 } 658 break; 659 case kRGB: 660 switch (dstInfo.colorType()) { 661 case kN32_SkColorType: 662 proc = &swizzle_rgbx_to_n32; 663 break; 664 default: 665 break; 666 } 667 break; 668 case kRGB_565: 669 switch (dstInfo.colorType()) { 670 case kRGB_565_SkColorType: 671 proc = &sample565; 672 break; 673 default: 674 break; 675 } 676 default: 677 break; 678 } 679 if (nullptr == proc) { 680 return nullptr; 681 } 682 683 // Store bpp in bytes if it is an even multiple, otherwise use bits 684 int bpp = SkIsAlign8(BitsPerPixel(sc)) ? BytesPerPixel(sc) : BitsPerPixel(sc); 685 686 int srcOffset = 0; 687 int srcWidth = dstInfo.width(); 688 if (options.fSubset) { 689 srcOffset = options.fSubset->left(); 690 srcWidth = options.fSubset->width(); 691 } 692 693 return new SkSwizzler(proc, ctable, srcOffset, srcWidth, bpp); 694} 695 696SkSwizzler::SkSwizzler(RowProc proc, const SkPMColor* ctable, int srcOffset, int subsetWidth, 697 int bpp) 698 : fRowProc(proc) 699 , fColorTable(ctable) 700 , fSrcOffset(srcOffset) 701 , fX0(srcOffset) 702 , fSubsetWidth(subsetWidth) 703 , fDstWidth(subsetWidth) 704 , fSampleX(1) 705 , fBPP(bpp) 706{} 707 708int SkSwizzler::onSetSampleX(int sampleX) { 709 SkASSERT(sampleX > 0); // Surely there is an upper limit? Should there be 710 // way to report failure? 711 fSampleX = sampleX; 712 fX0 = get_start_coord(sampleX) + fSrcOffset; 713 fDstWidth = get_scaled_dimension(fSubsetWidth, sampleX); 714 715 // check that fX0 is valid 716 SkASSERT(fX0 >= 0); 717 return fDstWidth; 718} 719 720SkSwizzler::ResultAlpha SkSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRICT src) { 721 SkASSERT(nullptr != dst && nullptr != src); 722 return fRowProc(dst, src, fDstWidth, fBPP, fSampleX * fBPP, fX0 * fBPP, fColorTable); 723} 724