1ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed/*
2ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed * Copyright 2017 Google Inc.
3ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed *
4ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed * Use of this source code is governed by a BSD-style license that can be
5ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed * found in the LICENSE file.
6ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed */
7ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
8ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed#include "SkSpriteBlitter.h"
9ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed#include "SkArenaAlloc.h"
10ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed#include "SkBlitRow.h"
11ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed#include "SkColorFilter.h"
12ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed#include "SkColorData.h"
1375ae421c24ee7ab5a86334e43404b24a6a6fb1f4Mike Reed#include "SkPaint.h"
14ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed#include "SkTemplates.h"
15ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed#include "SkUtils.h"
16ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed#include "SkXfermodePriv.h"
17ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
18ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed///////////////////////////////////////////////////////////////////////////////
19ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
20ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reedstatic void S32_src(uint16_t dst[], const SkPMColor src[], int count) {
21ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    for (int i = 0; i < count; ++i) {
22ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        dst[i] = SkPixel32ToPixel16(src[i]);
23ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    }
24ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed}
25ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
26ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reedstatic void S32_srcover(uint16_t dst[], const SkPMColor src[], int count) {
27ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    for (int i = 0; i < count; ++i) {
28ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        dst[i] = SkSrcOver32To16(src[i], dst[i]);
29ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    }
30ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed}
31ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
32ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reedclass Sprite_D16_S32 : public SkSpriteBlitter {
33ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reedpublic:
34ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    Sprite_D16_S32(const SkPixmap& src, SkBlendMode mode)  : INHERITED(src) {
35ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        SkASSERT(src.colorType() == kN32_SkColorType);
36ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        SkASSERT(mode == SkBlendMode::kSrc || mode == SkBlendMode::kSrcOver);
37ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
38ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        fUseSrcOver = (mode == SkBlendMode::kSrcOver) && !src.isOpaque();
39ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    }
40ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
41ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    void blitRect(int x, int y, int width, int height) override {
42ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        SkASSERT(width > 0 && height > 0);
43ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        uint16_t* SK_RESTRICT dst = fDst.writable_addr16(x, y);
44ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        const uint32_t* SK_RESTRICT src = fSource.addr32(x - fLeft, y - fTop);
45ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        size_t dstRB = fDst.rowBytes();
46ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        size_t srcRB = fSource.rowBytes();
47ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
48ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        do {
49ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed            if (fUseSrcOver) {
50ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed                S32_srcover(dst, src, width);
51ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed            } else {
52ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed                S32_src(dst, src, width);
53ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed            }
54ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
55ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed            dst = (uint16_t* SK_RESTRICT)((char*)dst + dstRB);
56ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed            src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB);
57ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        } while (--height != 0);
58ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    }
59ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
60ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reedprivate:
61ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    bool fUseSrcOver;
62ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
63ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    typedef SkSpriteBlitter INHERITED;
64ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed};
65ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
66ef8ce2858b7692c9ec9874c43656e603f304c760Mike ReedSkSpriteBlitter* SkSpriteBlitter::ChooseL565(const SkPixmap& source, const SkPaint& paint,
67ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed                                             SkArenaAlloc* allocator) {
68ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    SkASSERT(allocator != nullptr);
69ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
70ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    if (paint.getColorFilter() != nullptr) {
71ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        return nullptr;
72ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    }
73ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    if (paint.getMaskFilter() != nullptr) {
74ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        return nullptr;
75ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    }
76ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
77ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    U8CPU alpha = paint.getAlpha();
78ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    if (alpha != 0xFF) {
79ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        return nullptr;
80ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    }
81ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
82ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    if (source.colorType() == kN32_SkColorType) {
83ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        switch (paint.getBlendMode()) {
84ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed            case SkBlendMode::kSrc:
85ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed            case SkBlendMode::kSrcOver:
86ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed                return allocator->make<Sprite_D16_S32>(source, paint.getBlendMode());
87ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed            default:
88ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed                break;
89ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        }
90ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    }
91ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    return nullptr;
92ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed}
93ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
94ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed//////////////////////////////////////////////////////////////////////////////////////////////////
95ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
96ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reedstatic unsigned div255(unsigned a, unsigned b) {
97ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    return (a * b * 257 + 127) >> 16;
98ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed}
99ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
100ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reedstatic void S32_src_da8(uint8_t dst[], const SkPMColor src[], int count) {
101ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    for (int i = 0; i < count; ++i) {
102ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        dst[i] = SkGetPackedA32(src[i]);
103ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    }
104ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed}
105ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
106ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reedstatic void S32_srcover_da8(uint8_t dst[], const SkPMColor src[], int count) {
107ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    for (int i = 0; i < count; ++i) {
108ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        SkPMColor c = src[i];
109ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        if (c) {
110ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed            unsigned a = SkGetPackedA32(c);
111ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed            if (a == 0xFF) {
112ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed                dst[i] = 0xFF;
113ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed            } else {
114ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed                dst[i] = a + div255(255 - a, dst[i]);
115ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed            }
116ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        }
117ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    }
118ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed}
119ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
120ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reedclass Sprite_D8_S32 : public SkSpriteBlitter {
121ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reedpublic:
122ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    Sprite_D8_S32(const SkPixmap& src, SkBlendMode mode)  : INHERITED(src) {
123ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        SkASSERT(src.colorType() == kN32_SkColorType);
124ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        SkASSERT(mode == SkBlendMode::kSrc || mode == SkBlendMode::kSrcOver);
125ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
126ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        fUseSrcOver = (mode == SkBlendMode::kSrcOver) && !src.isOpaque();
127ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    }
128ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
129ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    void blitRect(int x, int y, int width, int height) override {
130ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        SkASSERT(width > 0 && height > 0);
131ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        uint8_t* SK_RESTRICT dst = fDst.writable_addr8(x, y);
132ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        const uint32_t* SK_RESTRICT src = fSource.addr32(x - fLeft, y - fTop);
133ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        size_t dstRB = fDst.rowBytes();
134ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        size_t srcRB = fSource.rowBytes();
135ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
136ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        do {
137ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed            if (fUseSrcOver) {
138ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed                S32_srcover_da8(dst, src, width);
139ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed            } else {
140ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed                S32_src_da8(dst, src, width);
141ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed            }
142ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
143ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed            dst = (uint8_t* SK_RESTRICT)((char*)dst + dstRB);
144ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed            src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB);
145ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        } while (--height != 0);
146ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    }
147ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
148ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reedprivate:
149ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    bool fUseSrcOver;
150ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
151ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    typedef SkSpriteBlitter INHERITED;
152ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed};
153ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
154ef8ce2858b7692c9ec9874c43656e603f304c760Mike ReedSkSpriteBlitter* SkSpriteBlitter::ChooseLA8(const SkPixmap& source, const SkPaint& paint,
155ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed                                            SkArenaAlloc* allocator) {
156ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    SkASSERT(allocator != nullptr);
157ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
158ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    if (paint.getColorFilter() != nullptr) {
159ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        return nullptr;
160ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    }
161ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    if (paint.getMaskFilter() != nullptr) {
162ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        return nullptr;
163ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    }
164ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
165ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    U8CPU alpha = paint.getAlpha();
166ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    if (alpha != 0xFF) {
167ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        return nullptr;
168ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    }
169ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed
170ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    if (source.colorType() == kN32_SkColorType) {
171ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        switch (paint.getBlendMode()) {
172ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed            case SkBlendMode::kSrc:
173ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed            case SkBlendMode::kSrcOver:
174ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed                return allocator->make<Sprite_D8_S32>(source, paint.getBlendMode());
175ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed            default:
176ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed                break;
177ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed        }
178ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    }
179ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed    return nullptr;
180ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed}
181