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