SkBlitter_RGB16.cpp revision 8a1c16ff38322f0210116fa7293eb8817c7e477e
1/* libs/graphics/sgl/SkBlitter_RGB16.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 "SkBlitRow.h" 19#include "SkCoreBlitters.h" 20#include "SkColorPriv.h" 21#include "SkDither.h" 22#include "SkShader.h" 23#include "SkUtils.h" 24#include "SkXfermode.h" 25 26void sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other, 27 int count) { 28 if (count > 0) { 29 // see if we need to write one short before we can cast to an 4byte ptr 30 // (we do this subtract rather than (unsigned)dst so we don't get warnings 31 // on 64bit machines) 32 if (((char*)dst - (char*)0) & 2) { 33 *dst++ = value; 34 count -= 1; 35 SkTSwap(value, other); 36 } 37 38 // fast way to set [value,other] pairs 39#ifdef SK_CPU_BENDIAN 40 sk_memset32((uint32_t*)dst, (value << 16) | other, count >> 1); 41#else 42 sk_memset32((uint32_t*)dst, (other << 16) | value, count >> 1); 43#endif 44 45 if (count & 1) { 46 dst[count - 1] = value; 47 } 48 } 49} 50 51/////////////////////////////////////////////////////////////////////////////// 52 53SkRGB16_Black_Blitter::SkRGB16_Black_Blitter(const SkBitmap& device, const SkPaint& paint) 54 : SkRGB16_Blitter(device, paint) { 55 SkASSERT(paint.getShader() == NULL); 56 SkASSERT(paint.getColorFilter() == NULL); 57 SkASSERT(paint.getXfermode() == NULL); 58 SkASSERT(paint.getColor() == SK_ColorBLACK); 59} 60 61#if 1 62#define black_8_pixels(mask, dst) \ 63 do { \ 64 if (mask & 0x80) dst[0] = 0; \ 65 if (mask & 0x40) dst[1] = 0; \ 66 if (mask & 0x20) dst[2] = 0; \ 67 if (mask & 0x10) dst[3] = 0; \ 68 if (mask & 0x08) dst[4] = 0; \ 69 if (mask & 0x04) dst[5] = 0; \ 70 if (mask & 0x02) dst[6] = 0; \ 71 if (mask & 0x01) dst[7] = 0; \ 72 } while (0) 73#else 74static inline black_8_pixels(U8CPU mask, uint16_t dst[]) 75{ 76 if (mask & 0x80) dst[0] = 0; 77 if (mask & 0x40) dst[1] = 0; 78 if (mask & 0x20) dst[2] = 0; 79 if (mask & 0x10) dst[3] = 0; 80 if (mask & 0x08) dst[4] = 0; 81 if (mask & 0x04) dst[5] = 0; 82 if (mask & 0x02) dst[6] = 0; 83 if (mask & 0x01) dst[7] = 0; 84} 85#endif 86 87#define SK_BLITBWMASK_NAME SkRGB16_Black_BlitBW 88#define SK_BLITBWMASK_ARGS 89#define SK_BLITBWMASK_BLIT8(mask, dst) black_8_pixels(mask, dst) 90#define SK_BLITBWMASK_GETADDR getAddr16 91#define SK_BLITBWMASK_DEVTYPE uint16_t 92#include "SkBlitBWMaskTemplate.h" 93 94void SkRGB16_Black_Blitter::blitMask(const SkMask& SK_RESTRICT mask, 95 const SkIRect& SK_RESTRICT clip) 96 SK_RESTRICT { 97 if (mask.fFormat == SkMask::kBW_Format) { 98 SkRGB16_Black_BlitBW(fDevice, mask, clip); 99 } else { 100 uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop); 101 const uint8_t* SK_RESTRICT alpha = mask.getAddr(clip.fLeft, clip.fTop); 102 unsigned width = clip.width(); 103 unsigned height = clip.height(); 104 unsigned deviceRB = fDevice.rowBytes() - (width << 1); 105 unsigned maskRB = mask.fRowBytes - width; 106 107 SkASSERT((int)height > 0); 108 SkASSERT((int)width > 0); 109 SkASSERT((int)deviceRB >= 0); 110 SkASSERT((int)maskRB >= 0); 111 112 do { 113 unsigned w = width; 114 do { 115 unsigned aa = *alpha++; 116 *device = SkAlphaMulRGB16(*device, SkAlpha255To256(255 - aa)); 117 device += 1; 118 } while (--w != 0); 119 device = (uint16_t*)((char*)device + deviceRB); 120 alpha += maskRB; 121 } while (--height != 0); 122 } 123} 124 125void SkRGB16_Black_Blitter::blitAntiH(int x, int y, 126 const SkAlpha* SK_RESTRICT antialias, 127 const int16_t* SK_RESTRICT runs) 128 SK_RESTRICT { 129 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 130 131 for (;;) { 132 int count = runs[0]; 133 SkASSERT(count >= 0); 134 if (count <= 0) { 135 return; 136 } 137 runs += count; 138 139 unsigned aa = antialias[0]; 140 antialias += count; 141 if (aa) { 142 if (aa == 255) { 143 memset(device, 0, count << 1); 144 } else { 145 aa = SkAlpha255To256(255 - aa); 146 do { 147 *device = SkAlphaMulRGB16(*device, aa); 148 device += 1; 149 } while (--count != 0); 150 continue; 151 } 152 } 153 device += count; 154 } 155} 156 157////////////////////////////////////////////////////////////////////////////////////////////////// 158////////////////////////////////////////////////////////////////////////////////////////////////// 159 160SkRGB16_Blitter::SkRGB16_Blitter(const SkBitmap& device, const SkPaint& paint) 161 : INHERITED(device) { 162 SkColor color = paint.getColor(); 163 164 fSrcColor32 = SkPreMultiplyColor(color); 165 fScale = SkAlpha255To256(SkColorGetA(color)); 166 167 int r = SkColorGetR(color); 168 int g = SkColorGetG(color); 169 int b = SkColorGetB(color); 170 171 fRawColor16 = fRawDither16 = SkPack888ToRGB16(r, g, b); 172 // if we're dithered, use fRawDither16 to hold that. 173 if ((fDoDither = paint.isDither()) != false) { 174 fRawDither16 = SkDitherPack888ToRGB16(r, g, b); 175 } 176 177 fColor16 = SkPackRGB16( SkAlphaMul(r, fScale) >> (8 - SK_R16_BITS), 178 SkAlphaMul(g, fScale) >> (8 - SK_G16_BITS), 179 SkAlphaMul(b, fScale) >> (8 - SK_B16_BITS)); 180} 181 182const SkBitmap* SkRGB16_Blitter::justAnOpaqueColor(uint32_t* value) { 183 if (!fDoDither && 256 == fScale) { 184 *value = fRawColor16; 185 return &fDevice; 186 } 187 return NULL; 188} 189 190void SkRGB16_Blitter::blitH(int x, int y, int width) SK_RESTRICT { 191 SkASSERT(width > 0); 192 SkASSERT(x + width <= fDevice.width()); 193 194 if (fScale == 0) { 195 return; 196 } 197 198 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 199 uint16_t srcColor = fColor16; 200 201 if (256 == fScale) { 202 SkASSERT(fRawColor16 == srcColor); 203 if (fDoDither) { 204 uint16_t ditherColor = fRawDither16; 205 if ((x ^ y) & 1) { 206 SkTSwap(ditherColor, srcColor); 207 } 208 sk_dither_memset16(device, srcColor, ditherColor, width); 209 } else { 210 sk_memset16(device, srcColor, width); 211 } 212 } else { 213 // TODO: respect fDoDither 214 SkPMColor src32 = fSrcColor32; 215 do { 216 *device = SkSrcOver32To16(src32, *device); 217 device += 1; 218 } while (--width != 0); 219 } 220} 221 222// return 1 or 0 from a bool 223static int Bool2Int(bool value) { 224 return !!value; 225} 226 227void SkRGB16_Blitter::blitAntiH(int x, int y, 228 const SkAlpha* SK_RESTRICT antialias, 229 const int16_t* SK_RESTRICT runs) SK_RESTRICT { 230 if (fScale == 0) { 231 return; 232 } 233 234 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 235 uint16_t srcColor = fRawColor16; 236 unsigned scale = fScale; 237 int ditherInt = Bool2Int(fDoDither); 238 239 if (256 == scale) { 240 uint16_t ditherColor = fRawDither16; 241 // if we have no dithering, this will always fail 242 if ((x ^ y) & ditherInt) { 243 SkTSwap(ditherColor, srcColor); 244 } 245 for (;;) { 246 int count = runs[0]; 247 SkASSERT(count >= 0); 248 if (count <= 0) { 249 return; 250 } 251 runs += count; 252 253 unsigned aa = antialias[0]; 254 antialias += count; 255 if (aa) { 256 if (aa == 255) { 257 if (ditherInt) { 258 sk_dither_memset16(device, srcColor, 259 ditherColor, count); 260 } else { 261 sk_memset16(device, srcColor, count); 262 } 263 } else { 264 // TODO: respect fDoDither 265 unsigned scale5 = SkAlpha255To256(aa) >> 3; 266 uint32_t src32 = SkExpand_rgb_16(srcColor) * scale5; 267 scale5 = 32 - scale5; // now we can use it on the device 268 int n = count; 269 do { 270 uint32_t dst32 = SkExpand_rgb_16(*device) * scale5; 271 *device++ = SkCompact_rgb_16((src32 + dst32) >> 5); 272 } while (--n != 0); 273 goto DONE; 274 } 275 } 276 device += count; 277 278 DONE: 279 // if we have no dithering, this will always fail 280 if (count & ditherInt) { 281 SkTSwap(ditherColor, srcColor); 282 } 283 } 284 } else { 285 // TODO: respect fDoDither 286 for (;;) { 287 int count = runs[0]; 288 SkASSERT(count >= 0); 289 if (count <= 0) { 290 return; 291 } 292 runs += count; 293 294 unsigned aa = antialias[0]; 295 antialias += count; 296 if (aa) { 297 unsigned scale5 = SkAlpha255To256(aa) * scale >> (8 + 3); 298 uint32_t src32 = SkExpand_rgb_16(srcColor) * scale5; 299 scale5 = 32 - scale5; 300 do { 301 uint32_t dst32 = SkExpand_rgb_16(*device) * scale5; 302 *device++ = SkCompact_rgb_16((src32 + dst32) >> 5); 303 } while (--count != 0); 304 continue; 305 } 306 device += count; 307 } 308 } 309} 310 311////////////////////////////////////////////////////////////////////////////////////// 312 313#define solid_8_pixels(mask, dst, color) \ 314 do { \ 315 if (mask & 0x80) dst[0] = color; \ 316 if (mask & 0x40) dst[1] = color; \ 317 if (mask & 0x20) dst[2] = color; \ 318 if (mask & 0x10) dst[3] = color; \ 319 if (mask & 0x08) dst[4] = color; \ 320 if (mask & 0x04) dst[5] = color; \ 321 if (mask & 0x02) dst[6] = color; \ 322 if (mask & 0x01) dst[7] = color; \ 323 } while (0) 324 325#define SK_BLITBWMASK_NAME SkRGB16_BlitBW 326#define SK_BLITBWMASK_ARGS , uint16_t color 327#define SK_BLITBWMASK_BLIT8(mask, dst) solid_8_pixels(mask, dst, color) 328#define SK_BLITBWMASK_GETADDR getAddr16 329#define SK_BLITBWMASK_DEVTYPE uint16_t 330#include "SkBlitBWMaskTemplate.h" 331 332static inline void blend_8_pixels(U8CPU bw, uint16_t dst[], unsigned dst_scale, 333 U16CPU srcColor) { 334 if (bw & 0x80) dst[0] = srcColor + SkAlphaMulRGB16(dst[0], dst_scale); 335 if (bw & 0x40) dst[1] = srcColor + SkAlphaMulRGB16(dst[1], dst_scale); 336 if (bw & 0x20) dst[2] = srcColor + SkAlphaMulRGB16(dst[2], dst_scale); 337 if (bw & 0x10) dst[3] = srcColor + SkAlphaMulRGB16(dst[3], dst_scale); 338 if (bw & 0x08) dst[4] = srcColor + SkAlphaMulRGB16(dst[4], dst_scale); 339 if (bw & 0x04) dst[5] = srcColor + SkAlphaMulRGB16(dst[5], dst_scale); 340 if (bw & 0x02) dst[6] = srcColor + SkAlphaMulRGB16(dst[6], dst_scale); 341 if (bw & 0x01) dst[7] = srcColor + SkAlphaMulRGB16(dst[7], dst_scale); 342} 343 344#define SK_BLITBWMASK_NAME SkRGB16_BlendBW 345#define SK_BLITBWMASK_ARGS , unsigned dst_scale, U16CPU src_color 346#define SK_BLITBWMASK_BLIT8(mask, dst) blend_8_pixels(mask, dst, dst_scale, src_color) 347#define SK_BLITBWMASK_GETADDR getAddr16 348#define SK_BLITBWMASK_DEVTYPE uint16_t 349#include "SkBlitBWMaskTemplate.h" 350 351static U16CPU blend_compact(uint32_t src32, uint32_t dst32, unsigned scale5) { 352 return SkCompact_rgb_16(dst32 + ((src32 - dst32) * scale5 >> 5)); 353} 354 355void SkRGB16_Blitter::blitMask(const SkMask& SK_RESTRICT mask, 356 const SkIRect& SK_RESTRICT clip) SK_RESTRICT { 357 if (fScale == 0) { 358 return; 359 } 360 if (mask.fFormat == SkMask::kBW_Format) { 361 if (fScale == 256) { 362 SkRGB16_BlitBW(fDevice, mask, clip, fColor16); 363 } else { 364 SkRGB16_BlendBW(fDevice, mask, clip, 256 - fScale, fColor16); 365 } 366 return; 367 } 368 369 uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop); 370 const uint8_t* SK_RESTRICT alpha = mask.getAddr(clip.fLeft, clip.fTop); 371 int width = clip.width(); 372 int height = clip.height(); 373 unsigned deviceRB = fDevice.rowBytes() - (width << 1); 374 unsigned maskRB = mask.fRowBytes - width; 375 uint32_t color32 = SkExpand_rgb_16(fRawColor16); 376 377 if (256 == fScale) { 378 do { 379 int w = width; 380 do { 381 *device = blend_compact(color32, SkExpand_rgb_16(*device), 382 SkAlpha255To256(*alpha++) >> 3); 383 device += 1; 384 } while (--w != 0); 385 device = (uint16_t*)((char*)device + deviceRB); 386 alpha += maskRB; 387 } while (--height != 0); 388 } else { // scale < 256 389 unsigned scale256 = fScale; 390 do { 391 int w = width; 392 do { 393 unsigned aa = *alpha++; 394 unsigned scale = SkAlpha255To256(aa) * scale256 >> (8 + 3); 395 uint32_t src32 = color32 * scale; 396 uint32_t dst32 = SkExpand_rgb_16(*device) * (32 - scale); 397 *device++ = SkCompact_rgb_16((src32 + dst32) >> 5); 398 } while (--w != 0); 399 device = (uint16_t*)((char*)device + deviceRB); 400 alpha += maskRB; 401 } while (--height != 0); 402 } 403} 404 405void SkRGB16_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { 406 if (fScale == 0) { 407 return; 408 } 409 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 410 uint16_t color16 = fRawColor16; 411 unsigned deviceRB = fDevice.rowBytes(); 412 413 if (alpha + fScale == (255 + 256)) { 414 if (fDoDither) { 415 uint16_t ditherColor = fRawDither16; 416 if ((x ^ y) & 1) { 417 SkTSwap(ditherColor, color16); 418 } 419 do { 420 device[0] = color16; 421 device = (uint16_t*)((char*)device + deviceRB); 422 SkTSwap(ditherColor, color16); 423 } while (--height != 0); 424 } else { 425 do { 426 device[0] = color16; 427 device = (uint16_t*)((char*)device + deviceRB); 428 } while (--height != 0); 429 } 430 } else { 431 // TODO: respect fDoDither 432 unsigned scale5 = SkAlpha255To256(alpha) * fScale >> (8 + 3); 433 uint32_t src32 = SkExpand_rgb_16(color16) * scale5; 434 scale5 = 32 - scale5; 435 do { 436 uint32_t dst32 = SkExpand_rgb_16(*device) * scale5; 437 *device = SkCompact_rgb_16((src32 + dst32) >> 5); 438 device = (uint16_t*)((char*)device + deviceRB); 439 } while (--height != 0); 440 } 441} 442 443void SkRGB16_Blitter::blitRect(int x, int y, int width, int height) { 444 SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height()); 445 446 if (fScale == 0) { 447 return; 448 } 449 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 450 unsigned deviceRB = fDevice.rowBytes(); 451 uint16_t color16 = fColor16; 452 453 if (256 == fScale) { 454 if (fDoDither) { 455 uint16_t ditherColor = fRawDither16; 456 if ((x ^ y) & 1) { 457 SkTSwap(ditherColor, color16); 458 } 459 while (--height >= 0) { 460 sk_dither_memset16(device, color16, ditherColor, width); 461 SkTSwap(ditherColor, color16); 462 device = (uint16_t*)((char*)device + deviceRB); 463 } 464 } else { // no dither 465 while (--height >= 0) { 466 sk_memset16(device, color16, width); 467 device = (uint16_t*)((char*)device + deviceRB); 468 } 469 } 470 } else { 471 SkPMColor src32 = fSrcColor32; 472 while (--height >= 0) { 473 for (int i = width - 1; i >= 0; --i) { 474 device[i] = SkSrcOver32To16(src32, device[i]); 475 } 476 device = (uint16_t*)((char*)device + deviceRB); 477 } 478 } 479} 480 481/////////////////////////////////////////////////////////////////////////////// 482 483SkRGB16_Shader16_Blitter::SkRGB16_Shader16_Blitter(const SkBitmap& device, 484 const SkPaint& paint) 485 : SkRGB16_Shader_Blitter(device, paint) { 486 SkASSERT(SkShader::CanCallShadeSpan16(fShader->getFlags())); 487} 488 489void SkRGB16_Shader16_Blitter::blitH(int x, int y, int width) SK_RESTRICT { 490 SkASSERT(x + width <= fDevice.width()); 491 492 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 493 SkShader* shader = fShader; 494 495 int alpha = shader->getSpan16Alpha(); 496 if (0xFF == alpha) { 497 shader->shadeSpan16(x, y, device, width); 498 } else { 499 uint16_t* span16 = (uint16_t*)fBuffer; 500 shader->shadeSpan16(x, y, span16, width); 501 SkBlendRGB16(span16, device, SkAlpha255To256(alpha), width); 502 } 503} 504 505void SkRGB16_Shader16_Blitter::blitAntiH(int x, int y, 506 const SkAlpha* SK_RESTRICT antialias, 507 const int16_t* SK_RESTRICT runs) 508 SK_RESTRICT { 509 SkShader* shader = fShader; 510 SkPMColor* SK_RESTRICT span = fBuffer; 511 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 512 513 int alpha = shader->getSpan16Alpha(); 514 uint16_t* span16 = (uint16_t*)span; 515 516 if (0xFF == alpha) { 517 for (;;) { 518 int count = *runs; 519 if (count <= 0) { 520 break; 521 } 522 SkASSERT(count <= fDevice.width()); // don't overrun fBuffer 523 524 int aa = *antialias; 525 if (aa == 255) { 526 // go direct to the device! 527 shader->shadeSpan16(x, y, device, count); 528 } else if (aa) { 529 shader->shadeSpan16(x, y, span16, count); 530 SkBlendRGB16(span16, device, SkAlpha255To256(aa), count); 531 } 532 device += count; 533 runs += count; 534 antialias += count; 535 x += count; 536 } 537 } else { // span alpha is < 255 538 alpha = SkAlpha255To256(alpha); 539 for (;;) { 540 int count = *runs; 541 if (count <= 0) { 542 break; 543 } 544 SkASSERT(count <= fDevice.width()); // don't overrun fBuffer 545 546 int aa = SkAlphaMul(*antialias, alpha); 547 if (aa) { 548 shader->shadeSpan16(x, y, span16, count); 549 SkBlendRGB16(span16, device, SkAlpha255To256(aa), count); 550 } 551 552 device += count; 553 runs += count; 554 antialias += count; 555 x += count; 556 } 557 } 558} 559 560/////////////////////////////////////////////////////////////////////////////// 561 562SkRGB16_Shader_Blitter::SkRGB16_Shader_Blitter(const SkBitmap& device, 563 const SkPaint& paint) 564: INHERITED(device, paint) { 565 SkASSERT(paint.getXfermode() == NULL); 566 567 fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * sizeof(SkPMColor)); 568 569 // compute SkBlitRow::Procs 570 unsigned flags = 0; 571 572 uint32_t shaderFlags = fShader->getFlags(); 573 // shaders take care of global alpha, so we never set it in SkBlitRow 574 if (!(shaderFlags & SkShader::kOpaqueAlpha_Flag)) { 575 flags |= SkBlitRow::kSrcPixelAlpha_Flag; 576 } 577 // don't dither if the shader is really 16bit 578 if (paint.isDither() && !(shaderFlags & SkShader::kIntrinsicly16_Flag)) { 579 flags |= SkBlitRow::kDither_Flag; 580 } 581 // used when we know our global alpha is 0xFF 582 fOpaqueProc = SkBlitRow::Factory(flags, SkBitmap::kRGB_565_Config); 583 // used when we know our global alpha is < 0xFF 584 fAlphaProc = SkBlitRow::Factory(flags | SkBlitRow::kGlobalAlpha_Flag, 585 SkBitmap::kRGB_565_Config); 586} 587 588SkRGB16_Shader_Blitter::~SkRGB16_Shader_Blitter() { 589 sk_free(fBuffer); 590} 591 592void SkRGB16_Shader_Blitter::blitH(int x, int y, int width) { 593 SkASSERT(x + width <= fDevice.width()); 594 595 fShader->shadeSpan(x, y, fBuffer, width); 596 // shaders take care of global alpha, so we pass 0xFF (should be ignored) 597 fOpaqueProc(fDevice.getAddr16(x, y), fBuffer, width, 0xFF, x, y); 598} 599 600static inline int count_nonzero_span(const int16_t runs[], const SkAlpha aa[]) { 601 int count = 0; 602 for (;;) { 603 int n = *runs; 604 if (n == 0 || *aa == 0) { 605 break; 606 } 607 runs += n; 608 aa += n; 609 count += n; 610 } 611 return count; 612} 613 614void SkRGB16_Shader_Blitter::blitAntiH(int x, int y, 615 const SkAlpha* SK_RESTRICT antialias, 616 const int16_t* SK_RESTRICT runs) 617 SK_RESTRICT { 618 SkShader* shader = fShader; 619 SkPMColor* SK_RESTRICT span = fBuffer; 620 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 621 622 for (;;) { 623 int count = *runs; 624 if (count <= 0) { 625 break; 626 } 627 int aa = *antialias; 628 if (0 == aa) { 629 device += count; 630 runs += count; 631 antialias += count; 632 x += count; 633 continue; 634 } 635 636 int nonZeroCount = count + count_nonzero_span(runs + count, antialias + count); 637 638 SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer 639 shader->shadeSpan(x, y, span, nonZeroCount); 640 641 SkPMColor* localSpan = span; 642 for (;;) { 643 SkBlitRow::Proc proc = (aa == 0xFF) ? fOpaqueProc : fAlphaProc; 644 proc(device, localSpan, count, aa, x, y); 645 646 x += count; 647 device += count; 648 runs += count; 649 antialias += count; 650 nonZeroCount -= count; 651 if (nonZeroCount == 0) { 652 break; 653 } 654 localSpan += count; 655 SkASSERT(nonZeroCount > 0); 656 count = *runs; 657 SkASSERT(count > 0); 658 aa = *antialias; 659 } 660 } 661} 662 663/////////////////////////////////////////////////////////////////////// 664 665SkRGB16_Shader_Xfermode_Blitter::SkRGB16_Shader_Xfermode_Blitter( 666 const SkBitmap& device, const SkPaint& paint) 667: INHERITED(device, paint) { 668 fXfermode = paint.getXfermode(); 669 SkASSERT(fXfermode); 670 fXfermode->ref(); 671 672 int width = device.width(); 673 fBuffer = (SkPMColor*)sk_malloc_throw((width + (SkAlign4(width) >> 2)) * sizeof(SkPMColor)); 674 fAAExpand = (uint8_t*)(fBuffer + width); 675} 676 677SkRGB16_Shader_Xfermode_Blitter::~SkRGB16_Shader_Xfermode_Blitter() { 678 fXfermode->unref(); 679 sk_free(fBuffer); 680} 681 682void SkRGB16_Shader_Xfermode_Blitter::blitH(int x, int y, int width) { 683 SkASSERT(x + width <= fDevice.width()); 684 685 uint16_t* device = fDevice.getAddr16(x, y); 686 SkPMColor* span = fBuffer; 687 688 fShader->shadeSpan(x, y, span, width); 689 fXfermode->xfer16(device, span, width, NULL); 690} 691 692void SkRGB16_Shader_Xfermode_Blitter::blitAntiH(int x, int y, 693 const SkAlpha* SK_RESTRICT antialias, 694 const int16_t* SK_RESTRICT runs) SK_RESTRICT { 695 SkShader* shader = fShader; 696 SkXfermode* mode = fXfermode; 697 SkPMColor* SK_RESTRICT span = fBuffer; 698 uint8_t* SK_RESTRICT aaExpand = fAAExpand; 699 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 700 701 for (;;) { 702 int count = *runs; 703 if (count <= 0) { 704 break; 705 } 706 int aa = *antialias; 707 if (0 == aa) { 708 device += count; 709 runs += count; 710 antialias += count; 711 x += count; 712 continue; 713 } 714 715 int nonZeroCount = count + count_nonzero_span(runs + count, 716 antialias + count); 717 718 SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer 719 shader->shadeSpan(x, y, span, nonZeroCount); 720 721 x += nonZeroCount; 722 SkPMColor* localSpan = span; 723 for (;;) { 724 if (aa == 0xFF) { 725 mode->xfer16(device, localSpan, count, NULL); 726 } else { 727 SkASSERT(aa); 728 memset(aaExpand, aa, count); 729 mode->xfer16(device, localSpan, count, aaExpand); 730 } 731 device += count; 732 runs += count; 733 antialias += count; 734 nonZeroCount -= count; 735 if (nonZeroCount == 0) { 736 break; 737 } 738 localSpan += count; 739 SkASSERT(nonZeroCount > 0); 740 count = *runs; 741 SkASSERT(count > 0); 742 aa = *antialias; 743 } 744 } 745} 746 747//////////////////////// 748 749#if 0 750static inline uint16_t aa_blendS32D16(SkPMColor src, U16CPU dst, int aa 751#ifdef DITHER_SHADER 752 , int dither 753#endif 754 ) 755{ 756 SkASSERT((unsigned)aa <= 255); 757 758 int src_scale = SkAlpha255To256(aa); 759 int sa = SkGetPackedA32(src); 760 int dst_scale = SkAlpha255To256(255 - SkAlphaMul(sa, src_scale)); 761 762#ifdef DITHER_SHADER 763 int sr = SkGetPackedR32(src); 764 int sg = SkGetPackedG32(src); 765 int sb = SkGetPackedB32(src); 766 sr = SkDITHER_R32To16(sr, dither); 767 sg = SkDITHER_G32To16(sg, dither); 768 sb = SkDITHER_B32To16(sb, dither); 769#else 770 int sr = SkPacked32ToR16(src); 771 int sg = SkPacked32ToG16(src); 772 int sb = SkPacked32ToB16(src); 773#endif 774 775 int dr = (sr * src_scale + SkGetPackedR16(dst) * dst_scale) >> 8; 776 int dg = (sg * src_scale + SkGetPackedG16(dst) * dst_scale) >> 8; 777 int db = (sb * src_scale + SkGetPackedB16(dst) * dst_scale) >> 8; 778 779 return SkPackRGB16(dr, dg, db); 780} 781#endif 782 783