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