• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* libs/graphics/sgl/SkSpriteBlitter_ARGB32.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 "SkColorFilter.h"
21 #include "SkColorPriv.h"
22 #include "SkTemplates.h"
23 #include "SkUtils.h"
24 #include "SkXfermode.h"
25 
26 ///////////////////////////////////////////////////////////////////////////////
27 
28 class Sprite_D32_S32 : public SkSpriteBlitter {
29 public:
Sprite_D32_S32(const SkBitmap & src,U8CPU alpha)30     Sprite_D32_S32(const SkBitmap& src, U8CPU alpha)  : INHERITED(src) {
31         SkASSERT(src.config() == SkBitmap::kARGB_8888_Config);
32 
33         unsigned flags32 = 0;
34         if (255 != alpha) {
35             flags32 |= SkBlitRow::kGlobalAlpha_Flag32;
36         }
37         if (!src.isOpaque()) {
38             flags32 |= SkBlitRow::kSrcPixelAlpha_Flag32;
39         }
40 
41         fProc32 = SkBlitRow::Factory32(flags32);
42         fAlpha = alpha;
43     }
44 
blitRect(int x,int y,int width,int height)45     virtual void blitRect(int x, int y, int width, int height) {
46         SkASSERT(width > 0 && height > 0);
47         SK_RESTRICT uint32_t* dst = fDevice->getAddr32(x, y);
48         const SK_RESTRICT uint32_t* src = fSource->getAddr32(x - fLeft,
49                                                              y - fTop);
50         size_t dstRB = fDevice->rowBytes();
51         size_t srcRB = fSource->rowBytes();
52         SkBlitRow::Proc32 proc = fProc32;
53         U8CPU             alpha = fAlpha;
54 
55         do {
56             proc(dst, src, width, alpha);
57             dst = (SK_RESTRICT uint32_t*)((char*)dst + dstRB);
58             src = (const SK_RESTRICT uint32_t*)((const char*)src + srcRB);
59         } while (--height != 0);
60     }
61 
62 private:
63     SkBlitRow::Proc32   fProc32;
64     U8CPU               fAlpha;
65 
66     typedef SkSpriteBlitter INHERITED;
67 };
68 
69 ///////////////////////////////////////////////////////////////////////////////
70 
71 class Sprite_D32_XferFilter : public SkSpriteBlitter {
72 public:
Sprite_D32_XferFilter(const SkBitmap & source,const SkPaint & paint)73     Sprite_D32_XferFilter(const SkBitmap& source, const SkPaint& paint)
74         : SkSpriteBlitter(source) {
75         fColorFilter = paint.getColorFilter();
76         fColorFilter->safeRef();
77 
78         fXfermode = paint.getXfermode();
79         fXfermode->safeRef();
80 
81         fBufferSize = 0;
82         fBuffer = NULL;
83 
84         unsigned flags32 = 0;
85         if (255 != paint.getAlpha()) {
86             flags32 |= SkBlitRow::kGlobalAlpha_Flag32;
87         }
88         if (!source.isOpaque()) {
89             flags32 |= SkBlitRow::kSrcPixelAlpha_Flag32;
90         }
91 
92         fProc32 = SkBlitRow::Factory32(flags32);
93         fAlpha = paint.getAlpha();
94     }
95 
~Sprite_D32_XferFilter()96     virtual ~Sprite_D32_XferFilter() {
97         delete[] fBuffer;
98         fXfermode->safeUnref();
99         fColorFilter->safeUnref();
100     }
101 
setup(const SkBitmap & device,int left,int top,const SkPaint & paint)102     virtual void setup(const SkBitmap& device, int left, int top,
103                        const SkPaint& paint) {
104         this->INHERITED::setup(device, left, top, paint);
105 
106         int width = device.width();
107         if (width > fBufferSize) {
108             fBufferSize = width;
109             delete[] fBuffer;
110             fBuffer = new SkPMColor[width];
111         }
112     }
113 
114 protected:
115     SkColorFilter*      fColorFilter;
116     SkXfermode*         fXfermode;
117     int                 fBufferSize;
118     SkPMColor*          fBuffer;
119     SkBlitRow::Proc32   fProc32;
120     U8CPU               fAlpha;
121 
122 private:
123     typedef SkSpriteBlitter INHERITED;
124 };
125 
126 ///////////////////////////////////////////////////////////////////////////////
127 
128 class Sprite_D32_S32A_XferFilter : public Sprite_D32_XferFilter {
129 public:
Sprite_D32_S32A_XferFilter(const SkBitmap & source,const SkPaint & paint)130     Sprite_D32_S32A_XferFilter(const SkBitmap& source, const SkPaint& paint)
131         : Sprite_D32_XferFilter(source, paint) {}
132 
blitRect(int x,int y,int width,int height)133     virtual void blitRect(int x, int y, int width, int height) {
134         SkASSERT(width > 0 && height > 0);
135         SK_RESTRICT uint32_t* dst = fDevice->getAddr32(x, y);
136         const SK_RESTRICT uint32_t* src = fSource->getAddr32(x - fLeft,
137                                                              y - fTop);
138         unsigned dstRB = fDevice->rowBytes();
139         unsigned srcRB = fSource->rowBytes();
140         SkColorFilter* colorFilter = fColorFilter;
141         SkXfermode* xfermode = fXfermode;
142 
143         do {
144             const SkPMColor* tmp = src;
145 
146             if (NULL != colorFilter) {
147                 colorFilter->filterSpan(src, width, fBuffer);
148                 tmp = fBuffer;
149             }
150 
151             if (NULL != xfermode) {
152                 xfermode->xfer32(dst, tmp, width, NULL);
153             } else {
154                 fProc32(dst, tmp, width, fAlpha);
155             }
156 
157             dst = (SK_RESTRICT uint32_t*)((char*)dst + dstRB);
158             src = (const SK_RESTRICT uint32_t*)((const char*)src + srcRB);
159         } while (--height != 0);
160     }
161 
162 private:
163     typedef Sprite_D32_XferFilter INHERITED;
164 };
165 
fillbuffer(SK_RESTRICT SkPMColor dst[],const SK_RESTRICT SkPMColor16 src[],int count)166 static void fillbuffer(SK_RESTRICT SkPMColor dst[],
167                        const SK_RESTRICT SkPMColor16 src[], int count) {
168     SkASSERT(count > 0);
169 
170     do {
171         *dst++ = SkPixel4444ToPixel32(*src++);
172     } while (--count != 0);
173 }
174 
175 class Sprite_D32_S4444_XferFilter : public Sprite_D32_XferFilter {
176 public:
Sprite_D32_S4444_XferFilter(const SkBitmap & source,const SkPaint & paint)177     Sprite_D32_S4444_XferFilter(const SkBitmap& source, const SkPaint& paint)
178         : Sprite_D32_XferFilter(source, paint) {}
179 
blitRect(int x,int y,int width,int height)180     virtual void blitRect(int x, int y, int width, int height) {
181         SkASSERT(width > 0 && height > 0);
182         SK_RESTRICT SkPMColor* dst = fDevice->getAddr32(x, y);
183         const SK_RESTRICT SkPMColor16* src = fSource->getAddr16(x - fLeft,
184                                                                 y - fTop);
185         unsigned dstRB = fDevice->rowBytes();
186         unsigned srcRB = fSource->rowBytes();
187         SK_RESTRICT SkPMColor* buffer = fBuffer;
188         SkColorFilter* colorFilter = fColorFilter;
189         SkXfermode* xfermode = fXfermode;
190 
191         do {
192             fillbuffer(buffer, src, width);
193 
194             if (NULL != colorFilter) {
195                 colorFilter->filterSpan(buffer, width, buffer);
196             }
197             if (NULL != xfermode) {
198                 xfermode->xfer32(dst, buffer, width, NULL);
199             } else {
200                 fProc32(dst, buffer, width, fAlpha);
201             }
202 
203             dst = (SK_RESTRICT SkPMColor*)((char*)dst + dstRB);
204             src = (const SK_RESTRICT SkPMColor16*)((const char*)src + srcRB);
205         } while (--height != 0);
206     }
207 
208 private:
209     typedef Sprite_D32_XferFilter INHERITED;
210 };
211 
212 ///////////////////////////////////////////////////////////////////////////////
213 
src_row(SK_RESTRICT SkPMColor dst[],const SK_RESTRICT SkPMColor16 src[],int count)214 static void src_row(SK_RESTRICT SkPMColor dst[],
215                     const SK_RESTRICT SkPMColor16 src[], int count) {
216     do {
217         *dst = SkPixel4444ToPixel32(*src);
218         src += 1;
219         dst += 1;
220     } while (--count != 0);
221 }
222 
223 class Sprite_D32_S4444_Opaque : public SkSpriteBlitter {
224 public:
Sprite_D32_S4444_Opaque(const SkBitmap & source)225     Sprite_D32_S4444_Opaque(const SkBitmap& source) : SkSpriteBlitter(source) {}
226 
blitRect(int x,int y,int width,int height)227     virtual void blitRect(int x, int y, int width, int height) {
228         SkASSERT(width > 0 && height > 0);
229         SK_RESTRICT SkPMColor* dst = fDevice->getAddr32(x, y);
230         const SK_RESTRICT SkPMColor16* src = fSource->getAddr16(x - fLeft,
231                                                                 y - fTop);
232         unsigned dstRB = fDevice->rowBytes();
233         unsigned srcRB = fSource->rowBytes();
234 
235         do {
236             src_row(dst, src, width);
237             dst = (SK_RESTRICT SkPMColor*)((char*)dst + dstRB);
238             src = (const SK_RESTRICT SkPMColor16*)((const char*)src + srcRB);
239         } while (--height != 0);
240     }
241 };
242 
srcover_row(SK_RESTRICT SkPMColor dst[],const SK_RESTRICT SkPMColor16 src[],int count)243 static void srcover_row(SK_RESTRICT SkPMColor dst[],
244                         const SK_RESTRICT SkPMColor16 src[], int count) {
245     do {
246         *dst = SkPMSrcOver(SkPixel4444ToPixel32(*src), *dst);
247         src += 1;
248         dst += 1;
249     } while (--count != 0);
250 }
251 
252 class Sprite_D32_S4444 : public SkSpriteBlitter {
253 public:
Sprite_D32_S4444(const SkBitmap & source)254     Sprite_D32_S4444(const SkBitmap& source) : SkSpriteBlitter(source) {}
255 
blitRect(int x,int y,int width,int height)256     virtual void blitRect(int x, int y, int width, int height) {
257         SkASSERT(width > 0 && height > 0);
258         SK_RESTRICT SkPMColor* dst = fDevice->getAddr32(x, y);
259         const SK_RESTRICT SkPMColor16* src = fSource->getAddr16(x - fLeft,
260                                                                 y - fTop);
261         unsigned dstRB = fDevice->rowBytes();
262         unsigned srcRB = fSource->rowBytes();
263 
264         do {
265             srcover_row(dst, src, width);
266             dst = (SK_RESTRICT SkPMColor*)((char*)dst + dstRB);
267             src = (const SK_RESTRICT SkPMColor16*)((const char*)src + srcRB);
268         } while (--height != 0);
269     }
270 };
271 
272 ///////////////////////////////////////////////////////////////////////////////
273 
274 #include "SkTemplatesPriv.h"
275 
ChooseD32(const SkBitmap & source,const SkPaint & paint,void * storage,size_t storageSize)276 SkSpriteBlitter* SkSpriteBlitter::ChooseD32(const SkBitmap& source,
277                                             const SkPaint& paint,
278                                             void* storage, size_t storageSize) {
279     if (paint.getMaskFilter() != NULL) {
280         return NULL;
281     }
282 
283     U8CPU       alpha = paint.getAlpha();
284     SkXfermode* xfermode = paint.getXfermode();
285     SkColorFilter* filter = paint.getColorFilter();
286     SkSpriteBlitter* blitter = NULL;
287 
288     switch (source.getConfig()) {
289         case SkBitmap::kARGB_4444_Config:
290             if (alpha != 0xFF) {
291                 return NULL;    // we only have opaque sprites
292             }
293             if (xfermode || filter) {
294                 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S4444_XferFilter,
295                                       storage, storageSize, (source, paint));
296             } else if (source.isOpaque()) {
297                 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S4444_Opaque,
298                                       storage, storageSize, (source));
299             } else {
300                 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S4444,
301                                       storage, storageSize, (source));
302             }
303             break;
304         case SkBitmap::kARGB_8888_Config:
305             if (xfermode || filter) {
306                 if (255 == alpha) {
307                     // this can handle xfermode or filter, but not alpha
308                     SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S32A_XferFilter,
309                                       storage, storageSize, (source, paint));
310                 }
311             } else {
312                 // this can handle alpha, but not xfermode or filter
313                 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S32,
314                               storage, storageSize, (source, alpha));
315             }
316             break;
317         default:
318             break;
319     }
320     return blitter;
321 }
322 
323