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