From 7bbda991af353fbe6b34132132d211d23a3dba8c Mon Sep 17 00:00:00 2001 From: msarett Date: Wed, 14 Sep 2016 11:02:04 -0700 Subject: [PATCH] Store SkColorSpaceXform gamma LUTs in a malloced field In order of likelihood: (1) Tables are never used, since gamma is recognized and named. (2) Only use one table, since all three gammas are the same. (3) Actually need three tables. No reason to waste a bunch of space for these tables on SkColorSpaceXform, when it will likely be unused. This will be more efficient in lots of cases, but is particularly useful when the client really only wants a gamut xform. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2336913005 Review-Url: https://codereview.chromium.org/2336913005 --- src/core/SkColorSpaceXform.cpp | 71 ++++++++++++++++++++++++++++++++---------- src/core/SkColorSpaceXform.h | 9 ++---- 2 files changed, 58 insertions(+), 22 deletions(-) diff --git a/src/core/SkColorSpaceXform.cpp b/src/core/SkColorSpaceXform.cpp index de7cf85..2677b3b 100644 --- a/src/core/SkColorSpaceXform.cpp +++ b/src/core/SkColorSpaceXform.cpp @@ -256,7 +256,8 @@ static const GammaFns kFromLinear { // Build tables to transform src gamma to linear. template static void build_gamma_tables(const T* outGammaTables[3], T* gammaTableStorage, int gammaTableSize, - const sk_sp& space, const GammaFns& fns) { + const sk_sp& space, const GammaFns& 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 SkColorSpaceXform_Base ::SkColorSpaceXform_Base(const sk_sp& srcSpace, const SkMatrix44& srcToDst, @@ -1166,11 +1190,24 @@ SkColorSpaceXform_Base : 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(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 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 SlowIdentityXform(const sk_sp& space) { return std::unique_ptr(new SkColorSpaceXform_Base diff --git a/src/core/SkColorSpaceXform.h b/src/core/SkColorSpaceXform.h index 6d63879..c80cd15 100644 --- a/src/core/SkColorSpaceXform.h +++ b/src/core/SkColorSpaceXform.h @@ -77,16 +77,13 @@ private: sk_sp fColorLUT; - // May contain pointers into storage or pointers into precomputed tables. + // Contain pointers into storage or pointers into precomputed tables. const float* fSrcGammaTables[3]; - float fSrcGammaTableStorage[3 * 256]; + const uint8_t* fDstGammaTables[3]; + SkAutoMalloc fStorage; float fSrcToDst[16]; - // May contain pointers into storage or pointers into precomputed tables. - const uint8_t* fDstGammaTables[3]; - uint8_t fDstGammaTableStorage[3 * kDstGammaTableSize]; - friend class SkColorSpaceXform; friend std::unique_ptr SlowIdentityXform(const sk_sp& space); }; -- 2.7.4