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 "SkDither.h" 21 #include "SkShader.h" 22 #include "SkTemplatesPriv.h" 23 #include "SkUtils.h" 24 #include "SkXfermode.h" 25 26 static inline SkPMColor SkBlendARGB4444(SkPMColor16 src, SkPMColor16 dst, 27 U8CPU aa) { 28 SkASSERT((unsigned)aa <= 255); 29 30 unsigned src_scale = SkAlpha255To256(aa) >> 4; 31 unsigned dst_scale = SkAlpha15To16(15 - SkAlphaMul4(SkGetPackedA4444(src), src_scale)); 32 33 uint32_t src32 = SkExpand_4444(src) * src_scale; 34 uint32_t dst32 = SkExpand_4444(dst) * dst_scale; 35 return SkCompact_4444((src32 + dst32) >> 4); 36 } 37 38 /////////////////////////////////////////////////////////////////////////////// 39 40 class SkARGB4444_Blitter : public SkRasterBlitter { 41 public: 42 SkARGB4444_Blitter(const SkBitmap& device, const SkPaint& paint); 43 virtual void blitH(int x, int y, int width); 44 virtual void blitAntiH(int x, int y, const SkAlpha antialias[], 45 const int16_t runs[]); 46 virtual void blitV(int x, int y, int height, SkAlpha alpha); 47 virtual void blitRect(int x, int y, int width, int height); 48 virtual void blitMask(const SkMask&, const SkIRect&); 49 virtual const SkBitmap* justAnOpaqueColor(uint32_t*); 50 51 protected: 52 SkPMColor16 fPMColor16, fPMColor16Other; 53 SkPMColor16 fRawColor16, fRawColor16Other; 54 uint8_t fScale16; 55 56 private: 57 // illegal 58 SkARGB4444_Blitter& operator=(const SkARGB4444_Blitter&); 59 60 typedef SkRasterBlitter INHERITED; 61 }; 62 63 64 SkARGB4444_Blitter::SkARGB4444_Blitter(const SkBitmap& device, 65 const SkPaint& paint) : INHERITED(device) { 66 // cache premultiplied versions in 4444 67 SkPMColor c = SkPreMultiplyColor(paint.getColor()); 68 fPMColor16 = SkPixel32ToPixel4444(c); 69 if (paint.isDither()) { 70 fPMColor16Other = SkDitherPixel32To4444(c); 71 } else { 72 fPMColor16Other = fPMColor16; 73 } 74 75 // cache raw versions in 4444 76 fRawColor16 = SkPackARGB4444(0xFF >> 4, SkColorGetR(c) >> 4, 77 SkColorGetG(c) >> 4, SkColorGetB(c) >> 4); 78 if (paint.isDither()) { 79 fRawColor16Other = SkDitherARGB32To4444(0xFF, SkColorGetR(c), 80 SkColorGetG(c), SkColorGetB(c)); 81 } else { 82 fRawColor16Other = fRawColor16; 83 } 84 85 fScale16 = SkAlpha15To16(SkGetPackedA4444(fPMColor16Other)); 86 if (16 == fScale16) { 87 // force the original to also be opaque 88 fPMColor16 |= (0xF << SK_A4444_SHIFT); 89 } 90 } 91 92 const SkBitmap* SkARGB4444_Blitter::justAnOpaqueColor(uint32_t* value) { 93 if (16 == fScale16) { 94 *value = fPMColor16; 95 return &fDevice; 96 } 97 return NULL; 98 } 99 100 static void src_over_4444(SkPMColor16 dst[], SkPMColor16 color, 101 SkPMColor16 other, unsigned invScale, int count) { 102 int twice = count >> 1; 103 while (--twice >= 0) { 104 *dst = color + SkAlphaMulQ4(*dst, invScale); 105 dst++; 106 *dst = other + SkAlphaMulQ4(*dst, invScale); 107 dst++; 108 } 109 if (count & 1) { 110 *dst = color + SkAlphaMulQ4(*dst, invScale); 111 } 112 } 113 114 static inline uint32_t SkExpand_4444_Replicate(SkPMColor16 c) { 115 uint32_t c32 = SkExpand_4444(c); 116 return c32 | (c32 << 4); 117 } 118 119 static void src_over_4444x(SkPMColor16 dst[], uint32_t color, 120 uint32_t other, unsigned invScale, int count) { 121 int twice = count >> 1; 122 uint32_t tmp; 123 while (--twice >= 0) { 124 tmp = SkExpand_4444(*dst) * invScale; 125 *dst++ = SkCompact_4444((color + tmp) >> 4); 126 tmp = SkExpand_4444(*dst) * invScale; 127 *dst++ = SkCompact_4444((other + tmp) >> 4); 128 } 129 if (count & 1) { 130 tmp = SkExpand_4444(*dst) * invScale; 131 *dst = SkCompact_4444((color + tmp) >> 4); 132 } 133 } 134 135 void SkARGB4444_Blitter::blitH(int x, int y, int width) { 136 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width()); 137 138 if (0 == fScale16) { 139 return; 140 } 141 142 SkPMColor16* device = fDevice.getAddr16(x, y); 143 SkPMColor16 color = fPMColor16; 144 SkPMColor16 other = fPMColor16Other; 145 146 if ((x ^ y) & 1) { 147 SkTSwap<SkPMColor16>(color, other); 148 } 149 150 if (16 == fScale16) { 151 sk_dither_memset16(device, color, other, width); 152 } else { 153 src_over_4444x(device, SkExpand_4444_Replicate(color), 154 SkExpand_4444_Replicate(other), 155 16 - fScale16, width); 156 } 157 } 158 159 void SkARGB4444_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { 160 if (0 == alpha || 0 == fScale16) { 161 return; 162 } 163 164 SkPMColor16* device = fDevice.getAddr16(x, y); 165 SkPMColor16 color = fPMColor16; 166 SkPMColor16 other = fPMColor16Other; 167 unsigned rb = fDevice.rowBytes(); 168 169 if ((x ^ y) & 1) { 170 SkTSwap<SkPMColor16>(color, other); 171 } 172 173 if (16 == fScale16 && 255 == alpha) { 174 while (--height >= 0) { 175 *device = color; 176 device = (SkPMColor16*)((char*)device + rb); 177 SkTSwap<SkPMColor16>(color, other); 178 } 179 } else { 180 unsigned alphaScale = SkAlpha255To256(alpha); 181 uint32_t c32 = SkExpand_4444(color) * (alphaScale >> 4); 182 // need to normalize the low nibble of each expanded component 183 // so we don't overflow the add with d32 184 c32 = SkCompact_4444(c32 >> 4); 185 unsigned invScale = 16 - SkAlpha15To16(SkGetPackedA4444(c32)); 186 // now re-expand and replicate 187 c32 = SkExpand_4444_Replicate(c32); 188 189 while (--height >= 0) { 190 uint32_t d32 = SkExpand_4444(*device) * invScale; 191 *device = SkCompact_4444((c32 + d32) >> 4); 192 device = (SkPMColor16*)((char*)device + rb); 193 } 194 } 195 } 196 197 void SkARGB4444_Blitter::blitRect(int x, int y, int width, int height) { 198 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width() && 199 y + height <= fDevice.height()); 200 201 if (0 == fScale16) { 202 return; 203 } 204 205 SkPMColor16* device = fDevice.getAddr16(x, y); 206 SkPMColor16 color = fPMColor16; 207 SkPMColor16 other = fPMColor16Other; 208 209 if ((x ^ y) & 1) { 210 SkTSwap<SkPMColor16>(color, other); 211 } 212 213 if (16 == fScale16) { 214 while (--height >= 0) { 215 sk_dither_memset16(device, color, other, width); 216 device = (SkPMColor16*)((char*)device + fDevice.rowBytes()); 217 SkTSwap<SkPMColor16>(color, other); 218 } 219 } else { 220 unsigned invScale = 16 - fScale16; 221 222 uint32_t c32 = SkExpand_4444_Replicate(color); 223 uint32_t o32 = SkExpand_4444_Replicate(other); 224 while (--height >= 0) { 225 src_over_4444x(device, c32, o32, invScale, width); 226 device = (SkPMColor16*)((char*)device + fDevice.rowBytes()); 227 SkTSwap<uint32_t>(c32, o32); 228 } 229 } 230 } 231 232 void SkARGB4444_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], 233 const int16_t runs[]) { 234 if (0 == fScale16) { 235 return; 236 } 237 238 SkPMColor16* device = fDevice.getAddr16(x, y); 239 SkPMColor16 color = fPMColor16; 240 SkPMColor16 other = fPMColor16Other; 241 242 if ((x ^ y) & 1) { 243 SkTSwap<SkPMColor16>(color, other); 244 } 245 246 for (;;) { 247 int count = runs[0]; 248 SkASSERT(count >= 0); 249 if (count <= 0) { 250 return; 251 } 252 253 unsigned aa = antialias[0]; 254 if (aa) { 255 if (0xFF == aa) { 256 if (16 == fScale16) { 257 sk_dither_memset16(device, color, other, count); 258 } else { 259 src_over_4444(device, color, other, 16 - fScale16, count); 260 } 261 } else { 262 // todo: respect dithering 263 aa = SkAlpha255To256(aa); // FIX 264 SkPMColor16 src = SkAlphaMulQ4(color, aa >> 4); 265 unsigned dst_scale = SkAlpha15To16(15 - SkGetPackedA4444(src)); // FIX 266 int n = count; 267 do { 268 --n; 269 device[n] = src + SkAlphaMulQ4(device[n], dst_scale); 270 } while (n > 0); 271 } 272 } 273 274 runs += count; 275 antialias += count; 276 device += count; 277 278 if (count & 1) { 279 SkTSwap<SkPMColor16>(color, other); 280 } 281 } 282 } 283 284 /////////////////////////////////////////////////////////////////////////////// 285 286 #define solid_8_pixels(mask, dst, color) \ 287 do { \ 288 if (mask & 0x80) dst[0] = color; \ 289 if (mask & 0x40) dst[1] = color; \ 290 if (mask & 0x20) dst[2] = color; \ 291 if (mask & 0x10) dst[3] = color; \ 292 if (mask & 0x08) dst[4] = color; \ 293 if (mask & 0x04) dst[5] = color; \ 294 if (mask & 0x02) dst[6] = color; \ 295 if (mask & 0x01) dst[7] = color; \ 296 } while (0) 297 298 #define SK_BLITBWMASK_NAME SkARGB4444_BlitBW 299 #define SK_BLITBWMASK_ARGS , SkPMColor16 color 300 #define SK_BLITBWMASK_BLIT8(mask, dst) solid_8_pixels(mask, dst, color) 301 #define SK_BLITBWMASK_GETADDR getAddr16 302 #define SK_BLITBWMASK_DEVTYPE uint16_t 303 #include "SkBlitBWMaskTemplate.h" 304 305 #define blend_8_pixels(mask, dst, sc, dst_scale) \ 306 do { \ 307 if (mask & 0x80) { dst[0] = sc + SkAlphaMulQ4(dst[0], dst_scale); } \ 308 if (mask & 0x40) { dst[1] = sc + SkAlphaMulQ4(dst[1], dst_scale); } \ 309 if (mask & 0x20) { dst[2] = sc + SkAlphaMulQ4(dst[2], dst_scale); } \ 310 if (mask & 0x10) { dst[3] = sc + SkAlphaMulQ4(dst[3], dst_scale); } \ 311 if (mask & 0x08) { dst[4] = sc + SkAlphaMulQ4(dst[4], dst_scale); } \ 312 if (mask & 0x04) { dst[5] = sc + SkAlphaMulQ4(dst[5], dst_scale); } \ 313 if (mask & 0x02) { dst[6] = sc + SkAlphaMulQ4(dst[6], dst_scale); } \ 314 if (mask & 0x01) { dst[7] = sc + SkAlphaMulQ4(dst[7], dst_scale); } \ 315 } while (0) 316 317 #define SK_BLITBWMASK_NAME SkARGB4444_BlendBW 318 #define SK_BLITBWMASK_ARGS , uint16_t sc, unsigned dst_scale 319 #define SK_BLITBWMASK_BLIT8(mask, dst) blend_8_pixels(mask, dst, sc, dst_scale) 320 #define SK_BLITBWMASK_GETADDR getAddr16 321 #define SK_BLITBWMASK_DEVTYPE uint16_t 322 #include "SkBlitBWMaskTemplate.h" 323 324 void SkARGB4444_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { 325 SkASSERT(mask.fBounds.contains(clip)); 326 327 if (0 == fScale16) { 328 return; 329 } 330 331 if (mask.fFormat == SkMask::kBW_Format) { 332 if (16 == fScale16) { 333 SkARGB4444_BlitBW(fDevice, mask, clip, fPMColor16); 334 } else { 335 SkARGB4444_BlendBW(fDevice, mask, clip, fPMColor16, 16 - fScale16); 336 } 337 return; 338 } 339 340 int x = clip.fLeft; 341 int y = clip.fTop; 342 int width = clip.width(); 343 int height = clip.height(); 344 345 SkPMColor16* device = fDevice.getAddr16(x, y); 346 const uint8_t* alpha = mask.getAddr(x, y); 347 SkPMColor16 srcColor = fPMColor16; 348 unsigned devRB = fDevice.rowBytes() - (width << 1); 349 unsigned maskRB = mask.fRowBytes - width; 350 351 do { 352 int w = width; 353 do { 354 unsigned aa = *alpha++; 355 *device = SkBlendARGB4444(srcColor, *device, aa); 356 device += 1; 357 } while (--w != 0); 358 device = (SkPMColor16*)((char*)device + devRB); 359 alpha += maskRB; 360 } while (--height != 0); 361 } 362 363 /////////////////////////////////////////////////////////////////////////////// 364 365 class SkARGB4444_Shader_Blitter : public SkShaderBlitter { 366 SkXfermode* fXfermode; 367 SkBlitRow::Proc fOpaqueProc; 368 SkBlitRow::Proc fAlphaProc; 369 SkPMColor* fBuffer; 370 uint8_t* fAAExpand; 371 public: 372 373 SkARGB4444_Shader_Blitter(const SkBitmap& device, const SkPaint& paint) 374 : INHERITED(device, paint) { 375 const int width = device.width(); 376 fBuffer = (SkPMColor*)sk_malloc_throw(width * sizeof(SkPMColor) + width); 377 fAAExpand = (uint8_t*)(fBuffer + width); 378 379 fXfermode = paint.getXfermode(); 380 SkSafeRef(fXfermode); 381 382 unsigned flags = 0; 383 if (!(fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) { 384 flags |= SkBlitRow::kSrcPixelAlpha_Flag; 385 } 386 if (paint.isDither()) { 387 flags |= SkBlitRow::kDither_Flag; 388 } 389 fOpaqueProc = SkBlitRow::Factory(flags, SkBitmap::kARGB_4444_Config); 390 fAlphaProc = SkBlitRow::Factory(flags | SkBlitRow::kGlobalAlpha_Flag, 391 SkBitmap::kARGB_4444_Config); 392 } 393 394 virtual ~SkARGB4444_Shader_Blitter() { 395 SkSafeUnref(fXfermode); 396 sk_free(fBuffer); 397 } 398 399 virtual void blitH(int x, int y, int width) { 400 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width()); 401 402 SkPMColor16* device = fDevice.getAddr16(x, y); 403 SkPMColor* span = fBuffer; 404 405 fShader->shadeSpan(x, y, span, width); 406 if (fXfermode) { 407 fXfermode->xfer4444(device, span, width, NULL); 408 } else { 409 fOpaqueProc(device, span, width, 0xFF, x, y); 410 } 411 } 412 413 virtual void blitAntiH(int x, int y, const SkAlpha antialias[], 414 const int16_t runs[]) { 415 SkPMColor* SK_RESTRICT span = fBuffer; 416 uint8_t* SK_RESTRICT aaExpand = fAAExpand; 417 SkPMColor16* device = fDevice.getAddr16(x, y); 418 SkShader* shader = fShader; 419 SkXfermode* xfer = fXfermode; 420 421 if (NULL != xfer) { 422 for (;;) { 423 int count = *runs; 424 if (count <= 0) { 425 break; 426 } 427 int aa = *antialias; 428 if (aa) { 429 shader->shadeSpan(x, y, span, count); 430 if (255 == aa) { 431 xfer->xfer4444(device, span, count, NULL); 432 } else { 433 const uint8_t* aaBuffer = antialias; 434 if (count > 1) { 435 memset(aaExpand, aa, count); 436 aaBuffer = aaExpand; 437 } 438 xfer->xfer4444(device, span, count, aaBuffer); 439 } 440 } 441 device += count; 442 runs += count; 443 antialias += count; 444 x += count; 445 } 446 } else { // no xfermode 447 for (;;) { 448 int count = *runs; 449 if (count <= 0) { 450 break; 451 } 452 int aa = *antialias; 453 if (aa) { 454 fShader->shadeSpan(x, y, span, count); 455 if (255 == aa) { 456 fOpaqueProc(device, span, count, aa, x, y); 457 } else { 458 fAlphaProc(device, span, count, aa, x, y); 459 } 460 } 461 device += count; 462 runs += count; 463 antialias += count; 464 x += count; 465 } 466 } 467 } 468 469 private: 470 typedef SkShaderBlitter INHERITED; 471 }; 472 473 /////////////////////////////////////////////////////////////////////////////// 474 /////////////////////////////////////////////////////////////////////////////// 475 476 SkBlitter* SkBlitter_ChooseD4444(const SkBitmap& device, 477 const SkPaint& paint, 478 void* storage, size_t storageSize) 479 { 480 SkBlitter* blitter; 481 482 if (paint.getShader()) { 483 SK_PLACEMENT_NEW_ARGS(blitter, SkARGB4444_Shader_Blitter, storage, storageSize, (device, paint)); 484 } else { 485 SK_PLACEMENT_NEW_ARGS(blitter, SkARGB4444_Blitter, storage, storageSize, (device, paint)); 486 } 487 return blitter; 488 } 489 490