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
S32_Opaque_BlitRow32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha)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 sk_memcpy32(dst, src, count);
22 }
23
S32_Blend_BlitRow32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha)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
S32A_Opaque_BlitRow32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha)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
S32A_Blend_BlitRow32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha)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
Factory32(unsigned flags)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
ColorProcFactory()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
Color32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,SkPMColor color)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
assignLoop(SkPMColor * dst,SkPMColor color)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
assignLoop(SkPMColor dst[],SkPMColor color,int count)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
ColorRect32(SkPMColor * dst,int width,int height,size_t rowBytes,SkPMColor color)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
ColorRectProcFactory()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 }
250