| 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 "SkPM4fPriv.h" | 8 #include "SkPM4fPriv.h" |
| 9 #include "SkUtils.h" | 9 #include "SkUtils.h" |
| 10 #include "SkXfermode.h" | 10 #include "SkXfermode.h" |
| (...skipping 29 matching lines...) Expand all Loading... |
| 40 } | 40 } |
| 41 | 41 |
| 42 template <DstType D> uint32_t store_dst(const Sk4f& x4) { | 42 template <DstType D> uint32_t store_dst(const Sk4f& x4) { |
| 43 return (D == kSRGB_Dst) ? Sk4f_toS32(x4) : Sk4f_toL32(x4); | 43 return (D == kSRGB_Dst) ? Sk4f_toS32(x4) : Sk4f_toL32(x4); |
| 44 } | 44 } |
| 45 | 45 |
| 46 static Sk4f linear_unit_to_srgb_255f(const Sk4f& l4) { | 46 static Sk4f linear_unit_to_srgb_255f(const Sk4f& l4) { |
| 47 return linear_to_srgb(l4) * Sk4f(255) + Sk4f(0.5f); | 47 return linear_to_srgb(l4) * Sk4f(255) + Sk4f(0.5f); |
| 48 } | 48 } |
| 49 | 49 |
| 50 // Load 4 interlaced 8888 sRGB pixels as an Sk4x4f, transposed and converted to
float. |
| 51 static Sk4x4f load_4_srgb(const void* ptr) { |
| 52 auto p = Sk4x4f::Transpose((const uint8_t*)ptr); |
| 53 |
| 54 // Scale to [0,1]. |
| 55 p.r *= 1/255.0f; |
| 56 p.g *= 1/255.0f; |
| 57 p.b *= 1/255.0f; |
| 58 p.a *= 1/255.0f; |
| 59 |
| 60 // Apply approximate sRGB gamma correction to convert to linear (as if gamma
were 2). |
| 61 p.r *= p.r; |
| 62 p.g *= p.g; |
| 63 p.b *= p.b; |
| 64 |
| 65 return p; |
| 66 } |
| 67 |
| 68 // Store an Sk4x4f back to 4 interlaced 8888 sRGB pixels. |
| 69 static void store_4_srgb(void* ptr, const Sk4x4f& p) { |
| 70 // Convert back to sRGB and [0,255], again approximating sRGB as gamma == 2. |
| 71 auto r = p.r.sqrt() * 255.0f + 0.5f, |
| 72 g = p.g.sqrt() * 255.0f + 0.5f, |
| 73 b = p.b.sqrt() * 255.0f + 0.5f, |
| 74 a = p.a * 255.0f + 0.5f; |
| 75 Sk4x4f{r,g,b,a}.transpose((uint8_t*)ptr); |
| 76 } |
| 77 |
| 50 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 78 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
| 51 | 79 |
| 52 template <DstType D> void general_1(const SkXfermode* xfer, uint32_t dst[], | 80 template <DstType D> void general_1(const SkXfermode* xfer, uint32_t dst[], |
| 53 const SkPM4f* src, int count, const SkAlpha
aa[]) { | 81 const SkPM4f* src, int count, const SkAlpha
aa[]) { |
| 54 const SkPM4f s = rgba_to_pmcolor_order(*src); | 82 const SkPM4f s = rgba_to_pmcolor_order(*src); |
| 55 SkXfermodeProc4f proc = xfer->getProc4f(); | 83 SkXfermodeProc4f proc = xfer->getProc4f(); |
| 56 SkPM4f d; | 84 SkPM4f d; |
| 57 if (aa) { | 85 if (aa) { |
| 58 for (int i = 0; i < count; ++i) { | 86 for (int i = 0; i < count; ++i) { |
| 59 Sk4f d4 = load_dst<D>(dst[i]); | 87 Sk4f d4 = load_dst<D>(dst[i]); |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 | 256 |
| 229 static void dst(const SkXfermode*, uint32_t dst[], const SkPM4f[], int count, co
nst SkAlpha aa[]) {} | 257 static void dst(const SkXfermode*, uint32_t dst[], const SkPM4f[], int count, co
nst SkAlpha aa[]) {} |
| 230 | 258 |
| 231 const SkXfermode::D32Proc gProcs_Dst[] = { | 259 const SkXfermode::D32Proc gProcs_Dst[] = { |
| 232 dst, dst, dst, dst, dst, dst, dst, dst, | 260 dst, dst, dst, dst, dst, dst, dst, dst, |
| 233 }; | 261 }; |
| 234 | 262 |
| 235 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 263 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
| 236 | 264 |
| 237 | 265 |
| 238 static void srcover_n_srgb_bw(uint32_t dst[], const SkPM4f src[], int count) { | |
| 239 while (count >= 4) { | |
| 240 // Load 4 sRGB RGBA/BGRA 8888 dst pixels. | |
| 241 // We'll write most of this as if they're RGBA, and just swizzle the src
pixels to match. | |
| 242 auto d = Sk4x4f::Transpose((const uint8_t*)dst); | |
| 243 | |
| 244 // Scale to [0,1]. | |
| 245 d.r *= 1/255.0f; | |
| 246 d.g *= 1/255.0f; | |
| 247 d.b *= 1/255.0f; | |
| 248 d.a *= 1/255.0f; | |
| 249 | |
| 250 // Apply approximate sRGB gamma correction to convert to linear (as if g
amma were 2). | |
| 251 d.r *= d.r; | |
| 252 d.g *= d.g; | |
| 253 d.b *= d.b; | |
| 254 | |
| 255 // Load 4 linear float src pixels. | |
| 256 auto s = Sk4x4f::Transpose(src->fVec); | |
| 257 | |
| 258 // Match color order with destination, if necessary. | |
| 259 #if defined(SK_PMCOLOR_IS_BGRA) | |
| 260 SkTSwap(s.r, s.b); | |
| 261 #endif | |
| 262 | |
| 263 // Now, the meat of what we wanted to do... perform the srcover blend. | |
| 264 auto invSA = 1.0f - s.a; | |
| 265 auto r = s.r + d.r * invSA, | |
| 266 g = s.g + d.g * invSA, | |
| 267 b = s.b + d.b * invSA, | |
| 268 a = s.a + d.a * invSA; | |
| 269 | |
| 270 // Convert back to sRGB and [0,255], again approximating sRGB as gamma =
= 2. | |
| 271 r = r.sqrt() * 255.0f + 0.5f; | |
| 272 g = g.sqrt() * 255.0f + 0.5f; | |
| 273 b = b.sqrt() * 255.0f + 0.5f; | |
| 274 a = a * 255.0f + 0.5f; | |
| 275 | |
| 276 Sk4x4f{r,g,b,a}.transpose((uint8_t*)dst); | |
| 277 | |
| 278 count -= 4; | |
| 279 dst += 4; | |
| 280 src += 4; | |
| 281 } | |
| 282 | |
| 283 // This should look just like the non-specialized case in srcover_n. | |
| 284 for (int i = 0; i < count; ++i) { | |
| 285 Sk4f s4 = src[i].to4f_pmorder(); | |
| 286 Sk4f d4 = load_dst<kSRGB_Dst>(dst[i]); | |
| 287 Sk4f r4 = s4 + d4 * Sk4f(1 - get_alpha(s4)); | |
| 288 dst[i] = store_dst<kSRGB_Dst>(r4); | |
| 289 } | |
| 290 } | |
| 291 | |
| 292 template <DstType D> void srcover_n(const SkXfermode*, uint32_t dst[], | 266 template <DstType D> void srcover_n(const SkXfermode*, uint32_t dst[], |
| 293 const SkPM4f src[], int count, const SkAlpha
aa[]) { | 267 const SkPM4f src[], int count, const SkAlpha
aa[]) { |
| 294 if (aa) { | 268 if (aa) { |
| 295 for (int i = 0; i < count; ++i) { | 269 for (int i = 0; i < count; ++i) { |
| 296 unsigned a = aa[i]; | 270 unsigned a = aa[i]; |
| 297 if (0 == a) { | 271 if (0 == a) { |
| 298 continue; | 272 continue; |
| 299 } | 273 } |
| 300 Sk4f s4 = src[i].to4f_pmorder(); | 274 Sk4f s4 = src[i].to4f_pmorder(); |
| 301 Sk4f d4 = load_dst<D>(dst[i]); | 275 Sk4f d4 = load_dst<D>(dst[i]); |
| 302 if (a != 0xFF) { | 276 if (a != 0xFF) { |
| 303 s4 = scale_by_coverage(s4, a); | 277 s4 = scale_by_coverage(s4, a); |
| 304 } | 278 } |
| 305 Sk4f r4 = s4 + d4 * Sk4f(1 - get_alpha(s4)); | 279 Sk4f r4 = s4 + d4 * Sk4f(1 - get_alpha(s4)); |
| 306 dst[i] = store_dst<D>(r4); | 280 dst[i] = store_dst<D>(r4); |
| 307 } | 281 } |
| 308 } else { | 282 } else { |
| 309 if (D == kSRGB_Dst) { | 283 while (count >= 4 && D == kSRGB_Dst) { |
| 310 srcover_n_srgb_bw(dst, src, count); | 284 auto d = load_4_srgb(dst); |
| 311 } else { | 285 |
| 312 for (int i = 0; i < count; ++i) { | 286 auto s = Sk4x4f::Transpose(src->fVec); |
| 313 Sk4f s4 = src[i].to4f_pmorder(); | 287 #if defined(SK_PMCOLOR_IS_BGRA) |
| 314 Sk4f d4 = load_dst<D>(dst[i]); | 288 SkTSwap(s.r, s.b); |
| 315 Sk4f r4 = s4 + d4 * Sk4f(1 - get_alpha(s4)); | 289 #endif |
| 316 dst[i] = store_dst<D>(r4); | 290 |
| 317 } | 291 auto invSA = 1.0f - s.a; |
| 292 auto r = s.r + d.r * invSA, |
| 293 g = s.g + d.g * invSA, |
| 294 b = s.b + d.b * invSA, |
| 295 a = s.a + d.a * invSA; |
| 296 |
| 297 store_4_srgb(dst, Sk4x4f{r,g,b,a}); |
| 298 count -= 4; |
| 299 dst += 4; |
| 300 src += 4; |
| 301 } |
| 302 for (int i = 0; i < count; ++i) { |
| 303 Sk4f s4 = src[i].to4f_pmorder(); |
| 304 Sk4f d4 = load_dst<D>(dst[i]); |
| 305 Sk4f r4 = s4 + d4 * Sk4f(1 - get_alpha(s4)); |
| 306 dst[i] = store_dst<D>(r4); |
| 318 } | 307 } |
| 319 } | 308 } |
| 320 } | 309 } |
| 321 | 310 |
| 322 static void srcover_linear_dst_1(const SkXfermode*, uint32_t dst[], | 311 static void srcover_linear_dst_1(const SkXfermode*, uint32_t dst[], |
| 323 const SkPM4f* src, int count, const SkAlpha aa[
]) { | 312 const SkPM4f* src, int count, const SkAlpha aa[
]) { |
| 324 const Sk4f s4 = src->to4f_pmorder(); | 313 const Sk4f s4 = src->to4f_pmorder(); |
| 325 const Sk4f dst_scale = Sk4f(1 - get_alpha(s4)); | 314 const Sk4f dst_scale = Sk4f(1 - get_alpha(s4)); |
| 326 | 315 |
| 327 if (aa) { | 316 if (aa) { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 378 if (a != 0xFF) { | 367 if (a != 0xFF) { |
| 379 const Sk4f s4_aa = scale_by_coverage(s4, a); | 368 const Sk4f s4_aa = scale_by_coverage(s4, a); |
| 380 r4 = s4_aa + d4 * Sk4f(1 - get_alpha(s4_aa)); | 369 r4 = s4_aa + d4 * Sk4f(1 - get_alpha(s4_aa)); |
| 381 } else { | 370 } else { |
| 382 r4 = s4 + d4 * dst_scale; | 371 r4 = s4 + d4 * dst_scale; |
| 383 } | 372 } |
| 384 dst[i] = to_4b(linear_unit_to_srgb_255f(r4)); | 373 dst[i] = to_4b(linear_unit_to_srgb_255f(r4)); |
| 385 } | 374 } |
| 386 } else { | 375 } else { |
| 387 while (count >= 4) { | 376 while (count >= 4) { |
| 388 Sk4f d0 = srgb_4b_to_linear_unit(dst[0]); | 377 auto d = load_4_srgb(dst); |
| 389 Sk4f d1 = srgb_4b_to_linear_unit(dst[1]); | 378 |
| 390 Sk4f d2 = srgb_4b_to_linear_unit(dst[2]); | 379 auto s = Sk4x4f{{ src->r() }, { src->g() }, { src->b() }, { src->a()
}}; |
| 391 Sk4f d3 = srgb_4b_to_linear_unit(dst[3]); | 380 #if defined(SK_PMCOLOR_IS_BGRA) |
| 392 Sk4f_ToBytes((uint8_t*)dst, | 381 SkTSwap(s.r, s.b); |
| 393 linear_unit_to_srgb_255f(s4 + d0 * dst_scale), | 382 #endif |
| 394 linear_unit_to_srgb_255f(s4 + d1 * dst_scale), | 383 |
| 395 linear_unit_to_srgb_255f(s4 + d2 * dst_scale), | 384 auto invSA = 1.0f - s.a; |
| 396 linear_unit_to_srgb_255f(s4 + d3 * dst_scale)); | 385 auto r = s.r + d.r * invSA, |
| 386 g = s.g + d.g * invSA, |
| 387 b = s.b + d.b * invSA, |
| 388 a = s.a + d.a * invSA; |
| 389 |
| 390 store_4_srgb(dst, Sk4x4f{r,g,b,a}); |
| 391 count -= 4; |
| 397 dst += 4; | 392 dst += 4; |
| 398 count -= 4; | |
| 399 } | 393 } |
| 400 for (int i = 0; i < count; ++i) { | 394 for (int i = 0; i < count; ++i) { |
| 401 Sk4f d4 = srgb_4b_to_linear_unit(dst[i]); | 395 Sk4f d4 = srgb_4b_to_linear_unit(dst[i]); |
| 402 dst[i] = to_4b(linear_unit_to_srgb_255f(s4 + d4 * dst_scale)); | 396 dst[i] = to_4b(linear_unit_to_srgb_255f(s4 + d4 * dst_scale)); |
| 403 } | 397 } |
| 404 } | 398 } |
| 405 } | 399 } |
| 406 | 400 |
| 407 const SkXfermode::D32Proc gProcs_SrcOver[] = { | 401 const SkXfermode::D32Proc gProcs_SrcOver[] = { |
| 408 srcover_n<kLinear_Dst>, src_n<kLinear_Dst>, | 402 srcover_n<kLinear_Dst>, src_n<kLinear_Dst>, |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 532 | 526 |
| 533 const LCD32Proc procs[] = { | 527 const LCD32Proc procs[] = { |
| 534 srcover_n_lcd<kSRGB_Dst>, src_n_lcd<kSRGB_Dst>, | 528 srcover_n_lcd<kSRGB_Dst>, src_n_lcd<kSRGB_Dst>, |
| 535 srcover_1_lcd<kSRGB_Dst>, src_1_lcd<kSRGB_Dst>, | 529 srcover_1_lcd<kSRGB_Dst>, src_1_lcd<kSRGB_Dst>, |
| 536 | 530 |
| 537 srcover_n_lcd<kLinear_Dst>, src_n_lcd<kLinear_Dst>, | 531 srcover_n_lcd<kLinear_Dst>, src_n_lcd<kLinear_Dst>, |
| 538 srcover_1_lcd<kLinear_Dst>, src_1_lcd<kLinear_Dst>, | 532 srcover_1_lcd<kLinear_Dst>, src_1_lcd<kLinear_Dst>, |
| 539 }; | 533 }; |
| 540 return procs[flags]; | 534 return procs[flags]; |
| 541 } | 535 } |
| OLD | NEW |