blob: a00ba88816832961e0cba4ee9e4045bd3ecff170 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
reed@android.comc4cae852009-09-23 15:06:10 +00008#include "SkBlitRow.h"
9#include "SkColorPriv.h"
10#include "SkUtils.h"
11
djsollen@google.com57f49692011-02-23 20:46:31 +000012#define UNROLL
13
reed@android.comc4cae852009-09-23 15:06:10 +000014static void S32_Opaque_BlitRow32(SkPMColor* SK_RESTRICT dst,
15 const SkPMColor* SK_RESTRICT src,
16 int count, U8CPU alpha) {
17 SkASSERT(255 == alpha);
18 memcpy(dst, src, count * sizeof(SkPMColor));
19}
20
21static void S32_Blend_BlitRow32(SkPMColor* SK_RESTRICT dst,
22 const SkPMColor* SK_RESTRICT src,
23 int count, U8CPU alpha) {
24 SkASSERT(alpha <= 255);
25 if (count > 0) {
26 unsigned src_scale = SkAlpha255To256(alpha);
27 unsigned dst_scale = 256 - src_scale;
djsollen@google.com57f49692011-02-23 20:46:31 +000028
29#ifdef UNROLL
30 if (count & 1) {
31 *dst = SkAlphaMulQ(*(src++), src_scale) + SkAlphaMulQ(*dst, dst_scale);
32 dst += 1;
33 count -= 1;
34 }
35
36 const SkPMColor* SK_RESTRICT srcEnd = src + count;
37 while (src != srcEnd) {
38 *dst = SkAlphaMulQ(*(src++), src_scale) + SkAlphaMulQ(*dst, dst_scale);
39 dst += 1;
40 *dst = SkAlphaMulQ(*(src++), src_scale) + SkAlphaMulQ(*dst, dst_scale);
41 dst += 1;
42 }
43#else
reed@android.comc4cae852009-09-23 15:06:10 +000044 do {
45 *dst = SkAlphaMulQ(*src, src_scale) + SkAlphaMulQ(*dst, dst_scale);
46 src += 1;
47 dst += 1;
48 } while (--count > 0);
djsollen@google.com57f49692011-02-23 20:46:31 +000049#endif
reed@android.comc4cae852009-09-23 15:06:10 +000050 }
51}
52
53//#define TEST_SRC_ALPHA
54
55static void S32A_Opaque_BlitRow32(SkPMColor* SK_RESTRICT dst,
56 const SkPMColor* SK_RESTRICT src,
57 int count, U8CPU alpha) {
58 SkASSERT(255 == alpha);
59 if (count > 0) {
djsollen@google.com57f49692011-02-23 20:46:31 +000060#ifdef UNROLL
61 if (count & 1) {
62 *dst = SkPMSrcOver(*(src++), *dst);
63 dst += 1;
64 count -= 1;
65 }
66
67 const SkPMColor* SK_RESTRICT srcEnd = src + count;
68 while (src != srcEnd) {
69 *dst = SkPMSrcOver(*(src++), *dst);
70 dst += 1;
71 *dst = SkPMSrcOver(*(src++), *dst);
72 dst += 1;
73 }
74#else
reed@android.comc4cae852009-09-23 15:06:10 +000075 do {
76#ifdef TEST_SRC_ALPHA
77 SkPMColor sc = *src;
78 if (sc) {
79 unsigned srcA = SkGetPackedA32(sc);
80 SkPMColor result = sc;
81 if (srcA != 255) {
82 result = SkPMSrcOver(sc, *dst);
83 }
84 *dst = result;
85 }
86#else
87 *dst = SkPMSrcOver(*src, *dst);
88#endif
89 src += 1;
90 dst += 1;
91 } while (--count > 0);
djsollen@google.com57f49692011-02-23 20:46:31 +000092#endif
reed@android.comc4cae852009-09-23 15:06:10 +000093 }
94}
95
96static void S32A_Blend_BlitRow32(SkPMColor* SK_RESTRICT dst,
97 const SkPMColor* SK_RESTRICT src,
98 int count, U8CPU alpha) {
99 SkASSERT(alpha <= 255);
100 if (count > 0) {
djsollen@google.com57f49692011-02-23 20:46:31 +0000101#ifdef UNROLL
102 if (count & 1) {
103 *dst = SkBlendARGB32(*(src++), *dst, alpha);
104 dst += 1;
105 count -= 1;
106 }
107
108 const SkPMColor* SK_RESTRICT srcEnd = src + count;
109 while (src != srcEnd) {
110 *dst = SkBlendARGB32(*(src++), *dst, alpha);
111 dst += 1;
112 *dst = SkBlendARGB32(*(src++), *dst, alpha);
113 dst += 1;
114 }
115#else
reed@android.comc4cae852009-09-23 15:06:10 +0000116 do {
117 *dst = SkBlendARGB32(*src, *dst, alpha);
118 src += 1;
119 dst += 1;
120 } while (--count > 0);
djsollen@google.com57f49692011-02-23 20:46:31 +0000121#endif
reed@android.comc4cae852009-09-23 15:06:10 +0000122 }
123}
124
125///////////////////////////////////////////////////////////////////////////////
126
127static const SkBlitRow::Proc32 gDefault_Procs32[] = {
128 S32_Opaque_BlitRow32,
129 S32_Blend_BlitRow32,
130 S32A_Opaque_BlitRow32,
131 S32A_Blend_BlitRow32
132};
133
134SkBlitRow::Proc32 SkBlitRow::Factory32(unsigned flags) {
135 SkASSERT(flags < SK_ARRAY_COUNT(gDefault_Procs32));
136 // just so we don't crash
137 flags &= kFlags32_Mask;
reed@google.com981d4792011-03-09 12:55:47 +0000138
senorblanco@chromium.org92727612009-11-04 20:51:06 +0000139 SkBlitRow::Proc32 proc = PlatformProcs32(flags);
reed@android.comc4cae852009-09-23 15:06:10 +0000140 if (NULL == proc) {
141 proc = gDefault_Procs32[flags];
142 }
143 SkASSERT(proc);
144 return proc;
145}
146
senorblanco@chromium.org29e50542010-12-16 19:07:45 +0000147SkBlitRow::Proc32 SkBlitRow::ColorProcFactory() {
senorblanco@chromium.orgc3856382010-12-13 15:27:20 +0000148 SkBlitRow::ColorProc proc = PlatformColorProc();
149 if (NULL == proc) {
senorblanco@chromium.org29e50542010-12-16 19:07:45 +0000150 proc = Color32;
senorblanco@chromium.orgc3856382010-12-13 15:27:20 +0000151 }
senorblanco@chromium.org29e50542010-12-16 19:07:45 +0000152 SkASSERT(proc);
153 return proc;
senorblanco@chromium.orgc3856382010-12-13 15:27:20 +0000154}
155
reed@google.com981d4792011-03-09 12:55:47 +0000156void SkBlitRow::Color32(SkPMColor dst[], const SkPMColor src[],
senorblanco@chromium.org29e50542010-12-16 19:07:45 +0000157 int count, SkPMColor color) {
reed@android.comc4cae852009-09-23 15:06:10 +0000158 if (count > 0) {
159 if (0 == color) {
160 if (src != dst) {
161 memcpy(dst, src, count * sizeof(SkPMColor));
162 }
163 }
164 unsigned colorA = SkGetPackedA32(color);
165 if (255 == colorA) {
166 sk_memset32(dst, color, count);
167 } else {
168 unsigned scale = 256 - SkAlpha255To256(colorA);
169 do {
170 *dst = color + SkAlphaMulQ(*src, scale);
171 src += 1;
172 dst += 1;
173 } while (--count);
174 }
175 }
176}
177
reed@google.com981d4792011-03-09 12:55:47 +0000178///////////////////////////////////////////////////////////////////////////////
reed@android.comc4cae852009-09-23 15:06:10 +0000179
reed@google.comee467ee2011-03-09 13:23:57 +0000180static void D32_Mask_Color(void* dst, size_t dstRB, SkBitmap::Config,
181 const uint8_t* mask, size_t maskRB, SkColor color,
182 int width, int height) {
183 SkPMColor pmc = SkPreMultiplyColor(color);
reed@google.com981d4792011-03-09 12:55:47 +0000184 size_t dstOffset = dstRB - (width << 2);
185 size_t maskOffset = maskRB - width;
186 SkPMColor *device = (SkPMColor *)dst;
187 do {
188 int w = width;
189 do {
190 unsigned aa = *mask++;
reed@google.comee467ee2011-03-09 13:23:57 +0000191 *device = SkBlendARGB32(pmc, *device, aa);
reed@google.com981d4792011-03-09 12:55:47 +0000192 device += 1;
193 } while (--w != 0);
194 device = (uint32_t*)((char*)device + dstOffset);
195 mask += maskOffset;
196 } while (--height != 0);
197}
198
reed@google.comee467ee2011-03-09 13:23:57 +0000199static void D32_Mask_Opaque(void* dst, size_t dstRB, SkBitmap::Config,
200 const uint8_t* mask, size_t maskRB, SkColor color,
201 int width, int height) {
202 SkPMColor pmc = SkPreMultiplyColor(color);
203 uint32_t* device = (uint32_t*)dst;
204
205 maskRB -= width;
206 dstRB -= (width << 2);
207 do {
208 int w = width;
209 do {
210 unsigned aa = *mask++;
211 *device = SkAlphaMulQ(pmc, SkAlpha255To256(aa)) + SkAlphaMulQ(*device, SkAlpha255To256(255 - aa));
212 device += 1;
213 } while (--w != 0);
214 device = (uint32_t*)((char*)device + dstRB);
215 mask += maskRB;
216 } while (--height != 0);
217}
218
219static void D32_Mask_Black(void* dst, size_t dstRB, SkBitmap::Config,
220 const uint8_t* mask, size_t maskRB, SkColor,
221 int width, int height) {
222 uint32_t* device = (uint32_t*)dst;
223
224 maskRB -= width;
225 dstRB -= (width << 2);
226 do {
227 int w = width;
228 do {
229 unsigned aa = *mask++;
230 *device = (aa << SK_A32_SHIFT) + SkAlphaMulQ(*device, SkAlpha255To256(255 - aa));
231 device += 1;
232 } while (--w != 0);
233 device = (uint32_t*)((char*)device + dstRB);
234 mask += maskRB;
235 } while (--height != 0);
236}
237
reed@google.com981d4792011-03-09 12:55:47 +0000238SkBlitMask::Proc SkBlitMask::Factory(SkBitmap::Config config, SkColor color) {
239 SkBlitMask::Proc proc = PlatformProcs(config, color);
240 if (NULL == proc) {
241 switch (config) {
242 case SkBitmap::kARGB_8888_Config:
reed@google.comee467ee2011-03-09 13:23:57 +0000243 if (SK_ColorBLACK == color) {
244 proc = D32_Mask_Black;
245 } else if (0xFF == SkColorGetA(color)) {
246 proc = D32_Mask_Opaque;
247 } else {
248 proc = D32_Mask_Color;
reed@google.com981d4792011-03-09 12:55:47 +0000249 }
250 break;
251 default:
252 break;
253 }
254 }
255 return proc;
256}
reed@android.comc4cae852009-09-23 15:06:10 +0000257