diff --git a/browser/base/content/test/performance/browser_startup_mainthreadio.js b/browser/base/content/test/performance/browser_startup_mainthreadio.js index 8c5da0a10e489..32f9786101ca5 100644 --- a/browser/base/content/test/performance/browser_startup_mainthreadio.js +++ b/browser/base/content/test/performance/browser_startup_mainthreadio.js @@ -357,6 +357,12 @@ const startupPhases = { ignoreIfUnused: true, // Only on Win7 read: 1, }, + { + // Bug 1626738 + path: "SysD:spool/drivers/color/*", + condition: WIN, + read: 1, + }, { // bug 1541246 path: "UAppData:", diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index a6b8adecaccbd..9fb8e0cddbe0f 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -4968,6 +4968,13 @@ mozilla::ipc::IPCResult ContentParent::RecvGetGraphicsDeviceInitData( return IPC_OK(); } +mozilla::ipc::IPCResult ContentParent::RecvGetOutputColorProfileData( + nsTArray* aOutputColorProfileData) { + (*aOutputColorProfileData) = + gfxPlatform::GetPlatform()->GetPlatformCMSOutputProfileData(); + return IPC_OK(); +} + mozilla::ipc::IPCResult ContentParent::RecvGetFontListShmBlock( const uint32_t& aGeneration, const uint32_t& aIndex, mozilla::ipc::SharedMemoryBasic::Handle* aOut) { diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index b8eb1c9a4e3b8..94304b6bc9a33 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -1143,6 +1143,9 @@ class ContentParent final mozilla::ipc::IPCResult RecvGetGraphicsDeviceInitData( ContentDeviceData* aOut); + mozilla::ipc::IPCResult RecvGetOutputColorProfileData( + nsTArray* aOutputColorProfileData); + mozilla::ipc::IPCResult RecvGetFontListShmBlock( const uint32_t& aGeneration, const uint32_t& aIndex, mozilla::ipc::SharedMemoryBasic::Handle* aOut); diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index 19e5654db5844..ee51ffb2aa717 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -1187,6 +1187,15 @@ parent: sync GetGraphicsDeviceInitData() returns (ContentDeviceData aData); + /** + * Request a buffer containing the contents of the output color profile. + * If set, this is the file pointed to by + * gfx.color_management.display_profile, otherwise it contains a + * platform-specific default + */ + sync GetOutputColorProfileData() + returns (uint8_t[] aOutputColorProfileData); + /** * A shared font list (see gfx/thebes/SharedFontList.*) contains a list * of shared-memory blocks that are used to store all the font list data. diff --git a/gfx/ipc/GraphicsMessages.ipdlh b/gfx/ipc/GraphicsMessages.ipdlh index e244d05220723..da51ad527f517 100644 --- a/gfx/ipc/GraphicsMessages.ipdlh +++ b/gfx/ipc/GraphicsMessages.ipdlh @@ -41,6 +41,7 @@ struct ContentDeviceData { DevicePrefs prefs; D3D11DeviceStatus d3d11; + uint8_t[] cmsOutputProfileData; }; // Represents the state of a feature that has failed to initialize. diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index bb0324408fae4..2d3a68b719d9c 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -2204,31 +2204,35 @@ DeviceColor gfxPlatform::TransformPixel(const sRGBColor& in, } nsTArray gfxPlatform::GetPlatformCMSOutputProfileData() { - return nsTArray(); + return GetPrefCMSOutputProfileData(); } -nsTArray gfxPlatform::GetCMSOutputProfileData() { +nsTArray gfxPlatform::GetPrefCMSOutputProfileData() { nsAutoCString fname; Preferences::GetCString("gfx.color_management.display_profile", fname); if (fname.IsEmpty()) { - return gfxPlatform::GetPlatform()->GetPlatformCMSOutputProfileData(); + return nsTArray(); } void* mem = nullptr; size_t size = 0; qcms_data_from_path(fname.get(), &mem, &size); - if (mem == nullptr) { - return gfxPlatform::GetPlatform()->GetPlatformCMSOutputProfileData(); - } nsTArray result; - result.AppendElements(static_cast(mem), size); - free(mem); + + if (mem) { + result.AppendElements(static_cast(mem), size); + free(mem); + } return result; } +const mozilla::gfx::ContentDeviceData* gfxPlatform::GetInitContentDeviceData() { + return gContentDeviceInitData; +} + void gfxPlatform::CreateCMSOutputProfile() { if (!gCMSOutputProfile) { /* Determine if we're using the internal override to force sRGB as @@ -2243,7 +2247,8 @@ void gfxPlatform::CreateCMSOutputProfile() { } if (!gCMSOutputProfile) { - nsTArray outputProfileData = GetCMSOutputProfileData(); + nsTArray outputProfileData = + gfxPlatform::GetPlatform()->GetPlatformCMSOutputProfileData(); if (!outputProfileData.IsEmpty()) { gCMSOutputProfile = qcms_profile_from_memory( outputProfileData.Elements(), outputProfileData.Length()); @@ -3418,7 +3423,8 @@ void gfxPlatform::GetFrameStats(mozilla::widget::InfoObject& aObj) { } void gfxPlatform::GetCMSSupportInfo(mozilla::widget::InfoObject& aObj) { - nsTArray outputProfileData = GetCMSOutputProfileData(); + nsTArray outputProfileData = + gfxPlatform::GetPlatform()->GetPlatformCMSOutputProfileData(); if (outputProfileData.IsEmpty()) { nsPrintfCString msg("Empty profile data"); aObj.DefineProperty("CMSOutputProfile", msg.get()); diff --git a/gfx/thebes/gfxPlatform.h b/gfx/thebes/gfxPlatform.h index 5620de966c087..73ebe987432eb 100644 --- a/gfx/thebes/gfxPlatform.h +++ b/gfx/thebes/gfxPlatform.h @@ -728,6 +728,12 @@ class gfxPlatform : public mozilla::layers::MemoryPressureListener { const gfxSkipChars& EmptySkipChars() const { return kEmptySkipChars; } + /** + * Returns a buffer containing the CMS output profile data. The way this + * is obtained is platform-specific. + */ + virtual nsTArray GetPlatformCMSOutputProfileData(); + /** * Return information on how child processes should initialize graphics * devices. @@ -806,6 +812,23 @@ class gfxPlatform : public mozilla::layers::MemoryPressureListener { virtual void ImportContentDeviceData( const mozilla::gfx::ContentDeviceData& aData); + /** + * Returns the contents of the file pointed to by the + * gfx.color_management.display_profile pref, if set. + * Returns an empty array if not set, or if an error occurs + */ + nsTArray GetPrefCMSOutputProfileData(); + + /** + * If inside a child process and currently being initialized by the + * SetXPCOMProcessAttributes message, this can be used by subclasses to + * retrieve the ContentDeviceData passed by the message + * + * If not currently being initialized, will return nullptr. In this case, + * child should send a sync message to ask parent for color profile + */ + const mozilla::gfx::ContentDeviceData* GetInitContentDeviceData(); + /** * Increase the global device counter after a device has been removed/reset. */ @@ -881,12 +904,8 @@ class gfxPlatform : public mozilla::layers::MemoryPressureListener { static void InitOpenGLConfig(); static void CreateCMSOutputProfile(); - static nsTArray GetCMSOutputProfileData(); - friend void RecordingPrefChanged(const char* aPrefName, void* aClosure); - virtual nsTArray GetPlatformCMSOutputProfileData(); - /** * Calling this function will compute and set the ideal tile size for the * platform. This will only have an effect in the parent process; child diff --git a/gfx/thebes/gfxPlatformGtk.cpp b/gfx/thebes/gfxPlatformGtk.cpp index f57b0c3df8088..3a533850e99c0 100644 --- a/gfx/thebes/gfxPlatformGtk.cpp +++ b/gfx/thebes/gfxPlatformGtk.cpp @@ -376,6 +376,11 @@ static nsTArray GetDisplayICCProfile(Display* dpy, Window& root) { } nsTArray gfxPlatformGtk::GetPlatformCMSOutputProfileData() { + nsTArray prefProfileData = GetPrefCMSOutputProfileData(); + if (!prefProfileData.IsEmpty()) { + return prefProfileData; + } + if (!mIsX11Display) { return nsTArray(); } diff --git a/gfx/thebes/gfxPlatformMac.cpp b/gfx/thebes/gfxPlatformMac.cpp index 456582e1cf26f..1e69650106f17 100644 --- a/gfx/thebes/gfxPlatformMac.cpp +++ b/gfx/thebes/gfxPlatformMac.cpp @@ -560,6 +560,11 @@ gfxPlatformMac::CreateHardwareVsyncSource() { } nsTArray gfxPlatformMac::GetPlatformCMSOutputProfileData() { + nsTArray prefProfileData = GetPrefCMSOutputProfileData(); + if (!prefProfileData.IsEmpty()) { + return prefProfileData; + } + CGColorSpaceRef cspace = ::CGDisplayCopyColorSpace(::CGMainDisplayID()); if (!cspace) { cspace = ::CGColorSpaceCreateDeviceRGB(); diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp index b7af2718eac69..1d3a947cb5001 100644 --- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -897,36 +897,66 @@ void gfxWindowsPlatform::CheckForContentOnlyDeviceReset() { } nsTArray gfxWindowsPlatform::GetPlatformCMSOutputProfileData() { - HDC dc = ::GetDC(nullptr); - if (!dc) { - return nsTArray(); + if (XRE_IsContentProcess()) { + // This will be passed in during InitChild so we can avoid sending a + // sync message back to the parent during init. + const mozilla::gfx::ContentDeviceData* contentDeviceData = + GetInitContentDeviceData(); + if (contentDeviceData) { + MOZ_ASSERT(!contentDeviceData->cmsOutputProfileData().IsEmpty()); + return contentDeviceData->cmsOutputProfileData(); + } + + // Otherwise we need to ask the parent for the updated color profile + mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton(); + nsTArray result; + Unused << cc->SendGetOutputColorProfileData(&result); + return result; } - WCHAR profilePath[MAX_PATH]; - DWORD profilePathLen = MAX_PATH; + if (!mCachedOutputColorProfile.IsEmpty()) { + return nsTArray(mCachedOutputColorProfile); + } - bool getProfileResult = ::GetICMProfileW(dc, &profilePathLen, profilePath); + mCachedOutputColorProfile = [&] { + nsTArray prefProfileData = GetPrefCMSOutputProfileData(); + if (!prefProfileData.IsEmpty()) { + return prefProfileData; + } - ::ReleaseDC(nullptr, dc); + HDC dc = ::GetDC(nullptr); + if (!dc) { + return nsTArray(); + } - if (!getProfileResult) { - return nsTArray(); - } + WCHAR profilePath[MAX_PATH]; + DWORD profilePathLen = MAX_PATH; - void* mem = nullptr; - size_t size = 0; + bool getProfileResult = ::GetICMProfileW(dc, &profilePathLen, profilePath); - qcms_data_from_unicode_path(profilePath, &mem, &size); - if (!mem) { - return nsTArray(); - } + ::ReleaseDC(nullptr, dc); - nsTArray result; - result.AppendElements(static_cast(mem), size); + if (!getProfileResult) { + return nsTArray(); + } - free(mem); + void* mem = nullptr; + size_t size = 0; - return result; + qcms_data_from_unicode_path(profilePath, &mem, &size); + if (!mem) { + return nsTArray(); + } + + nsTArray result; + result.AppendElements(static_cast(mem), size); + + free(mem); + + return result; + }(); + + return nsTArray(mCachedOutputColorProfile); } void gfxWindowsPlatform::GetDLLVersion(char16ptr_t aDLLPath, @@ -1907,6 +1937,9 @@ void gfxWindowsPlatform::ImportContentDeviceData( DeviceManagerDx* dm = DeviceManagerDx::Get(); dm->ImportDeviceInfo(aData.d3d11()); } + + // aData->cmsOutputProfileData() will be read during color profile init, + // not as part of this import function } void gfxWindowsPlatform::BuildContentDeviceData(ContentDeviceData* aOut) { @@ -1923,6 +1956,9 @@ void gfxWindowsPlatform::BuildContentDeviceData(ContentDeviceData* aOut) { DeviceManagerDx* dm = DeviceManagerDx::Get(); dm->ExportDeviceInfo(&aOut->d3d11()); } + + aOut->cmsOutputProfileData() = + gfxPlatform::GetPlatform()->GetPlatformCMSOutputProfileData(); } bool gfxWindowsPlatform::CheckVariationFontSupport() { diff --git a/gfx/thebes/gfxWindowsPlatform.h b/gfx/thebes/gfxWindowsPlatform.h index 307120461c62c..fe944ac20bdd7 100644 --- a/gfx/thebes/gfxWindowsPlatform.h +++ b/gfx/thebes/gfxWindowsPlatform.h @@ -253,6 +253,9 @@ class gfxWindowsPlatform final : public gfxPlatform { RefPtr mD3D11ReadbackManager; bool mInitializedDevices = false; + + // Cached contents of the output color profile file + nsTArray mCachedOutputColorProfile; }; #endif /* GFX_WINDOWS_PLATFORM_H */ diff --git a/ipc/ipdl/sync-messages.ini b/ipc/ipdl/sync-messages.ini index d04c07268f436..6f0a26153d14c 100644 --- a/ipc/ipdl/sync-messages.ini +++ b/ipc/ipdl/sync-messages.ini @@ -1014,7 +1014,9 @@ description = legacy sync IPC - please add detailed description [PContent::EndDriverCrashGuard] description = legacy sync IPC - please add detailed description [PContent::GetGraphicsDeviceInitData] -description = legacy sync IPC - please add detailed description +description = Retrieve information needed to initialize the graphics device in the content process +[PContent::GetOutputColorProfileData] +description = Retrieve the contents of the output color profile file [PContent::GetFontListShmBlock] description = for bug 1514869 - layout code needs synchronous access to font list, but this is used only once per block, after which content directly reads the shared memory [PContent::InitializeFamily]