SkBlitter_ARGB32.cpp revision e74e28df11abbe069d82221ee029d281a81ea328
1/* libs/graphics/sgl/SkBlitter_ARGB32.cpp 2** 3** Copyright 2006, The Android Open Source Project 4** 5** Licensed under the Apache License, Version 2.0 (the "License"); 6** you may not use this file except in compliance with the License. 7** You may obtain a copy of the License at 8** 9** http://www.apache.org/licenses/LICENSE-2.0 10** 11** Unless required by applicable law or agreed to in writing, software 12** distributed under the License is distributed on an "AS IS" BASIS, 13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14** See the License for the specific language governing permissions and 15** limitations under the License. 16*/ 17 18#include "SkCoreBlitters.h" 19#include "SkColorPriv.h" 20#include "SkShader.h" 21#include "SkUtils.h" 22#include "SkXfermode.h" 23 24/////////////////////////////////////////////////////////////////////////////// 25 26static inline int upscale31To32(int value) { 27 SkASSERT((unsigned)value <= 31); 28 return value + (value >> 4); 29} 30 31static inline int blend32(int src, int dst, int scale) { 32 SkASSERT((unsigned)src <= 0xFF); 33 SkASSERT((unsigned)dst <= 0xFF); 34 SkASSERT((unsigned)scale <= 32); 35 return dst + ((src - dst) * scale >> 5); 36} 37 38static void blit_lcd16_opaque(SkPMColor dst[], const uint16_t src[], 39 SkPMColor color, int width) { 40 int srcR = SkGetPackedR32(color); 41 int srcG = SkGetPackedG32(color); 42 int srcB = SkGetPackedB32(color); 43 44 for (int i = 0; i < width; i++) { 45 uint16_t mask = src[i]; 46 if (0 == mask) { 47 continue; 48 } 49 50 SkPMColor d = dst[i]; 51 52 /* We want all of these in 5bits, hence the shifts in case one of them 53 * (green) is 6bits. 54 */ 55 int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5); 56 int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5); 57 int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5); 58 59 // Now upscale them to 0..256, so we can use SkAlphaBlend 60 maskR = upscale31To32(maskR); 61 maskG = upscale31To32(maskG); 62 maskB = upscale31To32(maskB); 63 64 int maskA = SkMax32(SkMax32(maskR, maskG), maskB); 65 66 int dstA = SkGetPackedA32(d); 67 int dstR = SkGetPackedR32(d); 68 int dstG = SkGetPackedG32(d); 69 int dstB = SkGetPackedB32(d); 70 71 dst[i] = SkPackARGB32(blend32(0xFF, dstA, maskA), 72 blend32(srcR, dstR, maskR), 73 blend32(srcG, dstG, maskG), 74 blend32(srcB, dstB, maskB)); 75 } 76} 77 78static void blit_lcd32_opaque(SkPMColor dst[], const uint32_t src[], 79 SkPMColor color, int width) { 80 int srcR = SkGetPackedR32(color); 81 int srcG = SkGetPackedG32(color); 82 int srcB = SkGetPackedB32(color); 83 84 for (int i = 0; i < width; i++) { 85 uint32_t mask = src[i]; 86 if (0 == mask) { 87 continue; 88 } 89 90 SkPMColor d = dst[i]; 91 92 int maskR = SkGetPackedR32(mask); 93 int maskG = SkGetPackedG32(mask); 94 int maskB = SkGetPackedB32(mask); 95 96 // Now upscale them to 0..256, so we can use SkAlphaBlend 97 maskR = SkAlpha255To256(maskR); 98 maskG = SkAlpha255To256(maskG); 99 maskB = SkAlpha255To256(maskB); 100 101 int maskA = SkMax32(SkMax32(maskR, maskG), maskB); 102 103 int dstA = SkGetPackedA32(d); 104 int dstR = SkGetPackedR32(d); 105 int dstG = SkGetPackedG32(d); 106 int dstB = SkGetPackedB32(d); 107 108 dst[i] = SkPackARGB32(SkAlphaBlend(0xFF, dstA, maskA), 109 SkAlphaBlend(srcR, dstR, maskR), 110 SkAlphaBlend(srcG, dstG, maskG), 111 SkAlphaBlend(srcB, dstB, maskB)); 112 } 113} 114 115static void blitmask_lcd16(const SkBitmap& device, const SkMask& mask, 116 const SkIRect& clip, SkPMColor srcColor) { 117 int x = clip.fLeft; 118 int y = clip.fTop; 119 int width = clip.width(); 120 int height = clip.height(); 121 122 SkPMColor* dstRow = device.getAddr32(x, y); 123 const uint16_t* srcRow = mask.getAddrLCD16(x, y); 124 125 do { 126 blit_lcd16_opaque(dstRow, srcRow, srcColor, width); 127 dstRow = (SkPMColor*)((char*)dstRow + device.rowBytes()); 128 srcRow = (const uint16_t*)((const char*)srcRow + mask.fRowBytes); 129 } while (--height != 0); 130} 131 132static void blitmask_lcd32(const SkBitmap& device, const SkMask& mask, 133 const SkIRect& clip, SkPMColor srcColor) { 134 int x = clip.fLeft; 135 int y = clip.fTop; 136 int width = clip.width(); 137 int height = clip.height(); 138 139 SkPMColor* dstRow = device.getAddr32(x, y); 140 const uint32_t* srcRow = mask.getAddrLCD32(x, y); 141 142 do { 143 blit_lcd32_opaque(dstRow, srcRow, srcColor, width); 144 dstRow = (SkPMColor*)((char*)dstRow + device.rowBytes()); 145 srcRow = (const uint32_t*)((const char*)srcRow + mask.fRowBytes); 146 } while (--height != 0); 147} 148 149////////////////////////////////////////////////////////////////////////////////////// 150 151static void SkARGB32_Blit32(const SkBitmap& device, const SkMask& mask, 152 const SkIRect& clip, SkPMColor srcColor) { 153 U8CPU alpha = SkGetPackedA32(srcColor); 154 unsigned flags = SkBlitRow::kSrcPixelAlpha_Flag32; 155 if (alpha != 255) { 156 flags |= SkBlitRow::kGlobalAlpha_Flag32; 157 } 158 SkBlitRow::Proc32 proc = SkBlitRow::Factory32(flags); 159 160 int x = clip.fLeft; 161 int y = clip.fTop; 162 int width = clip.width(); 163 int height = clip.height(); 164 165 SkPMColor* dstRow = device.getAddr32(x, y); 166 const SkPMColor* srcRow = reinterpret_cast<const SkPMColor*>(mask.getAddr(x, y)); 167 168 do { 169 proc(dstRow, srcRow, width, alpha); 170 dstRow = (SkPMColor*)((char*)dstRow + device.rowBytes()); 171 srcRow = (const SkPMColor*)((const char*)srcRow + mask.fRowBytes); 172 } while (--height != 0); 173} 174 175////////////////////////////////////////////////////////////////////////////////////// 176 177SkARGB32_Blitter::SkARGB32_Blitter(const SkBitmap& device, const SkPaint& paint) 178 : INHERITED(device) { 179 SkColor color = paint.getColor(); 180 fColor = color; 181 182 fSrcA = SkColorGetA(color); 183 unsigned scale = SkAlpha255To256(fSrcA); 184 fSrcR = SkAlphaMul(SkColorGetR(color), scale); 185 fSrcG = SkAlphaMul(SkColorGetG(color), scale); 186 fSrcB = SkAlphaMul(SkColorGetB(color), scale); 187 188 fPMColor = SkPackARGB32(fSrcA, fSrcR, fSrcG, fSrcB); 189 fColor32Proc = SkBlitRow::ColorProcFactory(); 190 191 // init the pro for blitmask 192 fBlitMaskProc = SkBlitMask::Factory(SkBitmap::kARGB_8888_Config, color); 193} 194 195const SkBitmap* SkARGB32_Blitter::justAnOpaqueColor(uint32_t* value) { 196 if (255 == fSrcA) { 197 *value = fPMColor; 198 return &fDevice; 199 } 200 return NULL; 201} 202 203#if defined _WIN32 && _MSC_VER >= 1300 // disable warning : local variable used without having been initialized 204#pragma warning ( push ) 205#pragma warning ( disable : 4701 ) 206#endif 207 208void SkARGB32_Blitter::blitH(int x, int y, int width) { 209 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width()); 210 211 uint32_t* device = fDevice.getAddr32(x, y); 212 fColor32Proc(device, device, width, fPMColor); 213} 214 215void SkARGB32_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], 216 const int16_t runs[]) { 217 if (fSrcA == 0) { 218 return; 219 } 220 221 uint32_t color = fPMColor; 222 uint32_t* device = fDevice.getAddr32(x, y); 223 unsigned opaqueMask = fSrcA; // if fSrcA is 0xFF, then we will catch the fast opaque case 224 225 for (;;) { 226 int count = runs[0]; 227 SkASSERT(count >= 0); 228 if (count <= 0) { 229 return; 230 } 231 unsigned aa = antialias[0]; 232 if (aa) { 233 if ((opaqueMask & aa) == 255) { 234 sk_memset32(device, color, count); 235 } else { 236 uint32_t sc = SkAlphaMulQ(color, SkAlpha255To256(aa)); 237 fColor32Proc(device, device, count, sc); 238 } 239 } 240 runs += count; 241 antialias += count; 242 device += count; 243 } 244} 245 246////////////////////////////////////////////////////////////////////////////////////// 247 248#define solid_8_pixels(mask, dst, color) \ 249 do { \ 250 if (mask & 0x80) dst[0] = color; \ 251 if (mask & 0x40) dst[1] = color; \ 252 if (mask & 0x20) dst[2] = color; \ 253 if (mask & 0x10) dst[3] = color; \ 254 if (mask & 0x08) dst[4] = color; \ 255 if (mask & 0x04) dst[5] = color; \ 256 if (mask & 0x02) dst[6] = color; \ 257 if (mask & 0x01) dst[7] = color; \ 258 } while (0) 259 260#define SK_BLITBWMASK_NAME SkARGB32_BlitBW 261#define SK_BLITBWMASK_ARGS , SkPMColor color 262#define SK_BLITBWMASK_BLIT8(mask, dst) solid_8_pixels(mask, dst, color) 263#define SK_BLITBWMASK_GETADDR getAddr32 264#define SK_BLITBWMASK_DEVTYPE uint32_t 265#include "SkBlitBWMaskTemplate.h" 266 267#define blend_8_pixels(mask, dst, sc, dst_scale) \ 268 do { \ 269 if (mask & 0x80) { dst[0] = sc + SkAlphaMulQ(dst[0], dst_scale); } \ 270 if (mask & 0x40) { dst[1] = sc + SkAlphaMulQ(dst[1], dst_scale); } \ 271 if (mask & 0x20) { dst[2] = sc + SkAlphaMulQ(dst[2], dst_scale); } \ 272 if (mask & 0x10) { dst[3] = sc + SkAlphaMulQ(dst[3], dst_scale); } \ 273 if (mask & 0x08) { dst[4] = sc + SkAlphaMulQ(dst[4], dst_scale); } \ 274 if (mask & 0x04) { dst[5] = sc + SkAlphaMulQ(dst[5], dst_scale); } \ 275 if (mask & 0x02) { dst[6] = sc + SkAlphaMulQ(dst[6], dst_scale); } \ 276 if (mask & 0x01) { dst[7] = sc + SkAlphaMulQ(dst[7], dst_scale); } \ 277 } while (0) 278 279#define SK_BLITBWMASK_NAME SkARGB32_BlendBW 280#define SK_BLITBWMASK_ARGS , uint32_t sc, unsigned dst_scale 281#define SK_BLITBWMASK_BLIT8(mask, dst) blend_8_pixels(mask, dst, sc, dst_scale) 282#define SK_BLITBWMASK_GETADDR getAddr32 283#define SK_BLITBWMASK_DEVTYPE uint32_t 284#include "SkBlitBWMaskTemplate.h" 285 286void SkARGB32_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { 287 SkASSERT(mask.fBounds.contains(clip)); 288 SkASSERT(fSrcA != 0xFF); 289 290 if (fSrcA == 0) { 291 return; 292 } 293 294 if (mask.fFormat == SkMask::kBW_Format) { 295 SkARGB32_BlendBW(fDevice, mask, clip, fPMColor, SkAlpha255To256(255 - fSrcA)); 296 return; 297 } else if (SkMask::kARGB32_Format == mask.fFormat) { 298 SkARGB32_Blit32(fDevice, mask, clip, fPMColor); 299 return; 300 } else if (SkMask::kLCD16_Format == mask.fFormat) { 301 blitmask_lcd16(fDevice, mask, clip, fPMColor); 302 return; 303 } else if (SkMask::kLCD32_Format == mask.fFormat) { 304 blitmask_lcd32(fDevice, mask, clip, fPMColor); 305 return; 306 } 307 308 int x = clip.fLeft; 309 int y = clip.fTop; 310 311 fBlitMaskProc(fDevice.getAddr32(x, y), fDevice.rowBytes(), 312 SkBitmap::kARGB_8888_Config, 313 mask.getAddr(x, y), mask.fRowBytes, 314 fColor, clip.width(), clip.height()); 315} 316 317void SkARGB32_Opaque_Blitter::blitMask(const SkMask& mask, 318 const SkIRect& clip) { 319 SkASSERT(mask.fBounds.contains(clip)); 320 321 if (mask.fFormat == SkMask::kBW_Format) { 322 SkARGB32_BlitBW(fDevice, mask, clip, fPMColor); 323 return; 324 } else if (SkMask::kARGB32_Format == mask.fFormat) { 325 SkARGB32_Blit32(fDevice, mask, clip, fPMColor); 326 return; 327 } else if (SkMask::kLCD16_Format == mask.fFormat) { 328 blitmask_lcd16(fDevice, mask, clip, fPMColor); 329 return; 330 } else if (SkMask::kLCD32_Format == mask.fFormat) { 331 blitmask_lcd32(fDevice, mask, clip, fPMColor); 332 return; 333 } 334 335 int x = clip.fLeft; 336 int y = clip.fTop; 337 int width = clip.width(); 338 int height = clip.height(); 339 340 fBlitMaskProc(fDevice.getAddr32(x, y), fDevice.rowBytes(), 341 SkBitmap::kARGB_8888_Config, 342 mask.getAddr(x, y), mask.fRowBytes, fColor, width, height); 343} 344 345////////////////////////////////////////////////////////////////////////////////////// 346 347void SkARGB32_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { 348 if (alpha == 0 || fSrcA == 0) { 349 return; 350 } 351 352 uint32_t* device = fDevice.getAddr32(x, y); 353 uint32_t color = fPMColor; 354 355 if (alpha != 255) { 356 color = SkAlphaMulQ(color, SkAlpha255To256(alpha)); 357 } 358 359 unsigned dst_scale = 255 - SkGetPackedA32(color); 360 uint32_t prevDst = ~device[0]; 361 uint32_t result SK_INIT_TO_AVOID_WARNING; 362 uint32_t rowBytes = fDevice.rowBytes(); 363 364 while (--height >= 0) { 365 uint32_t dst = device[0]; 366 if (dst != prevDst) { 367 result = color + SkAlphaMulQ(dst, dst_scale); 368 prevDst = dst; 369 } 370 device[0] = result; 371 device = (uint32_t*)((char*)device + rowBytes); 372 } 373} 374 375void SkARGB32_Blitter::blitRect(int x, int y, int width, int height) { 376 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width() && y + height <= fDevice.height()); 377 378 if (fSrcA == 0) { 379 return; 380 } 381 382 uint32_t* device = fDevice.getAddr32(x, y); 383 uint32_t color = fPMColor; 384 size_t rowBytes = fDevice.rowBytes(); 385 386 while (--height >= 0) { 387 fColor32Proc(device, device, width, color); 388 device = (uint32_t*)((char*)device + rowBytes); 389 } 390} 391 392#if defined _WIN32 && _MSC_VER >= 1300 393#pragma warning ( pop ) 394#endif 395 396/////////////////////////////////////////////////////////////////////// 397 398void SkARGB32_Black_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { 399 SkASSERT(mask.fBounds.contains(clip)); 400 SkPMColor black = (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT); 401 402 if (mask.fFormat == SkMask::kBW_Format) { 403 SkARGB32_BlitBW(fDevice, mask, clip, black); 404 } else if (SkMask::kARGB32_Format == mask.fFormat) { 405 SkARGB32_Blit32(fDevice, mask, clip, fPMColor); 406 } else if (SkMask::kLCD16_Format == mask.fFormat) { 407 blitmask_lcd16(fDevice, mask, clip, fPMColor); 408 } else if (SkMask::kLCD32_Format == mask.fFormat) { 409 blitmask_lcd32(fDevice, mask, clip, fPMColor); 410 } else { 411 fBlitMaskProc(fDevice.getAddr32(clip.fLeft, clip.fTop), 412 fDevice.rowBytes(), 413 SkBitmap::kARGB_8888_Config, 414 mask.getAddr(clip.fLeft, clip.fTop), mask.fRowBytes, 415 black, clip.width(), clip.height()); 416 } 417} 418 419void SkARGB32_Black_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], 420 const int16_t runs[]) { 421 uint32_t* device = fDevice.getAddr32(x, y); 422 SkPMColor black = (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT); 423 424 for (;;) { 425 int count = runs[0]; 426 SkASSERT(count >= 0); 427 if (count <= 0) { 428 return; 429 } 430 unsigned aa = antialias[0]; 431 if (aa) { 432 if (aa == 255) { 433 sk_memset32(device, black, count); 434 } else { 435 SkPMColor src = aa << SK_A32_SHIFT; 436 unsigned dst_scale = 256 - aa; 437 int n = count; 438 do { 439 --n; 440 device[n] = src + SkAlphaMulQ(device[n], dst_scale); 441 } while (n > 0); 442 } 443 } 444 runs += count; 445 antialias += count; 446 device += count; 447 } 448} 449 450////////////////////////////////////////////////////////////////////////////////////////// 451 452SkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkBitmap& device, 453 const SkPaint& paint) : INHERITED(device, paint) { 454 fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor))); 455 456 fXfermode = paint.getXfermode(); 457 SkSafeRef(fXfermode); 458 459 int flags = 0; 460 if (!(fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) { 461 flags |= SkBlitRow::kSrcPixelAlpha_Flag32; 462 } 463 // we call this on the output from the shader 464 fProc32 = SkBlitRow::Factory32(flags); 465 // we call this on the output from the shader + alpha from the aa buffer 466 fProc32Blend = SkBlitRow::Factory32(flags | SkBlitRow::kGlobalAlpha_Flag32); 467} 468 469SkARGB32_Shader_Blitter::~SkARGB32_Shader_Blitter() { 470 SkSafeUnref(fXfermode); 471 sk_free(fBuffer); 472} 473 474void SkARGB32_Shader_Blitter::blitH(int x, int y, int width) { 475 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width()); 476 477 uint32_t* device = fDevice.getAddr32(x, y); 478 479 if (fXfermode == NULL && (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) { 480 fShader->shadeSpan(x, y, device, width); 481 } else { 482 SkPMColor* span = fBuffer; 483 fShader->shadeSpan(x, y, span, width); 484 if (fXfermode) { 485 fXfermode->xfer32(device, span, width, NULL); 486 } else { 487 fProc32(device, span, width, 255); 488 } 489 } 490} 491 492/////////////////////////////////////////////////////////////////////////////////////////////// 493 494void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], 495 const int16_t runs[]) { 496 SkPMColor* span = fBuffer; 497 uint32_t* device = fDevice.getAddr32(x, y); 498 SkShader* shader = fShader; 499 500 if (fXfermode) { 501 for (;;) { 502 SkXfermode* xfer = fXfermode; 503 504 int count = *runs; 505 if (count <= 0) 506 break; 507 int aa = *antialias; 508 if (aa) { 509 shader->shadeSpan(x, y, span, count); 510 if (aa == 255) { 511 xfer->xfer32(device, span, count, NULL); 512 } else { 513 // count is almost always 1 514 for (int i = count - 1; i >= 0; --i) { 515 xfer->xfer32(&device[i], &span[i], 1, antialias); 516 } 517 } 518 } 519 device += count; 520 runs += count; 521 antialias += count; 522 x += count; 523 } 524 } else if (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) { 525 for (;;) { 526 int count = *runs; 527 if (count <= 0) { 528 break; 529 } 530 int aa = *antialias; 531 if (aa) { 532 if (aa == 255) { 533 // cool, have the shader draw right into the device 534 shader->shadeSpan(x, y, device, count); 535 } else { 536 shader->shadeSpan(x, y, span, count); 537 fProc32Blend(device, span, count, aa); 538 } 539 } 540 device += count; 541 runs += count; 542 antialias += count; 543 x += count; 544 } 545 } else { // no xfermode but the shader not opaque 546 for (;;) { 547 int count = *runs; 548 if (count <= 0) { 549 break; 550 } 551 int aa = *antialias; 552 if (aa) { 553 fShader->shadeSpan(x, y, span, count); 554 if (aa == 255) { 555 fProc32(device, span, count, 255); 556 } else { 557 fProc32Blend(device, span, count, aa); 558 } 559 } 560 device += count; 561 runs += count; 562 antialias += count; 563 x += count; 564 } 565 } 566} 567