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