gfx/skia/trunk/src/core/SkBlitter_RGB16.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1
michael@0 2 /*
michael@0 3 * Copyright 2006 The Android Open Source Project
michael@0 4 *
michael@0 5 * Use of this source code is governed by a BSD-style license that can be
michael@0 6 * found in the LICENSE file.
michael@0 7 */
michael@0 8
michael@0 9
michael@0 10 #include "SkBlitRow.h"
michael@0 11 #include "SkCoreBlitters.h"
michael@0 12 #include "SkColorPriv.h"
michael@0 13 #include "SkDither.h"
michael@0 14 #include "SkShader.h"
michael@0 15 #include "SkUtils.h"
michael@0 16 #include "SkXfermode.h"
michael@0 17
michael@0 18 #if defined(__ARM_HAVE_NEON) && defined(SK_CPU_LENDIAN)
michael@0 19 #define SK_USE_NEON
michael@0 20 #include <arm_neon.h>
michael@0 21 #else
michael@0 22 // if we don't have neon, then our black blitter is worth the extra code
michael@0 23 #define USE_BLACK_BLITTER
michael@0 24 #endif
michael@0 25
michael@0 26 void sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other,
michael@0 27 int count) {
michael@0 28 if (count > 0) {
michael@0 29 // see if we need to write one short before we can cast to an 4byte ptr
michael@0 30 // (we do this subtract rather than (unsigned)dst so we don't get warnings
michael@0 31 // on 64bit machines)
michael@0 32 if (((char*)dst - (char*)0) & 2) {
michael@0 33 *dst++ = value;
michael@0 34 count -= 1;
michael@0 35 SkTSwap(value, other);
michael@0 36 }
michael@0 37
michael@0 38 // fast way to set [value,other] pairs
michael@0 39 #ifdef SK_CPU_BENDIAN
michael@0 40 sk_memset32((uint32_t*)dst, (value << 16) | other, count >> 1);
michael@0 41 #else
michael@0 42 sk_memset32((uint32_t*)dst, (other << 16) | value, count >> 1);
michael@0 43 #endif
michael@0 44
michael@0 45 if (count & 1) {
michael@0 46 dst[count - 1] = value;
michael@0 47 }
michael@0 48 }
michael@0 49 }
michael@0 50
michael@0 51 ///////////////////////////////////////////////////////////////////////////////
michael@0 52
michael@0 53 class SkRGB16_Blitter : public SkRasterBlitter {
michael@0 54 public:
michael@0 55 SkRGB16_Blitter(const SkBitmap& device, const SkPaint& paint);
michael@0 56 virtual void blitH(int x, int y, int width);
michael@0 57 virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
michael@0 58 const int16_t* runs);
michael@0 59 virtual void blitV(int x, int y, int height, SkAlpha alpha);
michael@0 60 virtual void blitRect(int x, int y, int width, int height);
michael@0 61 virtual void blitMask(const SkMask&,
michael@0 62 const SkIRect&);
michael@0 63 virtual const SkBitmap* justAnOpaqueColor(uint32_t*);
michael@0 64
michael@0 65 protected:
michael@0 66 SkPMColor fSrcColor32;
michael@0 67 uint32_t fExpandedRaw16;
michael@0 68 unsigned fScale;
michael@0 69 uint16_t fColor16; // already scaled by fScale
michael@0 70 uint16_t fRawColor16; // unscaled
michael@0 71 uint16_t fRawDither16; // unscaled
michael@0 72 SkBool8 fDoDither;
michael@0 73
michael@0 74 // illegal
michael@0 75 SkRGB16_Blitter& operator=(const SkRGB16_Blitter&);
michael@0 76
michael@0 77 typedef SkRasterBlitter INHERITED;
michael@0 78 };
michael@0 79
michael@0 80 class SkRGB16_Opaque_Blitter : public SkRGB16_Blitter {
michael@0 81 public:
michael@0 82 SkRGB16_Opaque_Blitter(const SkBitmap& device, const SkPaint& paint);
michael@0 83 virtual void blitH(int x, int y, int width);
michael@0 84 virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
michael@0 85 const int16_t* runs);
michael@0 86 virtual void blitV(int x, int y, int height, SkAlpha alpha);
michael@0 87 virtual void blitRect(int x, int y, int width, int height);
michael@0 88 virtual void blitMask(const SkMask&,
michael@0 89 const SkIRect&);
michael@0 90
michael@0 91 private:
michael@0 92 typedef SkRGB16_Blitter INHERITED;
michael@0 93 };
michael@0 94
michael@0 95 #ifdef USE_BLACK_BLITTER
michael@0 96 class SkRGB16_Black_Blitter : public SkRGB16_Opaque_Blitter {
michael@0 97 public:
michael@0 98 SkRGB16_Black_Blitter(const SkBitmap& device, const SkPaint& paint);
michael@0 99 virtual void blitMask(const SkMask&, const SkIRect&);
michael@0 100 virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
michael@0 101 const int16_t* runs);
michael@0 102
michael@0 103 private:
michael@0 104 typedef SkRGB16_Opaque_Blitter INHERITED;
michael@0 105 };
michael@0 106 #endif
michael@0 107
michael@0 108 class SkRGB16_Shader_Blitter : public SkShaderBlitter {
michael@0 109 public:
michael@0 110 SkRGB16_Shader_Blitter(const SkBitmap& device, const SkPaint& paint);
michael@0 111 virtual ~SkRGB16_Shader_Blitter();
michael@0 112 virtual void blitH(int x, int y, int width);
michael@0 113 virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
michael@0 114 const int16_t* runs);
michael@0 115 virtual void blitRect(int x, int y, int width, int height);
michael@0 116
michael@0 117 protected:
michael@0 118 SkPMColor* fBuffer;
michael@0 119 SkBlitRow::Proc fOpaqueProc;
michael@0 120 SkBlitRow::Proc fAlphaProc;
michael@0 121
michael@0 122 private:
michael@0 123 // illegal
michael@0 124 SkRGB16_Shader_Blitter& operator=(const SkRGB16_Shader_Blitter&);
michael@0 125
michael@0 126 typedef SkShaderBlitter INHERITED;
michael@0 127 };
michael@0 128
michael@0 129 // used only if the shader can perform shadSpan16
michael@0 130 class SkRGB16_Shader16_Blitter : public SkRGB16_Shader_Blitter {
michael@0 131 public:
michael@0 132 SkRGB16_Shader16_Blitter(const SkBitmap& device, const SkPaint& paint);
michael@0 133 virtual void blitH(int x, int y, int width);
michael@0 134 virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
michael@0 135 const int16_t* runs);
michael@0 136 virtual void blitRect(int x, int y, int width, int height);
michael@0 137
michael@0 138 private:
michael@0 139 typedef SkRGB16_Shader_Blitter INHERITED;
michael@0 140 };
michael@0 141
michael@0 142 class SkRGB16_Shader_Xfermode_Blitter : public SkShaderBlitter {
michael@0 143 public:
michael@0 144 SkRGB16_Shader_Xfermode_Blitter(const SkBitmap& device, const SkPaint& paint);
michael@0 145 virtual ~SkRGB16_Shader_Xfermode_Blitter();
michael@0 146 virtual void blitH(int x, int y, int width);
michael@0 147 virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
michael@0 148 const int16_t* runs);
michael@0 149
michael@0 150 private:
michael@0 151 SkXfermode* fXfermode;
michael@0 152 SkPMColor* fBuffer;
michael@0 153 uint8_t* fAAExpand;
michael@0 154
michael@0 155 // illegal
michael@0 156 SkRGB16_Shader_Xfermode_Blitter& operator=(const SkRGB16_Shader_Xfermode_Blitter&);
michael@0 157
michael@0 158 typedef SkShaderBlitter INHERITED;
michael@0 159 };
michael@0 160
michael@0 161 ///////////////////////////////////////////////////////////////////////////////
michael@0 162 #ifdef USE_BLACK_BLITTER
michael@0 163 SkRGB16_Black_Blitter::SkRGB16_Black_Blitter(const SkBitmap& device, const SkPaint& paint)
michael@0 164 : INHERITED(device, paint) {
michael@0 165 SkASSERT(paint.getShader() == NULL);
michael@0 166 SkASSERT(paint.getColorFilter() == NULL);
michael@0 167 SkASSERT(paint.getXfermode() == NULL);
michael@0 168 SkASSERT(paint.getColor() == SK_ColorBLACK);
michael@0 169 }
michael@0 170
michael@0 171 #if 1
michael@0 172 #define black_8_pixels(mask, dst) \
michael@0 173 do { \
michael@0 174 if (mask & 0x80) dst[0] = 0; \
michael@0 175 if (mask & 0x40) dst[1] = 0; \
michael@0 176 if (mask & 0x20) dst[2] = 0; \
michael@0 177 if (mask & 0x10) dst[3] = 0; \
michael@0 178 if (mask & 0x08) dst[4] = 0; \
michael@0 179 if (mask & 0x04) dst[5] = 0; \
michael@0 180 if (mask & 0x02) dst[6] = 0; \
michael@0 181 if (mask & 0x01) dst[7] = 0; \
michael@0 182 } while (0)
michael@0 183 #else
michael@0 184 static inline black_8_pixels(U8CPU mask, uint16_t dst[])
michael@0 185 {
michael@0 186 if (mask & 0x80) dst[0] = 0;
michael@0 187 if (mask & 0x40) dst[1] = 0;
michael@0 188 if (mask & 0x20) dst[2] = 0;
michael@0 189 if (mask & 0x10) dst[3] = 0;
michael@0 190 if (mask & 0x08) dst[4] = 0;
michael@0 191 if (mask & 0x04) dst[5] = 0;
michael@0 192 if (mask & 0x02) dst[6] = 0;
michael@0 193 if (mask & 0x01) dst[7] = 0;
michael@0 194 }
michael@0 195 #endif
michael@0 196
michael@0 197 #define SK_BLITBWMASK_NAME SkRGB16_Black_BlitBW
michael@0 198 #define SK_BLITBWMASK_ARGS
michael@0 199 #define SK_BLITBWMASK_BLIT8(mask, dst) black_8_pixels(mask, dst)
michael@0 200 #define SK_BLITBWMASK_GETADDR getAddr16
michael@0 201 #define SK_BLITBWMASK_DEVTYPE uint16_t
michael@0 202 #include "SkBlitBWMaskTemplate.h"
michael@0 203
michael@0 204 void SkRGB16_Black_Blitter::blitMask(const SkMask& mask,
michael@0 205 const SkIRect& clip) {
michael@0 206 if (mask.fFormat == SkMask::kBW_Format) {
michael@0 207 SkRGB16_Black_BlitBW(fDevice, mask, clip);
michael@0 208 } else {
michael@0 209 uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop);
michael@0 210 const uint8_t* SK_RESTRICT alpha = mask.getAddr8(clip.fLeft, clip.fTop);
michael@0 211 unsigned width = clip.width();
michael@0 212 unsigned height = clip.height();
michael@0 213 size_t deviceRB = fDevice.rowBytes() - (width << 1);
michael@0 214 unsigned maskRB = mask.fRowBytes - width;
michael@0 215
michael@0 216 SkASSERT((int)height > 0);
michael@0 217 SkASSERT((int)width > 0);
michael@0 218 SkASSERT((int)deviceRB >= 0);
michael@0 219 SkASSERT((int)maskRB >= 0);
michael@0 220
michael@0 221 do {
michael@0 222 unsigned w = width;
michael@0 223 do {
michael@0 224 unsigned aa = *alpha++;
michael@0 225 *device = SkAlphaMulRGB16(*device, SkAlpha255To256(255 - aa));
michael@0 226 device += 1;
michael@0 227 } while (--w != 0);
michael@0 228 device = (uint16_t*)((char*)device + deviceRB);
michael@0 229 alpha += maskRB;
michael@0 230 } while (--height != 0);
michael@0 231 }
michael@0 232 }
michael@0 233
michael@0 234 void SkRGB16_Black_Blitter::blitAntiH(int x, int y,
michael@0 235 const SkAlpha* SK_RESTRICT antialias,
michael@0 236 const int16_t* SK_RESTRICT runs) {
michael@0 237 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
michael@0 238
michael@0 239 for (;;) {
michael@0 240 int count = runs[0];
michael@0 241 SkASSERT(count >= 0);
michael@0 242 if (count <= 0) {
michael@0 243 return;
michael@0 244 }
michael@0 245 runs += count;
michael@0 246
michael@0 247 unsigned aa = antialias[0];
michael@0 248 antialias += count;
michael@0 249 if (aa) {
michael@0 250 if (aa == 255) {
michael@0 251 memset(device, 0, count << 1);
michael@0 252 } else {
michael@0 253 aa = SkAlpha255To256(255 - aa);
michael@0 254 do {
michael@0 255 *device = SkAlphaMulRGB16(*device, aa);
michael@0 256 device += 1;
michael@0 257 } while (--count != 0);
michael@0 258 continue;
michael@0 259 }
michael@0 260 }
michael@0 261 device += count;
michael@0 262 }
michael@0 263 }
michael@0 264 #endif
michael@0 265
michael@0 266 ///////////////////////////////////////////////////////////////////////////////
michael@0 267 ///////////////////////////////////////////////////////////////////////////////
michael@0 268
michael@0 269 SkRGB16_Opaque_Blitter::SkRGB16_Opaque_Blitter(const SkBitmap& device,
michael@0 270 const SkPaint& paint)
michael@0 271 : INHERITED(device, paint) {}
michael@0 272
michael@0 273 void SkRGB16_Opaque_Blitter::blitH(int x, int y, int width) {
michael@0 274 SkASSERT(width > 0);
michael@0 275 SkASSERT(x + width <= fDevice.width());
michael@0 276 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
michael@0 277 uint16_t srcColor = fColor16;
michael@0 278
michael@0 279 SkASSERT(fRawColor16 == srcColor);
michael@0 280 if (fDoDither) {
michael@0 281 uint16_t ditherColor = fRawDither16;
michael@0 282 if ((x ^ y) & 1) {
michael@0 283 SkTSwap(ditherColor, srcColor);
michael@0 284 }
michael@0 285 sk_dither_memset16(device, srcColor, ditherColor, width);
michael@0 286 } else {
michael@0 287 sk_memset16(device, srcColor, width);
michael@0 288 }
michael@0 289 }
michael@0 290
michael@0 291 // return 1 or 0 from a bool
michael@0 292 static inline int Bool2Int(int value) {
michael@0 293 return !!value;
michael@0 294 }
michael@0 295
michael@0 296 void SkRGB16_Opaque_Blitter::blitAntiH(int x, int y,
michael@0 297 const SkAlpha* SK_RESTRICT antialias,
michael@0 298 const int16_t* SK_RESTRICT runs) {
michael@0 299 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
michael@0 300 uint16_t srcColor = fRawColor16;
michael@0 301 uint32_t srcExpanded = fExpandedRaw16;
michael@0 302 int ditherInt = Bool2Int(fDoDither);
michael@0 303 uint16_t ditherColor = fRawDither16;
michael@0 304 // if we have no dithering, this will always fail
michael@0 305 if ((x ^ y) & ditherInt) {
michael@0 306 SkTSwap(ditherColor, srcColor);
michael@0 307 }
michael@0 308 for (;;) {
michael@0 309 int count = runs[0];
michael@0 310 SkASSERT(count >= 0);
michael@0 311 if (count <= 0) {
michael@0 312 return;
michael@0 313 }
michael@0 314 runs += count;
michael@0 315
michael@0 316 unsigned aa = antialias[0];
michael@0 317 antialias += count;
michael@0 318 if (aa) {
michael@0 319 if (aa == 255) {
michael@0 320 if (ditherInt) {
michael@0 321 sk_dither_memset16(device, srcColor,
michael@0 322 ditherColor, count);
michael@0 323 } else {
michael@0 324 sk_memset16(device, srcColor, count);
michael@0 325 }
michael@0 326 } else {
michael@0 327 // TODO: respect fDoDither
michael@0 328 unsigned scale5 = SkAlpha255To256(aa) >> 3;
michael@0 329 uint32_t src32 = srcExpanded * scale5;
michael@0 330 scale5 = 32 - scale5; // now we can use it on the device
michael@0 331 int n = count;
michael@0 332 do {
michael@0 333 uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
michael@0 334 *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
michael@0 335 } while (--n != 0);
michael@0 336 goto DONE;
michael@0 337 }
michael@0 338 }
michael@0 339 device += count;
michael@0 340
michael@0 341 DONE:
michael@0 342 // if we have no dithering, this will always fail
michael@0 343 if (count & ditherInt) {
michael@0 344 SkTSwap(ditherColor, srcColor);
michael@0 345 }
michael@0 346 }
michael@0 347 }
michael@0 348
michael@0 349 #define solid_8_pixels(mask, dst, color) \
michael@0 350 do { \
michael@0 351 if (mask & 0x80) dst[0] = color; \
michael@0 352 if (mask & 0x40) dst[1] = color; \
michael@0 353 if (mask & 0x20) dst[2] = color; \
michael@0 354 if (mask & 0x10) dst[3] = color; \
michael@0 355 if (mask & 0x08) dst[4] = color; \
michael@0 356 if (mask & 0x04) dst[5] = color; \
michael@0 357 if (mask & 0x02) dst[6] = color; \
michael@0 358 if (mask & 0x01) dst[7] = color; \
michael@0 359 } while (0)
michael@0 360
michael@0 361 #define SK_BLITBWMASK_NAME SkRGB16_BlitBW
michael@0 362 #define SK_BLITBWMASK_ARGS , uint16_t color
michael@0 363 #define SK_BLITBWMASK_BLIT8(mask, dst) solid_8_pixels(mask, dst, color)
michael@0 364 #define SK_BLITBWMASK_GETADDR getAddr16
michael@0 365 #define SK_BLITBWMASK_DEVTYPE uint16_t
michael@0 366 #include "SkBlitBWMaskTemplate.h"
michael@0 367
michael@0 368 static U16CPU blend_compact(uint32_t src32, uint32_t dst32, unsigned scale5) {
michael@0 369 return SkCompact_rgb_16(dst32 + ((src32 - dst32) * scale5 >> 5));
michael@0 370 }
michael@0 371
michael@0 372 void SkRGB16_Opaque_Blitter::blitMask(const SkMask& mask,
michael@0 373 const SkIRect& clip) {
michael@0 374 if (mask.fFormat == SkMask::kBW_Format) {
michael@0 375 SkRGB16_BlitBW(fDevice, mask, clip, fColor16);
michael@0 376 return;
michael@0 377 }
michael@0 378
michael@0 379 uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop);
michael@0 380 const uint8_t* SK_RESTRICT alpha = mask.getAddr8(clip.fLeft, clip.fTop);
michael@0 381 int width = clip.width();
michael@0 382 int height = clip.height();
michael@0 383 size_t deviceRB = fDevice.rowBytes() - (width << 1);
michael@0 384 unsigned maskRB = mask.fRowBytes - width;
michael@0 385 uint32_t expanded32 = fExpandedRaw16;
michael@0 386
michael@0 387 #ifdef SK_USE_NEON
michael@0 388 #define UNROLL 8
michael@0 389 do {
michael@0 390 int w = width;
michael@0 391 if (w >= UNROLL) {
michael@0 392 uint32x4_t color, dev_lo, dev_hi;
michael@0 393 uint32x4_t wn1, wn2, tmp;
michael@0 394 uint32x4_t vmask_g16, vmask_ng16;
michael@0 395 uint16x8_t valpha, vdev;
michael@0 396 uint16x4_t odev_lo, odev_hi, valpha_lo, valpha_hi;
michael@0 397
michael@0 398 // prepare constants
michael@0 399 vmask_g16 = vdupq_n_u32(SK_G16_MASK_IN_PLACE);
michael@0 400 vmask_ng16 = vdupq_n_u32(~SK_G16_MASK_IN_PLACE);
michael@0 401 color = vdupq_n_u32(expanded32);
michael@0 402
michael@0 403 do {
michael@0 404 // alpha is 8x8, widen and split to get a pair of 16x4
michael@0 405 valpha = vaddw_u8(vdupq_n_u16(1), vld1_u8(alpha));
michael@0 406 valpha = vshrq_n_u16(valpha, 3);
michael@0 407 valpha_lo = vget_low_u16(valpha);
michael@0 408 valpha_hi = vget_high_u16(valpha);
michael@0 409
michael@0 410 // load pixels
michael@0 411 vdev = vld1q_u16(device);
michael@0 412 dev_lo = vmovl_u16(vget_low_u16(vdev));
michael@0 413 dev_hi = vmovl_u16(vget_high_u16(vdev));
michael@0 414
michael@0 415 // unpack them in 32 bits
michael@0 416 dev_lo = (dev_lo & vmask_ng16) | vshlq_n_u32(dev_lo & vmask_g16, 16);
michael@0 417 dev_hi = (dev_hi & vmask_ng16) | vshlq_n_u32(dev_hi & vmask_g16, 16);
michael@0 418
michael@0 419 // blend with color
michael@0 420 tmp = (color - dev_lo) * vmovl_u16(valpha_lo);
michael@0 421 tmp = vshrq_n_u32(tmp, 5);
michael@0 422 dev_lo += tmp;
michael@0 423
michael@0 424 tmp = vmulq_u32(color - dev_hi, vmovl_u16(valpha_hi));
michael@0 425 tmp = vshrq_n_u32(tmp, 5);
michael@0 426 dev_hi += tmp;
michael@0 427
michael@0 428 // re-compact
michael@0 429 wn1 = dev_lo & vmask_ng16;
michael@0 430 wn2 = vshrq_n_u32(dev_lo, 16) & vmask_g16;
michael@0 431 odev_lo = vmovn_u32(wn1 | wn2);
michael@0 432
michael@0 433 wn1 = dev_hi & vmask_ng16;
michael@0 434 wn2 = vshrq_n_u32(dev_hi, 16) & vmask_g16;
michael@0 435 odev_hi = vmovn_u32(wn1 | wn2);
michael@0 436
michael@0 437 // store
michael@0 438 vst1q_u16(device, vcombine_u16(odev_lo, odev_hi));
michael@0 439
michael@0 440 device += UNROLL;
michael@0 441 alpha += UNROLL;
michael@0 442 w -= UNROLL;
michael@0 443 } while (w >= UNROLL);
michael@0 444 }
michael@0 445
michael@0 446 // residuals
michael@0 447 while (w > 0) {
michael@0 448 *device = blend_compact(expanded32, SkExpand_rgb_16(*device),
michael@0 449 SkAlpha255To256(*alpha++) >> 3);
michael@0 450 device += 1;
michael@0 451 --w;
michael@0 452 }
michael@0 453 device = (uint16_t*)((char*)device + deviceRB);
michael@0 454 alpha += maskRB;
michael@0 455 } while (--height != 0);
michael@0 456 #undef UNROLL
michael@0 457 #else // non-neon code
michael@0 458 do {
michael@0 459 int w = width;
michael@0 460 do {
michael@0 461 *device = blend_compact(expanded32, SkExpand_rgb_16(*device),
michael@0 462 SkAlpha255To256(*alpha++) >> 3);
michael@0 463 device += 1;
michael@0 464 } while (--w != 0);
michael@0 465 device = (uint16_t*)((char*)device + deviceRB);
michael@0 466 alpha += maskRB;
michael@0 467 } while (--height != 0);
michael@0 468 #endif
michael@0 469 }
michael@0 470
michael@0 471 void SkRGB16_Opaque_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
michael@0 472 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
michael@0 473 size_t deviceRB = fDevice.rowBytes();
michael@0 474
michael@0 475 // TODO: respect fDoDither
michael@0 476 unsigned scale5 = SkAlpha255To256(alpha) >> 3;
michael@0 477 uint32_t src32 = fExpandedRaw16 * scale5;
michael@0 478 scale5 = 32 - scale5;
michael@0 479 do {
michael@0 480 uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
michael@0 481 *device = SkCompact_rgb_16((src32 + dst32) >> 5);
michael@0 482 device = (uint16_t*)((char*)device + deviceRB);
michael@0 483 } while (--height != 0);
michael@0 484 }
michael@0 485
michael@0 486 void SkRGB16_Opaque_Blitter::blitRect(int x, int y, int width, int height) {
michael@0 487 SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height());
michael@0 488 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
michael@0 489 size_t deviceRB = fDevice.rowBytes();
michael@0 490 uint16_t color16 = fColor16;
michael@0 491
michael@0 492 if (fDoDither) {
michael@0 493 uint16_t ditherColor = fRawDither16;
michael@0 494 if ((x ^ y) & 1) {
michael@0 495 SkTSwap(ditherColor, color16);
michael@0 496 }
michael@0 497 while (--height >= 0) {
michael@0 498 sk_dither_memset16(device, color16, ditherColor, width);
michael@0 499 SkTSwap(ditherColor, color16);
michael@0 500 device = (uint16_t*)((char*)device + deviceRB);
michael@0 501 }
michael@0 502 } else { // no dither
michael@0 503 while (--height >= 0) {
michael@0 504 sk_memset16(device, color16, width);
michael@0 505 device = (uint16_t*)((char*)device + deviceRB);
michael@0 506 }
michael@0 507 }
michael@0 508 }
michael@0 509
michael@0 510 ///////////////////////////////////////////////////////////////////////////////
michael@0 511
michael@0 512 SkRGB16_Blitter::SkRGB16_Blitter(const SkBitmap& device, const SkPaint& paint)
michael@0 513 : INHERITED(device) {
michael@0 514 SkColor color = paint.getColor();
michael@0 515
michael@0 516 fSrcColor32 = SkPreMultiplyColor(color);
michael@0 517 fScale = SkAlpha255To256(SkColorGetA(color));
michael@0 518
michael@0 519 int r = SkColorGetR(color);
michael@0 520 int g = SkColorGetG(color);
michael@0 521 int b = SkColorGetB(color);
michael@0 522
michael@0 523 fRawColor16 = fRawDither16 = SkPack888ToRGB16(r, g, b);
michael@0 524 // if we're dithered, use fRawDither16 to hold that.
michael@0 525 if ((fDoDither = paint.isDither()) != false) {
michael@0 526 fRawDither16 = SkDitherPack888ToRGB16(r, g, b);
michael@0 527 }
michael@0 528
michael@0 529 fExpandedRaw16 = SkExpand_rgb_16(fRawColor16);
michael@0 530
michael@0 531 fColor16 = SkPackRGB16( SkAlphaMul(r, fScale) >> (8 - SK_R16_BITS),
michael@0 532 SkAlphaMul(g, fScale) >> (8 - SK_G16_BITS),
michael@0 533 SkAlphaMul(b, fScale) >> (8 - SK_B16_BITS));
michael@0 534 }
michael@0 535
michael@0 536 const SkBitmap* SkRGB16_Blitter::justAnOpaqueColor(uint32_t* value) {
michael@0 537 if (!fDoDither && 256 == fScale) {
michael@0 538 *value = fRawColor16;
michael@0 539 return &fDevice;
michael@0 540 }
michael@0 541 return NULL;
michael@0 542 }
michael@0 543
michael@0 544 static uint32_t pmcolor_to_expand16(SkPMColor c) {
michael@0 545 unsigned r = SkGetPackedR32(c);
michael@0 546 unsigned g = SkGetPackedG32(c);
michael@0 547 unsigned b = SkGetPackedB32(c);
michael@0 548 return (g << 24) | (r << 13) | (b << 2);
michael@0 549 }
michael@0 550
michael@0 551 static inline void blend32_16_row(SkPMColor src, uint16_t dst[], int count) {
michael@0 552 SkASSERT(count > 0);
michael@0 553 uint32_t src_expand = pmcolor_to_expand16(src);
michael@0 554 unsigned scale = SkAlpha255To256(0xFF - SkGetPackedA32(src)) >> 3;
michael@0 555 do {
michael@0 556 uint32_t dst_expand = SkExpand_rgb_16(*dst) * scale;
michael@0 557 *dst = SkCompact_rgb_16((src_expand + dst_expand) >> 5);
michael@0 558 dst += 1;
michael@0 559 } while (--count != 0);
michael@0 560 }
michael@0 561
michael@0 562 void SkRGB16_Blitter::blitH(int x, int y, int width) {
michael@0 563 SkASSERT(width > 0);
michael@0 564 SkASSERT(x + width <= fDevice.width());
michael@0 565 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
michael@0 566
michael@0 567 // TODO: respect fDoDither
michael@0 568 blend32_16_row(fSrcColor32, device, width);
michael@0 569 }
michael@0 570
michael@0 571 void SkRGB16_Blitter::blitAntiH(int x, int y,
michael@0 572 const SkAlpha* SK_RESTRICT antialias,
michael@0 573 const int16_t* SK_RESTRICT runs) {
michael@0 574 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
michael@0 575 uint32_t srcExpanded = fExpandedRaw16;
michael@0 576 unsigned scale = fScale;
michael@0 577
michael@0 578 // TODO: respect fDoDither
michael@0 579 for (;;) {
michael@0 580 int count = runs[0];
michael@0 581 SkASSERT(count >= 0);
michael@0 582 if (count <= 0) {
michael@0 583 return;
michael@0 584 }
michael@0 585 runs += count;
michael@0 586
michael@0 587 unsigned aa = antialias[0];
michael@0 588 antialias += count;
michael@0 589 if (aa) {
michael@0 590 unsigned scale5 = SkAlpha255To256(aa) * scale >> (8 + 3);
michael@0 591 uint32_t src32 = srcExpanded * scale5;
michael@0 592 scale5 = 32 - scale5;
michael@0 593 do {
michael@0 594 uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
michael@0 595 *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
michael@0 596 } while (--count != 0);
michael@0 597 continue;
michael@0 598 }
michael@0 599 device += count;
michael@0 600 }
michael@0 601 }
michael@0 602
michael@0 603 static inline void blend_8_pixels(U8CPU bw, uint16_t dst[], unsigned dst_scale,
michael@0 604 U16CPU srcColor) {
michael@0 605 if (bw & 0x80) dst[0] = srcColor + SkAlphaMulRGB16(dst[0], dst_scale);
michael@0 606 if (bw & 0x40) dst[1] = srcColor + SkAlphaMulRGB16(dst[1], dst_scale);
michael@0 607 if (bw & 0x20) dst[2] = srcColor + SkAlphaMulRGB16(dst[2], dst_scale);
michael@0 608 if (bw & 0x10) dst[3] = srcColor + SkAlphaMulRGB16(dst[3], dst_scale);
michael@0 609 if (bw & 0x08) dst[4] = srcColor + SkAlphaMulRGB16(dst[4], dst_scale);
michael@0 610 if (bw & 0x04) dst[5] = srcColor + SkAlphaMulRGB16(dst[5], dst_scale);
michael@0 611 if (bw & 0x02) dst[6] = srcColor + SkAlphaMulRGB16(dst[6], dst_scale);
michael@0 612 if (bw & 0x01) dst[7] = srcColor + SkAlphaMulRGB16(dst[7], dst_scale);
michael@0 613 }
michael@0 614
michael@0 615 #define SK_BLITBWMASK_NAME SkRGB16_BlendBW
michael@0 616 #define SK_BLITBWMASK_ARGS , unsigned dst_scale, U16CPU src_color
michael@0 617 #define SK_BLITBWMASK_BLIT8(mask, dst) blend_8_pixels(mask, dst, dst_scale, src_color)
michael@0 618 #define SK_BLITBWMASK_GETADDR getAddr16
michael@0 619 #define SK_BLITBWMASK_DEVTYPE uint16_t
michael@0 620 #include "SkBlitBWMaskTemplate.h"
michael@0 621
michael@0 622 void SkRGB16_Blitter::blitMask(const SkMask& mask,
michael@0 623 const SkIRect& clip) {
michael@0 624 if (mask.fFormat == SkMask::kBW_Format) {
michael@0 625 SkRGB16_BlendBW(fDevice, mask, clip, 256 - fScale, fColor16);
michael@0 626 return;
michael@0 627 }
michael@0 628
michael@0 629 uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop);
michael@0 630 const uint8_t* SK_RESTRICT alpha = mask.getAddr8(clip.fLeft, clip.fTop);
michael@0 631 int width = clip.width();
michael@0 632 int height = clip.height();
michael@0 633 size_t deviceRB = fDevice.rowBytes() - (width << 1);
michael@0 634 unsigned maskRB = mask.fRowBytes - width;
michael@0 635 uint32_t color32 = fExpandedRaw16;
michael@0 636
michael@0 637 unsigned scale256 = fScale;
michael@0 638 do {
michael@0 639 int w = width;
michael@0 640 do {
michael@0 641 unsigned aa = *alpha++;
michael@0 642 unsigned scale = SkAlpha255To256(aa) * scale256 >> (8 + 3);
michael@0 643 uint32_t src32 = color32 * scale;
michael@0 644 uint32_t dst32 = SkExpand_rgb_16(*device) * (32 - scale);
michael@0 645 *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
michael@0 646 } while (--w != 0);
michael@0 647 device = (uint16_t*)((char*)device + deviceRB);
michael@0 648 alpha += maskRB;
michael@0 649 } while (--height != 0);
michael@0 650 }
michael@0 651
michael@0 652 void SkRGB16_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
michael@0 653 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
michael@0 654 size_t deviceRB = fDevice.rowBytes();
michael@0 655
michael@0 656 // TODO: respect fDoDither
michael@0 657 unsigned scale5 = SkAlpha255To256(alpha) * fScale >> (8 + 3);
michael@0 658 uint32_t src32 = fExpandedRaw16 * scale5;
michael@0 659 scale5 = 32 - scale5;
michael@0 660 do {
michael@0 661 uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
michael@0 662 *device = SkCompact_rgb_16((src32 + dst32) >> 5);
michael@0 663 device = (uint16_t*)((char*)device + deviceRB);
michael@0 664 } while (--height != 0);
michael@0 665 }
michael@0 666
michael@0 667 void SkRGB16_Blitter::blitRect(int x, int y, int width, int height) {
michael@0 668 SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height());
michael@0 669 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
michael@0 670 size_t deviceRB = fDevice.rowBytes();
michael@0 671 SkPMColor src32 = fSrcColor32;
michael@0 672
michael@0 673 while (--height >= 0) {
michael@0 674 blend32_16_row(src32, device, width);
michael@0 675 device = (uint16_t*)((char*)device + deviceRB);
michael@0 676 }
michael@0 677 }
michael@0 678
michael@0 679 ///////////////////////////////////////////////////////////////////////////////
michael@0 680
michael@0 681 SkRGB16_Shader16_Blitter::SkRGB16_Shader16_Blitter(const SkBitmap& device,
michael@0 682 const SkPaint& paint)
michael@0 683 : SkRGB16_Shader_Blitter(device, paint) {
michael@0 684 SkASSERT(SkShader::CanCallShadeSpan16(fShaderFlags));
michael@0 685 }
michael@0 686
michael@0 687 void SkRGB16_Shader16_Blitter::blitH(int x, int y, int width) {
michael@0 688 SkASSERT(x + width <= fDevice.width());
michael@0 689
michael@0 690 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
michael@0 691 SkShader* shader = fShader;
michael@0 692
michael@0 693 int alpha = shader->getSpan16Alpha();
michael@0 694 if (0xFF == alpha) {
michael@0 695 shader->shadeSpan16(x, y, device, width);
michael@0 696 } else {
michael@0 697 uint16_t* span16 = (uint16_t*)fBuffer;
michael@0 698 shader->shadeSpan16(x, y, span16, width);
michael@0 699 SkBlendRGB16(span16, device, SkAlpha255To256(alpha), width);
michael@0 700 }
michael@0 701 }
michael@0 702
michael@0 703 void SkRGB16_Shader16_Blitter::blitRect(int x, int y, int width, int height) {
michael@0 704 SkShader* shader = fShader;
michael@0 705 uint16_t* dst = fDevice.getAddr16(x, y);
michael@0 706 size_t dstRB = fDevice.rowBytes();
michael@0 707 int alpha = shader->getSpan16Alpha();
michael@0 708
michael@0 709 if (0xFF == alpha) {
michael@0 710 if (fShaderFlags & SkShader::kConstInY16_Flag) {
michael@0 711 // have the shader blit directly into the device the first time
michael@0 712 shader->shadeSpan16(x, y, dst, width);
michael@0 713 // and now just memcpy that line on the subsequent lines
michael@0 714 if (--height > 0) {
michael@0 715 const uint16_t* orig = dst;
michael@0 716 do {
michael@0 717 dst = (uint16_t*)((char*)dst + dstRB);
michael@0 718 memcpy(dst, orig, width << 1);
michael@0 719 } while (--height);
michael@0 720 }
michael@0 721 } else { // need to call shadeSpan16 for every line
michael@0 722 do {
michael@0 723 shader->shadeSpan16(x, y, dst, width);
michael@0 724 y += 1;
michael@0 725 dst = (uint16_t*)((char*)dst + dstRB);
michael@0 726 } while (--height);
michael@0 727 }
michael@0 728 } else {
michael@0 729 int scale = SkAlpha255To256(alpha);
michael@0 730 uint16_t* span16 = (uint16_t*)fBuffer;
michael@0 731 if (fShaderFlags & SkShader::kConstInY16_Flag) {
michael@0 732 shader->shadeSpan16(x, y, span16, width);
michael@0 733 do {
michael@0 734 SkBlendRGB16(span16, dst, scale, width);
michael@0 735 dst = (uint16_t*)((char*)dst + dstRB);
michael@0 736 } while (--height);
michael@0 737 } else {
michael@0 738 do {
michael@0 739 shader->shadeSpan16(x, y, span16, width);
michael@0 740 SkBlendRGB16(span16, dst, scale, width);
michael@0 741 y += 1;
michael@0 742 dst = (uint16_t*)((char*)dst + dstRB);
michael@0 743 } while (--height);
michael@0 744 }
michael@0 745 }
michael@0 746 }
michael@0 747
michael@0 748 void SkRGB16_Shader16_Blitter::blitAntiH(int x, int y,
michael@0 749 const SkAlpha* SK_RESTRICT antialias,
michael@0 750 const int16_t* SK_RESTRICT runs) {
michael@0 751 SkShader* shader = fShader;
michael@0 752 SkPMColor* SK_RESTRICT span = fBuffer;
michael@0 753 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
michael@0 754
michael@0 755 int alpha = shader->getSpan16Alpha();
michael@0 756 uint16_t* span16 = (uint16_t*)span;
michael@0 757
michael@0 758 if (0xFF == alpha) {
michael@0 759 for (;;) {
michael@0 760 int count = *runs;
michael@0 761 if (count <= 0) {
michael@0 762 break;
michael@0 763 }
michael@0 764 SkASSERT(count <= fDevice.width()); // don't overrun fBuffer
michael@0 765
michael@0 766 int aa = *antialias;
michael@0 767 if (aa == 255) {
michael@0 768 // go direct to the device!
michael@0 769 shader->shadeSpan16(x, y, device, count);
michael@0 770 } else if (aa) {
michael@0 771 shader->shadeSpan16(x, y, span16, count);
michael@0 772 SkBlendRGB16(span16, device, SkAlpha255To256(aa), count);
michael@0 773 }
michael@0 774 device += count;
michael@0 775 runs += count;
michael@0 776 antialias += count;
michael@0 777 x += count;
michael@0 778 }
michael@0 779 } else { // span alpha is < 255
michael@0 780 alpha = SkAlpha255To256(alpha);
michael@0 781 for (;;) {
michael@0 782 int count = *runs;
michael@0 783 if (count <= 0) {
michael@0 784 break;
michael@0 785 }
michael@0 786 SkASSERT(count <= fDevice.width()); // don't overrun fBuffer
michael@0 787
michael@0 788 int aa = SkAlphaMul(*antialias, alpha);
michael@0 789 if (aa) {
michael@0 790 shader->shadeSpan16(x, y, span16, count);
michael@0 791 SkBlendRGB16(span16, device, SkAlpha255To256(aa), count);
michael@0 792 }
michael@0 793
michael@0 794 device += count;
michael@0 795 runs += count;
michael@0 796 antialias += count;
michael@0 797 x += count;
michael@0 798 }
michael@0 799 }
michael@0 800 }
michael@0 801
michael@0 802 ///////////////////////////////////////////////////////////////////////////////
michael@0 803
michael@0 804 SkRGB16_Shader_Blitter::SkRGB16_Shader_Blitter(const SkBitmap& device,
michael@0 805 const SkPaint& paint)
michael@0 806 : INHERITED(device, paint) {
michael@0 807 SkASSERT(paint.getXfermode() == NULL);
michael@0 808
michael@0 809 fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * sizeof(SkPMColor));
michael@0 810
michael@0 811 // compute SkBlitRow::Procs
michael@0 812 unsigned flags = 0;
michael@0 813
michael@0 814 uint32_t shaderFlags = fShaderFlags;
michael@0 815 // shaders take care of global alpha, so we never set it in SkBlitRow
michael@0 816 if (!(shaderFlags & SkShader::kOpaqueAlpha_Flag)) {
michael@0 817 flags |= SkBlitRow::kSrcPixelAlpha_Flag;
michael@0 818 }
michael@0 819 // don't dither if the shader is really 16bit
michael@0 820 if (paint.isDither() && !(shaderFlags & SkShader::kIntrinsicly16_Flag)) {
michael@0 821 flags |= SkBlitRow::kDither_Flag;
michael@0 822 }
michael@0 823 // used when we know our global alpha is 0xFF
michael@0 824 fOpaqueProc = SkBlitRow::Factory(flags, SkBitmap::kRGB_565_Config);
michael@0 825 // used when we know our global alpha is < 0xFF
michael@0 826 fAlphaProc = SkBlitRow::Factory(flags | SkBlitRow::kGlobalAlpha_Flag,
michael@0 827 SkBitmap::kRGB_565_Config);
michael@0 828 }
michael@0 829
michael@0 830 SkRGB16_Shader_Blitter::~SkRGB16_Shader_Blitter() {
michael@0 831 sk_free(fBuffer);
michael@0 832 }
michael@0 833
michael@0 834 void SkRGB16_Shader_Blitter::blitH(int x, int y, int width) {
michael@0 835 SkASSERT(x + width <= fDevice.width());
michael@0 836
michael@0 837 fShader->shadeSpan(x, y, fBuffer, width);
michael@0 838 // shaders take care of global alpha, so we pass 0xFF (should be ignored)
michael@0 839 fOpaqueProc(fDevice.getAddr16(x, y), fBuffer, width, 0xFF, x, y);
michael@0 840 }
michael@0 841
michael@0 842 void SkRGB16_Shader_Blitter::blitRect(int x, int y, int width, int height) {
michael@0 843 SkShader* shader = fShader;
michael@0 844 SkBlitRow::Proc proc = fOpaqueProc;
michael@0 845 SkPMColor* buffer = fBuffer;
michael@0 846 uint16_t* dst = fDevice.getAddr16(x, y);
michael@0 847 size_t dstRB = fDevice.rowBytes();
michael@0 848
michael@0 849 if (fShaderFlags & SkShader::kConstInY32_Flag) {
michael@0 850 shader->shadeSpan(x, y, buffer, width);
michael@0 851 do {
michael@0 852 proc(dst, buffer, width, 0xFF, x, y);
michael@0 853 y += 1;
michael@0 854 dst = (uint16_t*)((char*)dst + dstRB);
michael@0 855 } while (--height);
michael@0 856 } else {
michael@0 857 do {
michael@0 858 shader->shadeSpan(x, y, buffer, width);
michael@0 859 proc(dst, buffer, width, 0xFF, x, y);
michael@0 860 y += 1;
michael@0 861 dst = (uint16_t*)((char*)dst + dstRB);
michael@0 862 } while (--height);
michael@0 863 }
michael@0 864 }
michael@0 865
michael@0 866 static inline int count_nonzero_span(const int16_t runs[], const SkAlpha aa[]) {
michael@0 867 int count = 0;
michael@0 868 for (;;) {
michael@0 869 int n = *runs;
michael@0 870 if (n == 0 || *aa == 0) {
michael@0 871 break;
michael@0 872 }
michael@0 873 runs += n;
michael@0 874 aa += n;
michael@0 875 count += n;
michael@0 876 }
michael@0 877 return count;
michael@0 878 }
michael@0 879
michael@0 880 void SkRGB16_Shader_Blitter::blitAntiH(int x, int y,
michael@0 881 const SkAlpha* SK_RESTRICT antialias,
michael@0 882 const int16_t* SK_RESTRICT runs) {
michael@0 883 SkShader* shader = fShader;
michael@0 884 SkPMColor* SK_RESTRICT span = fBuffer;
michael@0 885 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
michael@0 886
michael@0 887 for (;;) {
michael@0 888 int count = *runs;
michael@0 889 if (count <= 0) {
michael@0 890 break;
michael@0 891 }
michael@0 892 int aa = *antialias;
michael@0 893 if (0 == aa) {
michael@0 894 device += count;
michael@0 895 runs += count;
michael@0 896 antialias += count;
michael@0 897 x += count;
michael@0 898 continue;
michael@0 899 }
michael@0 900
michael@0 901 int nonZeroCount = count + count_nonzero_span(runs + count, antialias + count);
michael@0 902
michael@0 903 SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
michael@0 904 shader->shadeSpan(x, y, span, nonZeroCount);
michael@0 905
michael@0 906 SkPMColor* localSpan = span;
michael@0 907 for (;;) {
michael@0 908 SkBlitRow::Proc proc = (aa == 0xFF) ? fOpaqueProc : fAlphaProc;
michael@0 909 proc(device, localSpan, count, aa, x, y);
michael@0 910
michael@0 911 x += count;
michael@0 912 device += count;
michael@0 913 runs += count;
michael@0 914 antialias += count;
michael@0 915 nonZeroCount -= count;
michael@0 916 if (nonZeroCount == 0) {
michael@0 917 break;
michael@0 918 }
michael@0 919 localSpan += count;
michael@0 920 SkASSERT(nonZeroCount > 0);
michael@0 921 count = *runs;
michael@0 922 SkASSERT(count > 0);
michael@0 923 aa = *antialias;
michael@0 924 }
michael@0 925 }
michael@0 926 }
michael@0 927
michael@0 928 ///////////////////////////////////////////////////////////////////////
michael@0 929
michael@0 930 SkRGB16_Shader_Xfermode_Blitter::SkRGB16_Shader_Xfermode_Blitter(
michael@0 931 const SkBitmap& device, const SkPaint& paint)
michael@0 932 : INHERITED(device, paint) {
michael@0 933 fXfermode = paint.getXfermode();
michael@0 934 SkASSERT(fXfermode);
michael@0 935 fXfermode->ref();
michael@0 936
michael@0 937 int width = device.width();
michael@0 938 fBuffer = (SkPMColor*)sk_malloc_throw((width + (SkAlign4(width) >> 2)) * sizeof(SkPMColor));
michael@0 939 fAAExpand = (uint8_t*)(fBuffer + width);
michael@0 940 }
michael@0 941
michael@0 942 SkRGB16_Shader_Xfermode_Blitter::~SkRGB16_Shader_Xfermode_Blitter() {
michael@0 943 fXfermode->unref();
michael@0 944 sk_free(fBuffer);
michael@0 945 }
michael@0 946
michael@0 947 void SkRGB16_Shader_Xfermode_Blitter::blitH(int x, int y, int width) {
michael@0 948 SkASSERT(x + width <= fDevice.width());
michael@0 949
michael@0 950 uint16_t* device = fDevice.getAddr16(x, y);
michael@0 951 SkPMColor* span = fBuffer;
michael@0 952
michael@0 953 fShader->shadeSpan(x, y, span, width);
michael@0 954 fXfermode->xfer16(device, span, width, NULL);
michael@0 955 }
michael@0 956
michael@0 957 void SkRGB16_Shader_Xfermode_Blitter::blitAntiH(int x, int y,
michael@0 958 const SkAlpha* SK_RESTRICT antialias,
michael@0 959 const int16_t* SK_RESTRICT runs) {
michael@0 960 SkShader* shader = fShader;
michael@0 961 SkXfermode* mode = fXfermode;
michael@0 962 SkPMColor* SK_RESTRICT span = fBuffer;
michael@0 963 uint8_t* SK_RESTRICT aaExpand = fAAExpand;
michael@0 964 uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
michael@0 965
michael@0 966 for (;;) {
michael@0 967 int count = *runs;
michael@0 968 if (count <= 0) {
michael@0 969 break;
michael@0 970 }
michael@0 971 int aa = *antialias;
michael@0 972 if (0 == aa) {
michael@0 973 device += count;
michael@0 974 runs += count;
michael@0 975 antialias += count;
michael@0 976 x += count;
michael@0 977 continue;
michael@0 978 }
michael@0 979
michael@0 980 int nonZeroCount = count + count_nonzero_span(runs + count,
michael@0 981 antialias + count);
michael@0 982
michael@0 983 SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
michael@0 984 shader->shadeSpan(x, y, span, nonZeroCount);
michael@0 985
michael@0 986 x += nonZeroCount;
michael@0 987 SkPMColor* localSpan = span;
michael@0 988 for (;;) {
michael@0 989 if (aa == 0xFF) {
michael@0 990 mode->xfer16(device, localSpan, count, NULL);
michael@0 991 } else {
michael@0 992 SkASSERT(aa);
michael@0 993 memset(aaExpand, aa, count);
michael@0 994 mode->xfer16(device, localSpan, count, aaExpand);
michael@0 995 }
michael@0 996 device += count;
michael@0 997 runs += count;
michael@0 998 antialias += count;
michael@0 999 nonZeroCount -= count;
michael@0 1000 if (nonZeroCount == 0) {
michael@0 1001 break;
michael@0 1002 }
michael@0 1003 localSpan += count;
michael@0 1004 SkASSERT(nonZeroCount > 0);
michael@0 1005 count = *runs;
michael@0 1006 SkASSERT(count > 0);
michael@0 1007 aa = *antialias;
michael@0 1008 }
michael@0 1009 }
michael@0 1010 }
michael@0 1011
michael@0 1012 ///////////////////////////////////////////////////////////////////////////////
michael@0 1013
michael@0 1014 SkBlitter* SkBlitter_ChooseD565(const SkBitmap& device, const SkPaint& paint,
michael@0 1015 SkTBlitterAllocator* allocator) {
michael@0 1016 SkASSERT(allocator != NULL);
michael@0 1017
michael@0 1018 SkBlitter* blitter;
michael@0 1019 SkShader* shader = paint.getShader();
michael@0 1020 SkXfermode* mode = paint.getXfermode();
michael@0 1021
michael@0 1022 // we require a shader if there is an xfermode, handled by our caller
michael@0 1023 SkASSERT(NULL == mode || NULL != shader);
michael@0 1024
michael@0 1025 if (shader) {
michael@0 1026 if (mode) {
michael@0 1027 blitter = allocator->createT<SkRGB16_Shader_Xfermode_Blitter>(device, paint);
michael@0 1028 } else if (shader->canCallShadeSpan16()) {
michael@0 1029 blitter = allocator->createT<SkRGB16_Shader16_Blitter>(device, paint);
michael@0 1030 } else {
michael@0 1031 blitter = allocator->createT<SkRGB16_Shader_Blitter>(device, paint);
michael@0 1032 }
michael@0 1033 } else {
michael@0 1034 // no shader, no xfermode, (and we always ignore colorfilter)
michael@0 1035 SkColor color = paint.getColor();
michael@0 1036 if (0 == SkColorGetA(color)) {
michael@0 1037 blitter = allocator->createT<SkNullBlitter>();
michael@0 1038 #ifdef USE_BLACK_BLITTER
michael@0 1039 } else if (SK_ColorBLACK == color) {
michael@0 1040 blitter = allocator->createT<SkRGB16_Black_Blitter>(device, paint);
michael@0 1041 #endif
michael@0 1042 } else if (0xFF == SkColorGetA(color)) {
michael@0 1043 blitter = allocator->createT<SkRGB16_Opaque_Blitter>(device, paint);
michael@0 1044 } else {
michael@0 1045 blitter = allocator->createT<SkRGB16_Blitter>(device, paint);
michael@0 1046 }
michael@0 1047 }
michael@0 1048
michael@0 1049 return blitter;
michael@0 1050 }

mercurial