Line data Source code
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 :
30 0 : void sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other,
31 : int count) {
32 0 : 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 0 : if (((char*)dst - (char*)0) & 2) {
37 0 : *dst++ = value;
38 0 : count -= 1;
39 0 : 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 0 : sk_memset32((uint32_t*)dst, (other << 16) | value, count >> 1);
47 : #endif
48 :
49 0 : if (count & 1) {
50 0 : dst[count - 1] = value;
51 : }
52 : }
53 0 : }
54 :
55 : ///////////////////////////////////////////////////////////////////////////////
56 :
57 0 : 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 0 : 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 0 : 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
154 0 : SkRGB16_Black_Blitter::SkRGB16_Black_Blitter(const SkPixmap& device, const SkPaint& paint)
155 0 : : INHERITED(device, paint) {
156 0 : SkASSERT(paint.getShader() == nullptr);
157 0 : SkASSERT(paint.getColorFilter() == nullptr);
158 0 : SkASSERT(paint.isSrcOver());
159 0 : SkASSERT(paint.getColor() == SK_ColorBLACK);
160 0 : }
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
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 :
195 0 : void SkRGB16_Black_Blitter::blitMask(const SkMask& mask,
196 : const SkIRect& clip) {
197 0 : if (mask.fFormat == SkMask::kBW_Format) {
198 0 : SkRGB16_Black_BlitBW(fDevice, mask, clip);
199 : } else {
200 0 : uint16_t* SK_RESTRICT device = fDevice.writable_addr16(clip.fLeft, clip.fTop);
201 0 : const uint8_t* SK_RESTRICT alpha = mask.getAddr8(clip.fLeft, clip.fTop);
202 0 : unsigned width = clip.width();
203 0 : unsigned height = clip.height();
204 0 : size_t deviceRB = fDevice.rowBytes() - (width << 1);
205 0 : unsigned maskRB = mask.fRowBytes - width;
206 :
207 0 : SkASSERT((int)height > 0);
208 0 : SkASSERT((int)width > 0);
209 0 : SkASSERT((int)deviceRB >= 0);
210 0 : SkASSERT((int)maskRB >= 0);
211 :
212 0 : do {
213 0 : unsigned w = width;
214 0 : do {
215 0 : unsigned aa = *alpha++;
216 0 : *device = SkAlphaMulRGB16(*device, SkAlpha255To256(255 - aa));
217 0 : device += 1;
218 : } while (--w != 0);
219 0 : device = (uint16_t*)((char*)device + deviceRB);
220 0 : alpha += maskRB;
221 : } while (--height != 0);
222 : }
223 0 : }
224 :
225 0 : void SkRGB16_Black_Blitter::blitAntiH(int x, int y,
226 : const SkAlpha* SK_RESTRICT antialias,
227 : const int16_t* SK_RESTRICT runs) {
228 0 : uint16_t* SK_RESTRICT device = fDevice.writable_addr16(x, y);
229 :
230 : for (;;) {
231 0 : int count = runs[0];
232 0 : SkASSERT(count >= 0);
233 0 : if (count <= 0) {
234 0 : return;
235 : }
236 0 : runs += count;
237 :
238 0 : unsigned aa = antialias[0];
239 0 : antialias += count;
240 0 : if (aa) {
241 0 : if (aa == 255) {
242 0 : memset(device, 0, count << 1);
243 : } else {
244 0 : aa = SkAlpha255To256(255 - aa);
245 0 : do {
246 0 : *device = SkAlphaMulRGB16(*device, aa);
247 0 : device += 1;
248 : } while (--count != 0);
249 0 : continue;
250 : }
251 : }
252 0 : device += count;
253 0 : }
254 : }
255 : #endif
256 :
257 : ///////////////////////////////////////////////////////////////////////////////
258 : ///////////////////////////////////////////////////////////////////////////////
259 :
260 0 : SkRGB16_Opaque_Blitter::SkRGB16_Opaque_Blitter(const SkPixmap& device, const SkPaint& paint)
261 0 : : INHERITED(device, paint) {}
262 :
263 0 : void SkRGB16_Opaque_Blitter::blitH(int x, int y, int width) {
264 0 : SkASSERT(width > 0);
265 0 : SkASSERT(x + width <= fDevice.width());
266 0 : uint16_t* SK_RESTRICT device = fDevice.writable_addr16(x, y);
267 0 : uint16_t srcColor = fColor16;
268 :
269 0 : SkASSERT(fRawColor16 == srcColor);
270 0 : if (fDoDither) {
271 0 : uint16_t ditherColor = fRawDither16;
272 0 : if ((x ^ y) & 1) {
273 0 : SkTSwap(ditherColor, srcColor);
274 : }
275 0 : sk_dither_memset16(device, srcColor, ditherColor, width);
276 : } else {
277 0 : sk_memset16(device, srcColor, width);
278 : }
279 0 : }
280 :
281 : // return 1 or 0 from a bool
282 0 : static inline int Bool2Int(int value) {
283 0 : return !!value;
284 : }
285 :
286 0 : void SkRGB16_Opaque_Blitter::blitAntiH(int x, int y,
287 : const SkAlpha* SK_RESTRICT antialias,
288 : const int16_t* SK_RESTRICT runs) {
289 0 : uint16_t* SK_RESTRICT device = fDevice.writable_addr16(x, y);
290 0 : uint16_t srcColor = fRawColor16;
291 0 : uint32_t srcExpanded = fExpandedRaw16;
292 0 : int ditherInt = Bool2Int(fDoDither);
293 0 : uint16_t ditherColor = fRawDither16;
294 : // if we have no dithering, this will always fail
295 0 : if ((x ^ y) & ditherInt) {
296 0 : SkTSwap(ditherColor, srcColor);
297 : }
298 : for (;;) {
299 0 : int count = runs[0];
300 0 : SkASSERT(count >= 0);
301 0 : if (count <= 0) {
302 0 : return;
303 : }
304 0 : runs += count;
305 :
306 0 : unsigned aa = antialias[0];
307 0 : antialias += count;
308 0 : if (aa) {
309 0 : if (aa == 255) {
310 0 : if (ditherInt) {
311 0 : sk_dither_memset16(device, srcColor,
312 0 : ditherColor, count);
313 : } else {
314 0 : sk_memset16(device, srcColor, count);
315 : }
316 : } else {
317 : // TODO: respect fDoDither
318 0 : unsigned scale5 = SkAlpha255To256(aa) >> 3;
319 0 : uint32_t src32 = srcExpanded * scale5;
320 0 : scale5 = 32 - scale5; // now we can use it on the device
321 0 : int n = count;
322 0 : do {
323 0 : uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
324 0 : *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
325 : } while (--n != 0);
326 0 : goto DONE;
327 : }
328 : }
329 0 : device += count;
330 :
331 : DONE:
332 : // if we have no dithering, this will always fail
333 0 : if (count & ditherInt) {
334 0 : SkTSwap(ditherColor, srcColor);
335 : }
336 0 : }
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 :
358 0 : static U16CPU blend_compact(uint32_t src32, uint32_t dst32, unsigned scale5) {
359 0 : return SkCompact_rgb_16(dst32 + ((src32 - dst32) * scale5 >> 5));
360 : }
361 :
362 0 : void SkRGB16_Opaque_Blitter::blitMask(const SkMask& mask,
363 : const SkIRect& clip) {
364 0 : if (mask.fFormat == SkMask::kBW_Format) {
365 0 : SkRGB16_BlitBW(fDevice, mask, clip, fColor16);
366 0 : return;
367 : }
368 :
369 0 : uint16_t* SK_RESTRICT device = fDevice.writable_addr16(clip.fLeft, clip.fTop);
370 0 : const uint8_t* SK_RESTRICT alpha = mask.getAddr8(clip.fLeft, clip.fTop);
371 0 : int width = clip.width();
372 0 : int height = clip.height();
373 0 : size_t deviceRB = fDevice.rowBytes() - (width << 1);
374 0 : unsigned maskRB = mask.fRowBytes - width;
375 0 : 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 0 : do {
449 0 : int w = width;
450 0 : do {
451 0 : *device = blend_compact(expanded32, SkExpand_rgb_16(*device),
452 0 : SkAlpha255To256(*alpha++) >> 3);
453 0 : device += 1;
454 : } while (--w != 0);
455 0 : device = (uint16_t*)((char*)device + deviceRB);
456 0 : alpha += maskRB;
457 : } while (--height != 0);
458 : #endif
459 : }
460 :
461 0 : void SkRGB16_Opaque_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
462 0 : uint16_t* SK_RESTRICT device = fDevice.writable_addr16(x, y);
463 0 : size_t deviceRB = fDevice.rowBytes();
464 :
465 : // TODO: respect fDoDither
466 0 : unsigned scale5 = SkAlpha255To256(alpha) >> 3;
467 0 : uint32_t src32 = fExpandedRaw16 * scale5;
468 0 : 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 0 : do {
473 0 : uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
474 0 : *device = SkCompact_rgb_16((src32 + dst32) >> 5);
475 0 : device = (uint16_t*)((char*)device + deviceRB);
476 : } while (--height != 0);
477 : #endif
478 0 : }
479 :
480 0 : void SkRGB16_Opaque_Blitter::blitRect(int x, int y, int width, int height) {
481 0 : SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height());
482 0 : uint16_t* SK_RESTRICT device = fDevice.writable_addr16(x, y);
483 0 : size_t deviceRB = fDevice.rowBytes();
484 0 : uint16_t color16 = fColor16;
485 :
486 0 : if (fDoDither) {
487 0 : uint16_t ditherColor = fRawDither16;
488 0 : if ((x ^ y) & 1) {
489 0 : SkTSwap(ditherColor, color16);
490 : }
491 0 : while (--height >= 0) {
492 0 : sk_dither_memset16(device, color16, ditherColor, width);
493 0 : SkTSwap(ditherColor, color16);
494 0 : device = (uint16_t*)((char*)device + deviceRB);
495 : }
496 : } else { // no dither
497 0 : while (--height >= 0) {
498 0 : sk_memset16(device, color16, width);
499 0 : device = (uint16_t*)((char*)device + deviceRB);
500 : }
501 : }
502 0 : }
503 :
504 : ///////////////////////////////////////////////////////////////////////////////
505 :
506 0 : SkRGB16_Blitter::SkRGB16_Blitter(const SkPixmap& device, const SkPaint& paint)
507 0 : : INHERITED(device) {
508 0 : SkColor color = paint.getColor();
509 :
510 0 : fSrcColor32 = SkPreMultiplyColor(color);
511 0 : fScale = SkAlpha255To256(SkColorGetA(color));
512 :
513 0 : int r = SkColorGetR(color);
514 0 : int g = SkColorGetG(color);
515 0 : int b = SkColorGetB(color);
516 :
517 0 : fRawColor16 = fRawDither16 = SkPack888ToRGB16(r, g, b);
518 : // if we're dithered, use fRawDither16 to hold that.
519 0 : if ((fDoDither = paint.isDither()) != false) {
520 0 : fRawDither16 = SkDitherPack888ToRGB16(r, g, b);
521 : }
522 :
523 0 : fExpandedRaw16 = SkExpand_rgb_16(fRawColor16);
524 :
525 0 : fColor16 = SkPackRGB16( SkAlphaMul(r, fScale) >> (8 - SK_R16_BITS),
526 0 : SkAlphaMul(g, fScale) >> (8 - SK_G16_BITS),
527 0 : SkAlphaMul(b, fScale) >> (8 - SK_B16_BITS));
528 :
529 : // compute SkBlitRow::Procs
530 0 : unsigned flags = 0;
531 :
532 0 : if (SkGetPackedA32(fSrcColor32) < 0xFF) {
533 0 : flags |= SkBlitRow::kSrcPixelAlpha_Flag;
534 : }
535 :
536 0 : if (fDoDither) {
537 0 : flags |= SkBlitRow::kDither_Flag;
538 : }
539 :
540 0 : fColorProc16 = SkBlitRow::ColorFactory16(flags);
541 0 : }
542 :
543 0 : const SkPixmap* SkRGB16_Blitter::justAnOpaqueColor(uint32_t* value) {
544 0 : if (!fDoDither && 256 == fScale) {
545 0 : *value = fRawColor16;
546 0 : return &fDevice;
547 : }
548 0 : return nullptr;
549 : }
550 :
551 0 : void SkRGB16_Blitter::blitH(int x, int y, int width) {
552 0 : SkASSERT(width > 0);
553 0 : SkASSERT(x + width <= fDevice.width());
554 0 : uint16_t* SK_RESTRICT device = fDevice.writable_addr16(x, y);
555 :
556 0 : fColorProc16(device, fSrcColor32, width, x, y);
557 0 : }
558 :
559 0 : void SkRGB16_Blitter::blitAntiH(int x, int y,
560 : const SkAlpha* SK_RESTRICT antialias,
561 : const int16_t* SK_RESTRICT runs) {
562 0 : uint16_t* SK_RESTRICT device = fDevice.writable_addr16(x, y);
563 0 : uint32_t srcExpanded = fExpandedRaw16;
564 0 : unsigned scale = fScale;
565 :
566 : // TODO: respect fDoDither
567 : for (;;) {
568 0 : int count = runs[0];
569 0 : SkASSERT(count >= 0);
570 0 : if (count <= 0) {
571 0 : return;
572 : }
573 0 : runs += count;
574 :
575 0 : unsigned aa = antialias[0];
576 0 : antialias += count;
577 0 : if (aa) {
578 0 : unsigned scale5 = SkAlpha255To256(aa) * scale >> (8 + 3);
579 0 : uint32_t src32 = srcExpanded * scale5;
580 0 : scale5 = 32 - scale5;
581 0 : do {
582 0 : uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
583 0 : *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
584 : } while (--count != 0);
585 0 : continue;
586 : }
587 0 : device += count;
588 0 : }
589 : }
590 :
591 0 : static inline void blend_8_pixels(U8CPU bw, uint16_t dst[], unsigned dst_scale,
592 : U16CPU srcColor) {
593 0 : if (bw & 0x80) dst[0] = srcColor + SkAlphaMulRGB16(dst[0], dst_scale);
594 0 : if (bw & 0x40) dst[1] = srcColor + SkAlphaMulRGB16(dst[1], dst_scale);
595 0 : if (bw & 0x20) dst[2] = srcColor + SkAlphaMulRGB16(dst[2], dst_scale);
596 0 : if (bw & 0x10) dst[3] = srcColor + SkAlphaMulRGB16(dst[3], dst_scale);
597 0 : if (bw & 0x08) dst[4] = srcColor + SkAlphaMulRGB16(dst[4], dst_scale);
598 0 : if (bw & 0x04) dst[5] = srcColor + SkAlphaMulRGB16(dst[5], dst_scale);
599 0 : if (bw & 0x02) dst[6] = srcColor + SkAlphaMulRGB16(dst[6], dst_scale);
600 0 : if (bw & 0x01) dst[7] = srcColor + SkAlphaMulRGB16(dst[7], dst_scale);
601 0 : }
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 :
610 0 : void SkRGB16_Blitter::blitMask(const SkMask& mask,
611 : const SkIRect& clip) {
612 0 : if (mask.fFormat == SkMask::kBW_Format) {
613 0 : SkRGB16_BlendBW(fDevice, mask, clip, 256 - fScale, fColor16);
614 0 : return;
615 : }
616 :
617 0 : uint16_t* SK_RESTRICT device = fDevice.writable_addr16(clip.fLeft, clip.fTop);
618 0 : const uint8_t* SK_RESTRICT alpha = mask.getAddr8(clip.fLeft, clip.fTop);
619 0 : int width = clip.width();
620 0 : int height = clip.height();
621 0 : size_t deviceRB = fDevice.rowBytes() - (width << 1);
622 0 : unsigned maskRB = mask.fRowBytes - width;
623 0 : uint32_t color32 = fExpandedRaw16;
624 :
625 0 : unsigned scale256 = fScale;
626 0 : do {
627 0 : int w = width;
628 0 : do {
629 0 : unsigned aa = *alpha++;
630 0 : unsigned scale = SkAlpha255To256(aa) * scale256 >> (8 + 3);
631 0 : uint32_t src32 = color32 * scale;
632 0 : uint32_t dst32 = SkExpand_rgb_16(*device) * (32 - scale);
633 0 : *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
634 : } while (--w != 0);
635 0 : device = (uint16_t*)((char*)device + deviceRB);
636 0 : alpha += maskRB;
637 : } while (--height != 0);
638 : }
639 :
640 0 : void SkRGB16_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
641 0 : uint16_t* SK_RESTRICT device = fDevice.writable_addr16(x, y);
642 0 : size_t deviceRB = fDevice.rowBytes();
643 :
644 : // TODO: respect fDoDither
645 0 : unsigned scale5 = SkAlpha255To256(alpha) * fScale >> (8 + 3);
646 0 : uint32_t src32 = fExpandedRaw16 * scale5;
647 0 : 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 0 : do {
652 0 : uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
653 0 : *device = SkCompact_rgb_16((src32 + dst32) >> 5);
654 0 : device = (uint16_t*)((char*)device + deviceRB);
655 : } while (--height != 0);
656 : #endif
657 0 : }
658 :
659 0 : void SkRGB16_Blitter::blitRect(int x, int y, int width, int height) {
660 0 : SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height());
661 0 : uint16_t* SK_RESTRICT device = fDevice.writable_addr16(x, y);
662 0 : size_t deviceRB = fDevice.rowBytes();
663 :
664 0 : while (--height >= 0) {
665 0 : fColorProc16(device, fSrcColor32, width, x, y);
666 0 : device = (uint16_t*)((char*)device + deviceRB);
667 : }
668 0 : }
669 :
670 : ///////////////////////////////////////////////////////////////////////////////
671 :
672 0 : SkRGB16_Shader_Blitter::SkRGB16_Shader_Blitter(const SkPixmap& device,
673 : const SkPaint& paint,
674 0 : SkShader::Context* shaderContext)
675 0 : : INHERITED(device, paint, shaderContext)
676 : {
677 0 : SkASSERT(paint.isSrcOver());
678 :
679 0 : fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * sizeof(SkPMColor));
680 :
681 : // compute SkBlitRow::Procs
682 0 : unsigned flags = 0;
683 :
684 0 : uint32_t shaderFlags = fShaderFlags;
685 : // shaders take care of global alpha, so we never set it in SkBlitRow
686 0 : if (!(shaderFlags & SkShader::kOpaqueAlpha_Flag)) {
687 0 : flags |= SkBlitRow::kSrcPixelAlpha_Flag;
688 : }
689 0 : if (paint.isDither()) {
690 0 : flags |= SkBlitRow::kDither_Flag;
691 : }
692 : // used when we know our global alpha is 0xFF
693 0 : fOpaqueProc = SkBlitRow::Factory16(flags);
694 : // used when we know our global alpha is < 0xFF
695 0 : fAlphaProc = SkBlitRow::Factory16(flags | SkBlitRow::kGlobalAlpha_Flag);
696 0 : }
697 :
698 0 : SkRGB16_Shader_Blitter::~SkRGB16_Shader_Blitter() {
699 0 : sk_free(fBuffer);
700 0 : }
701 :
702 0 : void SkRGB16_Shader_Blitter::blitH(int x, int y, int width) {
703 0 : SkASSERT(x + width <= fDevice.width());
704 :
705 0 : fShaderContext->shadeSpan(x, y, fBuffer, width);
706 : // shaders take care of global alpha, so we pass 0xFF (should be ignored)
707 0 : fOpaqueProc(fDevice.writable_addr16(x, y), fBuffer, width, 0xFF, x, y);
708 0 : }
709 :
710 0 : void SkRGB16_Shader_Blitter::blitRect(int x, int y, int width, int height) {
711 0 : SkShader::Context* shaderContext = fShaderContext;
712 0 : SkBlitRow::Proc16 proc = fOpaqueProc;
713 0 : SkPMColor* buffer = fBuffer;
714 0 : uint16_t* dst = fDevice.writable_addr16(x, y);
715 0 : size_t dstRB = fDevice.rowBytes();
716 :
717 0 : if (fShaderFlags & SkShader::kConstInY32_Flag) {
718 0 : shaderContext->shadeSpan(x, y, buffer, width);
719 0 : do {
720 0 : proc(dst, buffer, width, 0xFF, x, y);
721 0 : y += 1;
722 0 : dst = (uint16_t*)((char*)dst + dstRB);
723 : } while (--height);
724 : } else {
725 0 : do {
726 0 : shaderContext->shadeSpan(x, y, buffer, width);
727 0 : proc(dst, buffer, width, 0xFF, x, y);
728 0 : y += 1;
729 0 : dst = (uint16_t*)((char*)dst + dstRB);
730 : } while (--height);
731 : }
732 0 : }
733 :
734 0 : static inline int count_nonzero_span(const int16_t runs[], const SkAlpha aa[]) {
735 0 : int count = 0;
736 : for (;;) {
737 0 : int n = *runs;
738 0 : if (n == 0 || *aa == 0) {
739 : break;
740 : }
741 0 : runs += n;
742 0 : aa += n;
743 0 : count += n;
744 0 : }
745 0 : return count;
746 : }
747 :
748 0 : void SkRGB16_Shader_Blitter::blitAntiH(int x, int y,
749 : const SkAlpha* SK_RESTRICT antialias,
750 : const int16_t* SK_RESTRICT runs) {
751 0 : SkShader::Context* shaderContext = fShaderContext;
752 0 : SkPMColor* SK_RESTRICT span = fBuffer;
753 0 : uint16_t* SK_RESTRICT device = fDevice.writable_addr16(x, y);
754 :
755 : for (;;) {
756 0 : int count = *runs;
757 0 : if (count <= 0) {
758 0 : break;
759 : }
760 0 : int aa = *antialias;
761 0 : if (0 == aa) {
762 0 : device += count;
763 0 : runs += count;
764 0 : antialias += count;
765 0 : x += count;
766 0 : continue;
767 : }
768 :
769 0 : int nonZeroCount = count + count_nonzero_span(runs + count, antialias + count);
770 :
771 0 : SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
772 0 : shaderContext->shadeSpan(x, y, span, nonZeroCount);
773 :
774 0 : SkPMColor* localSpan = span;
775 : for (;;) {
776 0 : SkBlitRow::Proc16 proc = (aa == 0xFF) ? fOpaqueProc : fAlphaProc;
777 0 : proc(device, localSpan, count, aa, x, y);
778 :
779 0 : x += count;
780 0 : device += count;
781 0 : runs += count;
782 0 : antialias += count;
783 0 : nonZeroCount -= count;
784 0 : if (nonZeroCount == 0) {
785 0 : break;
786 : }
787 0 : localSpan += count;
788 0 : SkASSERT(nonZeroCount > 0);
789 0 : count = *runs;
790 0 : SkASSERT(count > 0);
791 0 : aa = *antialias;
792 0 : }
793 0 : }
794 0 : }
795 :
796 : ///////////////////////////////////////////////////////////////////////
797 :
798 0 : SkRGB16_Shader_Xfermode_Blitter::SkRGB16_Shader_Xfermode_Blitter(
799 : const SkPixmap& device, const SkPaint& paint,
800 0 : SkShader::Context* shaderContext)
801 0 : : INHERITED(device, paint, shaderContext)
802 : {
803 0 : fXfermode = SkXfermode::Peek(paint.getBlendMode());
804 0 : SkASSERT(fXfermode);
805 :
806 0 : int width = device.width();
807 0 : fBuffer = (SkPMColor*)sk_malloc_throw((width + (SkAlign4(width) >> 2)) * sizeof(SkPMColor));
808 0 : fAAExpand = (uint8_t*)(fBuffer + width);
809 0 : }
810 :
811 0 : SkRGB16_Shader_Xfermode_Blitter::~SkRGB16_Shader_Xfermode_Blitter() {
812 0 : sk_free(fBuffer);
813 0 : }
814 :
815 0 : void SkRGB16_Shader_Xfermode_Blitter::blitH(int x, int y, int width) {
816 0 : SkASSERT(x + width <= fDevice.width());
817 :
818 0 : uint16_t* device = fDevice.writable_addr16(x, y);
819 0 : SkPMColor* span = fBuffer;
820 :
821 0 : fShaderContext->shadeSpan(x, y, span, width);
822 0 : fXfermode->xfer16(device, span, width, nullptr);
823 0 : }
824 :
825 0 : void SkRGB16_Shader_Xfermode_Blitter::blitAntiH(int x, int y,
826 : const SkAlpha* SK_RESTRICT antialias,
827 : const int16_t* SK_RESTRICT runs) {
828 0 : SkShader::Context* shaderContext = fShaderContext;
829 0 : SkXfermode* mode = fXfermode;
830 0 : SkPMColor* SK_RESTRICT span = fBuffer;
831 0 : uint8_t* SK_RESTRICT aaExpand = fAAExpand;
832 0 : uint16_t* SK_RESTRICT device = fDevice.writable_addr16(x, y);
833 :
834 : for (;;) {
835 0 : int count = *runs;
836 0 : if (count <= 0) {
837 0 : break;
838 : }
839 0 : int aa = *antialias;
840 0 : if (0 == aa) {
841 0 : device += count;
842 0 : runs += count;
843 0 : antialias += count;
844 0 : x += count;
845 0 : continue;
846 : }
847 :
848 0 : int nonZeroCount = count + count_nonzero_span(runs + count,
849 0 : antialias + count);
850 :
851 0 : SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
852 0 : shaderContext->shadeSpan(x, y, span, nonZeroCount);
853 :
854 0 : x += nonZeroCount;
855 0 : SkPMColor* localSpan = span;
856 : for (;;) {
857 0 : if (aa == 0xFF) {
858 0 : mode->xfer16(device, localSpan, count, nullptr);
859 : } else {
860 0 : SkASSERT(aa);
861 0 : memset(aaExpand, aa, count);
862 0 : mode->xfer16(device, localSpan, count, aaExpand);
863 : }
864 0 : device += count;
865 0 : runs += count;
866 0 : antialias += count;
867 0 : nonZeroCount -= count;
868 0 : if (nonZeroCount == 0) {
869 0 : break;
870 : }
871 0 : localSpan += count;
872 0 : SkASSERT(nonZeroCount > 0);
873 0 : count = *runs;
874 0 : SkASSERT(count > 0);
875 0 : aa = *antialias;
876 : }
877 0 : }
878 0 : }
879 :
880 : ///////////////////////////////////////////////////////////////////////////////
881 :
882 0 : SkBlitter* SkBlitter_ChooseD565(const SkPixmap& device, const SkPaint& paint,
883 : SkShader::Context* shaderContext,
884 : SkArenaAlloc* alloc) {
885 0 : SkASSERT(alloc != nullptr);
886 :
887 : SkBlitter* blitter;
888 0 : SkShader* shader = paint.getShader();
889 0 : bool is_srcover = paint.isSrcOver();
890 :
891 : // we require a shader if there is an xfermode, handled by our caller
892 0 : SkASSERT(is_srcover || shader);
893 :
894 0 : if (shader) {
895 0 : SkASSERT(shaderContext != nullptr);
896 0 : if (!is_srcover) {
897 : blitter = alloc->make<SkRGB16_Shader_Xfermode_Blitter>(device, paint,
898 0 : shaderContext);
899 : } else {
900 0 : blitter = alloc->make<SkRGB16_Shader_Blitter>(device, paint, shaderContext);
901 : }
902 : } else {
903 : // no shader, no xfermode, (and we always ignore colorfilter)
904 0 : SkColor color = paint.getColor();
905 0 : if (0 == SkColorGetA(color)) {
906 0 : blitter = alloc->make<SkNullBlitter>();
907 : #ifdef USE_BLACK_BLITTER
908 0 : } else if (SK_ColorBLACK == color) {
909 0 : blitter = alloc->make<SkRGB16_Black_Blitter>(device, paint);
910 : #endif
911 0 : } else if (0xFF == SkColorGetA(color)) {
912 0 : blitter = alloc->make<SkRGB16_Opaque_Blitter>(device, paint);
913 : } else {
914 0 : blitter = alloc->make<SkRGB16_Blitter>(device, paint);
915 : }
916 : }
917 :
918 0 : return blitter;
919 : }
|