Revert "Fully embrace skcms types in SkColorSpace API"

This reverts commit 701522798a.

Reason for revert: Maybe blocking the Android roll

Original change's description:
> Fully embrace skcms types in SkColorSpace API
> 
> Remove the SkMatrix44 getter entirely.
> 
> Change-Id: I25bfe68a7a9b21d8a8696415b517cb79fc2d7a94
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/252596
> Commit-Queue: Brian Osman <brianosman@google.com>
> Reviewed-by: Mike Klein <mtklein@google.com>

TBR=mtklein@google.com,brianosman@google.com,reed@google.com

Change-Id: Ic277d54d4ac8c84f00405946c927a3aee4e33068
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/252801
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Robert Phillips 2019-11-05 15:03:42 +00:00 committed by Skia Commit-Bot
parent cfa4f60270
commit 6af9b1c673
6 changed files with 100 additions and 71 deletions

View File

@ -8,10 +8,6 @@ Milestone 80
<Insert new notes here- top is most recent.>
* Removed SkMatrix44 version of toXYZD50 from SkColorSpace. Switched to skcms types in
transferFn, invTrasnferFn, and gamutTransformTo functions.
https://review.skia.org/252596
* Removed rotation and YUV support from SkColorMatrix
https://review.skia.org/252188

View File

@ -1237,7 +1237,7 @@ struct Task {
};
skcms_TransferFunction tf;
cs->transferFn(&tf);
cs->transferFn(&tf.g);
switch (classify_transfer_fn(tf)) {
case sRGBish_TF:
if (tf.a == 1 && tf.b == 0 && tf.c == 0 && tf.d == 0 && tf.e == 0 && tf.f == 0) {

View File

@ -151,6 +151,8 @@ public:
* Returns true and sets |toXYZD50| if the color gamut can be described as a matrix.
* Returns false otherwise.
*/
bool toXYZD50(SkMatrix44* toXYZD50) const;
bool toXYZD50(skcms_Matrix3x3* toXYZD50) const;
/**
@ -217,9 +219,9 @@ public:
*/
static bool Equals(const SkColorSpace*, const SkColorSpace*);
void transferFn(skcms_TransferFunction* fn) const;
void invTransferFn(skcms_TransferFunction* fn) const;
void gamutTransformTo(const SkColorSpace* dst, skcms_Matrix3x3* src_to_dst) const;
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; }
@ -227,18 +229,19 @@ public:
private:
friend class SkColorSpaceSingletonFactory;
SkColorSpace(const skcms_TransferFunction& transferFn, const skcms_Matrix3x3& toXYZ);
SkColorSpace(const float transferFn[7],
const skcms_Matrix3x3& toXYZ);
void computeLazyDstFields() const;
uint32_t fTransferFnHash;
uint32_t fToXYZD50Hash;
skcms_TransferFunction fTransferFn;
skcms_Matrix3x3 fToXYZD50;
float fTransferFn[7];
float fToXYZD50_3x3[9]; // row-major
mutable skcms_TransferFunction fInvTransferFn;
mutable skcms_Matrix3x3 fFromXYZD50;
mutable float fInvTransferFn[7];
mutable float fFromXYZD50_3x3[9]; // row-major
mutable SkOnce fLazyDstFieldsOnce;
};

View File

