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