diff options
author | Matt Sarett <msarett@google.com> | 2016-10-16 10:20:41 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2016-10-16 14:51:57 +0000 |
commit | f489886915034093278353d06c6f1973b2e8b7d2 (patch) | |
tree | 284181b7f901cd0ac47ed0e52df17cc64a86fb49 /src | |
parent | 24a865c2c048faa615fcdde3b209a9c10a9be923 (diff) |
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>
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkColorSpace.cpp | 18 | ||||
-rw-r--r-- | src/core/SkColorSpaceXform.cpp | 86 | ||||
-rw-r--r-- | src/core/SkColorSpaceXform_Base.h | 29 | ||||
-rw-r--r-- | src/core/SkColorSpace_Base.h | 20 |
4 files changed, 100 insertions, 53 deletions
diff --git a/src/core/SkColorSpace.cpp b/src/core/SkColorSpace.cpp index bdef5b3b75..b956c7fe3e 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 @@ const SkMatrix44& SkColorSpace_Base::fromXYZD50() const { 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 50cd9c11e5..5e362464b4 100644 --- a/src/core/SkColorSpaceXform.cpp +++ b/src/core/SkColorSpaceXform.cpp @@ -138,9 +138,7 @@ static uint8_t clamp_normalized_float_to_byte(float v) { } } -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 @@ 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, - 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 @@ static void build_gamma_tables(const T* outGammaTables[3], T* gammaTableStorage, } } +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 @@ std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(SkColorSpace* srcSpace 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 @@ std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(SkColorSpace* srcSpace 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 @@ std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(SkColorSpace* srcSpace 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 @@ static inline int num_tables(SkColorSpace* space) { } 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 @@ static inline bool apply_set_src(void* dst, const void* src, int len, SkAlphaTyp } 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_Base<kSrc, kDst, kCSM> } } +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 02714ad59e..c1b9785424 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 @@ enum ColorSpaceMatch { }; 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 36cc47779a..a188a11dd1 100644 --- a/src/core/SkColorSpace_Base.h +++ b/src/core/SkColorSpace_Base.h @@ -177,6 +177,8 @@ public: 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 @@ private: 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; |