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 #ifndef SkColorSpaceXformOpts_DEFINED | 8 #ifndef SkColorSpaceXformOpts_DEFINED |
9 #define SkColorSpaceXformOpts_DEFINED | 9 #define SkColorSpaceXformOpts_DEFINED |
10 | 10 |
11 #include "SkNx.h" | 11 #include "SkNx.h" |
12 #include "SkColorPriv.h" | 12 #include "SkColorPriv.h" |
13 #include "SkHalf.h" | 13 #include "SkHalf.h" |
14 #include "SkSRGB.h" | 14 #include "SkSRGB.h" |
15 #include "SkTemplates.h" | 15 #include "SkTemplates.h" |
16 | 16 |
| 17 enum SwapRB { |
| 18 kNo_SwapRB, |
| 19 kYes_SwapRB, |
| 20 }; |
| 21 |
17 static inline void load_matrix(const float matrix[16], | 22 static inline void load_matrix(const float matrix[16], |
18 Sk4f& rXgXbX, Sk4f& rYgYbY, Sk4f& rZgZbZ, Sk4f& r
TgTbT) { | 23 Sk4f& rXgXbX, Sk4f& rYgYbY, Sk4f& rZgZbZ, Sk4f& r
TgTbT) { |
19 rXgXbX = Sk4f::Load(matrix + 0); | 24 rXgXbX = Sk4f::Load(matrix + 0); |
20 rYgYbY = Sk4f::Load(matrix + 4); | 25 rYgYbY = Sk4f::Load(matrix + 4); |
21 rZgZbZ = Sk4f::Load(matrix + 8); | 26 rZgZbZ = Sk4f::Load(matrix + 8); |
22 rTgTbT = Sk4f::Load(matrix + 12); | 27 rTgTbT = Sk4f::Load(matrix + 12); |
23 } | 28 } |
24 | 29 |
25 static inline void load_rgb_from_tables(const uint32_t* src, | 30 static inline void load_rgb_from_tables(const uint32_t* src, |
26 Sk4f& r, Sk4f& g, Sk4f& b, Sk4f&, | 31 Sk4f& r, Sk4f& g, Sk4f& b, Sk4f&, |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 dg = da * dg; | 111 dg = da * dg; |
107 db = da * db; | 112 db = da * db; |
108 } | 113 } |
109 | 114 |
110 static inline void premultiply_1(const Sk4f& a, Sk4f& rgba) { | 115 static inline void premultiply_1(const Sk4f& a, Sk4f& rgba) { |
111 rgba = a * rgba; | 116 rgba = a * rgba; |
112 } | 117 } |
113 | 118 |
114 static inline void store_srgb(void* dst, const uint32_t* src, | 119 static inline void store_srgb(void* dst, const uint32_t* src, |
115 Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f&, | 120 Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f&, |
116 const uint8_t* const[3], bool kSwapRB) { | 121 const uint8_t* const[3], SwapRB kSwapRB) { |
117 int kRShift = 0; | 122 int kRShift = 0; |
118 int kGShift = 8; | 123 int kGShift = 8; |
119 int kBShift = 16; | 124 int kBShift = 16; |
120 int kAShift = 24; | 125 if (kYes_SwapRB == kSwapRB) { |
121 if (kSwapRB) { | |
122 kBShift = 0; | 126 kBShift = 0; |
123 kRShift = 16; | 127 kRShift = 16; |
124 } | 128 } |
125 | 129 |
126 dr = sk_linear_to_srgb_needs_trunc(dr); | 130 dr = sk_linear_to_srgb_needs_trunc(dr); |
127 dg = sk_linear_to_srgb_needs_trunc(dg); | 131 dg = sk_linear_to_srgb_needs_trunc(dg); |
128 db = sk_linear_to_srgb_needs_trunc(db); | 132 db = sk_linear_to_srgb_needs_trunc(db); |
129 | 133 |
130 dr = sk_clamp_0_255(dr); | 134 dr = sk_clamp_0_255(dr); |
131 dg = sk_clamp_0_255(dg); | 135 dg = sk_clamp_0_255(dg); |
132 db = sk_clamp_0_255(db); | 136 db = sk_clamp_0_255(db); |
133 | 137 |
134 Sk4i da = SkNx_cast<int32_t>(Sk4u::Load(src) >> 24); | 138 Sk4i da = Sk4i::Load(src) & 0xFF000000; |
135 | 139 |
136 Sk4i rgba = (SkNx_cast<int>(dr) << kRShift) | 140 Sk4i rgba = (SkNx_cast<int>(dr) << kRShift) |
137 | (SkNx_cast<int>(dg) << kGShift) | 141 | (SkNx_cast<int>(dg) << kGShift) |
138 | (SkNx_cast<int>(db) << kBShift) | 142 | (SkNx_cast<int>(db) << kBShift) |
139 | (da << kAShift); | 143 | (da ); |
140 rgba.store(dst); | 144 rgba.store(dst); |
141 } | 145 } |
142 | 146 |
143 static inline void store_srgb_1(void* dst, const uint32_t* src, | 147 static inline void store_srgb_1(void* dst, const uint32_t* src, |
144 Sk4f& rgba, const Sk4f&, | 148 Sk4f& rgba, const Sk4f&, |
145 const uint8_t* const[3], bool kSwapRB) { | 149 const uint8_t* const[3], SwapRB kSwapRB) { |
146 rgba = sk_clamp_0_255(sk_linear_to_srgb_needs_trunc(rgba)); | 150 rgba = sk_clamp_0_255(sk_linear_to_srgb_needs_trunc(rgba)); |
147 | 151 |
148 uint32_t tmp; | 152 uint32_t tmp; |
149 SkNx_cast<uint8_t>(SkNx_cast<int32_t>(rgba)).store(&tmp); | 153 SkNx_cast<uint8_t>(SkNx_cast<int32_t>(rgba)).store(&tmp); |
150 tmp = (*src & 0xFF000000) | (tmp & 0x00FFFFFF); | 154 tmp = (*src & 0xFF000000) | (tmp & 0x00FFFFFF); |
151 if (kSwapRB) { | 155 if (kYes_SwapRB == kSwapRB) { |
152 tmp = SkSwizzle_RB(tmp); | 156 tmp = SkSwizzle_RB(tmp); |
153 } | 157 } |
154 | 158 |
155 *(uint32_t*)dst = tmp; | 159 *(uint32_t*)dst = tmp; |
156 } | 160 } |
157 | 161 |
158 static inline Sk4f linear_to_2dot2(const Sk4f& x) { | 162 static inline Sk4f linear_to_2dot2(const Sk4f& x) { |
159 // x^(29/64) is a very good approximation of the true value, x^(1/2.2). | 163 // x^(29/64) is a very good approximation of the true value, x^(1/2.2). |
160 auto x2 = x.rsqrt(), // x^(-1/2) | 164 auto x2 = x.rsqrt(), // x^(-1/2) |
161 x32 = x2.rsqrt().rsqrt().rsqrt().rsqrt(), // x^(-1/32) | 165 x32 = x2.rsqrt().rsqrt().rsqrt().rsqrt(), // x^(-1/32) |
162 x64 = x32.rsqrt(); // x^(+1/64) | 166 x64 = x32.rsqrt(); // x^(+1/64) |
163 | 167 |
164 // 29 = 32 - 2 - 1 | 168 // 29 = 32 - 2 - 1 |
165 return 255.0f * x2.invert() * x32 * x64.invert(); | 169 return 255.0f * x2.invert() * x32 * x64.invert(); |
166 } | 170 } |
167 | 171 |
168 static inline void store_2dot2(void* dst, const uint32_t* src, | 172 static inline void store_2dot2(void* dst, const uint32_t* src, |
169 Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f&, | 173 Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f&, |
170 const uint8_t* const[3], bool kSwapRB) { | 174 const uint8_t* const[3], SwapRB kSwapRB) { |
171 int kRShift = 0; | 175 int kRShift = 0; |
172 int kGShift = 8; | 176 int kGShift = 8; |
173 int kBShift = 16; | 177 int kBShift = 16; |
174 int kAShift = 24; | 178 if (kYes_SwapRB == kSwapRB) { |
175 if (kSwapRB) { | |
176 kBShift = 0; | 179 kBShift = 0; |
177 kRShift = 16; | 180 kRShift = 16; |
178 } | 181 } |
179 | 182 |
180 dr = linear_to_2dot2(dr); | 183 dr = linear_to_2dot2(dr); |
181 dg = linear_to_2dot2(dg); | 184 dg = linear_to_2dot2(dg); |
182 db = linear_to_2dot2(db); | 185 db = linear_to_2dot2(db); |
183 | 186 |
184 dr = sk_clamp_0_255(dr); | 187 dr = sk_clamp_0_255(dr); |
185 dg = sk_clamp_0_255(dg); | 188 dg = sk_clamp_0_255(dg); |
186 db = sk_clamp_0_255(db); | 189 db = sk_clamp_0_255(db); |
187 | 190 |
188 Sk4i da = SkNx_cast<int32_t>(Sk4u::Load(src) >> 24); | 191 Sk4i da = Sk4i::Load(src) & 0xFF000000; |
189 | 192 |
190 Sk4i rgba = (Sk4f_round(dr) << kRShift) | 193 Sk4i rgba = (Sk4f_round(dr) << kRShift) |
191 | (Sk4f_round(dg) << kGShift) | 194 | (Sk4f_round(dg) << kGShift) |
192 | (Sk4f_round(db) << kBShift) | 195 | (Sk4f_round(db) << kBShift) |
193 | (da << kAShift); | 196 | (da ); |
194 rgba.store(dst); | 197 rgba.store(dst); |
195 } | 198 } |
196 | 199 |
197 static inline void store_2dot2_1(void* dst, const uint32_t* src, | 200 static inline void store_2dot2_1(void* dst, const uint32_t* src, |
198 Sk4f& rgba, const Sk4f&, | 201 Sk4f& rgba, const Sk4f&, |
199 const uint8_t* const[3], bool kSwapRB) { | 202 const uint8_t* const[3], SwapRB kSwapRB) { |
200 rgba = sk_clamp_0_255(linear_to_2dot2(rgba)); | 203 rgba = sk_clamp_0_255(linear_to_2dot2(rgba)); |
201 | 204 |
202 uint32_t tmp; | 205 uint32_t tmp; |
203 SkNx_cast<uint8_t>(Sk4f_round(rgba)).store(&tmp); | 206 SkNx_cast<uint8_t>(Sk4f_round(rgba)).store(&tmp); |
204 tmp = (*src & 0xFF000000) | (tmp & 0x00FFFFFF); | 207 tmp = (*src & 0xFF000000) | (tmp & 0x00FFFFFF); |
205 if (kSwapRB) { | 208 if (kYes_SwapRB == kSwapRB) { |
206 tmp = SkSwizzle_RB(tmp); | 209 tmp = SkSwizzle_RB(tmp); |
207 } | 210 } |
208 | 211 |
209 *(uint32_t*)dst = tmp; | 212 *(uint32_t*)dst = tmp; |
210 } | 213 } |
211 | 214 |
212 static inline void store_f16(void* dst, const uint32_t* src, | 215 static inline void store_f16(void* dst, const uint32_t* src, |
213 Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f& da, | 216 Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f& da, |
214 const uint8_t* const[3], bool kSwapRB) { | 217 const uint8_t* const[3], SwapRB) { |
215 Sk4h_store4(dst, SkFloatToHalf_finite(dr), | 218 Sk4h_store4(dst, SkFloatToHalf_finite(dr), |
216 SkFloatToHalf_finite(dg), | 219 SkFloatToHalf_finite(dg), |
217 SkFloatToHalf_finite(db), | 220 SkFloatToHalf_finite(db), |
218 SkFloatToHalf_finite(da)); | 221 SkFloatToHalf_finite(da)); |
219 dst = SkTAddOffset<void>(dst, 4 * sizeof(uint64_t)); | |
220 } | 222 } |
221 | 223 |
222 static inline void store_f16_1(void* dst, const uint32_t* src, | 224 static inline void store_f16_1(void* dst, const uint32_t* src, |
223 Sk4f& rgba, const Sk4f& a, | 225 Sk4f& rgba, const Sk4f& a, |
224 const uint8_t* const[3], bool kSwapRB) { | 226 const uint8_t* const[3], SwapRB kSwapRB) { |
225 rgba = Sk4f(rgba[0], rgba[1], rgba[2], a[3]); | 227 rgba = Sk4f(rgba[0], rgba[1], rgba[2], a[3]); |
226 SkFloatToHalf_finite(rgba).store((uint64_t*) dst); | 228 SkFloatToHalf_finite(rgba).store((uint64_t*) dst); |
227 } | 229 } |
228 | 230 |
| 231 static inline void store_f16_opaque(void* dst, const uint32_t* src, |
| 232 Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f& da, |
| 233 const uint8_t* const[3], SwapRB) { |
| 234 Sk4h_store4(dst, SkFloatToHalf_finite(dr), |
| 235 SkFloatToHalf_finite(dg), |
| 236 SkFloatToHalf_finite(db), |
| 237 SK_Half1); |
| 238 } |
| 239 |
| 240 static inline void store_f16_1_opaque(void* dst, const uint32_t* src, |
| 241 Sk4f& rgba, const Sk4f& a, |
| 242 const uint8_t* const[3], SwapRB kSwapRB) { |
| 243 uint64_t tmp; |
| 244 SkFloatToHalf_finite(rgba).store(&tmp); |
| 245 tmp |= static_cast<uint64_t>(SK_Half1) << 48; |
| 246 *((uint64_t*) dst) = tmp; |
| 247 } |
| 248 |
229 static inline void store_generic(void* dst, const uint32_t* src, | 249 static inline void store_generic(void* dst, const uint32_t* src, |
230 Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f&, | 250 Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f&, |
231 const uint8_t* const dstTables[3], bool kSwapRB
) { | 251 const uint8_t* const dstTables[3], SwapRB kSwap
RB) { |
232 int kRShift = 0; | 252 int kRShift = 0; |
233 int kGShift = 8; | 253 int kGShift = 8; |
234 int kBShift = 16; | 254 int kBShift = 16; |
235 int kAShift = 24; | 255 if (kYes_SwapRB == kSwapRB) { |
236 if (kSwapRB) { | |
237 kBShift = 0; | 256 kBShift = 0; |
238 kRShift = 16; | 257 kRShift = 16; |
239 } | 258 } |
240 | 259 |
241 dr = Sk4f::Min(Sk4f::Max(1023.0f * dr, 0.0f), 1023.0f); | 260 dr = Sk4f::Min(Sk4f::Max(1023.0f * dr, 0.0f), 1023.0f); |
242 dg = Sk4f::Min(Sk4f::Max(1023.0f * dg, 0.0f), 1023.0f); | 261 dg = Sk4f::Min(Sk4f::Max(1023.0f * dg, 0.0f), 1023.0f); |
243 db = Sk4f::Min(Sk4f::Max(1023.0f * db, 0.0f), 1023.0f); | 262 db = Sk4f::Min(Sk4f::Max(1023.0f * db, 0.0f), 1023.0f); |
244 | 263 |
245 Sk4i ir = Sk4f_round(dr); | 264 Sk4i ir = Sk4f_round(dr); |
246 Sk4i ig = Sk4f_round(dg); | 265 Sk4i ig = Sk4f_round(dg); |
247 Sk4i ib = Sk4f_round(db); | 266 Sk4i ib = Sk4f_round(db); |
248 | 267 |
249 Sk4i da = SkNx_cast<int32_t>(Sk4u::Load(src) >> 24); | 268 Sk4i da = Sk4i::Load(src) & 0xFF000000; |
250 | 269 |
251 uint32_t* dst32 = (uint32_t*) dst; | 270 uint32_t* dst32 = (uint32_t*) dst; |
252 dst32[0] = dstTables[0][ir[0]] << kRShift | 271 dst32[0] = dstTables[0][ir[0]] << kRShift |
253 | dstTables[1][ig[0]] << kGShift | 272 | dstTables[1][ig[0]] << kGShift |
254 | dstTables[2][ib[0]] << kBShift | 273 | dstTables[2][ib[0]] << kBShift |
255 | da[0] << kAShift; | 274 | da[0]; |
256 dst32[1] = dstTables[0][ir[1]] << kRShift | 275 dst32[1] = dstTables[0][ir[1]] << kRShift |
257 | dstTables[1][ig[1]] << kGShift | 276 | dstTables[1][ig[1]] << kGShift |
258 | dstTables[2][ib[1]] << kBShift | 277 | dstTables[2][ib[1]] << kBShift |
259 | da[1] << kAShift; | 278 | da[1]; |
260 dst32[2] = dstTables[0][ir[2]] << kRShift | 279 dst32[2] = dstTables[0][ir[2]] << kRShift |
261 | dstTables[1][ig[2]] << kGShift | 280 | dstTables[1][ig[2]] << kGShift |
262 | dstTables[2][ib[2]] << kBShift | 281 | dstTables[2][ib[2]] << kBShift |
263 | da[2] << kAShift; | 282 | da[2]; |
264 dst32[3] = dstTables[0][ir[3]] << kRShift | 283 dst32[3] = dstTables[0][ir[3]] << kRShift |
265 | dstTables[1][ig[3]] << kGShift | 284 | dstTables[1][ig[3]] << kGShift |
266 | dstTables[2][ib[3]] << kBShift | 285 | dstTables[2][ib[3]] << kBShift |
267 | da[3] << kAShift; | 286 | da[3]; |
268 } | 287 } |
269 | 288 |
270 static inline void store_generic_1(void* dst, const uint32_t* src, | 289 static inline void store_generic_1(void* dst, const uint32_t* src, |
271 Sk4f& rgba, const Sk4f&, | 290 Sk4f& rgba, const Sk4f&, |
272 const uint8_t* const dstTables[3], bool kSwap
RB) { | 291 const uint8_t* const dstTables[3], SwapRB kSw
apRB) { |
273 rgba = Sk4f::Min(Sk4f::Max(1023.0f * rgba, 0.0f), 1023.0f); | 292 rgba = Sk4f::Min(Sk4f::Max(1023.0f * rgba, 0.0f), 1023.0f); |
274 | 293 |
275 Sk4i indices = Sk4f_round(rgba); | 294 Sk4i indices = Sk4f_round(rgba); |
276 | 295 |
277 *((uint32_t*) dst) = dstTables[0][indices[0]] << 0 | 296 *((uint32_t*) dst) = dstTables[0][indices[0]] << 0 |
278 | dstTables[1][indices[1]] << 8 | 297 | dstTables[1][indices[1]] << 8 |
279 | dstTables[2][indices[2]] << 16 | 298 | dstTables[2][indices[2]] << 16 |
280 | (*src & 0xFF000000); | 299 | (*src & 0xFF000000); |
281 } | 300 } |
282 | 301 |
283 template <SkColorSpace::GammaNamed kDstGamma, bool kPremul, bool kSwapRB> | 302 template <SkColorSpace::GammaNamed kDstGamma, SkAlphaType kAlphaType, SwapRB kSw
apRB> |
284 static void color_xform_RGBA(void* dst, const uint32_t* src, int len, | 303 static void color_xform_RGBA(void* dst, const uint32_t* src, int len, |
285 const float* const srcTables[3], const float matrix
[16], | 304 const float* const srcTables[3], const float matrix
[16], |
286 const uint8_t* const dstTables[3]) { | 305 const uint8_t* const dstTables[3]) { |
287 decltype(store_srgb )* store; | 306 decltype(store_srgb )* store; |
288 decltype(store_srgb_1 )* store_1; | 307 decltype(store_srgb_1 )* store_1; |
289 decltype(load_rgb_from_tables )* load; | 308 decltype(load_rgb_from_tables )* load; |
290 decltype(load_rgb_from_tables_1)* load_1; | 309 decltype(load_rgb_from_tables_1)* load_1; |
291 size_t sizeOfDstPixel; | 310 size_t sizeOfDstPixel; |
292 switch (kDstGamma) { | 311 switch (kDstGamma) { |
293 case SkColorSpace::kSRGB_GammaNamed: | 312 case SkColorSpace::kSRGB_GammaNamed: |
294 load = kPremul ? load_rgba_from_tables : load_rgb_from_tables; | 313 load = (kPremul_SkAlphaType == kAlphaType) ? load_rgba_from_table
s : |
295 load_1 = kPremul ? load_rgba_from_tables_1 : load_rgb_from_tables_1
; | 314 load_rgb_from_tables
; |
| 315 load_1 = (kPremul_SkAlphaType == kAlphaType) ? load_rgba_from_table
s_1 : |
| 316 load_rgb_from_tables
_1; |
296 store = store_srgb; | 317 store = store_srgb; |
297 store_1 = store_srgb_1; | 318 store_1 = store_srgb_1; |
298 sizeOfDstPixel = 4; | 319 sizeOfDstPixel = 4; |
299 break; | 320 break; |
300 case SkColorSpace::k2Dot2Curve_GammaNamed: | 321 case SkColorSpace::k2Dot2Curve_GammaNamed: |
301 load = kPremul ? load_rgba_from_tables : load_rgb_from_tables; | 322 load = (kPremul_SkAlphaType == kAlphaType) ? load_rgba_from_table
s : |
302 load_1 = kPremul ? load_rgba_from_tables_1 : load_rgb_from_tables_1
; | 323 load_rgb_from_tables
; |
| 324 load_1 = (kPremul_SkAlphaType == kAlphaType) ? load_rgba_from_table
s_1 : |
| 325 load_rgb_from_tables
_1; |
303 store = store_2dot2; | 326 store = store_2dot2; |
304 store_1 = store_2dot2_1; | 327 store_1 = store_2dot2_1; |
305 sizeOfDstPixel = 4; | 328 sizeOfDstPixel = 4; |
306 break; | 329 break; |
307 case SkColorSpace::kLinear_GammaNamed: | 330 case SkColorSpace::kLinear_GammaNamed: |
308 load = load_rgba_from_tables; | 331 load = load_rgba_from_tables; |
309 load_1 = load_rgba_from_tables_1; | 332 load_1 = load_rgba_from_tables_1; |
310 store = store_f16; | 333 store = (kOpaque_SkAlphaType == kAlphaType) ? store_f16_opaque : |
311 store_1 = store_f16_1; | 334 store_f16; |
| 335 store_1 = (kOpaque_SkAlphaType == kAlphaType) ? store_f16_1_opaque : |
| 336 store_f16_1; |
312 sizeOfDstPixel = 8; | 337 sizeOfDstPixel = 8; |
313 break; | 338 break; |
314 case SkColorSpace::kNonStandard_GammaNamed: | 339 case SkColorSpace::kNonStandard_GammaNamed: |
315 load = kPremul ? load_rgba_from_tables : load_rgb_from_tables; | 340 load = (kPremul_SkAlphaType == kAlphaType) ? load_rgba_from_table
s : |
316 load_1 = kPremul ? load_rgba_from_tables_1 : load_rgb_from_tables_1
; | 341 load_rgb_from_tables
; |
| 342 load_1 = (kPremul_SkAlphaType == kAlphaType) ? load_rgba_from_table
s_1 : |
| 343 load_rgb_from_tables
_1; |
317 store = store_generic; | 344 store = store_generic; |
318 store_1 = store_generic_1; | 345 store_1 = store_generic_1; |
319 sizeOfDstPixel = 4; | 346 sizeOfDstPixel = 4; |
320 break; | 347 break; |
321 } | 348 } |
322 | 349 |
323 Sk4f rXgXbX, rYgYbY, rZgZbZ, rTgTbT; | 350 Sk4f rXgXbX, rYgYbY, rZgZbZ, rTgTbT; |
324 load_matrix(matrix, rXgXbX, rYgYbY, rZgZbZ, rTgTbT); | 351 load_matrix(matrix, rXgXbX, rYgYbY, rZgZbZ, rTgTbT); |
325 | 352 |
326 if (len >= 4) { | 353 if (len >= 4) { |
327 // Naively this would be a loop of load-transform-store, but we found it
faster to | 354 // Naively this would be a loop of load-transform-store, but we found it
faster to |
328 // move the N+1th load ahead of the Nth store. We don't bother doing th
is for N<4. | 355 // move the N+1th load ahead of the Nth store. We don't bother doing th
is for N<4. |
329 Sk4f r, g, b, a; | 356 Sk4f r, g, b, a; |
330 load(src, r, g, b, a, srcTables); | 357 load(src, r, g, b, a, srcTables); |
331 src += 4; | 358 src += 4; |
332 len -= 4; | 359 len -= 4; |
333 | 360 |
334 Sk4f dr, dg, db, da; | 361 Sk4f dr, dg, db, da; |
335 while (len >= 4) { | 362 while (len >= 4) { |
336 transform_gamut(r, g, b, a, rXgXbX, rYgYbY, rZgZbZ, dr, dg, db, da); | 363 transform_gamut(r, g, b, a, rXgXbX, rYgYbY, rZgZbZ, dr, dg, db, da); |
337 translate_gamut(rTgTbT, dr, dg, db); | 364 translate_gamut(rTgTbT, dr, dg, db); |
338 | 365 |
339 if (kPremul) { | 366 if (kPremul_SkAlphaType == kAlphaType) { |
340 premultiply(dr, dg, db, da); | 367 premultiply(dr, dg, db, da); |
341 } | 368 } |
342 | 369 |
343 load(src, r, g, b, a, srcTables); | 370 load(src, r, g, b, a, srcTables); |
344 src += 4; | 371 src += 4; |
345 len -= 4; | 372 len -= 4; |
346 | 373 |
347 store(dst, src - 4, dr, dg, db, da, dstTables, kSwapRB); | 374 store(dst, src - 4, dr, dg, db, da, dstTables, kSwapRB); |
348 dst = SkTAddOffset<void>(dst, 4 * sizeOfDstPixel); | 375 dst = SkTAddOffset<void>(dst, 4 * sizeOfDstPixel); |
349 } | 376 } |
350 | 377 |
351 transform_gamut(r, g, b, a, rXgXbX, rYgYbY, rZgZbZ, dr, dg, db, da); | 378 transform_gamut(r, g, b, a, rXgXbX, rYgYbY, rZgZbZ, dr, dg, db, da); |
352 translate_gamut(rTgTbT, dr, dg, db); | 379 translate_gamut(rTgTbT, dr, dg, db); |
353 | 380 |
354 if (kPremul) { | 381 if (kPremul_SkAlphaType == kAlphaType) { |
355 premultiply(dr, dg, db, da); | 382 premultiply(dr, dg, db, da); |
356 } | 383 } |
357 | 384 |
358 store(dst, src - 4, dr, dg, db, da, dstTables, kSwapRB); | 385 store(dst, src - 4, dr, dg, db, da, dstTables, kSwapRB); |
359 dst = SkTAddOffset<void>(dst, 4 * sizeOfDstPixel); | 386 dst = SkTAddOffset<void>(dst, 4 * sizeOfDstPixel); |
360 } | 387 } |
361 | 388 |
362 while (len > 0) { | 389 while (len > 0) { |
363 Sk4f r, g, b, a; | 390 Sk4f r, g, b, a; |
364 load_1(src, r, g, b, a, srcTables); | 391 load_1(src, r, g, b, a, srcTables); |
365 | 392 |
366 Sk4f rgba; | 393 Sk4f rgba; |
367 transform_gamut_1(r, g, b, rXgXbX, rYgYbY, rZgZbZ, rgba); | 394 transform_gamut_1(r, g, b, rXgXbX, rYgYbY, rZgZbZ, rgba); |
368 | 395 |
369 translate_gamut_1(rTgTbT, rgba); | 396 translate_gamut_1(rTgTbT, rgba); |
370 | 397 |
371 store_1(dst, src, rgba, a, dstTables, kSwapRB); | 398 store_1(dst, src, rgba, a, dstTables, kSwapRB); |
372 | 399 |
373 src += 1; | 400 src += 1; |
374 len -= 1; | 401 len -= 1; |
375 dst = SkTAddOffset<void>(dst, sizeOfDstPixel); | 402 dst = SkTAddOffset<void>(dst, sizeOfDstPixel); |
376 } | 403 } |
377 } | 404 } |
378 | 405 |
379 #endif // SkColorSpaceXformOpts_DEFINED | 406 #endif // SkColorSpaceXformOpts_DEFINED |
OLD | NEW |