diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index e6bb2fa2c81e..2475116ec07c 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -152,9 +152,6 @@ static const uint32_t kDefaultGlyphCacheSize = -1; #include "mozilla/gfx/GPUParent.h" #include "prsystem.h" -#include "mozilla/gfx/2D.h" -#include "mozilla/gfx/SourceSurfaceCairo.h" - using namespace mozilla; using namespace mozilla::layers; using namespace mozilla::gl; @@ -169,17 +166,23 @@ const ContentDeviceData* gContentDeviceInitData = nullptr; static Mutex* gGfxPlatformPrefsLock = nullptr; -Atomic gfxPlatform::gCMSInitialized; -CMSMode gfxPlatform::gCMSMode = CMSMode::Off; - // These two may point to the same profile -qcms_profile* gfxPlatform::gCMSOutputProfile = nullptr; -qcms_profile* gfxPlatform::gCMSsRGBProfile = nullptr; +static qcms_profile* gCMSOutputProfile = nullptr; +static qcms_profile* gCMSsRGBProfile = nullptr; -qcms_transform* gfxPlatform::gCMSRGBTransform = nullptr; -qcms_transform* gfxPlatform::gCMSInverseRGBTransform = nullptr; -qcms_transform* gfxPlatform::gCMSRGBATransform = nullptr; -qcms_transform* gfxPlatform::gCMSBGRATransform = nullptr; +static bool gCMSRGBTransformFailed = false; +static qcms_transform* gCMSRGBTransform = nullptr; +static qcms_transform* gCMSInverseRGBTransform = nullptr; +static qcms_transform* gCMSRGBATransform = nullptr; +static qcms_transform* gCMSBGRATransform = nullptr; + +static bool gCMSInitialized = false; +static CMSMode gCMSMode = CMSMode::Off; + +static void ShutdownCMS(); + +#include "mozilla/gfx/2D.h" +#include "mozilla/gfx/SourceSurfaceCairo.h" /// This override of the LogForwarder, initially used for the critical graphics /// errors, is sending the log to the crash annotations as well, but only @@ -999,9 +1002,13 @@ void gfxPlatform::Init() { Preferences::RegisterCallbackAndCall(RecordingPrefChanged, "gfx.2d.recording"); + CreateCMSOutputProfile(); + // Create the sRGB to output display profile transforms. They can be accessed // off the main thread so we want to avoid a race condition. - InitializeCMS(); + GetCMSRGBTransform(); + GetCMSRGBATransform(); + GetCMSBGRATransform(); // Listen to memory pressure event so we can purge DrawTarget caches gPlatform->mMemoryPressureObserver = @@ -2035,6 +2042,22 @@ bool gfxPlatform::OffMainThreadCompositingEnabled() { return UsesOffMainThreadCompositing(); } +CMSMode gfxPlatform::GetCMSMode() { + if (!gCMSInitialized) { + int32_t mode = StaticPrefs::gfx_color_management_mode(); + if (mode >= 0 && mode < int32_t(CMSMode::AllCount)) { + gCMSMode = CMSMode(mode); + } + + bool enableV4 = StaticPrefs::gfx_color_management_enablev4(); + if (enableV4) { + qcms_enable_iccv4(); + } + gCMSInitialized = true; + } + return gCMSMode; +} + void gfxPlatform::SetCMSModeOverride(CMSMode aMode) { MOZ_ASSERT(gCMSInitialized); gCMSMode = aMode; @@ -2109,85 +2132,121 @@ const mozilla::gfx::ContentDeviceData* gfxPlatform::GetInitContentDeviceData() { return gContentDeviceInitData; } -void gfxPlatform::InitializeCMS() { - MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread(), - "CMS should be initialized on the main thread"); - if (gCMSInitialized) { - return; - } - - { - int32_t mode = StaticPrefs::gfx_color_management_mode(); - if (mode >= 0 && mode < int32_t(CMSMode::AllCount)) { - gCMSMode = CMSMode(mode); - } - - bool enableV4 = StaticPrefs::gfx_color_management_enablev4(); - if (enableV4) { - qcms_enable_iccv4(); - } - } - - gCMSsRGBProfile = qcms_profile_sRGB(); - - /* Determine if we're using the internal override to force sRGB as - an output profile for reftests. See Bug 452125. - - Note that we don't normally (outside of tests) set a default value - of this preference, which means nsIPrefBranch::GetBoolPref will - typically throw (and leave its out-param untouched). - */ - if (StaticPrefs::gfx_color_management_force_srgb()) { - gCMSOutputProfile = gCMSsRGBProfile; - } - +void gfxPlatform::CreateCMSOutputProfile() { if (!gCMSOutputProfile) { - nsTArray outputProfileData = - gfxPlatform::GetPlatform()->GetPlatformCMSOutputProfileData(); - if (!outputProfileData.IsEmpty()) { - gCMSOutputProfile = qcms_profile_from_memory(outputProfileData.Elements(), - outputProfileData.Length()); + /* Determine if we're using the internal override to force sRGB as + an output profile for reftests. See Bug 452125. + + Note that we don't normally (outside of tests) set a default value + of this preference, which means nsIPrefBranch::GetBoolPref will + typically throw (and leave its out-param untouched). + */ + if (StaticPrefs::gfx_color_management_force_srgb()) { + gCMSOutputProfile = GetCMSsRGBProfile(); + } + + if (!gCMSOutputProfile) { + nsTArray outputProfileData = + gfxPlatform::GetPlatform()->GetPlatformCMSOutputProfileData(); + if (!outputProfileData.IsEmpty()) { + gCMSOutputProfile = qcms_profile_from_memory( + outputProfileData.Elements(), outputProfileData.Length()); + } + } + + /* Determine if the profile looks bogus. If so, close the profile + * and use sRGB instead. See bug 460629, */ + if (gCMSOutputProfile && qcms_profile_is_bogus(gCMSOutputProfile)) { + NS_ASSERTION(gCMSOutputProfile != GetCMSsRGBProfile(), + "Builtin sRGB profile tagged as bogus!!!"); + qcms_profile_release(gCMSOutputProfile); + gCMSOutputProfile = nullptr; + } + + if (!gCMSOutputProfile) { + gCMSOutputProfile = GetCMSsRGBProfile(); + } + /* Precache the LUT16 Interpolations for the output profile. See + bug 444661 for details. */ + qcms_profile_precache_output_transform(gCMSOutputProfile); + } +} + +qcms_profile* gfxPlatform::GetCMSOutputProfile() { return gCMSOutputProfile; } + +qcms_profile* gfxPlatform::GetCMSsRGBProfile() { + if (!gCMSsRGBProfile) { + /* Create the profile using qcms. */ + gCMSsRGBProfile = qcms_profile_sRGB(); + } + return gCMSsRGBProfile; +} + +qcms_transform* gfxPlatform::GetCMSRGBTransform() { + if (!gCMSRGBTransform && !gCMSRGBTransformFailed) { + qcms_profile *inProfile, *outProfile; + outProfile = GetCMSOutputProfile(); + inProfile = GetCMSsRGBProfile(); + + if (!inProfile || !outProfile) return nullptr; + + gCMSRGBTransform = + qcms_transform_create(inProfile, QCMS_DATA_RGB_8, outProfile, + QCMS_DATA_RGB_8, QCMS_INTENT_PERCEPTUAL); + if (!gCMSRGBTransform) { + gCMSRGBTransformFailed = true; } } - /* Determine if the profile looks bogus. If so, close the profile - * and use sRGB instead. See bug 460629, */ - if (gCMSOutputProfile && qcms_profile_is_bogus(gCMSOutputProfile)) { - NS_ASSERTION(gCMSOutputProfile != gCMSsRGBProfile, - "Builtin sRGB profile tagged as bogus!!!"); - qcms_profile_release(gCMSOutputProfile); - gCMSOutputProfile = nullptr; + return gCMSRGBTransform; +} + +qcms_transform* gfxPlatform::GetCMSInverseRGBTransform() { + if (!gCMSInverseRGBTransform) { + qcms_profile *inProfile, *outProfile; + inProfile = GetCMSOutputProfile(); + outProfile = GetCMSsRGBProfile(); + + if (!inProfile || !outProfile) return nullptr; + + gCMSInverseRGBTransform = + qcms_transform_create(inProfile, QCMS_DATA_RGB_8, outProfile, + QCMS_DATA_RGB_8, QCMS_INTENT_PERCEPTUAL); } - if (!gCMSOutputProfile) { - gCMSOutputProfile = gCMSsRGBProfile; + return gCMSInverseRGBTransform; +} + +qcms_transform* gfxPlatform::GetCMSRGBATransform() { + if (!gCMSRGBATransform) { + qcms_profile *inProfile, *outProfile; + outProfile = GetCMSOutputProfile(); + inProfile = GetCMSsRGBProfile(); + + if (!inProfile || !outProfile) return nullptr; + + gCMSRGBATransform = + qcms_transform_create(inProfile, QCMS_DATA_RGBA_8, outProfile, + QCMS_DATA_RGBA_8, QCMS_INTENT_PERCEPTUAL); } - /* Precache the LUT16 Interpolations for the output profile. See - bug 444661 for details. */ - qcms_profile_precache_output_transform(gCMSOutputProfile); + return gCMSRGBATransform; +} - // Create the RGB transform. - gCMSRGBTransform = - qcms_transform_create(gCMSsRGBProfile, QCMS_DATA_RGB_8, gCMSOutputProfile, - QCMS_DATA_RGB_8, QCMS_INTENT_PERCEPTUAL); +qcms_transform* gfxPlatform::GetCMSBGRATransform() { + if (!gCMSBGRATransform) { + qcms_profile *inProfile, *outProfile; + outProfile = GetCMSOutputProfile(); + inProfile = GetCMSsRGBProfile(); - // And the inverse. - gCMSInverseRGBTransform = - qcms_transform_create(gCMSOutputProfile, QCMS_DATA_RGB_8, gCMSsRGBProfile, - QCMS_DATA_RGB_8, QCMS_INTENT_PERCEPTUAL); + if (!inProfile || !outProfile) return nullptr; - // The RGBA transform. - gCMSRGBATransform = qcms_transform_create(gCMSsRGBProfile, QCMS_DATA_RGBA_8, - gCMSOutputProfile, QCMS_DATA_RGBA_8, - QCMS_INTENT_PERCEPTUAL); + gCMSBGRATransform = + qcms_transform_create(inProfile, QCMS_DATA_BGRA_8, outProfile, + QCMS_DATA_BGRA_8, QCMS_INTENT_PERCEPTUAL); + } - // And the BGRA one. - gCMSBGRATransform = qcms_transform_create(gCMSsRGBProfile, QCMS_DATA_BGRA_8, - gCMSOutputProfile, QCMS_DATA_BGRA_8, - QCMS_INTENT_PERCEPTUAL); - - gCMSInitialized = true; + return gCMSBGRATransform; } qcms_transform* gfxPlatform::GetCMSOSRGBATransform() { @@ -2215,7 +2274,7 @@ qcms_data_type gfxPlatform::GetCMSOSRGBAType() { } /* Shuts down various transforms and profiles for CMS. */ -void gfxPlatform::ShutdownCMS() { +static void ShutdownCMS() { if (gCMSRGBTransform) { qcms_transform_release(gCMSRGBTransform); gCMSRGBTransform = nullptr; @@ -2236,9 +2295,7 @@ void gfxPlatform::ShutdownCMS() { qcms_profile_release(gCMSOutputProfile); // handle the aliased case - if (gCMSsRGBProfile == gCMSOutputProfile) { - gCMSsRGBProfile = nullptr; - } + if (gCMSsRGBProfile == gCMSOutputProfile) gCMSsRGBProfile = nullptr; gCMSOutputProfile = nullptr; } if (gCMSsRGBProfile) { diff --git a/gfx/thebes/gfxPlatform.h b/gfx/thebes/gfxPlatform.h index 4b46df172608..3b4207d8037e 100644 --- a/gfx/thebes/gfxPlatform.h +++ b/gfx/thebes/gfxPlatform.h @@ -535,10 +535,7 @@ class gfxPlatform : public mozilla::layers::MemoryPressureListener { /** * Are we going to try color management? */ - static CMSMode GetCMSMode() { - EnsureCMSInitialized(); - return gCMSMode; - } + static CMSMode GetCMSMode(); /** * Used only for testing. Override the pref setting. @@ -566,50 +563,32 @@ class gfxPlatform : public mozilla::layers::MemoryPressureListener { /** * Return the output device ICC profile. */ - static qcms_profile* GetCMSOutputProfile() { - EnsureCMSInitialized(); - return gCMSOutputProfile; - } + static qcms_profile* GetCMSOutputProfile(); /** * Return the sRGB ICC profile. */ - static qcms_profile* GetCMSsRGBProfile() { - EnsureCMSInitialized(); - return gCMSsRGBProfile; - } + static qcms_profile* GetCMSsRGBProfile(); /** * Return sRGB -> output device transform. */ - static qcms_transform* GetCMSRGBTransform() { - EnsureCMSInitialized(); - return gCMSRGBTransform; - } + static qcms_transform* GetCMSRGBTransform(); /** * Return output -> sRGB device transform. */ - static qcms_transform* GetCMSInverseRGBTransform() { - MOZ_ASSERT(gCMSInitialized); - return gCMSInverseRGBTransform; - } + static qcms_transform* GetCMSInverseRGBTransform(); /** * Return sRGBA -> output device transform. */ - static qcms_transform* GetCMSRGBATransform() { - MOZ_ASSERT(gCMSInitialized); - return gCMSRGBATransform; - } + static qcms_transform* GetCMSRGBATransform(); /** * Return sBGRA -> output device transform. */ - static qcms_transform* GetCMSBGRATransform() { - MOZ_ASSERT(gCMSInitialized); - return gCMSBGRATransform; - } + static qcms_transform* GetCMSBGRATransform(); /** * Return OS RGBA -> output device transform. @@ -978,28 +957,7 @@ class gfxPlatform : public mozilla::layers::MemoryPressureListener { static void Init(); static void InitOpenGLConfig(); - - static mozilla::Atomic - gCMSInitialized; - static CMSMode gCMSMode; - - // These two may point to the same profile - static qcms_profile* gCMSOutputProfile; - static qcms_profile* gCMSsRGBProfile; - - static qcms_transform* gCMSRGBTransform; - static qcms_transform* gCMSInverseRGBTransform; - static qcms_transform* gCMSRGBATransform; - static qcms_transform* gCMSBGRATransform; - - inline static void EnsureCMSInitialized() { - if (MOZ_UNLIKELY(!gCMSInitialized)) { - InitializeCMS(); - } - } - - static void InitializeCMS(); - static void ShutdownCMS(); + static void CreateCMSOutputProfile(); friend void RecordingPrefChanged(const char* aPrefName, void* aClosure); diff --git a/image/test/gtest/Common.cpp b/image/test/gtest/Common.cpp index 06323765fe12..e8265542bacc 100644 --- a/image/test/gtest/Common.cpp +++ b/image/test/gtest/Common.cpp @@ -55,6 +55,7 @@ AutoInitializeImageLib::AutoInitializeImageLib() { gfxPlatform::GetPlatform(); // Ensure we always color manage images with gtests. + gfxPlatform::GetCMSMode(); gfxPlatform::SetCMSModeOverride(CMSMode::All); // Depending on initialization order, it is possible that our pref changes diff --git a/widget/nsXPLookAndFeel.cpp b/widget/nsXPLookAndFeel.cpp index c6496d25f309..77081532e2b8 100644 --- a/widget/nsXPLookAndFeel.cpp +++ b/widget/nsXPLookAndFeel.cpp @@ -824,23 +824,26 @@ nsresult nsXPLookAndFeel::GetColorValue(ColorID aID, } if (NS_SUCCEEDED(NativeGetColor(aID, aResult))) { - if (gfxPlatform::GetCMSMode() == CMSMode::All && - !IsSpecialColor(aID, aResult)) { - qcms_transform* transform = gfxPlatform::GetCMSInverseRGBTransform(); - if (transform) { - uint8_t color[4]; - color[0] = NS_GET_R(aResult); - color[1] = NS_GET_G(aResult); - color[2] = NS_GET_B(aResult); - color[3] = NS_GET_A(aResult); - qcms_transform_data(transform, color, color, 1); - aResult = NS_RGBA(color[0], color[1], color[2], color[3]); + // TODO(bug 1678487): We should color-correct style colors as well when in + // the traversal. + if (!mozilla::ServoStyleSet::IsInServoTraversal()) { + MOZ_ASSERT(NS_IsMainThread()); + if (gfxPlatform::GetCMSMode() == CMSMode::All && + !IsSpecialColor(aID, aResult)) { + qcms_transform* transform = gfxPlatform::GetCMSInverseRGBTransform(); + if (transform) { + uint8_t color[4]; + color[0] = NS_GET_R(aResult); + color[1] = NS_GET_G(aResult); + color[2] = NS_GET_B(aResult); + color[3] = NS_GET_A(aResult); + qcms_transform_data(transform, color, color, 1); + aResult = NS_RGBA(color[0], color[1], color[2], color[3]); + } } - } - // NOTE: Servo holds a lock and the main thread is paused, so writing to the - // global cache here is fine. - CACHE_COLOR(aID, aResult); + CACHE_COLOR(aID, aResult); + } return NS_OK; }