SkSpriteBlitter_ARGB32.cpp revision a624d12b2d10cff79ba4b31744d81cc2e0a8db5f
1
2/*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#include "SkSpriteBlitter.h"
11#include "SkBlitRow.h"
12#include "SkColorFilter.h"
13#include "SkColorPriv.h"
14#include "SkTemplates.h"
15#include "SkUtils.h"
16#include "SkXfermode.h"
17
18///////////////////////////////////////////////////////////////////////////////
19
20class Sprite_D32_S32 : public SkSpriteBlitter {
21public:
22    Sprite_D32_S32(const SkBitmap& src, U8CPU alpha)  : INHERITED(src) {
23        SkASSERT(src.colorType() == kN32_SkColorType);
24
25        unsigned flags32 = 0;
26        if (255 != alpha) {
27            flags32 |= SkBlitRow::kGlobalAlpha_Flag32;
28        }
29        if (!src.isOpaque()) {
30            flags32 |= SkBlitRow::kSrcPixelAlpha_Flag32;
31        }
32
33        fProc32 = SkBlitRow::Factory32(flags32);
34        fAlpha = alpha;
35    }
36
37    void blitRect(int x, int y, int width, int height) override {
38        SkASSERT(width > 0 && height > 0);
39        uint32_t* SK_RESTRICT dst = fDevice->getAddr32(x, y);
40        const uint32_t* SK_RESTRICT src = fSource->addr32(x - fLeft, y - fTop);
41        size_t dstRB = fDevice->rowBytes();
42        size_t srcRB = fSource->rowBytes();
43        SkBlitRow::Proc32 proc = fProc32;
44        U8CPU             alpha = fAlpha;
45
46        do {
47            proc(dst, src, width, alpha);
48            dst = (uint32_t* SK_RESTRICT)((char*)dst + dstRB);
49            src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB);
50        } while (--height != 0);
51    }
52
53private:
54    SkBlitRow::Proc32   fProc32;
55    U8CPU               fAlpha;
56
57    typedef SkSpriteBlitter INHERITED;
58};
59
60///////////////////////////////////////////////////////////////////////////////
61
62class Sprite_D32_XferFilter : public SkSpriteBlitter {
63public:
64    Sprite_D32_XferFilter(const SkBitmap& source, const SkPaint& paint)
65        : SkSpriteBlitter(source) {
66        fColorFilter = paint.getColorFilter();
67        SkSafeRef(fColorFilter);
68
69        fXfermode = paint.getXfermode();
70        SkSafeRef(fXfermode);
71
72        fBufferSize = 0;
73        fBuffer = NULL;
74
75        unsigned flags32 = 0;
76        if (255 != paint.getAlpha()) {
77            flags32 |= SkBlitRow::kGlobalAlpha_Flag32;
78        }
79        if (!source.isOpaque()) {
80            flags32 |= SkBlitRow::kSrcPixelAlpha_Flag32;
81        }
82
83        fProc32 = SkBlitRow::Factory32(flags32);
84        fAlpha = paint.getAlpha();
85    }
86
87    virtual ~Sprite_D32_XferFilter() {
88        delete[] fBuffer;
89        SkSafeUnref(fXfermode);
90        SkSafeUnref(fColorFilter);
91    }
92
93    bool setup(const SkBitmap& device, int left, int top, const SkPaint& paint) override {
94        if (!this->INHERITED::setup(device, left, top, paint)) {
95            return false;
96        }
97
98        int width = device.width();
99        if (width > fBufferSize) {
100            fBufferSize = width;
101            delete[] fBuffer;
102            fBuffer = new SkPMColor[width];
103        }
104        return true;
105    }
106
107protected:
108    SkColorFilter*      fColorFilter;
109    SkXfermode*         fXfermode;
110    int                 fBufferSize;
111    SkPMColor*          fBuffer;
112    SkBlitRow::Proc32   fProc32;
113    U8CPU               fAlpha;
114
115private:
116    typedef SkSpriteBlitter INHERITED;
117};
118
119///////////////////////////////////////////////////////////////////////////////
120
121class Sprite_D32_S32A_XferFilter : public Sprite_D32_XferFilter {
122public:
123    Sprite_D32_S32A_XferFilter(const SkBitmap& source, const SkPaint& paint)
124        : Sprite_D32_XferFilter(source, paint) {}
125
126    void blitRect(int x, int y, int width, int height) override {
127        SkASSERT(width > 0 && height > 0);
128        uint32_t* SK_RESTRICT dst = fDevice->getAddr32(x, y);
129        const uint32_t* SK_RESTRICT src = fSource->addr32(x - fLeft, y - fTop);
130        size_t dstRB = fDevice->rowBytes();
131        size_t srcRB = fSource->rowBytes();
132        SkColorFilter* colorFilter = fColorFilter;
133        SkXfermode* xfermode = fXfermode;
134
135        do {
136            const SkPMColor* tmp = src;
137
138            if (colorFilter) {
139                colorFilter->filterSpan(src, width, fBuffer);
140                tmp = fBuffer;
141            }
142
143            if (xfermode) {
144                xfermode->xfer32(dst, tmp, width, NULL);
145            } else {
146                fProc32(dst, tmp, width, fAlpha);
147            }
148
149            dst = (uint32_t* SK_RESTRICT)((char*)dst + dstRB);
150            src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB);
151        } while (--height != 0);
152    }
153
154private:
155    typedef Sprite_D32_XferFilter INHERITED;
156};
157
158static void fillbuffer(SkPMColor* SK_RESTRICT dst,
159                       const SkPMColor16* SK_RESTRICT src, int count) {
160    SkASSERT(count > 0);
161
162    do {
163        *dst++ = SkPixel4444ToPixel32(*src++);
164    } while (--count != 0);
165}
166
167class Sprite_D32_S4444_XferFilter : public Sprite_D32_XferFilter {
168public:
169    Sprite_D32_S4444_XferFilter(const SkBitmap& source, const SkPaint& paint)
170        : Sprite_D32_XferFilter(source, paint) {}
171
172    void blitRect(int x, int y, int width, int height) override {
173        SkASSERT(width > 0 && height > 0);
174        SkPMColor* SK_RESTRICT dst = fDevice->getAddr32(x, y);
175        const SkPMColor16* SK_RESTRICT src = fSource->addr16(x - fLeft, y - fTop);
176        size_t dstRB = fDevice->rowBytes();
177        size_t srcRB = fSource->rowBytes();
178        SkPMColor* SK_RESTRICT buffer = fBuffer;
179        SkColorFilter* colorFilter = fColorFilter;
180        SkXfermode* xfermode = fXfermode;
181
182        do {
183            fillbuffer(buffer, src, width);
184
185            if (colorFilter) {
186                colorFilter->filterSpan(buffer, width, buffer);
187            }
188            if (xfermode) {
189                xfermode->xfer32(dst, buffer, width, NULL);
190            } else {
191                fProc32(dst, buffer, width, fAlpha);
192            }
193
194            dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB);
195            src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB);
196        } while (--height != 0);
197    }
198
199private:
200    typedef Sprite_D32_XferFilter INHERITED;
201};
202
203///////////////////////////////////////////////////////////////////////////////
204
205static void src_row(SkPMColor* SK_RESTRICT dst,
206                    const SkPMColor16* SK_RESTRICT src, int count) {
207    do {
208        *dst = SkPixel4444ToPixel32(*src);
209        src += 1;
210        dst += 1;
211    } while (--count != 0);
212}
213
214class Sprite_D32_S4444_Opaque : public SkSpriteBlitter {
215public:
216    Sprite_D32_S4444_Opaque(const SkBitmap& source) : SkSpriteBlitter(source) {}
217
218    void blitRect(int x, int y, int width, int height) override {
219        SkASSERT(width > 0 && height > 0);
220        SkPMColor* SK_RESTRICT dst = fDevice->getAddr32(x, y);
221        const SkPMColor16* SK_RESTRICT src = fSource->addr16(x - fLeft, y - fTop);
222        size_t dstRB = fDevice->rowBytes();
223        size_t srcRB = fSource->rowBytes();
224
225        do {
226            src_row(dst, src, width);
227            dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB);
228            src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB);
229        } while (--height != 0);
230    }
231};
232
233static void srcover_row(SkPMColor* SK_RESTRICT dst,
234                        const SkPMColor16* SK_RESTRICT src, int count) {
235    do {
236        *dst = SkPMSrcOver(SkPixel4444ToPixel32(*src), *dst);
237        src += 1;
238        dst += 1;
239    } while (--count != 0);
240}
241
242class Sprite_D32_S4444 : public SkSpriteBlitter {
243public:
244    Sprite_D32_S4444(const SkBitmap& source) : SkSpriteBlitter(source) {}
245
246    void blitRect(int x, int y, int width, int height) override {
247        SkASSERT(width > 0 && height > 0);
248        SkPMColor* SK_RESTRICT dst = fDevice->getAddr32(x, y);
249        const SkPMColor16* SK_RESTRICT src = fSource->addr16(x - fLeft, y - fTop);
250        size_t dstRB = fDevice->rowBytes();
251        size_t srcRB = fSource->rowBytes();
252
253        do {
254            srcover_row(dst, src, width);
255            dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB);
256            src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB);
257        } while (--height != 0);
258    }
259};
260
261///////////////////////////////////////////////////////////////////////////////
262
263SkSpriteBlitter* SkSpriteBlitter::ChooseD32(const SkBitmap& source, const SkPaint& paint,
264        SkTBlitterAllocator* allocator) {
265    SkASSERT(allocator != NULL);
266
267    if (paint.getMaskFilter() != NULL) {
268        return NULL;
269    }
270
271    U8CPU       alpha = paint.getAlpha();
272    SkXfermode* xfermode = paint.getXfermode();
273    SkColorFilter* filter = paint.getColorFilter();
274    SkSpriteBlitter* blitter = NULL;
275
276    switch (source.colorType()) {
277        case kARGB_4444_SkColorType:
278            if (alpha != 0xFF) {
279                return NULL;    // we only have opaque sprites
280            }
281            if (xfermode || filter) {
282                blitter = allocator->createT<Sprite_D32_S4444_XferFilter>(source, paint);
283            } else if (source.isOpaque()) {
284                blitter = allocator->createT<Sprite_D32_S4444_Opaque>(source);
285            } else {
286                blitter = allocator->createT<Sprite_D32_S4444>(source);
287            }
288            break;
289        case kN32_SkColorType:
290            if (xfermode || filter) {
291                if (255 == alpha) {
292                    // this can handle xfermode or filter, but not alpha
293                    blitter = allocator->createT<Sprite_D32_S32A_XferFilter>(source, paint);
294                }
295            } else {
296                // this can handle alpha, but not xfermode or filter
297                blitter = allocator->createT<Sprite_D32_S32>(source, alpha);
298            }
299            break;
300        default:
301            break;
302    }
303    return blitter;
304}
305