1 /*
2 * Copyright 2011 Google Inc.
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 #include "SkBlitRow.h"
9 #include "SkColorPriv.h"
10 #include "SkDither.h"
11 #include "SkMathPriv.h"
12
13 ///////////////////////////////////////////////////////////////////////////////
14
S32_D565_Opaque(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha,int,int)15 static void S32_D565_Opaque(uint16_t* SK_RESTRICT dst,
16 const SkPMColor* SK_RESTRICT src, int count,
17 U8CPU alpha, int /*x*/, int /*y*/) {
18 SkASSERT(255 == alpha);
19
20 if (count > 0) {
21 do {
22 SkPMColor c = *src++;
23 SkPMColorAssert(c);
24 *dst++ = SkPixel32ToPixel16_ToU16(c);
25 } while (--count != 0);
26 }
27 }
28
S32_D565_Blend(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha,int,int)29 static void S32_D565_Blend(uint16_t* SK_RESTRICT dst,
30 const SkPMColor* SK_RESTRICT src, int count,
31 U8CPU alpha, int /*x*/, int /*y*/) {
32 SkASSERT(255 > alpha);
33
34 if (count > 0) {
35 int scale = SkAlpha255To256(alpha);
36 do {
37 SkPMColor c = *src++;
38 SkPMColorAssert(c);
39 uint16_t d = *dst;
40 *dst++ = SkPackRGB16(
41 SkAlphaBlend(SkPacked32ToR16(c), SkGetPackedR16(d), scale),
42 SkAlphaBlend(SkPacked32ToG16(c), SkGetPackedG16(d), scale),
43 SkAlphaBlend(SkPacked32ToB16(c), SkGetPackedB16(d), scale));
44 } while (--count != 0);
45 }
46 }
47
S32A_D565_Opaque(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha,int,int)48 static void S32A_D565_Opaque(uint16_t* SK_RESTRICT dst,
49 const SkPMColor* SK_RESTRICT src, int count,
50 U8CPU alpha, int /*x*/, int /*y*/) {
51 SkASSERT(255 == alpha);
52
53 if (count > 0) {
54 do {
55 SkPMColor c = *src++;
56 SkPMColorAssert(c);
57 // if (__builtin_expect(c!=0, 1))
58 if (c) {
59 *dst = SkSrcOver32To16(c, *dst);
60 }
61 dst += 1;
62 } while (--count != 0);
63 }
64 }
65
S32A_D565_Blend(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha,int,int)66 static void S32A_D565_Blend(uint16_t* SK_RESTRICT dst,
67 const SkPMColor* SK_RESTRICT src, int count,
68 U8CPU alpha, int /*x*/, int /*y*/) {
69 SkASSERT(255 > alpha);
70
71 if (count > 0) {
72 do {
73 SkPMColor sc = *src++;
74 SkPMColorAssert(sc);
75 if (sc) {
76 uint16_t dc = *dst;
77 SkPMColor res = SkBlendARGB32(sc, SkPixel16ToPixel32(dc), alpha);
78 *dst = SkPixel32ToPixel16(res);
79 }
80 dst += 1;
81 } while (--count != 0);
82 }
83 }
84
85 /////////////////////////////////////////////////////////////////////////////
86
S32_D565_Opaque_Dither(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha,int x,int y)87 static void S32_D565_Opaque_Dither(uint16_t* SK_RESTRICT dst,
88 const SkPMColor* SK_RESTRICT src,
89 int count, U8CPU alpha, int x, int y) {
90 SkASSERT(255 == alpha);
91
92 if (count > 0) {
93 DITHER_565_SCAN(y);
94 do {
95 SkPMColor c = *src++;
96 SkPMColorAssert(c);
97
98 unsigned dither = DITHER_VALUE(x);
99 *dst++ = SkDitherRGB32To565(c, dither);
100 DITHER_INC_X(x);
101 } while (--count != 0);
102 }
103 }
104
S32_D565_Blend_Dither(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha,int x,int y)105 static void S32_D565_Blend_Dither(uint16_t* SK_RESTRICT dst,
106 const SkPMColor* SK_RESTRICT src,
107 int count, U8CPU alpha, int x, int y) {
108 SkASSERT(255 > alpha);
109
110 if (count > 0) {
111 int scale = SkAlpha255To256(alpha);
112 DITHER_565_SCAN(y);
113 do {
114 SkPMColor c = *src++;
115 SkPMColorAssert(c);
116
117 int dither = DITHER_VALUE(x);
118 int sr = SkGetPackedR32(c);
119 int sg = SkGetPackedG32(c);
120 int sb = SkGetPackedB32(c);
121 sr = SkDITHER_R32To565(sr, dither);
122 sg = SkDITHER_G32To565(sg, dither);
123 sb = SkDITHER_B32To565(sb, dither);
124
125 uint16_t d = *dst;
126 *dst++ = SkPackRGB16(SkAlphaBlend(sr, SkGetPackedR16(d), scale),
127 SkAlphaBlend(sg, SkGetPackedG16(d), scale),
128 SkAlphaBlend(sb, SkGetPackedB16(d), scale));
129 DITHER_INC_X(x);
130 } while (--count != 0);
131 }
132 }
133
S32A_D565_Opaque_Dither(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha,int x,int y)134 static void S32A_D565_Opaque_Dither(uint16_t* SK_RESTRICT dst,
135 const SkPMColor* SK_RESTRICT src,
136 int count, U8CPU alpha, int x, int y) {
137 SkASSERT(255 == alpha);
138
139 if (count > 0) {
140 DITHER_565_SCAN(y);
141 do {
142 SkPMColor c = *src++;
143 SkPMColorAssert(c);
144 if (c) {
145 unsigned a = SkGetPackedA32(c);
146
147 int d = SkAlphaMul(DITHER_VALUE(x), SkAlpha255To256(a));
148
149 unsigned sr = SkGetPackedR32(c);
150 unsigned sg = SkGetPackedG32(c);
151 unsigned sb = SkGetPackedB32(c);
152 sr = SkDITHER_R32_FOR_565(sr, d);
153 sg = SkDITHER_G32_FOR_565(sg, d);
154 sb = SkDITHER_B32_FOR_565(sb, d);
155
156 uint32_t src_expanded = (sg << 24) | (sr << 13) | (sb << 2);
157 uint32_t dst_expanded = SkExpand_rgb_16(*dst);
158 dst_expanded = dst_expanded * (SkAlpha255To256(255 - a) >> 3);
159 // now src and dst expanded are in g:11 r:10 x:1 b:10
160 *dst = SkCompact_rgb_16((src_expanded + dst_expanded) >> 5);
161 }
162 dst += 1;
163 DITHER_INC_X(x);
164 } while (--count != 0);
165 }
166 }
167
S32A_D565_Blend_Dither(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha,int x,int y)168 static void S32A_D565_Blend_Dither(uint16_t* SK_RESTRICT dst,
169 const SkPMColor* SK_RESTRICT src,
170 int count, U8CPU alpha, int x, int y) {
171 SkASSERT(255 > alpha);
172
173 if (count > 0) {
174 int src_scale = SkAlpha255To256(alpha);
175 DITHER_565_SCAN(y);
176 do {
177 SkPMColor c = *src++;
178 SkPMColorAssert(c);
179 if (c)
180 {
181 unsigned d = *dst;
182 int sa = SkGetPackedA32(c);
183 int dst_scale = SkAlpha255To256(255 - SkAlphaMul(sa, src_scale));
184 int dither = DITHER_VALUE(x);
185
186 int sr = SkGetPackedR32(c);
187 int sg = SkGetPackedG32(c);
188 int sb = SkGetPackedB32(c);
189 sr = SkDITHER_R32To565(sr, dither);
190 sg = SkDITHER_G32To565(sg, dither);
191 sb = SkDITHER_B32To565(sb, dither);
192
193 int dr = (sr * src_scale + SkGetPackedR16(d) * dst_scale) >> 8;
194 int dg = (sg * src_scale + SkGetPackedG16(d) * dst_scale) >> 8;
195 int db = (sb * src_scale + SkGetPackedB16(d) * dst_scale) >> 8;
196
197 *dst = SkPackRGB16(dr, dg, db);
198 }
199 dst += 1;
200 DITHER_INC_X(x);
201 } while (--count != 0);
202 }
203 }
204
205 ///////////////////////////////////////////////////////////////////////////////
206
pmcolor_to_expand16(SkPMColor c)207 static uint32_t pmcolor_to_expand16(SkPMColor c) {
208 unsigned r = SkGetPackedR32(c);
209 unsigned g = SkGetPackedG32(c);
210 unsigned b = SkGetPackedB32(c);
211 return (g << 24) | (r << 13) | (b << 2);
212 }
213
Color32A_D565(uint16_t dst[],SkPMColor src,int count,int x,int y)214 static void Color32A_D565(uint16_t dst[], SkPMColor src, int count, int x, int y) {
215 SkASSERT(count > 0);
216 uint32_t src_expand = pmcolor_to_expand16(src);
217 unsigned scale = SkAlpha255To256(0xFF - SkGetPackedA32(src)) >> 3;
218 do {
219 *dst = SkBlend32_RGB16(src_expand, *dst, scale);
220 dst += 1;
221 } while (--count != 0);
222 }
223
224 ///////////////////////////////////////////////////////////////////////////////
225 ///////////////////////////////////////////////////////////////////////////////
226
227 static const SkBlitRow::Proc16 gDefault_565_Procs[] = {
228 // no dither
229 S32_D565_Opaque,
230 S32_D565_Blend,
231
232 S32A_D565_Opaque,
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
Factory16(unsigned flags)243 SkBlitRow::Proc16 SkBlitRow::Factory16(unsigned flags) {
244 SkASSERT(flags < SK_ARRAY_COUNT(gDefault_565_Procs));
245 // just so we don't crash
246 flags &= kFlags16_Mask;
247
248 SkBlitRow::Proc16 proc = PlatformFactory565(flags);
249 if (nullptr == proc) {
250 proc = gDefault_565_Procs[flags];
251 }
252 return proc;
253 }
254
255 static const SkBlitRow::ColorProc16 gDefault_565_ColorProcs[] = {
256 #if 0
257 Color32A_D565,
258 Color32A_D565_Dither
259 #else
260 // TODO: stop cheating and fill dither from the above specializations!
261 Color32A_D565,
262 Color32A_D565,
263 #endif
264 };
265
ColorFactory16(unsigned flags)266 SkBlitRow::ColorProc16 SkBlitRow::ColorFactory16(unsigned flags) {
267 SkASSERT((flags & ~kFlags16_Mask) == 0);
268 // just so we don't crash
269 flags &= kFlags16_Mask;
270 // we ignore both kGlobalAlpha_Flag and kSrcPixelAlpha_Flag, so shift down
271 // no need for the additional code specializing on opaque alpha at this time
272 flags >>= 2;
273
274 SkASSERT(flags < SK_ARRAY_COUNT(gDefault_565_ColorProcs));
275
276 SkBlitRow::ColorProc16 proc = PlatformColorFactory565(flags);
277 if (nullptr == proc) {
278 proc = gDefault_565_ColorProcs[flags];
279 }
280 return proc;
281 }
282