blob: f40df36da3fe7017e302c4c095e7691b02c7a787 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001#include "SkBlitRow.h"
2#include "SkColorPriv.h"
3#include "SkDither.h"
4
5///////////////////////////////////////////////////////////////////////////////
6
7static void S32_D565_Opaque(uint16_t* SK_RESTRICT dst,
8 const SkPMColor* SK_RESTRICT src, int count,
9 U8CPU alpha, int /*x*/, int /*y*/) {
10 SkASSERT(255 == alpha);
11
12 if (count > 0) {
13 do {
14 SkPMColor c = *src++;
15 SkPMColorAssert(c);
16 SkASSERT(SkGetPackedA32(c) == 255);
17 *dst++ = SkPixel32ToPixel16_ToU16(c);
18 } while (--count != 0);
19 }
20}
21
22static void S32_D565_Blend(uint16_t* SK_RESTRICT dst,
23 const SkPMColor* SK_RESTRICT src, int count,
24 U8CPU alpha, int /*x*/, int /*y*/) {
25 SkASSERT(255 > alpha);
26
27 if (count > 0) {
28 int scale = SkAlpha255To256(alpha);
29 do {
30 SkPMColor c = *src++;
31 SkPMColorAssert(c);
32 SkASSERT(SkGetPackedA32(c) == 255);
33 uint16_t d = *dst;
34 *dst++ = SkPackRGB16(
35 SkAlphaBlend(SkPacked32ToR16(c), SkGetPackedR16(d), scale),
36 SkAlphaBlend(SkPacked32ToG16(c), SkGetPackedG16(d), scale),
37 SkAlphaBlend(SkPacked32ToB16(c), SkGetPackedB16(d), scale));
38 } while (--count != 0);
39 }
40}
41
42static void S32A_D565_Opaque(uint16_t* SK_RESTRICT dst,
43 const SkPMColor* SK_RESTRICT src, int count,
44 U8CPU alpha, int /*x*/, int /*y*/) {
45 SkASSERT(255 == alpha);
46
47 if (count > 0) {
48 do {
49 SkPMColor c = *src++;
50 SkPMColorAssert(c);
51// if (__builtin_expect(c!=0, 1))
52 if (c) {
53 *dst = SkSrcOver32To16(c, *dst);
54 }
55 dst += 1;
56 } while (--count != 0);
57 }
58}
59
60static void S32A_D565_Blend(uint16_t* SK_RESTRICT dst,
61 const SkPMColor* SK_RESTRICT src, int count,
62 U8CPU alpha, int /*x*/, int /*y*/) {
63 SkASSERT(255 > alpha);
64
65 if (count > 0) {
66 int src_scale = SkAlpha255To256(alpha);
67 do {
68 SkPMColor sc = *src++;
69 SkPMColorAssert(sc);
70 if (sc)
71 {
72 uint16_t dc = *dst;
73 unsigned sa = SkGetPackedA32(sc);
74 unsigned dr, dg, db;
75
76 if (sa == 255) {
77 dr = SkAlphaBlend(SkPacked32ToR16(sc), SkGetPackedR16(dc), src_scale);
78 dg = SkAlphaBlend(SkPacked32ToG16(sc), SkGetPackedG16(dc), src_scale);
79 db = SkAlphaBlend(SkPacked32ToB16(sc), SkGetPackedB16(dc), src_scale);
80 } else {
81 unsigned dst_scale = 255 - SkAlphaMul(sa, src_scale);
82 dr = (SkPacked32ToR16(sc) * src_scale + SkGetPackedR16(dc) * dst_scale) >> 8;
83 dg = (SkPacked32ToG16(sc) * src_scale + SkGetPackedG16(dc) * dst_scale) >> 8;
84 db = (SkPacked32ToB16(sc) * src_scale + SkGetPackedB16(dc) * dst_scale) >> 8;
85 }
86 *dst = SkPackRGB16(dr, dg, db);
87 }
88 dst += 1;
89 } while (--count != 0);
90 }
91}
92
93/////////////////////////////////////////////////////////////////////////////
94
95static void S32_D565_Opaque_Dither(uint16_t* SK_RESTRICT dst,
96 const SkPMColor* SK_RESTRICT src,
97 int count, U8CPU alpha, int x, int y) {
98 SkASSERT(255 == alpha);
99
100 if (count > 0) {
101 DITHER_565_SCAN(y);
102 do {
103 SkPMColor c = *src++;
104 SkPMColorAssert(c);
105 SkASSERT(SkGetPackedA32(c) == 255);
106
107 unsigned dither = DITHER_VALUE(x);
108 *dst++ = SkDitherRGB32To565(c, dither);
109 DITHER_INC_X(x);
110 } while (--count != 0);
111 }
112}
113
114static void S32_D565_Blend_Dither(uint16_t* SK_RESTRICT dst,
115 const SkPMColor* SK_RESTRICT src,
116 int count, U8CPU alpha, int x, int y) {
117 SkASSERT(255 > alpha);
118
119 if (count > 0) {
120 int scale = SkAlpha255To256(alpha);
121 DITHER_565_SCAN(y);
122 do {
123 SkPMColor c = *src++;
124 SkPMColorAssert(c);
125 SkASSERT(SkGetPackedA32(c) == 255);
126
127 int dither = DITHER_VALUE(x);
128 int sr = SkGetPackedR32(c);
129 int sg = SkGetPackedG32(c);
130 int sb = SkGetPackedB32(c);
131 sr = SkDITHER_R32To565(sr, dither);
132 sg = SkDITHER_G32To565(sg, dither);
133 sb = SkDITHER_B32To565(sb, dither);
134
135 uint16_t d = *dst;
136 *dst++ = SkPackRGB16(SkAlphaBlend(sr, SkGetPackedR16(d), scale),
137 SkAlphaBlend(sg, SkGetPackedG16(d), scale),
138 SkAlphaBlend(sb, SkGetPackedB16(d), scale));
139 DITHER_INC_X(x);
140 } while (--count != 0);
141 }
142}
143
144static void S32A_D565_Opaque_Dither(uint16_t* SK_RESTRICT dst,
145 const SkPMColor* SK_RESTRICT src,
146 int count, U8CPU alpha, int x, int y) {
147 SkASSERT(255 == alpha);
148
149 if (count > 0) {
150 DITHER_565_SCAN(y);
151 do {
152 SkPMColor c = *src++;
153 SkPMColorAssert(c);
154 if (c) {
155 unsigned a = SkGetPackedA32(c);
156
157 int d = SkAlphaMul(DITHER_VALUE(x), SkAlpha255To256(a));
158
159 unsigned sr = SkGetPackedR32(c);
160 unsigned sg = SkGetPackedG32(c);
161 unsigned sb = SkGetPackedB32(c);
162 sr = SkDITHER_R32_FOR_565(sr, d);
163 sg = SkDITHER_G32_FOR_565(sg, d);
164 sb = SkDITHER_B32_FOR_565(sb, d);
165
166 uint32_t src_expanded = (sg << 24) | (sr << 13) | (sb << 2);
167 uint32_t dst_expanded = SkExpand_rgb_16(*dst);
168 dst_expanded = dst_expanded * (SkAlpha255To256(255 - a) >> 3);
169 // now src and dst expanded are in g:11 r:10 x:1 b:10
170 *dst = SkCompact_rgb_16((src_expanded + dst_expanded) >> 5);
171 }
172 dst += 1;
173 DITHER_INC_X(x);
174 } while (--count != 0);
175 }
176}
177
178static void S32A_D565_Blend_Dither(uint16_t* SK_RESTRICT dst,
179 const SkPMColor* SK_RESTRICT src,
180 int count, U8CPU alpha, int x, int y) {
181 SkASSERT(255 > alpha);
182
183 if (count > 0) {
184 int src_scale = SkAlpha255To256(alpha);
185 DITHER_565_SCAN(y);
186 do {
187 SkPMColor c = *src++;
188 SkPMColorAssert(c);
189 if (c)
190 {
191 unsigned d = *dst;
192 int sa = SkGetPackedA32(c);
193 int dst_scale = SkAlpha255To256(255 - SkAlphaMul(sa, src_scale));
194 int dither = DITHER_VALUE(x);
195
196 int sr = SkGetPackedR32(c);
197 int sg = SkGetPackedG32(c);
198 int sb = SkGetPackedB32(c);
199 sr = SkDITHER_R32To565(sr, dither);
200 sg = SkDITHER_G32To565(sg, dither);
201 sb = SkDITHER_B32To565(sb, dither);
202
203 int dr = (sr * src_scale + SkGetPackedR16(d) * dst_scale) >> 8;
204 int dg = (sg * src_scale + SkGetPackedG16(d) * dst_scale) >> 8;
205 int db = (sb * src_scale + SkGetPackedB16(d) * dst_scale) >> 8;
206
207 *dst = SkPackRGB16(dr, dg, db);
208 }
209 dst += 1;
210 DITHER_INC_X(x);
211 } while (--count != 0);
212 }
213}
214
215///////////////////////////////////////////////////////////////////////////////
216///////////////////////////////////////////////////////////////////////////////
217
218#ifdef USE_T32CB16BLEND_ASM
219 extern "C" void scanline_t32cb16blend_arm(uint16_t*, uint32_t*, size_t);
220#endif
221
222static const SkBlitRow::Proc gProcs16[] = {
223 // no dither
224 S32_D565_Opaque,
225 S32_D565_Blend,
226
227#ifdef USE_T32CB16BLEND_ASM
228 (SkBlitRow::Proc)scanline_t32cb16blend_arm,
229#else
230 S32A_D565_Opaque,
231#endif
232
233 S32A_D565_Blend,
234
235 // dither
236 S32_D565_Opaque_Dither,
237 S32_D565_Blend_Dither,
238
239 S32A_D565_Opaque_Dither,
240 S32A_D565_Blend_Dither
241};
242
243extern SkBlitRow::Proc SkBlitRow_Factory_4444(unsigned flags);
244
245SkBlitRow::Proc SkBlitRow::Factory(unsigned flags, SkBitmap::Config config) {
246 SkASSERT(flags < SK_ARRAY_COUNT(gProcs16));
247
248 switch (config) {
249 case SkBitmap::kRGB_565_Config:
250 return gProcs16[flags];
251 case SkBitmap::kARGB_4444_Config:
252 return SkBlitRow_Factory_4444(flags);
253 default:
254 break;
255 }
256 return NULL;
257}
258