| 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 |