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 
10 #include "SkArenaAlloc.h"
11 #include "SkColorPriv.h"
12 #include "SkShader.h"
13 #include "SkUtils.h"
14 #include "SkXfermodePriv.h"
15 #include "SkBlitMask.h"
16 #include "SkTemplates.h"
17 #include "SkPM4f.h"
18 
19 template <typename State> class SkState_Blitter : public SkRasterBlitter {
20     typedef SkRasterBlitter INHERITED;
21     State fState;
22 
23 public:
SkState_Blitter(const SkPixmap & device,const SkPaint & paint)24     SkState_Blitter(const SkPixmap& device, const SkPaint& paint)
25         : INHERITED(device)
26         , fState(device.info(), paint, nullptr)
27     {}
28 
blitH(int x,int y,int width)29     void blitH(int x, int y, int width) override {
30         SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
31 
32         fState.fProc1(fState.fMode, State::WritableAddr(fDevice, x, y),
33                       &fState.fPM4f, width, nullptr);
34     }
35 
blitV(int x,int y,int height,SkAlpha alpha)36     void blitV(int x, int y, int height, SkAlpha alpha) override {
37         SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height());
38 
39         typename State::DstType* device = State::WritableAddr(fDevice, x, y);
40         size_t                 deviceRB = fDevice.rowBytes();
41 
42         for (int i = 0; i < height; ++i) {
43             fState.fProc1(fState.fMode, device, &fState.fPM4f, 1, &alpha);
44             device = (typename State::DstType*)((char*)device + deviceRB);
45         }
46     }
47 
blitRect(int x,int y,int width,int height)48     void blitRect(int x, int y, int width, int height) override {
49         SkASSERT(x >= 0 && y >= 0 &&
50                  x + width <= fDevice.width() && y + height <= fDevice.height());
51 
52         typename State::DstType* device = State::WritableAddr(fDevice, x, y);
53         size_t        deviceRB = fDevice.rowBytes();
54 
55         do {
56             fState.fProc1(fState.fMode, device, &fState.fPM4f, width, nullptr);
57             y += 1;
58             device = (typename State::DstType*)((char*)device + deviceRB);
59         } while (--height > 0);
60     }
61 
blitAntiH(int x,int y,const SkAlpha antialias[],const int16_t runs[])62     void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) override {
63         typename State::DstType* device = State::WritableAddr(fDevice, x, y);
64 
65         for (;;) {
66             int count = *runs;
67             if (count <= 0) {
68                 break;
69             }
70             int aa = *antialias;
71             if (aa) {
72                 if (aa == 255) {
73                     fState.fProc1(fState.fMode, device, &fState.fPM4f, count, nullptr);
74                 } else {
75                     for (int i = 0; i < count; ++i) {
76                         fState.fProc1(fState.fMode, &device[i], &fState.fPM4f, 1, antialias);
77                     }
78                 }
79             }
80             device += count;
81             runs += count;
82             antialias += count;
83             x += count;
84         }
85     }
86 
blitLCDMask(const SkMask & mask,const SkIRect & clip)87     void blitLCDMask(const SkMask& mask, const SkIRect& clip) {
88         auto proc = fState.getLCDProc(SkXfermode::kSrcIsSingle_LCDFlag);
89 
90         const int x = clip.fLeft;
91         const int width = clip.width();
92         const int y = clip.fTop;
93         const int height = clip.height();
94 
95         typename State::DstType* device = State::WritableAddr(fDevice, x, y);
96         const size_t dstRB = fDevice.rowBytes();
97         const uint16_t* maskRow = (const uint16_t*)mask.getAddr(x, y);
98         const size_t maskRB = mask.fRowBytes;
99 
100         for (int i = 0; i < height; ++i) {
101             proc(device, &fState.fPM4f, width, maskRow);
102             device = (typename State::DstType*)((char*)device + dstRB);
103             maskRow = (const uint16_t*)((const char*)maskRow + maskRB);
104         }
105     }
106 
blitMask(const SkMask & mask,const SkIRect & clip)107     void blitMask(const SkMask& mask, const SkIRect& clip) override {
108         if (SkMask::kLCD16_Format == mask.fFormat) {
109             this->blitLCDMask(mask, clip);
110             return;
111         }
112         if (SkMask::kA8_Format != mask.fFormat) {
113             this->INHERITED::blitMask(mask, clip);
114             return;
115         }
116 
117         SkASSERT(mask.fBounds.contains(clip));
118 
119         const int x = clip.fLeft;
120         const int width = clip.width();
121         const int y = clip.fTop;
122         const int height = clip.height();
123 
124         typename State::DstType* device = State::WritableAddr(fDevice, x, y);
125         const size_t dstRB = fDevice.rowBytes();
126         const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y);
127         const size_t maskRB = mask.fRowBytes;
128 
129         for (int i = 0; i < height; ++i) {
130             fState.fProc1(fState.fMode, device, &fState.fPM4f, width, maskRow);
131             device = (typename State::DstType*)((char*)device + dstRB);
132             maskRow += maskRB;
133         }
134     }
135 };
136 
137 ///////////////////////////////////////////////////////////////////////////////////////////////////
138 
139 template <typename State> class SkState_Shader_Blitter : public SkShaderBlitter {
140 public:
SkState_Shader_Blitter(const SkPixmap & device,const SkPaint & paint,const SkShader::Context::BlitState & bstate)141     SkState_Shader_Blitter(const SkPixmap& device, const SkPaint& paint,
142                            const SkShader::Context::BlitState& bstate)
143         : INHERITED(device, paint, bstate.fCtx)
144         , fState(device.info(), paint, bstate.fCtx)
145         , fBState(bstate)
146         , fBlitBW(bstate.fBlitBW)
147         , fBlitAA(bstate.fBlitAA)
148     {}
149 
blitH(int x,int y,int width)150     void blitH(int x, int y, int width) override {
151         SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
152 
153         if (fBlitBW) {
154             fBlitBW(&fBState, x, y, fDevice, width);
155             return;
156         }
157 
158         typename State::DstType* device = State::WritableAddr(fDevice, x, y);
159         fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width);
160         fState.fProcN(fState.fMode, device, fState.fBuffer, width, nullptr);
161     }
162 
blitV(int x,int y,int height,SkAlpha alpha)163     void blitV(int x, int y, int height, SkAlpha alpha) override {
164         SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height());
165 
166         if (fBlitAA) {
167             for (const int bottom = y + height; y < bottom; ++y) {
168                 fBlitAA(&fBState, x, y, fDevice, 1, &alpha);
169             }
170             return;
171         }
172 
173         typename State::DstType* device = State::WritableAddr(fDevice, x, y);
174         size_t                   deviceRB = fDevice.rowBytes();
175 
176         if (fConstInY) {
177             fShaderContext->shadeSpan4f(x, y, fState.fBuffer, 1);
178         }
179         for (const int bottom = y + height; y < bottom; ++y) {
180             if (!fConstInY) {
181                 fShaderContext->shadeSpan4f(x, y, fState.fBuffer, 1);
182             }
183             fState.fProcN(fState.fMode, device, fState.fBuffer, 1, &alpha);
184             device = (typename State::DstType*)((char*)device + deviceRB);
185         }
186     }
187 
blitRect(int x,int y,int width,int height)188     void blitRect(int x, int y, int width, int height) override {
189         SkASSERT(x >= 0 && y >= 0 &&
190                  x + width <= fDevice.width() && y + height <= fDevice.height());
191 
192         if (fBlitBW) {
193             for (const int bottom = y + height; y < bottom; ++y) {
194                 fBlitBW(&fBState, x, y, fDevice, width);
195             }
196             return;
197         }
198 
199         typename State::DstType* device = State::WritableAddr(fDevice, x, y);
200         size_t                   deviceRB = fDevice.rowBytes();
201 
202         if (fConstInY) {
203             fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width);
204         }
205         for (const int bottom = y + height; y < bottom; ++y) {
206             if (!fConstInY) {
207                 fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width);
208             }
209             fState.fProcN(fState.fMode, device, fState.fBuffer, width, nullptr);
210             device = (typename State::DstType*)((char*)device + deviceRB);
211         }
212     }
213 
blitAntiH(int x,int y,const SkAlpha antialias[],const int16_t runs[])214     void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) override {
215         typename State::DstType* device = State::WritableAddr(fDevice, x, y);
216 
217         for (;;) {
218             int count = *runs;
219             if (count <= 0) {
220                 break;
221             }
222             int aa = *antialias;
223             if (aa) {
224                 if (fBlitBW && (aa == 255)) {
225                     fBlitBW(&fBState, x, y, fDevice, count);
226                 } else {
227                     fShaderContext->shadeSpan4f(x, y, fState.fBuffer, count);
228                     if (aa == 255) {
229                         fState.fProcN(fState.fMode, device, fState.fBuffer, count, nullptr);
230                     } else {
231                         for (int i = 0; i < count; ++i) {
232                             fState.fProcN(fState.fMode, &device[i], &fState.fBuffer[i], 1, antialias);
233                         }
234                     }
235                 }
236             }
237             device += count;
238             runs += count;
239             antialias += count;
240             x += count;
241         }
242     }
243 
blitLCDMask(const SkMask & mask,const SkIRect & clip)244     void blitLCDMask(const SkMask& mask, const SkIRect& clip) {
245         auto proc = fState.getLCDProc(0);
246 
247         const int x = clip.fLeft;
248         const int width = clip.width();
249         int y = clip.fTop;
250 
251         typename State::DstType* device = State::WritableAddr(fDevice, x, y);
252         const size_t deviceRB = fDevice.rowBytes();
253         const uint16_t* maskRow = (const uint16_t*)mask.getAddr(x, y);
254         const size_t maskRB = mask.fRowBytes;
255 
256         if (fConstInY) {
257             fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width);
258         }
259         for (; y < clip.fBottom; ++y) {
260             if (!fConstInY) {
261                 fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width);
262             }
263             proc(device, fState.fBuffer, width, maskRow);
264             device = (typename State::DstType*)((char*)device + deviceRB);
265             maskRow = (const uint16_t*)((const char*)maskRow + maskRB);
266         }
267     }
268 
blitMask(const SkMask & mask,const SkIRect & clip)269     void blitMask(const SkMask& mask, const SkIRect& clip) override {
270         if (SkMask::kLCD16_Format == mask.fFormat) {
271             this->blitLCDMask(mask, clip);
272             return;
273         }
274         if (SkMask::kA8_Format != mask.fFormat) {
275             this->INHERITED::blitMask(mask, clip);
276             return;
277         }
278 
279         SkASSERT(mask.fBounds.contains(clip));
280 
281         const int x = clip.fLeft;
282         const int width = clip.width();
283         int y = clip.fTop;
284         const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y);
285         const size_t maskRB = mask.fRowBytes;
286 
287         if (fBlitAA) {
288             for (; y < clip.fBottom; ++y) {
289                 fBlitAA(&fBState, x, y, fDevice, width, maskRow);
290                 maskRow += maskRB;
291             }
292             return;
293         }
294 
295         typename State::DstType* device = State::WritableAddr(fDevice, x, y);
296         const size_t deviceRB = fDevice.rowBytes();
297 
298         if (fConstInY) {
299             fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width);
300         }
301         for (; y < clip.fBottom; ++y) {
302             if (!fConstInY) {
303                 fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width);
304             }
305             fState.fProcN(fState.fMode, device, fState.fBuffer, width, maskRow);
306             device = (typename State::DstType*)((char*)device + deviceRB);
307             maskRow += maskRB;
308         }
309     }
310 
311 protected:
312     State                        fState;
313     SkShader::Context::BlitState fBState;
314     SkShader::Context::BlitBW    fBlitBW;
315     SkShader::Context::BlitAA    fBlitAA;
316 
317     typedef SkShaderBlitter INHERITED;
318 };
319 
320 ///////////////////////////////////////////////////////////////////////////////////////////////////
321 ///////////////////////////////////////////////////////////////////////////////////////////////////
322 
is_opaque(const SkPaint & paint,const SkShader::Context * shaderContext)323 static bool is_opaque(const SkPaint& paint, const SkShader::Context* shaderContext) {
324     return shaderContext ? SkToBool(shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag)
325     : 0xFF == paint.getAlpha();
326 }
327 
328 struct State4f {
State4fState4f329     State4f(const SkImageInfo& info, const SkPaint& paint, const SkShader::Context* shaderContext) {
330         fMode = paint.getBlendMode();
331         if (shaderContext) {
332             fBuffer.reset(info.width());
333         } else {
334             fPM4f = SkColor4f::FromColor(paint.getColor()).premul();
335         }
336         fFlags = 0;
337     }
338 
339     SkPM4f                  fPM4f;
340     SkAutoTMalloc<SkPM4f>   fBuffer;
341     uint32_t                fFlags;
342     SkBlendMode             fMode;
343 
344     SkShader::Context::BlitState fBState;
345 };
346 
347 struct State32 : State4f {
348     typedef uint32_t    DstType;
349 
350     SkXfermode::D32Proc fProc1;
351     SkXfermode::D32Proc fProcN;
352 
State32State32353     State32(const SkImageInfo& info, const SkPaint& paint, const SkShader::Context* shaderContext)
354         : State4f(info, paint, shaderContext)
355     {
356         if (is_opaque(paint, shaderContext)) {
357             fFlags |= SkXfermode::kSrcIsOpaque_D32Flag;
358         }
359         if (info.gammaCloseToSRGB()) {
360             fFlags |= SkXfermode::kDstIsSRGB_D32Flag;
361         }
362         fProc1 = SkXfermode::GetD32Proc(fMode, fFlags | SkXfermode::kSrcIsSingle_D32Flag);
363         fProcN = SkXfermode::GetD32Proc(fMode, fFlags);
364     }
365 
getLCDProcState32366     SkXfermode::LCD32Proc getLCDProc(uint32_t oneOrManyFlag) const {
367         uint32_t flags = fFlags & 1;
368         if (fFlags & SkXfermode::kDstIsSRGB_D32Flag) {
369             flags |= SkXfermode::kDstIsSRGB_LCDFlag;
370         }
371         return SkXfermode::GetLCD32Proc(flags | oneOrManyFlag);
372     }
373 
WritableAddrState32374     static DstType* WritableAddr(const SkPixmap& device, int x, int y) {
375         return device.writable_addr32(x, y);
376     }
377 };
378 
379 struct StateF16 : State4f {
380     typedef uint64_t    DstType;
381 
382     SkXfermode::F16Proc fProc1;
383     SkXfermode::F16Proc fProcN;
384 
StateF16StateF16385     StateF16(const SkImageInfo& info, const SkPaint& paint, const SkShader::Context* shaderContext)
386         : State4f(info, paint, shaderContext)
387     {
388         if (is_opaque(paint, shaderContext)) {
389             fFlags |= SkXfermode::kSrcIsOpaque_F16Flag;
390         }
391         SkASSERT(kRGBA_F16_SkColorType == info.colorType());
392         fProc1 = SkXfermode::GetF16Proc(fMode, fFlags | SkXfermode::kSrcIsSingle_F16Flag);
393         fProcN = SkXfermode::GetF16Proc(fMode, fFlags);
394     }
395 
getLCDProcStateF16396     SkXfermode::LCDF16Proc getLCDProc(uint32_t oneOrManyFlag) const {
397         uint32_t flags = fFlags & 1;
398         return SkXfermode::GetLCDF16Proc(flags | oneOrManyFlag);
399     }
400 
WritableAddrStateF16401     static DstType* WritableAddr(const SkPixmap& device, int x, int y) {
402         return device.writable_addr64(x, y);
403     }
404 };
405 
create(const SkPixmap & device,const SkPaint & paint,SkShader::Context * shaderContext,SkArenaAlloc * alloc)406 template <typename State> SkBlitter* create(const SkPixmap& device, const SkPaint& paint,
407                                             SkShader::Context* shaderContext,
408                                             SkArenaAlloc* alloc) {
409     SkASSERT(alloc != nullptr);
410 
411     if (shaderContext) {
412         SkShader::Context::BlitState bstate;
413         sk_bzero(&bstate, sizeof(bstate));
414         bstate.fCtx = shaderContext;
415         bstate.fMode = paint.getBlendMode();
416 
417         (void)shaderContext->chooseBlitProcs(device.info(), &bstate);
418         return alloc->make<SkState_Shader_Blitter<State>>(device, paint, bstate);
419     } else {
420         SkColor color = paint.getColor();
421         if (0 == SkColorGetA(color)) {
422             return nullptr;
423         }
424         return alloc->make<SkState_Blitter<State>>(device, paint);
425     }
426 }
427 
SkBlitter_ARGB32_Create(const SkPixmap & device,const SkPaint & paint,SkShader::Context * shaderContext,SkArenaAlloc * alloc)428 SkBlitter* SkBlitter_ARGB32_Create(const SkPixmap& device, const SkPaint& paint,
429                                    SkShader::Context* shaderContext,
430                                    SkArenaAlloc* alloc) {
431     return create<State32>(device, paint, shaderContext, alloc);
432 }
433 
SkBlitter_F16_Create(const SkPixmap & device,const SkPaint & paint,SkShader::Context * shaderContext,SkArenaAlloc * alloc)434 SkBlitter* SkBlitter_F16_Create(const SkPixmap& device, const SkPaint& paint,
435                                 SkShader::Context* shaderContext,
436                                 SkArenaAlloc* alloc) {
437     return create<StateF16>(device, paint, shaderContext, alloc);
438 }
439