diff options
author | Mike Klein <mtklein@chromium.org> | 2017-09-19 16:12:29 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-09-19 20:46:11 +0000 |
commit | 6c4ea7e8801c5b2b758c67d01e236da29292799b (patch) | |
tree | ba399fa6fb70fde0c2ad42c9dc88abffe5259153 /src/core | |
parent | 76399d1b4f987f99deae35d4608641a762c08645 (diff) |
Fix 3 related races in SkColorSpace.cpp.
As written one thread can be comparing against, say, gSRGB, while
another thread is initializing it. TSAN caught us.
To fix this, we funnel everything through a function that returns its
own local static, which is intialized on first use in a thread safe way.
Change-Id: I2b7aa4628daff0511ad969d9800d40d967e2938e
Reviewed-on: https://skia-review.googlesource.com/48761
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Mike Klein <mtklein@chromium.org>
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/SkColorSpace.cpp | 74 |
1 files changed, 27 insertions, 47 deletions
diff --git a/src/core/SkColorSpace.cpp b/src/core/SkColorSpace.cpp index 9942406a0e..ec34f1f418 100644 --- a/src/core/SkColorSpace.cpp +++ b/src/core/SkColorSpace.cpp @@ -9,7 +9,6 @@ #include "SkColorSpace_Base.h" #include "SkColorSpace_XYZ.h" #include "SkColorSpacePriv.h" -#include "SkOnce.h" #include "SkPoint3.h" bool SkColorSpacePrimaries::toXYZD50(SkMatrix44* toXYZ_D50) const { @@ -195,51 +194,32 @@ sk_sp<SkColorSpace> SkColorSpace::MakeRGB(const SkColorSpaceTransferFn& coeffs, return SkColorSpace::MakeRGB(coeffs, toXYZD50); } -static SkColorSpace* gAdobeRGB; -static SkColorSpace* gSRGB; -static SkColorSpace* gSRGBLinear; +static SkColorSpace* singleton_colorspace(SkGammaNamed gamma, const float to_xyz[9]) { + SkMatrix44 m44(SkMatrix44::kUninitialized_Constructor); + m44.set3x3RowMajorf(to_xyz); + (void)m44.getType(); // Force typemask to be computed to avoid races. + return new SkColorSpace_XYZ(gamma, m44); +} -sk_sp<SkColorSpace> SkColorSpace_Base::MakeNamed(Named named) { - static SkOnce sRGBOnce; - static SkOnce adobeRGBOnce; - static SkOnce sRGBLinearOnce; +static SkColorSpace* adobe_rgb() { + static SkColorSpace* cs = singleton_colorspace(k2Dot2Curve_SkGammaNamed, gAdobeRGB_toXYZD50); + return cs; +} +static SkColorSpace* srgb() { + static SkColorSpace* cs = singleton_colorspace(kSRGB_SkGammaNamed, gSRGB_toXYZD50); + return cs; +} +static SkColorSpace* srgb_linear() { + static SkColorSpace* cs = singleton_colorspace(kLinear_SkGammaNamed, gSRGB_toXYZD50); + return cs; +} +sk_sp<SkColorSpace> SkColorSpace_Base::MakeNamed(Named named) { switch (named) { - case kSRGB_Named: { - sRGBOnce([] { - SkMatrix44 srgbToxyzD50(SkMatrix44::kUninitialized_Constructor); - srgbToxyzD50.set3x3RowMajorf(gSRGB_toXYZD50); - - // Force the mutable type mask to be computed. This avoids races. - (void)srgbToxyzD50.getType(); - gSRGB = new SkColorSpace_XYZ(kSRGB_SkGammaNamed, srgbToxyzD50); - }); - return sk_ref_sp<SkColorSpace>(gSRGB); - } - case kAdobeRGB_Named: { - adobeRGBOnce([] { - SkMatrix44 adobergbToxyzD50(SkMatrix44::kUninitialized_Constructor); - adobergbToxyzD50.set3x3RowMajorf(gAdobeRGB_toXYZD50); - - // Force the mutable type mask to be computed. This avoids races. - (void)adobergbToxyzD50.getType(); - gAdobeRGB = new SkColorSpace_XYZ(k2Dot2Curve_SkGammaNamed, adobergbToxyzD50); - }); - return sk_ref_sp<SkColorSpace>(gAdobeRGB); - } - case kSRGBLinear_Named: { - sRGBLinearOnce([] { - SkMatrix44 srgbToxyzD50(SkMatrix44::kUninitialized_Constructor); - srgbToxyzD50.set3x3RowMajorf(gSRGB_toXYZD50); - - // Force the mutable type mask to be computed. This avoids races. - (void)srgbToxyzD50.getType(); - gSRGBLinear = new SkColorSpace_XYZ(kLinear_SkGammaNamed, srgbToxyzD50); - }); - return sk_ref_sp<SkColorSpace>(gSRGBLinear); - } - default: - break; + case kSRGB_Named: return sk_ref_sp(srgb()); + case kAdobeRGB_Named: return sk_ref_sp(adobe_rgb()); + case kSRGBLinear_Named: return sk_ref_sp(srgb_linear()); + default: break; } return nullptr; } @@ -277,7 +257,7 @@ bool SkColorSpace::toXYZD50(SkMatrix44* toXYZD50) const { } bool SkColorSpace::isSRGB() const { - return gSRGB == this; + return srgb() == this; } /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -344,19 +324,19 @@ size_t SkColorSpace::writeToMemory(void* memory) const { const SkColorSpace_XYZ* thisXYZ = static_cast<const SkColorSpace_XYZ*>(this); // If we have a named profile, only write the enum. const SkGammaNamed gammaNamed = thisXYZ->gammaNamed(); - if (this == gSRGB) { + if (this == srgb()) { if (memory) { *((ColorSpaceHeader*) memory) = ColorSpaceHeader::Pack( k0_Version, SkColorSpace_Base::kSRGB_Named, gammaNamed, 0); } return sizeof(ColorSpaceHeader); - } else if (this == gAdobeRGB) { + } else if (this == adobe_rgb()) { if (memory) { *((ColorSpaceHeader*) memory) = ColorSpaceHeader::Pack( k0_Version, SkColorSpace_Base::kAdobeRGB_Named, gammaNamed, 0); } return sizeof(ColorSpaceHeader); - } else if (this == gSRGBLinear) { + } else if (this == srgb_linear()) { if (memory) { *((ColorSpaceHeader*) memory) = ColorSpaceHeader::Pack( k0_Version, SkColorSpace_Base::kSRGBLinear_Named, gammaNamed, 0); |