• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "SkSpriteBlitter.h"
11 #include "SkBlitRow.h"
12 #include "SkTemplates.h"
13 #include "SkUtils.h"
14 #include "SkColorPriv.h"
15 
16 #define D16_S32A_Opaque_Pixel(dst, sc)                                        \
17 do {                                                                          \
18     if (sc) {                                                                 \
19         *dst = SkSrcOver32To16(sc, *dst);                                     \
20     }                                                                         \
21 } while (0)
22 
D16_S32A_Blend_Pixel_helper(uint16_t * dst,SkPMColor sc,unsigned src_scale)23 static inline void D16_S32A_Blend_Pixel_helper(uint16_t* dst, SkPMColor sc,
24                                                unsigned src_scale) {
25     uint16_t dc = *dst;
26     unsigned sa = SkGetPackedA32(sc);
27     unsigned dr, dg, db;
28 
29     if (255 == sa) {
30         dr = SkAlphaBlend(SkPacked32ToR16(sc), SkGetPackedR16(dc), src_scale);
31         dg = SkAlphaBlend(SkPacked32ToG16(sc), SkGetPackedG16(dc), src_scale);
32         db = SkAlphaBlend(SkPacked32ToB16(sc), SkGetPackedB16(dc), src_scale);
33     } else {
34         unsigned dst_scale = 255 - SkAlphaMul(sa, src_scale);
35         dr = (SkPacked32ToR16(sc) * src_scale +
36               SkGetPackedR16(dc) * dst_scale) >> 8;
37         dg = (SkPacked32ToG16(sc) * src_scale +
38               SkGetPackedG16(dc) * dst_scale) >> 8;
39         db = (SkPacked32ToB16(sc) * src_scale +
40               SkGetPackedB16(dc) * dst_scale) >> 8;
41     }
42     *dst = SkPackRGB16(dr, dg, db);
43 }
44 
45 #define D16_S32A_Blend_Pixel(dst, sc, src_scale) \
46     do { if (sc) D16_S32A_Blend_Pixel_helper(dst, sc, src_scale); } while (0)
47 
48 
49 ///////////////////////////////////////////////////////////////////////////////
50 
51 class Sprite_D16_S16_Opaque : public SkSpriteBlitter {
52 public:
Sprite_D16_S16_Opaque(const SkBitmap & source)53     Sprite_D16_S16_Opaque(const SkBitmap& source)
54         : SkSpriteBlitter(source) {}
55 
56     // overrides
blitRect(int x,int y,int width,int height)57     virtual void blitRect(int x, int y, int width, int height) {
58         uint16_t* SK_RESTRICT dst = fDevice->getAddr16(x, y);
59         const uint16_t* SK_RESTRICT src = fSource->getAddr16(x - fLeft,
60                                                              y - fTop);
61         unsigned dstRB = fDevice->rowBytes();
62         unsigned srcRB = fSource->rowBytes();
63 
64         while (--height >= 0) {
65             memcpy(dst, src, width << 1);
66             dst = (uint16_t*)((char*)dst + dstRB);
67             src = (const uint16_t*)((const char*)src + srcRB);
68         }
69     }
70 };
71 
72 #define D16_S16_Blend_Pixel(dst, sc, scale)     \
73     do {                                        \
74         uint16_t dc = *dst;                     \
75         *dst = SkBlendRGB16(sc, dc, scale);     \
76     } while (0)
77 
78 #define SkSPRITE_CLASSNAME                  Sprite_D16_S16_Blend
79 #define SkSPRITE_ARGS                       , uint8_t alpha
80 #define SkSPRITE_FIELDS                     uint8_t  fSrcAlpha;
81 #define SkSPRITE_INIT                       fSrcAlpha = alpha;
82 #define SkSPRITE_DST_TYPE                   uint16_t
83 #define SkSPRITE_SRC_TYPE                   uint16_t
84 #define SkSPRITE_DST_GETADDR                getAddr16
85 #define SkSPRITE_SRC_GETADDR                getAddr16
86 #define SkSPRITE_PREAMBLE(srcBM, x, y)      int scale = SkAlpha255To256(fSrcAlpha);
87 #define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S16_Blend_Pixel(dst, src, scale)
88 #define SkSPRITE_NEXT_ROW
89 #define SkSPRITE_POSTAMBLE(srcBM)
90 #include "SkSpriteBlitterTemplate.h"
91 
92 ///////////////////////////////////////////////////////////////////////////////
93 
94 #define D16_S4444_Opaque(dst, sc)           \
95     do {                                    \
96         uint16_t dc = *dst;                 \
97         *dst = SkSrcOver4444To16(sc, dc);   \
98     } while (0)
99 
100 #define SkSPRITE_CLASSNAME                  Sprite_D16_S4444_Opaque
101 #define SkSPRITE_ARGS
102 #define SkSPRITE_FIELDS
103 #define SkSPRITE_INIT
104 #define SkSPRITE_DST_TYPE                   uint16_t
105 #define SkSPRITE_SRC_TYPE                   SkPMColor16
106 #define SkSPRITE_DST_GETADDR                getAddr16
107 #define SkSPRITE_SRC_GETADDR                getAddr16
108 #define SkSPRITE_PREAMBLE(srcBM, x, y)
109 #define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S4444_Opaque(dst, src)
110 #define SkSPRITE_NEXT_ROW
111 #define SkSPRITE_POSTAMBLE(srcBM)
112 #include "SkSpriteBlitterTemplate.h"
113 
114 #define D16_S4444_Blend(dst, sc, scale16)           \
115     do {                                            \
116         uint16_t dc = *dst;                         \
117         *dst = SkBlend4444To16(sc, dc, scale16);    \
118     } while (0)
119 
120 
121 #define SkSPRITE_CLASSNAME                  Sprite_D16_S4444_Blend
122 #define SkSPRITE_ARGS                       , uint8_t alpha
123 #define SkSPRITE_FIELDS                     uint8_t  fSrcAlpha;
124 #define SkSPRITE_INIT                       fSrcAlpha = alpha;
125 #define SkSPRITE_DST_TYPE                   uint16_t
126 #define SkSPRITE_SRC_TYPE                   uint16_t
127 #define SkSPRITE_DST_GETADDR                getAddr16
128 #define SkSPRITE_SRC_GETADDR                getAddr16
129 #define SkSPRITE_PREAMBLE(srcBM, x, y)      int scale = SkAlpha15To16(fSrcAlpha);
130 #define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S4444_Blend(dst, src, scale)
131 #define SkSPRITE_NEXT_ROW
132 #define SkSPRITE_POSTAMBLE(srcBM)
133 #include "SkSpriteBlitterTemplate.h"
134 
135 ///////////////////////////////////////////////////////////////////////////////
136 
137 #define SkSPRITE_CLASSNAME                  Sprite_D16_SIndex8A_Opaque
138 #define SkSPRITE_ARGS
139 #define SkSPRITE_FIELDS
140 #define SkSPRITE_INIT
141 #define SkSPRITE_DST_TYPE                   uint16_t
142 #define SkSPRITE_SRC_TYPE                   uint8_t
143 #define SkSPRITE_DST_GETADDR                getAddr16
144 #define SkSPRITE_SRC_GETADDR                getAddr8
145 #define SkSPRITE_PREAMBLE(srcBM, x, y)      const SkPMColor* ctable = srcBM.getColorTable()->lockColors()
146 #define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S32A_Opaque_Pixel(dst, ctable[src])
147 #define SkSPRITE_NEXT_ROW
148 #define SkSPRITE_POSTAMBLE(srcBM)           srcBM.getColorTable()->unlockColors(false)
149 #include "SkSpriteBlitterTemplate.h"
150 
151 #define SkSPRITE_CLASSNAME                  Sprite_D16_SIndex8A_Blend
152 #define SkSPRITE_ARGS                       , uint8_t alpha
153 #define SkSPRITE_FIELDS                     uint8_t fSrcAlpha;
154 #define SkSPRITE_INIT                       fSrcAlpha = alpha;
155 #define SkSPRITE_DST_TYPE                   uint16_t
156 #define SkSPRITE_SRC_TYPE                   uint8_t
157 #define SkSPRITE_DST_GETADDR                getAddr16
158 #define SkSPRITE_SRC_GETADDR                getAddr8
159 #define SkSPRITE_PREAMBLE(srcBM, x, y)      const SkPMColor* ctable = srcBM.getColorTable()->lockColors(); unsigned src_scale = SkAlpha255To256(fSrcAlpha);
160 #define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S32A_Blend_Pixel(dst, ctable[src], src_scale)
161 #define SkSPRITE_NEXT_ROW
162 #define SkSPRITE_POSTAMBLE(srcBM)           srcBM.getColorTable()->unlockColors(false);
163 #include "SkSpriteBlitterTemplate.h"
164 
165 ///////////////////////////////////////////////////////////////////////////////
166 
asint(const void * ptr)167 static intptr_t asint(const void* ptr) {
168     return reinterpret_cast<const char*>(ptr) - (const char*)0;
169 }
170 
blitrow_d16_si8(uint16_t * SK_RESTRICT dst,const uint8_t * SK_RESTRICT src,int count,const uint16_t * SK_RESTRICT ctable)171 static void blitrow_d16_si8(uint16_t* SK_RESTRICT dst,
172                             const uint8_t* SK_RESTRICT src, int count,
173                             const uint16_t* SK_RESTRICT ctable) {
174     if (count <= 8) {
175         do {
176             *dst++ = ctable[*src++];
177         } while (--count);
178         return;
179     }
180 
181     // eat src until we're on a 4byte boundary
182     while (asint(src) & 3) {
183         *dst++ = ctable[*src++];
184         count -= 1;
185     }
186 
187     int qcount = count >> 2;
188     SkASSERT(qcount > 0);
189     const uint32_t* qsrc = reinterpret_cast<const uint32_t*>(src);
190     if (asint(dst) & 2) {
191         do {
192             uint32_t s4 = *qsrc++;
193 #ifdef SK_CPU_LENDIAN
194             *dst++ = ctable[s4 & 0xFF];
195             *dst++ = ctable[(s4 >> 8) & 0xFF];
196             *dst++ = ctable[(s4 >> 16) & 0xFF];
197             *dst++ = ctable[s4 >> 24];
198 #else   // BENDIAN
199             *dst++ = ctable[s4 >> 24];
200             *dst++ = ctable[(s4 >> 16) & 0xFF];
201             *dst++ = ctable[(s4 >> 8) & 0xFF];
202             *dst++ = ctable[s4 & 0xFF];
203 #endif
204         } while (--qcount);
205     } else {    // dst is on a 4byte boundary
206         uint32_t* ddst = reinterpret_cast<uint32_t*>(dst);
207         do {
208             uint32_t s4 = *qsrc++;
209 #ifdef SK_CPU_LENDIAN
210             *ddst++ = (ctable[(s4 >> 8) & 0xFF] << 16) | ctable[s4 & 0xFF];
211             *ddst++ = (ctable[s4 >> 24] << 16) | ctable[(s4 >> 16) & 0xFF];
212 #else   // BENDIAN
213             *ddst++ = (ctable[s4 >> 24] << 16) | ctable[(s4 >> 16) & 0xFF];
214             *ddst++ = (ctable[(s4 >> 8) & 0xFF] << 16) | ctable[s4 & 0xFF];
215 #endif
216         } while (--qcount);
217         dst = reinterpret_cast<uint16_t*>(ddst);
218     }
219     src = reinterpret_cast<const uint8_t*>(qsrc);
220     count &= 3;
221     // catch any remaining (will be < 4)
222     while (--count >= 0) {
223         *dst++ = ctable[*src++];
224     }
225 }
226 
227 #define SkSPRITE_ROW_PROC(d, s, n, x, y)    blitrow_d16_si8(d, s, n, ctable)
228 
229 #define SkSPRITE_CLASSNAME                  Sprite_D16_SIndex8_Opaque
230 #define SkSPRITE_ARGS
231 #define SkSPRITE_FIELDS
232 #define SkSPRITE_INIT
233 #define SkSPRITE_DST_TYPE                   uint16_t
234 #define SkSPRITE_SRC_TYPE                   uint8_t
235 #define SkSPRITE_DST_GETADDR                getAddr16
236 #define SkSPRITE_SRC_GETADDR                getAddr8
237 #define SkSPRITE_PREAMBLE(srcBM, x, y)      const uint16_t* ctable = srcBM.getColorTable()->lock16BitCache()
238 #define SkSPRITE_BLIT_PIXEL(dst, src)       *dst = ctable[src]
239 #define SkSPRITE_NEXT_ROW
240 #define SkSPRITE_POSTAMBLE(srcBM)           srcBM.getColorTable()->unlock16BitCache()
241 #include "SkSpriteBlitterTemplate.h"
242 
243 #define SkSPRITE_CLASSNAME                  Sprite_D16_SIndex8_Blend
244 #define SkSPRITE_ARGS                       , uint8_t alpha
245 #define SkSPRITE_FIELDS                     uint8_t fSrcAlpha;
246 #define SkSPRITE_INIT                       fSrcAlpha = alpha;
247 #define SkSPRITE_DST_TYPE                   uint16_t
248 #define SkSPRITE_SRC_TYPE                   uint8_t
249 #define SkSPRITE_DST_GETADDR                getAddr16
250 #define SkSPRITE_SRC_GETADDR                getAddr8
251 #define SkSPRITE_PREAMBLE(srcBM, x, y)      const uint16_t* ctable = srcBM.getColorTable()->lock16BitCache(); unsigned src_scale = SkAlpha255To256(fSrcAlpha);
252 #define SkSPRITE_BLIT_PIXEL(dst, src)       D16_S16_Blend_Pixel(dst, ctable[src], src_scale)
253 #define SkSPRITE_NEXT_ROW
254 #define SkSPRITE_POSTAMBLE(srcBM)           srcBM.getColorTable()->unlock16BitCache();
255 #include "SkSpriteBlitterTemplate.h"
256 
257 ///////////////////////////////////////////////////////////////////////////////
258 
259 class Sprite_D16_S32_BlitRowProc : public SkSpriteBlitter {
260 public:
Sprite_D16_S32_BlitRowProc(const SkBitmap & source)261     Sprite_D16_S32_BlitRowProc(const SkBitmap& source)
262         : SkSpriteBlitter(source) {}
263 
264     // overrides
265 
setup(const SkBitmap & device,int left,int top,const SkPaint & paint)266     virtual void setup(const SkBitmap& device, int left, int top,
267                        const SkPaint& paint) {
268         this->INHERITED::setup(device, left, top, paint);
269 
270         unsigned flags = 0;
271 
272         if (paint.getAlpha() < 0xFF) {
273             flags |= SkBlitRow::kGlobalAlpha_Flag;
274         }
275         if (!fSource->isOpaque()) {
276             flags |= SkBlitRow::kSrcPixelAlpha_Flag;
277         }
278         if (paint.isDither()) {
279             flags |= SkBlitRow::kDither_Flag;
280         }
281         fProc = SkBlitRow::Factory(flags, SkBitmap::kRGB_565_Config);
282     }
283 
blitRect(int x,int y,int width,int height)284     virtual void blitRect(int x, int y, int width, int height) {
285         uint16_t* SK_RESTRICT dst = fDevice->getAddr16(x, y);
286         const SkPMColor* SK_RESTRICT src = fSource->getAddr32(x - fLeft,
287                                                               y - fTop);
288         unsigned dstRB = fDevice->rowBytes();
289         unsigned srcRB = fSource->rowBytes();
290         SkBlitRow::Proc proc = fProc;
291         U8CPU alpha = fPaint->getAlpha();
292 
293         while (--height >= 0) {
294             proc(dst, src, width, alpha, x, y);
295             y += 1;
296             dst = (uint16_t* SK_RESTRICT)((char*)dst + dstRB);
297             src = (const SkPMColor* SK_RESTRICT)((const char*)src + srcRB);
298         }
299     }
300 
301 private:
302     SkBlitRow::Proc fProc;
303 
304     typedef SkSpriteBlitter INHERITED;
305 };
306 
307 ///////////////////////////////////////////////////////////////////////////////
308 
309 #include "SkTemplatesPriv.h"
310 
ChooseD16(const SkBitmap & source,const SkPaint & paint,void * storage,size_t storageSize)311 SkSpriteBlitter* SkSpriteBlitter::ChooseD16(const SkBitmap& source,
312                                             const SkPaint& paint,
313                                             void* storage, size_t storageSize) {
314     if (paint.getMaskFilter() != NULL) { // may add cases for this
315         return NULL;
316     }
317     if (paint.getXfermode() != NULL) { // may add cases for this
318         return NULL;
319     }
320     if (paint.getColorFilter() != NULL) { // may add cases for this
321         return NULL;
322     }
323 
324     SkSpriteBlitter* blitter = NULL;
325     unsigned alpha = paint.getAlpha();
326 
327     switch (source.getConfig()) {
328         case SkBitmap::kARGB_8888_Config:
329             SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S32_BlitRowProc,
330                                   storage, storageSize, (source));
331             break;
332         case SkBitmap::kARGB_4444_Config:
333             if (255 == alpha) {
334                 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S4444_Opaque,
335                                       storage, storageSize, (source));
336             } else {
337                 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S4444_Blend,
338                                     storage, storageSize, (source, alpha >> 4));
339             }
340             break;
341         case SkBitmap::kRGB_565_Config:
342             if (255 == alpha) {
343                 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S16_Opaque,
344                                       storage, storageSize, (source));
345             } else {
346                 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S16_Blend,
347                                       storage, storageSize, (source, alpha));
348             }
349             break;
350         case SkBitmap::kIndex8_Config:
351             if (paint.isDither()) {
352                 // we don't support dither yet in these special cases
353                 break;
354             }
355             if (source.isOpaque()) {
356                 if (255 == alpha) {
357                     SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8_Opaque,
358                                           storage, storageSize, (source));
359                 } else {
360                     SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8_Blend,
361                                          storage, storageSize, (source, alpha));
362                 }
363             } else {
364                 if (255 == alpha) {
365                     SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8A_Opaque,
366                                           storage, storageSize, (source));
367                 } else {
368                     SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8A_Blend,
369                                          storage, storageSize, (source, alpha));
370                 }
371             }
372             break;
373         default:
374             break;
375     }
376     return blitter;
377 }
378