diff --git a/include/core/SkColorSpace.h b/include/core/SkColorSpace.h index 99e9aae6c5..485df98189 100644 --- a/include/core/SkColorSpace.h +++ b/include/core/SkColorSpace.h @@ -165,9 +165,8 @@ public: bool toXYZD50(SkMatrix44* toXYZD50) const; /** - * Returns a hash of the gamut transofmration to XYZ D50. Allows for fast equality checking + * Returns a hash of the gamut transformation to XYZ D50. Allows for fast equality checking * of gamuts, at the (very small) risk of collision. - * Returns 0 if color gamut cannot be described in terms of XYZ D50. */ uint32_t toXYZD50Hash() const { return fToXYZD50Hash; } @@ -227,12 +226,15 @@ public: * If both are null, we return true. If one is null and the other is not, we return false. * If both are non-null, we do a deeper compare. */ - static bool Equals(const SkColorSpace* src, const SkColorSpace* dst); + static bool Equals(const SkColorSpace*, const SkColorSpace*); void transferFn(float gabcdef[7]) const; void invTransferFn(float gabcdef[7]) const; void gamutTransformTo(const SkColorSpace* dst, float src_to_dst_row_major[9]) const; + uint32_t transferFnHash() const { return fTransferFnHash; } + uint64_t hash() const { return (uint64_t)fTransferFnHash << 32 | fToXYZD50Hash; } + private: friend class SkColorSpaceSingletonFactory; @@ -243,7 +245,8 @@ private: void computeLazyDstFields() const; SkGammaNamed fGammaNamed; // TODO: 2-bit, pack tightly? drop? - uint32_t fToXYZD50Hash; // TODO: Switch to whole-CS hash? + uint32_t fTransferFnHash; + uint32_t fToXYZD50Hash; float fTransferFn[7]; float fToXYZD50_3x3[9]; // row-major diff --git a/src/core/SkColorSpace.cpp b/src/core/SkColorSpace.cpp index 49fa6c005d..b8ef12a1e4 100644 --- a/src/core/SkColorSpace.cpp +++ b/src/core/SkColorSpace.cpp @@ -49,7 +49,7 @@ SkColorSpace::SkColorSpace(SkGammaNamed gammaNamed, fToXYZD50_3x3[3*r+c] = toXYZD50.get(r,c); } SkASSERT(xyz_almost_equal(toXYZD50, fToXYZD50_3x3)); - fToXYZD50Hash = SkOpts::hash_fn(fToXYZD50_3x3, sizeof(fToXYZD50_3x3), 0); + fToXYZD50Hash = SkOpts::hash_fn(fToXYZD50_3x3, 9*sizeof(float), 0); switch (fGammaNamed) { case kSRGB_SkGammaNamed: transferFn = & gSRGB_TransferFn.fG; break; @@ -58,6 +58,7 @@ SkColorSpace::SkColorSpace(SkGammaNamed gammaNamed, case kNonStandard_SkGammaNamed: break; } memcpy(fTransferFn, transferFn, 7*sizeof(float)); + fTransferFnHash = SkOpts::hash_fn(fTransferFn, 7*sizeof(float), 0); } @@ -498,39 +499,25 @@ sk_sp SkColorSpace::Deserialize(const void* data, size_t length) { } } -bool SkColorSpace::Equals(const SkColorSpace* src, const SkColorSpace* dst) { - if (src == dst) { +bool SkColorSpace::Equals(const SkColorSpace* x, const SkColorSpace* y) { + if (x == y) { return true; } - if (!src || !dst) { + if (!x || !y) { return false; } - if (src->gammaNamed() != dst->gammaNamed()) { - return false; - } - - switch (src->gammaNamed()) { - case kSRGB_SkGammaNamed: - case k2Dot2Curve_SkGammaNamed: - case kLinear_SkGammaNamed: - if (src->toXYZD50Hash() == dst->toXYZD50Hash()) { - for (int i = 0; i < 9; i++) { - SkASSERT(src->fToXYZD50_3x3[i] == dst->fToXYZD50_3x3[i] && "Hash collsion"); - } - return true; - } - return false; - default: - // It is unlikely that we will reach this case. - // TODO: Simplify this case now that color spaces have one representation. - sk_sp serializedSrcData = src->serialize(); - sk_sp serializedDstData = dst->serialize(); - return serializedSrcData->size() == serializedDstData->size() && - 0 == memcmp(serializedSrcData->data(), serializedDstData->data(), - serializedSrcData->size()); + if (x->hash() == y->hash()) { + for (int i = 0; i < 7; i++) { + SkASSERT(x-> fTransferFn[i] == y-> fTransferFn[i] && "Hash collsion"); + } + for (int i = 0; i < 9; i++) { + SkASSERT(x->fToXYZD50_3x3[i] == y->fToXYZD50_3x3[i] && "Hash collsion"); + } + return true; } + return false; } SkColorSpaceTransferFn SkColorSpaceTransferFn::invert() const { diff --git a/src/core/SkColorSpaceXformSteps.cpp b/src/core/SkColorSpaceXformSteps.cpp index 78409c6c2f..75489300d4 100644 --- a/src/core/SkColorSpaceXformSteps.cpp +++ b/src/core/SkColorSpaceXformSteps.cpp @@ -24,7 +24,8 @@ SkColorSpaceXformSteps::SkColorSpaceXformSteps(SkColorSpace* src, SkAlphaType sr if (!src) { src = sk_srgb_singleton(); } if (!dst) { dst = src; } - if (src == dst && srcAT == dstAT) { + if (src->hash() == dst->hash() && srcAT == dstAT) { + SkASSERT(SkColorSpace::Equals(src,dst)); return; } @@ -49,15 +50,19 @@ SkColorSpaceXformSteps::SkColorSpaceXformSteps(SkColorSpace* src, SkAlphaType sr this->src_to_dst_matrix[6] = row_major[2]; this->src_to_dst_matrix[7] = row_major[5]; this->src_to_dst_matrix[8] = row_major[8]; + } else { + #ifdef SK_DEBUG + SkMatrix44 srcM, dstM; + src->toXYZD50(&srcM); + dst->toXYZD50(&dstM); + SkASSERT(srcM == dstM && "Hash collision"); + #endif } // Fill out all the transfer functions we'll use. src-> transferFn(&this->srcTF .fG); dst->invTransferFn(&this->dstTFInv.fG); - SkColorSpaceTransferFn dstTF; - dst->transferFn(&dstTF.fG); - this->srcTF_is_sRGB = src->gammaCloseToSRGB(); this->dstTF_is_sRGB = dst->gammaCloseToSRGB(); @@ -65,8 +70,15 @@ SkColorSpaceXformSteps::SkColorSpaceXformSteps(SkColorSpace* src, SkAlphaType sr if ( this->flags.linearize && !this->flags.gamut_transform && this->flags.encode && - 0 == memcmp(&srcTF, &dstTF, sizeof(SkColorSpaceTransferFn))) + src->transferFnHash() == dst->transferFnHash()) { + #ifdef SK_DEBUG + float dstTF[7]; + dst->transferFn(dstTF); + for (int i = 0; i < 7; i++) { + SkASSERT( (&srcTF.fG)[i] == dstTF[i] && "Hash collision" ); + } + #endif this->flags.linearize = false; this->flags.encode = false; }