Cache dst LUTs in SkColorSpaceXform
This is only useful in the rare case that the dst does not
fall into one of our main paths.
But it's a good optimization, since this does happen,
and typically, the dst won't change.
ColorCodecBench z620 --nonstd --xform_only
Without Patch 511us
With Patch 348us
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=3400
Change-Id: Ibf68d9ce7072680465662922f4aa15630545e3d6
Reviewed-on: https://skia-review.googlesource.com/3400
Reviewed-by: Mike Klein <mtklein@chromium.org>
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Matt Sarett <msarett@google.com>
diff --git a/bench/ColorCodecBench.cpp b/bench/ColorCodecBench.cpp
index 9ae5601..6aa46d6 100644
--- a/bench/ColorCodecBench.cpp
+++ b/bench/ColorCodecBench.cpp
@@ -18,6 +18,7 @@
#endif
DEFINE_bool(xform_only, false, "Only time the color xform, do not include the decode time");
DEFINE_bool(srgb, false, "Convert to srgb dst space");
+DEFINE_bool(nonstd, false, "Convert to non-standard dst space");
DEFINE_bool(half, false, "Convert to half floats");
ColorCodecBench::ColorCodecBench(const char* name, sk_sp<SkData> encoded)
@@ -172,6 +173,13 @@
fDstSpace = as_CSB(fDstSpace)->makeLinearGamma();
}
+ if (FLAGS_nonstd) {
+ float gammas[3] = { 1.8f, 2.0f, 2.5f, };
+ SkMatrix44 matrix = SkMatrix44(SkMatrix44::kUninitialized_Constructor);
+ matrix.set3x3(0.30f, 0.31f, 0.28f, 0.32f, 0.33f, 0.29f, 0.27f, 0.30f, 0.30f);
+ fDstSpace = SkColorSpace::NewRGB(gammas, matrix);
+ }
+
fDstInfo = fDstInfo.makeColorSpace(fDstSpace);
fDst.reset(fDstInfo.getSafeSize(fDstInfo.minRowBytes()));
diff --git a/include/core/SkColorSpaceXform.h b/include/core/SkColorSpaceXform.h
index 15b3d49..b1ca92e 100644
--- a/include/core/SkColorSpaceXform.h
+++ b/include/core/SkColorSpaceXform.h
@@ -50,17 +50,11 @@
*
*/
bool apply(ColorFormat dstFormat, void* dst, ColorFormat srcFormat, const void* src, int count,
- SkAlphaType alphaType) const {
- return this->onApply(dstFormat, dst, srcFormat, src, count, alphaType);
- }
-
+ SkAlphaType alphaType) const;
virtual ~SkColorSpaceXform() {}
protected:
- virtual bool onApply(ColorFormat dstFormat, void* dst, ColorFormat srcFormat, const void* src,
- int count, SkAlphaType alphaType) const = 0;
-
SkColorSpaceXform() {}
};
diff --git a/src/core/SkColorSpace.cpp b/src/core/SkColorSpace.cpp
index bdef5b3..b956c7f 100644
--- a/src/core/SkColorSpace.cpp
+++ b/src/core/SkColorSpace.cpp
@@ -8,6 +8,7 @@
#include "SkColorSpace.h"
#include "SkColorSpace_Base.h"
#include "SkColorSpacePriv.h"
+#include "SkColorSpaceXform_Base.h"
#include "SkOnce.h"
#include "SkPoint3.h"
@@ -319,6 +320,23 @@
return fFromXYZD50;
}
+void SkColorSpace_Base::toDstGammaTables(const uint8_t* tables[3], sk_sp<SkData>* storage,
+ int numTables) const {
+ fToDstGammaOnce([this, numTables] {
+ const bool gammasAreMatching = numTables <= 1;
+ fDstStorage =
+ SkData::MakeUninitialized(numTables * SkColorSpaceXform_Base::kDstGammaTableSize);
+ SkColorSpaceXform_Base::BuildDstGammaTables(fToDstGammaTables,
+ (uint8_t*) fDstStorage->writable_data(), this,
+ gammasAreMatching);
+ });
+
+ *storage = fDstStorage;
+ tables[0] = fToDstGammaTables[0];
+ tables[1] = fToDstGammaTables[1];
+ tables[2] = fToDstGammaTables[2];
+}
+
///////////////////////////////////////////////////////////////////////////////////////////////////
enum Version {
diff --git a/src/core/SkColorSpaceXform.cpp b/src/core/SkColorSpaceXform.cpp
index 50cd9c1..5e36246 100644
--- a/src/core/SkColorSpaceXform.cpp
+++ b/src/core/SkColorSpaceXform.cpp
@@ -138,9 +138,7 @@
}
}
-static const int kDstGammaTableSize =
- SkColorSpaceXform_Base<kTable_SrcGamma, kTable_DstGamma, kNone_ColorSpaceMatch>
- ::kDstGammaTableSize;
+static const int kDstGammaTableSize = SkColorSpaceXform_Base::kDstGammaTableSize;
static void build_table_linear_to_gamma(uint8_t* outTable, float exponent) {
float toGammaExp = 1.0f / exponent;
@@ -256,7 +254,8 @@
// Build tables to transform src gamma to linear.
template <typename T>
static void build_gamma_tables(const T* outGammaTables[3], T* gammaTableStorage, int gammaTableSize,
- SkColorSpace* space, const GammaFns<T>& fns, bool gammasAreMatching)
+ const SkColorSpace* space, const GammaFns<T>& fns,
+ bool gammasAreMatching)
{
switch (as_CSB(space)->gammaNamed()) {
case kSRGB_SkGammaNamed:
@@ -326,6 +325,13 @@
}
}
+void SkColorSpaceXform_Base::BuildDstGammaTables(const uint8_t* dstGammaTables[3],
+ uint8_t* dstStorage, const SkColorSpace* space,
+ bool gammasAreMatching) {
+ build_gamma_tables(dstGammaTables, dstStorage, kDstGammaTableSize, space, kFromLinear,
+ gammasAreMatching);
+}
+
///////////////////////////////////////////////////////////////////////////////////////////////////
static inline bool is_almost_identity(const SkMatrix44& srcToDst) {
@@ -368,41 +374,41 @@
switch (as_CSB(dstSpace)->gammaNamed()) {
case kSRGB_SkGammaNamed:
if (srcSpace->gammaIsLinear()) {
- return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base
+ return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
<kLinear_SrcGamma, kSRGB_DstGamma, kNone_ColorSpaceMatch>
(srcSpace, srcToDst, dstSpace));
} else {
- return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base
+ return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
<kTable_SrcGamma, kSRGB_DstGamma, kNone_ColorSpaceMatch>
(srcSpace, srcToDst, dstSpace));
}
case k2Dot2Curve_SkGammaNamed:
if (srcSpace->gammaIsLinear()) {
- return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base
+ return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
<kLinear_SrcGamma, k2Dot2_DstGamma, kNone_ColorSpaceMatch>
(srcSpace, srcToDst, dstSpace));
} else {
- return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base
+ return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
<kTable_SrcGamma, k2Dot2_DstGamma, kNone_ColorSpaceMatch>
(srcSpace, srcToDst, dstSpace));
}
case kLinear_SkGammaNamed:
if (srcSpace->gammaIsLinear()) {
- return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base
+ return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
<kLinear_SrcGamma, kLinear_DstGamma, kNone_ColorSpaceMatch>
(srcSpace, srcToDst, dstSpace));
} else {
- return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base
+ return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
<kTable_SrcGamma, kLinear_DstGamma, kNone_ColorSpaceMatch>
(srcSpace, srcToDst, dstSpace));
}
default:
if (srcSpace->gammaIsLinear()) {
- return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base
+ return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
<kLinear_SrcGamma, kTable_DstGamma, kNone_ColorSpaceMatch>
(srcSpace, srcToDst, dstSpace));
} else {
- return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base
+ return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
<kTable_SrcGamma, kTable_DstGamma, kNone_ColorSpaceMatch>
(srcSpace, srcToDst, dstSpace));
}
@@ -411,41 +417,41 @@
switch (as_CSB(dstSpace)->gammaNamed()) {
case kSRGB_SkGammaNamed:
if (srcSpace->gammaIsLinear()) {
- return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base
+ return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
<kLinear_SrcGamma, kSRGB_DstGamma, kGamut_ColorSpaceMatch>
(srcSpace, srcToDst, dstSpace));
} else {
- return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base
+ return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
<kTable_SrcGamma, kSRGB_DstGamma, kGamut_ColorSpaceMatch>
(srcSpace, srcToDst, dstSpace));
}
case k2Dot2Curve_SkGammaNamed:
if (srcSpace->gammaIsLinear()) {
- return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base
+ return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
<kLinear_SrcGamma, k2Dot2_DstGamma, kGamut_ColorSpaceMatch>
(srcSpace, srcToDst, dstSpace));
} else {
- return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base
+ return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
<kTable_SrcGamma, k2Dot2_DstGamma, kGamut_ColorSpaceMatch>
(srcSpace, srcToDst, dstSpace));
}
case kLinear_SkGammaNamed:
if (srcSpace->gammaIsLinear()) {
- return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base
+ return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
<kLinear_SrcGamma, kLinear_DstGamma, kGamut_ColorSpaceMatch>
(srcSpace, srcToDst, dstSpace));
} else {
- return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base
+ return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
<kTable_SrcGamma, kLinear_DstGamma, kGamut_ColorSpaceMatch>
(srcSpace, srcToDst, dstSpace));
}
default:
if (srcSpace->gammaIsLinear()) {
- return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base
+ return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
<kLinear_SrcGamma, kTable_DstGamma, kGamut_ColorSpaceMatch>
(srcSpace, srcToDst, dstSpace));
} else {
- return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base
+ return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
<kTable_SrcGamma, kTable_DstGamma, kGamut_ColorSpaceMatch>
(srcSpace, srcToDst, dstSpace));
}
@@ -453,19 +459,19 @@
case kFull_ColorSpaceMatch:
switch (as_CSB(dstSpace)->gammaNamed()) {
case kSRGB_SkGammaNamed:
- return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base
+ return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
<kTable_SrcGamma, kSRGB_DstGamma, kFull_ColorSpaceMatch>
(srcSpace, srcToDst, dstSpace));
case k2Dot2Curve_SkGammaNamed:
- return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base
+ return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
<kTable_SrcGamma, k2Dot2_DstGamma, kFull_ColorSpaceMatch>
(srcSpace, srcToDst, dstSpace));
case kLinear_SkGammaNamed:
- return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base
+ return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
<kLinear_SrcGamma, kLinear_DstGamma, kFull_ColorSpaceMatch>
(srcSpace, srcToDst, dstSpace));
default:
- return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base
+ return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
<kTable_SrcGamma, kTable_DstGamma, kFull_ColorSpaceMatch>
(srcSpace, srcToDst, dstSpace));
}
@@ -1243,25 +1249,21 @@
}
template <SrcGamma kSrc, DstGamma kDst, ColorSpaceMatch kCSM>
-SkColorSpaceXform_Base<kSrc, kDst, kCSM>
-::SkColorSpaceXform_Base(SkColorSpace* srcSpace, const SkMatrix44& srcToDst, SkColorSpace* dstSpace)
+SkColorSpaceXform_XYZ<kSrc, kDst, kCSM>
+::SkColorSpaceXform_XYZ(SkColorSpace* srcSpace, const SkMatrix44& srcToDst, SkColorSpace* dstSpace)
: fColorLUT(sk_ref_sp((SkColorLookUpTable*) as_CSB(srcSpace)->colorLUT()))
{
srcToDst.asColMajorf(fSrcToDst);
const int numSrcTables = num_tables(srcSpace);
- const int numDstTables = num_tables(dstSpace);
- 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 size_t srcEntries = numSrcTables * 256;
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);
+ fSrcStorage.reset(srcEntries);
+ build_gamma_tables(fSrcGammaTables, fSrcStorage.get(), 256, srcSpace, kToLinear,
+ srcGammasAreMatching);
+
+ const int numDstTables = num_tables(dstSpace);
+ as_CSB(dstSpace)->toDstGammaTables(fDstGammaTables, &fDstStorage, numDstTables);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -1318,7 +1320,7 @@
}
template <SrcGamma kSrc, DstGamma kDst, ColorSpaceMatch kCSM>
-bool SkColorSpaceXform_Base<kSrc, kDst, kCSM>
+bool SkColorSpaceXform_XYZ<kSrc, kDst, kCSM>
::onApply(ColorFormat dstColorFormat, void* dst, ColorFormat srcColorFormat, const void* src,
int len, SkAlphaType alphaType) const
{
@@ -1421,10 +1423,16 @@
}
}
+bool SkColorSpaceXform::apply(ColorFormat dstColorFormat, void* dst, ColorFormat srcColorFormat,
+ const void* src, int len, SkAlphaType alphaType) const {
+ return ((SkColorSpaceXform_Base*) this)->onApply(dstColorFormat, dst, srcColorFormat, src, len,
+ alphaType);
+}
+
///////////////////////////////////////////////////////////////////////////////////////////////////
std::unique_ptr<SkColorSpaceXform> SlowIdentityXform(SkColorSpace* space) {
- return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base
+ return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
<kTable_SrcGamma, kTable_DstGamma, kNone_ColorSpaceMatch>
(space, SkMatrix::I(), space));
}
diff --git a/src/core/SkColorSpaceXform_Base.h b/src/core/SkColorSpaceXform_Base.h
index 02714ad..c1b9785 100644
--- a/src/core/SkColorSpaceXform_Base.h
+++ b/src/core/SkColorSpaceXform_Base.h
@@ -11,6 +11,23 @@
#include "SkColorSpace.h"
#include "SkColorSpace_Base.h"
#include "SkColorSpaceXform.h"
+#include "SkResourceCache.h"
+
+class SkColorSpaceXform_Base : public SkColorSpaceXform {
+public:
+ static constexpr int kDstGammaTableSize = 1024;
+
+protected:
+ virtual bool onApply(ColorFormat dstFormat, void* dst, ColorFormat srcFormat, const void* src,
+ int count, SkAlphaType alphaType) const = 0;
+
+private:
+ static void BuildDstGammaTables(const uint8_t* outGammaTables[3], uint8_t* gammaTableStorage,
+ const SkColorSpace* space, bool gammasAreMatching);
+
+ friend class SkColorSpaceXform;
+ friend class SkColorSpace_Base;
+};
enum SrcGamma {
kLinear_SrcGamma,
@@ -31,24 +48,22 @@
};
template <SrcGamma kSrc, DstGamma kDst, ColorSpaceMatch kCSM>
-class SkColorSpaceXform_Base : public SkColorSpaceXform {
-public:
- static constexpr int kDstGammaTableSize = 1024;
-
+class SkColorSpaceXform_XYZ : public SkColorSpaceXform_Base {
protected:
bool onApply(ColorFormat dstFormat, void* dst, ColorFormat srcFormat, const void* src,
int count, SkAlphaType alphaType) const override;
private:
- SkColorSpaceXform_Base(SkColorSpace* srcSpace, const SkMatrix44& srcToDst,
- SkColorSpace* dstSpace);
+ SkColorSpaceXform_XYZ(SkColorSpace* srcSpace, const SkMatrix44& srcToDst,
+ SkColorSpace* dstSpace);
sk_sp<SkColorLookUpTable> fColorLUT;
// Contain pointers into storage or pointers into precomputed tables.
const float* fSrcGammaTables[3];
+ SkAutoTMalloc<float> fSrcStorage;
const uint8_t* fDstGammaTables[3];
- SkAutoMalloc fStorage;
+ sk_sp<SkData> fDstStorage;
float fSrcToDst[16];
diff --git a/src/core/SkColorSpace_Base.h b/src/core/SkColorSpace_Base.h
index 36cc477..a188a11 100644
--- a/src/core/SkColorSpace_Base.h
+++ b/src/core/SkColorSpace_Base.h
@@ -177,6 +177,8 @@
const SkMatrix44& toXYZD50() const { return fToXYZD50; }
const SkMatrix44& fromXYZD50() const;
+ void toDstGammaTables(const uint8_t* tables[3], sk_sp<SkData>* storage, int numTables) const;
+
/**
* Create an SkColorSpace with the same gamut as this color space, but with linear gamma.
*/
@@ -200,14 +202,18 @@
SkColorSpace_Base(sk_sp<SkColorLookUpTable> colorLUT, SkGammaNamed gammaNamed,
sk_sp<SkGammas> gammas, const SkMatrix44& toXYZ, sk_sp<SkData> profileData);
- sk_sp<SkColorLookUpTable> fColorLUT;
- const SkGammaNamed fGammaNamed;
- sk_sp<SkGammas> fGammas;
- sk_sp<SkData> fProfileData;
+ sk_sp<SkColorLookUpTable> fColorLUT;
+ const SkGammaNamed fGammaNamed;
+ sk_sp<SkGammas> fGammas;
+ sk_sp<SkData> fProfileData;
- const SkMatrix44 fToXYZD50;
- mutable SkMatrix44 fFromXYZD50;
- mutable SkOnce fFromXYZOnce;
+ const SkMatrix44 fToXYZD50;
+ mutable SkMatrix44 fFromXYZD50;
+ mutable SkOnce fFromXYZOnce;
+
+ mutable sk_sp<SkData> fDstStorage;
+ mutable const uint8_t* fToDstGammaTables[3];
+ mutable SkOnce fToDstGammaOnce;
friend class SkColorSpace;
friend class ColorSpaceXformTest;
diff --git a/tests/ColorSpaceXformTest.cpp b/tests/ColorSpaceXformTest.cpp
index 0885d58..6cf0dbe 100644
--- a/tests/ColorSpaceXformTest.cpp
+++ b/tests/ColorSpaceXformTest.cpp
@@ -30,7 +30,8 @@
return SkTAbs(x - y) <= 1;
}
-static void test_identity_xform(skiatest::Reporter* r, const sk_sp<SkGammas>& gammas) {
+static void test_identity_xform(skiatest::Reporter* r, const sk_sp<SkGammas>& gammas,
+ bool repeat) {
// Arbitrary set of 10 pixels
constexpr int width = 10;
constexpr uint32_t srcPixels[width] = {
@@ -57,6 +58,12 @@
REPORTER_ASSERT(r, almost_equal(((srcPixels[i] >> 24) & 0xFF),
SkGetPackedA32(dstPixels[i])));
}
+
+ if (repeat) {
+ // We should cache part of the transform after the run. So it is interesting
+ // to make sure it still runs correctly the second time.
+ test_identity_xform(r, gammas, false);
+ }
}
DEF_TEST(ColorSpaceXform_TableGamma, r) {
@@ -81,7 +88,7 @@
table[7] = 0.60f;
table[8] = 0.75f;
table[9] = 1.00f;
- test_identity_xform(r, gammas);
+ test_identity_xform(r, gammas, true);
}
DEF_TEST(ColorSpaceXform_ParametricGamma, r) {
@@ -107,7 +114,7 @@
params->fB = 0.055f / 1.055f;
params->fC = 0.0f;
params->fG = 2.4f;
- test_identity_xform(r, gammas);
+ test_identity_xform(r, gammas, true);
}
DEF_TEST(ColorSpaceXform_ExponentialGamma, r) {
@@ -115,7 +122,7 @@
sk_sp<SkGammas> gammas = sk_sp<SkGammas>(new SkGammas());
gammas->fRedType = gammas->fGreenType = gammas->fBlueType = SkGammas::Type::kValue_Type;
gammas->fRedData.fValue = gammas->fGreenData.fValue = gammas->fBlueData.fValue = 1.4f;
- test_identity_xform(r, gammas);
+ test_identity_xform(r, gammas, true);
}
DEF_TEST(ColorSpaceXform_NamedGamma, r) {
@@ -124,7 +131,7 @@
gammas->fRedData.fNamed = kSRGB_SkGammaNamed;
gammas->fGreenData.fNamed = k2Dot2Curve_SkGammaNamed;
gammas->fBlueData.fNamed = kLinear_SkGammaNamed;
- test_identity_xform(r, gammas);
+ test_identity_xform(r, gammas, true);
}
DEF_TEST(ColorSpaceXform_NonMatchingGamma, r) {
@@ -165,7 +172,7 @@
gammas->fBlueType = SkGammas::Type::kParam_Type;
gammas->fBlueData.fParamOffset = sizeof(float) * tableSize;
- test_identity_xform(r, gammas);
+ test_identity_xform(r, gammas, true);
}
DEF_TEST(ColorSpaceXform_applyCLUTMemoryAccess, r) {