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 "SkBlitter.h" | 8 #include "SkBlitter.h" |
9 #include "SkColor.h" | 9 #include "SkColor.h" |
10 #include "SkColorFilter.h" | 10 #include "SkColorFilter.h" |
| 11 #include "SkHalf.h" |
11 #include "SkPM4f.h" | 12 #include "SkPM4f.h" |
12 #include "SkRasterPipeline.h" | 13 #include "SkRasterPipeline.h" |
13 #include "SkShader.h" | 14 #include "SkShader.h" |
14 #include "SkSRGB.h" | 15 #include "SkSRGB.h" |
15 #include "SkXfermode.h" | 16 #include "SkXfermode.h" |
16 | 17 |
17 | 18 |
18 class SkRasterPipelineBlitter : public SkBlitter { | 19 class SkRasterPipelineBlitter : public SkBlitter { |
19 public: | 20 public: |
20 static SkBlitter* Create(const SkPixmap&, const SkPaint&, SkTBlitterAllocato
r*); | 21 static SkBlitter* Create(const SkPixmap&, const SkPaint&, SkTBlitterAllocato
r*); |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 } | 218 } |
218 | 219 |
219 // Store 1 565 pixel. | 220 // Store 1 565 pixel. |
220 static void SK_VECTORCALL store_565_1(SkRasterPipeline::Stage* st, size_t x, | 221 static void SK_VECTORCALL store_565_1(SkRasterPipeline::Stage* st, size_t x, |
221 Sk4f r, Sk4f g, Sk4f b, Sk4f a, | 222 Sk4f r, Sk4f g, Sk4f b, Sk4f a, |
222 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { | 223 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { |
223 auto ptr = st->ctx<uint16_t*>() + x; | 224 auto ptr = st->ctx<uint16_t*>() + x; |
224 *ptr = to_565(r,g,b)[0]; | 225 *ptr = to_565(r,g,b)[0]; |
225 } | 226 } |
226 | 227 |
| 228 // Load 4 F16 pixels. |
| 229 static void SK_VECTORCALL load_d_f16(SkRasterPipeline::Stage* st, size_t x, |
| 230 Sk4f r, Sk4f g, Sk4f b, Sk4f a, |
| 231 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { |
| 232 auto ptr = st->ctx<const uint64_t*>() + x; |
| 233 |
| 234 // TODO: This can be made a lot more efficient with platform-specific code. |
| 235 auto p0 = SkHalfToFloat_finite(ptr[0]), |
| 236 p1 = SkHalfToFloat_finite(ptr[1]), |
| 237 p2 = SkHalfToFloat_finite(ptr[2]), |
| 238 p3 = SkHalfToFloat_finite(ptr[3]); |
| 239 dr = { p0[0], p1[0], p2[0], p3[0] }; |
| 240 dg = { p0[1], p1[1], p2[1], p3[1] }; |
| 241 db = { p0[2], p1[2], p2[2], p3[2] }; |
| 242 da = { p0[3], p1[3], p2[3], p3[3] }; |
| 243 |
| 244 st->next(x, r,g,b,a, dr,dg,db,da); |
| 245 } |
| 246 |
| 247 // Load 1 F16 pixel. |
| 248 static void SK_VECTORCALL load_d_f16_1(SkRasterPipeline::Stage* st, size_t x, |
| 249 Sk4f r, Sk4f g, Sk4f b, Sk4f a, |
| 250 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { |
| 251 auto ptr = st->ctx<const uint64_t*>() + x; |
| 252 |
| 253 auto p0 = SkHalfToFloat_finite(ptr[0]); |
| 254 dr = { p0[0],0,0,0 }; |
| 255 dg = { p0[1],0,0,0 }; |
| 256 db = { p0[2],0,0,0 }; |
| 257 da = { p0[3],0,0,0 }; |
| 258 |
| 259 st->next(x, r,g,b,a, dr,dg,db,da); |
| 260 } |
| 261 |
| 262 // Store 4 F16 pixels. |
| 263 static void SK_VECTORCALL store_f16(SkRasterPipeline::Stage* st, size_t x, |
| 264 Sk4f r, Sk4f g, Sk4f b, Sk4f a, |
| 265 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { |
| 266 auto ptr = st->ctx<uint64_t*>() + x; |
| 267 |
| 268 Sk4h_store4(ptr, SkFloatToHalf_finite(r), SkFloatToHalf_finite(g), |
| 269 SkFloatToHalf_finite(b), SkFloatToHalf_finite(a)); |
| 270 } |
| 271 |
| 272 // Store 1 F16 pixel. |
| 273 static void SK_VECTORCALL store_f16_1(SkRasterPipeline::Stage* st, size_t x, |
| 274 Sk4f r, Sk4f g, Sk4f b, Sk4f a, |
| 275 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { |
| 276 auto ptr = st->ctx<uint64_t*>() + x; |
| 277 |
| 278 SkFloatToHalf_finite({r[0], g[0], b[0], a[0]}).store(ptr); |
| 279 } |
| 280 |
227 // Load 4 8-bit sRGB pixels from SkPMColor order to RGBA. | 281 // Load 4 8-bit sRGB pixels from SkPMColor order to RGBA. |
228 static void SK_VECTORCALL load_d_srgb(SkRasterPipeline::Stage* st, size_t x, | 282 static void SK_VECTORCALL load_d_srgb(SkRasterPipeline::Stage* st, size_t x, |
229 Sk4f r, Sk4f g, Sk4f b, Sk4f a, | 283 Sk4f r, Sk4f g, Sk4f b, Sk4f a, |
230 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { | 284 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { |
231 auto ptr = st->ctx<const uint32_t*>() + x; | 285 auto ptr = st->ctx<const uint32_t*>() + x; |
232 | 286 |
233 dr = { sk_linear_from_srgb[(ptr[0] >> SK_R32_SHIFT) & 0xff], | 287 dr = { sk_linear_from_srgb[(ptr[0] >> SK_R32_SHIFT) & 0xff], |
234 sk_linear_from_srgb[(ptr[1] >> SK_R32_SHIFT) & 0xff], | 288 sk_linear_from_srgb[(ptr[1] >> SK_R32_SHIFT) & 0xff], |
235 sk_linear_from_srgb[(ptr[2] >> SK_R32_SHIFT) & 0xff], | 289 sk_linear_from_srgb[(ptr[2] >> SK_R32_SHIFT) & 0xff], |
236 sk_linear_from_srgb[(ptr[3] >> SK_R32_SHIFT) & 0xff] }; | 290 sk_linear_from_srgb[(ptr[3] >> SK_R32_SHIFT) & 0xff] }; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 auto dst = st->ctx<uint32_t*>() + x; | 337 auto dst = st->ctx<uint32_t*>() + x; |
284 Sk4i rgb = sk_linear_to_srgb_noclamp(swizzle_rb_if_bgra({ r[0], g[0], b[0],
0.0f })); | 338 Sk4i rgb = sk_linear_to_srgb_noclamp(swizzle_rb_if_bgra({ r[0], g[0], b[0],
0.0f })); |
285 | 339 |
286 uint32_t rgba; | 340 uint32_t rgba; |
287 SkNx_cast<uint8_t>(rgb).store(&rgba); | 341 SkNx_cast<uint8_t>(rgb).store(&rgba); |
288 rgba |= (uint32_t)(255.0f * a[0] + 0.5f) << 24; | 342 rgba |= (uint32_t)(255.0f * a[0] + 0.5f) << 24; |
289 *dst = rgba; | 343 *dst = rgba; |
290 } | 344 } |
291 | 345 |
292 static bool supported(const SkImageInfo& info) { | 346 static bool supported(const SkImageInfo& info) { |
293 // TODO: f16, more? | |
294 switch (info.colorType()) { | 347 switch (info.colorType()) { |
295 case kN32_SkColorType: return info.gammaCloseToSRGB(); | 348 case kN32_SkColorType: return info.gammaCloseToSRGB(); |
296 case kRGB_565_SkColorType: return true; | 349 case kRGBA_F16_SkColorType: return true; |
297 default: return false; | 350 case kRGB_565_SkColorType: return true; |
| 351 default: return false; |
298 } | 352 } |
299 } | 353 } |
300 | 354 |
301 template <typename Effect> | 355 template <typename Effect> |
302 static bool append_effect_stages(const Effect* effect, SkRasterPipeline* pipelin
e) { | 356 static bool append_effect_stages(const Effect* effect, SkRasterPipeline* pipelin
e) { |
303 return !effect || effect->appendStages(pipeline); | 357 return !effect || effect->appendStages(pipeline); |
304 } | 358 } |
305 | 359 |
306 | 360 |
307 SkBlitter* SkRasterPipelineBlitter::Create(const SkPixmap& dst, | 361 SkBlitter* SkRasterPipelineBlitter::Create(const SkPixmap& dst, |
308 const SkPaint& paint, | 362 const SkPaint& paint, |
309 SkTBlitterAllocator* alloc) { | 363 SkTBlitterAllocator* alloc) { |
310 if (!supported(dst.info())) { | 364 if (!supported(dst.info())) { |
311 return nullptr; | 365 return nullptr; |
312 } | 366 } |
313 if (paint.getShader()) { | 367 if (paint.getShader()) { |
314 return nullptr; // TODO: need to work out how shaders and their context
s work | 368 return nullptr; // TODO: need to work out how shaders and their context
s work |
315 } | 369 } |
316 | 370 |
317 SkRasterPipeline shader, colorFilter, xfermode; | 371 SkRasterPipeline shader, colorFilter, xfermode; |
318 if (!append_effect_stages(paint.getColorFilter(), &colorFilter) || | 372 if (!append_effect_stages(paint.getColorFilter(), &colorFilter) || |
319 !append_effect_stages(paint.getXfermode(), &xfermode )) { | 373 !append_effect_stages(paint.getXfermode(), &xfermode )) { |
320 return nullptr; | 374 return nullptr; |
321 } | 375 } |
322 | 376 |
323 uint32_t paintColor = paint.getColor(); | 377 uint32_t paintColor = paint.getColor(); |
324 | 378 |
325 SkColor4f color; | 379 SkColor4f color; |
326 if (dst.info().colorSpace()) { | 380 if (SkImageInfoIsGammaCorrect(dst.info())) { |
327 color = SkColor4f::FromColor(paintColor); | 381 color = SkColor4f::FromColor(paintColor); |
328 } else { | 382 } else { |
329 swizzle_rb(SkNx_cast<float>(Sk4b::Load(&paintColor)) * (1/255.0f)).store
(&color); | 383 swizzle_rb(SkNx_cast<float>(Sk4b::Load(&paintColor)) * (1/255.0f)).store
(&color); |
330 } | 384 } |
331 | 385 |
332 auto blitter = alloc->createT<SkRasterPipelineBlitter>( | 386 auto blitter = alloc->createT<SkRasterPipelineBlitter>( |
333 dst, | 387 dst, |
334 shader, colorFilter, xfermode, | 388 shader, colorFilter, xfermode, |
335 color.premul()); | 389 color.premul()); |
336 | 390 |
337 if (!paint.getShader()) { | 391 if (!paint.getShader()) { |
338 blitter->fShader.append(constant_color, &blitter->fPaintColor); | 392 blitter->fShader.append(constant_color, &blitter->fPaintColor); |
339 } | 393 } |
340 if (!paint.getXfermode()) { | 394 if (!paint.getXfermode()) { |
341 blitter->fXfermode.append(srcover); | 395 blitter->fXfermode.append(srcover); |
342 } | 396 } |
343 | 397 |
344 return blitter; | 398 return blitter; |
345 } | 399 } |
346 | 400 |
347 void SkRasterPipelineBlitter::append_load_d(SkRasterPipeline* p, const void* dst
) const { | 401 void SkRasterPipelineBlitter::append_load_d(SkRasterPipeline* p, const void* dst
) const { |
348 SkASSERT(supported(fDst.info())); | 402 SkASSERT(supported(fDst.info())); |
349 | 403 |
350 switch (fDst.info().colorType()) { | 404 switch (fDst.info().colorType()) { |
351 case kN32_SkColorType: | 405 case kN32_SkColorType: |
352 if (fDst.info().gammaCloseToSRGB()) { | 406 if (fDst.info().gammaCloseToSRGB()) { |
353 p->append(load_d_srgb, load_d_srgb_1, dst); | 407 p->append(load_d_srgb, load_d_srgb_1, dst); |
354 } | 408 } |
355 break; | 409 break; |
| 410 case kRGBA_F16_SkColorType: |
| 411 p->append(load_d_f16, load_d_f16_1, dst); |
| 412 break; |
356 case kRGB_565_SkColorType: | 413 case kRGB_565_SkColorType: |
357 p->append(load_d_565, load_d_565_1, dst); | 414 p->append(load_d_565, load_d_565_1, dst); |
358 break; | 415 break; |
359 default: break; | 416 default: break; |
360 } | 417 } |
361 } | 418 } |
362 | 419 |
363 void SkRasterPipelineBlitter::append_store(SkRasterPipeline* p, void* dst) const
{ | 420 void SkRasterPipelineBlitter::append_store(SkRasterPipeline* p, void* dst) const
{ |
364 SkASSERT(supported(fDst.info())); | 421 SkASSERT(supported(fDst.info())); |
365 | 422 |
366 p->append(clamp_01_premul); | 423 p->append(clamp_01_premul); |
367 switch (fDst.info().colorType()) { | 424 switch (fDst.info().colorType()) { |
368 case kN32_SkColorType: | 425 case kN32_SkColorType: |
369 if (fDst.info().gammaCloseToSRGB()) { | 426 if (fDst.info().gammaCloseToSRGB()) { |
370 p->append(store_srgb, store_srgb_1, dst); | 427 p->append(store_srgb, store_srgb_1, dst); |
371 } | 428 } |
372 break; | 429 break; |
| 430 case kRGBA_F16_SkColorType: |
| 431 p->append(store_f16, store_f16_1, dst); |
| 432 break; |
373 case kRGB_565_SkColorType: | 433 case kRGB_565_SkColorType: |
374 p->append(store_565, store_565_1, dst); | 434 p->append(store_565, store_565_1, dst); |
375 break; | 435 break; |
376 default: break; | 436 default: break; |
377 } | 437 } |
378 } | 438 } |
379 | 439 |
380 void SkRasterPipelineBlitter::blitH(int x, int y, int w) { | 440 void SkRasterPipelineBlitter::blitH(int x, int y, int w) { |
381 auto dst = fDst.writable_addr(0,y); | 441 auto dst = fDst.writable_addr(0,y); |
382 | 442 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
434 case SkMask::kLCD16_Format: | 494 case SkMask::kLCD16_Format: |
435 p.append(lerp_lcd16, lerp_lcd16_1, mask.getAddrLCD16(x,y)-x); | 495 p.append(lerp_lcd16, lerp_lcd16_1, mask.getAddrLCD16(x,y)-x); |
436 break; | 496 break; |
437 default: break; | 497 default: break; |
438 } | 498 } |
439 this->append_store(&p, dst); | 499 this->append_store(&p, dst); |
440 | 500 |
441 p.run(x, clip.width()); | 501 p.run(x, clip.width()); |
442 } | 502 } |
443 } | 503 } |
OLD | NEW |