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 "SkColorPriv.h" | 8 #include "SkColorPriv.h" |
9 #include "SkColorSpace_Base.h" | 9 #include "SkColorSpace_Base.h" |
10 #include "SkColorSpacePriv.h" | 10 #include "SkColorSpacePriv.h" |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 nullptr, | 249 nullptr, |
250 nullptr, | 250 nullptr, |
251 &build_table_linear_to_gamma, | 251 &build_table_linear_to_gamma, |
252 &build_table_linear_to_gamma, | 252 &build_table_linear_to_gamma, |
253 &build_table_linear_to_gamma, | 253 &build_table_linear_to_gamma, |
254 }; | 254 }; |
255 | 255 |
256 // Build tables to transform src gamma to linear. | 256 // Build tables to transform src gamma to linear. |
257 template <typename T> | 257 template <typename T> |
258 static void build_gamma_tables(const T* outGammaTables[3], T* gammaTableStorage,
int gammaTableSize, | 258 static void build_gamma_tables(const T* outGammaTables[3], T* gammaTableStorage,
int gammaTableSize, |
259 const sk_sp<SkColorSpace>& space, const GammaFns<
T>& fns) { | 259 const sk_sp<SkColorSpace>& space, const GammaFns<
T>& fns, |
| 260 bool gammasAreMatching) { |
260 switch (as_CSB(space)->gammaNamed()) { | 261 switch (as_CSB(space)->gammaNamed()) { |
261 case kSRGB_SkGammaNamed: | 262 case kSRGB_SkGammaNamed: |
262 outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = fns.fSRG
BTable; | 263 outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = fns.fSRG
BTable; |
263 break; | 264 break; |
264 case k2Dot2Curve_SkGammaNamed: | 265 case k2Dot2Curve_SkGammaNamed: |
265 outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = fns.f2Do
t2Table; | 266 outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = fns.f2Do
t2Table; |
266 break; | 267 break; |
267 case kLinear_SkGammaNamed: | 268 case kLinear_SkGammaNamed: |
268 outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = nullptr; | 269 outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = nullptr; |
269 break; | 270 break; |
270 default: { | 271 default: { |
271 const SkGammas* gammas = as_CSB(space)->gammas(); | 272 const SkGammas* gammas = as_CSB(space)->gammas(); |
272 SkASSERT(gammas); | 273 SkASSERT(gammas); |
273 | 274 |
274 for (int i = 0; i < 3; i++) { | 275 auto build_table = [=](int i) { |
275 if (i > 0) { | |
276 // Check if this curve matches the first curve. In this cas
e, we can | |
277 // share the same table pointer. This should almost always
be true. | |
278 // I've never seen a profile where all three gamma curves di
dn't match. | |
279 // But it is possible that they won't. | |
280 if (gammas->type(0) == gammas->type(i) && gammas->data(0) ==
gammas->data(i)) { | |
281 outGammaTables[i] = outGammaTables[0]; | |
282 continue; | |
283 } | |
284 } | |
285 | |
286 if (gammas->isNamed(i)) { | 276 if (gammas->isNamed(i)) { |
287 switch (gammas->data(i).fNamed) { | 277 switch (gammas->data(i).fNamed) { |
288 case kSRGB_SkGammaNamed: | 278 case kSRGB_SkGammaNamed: |
289 (*fns.fBuildFromParam)(&gammaTableStorage[i * gammaT
ableSize], 2.4f, | 279 (*fns.fBuildFromParam)(&gammaTableStorage[i * gammaT
ableSize], 2.4f, |
290 (1.0f / 1.055f), (0.055f / 1.
055f), 0.0f, | 280 (1.0f / 1.055f), (0.055f / 1.
055f), 0.0f, |
291 0.04045f, (1.0f / 12.92f), 0.
0f); | 281 0.04045f, (1.0f / 12.92f), 0.
0f); |
292 outGammaTables[i] = &gammaTableStorage[i * gammaTabl
eSize]; | 282 outGammaTables[i] = &gammaTableStorage[i * gammaTabl
eSize]; |
293 break; | 283 break; |
294 case k2Dot2Curve_SkGammaNamed: | 284 case k2Dot2Curve_SkGammaNamed: |
295 (*fns.fBuildFromValue)(&gammaTableStorage[i * gammaT
ableSize], 2.2f); | 285 (*fns.fBuildFromValue)(&gammaTableStorage[i * gammaT
ableSize], 2.2f); |
(...skipping 16 matching lines...) Expand all Loading... |
312 gammas->data(i).fTable.fSize); | 302 gammas->data(i).fTable.fSize); |
313 outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; | 303 outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; |
314 } else { | 304 } else { |
315 SkASSERT(gammas->isParametric(i)); | 305 SkASSERT(gammas->isParametric(i)); |
316 const SkGammas::Params& params = gammas->params(i); | 306 const SkGammas::Params& params = gammas->params(i); |
317 (*fns.fBuildFromParam)(&gammaTableStorage[i * gammaTableSize
], params.fG, | 307 (*fns.fBuildFromParam)(&gammaTableStorage[i * gammaTableSize
], params.fG, |
318 params.fA, params.fB, params.fC, para
ms.fD, params.fE, | 308 params.fA, params.fB, params.fC, para
ms.fD, params.fE, |
319 params.fF); | 309 params.fF); |
320 outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; | 310 outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; |
321 } | 311 } |
| 312 }; |
| 313 |
| 314 if (gammasAreMatching) { |
| 315 build_table(0); |
| 316 outGammaTables[1] = outGammaTables[0]; |
| 317 outGammaTables[2] = outGammaTables[0]; |
| 318 } else { |
| 319 build_table(0); |
| 320 build_table(1); |
| 321 build_table(2); |
322 } | 322 } |
| 323 |
| 324 break; |
323 } | 325 } |
324 } | 326 } |
325 } | 327 } |
326 | 328 |
327 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 329 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
328 | 330 |
329 static inline bool is_almost_identity(const SkMatrix44& srcToDst) { | 331 static inline bool is_almost_identity(const SkMatrix44& srcToDst) { |
330 for (int i = 0; i < 4; i++) { | 332 for (int i = 0; i < 4; i++) { |
331 for (int j = 0; j < 4; j++) { | 333 for (int j = 0; j < 4; j++) { |
332 float expected = (i == j) ? 1.0f : 0.0f; | 334 float expected = (i == j) ? 1.0f : 0.0f; |
(...skipping 819 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1152 break; | 1154 break; |
1153 } | 1155 } |
1154 | 1156 |
1155 do_color_xform<kAlphaType, kCSM> | 1157 do_color_xform<kAlphaType, kCSM> |
1156 (dst, src, len, srcTables, matrix, dstTables, load, load_1, store, s
tore_1, | 1158 (dst, src, len, srcTables, matrix, dstTables, load, load_1, store, s
tore_1, |
1157 sizeOfDstPixel); | 1159 sizeOfDstPixel); |
1158 } | 1160 } |
1159 | 1161 |
1160 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 1162 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
1161 | 1163 |
| 1164 static inline int num_tables(SkColorSpace* space) { |
| 1165 switch (as_CSB(space)->gammaNamed()) { |
| 1166 case kSRGB_SkGammaNamed: |
| 1167 case k2Dot2Curve_SkGammaNamed: |
| 1168 case kLinear_SkGammaNamed: |
| 1169 return 0; |
| 1170 default: { |
| 1171 const SkGammas* gammas = as_CSB(space)->gammas(); |
| 1172 SkASSERT(gammas); |
| 1173 |
| 1174 bool gammasAreMatching = (gammas->type(0) == gammas->type(1)) && |
| 1175 (gammas->data(0) == gammas->data(1)) && |
| 1176 (gammas->type(0) == gammas->type(2)) && |
| 1177 (gammas->data(0) == gammas->data(2)); |
| 1178 |
| 1179 // It's likely that each component will have the same gamma. In thi
s case, |
| 1180 // we only need to build one table. |
| 1181 return gammasAreMatching ? 1 : 3; |
| 1182 } |
| 1183 } |
| 1184 } |
| 1185 |
1162 template <SrcGamma kSrc, DstGamma kDst, ColorSpaceMatch kCSM> | 1186 template <SrcGamma kSrc, DstGamma kDst, ColorSpaceMatch kCSM> |
1163 SkColorSpaceXform_Base<kSrc, kDst, kCSM> | 1187 SkColorSpaceXform_Base<kSrc, kDst, kCSM> |
1164 ::SkColorSpaceXform_Base(const sk_sp<SkColorSpace>& srcSpace, const SkMatrix44&
srcToDst, | 1188 ::SkColorSpaceXform_Base(const sk_sp<SkColorSpace>& srcSpace, const SkMatrix44&
srcToDst, |
1165 const sk_sp<SkColorSpace>& dstSpace) | 1189 const sk_sp<SkColorSpace>& dstSpace) |
1166 : fColorLUT(sk_ref_sp((SkColorLookUpTable*) as_CSB(srcSpace)->colorLUT())) | 1190 : fColorLUT(sk_ref_sp((SkColorLookUpTable*) as_CSB(srcSpace)->colorLUT())) |
1167 { | 1191 { |
1168 srcToDst.asColMajorf(fSrcToDst); | 1192 srcToDst.asColMajorf(fSrcToDst); |
1169 build_gamma_tables(fSrcGammaTables, fSrcGammaTableStorage, 256, srcSpace, kT
oLinear); | 1193 |
1170 build_gamma_tables(fDstGammaTables, fDstGammaTableStorage, kDstGammaTableSiz
e, dstSpace, | 1194 const int numSrcTables = num_tables(srcSpace.get()); |
1171 kFromLinear); | 1195 const int numDstTables = num_tables(dstSpace.get()); |
| 1196 const size_t srcTableBytes = numSrcTables * 256 * sizeof(float); |
| 1197 const size_t dstTableBytes = numDstTables * kDstGammaTableSize * sizeof(uint
8_t); |
| 1198 fStorage.reset(srcTableBytes + dstTableBytes); |
| 1199 float* srcStorage = (float*) fStorage.get(); |
| 1200 uint8_t* dstStorage = SkTAddOffset<uint8_t>(fStorage.get(), srcTableBytes); |
| 1201 |
| 1202 const bool srcGammasAreMatching = (1 >= numSrcTables); |
| 1203 const bool dstGammasAreMatching = (1 >= numDstTables); |
| 1204 build_gamma_tables(fSrcGammaTables, srcStorage, 256, srcSpace, kToLinear, sr
cGammasAreMatching); |
| 1205 build_gamma_tables(fDstGammaTables, dstStorage, kDstGammaTableSize, dstSpace
, kFromLinear, |
| 1206 dstGammasAreMatching); |
1172 } | 1207 } |
1173 | 1208 |
| 1209 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
| 1210 |
1174 template <SrcFormat kSrc, DstFormat kDst, ColorSpaceMatch kCSM, SwapRB kSwap> | 1211 template <SrcFormat kSrc, DstFormat kDst, ColorSpaceMatch kCSM, SwapRB kSwap> |
1175 static inline void apply_set_alpha(void* dst, const uint32_t* src, int len, SkAl
phaType alphaType, | 1212 static inline void apply_set_alpha(void* dst, const uint32_t* src, int len, SkAl
phaType alphaType, |
1176 const float* const srcTables[3], const float
matrix[16], | 1213 const float* const srcTables[3], const float
matrix[16], |
1177 const uint8_t* const dstTables[3]) { | 1214 const uint8_t* const dstTables[3]) { |
1178 switch (alphaType) { | 1215 switch (alphaType) { |
1179 case kOpaque_SkAlphaType: | 1216 case kOpaque_SkAlphaType: |
1180 return color_xform_RGBA<kSrc, kDst, kOpaque_SkAlphaType, kCSM, kSwap
> | 1217 return color_xform_RGBA<kSrc, kDst, kOpaque_SkAlphaType, kCSM, kSwap
> |
1181 (dst, src, len, srcTables, matrix, dstTables); | 1218 (dst, src, len, srcTables, matrix, dstTables); |
1182 case kPremul_SkAlphaType: | 1219 case kPremul_SkAlphaType: |
1183 return color_xform_RGBA<kSrc, kDst, kPremul_SkAlphaType, kCSM, kSwap
> | 1220 return color_xform_RGBA<kSrc, kDst, kPremul_SkAlphaType, kCSM, kSwap
> |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1284 default: | 1321 default: |
1285 SkASSERT(false); | 1322 SkASSERT(false); |
1286 return; | 1323 return; |
1287 } | 1324 } |
1288 default: | 1325 default: |
1289 SkASSERT(false); | 1326 SkASSERT(false); |
1290 return; | 1327 return; |
1291 } | 1328 } |
1292 } | 1329 } |
1293 | 1330 |
| 1331 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
| 1332 |
1294 std::unique_ptr<SkColorSpaceXform> SlowIdentityXform(const sk_sp<SkColorSpace>&
space) { | 1333 std::unique_ptr<SkColorSpaceXform> SlowIdentityXform(const sk_sp<SkColorSpace>&
space) { |
1295 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base | 1334 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base |
1296 <kTable_SrcGamma, kTable_DstGamma, kNone_ColorSpaceMatch> | 1335 <kTable_SrcGamma, kTable_DstGamma, kNone_ColorSpaceMatch> |
1297 (space, SkMatrix::I(), space)); | 1336 (space, SkMatrix::I(), space)); |
1298 } | 1337 } |
OLD | NEW |