Reland "hash tf, and whole colorspace"

This is a reland of 58887bc3c1

Original change's description:
> hash tf, and whole colorspace
> 
> Change-Id: I088124ead162d369c5c9f8bdd3fc0a39b2b3de46
> Reviewed-on: https://skia-review.googlesource.com/c/159486
> Commit-Queue: Mike Klein <mtklein@google.com>
> Reviewed-by: Brian Osman <brianosman@google.com>

Change-Id: Idec6b6817f7a2136083caecd20c35e1eb9f2f388
Reviewed-on: https://skia-review.googlesource.com/c/159622
Commit-Queue: Mike Klein <mtklein@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
This commit is contained in:
Mike Klein 2018-10-04 11:15:17 -04:00 committed by Skia Commit-Bot
parent 4fea17393a
commit ae16b74365
3 changed files with 38 additions and 36 deletions

View File

@ -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

View File

@ -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> 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;
if (x->hash() == y->hash()) {
for (int i = 0; i < 7; i++) {
SkASSERT(x-> fTransferFn[i] == y-> fTransferFn[i] && "Hash collsion");
}
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");
SkASSERT(x->fToXYZD50_3x3[i] == y->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<SkData> serializedSrcData = src->serialize();
sk_sp<SkData> serializedDstData = dst->serialize();
return serializedSrcData->size() == serializedDstData->size() &&
0 == memcmp(serializedSrcData->data(), serializedDstData->data(),
serializedSrcData->size());
}
}
SkColorSpaceTransferFn SkColorSpaceTransferFn::invert() const {

View File

@ -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;
}