|
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 "SkBlitMask.h" |
|
10 #include "SkColorPriv.h" |
|
11 #include "SkUtils.h" |
|
12 |
|
13 #define UNROLL |
|
14 |
|
15 SkBlitRow::ColorRectProc PlatformColorRectProcFactory(); |
|
16 |
|
17 static void S32_Opaque_BlitRow32(SkPMColor* SK_RESTRICT dst, |
|
18 const SkPMColor* SK_RESTRICT src, |
|
19 int count, U8CPU alpha) { |
|
20 SkASSERT(255 == alpha); |
|
21 memcpy(dst, src, count * sizeof(SkPMColor)); |
|
22 } |
|
23 |
|
24 static void S32_Blend_BlitRow32(SkPMColor* SK_RESTRICT dst, |
|
25 const SkPMColor* SK_RESTRICT src, |
|
26 int count, U8CPU alpha) { |
|
27 SkASSERT(alpha <= 255); |
|
28 if (count > 0) { |
|
29 unsigned src_scale = SkAlpha255To256(alpha); |
|
30 unsigned dst_scale = 256 - src_scale; |
|
31 |
|
32 #ifdef UNROLL |
|
33 if (count & 1) { |
|
34 *dst = SkAlphaMulQ(*(src++), src_scale) + SkAlphaMulQ(*dst, dst_scale); |
|
35 dst += 1; |
|
36 count -= 1; |
|
37 } |
|
38 |
|
39 const SkPMColor* SK_RESTRICT srcEnd = src + count; |
|
40 while (src != srcEnd) { |
|
41 *dst = SkAlphaMulQ(*(src++), src_scale) + SkAlphaMulQ(*dst, dst_scale); |
|
42 dst += 1; |
|
43 *dst = SkAlphaMulQ(*(src++), src_scale) + SkAlphaMulQ(*dst, dst_scale); |
|
44 dst += 1; |
|
45 } |
|
46 #else |
|
47 do { |
|
48 *dst = SkAlphaMulQ(*src, src_scale) + SkAlphaMulQ(*dst, dst_scale); |
|
49 src += 1; |
|
50 dst += 1; |
|
51 } while (--count > 0); |
|
52 #endif |
|
53 } |
|
54 } |
|
55 |
|
56 static void S32A_Opaque_BlitRow32(SkPMColor* SK_RESTRICT dst, |
|
57 const SkPMColor* SK_RESTRICT src, |
|
58 int count, U8CPU alpha) { |
|
59 SkASSERT(255 == alpha); |
|
60 if (count > 0) { |
|
61 #ifdef UNROLL |
|
62 if (count & 1) { |
|
63 *dst = SkPMSrcOver(*(src++), *dst); |
|
64 dst += 1; |
|
65 count -= 1; |
|
66 } |
|
67 |
|
68 const SkPMColor* SK_RESTRICT srcEnd = src + count; |
|
69 while (src != srcEnd) { |
|
70 *dst = SkPMSrcOver(*(src++), *dst); |
|
71 dst += 1; |
|
72 *dst = SkPMSrcOver(*(src++), *dst); |
|
73 dst += 1; |
|
74 } |
|
75 #else |
|
76 do { |
|
77 *dst = SkPMSrcOver(*src, *dst); |
|
78 src += 1; |
|
79 dst += 1; |
|
80 } while (--count > 0); |
|
81 #endif |
|
82 } |
|
83 } |
|
84 |
|
85 static void S32A_Blend_BlitRow32(SkPMColor* SK_RESTRICT dst, |
|
86 const SkPMColor* SK_RESTRICT src, |
|
87 int count, U8CPU alpha) { |
|
88 SkASSERT(alpha <= 255); |
|
89 if (count > 0) { |
|
90 #ifdef UNROLL |
|
91 if (count & 1) { |
|
92 *dst = SkBlendARGB32(*(src++), *dst, alpha); |
|
93 dst += 1; |
|
94 count -= 1; |
|
95 } |
|
96 |
|
97 const SkPMColor* SK_RESTRICT srcEnd = src + count; |
|
98 while (src != srcEnd) { |
|
99 *dst = SkBlendARGB32(*(src++), *dst, alpha); |
|
100 dst += 1; |
|
101 *dst = SkBlendARGB32(*(src++), *dst, alpha); |
|
102 dst += 1; |
|
103 } |
|
104 #else |
|
105 do { |
|
106 *dst = SkBlendARGB32(*src, *dst, alpha); |
|
107 src += 1; |
|
108 dst += 1; |
|
109 } while (--count > 0); |
|
110 #endif |
|
111 } |
|
112 } |
|
113 |
|
114 /////////////////////////////////////////////////////////////////////////////// |
|
115 |
|
116 static const SkBlitRow::Proc32 gDefault_Procs32[] = { |
|
117 S32_Opaque_BlitRow32, |
|
118 S32_Blend_BlitRow32, |
|
119 S32A_Opaque_BlitRow32, |
|
120 S32A_Blend_BlitRow32 |
|
121 }; |
|
122 |
|
123 SkBlitRow::Proc32 SkBlitRow::Factory32(unsigned flags) { |
|
124 SkASSERT(flags < SK_ARRAY_COUNT(gDefault_Procs32)); |
|
125 // just so we don't crash |
|
126 flags &= kFlags32_Mask; |
|
127 |
|
128 SkBlitRow::Proc32 proc = PlatformProcs32(flags); |
|
129 if (NULL == proc) { |
|
130 proc = gDefault_Procs32[flags]; |
|
131 } |
|
132 SkASSERT(proc); |
|
133 return proc; |
|
134 } |
|
135 |
|
136 SkBlitRow::Proc32 SkBlitRow::ColorProcFactory() { |
|
137 SkBlitRow::ColorProc proc = PlatformColorProc(); |
|
138 if (NULL == proc) { |
|
139 proc = Color32; |
|
140 } |
|
141 SkASSERT(proc); |
|
142 return proc; |
|
143 } |
|
144 |
|
145 void SkBlitRow::Color32(SkPMColor* SK_RESTRICT dst, |
|
146 const SkPMColor* SK_RESTRICT src, |
|
147 int count, SkPMColor color) { |
|
148 if (count > 0) { |
|
149 if (0 == color) { |
|
150 if (src != dst) { |
|
151 memcpy(dst, src, count * sizeof(SkPMColor)); |
|
152 } |
|
153 return; |
|
154 } |
|
155 unsigned colorA = SkGetPackedA32(color); |
|
156 if (255 == colorA) { |
|
157 sk_memset32(dst, color, count); |
|
158 } else { |
|
159 unsigned scale = 256 - SkAlpha255To256(colorA); |
|
160 do { |
|
161 *dst = color + SkAlphaMulQ(*src, scale); |
|
162 src += 1; |
|
163 dst += 1; |
|
164 } while (--count); |
|
165 } |
|
166 } |
|
167 } |
|
168 |
|
169 template <size_t N> void assignLoop(SkPMColor* dst, SkPMColor color) { |
|
170 for (size_t i = 0; i < N; ++i) { |
|
171 *dst++ = color; |
|
172 } |
|
173 } |
|
174 |
|
175 static inline void assignLoop(SkPMColor dst[], SkPMColor color, int count) { |
|
176 while (count >= 4) { |
|
177 *dst++ = color; |
|
178 *dst++ = color; |
|
179 *dst++ = color; |
|
180 *dst++ = color; |
|
181 count -= 4; |
|
182 } |
|
183 if (count >= 2) { |
|
184 *dst++ = color; |
|
185 *dst++ = color; |
|
186 count -= 2; |
|
187 } |
|
188 if (count > 0) { |
|
189 *dst++ = color; |
|
190 } |
|
191 } |
|
192 |
|
193 void SkBlitRow::ColorRect32(SkPMColor* dst, int width, int height, |
|
194 size_t rowBytes, SkPMColor color) { |
|
195 if (width <= 0 || height <= 0 || 0 == color) { |
|
196 return; |
|
197 } |
|
198 |
|
199 // Just made up this value, since I saw it once in a SSE2 file. |
|
200 // We should consider writing some tests to find the optimimal break-point |
|
201 // (or query the Platform proc?) |
|
202 static const int MIN_WIDTH_FOR_SCANLINE_PROC = 32; |
|
203 |
|
204 bool isOpaque = (0xFF == SkGetPackedA32(color)); |
|
205 |
|
206 if (!isOpaque || width >= MIN_WIDTH_FOR_SCANLINE_PROC) { |
|
207 SkBlitRow::ColorProc proc = SkBlitRow::ColorProcFactory(); |
|
208 while (--height >= 0) { |
|
209 (*proc)(dst, dst, width, color); |
|
210 dst = (SkPMColor*) ((char*)dst + rowBytes); |
|
211 } |
|
212 } else { |
|
213 switch (width) { |
|
214 case 1: |
|
215 while (--height >= 0) { |
|
216 assignLoop<1>(dst, color); |
|
217 dst = (SkPMColor*) ((char*)dst + rowBytes); |
|
218 } |
|
219 break; |
|
220 case 2: |
|
221 while (--height >= 0) { |
|
222 assignLoop<2>(dst, color); |
|
223 dst = (SkPMColor*) ((char*)dst + rowBytes); |
|
224 } |
|
225 break; |
|
226 case 3: |
|
227 while (--height >= 0) { |
|
228 assignLoop<3>(dst, color); |
|
229 dst = (SkPMColor*) ((char*)dst + rowBytes); |
|
230 } |
|
231 break; |
|
232 default: |
|
233 while (--height >= 0) { |
|
234 assignLoop(dst, color, width); |
|
235 dst = (SkPMColor*) ((char*)dst + rowBytes); |
|
236 } |
|
237 break; |
|
238 } |
|
239 } |
|
240 } |
|
241 |
|
242 SkBlitRow::ColorRectProc SkBlitRow::ColorRectProcFactory() { |
|
243 SkBlitRow::ColorRectProc proc = PlatformColorRectProcFactory(); |
|
244 if (NULL == proc) { |
|
245 proc = ColorRect32; |
|
246 } |
|
247 SkASSERT(proc); |
|
248 return proc; |
|
249 } |