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