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