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 "SkPM4fPriv.h" 9 #include "SkUtils.h" 10 #include "SkXfermodePriv.h" 11 #include "Sk4x4f.h" 12 13 static SkPM4f rgba_to_pmcolor_order(const SkPM4f& x) { 14 #ifdef SK_PMCOLOR_IS_BGRA 15 return {{ x.fVec[2], x.fVec[1], x.fVec[0], x.fVec[3] }}; 16 #else 17 return x; 18 #endif 19 } 20 21 enum DstType { 22 kLinear_Dst, 23 kSRGB_Dst, 24 }; 25 26 static Sk4f scale_by_coverage(const Sk4f& x4, uint8_t coverage) { 27 return x4 * Sk4f(coverage * (1/255.0f)); 28 } 29 30 static Sk4f lerp(const Sk4f& src, const Sk4f& dst, uint8_t srcCoverage) { 31 return dst + (src - dst) * Sk4f(srcCoverage * (1/255.0f)); 32 } 33 34 template <DstType D> Sk4f load_dst(SkPMColor dstC) { 35 return (D == kSRGB_Dst) ? Sk4f_fromS32(dstC) : Sk4f_fromL32(dstC); 36 } 37 38 template <DstType D> uint32_t store_dst(const Sk4f& x4) { 39 return (D == kSRGB_Dst) ? Sk4f_toS32(x4) : Sk4f_toL32(x4); 40 } 41 42 static Sk4x4f load_4_srgb(const void* vptr) { 43 auto ptr = (const uint32_t*)vptr; 44 45 Sk4x4f rgba; 46 47 rgba.r = { sk_linear_from_srgb[(ptr[0] >> 0) & 0xff], 48 sk_linear_from_srgb[(ptr[1] >> 0) & 0xff], 49 sk_linear_from_srgb[(ptr[2] >> 0) & 0xff], 50 sk_linear_from_srgb[(ptr[3] >> 0) & 0xff] }; 51 52 rgba.g = { sk_linear_from_srgb[(ptr[0] >> 8) & 0xff], 53 sk_linear_from_srgb[(ptr[1] >> 8) & 0xff], 54 sk_linear_from_srgb[(ptr[2] >> 8) & 0xff], 55 sk_linear_from_srgb[(ptr[3] >> 8) & 0xff] }; 56 57 rgba.b = { sk_linear_from_srgb[(ptr[0] >> 16) & 0xff], 58 sk_linear_from_srgb[(ptr[1] >> 16) & 0xff], 59 sk_linear_from_srgb[(ptr[2] >> 16) & 0xff], 60 sk_linear_from_srgb[(ptr[3] >> 16) & 0xff] }; 61 62 rgba.a = SkNx_cast<float>((Sk4i::Load(ptr) >> 24) & 0xff) * (1/255.0f); 63 64 return rgba; 65 } 66 67 static void store_4_srgb(void* ptr, const Sk4x4f& p) { 68 ( sk_linear_to_srgb(p.r) << 0 69 | sk_linear_to_srgb(p.g) << 8 70 | sk_linear_to_srgb(p.b) << 16 71 | Sk4f_round(255.0f*p.a) << 24).store(ptr); 72 } 73 74 /////////////////////////////////////////////////////////////////////////////////////////////////// 75 76 template <DstType D> void general_1(SkBlendMode mode, uint32_t dst[], 77 const SkPM4f* src, int count, const SkAlpha aa[]) { 78 const SkPM4f s = rgba_to_pmcolor_order(*src); 79 SkXfermodeProc4f proc = SkXfermode::GetProc4f(mode); 80 SkPM4f d; 81 if (aa) { 82 for (int i = 0; i < count; ++i) { 83 Sk4f d4 = load_dst<D>(dst[i]); 84 d4.store(d.fVec); 85 Sk4f r4 = Sk4f::Load(proc(s, d).fVec); 86 dst[i] = store_dst<D>(lerp(r4, d4, aa[i])); 87 } 88 } else { 89 for (int i = 0; i < count; ++i) { 90 load_dst<D>(dst[i]).store(d.fVec); 91 Sk4f r4 = Sk4f::Load(proc(s, d).fVec); 92 dst[i] = store_dst<D>(r4); 93 } 94 } 95 } 96 97 template <DstType D> void general_n(SkBlendMode mode, uint32_t dst[], 98 const SkPM4f src[], int count, const SkAlpha aa[]) { 99 SkXfermodeProc4f proc = SkXfermode::GetProc4f(mode); 100 SkPM4f d; 101 if (aa) { 102 for (int i = 0; i < count; ++i) { 103 Sk4f d4 = load_dst<D>(dst[i]); 104 d4.store(d.fVec); 105 Sk4f r4 = Sk4f::Load(proc(rgba_to_pmcolor_order(src[i]), d).fVec); 106 dst[i] = store_dst<D>(lerp(r4, d4, aa[i])); 107 } 108 } else { 109 for (int i = 0; i < count; ++i) { 110 load_dst<D>(dst[i]).store(d.fVec); 111 Sk4f r4 = Sk4f::Load(proc(rgba_to_pmcolor_order(src[i]), d).fVec); 112 dst[i] = store_dst<D>(r4); 113 } 114 } 115 } 116 117 const SkXfermode::D32Proc gProcs_General[] = { 118 general_n<kLinear_Dst>, general_n<kLinear_Dst>, 119 general_1<kLinear_Dst>, general_1<kLinear_Dst>, 120 general_n<kSRGB_Dst>, general_n<kSRGB_Dst>, 121 general_1<kSRGB_Dst>, general_1<kSRGB_Dst>, 122 }; 123 124 /////////////////////////////////////////////////////////////////////////////////////////////////// 125 126 static void clear_linear(SkBlendMode, uint32_t dst[], const SkPM4f[], int count, 127 const SkAlpha aa[]) { 128 if (aa) { 129 for (int i = 0; i < count; ++i) { 130 unsigned a = aa[i]; 131 if (a) { 132 SkPMColor dstC = dst[i]; 133 SkPMColor C = 0; 134 if (0xFF != a) { 135 C = SkFourByteInterp(C, dstC, a); 136 } 137 dst[i] = C; 138 } 139 } 140 } else { 141 sk_memset32(dst, 0, count); 142 } 143 } 144 145 static void clear_srgb(SkBlendMode, uint32_t dst[], const SkPM4f[], int count, const SkAlpha aa[]) { 146 if (aa) { 147 for (int i = 0; i < count; ++i) { 148 if (aa[i]) { 149 Sk4f d = Sk4f_fromS32(dst[i]) * Sk4f((255 - aa[i]) * (1/255.0f)); 150 dst[i] = Sk4f_toS32(d); 151 } 152 } 153 } else { 154 sk_memset32(dst, 0, count); 155 } 156 } 157 158 const SkXfermode::D32Proc gProcs_Clear[] = { 159 clear_linear, clear_linear, 160 clear_linear, clear_linear, 161 clear_srgb, clear_srgb, 162 clear_srgb, clear_srgb, 163 }; 164 165 /////////////////////////////////////////////////////////////////////////////////////////////////// 166 167 template <DstType D> void src_n(SkBlendMode, uint32_t dst[], const SkPM4f src[], int count, 168 const SkAlpha aa[]) { 169 for (int i = 0; i < count; ++i) { 170 unsigned a = 0xFF; 171 if (aa) { 172 a = aa[i]; 173 if (0 == a) { 174 continue; 175 } 176 } 177 Sk4f r4 = src[i].to4f_pmorder(); 178 if (a != 0xFF) { 179 Sk4f d4 = load_dst<D>(dst[i]); 180 r4 = lerp(r4, d4, a); 181 } 182 dst[i] = store_dst<D>(r4); 183 } 184 } 185 186 static Sk4f lerp(const Sk4f& src, const Sk4f& dst, const Sk4f& src_scale) { 187 return dst + (src - dst) * src_scale; 188 } 189 190 template <DstType D> void src_1(SkBlendMode, uint32_t dst[], const SkPM4f* src, int count, 191 const SkAlpha aa[]) { 192 const Sk4f s4 = src->to4f_pmorder(); 193 194 if (aa) { 195 SkPMColor srcColor = store_dst<D>(s4); 196 while (count-- > 0) { 197 SkAlpha cover = *aa++; 198 switch (cover) { 199 case 0xFF: { 200 *dst++ = srcColor; 201 break; 202 } 203 case 0x00: { 204 dst++; 205 break; 206 } 207 default: { 208 Sk4f d4 = load_dst<D>(*dst); 209 *dst++ = store_dst<D>(lerp(s4, d4, cover)); 210 } 211 } 212 } 213 } else { 214 sk_memset32(dst, store_dst<D>(s4), count); 215 } 216 } 217 218 const SkXfermode::D32Proc gProcs_Src[] = { 219 src_n<kLinear_Dst>, src_n<kLinear_Dst>, 220 src_1<kLinear_Dst>, src_1<kLinear_Dst>, 221 src_n<kSRGB_Dst>, src_n<kSRGB_Dst>, 222 src_1<kSRGB_Dst>, src_1<kSRGB_Dst>, 223 }; 224 225 /////////////////////////////////////////////////////////////////////////////////////////////////// 226 227 static void dst(SkBlendMode, uint32_t dst[], const SkPM4f[], int count, const SkAlpha aa[]) {} 228 229 const SkXfermode::D32Proc gProcs_Dst[] = { 230 dst, dst, dst, dst, dst, dst, dst, dst, 231 }; 232 233 /////////////////////////////////////////////////////////////////////////////////////////////////// 234 235 236 template <DstType D> void srcover_n(SkBlendMode, uint32_t dst[], const SkPM4f src[], int count, 237 const SkAlpha aa[]) { 238 if (aa) { 239 for (int i = 0; i < count; ++i) { 240 unsigned a = aa[i]; 241 if (0 == a) { 242 continue; 243 } 244 Sk4f s4 = src[i].to4f_pmorder(); 245 Sk4f d4 = load_dst<D>(dst[i]); 246 if (a != 0xFF) { 247 s4 = scale_by_coverage(s4, a); 248 } 249 Sk4f r4 = s4 + d4 * Sk4f(1 - get_alpha(s4)); 250 dst[i] = store_dst<D>(r4); 251 } 252 } else { 253 while (count >= 4 && D == kSRGB_Dst) { 254 auto d = load_4_srgb(dst); 255 auto s = Sk4x4f::Transpose(src->fVec); 256 #if defined(SK_PMCOLOR_IS_BGRA) 257 SkTSwap(s.r, s.b); 258 #endif 259 auto invSA = 1.0f - s.a; 260 auto r = s.r + d.r * invSA, 261 g = s.g + d.g * invSA, 262 b = s.b + d.b * invSA, 263 a = s.a + d.a * invSA; 264 store_4_srgb(dst, Sk4x4f{r,g,b,a}); 265 count -= 4; 266 dst += 4; 267 src += 4; 268 } 269 for (int i = 0; i < count; ++i) { 270 Sk4f s4 = src[i].to4f_pmorder(); 271 Sk4f d4 = load_dst<D>(dst[i]); 272 Sk4f r4 = s4 + d4 * Sk4f(1 - get_alpha(s4)); 273 dst[i] = store_dst<D>(r4); 274 } 275 } 276 } 277 278 static void srcover_linear_dst_1(SkBlendMode, uint32_t dst[], const SkPM4f* src, int count, 279 const SkAlpha aa[]) { 280 const Sk4f s4 = src->to4f_pmorder(); 281 const Sk4f dst_scale = Sk4f(1 - get_alpha(s4)); 282 283 if (aa) { 284 for (int i = 0; i < count; ++i) { 285 unsigned a = aa[i]; 286 if (0 == a) { 287 continue; 288 } 289 Sk4f d4 = Sk4f_fromL32(dst[i]); 290 Sk4f r4; 291 if (a != 0xFF) { 292 Sk4f s4_aa = scale_by_coverage(s4, a); 293 r4 = s4_aa + d4 * Sk4f(1 - get_alpha(s4_aa)); 294 } else { 295 r4 = s4 + d4 * dst_scale; 296 } 297 dst[i] = Sk4f_toL32(r4); 298 } 299 } else { 300 for (int i = 0; i < count; ++i) { 301 Sk4f d4 = Sk4f_fromL32(dst[i]); 302 dst[i] = Sk4f_toL32(s4 + d4 * dst_scale); 303 } 304 } 305 } 306 307 static void srcover_srgb_dst_1(SkBlendMode, uint32_t dst[], const SkPM4f* src, int count, 308 const SkAlpha aa[]) { 309 Sk4f s4 = src->to4f_pmorder(); 310 Sk4f dst_scale = Sk4f(1 - get_alpha(s4)); 311 312 if (aa) { 313 for (int i = 0; i < count; ++i) { 314 unsigned a = aa[i]; 315 if (0 == a) { 316 continue; 317 } 318 319 Sk4f d4 = Sk4f_fromS32(dst[i]); 320 Sk4f r4; 321 if (a != 0xFF) { 322 const Sk4f s4_aa = scale_by_coverage(s4, a); 323 r4 = s4_aa + d4 * Sk4f(1 - get_alpha(s4_aa)); 324 } else { 325 r4 = s4 + d4 * dst_scale; 326 } 327 dst[i] = Sk4f_toS32(r4); 328 } 329 } else { 330 while (count >= 4) { 331 auto d = load_4_srgb(dst); 332 auto s = Sk4x4f{{ src->r() }, { src->g() }, { src->b() }, { src->a() }}; 333 #if defined(SK_PMCOLOR_IS_BGRA) 334 SkTSwap(s.r, s.b); 335 #endif 336 auto invSA = 1.0f - s.a; 337 auto r = s.r + d.r * invSA, 338 g = s.g + d.g * invSA, 339 b = s.b + d.b * invSA, 340 a = s.a + d.a * invSA; 341 store_4_srgb(dst, Sk4x4f{r,g,b,a}); 342 count -= 4; 343 dst += 4; 344 } 345 for (int i = 0; i < count; ++i) { 346 Sk4f d4 = Sk4f_fromS32(dst[i]); 347 dst[i] = Sk4f_toS32(s4 + d4 * dst_scale); 348 } 349 } 350 } 351 352 const SkXfermode::D32Proc gProcs_SrcOver[] = { 353 srcover_n<kLinear_Dst>, src_n<kLinear_Dst>, 354 srcover_linear_dst_1, src_1<kLinear_Dst>, 355 356 srcover_n<kSRGB_Dst>, src_n<kSRGB_Dst>, 357 srcover_srgb_dst_1, src_1<kSRGB_Dst>, 358 }; 359 360 /////////////////////////////////////////////////////////////////////////////////////////////////// 361 362 SkXfermode::D32Proc SkXfermode::GetD32Proc(SkBlendMode mode, uint32_t flags) { 363 SkASSERT(0 == (flags & ~7)); 364 flags &= 7; 365 366 switch (mode) { 367 case SkBlendMode::kClear: return gProcs_Clear[flags]; 368 case SkBlendMode::kSrc: return gProcs_Src[flags]; 369 case SkBlendMode::kDst: return gProcs_Dst[flags]; 370 case SkBlendMode::kSrcOver: return gProcs_SrcOver[flags]; 371 default: 372 break; 373 } 374 return gProcs_General[flags]; 375 } 376 377 /////////////////////////////////////////////////////////////////////////////////////////////////// 378 #include "SkColorPriv.h" 379 380 static Sk4f lcd16_to_unit_4f(uint16_t rgb) { 381 #ifdef SK_PMCOLOR_IS_RGBA 382 Sk4i rgbi = Sk4i(SkGetPackedR16(rgb), SkGetPackedG16(rgb), SkGetPackedB16(rgb), 0); 383 #else 384 Sk4i rgbi = Sk4i(SkGetPackedB16(rgb), SkGetPackedG16(rgb), SkGetPackedR16(rgb), 0); 385 #endif 386 return SkNx_cast<float>(rgbi) * Sk4f(1.0f/31, 1.0f/63, 1.0f/31, 0); 387 } 388 389 template <DstType D> 390 void src_1_lcd(uint32_t dst[], const SkPM4f* src, int count, const uint16_t lcd[]) { 391 const Sk4f s4 = src->to4f_pmorder(); 392 393 for (int i = 0; i < count; ++i) { 394 uint16_t rgb = lcd[i]; 395 if (0 == rgb) { 396 continue; 397 } 398 Sk4f d4 = load_dst<D>(dst[i]); 399 dst[i] = store_dst<D>(lerp(s4, d4, lcd16_to_unit_4f(rgb))) | (SK_A32_MASK << SK_A32_SHIFT); 400 } 401 } 402 403 template <DstType D> 404 void src_n_lcd(uint32_t dst[], const SkPM4f src[], int count, const uint16_t lcd[]) { 405 for (int i = 0; i < count; ++i) { 406 uint16_t rgb = lcd[i]; 407 if (0 == rgb) { 408 continue; 409 } 410 Sk4f s4 = src[i].to4f_pmorder(); 411 Sk4f d4 = load_dst<D>(dst[i]); 412 dst[i] = store_dst<D>(lerp(s4, d4, lcd16_to_unit_4f(rgb))) | (SK_A32_MASK << SK_A32_SHIFT); 413 } 414 } 415 416 template <DstType D> 417 void srcover_1_lcd(uint32_t dst[], const SkPM4f* src, int count, const uint16_t lcd[]) { 418 const Sk4f s4 = src->to4f_pmorder(); 419 Sk4f dst_scale = Sk4f(1 - get_alpha(s4)); 420 421 for (int i = 0; i < count; ++i) { 422 uint16_t rgb = lcd[i]; 423 if (0 == rgb) { 424 continue; 425 } 426 Sk4f d4 = load_dst<D>(dst[i]); 427 Sk4f r4 = s4 + d4 * dst_scale; 428 r4 = lerp(r4, d4, lcd16_to_unit_4f(rgb)); 429 dst[i] = store_dst<D>(r4) | (SK_A32_MASK << SK_A32_SHIFT); 430 } 431 } 432 433 template <DstType D> 434 void srcover_n_lcd(uint32_t dst[], const SkPM4f src[], int count, const uint16_t lcd[]) { 435 for (int i = 0; i < count; ++i) { 436 uint16_t rgb = lcd[i]; 437 if (0 == rgb) { 438 continue; 439 } 440 Sk4f s4 = src[i].to4f_pmorder(); 441 Sk4f dst_scale = Sk4f(1 - get_alpha(s4)); 442 Sk4f d4 = load_dst<D>(dst[i]); 443 Sk4f r4 = s4 + d4 * dst_scale; 444 r4 = lerp(r4, d4, lcd16_to_unit_4f(rgb)); 445 dst[i] = store_dst<D>(r4) | (SK_A32_MASK << SK_A32_SHIFT); 446 } 447 } 448 449 SkXfermode::LCD32Proc SkXfermode::GetLCD32Proc(uint32_t flags) { 450 SkASSERT((flags & ~7) == 0); 451 flags &= 7; 452 453 const LCD32Proc procs[] = { 454 srcover_n_lcd<kLinear_Dst>, src_n_lcd<kLinear_Dst>, 455 srcover_1_lcd<kLinear_Dst>, src_1_lcd<kLinear_Dst>, 456 457 srcover_n_lcd<kSRGB_Dst>, src_n_lcd<kSRGB_Dst>, 458 srcover_1_lcd<kSRGB_Dst>, src_1_lcd<kSRGB_Dst>, 459 }; 460 return procs[flags]; 461 } 462