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