• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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