| Index: src/core/SkColorSpaceXform.cpp
|
| diff --git a/src/core/SkColorSpaceXform.cpp b/src/core/SkColorSpaceXform.cpp
|
| index 5a6f015bff4670570907bfd4ae4908760ecd4940..29528db98324a0d205b8e30684a6030c7b5a063d 100644
|
| --- a/src/core/SkColorSpaceXform.cpp
|
| +++ b/src/core/SkColorSpaceXform.cpp
|
| @@ -256,7 +256,8 @@ static const GammaFns<uint8_t> kFromLinear {
|
| // Build tables to transform src gamma to linear.
|
| template <typename T>
|
| static void build_gamma_tables(const T* outGammaTables[3], T* gammaTableStorage, int gammaTableSize,
|
| - const sk_sp<SkColorSpace>& space, const GammaFns<T>& fns) {
|
| + const sk_sp<SkColorSpace>& space, const GammaFns<T>& fns,
|
| + bool gammasAreMatching) {
|
| switch (as_CSB(space)->gammaNamed()) {
|
| case kSRGB_SkGammaNamed:
|
| outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = fns.fSRGBTable;
|
| @@ -271,18 +272,7 @@ static void build_gamma_tables(const T* outGammaTables[3], T* gammaTableStorage,
|
| const SkGammas* gammas = as_CSB(space)->gammas();
|
| SkASSERT(gammas);
|
|
|
| - for (int i = 0; i < 3; i++) {
|
| - if (i > 0) {
|
| - // Check if this curve matches the first curve. In this case, we can
|
| - // share the same table pointer. This should almost always be true.
|
| - // I've never seen a profile where all three gamma curves didn't match.
|
| - // But it is possible that they won't.
|
| - if (gammas->type(0) == gammas->type(i) && gammas->data(0) == gammas->data(i)) {
|
| - outGammaTables[i] = outGammaTables[0];
|
| - continue;
|
| - }
|
| - }
|
| -
|
| + auto build_table = [=](int i) {
|
| if (gammas->isNamed(i)) {
|
| switch (gammas->data(i).fNamed) {
|
| case kSRGB_SkGammaNamed:
|
| @@ -319,7 +309,19 @@ static void build_gamma_tables(const T* outGammaTables[3], T* gammaTableStorage,
|
| params.fF);
|
| outGammaTables[i] = &gammaTableStorage[i * gammaTableSize];
|
| }
|
| + };
|
| +
|
| + if (gammasAreMatching) {
|
| + build_table(0);
|
| + outGammaTables[1] = outGammaTables[0];
|
| + outGammaTables[2] = outGammaTables[0];
|
| + } else {
|
| + build_table(0);
|
| + build_table(1);
|
| + build_table(2);
|
| }
|
| +
|
| + break;
|
| }
|
| }
|
| }
|
| @@ -1159,6 +1161,28 @@ static void color_xform_RGBA(void* dst, const uint32_t* src, int len,
|
|
|
| ///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
| +static inline int num_tables(SkColorSpace* space) {
|
| + switch (as_CSB(space)->gammaNamed()) {
|
| + case kSRGB_SkGammaNamed:
|
| + case k2Dot2Curve_SkGammaNamed:
|
| + case kLinear_SkGammaNamed:
|
| + return 0;
|
| + default: {
|
| + const SkGammas* gammas = as_CSB(space)->gammas();
|
| + SkASSERT(gammas);
|
| +
|
| + bool gammasAreMatching = (gammas->type(0) == gammas->type(1)) &&
|
| + (gammas->data(0) == gammas->data(1)) &&
|
| + (gammas->type(0) == gammas->type(2)) &&
|
| + (gammas->data(0) == gammas->data(2));
|
| +
|
| + // It's likely that each component will have the same gamma. In this case,
|
| + // we only need to build one table.
|
| + return gammasAreMatching ? 1 : 3;
|
| + }
|
| + }
|
| +}
|
| +
|
| template <SrcGamma kSrc, DstGamma kDst, ColorSpaceMatch kCSM>
|
| SkColorSpaceXform_Base<kSrc, kDst, kCSM>
|
| ::SkColorSpaceXform_Base(const sk_sp<SkColorSpace>& srcSpace, const SkMatrix44& srcToDst,
|
| @@ -1166,11 +1190,24 @@ SkColorSpaceXform_Base<kSrc, kDst, kCSM>
|
| : fColorLUT(sk_ref_sp((SkColorLookUpTable*) as_CSB(srcSpace)->colorLUT()))
|
| {
|
| srcToDst.asColMajorf(fSrcToDst);
|
| - build_gamma_tables(fSrcGammaTables, fSrcGammaTableStorage, 256, srcSpace, kToLinear);
|
| - build_gamma_tables(fDstGammaTables, fDstGammaTableStorage, kDstGammaTableSize, dstSpace,
|
| - kFromLinear);
|
| +
|
| + const int numSrcTables = num_tables(srcSpace.get());
|
| + const int numDstTables = num_tables(dstSpace.get());
|
| + const size_t srcTableBytes = numSrcTables * 256 * sizeof(float);
|
| + const size_t dstTableBytes = numDstTables * kDstGammaTableSize * sizeof(uint8_t);
|
| + fStorage.reset(srcTableBytes + dstTableBytes);
|
| + float* srcStorage = (float*) fStorage.get();
|
| + uint8_t* dstStorage = SkTAddOffset<uint8_t>(fStorage.get(), srcTableBytes);
|
| +
|
| + const bool srcGammasAreMatching = (1 >= numSrcTables);
|
| + const bool dstGammasAreMatching = (1 >= numDstTables);
|
| + build_gamma_tables(fSrcGammaTables, srcStorage, 256, srcSpace, kToLinear, srcGammasAreMatching);
|
| + build_gamma_tables(fDstGammaTables, dstStorage, kDstGammaTableSize, dstSpace, kFromLinear,
|
| + dstGammasAreMatching);
|
| }
|
|
|
| +///////////////////////////////////////////////////////////////////////////////////////////////////
|
| +
|
| template <SrcFormat kSrc, DstFormat kDst, ColorSpaceMatch kCSM, SwapRB kSwap>
|
| static inline void apply_set_alpha(void* dst, const uint32_t* src, int len, SkAlphaType alphaType,
|
| const float* const srcTables[3], const float matrix[16],
|
| @@ -1291,6 +1328,8 @@ const
|
| }
|
| }
|
|
|
| +///////////////////////////////////////////////////////////////////////////////////////////////////
|
| +
|
| std::unique_ptr<SkColorSpaceXform> SlowIdentityXform(const sk_sp<SkColorSpace>& space) {
|
| return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base
|
| <kTable_SrcGamma, kTable_DstGamma, kNone_ColorSpaceMatch>
|
|
|