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