Line data Source code
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 0 : 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 0 : SkASSERT(255 == alpha);
19 :
20 0 : if (count > 0) {
21 0 : do {
22 0 : SkPMColor c = *src++;
23 0 : SkPMColorAssert(c);
24 0 : *dst++ = SkPixel32ToPixel16_ToU16(c);
25 : } while (--count != 0);
26 : }
27 0 : }
28 :
29 0 : 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 0 : SkASSERT(255 > alpha);
33 :
34 0 : if (count > 0) {
35 0 : int scale = SkAlpha255To256(alpha);
36 0 : do {
37 0 : SkPMColor c = *src++;
38 0 : SkPMColorAssert(c);
39 0 : uint16_t d = *dst;
40 0 : *dst++ = SkPackRGB16(
41 0 : SkAlphaBlend(SkPacked32ToR16(c), SkGetPackedR16(d), scale),
42 0 : SkAlphaBlend(SkPacked32ToG16(c), SkGetPackedG16(d), scale),
43 0 : SkAlphaBlend(SkPacked32ToB16(c), SkGetPackedB16(d), scale));
44 : } while (--count != 0);
45 : }
46 0 : }
47 :
48 0 : 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 0 : SkASSERT(255 == alpha);
52 :
53 0 : if (count > 0) {
54 0 : do {
55 0 : SkPMColor c = *src++;
56 0 : SkPMColorAssert(c);
57 : // if (__builtin_expect(c!=0, 1))
58 0 : if (c) {
59 0 : *dst = SkSrcOver32To16(c, *dst);
60 : }
61 0 : dst += 1;
62 : } while (--count != 0);
63 : }
64 0 : }
65 :
66 0 : 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 0 : SkASSERT(255 > alpha);
70 :
71 0 : if (count > 0) {
72 0 : do {
73 0 : SkPMColor sc = *src++;
74 0 : SkPMColorAssert(sc);
75 0 : if (sc) {
76 0 : uint16_t dc = *dst;
77 0 : SkPMColor res = SkBlendARGB32(sc, SkPixel16ToPixel32(dc), alpha);
78 0 : *dst = SkPixel32ToPixel16(res);
79 : }
80 0 : dst += 1;
81 : } while (--count != 0);
82 : }
83 0 : }
84 :
85 : /////////////////////////////////////////////////////////////////////////////
86 :
87 0 : 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 0 : SkASSERT(255 == alpha);
91 :
92 0 : if (count > 0) {
93 0 : DITHER_565_SCAN(y);
94 0 : do {
95 0 : SkPMColor c = *src++;
96 0 : SkPMColorAssert(c);
97 :
98 0 : unsigned dither = DITHER_VALUE(x);
99 0 : *dst++ = SkDitherRGB32To565(c, dither);
100 0 : DITHER_INC_X(x);
101 : } while (--count != 0);
102 : }
103 0 : }
104 :
105 0 : 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 0 : SkASSERT(255 > alpha);
109 :
110 0 : if (count > 0) {
111 0 : int scale = SkAlpha255To256(alpha);
112 0 : DITHER_565_SCAN(y);
113 0 : do {
114 0 : SkPMColor c = *src++;
115 0 : SkPMColorAssert(c);
116 :
117 0 : int dither = DITHER_VALUE(x);
118 0 : int sr = SkGetPackedR32(c);
119 0 : int sg = SkGetPackedG32(c);
120 0 : int sb = SkGetPackedB32(c);
121 0 : sr = SkDITHER_R32To565(sr, dither);
122 0 : sg = SkDITHER_G32To565(sg, dither);
123 0 : sb = SkDITHER_B32To565(sb, dither);
124 :
125 0 : uint16_t d = *dst;
126 0 : *dst++ = SkPackRGB16(SkAlphaBlend(sr, SkGetPackedR16(d), scale),
127 0 : SkAlphaBlend(sg, SkGetPackedG16(d), scale),
128 0 : SkAlphaBlend(sb, SkGetPackedB16(d), scale));
129 0 : DITHER_INC_X(x);
130 : } while (--count != 0);
131 : }
132 0 : }
133 :
134 0 : 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 0 : SkASSERT(255 == alpha);
138 :
139 0 : if (count > 0) {
140 0 : DITHER_565_SCAN(y);
141 0 : do {
142 0 : SkPMColor c = *src++;
143 0 : SkPMColorAssert(c);
144 0 : if (c) {
145 0 : unsigned a = SkGetPackedA32(c);
146 :
147 0 : int d = SkAlphaMul(DITHER_VALUE(x), SkAlpha255To256(a));
148 :
149 0 : unsigned sr = SkGetPackedR32(c);
150 0 : unsigned sg = SkGetPackedG32(c);
151 0 : unsigned sb = SkGetPackedB32(c);
152 0 : sr = SkDITHER_R32_FOR_565(sr, d);
153 0 : sg = SkDITHER_G32_FOR_565(sg, d);
154 0 : sb = SkDITHER_B32_FOR_565(sb, d);
155 :
156 0 : uint32_t src_expanded = (sg << 24) | (sr << 13) | (sb << 2);
157 0 : uint32_t dst_expanded = SkExpand_rgb_16(*dst);
158 0 : 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 0 : *dst = SkCompact_rgb_16((src_expanded + dst_expanded) >> 5);
161 : }
162 0 : dst += 1;
163 0 : DITHER_INC_X(x);
164 : } while (--count != 0);
165 : }
166 0 : }
167 :
168 0 : 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 0 : SkASSERT(255 > alpha);
172 :
173 0 : if (count > 0) {
174 0 : int src_scale = SkAlpha255To256(alpha);
175 0 : DITHER_565_SCAN(y);
176 0 : do {
177 0 : SkPMColor c = *src++;
178 0 : SkPMColorAssert(c);
179 0 : if (c)
180 : {
181 0 : unsigned d = *dst;
182 0 : int sa = SkGetPackedA32(c);
183 0 : int dst_scale = SkAlphaMulInv256(sa, src_scale);
184 0 : int dither = DITHER_VALUE(x);
185 :
186 0 : int sr = SkGetPackedR32(c);
187 0 : int sg = SkGetPackedG32(c);
188 0 : int sb = SkGetPackedB32(c);
189 0 : sr = SkDITHER_R32To565(sr, dither);
190 0 : sg = SkDITHER_G32To565(sg, dither);
191 0 : sb = SkDITHER_B32To565(sb, dither);
192 :
193 0 : int dr = (sr * src_scale + SkGetPackedR16(d) * dst_scale) >> 8;
194 0 : int dg = (sg * src_scale + SkGetPackedG16(d) * dst_scale) >> 8;
195 0 : int db = (sb * src_scale + SkGetPackedB16(d) * dst_scale) >> 8;
196 :
197 0 : *dst = SkPackRGB16(dr, dg, db);
198 : }
199 0 : dst += 1;
200 0 : DITHER_INC_X(x);
201 : } while (--count != 0);
202 : }
203 0 : }
204 :
205 : ///////////////////////////////////////////////////////////////////////////////
206 :
207 0 : static uint32_t pmcolor_to_expand16(SkPMColor c) {
208 0 : unsigned r = SkGetPackedR32(c);
209 0 : unsigned g = SkGetPackedG32(c);
210 0 : unsigned b = SkGetPackedB32(c);
211 0 : return (g << 24) | (r << 13) | (b << 2);
212 : }
213 :
214 0 : static void Color32A_D565(uint16_t dst[], SkPMColor src, int count, int x, int y) {
215 0 : SkASSERT(count > 0);
216 0 : uint32_t src_expand = pmcolor_to_expand16(src);
217 0 : unsigned scale = SkAlpha255To256(0xFF - SkGetPackedA32(src)) >> 3;
218 0 : do {
219 0 : *dst = SkBlend32_RGB16(src_expand, *dst, scale);
220 0 : dst += 1;
221 : } while (--count != 0);
222 0 : }
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 :
243 0 : SkBlitRow::Proc16 SkBlitRow::Factory16(unsigned flags) {
244 0 : SkASSERT(flags < SK_ARRAY_COUNT(gDefault_565_Procs));
245 : // just so we don't crash
246 0 : flags &= kFlags16_Mask;
247 :
248 0 : SkBlitRow::Proc16 proc = PlatformFactory565(flags);
249 0 : if (nullptr == proc) {
250 0 : proc = gDefault_565_Procs[flags];
251 : }
252 0 : 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 :
266 0 : SkBlitRow::ColorProc16 SkBlitRow::ColorFactory16(unsigned flags) {
267 0 : SkASSERT((flags & ~kFlags16_Mask) == 0);
268 : // just so we don't crash
269 0 : 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 0 : flags >>= 2;
273 :
274 0 : SkASSERT(flags < SK_ARRAY_COUNT(gDefault_565_ColorProcs));
275 :
276 0 : SkBlitRow::ColorProc16 proc = PlatformColorFactory565(flags);
277 0 : if (nullptr == proc) {
278 0 : proc = gDefault_565_ColorProcs[flags];
279 : }
280 0 : return proc;
281 : }
|