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 ///////////////////////////////////////////////////////////////////////////////
207
208 static const SkBlitRow::Proc gDefault_565_Procs[] = {
209 // no dither
210 S32_D565_Opaque,
211 S32_D565_Blend,
212
213 S32A_D565_Opaque,
214 S32A_D565_Blend,
215
216 // dither
217 S32_D565_Opaque_Dither,
218 S32_D565_Blend_Dither,
219
220 S32A_D565_Opaque_Dither,
221 S32A_D565_Blend_Dither
222 };
223
Factory(unsigned flags,SkColorType ct)224 SkBlitRow::Proc SkBlitRow::Factory(unsigned flags, SkColorType ct) {
225 SkASSERT(flags < SK_ARRAY_COUNT(gDefault_565_Procs));
226 // just so we don't crash
227 flags &= kFlags16_Mask;
228
229 SkBlitRow::Proc proc = NULL;
230
231 switch (ct) {
232 case kRGB_565_SkColorType:
233 proc = PlatformProcs565(flags);
234 if (NULL == proc) {
235 proc = gDefault_565_Procs[flags];
236 }
237 break;
238 default:
239 break;
240 }
241 return proc;
242 }
243