1 #include "SkBlitRow.h"
2 #include "SkColorPriv.h"
3 #include "SkDither.h"
4
5 ///////////////////////////////////////////////////////////////////////////////
6
S32_D565_Opaque(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha,int,int)7 static 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
S32_D565_Blend(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha,int,int)22 static 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
S32A_D565_Opaque(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha,int,int)42 static 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
S32A_D565_Blend(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha,int,int)60 static 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
S32_D565_Opaque_Dither(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha,int x,int y)95 static 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
S32_D565_Blend_Dither(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha,int x,int y)114 static 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
S32A_D565_Opaque_Dither(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha,int x,int y)144 static 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
S32A_D565_Blend_Dither(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha,int x,int y)178 static 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 static const SkBlitRow::Proc gDefault_565_Procs[] = {
219 // no dither
220 S32_D565_Opaque,
221 S32_D565_Blend,
222
223 S32A_D565_Opaque,
224 S32A_D565_Blend,
225
226 // dither
227 S32_D565_Opaque_Dither,
228 S32_D565_Blend_Dither,
229
230 S32A_D565_Opaque_Dither,
231 S32A_D565_Blend_Dither
232 };
233
234 extern SkBlitRow::Proc SkBlitRow_Factory_4444(unsigned flags);
235
Factory(unsigned flags,SkBitmap::Config config)236 SkBlitRow::Proc SkBlitRow::Factory(unsigned flags, SkBitmap::Config config) {
237 SkASSERT(flags < SK_ARRAY_COUNT(gDefault_565_Procs));
238 // just so we don't crash
239 flags &= kFlags16_Mask;
240
241 SkBlitRow::Proc proc = NULL;
242
243 switch (config) {
244 case SkBitmap::kRGB_565_Config:
245 proc = gPlatform_565_Procs[flags];
246 if (NULL == proc) {
247 proc = gDefault_565_Procs[flags];
248 }
249 break;
250 case SkBitmap::kARGB_4444_Config:
251 proc = gPlatform_4444_Procs[flags];
252 if (NULL == proc) {
253 proc = SkBlitRow_Factory_4444(flags);
254 }
255 break;
256 default:
257 break;
258 }
259 return proc;
260 }
261
262