1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2016 Google Inc.
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 "include/core/SkColor.h"
9cb93a386Sopenharmony_ci#include "include/core/SkPaint.h"
10cb93a386Sopenharmony_ci#include "include/core/SkShader.h"
11cb93a386Sopenharmony_ci#include "include/private/SkTo.h"
12cb93a386Sopenharmony_ci#include "src/core/SkArenaAlloc.h"
13cb93a386Sopenharmony_ci#include "src/core/SkBlendModePriv.h"
14cb93a386Sopenharmony_ci#include "src/core/SkBlitter.h"
15cb93a386Sopenharmony_ci#include "src/core/SkColorFilterBase.h"
16cb93a386Sopenharmony_ci#include "src/core/SkColorSpacePriv.h"
17cb93a386Sopenharmony_ci#include "src/core/SkColorSpaceXformSteps.h"
18cb93a386Sopenharmony_ci#include "src/core/SkMatrixProvider.h"
19cb93a386Sopenharmony_ci#include "src/core/SkOpts.h"
20cb93a386Sopenharmony_ci#include "src/core/SkRasterPipeline.h"
21cb93a386Sopenharmony_ci#include "src/core/SkUtils.h"
22cb93a386Sopenharmony_ci#include "src/shaders/SkShaderBase.h"
23cb93a386Sopenharmony_ci
24cb93a386Sopenharmony_ciclass SkRasterPipelineBlitter final : public SkBlitter {
25cb93a386Sopenharmony_cipublic:
26cb93a386Sopenharmony_ci    // This is our common entrypoint for creating the blitter once we've sorted out shaders.
27cb93a386Sopenharmony_ci    static SkBlitter* Create(const SkPixmap&, const SkPaint&, SkArenaAlloc*,
28cb93a386Sopenharmony_ci                             const SkRasterPipeline& shaderPipeline,
29cb93a386Sopenharmony_ci                             bool is_opaque, bool is_constant,
30cb93a386Sopenharmony_ci                             sk_sp<SkShader> clipShader);
31cb93a386Sopenharmony_ci
32cb93a386Sopenharmony_ci    SkRasterPipelineBlitter(SkPixmap dst,
33cb93a386Sopenharmony_ci                            SkBlendMode blend,
34cb93a386Sopenharmony_ci                            SkArenaAlloc* alloc)
35cb93a386Sopenharmony_ci        : fDst(dst)
36cb93a386Sopenharmony_ci        , fBlend(blend)
37cb93a386Sopenharmony_ci        , fAlloc(alloc)
38cb93a386Sopenharmony_ci        , fColorPipeline(alloc)
39cb93a386Sopenharmony_ci    {}
40cb93a386Sopenharmony_ci
41cb93a386Sopenharmony_ci    void blitH     (int x, int y, int w)                            override;
42cb93a386Sopenharmony_ci    void blitAntiH (int x, int y, const SkAlpha[], const int16_t[]) override;
43cb93a386Sopenharmony_ci    void blitAntiH2(int x, int y, U8CPU a0, U8CPU a1)               override;
44cb93a386Sopenharmony_ci    void blitAntiV2(int x, int y, U8CPU a0, U8CPU a1)               override;
45cb93a386Sopenharmony_ci    void blitMask  (const SkMask&, const SkIRect& clip)             override;
46cb93a386Sopenharmony_ci    void blitRect  (int x, int y, int width, int height)            override;
47cb93a386Sopenharmony_ci    void blitV     (int x, int y, int height, SkAlpha alpha)        override;
48cb93a386Sopenharmony_ci
49cb93a386Sopenharmony_ciprivate:
50cb93a386Sopenharmony_ci    void append_load_dst      (SkRasterPipeline*) const;
51cb93a386Sopenharmony_ci    void append_store         (SkRasterPipeline*) const;
52cb93a386Sopenharmony_ci
53cb93a386Sopenharmony_ci    // these check internally, and only append if there was a native clipShader
54cb93a386Sopenharmony_ci    void append_clip_scale    (SkRasterPipeline*) const;
55cb93a386Sopenharmony_ci    void append_clip_lerp     (SkRasterPipeline*) const;
56cb93a386Sopenharmony_ci
57cb93a386Sopenharmony_ci    SkPixmap               fDst;
58cb93a386Sopenharmony_ci    SkBlendMode            fBlend;
59cb93a386Sopenharmony_ci    SkArenaAlloc*          fAlloc;
60cb93a386Sopenharmony_ci    SkRasterPipeline       fColorPipeline;
61cb93a386Sopenharmony_ci    // set to pipeline storage (for alpha) if we have a clipShader
62cb93a386Sopenharmony_ci    void*                  fClipShaderBuffer = nullptr; // "native" : float or U16
63cb93a386Sopenharmony_ci
64cb93a386Sopenharmony_ci    SkRasterPipeline_MemoryCtx
65cb93a386Sopenharmony_ci        fDstPtr       = {nullptr,0},  // Always points to the top-left of fDst.
66cb93a386Sopenharmony_ci        fMaskPtr      = {nullptr,0};  // Updated each call to blitMask().
67cb93a386Sopenharmony_ci    SkRasterPipeline_EmbossCtx fEmbossCtx;  // Used only for k3D_Format masks.
68cb93a386Sopenharmony_ci
69cb93a386Sopenharmony_ci    // We may be able to specialize blitH() or blitRect() into a memset.
70cb93a386Sopenharmony_ci    void   (*fMemset2D)(SkPixmap*, int x,int y, int w,int h, uint64_t color) = nullptr;
71cb93a386Sopenharmony_ci    uint64_t fMemsetColor = 0;   // Big enough for largest memsettable dst format, F16.
72cb93a386Sopenharmony_ci
73cb93a386Sopenharmony_ci    // Built lazily on first use.
74cb93a386Sopenharmony_ci    std::function<void(size_t, size_t, size_t, size_t)> fBlitRect,
75cb93a386Sopenharmony_ci                                                        fBlitAntiH,
76cb93a386Sopenharmony_ci                                                        fBlitMaskA8,
77cb93a386Sopenharmony_ci                                                        fBlitMaskLCD16,
78cb93a386Sopenharmony_ci                                                        fBlitMask3D;
79cb93a386Sopenharmony_ci
80cb93a386Sopenharmony_ci    // These values are pointed to by the blit pipelines above,
81cb93a386Sopenharmony_ci    // which allows us to adjust them from call to call.
82cb93a386Sopenharmony_ci    float fCurrentCoverage = 0.0f;
83cb93a386Sopenharmony_ci    float fDitherRate      = 0.0f;
84cb93a386Sopenharmony_ci
85cb93a386Sopenharmony_ci    using INHERITED = SkBlitter;
86cb93a386Sopenharmony_ci};
87cb93a386Sopenharmony_ci
88cb93a386Sopenharmony_ciSkBlitter* SkCreateRasterPipelineBlitter(const SkPixmap& dst,
89cb93a386Sopenharmony_ci                                         const SkPaint& paint,
90cb93a386Sopenharmony_ci                                         const SkMatrixProvider& matrixProvider,
91cb93a386Sopenharmony_ci                                         SkArenaAlloc* alloc,
92cb93a386Sopenharmony_ci                                         sk_sp<SkShader> clipShader) {
93cb93a386Sopenharmony_ci    if (!paint.asBlendMode()) {
94cb93a386Sopenharmony_ci        // The raster pipeline doesn't support SkBlender.
95cb93a386Sopenharmony_ci        return nullptr;
96cb93a386Sopenharmony_ci    }
97cb93a386Sopenharmony_ci
98cb93a386Sopenharmony_ci    SkColorSpace* dstCS = dst.colorSpace();
99cb93a386Sopenharmony_ci    SkColorType dstCT = dst.colorType();
100cb93a386Sopenharmony_ci    SkColor4f paintColor = paint.getColor4f();
101cb93a386Sopenharmony_ci    SkColorSpaceXformSteps(sk_srgb_singleton(), kUnpremul_SkAlphaType,
102cb93a386Sopenharmony_ci                           dstCS,               kUnpremul_SkAlphaType).apply(paintColor.vec());
103cb93a386Sopenharmony_ci
104cb93a386Sopenharmony_ci    auto shader = as_SB(paint.getShader());
105cb93a386Sopenharmony_ci
106cb93a386Sopenharmony_ci    SkRasterPipeline_<256> shaderPipeline;
107cb93a386Sopenharmony_ci    if (!shader) {
108cb93a386Sopenharmony_ci        // Having no shader makes things nice and easy... just use the paint color.
109cb93a386Sopenharmony_ci        shaderPipeline.append_constant_color(alloc, paintColor.premul().vec());
110cb93a386Sopenharmony_ci        bool is_opaque    = paintColor.fA == 1.0f,
111cb93a386Sopenharmony_ci             is_constant  = true;
112cb93a386Sopenharmony_ci        return SkRasterPipelineBlitter::Create(dst, paint, alloc,
113cb93a386Sopenharmony_ci                                               shaderPipeline, is_opaque, is_constant,
114cb93a386Sopenharmony_ci                                               std::move(clipShader));
115cb93a386Sopenharmony_ci    }
116cb93a386Sopenharmony_ci
117cb93a386Sopenharmony_ci    bool is_opaque    = shader->isOpaque() && paintColor.fA == 1.0f;
118cb93a386Sopenharmony_ci    bool is_constant  = shader->isConstant();
119cb93a386Sopenharmony_ci
120cb93a386Sopenharmony_ci    if (shader->appendStages(
121cb93a386Sopenharmony_ci                {&shaderPipeline, alloc, dstCT, dstCS, paint, nullptr, matrixProvider})) {
122cb93a386Sopenharmony_ci        if (paintColor.fA != 1.0f) {
123cb93a386Sopenharmony_ci            shaderPipeline.append(SkRasterPipeline::scale_1_float,
124cb93a386Sopenharmony_ci                                  alloc->make<float>(paintColor.fA));
125cb93a386Sopenharmony_ci        }
126cb93a386Sopenharmony_ci        return SkRasterPipelineBlitter::Create(dst, paint, alloc,
127cb93a386Sopenharmony_ci                                               shaderPipeline, is_opaque, is_constant,
128cb93a386Sopenharmony_ci                                               std::move(clipShader));
129cb93a386Sopenharmony_ci    }
130cb93a386Sopenharmony_ci
131cb93a386Sopenharmony_ci    // The shader can't draw with SkRasterPipeline.
132cb93a386Sopenharmony_ci    return nullptr;
133cb93a386Sopenharmony_ci}
134cb93a386Sopenharmony_ci
135cb93a386Sopenharmony_ciSkBlitter* SkCreateRasterPipelineBlitter(const SkPixmap& dst,
136cb93a386Sopenharmony_ci                                         const SkPaint& paint,
137cb93a386Sopenharmony_ci                                         const SkRasterPipeline& shaderPipeline,
138cb93a386Sopenharmony_ci                                         bool is_opaque,
139cb93a386Sopenharmony_ci                                         SkArenaAlloc* alloc,
140cb93a386Sopenharmony_ci                                         sk_sp<SkShader> clipShader) {
141cb93a386Sopenharmony_ci    bool is_constant = false;  // If this were the case, it'd be better to just set a paint color.
142cb93a386Sopenharmony_ci    return SkRasterPipelineBlitter::Create(dst, paint, alloc,
143cb93a386Sopenharmony_ci                                           shaderPipeline, is_opaque, is_constant,
144cb93a386Sopenharmony_ci                                           clipShader);
145cb93a386Sopenharmony_ci}
146cb93a386Sopenharmony_ci
147cb93a386Sopenharmony_ciSkBlitter* SkRasterPipelineBlitter::Create(const SkPixmap& dst,
148cb93a386Sopenharmony_ci                                           const SkPaint& paint,
149cb93a386Sopenharmony_ci                                           SkArenaAlloc* alloc,
150cb93a386Sopenharmony_ci                                           const SkRasterPipeline& shaderPipeline,
151cb93a386Sopenharmony_ci                                           bool is_opaque,
152cb93a386Sopenharmony_ci                                           bool is_constant,
153cb93a386Sopenharmony_ci                                           sk_sp<SkShader> clipShader) {
154cb93a386Sopenharmony_ci    const auto bm = paint.asBlendMode();
155cb93a386Sopenharmony_ci    if (!bm) {
156cb93a386Sopenharmony_ci        return nullptr;
157cb93a386Sopenharmony_ci    }
158cb93a386Sopenharmony_ci
159cb93a386Sopenharmony_ci    auto blitter = alloc->make<SkRasterPipelineBlitter>(dst, bm.value(), alloc);
160cb93a386Sopenharmony_ci
161cb93a386Sopenharmony_ci    // Our job in this factory is to fill out the blitter's color pipeline.
162cb93a386Sopenharmony_ci    // This is the common front of the full blit pipelines, each constructed lazily on first use.
163cb93a386Sopenharmony_ci    // The full blit pipelines handle reading and writing the dst, blending, coverage, dithering.
164cb93a386Sopenharmony_ci    auto colorPipeline = &blitter->fColorPipeline;
165cb93a386Sopenharmony_ci
166cb93a386Sopenharmony_ci    if (clipShader) {
167cb93a386Sopenharmony_ci        auto clipP = colorPipeline;
168cb93a386Sopenharmony_ci        SkPaint clipPaint;  // just need default values
169cb93a386Sopenharmony_ci        SkColorType clipCT = kRGBA_8888_SkColorType;
170cb93a386Sopenharmony_ci        SkColorSpace* clipCS = nullptr;
171cb93a386Sopenharmony_ci        SkSimpleMatrixProvider clipMatrixProvider(SkMatrix::I());
172cb93a386Sopenharmony_ci        SkStageRec rec = {clipP, alloc, clipCT, clipCS, clipPaint, nullptr, clipMatrixProvider};
173cb93a386Sopenharmony_ci        if (as_SB(clipShader)->appendStages(rec)) {
174cb93a386Sopenharmony_ci            struct Storage {
175cb93a386Sopenharmony_ci                // large enough for highp (float) or lowp(U16)
176cb93a386Sopenharmony_ci                float   fA[SkRasterPipeline_kMaxStride];
177cb93a386Sopenharmony_ci            };
178cb93a386Sopenharmony_ci            auto storage = alloc->make<Storage>();
179cb93a386Sopenharmony_ci            clipP->append(SkRasterPipeline::store_src_a, storage->fA);
180cb93a386Sopenharmony_ci            blitter->fClipShaderBuffer = storage->fA;
181cb93a386Sopenharmony_ci            is_constant = false;
182cb93a386Sopenharmony_ci        } else {
183cb93a386Sopenharmony_ci            return nullptr;
184cb93a386Sopenharmony_ci        }
185cb93a386Sopenharmony_ci    }
186cb93a386Sopenharmony_ci
187cb93a386Sopenharmony_ci    // Let's get the shader in first.
188cb93a386Sopenharmony_ci    colorPipeline->extend(shaderPipeline);
189cb93a386Sopenharmony_ci
190cb93a386Sopenharmony_ci    // If there's a color filter it comes next.
191cb93a386Sopenharmony_ci    if (auto colorFilter = paint.getColorFilter()) {
192cb93a386Sopenharmony_ci        SkSimpleMatrixProvider matrixProvider(SkMatrix::I());
193cb93a386Sopenharmony_ci        SkStageRec rec = {
194cb93a386Sopenharmony_ci            colorPipeline, alloc, dst.colorType(), dst.colorSpace(), paint, nullptr, matrixProvider
195cb93a386Sopenharmony_ci        };
196cb93a386Sopenharmony_ci        if (!as_CFB(colorFilter)->appendStages(rec, is_opaque)) {
197cb93a386Sopenharmony_ci            return nullptr;
198cb93a386Sopenharmony_ci        }
199cb93a386Sopenharmony_ci        is_opaque = is_opaque && as_CFB(colorFilter)->isAlphaUnchanged();
200cb93a386Sopenharmony_ci    }
201cb93a386Sopenharmony_ci
202cb93a386Sopenharmony_ci    // Not all formats make sense to dither (think, F16).  We set their dither rate
203cb93a386Sopenharmony_ci    // to zero.  We only dither non-constant shaders, so is_constant won't change here.
204cb93a386Sopenharmony_ci    if (paint.isDither() && !is_constant) {
205cb93a386Sopenharmony_ci        switch (dst.info().colorType()) {
206cb93a386Sopenharmony_ci            case kARGB_4444_SkColorType:    blitter->fDitherRate =   1/15.0f; break;
207cb93a386Sopenharmony_ci            case   kRGB_565_SkColorType:    blitter->fDitherRate =   1/63.0f; break;
208cb93a386Sopenharmony_ci            case    kGray_8_SkColorType:
209cb93a386Sopenharmony_ci            case  kRGB_888x_SkColorType:
210cb93a386Sopenharmony_ci            case kRGBA_8888_SkColorType:
211cb93a386Sopenharmony_ci            case kBGRA_8888_SkColorType:
212cb93a386Sopenharmony_ci            case kSRGBA_8888_SkColorType:   blitter->fDitherRate =  1/255.0f; break;
213cb93a386Sopenharmony_ci            case kRGB_101010x_SkColorType:
214cb93a386Sopenharmony_ci            case kRGBA_1010102_SkColorType:
215cb93a386Sopenharmony_ci            case kBGR_101010x_SkColorType:
216cb93a386Sopenharmony_ci            case kBGRA_1010102_SkColorType: blitter->fDitherRate = 1/1023.0f; break;
217cb93a386Sopenharmony_ci
218cb93a386Sopenharmony_ci            case kUnknown_SkColorType:
219cb93a386Sopenharmony_ci            case kAlpha_8_SkColorType:
220cb93a386Sopenharmony_ci            case kRGBA_F16_SkColorType:
221cb93a386Sopenharmony_ci            case kRGBA_F16Norm_SkColorType:
222cb93a386Sopenharmony_ci            case kRGBA_F32_SkColorType:
223cb93a386Sopenharmony_ci            case kR8G8_unorm_SkColorType:
224cb93a386Sopenharmony_ci            case kA16_float_SkColorType:
225cb93a386Sopenharmony_ci            case kA16_unorm_SkColorType:
226cb93a386Sopenharmony_ci            case kR16G16_float_SkColorType:
227cb93a386Sopenharmony_ci            case kR16G16_unorm_SkColorType:
228cb93a386Sopenharmony_ci            case kR16G16B16A16_unorm_SkColorType: blitter->fDitherRate = 0.0f; break;
229cb93a386Sopenharmony_ci        }
230cb93a386Sopenharmony_ci        if (blitter->fDitherRate > 0.0f) {
231cb93a386Sopenharmony_ci            colorPipeline->append(SkRasterPipeline::dither, &blitter->fDitherRate);
232cb93a386Sopenharmony_ci        }
233cb93a386Sopenharmony_ci    }
234cb93a386Sopenharmony_ci
235cb93a386Sopenharmony_ci    // We're logically done here.  The code between here and return blitter is all optimization.
236cb93a386Sopenharmony_ci
237cb93a386Sopenharmony_ci    // A pipeline that's still constant here can collapse back into a constant color.
238cb93a386Sopenharmony_ci    if (is_constant) {
239cb93a386Sopenharmony_ci        SkColor4f constantColor;
240cb93a386Sopenharmony_ci        SkRasterPipeline_MemoryCtx constantColorPtr = { &constantColor, 0 };
241cb93a386Sopenharmony_ci        colorPipeline->append_gamut_clamp_if_normalized(dst.info());
242cb93a386Sopenharmony_ci        colorPipeline->append(SkRasterPipeline::store_f32, &constantColorPtr);
243cb93a386Sopenharmony_ci        colorPipeline->run(0,0,1,1);
244cb93a386Sopenharmony_ci        colorPipeline->reset();
245cb93a386Sopenharmony_ci        colorPipeline->append_constant_color(alloc, constantColor);
246cb93a386Sopenharmony_ci
247cb93a386Sopenharmony_ci        is_opaque = constantColor.fA == 1.0f;
248cb93a386Sopenharmony_ci    }
249cb93a386Sopenharmony_ci
250cb93a386Sopenharmony_ci    // We can strength-reduce SrcOver into Src when opaque.
251cb93a386Sopenharmony_ci    if (is_opaque && blitter->fBlend == SkBlendMode::kSrcOver) {
252cb93a386Sopenharmony_ci        blitter->fBlend = SkBlendMode::kSrc;
253cb93a386Sopenharmony_ci    }
254cb93a386Sopenharmony_ci
255cb93a386Sopenharmony_ci    // When we're drawing a constant color in Src mode, we can sometimes just memset.
256cb93a386Sopenharmony_ci    // (The previous two optimizations help find more opportunities for this one.)
257cb93a386Sopenharmony_ci    if (is_constant && blitter->fBlend == SkBlendMode::kSrc) {
258cb93a386Sopenharmony_ci        // Run our color pipeline all the way through to produce what we'd memset when we can.
259cb93a386Sopenharmony_ci        // Not all blits can memset, so we need to keep colorPipeline too.
260cb93a386Sopenharmony_ci        SkRasterPipeline_<256> p;
261cb93a386Sopenharmony_ci        p.extend(*colorPipeline);
262cb93a386Sopenharmony_ci        p.append_gamut_clamp_if_normalized(dst.info());
263cb93a386Sopenharmony_ci        blitter->fDstPtr = SkRasterPipeline_MemoryCtx{&blitter->fMemsetColor, 0};
264cb93a386Sopenharmony_ci        blitter->append_store(&p);
265cb93a386Sopenharmony_ci        p.run(0,0,1,1);
266cb93a386Sopenharmony_ci
267cb93a386Sopenharmony_ci        switch (blitter->fDst.shiftPerPixel()) {
268cb93a386Sopenharmony_ci            case 0: blitter->fMemset2D = [](SkPixmap* dst, int x,int y, int w,int h, uint64_t c) {
269cb93a386Sopenharmony_ci                void* p = dst->writable_addr(x,y);
270cb93a386Sopenharmony_ci                while (h --> 0) {
271cb93a386Sopenharmony_ci                    memset(p, c, w);
272cb93a386Sopenharmony_ci                    p = SkTAddOffset<void>(p, dst->rowBytes());
273cb93a386Sopenharmony_ci                }
274cb93a386Sopenharmony_ci            }; break;
275cb93a386Sopenharmony_ci
276cb93a386Sopenharmony_ci            case 1: blitter->fMemset2D = [](SkPixmap* dst, int x,int y, int w,int h, uint64_t c) {
277cb93a386Sopenharmony_ci                SkOpts::rect_memset16(dst->writable_addr16(x,y), c, w, dst->rowBytes(), h);
278cb93a386Sopenharmony_ci            }; break;
279cb93a386Sopenharmony_ci
280cb93a386Sopenharmony_ci            case 2: blitter->fMemset2D = [](SkPixmap* dst, int x,int y, int w,int h, uint64_t c) {
281cb93a386Sopenharmony_ci                SkOpts::rect_memset32(dst->writable_addr32(x,y), c, w, dst->rowBytes(), h);
282cb93a386Sopenharmony_ci            }; break;
283cb93a386Sopenharmony_ci
284cb93a386Sopenharmony_ci            case 3: blitter->fMemset2D = [](SkPixmap* dst, int x,int y, int w,int h, uint64_t c) {
285cb93a386Sopenharmony_ci                SkOpts::rect_memset64(dst->writable_addr64(x,y), c, w, dst->rowBytes(), h);
286cb93a386Sopenharmony_ci            }; break;
287cb93a386Sopenharmony_ci
288cb93a386Sopenharmony_ci            // TODO(F32)?
289cb93a386Sopenharmony_ci        }
290cb93a386Sopenharmony_ci    }
291cb93a386Sopenharmony_ci
292cb93a386Sopenharmony_ci    blitter->fDstPtr = SkRasterPipeline_MemoryCtx{
293cb93a386Sopenharmony_ci        blitter->fDst.writable_addr(),
294cb93a386Sopenharmony_ci        blitter->fDst.rowBytesAsPixels(),
295cb93a386Sopenharmony_ci    };
296cb93a386Sopenharmony_ci
297cb93a386Sopenharmony_ci    return blitter;
298cb93a386Sopenharmony_ci}
299cb93a386Sopenharmony_ci
300cb93a386Sopenharmony_civoid SkRasterPipelineBlitter::append_load_dst(SkRasterPipeline* p) const {
301cb93a386Sopenharmony_ci    p->append_load_dst(fDst.info().colorType(), &fDstPtr);
302cb93a386Sopenharmony_ci    if (fDst.info().alphaType() == kUnpremul_SkAlphaType) {
303cb93a386Sopenharmony_ci        p->append(SkRasterPipeline::premul_dst);
304cb93a386Sopenharmony_ci    }
305cb93a386Sopenharmony_ci}
306cb93a386Sopenharmony_ci
307cb93a386Sopenharmony_civoid SkRasterPipelineBlitter::append_store(SkRasterPipeline* p) const {
308cb93a386Sopenharmony_ci    if (fDst.info().alphaType() == kUnpremul_SkAlphaType) {
309cb93a386Sopenharmony_ci        p->append(SkRasterPipeline::unpremul);
310cb93a386Sopenharmony_ci    }
311cb93a386Sopenharmony_ci    p->append_store(fDst.info().colorType(), &fDstPtr);
312cb93a386Sopenharmony_ci}
313cb93a386Sopenharmony_ci
314cb93a386Sopenharmony_civoid SkRasterPipelineBlitter::append_clip_scale(SkRasterPipeline* p) const {
315cb93a386Sopenharmony_ci    if (fClipShaderBuffer) {
316cb93a386Sopenharmony_ci        p->append(SkRasterPipeline::scale_native, fClipShaderBuffer);
317cb93a386Sopenharmony_ci    }
318cb93a386Sopenharmony_ci}
319cb93a386Sopenharmony_ci
320cb93a386Sopenharmony_civoid SkRasterPipelineBlitter::append_clip_lerp(SkRasterPipeline* p) const {
321cb93a386Sopenharmony_ci    if (fClipShaderBuffer) {
322cb93a386Sopenharmony_ci        p->append(SkRasterPipeline::lerp_native, fClipShaderBuffer);
323cb93a386Sopenharmony_ci    }
324cb93a386Sopenharmony_ci}
325cb93a386Sopenharmony_ci
326cb93a386Sopenharmony_civoid SkRasterPipelineBlitter::blitH(int x, int y, int w) {
327cb93a386Sopenharmony_ci    this->blitRect(x,y,w,1);
328cb93a386Sopenharmony_ci}
329cb93a386Sopenharmony_ci
330cb93a386Sopenharmony_civoid SkRasterPipelineBlitter::blitRect(int x, int y, int w, int h) {
331cb93a386Sopenharmony_ci    if (fMemset2D) {
332cb93a386Sopenharmony_ci        fMemset2D(&fDst, x,y, w,h, fMemsetColor);
333cb93a386Sopenharmony_ci        return;
334cb93a386Sopenharmony_ci    }
335cb93a386Sopenharmony_ci
336cb93a386Sopenharmony_ci    if (!fBlitRect) {
337cb93a386Sopenharmony_ci        SkRasterPipeline p(fAlloc);
338cb93a386Sopenharmony_ci        p.extend(fColorPipeline);
339cb93a386Sopenharmony_ci        p.append_gamut_clamp_if_normalized(fDst.info());
340cb93a386Sopenharmony_ci        if (fBlend == SkBlendMode::kSrcOver
341cb93a386Sopenharmony_ci                && (fDst.info().colorType() == kRGBA_8888_SkColorType ||
342cb93a386Sopenharmony_ci                    fDst.info().colorType() == kBGRA_8888_SkColorType)
343cb93a386Sopenharmony_ci                && !fDst.colorSpace()
344cb93a386Sopenharmony_ci                && fDst.info().alphaType() != kUnpremul_SkAlphaType
345cb93a386Sopenharmony_ci                && fDitherRate == 0.0f) {
346cb93a386Sopenharmony_ci            if (fDst.info().colorType() == kBGRA_8888_SkColorType) {
347cb93a386Sopenharmony_ci                p.append(SkRasterPipeline::swap_rb);
348cb93a386Sopenharmony_ci            }
349cb93a386Sopenharmony_ci            this->append_clip_scale(&p);
350cb93a386Sopenharmony_ci            p.append(SkRasterPipeline::srcover_rgba_8888, &fDstPtr);
351cb93a386Sopenharmony_ci        } else {
352cb93a386Sopenharmony_ci            if (fBlend != SkBlendMode::kSrc) {
353cb93a386Sopenharmony_ci                this->append_load_dst(&p);
354cb93a386Sopenharmony_ci                SkBlendMode_AppendStages(fBlend, &p);
355cb93a386Sopenharmony_ci                this->append_clip_lerp(&p);
356cb93a386Sopenharmony_ci            } else if (fClipShaderBuffer) {
357cb93a386Sopenharmony_ci                this->append_load_dst(&p);
358cb93a386Sopenharmony_ci                this->append_clip_lerp(&p);
359cb93a386Sopenharmony_ci            }
360cb93a386Sopenharmony_ci            this->append_store(&p);
361cb93a386Sopenharmony_ci        }
362cb93a386Sopenharmony_ci        fBlitRect = p.compile();
363cb93a386Sopenharmony_ci    }
364cb93a386Sopenharmony_ci
365cb93a386Sopenharmony_ci    fBlitRect(x,y,w,h);
366cb93a386Sopenharmony_ci}
367cb93a386Sopenharmony_ci
368cb93a386Sopenharmony_civoid SkRasterPipelineBlitter::blitAntiH(int x, int y, const SkAlpha aa[], const int16_t runs[]) {
369cb93a386Sopenharmony_ci    if (!fBlitAntiH) {
370cb93a386Sopenharmony_ci        SkRasterPipeline p(fAlloc);
371cb93a386Sopenharmony_ci        p.extend(fColorPipeline);
372cb93a386Sopenharmony_ci        p.append_gamut_clamp_if_normalized(fDst.info());
373cb93a386Sopenharmony_ci        if (SkBlendMode_ShouldPreScaleCoverage(fBlend, /*rgb_coverage=*/false)) {
374cb93a386Sopenharmony_ci            p.append(SkRasterPipeline::scale_1_float, &fCurrentCoverage);
375cb93a386Sopenharmony_ci            this->append_clip_scale(&p);
376cb93a386Sopenharmony_ci            this->append_load_dst(&p);
377cb93a386Sopenharmony_ci            SkBlendMode_AppendStages(fBlend, &p);
378cb93a386Sopenharmony_ci        } else {
379cb93a386Sopenharmony_ci            this->append_load_dst(&p);
380cb93a386Sopenharmony_ci            SkBlendMode_AppendStages(fBlend, &p);
381cb93a386Sopenharmony_ci            p.append(SkRasterPipeline::lerp_1_float, &fCurrentCoverage);
382cb93a386Sopenharmony_ci            this->append_clip_lerp(&p);
383cb93a386Sopenharmony_ci        }
384cb93a386Sopenharmony_ci
385cb93a386Sopenharmony_ci        this->append_store(&p);
386cb93a386Sopenharmony_ci        fBlitAntiH = p.compile();
387cb93a386Sopenharmony_ci    }
388cb93a386Sopenharmony_ci
389cb93a386Sopenharmony_ci    for (int16_t run = *runs; run > 0; run = *runs) {
390cb93a386Sopenharmony_ci        switch (*aa) {
391cb93a386Sopenharmony_ci            case 0x00:                       break;
392cb93a386Sopenharmony_ci            case 0xff: this->blitH(x,y,run); break;
393cb93a386Sopenharmony_ci            default:
394cb93a386Sopenharmony_ci                fCurrentCoverage = *aa * (1/255.0f);
395cb93a386Sopenharmony_ci                fBlitAntiH(x,y,run,1);
396cb93a386Sopenharmony_ci        }
397cb93a386Sopenharmony_ci        x    += run;
398cb93a386Sopenharmony_ci        runs += run;
399cb93a386Sopenharmony_ci        aa   += run;
400cb93a386Sopenharmony_ci    }
401cb93a386Sopenharmony_ci}
402cb93a386Sopenharmony_ci
403cb93a386Sopenharmony_civoid SkRasterPipelineBlitter::blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) {
404cb93a386Sopenharmony_ci    SkIRect clip = {x,y, x+2,y+1};
405cb93a386Sopenharmony_ci    uint8_t coverage[] = { (uint8_t)a0, (uint8_t)a1 };
406cb93a386Sopenharmony_ci
407cb93a386Sopenharmony_ci    SkMask mask;
408cb93a386Sopenharmony_ci    mask.fImage    = coverage;
409cb93a386Sopenharmony_ci    mask.fBounds   = clip;
410cb93a386Sopenharmony_ci    mask.fRowBytes = 2;
411cb93a386Sopenharmony_ci    mask.fFormat   = SkMask::kA8_Format;
412cb93a386Sopenharmony_ci
413cb93a386Sopenharmony_ci    this->blitMask(mask, clip);
414cb93a386Sopenharmony_ci}
415cb93a386Sopenharmony_ci
416cb93a386Sopenharmony_civoid SkRasterPipelineBlitter::blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) {
417cb93a386Sopenharmony_ci    SkIRect clip = {x,y, x+1,y+2};
418cb93a386Sopenharmony_ci    uint8_t coverage[] = { (uint8_t)a0, (uint8_t)a1 };
419cb93a386Sopenharmony_ci
420cb93a386Sopenharmony_ci    SkMask mask;
421cb93a386Sopenharmony_ci    mask.fImage    = coverage;
422cb93a386Sopenharmony_ci    mask.fBounds   = clip;
423cb93a386Sopenharmony_ci    mask.fRowBytes = 1;
424cb93a386Sopenharmony_ci    mask.fFormat   = SkMask::kA8_Format;
425cb93a386Sopenharmony_ci
426cb93a386Sopenharmony_ci    this->blitMask(mask, clip);
427cb93a386Sopenharmony_ci}
428cb93a386Sopenharmony_ci
429cb93a386Sopenharmony_civoid SkRasterPipelineBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
430cb93a386Sopenharmony_ci    SkIRect clip = {x,y, x+1,y+height};
431cb93a386Sopenharmony_ci
432cb93a386Sopenharmony_ci    SkMask mask;
433cb93a386Sopenharmony_ci    mask.fImage    = &alpha;
434cb93a386Sopenharmony_ci    mask.fBounds   = clip;
435cb93a386Sopenharmony_ci    mask.fRowBytes = 0;     // so we reuse the 1 "row" for all of height
436cb93a386Sopenharmony_ci    mask.fFormat   = SkMask::kA8_Format;
437cb93a386Sopenharmony_ci
438cb93a386Sopenharmony_ci    this->blitMask(mask, clip);
439cb93a386Sopenharmony_ci}
440cb93a386Sopenharmony_ci
441cb93a386Sopenharmony_civoid SkRasterPipelineBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
442cb93a386Sopenharmony_ci    if (mask.fFormat == SkMask::kBW_Format) {
443cb93a386Sopenharmony_ci        // TODO: native BW masks?
444cb93a386Sopenharmony_ci        return INHERITED::blitMask(mask, clip);
445cb93a386Sopenharmony_ci    }
446cb93a386Sopenharmony_ci
447cb93a386Sopenharmony_ci    // ARGB and SDF masks shouldn't make it here.
448cb93a386Sopenharmony_ci    SkASSERT(mask.fFormat == SkMask::kA8_Format
449cb93a386Sopenharmony_ci          || mask.fFormat == SkMask::kLCD16_Format
450cb93a386Sopenharmony_ci          || mask.fFormat == SkMask::k3D_Format);
451cb93a386Sopenharmony_ci
452cb93a386Sopenharmony_ci    auto extract_mask_plane = [&mask](int plane, SkRasterPipeline_MemoryCtx* ctx) {
453cb93a386Sopenharmony_ci        // LCD is 16-bit per pixel; A8 and 3D are 8-bit per pixel.
454cb93a386Sopenharmony_ci        size_t bpp = mask.fFormat == SkMask::kLCD16_Format ? 2 : 1;
455cb93a386Sopenharmony_ci
456cb93a386Sopenharmony_ci        // Select the right mask plane.  Usually plane == 0 and this is just mask.fImage.
457cb93a386Sopenharmony_ci        auto ptr = (uintptr_t)mask.fImage
458cb93a386Sopenharmony_ci                 + plane * mask.computeImageSize();
459cb93a386Sopenharmony_ci
460cb93a386Sopenharmony_ci        // Update ctx to point "into" this current mask, but lined up with fDstPtr at (0,0).
461cb93a386Sopenharmony_ci        // This sort of trickery upsets UBSAN (pointer-overflow) so our ptr must be a uintptr_t.
462cb93a386Sopenharmony_ci        // mask.fRowBytes is a uint32_t, which would break our addressing math on 64-bit builds.
463cb93a386Sopenharmony_ci        size_t rowBytes = mask.fRowBytes;
464cb93a386Sopenharmony_ci        ctx->stride = rowBytes / bpp;
465cb93a386Sopenharmony_ci        ctx->pixels = (void*)(ptr - mask.fBounds.left() * bpp
466cb93a386Sopenharmony_ci                                  - mask.fBounds.top()  * rowBytes);
467cb93a386Sopenharmony_ci    };
468cb93a386Sopenharmony_ci
469cb93a386Sopenharmony_ci    extract_mask_plane(0, &fMaskPtr);
470cb93a386Sopenharmony_ci    if (mask.fFormat == SkMask::k3D_Format) {
471cb93a386Sopenharmony_ci        extract_mask_plane(1, &fEmbossCtx.mul);
472cb93a386Sopenharmony_ci        extract_mask_plane(2, &fEmbossCtx.add);
473cb93a386Sopenharmony_ci    }
474cb93a386Sopenharmony_ci
475cb93a386Sopenharmony_ci    // Lazily build whichever pipeline we need, specialized for each mask format.
476cb93a386Sopenharmony_ci    if (mask.fFormat == SkMask::kA8_Format && !fBlitMaskA8) {
477cb93a386Sopenharmony_ci        SkRasterPipeline p(fAlloc);
478cb93a386Sopenharmony_ci        p.extend(fColorPipeline);
479cb93a386Sopenharmony_ci        p.append_gamut_clamp_if_normalized(fDst.info());
480cb93a386Sopenharmony_ci        if (SkBlendMode_ShouldPreScaleCoverage(fBlend, /*rgb_coverage=*/false)) {
481cb93a386Sopenharmony_ci            p.append(SkRasterPipeline::scale_u8, &fMaskPtr);
482cb93a386Sopenharmony_ci            this->append_clip_scale(&p);
483cb93a386Sopenharmony_ci            this->append_load_dst(&p);
484cb93a386Sopenharmony_ci            SkBlendMode_AppendStages(fBlend, &p);
485cb93a386Sopenharmony_ci        } else {
486cb93a386Sopenharmony_ci            this->append_load_dst(&p);
487cb93a386Sopenharmony_ci            SkBlendMode_AppendStages(fBlend, &p);
488cb93a386Sopenharmony_ci            p.append(SkRasterPipeline::lerp_u8, &fMaskPtr);
489cb93a386Sopenharmony_ci            this->append_clip_lerp(&p);
490cb93a386Sopenharmony_ci        }
491cb93a386Sopenharmony_ci        this->append_store(&p);
492cb93a386Sopenharmony_ci        fBlitMaskA8 = p.compile();
493cb93a386Sopenharmony_ci    }
494cb93a386Sopenharmony_ci    if (mask.fFormat == SkMask::kLCD16_Format && !fBlitMaskLCD16) {
495cb93a386Sopenharmony_ci        SkRasterPipeline p(fAlloc);
496cb93a386Sopenharmony_ci        p.extend(fColorPipeline);
497cb93a386Sopenharmony_ci        p.append_gamut_clamp_if_normalized(fDst.info());
498cb93a386Sopenharmony_ci        if (SkBlendMode_ShouldPreScaleCoverage(fBlend, /*rgb_coverage=*/true)) {
499cb93a386Sopenharmony_ci            // Somewhat unusually, scale_565 needs dst loaded first.
500cb93a386Sopenharmony_ci            this->append_load_dst(&p);
501cb93a386Sopenharmony_ci            p.append(SkRasterPipeline::scale_565, &fMaskPtr);
502cb93a386Sopenharmony_ci            this->append_clip_scale(&p);
503cb93a386Sopenharmony_ci            SkBlendMode_AppendStages(fBlend, &p);
504cb93a386Sopenharmony_ci        } else {
505cb93a386Sopenharmony_ci            this->append_load_dst(&p);
506cb93a386Sopenharmony_ci            SkBlendMode_AppendStages(fBlend, &p);
507cb93a386Sopenharmony_ci            p.append(SkRasterPipeline::lerp_565, &fMaskPtr);
508cb93a386Sopenharmony_ci            this->append_clip_lerp(&p);
509cb93a386Sopenharmony_ci        }
510cb93a386Sopenharmony_ci        this->append_store(&p);
511cb93a386Sopenharmony_ci        fBlitMaskLCD16 = p.compile();
512cb93a386Sopenharmony_ci    }
513cb93a386Sopenharmony_ci    if (mask.fFormat == SkMask::k3D_Format && !fBlitMask3D) {
514cb93a386Sopenharmony_ci        SkRasterPipeline p(fAlloc);
515cb93a386Sopenharmony_ci        p.extend(fColorPipeline);
516cb93a386Sopenharmony_ci        // This bit is where we differ from kA8_Format:
517cb93a386Sopenharmony_ci        p.append(SkRasterPipeline::emboss, &fEmbossCtx);
518cb93a386Sopenharmony_ci        // Now onward just as kA8.
519cb93a386Sopenharmony_ci        p.append_gamut_clamp_if_normalized(fDst.info());
520cb93a386Sopenharmony_ci        if (SkBlendMode_ShouldPreScaleCoverage(fBlend, /*rgb_coverage=*/false)) {
521cb93a386Sopenharmony_ci            p.append(SkRasterPipeline::scale_u8, &fMaskPtr);
522cb93a386Sopenharmony_ci            this->append_clip_scale(&p);
523cb93a386Sopenharmony_ci            this->append_load_dst(&p);
524cb93a386Sopenharmony_ci            SkBlendMode_AppendStages(fBlend, &p);
525cb93a386Sopenharmony_ci        } else {
526cb93a386Sopenharmony_ci            this->append_load_dst(&p);
527cb93a386Sopenharmony_ci            SkBlendMode_AppendStages(fBlend, &p);
528cb93a386Sopenharmony_ci            p.append(SkRasterPipeline::lerp_u8, &fMaskPtr);
529cb93a386Sopenharmony_ci            this->append_clip_lerp(&p);
530cb93a386Sopenharmony_ci        }
531cb93a386Sopenharmony_ci        this->append_store(&p);
532cb93a386Sopenharmony_ci        fBlitMask3D = p.compile();
533cb93a386Sopenharmony_ci    }
534cb93a386Sopenharmony_ci
535cb93a386Sopenharmony_ci    std::function<void(size_t,size_t,size_t,size_t)>* blitter = nullptr;
536cb93a386Sopenharmony_ci    switch (mask.fFormat) {
537cb93a386Sopenharmony_ci        case SkMask::kA8_Format:    blitter = &fBlitMaskA8;    break;
538cb93a386Sopenharmony_ci        case SkMask::kLCD16_Format: blitter = &fBlitMaskLCD16; break;
539cb93a386Sopenharmony_ci        case SkMask::k3D_Format:    blitter = &fBlitMask3D;    break;
540cb93a386Sopenharmony_ci        default:
541cb93a386Sopenharmony_ci            SkASSERT(false);
542cb93a386Sopenharmony_ci            return;
543cb93a386Sopenharmony_ci    }
544cb93a386Sopenharmony_ci
545cb93a386Sopenharmony_ci    SkASSERT(blitter);
546cb93a386Sopenharmony_ci    (*blitter)(clip.left(),clip.top(), clip.width(),clip.height());
547cb93a386Sopenharmony_ci}
548