• 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     : SkRGB16_Blitter(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_Blitter(const SkBitmap & device,const SkPaint & paint)160 SkRGB16_Blitter::SkRGB16_Blitter(const SkBitmap& device, const SkPaint& paint)
161     : INHERITED(device) {
162     SkColor color = paint.getColor();
163 
164     fSrcColor32 = SkPreMultiplyColor(color);
165     fScale = SkAlpha255To256(SkColorGetA(color));
166 
167     int r = SkColorGetR(color);
168     int g = SkColorGetG(color);
169     int b = SkColorGetB(color);
170 
171     fRawColor16 = fRawDither16 = SkPack888ToRGB16(r, g, b);
172     // if we're dithered, use fRawDither16 to hold that.
173     if ((fDoDither = paint.isDither()) != false) {
174         fRawDither16 = SkDitherPack888ToRGB16(r, g, b);
175     }
176 
177     fColor16 = SkPackRGB16( SkAlphaMul(r, fScale) >> (8 - SK_R16_BITS),
178                             SkAlphaMul(g, fScale) >> (8 - SK_G16_BITS),
179                             SkAlphaMul(b, fScale) >> (8 - SK_B16_BITS));
180 }
181 
justAnOpaqueColor(uint32_t * value)182 const SkBitmap* SkRGB16_Blitter::justAnOpaqueColor(uint32_t* value) {
183     if (!fDoDither && 256 == fScale) {
184         *value = fRawColor16;
185         return &fDevice;
186     }
187     return NULL;
188 }
189 
blitH(int x,int y,int width)190 void SkRGB16_Blitter::blitH(int x, int y, int width) SK_RESTRICT {
191     SkASSERT(width > 0);
192     SkASSERT(x + width <= fDevice.width());
193 
194     if (fScale == 0) {
195         return;
196     }
197 
198     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
199     uint16_t srcColor = fColor16;
200 
201     if (256 == fScale) {
202         SkASSERT(fRawColor16 == srcColor);
203         if (fDoDither) {
204             uint16_t ditherColor = fRawDither16;
205             if ((x ^ y) & 1) {
206                 SkTSwap(ditherColor, srcColor);
207             }
208             sk_dither_memset16(device, srcColor, ditherColor, width);
209         } else {
210             sk_memset16(device, srcColor, width);
211         }
212     } else {
213         // TODO: respect fDoDither
214         SkPMColor src32 = fSrcColor32;
215         do {
216             *device = SkSrcOver32To16(src32, *device);
217             device += 1;
218         } while (--width != 0);
219     }
220 }
221 
222 // return 1 or 0 from a bool
Bool2Int(bool value)223 static int Bool2Int(bool value) {
224     return !!value;
225 }
226 
blitAntiH(int x,int y,const SkAlpha * SK_RESTRICT antialias,const int16_t * SK_RESTRICT runs)227 void SkRGB16_Blitter::blitAntiH(int x, int y,
228                                 const SkAlpha* SK_RESTRICT antialias,
229                                 const int16_t* SK_RESTRICT runs) SK_RESTRICT {
230     if (fScale == 0) {
231         return;
232     }
233 
234     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
235     uint16_t    srcColor = fRawColor16;
236     unsigned    scale = fScale;
237     int         ditherInt = Bool2Int(fDoDither);
238 
239     if (256 == scale) {
240         uint16_t    ditherColor = fRawDither16;
241         // if we have no dithering, this will always fail
242         if ((x ^ y) & ditherInt) {
243             SkTSwap(ditherColor, srcColor);
244         }
245         for (;;) {
246             int count = runs[0];
247             SkASSERT(count >= 0);
248             if (count <= 0) {
249                 return;
250             }
251             runs += count;
252 
253             unsigned aa = antialias[0];
254             antialias += count;
255             if (aa) {
256                 if (aa == 255) {
257                     if (ditherInt) {
258                         sk_dither_memset16(device, srcColor,
259                                            ditherColor, count);
260                     } else {
261                         sk_memset16(device, srcColor, count);
262                     }
263                 } else {
264                     // TODO: respect fDoDither
265                     unsigned scale5 = SkAlpha255To256(aa) >> 3;
266                     uint32_t src32 = SkExpand_rgb_16(srcColor) * scale5;
267                     scale5 = 32 - scale5; // now we can use it on the device
268                     int n = count;
269                     do {
270                         uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
271                         *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
272                     } while (--n != 0);
273                     goto DONE;
274                 }
275             }
276             device += count;
277 
278             DONE:
279             // if we have no dithering, this will always fail
280             if (count & ditherInt) {
281                 SkTSwap(ditherColor, srcColor);
282             }
283         }
284     } else {
285         // TODO: respect fDoDither
286         for (;;) {
287             int count = runs[0];
288             SkASSERT(count >= 0);
289             if (count <= 0) {
290                 return;
291             }
292             runs += count;
293 
294             unsigned aa = antialias[0];
295             antialias += count;
296             if (aa) {
297                 unsigned scale5 = SkAlpha255To256(aa) * scale >> (8 + 3);
298                 uint32_t src32 =  SkExpand_rgb_16(srcColor) * scale5;
299                 scale5 = 32 - scale5;
300                 do {
301                     uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
302                     *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
303                 } while (--count != 0);
304                 continue;
305             }
306             device += count;
307         }
308     }
309 }
310 
311 //////////////////////////////////////////////////////////////////////////////////////
312 
313 #define solid_8_pixels(mask, dst, color)    \
314     do {                                    \
315         if (mask & 0x80) dst[0] = color;    \
316         if (mask & 0x40) dst[1] = color;    \
317         if (mask & 0x20) dst[2] = color;    \
318         if (mask & 0x10) dst[3] = color;    \
319         if (mask & 0x08) dst[4] = color;    \
320         if (mask & 0x04) dst[5] = color;    \
321         if (mask & 0x02) dst[6] = color;    \
322         if (mask & 0x01) dst[7] = color;    \
323     } while (0)
324 
325 #define SK_BLITBWMASK_NAME                  SkRGB16_BlitBW
326 #define SK_BLITBWMASK_ARGS                  , uint16_t color
327 #define SK_BLITBWMASK_BLIT8(mask, dst)      solid_8_pixels(mask, dst, color)
328 #define SK_BLITBWMASK_GETADDR               getAddr16
329 #define SK_BLITBWMASK_DEVTYPE               uint16_t
330 #include "SkBlitBWMaskTemplate.h"
331 
blend_8_pixels(U8CPU bw,uint16_t dst[],unsigned dst_scale,U16CPU srcColor)332 static inline void blend_8_pixels(U8CPU bw, uint16_t dst[], unsigned dst_scale,
333                                   U16CPU srcColor) {
334     if (bw & 0x80) dst[0] = srcColor + SkAlphaMulRGB16(dst[0], dst_scale);
335     if (bw & 0x40) dst[1] = srcColor + SkAlphaMulRGB16(dst[1], dst_scale);
336     if (bw & 0x20) dst[2] = srcColor + SkAlphaMulRGB16(dst[2], dst_scale);
337     if (bw & 0x10) dst[3] = srcColor + SkAlphaMulRGB16(dst[3], dst_scale);
338     if (bw & 0x08) dst[4] = srcColor + SkAlphaMulRGB16(dst[4], dst_scale);
339     if (bw & 0x04) dst[5] = srcColor + SkAlphaMulRGB16(dst[5], dst_scale);
340     if (bw & 0x02) dst[6] = srcColor + SkAlphaMulRGB16(dst[6], dst_scale);
341     if (bw & 0x01) dst[7] = srcColor + SkAlphaMulRGB16(dst[7], dst_scale);
342 }
343 
344 #define SK_BLITBWMASK_NAME                  SkRGB16_BlendBW
345 #define SK_BLITBWMASK_ARGS                  , unsigned dst_scale, U16CPU src_color
346 #define SK_BLITBWMASK_BLIT8(mask, dst)      blend_8_pixels(mask, dst, dst_scale, src_color)
347 #define SK_BLITBWMASK_GETADDR               getAddr16
348 #define SK_BLITBWMASK_DEVTYPE               uint16_t
349 #include "SkBlitBWMaskTemplate.h"
350 
blend_compact(uint32_t src32,uint32_t dst32,unsigned scale5)351 static U16CPU blend_compact(uint32_t src32, uint32_t dst32, unsigned scale5) {
352     return SkCompact_rgb_16(dst32 + ((src32 - dst32) * scale5 >> 5));
353 }
354 
blitMask(const SkMask & SK_RESTRICT mask,const SkIRect & SK_RESTRICT clip)355 void SkRGB16_Blitter::blitMask(const SkMask& SK_RESTRICT mask,
356                                const SkIRect& SK_RESTRICT clip) SK_RESTRICT {
357     if (fScale == 0) {
358         return;
359     }
360     if (mask.fFormat == SkMask::kBW_Format) {
361         if (fScale == 256) {
362             SkRGB16_BlitBW(fDevice, mask, clip, fColor16);
363         } else {
364             SkRGB16_BlendBW(fDevice, mask, clip, 256 - fScale, fColor16);
365         }
366         return;
367     }
368 
369     uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop);
370     const uint8_t* SK_RESTRICT alpha = mask.getAddr(clip.fLeft, clip.fTop);
371     int width = clip.width();
372     int height = clip.height();
373     unsigned    deviceRB = fDevice.rowBytes() - (width << 1);
374     unsigned    maskRB = mask.fRowBytes - width;
375     uint32_t    color32 = SkExpand_rgb_16(fRawColor16);
376 
377     if (256 == fScale) {
378         do {
379             int w = width;
380             do {
381                 *device = blend_compact(color32, SkExpand_rgb_16(*device),
382                                         SkAlpha255To256(*alpha++) >> 3);
383                 device += 1;
384             } while (--w != 0);
385             device = (uint16_t*)((char*)device + deviceRB);
386             alpha += maskRB;
387         } while (--height != 0);
388     } else {   // scale < 256
389         unsigned scale256 = fScale;
390         do {
391             int w = width;
392             do {
393                 unsigned aa = *alpha++;
394                 unsigned scale = SkAlpha255To256(aa) * scale256 >> (8 + 3);
395                 uint32_t src32 = color32 * scale;
396                 uint32_t dst32 = SkExpand_rgb_16(*device) * (32 - scale);
397                 *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
398             } while (--w != 0);
399             device = (uint16_t*)((char*)device + deviceRB);
400             alpha += maskRB;
401         } while (--height != 0);
402     }
403 }
404 
blitV(int x,int y,int height,SkAlpha alpha)405 void SkRGB16_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
406     if (fScale == 0) {
407         return;
408     }
409     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
410     uint16_t    color16 = fRawColor16;
411     unsigned    deviceRB = fDevice.rowBytes();
412 
413     if (alpha + fScale == (255 + 256)) {
414         if (fDoDither) {
415             uint16_t ditherColor = fRawDither16;
416             if ((x ^ y) & 1) {
417                 SkTSwap(ditherColor, color16);
418             }
419             do {
420                 device[0] = color16;
421                 device = (uint16_t*)((char*)device + deviceRB);
422                 SkTSwap(ditherColor, color16);
423             } while (--height != 0);
424         } else {
425             do {
426                 device[0] = color16;
427                 device = (uint16_t*)((char*)device + deviceRB);
428             } while (--height != 0);
429         }
430     } else {
431         // TODO: respect fDoDither
432         unsigned scale5 = SkAlpha255To256(alpha) * fScale >> (8 + 3);
433         uint32_t src32 =  SkExpand_rgb_16(color16) * scale5;
434         scale5 = 32 - scale5;
435         do {
436             uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
437             *device = SkCompact_rgb_16((src32 + dst32) >> 5);
438             device = (uint16_t*)((char*)device + deviceRB);
439         } while (--height != 0);
440     }
441 }
442 
blitRect(int x,int y,int width,int height)443 void SkRGB16_Blitter::blitRect(int x, int y, int width, int height) {
444     SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height());
445 
446     if (fScale == 0) {
447         return;
448     }
449     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
450     unsigned    deviceRB = fDevice.rowBytes();
451     uint16_t    color16 = fColor16;
452 
453     if (256 == fScale) {
454         if (fDoDither) {
455             uint16_t ditherColor = fRawDither16;
456             if ((x ^ y) & 1) {
457                 SkTSwap(ditherColor, color16);
458             }
459             while (--height >= 0) {
460                 sk_dither_memset16(device, color16, ditherColor, width);
461                 SkTSwap(ditherColor, color16);
462                 device = (uint16_t*)((char*)device + deviceRB);
463             }
464         } else {  // no dither
465             while (--height >= 0) {
466                 sk_memset16(device, color16, width);
467                 device = (uint16_t*)((char*)device + deviceRB);
468             }
469         }
470     } else {
471         SkPMColor src32 = fSrcColor32;
472         while (--height >= 0) {
473             for (int i = width - 1; i >= 0; --i) {
474                 device[i] = SkSrcOver32To16(src32, device[i]);
475             }
476             device = (uint16_t*)((char*)device + deviceRB);
477         }
478     }
479 }
480 
481 ///////////////////////////////////////////////////////////////////////////////
482 
SkRGB16_Shader16_Blitter(const SkBitmap & device,const SkPaint & paint)483 SkRGB16_Shader16_Blitter::SkRGB16_Shader16_Blitter(const SkBitmap& device,
484                                                    const SkPaint& paint)
485     : SkRGB16_Shader_Blitter(device, paint) {
486     SkASSERT(SkShader::CanCallShadeSpan16(fShader->getFlags()));
487 }
488 
blitH(int x,int y,int width)489 void SkRGB16_Shader16_Blitter::blitH(int x, int y, int width) SK_RESTRICT {
490     SkASSERT(x + width <= fDevice.width());
491 
492     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
493     SkShader*   shader = fShader;
494 
495     int alpha = shader->getSpan16Alpha();
496     if (0xFF == alpha) {
497         shader->shadeSpan16(x, y, device, width);
498     } else {
499         uint16_t* span16 = (uint16_t*)fBuffer;
500         shader->shadeSpan16(x, y, span16, width);
501         SkBlendRGB16(span16, device, SkAlpha255To256(alpha), width);
502     }
503 }
504 
blitAntiH(int x,int y,const SkAlpha * SK_RESTRICT antialias,const int16_t * SK_RESTRICT runs)505 void SkRGB16_Shader16_Blitter::blitAntiH(int x, int y,
506                                          const SkAlpha* SK_RESTRICT antialias,
507                                          const int16_t* SK_RESTRICT runs)
508                                          SK_RESTRICT {
509     SkShader*   shader = fShader;
510     SkPMColor* SK_RESTRICT span = fBuffer;
511     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
512 
513     int alpha = shader->getSpan16Alpha();
514     uint16_t* span16 = (uint16_t*)span;
515 
516     if (0xFF == alpha) {
517         for (;;) {
518             int count = *runs;
519             if (count <= 0) {
520                 break;
521             }
522             SkASSERT(count <= fDevice.width()); // don't overrun fBuffer
523 
524             int aa = *antialias;
525             if (aa == 255) {
526                 // go direct to the device!
527                 shader->shadeSpan16(x, y, device, count);
528             } else if (aa) {
529                 shader->shadeSpan16(x, y, span16, count);
530                 SkBlendRGB16(span16, device, SkAlpha255To256(aa), count);
531             }
532             device += count;
533             runs += count;
534             antialias += count;
535             x += count;
536         }
537     } else {  // span alpha is < 255
538         alpha = SkAlpha255To256(alpha);
539         for (;;) {
540             int count = *runs;
541             if (count <= 0) {
542                 break;
543             }
544             SkASSERT(count <= fDevice.width()); // don't overrun fBuffer
545 
546             int aa = SkAlphaMul(*antialias, alpha);
547             if (aa) {
548                 shader->shadeSpan16(x, y, span16, count);
549                 SkBlendRGB16(span16, device, SkAlpha255To256(aa), count);
550             }
551 
552             device += count;
553             runs += count;
554             antialias += count;
555             x += count;
556         }
557     }
558 }
559 
560 ///////////////////////////////////////////////////////////////////////////////
561 
SkRGB16_Shader_Blitter(const SkBitmap & device,const SkPaint & paint)562 SkRGB16_Shader_Blitter::SkRGB16_Shader_Blitter(const SkBitmap& device,
563                                                const SkPaint& paint)
564 : INHERITED(device, paint) {
565     SkASSERT(paint.getXfermode() == NULL);
566 
567     fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * sizeof(SkPMColor));
568 
569     // compute SkBlitRow::Procs
570     unsigned flags = 0;
571 
572     uint32_t shaderFlags = fShader->getFlags();
573     // shaders take care of global alpha, so we never set it in SkBlitRow
574     if (!(shaderFlags & SkShader::kOpaqueAlpha_Flag)) {
575         flags |= SkBlitRow::kSrcPixelAlpha_Flag;
576         }
577     // don't dither if the shader is really 16bit
578     if (paint.isDither() && !(shaderFlags & SkShader::kIntrinsicly16_Flag)) {
579         flags |= SkBlitRow::kDither_Flag;
580     }
581     // used when we know our global alpha is 0xFF
582     fOpaqueProc = SkBlitRow::Factory(flags, SkBitmap::kRGB_565_Config);
583     // used when we know our global alpha is < 0xFF
584     fAlphaProc  = SkBlitRow::Factory(flags | SkBlitRow::kGlobalAlpha_Flag,
585                                      SkBitmap::kRGB_565_Config);
586 }
587 
~SkRGB16_Shader_Blitter()588 SkRGB16_Shader_Blitter::~SkRGB16_Shader_Blitter() {
589     sk_free(fBuffer);
590 }
591 
blitH(int x,int y,int width)592 void SkRGB16_Shader_Blitter::blitH(int x, int y, int width) {
593     SkASSERT(x + width <= fDevice.width());
594 
595     fShader->shadeSpan(x, y, fBuffer, width);
596     // shaders take care of global alpha, so we pass 0xFF (should be ignored)
597     fOpaqueProc(fDevice.getAddr16(x, y), fBuffer, width, 0xFF, x, y);
598 }
599 
count_nonzero_span(const int16_t runs[],const SkAlpha aa[])600 static inline int count_nonzero_span(const int16_t runs[], const SkAlpha aa[]) {
601     int count = 0;
602     for (;;) {
603         int n = *runs;
604         if (n == 0 || *aa == 0) {
605             break;
606         }
607         runs += n;
608         aa += n;
609         count += n;
610     }
611     return count;
612 }
613 
blitAntiH(int x,int y,const SkAlpha * SK_RESTRICT antialias,const int16_t * SK_RESTRICT runs)614 void SkRGB16_Shader_Blitter::blitAntiH(int x, int y,
615                                        const SkAlpha* SK_RESTRICT antialias,
616                                        const int16_t* SK_RESTRICT runs)
617                                        SK_RESTRICT {
618     SkShader*   shader = fShader;
619     SkPMColor* SK_RESTRICT span = fBuffer;
620     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
621 
622     for (;;) {
623         int count = *runs;
624         if (count <= 0) {
625             break;
626         }
627         int aa = *antialias;
628         if (0 == aa) {
629             device += count;
630             runs += count;
631             antialias += count;
632             x += count;
633             continue;
634         }
635 
636         int nonZeroCount = count + count_nonzero_span(runs + count, antialias + count);
637 
638         SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
639         shader->shadeSpan(x, y, span, nonZeroCount);
640 
641         SkPMColor* localSpan = span;
642         for (;;) {
643             SkBlitRow::Proc proc = (aa == 0xFF) ? fOpaqueProc : fAlphaProc;
644             proc(device, localSpan, count, aa, x, y);
645 
646             x += count;
647             device += count;
648             runs += count;
649             antialias += count;
650             nonZeroCount -= count;
651             if (nonZeroCount == 0) {
652                 break;
653             }
654             localSpan += count;
655             SkASSERT(nonZeroCount > 0);
656             count = *runs;
657             SkASSERT(count > 0);
658             aa = *antialias;
659         }
660     }
661 }
662 
663 ///////////////////////////////////////////////////////////////////////
664 
SkRGB16_Shader_Xfermode_Blitter(const SkBitmap & device,const SkPaint & paint)665 SkRGB16_Shader_Xfermode_Blitter::SkRGB16_Shader_Xfermode_Blitter(
666                                 const SkBitmap& device, const SkPaint& paint)
667 : INHERITED(device, paint) {
668     fXfermode = paint.getXfermode();
669     SkASSERT(fXfermode);
670     fXfermode->ref();
671 
672     int width = device.width();
673     fBuffer = (SkPMColor*)sk_malloc_throw((width + (SkAlign4(width) >> 2)) * sizeof(SkPMColor));
674     fAAExpand = (uint8_t*)(fBuffer + width);
675 }
676 
~SkRGB16_Shader_Xfermode_Blitter()677 SkRGB16_Shader_Xfermode_Blitter::~SkRGB16_Shader_Xfermode_Blitter() {
678     fXfermode->unref();
679     sk_free(fBuffer);
680 }
681 
blitH(int x,int y,int width)682 void SkRGB16_Shader_Xfermode_Blitter::blitH(int x, int y, int width) {
683     SkASSERT(x + width <= fDevice.width());
684 
685     uint16_t*   device = fDevice.getAddr16(x, y);
686     SkPMColor*  span = fBuffer;
687 
688     fShader->shadeSpan(x, y, span, width);
689     fXfermode->xfer16(device, span, width, NULL);
690 }
691 
blitAntiH(int x,int y,const SkAlpha * SK_RESTRICT antialias,const int16_t * SK_RESTRICT runs)692 void SkRGB16_Shader_Xfermode_Blitter::blitAntiH(int x, int y,
693                                 const SkAlpha* SK_RESTRICT antialias,
694                                 const int16_t* SK_RESTRICT runs) SK_RESTRICT {
695     SkShader*   shader = fShader;
696     SkXfermode* mode = fXfermode;
697     SkPMColor* SK_RESTRICT span = fBuffer;
698     uint8_t* SK_RESTRICT aaExpand = fAAExpand;
699     uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
700 
701     for (;;) {
702         int count = *runs;
703         if (count <= 0) {
704             break;
705         }
706         int aa = *antialias;
707         if (0 == aa) {
708             device += count;
709             runs += count;
710             antialias += count;
711             x += count;
712             continue;
713         }
714 
715         int nonZeroCount = count + count_nonzero_span(runs + count,
716                                                       antialias + count);
717 
718         SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
719         shader->shadeSpan(x, y, span, nonZeroCount);
720 
721         x += nonZeroCount;
722         SkPMColor* localSpan = span;
723         for (;;) {
724             if (aa == 0xFF) {
725                 mode->xfer16(device, localSpan, count, NULL);
726             } else {
727                 SkASSERT(aa);
728                 memset(aaExpand, aa, count);
729                 mode->xfer16(device, localSpan, count, aaExpand);
730             }
731             device += count;
732             runs += count;
733             antialias += count;
734             nonZeroCount -= count;
735             if (nonZeroCount == 0) {
736                 break;
737             }
738             localSpan += count;
739             SkASSERT(nonZeroCount > 0);
740             count = *runs;
741             SkASSERT(count > 0);
742             aa = *antialias;
743         }
744     }
745 }
746 
747 ////////////////////////
748 
749 #if 0
750 static inline uint16_t aa_blendS32D16(SkPMColor src, U16CPU dst, int aa
751 #ifdef DITHER_SHADER
752                                       , int dither
753 #endif
754                                       )
755 {
756     SkASSERT((unsigned)aa <= 255);
757 
758     int src_scale = SkAlpha255To256(aa);
759     int sa = SkGetPackedA32(src);
760     int dst_scale = SkAlpha255To256(255 - SkAlphaMul(sa, src_scale));
761 
762 #ifdef DITHER_SHADER
763     int sr = SkGetPackedR32(src);
764     int sg = SkGetPackedG32(src);
765     int sb = SkGetPackedB32(src);
766     sr = SkDITHER_R32To16(sr, dither);
767     sg = SkDITHER_G32To16(sg, dither);
768     sb = SkDITHER_B32To16(sb, dither);
769 #else
770     int sr = SkPacked32ToR16(src);
771     int sg = SkPacked32ToG16(src);
772     int sb = SkPacked32ToB16(src);
773 #endif
774 
775     int dr = (sr * src_scale + SkGetPackedR16(dst) * dst_scale) >> 8;
776     int dg = (sg * src_scale + SkGetPackedG16(dst) * dst_scale) >> 8;
777     int db = (sb * src_scale + SkGetPackedB16(dst) * dst_scale) >> 8;
778 
779     return SkPackRGB16(dr, dg, db);
780 }
781 #endif
782 
783