1395eabeb0e72334c45324874c6e009b54634df21reed/*
2395eabeb0e72334c45324874c6e009b54634df21reed * Copyright 2016 Google Inc.
3395eabeb0e72334c45324874c6e009b54634df21reed *
4395eabeb0e72334c45324874c6e009b54634df21reed * Use of this source code is governed by a BSD-style license that can be
5395eabeb0e72334c45324874c6e009b54634df21reed * found in the LICENSE file.
6395eabeb0e72334c45324874c6e009b54634df21reed */
7395eabeb0e72334c45324874c6e009b54634df21reed
8395eabeb0e72334c45324874c6e009b54634df21reed#include "SkCoreBlitters.h"
9395eabeb0e72334c45324874c6e009b54634df21reed#include "SkColorPriv.h"
10395eabeb0e72334c45324874c6e009b54634df21reed#include "SkShader.h"
11395eabeb0e72334c45324874c6e009b54634df21reed#include "SkUtils.h"
12395eabeb0e72334c45324874c6e009b54634df21reed#include "SkXfermode.h"
13395eabeb0e72334c45324874c6e009b54634df21reed#include "SkBlitMask.h"
14a34be68a7eff0ae475b194f8a29975460cf3e456reed#include "SkTemplates.h"
15dd9ffea9ce051a49dbc6544e6aa3cb68fe987f47reed#include "SkPM4f.h"
16395eabeb0e72334c45324874c6e009b54634df21reed
17a34be68a7eff0ae475b194f8a29975460cf3e456reedtemplate <typename State> class SkState_Blitter : public SkRasterBlitter {
18a34be68a7eff0ae475b194f8a29975460cf3e456reed    typedef SkRasterBlitter INHERITED;
19a34be68a7eff0ae475b194f8a29975460cf3e456reed    State fState;
20395eabeb0e72334c45324874c6e009b54634df21reed
21a34be68a7eff0ae475b194f8a29975460cf3e456reedpublic:
22a34be68a7eff0ae475b194f8a29975460cf3e456reed    SkState_Blitter(const SkPixmap& device, const SkPaint& paint)
23a34be68a7eff0ae475b194f8a29975460cf3e456reed        : INHERITED(device)
24a34be68a7eff0ae475b194f8a29975460cf3e456reed        , fState(device.info(), paint, nullptr)
25a34be68a7eff0ae475b194f8a29975460cf3e456reed    {}
26395eabeb0e72334c45324874c6e009b54634df21reed
27a34be68a7eff0ae475b194f8a29975460cf3e456reed    void blitH(int x, int y, int width) override {
28a34be68a7eff0ae475b194f8a29975460cf3e456reed        SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
29a34be68a7eff0ae475b194f8a29975460cf3e456reed
308f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed        fState.fProc1(fState.fXfer, State::WritableAddr(fDevice, x, y),
318f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed                      &fState.fPM4f, width, nullptr);
32395eabeb0e72334c45324874c6e009b54634df21reed    }
33a34be68a7eff0ae475b194f8a29975460cf3e456reed
34a34be68a7eff0ae475b194f8a29975460cf3e456reed    void blitV(int x, int y, int height, SkAlpha alpha) override {
35a34be68a7eff0ae475b194f8a29975460cf3e456reed        SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height());
36a34be68a7eff0ae475b194f8a29975460cf3e456reed
37a34be68a7eff0ae475b194f8a29975460cf3e456reed        typename State::DstType* device = State::WritableAddr(fDevice, x, y);
38a34be68a7eff0ae475b194f8a29975460cf3e456reed        size_t                 deviceRB = fDevice.rowBytes();
39a34be68a7eff0ae475b194f8a29975460cf3e456reed
40a34be68a7eff0ae475b194f8a29975460cf3e456reed        for (int i = 0; i < height; ++i) {
418f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed            fState.fProc1(fState.fXfer, device, &fState.fPM4f, 1, &alpha);
42a34be68a7eff0ae475b194f8a29975460cf3e456reed            device = (typename State::DstType*)((char*)device + deviceRB);
43a34be68a7eff0ae475b194f8a29975460cf3e456reed        }
44395eabeb0e72334c45324874c6e009b54634df21reed    }
45395eabeb0e72334c45324874c6e009b54634df21reed
46a34be68a7eff0ae475b194f8a29975460cf3e456reed    void blitRect(int x, int y, int width, int height) override {
47a34be68a7eff0ae475b194f8a29975460cf3e456reed        SkASSERT(x >= 0 && y >= 0 &&
48a34be68a7eff0ae475b194f8a29975460cf3e456reed                 x + width <= fDevice.width() && y + height <= fDevice.height());
49a34be68a7eff0ae475b194f8a29975460cf3e456reed
50a34be68a7eff0ae475b194f8a29975460cf3e456reed        typename State::DstType* device = State::WritableAddr(fDevice, x, y);
51a34be68a7eff0ae475b194f8a29975460cf3e456reed        size_t        deviceRB = fDevice.rowBytes();
52a34be68a7eff0ae475b194f8a29975460cf3e456reed
53a34be68a7eff0ae475b194f8a29975460cf3e456reed        do {
548f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed            fState.fProc1(fState.fXfer, device, &fState.fPM4f, width, nullptr);
55a34be68a7eff0ae475b194f8a29975460cf3e456reed            y += 1;
56a34be68a7eff0ae475b194f8a29975460cf3e456reed            device = (typename State::DstType*)((char*)device + deviceRB);
57a34be68a7eff0ae475b194f8a29975460cf3e456reed        } while (--height > 0);
58a34be68a7eff0ae475b194f8a29975460cf3e456reed    }
59395eabeb0e72334c45324874c6e009b54634df21reed
60a34be68a7eff0ae475b194f8a29975460cf3e456reed    void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) override {
61a34be68a7eff0ae475b194f8a29975460cf3e456reed        typename State::DstType* device = State::WritableAddr(fDevice, x, y);
62a34be68a7eff0ae475b194f8a29975460cf3e456reed
63a34be68a7eff0ae475b194f8a29975460cf3e456reed        for (;;) {
64a34be68a7eff0ae475b194f8a29975460cf3e456reed            int count = *runs;
65a34be68a7eff0ae475b194f8a29975460cf3e456reed            if (count <= 0) {
66a34be68a7eff0ae475b194f8a29975460cf3e456reed                break;
67a34be68a7eff0ae475b194f8a29975460cf3e456reed            }
68a34be68a7eff0ae475b194f8a29975460cf3e456reed            int aa = *antialias;
69a34be68a7eff0ae475b194f8a29975460cf3e456reed            if (aa) {
70a34be68a7eff0ae475b194f8a29975460cf3e456reed                if (aa == 255) {
718f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed                    fState.fProc1(fState.fXfer, device, &fState.fPM4f, count, nullptr);
72a34be68a7eff0ae475b194f8a29975460cf3e456reed                } else {
73a34be68a7eff0ae475b194f8a29975460cf3e456reed                    for (int i = 0; i < count; ++i) {
748f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed                        fState.fProc1(fState.fXfer, &device[i], &fState.fPM4f, 1, antialias);
75a34be68a7eff0ae475b194f8a29975460cf3e456reed                    }
76a34be68a7eff0ae475b194f8a29975460cf3e456reed                }
77a34be68a7eff0ae475b194f8a29975460cf3e456reed            }
78a34be68a7eff0ae475b194f8a29975460cf3e456reed            device += count;
79a34be68a7eff0ae475b194f8a29975460cf3e456reed            runs += count;
80a34be68a7eff0ae475b194f8a29975460cf3e456reed            antialias += count;
81a34be68a7eff0ae475b194f8a29975460cf3e456reed            x += count;
82a34be68a7eff0ae475b194f8a29975460cf3e456reed        }
83a34be68a7eff0ae475b194f8a29975460cf3e456reed    }
84395eabeb0e72334c45324874c6e009b54634df21reed
854528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed    void blitLCDMask(const SkMask& mask, const SkIRect& clip) {
864528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        auto proc = fState.getLCDProc(SkXfermode::kSrcIsSingle_LCDFlag);
874528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed
884528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        const int x = clip.fLeft;
894528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        const int width = clip.width();
904528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        const int y = clip.fTop;
914528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        const int height = clip.height();
924528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed
934528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        typename State::DstType* device = State::WritableAddr(fDevice, x, y);
944528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        const size_t dstRB = fDevice.rowBytes();
954528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        const uint16_t* maskRow = (const uint16_t*)mask.getAddr(x, y);
964528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        const size_t maskRB = mask.fRowBytes;
974528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed
984528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        for (int i = 0; i < height; ++i) {
994528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed            proc(device, &fState.fPM4f, width, maskRow);
1004528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed            device = (typename State::DstType*)((char*)device + dstRB);
1014528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed            maskRow = (const uint16_t*)((const char*)maskRow + maskRB);
1024528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        }
1034528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed    }
1044528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed
105a34be68a7eff0ae475b194f8a29975460cf3e456reed    void blitMask(const SkMask& mask, const SkIRect& clip) override {
1064528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        if (SkMask::kLCD16_Format == mask.fFormat) {
1074528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed            this->blitLCDMask(mask, clip);
1084528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed            return;
1094528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        }
110a34be68a7eff0ae475b194f8a29975460cf3e456reed        if (SkMask::kA8_Format != mask.fFormat) {
111a34be68a7eff0ae475b194f8a29975460cf3e456reed            this->INHERITED::blitMask(mask, clip);
112a34be68a7eff0ae475b194f8a29975460cf3e456reed            return;
113a34be68a7eff0ae475b194f8a29975460cf3e456reed        }
114a34be68a7eff0ae475b194f8a29975460cf3e456reed
115a34be68a7eff0ae475b194f8a29975460cf3e456reed        SkASSERT(mask.fBounds.contains(clip));
116a34be68a7eff0ae475b194f8a29975460cf3e456reed
117a34be68a7eff0ae475b194f8a29975460cf3e456reed        const int x = clip.fLeft;
118a34be68a7eff0ae475b194f8a29975460cf3e456reed        const int width = clip.width();
119a34be68a7eff0ae475b194f8a29975460cf3e456reed        const int y = clip.fTop;
120a34be68a7eff0ae475b194f8a29975460cf3e456reed        const int height = clip.height();
121a34be68a7eff0ae475b194f8a29975460cf3e456reed
122a34be68a7eff0ae475b194f8a29975460cf3e456reed        typename State::DstType* device = State::WritableAddr(fDevice, x, y);
123a34be68a7eff0ae475b194f8a29975460cf3e456reed        const size_t dstRB = fDevice.rowBytes();
124a34be68a7eff0ae475b194f8a29975460cf3e456reed        const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y);
125a34be68a7eff0ae475b194f8a29975460cf3e456reed        const size_t maskRB = mask.fRowBytes;
126a34be68a7eff0ae475b194f8a29975460cf3e456reed
127a34be68a7eff0ae475b194f8a29975460cf3e456reed        for (int i = 0; i < height; ++i) {
1288f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed            fState.fProc1(fState.fXfer, device, &fState.fPM4f, width, maskRow);
129a34be68a7eff0ae475b194f8a29975460cf3e456reed            device = (typename State::DstType*)((char*)device + dstRB);
130a34be68a7eff0ae475b194f8a29975460cf3e456reed            maskRow += maskRB;
131a34be68a7eff0ae475b194f8a29975460cf3e456reed        }
132a34be68a7eff0ae475b194f8a29975460cf3e456reed    }
133a34be68a7eff0ae475b194f8a29975460cf3e456reed};
134395eabeb0e72334c45324874c6e009b54634df21reed
135a34be68a7eff0ae475b194f8a29975460cf3e456reed///////////////////////////////////////////////////////////////////////////////////////////////////
136395eabeb0e72334c45324874c6e009b54634df21reed
137a34be68a7eff0ae475b194f8a29975460cf3e456reedtemplate <typename State> class SkState_Shader_Blitter : public SkShaderBlitter {
138a34be68a7eff0ae475b194f8a29975460cf3e456reedpublic:
139a34be68a7eff0ae475b194f8a29975460cf3e456reed    SkState_Shader_Blitter(const SkPixmap& device, const SkPaint& paint,
140a34be68a7eff0ae475b194f8a29975460cf3e456reed                           SkShader::Context* shaderContext)
141a34be68a7eff0ae475b194f8a29975460cf3e456reed        : INHERITED(device, paint, shaderContext)
142a34be68a7eff0ae475b194f8a29975460cf3e456reed        , fState(device.info(), paint, shaderContext)
143a34be68a7eff0ae475b194f8a29975460cf3e456reed    {}
144a34be68a7eff0ae475b194f8a29975460cf3e456reed
145a34be68a7eff0ae475b194f8a29975460cf3e456reed    void blitH(int x, int y, int width) override {
146a34be68a7eff0ae475b194f8a29975460cf3e456reed        SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
147a34be68a7eff0ae475b194f8a29975460cf3e456reed
148a34be68a7eff0ae475b194f8a29975460cf3e456reed        typename State::DstType* device = State::WritableAddr(fDevice, x, y);
149a34be68a7eff0ae475b194f8a29975460cf3e456reed        fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width);
1508f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed        fState.fProcN(fState.fXfer, device, fState.fBuffer, width, nullptr);
151a34be68a7eff0ae475b194f8a29975460cf3e456reed    }
152395eabeb0e72334c45324874c6e009b54634df21reed
153a34be68a7eff0ae475b194f8a29975460cf3e456reed    void blitV(int x, int y, int height, SkAlpha alpha) override {
154a34be68a7eff0ae475b194f8a29975460cf3e456reed        SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height());
155a34be68a7eff0ae475b194f8a29975460cf3e456reed
156a34be68a7eff0ae475b194f8a29975460cf3e456reed        typename State::DstType* device = State::WritableAddr(fDevice, x, y);
157a34be68a7eff0ae475b194f8a29975460cf3e456reed        size_t      deviceRB = fDevice.rowBytes();
158a34be68a7eff0ae475b194f8a29975460cf3e456reed        const int   bottom = y + height;
159a34be68a7eff0ae475b194f8a29975460cf3e456reed
160a34be68a7eff0ae475b194f8a29975460cf3e456reed        if (fConstInY) {
161a34be68a7eff0ae475b194f8a29975460cf3e456reed            fShaderContext->shadeSpan4f(x, y, fState.fBuffer, 1);
162a34be68a7eff0ae475b194f8a29975460cf3e456reed        }
163a34be68a7eff0ae475b194f8a29975460cf3e456reed        for (; y < bottom; ++y) {
164a34be68a7eff0ae475b194f8a29975460cf3e456reed            if (!fConstInY) {
165a34be68a7eff0ae475b194f8a29975460cf3e456reed                fShaderContext->shadeSpan4f(x, y, fState.fBuffer, 1);
166a34be68a7eff0ae475b194f8a29975460cf3e456reed            }
1678f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed            fState.fProcN(fState.fXfer, device, fState.fBuffer, 1, &alpha);
168a34be68a7eff0ae475b194f8a29975460cf3e456reed            device = (typename State::DstType*)((char*)device + deviceRB);
169a34be68a7eff0ae475b194f8a29975460cf3e456reed        }
170a34be68a7eff0ae475b194f8a29975460cf3e456reed    }
171395eabeb0e72334c45324874c6e009b54634df21reed
172a34be68a7eff0ae475b194f8a29975460cf3e456reed    void blitRect(int x, int y, int width, int height) override {
173a34be68a7eff0ae475b194f8a29975460cf3e456reed        SkASSERT(x >= 0 && y >= 0 &&
174a34be68a7eff0ae475b194f8a29975460cf3e456reed                 x + width <= fDevice.width() && y + height <= fDevice.height());
175a34be68a7eff0ae475b194f8a29975460cf3e456reed
176a34be68a7eff0ae475b194f8a29975460cf3e456reed        typename State::DstType* device = State::WritableAddr(fDevice, x, y);
177a34be68a7eff0ae475b194f8a29975460cf3e456reed        size_t        deviceRB = fDevice.rowBytes();
178a34be68a7eff0ae475b194f8a29975460cf3e456reed        const int       bottom = y + height;
179a34be68a7eff0ae475b194f8a29975460cf3e456reed
180a34be68a7eff0ae475b194f8a29975460cf3e456reed        if (fConstInY) {
181a34be68a7eff0ae475b194f8a29975460cf3e456reed            fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width);
182a34be68a7eff0ae475b194f8a29975460cf3e456reed        }
183a34be68a7eff0ae475b194f8a29975460cf3e456reed        for (; y < bottom; ++y) {
184a34be68a7eff0ae475b194f8a29975460cf3e456reed            if (!fConstInY) {
185a34be68a7eff0ae475b194f8a29975460cf3e456reed                fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width);
186a34be68a7eff0ae475b194f8a29975460cf3e456reed            }
1878f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed            fState.fProcN(fState.fXfer, device, fState.fBuffer, width, nullptr);
188a34be68a7eff0ae475b194f8a29975460cf3e456reed            device = (typename State::DstType*)((char*)device + deviceRB);
189a34be68a7eff0ae475b194f8a29975460cf3e456reed        }
190395eabeb0e72334c45324874c6e009b54634df21reed    }
191395eabeb0e72334c45324874c6e009b54634df21reed
192a34be68a7eff0ae475b194f8a29975460cf3e456reed    void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) override {
193a34be68a7eff0ae475b194f8a29975460cf3e456reed        typename State::DstType* device = State::WritableAddr(fDevice, x, y);
194a34be68a7eff0ae475b194f8a29975460cf3e456reed
195a34be68a7eff0ae475b194f8a29975460cf3e456reed        for (;;) {
196a34be68a7eff0ae475b194f8a29975460cf3e456reed            int count = *runs;
197a34be68a7eff0ae475b194f8a29975460cf3e456reed            if (count <= 0) {
198a34be68a7eff0ae475b194f8a29975460cf3e456reed                break;
199a34be68a7eff0ae475b194f8a29975460cf3e456reed            }
200a34be68a7eff0ae475b194f8a29975460cf3e456reed            int aa = *antialias;
201a34be68a7eff0ae475b194f8a29975460cf3e456reed            if (aa) {
202a34be68a7eff0ae475b194f8a29975460cf3e456reed                fShaderContext->shadeSpan4f(x, y, fState.fBuffer, count);
203a34be68a7eff0ae475b194f8a29975460cf3e456reed                if (aa == 255) {
2048f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed                    fState.fProcN(fState.fXfer, device, fState.fBuffer, count, nullptr);
205a34be68a7eff0ae475b194f8a29975460cf3e456reed                } else {
206a34be68a7eff0ae475b194f8a29975460cf3e456reed                    for (int i = 0; i < count; ++i) {
2078f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed                        fState.fProcN(fState.fXfer, &device[i], &fState.fBuffer[i], 1, antialias);
208a34be68a7eff0ae475b194f8a29975460cf3e456reed                    }
209395eabeb0e72334c45324874c6e009b54634df21reed                }
210395eabeb0e72334c45324874c6e009b54634df21reed            }
211a34be68a7eff0ae475b194f8a29975460cf3e456reed            device += count;
212a34be68a7eff0ae475b194f8a29975460cf3e456reed            runs += count;
213a34be68a7eff0ae475b194f8a29975460cf3e456reed            antialias += count;
214a34be68a7eff0ae475b194f8a29975460cf3e456reed            x += count;
215395eabeb0e72334c45324874c6e009b54634df21reed        }
216395eabeb0e72334c45324874c6e009b54634df21reed    }
217395eabeb0e72334c45324874c6e009b54634df21reed
2184528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed    void blitLCDMask(const SkMask& mask, const SkIRect& clip) {
2194528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        auto proc = fState.getLCDProc(0);
2204528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed
2214528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        const int x = clip.fLeft;
2224528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        const int width = clip.width();
2234528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        int y = clip.fTop;
2244528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed
2254528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        typename State::DstType* device = State::WritableAddr(fDevice, x, y);
2264528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        const size_t deviceRB = fDevice.rowBytes();
2274528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        const uint16_t* maskRow = (const uint16_t*)mask.getAddr(x, y);
2284528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        const size_t maskRB = mask.fRowBytes;
2294528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed
2304528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        if (fConstInY) {
2314528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed            fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width);
2324528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        }
2334528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        for (; y < clip.fBottom; ++y) {
2344528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed            if (!fConstInY) {
2354528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed                fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width);
2364528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed            }
2374528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed            proc(device, fState.fBuffer, width, maskRow);
2384528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed            device = (typename State::DstType*)((char*)device + deviceRB);
2394528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed            maskRow = (const uint16_t*)((const char*)maskRow + maskRB);
2404528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        }
2414528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed    }
2424528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed
243a34be68a7eff0ae475b194f8a29975460cf3e456reed    void blitMask(const SkMask& mask, const SkIRect& clip) override {
2444528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        if (SkMask::kLCD16_Format == mask.fFormat) {
2454528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed            this->blitLCDMask(mask, clip);
2464528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed            return;
2474528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        }
248a34be68a7eff0ae475b194f8a29975460cf3e456reed        if (SkMask::kA8_Format != mask.fFormat) {
249a34be68a7eff0ae475b194f8a29975460cf3e456reed            this->INHERITED::blitMask(mask, clip);
250a34be68a7eff0ae475b194f8a29975460cf3e456reed            return;
251a34be68a7eff0ae475b194f8a29975460cf3e456reed        }
252a34be68a7eff0ae475b194f8a29975460cf3e456reed
253a34be68a7eff0ae475b194f8a29975460cf3e456reed        SkASSERT(mask.fBounds.contains(clip));
254a34be68a7eff0ae475b194f8a29975460cf3e456reed
255a34be68a7eff0ae475b194f8a29975460cf3e456reed        const int x = clip.fLeft;
256a34be68a7eff0ae475b194f8a29975460cf3e456reed        const int width = clip.width();
257a34be68a7eff0ae475b194f8a29975460cf3e456reed        int y = clip.fTop;
258a34be68a7eff0ae475b194f8a29975460cf3e456reed
259a34be68a7eff0ae475b194f8a29975460cf3e456reed        typename State::DstType* device = State::WritableAddr(fDevice, x, y);
260a34be68a7eff0ae475b194f8a29975460cf3e456reed        const size_t deviceRB = fDevice.rowBytes();
261a34be68a7eff0ae475b194f8a29975460cf3e456reed        const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y);
262a34be68a7eff0ae475b194f8a29975460cf3e456reed        const size_t maskRB = mask.fRowBytes;
263a34be68a7eff0ae475b194f8a29975460cf3e456reed
264a34be68a7eff0ae475b194f8a29975460cf3e456reed        if (fConstInY) {
265a34be68a7eff0ae475b194f8a29975460cf3e456reed            fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width);
266a34be68a7eff0ae475b194f8a29975460cf3e456reed        }
267a34be68a7eff0ae475b194f8a29975460cf3e456reed        for (; y < clip.fBottom; ++y) {
268a34be68a7eff0ae475b194f8a29975460cf3e456reed            if (!fConstInY) {
269a34be68a7eff0ae475b194f8a29975460cf3e456reed                fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width);
270a34be68a7eff0ae475b194f8a29975460cf3e456reed            }
2718f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed            fState.fProcN(fState.fXfer, device, fState.fBuffer, width, maskRow);
272a34be68a7eff0ae475b194f8a29975460cf3e456reed            device = (typename State::DstType*)((char*)device + deviceRB);
273a34be68a7eff0ae475b194f8a29975460cf3e456reed            maskRow += maskRB;
274a34be68a7eff0ae475b194f8a29975460cf3e456reed        }
275395eabeb0e72334c45324874c6e009b54634df21reed    }
276a34be68a7eff0ae475b194f8a29975460cf3e456reed
277a34be68a7eff0ae475b194f8a29975460cf3e456reedprivate:
278a34be68a7eff0ae475b194f8a29975460cf3e456reed    State   fState;
279395eabeb0e72334c45324874c6e009b54634df21reed
280a34be68a7eff0ae475b194f8a29975460cf3e456reed    typedef SkShaderBlitter INHERITED;
281a34be68a7eff0ae475b194f8a29975460cf3e456reed};
282395eabeb0e72334c45324874c6e009b54634df21reed
283a34be68a7eff0ae475b194f8a29975460cf3e456reed//////////////////////////////////////////////////////////////////////////////////////
284395eabeb0e72334c45324874c6e009b54634df21reed
285a34be68a7eff0ae475b194f8a29975460cf3e456reedstatic bool is_opaque(const SkPaint& paint, const SkShader::Context* shaderContext) {
286a34be68a7eff0ae475b194f8a29975460cf3e456reed    return shaderContext ? SkToBool(shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag)
287a34be68a7eff0ae475b194f8a29975460cf3e456reed    : 0xFF == paint.getAlpha();
288395eabeb0e72334c45324874c6e009b54634df21reed}
289395eabeb0e72334c45324874c6e009b54634df21reed
2908f7b0b2d809510d4af4e6ff6f731bac78eded6c4reedstruct State4f {
2918f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    State4f(const SkImageInfo& info, const SkPaint& paint, const SkShader::Context* shaderContext) {
2928f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed        fXfer = paint.getXfermode();
2938f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed        if (shaderContext) {
2948f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed            fBuffer.reset(info.width());
2958f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed        } else {
2968f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed            fPM4f = SkColor4f::FromColor(paint.getColor()).premul();
2978f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed        }
2988f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed        fFlags = 0;
2998f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    }
3008f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed
3018f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    SkXfermode*             fXfer;
302a34be68a7eff0ae475b194f8a29975460cf3e456reed    SkPM4f                  fPM4f;
3038f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    SkAutoTMalloc<SkPM4f>   fBuffer;
3048f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    uint32_t                fFlags;
3058f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed};
3068f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed
3078f7b0b2d809510d4af4e6ff6f731bac78eded6c4reedstruct State32 : State4f {
3088f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    typedef uint32_t    DstType;
309a34be68a7eff0ae475b194f8a29975460cf3e456reed
3108f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    SkXfermode::D32Proc fProc1;
3118f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    SkXfermode::D32Proc fProcN;
3128f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed
3138f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    State32(const SkImageInfo& info, const SkPaint& paint, const SkShader::Context* shaderContext)
3148f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed        : State4f(info, paint, shaderContext)
3158f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    {
316a34be68a7eff0ae475b194f8a29975460cf3e456reed        if (is_opaque(paint, shaderContext)) {
3178f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed            fFlags |= SkXfermode::kSrcIsOpaque_D32Flag;
318a34be68a7eff0ae475b194f8a29975460cf3e456reed        }
319a34be68a7eff0ae475b194f8a29975460cf3e456reed        if (info.isSRGB()) {
3208f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed            fFlags |= SkXfermode::kDstIsSRGB_D32Flag;
321a34be68a7eff0ae475b194f8a29975460cf3e456reed        }
3228f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed        fProc1 = SkXfermode::GetD32Proc(fXfer, fFlags | SkXfermode::kSrcIsSingle_D32Flag);
3238f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed        fProcN = SkXfermode::GetD32Proc(fXfer, fFlags);
324a34be68a7eff0ae475b194f8a29975460cf3e456reed    }
325a34be68a7eff0ae475b194f8a29975460cf3e456reed
3264528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed    SkXfermode::LCD32Proc getLCDProc(uint32_t oneOrManyFlag) const {
3274528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        uint32_t flags = fFlags & 1;
3288f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed        if (!(fFlags & SkXfermode::kDstIsSRGB_D32Flag)) {
3294528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed            flags |= SkXfermode::kDstIsLinearInt_LCDFlag;
3304528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        }
3314528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        return SkXfermode::GetLCD32Proc(flags | oneOrManyFlag);
3324528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed    }
3334528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed
334a34be68a7eff0ae475b194f8a29975460cf3e456reed    static DstType* WritableAddr(const SkPixmap& device, int x, int y) {
335a34be68a7eff0ae475b194f8a29975460cf3e456reed        return device.writable_addr32(x, y);
336a34be68a7eff0ae475b194f8a29975460cf3e456reed    }
337a34be68a7eff0ae475b194f8a29975460cf3e456reed};
338395eabeb0e72334c45324874c6e009b54634df21reed
3398f7b0b2d809510d4af4e6ff6f731bac78eded6c4reedstruct State64 : State4f {
3408f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    typedef uint64_t    DstType;
341a34be68a7eff0ae475b194f8a29975460cf3e456reed
3428f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    SkXfermode::D64Proc fProc1;
3438f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    SkXfermode::D64Proc fProcN;
344a34be68a7eff0ae475b194f8a29975460cf3e456reed
3458f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    State64(const SkImageInfo& info, const SkPaint& paint, const SkShader::Context* shaderContext)
3468f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed        : State4f(info, paint, shaderContext)
3478f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    {
348a34be68a7eff0ae475b194f8a29975460cf3e456reed        if (is_opaque(paint, shaderContext)) {
3498f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed            fFlags |= SkXfermode::kSrcIsOpaque_D64Flag;
350a34be68a7eff0ae475b194f8a29975460cf3e456reed        }
351a34be68a7eff0ae475b194f8a29975460cf3e456reed        if (kRGBA_F16_SkColorType == info.colorType()) {
3528f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed            fFlags |= SkXfermode::kDstIsFloat16_D64Flag;
353a34be68a7eff0ae475b194f8a29975460cf3e456reed        }
3548f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed        fProc1 = SkXfermode::GetD64Proc(fXfer, fFlags | SkXfermode::kSrcIsSingle_D64Flag);
3558f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed        fProcN = SkXfermode::GetD64Proc(fXfer, fFlags);
356a34be68a7eff0ae475b194f8a29975460cf3e456reed    }
3578f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed
3584528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed    SkXfermode::LCD64Proc getLCDProc(uint32_t oneOrManyFlag) const {
3594528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        uint32_t flags = fFlags & 1;
3608f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed        if (!(fFlags & SkXfermode::kDstIsFloat16_D64Flag)) {
3614528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed            flags |= SkXfermode::kDstIsLinearInt_LCDFlag;
3624528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        }
3634528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed        return SkXfermode::GetLCD64Proc(flags | oneOrManyFlag);
3644528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed    }
3654528c867c4ba65fdf5cfd6de35ea4c36a16c73f6reed
366a34be68a7eff0ae475b194f8a29975460cf3e456reed    static DstType* WritableAddr(const SkPixmap& device, int x, int y) {
367a34be68a7eff0ae475b194f8a29975460cf3e456reed        return device.writable_addr64(x, y);
368a34be68a7eff0ae475b194f8a29975460cf3e456reed    }
369a34be68a7eff0ae475b194f8a29975460cf3e456reed};
370a34be68a7eff0ae475b194f8a29975460cf3e456reed
371a34be68a7eff0ae475b194f8a29975460cf3e456reedtemplate <typename State> SkBlitter* create(const SkPixmap& device, const SkPaint& paint,
372a34be68a7eff0ae475b194f8a29975460cf3e456reed                                            SkShader::Context* shaderContext,
373a34be68a7eff0ae475b194f8a29975460cf3e456reed                                            SkTBlitterAllocator* allocator) {
374a34be68a7eff0ae475b194f8a29975460cf3e456reed    SkASSERT(allocator != nullptr);
375a34be68a7eff0ae475b194f8a29975460cf3e456reed
376a34be68a7eff0ae475b194f8a29975460cf3e456reed    if (shaderContext) {
377a34be68a7eff0ae475b194f8a29975460cf3e456reed        return allocator->createT<SkState_Shader_Blitter<State>>(device, paint, shaderContext);
378395eabeb0e72334c45324874c6e009b54634df21reed    } else {
379a34be68a7eff0ae475b194f8a29975460cf3e456reed        SkColor color = paint.getColor();
380a34be68a7eff0ae475b194f8a29975460cf3e456reed        if (0 == SkColorGetA(color)) {
381a34be68a7eff0ae475b194f8a29975460cf3e456reed            return nullptr;
382a34be68a7eff0ae475b194f8a29975460cf3e456reed        }
383a34be68a7eff0ae475b194f8a29975460cf3e456reed        return allocator->createT<SkState_Blitter<State>>(device, paint);
384395eabeb0e72334c45324874c6e009b54634df21reed    }
385395eabeb0e72334c45324874c6e009b54634df21reed}
386a34be68a7eff0ae475b194f8a29975460cf3e456reed
387a34be68a7eff0ae475b194f8a29975460cf3e456reedSkBlitter* SkBlitter_ARGB32_Create(const SkPixmap& device, const SkPaint& paint,
388a34be68a7eff0ae475b194f8a29975460cf3e456reed                                   SkShader::Context* shaderContext,
389a34be68a7eff0ae475b194f8a29975460cf3e456reed                                   SkTBlitterAllocator* allocator) {
390a34be68a7eff0ae475b194f8a29975460cf3e456reed    return create<State32>(device, paint, shaderContext, allocator);
391a34be68a7eff0ae475b194f8a29975460cf3e456reed}
392a34be68a7eff0ae475b194f8a29975460cf3e456reed
393a34be68a7eff0ae475b194f8a29975460cf3e456reedSkBlitter* SkBlitter_ARGB64_Create(const SkPixmap& device, const SkPaint& paint,
394a34be68a7eff0ae475b194f8a29975460cf3e456reed                                   SkShader::Context* shaderContext,
395a34be68a7eff0ae475b194f8a29975460cf3e456reed                                   SkTBlitterAllocator* allocator) {
396a34be68a7eff0ae475b194f8a29975460cf3e456reed    return create<State64>(device, paint, shaderContext, allocator);
397a34be68a7eff0ae475b194f8a29975460cf3e456reed}
398