diff options
author | 2016-06-16 10:50:55 -0700 | |
---|---|---|
committer | 2016-06-16 10:50:55 -0700 | |
commit | dea0340cadb759932e53416a657f5ea75fee8b5f (patch) | |
tree | f3c7e4c1873771ee818e0a1c86515a3ea5250d75 /src/core/SkColorSpaceXform.cpp | |
parent | bd770d619553a88eeaa64ff29082f62db5c9b4d2 (diff) |
Implement fast, correct gamma conversion for color xforms
201295.jpg on HP z620
(300x280, most common form of sRGB profile)
QCMS Xform 0.495 ms
Skia Old Xform 0.235 ms
Skia NEW Xform 0.423 ms
Vs Old Code 0.56x
Vs QCMS 1.17x
So to summarize, we are now much slower than before,
but still a bit faster than QCMS. And now we are also
far more accurate than QCMS :).
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2060823003
CQ_EXTRA_TRYBOTS=client.skia:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD-Trybot
Review-Url: https://codereview.chromium.org/2060823003
Diffstat (limited to 'src/core/SkColorSpaceXform.cpp')
-rw-r--r-- | src/core/SkColorSpaceXform.cpp | 92 |
1 files changed, 63 insertions, 29 deletions
diff --git a/src/core/SkColorSpaceXform.cpp b/src/core/SkColorSpaceXform.cpp index e142011305..4c67e8d3f0 100644 --- a/src/core/SkColorSpaceXform.cpp +++ b/src/core/SkColorSpaceXform.cpp @@ -37,10 +37,16 @@ std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(const sk_sp<SkColorSpa return nullptr; } - if (SkColorSpace::k2Dot2Curve_GammaNamed == srcSpace->gammaNamed() && - SkColorSpace::k2Dot2Curve_GammaNamed == dstSpace->gammaNamed()) + if (SkColorSpace::k2Dot2Curve_GammaNamed == dstSpace->gammaNamed() && + 0.0f == srcToDst.getFloat(3, 0) && + 0.0f == srcToDst.getFloat(3, 1) && + 0.0f == srcToDst.getFloat(3, 2)) { - return std::unique_ptr<SkColorSpaceXform>(new Sk2Dot2Xform(srcToDst)); + if (SkColorSpace::kSRGB_GammaNamed == srcSpace->gammaNamed()) { + return std::unique_ptr<SkColorSpaceXform>(new SkSRGBTo2Dot2Xform(srcToDst)); + } else if (SkColorSpace::k2Dot2Curve_GammaNamed == srcSpace->gammaNamed()) { + return std::unique_ptr<SkColorSpaceXform>(new Sk2Dot2To2Dot2Xform(srcToDst)); + } } return std::unique_ptr<SkColorSpaceXform>( @@ -49,33 +55,59 @@ std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(const sk_sp<SkColorSpa /////////////////////////////////////////////////////////////////////////////////////////////////// -Sk2Dot2Xform::Sk2Dot2Xform(const SkMatrix44& srcToDst) -{ - // Build row major 4x4 matrix: +static void build_src_to_dst(float srcToDstArray[12], const SkMatrix44& srcToDstMatrix) { + // Build the following row major matrix: // rX gX bX 0 // rY gY bY 0 // rZ gZ bZ 0 - // rQ gQ bQ 0 - fSrcToDst[0] = srcToDst.getFloat(0, 0); - fSrcToDst[1] = srcToDst.getFloat(0, 1); - fSrcToDst[2] = srcToDst.getFloat(0, 2); - fSrcToDst[3] = 0.0f; - fSrcToDst[4] = srcToDst.getFloat(1, 0); - fSrcToDst[5] = srcToDst.getFloat(1, 1); - fSrcToDst[6] = srcToDst.getFloat(1, 2); - fSrcToDst[7] = 0.0f; - fSrcToDst[8] = srcToDst.getFloat(2, 0); - fSrcToDst[9] = srcToDst.getFloat(2, 1); - fSrcToDst[10] = srcToDst.getFloat(2, 2); - fSrcToDst[11] = 0.0f; - fSrcToDst[12] = srcToDst.getFloat(3, 0); - fSrcToDst[13] = srcToDst.getFloat(3, 1); - fSrcToDst[14] = srcToDst.getFloat(3, 2); - fSrcToDst[15] = 0.0f; + // Swap R and B if necessary to make sure that we output SkPMColor order. +#ifdef SK_PMCOLOR_IS_BGRA + srcToDstArray[0] = srcToDstMatrix.getFloat(0, 2); + srcToDstArray[1] = srcToDstMatrix.getFloat(0, 1); + srcToDstArray[2] = srcToDstMatrix.getFloat(0, 0); + srcToDstArray[3] = 0.0f; + srcToDstArray[4] = srcToDstMatrix.getFloat(1, 2); + srcToDstArray[5] = srcToDstMatrix.getFloat(1, 1); + srcToDstArray[6] = srcToDstMatrix.getFloat(1, 0); + srcToDstArray[7] = 0.0f; + srcToDstArray[8] = srcToDstMatrix.getFloat(2, 2); + srcToDstArray[9] = srcToDstMatrix.getFloat(2, 1); + srcToDstArray[10] = srcToDstMatrix.getFloat(2, 0); + srcToDstArray[11] = 0.0f; +#else + srcToDstArray[0] = srcToDstMatrix.getFloat(0, 0); + srcToDstArray[1] = srcToDstMatrix.getFloat(0, 1); + srcToDstArray[2] = srcToDstMatrix.getFloat(0, 2); + srcToDstArray[3] = 0.0f; + srcToDstArray[4] = srcToDstMatrix.getFloat(1, 0); + srcToDstArray[5] = srcToDstMatrix.getFloat(1, 1); + srcToDstArray[6] = srcToDstMatrix.getFloat(1, 2); + srcToDstArray[7] = 0.0f; + srcToDstArray[8] = srcToDstMatrix.getFloat(2, 0); + srcToDstArray[9] = srcToDstMatrix.getFloat(2, 1); + srcToDstArray[10] = srcToDstMatrix.getFloat(2, 2); + srcToDstArray[11] = 0.0f; +#endif +} + +SkSRGBTo2Dot2Xform::SkSRGBTo2Dot2Xform(const SkMatrix44& srcToDst) +{ + build_src_to_dst(fSrcToDst, srcToDst); +} + +void SkSRGBTo2Dot2Xform::xform_RGB1_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const { + SkOpts::color_xform_RGB1_srgb_to_2dot2(dst, src, len, fSrcToDst); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +Sk2Dot2To2Dot2Xform::Sk2Dot2To2Dot2Xform(const SkMatrix44& srcToDst) +{ + build_src_to_dst(fSrcToDst, srcToDst); } -void Sk2Dot2Xform::xform_RGBA_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const { - SkOpts::color_xform_2Dot2_RGBA_to_8888(dst, src, len, fSrcToDst); +void Sk2Dot2To2Dot2Xform::xform_RGB1_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const { + SkOpts::color_xform_RGB1_2dot2_to_2dot2(dst, src, len, fSrcToDst); } /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -86,13 +118,15 @@ static inline float byte_to_float(uint8_t v) { // Expand range from 0-1 to 0-255, then convert. static inline uint8_t clamp_normalized_float_to_byte(float v) { + // The ordering of the logic is a little strange here in order + // to make sure we convert NaNs to 0. v = v * 255.0f; if (v >= 254.5f) { return 255; - } else if (v < 0.5f) { - return 0; - } else { + } else if (v >= 0.5f) { return (uint8_t) (v + 0.5f); + } else { + return 0; } } @@ -142,7 +176,7 @@ SkDefaultXform::SkDefaultXform(const sk_sp<SkGammas>& srcGammas, const SkMatrix4 , fDstGammas(dstGammas) {} -void SkDefaultXform::xform_RGBA_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const { +void SkDefaultXform::xform_RGB1_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const { while (len-- > 0) { // Convert to linear. // FIXME (msarett): |