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