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