зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1678487 - Ensure CMS is initialized all at once on the main thread, have thread-safe accessors for the various transforms. r=aosmond,jrmuizel
Well, mostly thread-safe, in the sense that on shutdown we might free them, but that is pre-existing and can't happen for the code-path that I'm about to touch. We could probably just avoid freeing these transforms if we wanted... Differential Revision: https://phabricator.services.mozilla.com/D104946
This commit is contained in:
Родитель
72537078cb
Коммит
ec2e64fa12
|
@ -152,6 +152,9 @@ 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;
|
||||
|
@ -166,23 +169,17 @@ const ContentDeviceData* gContentDeviceInitData = nullptr;
|
|||
|
||||
static Mutex* gGfxPlatformPrefsLock = nullptr;
|
||||
|
||||
Atomic<bool, MemoryOrdering::ReleaseAcquire> gfxPlatform::gCMSInitialized;
|
||||
CMSMode gfxPlatform::gCMSMode = CMSMode::Off;
|
||||
|
||||
// These two may point to the same profile
|
||||
static qcms_profile* gCMSOutputProfile = nullptr;
|
||||
static qcms_profile* gCMSsRGBProfile = nullptr;
|
||||
qcms_profile* gfxPlatform::gCMSOutputProfile = nullptr;
|
||||
qcms_profile* gfxPlatform::gCMSsRGBProfile = 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"
|
||||
qcms_transform* gfxPlatform::gCMSRGBTransform = nullptr;
|
||||
qcms_transform* gfxPlatform::gCMSInverseRGBTransform = nullptr;
|
||||
qcms_transform* gfxPlatform::gCMSRGBATransform = nullptr;
|
||||
qcms_transform* gfxPlatform::gCMSBGRATransform = nullptr;
|
||||
|
||||
/// This override of the LogForwarder, initially used for the critical graphics
|
||||
/// errors, is sending the log to the crash annotations as well, but only
|
||||
|
@ -952,6 +949,10 @@ void gfxPlatform::Init() {
|
|||
// Set up the vsync source for the parent process.
|
||||
ReInitFrameRate();
|
||||
|
||||
// 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();
|
||||
|
||||
#ifdef USE_SKIA
|
||||
SkGraphics::Init();
|
||||
# ifdef MOZ_ENABLE_FREETYPE
|
||||
|
@ -1002,14 +1003,6 @@ 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.
|
||||
GetCMSRGBTransform();
|
||||
GetCMSRGBATransform();
|
||||
GetCMSBGRATransform();
|
||||
|
||||
// Listen to memory pressure event so we can purge DrawTarget caches
|
||||
gPlatform->mMemoryPressureObserver =
|
||||
layers::MemoryPressureObserver::Create(gPlatform);
|
||||
|
@ -2042,22 +2035,6 @@ 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;
|
||||
|
@ -2132,121 +2109,96 @@ const mozilla::gfx::ContentDeviceData* gfxPlatform::GetInitContentDeviceData() {
|
|||
return gContentDeviceInitData;
|
||||
}
|
||||
|
||||
void gfxPlatform::CreateCMSOutputProfile() {
|
||||
void gfxPlatform::InitializeCMS() {
|
||||
if (gCMSInitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (XRE_IsGPUProcess()) {
|
||||
// Colors in the GPU process should already be managed, so we don't need to
|
||||
// perform color management there.
|
||||
gCMSInitialized = true;
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread(),
|
||||
"CMS should be initialized on the main thread");
|
||||
if (MOZ_UNLIKELY(!NS_IsMainThread())) {
|
||||
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;
|
||||
}
|
||||
|
||||
if (!gCMSOutputProfile) {
|
||||
/* 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<uint8_t> 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;
|
||||
nsTArray<uint8_t> outputProfileData =
|
||||
gfxPlatform::GetPlatform()->GetPlatformCMSOutputProfileData();
|
||||
if (!outputProfileData.IsEmpty()) {
|
||||
gCMSOutputProfile = qcms_profile_from_memory(outputProfileData.Elements(),
|
||||
outputProfileData.Length());
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
/* 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 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);
|
||||
if (!gCMSOutputProfile) {
|
||||
gCMSOutputProfile = gCMSsRGBProfile;
|
||||
}
|
||||
|
||||
return gCMSRGBATransform;
|
||||
}
|
||||
/* Precache the LUT16 Interpolations for the output profile. See
|
||||
bug 444661 for details. */
|
||||
qcms_profile_precache_output_transform(gCMSOutputProfile);
|
||||
|
||||
qcms_transform* gfxPlatform::GetCMSBGRATransform() {
|
||||
if (!gCMSBGRATransform) {
|
||||
qcms_profile *inProfile, *outProfile;
|
||||
outProfile = GetCMSOutputProfile();
|
||||
inProfile = GetCMSsRGBProfile();
|
||||
// Create the RGB transform.
|
||||
gCMSRGBTransform =
|
||||
qcms_transform_create(gCMSsRGBProfile, QCMS_DATA_RGB_8, gCMSOutputProfile,
|
||||
QCMS_DATA_RGB_8, QCMS_INTENT_PERCEPTUAL);
|
||||
|
||||
if (!inProfile || !outProfile) return nullptr;
|
||||
// And the inverse.
|
||||
gCMSInverseRGBTransform =
|
||||
qcms_transform_create(gCMSOutputProfile, QCMS_DATA_RGB_8, gCMSsRGBProfile,
|
||||
QCMS_DATA_RGB_8, QCMS_INTENT_PERCEPTUAL);
|
||||
|
||||
gCMSBGRATransform =
|
||||
qcms_transform_create(inProfile, QCMS_DATA_BGRA_8, outProfile,
|
||||
QCMS_DATA_BGRA_8, QCMS_INTENT_PERCEPTUAL);
|
||||
}
|
||||
// The RGBA transform.
|
||||
gCMSRGBATransform = qcms_transform_create(gCMSsRGBProfile, QCMS_DATA_RGBA_8,
|
||||
gCMSOutputProfile, QCMS_DATA_RGBA_8,
|
||||
QCMS_INTENT_PERCEPTUAL);
|
||||
|
||||
return gCMSBGRATransform;
|
||||
// And the BGRA one.
|
||||
gCMSBGRATransform = qcms_transform_create(gCMSsRGBProfile, QCMS_DATA_BGRA_8,
|
||||
gCMSOutputProfile, QCMS_DATA_BGRA_8,
|
||||
QCMS_INTENT_PERCEPTUAL);
|
||||
|
||||
gCMSInitialized = true;
|
||||
}
|
||||
|
||||
qcms_transform* gfxPlatform::GetCMSOSRGBATransform() {
|
||||
|
@ -2274,7 +2226,7 @@ qcms_data_type gfxPlatform::GetCMSOSRGBAType() {
|
|||
}
|
||||
|
||||
/* Shuts down various transforms and profiles for CMS. */
|
||||
static void ShutdownCMS() {
|
||||
void gfxPlatform::ShutdownCMS() {
|
||||
if (gCMSRGBTransform) {
|
||||
qcms_transform_release(gCMSRGBTransform);
|
||||
gCMSRGBTransform = nullptr;
|
||||
|
@ -2295,7 +2247,9 @@ static void ShutdownCMS() {
|
|||
qcms_profile_release(gCMSOutputProfile);
|
||||
|
||||
// handle the aliased case
|
||||
if (gCMSsRGBProfile == gCMSOutputProfile) gCMSsRGBProfile = nullptr;
|
||||
if (gCMSsRGBProfile == gCMSOutputProfile) {
|
||||
gCMSsRGBProfile = nullptr;
|
||||
}
|
||||
gCMSOutputProfile = nullptr;
|
||||
}
|
||||
if (gCMSsRGBProfile) {
|
||||
|
|
|
@ -535,7 +535,10 @@ class gfxPlatform : public mozilla::layers::MemoryPressureListener {
|
|||
/**
|
||||
* Are we going to try color management?
|
||||
*/
|
||||
static CMSMode GetCMSMode();
|
||||
static CMSMode GetCMSMode() {
|
||||
EnsureCMSInitialized();
|
||||
return gCMSMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used only for testing. Override the pref setting.
|
||||
|
@ -563,32 +566,50 @@ class gfxPlatform : public mozilla::layers::MemoryPressureListener {
|
|||
/**
|
||||
* Return the output device ICC profile.
|
||||
*/
|
||||
static qcms_profile* GetCMSOutputProfile();
|
||||
static qcms_profile* GetCMSOutputProfile() {
|
||||
EnsureCMSInitialized();
|
||||
return gCMSOutputProfile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the sRGB ICC profile.
|
||||
*/
|
||||
static qcms_profile* GetCMSsRGBProfile();
|
||||
static qcms_profile* GetCMSsRGBProfile() {
|
||||
EnsureCMSInitialized();
|
||||
return gCMSsRGBProfile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return sRGB -> output device transform.
|
||||
*/
|
||||
static qcms_transform* GetCMSRGBTransform();
|
||||
static qcms_transform* GetCMSRGBTransform() {
|
||||
EnsureCMSInitialized();
|
||||
return gCMSRGBTransform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return output -> sRGB device transform.
|
||||
*/
|
||||
static qcms_transform* GetCMSInverseRGBTransform();
|
||||
static qcms_transform* GetCMSInverseRGBTransform() {
|
||||
MOZ_ASSERT(gCMSInitialized);
|
||||
return gCMSInverseRGBTransform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return sRGBA -> output device transform.
|
||||
*/
|
||||
static qcms_transform* GetCMSRGBATransform();
|
||||
static qcms_transform* GetCMSRGBATransform() {
|
||||
MOZ_ASSERT(gCMSInitialized);
|
||||
return gCMSRGBATransform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return sBGRA -> output device transform.
|
||||
*/
|
||||
static qcms_transform* GetCMSBGRATransform();
|
||||
static qcms_transform* GetCMSBGRATransform() {
|
||||
MOZ_ASSERT(gCMSInitialized);
|
||||
return gCMSBGRATransform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return OS RGBA -> output device transform.
|
||||
|
@ -957,7 +978,28 @@ class gfxPlatform : public mozilla::layers::MemoryPressureListener {
|
|||
static void Init();
|
||||
|
||||
static void InitOpenGLConfig();
|
||||
static void CreateCMSOutputProfile();
|
||||
|
||||
static mozilla::Atomic<bool, mozilla::MemoryOrdering::ReleaseAcquire>
|
||||
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();
|
||||
|
||||
friend void RecordingPrefChanged(const char* aPrefName, void* aClosure);
|
||||
|
||||
|
|
|
@ -55,7 +55,6 @@ 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
|
||||
|
|
Загрузка…
Ссылка в новой задаче