• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* libs/graphics/sgl/SkBlitter_RGB16.cpp
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17 
18 #include "SkBlitRow.h"
19 #include "SkCoreBlitters.h"
20 #include "SkColorPriv.h"
21 #include "SkDither.h"
22 #include "SkShader.h"
23 #include "SkUtils.h"
24 #include "SkXfermode.h"
25 
sk_dither_memset16(uint16_t dst[],uint16_t value,uint16_t other,int count)26 void sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other,
27                         int count) {
28     if (count > 0) {
29         // see if we need to write one short before we can cast to an 4byte ptr
30         // (we do this subtract rather than (unsigned)dst so we don't get warnings
31         //  on 64bit machines)
32         if (((char*)dst - (char*)0) & 2) {
33             *dst++ = value;
34             count -= 1;
35             SkTSwap(value, other);
36         }
37 
38         // fast way to set [value,other] pairs
39 #ifdef SK_CPU_BENDIAN
40         sk_memset32((uint32_t*)dst, (value << 16) | other, count >> 1);
41 #else
42         sk_memset32((uint32_t*)dst, (other << 16) | value, count >> 1);
43 #endif
44 
45         if (count & 1) {
46             dst[count - 1] = value;
47         }
48     }
49 }
50 
51 ///////////////////////////////////////////////////////////////////////////////
52 
SkRGB16_Black_Blitter(const SkBitmap & device,const SkPaint & paint)53 SkRGB16_Black_Blitter::SkRGB16_Black_Blitter(const SkBitmap& device, const SkPaint& paint)
54     : INHERITED(device, paint) {
55     SkASSERT(paint.getShader() == NULL);
56     SkASSERT(paint.getColorFilter() == NULL);
57     SkASSERT(paint.getXfermode() == NULL);
58     SkASSERT(paint.getColor() == SK_ColorBLACK);
59 }
60 
61 #if 1
62 #define black_8_pixels(mask, dst)       \
63     do {                                \
64         if (mask & 0x80) dst[0] = 0;    \
65         if (mask & 0x40) dst[1] = 0;    \
66         if (mask & 0x20) dst[2] = 0;    \
67         if (mask & 0x10) dst[3] = 0;    \
68         if (mask & 0x08) dst[4] = 0;    \
69         if (mask & 0x04) dst[5] = 0;    \
70         if (mask & 0x02) dst[6] = 0;    \
71         if (mask & 0x01) dst[7] = 0;    \
72     } while (0)
73 #else
black_8_pixels(U8CPU mask,uint16_t dst[])74 static inline black_8_pixels(U8CPU mask, uint16_t dst[])
75 {
76     if (mask & 0x80) dst[0] = 0;
77     if (mask & 0x40) dst[1] = 0;
78     if (mask & 0x20) dst[2] = 0;
79     if (mask & 0x10) dst[3] = 0;
80     if (mask & 0x08) dst[4] = 0;
81     if (mask & 0x04) dst[5] = 0;
82     if (mask & 0x02) dst[6] = 0;
83     if (mask & 0x01) dst[7] = 0;
84 }
85 #endif
86 
87 #define SK_BLITBWMASK_NAME                  SkRGB16_Black_BlitBW
88 #define SK_BLITBWMASK_ARGS
89 #define SK_BLITBWMASK_BLIT8(mask, dst)      black_8_pixels(mask, dst)
90 #define SK_BLITBWMASK_GETADDR               getAddr16
91 #define SK_BLITBWMASK_DEVTYPE               uint16_t
92 #include "SkBlitBWMaskTemplate.h"
93 
blitMask(const SkMask & SK_RESTRICT mask,const SkIRect & SK_RESTRICT clip)94 void SkRGB16_Black_Blitter::blitMask(const SkMask& SK_RESTRICT mask,
95                                      const SkIRect& SK_RESTRICT clip)
96                                      SK_RESTRICT {
97     if (mask.fFormat == SkMask::kBW_Format) {
98         SkRGB16_Black_BlitBW(fDevice, mask, clip);
99     } else {
100         uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop);
101         const uint8_t* SK_RESTRICT alpha = mask.getAddr(clip.fLeft, clip.fTop);
102         unsigned width = clip.width();
103         unsigned height = clip.height();
104         unsigned deviceRB = fDevice.rowBytes() - (width << 1);
105         unsigned maskRB = mask.fRowBytes - width;
106 
107         SkASSERT((int)height > 0);
108         SkASSERT((int)width > 0);
109         SkASSERT((int)deviceRB >= 0);
110         SkASSERT((int)maskRB >= 0);
111 
112         do {
113             unsigned w = width;
114             do {
115                 unsigned aa = *alpha++;
116                 *device = SkAlphaMulRGB16(*device, SkAlpha255To256(255 - aa));
117                 device += 1;
118             } while (--w != 0);
119             device = (uint16_t*)((char*)device + deviceRB);
120             alpha += maskRB;
121         } while (--height != 0);
122     }
123 }
124 
blitAntiH(int x,int y,const SkAlpha * SK_RESTRICT antialias,const int16_t * SK_RESTRICT runs)125 void SkRGB16_Black_Blitter::blitAntiH(int x, int y,
126                                       const SkAlpha* SK_RESTRICT antialias,
127                                       const int16_t* SK_RESTRICT runs)
128                                       SK_RESTRICT {
129     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
130 
131     for (;;) {
132         int count = runs[0];
133         SkASSERT(count >= 0);
134         if (count <= 0) {
135             return;
136         }
137         runs += count;
138 
139         unsigned aa = antialias[0];
140         antialias += count;
141         if (aa) {
142             if (aa == 255) {
143                 memset(device, 0, count << 1);
144             } else {
145                 aa = SkAlpha255To256(255 - aa);
146                 do {
147                     *device = SkAlphaMulRGB16(*device, aa);
148                     device += 1;
149                 } while (--count != 0);
150                 continue;
151             }
152         }
153         device += count;
154     }
155 }
156 
157 ///////////////////////////////////////////////////////////////////////////////
158 ///////////////////////////////////////////////////////////////////////////////
159 
SkRGB16_Opaque_Blitter(const SkBitmap & device,const SkPaint & paint)160 SkRGB16_Opaque_Blitter::SkRGB16_Opaque_Blitter(const SkBitmap& device,
161                                                const SkPaint& paint)
162 : INHERITED(device, paint) {}
163 
blitH(int x,int y,int width)164 void SkRGB16_Opaque_Blitter::blitH(int x, int y, int width) SK_RESTRICT {
165     SkASSERT(width > 0);
166     SkASSERT(x + width <= fDevice.width());
167     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
168     uint16_t srcColor = fColor16;
169 
170     SkASSERT(fRawColor16 == srcColor);
171     if (fDoDither) {
172         uint16_t ditherColor = fRawDither16;
173         if ((x ^ y) & 1) {
174             SkTSwap(ditherColor, srcColor);
175         }
176         sk_dither_memset16(device, srcColor, ditherColor, width);
177     } else {
178         sk_memset16(device, srcColor, width);
179     }
180 }
181 
182 // return 1 or 0 from a bool
Bool2Int(bool value)183 static int Bool2Int(bool value) {
184     return !!value;
185 }
186 
blitAntiH(int x,int y,const SkAlpha * SK_RESTRICT antialias,const int16_t * SK_RESTRICT runs)187 void SkRGB16_Opaque_Blitter::blitAntiH(int x, int y,
188                                        const SkAlpha* SK_RESTRICT antialias,
189                                        const int16_t* SK_RESTRICT runs) SK_RESTRICT {
190     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
191     uint16_t    srcColor = fRawColor16;
192     int         ditherInt = Bool2Int(fDoDither);
193     uint16_t    ditherColor = fRawDither16;
194     // if we have no dithering, this will always fail
195     if ((x ^ y) & ditherInt) {
196         SkTSwap(ditherColor, srcColor);
197     }
198     for (;;) {
199         int count = runs[0];
200         SkASSERT(count >= 0);
201         if (count <= 0) {
202             return;
203         }
204         runs += count;
205 
206         unsigned aa = antialias[0];
207         antialias += count;
208         if (aa) {
209             if (aa == 255) {
210                 if (ditherInt) {
211                     sk_dither_memset16(device, srcColor,
212                                        ditherColor, count);
213                 } else {
214                     sk_memset16(device, srcColor, count);
215                 }
216             } else {
217                 // TODO: respect fDoDither
218                 unsigned scale5 = SkAlpha255To256(aa) >> 3;
219                 uint32_t src32 = SkExpand_rgb_16(srcColor) * scale5;
220                 scale5 = 32 - scale5; // now we can use it on the device
221                 int n = count;
222                 do {
223                     uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
224                     *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
225                 } while (--n != 0);
226                 goto DONE;
227             }
228         }
229         device += count;
230 
231     DONE:
232         // if we have no dithering, this will always fail
233         if (count & ditherInt) {
234             SkTSwap(ditherColor, srcColor);
235         }
236     }
237 }
238 
239 #define solid_8_pixels(mask, dst, color)    \
240     do {                                    \
241         if (mask & 0x80) dst[0] = color;    \
242         if (mask & 0x40) dst[1] = color;    \
243         if (mask & 0x20) dst[2] = color;    \
244         if (mask & 0x10) dst[3] = color;    \
245         if (mask & 0x08) dst[4] = color;    \
246         if (mask & 0x04) dst[5] = color;    \
247         if (mask & 0x02) dst[6] = color;    \
248         if (mask & 0x01) dst[7] = color;    \
249     } while (0)
250 
251 #define SK_BLITBWMASK_NAME                  SkRGB16_BlitBW
252 #define SK_BLITBWMASK_ARGS                  , uint16_t color
253 #define SK_BLITBWMASK_BLIT8(mask, dst)      solid_8_pixels(mask, dst, color)
254 #define SK_BLITBWMASK_GETADDR               getAddr16
255 #define SK_BLITBWMASK_DEVTYPE               uint16_t
256 #include "SkBlitBWMaskTemplate.h"
257 
blend_compact(uint32_t src32,uint32_t dst32,unsigned scale5)258 static U16CPU blend_compact(uint32_t src32, uint32_t dst32, unsigned scale5) {
259     return SkCompact_rgb_16(dst32 + ((src32 - dst32) * scale5 >> 5));
260 }
261 
blitMask(const SkMask & SK_RESTRICT mask,const SkIRect & SK_RESTRICT clip)262 void SkRGB16_Opaque_Blitter::blitMask(const SkMask& SK_RESTRICT mask,
263                                       const SkIRect& SK_RESTRICT clip) SK_RESTRICT {
264     if (mask.fFormat == SkMask::kBW_Format) {
265         SkRGB16_BlitBW(fDevice, mask, clip, fColor16);
266         return;
267     }
268 
269     uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop);
270     const uint8_t* SK_RESTRICT alpha = mask.getAddr(clip.fLeft, clip.fTop);
271     int width = clip.width();
272     int height = clip.height();
273     unsigned    deviceRB = fDevice.rowBytes() - (width << 1);
274     unsigned    maskRB = mask.fRowBytes - width;
275     uint32_t    color32 = SkExpand_rgb_16(fRawColor16);
276 
277     do {
278         int w = width;
279         do {
280             *device = blend_compact(color32, SkExpand_rgb_16(*device),
281                                     SkAlpha255To256(*alpha++) >> 3);
282             device += 1;
283         } while (--w != 0);
284         device = (uint16_t*)((char*)device + deviceRB);
285         alpha += maskRB;
286     } while (--height != 0);
287 }
288 
blitRect(int x,int y,int width,int height)289 void SkRGB16_Opaque_Blitter::blitRect(int x, int y, int width, int height) {
290     SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height());
291     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
292     unsigned    deviceRB = fDevice.rowBytes();
293     uint16_t    color16 = fColor16;
294 
295     if (fDoDither) {
296         uint16_t ditherColor = fRawDither16;
297         if ((x ^ y) & 1) {
298             SkTSwap(ditherColor, color16);
299         }
300         while (--height >= 0) {
301             sk_dither_memset16(device, color16, ditherColor, width);
302             SkTSwap(ditherColor, color16);
303             device = (uint16_t*)((char*)device + deviceRB);
304         }
305     } else {  // no dither
306         while (--height >= 0) {
307             sk_memset16(device, color16, width);
308             device = (uint16_t*)((char*)device + deviceRB);
309         }
310     }
311 }
312 
313 ///////////////////////////////////////////////////////////////////////////////
314 
SkRGB16_Blitter(const SkBitmap & device,const SkPaint & paint)315 SkRGB16_Blitter::SkRGB16_Blitter(const SkBitmap& device, const SkPaint& paint)
316     : INHERITED(device) {
317     SkColor color = paint.getColor();
318 
319     fSrcColor32 = SkPreMultiplyColor(color);
320     fScale = SkAlpha255To256(SkColorGetA(color));
321 
322     int r = SkColorGetR(color);
323     int g = SkColorGetG(color);
324     int b = SkColorGetB(color);
325 
326     fRawColor16 = fRawDither16 = SkPack888ToRGB16(r, g, b);
327     // if we're dithered, use fRawDither16 to hold that.
328     if ((fDoDither = paint.isDither()) != false) {
329         fRawDither16 = SkDitherPack888ToRGB16(r, g, b);
330     }
331 
332     fColor16 = SkPackRGB16( SkAlphaMul(r, fScale) >> (8 - SK_R16_BITS),
333                             SkAlphaMul(g, fScale) >> (8 - SK_G16_BITS),
334                             SkAlphaMul(b, fScale) >> (8 - SK_B16_BITS));
335 }
336 
justAnOpaqueColor(uint32_t * value)337 const SkBitmap* SkRGB16_Blitter::justAnOpaqueColor(uint32_t* value) {
338     if (!fDoDither && 256 == fScale) {
339         *value = fRawColor16;
340         return &fDevice;
341     }
342     return NULL;
343 }
344 
pmcolor_to_expand16(SkPMColor c)345 static uint32_t pmcolor_to_expand16(SkPMColor c) {
346     unsigned r = SkGetPackedR32(c);
347     unsigned g = SkGetPackedG32(c);
348     unsigned b = SkGetPackedB32(c);
349     return (g << 24) | (r << 13) | (b << 2);
350 }
351 
blend32_16_row(SkPMColor src,uint16_t dst[],int count)352 static inline void blend32_16_row(SkPMColor src, uint16_t dst[], int count) {
353     SkASSERT(count > 0);
354     uint32_t src_expand = pmcolor_to_expand16(src);
355     unsigned scale = SkAlpha255To256(0xFF - SkGetPackedA32(src)) >> 3;
356     do {
357         uint32_t dst_expand = SkExpand_rgb_16(*dst) * scale;
358         *dst = SkCompact_rgb_16((src_expand + dst_expand) >> 5);
359         dst += 1;
360     } while (--count != 0);
361 }
362 
blitH(int x,int y,int width)363 void SkRGB16_Blitter::blitH(int x, int y, int width) SK_RESTRICT {
364     SkASSERT(width > 0);
365     SkASSERT(x + width <= fDevice.width());
366     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
367 
368     // TODO: respect fDoDither
369     blend32_16_row(fSrcColor32, device, width);
370 }
371 
blitAntiH(int x,int y,const SkAlpha * SK_RESTRICT antialias,const int16_t * SK_RESTRICT runs)372 void SkRGB16_Blitter::blitAntiH(int x, int y,
373                                 const SkAlpha* SK_RESTRICT antialias,
374                                 const int16_t* SK_RESTRICT runs) SK_RESTRICT {
375     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
376     uint16_t    srcColor = fRawColor16;
377     unsigned    scale = fScale;
378 
379     // TODO: respect fDoDither
380     for (;;) {
381         int count = runs[0];
382         SkASSERT(count >= 0);
383         if (count <= 0) {
384             return;
385         }
386         runs += count;
387 
388         unsigned aa = antialias[0];
389         antialias += count;
390         if (aa) {
391             unsigned scale5 = SkAlpha255To256(aa) * scale >> (8 + 3);
392             uint32_t src32 =  SkExpand_rgb_16(srcColor) * scale5;
393             scale5 = 32 - scale5;
394             do {
395                 uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
396                 *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
397             } while (--count != 0);
398             continue;
399         }
400         device += count;
401     }
402 }
403 
blend_8_pixels(U8CPU bw,uint16_t dst[],unsigned dst_scale,U16CPU srcColor)404 static inline void blend_8_pixels(U8CPU bw, uint16_t dst[], unsigned dst_scale,
405                                   U16CPU srcColor) {
406     if (bw & 0x80) dst[0] = srcColor + SkAlphaMulRGB16(dst[0], dst_scale);
407     if (bw & 0x40) dst[1] = srcColor + SkAlphaMulRGB16(dst[1], dst_scale);
408     if (bw & 0x20) dst[2] = srcColor + SkAlphaMulRGB16(dst[2], dst_scale);
409     if (bw & 0x10) dst[3] = srcColor + SkAlphaMulRGB16(dst[3], dst_scale);
410     if (bw & 0x08) dst[4] = srcColor + SkAlphaMulRGB16(dst[4], dst_scale);
411     if (bw & 0x04) dst[5] = srcColor + SkAlphaMulRGB16(dst[5], dst_scale);
412     if (bw & 0x02) dst[6] = srcColor + SkAlphaMulRGB16(dst[6], dst_scale);
413     if (bw & 0x01) dst[7] = srcColor + SkAlphaMulRGB16(dst[7], dst_scale);
414 }
415 
416 #define SK_BLITBWMASK_NAME                  SkRGB16_BlendBW
417 #define SK_BLITBWMASK_ARGS                  , unsigned dst_scale, U16CPU src_color
418 #define SK_BLITBWMASK_BLIT8(mask, dst)      blend_8_pixels(mask, dst, dst_scale, src_color)
419 #define SK_BLITBWMASK_GETADDR               getAddr16
420 #define SK_BLITBWMASK_DEVTYPE               uint16_t
421 #include "SkBlitBWMaskTemplate.h"
422 
blitMask(const SkMask & SK_RESTRICT mask,const SkIRect & SK_RESTRICT clip)423 void SkRGB16_Blitter::blitMask(const SkMask& SK_RESTRICT mask,
424                                const SkIRect& SK_RESTRICT clip) SK_RESTRICT {
425     if (mask.fFormat == SkMask::kBW_Format) {
426         SkRGB16_BlendBW(fDevice, mask, clip, 256 - fScale, fColor16);
427         return;
428     }
429 
430     uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop);
431     const uint8_t* SK_RESTRICT alpha = mask.getAddr(clip.fLeft, clip.fTop);
432     int width = clip.width();
433     int height = clip.height();
434     unsigned    deviceRB = fDevice.rowBytes() - (width << 1);
435     unsigned    maskRB = mask.fRowBytes - width;
436     uint32_t    color32 = SkExpand_rgb_16(fRawColor16);
437 
438     unsigned scale256 = fScale;
439     do {
440         int w = width;
441         do {
442             unsigned aa = *alpha++;
443             unsigned scale = SkAlpha255To256(aa) * scale256 >> (8 + 3);
444             uint32_t src32 = color32 * scale;
445             uint32_t dst32 = SkExpand_rgb_16(*device) * (32 - scale);
446             *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
447         } while (--w != 0);
448         device = (uint16_t*)((char*)device + deviceRB);
449         alpha += maskRB;
450     } while (--height != 0);
451 }
452 
blitV(int x,int y,int height,SkAlpha alpha)453 void SkRGB16_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
454     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
455     uint16_t    color16 = fRawColor16;
456     unsigned    deviceRB = fDevice.rowBytes();
457 
458     if (alpha + fScale == (255 + 256)) {
459         if (fDoDither) {
460             uint16_t ditherColor = fRawDither16;
461             if ((x ^ y) & 1) {
462                 SkTSwap(ditherColor, color16);
463             }
464             do {
465                 device[0] = color16;
466                 device = (uint16_t*)((char*)device + deviceRB);
467                 SkTSwap(ditherColor, color16);
468             } while (--height != 0);
469         } else {
470             do {
471                 device[0] = color16;
472                 device = (uint16_t*)((char*)device + deviceRB);
473             } while (--height != 0);
474         }
475     } else {
476         // TODO: respect fDoDither
477         unsigned scale5 = SkAlpha255To256(alpha) * fScale >> (8 + 3);
478         uint32_t src32 =  SkExpand_rgb_16(color16) * scale5;
479         scale5 = 32 - scale5;
480         do {
481             uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
482             *device = SkCompact_rgb_16((src32 + dst32) >> 5);
483             device = (uint16_t*)((char*)device + deviceRB);
484         } while (--height != 0);
485     }
486 }
487 
blitRect(int x,int y,int width,int height)488 void SkRGB16_Blitter::blitRect(int x, int y, int width, int height) {
489     SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height());
490     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
491     unsigned    deviceRB = fDevice.rowBytes();
492     SkPMColor src32 = fSrcColor32;
493 
494     while (--height >= 0) {
495         blend32_16_row(src32, device, width);
496         device = (uint16_t*)((char*)device + deviceRB);
497     }
498 }
499 
500 ///////////////////////////////////////////////////////////////////////////////
501 
SkRGB16_Shader16_Blitter(const SkBitmap & device,const SkPaint & paint)502 SkRGB16_Shader16_Blitter::SkRGB16_Shader16_Blitter(const SkBitmap& device,
503                                                    const SkPaint& paint)
504     : SkRGB16_Shader_Blitter(device, paint) {
505     SkASSERT(SkShader::CanCallShadeSpan16(fShaderFlags));
506 }
507 
blitH(int x,int y,int width)508 void SkRGB16_Shader16_Blitter::blitH(int x, int y, int width) SK_RESTRICT {
509     SkASSERT(x + width <= fDevice.width());
510 
511     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
512     SkShader*   shader = fShader;
513 
514     int alpha = shader->getSpan16Alpha();
515     if (0xFF == alpha) {
516         shader->shadeSpan16(x, y, device, width);
517     } else {
518         uint16_t* span16 = (uint16_t*)fBuffer;
519         shader->shadeSpan16(x, y, span16, width);
520         SkBlendRGB16(span16, device, SkAlpha255To256(alpha), width);
521     }
522 }
523 
blitRect(int x,int y,int width,int height)524 void SkRGB16_Shader16_Blitter::blitRect(int x, int y, int width, int height) {
525     SkShader*   shader = fShader;
526     uint16_t*   dst = fDevice.getAddr16(x, y);
527     size_t      dstRB = fDevice.rowBytes();
528     int         alpha = shader->getSpan16Alpha();
529 
530     if (0xFF == alpha) {
531         if (fShaderFlags & SkShader::kConstInY16_Flag) {
532             // have the shader blit directly into the device the first time
533             shader->shadeSpan16(x, y, dst, width);
534             // and now just memcpy that line on the subsequent lines
535             if (--height > 0) {
536                 const uint16_t* orig = dst;
537                 do {
538                     dst = (uint16_t*)((char*)dst + dstRB);
539                     memcpy(dst, orig, width << 1);
540                 } while (--height);
541             }
542         } else {    // need to call shadeSpan16 for every line
543             do {
544                 shader->shadeSpan16(x, y, dst, width);
545                 y += 1;
546                 dst = (uint16_t*)((char*)dst + dstRB);
547             } while (--height);
548         }
549     } else {
550         int scale = SkAlpha255To256(alpha);
551         uint16_t* span16 = (uint16_t*)fBuffer;
552         if (fShaderFlags & SkShader::kConstInY16_Flag) {
553             shader->shadeSpan16(x, y, span16, width);
554             do {
555                 SkBlendRGB16(span16, dst, scale, width);
556                 dst = (uint16_t*)((char*)dst + dstRB);
557             } while (--height);
558         } else {
559             do {
560                 shader->shadeSpan16(x, y, span16, width);
561                 SkBlendRGB16(span16, dst, scale, width);
562                 y += 1;
563                 dst = (uint16_t*)((char*)dst + dstRB);
564             } while (--height);
565         }
566     }
567 }
568 
blitAntiH(int x,int y,const SkAlpha * SK_RESTRICT antialias,const int16_t * SK_RESTRICT runs)569 void SkRGB16_Shader16_Blitter::blitAntiH(int x, int y,
570                                          const SkAlpha* SK_RESTRICT antialias,
571                                          const int16_t* SK_RESTRICT runs)
572                                          SK_RESTRICT {
573     SkShader*   shader = fShader;
574     SkPMColor* SK_RESTRICT span = fBuffer;
575     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
576 
577     int alpha = shader->getSpan16Alpha();
578     uint16_t* span16 = (uint16_t*)span;
579 
580     if (0xFF == alpha) {
581         for (;;) {
582             int count = *runs;
583             if (count <= 0) {
584                 break;
585             }
586             SkASSERT(count <= fDevice.width()); // don't overrun fBuffer
587 
588             int aa = *antialias;
589             if (aa == 255) {
590                 // go direct to the device!
591                 shader->shadeSpan16(x, y, device, count);
592             } else if (aa) {
593                 shader->shadeSpan16(x, y, span16, count);
594                 SkBlendRGB16(span16, device, SkAlpha255To256(aa), count);
595             }
596             device += count;
597             runs += count;
598             antialias += count;
599             x += count;
600         }
601     } else {  // span alpha is < 255
602         alpha = SkAlpha255To256(alpha);
603         for (;;) {
604             int count = *runs;
605             if (count <= 0) {
606                 break;
607             }
608             SkASSERT(count <= fDevice.width()); // don't overrun fBuffer
609 
610             int aa = SkAlphaMul(*antialias, alpha);
611             if (aa) {
612                 shader->shadeSpan16(x, y, span16, count);
613                 SkBlendRGB16(span16, device, SkAlpha255To256(aa), count);
614             }
615 
616             device += count;
617             runs += count;
618             antialias += count;
619             x += count;
620         }
621     }
622 }
623 
624 ///////////////////////////////////////////////////////////////////////////////
625 
SkRGB16_Shader_Blitter(const SkBitmap & device,const SkPaint & paint)626 SkRGB16_Shader_Blitter::SkRGB16_Shader_Blitter(const SkBitmap& device,
627                                                const SkPaint& paint)
628 : INHERITED(device, paint) {
629     SkASSERT(paint.getXfermode() == NULL);
630 
631     fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * sizeof(SkPMColor));
632 
633     // compute SkBlitRow::Procs
634     unsigned flags = 0;
635 
636     uint32_t shaderFlags = fShaderFlags;
637     // shaders take care of global alpha, so we never set it in SkBlitRow
638     if (!(shaderFlags & SkShader::kOpaqueAlpha_Flag)) {
639         flags |= SkBlitRow::kSrcPixelAlpha_Flag;
640         }
641     // don't dither if the shader is really 16bit
642     if (paint.isDither() && !(shaderFlags & SkShader::kIntrinsicly16_Flag)) {
643         flags |= SkBlitRow::kDither_Flag;
644     }
645     // used when we know our global alpha is 0xFF
646     fOpaqueProc = SkBlitRow::Factory(flags, SkBitmap::kRGB_565_Config);
647     // used when we know our global alpha is < 0xFF
648     fAlphaProc  = SkBlitRow::Factory(flags | SkBlitRow::kGlobalAlpha_Flag,
649                                      SkBitmap::kRGB_565_Config);
650 }
651 
~SkRGB16_Shader_Blitter()652 SkRGB16_Shader_Blitter::~SkRGB16_Shader_Blitter() {
653     sk_free(fBuffer);
654 }
655 
blitH(int x,int y,int width)656 void SkRGB16_Shader_Blitter::blitH(int x, int y, int width) {
657     SkASSERT(x + width <= fDevice.width());
658 
659     fShader->shadeSpan(x, y, fBuffer, width);
660     // shaders take care of global alpha, so we pass 0xFF (should be ignored)
661     fOpaqueProc(fDevice.getAddr16(x, y), fBuffer, width, 0xFF, x, y);
662 }
663 
blitRect(int x,int y,int width,int height)664 void SkRGB16_Shader_Blitter::blitRect(int x, int y, int width, int height) {
665     SkShader*       shader = fShader;
666     SkBlitRow::Proc proc = fOpaqueProc;
667     SkPMColor*      buffer = fBuffer;
668     uint16_t*       dst = fDevice.getAddr16(x, y);
669     size_t          dstRB = fDevice.rowBytes();
670 
671     if (fShaderFlags & SkShader::kConstInY32_Flag) {
672         shader->shadeSpan(x, y, buffer, width);
673         do {
674             proc(dst, buffer, width, 0xFF, x, y);
675             y += 1;
676             dst = (uint16_t*)((char*)dst + dstRB);
677         } while (--height);
678     } else {
679         do {
680             shader->shadeSpan(x, y, buffer, width);
681             proc(dst, buffer, width, 0xFF, x, y);
682             y += 1;
683             dst = (uint16_t*)((char*)dst + dstRB);
684         } while (--height);
685     }
686 }
687 
count_nonzero_span(const int16_t runs[],const SkAlpha aa[])688 static inline int count_nonzero_span(const int16_t runs[], const SkAlpha aa[]) {
689     int count = 0;
690     for (;;) {
691         int n = *runs;
692         if (n == 0 || *aa == 0) {
693             break;
694         }
695         runs += n;
696         aa += n;
697         count += n;
698     }
699     return count;
700 }
701 
blitAntiH(int x,int y,const SkAlpha * SK_RESTRICT antialias,const int16_t * SK_RESTRICT runs)702 void SkRGB16_Shader_Blitter::blitAntiH(int x, int y,
703                                        const SkAlpha* SK_RESTRICT antialias,
704                                        const int16_t* SK_RESTRICT runs)
705                                        SK_RESTRICT {
706     SkShader*   shader = fShader;
707     SkPMColor* SK_RESTRICT span = fBuffer;
708     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
709 
710     for (;;) {
711         int count = *runs;
712         if (count <= 0) {
713             break;
714         }
715         int aa = *antialias;
716         if (0 == aa) {
717             device += count;
718             runs += count;
719             antialias += count;
720             x += count;
721             continue;
722         }
723 
724         int nonZeroCount = count + count_nonzero_span(runs + count, antialias + count);
725 
726         SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
727         shader->shadeSpan(x, y, span, nonZeroCount);
728 
729         SkPMColor* localSpan = span;
730         for (;;) {
731             SkBlitRow::Proc proc = (aa == 0xFF) ? fOpaqueProc : fAlphaProc;
732             proc(device, localSpan, count, aa, x, y);
733 
734             x += count;
735             device += count;
736             runs += count;
737             antialias += count;
738             nonZeroCount -= count;
739             if (nonZeroCount == 0) {
740                 break;
741             }
742             localSpan += count;
743             SkASSERT(nonZeroCount > 0);
744             count = *runs;
745             SkASSERT(count > 0);
746             aa = *antialias;
747         }
748     }
749 }
750 
751 ///////////////////////////////////////////////////////////////////////
752 
SkRGB16_Shader_Xfermode_Blitter(const SkBitmap & device,const SkPaint & paint)753 SkRGB16_Shader_Xfermode_Blitter::SkRGB16_Shader_Xfermode_Blitter(
754                                 const SkBitmap& device, const SkPaint& paint)
755 : INHERITED(device, paint) {
756     fXfermode = paint.getXfermode();
757     SkASSERT(fXfermode);
758     fXfermode->ref();
759 
760     int width = device.width();
761     fBuffer = (SkPMColor*)sk_malloc_throw((width + (SkAlign4(width) >> 2)) * sizeof(SkPMColor));
762     fAAExpand = (uint8_t*)(fBuffer + width);
763 }
764 
~SkRGB16_Shader_Xfermode_Blitter()765 SkRGB16_Shader_Xfermode_Blitter::~SkRGB16_Shader_Xfermode_Blitter() {
766     fXfermode->unref();
767     sk_free(fBuffer);
768 }
769 
blitH(int x,int y,int width)770 void SkRGB16_Shader_Xfermode_Blitter::blitH(int x, int y, int width) {
771     SkASSERT(x + width <= fDevice.width());
772 
773     uint16_t*   device = fDevice.getAddr16(x, y);
774     SkPMColor*  span = fBuffer;
775 
776     fShader->shadeSpan(x, y, span, width);
777     fXfermode->xfer16(device, span, width, NULL);
778 }
779 
blitAntiH(int x,int y,const SkAlpha * SK_RESTRICT antialias,const int16_t * SK_RESTRICT runs)780 void SkRGB16_Shader_Xfermode_Blitter::blitAntiH(int x, int y,
781                                 const SkAlpha* SK_RESTRICT antialias,
782                                 const int16_t* SK_RESTRICT runs) SK_RESTRICT {
783     SkShader*   shader = fShader;
784     SkXfermode* mode = fXfermode;
785     SkPMColor* SK_RESTRICT span = fBuffer;
786     uint8_t* SK_RESTRICT aaExpand = fAAExpand;
787     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
788 
789     for (;;) {
790         int count = *runs;
791         if (count <= 0) {
792             break;
793         }
794         int aa = *antialias;
795         if (0 == aa) {
796             device += count;
797             runs += count;
798             antialias += count;
799             x += count;
800             continue;
801         }
802 
803         int nonZeroCount = count + count_nonzero_span(runs + count,
804                                                       antialias + count);
805 
806         SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
807         shader->shadeSpan(x, y, span, nonZeroCount);
808 
809         x += nonZeroCount;
810         SkPMColor* localSpan = span;
811         for (;;) {
812             if (aa == 0xFF) {
813                 mode->xfer16(device, localSpan, count, NULL);
814             } else {
815                 SkASSERT(aa);
816                 memset(aaExpand, aa, count);
817                 mode->xfer16(device, localSpan, count, aaExpand);
818             }
819             device += count;
820             runs += count;
821             antialias += count;
822             nonZeroCount -= count;
823             if (nonZeroCount == 0) {
824                 break;
825             }
826             localSpan += count;
827             SkASSERT(nonZeroCount > 0);
828             count = *runs;
829             SkASSERT(count > 0);
830             aa = *antialias;
831         }
832     }
833 }
834 
835 ////////////////////////
836 
837 #if 0
838 static inline uint16_t aa_blendS32D16(SkPMColor src, U16CPU dst, int aa
839 #ifdef DITHER_SHADER
840                                       , int dither
841 #endif
842                                       )
843 {
844     SkASSERT((unsigned)aa <= 255);
845 
846     int src_scale = SkAlpha255To256(aa);
847     int sa = SkGetPackedA32(src);
848     int dst_scale = SkAlpha255To256(255 - SkAlphaMul(sa, src_scale));
849 
850 #ifdef DITHER_SHADER
851     int sr = SkGetPackedR32(src);
852     int sg = SkGetPackedG32(src);
853     int sb = SkGetPackedB32(src);
854     sr = SkDITHER_R32To16(sr, dither);
855     sg = SkDITHER_G32To16(sg, dither);
856     sb = SkDITHER_B32To16(sb, dither);
857 #else
858     int sr = SkPacked32ToR16(src);
859     int sg = SkPacked32ToG16(src);
860     int sb = SkPacked32ToB16(src);
861 #endif
862 
863     int dr = (sr * src_scale + SkGetPackedR16(dst) * dst_scale) >> 8;
864     int dg = (sg * src_scale + SkGetPackedG16(dst) * dst_scale) >> 8;
865     int db = (sb * src_scale + SkGetPackedB16(dst) * dst_scale) >> 8;
866 
867     return SkPackRGB16(dr, dg, db);
868 }
869 #endif
870 
871