• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "SkCoreBlitters.h"
9 #include "SkColorPriv.h"
10 #include "SkShader.h"
11 #include "SkUtils.h"
12 #include "SkXfermode.h"
13 #include "SkBlitMask.h"
14 #include "SkTemplates.h"
15 #include "SkPM4f.h"
16 
17 template <typename State> class SkState_Blitter : public SkRasterBlitter {
18     typedef SkRasterBlitter INHERITED;
19     State fState;
20 
21 public:
SkState_Blitter(const SkPixmap & device,const SkPaint & paint)22     SkState_Blitter(const SkPixmap& device, const SkPaint& paint)
23         : INHERITED(device)
24         , fState(device.info(), paint, nullptr)
25     {}
26 
blitH(int x,int y,int width)27     void blitH(int x, int y, int width) override {
28         SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
29 
30         fState.fProc1(fState.fXfer, State::WritableAddr(fDevice, x, y),
31                       &fState.fPM4f, width, nullptr);
32     }
33 
blitV(int x,int y,int height,SkAlpha alpha)34     void blitV(int x, int y, int height, SkAlpha alpha) override {
35         SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height());
36 
37         typename State::DstType* device = State::WritableAddr(fDevice, x, y);
38         size_t                 deviceRB = fDevice.rowBytes();
39 
40         for (int i = 0; i < height; ++i) {
41             fState.fProc1(fState.fXfer, device, &fState.fPM4f, 1, &alpha);
42             device = (typename State::DstType*)((char*)device + deviceRB);
43         }
44     }
45 
blitRect(int x,int y,int width,int height)46     void blitRect(int x, int y, int width, int height) override {
47         SkASSERT(x >= 0 && y >= 0 &&
48                  x + width <= fDevice.width() && y + height <= fDevice.height());
49 
50         typename State::DstType* device = State::WritableAddr(fDevice, x, y);
51         size_t        deviceRB = fDevice.rowBytes();
52 
53         do {
54             fState.fProc1(fState.fXfer, device, &fState.fPM4f, width, nullptr);
55             y += 1;
56             device = (typename State::DstType*)((char*)device + deviceRB);
57         } while (--height > 0);
58     }
59 
blitAntiH(int x,int y,const SkAlpha antialias[],const int16_t runs[])60     void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) override {
61         typename State::DstType* device = State::WritableAddr(fDevice, x, y);
62 
63         for (;;) {
64             int count = *runs;
65             if (count <= 0) {
66                 break;
67             }
68             int aa = *antialias;
69             if (aa) {
70                 if (aa == 255) {
71                     fState.fProc1(fState.fXfer, device, &fState.fPM4f, count, nullptr);
72                 } else {
73                     for (int i = 0; i < count; ++i) {
74                         fState.fProc1(fState.fXfer, &device[i], &fState.fPM4f, 1, antialias);
75                     }
76                 }
77             }
78             device += count;
79             runs += count;
80             antialias += count;
81             x += count;
82         }
83     }
84 
blitLCDMask(const SkMask & mask,const SkIRect & clip)85     void blitLCDMask(const SkMask& mask, const SkIRect& clip) {
86         auto proc = fState.getLCDProc(SkXfermode::kSrcIsSingle_LCDFlag);
87 
88         const int x = clip.fLeft;
89         const int width = clip.width();
90         const int y = clip.fTop;
91         const int height = clip.height();
92 
93         typename State::DstType* device = State::WritableAddr(fDevice, x, y);
94         const size_t dstRB = fDevice.rowBytes();
95         const uint16_t* maskRow = (const uint16_t*)mask.getAddr(x, y);
96         const size_t maskRB = mask.fRowBytes;
97 
98         for (int i = 0; i < height; ++i) {
99             proc(device, &fState.fPM4f, width, maskRow);
100             device = (typename State::DstType*)((char*)device + dstRB);
101             maskRow = (const uint16_t*)((const char*)maskRow + maskRB);
102         }
103     }
104 
blitMask(const SkMask & mask,const SkIRect & clip)105     void blitMask(const SkMask& mask, const SkIRect& clip) override {
106         if (SkMask::kLCD16_Format == mask.fFormat) {
107             this->blitLCDMask(mask, clip);
108             return;
109         }
110         if (SkMask::kA8_Format != mask.fFormat) {
111             this->INHERITED::blitMask(mask, clip);
112             return;
113         }
114 
115         SkASSERT(mask.fBounds.contains(clip));
116 
117         const int x = clip.fLeft;
118         const int width = clip.width();
119         const int y = clip.fTop;
120         const int height = clip.height();
121 
122         typename State::DstType* device = State::WritableAddr(fDevice, x, y);
123         const size_t dstRB = fDevice.rowBytes();
124         const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y);
125         const size_t maskRB = mask.fRowBytes;
126 
127         for (int i = 0; i < height; ++i) {
128             fState.fProc1(fState.fXfer, device, &fState.fPM4f, width, maskRow);
129             device = (typename State::DstType*)((char*)device + dstRB);
130             maskRow += maskRB;
131         }
132     }
133 };
134 
135 ///////////////////////////////////////////////////////////////////////////////////////////////////
136 
137 template <typename State> class SkState_Shader_Blitter : public SkShaderBlitter {
138 public:
SkState_Shader_Blitter(const SkPixmap & device,const SkPaint & paint,SkShader::Context * shaderContext)139     SkState_Shader_Blitter(const SkPixmap& device, const SkPaint& paint,
140                            SkShader::Context* shaderContext)
141         : INHERITED(device, paint, shaderContext)
142         , fState(device.info(), paint, shaderContext)
143     {}
144 
blitH(int x,int y,int width)145     void blitH(int x, int y, int width) override {
146         SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
147 
148         typename State::DstType* device = State::WritableAddr(fDevice, x, y);
149         fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width);
150         fState.fProcN(fState.fXfer, device, fState.fBuffer, width, nullptr);
151     }
152 
blitV(int x,int y,int height,SkAlpha alpha)153     void blitV(int x, int y, int height, SkAlpha alpha) override {
154         SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height());
155 
156         typename State::DstType* device = State::WritableAddr(fDevice, x, y);
157         size_t      deviceRB = fDevice.rowBytes();
158         const int   bottom = y + height;
159 
160         if (fConstInY) {
161             fShaderContext->shadeSpan4f(x, y, fState.fBuffer, 1);
162         }
163         for (; y < bottom; ++y) {
164             if (!fConstInY) {
165                 fShaderContext->shadeSpan4f(x, y, fState.fBuffer, 1);
166             }
167             fState.fProcN(fState.fXfer, device, fState.fBuffer, 1, &alpha);
168             device = (typename State::DstType*)((char*)device + deviceRB);
169         }
170     }
171 
blitRect(int x,int y,int width,int height)172     void blitRect(int x, int y, int width, int height) override {
173         SkASSERT(x >= 0 && y >= 0 &&
174                  x + width <= fDevice.width() && y + height <= fDevice.height());
175 
176         typename State::DstType* device = State::WritableAddr(fDevice, x, y);
177         size_t        deviceRB = fDevice.rowBytes();
178         const int       bottom = y + height;
179 
180         if (fConstInY) {
181             fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width);
182         }
183         for (; y < bottom; ++y) {
184             if (!fConstInY) {
185                 fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width);
186             }
187             fState.fProcN(fState.fXfer, device, fState.fBuffer, width, nullptr);
188             device = (typename State::DstType*)((char*)device + deviceRB);
189         }
190     }
191 
blitAntiH(int x,int y,const SkAlpha antialias[],const int16_t runs[])192     void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) override {
193         typename State::DstType* device = State::WritableAddr(fDevice, x, y);
194 
195         for (;;) {
196             int count = *runs;
197             if (count <= 0) {
198                 break;
199             }
200             int aa = *antialias;
201             if (aa) {
202                 fShaderContext->shadeSpan4f(x, y, fState.fBuffer, count);
203                 if (aa == 255) {
204                     fState.fProcN(fState.fXfer, device, fState.fBuffer, count, nullptr);
205                 } else {
206                     for (int i = 0; i < count; ++i) {
207                         fState.fProcN(fState.fXfer, &device[i], &fState.fBuffer[i], 1, antialias);
208                     }
209                 }
210             }
211             device += count;
212             runs += count;
213             antialias += count;
214             x += count;
215         }
216     }
217 
blitLCDMask(const SkMask & mask,const SkIRect & clip)218     void blitLCDMask(const SkMask& mask, const SkIRect& clip) {
219         auto proc = fState.getLCDProc(0);
220 
221         const int x = clip.fLeft;
222         const int width = clip.width();
223         int y = clip.fTop;
224 
225         typename State::DstType* device = State::WritableAddr(fDevice, x, y);
226         const size_t deviceRB = fDevice.rowBytes();
227         const uint16_t* maskRow = (const uint16_t*)mask.getAddr(x, y);
228         const size_t maskRB = mask.fRowBytes;
229 
230         if (fConstInY) {
231             fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width);
232         }
233         for (; y < clip.fBottom; ++y) {
234             if (!fConstInY) {
235                 fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width);
236             }
237             proc(device, fState.fBuffer, width, maskRow);
238             device = (typename State::DstType*)((char*)device + deviceRB);
239             maskRow = (const uint16_t*)((const char*)maskRow + maskRB);
240         }
241     }
242 
blitMask(const SkMask & mask,const SkIRect & clip)243     void blitMask(const SkMask& mask, const SkIRect& clip) override {
244         if (SkMask::kLCD16_Format == mask.fFormat) {
245             this->blitLCDMask(mask, clip);
246             return;
247         }
248         if (SkMask::kA8_Format != mask.fFormat) {
249             this->INHERITED::blitMask(mask, clip);
250             return;
251         }
252 
253         SkASSERT(mask.fBounds.contains(clip));
254 
255         const int x = clip.fLeft;
256         const int width = clip.width();
257         int y = clip.fTop;
258 
259         typename State::DstType* device = State::WritableAddr(fDevice, x, y);
260         const size_t deviceRB = fDevice.rowBytes();
261         const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y);
262         const size_t maskRB = mask.fRowBytes;
263 
264         if (fConstInY) {
265             fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width);
266         }
267         for (; y < clip.fBottom; ++y) {
268             if (!fConstInY) {
269                 fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width);
270             }
271             fState.fProcN(fState.fXfer, device, fState.fBuffer, width, maskRow);
272             device = (typename State::DstType*)((char*)device + deviceRB);
273             maskRow += maskRB;
274         }
275     }
276 
277 private:
278     State   fState;
279 
280     typedef SkShaderBlitter INHERITED;
281 };
282 
283 //////////////////////////////////////////////////////////////////////////////////////
284 
is_opaque(const SkPaint & paint,const SkShader::Context * shaderContext)285 static bool is_opaque(const SkPaint& paint, const SkShader::Context* shaderContext) {
286     return shaderContext ? SkToBool(shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag)
287     : 0xFF == paint.getAlpha();
288 }
289 
290 struct State4f {
State4fState4f291     State4f(const SkImageInfo& info, const SkPaint& paint, const SkShader::Context* shaderContext) {
292         fXfer = paint.getXfermode();
293         if (shaderContext) {
294             fBuffer.reset(info.width());
295         } else {
296             fPM4f = SkColor4f::FromColor(paint.getColor()).premul();
297         }
298         fFlags = 0;
299     }
300 
301     SkXfermode*             fXfer;
302     SkPM4f                  fPM4f;
303     SkAutoTMalloc<SkPM4f>   fBuffer;
304     uint32_t                fFlags;
305 };
306 
307 struct State32 : State4f {
308     typedef uint32_t    DstType;
309 
310     SkXfermode::D32Proc fProc1;
311     SkXfermode::D32Proc fProcN;
312 
State32State32313     State32(const SkImageInfo& info, const SkPaint& paint, const SkShader::Context* shaderContext)
314         : State4f(info, paint, shaderContext)
315     {
316         if (is_opaque(paint, shaderContext)) {
317             fFlags |= SkXfermode::kSrcIsOpaque_D32Flag;
318         }
319         if (info.isSRGB()) {
320             fFlags |= SkXfermode::kDstIsSRGB_D32Flag;
321         }
322         fProc1 = SkXfermode::GetD32Proc(fXfer, fFlags | SkXfermode::kSrcIsSingle_D32Flag);
323         fProcN = SkXfermode::GetD32Proc(fXfer, fFlags);
324     }
325 
getLCDProcState32326     SkXfermode::LCD32Proc getLCDProc(uint32_t oneOrManyFlag) const {
327         uint32_t flags = fFlags & 1;
328         if (!(fFlags & SkXfermode::kDstIsSRGB_D32Flag)) {
329             flags |= SkXfermode::kDstIsLinearInt_LCDFlag;
330         }
331         return SkXfermode::GetLCD32Proc(flags | oneOrManyFlag);
332     }
333 
WritableAddrState32334     static DstType* WritableAddr(const SkPixmap& device, int x, int y) {
335         return device.writable_addr32(x, y);
336     }
337 };
338 
339 struct State64 : State4f {
340     typedef uint64_t    DstType;
341 
342     SkXfermode::D64Proc fProc1;
343     SkXfermode::D64Proc fProcN;
344 
State64State64345     State64(const SkImageInfo& info, const SkPaint& paint, const SkShader::Context* shaderContext)
346         : State4f(info, paint, shaderContext)
347     {
348         if (is_opaque(paint, shaderContext)) {
349             fFlags |= SkXfermode::kSrcIsOpaque_D64Flag;
350         }
351         if (kRGBA_F16_SkColorType == info.colorType()) {
352             fFlags |= SkXfermode::kDstIsFloat16_D64Flag;
353         }
354         fProc1 = SkXfermode::GetD64Proc(fXfer, fFlags | SkXfermode::kSrcIsSingle_D64Flag);
355         fProcN = SkXfermode::GetD64Proc(fXfer, fFlags);
356     }
357 
getLCDProcState64358     SkXfermode::LCD64Proc getLCDProc(uint32_t oneOrManyFlag) const {
359         uint32_t flags = fFlags & 1;
360         if (!(fFlags & SkXfermode::kDstIsFloat16_D64Flag)) {
361             flags |= SkXfermode::kDstIsLinearInt_LCDFlag;
362         }
363         return SkXfermode::GetLCD64Proc(flags | oneOrManyFlag);
364     }
365 
WritableAddrState64366     static DstType* WritableAddr(const SkPixmap& device, int x, int y) {
367         return device.writable_addr64(x, y);
368     }
369 };
370 
create(const SkPixmap & device,const SkPaint & paint,SkShader::Context * shaderContext,SkTBlitterAllocator * allocator)371 template <typename State> SkBlitter* create(const SkPixmap& device, const SkPaint& paint,
372                                             SkShader::Context* shaderContext,
373                                             SkTBlitterAllocator* allocator) {
374     SkASSERT(allocator != nullptr);
375 
376     if (shaderContext) {
377         return allocator->createT<SkState_Shader_Blitter<State>>(device, paint, shaderContext);
378     } else {
379         SkColor color = paint.getColor();
380         if (0 == SkColorGetA(color)) {
381             return nullptr;
382         }
383         return allocator->createT<SkState_Blitter<State>>(device, paint);
384     }
385 }
386 
SkBlitter_ARGB32_Create(const SkPixmap & device,const SkPaint & paint,SkShader::Context * shaderContext,SkTBlitterAllocator * allocator)387 SkBlitter* SkBlitter_ARGB32_Create(const SkPixmap& device, const SkPaint& paint,
388                                    SkShader::Context* shaderContext,
389                                    SkTBlitterAllocator* allocator) {
390     return create<State32>(device, paint, shaderContext, allocator);
391 }
392 
SkBlitter_ARGB64_Create(const SkPixmap & device,const SkPaint & paint,SkShader::Context * shaderContext,SkTBlitterAllocator * allocator)393 SkBlitter* SkBlitter_ARGB64_Create(const SkPixmap& device, const SkPaint& paint,
394                                    SkShader::Context* shaderContext,
395                                    SkTBlitterAllocator* allocator) {
396     return create<State64>(device, paint, shaderContext, allocator);
397 }
398