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