1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2006 The Android Open Source Project
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "src/core/SkBlitter.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "include/core/SkColor.h"
11cb93a386Sopenharmony_ci#include "include/core/SkColorFilter.h"
12cb93a386Sopenharmony_ci#include "include/core/SkString.h"
13cb93a386Sopenharmony_ci#include "include/private/SkColorData.h"
14cb93a386Sopenharmony_ci#include "include/private/SkTo.h"
15cb93a386Sopenharmony_ci#include "src/core/SkAntiRun.h"
16cb93a386Sopenharmony_ci#include "src/core/SkArenaAlloc.h"
17cb93a386Sopenharmony_ci#include "src/core/SkMask.h"
18cb93a386Sopenharmony_ci#include "src/core/SkMaskFilterBase.h"
19cb93a386Sopenharmony_ci#include "src/core/SkMatrixProvider.h"
20cb93a386Sopenharmony_ci#include "src/core/SkOpts.h"
21cb93a386Sopenharmony_ci#include "src/core/SkPaintPriv.h"
22cb93a386Sopenharmony_ci#include "src/core/SkReadBuffer.h"
23cb93a386Sopenharmony_ci#include "src/core/SkRegionPriv.h"
24cb93a386Sopenharmony_ci#include "src/core/SkTLazy.h"
25cb93a386Sopenharmony_ci#include "src/core/SkVMBlitter.h"
26cb93a386Sopenharmony_ci#include "src/core/SkWriteBuffer.h"
27cb93a386Sopenharmony_ci#include "src/core/SkXfermodeInterpretation.h"
28cb93a386Sopenharmony_ci#include "src/shaders/SkShaderBase.h"
29cb93a386Sopenharmony_ci
30cb93a386Sopenharmony_ci// Hacks for testing.
31cb93a386Sopenharmony_cibool gUseSkVMBlitter{false};
32cb93a386Sopenharmony_cibool gSkForceRasterPipelineBlitter{false};
33cb93a386Sopenharmony_ci
34cb93a386Sopenharmony_ciSkBlitter::~SkBlitter() {}
35cb93a386Sopenharmony_ci
36cb93a386Sopenharmony_cibool SkBlitter::isNullBlitter() const { return false; }
37cb93a386Sopenharmony_ci
38cb93a386Sopenharmony_ciconst SkPixmap* SkBlitter::justAnOpaqueColor(uint32_t* value) {
39cb93a386Sopenharmony_ci    return nullptr;
40cb93a386Sopenharmony_ci}
41cb93a386Sopenharmony_ci
42cb93a386Sopenharmony_ci/*
43cb93a386Sopenharmony_civoid SkBlitter::blitH(int x, int y, int width) {
44cb93a386Sopenharmony_ci    SkDEBUGFAIL("unimplemented");
45cb93a386Sopenharmony_ci}
46cb93a386Sopenharmony_ci
47cb93a386Sopenharmony_ci
48cb93a386Sopenharmony_civoid SkBlitter::blitAntiH(int x, int y, const SkAlpha antialias[],
49cb93a386Sopenharmony_ci                          const int16_t runs[]) {
50cb93a386Sopenharmony_ci    SkDEBUGFAIL("unimplemented");
51cb93a386Sopenharmony_ci}
52cb93a386Sopenharmony_ci */
53cb93a386Sopenharmony_ci
54cb93a386Sopenharmony_ciinline static SkAlpha ScalarToAlpha(SkScalar a) {
55cb93a386Sopenharmony_ci    SkAlpha alpha = (SkAlpha)(a * 255);
56cb93a386Sopenharmony_ci    return alpha > 247 ? 0xFF : alpha < 8 ? 0 : alpha;
57cb93a386Sopenharmony_ci}
58cb93a386Sopenharmony_ci
59cb93a386Sopenharmony_civoid SkBlitter::blitFatAntiRect(const SkRect& rect) {
60cb93a386Sopenharmony_ci    SkIRect bounds = rect.roundOut();
61cb93a386Sopenharmony_ci    SkASSERT(bounds.width() >= 3);
62cb93a386Sopenharmony_ci
63cb93a386Sopenharmony_ci    // skbug.com/7813
64cb93a386Sopenharmony_ci    // To ensure consistency of the threaded backend (a rect that's considered fat in the init-once
65cb93a386Sopenharmony_ci    // phase must also be considered fat in the draw phase), we have to deal with rects with small
66cb93a386Sopenharmony_ci    // heights because the horizontal tiling in the threaded backend may change the height.
67cb93a386Sopenharmony_ci    //
68cb93a386Sopenharmony_ci    // This also implies that we cannot do vertical tiling unless we can blit any rect (not just the
69cb93a386Sopenharmony_ci    // fat one.)
70cb93a386Sopenharmony_ci    if (bounds.height() == 0) {
71cb93a386Sopenharmony_ci        return;
72cb93a386Sopenharmony_ci    }
73cb93a386Sopenharmony_ci
74cb93a386Sopenharmony_ci    int         runSize = bounds.width() + 1; // +1 so we can set runs[bounds.width()] = 0
75cb93a386Sopenharmony_ci    void*       storage = this->allocBlitMemory(runSize * (sizeof(int16_t) + sizeof(SkAlpha)));
76cb93a386Sopenharmony_ci    int16_t*    runs    = reinterpret_cast<int16_t*>(storage);
77cb93a386Sopenharmony_ci    SkAlpha*    alphas  = reinterpret_cast<SkAlpha*>(runs + runSize);
78cb93a386Sopenharmony_ci
79cb93a386Sopenharmony_ci    runs[0] = 1;
80cb93a386Sopenharmony_ci    runs[1] = bounds.width() - 2;
81cb93a386Sopenharmony_ci    runs[bounds.width() - 1] = 1;
82cb93a386Sopenharmony_ci    runs[bounds.width()]  = 0;
83cb93a386Sopenharmony_ci
84cb93a386Sopenharmony_ci    SkScalar partialL = bounds.fLeft + 1 - rect.fLeft;
85cb93a386Sopenharmony_ci    SkScalar partialR = rect.fRight - (bounds.fRight - 1);
86cb93a386Sopenharmony_ci    SkScalar partialT = bounds.fTop + 1 - rect.fTop;
87cb93a386Sopenharmony_ci    SkScalar partialB = rect.fBottom - (bounds.fBottom - 1);
88cb93a386Sopenharmony_ci
89cb93a386Sopenharmony_ci    if (bounds.height() == 1) {
90cb93a386Sopenharmony_ci        partialT = rect.fBottom - rect.fTop;
91cb93a386Sopenharmony_ci    }
92cb93a386Sopenharmony_ci
93cb93a386Sopenharmony_ci    alphas[0] = ScalarToAlpha(partialL * partialT);
94cb93a386Sopenharmony_ci    alphas[1] = ScalarToAlpha(partialT);
95cb93a386Sopenharmony_ci    alphas[bounds.width() - 1] = ScalarToAlpha(partialR * partialT);
96cb93a386Sopenharmony_ci    this->blitAntiH(bounds.fLeft, bounds.fTop, alphas, runs);
97cb93a386Sopenharmony_ci
98cb93a386Sopenharmony_ci    if (bounds.height() > 2) {
99cb93a386Sopenharmony_ci        this->blitAntiRect(bounds.fLeft, bounds.fTop + 1, bounds.width() - 2, bounds.height() - 2,
100cb93a386Sopenharmony_ci                           ScalarToAlpha(partialL), ScalarToAlpha(partialR));
101cb93a386Sopenharmony_ci    }
102cb93a386Sopenharmony_ci
103cb93a386Sopenharmony_ci    if (bounds.height() > 1) {
104cb93a386Sopenharmony_ci        alphas[0] = ScalarToAlpha(partialL * partialB);
105cb93a386Sopenharmony_ci        alphas[1] = ScalarToAlpha(partialB);
106cb93a386Sopenharmony_ci        alphas[bounds.width() - 1] = ScalarToAlpha(partialR * partialB);
107cb93a386Sopenharmony_ci        this->blitAntiH(bounds.fLeft, bounds.fBottom - 1, alphas, runs);
108cb93a386Sopenharmony_ci    }
109cb93a386Sopenharmony_ci}
110cb93a386Sopenharmony_ci
111cb93a386Sopenharmony_civoid SkBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
112cb93a386Sopenharmony_ci    if (alpha == 255) {
113cb93a386Sopenharmony_ci        this->blitRect(x, y, 1, height);
114cb93a386Sopenharmony_ci    } else {
115cb93a386Sopenharmony_ci        int16_t runs[2];
116cb93a386Sopenharmony_ci        runs[0] = 1;
117cb93a386Sopenharmony_ci        runs[1] = 0;
118cb93a386Sopenharmony_ci
119cb93a386Sopenharmony_ci        while (--height >= 0) {
120cb93a386Sopenharmony_ci            this->blitAntiH(x, y++, &alpha, runs);
121cb93a386Sopenharmony_ci        }
122cb93a386Sopenharmony_ci    }
123cb93a386Sopenharmony_ci}
124cb93a386Sopenharmony_ci
125cb93a386Sopenharmony_civoid SkBlitter::blitRect(int x, int y, int width, int height) {
126cb93a386Sopenharmony_ci    SkASSERT(width > 0);
127cb93a386Sopenharmony_ci    while (--height >= 0) {
128cb93a386Sopenharmony_ci        this->blitH(x, y++, width);
129cb93a386Sopenharmony_ci    }
130cb93a386Sopenharmony_ci}
131cb93a386Sopenharmony_ci
132cb93a386Sopenharmony_ci/// Default implementation doesn't check for easy optimizations
133cb93a386Sopenharmony_ci/// such as alpha == 255; also uses blitV(), which some subclasses
134cb93a386Sopenharmony_ci/// may not support.
135cb93a386Sopenharmony_civoid SkBlitter::blitAntiRect(int x, int y, int width, int height,
136cb93a386Sopenharmony_ci                             SkAlpha leftAlpha, SkAlpha rightAlpha) {
137cb93a386Sopenharmony_ci    if (leftAlpha > 0) { // we may send in x = -1 with leftAlpha = 0
138cb93a386Sopenharmony_ci        this->blitV(x, y, height, leftAlpha);
139cb93a386Sopenharmony_ci    }
140cb93a386Sopenharmony_ci    x++;
141cb93a386Sopenharmony_ci    if (width > 0) {
142cb93a386Sopenharmony_ci        this->blitRect(x, y, width, height);
143cb93a386Sopenharmony_ci        x += width;
144cb93a386Sopenharmony_ci    }
145cb93a386Sopenharmony_ci    if (rightAlpha > 0) {
146cb93a386Sopenharmony_ci        this->blitV(x, y, height, rightAlpha);
147cb93a386Sopenharmony_ci    }
148cb93a386Sopenharmony_ci}
149cb93a386Sopenharmony_ci
150cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////
151cb93a386Sopenharmony_ci
152cb93a386Sopenharmony_cistatic inline void bits_to_runs(SkBlitter* blitter, int x, int y,
153cb93a386Sopenharmony_ci                                const uint8_t bits[],
154cb93a386Sopenharmony_ci                                uint8_t left_mask, ptrdiff_t rowBytes,
155cb93a386Sopenharmony_ci                                uint8_t right_mask) {
156cb93a386Sopenharmony_ci    int inFill = 0;
157cb93a386Sopenharmony_ci    int pos = 0;
158cb93a386Sopenharmony_ci
159cb93a386Sopenharmony_ci    while (--rowBytes >= 0) {
160cb93a386Sopenharmony_ci        uint8_t b = *bits++ & left_mask;
161cb93a386Sopenharmony_ci        if (rowBytes == 0) {
162cb93a386Sopenharmony_ci            b &= right_mask;
163cb93a386Sopenharmony_ci        }
164cb93a386Sopenharmony_ci
165cb93a386Sopenharmony_ci        for (uint8_t test = 0x80U; test != 0; test >>= 1) {
166cb93a386Sopenharmony_ci            if (b & test) {
167cb93a386Sopenharmony_ci                if (!inFill) {
168cb93a386Sopenharmony_ci                    pos = x;
169cb93a386Sopenharmony_ci                    inFill = true;
170cb93a386Sopenharmony_ci                }
171cb93a386Sopenharmony_ci            } else {
172cb93a386Sopenharmony_ci                if (inFill) {
173cb93a386Sopenharmony_ci                    blitter->blitH(pos, y, x - pos);
174cb93a386Sopenharmony_ci                    inFill = false;
175cb93a386Sopenharmony_ci                }
176cb93a386Sopenharmony_ci            }
177cb93a386Sopenharmony_ci            x += 1;
178cb93a386Sopenharmony_ci        }
179cb93a386Sopenharmony_ci        left_mask = 0xFFU;
180cb93a386Sopenharmony_ci    }
181cb93a386Sopenharmony_ci
182cb93a386Sopenharmony_ci    // final cleanup
183cb93a386Sopenharmony_ci    if (inFill) {
184cb93a386Sopenharmony_ci        blitter->blitH(pos, y, x - pos);
185cb93a386Sopenharmony_ci    }
186cb93a386Sopenharmony_ci}
187cb93a386Sopenharmony_ci
188cb93a386Sopenharmony_ci// maskBitCount is the number of 1's to place in the mask. It must be in the range between 1 and 8.
189cb93a386Sopenharmony_cistatic uint8_t generate_right_mask(int maskBitCount) {
190cb93a386Sopenharmony_ci    return static_cast<uint8_t>((0xFF00U >> maskBitCount) & 0xFF);
191cb93a386Sopenharmony_ci}
192cb93a386Sopenharmony_ci
193cb93a386Sopenharmony_civoid SkBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
194cb93a386Sopenharmony_ci    SkASSERT(mask.fBounds.contains(clip));
195cb93a386Sopenharmony_ci
196cb93a386Sopenharmony_ci    if (mask.fFormat == SkMask::kLCD16_Format) {
197cb93a386Sopenharmony_ci        return; // needs to be handled by subclass
198cb93a386Sopenharmony_ci    }
199cb93a386Sopenharmony_ci
200cb93a386Sopenharmony_ci    if (mask.fFormat == SkMask::kBW_Format) {
201cb93a386Sopenharmony_ci        int cx = clip.fLeft;
202cb93a386Sopenharmony_ci        int cy = clip.fTop;
203cb93a386Sopenharmony_ci        int maskLeft = mask.fBounds.fLeft;
204cb93a386Sopenharmony_ci        int maskRowBytes = mask.fRowBytes;
205cb93a386Sopenharmony_ci        int height = clip.height();
206cb93a386Sopenharmony_ci
207cb93a386Sopenharmony_ci        const uint8_t* bits = mask.getAddr1(cx, cy);
208cb93a386Sopenharmony_ci
209cb93a386Sopenharmony_ci        SkDEBUGCODE(const uint8_t* endOfImage =
210cb93a386Sopenharmony_ci            mask.fImage + (mask.fBounds.height() - 1) * maskRowBytes
211cb93a386Sopenharmony_ci            + ((mask.fBounds.width() + 7) >> 3));
212cb93a386Sopenharmony_ci
213cb93a386Sopenharmony_ci        if (cx == maskLeft && clip.fRight == mask.fBounds.fRight) {
214cb93a386Sopenharmony_ci            while (--height >= 0) {
215cb93a386Sopenharmony_ci                int affectedRightBit = mask.fBounds.width() - 1;
216cb93a386Sopenharmony_ci                ptrdiff_t rowBytes = (affectedRightBit >> 3) + 1;
217cb93a386Sopenharmony_ci                SkASSERT(bits + rowBytes <= endOfImage);
218cb93a386Sopenharmony_ci                U8CPU rightMask = generate_right_mask((affectedRightBit & 7) + 1);
219cb93a386Sopenharmony_ci                bits_to_runs(this, cx, cy, bits, 0xFF, rowBytes, rightMask);
220cb93a386Sopenharmony_ci                bits += maskRowBytes;
221cb93a386Sopenharmony_ci                cy += 1;
222cb93a386Sopenharmony_ci            }
223cb93a386Sopenharmony_ci        } else {
224cb93a386Sopenharmony_ci            // Bits is calculated as the offset into the mask at the point {cx, cy} therefore, all
225cb93a386Sopenharmony_ci            // addressing into the bit mask is relative to that point. Since this is an address
226cb93a386Sopenharmony_ci            // calculated from a arbitrary bit in that byte, calculate the left most bit.
227cb93a386Sopenharmony_ci            int bitsLeft = cx - ((cx - maskLeft) & 7);
228cb93a386Sopenharmony_ci
229cb93a386Sopenharmony_ci            // Everything is relative to the bitsLeft.
230cb93a386Sopenharmony_ci            int leftEdge = cx - bitsLeft;
231cb93a386Sopenharmony_ci            SkASSERT(leftEdge >= 0);
232cb93a386Sopenharmony_ci            int rightEdge = clip.fRight - bitsLeft;
233cb93a386Sopenharmony_ci            SkASSERT(rightEdge > leftEdge);
234cb93a386Sopenharmony_ci
235cb93a386Sopenharmony_ci            // Calculate left byte and mask
236cb93a386Sopenharmony_ci            const uint8_t* leftByte = bits;
237cb93a386Sopenharmony_ci            U8CPU leftMask = 0xFFU >> (leftEdge & 7);
238cb93a386Sopenharmony_ci
239cb93a386Sopenharmony_ci            // Calculate right byte and mask
240cb93a386Sopenharmony_ci            int affectedRightBit = rightEdge - 1;
241cb93a386Sopenharmony_ci            const uint8_t* rightByte = bits + (affectedRightBit >> 3);
242cb93a386Sopenharmony_ci            U8CPU rightMask = generate_right_mask((affectedRightBit & 7) + 1);
243cb93a386Sopenharmony_ci
244cb93a386Sopenharmony_ci            // leftByte and rightByte are byte locations therefore, to get a count of bytes the
245cb93a386Sopenharmony_ci            // code must add one.
246cb93a386Sopenharmony_ci            ptrdiff_t rowBytes = rightByte - leftByte + 1;
247cb93a386Sopenharmony_ci
248cb93a386Sopenharmony_ci            while (--height >= 0) {
249cb93a386Sopenharmony_ci                SkASSERT(bits + rowBytes <= endOfImage);
250cb93a386Sopenharmony_ci                bits_to_runs(this, bitsLeft, cy, bits, leftMask, rowBytes, rightMask);
251cb93a386Sopenharmony_ci                bits += maskRowBytes;
252cb93a386Sopenharmony_ci                cy += 1;
253cb93a386Sopenharmony_ci            }
254cb93a386Sopenharmony_ci        }
255cb93a386Sopenharmony_ci    } else {
256cb93a386Sopenharmony_ci        int                         width = clip.width();
257cb93a386Sopenharmony_ci        SkAutoSTMalloc<64, int16_t> runStorage(width + 1);
258cb93a386Sopenharmony_ci        int16_t*                    runs = runStorage.get();
259cb93a386Sopenharmony_ci        const uint8_t*              aa = mask.getAddr8(clip.fLeft, clip.fTop);
260cb93a386Sopenharmony_ci
261cb93a386Sopenharmony_ci        sk_memset16((uint16_t*)runs, 1, width);
262cb93a386Sopenharmony_ci        runs[width] = 0;
263cb93a386Sopenharmony_ci
264cb93a386Sopenharmony_ci        int height = clip.height();
265cb93a386Sopenharmony_ci        int y = clip.fTop;
266cb93a386Sopenharmony_ci        while (--height >= 0) {
267cb93a386Sopenharmony_ci            this->blitAntiH(clip.fLeft, y, aa, runs);
268cb93a386Sopenharmony_ci            aa += mask.fRowBytes;
269cb93a386Sopenharmony_ci            y += 1;
270cb93a386Sopenharmony_ci        }
271cb93a386Sopenharmony_ci    }
272cb93a386Sopenharmony_ci}
273cb93a386Sopenharmony_ci
274cb93a386Sopenharmony_ci/////////////////////// these are not virtual, just helpers
275cb93a386Sopenharmony_ci
276cb93a386Sopenharmony_civoid SkBlitter::blitMaskRegion(const SkMask& mask, const SkRegion& clip) {
277cb93a386Sopenharmony_ci    if (clip.quickReject(mask.fBounds)) {
278cb93a386Sopenharmony_ci        return;
279cb93a386Sopenharmony_ci    }
280cb93a386Sopenharmony_ci
281cb93a386Sopenharmony_ci    SkRegion::Cliperator clipper(clip, mask.fBounds);
282cb93a386Sopenharmony_ci
283cb93a386Sopenharmony_ci    while (!clipper.done()) {
284cb93a386Sopenharmony_ci        const SkIRect& cr = clipper.rect();
285cb93a386Sopenharmony_ci        this->blitMask(mask, cr);
286cb93a386Sopenharmony_ci        clipper.next();
287cb93a386Sopenharmony_ci    }
288cb93a386Sopenharmony_ci}
289cb93a386Sopenharmony_ci
290cb93a386Sopenharmony_civoid SkBlitter::blitRectRegion(const SkIRect& rect, const SkRegion& clip) {
291cb93a386Sopenharmony_ci    SkRegion::Cliperator clipper(clip, rect);
292cb93a386Sopenharmony_ci
293cb93a386Sopenharmony_ci    while (!clipper.done()) {
294cb93a386Sopenharmony_ci        const SkIRect& cr = clipper.rect();
295cb93a386Sopenharmony_ci        this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height());
296cb93a386Sopenharmony_ci        clipper.next();
297cb93a386Sopenharmony_ci    }
298cb93a386Sopenharmony_ci}
299cb93a386Sopenharmony_ci
300cb93a386Sopenharmony_civoid SkBlitter::blitRegion(const SkRegion& clip) {
301cb93a386Sopenharmony_ci    SkRegionPriv::VisitSpans(clip, [this](const SkIRect& r) {
302cb93a386Sopenharmony_ci        this->blitRect(r.left(), r.top(), r.width(), r.height());
303cb93a386Sopenharmony_ci    });
304cb93a386Sopenharmony_ci}
305cb93a386Sopenharmony_ci
306cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
307cb93a386Sopenharmony_ci
308cb93a386Sopenharmony_civoid SkNullBlitter::blitH(int x, int y, int width) {}
309cb93a386Sopenharmony_ci
310cb93a386Sopenharmony_civoid SkNullBlitter::blitAntiH(int x, int y, const SkAlpha antialias[],
311cb93a386Sopenharmony_ci                              const int16_t runs[]) {}
312cb93a386Sopenharmony_ci
313cb93a386Sopenharmony_civoid SkNullBlitter::blitV(int x, int y, int height, SkAlpha alpha) {}
314cb93a386Sopenharmony_ci
315cb93a386Sopenharmony_civoid SkNullBlitter::blitRect(int x, int y, int width, int height) {}
316cb93a386Sopenharmony_ci
317cb93a386Sopenharmony_civoid SkNullBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {}
318cb93a386Sopenharmony_ci
319cb93a386Sopenharmony_ciconst SkPixmap* SkNullBlitter::justAnOpaqueColor(uint32_t* value) {
320cb93a386Sopenharmony_ci    return nullptr;
321cb93a386Sopenharmony_ci}
322cb93a386Sopenharmony_ci
323cb93a386Sopenharmony_cibool SkNullBlitter::isNullBlitter() const { return true; }
324cb93a386Sopenharmony_ci
325cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
326cb93a386Sopenharmony_ci
327cb93a386Sopenharmony_cistatic int compute_anti_width(const int16_t runs[]) {
328cb93a386Sopenharmony_ci    int width = 0;
329cb93a386Sopenharmony_ci
330cb93a386Sopenharmony_ci    for (;;) {
331cb93a386Sopenharmony_ci        int count = runs[0];
332cb93a386Sopenharmony_ci
333cb93a386Sopenharmony_ci        SkASSERT(count >= 0);
334cb93a386Sopenharmony_ci        if (count == 0) {
335cb93a386Sopenharmony_ci            break;
336cb93a386Sopenharmony_ci        }
337cb93a386Sopenharmony_ci        width += count;
338cb93a386Sopenharmony_ci        runs += count;
339cb93a386Sopenharmony_ci    }
340cb93a386Sopenharmony_ci    return width;
341cb93a386Sopenharmony_ci}
342cb93a386Sopenharmony_ci
343cb93a386Sopenharmony_cistatic inline bool y_in_rect(int y, const SkIRect& rect) {
344cb93a386Sopenharmony_ci    return (unsigned)(y - rect.fTop) < (unsigned)rect.height();
345cb93a386Sopenharmony_ci}
346cb93a386Sopenharmony_ci
347cb93a386Sopenharmony_cistatic inline bool x_in_rect(int x, const SkIRect& rect) {
348cb93a386Sopenharmony_ci    return (unsigned)(x - rect.fLeft) < (unsigned)rect.width();
349cb93a386Sopenharmony_ci}
350cb93a386Sopenharmony_ci
351cb93a386Sopenharmony_civoid SkRectClipBlitter::blitH(int left, int y, int width) {
352cb93a386Sopenharmony_ci    SkASSERT(width > 0);
353cb93a386Sopenharmony_ci
354cb93a386Sopenharmony_ci    if (!y_in_rect(y, fClipRect)) {
355cb93a386Sopenharmony_ci        return;
356cb93a386Sopenharmony_ci    }
357cb93a386Sopenharmony_ci
358cb93a386Sopenharmony_ci    int right = left + width;
359cb93a386Sopenharmony_ci
360cb93a386Sopenharmony_ci    if (left < fClipRect.fLeft) {
361cb93a386Sopenharmony_ci        left = fClipRect.fLeft;
362cb93a386Sopenharmony_ci    }
363cb93a386Sopenharmony_ci    if (right > fClipRect.fRight) {
364cb93a386Sopenharmony_ci        right = fClipRect.fRight;
365cb93a386Sopenharmony_ci    }
366cb93a386Sopenharmony_ci
367cb93a386Sopenharmony_ci    width = right - left;
368cb93a386Sopenharmony_ci    if (width > 0) {
369cb93a386Sopenharmony_ci        fBlitter->blitH(left, y, width);
370cb93a386Sopenharmony_ci    }
371cb93a386Sopenharmony_ci}
372cb93a386Sopenharmony_ci
373cb93a386Sopenharmony_civoid SkRectClipBlitter::blitAntiH(int left, int y, const SkAlpha aa[],
374cb93a386Sopenharmony_ci                                  const int16_t runs[]) {
375cb93a386Sopenharmony_ci    if (!y_in_rect(y, fClipRect) || left >= fClipRect.fRight) {
376cb93a386Sopenharmony_ci        return;
377cb93a386Sopenharmony_ci    }
378cb93a386Sopenharmony_ci
379cb93a386Sopenharmony_ci    int x0 = left;
380cb93a386Sopenharmony_ci    int x1 = left + compute_anti_width(runs);
381cb93a386Sopenharmony_ci
382cb93a386Sopenharmony_ci    if (x1 <= fClipRect.fLeft) {
383cb93a386Sopenharmony_ci        return;
384cb93a386Sopenharmony_ci    }
385cb93a386Sopenharmony_ci
386cb93a386Sopenharmony_ci    SkASSERT(x0 < x1);
387cb93a386Sopenharmony_ci    if (x0 < fClipRect.fLeft) {
388cb93a386Sopenharmony_ci        int dx = fClipRect.fLeft - x0;
389cb93a386Sopenharmony_ci        SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, dx);
390cb93a386Sopenharmony_ci        runs += dx;
391cb93a386Sopenharmony_ci        aa += dx;
392cb93a386Sopenharmony_ci        x0 = fClipRect.fLeft;
393cb93a386Sopenharmony_ci    }
394cb93a386Sopenharmony_ci
395cb93a386Sopenharmony_ci    SkASSERT(x0 < x1 && runs[x1 - x0] == 0);
396cb93a386Sopenharmony_ci    if (x1 > fClipRect.fRight) {
397cb93a386Sopenharmony_ci        x1 = fClipRect.fRight;
398cb93a386Sopenharmony_ci        SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, x1 - x0);
399cb93a386Sopenharmony_ci        ((int16_t*)runs)[x1 - x0] = 0;
400cb93a386Sopenharmony_ci    }
401cb93a386Sopenharmony_ci
402cb93a386Sopenharmony_ci    SkASSERT(x0 < x1 && runs[x1 - x0] == 0);
403cb93a386Sopenharmony_ci    SkASSERT(compute_anti_width(runs) == x1 - x0);
404cb93a386Sopenharmony_ci
405cb93a386Sopenharmony_ci    fBlitter->blitAntiH(x0, y, aa, runs);
406cb93a386Sopenharmony_ci}
407cb93a386Sopenharmony_ci
408cb93a386Sopenharmony_civoid SkRectClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
409cb93a386Sopenharmony_ci    SkASSERT(height > 0);
410cb93a386Sopenharmony_ci
411cb93a386Sopenharmony_ci    if (!x_in_rect(x, fClipRect)) {
412cb93a386Sopenharmony_ci        return;
413cb93a386Sopenharmony_ci    }
414cb93a386Sopenharmony_ci
415cb93a386Sopenharmony_ci    int y0 = y;
416cb93a386Sopenharmony_ci    int y1 = y + height;
417cb93a386Sopenharmony_ci
418cb93a386Sopenharmony_ci    if (y0 < fClipRect.fTop) {
419cb93a386Sopenharmony_ci        y0 = fClipRect.fTop;
420cb93a386Sopenharmony_ci    }
421cb93a386Sopenharmony_ci    if (y1 > fClipRect.fBottom) {
422cb93a386Sopenharmony_ci        y1 = fClipRect.fBottom;
423cb93a386Sopenharmony_ci    }
424cb93a386Sopenharmony_ci
425cb93a386Sopenharmony_ci    if (y0 < y1) {
426cb93a386Sopenharmony_ci        fBlitter->blitV(x, y0, y1 - y0, alpha);
427cb93a386Sopenharmony_ci    }
428cb93a386Sopenharmony_ci}
429cb93a386Sopenharmony_ci
430cb93a386Sopenharmony_civoid SkRectClipBlitter::blitRect(int left, int y, int width, int height) {
431cb93a386Sopenharmony_ci    SkIRect    r;
432cb93a386Sopenharmony_ci
433cb93a386Sopenharmony_ci    r.setLTRB(left, y, left + width, y + height);
434cb93a386Sopenharmony_ci    if (r.intersect(fClipRect)) {
435cb93a386Sopenharmony_ci        fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
436cb93a386Sopenharmony_ci    }
437cb93a386Sopenharmony_ci}
438cb93a386Sopenharmony_ci
439cb93a386Sopenharmony_civoid SkRectClipBlitter::blitAntiRect(int left, int y, int width, int height,
440cb93a386Sopenharmony_ci                                     SkAlpha leftAlpha, SkAlpha rightAlpha) {
441cb93a386Sopenharmony_ci    SkIRect    r;
442cb93a386Sopenharmony_ci
443cb93a386Sopenharmony_ci    // The *true* width of the rectangle blitted is width+2:
444cb93a386Sopenharmony_ci    r.setLTRB(left, y, left + width + 2, y + height);
445cb93a386Sopenharmony_ci    if (r.intersect(fClipRect)) {
446cb93a386Sopenharmony_ci        if (r.fLeft != left) {
447cb93a386Sopenharmony_ci            SkASSERT(r.fLeft > left);
448cb93a386Sopenharmony_ci            leftAlpha = 255;
449cb93a386Sopenharmony_ci        }
450cb93a386Sopenharmony_ci        if (r.fRight != left + width + 2) {
451cb93a386Sopenharmony_ci            SkASSERT(r.fRight < left + width + 2);
452cb93a386Sopenharmony_ci            rightAlpha = 255;
453cb93a386Sopenharmony_ci        }
454cb93a386Sopenharmony_ci        if (255 == leftAlpha && 255 == rightAlpha) {
455cb93a386Sopenharmony_ci            fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
456cb93a386Sopenharmony_ci        } else if (1 == r.width()) {
457cb93a386Sopenharmony_ci            if (r.fLeft == left) {
458cb93a386Sopenharmony_ci                fBlitter->blitV(r.fLeft, r.fTop, r.height(), leftAlpha);
459cb93a386Sopenharmony_ci            } else {
460cb93a386Sopenharmony_ci                SkASSERT(r.fLeft == left + width + 1);
461cb93a386Sopenharmony_ci                fBlitter->blitV(r.fLeft, r.fTop, r.height(), rightAlpha);
462cb93a386Sopenharmony_ci            }
463cb93a386Sopenharmony_ci        } else {
464cb93a386Sopenharmony_ci            fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(),
465cb93a386Sopenharmony_ci                                   leftAlpha, rightAlpha);
466cb93a386Sopenharmony_ci        }
467cb93a386Sopenharmony_ci    }
468cb93a386Sopenharmony_ci}
469cb93a386Sopenharmony_ci
470cb93a386Sopenharmony_civoid SkRectClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
471cb93a386Sopenharmony_ci    SkASSERT(mask.fBounds.contains(clip));
472cb93a386Sopenharmony_ci
473cb93a386Sopenharmony_ci    SkIRect    r = clip;
474cb93a386Sopenharmony_ci
475cb93a386Sopenharmony_ci    if (r.intersect(fClipRect)) {
476cb93a386Sopenharmony_ci        fBlitter->blitMask(mask, r);
477cb93a386Sopenharmony_ci    }
478cb93a386Sopenharmony_ci}
479cb93a386Sopenharmony_ci
480cb93a386Sopenharmony_ciconst SkPixmap* SkRectClipBlitter::justAnOpaqueColor(uint32_t* value) {
481cb93a386Sopenharmony_ci    return fBlitter->justAnOpaqueColor(value);
482cb93a386Sopenharmony_ci}
483cb93a386Sopenharmony_ci
484cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
485cb93a386Sopenharmony_ci
486cb93a386Sopenharmony_civoid SkRgnClipBlitter::blitH(int x, int y, int width) {
487cb93a386Sopenharmony_ci    SkRegion::Spanerator span(*fRgn, y, x, x + width);
488cb93a386Sopenharmony_ci    int left, right;
489cb93a386Sopenharmony_ci
490cb93a386Sopenharmony_ci    while (span.next(&left, &right)) {
491cb93a386Sopenharmony_ci        SkASSERT(left < right);
492cb93a386Sopenharmony_ci        fBlitter->blitH(left, y, right - left);
493cb93a386Sopenharmony_ci    }
494cb93a386Sopenharmony_ci}
495cb93a386Sopenharmony_ci
496cb93a386Sopenharmony_civoid SkRgnClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[],
497cb93a386Sopenharmony_ci                                 const int16_t runs[]) {
498cb93a386Sopenharmony_ci    int width = compute_anti_width(runs);
499cb93a386Sopenharmony_ci    SkRegion::Spanerator span(*fRgn, y, x, x + width);
500cb93a386Sopenharmony_ci    int left, right;
501cb93a386Sopenharmony_ci    SkDEBUGCODE(const SkIRect& bounds = fRgn->getBounds();)
502cb93a386Sopenharmony_ci
503cb93a386Sopenharmony_ci    int prevRite = x;
504cb93a386Sopenharmony_ci    while (span.next(&left, &right)) {
505cb93a386Sopenharmony_ci        SkASSERT(x <= left);
506cb93a386Sopenharmony_ci        SkASSERT(left < right);
507cb93a386Sopenharmony_ci        SkASSERT(left >= bounds.fLeft && right <= bounds.fRight);
508cb93a386Sopenharmony_ci
509cb93a386Sopenharmony_ci        SkAlphaRuns::Break((int16_t*)runs, (uint8_t*)aa, left - x, right - left);
510cb93a386Sopenharmony_ci
511cb93a386Sopenharmony_ci        // now zero before left
512cb93a386Sopenharmony_ci        if (left > prevRite) {
513cb93a386Sopenharmony_ci            int index = prevRite - x;
514cb93a386Sopenharmony_ci            ((uint8_t*)aa)[index] = 0;   // skip runs after right
515cb93a386Sopenharmony_ci            ((int16_t*)runs)[index] = SkToS16(left - prevRite);
516cb93a386Sopenharmony_ci        }
517cb93a386Sopenharmony_ci
518cb93a386Sopenharmony_ci        prevRite = right;
519cb93a386Sopenharmony_ci    }
520cb93a386Sopenharmony_ci
521cb93a386Sopenharmony_ci    if (prevRite > x) {
522cb93a386Sopenharmony_ci        ((int16_t*)runs)[prevRite - x] = 0;
523cb93a386Sopenharmony_ci
524cb93a386Sopenharmony_ci        if (x < 0) {
525cb93a386Sopenharmony_ci            int skip = runs[0];
526cb93a386Sopenharmony_ci            SkASSERT(skip >= -x);
527cb93a386Sopenharmony_ci            aa += skip;
528cb93a386Sopenharmony_ci            runs += skip;
529cb93a386Sopenharmony_ci            x += skip;
530cb93a386Sopenharmony_ci        }
531cb93a386Sopenharmony_ci        fBlitter->blitAntiH(x, y, aa, runs);
532cb93a386Sopenharmony_ci    }
533cb93a386Sopenharmony_ci}
534cb93a386Sopenharmony_ci
535cb93a386Sopenharmony_civoid SkRgnClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
536cb93a386Sopenharmony_ci    SkIRect    bounds;
537cb93a386Sopenharmony_ci    bounds.setXYWH(x, y, 1, height);
538cb93a386Sopenharmony_ci
539cb93a386Sopenharmony_ci    SkRegion::Cliperator    iter(*fRgn, bounds);
540cb93a386Sopenharmony_ci
541cb93a386Sopenharmony_ci    while (!iter.done()) {
542cb93a386Sopenharmony_ci        const SkIRect& r = iter.rect();
543cb93a386Sopenharmony_ci        SkASSERT(bounds.contains(r));
544cb93a386Sopenharmony_ci
545cb93a386Sopenharmony_ci        fBlitter->blitV(x, r.fTop, r.height(), alpha);
546cb93a386Sopenharmony_ci        iter.next();
547cb93a386Sopenharmony_ci    }
548cb93a386Sopenharmony_ci}
549cb93a386Sopenharmony_ci
550cb93a386Sopenharmony_civoid SkRgnClipBlitter::blitRect(int x, int y, int width, int height) {
551cb93a386Sopenharmony_ci    SkIRect    bounds;
552cb93a386Sopenharmony_ci    bounds.setXYWH(x, y, width, height);
553cb93a386Sopenharmony_ci
554cb93a386Sopenharmony_ci    SkRegion::Cliperator    iter(*fRgn, bounds);
555cb93a386Sopenharmony_ci
556cb93a386Sopenharmony_ci    while (!iter.done()) {
557cb93a386Sopenharmony_ci        const SkIRect& r = iter.rect();
558cb93a386Sopenharmony_ci        SkASSERT(bounds.contains(r));
559cb93a386Sopenharmony_ci
560cb93a386Sopenharmony_ci        fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
561cb93a386Sopenharmony_ci        iter.next();
562cb93a386Sopenharmony_ci    }
563cb93a386Sopenharmony_ci}
564cb93a386Sopenharmony_ci
565cb93a386Sopenharmony_civoid SkRgnClipBlitter::blitAntiRect(int x, int y, int width, int height,
566cb93a386Sopenharmony_ci                                    SkAlpha leftAlpha, SkAlpha rightAlpha) {
567cb93a386Sopenharmony_ci    // The *true* width of the rectangle to blit is width + 2
568cb93a386Sopenharmony_ci    SkIRect    bounds;
569cb93a386Sopenharmony_ci    bounds.setXYWH(x, y, width + 2, height);
570cb93a386Sopenharmony_ci
571cb93a386Sopenharmony_ci    SkRegion::Cliperator    iter(*fRgn, bounds);
572cb93a386Sopenharmony_ci
573cb93a386Sopenharmony_ci    while (!iter.done()) {
574cb93a386Sopenharmony_ci        const SkIRect& r = iter.rect();
575cb93a386Sopenharmony_ci        SkASSERT(bounds.contains(r));
576cb93a386Sopenharmony_ci        SkASSERT(r.fLeft >= x);
577cb93a386Sopenharmony_ci        SkASSERT(r.fRight <= x + width + 2);
578cb93a386Sopenharmony_ci
579cb93a386Sopenharmony_ci        SkAlpha effectiveLeftAlpha = (r.fLeft == x) ? leftAlpha : 255;
580cb93a386Sopenharmony_ci        SkAlpha effectiveRightAlpha = (r.fRight == x + width + 2) ?
581cb93a386Sopenharmony_ci                                      rightAlpha : 255;
582cb93a386Sopenharmony_ci
583cb93a386Sopenharmony_ci        if (255 == effectiveLeftAlpha && 255 == effectiveRightAlpha) {
584cb93a386Sopenharmony_ci            fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
585cb93a386Sopenharmony_ci        } else if (1 == r.width()) {
586cb93a386Sopenharmony_ci            if (r.fLeft == x) {
587cb93a386Sopenharmony_ci                fBlitter->blitV(r.fLeft, r.fTop, r.height(),
588cb93a386Sopenharmony_ci                                effectiveLeftAlpha);
589cb93a386Sopenharmony_ci            } else {
590cb93a386Sopenharmony_ci                SkASSERT(r.fLeft == x + width + 1);
591cb93a386Sopenharmony_ci                fBlitter->blitV(r.fLeft, r.fTop, r.height(),
592cb93a386Sopenharmony_ci                                effectiveRightAlpha);
593cb93a386Sopenharmony_ci            }
594cb93a386Sopenharmony_ci        } else {
595cb93a386Sopenharmony_ci            fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(),
596cb93a386Sopenharmony_ci                                   effectiveLeftAlpha, effectiveRightAlpha);
597cb93a386Sopenharmony_ci        }
598cb93a386Sopenharmony_ci        iter.next();
599cb93a386Sopenharmony_ci    }
600cb93a386Sopenharmony_ci}
601cb93a386Sopenharmony_ci
602cb93a386Sopenharmony_ci
603cb93a386Sopenharmony_civoid SkRgnClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
604cb93a386Sopenharmony_ci    SkASSERT(mask.fBounds.contains(clip));
605cb93a386Sopenharmony_ci
606cb93a386Sopenharmony_ci    SkRegion::Cliperator iter(*fRgn, clip);
607cb93a386Sopenharmony_ci    const SkIRect&       r = iter.rect();
608cb93a386Sopenharmony_ci    SkBlitter*           blitter = fBlitter;
609cb93a386Sopenharmony_ci
610cb93a386Sopenharmony_ci    while (!iter.done()) {
611cb93a386Sopenharmony_ci        blitter->blitMask(mask, r);
612cb93a386Sopenharmony_ci        iter.next();
613cb93a386Sopenharmony_ci    }
614cb93a386Sopenharmony_ci}
615cb93a386Sopenharmony_ci
616cb93a386Sopenharmony_ciconst SkPixmap* SkRgnClipBlitter::justAnOpaqueColor(uint32_t* value) {
617cb93a386Sopenharmony_ci    return fBlitter->justAnOpaqueColor(value);
618cb93a386Sopenharmony_ci}
619cb93a386Sopenharmony_ci
620cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
621cb93a386Sopenharmony_ci
622cb93a386Sopenharmony_ciSkBlitter* SkBlitterClipper::apply(SkBlitter* blitter, const SkRegion* clip,
623cb93a386Sopenharmony_ci                                   const SkIRect* ir) {
624cb93a386Sopenharmony_ci    if (clip) {
625cb93a386Sopenharmony_ci        const SkIRect& clipR = clip->getBounds();
626cb93a386Sopenharmony_ci
627cb93a386Sopenharmony_ci        if (clip->isEmpty() || (ir && !SkIRect::Intersects(clipR, *ir))) {
628cb93a386Sopenharmony_ci            blitter = &fNullBlitter;
629cb93a386Sopenharmony_ci        } else if (clip->isRect()) {
630cb93a386Sopenharmony_ci            if (ir == nullptr || !clipR.contains(*ir)) {
631cb93a386Sopenharmony_ci                fRectBlitter.init(blitter, clipR);
632cb93a386Sopenharmony_ci                blitter = &fRectBlitter;
633cb93a386Sopenharmony_ci            }
634cb93a386Sopenharmony_ci        } else {
635cb93a386Sopenharmony_ci            fRgnBlitter.init(blitter, clip);
636cb93a386Sopenharmony_ci            blitter = &fRgnBlitter;
637cb93a386Sopenharmony_ci        }
638cb93a386Sopenharmony_ci    }
639cb93a386Sopenharmony_ci    return blitter;
640cb93a386Sopenharmony_ci}
641cb93a386Sopenharmony_ci
642cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
643cb93a386Sopenharmony_ci
644cb93a386Sopenharmony_ci#include "src/core/SkCoreBlitters.h"
645cb93a386Sopenharmony_ci
646cb93a386Sopenharmony_cibool SkBlitter::UseLegacyBlitter(const SkPixmap& device,
647cb93a386Sopenharmony_ci                                 const SkPaint& paint,
648cb93a386Sopenharmony_ci                                 const SkMatrix& matrix) {
649cb93a386Sopenharmony_ci    if (gSkForceRasterPipelineBlitter) {
650cb93a386Sopenharmony_ci        return false;
651cb93a386Sopenharmony_ci    }
652cb93a386Sopenharmony_ci#if defined(SK_FORCE_RASTER_PIPELINE_BLITTER)
653cb93a386Sopenharmony_ci    return false;
654cb93a386Sopenharmony_ci#else
655cb93a386Sopenharmony_ci
656cb93a386Sopenharmony_ci#if !defined(SK_SUPPORT_LEGACY_DITHER)
657cb93a386Sopenharmony_ci    if (paint.isDither()) {
658cb93a386Sopenharmony_ci        return false;
659cb93a386Sopenharmony_ci    }
660cb93a386Sopenharmony_ci#endif
661cb93a386Sopenharmony_ci
662cb93a386Sopenharmony_ci    const SkMaskFilterBase* mf = as_MFB(paint.getMaskFilter());
663cb93a386Sopenharmony_ci    const auto mode = paint.asBlendMode();
664cb93a386Sopenharmony_ci
665cb93a386Sopenharmony_ci    // The legacy blitters cannot handle any of these complex features (anymore).
666cb93a386Sopenharmony_ci    if (device.alphaType() == kUnpremul_SkAlphaType   ||
667cb93a386Sopenharmony_ci        !mode                                         ||
668cb93a386Sopenharmony_ci        mode.value() > SkBlendMode::kLastCoeffMode    ||
669cb93a386Sopenharmony_ci        (mf && mf->getFormat() == SkMask::k3D_Format)) {
670cb93a386Sopenharmony_ci        return false;
671cb93a386Sopenharmony_ci    }
672cb93a386Sopenharmony_ci
673cb93a386Sopenharmony_ci    // All the real legacy fast paths are for shaders and SrcOver.
674cb93a386Sopenharmony_ci    // Choosing SkRasterPipelineBlitter will also let us to hit its single-color memset path.
675cb93a386Sopenharmony_ci    if (!paint.getShader() && mode != SkBlendMode::kSrcOver) {
676cb93a386Sopenharmony_ci        return false;
677cb93a386Sopenharmony_ci    }
678cb93a386Sopenharmony_ci
679cb93a386Sopenharmony_ci    auto cs = device.colorSpace();
680cb93a386Sopenharmony_ci    // We check (indirectly via makeContext()) later on if the shader can handle the colorspace
681cb93a386Sopenharmony_ci    // in legacy mode, so here we just focus on if a single color needs raster-pipeline.
682cb93a386Sopenharmony_ci    if (cs && !paint.getShader()) {
683cb93a386Sopenharmony_ci        if (!paint.getColor4f().fitsInBytes() || !cs->isSRGB()) {
684cb93a386Sopenharmony_ci            return false;
685cb93a386Sopenharmony_ci        }
686cb93a386Sopenharmony_ci    }
687cb93a386Sopenharmony_ci
688cb93a386Sopenharmony_ci    // Only kN32 and 565 are handled by legacy blitters now, 565 mostly just for Android.
689cb93a386Sopenharmony_ci    return device.colorType() == kN32_SkColorType
690cb93a386Sopenharmony_ci        || device.colorType() == kRGB_565_SkColorType;
691cb93a386Sopenharmony_ci#endif
692cb93a386Sopenharmony_ci}
693cb93a386Sopenharmony_ci
694cb93a386Sopenharmony_ciSkBlitter* SkBlitter::Choose(const SkPixmap& device,
695cb93a386Sopenharmony_ci                             const SkMatrixProvider& matrixProvider,
696cb93a386Sopenharmony_ci                             const SkPaint& origPaint,
697cb93a386Sopenharmony_ci                             SkArenaAlloc* alloc,
698cb93a386Sopenharmony_ci                             bool drawCoverage,
699cb93a386Sopenharmony_ci                             sk_sp<SkShader> clipShader) {
700cb93a386Sopenharmony_ci    SkASSERT(alloc);
701cb93a386Sopenharmony_ci
702cb93a386Sopenharmony_ci    if (kUnknown_SkColorType == device.colorType()) {
703cb93a386Sopenharmony_ci        return alloc->make<SkNullBlitter>();
704cb93a386Sopenharmony_ci    }
705cb93a386Sopenharmony_ci
706cb93a386Sopenharmony_ci    // We may tweak the original paint as we go.
707cb93a386Sopenharmony_ci    SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
708cb93a386Sopenharmony_ci
709cb93a386Sopenharmony_ci    if (auto mode = paint->asBlendMode()) {
710cb93a386Sopenharmony_ci        // We have the most fast-paths for SrcOver, so see if we can act like SrcOver.
711cb93a386Sopenharmony_ci        if (mode.value() != SkBlendMode::kSrcOver) {
712cb93a386Sopenharmony_ci            switch (SkInterpretXfermode(*paint, SkColorTypeIsAlwaysOpaque(device.colorType()))) {
713cb93a386Sopenharmony_ci                case kSrcOver_SkXfermodeInterpretation:
714cb93a386Sopenharmony_ci                    paint.writable()->setBlendMode(SkBlendMode::kSrcOver);
715cb93a386Sopenharmony_ci                    break;
716cb93a386Sopenharmony_ci                case kSkipDrawing_SkXfermodeInterpretation:
717cb93a386Sopenharmony_ci                    return alloc->make<SkNullBlitter>();
718cb93a386Sopenharmony_ci                default:
719cb93a386Sopenharmony_ci                    break;
720cb93a386Sopenharmony_ci            }
721cb93a386Sopenharmony_ci        }
722cb93a386Sopenharmony_ci
723cb93a386Sopenharmony_ci        // A Clear blend mode will ignore the entire color pipeline, as if Src mode with 0x00000000.
724cb93a386Sopenharmony_ci        if (mode.value() == SkBlendMode::kClear) {
725cb93a386Sopenharmony_ci            SkPaint* p = paint.writable();
726cb93a386Sopenharmony_ci            p->setShader(nullptr);
727cb93a386Sopenharmony_ci            p->setColorFilter(nullptr);
728cb93a386Sopenharmony_ci            p->setBlendMode(SkBlendMode::kSrc);
729cb93a386Sopenharmony_ci            p->setColor(0x00000000);
730cb93a386Sopenharmony_ci        }
731cb93a386Sopenharmony_ci    }
732cb93a386Sopenharmony_ci
733cb93a386Sopenharmony_ci    if (paint->getColorFilter()) {
734cb93a386Sopenharmony_ci        SkPaintPriv::RemoveColorFilter(paint.writable(), device.colorSpace());
735cb93a386Sopenharmony_ci    }
736cb93a386Sopenharmony_ci    SkASSERT(!paint->getColorFilter());
737cb93a386Sopenharmony_ci
738cb93a386Sopenharmony_ci    if (drawCoverage) {
739cb93a386Sopenharmony_ci        if (device.colorType() == kAlpha_8_SkColorType) {
740cb93a386Sopenharmony_ci            SkASSERT(!paint->getShader());
741cb93a386Sopenharmony_ci            SkASSERT(paint->isSrcOver());
742cb93a386Sopenharmony_ci            return alloc->make<SkA8_Coverage_Blitter>(device, *paint);
743cb93a386Sopenharmony_ci        }
744cb93a386Sopenharmony_ci        return alloc->make<SkNullBlitter>();
745cb93a386Sopenharmony_ci    }
746cb93a386Sopenharmony_ci
747cb93a386Sopenharmony_ci    if (paint->isDither() && !SkPaintPriv::ShouldDither(*paint, device.colorType())) {
748cb93a386Sopenharmony_ci        paint.writable()->setDither(false);
749cb93a386Sopenharmony_ci    }
750cb93a386Sopenharmony_ci
751cb93a386Sopenharmony_ci    if (gUseSkVMBlitter) {
752cb93a386Sopenharmony_ci        if (auto blitter = SkVMBlitter::Make(device, *paint, matrixProvider,
753cb93a386Sopenharmony_ci                                             alloc, clipShader)) {
754cb93a386Sopenharmony_ci            return blitter;
755cb93a386Sopenharmony_ci        }
756cb93a386Sopenharmony_ci    }
757cb93a386Sopenharmony_ci
758cb93a386Sopenharmony_ci    // Same basic idea used a few times: try SkRP, then try SkVM, then give up with a null-blitter.
759cb93a386Sopenharmony_ci    // (Setting gUseSkVMBlitter is the only way we prefer SkVM over SkRP at the moment.)
760cb93a386Sopenharmony_ci    auto create_SkRP_or_SkVMBlitter = [&]() -> SkBlitter* {
761cb93a386Sopenharmony_ci        if (auto blitter = SkCreateRasterPipelineBlitter(device, *paint, matrixProvider,
762cb93a386Sopenharmony_ci                                                         alloc, clipShader)) {
763cb93a386Sopenharmony_ci            return blitter;
764cb93a386Sopenharmony_ci        }
765cb93a386Sopenharmony_ci        if (auto blitter = SkVMBlitter::Make(device, *paint, matrixProvider,
766cb93a386Sopenharmony_ci                                             alloc, clipShader)) {
767cb93a386Sopenharmony_ci            return blitter;
768cb93a386Sopenharmony_ci        }
769cb93a386Sopenharmony_ci        return alloc->make<SkNullBlitter>();
770cb93a386Sopenharmony_ci    };
771cb93a386Sopenharmony_ci
772cb93a386Sopenharmony_ci    SkMatrix ctm = matrixProvider.localToDevice();
773cb93a386Sopenharmony_ci    // We'll end here for many interesting cases: color spaces, color filters, most color types.
774cb93a386Sopenharmony_ci    if (clipShader || !UseLegacyBlitter(device, *paint, ctm)) {
775cb93a386Sopenharmony_ci        return create_SkRP_or_SkVMBlitter();
776cb93a386Sopenharmony_ci    }
777cb93a386Sopenharmony_ci
778cb93a386Sopenharmony_ci    // Everything but legacy kN32_SkColorType and kRGB_565_SkColorType should already be handled.
779cb93a386Sopenharmony_ci    SkASSERT(device.colorType() == kN32_SkColorType ||
780cb93a386Sopenharmony_ci             device.colorType() == kRGB_565_SkColorType);
781cb93a386Sopenharmony_ci
782cb93a386Sopenharmony_ci    // And we should either have a shader, be blending with SrcOver, or both.
783cb93a386Sopenharmony_ci    SkASSERT(paint->getShader() || paint->asBlendMode() == SkBlendMode::kSrcOver);
784cb93a386Sopenharmony_ci
785cb93a386Sopenharmony_ci    // Legacy blitters keep their shader state on a shader context.
786cb93a386Sopenharmony_ci    SkShaderBase::Context* shaderContext = nullptr;
787cb93a386Sopenharmony_ci    if (paint->getShader()) {
788cb93a386Sopenharmony_ci        shaderContext = as_SB(paint->getShader())->makeContext(
789cb93a386Sopenharmony_ci                {*paint, ctm, nullptr, device.colorType(), device.colorSpace()},
790cb93a386Sopenharmony_ci                alloc);
791cb93a386Sopenharmony_ci
792cb93a386Sopenharmony_ci        // Creating the context isn't always possible... try fallbacks before giving up.
793cb93a386Sopenharmony_ci        if (!shaderContext) {
794cb93a386Sopenharmony_ci            return create_SkRP_or_SkVMBlitter();
795cb93a386Sopenharmony_ci        }
796cb93a386Sopenharmony_ci    }
797cb93a386Sopenharmony_ci
798cb93a386Sopenharmony_ci    switch (device.colorType()) {
799cb93a386Sopenharmony_ci        case kN32_SkColorType:
800cb93a386Sopenharmony_ci            if (shaderContext) {
801cb93a386Sopenharmony_ci                return alloc->make<SkARGB32_Shader_Blitter>(device, *paint, shaderContext);
802cb93a386Sopenharmony_ci            } else if (paint->getColor() == SK_ColorBLACK) {
803cb93a386Sopenharmony_ci                return alloc->make<SkARGB32_Black_Blitter>(device, *paint);
804cb93a386Sopenharmony_ci            } else if (paint->getAlpha() == 0xFF) {
805cb93a386Sopenharmony_ci                return alloc->make<SkARGB32_Opaque_Blitter>(device, *paint);
806cb93a386Sopenharmony_ci            } else {
807cb93a386Sopenharmony_ci                return alloc->make<SkARGB32_Blitter>(device, *paint);
808cb93a386Sopenharmony_ci            }
809cb93a386Sopenharmony_ci
810cb93a386Sopenharmony_ci        case kRGB_565_SkColorType:
811cb93a386Sopenharmony_ci            if (shaderContext && SkRGB565_Shader_Blitter::Supports(device, *paint)) {
812cb93a386Sopenharmony_ci                return alloc->make<SkRGB565_Shader_Blitter>(device, *paint, shaderContext);
813cb93a386Sopenharmony_ci            } else {
814cb93a386Sopenharmony_ci                return create_SkRP_or_SkVMBlitter();
815cb93a386Sopenharmony_ci            }
816cb93a386Sopenharmony_ci
817cb93a386Sopenharmony_ci        default:
818cb93a386Sopenharmony_ci            SkASSERT(false);
819cb93a386Sopenharmony_ci            return alloc->make<SkNullBlitter>();
820cb93a386Sopenharmony_ci    }
821cb93a386Sopenharmony_ci}
822cb93a386Sopenharmony_ci
823cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
824cb93a386Sopenharmony_ci
825cb93a386Sopenharmony_ciSkShaderBlitter::SkShaderBlitter(const SkPixmap& device, const SkPaint& paint,
826cb93a386Sopenharmony_ci                                 SkShaderBase::Context* shaderContext)
827cb93a386Sopenharmony_ci        : INHERITED(device)
828cb93a386Sopenharmony_ci        , fShader(paint.getShader())
829cb93a386Sopenharmony_ci        , fShaderContext(shaderContext) {
830cb93a386Sopenharmony_ci    SkASSERT(fShader);
831cb93a386Sopenharmony_ci    SkASSERT(fShaderContext);
832cb93a386Sopenharmony_ci
833cb93a386Sopenharmony_ci    fShader->ref();
834cb93a386Sopenharmony_ci    fShaderFlags = fShaderContext->getFlags();
835cb93a386Sopenharmony_ci    fConstInY = SkToBool(fShaderFlags & SkShaderBase::kConstInY32_Flag);
836cb93a386Sopenharmony_ci}
837cb93a386Sopenharmony_ci
838cb93a386Sopenharmony_ciSkShaderBlitter::~SkShaderBlitter() {
839cb93a386Sopenharmony_ci    fShader->unref();
840cb93a386Sopenharmony_ci}
841cb93a386Sopenharmony_ci
842cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////////////////////////
843cb93a386Sopenharmony_ci
844cb93a386Sopenharmony_ci#ifdef SK_DEBUG
845cb93a386Sopenharmony_ci
846cb93a386Sopenharmony_civoid SkRectClipCheckBlitter::blitH(int x, int y, int width) {
847cb93a386Sopenharmony_ci    SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, width, 1)));
848cb93a386Sopenharmony_ci    fBlitter->blitH(x, y, width);
849cb93a386Sopenharmony_ci}
850cb93a386Sopenharmony_ci
851cb93a386Sopenharmony_civoid SkRectClipCheckBlitter::blitAntiH(int x, int y, const SkAlpha aa[], const int16_t runs[]) {
852cb93a386Sopenharmony_ci    const int16_t* iter = runs;
853cb93a386Sopenharmony_ci    for (; *iter; iter += *iter)
854cb93a386Sopenharmony_ci        ;
855cb93a386Sopenharmony_ci    int width = iter - runs;
856cb93a386Sopenharmony_ci    SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, width, 1)));
857cb93a386Sopenharmony_ci    fBlitter->blitAntiH(x, y, aa, runs);
858cb93a386Sopenharmony_ci}
859cb93a386Sopenharmony_ci
860cb93a386Sopenharmony_civoid SkRectClipCheckBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
861cb93a386Sopenharmony_ci    SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, 1, height)));
862cb93a386Sopenharmony_ci    fBlitter->blitV(x, y, height, alpha);
863cb93a386Sopenharmony_ci}
864cb93a386Sopenharmony_ci
865cb93a386Sopenharmony_civoid SkRectClipCheckBlitter::blitRect(int x, int y, int width, int height) {
866cb93a386Sopenharmony_ci    SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, width, height)));
867cb93a386Sopenharmony_ci    fBlitter->blitRect(x, y, width, height);
868cb93a386Sopenharmony_ci}
869cb93a386Sopenharmony_ci
870cb93a386Sopenharmony_civoid SkRectClipCheckBlitter::blitAntiRect(int x, int y, int width, int height,
871cb93a386Sopenharmony_ci                                     SkAlpha leftAlpha, SkAlpha rightAlpha) {
872cb93a386Sopenharmony_ci    bool skipLeft = !leftAlpha;
873cb93a386Sopenharmony_ci    bool skipRight = !rightAlpha;
874cb93a386Sopenharmony_ci    SkIRect r = SkIRect::MakeXYWH(x + skipLeft, y, width + 2 - skipRight - skipLeft, height);
875cb93a386Sopenharmony_ci    SkASSERT(r.isEmpty() || fClipRect.contains(r));
876cb93a386Sopenharmony_ci    fBlitter->blitAntiRect(x, y, width, height, leftAlpha, rightAlpha);
877cb93a386Sopenharmony_ci}
878cb93a386Sopenharmony_ci
879cb93a386Sopenharmony_civoid SkRectClipCheckBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
880cb93a386Sopenharmony_ci    SkASSERT(mask.fBounds.contains(clip));
881cb93a386Sopenharmony_ci    SkASSERT(fClipRect.contains(clip));
882cb93a386Sopenharmony_ci    fBlitter->blitMask(mask, clip);
883cb93a386Sopenharmony_ci}
884cb93a386Sopenharmony_ci
885cb93a386Sopenharmony_ciconst SkPixmap* SkRectClipCheckBlitter::justAnOpaqueColor(uint32_t* value) {
886cb93a386Sopenharmony_ci    return fBlitter->justAnOpaqueColor(value);
887cb93a386Sopenharmony_ci}
888cb93a386Sopenharmony_ci
889cb93a386Sopenharmony_civoid SkRectClipCheckBlitter::blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) {
890cb93a386Sopenharmony_ci    SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, 2, 1)));
891cb93a386Sopenharmony_ci    fBlitter->blitAntiH2(x, y, a0, a1);
892cb93a386Sopenharmony_ci}
893cb93a386Sopenharmony_ci
894cb93a386Sopenharmony_civoid SkRectClipCheckBlitter::blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) {
895cb93a386Sopenharmony_ci    SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, 1, 2)));
896cb93a386Sopenharmony_ci    fBlitter->blitAntiV2(x, y, a0, a1);
897cb93a386Sopenharmony_ci}
898cb93a386Sopenharmony_ci
899cb93a386Sopenharmony_ci#endif
900