blob: 1a40f4d9b9a93b1ecc65f70f2d8bf316f646b1e7 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
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 */
reed@google.com58af9a62011-10-12 13:43:52 +00007
reed@android.comc4cae852009-09-23 15:06:10 +00008#include "SkBlitRow.h"
reed@google.com58af9a62011-10-12 13:43:52 +00009#include "SkBlitMask.h"
reed@android.comc4cae852009-09-23 15:06:10 +000010#include "SkColorPriv.h"
11#include "SkUtils.h"
12
djsollen@google.com57f49692011-02-23 20:46:31 +000013#define UNROLL
14
reed@android.comc4cae852009-09-23 15:06:10 +000015static void S32_Opaque_BlitRow32(SkPMColor* SK_RESTRICT dst,
16 const SkPMColor* SK_RESTRICT src,
17 int count, U8CPU alpha) {
18 SkASSERT(255 == alpha);
19 memcpy(dst, src, count * sizeof(SkPMColor));
20}
21
22static void S32_Blend_BlitRow32(SkPMColor* SK_RESTRICT dst,
23 const SkPMColor* SK_RESTRICT src,
24 int count, U8CPU alpha) {
25 SkASSERT(alpha <= 255);
26 if (count > 0) {
27 unsigned src_scale = SkAlpha255To256(alpha);
28 unsigned dst_scale = 256 - src_scale;
djsollen@google.com57f49692011-02-23 20:46:31 +000029
30#ifdef UNROLL
31 if (count & 1) {
32 *dst = SkAlphaMulQ(*(src++), src_scale) + SkAlphaMulQ(*dst, dst_scale);
33 dst += 1;
34 count -= 1;
35 }
36
37 const SkPMColor* SK_RESTRICT srcEnd = src + count;
38 while (src != srcEnd) {
39 *dst = SkAlphaMulQ(*(src++), src_scale) + SkAlphaMulQ(*dst, dst_scale);
40 dst += 1;
41 *dst = SkAlphaMulQ(*(src++), src_scale) + SkAlphaMulQ(*dst, dst_scale);
42 dst += 1;
43 }
44#else
reed@android.comc4cae852009-09-23 15:06:10 +000045 do {
46 *dst = SkAlphaMulQ(*src, src_scale) + SkAlphaMulQ(*dst, dst_scale);
47 src += 1;
48 dst += 1;
49 } while (--count > 0);
djsollen@google.com57f49692011-02-23 20:46:31 +000050#endif
reed@android.comc4cae852009-09-23 15:06:10 +000051 }
52}
53
54//#define TEST_SRC_ALPHA
55
56static 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) {
djsollen@google.com57f49692011-02-23 20:46:31 +000061#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
reed@android.comc4cae852009-09-23 15:06:10 +000076 do {
77#ifdef TEST_SRC_ALPHA
78 SkPMColor sc = *src;
79 if (sc) {
80 unsigned srcA = SkGetPackedA32(sc);
81 SkPMColor result = sc;
82 if (srcA != 255) {
83 result = SkPMSrcOver(sc, *dst);
84 }
85 *dst = result;
86 }
87#else
88 *dst = SkPMSrcOver(*src, *dst);
89#endif
90 src += 1;
91 dst += 1;
92 } while (--count > 0);
djsollen@google.com57f49692011-02-23 20:46:31 +000093#endif
reed@android.comc4cae852009-09-23 15:06:10 +000094 }
95}
96
97static void S32A_Blend_BlitRow32(SkPMColor* SK_RESTRICT dst,
98 const SkPMColor* SK_RESTRICT src,
99 int count, U8CPU alpha) {
100 SkASSERT(alpha <= 255);
101 if (count > 0) {
djsollen@google.com57f49692011-02-23 20:46:31 +0000102#ifdef UNROLL
103 if (count & 1) {
104 *dst = SkBlendARGB32(*(src++), *dst, alpha);
105 dst += 1;
106 count -= 1;
107 }
108
109 const SkPMColor* SK_RESTRICT srcEnd = src + count;
110 while (src != srcEnd) {
111 *dst = SkBlendARGB32(*(src++), *dst, alpha);
112 dst += 1;
113 *dst = SkBlendARGB32(*(src++), *dst, alpha);
114 dst += 1;
115 }
116#else
reed@android.comc4cae852009-09-23 15:06:10 +0000117 do {
118 *dst = SkBlendARGB32(*src, *dst, alpha);
119 src += 1;
120 dst += 1;
121 } while (--count > 0);
djsollen@google.com57f49692011-02-23 20:46:31 +0000122#endif
reed@android.comc4cae852009-09-23 15:06:10 +0000123 }
124}
125
126///////////////////////////////////////////////////////////////////////////////
127
128static const SkBlitRow::Proc32 gDefault_Procs32[] = {
129 S32_Opaque_BlitRow32,
130 S32_Blend_BlitRow32,
131 S32A_Opaque_BlitRow32,
132 S32A_Blend_BlitRow32
133};
134
135SkBlitRow::Proc32 SkBlitRow::Factory32(unsigned flags) {
136 SkASSERT(flags < SK_ARRAY_COUNT(gDefault_Procs32));
137 // just so we don't crash
138 flags &= kFlags32_Mask;
reed@google.com981d4792011-03-09 12:55:47 +0000139
senorblanco@chromium.org92727612009-11-04 20:51:06 +0000140 SkBlitRow::Proc32 proc = PlatformProcs32(flags);
reed@android.comc4cae852009-09-23 15:06:10 +0000141 if (NULL == proc) {
142 proc = gDefault_Procs32[flags];
143 }
144 SkASSERT(proc);
145 return proc;
146}
147
senorblanco@chromium.org29e50542010-12-16 19:07:45 +0000148SkBlitRow::Proc32 SkBlitRow::ColorProcFactory() {
senorblanco@chromium.orgc3856382010-12-13 15:27:20 +0000149 SkBlitRow::ColorProc proc = PlatformColorProc();
150 if (NULL == proc) {
senorblanco@chromium.org29e50542010-12-16 19:07:45 +0000151 proc = Color32;
senorblanco@chromium.orgc3856382010-12-13 15:27:20 +0000152 }
senorblanco@chromium.org29e50542010-12-16 19:07:45 +0000153 SkASSERT(proc);
154 return proc;
senorblanco@chromium.orgc3856382010-12-13 15:27:20 +0000155}
156
reed@google.comf2068ad2011-09-13 13:56:57 +0000157void SkBlitRow::Color32(SkPMColor* SK_RESTRICT dst,
158 const SkPMColor* SK_RESTRICT src,
senorblanco@chromium.org29e50542010-12-16 19:07:45 +0000159 int count, SkPMColor color) {
reed@android.comc4cae852009-09-23 15:06:10 +0000160 if (count > 0) {
161 if (0 == color) {
162 if (src != dst) {
163 memcpy(dst, src, count * sizeof(SkPMColor));
164 }
165 }
166 unsigned colorA = SkGetPackedA32(color);
167 if (255 == colorA) {
168 sk_memset32(dst, color, count);
169 } else {
170 unsigned scale = 256 - SkAlpha255To256(colorA);
171 do {
172 *dst = color + SkAlphaMulQ(*src, scale);
173 src += 1;
174 dst += 1;
175 } while (--count);
176 }
177 }
178}
179
reed@google.com981d4792011-03-09 12:55:47 +0000180///////////////////////////////////////////////////////////////////////////////
reed@android.comc4cae852009-09-23 15:06:10 +0000181
reed@google.comf2068ad2011-09-13 13:56:57 +0000182static void D32_Mask_Color(void* SK_RESTRICT dst, size_t dstRB, SkBitmap::Config,
183 const uint8_t* SK_RESTRICT mask, size_t maskRB, SkColor color,
reed@google.comee467ee2011-03-09 13:23:57 +0000184 int width, int height) {
185 SkPMColor pmc = SkPreMultiplyColor(color);
reed@google.com981d4792011-03-09 12:55:47 +0000186 size_t dstOffset = dstRB - (width << 2);
187 size_t maskOffset = maskRB - width;
188 SkPMColor *device = (SkPMColor *)dst;
189 do {
190 int w = width;
191 do {
192 unsigned aa = *mask++;
reed@google.comee467ee2011-03-09 13:23:57 +0000193 *device = SkBlendARGB32(pmc, *device, aa);
reed@google.com981d4792011-03-09 12:55:47 +0000194 device += 1;
195 } while (--w != 0);
196 device = (uint32_t*)((char*)device + dstOffset);
197 mask += maskOffset;
198 } while (--height != 0);
199}
200
reed@google.comf2068ad2011-09-13 13:56:57 +0000201static void D32_Mask_Opaque(void* SK_RESTRICT dst, size_t dstRB, SkBitmap::Config,
202 const uint8_t* SK_RESTRICT mask, size_t maskRB, SkColor color,
reed@google.comee467ee2011-03-09 13:23:57 +0000203 int width, int height) {
204 SkPMColor pmc = SkPreMultiplyColor(color);
205 uint32_t* device = (uint32_t*)dst;
206
207 maskRB -= width;
208 dstRB -= (width << 2);
209 do {
210 int w = width;
211 do {
212 unsigned aa = *mask++;
213 *device = SkAlphaMulQ(pmc, SkAlpha255To256(aa)) + SkAlphaMulQ(*device, SkAlpha255To256(255 - aa));
214 device += 1;
215 } while (--w != 0);
216 device = (uint32_t*)((char*)device + dstRB);
217 mask += maskRB;
218 } while (--height != 0);
219}
220
reed@google.comf2068ad2011-09-13 13:56:57 +0000221static void D32_Mask_Black(void* SK_RESTRICT dst, size_t dstRB, SkBitmap::Config,
222 const uint8_t* SK_RESTRICT mask, size_t maskRB, SkColor,
reed@google.comee467ee2011-03-09 13:23:57 +0000223 int width, int height) {
224 uint32_t* device = (uint32_t*)dst;
225
226 maskRB -= width;
227 dstRB -= (width << 2);
228 do {
229 int w = width;
230 do {
231 unsigned aa = *mask++;
232 *device = (aa << SK_A32_SHIFT) + SkAlphaMulQ(*device, SkAlpha255To256(255 - aa));
233 device += 1;
234 } while (--w != 0);
235 device = (uint32_t*)((char*)device + dstRB);
236 mask += maskRB;
237 } while (--height != 0);
238}
239
reed@google.com981d4792011-03-09 12:55:47 +0000240SkBlitMask::Proc SkBlitMask::Factory(SkBitmap::Config config, SkColor color) {
241 SkBlitMask::Proc proc = PlatformProcs(config, color);
242 if (NULL == proc) {
243 switch (config) {
244 case SkBitmap::kARGB_8888_Config:
reed@google.comee467ee2011-03-09 13:23:57 +0000245 if (SK_ColorBLACK == color) {
246 proc = D32_Mask_Black;
247 } else if (0xFF == SkColorGetA(color)) {
248 proc = D32_Mask_Opaque;
249 } else {
250 proc = D32_Mask_Color;
reed@google.com981d4792011-03-09 12:55:47 +0000251 }
252 break;
253 default:
254 break;
255 }
256 }
257 return proc;
258}
reed@android.comc4cae852009-09-23 15:06:10 +0000259