@ -15,12 +15,13 @@ bool SkColorSpacePrimaries::toXYZD50(skcms_Matrix3x3* toXYZ_D50) const {
return skcms_PrimariesToXYZD50(fRX, fRY, fGX, fGY, fBX, fBY, fWX, fWY, toXYZ_D50);
}
SkColorSpace::SkColorSpace(const skcms_TransferFunction& transferFn,
const skcms_Matrix3x3& toXYZD50)
: fTransferFn(transferFn)
, fToXYZD50(toXYZD50) {
fTransferFnHash = SkOpts::hash_fn(&fTransferFn, 7*sizeof(float), 0);
fToXYZD50Hash = SkOpts::hash_fn(&fToXYZD50, 9*sizeof(float), 0);
SkColorSpace::SkColorSpace(const float transferFn[7],
const skcms_Matrix3x3& toXYZD50) {
memcpy(fToXYZD50_3x3, &toXYZD50.vals[0][0], 9*sizeof(float));
fToXYZD50Hash = SkOpts::hash_fn(fToXYZD50_3x3, 9*sizeof(float), 0);
memcpy(fTransferFn, transferFn, 7*sizeof(float));
fTransferFnHash = SkOpts::hash_fn(fTransferFn, 7*sizeof(float), 0);
}
static bool xyz_almost_equal(const skcms_Matrix3x3& mA, const skcms_Matrix3x3& mB) {
@ -41,30 +42,30 @@ sk_sp<SkColorSpace> SkColorSpace::MakeRGB(const skcms_TransferFunction& transfer
return nullptr;
}
const skcms_TransferFunction* tf = &transferFn;
const float* tf = &transferFn.g;
if (is_almost_srgb(transferFn)) {
if (xyz_almost_equal(toXYZ, SkNamedGamut::kSRGB)) {
return SkColorSpace::MakeSRGB();
}
tf = &SkNamedTransferFn::kSRGB;
tf = &SkNamedTransferFn::kSRGB.g;
} else if (is_almost_2dot2(transferFn)) {
tf = &SkNamedTransferFn::k2Dot2;
tf = &SkNamedTransferFn::k2Dot2.g;
} else if (is_almost_linear(transferFn)) {
if (xyz_almost_equal(toXYZ, SkNamedGamut::kSRGB)) {
return SkColorSpace::MakeSRGBLinear();
}
tf = &SkNamedTransferFn::kLinear;
tf = &SkNamedTransferFn::kLinear.g;
}
return sk_sp<SkColorSpace>(new SkColorSpace(*tf, toXYZ));
return sk_sp<SkColorSpace>(new SkColorSpace(tf, toXYZ));
}
class SkColorSpaceSingletonFactory {
public:
static SkColorSpace* Make(const skcms_TransferFunction& transferFn,
const skcms_Matrix3x3& to_xyz) {
return new SkColorSpace(transferFn, to_xyz);
return new SkColorSpace(&transferFn.g, to_xyz);
}
};
@ -93,17 +94,22 @@ void SkColorSpace::computeLazyDstFields() const {
// Invert 3x3 gamut, defaulting to sRGB if we can't.
{
if (!skcms_Matrix3x3_invert(&fToXYZD50, &fFromXYZD50)) {
SkAssertResult(skcms_Matrix3x3_invert(&skcms_sRGB_profile()->toXYZD50,
&fFromXYZD50));
skcms_Matrix3x3 fwd, inv;
memcpy(&fwd, fToXYZD50_3x3, 9*sizeof(float));
if (!skcms_Matrix3x3_invert(&fwd, &inv)) {
SkAssertResult(skcms_Matrix3x3_invert(&skcms_sRGB_profile()->toXYZD50, &inv));
}
memcpy(fFromXYZD50_3x3, &inv, 9*sizeof(float));
}
// Invert transfer function, defaulting to sRGB if we can't.
{
if (!skcms_TransferFunction_invert(&fTransferFn, &fInvTransferFn)) {
fInvTransferFn = *skcms_sRGB_Inverse_TransferFunction();
skcms_TransferFunction fwd, inv;
this->transferFn(&fwd.g);
if (!skcms_TransferFunction_invert(&fwd, &inv)) {
inv = *skcms_sRGB_Inverse_TransferFunction();
}
memcpy(fInvTransferFn, &inv, 7*sizeof(float));
}
});
@ -113,27 +119,40 @@ bool SkColorSpace::isNumericalTransferFn(skcms_TransferFunction* coeffs) const {
// TODO: Change transferFn/invTransferFn to just operate on skcms_TransferFunction (all callers
// already pass pointers to an skcms struct). Then remove this function, and update the two
// remaining callers to do the right thing with transferFn and classify.
this->transferFn(coeffs);
this->transferFn(&coeffs->g);
return classify_transfer_fn(*coeffs) == sRGBish_TF;
}
void SkColorSpace::transferFn(skcms_TransferFunction* fn) const {
*fn = fTransferFn;
void SkColorSpace::transferFn(float gabcdef[7]) const {
memcpy(gabcdef, &fTransferFn, 7*sizeof(float));
}
void SkColorSpace::invTransferFn(skcms_TransferFunction* fn) const {
void SkColorSpace::invTransferFn(float gabcdef[7]) const {
this->computeLazyDstFields();
*fn = fInvTransferFn;
memcpy(gabcdef, &fInvTransferFn, 7*sizeof(float));
}
bool SkColorSpace::toXYZD50(skcms_Matrix3x3* toXYZD50) const {
*toXYZD50 = fToXYZD50;
bool SkColorSpace::toXYZD50(SkMatrix44* toXYZD50) const {
toXYZD50->set3x3RowMajorf(fToXYZD50_3x3);
return true;
}
void SkColorSpace::gamutTransformTo(const SkColorSpace* dst, skcms_Matrix3x3* src_to_dst) const {
bool SkColorSpace::toXYZD50(skcms_Matrix3x3* toXYZD50) const {
memcpy(toXYZD50, fToXYZD50_3x3, 9*sizeof(float));
return true;
}
void SkColorSpace::gamutTransformTo(const SkColorSpace* dst, float src_to_dst[9]) const {
dst->computeLazyDstFields();
*src_to_dst = skcms_Matrix3x3_concat(&dst->fFromXYZD50, &fToXYZD50);
skcms_Matrix3x3 toXYZD50,
fromXYZD50;
memcpy(& toXYZD50, this-> fToXYZD50_3x3, 9*sizeof(float));
memcpy(&fromXYZD50, dst ->fFromXYZD50_3x3, 9*sizeof(float));
skcms_Matrix3x3 srcToDst = skcms_Matrix3x3_concat(&fromXYZD50, &toXYZD50);
memcpy(src_to_dst, &srcToDst, 9*sizeof(float));
}
bool SkColorSpace::isSRGB() const {
@ -142,26 +161,30 @@ bool SkColorSpace::isSRGB() const {
bool SkColorSpace::gammaCloseToSRGB() const {
// Nearly-equal transfer functions were snapped at construction time, so just do an exact test
return memcmp(&fTransferFn, &SkNamedTransferFn::kSRGB, 7*sizeof(float)) == 0;
return memcmp(fTransferFn, &SkNamedTransferFn::kSRGB.g, 7*sizeof(float)) == 0;
}
bool SkColorSpace::gammaIsLinear() const {
// Nearly-equal transfer functions were snapped at construction time, so just do an exact test
return memcmp(&fTransferFn, &SkNamedTransferFn::kLinear, 7*sizeof(float)) == 0;
return memcmp(fTransferFn, &SkNamedTransferFn::kLinear.g, 7*sizeof(float)) == 0;
}
sk_sp<SkColorSpace> SkColorSpace::makeLinearGamma() const {
if (this->gammaIsLinear()) {
return sk_ref_sp(const_cast<SkColorSpace*>(this));
}
return SkColorSpace::MakeRGB(SkNamedTransferFn::kLinear, fToXYZD50);
skcms_Matrix3x3 gamut;
this->toXYZD50(&gamut);
return SkColorSpace::MakeRGB(SkNamedTransferFn::kLinear, gamut);
}
sk_sp<SkColorSpace> SkColorSpace::makeSRGBGamma() const {
if (this->gammaCloseToSRGB()) {
return sk_ref_sp(const_cast<SkColorSpace*>(this));
}
return SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, fToXYZD50);
skcms_Matrix3x3 gamut;
this->toXYZD50(&gamut);
return SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, gamut);
}
sk_sp<SkColorSpace> SkColorSpace::makeColorSpin() const {
@ -171,15 +194,24 @@ sk_sp<SkColorSpace> SkColorSpace::makeColorSpin() const {
{ 0, 1, 0 },
}};
skcms_Matrix3x3 spun = skcms_Matrix3x3_concat(&fToXYZD50, &spin);
skcms_Matrix3x3 toXYZ;
this->toXYZD50(&toXYZ);
skcms_Matrix3x3 spun = skcms_Matrix3x3_concat(&toXYZ, &spin);
return sk_sp<SkColorSpace>(new SkColorSpace(fTransferFn, spun));
}
void SkColorSpace::toProfile(skcms_ICCProfile* profile) const {
skcms_TransferFunction tf;
skcms_Matrix3x3 toXYZD50;
memcpy(&tf, fTransferFn, 7*sizeof(float));
memcpy(&toXYZD50, fToXYZD50_3x3, 9*sizeof(float));
skcms_Init (profile);
skcms_SetTransferFunction(profile, &fTransferFn);
skcms_SetXYZD50 (profile, &fToXYZD50);
skcms_SetTransferFunction(profile, &tf);
skcms_SetXYZD50 (profile, &toXYZD50);
}
sk_sp<SkColorSpace> SkColorSpace::Make(const skcms_ICCProfile& profile) {
@ -257,10 +289,10 @@ size_t SkColorSpace::writeToMemory(void* memory) const {
*((ColorSpaceHeader*) memory) = ColorSpaceHeader();
memory = SkTAddOffset<void>(memory, sizeof(ColorSpaceHeader));
memcpy(memory, &fTransferFn, 7 * sizeof(float));
memcpy(memory, fTransferFn, 7 * sizeof(float));
memory = SkTAddOffset<void>(memory, 7 * sizeof(float));
memcpy(memory, &fToXYZD50, 9 * sizeof(float));
memcpy(memory, fToXYZD50_3x3, 9 * sizeof(float));
}
return sizeof(ColorSpaceHeader) + 16 * sizeof(float);
@ -376,12 +408,10 @@ bool SkColorSpace::Equals(const SkColorSpace* x, const SkColorSpace* y) {
if (x->hash() == y->hash()) {
for (int i = 0; i < 7; i++) {
SkASSERT((&x->fTransferFn.g)[i] == (&y->fTransferFn.g)[i] && "Hash collsion");
SkASSERT(x-> fTransferFn[i] == y-> fTransferFn[i] && "Hash collsion");
}
for (int r = 0; r < 3; r++) {
for (int c = 0; c < 3; ++c) {
SkASSERT(x->fToXYZD50.vals[r][c] == y->fToXYZD50.vals[r][c] && "Hash collsion");
}
for (int i = 0; i < 9; i++) {
SkASSERT(x->fToXYZD50_3x3[i] == y->fToXYZD50_3x3[i] && "Hash collsion");
}
return true;
}

View File

@ -45,20 +45,20 @@ SkColorSpaceXformSteps::SkColorSpaceXformSteps(SkColorSpace* src, SkAlphaType sr
this->flags.premul = srcAT != kOpaque_SkAlphaType && dstAT == kPremul_SkAlphaType;
if (this->flags.gamut_transform) {
skcms_Matrix3x3 src_to_dst; // TODO: switch src_to_dst_matrix to row-major
src->gamutTransformTo(dst, &src_to_dst);
float row_major[9]; // TODO: switch src_to_dst_matrix to row-major
src->gamutTransformTo(dst, row_major);
this->src_to_dst_matrix[0] = src_to_dst.vals[0][0];
this->src_to_dst_matrix[1] = src_to_dst.vals[1][0];
this->src_to_dst_matrix[2] = src_to_dst.vals[2][0];
this->src_to_dst_matrix[0] = row_major[0];
this->src_to_dst_matrix[1] = row_major[3];
this->src_to_dst_matrix[2] = row_major[6];
this->src_to_dst_matrix[3] = src_to_dst.vals[0][1];
this->src_to_dst_matrix[4] = src_to_dst.vals[1][1];
this->src_to_dst_matrix[5] = src_to_dst.vals[2][1];
this->src_to_dst_matrix[3] = row_major[1];
this->src_to_dst_matrix[4] = row_major[4];
this->src_to_dst_matrix[5] = row_major[7];
this->src_to_dst_matrix[6] = src_to_dst.vals[0][2];
this->src_to_dst_matrix[7] = src_to_dst.vals[1][2];
this->src_to_dst_matrix[8] = src_to_dst.vals[2][2];
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
skcms_Matrix3x3 srcM, dstM;
@ -69,8 +69,8 @@ SkColorSpaceXformSteps::SkColorSpaceXformSteps(SkColorSpace* src, SkAlphaType sr
}
// Fill out all the transfer functions we'll use.
src-> transferFn(&this->srcTF );
dst->invTransferFn(&this->dstTFInv);
src-> transferFn(&this->srcTF .g);
dst->invTransferFn(&this->dstTFInv.g);
this->srcTF_is_sRGB = src->gammaCloseToSRGB();
this->dstTF_is_sRGB = dst->gammaCloseToSRGB();
@ -82,10 +82,10 @@ SkColorSpaceXformSteps::SkColorSpaceXformSteps(SkColorSpace* src, SkAlphaType sr
src->transferFnHash() == dst->transferFnHash())
{
#ifdef SK_DEBUG
skcms_TransferFunction dstTF;
dst->transferFn(&dstTF);
float dstTF[7];
dst->transferFn(dstTF);
for (int i = 0; i < 7; i++) {
SkASSERT( (&srcTF.g)[i] == (&dstTF.g)[i] && "Hash collision" );
SkASSERT( (&srcTF.g)[i] == dstTF[i] && "Hash collision" );
}
#endif
this->flags.linearize = false;

View File

@ -66,7 +66,7 @@ bool SkHighContrast_Filter::onAppendStages(const SkStageRec& rec, bool shaderIsO
// Linearize before applying high-contrast filter.
auto tf = alloc->make<skcms_TransferFunction>();
if (rec.fDstCS) {
rec.fDstCS->transferFn(tf);
rec.fDstCS->transferFn(&tf->g);
} else {
// Historically we approximate untagged destinations as gamma 2.
// TODO: sRGB?
@ -115,7 +115,7 @@ bool SkHighContrast_Filter::onAppendStages(const SkStageRec& rec, bool shaderIsO
// Re-encode back from linear.
auto invTF = alloc->make<skcms_TransferFunction>();
if (rec.fDstCS) {
rec.fDstCS->invTransferFn(invTF);
rec.fDstCS->invTransferFn(&invTF->g);
} else {
// See above... historically untagged == gamma 2 in this filter.
*invTF ={0.5f,1, 0,0,0,0,0};