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 :
12 : ///////////////////////////////////////////////////////////////////////////////
13 :
14 0 : static void S32_D565_Opaque(uint16_t* SK_RESTRICT dst,
15 : const SkPMColor* SK_RESTRICT src, int count,
16 : U8CPU alpha, int /*x*/, int /*y*/) {
17 0 : SkASSERT(255 == alpha);
18 :
19 0 : if (count > 0) {
20 0 : do {
21 0 : SkPMColor c = *src++;
22 0 : SkPMColorAssert(c);
23 0 : *dst++ = SkPixel32ToPixel16_ToU16(c);
24 : } while (--count != 0);
25 : }
26 0 : }
27 :
28 0 : static void S32_D565_Blend(uint16_t* SK_RESTRICT dst,
29 : const SkPMColor* SK_RESTRICT src, int count,
30 : U8CPU alpha, int /*x*/, int /*y*/) {
31 0 : SkASSERT(255 > alpha);
32 :
33 0 : if (count > 0) {
34 0 : int scale = SkAlpha255To256(alpha);
35 0 : do {
36 0 : SkPMColor c = *src++;
37 0 : SkPMColorAssert(c);
38 0 : uint16_t d = *dst;
39 : *dst++ = SkPackRGB16(
40 0 : SkAlphaBlend(SkPacked32ToR16(c), SkGetPackedR16(d), scale),
41 0 : SkAlphaBlend(SkPacked32ToG16(c), SkGetPackedG16(d), scale),
42 0 : SkAlphaBlend(SkPacked32ToB16(c), SkGetPackedB16(d), scale));
43 : } while (--count != 0);
44 : }
45 0 : }
46 :
47 0 : static void S32A_D565_Opaque(uint16_t* SK_RESTRICT dst,
48 : const SkPMColor* SK_RESTRICT src, int count,
49 : U8CPU alpha, int /*x*/, int /*y*/) {
50 0 : SkASSERT(255 == alpha);
51 :
52 0 : if (count > 0) {
53 0 : do {
54 0 : SkPMColor c = *src++;
55 0 : SkPMColorAssert(c);
56 : // if (__builtin_expect(c!=0, 1))
57 0 : if (c) {
58 0 : *dst = SkSrcOver32To16(c, *dst);
59 : }
60 0 : dst += 1;
61 : } while (--count != 0);
62 : }
63 0 : }
64 :
65 0 : static void S32A_D565_Blend(uint16_t* SK_RESTRICT dst,
66 : const SkPMColor* SK_RESTRICT src, int count,
67 : U8CPU alpha, int /*x*/, int /*y*/) {
68 0 : SkASSERT(255 > alpha);
69 :
70 0 : if (count > 0) {
71 0 : do {
72 0 : SkPMColor sc = *src++;
73 0 : SkPMColorAssert(sc);
74 0 : if (sc) {
75 0 : uint16_t dc = *dst;
76 0 : unsigned dst_scale = 255 - SkMulDiv255Round(SkGetPackedA32(sc), alpha);
77 0 : unsigned dr = SkMulS16(SkPacked32ToR16(sc), alpha) + SkMulS16(SkGetPackedR16(dc), dst_scale);
78 0 : unsigned dg = SkMulS16(SkPacked32ToG16(sc), alpha) + SkMulS16(SkGetPackedG16(dc), dst_scale);
79 0 : unsigned db = SkMulS16(SkPacked32ToB16(sc), alpha) + SkMulS16(SkGetPackedB16(dc), dst_scale);
80 0 : *dst = SkPackRGB16(SkDiv255Round(dr), SkDiv255Round(dg), SkDiv255Round(db));
81 : }
82 0 : dst += 1;
83 : } while (--count != 0);
84 : }
85 0 : }
86 :
87 : /////////////////////////////////////////////////////////////////////////////
88 :
89 0 : static void S32_D565_Opaque_Dither(uint16_t* SK_RESTRICT dst,
90 : const SkPMColor* SK_RESTRICT src,
91 : int count, U8CPU alpha, int x, int y) {
92 0 : SkASSERT(255 == alpha);
93 :
94 0 : if (count > 0) {
95 0 : DITHER_565_SCAN(y);
96 0 : do {
97 0 : SkPMColor c = *src++;
98 0 : SkPMColorAssert(c);
99 :
100 0 : unsigned dither = DITHER_VALUE(x);
101 0 : *dst++ = SkDitherRGB32To565(c, dither);
102 0 : DITHER_INC_X(x);
103 : } while (--count != 0);
104 : }
105 0 : }
106 :
107 0 : static void S32_D565_Blend_Dither(uint16_t* SK_RESTRICT dst,
108 : const SkPMColor* SK_RESTRICT src,
109 : int count, U8CPU alpha, int x, int y) {
110 0 : SkASSERT(255 > alpha);
111 :
112 0 : if (count > 0) {
113 0 : int scale = SkAlpha255To256(alpha);
114 0 : DITHER_565_SCAN(y);
115 0 : do {
116 0 : SkPMColor c = *src++;
117 0 : SkPMColorAssert(c);
118 :
119 0 : int dither = DITHER_VALUE(x);
120 0 : int sr = SkGetPackedR32(c);
121 0 : int sg = SkGetPackedG32(c);
122 0 : int sb = SkGetPackedB32(c);
123 0 : sr = SkDITHER_R32To565(sr, dither);
124 0 : sg = SkDITHER_G32To565(sg, dither);
125 0 : sb = SkDITHER_B32To565(sb, dither);
126 :
127 0 : uint16_t d = *dst;
128 0 : *dst++ = SkPackRGB16(SkAlphaBlend(sr, SkGetPackedR16(d), scale),
129 0 : SkAlphaBlend(sg, SkGetPackedG16(d), scale),
130 0 : SkAlphaBlend(sb, SkGetPackedB16(d), scale));
131 0 : DITHER_INC_X(x);
132 : } while (--count != 0);
133 : }
134 0 : }
135 :
136 0 : static void S32A_D565_Opaque_Dither(uint16_t* SK_RESTRICT dst,
137 : const SkPMColor* SK_RESTRICT src,
138 : int count, U8CPU alpha, int x, int y) {
139 0 : SkASSERT(255 == alpha);
140 :
141 0 : if (count > 0) {
142 0 : DITHER_565_SCAN(y);
143 0 : do {
144 0 : SkPMColor c = *src++;
145 0 : SkPMColorAssert(c);
146 0 : if (c) {
147 0 : unsigned a = SkGetPackedA32(c);
148 :
149 0 : int d = SkAlphaMul(DITHER_VALUE(x), SkAlpha255To256(a));
150 :
151 0 : unsigned sr = SkGetPackedR32(c);
152 0 : unsigned sg = SkGetPackedG32(c);
153 0 : unsigned sb = SkGetPackedB32(c);
154 0 : sr = SkDITHER_R32_FOR_565(sr, d);
155 0 : sg = SkDITHER_G32_FOR_565(sg, d);
156 0 : sb = SkDITHER_B32_FOR_565(sb, d);
157 :
158 0 : uint32_t src_expanded = (sg << 24) | (sr << 13) | (sb << 2);
159 0 : uint32_t dst_expanded = SkExpand_rgb_16(*dst);
160 0 : dst_expanded = dst_expanded * (SkAlpha255To256(255 - a) >> 3);
161 : // now src and dst expanded are in g:11 r:10 x:1 b:10
162 0 : *dst = SkCompact_rgb_16((src_expanded + dst_expanded) >> 5);
163 : }
164 0 : dst += 1;
165 0 : DITHER_INC_X(x);
166 : } while (--count != 0);
167 : }
168 0 : }
169 :
170 0 : static void S32A_D565_Blend_Dither(uint16_t* SK_RESTRICT dst,
171 : const SkPMColor* SK_RESTRICT src,
172 : int count, U8CPU alpha, int x, int y) {
173 0 : SkASSERT(255 > alpha);
174 :
175 0 : if (count > 0) {
176 0 : int src_scale = SkAlpha255To256(alpha);
177 0 : DITHER_565_SCAN(y);
178 0 : do {
179 0 : SkPMColor c = *src++;
180 0 : SkPMColorAssert(c);
181 0 : if (c)
182 : {
183 0 : unsigned d = *dst;
184 0 : int sa = SkGetPackedA32(c);
185 0 : int dst_scale = SkAlpha255To256(255 - SkAlphaMul(sa, src_scale));
186 0 : int dither = DITHER_VALUE(x);
187 :
188 0 : int sr = SkGetPackedR32(c);
189 0 : int sg = SkGetPackedG32(c);
190 0 : int sb = SkGetPackedB32(c);
191 0 : sr = SkDITHER_R32To565(sr, dither);
192 0 : sg = SkDITHER_G32To565(sg, dither);
193 0 : sb = SkDITHER_B32To565(sb, dither);
194 :
195 0 : int dr = (sr * src_scale + SkGetPackedR16(d) * dst_scale) >> 8;
196 0 : int dg = (sg * src_scale + SkGetPackedG16(d) * dst_scale) >> 8;
197 0 : int db = (sb * src_scale + SkGetPackedB16(d) * dst_scale) >> 8;
198 :
199 0 : *dst = SkPackRGB16(dr, dg, db);
200 : }
201 0 : dst += 1;
202 0 : DITHER_INC_X(x);
203 : } while (--count != 0);
204 : }
205 0 : }
206 :
207 : ///////////////////////////////////////////////////////////////////////////////
208 : ///////////////////////////////////////////////////////////////////////////////
209 :
210 : static const SkBlitRow::Proc gDefault_565_Procs[] = {
211 : // no dither
212 : S32_D565_Opaque,
213 : S32_D565_Blend,
214 :
215 : S32A_D565_Opaque,
216 : S32A_D565_Blend,
217 :
218 : // dither
219 : S32_D565_Opaque_Dither,
220 : S32_D565_Blend_Dither,
221 :
222 : S32A_D565_Opaque_Dither,
223 : S32A_D565_Blend_Dither
224 : };
225 :
226 : extern SkBlitRow::Proc SkBlitRow_Factory_4444(unsigned flags);
227 :
228 0 : SkBlitRow::Proc SkBlitRow::Factory(unsigned flags, SkBitmap::Config config) {
229 0 : SkASSERT(flags < SK_ARRAY_COUNT(gDefault_565_Procs));
230 : // just so we don't crash
231 0 : flags &= kFlags16_Mask;
232 :
233 0 : SkBlitRow::Proc proc = NULL;
234 :
235 0 : switch (config) {
236 : case SkBitmap::kRGB_565_Config:
237 0 : proc = PlatformProcs565(flags);
238 0 : if (NULL == proc) {
239 0 : proc = gDefault_565_Procs[flags];
240 : }
241 0 : break;
242 : case SkBitmap::kARGB_4444_Config:
243 0 : proc = PlatformProcs4444(flags);
244 0 : if (NULL == proc) {
245 0 : proc = SkBlitRow_Factory_4444(flags);
246 : }
247 0 : break;
248 : default:
249 0 : break;
250 : }
251 0 : return proc;
252 : }
253 :
|