aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkColorSpaceXform.cpp
diff options
context:
space:
mode:
authorGravatar msarett <msarett@google.com>2016-09-14 11:02:04 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-09-14 11:02:04 -0700
commit7bbda991af353fbe6b34132132d211d23a3dba8c (patch)
tree205864d063703caca27646095ba244dac6781ce2 /src/core/SkColorSpaceXform.cpp
parent896ddb706d2eb9d8ebad61f767de058f7f0708a0 (diff)
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
Diffstat (limited to 'src/core/SkColorSpaceXform.cpp')
-rw-r--r--src/core/SkColorSpaceXform.cpp71
1 files changed, 55 insertions, 16 deletions
diff --git a/src/core/SkColorSpaceXform.cpp b/src/core/SkColorSpaceXform.cpp
index de7cf85d23..2677b3bb8d 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>