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