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 "SkHalf.h" 9 #include "SkPM4fPriv.h" 10 #include "SkUtils.h" 11 #include "SkXfermode.h" 12 13 static void sk_memset64(uint64_t dst[], uint64_t value, int count) { 14 for (int i = 0; i < count; ++i) { 15 dst[i] = value; 16 } 17 } 18 19 enum DstType { 20 kU16_Dst, 21 kF16_Dst, 22 }; 23 24 static Sk4f lerp_by_coverage(const Sk4f& src, const Sk4f& dst, uint8_t srcCoverage) { 25 return dst + (src - dst) * Sk4f(srcCoverage * (1/255.0f)); 26 } 27 28 template <DstType D> Sk4f unit_to_bias(const Sk4f& x4) { 29 return (D == kU16_Dst) ? x4 * Sk4f(65535) : x4; 30 } 31 32 template <DstType D> Sk4f bias_to_unit(const Sk4f& x4) { 33 return (D == kU16_Dst) ? x4 * Sk4f(1.0f/65535) : x4; 34 } 35 36 // returns value already biased by 65535 37 static Sk4f load_from_u16(uint64_t value) { 38 return SkNx_cast<float>(Sk4h::Load(&value)); 39 } 40 41 // takes floats already biased by 65535 42 static uint64_t store_to_u16(const Sk4f& x4) { 43 uint64_t value; 44 SkNx_cast<uint16_t>(x4 + Sk4f(0.5f)).store(&value); 45 return value; 46 } 47 48 // Returns dst in its "natural" bias (either unit-float or 16bit int) 49 // 50 template <DstType D> Sk4f load_from_dst(uint64_t dst) { 51 return (D == kU16_Dst) ? load_from_u16(dst) : SkHalfToFloat_01(dst); 52 } 53 54 // Assumes x4 is already in the "natural" bias (either unit-float or 16bit int) 55 template <DstType D> uint64_t store_to_dst(const Sk4f& x4) { 56 return (D == kU16_Dst) ? store_to_u16(x4) : SkFloatToHalf_01(x4); 57 } 58 59 static inline Sk4f pm_to_rgba_order(const Sk4f& x) { 60 if (SkPM4f::R == 0) { 61 return x; // we're already RGBA 62 } else { 63 // we're BGRA, so swap R and B 64 return SkNx_shuffle<2, 1, 0, 3>(x); 65 } 66 } 67 68 /////////////////////////////////////////////////////////////////////////////////////////////////// 69 70 template <DstType D> void xfer_u64_1(const SkXfermode* xfer, uint64_t dst[], 71 const SkPM4f* src, int count, const SkAlpha aa[]) { 72 SkXfermodeProc4f proc = xfer->getProc4f(); 73 SkPM4f d; 74 if (aa) { 75 for (int i = 0; i < count; ++i) { 76 Sk4f d4 = bias_to_unit<D>(load_from_dst<D>(dst[i])); 77 d4.store(d.fVec); 78 Sk4f r4 = unit_to_bias<D>(Sk4f::Load(proc(*src, d).fVec)); 79 dst[i] = store_to_dst<D>(lerp_by_coverage(r4, d4, aa[i])); 80 } 81 } else { 82 for (int i = 0; i < count; ++i) { 83 bias_to_unit<D>(load_from_dst<D>(dst[i])).store(d.fVec); 84 Sk4f r4 = unit_to_bias<D>(Sk4f::Load(proc(*src, d).fVec)); 85 dst[i] = store_to_dst<D>(r4); 86 } 87 } 88 } 89 90 template <DstType D> void xfer_u64_n(const SkXfermode* xfer, uint64_t dst[], 91 const SkPM4f src[], int count, const SkAlpha aa[]) { 92 SkXfermodeProc4f proc = xfer->getProc4f(); 93 SkPM4f d; 94 if (aa) { 95 for (int i = 0; i < count; ++i) { 96 Sk4f d4 = bias_to_unit<D>(load_from_dst<D>(dst[i])); 97 d4.store(d.fVec); 98 Sk4f r4 = unit_to_bias<D>(Sk4f::Load(proc(src[i], d).fVec)); 99 dst[i] = store_to_dst<D>(lerp_by_coverage(r4, d4, aa[i])); 100 } 101 } else { 102 for (int i = 0; i < count; ++i) { 103 bias_to_unit<D>(load_from_dst<D>(dst[i])).store(d.fVec); 104 Sk4f r4 = unit_to_bias<D>(Sk4f::Load(proc(src[i], d).fVec)); 105 dst[i] = store_to_dst<D>(r4); 106 } 107 } 108 } 109 110 const SkXfermode::D64Proc gProcs_General[] = { 111 xfer_u64_n<kU16_Dst>, xfer_u64_n<kU16_Dst>, 112 xfer_u64_1<kU16_Dst>, xfer_u64_1<kU16_Dst>, 113 xfer_u64_n<kF16_Dst>, xfer_u64_n<kF16_Dst>, 114 xfer_u64_1<kF16_Dst>, xfer_u64_1<kF16_Dst>, 115 }; 116 117 /////////////////////////////////////////////////////////////////////////////////////////////////// 118 119 template <DstType D> void clear(const SkXfermode*, uint64_t dst[], 120 const SkPM4f*, int count, const SkAlpha aa[]) { 121 if (aa) { 122 for (int i = 0; i < count; ++i) { 123 if (aa[i]) { 124 const Sk4f d4 = load_from_dst<D>(dst[i]); 125 dst[i] = store_to_dst<D>(d4 * Sk4f((255 - aa[i]) * 1.0f/255)); 126 } 127 } 128 } else { 129 sk_memset64(dst, 0, count); 130 } 131 } 132 133 const SkXfermode::D64Proc gProcs_Clear[] = { 134 clear<kU16_Dst>, clear<kU16_Dst>, 135 clear<kU16_Dst>, clear<kU16_Dst>, 136 clear<kF16_Dst>, clear<kF16_Dst>, 137 clear<kF16_Dst>, clear<kF16_Dst>, 138 }; 139 140 /////////////////////////////////////////////////////////////////////////////////////////////////// 141 142 template <DstType D> void src_1(const SkXfermode*, uint64_t dst[], 143 const SkPM4f* src, int count, const SkAlpha aa[]) { 144 const Sk4f s4 = pm_to_rgba_order(unit_to_bias<D>(Sk4f::Load(src->fVec))); 145 if (aa) { 146 for (int i = 0; i < count; ++i) { 147 const Sk4f d4 = load_from_dst<D>(dst[i]); 148 dst[i] = store_to_dst<D>(lerp_by_coverage(s4, d4, aa[i])); 149 } 150 } else { 151 sk_memset64(dst, store_to_dst<D>(s4), count); 152 } 153 } 154 155 template <DstType D> void src_n(const SkXfermode*, uint64_t dst[], 156 const SkPM4f src[], int count, const SkAlpha aa[]) { 157 if (aa) { 158 for (int i = 0; i < count; ++i) { 159 const Sk4f s4 = pm_to_rgba_order(unit_to_bias<D>(Sk4f::Load(src[i].fVec))); 160 const Sk4f d4 = load_from_dst<D>(dst[i]); 161 dst[i] = store_to_dst<D>(lerp_by_coverage(s4, d4, aa[i])); 162 } 163 } else { 164 for (int i = 0; i < count; ++i) { 165 const Sk4f s4 = pm_to_rgba_order(unit_to_bias<D>(Sk4f::Load(src[i].fVec))); 166 dst[i] = store_to_dst<D>(s4); 167 } 168 } 169 } 170 171 const SkXfermode::D64Proc gProcs_Src[] = { 172 src_n<kU16_Dst>, src_n<kU16_Dst>, 173 src_1<kU16_Dst>, src_1<kU16_Dst>, 174 src_n<kF16_Dst>, src_n<kF16_Dst>, 175 src_1<kF16_Dst>, src_1<kF16_Dst>, 176 }; 177 178 /////////////////////////////////////////////////////////////////////////////////////////////////// 179 180 static void dst(const SkXfermode*, uint64_t*, const SkPM4f*, int count, const SkAlpha[]) {} 181 182 const SkXfermode::D64Proc gProcs_Dst[] = { 183 dst, dst, dst, dst, dst, dst, dst, dst, 184 }; 185 186 /////////////////////////////////////////////////////////////////////////////////////////////////// 187 188 template <DstType D> void srcover_1(const SkXfermode*, uint64_t dst[], 189 const SkPM4f* src, int count, const SkAlpha aa[]) { 190 const Sk4f s4 = pm_to_rgba_order(Sk4f::Load(src->fVec)); 191 const Sk4f dst_scale = Sk4f(1 - get_alpha(s4)); 192 const Sk4f s4bias = unit_to_bias<D>(s4); 193 for (int i = 0; i < count; ++i) { 194 const Sk4f d4bias = load_from_dst<D>(dst[i]); 195 const Sk4f r4bias = s4bias + d4bias * dst_scale; 196 if (aa) { 197 dst[i] = store_to_dst<D>(lerp_by_coverage(r4bias, d4bias, aa[i])); 198 } else { 199 dst[i] = store_to_dst<D>(r4bias); 200 } 201 } 202 } 203 204 template <DstType D> void srcover_n(const SkXfermode*, uint64_t dst[], 205 const SkPM4f src[], int count, const SkAlpha aa[]) { 206 for (int i = 0; i < count; ++i) { 207 const Sk4f s4 = pm_to_rgba_order(Sk4f::Load(src[i].fVec)); 208 const Sk4f dst_scale = Sk4f(1 - get_alpha(s4)); 209 const Sk4f s4bias = unit_to_bias<D>(s4); 210 const Sk4f d4bias = load_from_dst<D>(dst[i]); 211 const Sk4f r4bias = s4bias + d4bias * dst_scale; 212 if (aa) { 213 dst[i] = store_to_dst<D>(lerp_by_coverage(r4bias, d4bias, aa[i])); 214 } else { 215 dst[i] = store_to_dst<D>(r4bias); 216 } 217 } 218 } 219 220 const SkXfermode::D64Proc gProcs_SrcOver[] = { 221 srcover_n<kU16_Dst>, src_n<kU16_Dst>, 222 srcover_1<kU16_Dst>, src_1<kU16_Dst>, 223 srcover_n<kF16_Dst>, src_n<kF16_Dst>, 224 srcover_1<kF16_Dst>, src_1<kF16_Dst>, 225 }; 226 227 /////////////////////////////////////////////////////////////////////////////////////////////////// 228 229 static SkXfermode::D64Proc find_proc(SkXfermode::Mode mode, uint32_t flags) { 230 SkASSERT(0 == (flags & ~7)); 231 flags &= 7; 232 233 switch (mode) { 234 case SkXfermode::kClear_Mode: return gProcs_Clear[flags]; 235 case SkXfermode::kSrc_Mode: return gProcs_Src[flags]; 236 case SkXfermode::kDst_Mode: return gProcs_Dst[flags]; 237 case SkXfermode::kSrcOver_Mode: return gProcs_SrcOver[flags]; 238 default: 239 break; 240 } 241 return gProcs_General[flags]; 242 } 243 244 SkXfermode::D64Proc SkXfermode::onGetD64Proc(uint32_t flags) const { 245 SkASSERT(0 == (flags & ~7)); 246 flags &= 7; 247 248 Mode mode; 249 return this->asMode(&mode) ? find_proc(mode, flags) : gProcs_General[flags]; 250 } 251 252 SkXfermode::D64Proc SkXfermode::GetD64Proc(SkXfermode* xfer, uint32_t flags) { 253 return xfer ? xfer->onGetD64Proc(flags) : find_proc(SkXfermode::kSrcOver_Mode, flags); 254 } 255 256