|
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 |
|
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 |
|
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 |
|
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 |
|
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 unsigned dst_scale = 255 - SkMulDiv255Round(SkGetPackedA32(sc), alpha); |
|
78 unsigned dr = SkMulS16(SkPacked32ToR16(sc), alpha) + SkMulS16(SkGetPackedR16(dc), dst_scale); |
|
79 unsigned dg = SkMulS16(SkPacked32ToG16(sc), alpha) + SkMulS16(SkGetPackedG16(dc), dst_scale); |
|
80 unsigned db = SkMulS16(SkPacked32ToB16(sc), alpha) + SkMulS16(SkGetPackedB16(dc), dst_scale); |
|
81 *dst = SkPackRGB16(SkDiv255Round(dr), SkDiv255Round(dg), SkDiv255Round(db)); |
|
82 } |
|
83 dst += 1; |
|
84 } while (--count != 0); |
|
85 } |
|
86 } |
|
87 |
|
88 ///////////////////////////////////////////////////////////////////////////// |
|
89 |
|
90 static void S32_D565_Opaque_Dither(uint16_t* SK_RESTRICT dst, |
|
91 const SkPMColor* SK_RESTRICT src, |
|
92 int count, U8CPU alpha, int x, int y) { |
|
93 SkASSERT(255 == alpha); |
|
94 |
|
95 if (count > 0) { |
|
96 DITHER_565_SCAN(y); |
|
97 do { |
|
98 SkPMColor c = *src++; |
|
99 SkPMColorAssert(c); |
|
100 |
|
101 unsigned dither = DITHER_VALUE(x); |
|
102 *dst++ = SkDitherRGB32To565(c, dither); |
|
103 DITHER_INC_X(x); |
|
104 } while (--count != 0); |
|
105 } |
|
106 } |
|
107 |
|
108 static void S32_D565_Blend_Dither(uint16_t* SK_RESTRICT dst, |
|
109 const SkPMColor* SK_RESTRICT src, |
|
110 int count, U8CPU alpha, int x, int y) { |
|
111 SkASSERT(255 > alpha); |
|
112 |
|
113 if (count > 0) { |
|
114 int scale = SkAlpha255To256(alpha); |
|
115 DITHER_565_SCAN(y); |
|
116 do { |
|
117 SkPMColor c = *src++; |
|
118 SkPMColorAssert(c); |
|
119 |
|
120 int dither = DITHER_VALUE(x); |
|
121 int sr = SkGetPackedR32(c); |
|
122 int sg = SkGetPackedG32(c); |
|
123 int sb = SkGetPackedB32(c); |
|
124 sr = SkDITHER_R32To565(sr, dither); |
|
125 sg = SkDITHER_G32To565(sg, dither); |
|
126 sb = SkDITHER_B32To565(sb, dither); |
|
127 |
|
128 uint16_t d = *dst; |
|
129 *dst++ = SkPackRGB16(SkAlphaBlend(sr, SkGetPackedR16(d), scale), |
|
130 SkAlphaBlend(sg, SkGetPackedG16(d), scale), |
|
131 SkAlphaBlend(sb, SkGetPackedB16(d), scale)); |
|
132 DITHER_INC_X(x); |
|
133 } while (--count != 0); |
|
134 } |
|
135 } |
|
136 |
|
137 static void S32A_D565_Opaque_Dither(uint16_t* SK_RESTRICT dst, |
|
138 const SkPMColor* SK_RESTRICT src, |
|
139 int count, U8CPU alpha, int x, int y) { |
|
140 SkASSERT(255 == alpha); |
|
141 |
|
142 if (count > 0) { |
|
143 DITHER_565_SCAN(y); |
|
144 do { |
|
145 SkPMColor c = *src++; |
|
146 SkPMColorAssert(c); |
|
147 if (c) { |
|
148 unsigned a = SkGetPackedA32(c); |
|
149 |
|
150 int d = SkAlphaMul(DITHER_VALUE(x), SkAlpha255To256(a)); |
|
151 |
|
152 unsigned sr = SkGetPackedR32(c); |
|
153 unsigned sg = SkGetPackedG32(c); |
|
154 unsigned sb = SkGetPackedB32(c); |
|
155 sr = SkDITHER_R32_FOR_565(sr, d); |
|
156 sg = SkDITHER_G32_FOR_565(sg, d); |
|
157 sb = SkDITHER_B32_FOR_565(sb, d); |
|
158 |
|
159 uint32_t src_expanded = (sg << 24) | (sr << 13) | (sb << 2); |
|
160 uint32_t dst_expanded = SkExpand_rgb_16(*dst); |
|
161 dst_expanded = dst_expanded * (SkAlpha255To256(255 - a) >> 3); |
|
162 // now src and dst expanded are in g:11 r:10 x:1 b:10 |
|
163 *dst = SkCompact_rgb_16((src_expanded + dst_expanded) >> 5); |
|
164 } |
|
165 dst += 1; |
|
166 DITHER_INC_X(x); |
|
167 } while (--count != 0); |
|
168 } |
|
169 } |
|
170 |
|
171 static void S32A_D565_Blend_Dither(uint16_t* SK_RESTRICT dst, |
|
172 const SkPMColor* SK_RESTRICT src, |
|
173 int count, U8CPU alpha, int x, int y) { |
|
174 SkASSERT(255 > alpha); |
|
175 |
|
176 if (count > 0) { |
|
177 int src_scale = SkAlpha255To256(alpha); |
|
178 DITHER_565_SCAN(y); |
|
179 do { |
|
180 SkPMColor c = *src++; |
|
181 SkPMColorAssert(c); |
|
182 if (c) |
|
183 { |
|
184 unsigned d = *dst; |
|
185 int sa = SkGetPackedA32(c); |
|
186 int dst_scale = SkAlpha255To256(255 - SkAlphaMul(sa, src_scale)); |
|
187 int dither = DITHER_VALUE(x); |
|
188 |
|
189 int sr = SkGetPackedR32(c); |
|
190 int sg = SkGetPackedG32(c); |
|
191 int sb = SkGetPackedB32(c); |
|
192 sr = SkDITHER_R32To565(sr, dither); |
|
193 sg = SkDITHER_G32To565(sg, dither); |
|
194 sb = SkDITHER_B32To565(sb, dither); |
|
195 |
|
196 int dr = (sr * src_scale + SkGetPackedR16(d) * dst_scale) >> 8; |
|
197 int dg = (sg * src_scale + SkGetPackedG16(d) * dst_scale) >> 8; |
|
198 int db = (sb * src_scale + SkGetPackedB16(d) * dst_scale) >> 8; |
|
199 |
|
200 *dst = SkPackRGB16(dr, dg, db); |
|
201 } |
|
202 dst += 1; |
|
203 DITHER_INC_X(x); |
|
204 } while (--count != 0); |
|
205 } |
|
206 } |
|
207 |
|
208 /////////////////////////////////////////////////////////////////////////////// |
|
209 /////////////////////////////////////////////////////////////////////////////// |
|
210 |
|
211 static const SkBlitRow::Proc gDefault_565_Procs[] = { |
|
212 // no dither |
|
213 S32_D565_Opaque, |
|
214 S32_D565_Blend, |
|
215 |
|
216 S32A_D565_Opaque, |
|
217 S32A_D565_Blend, |
|
218 |
|
219 // dither |
|
220 S32_D565_Opaque_Dither, |
|
221 S32_D565_Blend_Dither, |
|
222 |
|
223 S32A_D565_Opaque_Dither, |
|
224 S32A_D565_Blend_Dither |
|
225 }; |
|
226 |
|
227 SkBlitRow::Proc SkBlitRow::Factory(unsigned flags, SkBitmap::Config config) { |
|
228 SkASSERT(flags < SK_ARRAY_COUNT(gDefault_565_Procs)); |
|
229 // just so we don't crash |
|
230 flags &= kFlags16_Mask; |
|
231 |
|
232 SkBlitRow::Proc proc = NULL; |
|
233 |
|
234 switch (config) { |
|
235 case SkBitmap::kRGB_565_Config: |
|
236 proc = PlatformProcs565(flags); |
|
237 if (NULL == proc) { |
|
238 proc = gDefault_565_Procs[flags]; |
|
239 } |
|
240 break; |
|
241 default: |
|
242 break; |
|
243 } |
|
244 return proc; |
|
245 } |