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
15static 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;
29
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
45        do {
46            *dst = SkAlphaMulQ(*src, src_scale) + SkAlphaMulQ(*dst, dst_scale);
47            src += 1;
48            dst += 1;
49        } while (--count > 0);
50#endif
51    }
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) {
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#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);
93#endif
94    }
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) {
102#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
117        do {
118            *dst = SkBlendARGB32(*src, *dst, alpha);
119            src += 1;
120            dst += 1;
121        } while (--count > 0);
122#endif
123    }
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;
139
140    SkBlitRow::Proc32 proc = PlatformProcs32(flags);
141    if (NULL == proc) {
142        proc = gDefault_Procs32[flags];
143    }
144    SkASSERT(proc);
145    return proc;
146}
147
148SkBlitRow::Proc32 SkBlitRow::ColorProcFactory() {
149    SkBlitRow::ColorProc proc = PlatformColorProc();
150    if (NULL == proc) {
151        proc = Color32;
152    }
153    SkASSERT(proc);
154    return proc;
155}
156
157void SkBlitRow::Color32(SkPMColor* SK_RESTRICT dst,
158                        const SkPMColor* SK_RESTRICT src,
159                        int count, SkPMColor color) {
160    if (count > 0) {
161        if (0 == color) {
162            if (src != dst) {
163                memcpy(dst, src, count * sizeof(SkPMColor));
164            }
165            return;
166        }
167        unsigned colorA = SkGetPackedA32(color);
168        if (255 == colorA) {
169            sk_memset32(dst, color, count);
170        } else {
171            unsigned scale = 256 - SkAlpha255To256(colorA);
172            do {
173                *dst = color + SkAlphaMulQ(*src, scale);
174                src += 1;
175                dst += 1;
176            } while (--count);
177        }
178    }
179}
180
181