OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkCoreBlitters.h" | 8 #include "SkCoreBlitters.h" |
9 #include "SkColorPriv.h" | 9 #include "SkColorPriv.h" |
10 #include "SkShader.h" | 10 #include "SkShader.h" |
11 #include "SkUtils.h" | 11 #include "SkUtils.h" |
12 #include "SkXfermode.h" | 12 #include "SkXfermode.h" |
13 #include "SkBlitMask.h" | 13 #include "SkBlitMask.h" |
14 #include "SkTemplates.h" | |
15 | |
16 template <typename State> class SkState_Blitter : public SkRasterBlitter { | |
17 typedef SkRasterBlitter INHERITED; | |
18 State fState; | |
19 | |
20 public: | |
21 SkState_Blitter(const SkPixmap& device, const SkPaint& paint) | |
22 : INHERITED(device) | |
23 , fState(device.info(), paint, nullptr) | |
24 {} | |
25 | |
26 void blitH(int x, int y, int width) override { | |
27 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width()); | |
28 | |
29 fState.fProc1(fState, State::WritableAddr(fDevice, x, y), fState.fPM4f, width, nullptr); | |
30 } | |
31 | |
32 void blitV(int x, int y, int height, SkAlpha alpha) override { | |
33 SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height()); | |
34 | |
35 typename State::DstType* device = State::WritableAddr(fDevice, x, y); | |
36 size_t deviceRB = fDevice.rowBytes(); | |
37 | |
38 for (int i = 0; i < height; ++i) { | |
39 fState.fProc1(fState, device, fState.fPM4f, 1, &alpha); | |
40 device = (typename State::DstType*)((char*)device + deviceRB); | |
41 } | |
42 } | |
43 | |
44 void blitRect(int x, int y, int width, int height) override { | |
45 SkASSERT(x >= 0 && y >= 0 && | |
46 x + width <= fDevice.width() && y + height <= fDevice.height()) ; | |
47 | |
48 typename State::DstType* device = State::WritableAddr(fDevice, x, y); | |
49 size_t deviceRB = fDevice.rowBytes(); | |
50 | |
51 do { | |
52 fState.fProc1(fState, device, fState.fPM4f, width, nullptr); | |
53 y += 1; | |
54 device = (typename State::DstType*)((char*)device + deviceRB); | |
55 } while (--height > 0); | |
56 } | |
57 | |
58 void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[] ) override { | |
59 typename State::DstType* device = State::WritableAddr(fDevice, x, y); | |
60 | |
61 for (;;) { | |
62 int count = *runs; | |
63 if (count <= 0) { | |
64 break; | |
65 } | |
66 int aa = *antialias; | |
67 if (aa) { | |
68 if (aa == 255) { | |
69 fState.fProc1(fState, device, fState.fPM4f, count, nullptr); | |
70 } else { | |
71 for (int i = 0; i < count; ++i) { | |
72 fState.fProc1(fState, &device[i], fState.fPM4f, 1, antia lias); | |
73 } | |
74 } | |
75 } | |
76 device += count; | |
77 runs += count; | |
78 antialias += count; | |
79 x += count; | |
80 } | |
81 } | |
82 | |
83 void blitMask(const SkMask& mask, const SkIRect& clip) override { | |
84 // we only handle kA8 | |
85 if (SkMask::kA8_Format != mask.fFormat) { | |
86 this->INHERITED::blitMask(mask, clip); | |
87 return; | |
88 } | |
89 | |
90 SkASSERT(mask.fBounds.contains(clip)); | |
91 | |
92 const int x = clip.fLeft; | |
93 const int width = clip.width(); | |
94 const int y = clip.fTop; | |
95 const int height = clip.height(); | |
96 | |
97 typename State::DstType* device = State::WritableAddr(fDevice, x, y); | |
98 const size_t dstRB = fDevice.rowBytes(); | |
99 const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y); | |
100 const size_t maskRB = mask.fRowBytes; | |
101 | |
102 for (int i = 0; i < height; ++i) { | |
103 fState.fProc1(fState, device, fState.fPM4f, width, maskRow); | |
104 device = (typename State::DstType*)((char*)device + dstRB); | |
105 maskRow += maskRB; | |
106 } | |
107 } | |
108 }; | |
109 | |
110 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
111 | |
112 template <typename State> class SkState_Shader_Blitter : public SkShaderBlitter { | |
113 public: | |
114 SkState_Shader_Blitter(const SkPixmap& device, const SkPaint& paint, | |
115 SkShader::Context* shaderContext) | |
116 : INHERITED(device, paint, shaderContext) | |
117 , fState(device.info(), paint, shaderContext) | |
118 {} | |
119 | |
120 void blitH(int x, int y, int width) override { | |
121 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width()); | |
122 | |
123 typename State::DstType* device = State::WritableAddr(fDevice, x, y); | |
124 fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width); | |
125 fState.fProcN(fState, device, fState.fBuffer, width, nullptr); | |
126 } | |
127 | |
128 void blitV(int x, int y, int height, SkAlpha alpha) override { | |
129 SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height()); | |
130 | |
131 typename State::DstType* device = State::WritableAddr(fDevice, x, y); | |
132 size_t deviceRB = fDevice.rowBytes(); | |
133 const int bottom = y + height; | |
134 | |
135 if (fConstInY) { | |
136 fShaderContext->shadeSpan4f(x, y, fState.fBuffer, 1); | |
137 } | |
138 for (; y < bottom; ++y) { | |
139 if (!fConstInY) { | |
f(malita)
2016/02/15 04:31:17
Is it worth hoisting this conditional out? I imag
reed2
2016/02/15 15:25:22
Was trying to keep everything very succinct until
| |
140 fShaderContext->shadeSpan4f(x, y, fState.fBuffer, 1); | |
141 } | |
142 fState.fProcN(fState, device, fState.fBuffer, 1, &alpha); | |
143 device = (typename State::DstType*)((char*)device + deviceRB); | |
144 } | |
145 } | |
146 | |
147 void blitRect(int x, int y, int width, int height) override { | |
148 SkASSERT(x >= 0 && y >= 0 && | |
149 x + width <= fDevice.width() && y + height <= fDevice.height()) ; | |
150 | |
151 typename State::DstType* device = State::WritableAddr(fDevice, x, y); | |
152 size_t deviceRB = fDevice.rowBytes(); | |
153 const int bottom = y + height; | |
154 | |
155 if (fConstInY) { | |
156 fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width); | |
157 } | |
158 for (; y < bottom; ++y) { | |
159 if (!fConstInY) { | |
f(malita)
2016/02/15 04:31:17
Ditto.
| |
160 fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width); | |
161 } | |
162 fState.fProcN(fState, device, fState.fBuffer, width, nullptr); | |
163 device = (typename State::DstType*)((char*)device + deviceRB); | |
164 } | |
165 } | |
166 | |
167 void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[] ) override { | |
168 typename State::DstType* device = State::WritableAddr(fDevice, x, y); | |
169 | |
170 for (;;) { | |
171 int count = *runs; | |
172 if (count <= 0) { | |
173 break; | |
174 } | |
175 int aa = *antialias; | |
176 if (aa) { | |
177 fShaderContext->shadeSpan4f(x, y, fState.fBuffer, count); | |
178 if (aa == 255) { | |
179 fState.fProcN(fState, device, fState.fBuffer, count, nullptr ); | |
180 } else { | |
181 for (int i = 0; i < count; ++i) { | |
182 fState.fProcN(fState, &device[i], &fState.fBuffer[i], 1, antialias); | |
183 } | |
184 } | |
185 } | |
186 device += count; | |
187 runs += count; | |
188 antialias += count; | |
189 x += count; | |
190 } | |
191 } | |
192 | |
193 void blitMask(const SkMask& mask, const SkIRect& clip) override { | |
194 // we only handle kA8 | |
195 if (SkMask::kA8_Format != mask.fFormat) { | |
196 this->INHERITED::blitMask(mask, clip); | |
197 return; | |
198 } | |
199 | |
200 SkASSERT(mask.fBounds.contains(clip)); | |
201 | |
202 const int x = clip.fLeft; | |
203 const int width = clip.width(); | |
204 int y = clip.fTop; | |
205 | |
206 typename State::DstType* device = State::WritableAddr(fDevice, x, y); | |
207 const size_t deviceRB = fDevice.rowBytes(); | |
208 const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y); | |
209 const size_t maskRB = mask.fRowBytes; | |
210 | |
211 if (fConstInY) { | |
212 fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width); | |
213 } | |
214 for (; y < clip.fBottom; ++y) { | |
215 if (!fConstInY) { | |
216 fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width); | |
217 } | |
218 fState.fProcN(fState, device, fState.fBuffer, width, maskRow); | |
219 device = (typename State::DstType*)((char*)device + deviceRB); | |
220 maskRow += maskRB; | |
221 } | |
222 } | |
223 | |
224 private: | |
225 State fState; | |
226 | |
227 typedef SkShaderBlitter INHERITED; | |
228 }; | |
14 | 229 |
15 //////////////////////////////////////////////////////////////////////////////// ////// | 230 //////////////////////////////////////////////////////////////////////////////// ////// |
16 | 231 |
17 SkARGB32_Shader4f_Blitter::SkARGB32_Shader4f_Blitter(const SkPixmap& device, | 232 static bool is_opaque(const SkPaint& paint, const SkShader::Context* shaderConte xt) { |
18 const SkPaint& paint, SkShader::Context* shaderContext) | 233 return shaderContext ? SkToBool(shaderContext->getFlags() & SkShader::kOpaqu eAlpha_Flag) |
19 : INHERITED(device, paint, shaderContext) | 234 : 0xFF == paint.getAlpha(); |
20 { | 235 } |
21 const uint32_t shaderFlags = shaderContext->getFlags(); | 236 |
22 | 237 struct State32 : SkXfermode::PM4fState { |
23 SkASSERT(shaderFlags & SkShader::kSupports4f_Flag); | 238 typedef uint32_t DstType; |
24 | 239 |
25 fBuffer = (SkPM4f*)sk_malloc_throw(device.width() * (sizeof(SkPM4f))); | 240 SkXfermode::PM4fProc1 fProc1; |
26 | 241 SkXfermode::PM4fProcN fProcN; |
27 fState.fXfer = SkSafeRef(paint.getXfermode()); | 242 SkPM4f fPM4f; |
28 fState.fFlags = 0; | 243 SkPM4f* fBuffer; |
29 if (shaderFlags & SkShader::kOpaqueAlpha_Flag) { | 244 |
30 fState.fFlags |= SkXfermode::kSrcIsOpaque_PM4fFlag; | 245 State32(const SkImageInfo& info, const SkPaint& paint, const SkShader::Conte xt* shaderContext) { |
31 } | 246 fXfer = SkSafeRef(paint.getXfermode()); |
32 if (device.info().isSRGB()) { | 247 fFlags = 0; |
33 fState.fFlags |= SkXfermode::kDstIsSRGB_PM4fFlag; | 248 if (is_opaque(paint, shaderContext)) { |
34 } | 249 fFlags |= SkXfermode::kSrcIsOpaque_PM4fFlag; |
35 if (fState.fXfer) { | 250 } |
36 fProc1 = fState.fXfer->getPM4fProc1(fState.fFlags); | 251 if (info.isSRGB()) { |
37 fProcN = fState.fXfer->getPM4fProcN(fState.fFlags); | 252 fFlags |= SkXfermode::kDstIsSRGB_PM4fFlag; |
253 } | |
254 if (fXfer) { | |
255 fProc1 = fXfer->getPM4fProc1(fFlags); | |
256 fProcN = fXfer->getPM4fProcN(fFlags); | |
257 } else { | |
258 fProc1 = SkXfermode::GetPM4fProc1(SkXfermode::kSrcOver_Mode, fFlags) ; | |
259 fProcN = SkXfermode::GetPM4fProcN(SkXfermode::kSrcOver_Mode, fFlags) ; | |
260 } | |
261 | |
262 fBuffer = nullptr; | |
263 if (shaderContext) { | |
264 fBuffer = new SkPM4f[info.width()]; | |
265 } else { | |
266 fPM4f = SkColor4f::FromColor(paint.getColor()).premul(); | |
267 } | |
268 } | |
269 | |
270 ~State32() { | |
271 SkSafeUnref(fXfer); | |
272 delete[] fBuffer; | |
273 } | |
274 | |
275 static DstType* WritableAddr(const SkPixmap& device, int x, int y) { | |
276 return device.writable_addr32(x, y); | |
277 } | |
278 }; | |
279 | |
280 struct State64 : SkXfermode::U64State { | |
281 typedef uint64_t DstType; | |
282 | |
283 SkXfermode::U64Proc1 fProc1; | |
284 SkXfermode::U64ProcN fProcN; | |
285 SkPM4f fPM4f; | |
286 SkPM4f* fBuffer; | |
287 | |
288 State64(const SkImageInfo& info, const SkPaint& paint, const SkShader::Conte xt* shaderContext) { | |
289 fXfer = SkSafeRef(paint.getXfermode()); | |
290 fFlags = 0; | |
291 if (is_opaque(paint, shaderContext)) { | |
292 fFlags |= SkXfermode::kSrcIsOpaque_PM4fFlag; | |
293 } | |
294 if (kRGBA_F16_SkColorType == info.colorType()) { | |
295 fFlags |= SkXfermode::kDstIsFloat16_U64Flag; | |
296 } | |
297 | |
298 SkXfermode::Mode mode; | |
299 if (SkXfermode::AsMode(fXfer, &mode)) { | |
300 mode = SkXfermode::kSrcOver_Mode; | |
301 } | |
302 fProc1 = SkXfermode::GetU64Proc1(mode, fFlags); | |
303 fProcN = SkXfermode::GetU64ProcN(mode, fFlags); | |
304 | |
305 fBuffer = nullptr; | |
306 if (shaderContext) { | |
307 fBuffer = new SkPM4f[info.width()]; | |
308 } else { | |
309 fPM4f = SkColor4f::FromColor(paint.getColor()).premul(); | |
310 } | |
311 } | |
312 | |
313 ~State64() { | |
314 SkSafeUnref(fXfer); | |
315 delete[] fBuffer; | |
316 } | |
317 | |
318 static DstType* WritableAddr(const SkPixmap& device, int x, int y) { | |
319 return device.writable_addr64(x, y); | |
320 } | |
321 }; | |
322 | |
323 template <typename State> SkBlitter* create(const SkPixmap& device, const SkPain t& paint, | |
324 SkShader::Context* shaderContext, | |
325 SkTBlitterAllocator* allocator) { | |
326 SkASSERT(allocator != nullptr); | |
327 | |
328 if (shaderContext) { | |
329 return allocator->createT<SkState_Shader_Blitter<State>>(device, paint, shaderContext); | |
38 } else { | 330 } else { |
39 fProc1 = SkXfermode::GetPM4fProc1(SkXfermode::kSrcOver_Mode, fState.fFla gs); | 331 SkColor color = paint.getColor(); |
40 fProcN = SkXfermode::GetPM4fProcN(SkXfermode::kSrcOver_Mode, fState.fFla gs); | 332 if (0 == SkColorGetA(color)) { |
41 } | 333 return nullptr; |
42 | 334 } |
43 fConstInY = SkToBool(shaderFlags & SkShader::kConstInY32_Flag); | 335 return allocator->createT<SkState_Blitter<State>>(device, paint); |
336 } | |
44 } | 337 } |
45 | 338 |
46 SkARGB32_Shader4f_Blitter::~SkARGB32_Shader4f_Blitter() { | 339 SkBlitter* SkBlitter_ARGB32_Create(const SkPixmap& device, const SkPaint& paint, |
47 SkSafeUnref(fState.fXfer); | 340 SkShader::Context* shaderContext, |
48 sk_free(fBuffer); | 341 SkTBlitterAllocator* allocator) { |
342 return create<State32>(device, paint, shaderContext, allocator); | |
49 } | 343 } |
50 | 344 |
51 void SkARGB32_Shader4f_Blitter::blitH(int x, int y, int width) { | 345 SkBlitter* SkBlitter_ARGB64_Create(const SkPixmap& device, const SkPaint& paint, |
52 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width()); | 346 SkShader::Context* shaderContext, |
53 | 347 SkTBlitterAllocator* allocator) { |
54 uint32_t* device = fDevice.writable_addr32(x, y); | 348 return create<State64>(device, paint, shaderContext, allocator); |
55 fShaderContext->shadeSpan4f(x, y, fBuffer, width); | |
56 fProcN(fState, device, fBuffer, width, nullptr); | |
57 } | 349 } |
58 | |
59 void SkARGB32_Shader4f_Blitter::blitRect(int x, int y, int width, int height) { | |
60 SkASSERT(x >= 0 && y >= 0 && | |
61 x + width <= fDevice.width() && y + height <= fDevice.height()); | |
62 | |
63 uint32_t* device = fDevice.writable_addr32(x, y); | |
64 size_t deviceRB = fDevice.rowBytes(); | |
65 | |
66 if (fConstInY) { | |
67 fShaderContext->shadeSpan4f(x, y, fBuffer, width); | |
68 do { | |
69 fProcN(fState, device, fBuffer, width, nullptr); | |
70 y += 1; | |
71 device = (uint32_t*)((char*)device + deviceRB); | |
72 } while (--height > 0); | |
73 } else { | |
74 do { | |
75 fShaderContext->shadeSpan4f(x, y, fBuffer, width); | |
76 fProcN(fState, device, fBuffer, width, nullptr); | |
77 y += 1; | |
78 device = (uint32_t*)((char*)device + deviceRB); | |
79 } while (--height > 0); | |
80 } | |
81 } | |
82 | |
83 void SkARGB32_Shader4f_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[ ], | |
84 const int16_t runs[]) { | |
85 uint32_t* device = fDevice.writable_addr32(x, y); | |
86 | |
87 for (;;) { | |
88 int count = *runs; | |
89 if (count <= 0) { | |
90 break; | |
91 } | |
92 int aa = *antialias; | |
93 if (aa) { | |
94 fShaderContext->shadeSpan4f(x, y, fBuffer, count); | |
95 if (aa == 255) { | |
96 fProcN(fState, device, fBuffer, count, nullptr); | |
97 } else { | |
98 // count is almost always 1 | |
99 for (int i = count - 1; i >= 0; --i) { | |
100 fProcN(fState, &device[i], &fBuffer[i], 1, antialias); | |
101 } | |
102 } | |
103 } | |
104 device += count; | |
105 runs += count; | |
106 antialias += count; | |
107 x += count; | |
108 } | |
109 } | |
110 | |
111 void SkARGB32_Shader4f_Blitter::blitMask(const SkMask& mask, const SkIRect& clip ) { | |
112 // we only handle kA8 | |
113 if (SkMask::kA8_Format != mask.fFormat) { | |
114 this->INHERITED::blitMask(mask, clip); | |
115 return; | |
116 } | |
117 | |
118 SkASSERT(mask.fBounds.contains(clip)); | |
119 | |
120 const int x = clip.fLeft; | |
121 const int width = clip.width(); | |
122 int y = clip.fTop; | |
123 int height = clip.height(); | |
124 | |
125 char* dstRow = (char*)fDevice.writable_addr32(x, y); | |
126 const size_t dstRB = fDevice.rowBytes(); | |
127 const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y); | |
128 const size_t maskRB = mask.fRowBytes; | |
129 | |
130 do { | |
131 fShaderContext->shadeSpan4f(x, y, fBuffer, width); | |
132 fProcN(fState, reinterpret_cast<SkPMColor*>(dstRow), fBuffer, width, mas kRow); | |
133 dstRow += dstRB; | |
134 maskRow += maskRB; | |
135 y += 1; | |
136 } while (--height > 0); | |
137 } | |
138 | |
139 void SkARGB32_Shader4f_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { | |
140 SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height()); | |
141 | |
142 uint32_t* device = fDevice.writable_addr32(x, y); | |
143 size_t deviceRB = fDevice.rowBytes(); | |
144 | |
145 if (fConstInY) { | |
146 fShaderContext->shadeSpan4f(x, y, fBuffer, 1); | |
147 do { | |
148 fProcN(fState, device, fBuffer, 1, &alpha); | |
149 device = (uint32_t*)((char*)device + deviceRB); | |
150 } while (--height > 0); | |
151 } else { | |
152 do { | |
153 fShaderContext->shadeSpan4f(x, y, fBuffer, 1); | |
154 fProcN(fState, device, fBuffer, 1, &alpha); | |
155 y += 1; | |
156 device = (uint32_t*)((char*)device + deviceRB); | |
157 } while (--height > 0); | |
158 } | |
159 } | |
OLD | NEW |