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