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