aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Mike Klein <mtklein@chromium.org>2017-09-19 16:12:29 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-09-19 20:46:11 +0000
commit6c4ea7e8801c5b2b758c67d01e236da29292799b (patch)
treeba399fa6fb70fde0c2ad42c9dc88abffe5259153 /src/core
parent76399d1b4f987f99deae35d4608641a762c08645 (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.cpp74
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);