SkSpriteBlitter_ARGB32.cpp revision 5f46e96757e9b914485cc6c819ed97b637503fcc
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 "SkArenaAlloc.h"
10#include "SkBlitRow.h"
11#include "SkColorFilter.h"
12#include "SkColorPriv.h"
13#include "SkTemplates.h"
14#include "SkUtils.h"
15#include "SkXfermodePriv.h"
16
17///////////////////////////////////////////////////////////////////////////////
18
19class Sprite_D32_S32 : public SkSpriteBlitter {
20public:
21    Sprite_D32_S32(const SkPixmap& src, U8CPU alpha)  : INHERITED(src) {
22        SkASSERT(src.colorType() == kN32_SkColorType);
23
24        unsigned flags32 = 0;
25        if (255 != alpha) {
26            flags32 |= SkBlitRow::kGlobalAlpha_Flag32;
27        }
28        if (!src.isOpaque()) {
29            flags32 |= SkBlitRow::kSrcPixelAlpha_Flag32;
30        }
31
32        fProc32 = SkBlitRow::Factory32(flags32);
33        fAlpha = alpha;
34    }
35
36    void blitRect(int x, int y, int width, int height) override {
37        SkASSERT(width > 0 && height > 0);
38        uint32_t* SK_RESTRICT dst = fDst.writable_addr32(x, y);
39        const uint32_t* SK_RESTRICT src = fSource.addr32(x - fLeft, y - fTop);
40        size_t dstRB = fDst.rowBytes();
41        size_t srcRB = fSource.rowBytes();
42        SkBlitRow::Proc32 proc = fProc32;
43        U8CPU             alpha = fAlpha;
44
45        do {
46            proc(dst, src, width, alpha);
47            dst = (uint32_t* SK_RESTRICT)((char*)dst + dstRB);
48            src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB);
49        } while (--height != 0);
50    }
51
52private:
53    SkBlitRow::Proc32   fProc32;
54    U8CPU               fAlpha;
55
56    typedef SkSpriteBlitter INHERITED;
57};
58
59///////////////////////////////////////////////////////////////////////////////
60
61class Sprite_D32_XferFilter : public SkSpriteBlitter {
62public:
63    Sprite_D32_XferFilter(const SkPixmap& source, const SkPaint& paint) : SkSpriteBlitter(source) {
64        fColorFilter = paint.getColorFilter();
65        SkSafeRef(fColorFilter);
66
67        fXfermode = SkXfermode::Peek(paint.getBlendMode());
68
69        fBufferSize = 0;
70        fBuffer = nullptr;
71
72        unsigned flags32 = 0;
73        if (255 != paint.getAlpha()) {
74            flags32 |= SkBlitRow::kGlobalAlpha_Flag32;
75        }
76        if (!source.isOpaque()) {
77            flags32 |= SkBlitRow::kSrcPixelAlpha_Flag32;
78        }
79
80        fProc32 = SkBlitRow::Factory32(flags32);
81        fAlpha = paint.getAlpha();
82    }
83
84    ~Sprite_D32_XferFilter() override {
85        delete[] fBuffer;
86        SkSafeUnref(fColorFilter);
87    }
88
89    void setup(const SkPixmap& dst, int left, int top, const SkPaint& paint) override {
90        this->INHERITED::setup(dst, left, top, paint);
91
92        int width = dst.width();
93        if (width > fBufferSize) {
94            fBufferSize = width;
95            delete[] fBuffer;
96            fBuffer = new SkPMColor[width];
97        }
98    }
99
100protected:
101    SkColorFilter*      fColorFilter;
102    SkXfermode*         fXfermode;
103    int                 fBufferSize;
104    SkPMColor*          fBuffer;
105    SkBlitRow::Proc32   fProc32;
106    U8CPU               fAlpha;
107
108private:
109    typedef SkSpriteBlitter INHERITED;
110};
111
112///////////////////////////////////////////////////////////////////////////////
113
114class Sprite_D32_S32A_XferFilter : public Sprite_D32_XferFilter {
115public:
116    Sprite_D32_S32A_XferFilter(const SkPixmap& source, const SkPaint& paint)
117        : Sprite_D32_XferFilter(source, paint) {}
118
119    void blitRect(int x, int y, int width, int height) override {
120        SkASSERT(width > 0 && height > 0);
121        uint32_t* SK_RESTRICT dst = fDst.writable_addr32(x, y);
122        const uint32_t* SK_RESTRICT src = fSource.addr32(x - fLeft, y - fTop);
123        size_t dstRB = fDst.rowBytes();
124        size_t srcRB = fSource.rowBytes();
125        SkColorFilter* colorFilter = fColorFilter;
126        SkXfermode* xfermode = fXfermode;
127
128        do {
129            const SkPMColor* tmp = src;
130
131            if (colorFilter) {
132                colorFilter->filterSpan(src, width, fBuffer);
133                tmp = fBuffer;
134            }
135
136            if (xfermode) {
137                xfermode->xfer32(dst, tmp, width, nullptr);
138            } else {
139                fProc32(dst, tmp, width, fAlpha);
140            }
141
142            dst = (uint32_t* SK_RESTRICT)((char*)dst + dstRB);
143            src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB);
144        } while (--height != 0);
145    }
146
147private:
148    typedef Sprite_D32_XferFilter INHERITED;
149};
150
151///////////////////////////////////////////////////////////////////////////////
152
153SkSpriteBlitter* SkSpriteBlitter::ChooseL32(const SkPixmap& source, const SkPaint& paint,
154                                            SkArenaAlloc* allocator) {
155    SkASSERT(allocator != nullptr);
156
157    if (paint.getMaskFilter() != nullptr) {
158        return nullptr;
159    }
160
161    U8CPU       alpha = paint.getAlpha();
162    bool isSrcOver = paint.isSrcOver();
163    SkColorFilter* filter = paint.getColorFilter();
164    SkSpriteBlitter* blitter = nullptr;
165
166    if (source.colorType() == kN32_SkColorType) {
167        if (!isSrcOver || filter) {
168            if (255 == alpha) {
169                // this can handle xfermode or filter, but not alpha
170                blitter = allocator->make<Sprite_D32_S32A_XferFilter>(source, paint);
171            }
172        } else {
173            // this can handle alpha, but not xfermode or filter
174            blitter = allocator->make<Sprite_D32_S32>(source, alpha);
175        }
176    }
177    return blitter;
178}
179