1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "mozilla/layers/CompositorManagerChild.h"
7 #include "mozilla/layers/CompositorThread.h"
8 #include "mozilla/layers/ImageBridgeChild.h"
9 #include "mozilla/layers/ISurfaceAllocator.h" // for GfxMemoryImageReporter
10 #include "mozilla/layers/SharedSurfacesParent.h"
11 #include "mozilla/webrender/RenderThread.h"
12 #include "mozilla/webrender/WebRenderAPI.h"
13 #include "mozilla/webrender/webrender_ffi.h"
14 #include "mozilla/layers/PaintThread.h"
15 #include "mozilla/gfx/gfxVars.h"
16 #include "mozilla/gfx/GPUProcessManager.h"
17 #include "mozilla/gfx/GraphicsMessages.h"
18 #include "mozilla/ClearOnShutdown.h"
19 #include "mozilla/Telemetry.h"
20 #include "mozilla/TimeStamp.h"
21 #include "mozilla/Unused.h"
23 #include "mozilla/Logging.h"
24 #include "mozilla/Services.h"
26 #include "gfxCrashReporterUtils.h"
27 #include "gfxPlatform.h"
30 #include "gfxTextRun.h"
31 #include "gfxUserFontSet.h"
32 #include "gfxConfig.h"
33 #include "MediaPrefs.h"
38 #define getpid _getpid
43 #include "nsXULAppAPI.h"
44 #include "nsDirectoryServiceUtils.h"
45 #include "nsDirectoryServiceDefs.h"
48 #include "gfxWindowsPlatform.h"
49 #elif defined(XP_MACOSX)
50 #include "gfxPlatformMac.h"
51 #include "gfxQuartzSurface.h"
52 #elif defined(MOZ_WIDGET_GTK)
53 #include "gfxPlatformGtk.h"
54 #elif defined(ANDROID)
55 #include "gfxAndroidPlatform.h"
59 #include "mozilla/WindowsVersion.h"
60 #include "mozilla/gfx/DeviceManagerDx.h"
63 #include "nsGkAtoms.h"
64 #include "gfxPlatformFontList.h"
65 #include "gfxContext.h"
66 #include "gfxImageSurface.h"
67 #include "nsUnicodeProperties.h"
68 #include "harfbuzz/hb.h"
69 #include "gfxGraphiteShaper.h"
70 #include "gfx2DGlue.h"
71 #include "gfxGradientCache.h"
72 #include "gfxUtils.h" // for NextPowerOfTwo
74 #include "nsExceptionHandler.h"
75 #include "nsUnicodeRange.h"
76 #include "nsServiceManagerUtils.h"
78 #include "nsIObserverService.h"
79 #include "nsIScreenManager.h"
80 #include "FrameMetrics.h"
81 #include "MainThreadUtils.h"
83 #include "nsWeakReference.h"
88 #include "imgITools.h"
92 #include "GLContext.h"
93 #include "GLContextProvider.h"
94 #include "mozilla/gfx/Logging.h"
98 # pragma GCC diagnostic push
99 # pragma GCC diagnostic ignored "-Wshadow"
101 # include "skia/include/core/SkGraphics.h"
103 # include "skia/include/gpu/GrContext.h"
104 # include "skia/include/gpu/gl/GrGLInterface.h"
105 # include "SkiaGLGlue.h"
107 # ifdef MOZ_ENABLE_FREETYPE
108 # include "skia/include/ports/SkTypeface_cairo.h"
111 # pragma GCC diagnostic pop // -Wshadow
113 static const uint32_t kDefaultGlyphCacheSize
= -1;
117 #if !defined(USE_SKIA) || !defined(USE_SKIA_GPU)
118 class mozilla::gl::SkiaGLGlue
: public GenericAtomicRefCounted
{
122 #include "mozilla/Preferences.h"
123 #include "mozilla/Assertions.h"
124 #include "mozilla/Atomics.h"
125 #include "mozilla/Attributes.h"
126 #include "mozilla/Mutex.h"
128 #include "nsAlgorithm.h"
129 #include "nsIGfxInfo.h"
130 #include "nsIXULRuntime.h"
131 #include "VsyncSource.h"
132 #include "SoftwareVsyncSource.h"
133 #include "nscore.h" // for NS_FREE_PERMANENT_DATA
134 #include "mozilla/dom/ContentChild.h"
135 #include "mozilla/dom/TouchEvent.h"
137 #include "VRManagerChild.h"
138 #include "mozilla/gfx/GPUParent.h"
139 #include "mozilla/layers/MemoryReportingMLGPU.h"
140 #include "prsystem.h"
144 void ShutdownTileCache();
145 } // namespace layers
146 } // namespace mozilla
148 using namespace mozilla
;
149 using namespace mozilla::layers
;
150 using namespace mozilla::gl
;
151 using namespace mozilla::gfx
;
153 gfxPlatform
*gPlatform
= nullptr;
154 static bool gEverInitialized
= false;
156 const ContentDeviceData
* gContentDeviceInitData
= nullptr;
158 static Mutex
* gGfxPlatformPrefsLock
= nullptr;
160 // These two may point to the same profile
161 static qcms_profile
*gCMSOutputProfile
= nullptr;
162 static qcms_profile
*gCMSsRGBProfile
= nullptr;
164 static qcms_transform
*gCMSRGBTransform
= nullptr;
165 static qcms_transform
*gCMSInverseRGBTransform
= nullptr;
166 static qcms_transform
*gCMSRGBATransform
= nullptr;
168 static bool gCMSInitialized
= false;
169 static eCMSMode gCMSMode
= eCMSMode_Off
;
171 static void ShutdownCMS();
173 #include "mozilla/gfx/2D.h"
174 #include "mozilla/gfx/SourceSurfaceCairo.h"
175 using namespace mozilla::gfx
;
177 /* Class to listen for pref changes so that chrome code can dynamically
178 force sRGB as an output profile. See Bug #452125. */
179 class SRGBOverrideObserver final
: public nsIObserver
,
180 public nsSupportsWeakReference
182 ~SRGBOverrideObserver() = default;
188 /// This override of the LogForwarder, initially used for the critical graphics
189 /// errors, is sending the log to the crash annotations as well, but only
190 /// if the capacity set with the method below is >= 2. We always retain the
191 /// very first critical message, and the latest capacity-1 messages are
192 /// rotated through. Note that we don't expect the total number of times
193 /// this gets called to be large - it is meant for critical errors only.
195 class CrashStatsLogForwarder
: public mozilla::gfx::LogForwarder
198 explicit CrashStatsLogForwarder(const char* aKey
);
199 void Log(const std::string
& aString
) override
;
200 void CrashAction(LogReason aReason
) override
;
201 bool UpdateStringsVector(const std::string
& aString
) override
;
203 LoggingRecord
LoggingRecordCopy() override
;
205 void SetCircularBufferSize(uint32_t aCapacity
);
208 // Helper for the Log()
209 void UpdateCrashReport();
212 LoggingRecord mBuffer
;
213 nsCString mCrashCriticalKey
;
214 uint32_t mMaxCapacity
;
219 CrashStatsLogForwarder::CrashStatsLogForwarder(const char* aKey
)
221 , mCrashCriticalKey(aKey
)
224 , mMutex("CrashStatsLogForwarder")
228 void CrashStatsLogForwarder::SetCircularBufferSize(uint32_t aCapacity
)
230 MutexAutoLock
lock(mMutex
);
232 mMaxCapacity
= aCapacity
;
233 mBuffer
.reserve(static_cast<size_t>(aCapacity
));
237 CrashStatsLogForwarder::LoggingRecordCopy()
239 MutexAutoLock
lock(mMutex
);
244 CrashStatsLogForwarder::UpdateStringsVector(const std::string
& aString
)
246 // We want at least the first one and the last one. Otherwise, no point.
247 if (mMaxCapacity
< 2) {
252 MOZ_ASSERT(mIndex
>= 0);
254 // index will count 0, 1, 2, ..., max-1, 1, 2, ..., max-1, 1, 2, ...
255 int32_t index
= mIndex
? (mIndex
-1) % (mMaxCapacity
-1) + 1 : 0;
256 MOZ_ASSERT(index
>= 0 && index
< (int32_t)mMaxCapacity
);
257 MOZ_ASSERT(index
<= mIndex
&& index
<= (int32_t)mBuffer
.size());
259 double tStamp
= (TimeStamp::NowLoRes() - TimeStamp::ProcessCreation()).ToSecondsSigDigits();
261 // Checking for index >= mBuffer.size(), rather than index == mBuffer.size()
262 // just out of paranoia, but we know index <= mBuffer.size().
263 LoggingRecordEntry
newEntry(mIndex
,aString
,tStamp
);
264 if (index
>= static_cast<int32_t>(mBuffer
.size())) {
265 mBuffer
.push_back(newEntry
);
267 mBuffer
[index
] = newEntry
;
272 void CrashStatsLogForwarder::UpdateCrashReport()
274 std::stringstream message
;
275 std::string logAnnotation
;
277 switch (XRE_GetProcessType()) {
278 case GeckoProcessType_Default
:
279 logAnnotation
= "|[";
281 case GeckoProcessType_Content
:
282 logAnnotation
= "|[C";
284 case GeckoProcessType_GPU
:
285 logAnnotation
= "|[G";
288 logAnnotation
= "|[X";
292 for (auto& it
: mBuffer
) {
293 message
<< logAnnotation
<< Get
<0>(it
) << "]" << Get
<1>(it
) << " (t=" << Get
<2>(it
) << ") ";
296 nsCString
reportString(message
.str().c_str());
297 nsresult annotated
= CrashReporter::AnnotateCrashReport(mCrashCriticalKey
, reportString
);
299 if (annotated
!= NS_OK
) {
300 printf("Crash Annotation %s: %s",
301 mCrashCriticalKey
.get(), message
.str().c_str());
305 class LogForwarderEvent
: public Runnable
307 ~LogForwarderEvent() override
= default;
310 NS_INLINE_DECL_REFCOUNTING_INHERITED(LogForwarderEvent
, Runnable
)
312 explicit LogForwarderEvent(const nsCString
& aMessage
)
313 : mozilla::Runnable("LogForwarderEvent")
318 NS_IMETHOD
Run() override
{
319 MOZ_ASSERT(NS_IsMainThread() && (XRE_IsContentProcess() || XRE_IsGPUProcess()));
321 if (XRE_IsContentProcess()) {
322 dom::ContentChild
* cc
= dom::ContentChild::GetSingleton();
323 Unused
<< cc
->SendGraphicsError(mMessage
);
324 } else if (XRE_IsGPUProcess()) {
325 GPUParent
* gp
= GPUParent::GetSingleton();
326 Unused
<< gp
->SendGraphicsError(mMessage
);
336 void CrashStatsLogForwarder::Log(const std::string
& aString
)
338 MutexAutoLock
lock(mMutex
);
340 if (UpdateStringsVector(aString
)) {
344 // Add it to the parent strings
345 if (!XRE_IsParentProcess()) {
346 nsCString
stringToSend(aString
.c_str());
347 if (NS_IsMainThread()) {
348 if (XRE_IsContentProcess()) {
349 dom::ContentChild
* cc
= dom::ContentChild::GetSingleton();
350 Unused
<< cc
->SendGraphicsError(stringToSend
);
351 } else if (XRE_IsGPUProcess()) {
352 GPUParent
* gp
= GPUParent::GetSingleton();
353 Unused
<< gp
->SendGraphicsError(stringToSend
);
356 nsCOMPtr
<nsIRunnable
> r1
= new LogForwarderEvent(stringToSend
);
357 NS_DispatchToMainThread(r1
);
362 class CrashTelemetryEvent
: public Runnable
364 ~CrashTelemetryEvent() override
= default;
367 NS_INLINE_DECL_REFCOUNTING_INHERITED(CrashTelemetryEvent
, Runnable
)
369 explicit CrashTelemetryEvent(uint32_t aReason
)
370 : mozilla::Runnable("CrashTelemetryEvent")
375 NS_IMETHOD
Run() override
{
376 MOZ_ASSERT(NS_IsMainThread());
377 Telemetry::Accumulate(Telemetry::GFX_CRASH
, mReason
);
386 CrashStatsLogForwarder::CrashAction(LogReason aReason
)
388 #ifndef RELEASE_OR_BETA
389 // Non-release builds crash by default, but will use telemetry
390 // if this environment variable is present.
391 static bool useTelemetry
= gfxEnv::GfxDevCrashTelemetry();
393 // Release builds use telemetry by default, but will crash instead
394 // if this environment variable is present.
395 static bool useTelemetry
= !gfxEnv::GfxDevCrashMozCrash();
399 // The callers need to assure that aReason is in the range
400 // that the telemetry call below supports.
401 if (NS_IsMainThread()) {
402 Telemetry::Accumulate(Telemetry::GFX_CRASH
, (uint32_t)aReason
);
404 nsCOMPtr
<nsIRunnable
> r1
= new CrashTelemetryEvent((uint32_t)aReason
);
405 NS_DispatchToMainThread(r1
);
408 // ignoring aReason, we can get the information we need from the stack
409 MOZ_CRASH("GFX_CRASH");
413 NS_IMPL_ISUPPORTS(SRGBOverrideObserver
, nsIObserver
, nsISupportsWeakReference
)
415 #define GFX_DOWNLOADABLE_FONTS_ENABLED "gfx.downloadable_fonts.enabled"
417 #define GFX_PREF_FALLBACK_USE_CMAPS "gfx.font_rendering.fallback.always_use_cmaps"
419 #define GFX_PREF_OPENTYPE_SVG "gfx.font_rendering.opentype_svg.enabled"
421 #define GFX_PREF_WORD_CACHE_CHARLIMIT "gfx.font_rendering.wordcache.charlimit"
422 #define GFX_PREF_WORD_CACHE_MAXENTRIES "gfx.font_rendering.wordcache.maxentries"
424 #define GFX_PREF_GRAPHITE_SHAPING "gfx.font_rendering.graphite.enabled"
426 #define BIDI_NUMERAL_PREF "bidi.numeral"
428 #define GFX_PREF_CMS_FORCE_SRGB "gfx.color_management.force_srgb"
431 SRGBOverrideObserver::Observe(nsISupports
*aSubject
,
433 const char16_t
* someData
)
435 NS_ASSERTION(NS_strcmp(someData
,
436 (u
"" GFX_PREF_CMS_FORCE_SRGB
)) == 0,
437 "Restarting CMS on wrong pref!");
439 // Update current cms profile.
440 gfxPlatform::CreateCMSOutputProfile();
444 static const char* kObservedPrefs
[] = {
445 "gfx.downloadable_fonts.",
446 "gfx.font_rendering.",
451 class FontPrefsObserver final
: public nsIObserver
453 ~FontPrefsObserver() = default;
459 NS_IMPL_ISUPPORTS(FontPrefsObserver
, nsIObserver
)
462 FontPrefsObserver::Observe(nsISupports
*aSubject
,
464 const char16_t
*someData
)
467 NS_ERROR("font pref observer code broken");
468 return NS_ERROR_UNEXPECTED
;
470 NS_ASSERTION(gfxPlatform::GetPlatform(), "the singleton instance has gone");
471 gfxPlatform::GetPlatform()->FontsPrefsChanged(NS_ConvertUTF16toUTF8(someData
).get());
476 class MemoryPressureObserver final
: public nsIObserver
478 ~MemoryPressureObserver() = default;
484 NS_IMPL_ISUPPORTS(MemoryPressureObserver
, nsIObserver
)
487 MemoryPressureObserver::Observe(nsISupports
*aSubject
,
489 const char16_t
*someData
)
491 NS_ASSERTION(strcmp(aTopic
, "memory-pressure") == 0, "unexpected event topic");
492 Factory::PurgeAllCaches();
493 gfxGradientCache::PurgeAllCaches();
495 gfxPlatform::PurgeSkiaFontCache();
496 gfxPlatform::GetPlatform()->PurgeSkiaGPUCache();
500 gfxPlatform::gfxPlatform()
501 : mAzureCanvasBackendCollector(this, &gfxPlatform::GetAzureBackendInfo
)
502 , mApzSupportCollector(this, &gfxPlatform::GetApzSupportInfo
)
503 , mTilesInfoCollector(this, &gfxPlatform::GetTilesSupportInfo
)
504 , mCompositorBackend(layers::LayersBackend::LAYERS_NONE
)
507 mAllowDownloadableFonts
= UNINITIALIZED_VALUE
;
508 mFallbackUsesCmaps
= UNINITIALIZED_VALUE
;
510 mWordCacheCharLimit
= UNINITIALIZED_VALUE
;
511 mWordCacheMaxEntries
= UNINITIALIZED_VALUE
;
512 mGraphiteShapingEnabled
= UNINITIALIZED_VALUE
;
513 mOpenTypeSVGEnabled
= UNINITIALIZED_VALUE
;
514 mBidiNumeralOption
= UNINITIALIZED_VALUE
;
518 InitBackendPrefs(GetBackendPrefs());
520 mTotalSystemMemory
= PR_GetPhysicalMemorySize();
522 VRManager::ManagerInit();
526 gfxPlatform::GetPlatform()
529 MOZ_RELEASE_ASSERT(!XRE_IsContentProcess(),
530 "Content Process should have called InitChild() before first GetPlatform()");
537 gfxPlatform::Initialized()
543 gfxPlatform::InitChild(const ContentDeviceData
& aData
)
545 MOZ_ASSERT(XRE_IsContentProcess());
546 MOZ_RELEASE_ASSERT(!gPlatform
,
547 "InitChild() should be called before first GetPlatform()");
548 // Make the provided initial ContentDeviceData available to the init
549 // routines, so they don't have to do a sync request from the parent.
550 gContentDeviceInitData
= &aData
;
552 gContentDeviceInitData
= nullptr;
555 void RecordingPrefChanged(const char *aPrefName
, void *aClosure
)
557 if (Preferences::GetBool("gfx.2d.recording", false)) {
558 nsAutoCString fileName
;
559 nsAutoString prefFileName
;
560 nsresult rv
= Preferences::GetString("gfx.2d.recordingfile", prefFileName
);
561 if (NS_SUCCEEDED(rv
)) {
562 CopyUTF16toUTF8(prefFileName
, fileName
);
564 nsCOMPtr
<nsIFile
> tmpFile
;
565 if (NS_FAILED(NS_GetSpecialDirectory(NS_OS_TEMP_DIR
, getter_AddRefs(tmpFile
)))) {
568 fileName
.AppendPrintf("moz2drec_%i_%i.aer", XRE_GetProcessType(), getpid());
570 nsresult rv
= tmpFile
->AppendNative(fileName
);
575 rv
= tmpFile
->GetPath(prefFileName
);
576 CopyUTF16toUTF8(prefFileName
, fileName
);
578 rv
= tmpFile
->GetNativePath(fileName
);
585 gPlatform
->mRecorder
= Factory::CreateEventRecorderForFile(prefFileName
.BeginReading());
587 gPlatform
->mRecorder
= Factory::CreateEventRecorderForFile(fileName
.BeginReading());
589 printf_stderr("Recording to %s\n", fileName
.get());
590 Factory::SetGlobalEventRecorder(gPlatform
->mRecorder
);
592 Factory::SetGlobalEventRecorder(nullptr);
596 #define WR_DEBUG_PREF "gfx.webrender.debug"
599 WebRenderDebugPrefChangeCallback(const char* aPrefName
, void*)
602 #define GFX_WEBRENDER_DEBUG(suffix, bit) \
603 if (Preferences::GetBool(WR_DEBUG_PREF suffix, false)) { \
607 // TODO: It would be nice to get the bit patterns directly from the rust code.
608 GFX_WEBRENDER_DEBUG(".profiler", 1 << 0)
609 GFX_WEBRENDER_DEBUG(".render-targets", 1 << 1)
610 GFX_WEBRENDER_DEBUG(".texture-cache", 1 << 2)
611 GFX_WEBRENDER_DEBUG(".gpu-time-queries", 1 << 3)
612 GFX_WEBRENDER_DEBUG(".gpu-sample-queries", 1 << 4)
613 GFX_WEBRENDER_DEBUG(".disable-batching", 1 << 5)
614 GFX_WEBRENDER_DEBUG(".epochs", 1 << 6)
615 GFX_WEBRENDER_DEBUG(".compact-profiler", 1 << 7)
616 #undef GFX_WEBRENDER_DEBUG
618 gfx::gfxVars::SetWebRenderDebugFlags(flags
);
622 #if defined(USE_SKIA)
623 static uint32_t GetSkiaGlyphCacheSize()
625 // Only increase font cache size on non-android to save memory.
626 #if !defined(MOZ_WIDGET_ANDROID)
627 // 10mb as the default pref cache size on desktop due to talos perf tweaking.
628 // Chromium uses 20mb and skia default uses 2mb.
629 // We don't need to change the font cache count since we usually
630 // cache thrash due to asian character sets in talos.
631 // Only increase memory on the content proces
632 uint32_t cacheSize
= gfxPrefs::SkiaContentFontCacheSize() * 1024 * 1024;
633 if (mozilla::BrowserTabsRemoteAutostart()) {
634 return XRE_IsContentProcess() ? cacheSize
: kDefaultGlyphCacheSize
;
639 return kDefaultGlyphCacheSize
;
640 #endif // MOZ_WIDGET_ANDROID
647 MOZ_RELEASE_ASSERT(!XRE_IsGPUProcess(), "GFX: Not allowed in GPU process.");
648 MOZ_RELEASE_ASSERT(NS_IsMainThread(), "GFX: Not in main thread.");
650 if (gEverInitialized
) {
651 MOZ_CRASH("Already started???");
653 gEverInitialized
= true;
655 // Initialize the preferences by creating the singleton.
656 gfxPrefs::GetSingleton();
657 MediaPrefs::GetSingleton();
658 gfxVars::Initialize();
662 if (XRE_IsParentProcess()) {
663 GPUProcessManager::Initialize();
665 if (Preferences::GetBool("media.wmf.skip-blacklist")) {
666 gfxVars::SetPDMWMFDisableD3D11Dlls(nsCString());
667 gfxVars::SetPDMWMFDisableD3D9Dlls(nsCString());
670 Preferences::GetCString("media.wmf.disable-d3d11-for-dlls", d3d11
);
671 gfxVars::SetPDMWMFDisableD3D11Dlls(d3d11
);
673 Preferences::GetCString("media.wmf.disable-d3d9-for-dlls", d3d9
);
674 gfxVars::SetPDMWMFDisableD3D9Dlls(d3d9
);
677 nsCOMPtr
<nsIFile
> file
;
678 nsresult rv
= NS_GetSpecialDirectory(NS_GRE_DIR
, getter_AddRefs(file
));
680 gfxVars::SetGREDirectory(nsString());
684 gfxVars::SetGREDirectory(nsString(path
));
688 // Drop a note in the crash report if we end up forcing an option that could
689 // destabilize things. New items should be appended at the end (of an existing
690 // or in a new section), so that we don't have to know the version to interpret
691 // these cryptic strings.
693 nsAutoCString forcedPrefs
;
695 forcedPrefs
.AppendPrintf("FP(D%d%d",
696 gfxPrefs::Direct2DDisabled(),
697 gfxPrefs::Direct2DForceEnabled());
699 forcedPrefs
.AppendPrintf("-L%d%d%d%d",
700 gfxPrefs::LayersAMDSwitchableGfxEnabled(),
701 gfxPrefs::LayersAccelerationDisabledDoNotUseDirectly(),
702 gfxPrefs::LayersAccelerationForceEnabledDoNotUseDirectly(),
703 gfxPrefs::LayersD3D11ForceWARP());
705 forcedPrefs
.AppendPrintf("-W%d%d%d%d%d%d%d%d",
706 gfxPrefs::WebGLANGLEForceD3D11(),
707 gfxPrefs::WebGLANGLEForceWARP(),
708 gfxPrefs::WebGLDisabled(),
709 gfxPrefs::WebGLDisableANGLE(),
710 gfxPrefs::WebGLDXGLEnabled(),
711 gfxPrefs::WebGLForceEnabled(),
712 gfxPrefs::WebGLForceLayersReadback(),
713 gfxPrefs::WebGLForceMSAA());
714 // Prefs that don't fit into any of the other sections
715 forcedPrefs
.AppendPrintf("-T%d%d%d) ",
716 gfxPrefs::AndroidRGB16Force(),
717 gfxPrefs::CanvasAzureAccelerated(),
718 gfxPrefs::ForceShmemTiles());
719 ScopedGfxFeatureReporter::AppNote(forcedPrefs
);
724 gGfxPlatformPrefsLock
= new Mutex("gfxPlatform::gGfxPlatformPrefsLock");
726 /* Initialize the GfxInfo service.
727 * Note: we can't call functions on GfxInfo that depend
728 * on gPlatform until after it has been initialized
729 * below. GfxInfo initialization annotates our
730 * crash reports so we want to do it before
731 * we try to load any drivers and do device detection
732 * incase that code crashes. See bug #591561. */
733 nsCOMPtr
<nsIGfxInfo
> gfxInfo
;
734 /* this currently will only succeed on Windows */
735 gfxInfo
= services::GetGfxInfo();
738 gPlatform
= new gfxWindowsPlatform
;
739 #elif defined(XP_MACOSX)
740 gPlatform
= new gfxPlatformMac
;
741 #elif defined(MOZ_WIDGET_GTK)
742 gPlatform
= new gfxPlatformGtk
;
743 #elif defined(ANDROID)
744 gPlatform
= new gfxAndroidPlatform
;
746 #error "No gfxPlatform implementation available"
748 gPlatform
->InitAcceleration();
749 gPlatform
->InitWebRenderConfig();
750 gPlatform
->InitOMTPConfig();
752 if (gfxConfig::IsEnabled(Feature::GPU_PROCESS
)) {
753 GPUProcessManager
* gpu
= GPUProcessManager::Get();
754 gpu
->LaunchGPUProcess();
757 if (XRE_IsParentProcess()) {
758 if (gfxPlatform::ForceSoftwareVsync()) {
759 gPlatform
->mVsyncSource
= (gPlatform
)->gfxPlatform::CreateHardwareVsyncSource();
761 gPlatform
->mVsyncSource
= gPlatform
->CreateHardwareVsyncSource();
767 # ifdef MOZ_ENABLE_FREETYPE
768 SkInitCairoFT(gPlatform
->FontHintingEnabled());
774 gPlatform
->PopulateScreenInfo();
775 gPlatform
->ComputeTileSize();
778 rv
= gfxPlatformFontList::Init();
780 MOZ_CRASH("Could not initialize gfxPlatformFontList");
783 gPlatform
->mScreenReferenceSurface
=
784 gPlatform
->CreateOffscreenSurface(IntSize(1, 1),
785 SurfaceFormat::A8R8G8B8_UINT32
);
786 if (!gPlatform
->mScreenReferenceSurface
) {
787 MOZ_CRASH("Could not initialize mScreenReferenceSurface");
790 gPlatform
->mScreenReferenceDrawTarget
=
791 gPlatform
->CreateOffscreenContentDrawTarget(IntSize(1, 1),
792 SurfaceFormat::B8G8R8A8
);
793 if (!gPlatform
->mScreenReferenceDrawTarget
||
794 !gPlatform
->mScreenReferenceDrawTarget
->IsValid()) {
795 // If TDR is detected, create a draw target with software backend
796 // and it should be replaced later when the process gets the device
797 // reset notification.
798 if (!gPlatform
->DidRenderingDeviceReset()) {
799 gfxCriticalError() << "Could not initialize mScreenReferenceDrawTarget";
803 rv
= gfxFontCache::Init();
805 MOZ_CRASH("Could not initialize gfxFontCache");
808 #ifdef MOZ_ENABLE_FREETYPE
809 Factory::SetFTLibrary(gPlatform
->GetFTLibrary());
812 /* Create and register our CMS Override observer. */
813 gPlatform
->mSRGBOverrideObserver
= new SRGBOverrideObserver();
814 Preferences::AddWeakObserver(gPlatform
->mSRGBOverrideObserver
, GFX_PREF_CMS_FORCE_SRGB
);
816 gPlatform
->mFontPrefsObserver
= new FontPrefsObserver();
817 Preferences::AddStrongObservers(gPlatform
->mFontPrefsObserver
, kObservedPrefs
);
819 GLContext::PlatformStartup();
821 Preferences::RegisterCallbackAndCall(RecordingPrefChanged
, "gfx.2d.recording");
823 CreateCMSOutputProfile();
825 // Listen to memory pressure event so we can purge DrawTarget caches
826 nsCOMPtr
<nsIObserverService
> obs
= mozilla::services::GetObserverService();
828 gPlatform
->mMemoryPressureObserver
= new MemoryPressureObserver();
829 obs
->AddObserver(gPlatform
->mMemoryPressureObserver
, "memory-pressure", false);
832 // Request the imgITools service, implicitly initializing ImageLib.
833 nsCOMPtr
<imgITools
> imgTools
= do_GetService("@mozilla.org/image/tools;1");
835 MOZ_CRASH("Could not initialize ImageLib");
838 RegisterStrongMemoryReporter(new GfxMemoryImageReporter());
839 mlg::InitializeMemoryReporters();
842 uint32_t skiaCacheSize
= GetSkiaGlyphCacheSize();
843 if (skiaCacheSize
!= kDefaultGlyphCacheSize
) {
844 SkGraphics::SetFontCacheLimit(skiaCacheSize
);
851 if (XRE_IsParentProcess()) {
852 gfxVars::SetDXInterop2Blocked(IsDXInterop2Blocked());
856 obs
->NotifyObservers(nullptr, "gfx-features-ready", nullptr);
861 gfxPlatform::IsDXInterop2Blocked()
863 nsCOMPtr
<nsIGfxInfo
> gfxInfo
= services::GetGfxInfo();
866 if (!NS_SUCCEEDED(gfxInfo
->GetFeatureStatus(nsIGfxInfo::FEATURE_DX_INTEROP2
,
867 blockId
, &status
))) {
870 return status
!= nsIGfxInfo::FEATURE_STATUS_OK
;
874 gfxPlatform::MaxTextureSize()
876 // Make sure we don't completely break rendering because of a typo in the
878 const int32_t kMinSizePref
= 2048;
879 return std::max(kMinSizePref
, gfxPrefs::MaxTextureSizeDoNotUseDirectly());
883 gfxPlatform::MaxAllocSize()
885 // Make sure we don't completely break rendering because of a typo in the
887 const int32_t kMinAllocPref
= 10000000;
888 return std::max(kMinAllocPref
, gfxPrefs::MaxAllocSizeDoNotUseDirectly());
892 gfxPlatform::InitMoz2DLogging()
894 auto fwd
= new CrashStatsLogForwarder("GraphicsCriticalError");
895 fwd
->SetCircularBufferSize(gfxPrefs::GfxLoggingCrashLength());
897 mozilla::gfx::Config cfg
;
898 cfg
.mLogForwarder
= fwd
;
899 cfg
.mMaxTextureSize
= gfxPlatform::MaxTextureSize();
900 cfg
.mMaxAllocSize
= gfxPlatform::MaxAllocSize();
902 gfx::Factory::Init(cfg
);
906 gfxPlatform::IsHeadless()
908 static bool initialized
= false;
909 static bool headless
= false;
912 headless
= PR_GetEnv("MOZ_HEADLESS");
917 static bool sLayersIPCIsUp
= false;
920 gfxPlatform::InitNullMetadata()
922 ScrollMetadata::sNullMetadata
= new ScrollMetadata();
923 ClearOnShutdown(&ScrollMetadata::sNullMetadata
);
927 gfxPlatform::Shutdown()
929 // In some cases, gPlatform may not be created but Shutdown() called,
930 // e.g., during xpcshell tests.
935 MOZ_ASSERT(!sLayersIPCIsUp
);
937 // These may be called before the corresponding subsystems have actually
938 // started up. That's OK, they can handle it.
939 gfxFontCache::Shutdown();
940 gfxGradientCache::Shutdown();
941 gfxAlphaBoxBlur::ShutdownBlurCache();
942 gfxGraphiteShaper::Shutdown();
943 gfxPlatformFontList::Shutdown();
946 // Free the various non-null transforms and loaded profiles
949 /* Unregister our CMS Override callback. */
950 NS_ASSERTION(gPlatform
->mSRGBOverrideObserver
, "mSRGBOverrideObserver has alreay gone");
951 Preferences::RemoveObserver(gPlatform
->mSRGBOverrideObserver
, GFX_PREF_CMS_FORCE_SRGB
);
952 gPlatform
->mSRGBOverrideObserver
= nullptr;
954 NS_ASSERTION(gPlatform
->mFontPrefsObserver
, "mFontPrefsObserver has alreay gone");
955 Preferences::RemoveObservers(gPlatform
->mFontPrefsObserver
, kObservedPrefs
);
956 gPlatform
->mFontPrefsObserver
= nullptr;
958 NS_ASSERTION(gPlatform
->mMemoryPressureObserver
, "mMemoryPressureObserver has already gone");
959 nsCOMPtr
<nsIObserverService
> obs
= mozilla::services::GetObserverService();
961 obs
->RemoveObserver(gPlatform
->mMemoryPressureObserver
, "memory-pressure");
964 gPlatform
->mMemoryPressureObserver
= nullptr;
965 gPlatform
->mSkiaGlue
= nullptr;
967 if (XRE_IsParentProcess()) {
968 gPlatform
->mVsyncSource
->Shutdown();
971 gPlatform
->mVsyncSource
= nullptr;
973 // Shut down the default GL context provider.
974 GLContextProvider::Shutdown();
977 // The above shutdown calls operate on the available context providers on
978 // most platforms. Windows is a "special snowflake", though, and has three
979 // context providers available, so we have to shut all of them down.
980 // We should only support the default GL provider on Windows; then, this
981 // could go away. Unfortunately, we currently support WGL (the default) for
983 GLContextProviderEGL::Shutdown();
986 if (XRE_IsParentProcess()) {
987 GPUProcessManager::Shutdown();
990 gfx::Factory::ShutDown();
992 delete gGfxPlatformPrefsLock
;
995 gfxPrefs::DestroySingleton();
996 gfxFont::DestroySingletons();
998 gfxConfig::Shutdown();
1000 gPlatform
->WillShutdown();
1003 gPlatform
= nullptr;
1007 gfxPlatform::InitLayersIPC()
1009 if (sLayersIPCIsUp
) {
1012 sLayersIPCIsUp
= true;
1014 if (gfxVars::UseWebRender()) {
1015 wr::WebRenderAPI::InitExternalLogHandler();
1018 if (XRE_IsContentProcess()) {
1019 if (gfxVars::UseOMTP()) {
1020 layers::PaintThread::Start();
1022 } else if (XRE_IsParentProcess()) {
1023 if (gfxVars::UseWebRender()) {
1024 wr::RenderThread::Start();
1025 layers::SharedSurfacesParent::Initialize();
1028 layers::CompositorThreadHolder::Start();
1029 gfx::VRListenerThreadHolder::Start();
1034 gfxPlatform::ShutdownLayersIPC()
1036 if (!sLayersIPCIsUp
) {
1039 sLayersIPCIsUp
= false;
1041 if (XRE_IsContentProcess()) {
1042 gfx::VRManagerChild::ShutDown();
1044 if (gfxPrefs::ChildProcessShutdown()) {
1045 layers::CompositorManagerChild::Shutdown();
1046 layers::ImageBridgeChild::ShutDown();
1049 if (gfxVars::UseOMTP()) {
1050 layers::PaintThread::Shutdown();
1052 } else if (XRE_IsParentProcess()) {
1053 gfx::VRManagerChild::ShutDown();
1054 layers::CompositorManagerChild::Shutdown();
1055 layers::ImageBridgeChild::ShutDown();
1056 // This has to happen after shutting down the child protocols.
1057 layers::CompositorThreadHolder::Shutdown();
1058 gfx::VRListenerThreadHolder::Shutdown();
1059 // There is a case that RenderThread exists when gfxVars::UseWebRender() is false.
1060 // This could happen when WebRender was fallbacked to compositor.
1061 if (wr::RenderThread::Get()) {
1062 layers::SharedSurfacesParent::Shutdown();
1063 wr::RenderThread::ShutDown();
1065 Preferences::UnregisterCallback(WebRenderDebugPrefChangeCallback
, WR_DEBUG_PREF
);
1069 // TODO: There are other kind of processes and we should make sure gfx
1070 // stuff is either not created there or shut down properly.
1073 if (gfxVars::UseWebRender()) {
1074 wr::WebRenderAPI::ShutdownExternalLogHandler();
1079 gfxPlatform::WillShutdown()
1081 // Destoy these first in case they depend on backend-specific resources.
1082 // Otherwise, the backend's destructor would be called before the
1083 // base gfxPlatform destructor.
1084 mScreenReferenceSurface
= nullptr;
1085 mScreenReferenceDrawTarget
= nullptr;
1088 gfxPlatform::~gfxPlatform()
1090 // The cairo folks think we should only clean up in debug builds,
1091 // but we're generally in the habit of trying to shut down as
1092 // cleanly as possible even in production code, so call this
1093 // cairo_debug_* function unconditionally.
1095 // because cairo can assert and thus crash on shutdown, don't do this in release builds
1096 #ifdef NS_FREE_PERMANENT_DATA
1098 // must do Skia cleanup before Cairo cleanup, because Skia may be referencing
1099 // Cairo objects e.g. through SkCairoFTTypeface
1100 SkGraphics::PurgeFontCache();
1104 cairo_debug_reset_static_data();
1109 /* static */ already_AddRefed
<DrawTarget
>
1110 gfxPlatform::CreateDrawTargetForSurface(gfxASurface
*aSurface
, const IntSize
& aSize
)
1112 SurfaceFormat format
= aSurface
->GetSurfaceFormat();
1113 RefPtr
<DrawTarget
> drawTarget
= Factory::CreateDrawTargetForCairoSurface(aSurface
->CairoSurface(), aSize
, &format
);
1115 gfxWarning() << "gfxPlatform::CreateDrawTargetForSurface failed in CreateDrawTargetForCairoSurface";
1118 return drawTarget
.forget();
1121 cairo_user_data_key_t kSourceSurface
;
1124 * Record the backend that was used to construct the SourceSurface.
1125 * When getting the cached SourceSurface for a gfxASurface/DrawTarget pair,
1126 * we check to make sure the DrawTarget's backend matches the backend
1127 * for the cached SourceSurface, and only use it if they match. This
1128 * can avoid expensive and unnecessary readbacks.
1130 struct SourceSurfaceUserData
1132 RefPtr
<SourceSurface
> mSrcSurface
;
1133 BackendType mBackendType
;
1136 void SourceBufferDestroy(void *srcSurfUD
)
1138 delete static_cast<SourceSurfaceUserData
*>(srcSurfUD
);
1141 UserDataKey kThebesSurface
;
1143 struct DependentSourceSurfaceUserData
1145 RefPtr
<gfxASurface
> mSurface
;
1148 void SourceSurfaceDestroyed(void *aData
)
1150 delete static_cast<DependentSourceSurfaceUserData
*>(aData
);
1154 gfxPlatform::ClearSourceSurfaceForSurface(gfxASurface
*aSurface
)
1156 aSurface
->SetData(&kSourceSurface
, nullptr, nullptr);
1159 /* static */ already_AddRefed
<SourceSurface
>
1160 gfxPlatform::GetSourceSurfaceForSurface(RefPtr
<DrawTarget
> aTarget
,
1161 gfxASurface
* aSurface
,
1164 if (!aSurface
->CairoSurface() || aSurface
->CairoStatus()) {
1169 aTarget
= gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
1172 void *userData
= aSurface
->GetData(&kSourceSurface
);
1175 SourceSurfaceUserData
*surf
= static_cast<SourceSurfaceUserData
*>(userData
);
1177 if (surf
->mSrcSurface
->IsValid() && surf
->mBackendType
== aTarget
->GetBackendType()) {
1178 RefPtr
<SourceSurface
> srcSurface(surf
->mSrcSurface
);
1179 return srcSurface
.forget();
1181 // We can just continue here as when setting new user data the destroy
1182 // function will be called for the old user data.
1185 SurfaceFormat format
= aSurface
->GetSurfaceFormat();
1187 if (aTarget
->GetBackendType() == BackendType::CAIRO
) {
1188 // If we're going to be used with a CAIRO DrawTarget, then just create a
1189 // SourceSurfaceCairo since we don't know the underlying type of the CAIRO
1190 // DrawTarget and can't pick a better surface type. Doing this also avoids
1191 // readback of aSurface's surface into memory if, for example, aSurface
1192 // wraps an xlib cairo surface (which can be important to avoid a major
1195 // We return here regardless of whether CreateSourceSurfaceFromNativeSurface
1196 // succeeds or not since we don't expect to be able to do any better below
1199 // Note that the returned SourceSurfaceCairo holds a strong reference to
1200 // the cairo_surface_t* that it wraps, which essencially means it holds a
1201 // strong reference to aSurface since aSurface shares its
1202 // cairo_surface_t*'s reference count variable. As a result we can't cache
1203 // srcBuffer on aSurface (see below) since aSurface would then hold a
1204 // strong reference back to srcBuffer, creating a reference loop and a
1205 // memory leak. Not caching is fine since wrapping is cheap enough (no
1206 // copying) so we can just wrap again next time we're called.
1207 return Factory::CreateSourceSurfaceForCairoSurface(aSurface
->CairoSurface(),
1208 aSurface
->GetSize(), format
);
1211 RefPtr
<SourceSurface
> srcBuffer
;
1213 // Currently no other DrawTarget types implement CreateSourceSurfaceFromNativeSurface
1216 // If aSurface wraps data, we can create a SourceSurfaceRawData that wraps
1217 // the same data, then optimize it for aTarget:
1218 RefPtr
<DataSourceSurface
> surf
= GetWrappedDataSourceSurface(aSurface
);
1220 srcBuffer
= aIsPlugin
? aTarget
->OptimizeSourceSurfaceForUnknownAlpha(surf
)
1221 : aTarget
->OptimizeSourceSurface(surf
);
1223 if (srcBuffer
== surf
) {
1224 // GetWrappedDataSourceSurface returns a SourceSurface that holds a
1225 // strong reference to aSurface since it wraps aSurface's data and
1226 // needs it to stay alive. As a result we can't cache srcBuffer on
1227 // aSurface (below) since aSurface would then hold a strong reference
1228 // back to srcBuffer, creating a reference loop and a memory leak. Not
1229 // caching is fine since wrapping is cheap enough (no copying) so we
1230 // can just wrap again next time we're called.
1232 // Note that the check below doesn't catch this since srcBuffer will be a
1233 // SourceSurfaceRawData object (even if aSurface is not a gfxImageSurface
1234 // object), which is why we need this separate check.
1235 return srcBuffer
.forget();
1241 MOZ_ASSERT(aTarget
->GetBackendType() != BackendType::CAIRO
,
1242 "We already tried CreateSourceSurfaceFromNativeSurface with a "
1243 "DrawTargetCairo above");
1244 // We've run out of performant options. We now try creating a SourceSurface
1245 // using a temporary DrawTargetCairo and then optimizing it to aTarget's
1246 // actual type. The CreateSourceSurfaceFromNativeSurface() call will
1247 // likely create a DataSourceSurface (possibly involving copying and/or
1248 // readback), and the OptimizeSourceSurface may well copy again and upload
1249 // to the GPU. So, while this code path is rarely hit, hitting it may be
1251 srcBuffer
= Factory::CreateSourceSurfaceForCairoSurface(aSurface
->CairoSurface(),
1252 aSurface
->GetSize(), format
);
1254 srcBuffer
= aTarget
->OptimizeSourceSurface(srcBuffer
);
1262 if ((srcBuffer
->GetType() == SurfaceType::CAIRO
&&
1263 static_cast<SourceSurfaceCairo
*>(srcBuffer
.get())->GetSurface() ==
1264 aSurface
->CairoSurface()) ||
1265 (srcBuffer
->GetType() == SurfaceType::CAIRO_IMAGE
&&
1266 static_cast<DataSourceSurfaceCairo
*>(srcBuffer
.get())->GetSurface() ==
1267 aSurface
->CairoSurface())) {
1268 // See the "Note that the returned SourceSurfaceCairo..." comment above.
1269 return srcBuffer
.forget();
1272 // Add user data to aSurface so we can cache lookups in the future.
1273 auto *srcSurfUD
= new SourceSurfaceUserData
;
1274 srcSurfUD
->mBackendType
= aTarget
->GetBackendType();
1275 srcSurfUD
->mSrcSurface
= srcBuffer
;
1276 aSurface
->SetData(&kSourceSurface
, srcSurfUD
, SourceBufferDestroy
);
1278 return srcBuffer
.forget();
1281 already_AddRefed
<DataSourceSurface
>
1282 gfxPlatform::GetWrappedDataSourceSurface(gfxASurface
* aSurface
)
1284 RefPtr
<gfxImageSurface
> image
= aSurface
->GetAsImageSurface();
1288 RefPtr
<DataSourceSurface
> result
=
1289 Factory::CreateWrappingDataSourceSurface(image
->Data(),
1292 ImageFormatToSurfaceFormat(image
->Format()));
1298 // If we wrapped the underlying data of aSurface, then we need to add user data
1299 // to make sure aSurface stays alive until we are done with the data.
1300 auto *srcSurfUD
= new DependentSourceSurfaceUserData
;
1301 srcSurfUD
->mSurface
= aSurface
;
1302 result
->AddUserData(&kThebesSurface
, srcSurfUD
, SourceSurfaceDestroyed
);
1304 return result
.forget();
1308 gfxPlatform::ComputeTileSize()
1310 // The tile size should be picked in the parent processes
1311 // and sent to the child processes over IPDL GetTileSize.
1312 if (!XRE_IsParentProcess()) {
1316 int32_t w
= gfxPrefs::LayersTileWidth();
1317 int32_t h
= gfxPrefs::LayersTileHeight();
1319 if (gfxPrefs::LayersTilesAdjust()) {
1320 gfx::IntSize screenSize
= GetScreenSize();
1321 if (screenSize
.width
> 0) {
1322 // Choose a size so that there are between 2 and 4 tiles per screen width.
1323 // FIXME: we should probably make sure this is within the max texture size,
1324 // but I think everything should at least support 1024
1325 w
= h
= clamped(int32_t(RoundUpPow2(screenSize
.width
)) / 4, 256, 1024);
1329 // Don't allow changing the tile size after we've set it.
1330 // Right now the code assumes that the tile size doesn't change.
1331 MOZ_ASSERT(gfxVars::TileSize().width
== -1 &&
1332 gfxVars::TileSize().height
== -1);
1334 gfxVars::SetTileSize(IntSize(w
, h
));
1338 gfxPlatform::PopulateScreenInfo()
1340 nsCOMPtr
<nsIScreenManager
> manager
= do_GetService("@mozilla.org/gfx/screenmanager;1");
1341 MOZ_ASSERT(manager
, "failed to get nsIScreenManager");
1343 nsCOMPtr
<nsIScreen
> screen
;
1344 manager
->GetPrimaryScreen(getter_AddRefs(screen
));
1346 // This can happen in xpcshell, for instance
1350 screen
->GetColorDepth(&mScreenDepth
);
1351 if (XRE_IsParentProcess()) {
1352 gfxVars::SetScreenDepth(mScreenDepth
);
1356 screen
->GetRect(&left
, &top
, &mScreenSize
.width
, &mScreenSize
.height
);
1360 gfxPlatform::SupportsAzureContentForDrawTarget(DrawTarget
* aTarget
)
1362 if (!aTarget
|| !aTarget
->IsValid()) {
1367 // Skia content rendering doesn't support GPU acceleration, so we can't
1368 // use the same backend if the current backend is accelerated.
1369 if ((aTarget
->GetType() == DrawTargetType::HARDWARE_RASTER
)
1370 && (aTarget
->GetBackendType() == BackendType::SKIA
))
1376 return SupportsAzureContentForType(aTarget
->GetBackendType());
1379 bool gfxPlatform::AllowOpenGLCanvas()
1381 // For now, only allow Skia+OpenGL, unless it's blocked.
1382 // Allow acceleration on Skia if the preference is set, unless it's blocked
1383 // as long as we have the accelerated layers
1385 // The compositor backend is only set correctly in the parent process,
1386 // so we let content process always assume correct compositor backend.
1387 // The callers have to do the right thing.
1388 bool correctBackend
= !XRE_IsParentProcess() ||
1389 ((mCompositorBackend
== LayersBackend::LAYERS_OPENGL
||
1390 mCompositorBackend
== LayersBackend::LAYERS_WR
) &&
1391 (GetContentBackendFor(mCompositorBackend
) == BackendType::SKIA
));
1393 if (gfxPrefs::CanvasAzureAccelerated() && correctBackend
) {
1394 nsCOMPtr
<nsIGfxInfo
> gfxInfo
= do_GetService("@mozilla.org/gfx/info;1");
1396 nsCString discardFailureId
;
1398 (NS_SUCCEEDED(gfxInfo
->GetFeatureStatus(nsIGfxInfo::FEATURE_CANVAS2D_ACCELERATION
,
1401 status
== nsIGfxInfo::FEATURE_STATUS_OK
);
1407 gfxPlatform::InitializeSkiaCacheLimits()
1409 if (AllowOpenGLCanvas()) {
1411 bool usingDynamicCache
= gfxPrefs::CanvasSkiaGLDynamicCache();
1412 int cacheItemLimit
= gfxPrefs::CanvasSkiaGLCacheItems();
1413 uint64_t cacheSizeLimit
= std::max(gfxPrefs::CanvasSkiaGLCacheSize(), (int32_t)0);
1415 // Prefs are in megabytes, but we want the sizes in bytes
1416 cacheSizeLimit
*= 1024*1024;
1418 if (usingDynamicCache
) {
1419 if (mTotalSystemMemory
< 512*1024*1024) {
1420 // We need a very minimal cache on anything smaller than 512mb.
1421 // Note the large jump as we cross 512mb (from 2mb to 32mb).
1422 cacheSizeLimit
= 2*1024*1024;
1423 } else if (mTotalSystemMemory
> 0) {
1424 cacheSizeLimit
= mTotalSystemMemory
/ 16;
1428 // Ensure cache size doesn't overflow on 32-bit platforms.
1429 cacheSizeLimit
= std::min(cacheSizeLimit
, (uint64_t)SIZE_MAX
);
1432 printf_stderr("Determined SkiaGL cache limits: Size %" PRIu64
", Items: %i\n", cacheSizeLimit
, cacheItemLimit
);
1435 mSkiaGlue
->GetGrContext()->setResourceCacheLimits(cacheItemLimit
, (size_t)cacheSizeLimit
);
1441 gfxPlatform::GetSkiaGLGlue()
1444 // Check the accelerated Canvas is enabled for the first time,
1445 // because the callers should check it before using.
1446 if (!mSkiaGlue
&& !AllowOpenGLCanvas()) {
1451 /* Dummy context. We always draw into a FBO.
1453 * FIXME: This should be stored in TLS or something, since there needs to be one for each thread using it. As it
1454 * stands, this only works on the main thread.
1456 RefPtr
<GLContext
> glContext
;
1457 nsCString discardFailureId
;
1458 glContext
= GLContextProvider::CreateHeadless(CreateContextFlags::REQUIRE_COMPAT_PROFILE
|
1459 CreateContextFlags::ALLOW_OFFLINE_RENDERER
,
1462 printf_stderr("Failed to create GLContext for SkiaGL!\n");
1465 mSkiaGlue
= new SkiaGLGlue(glContext
);
1466 MOZ_ASSERT(mSkiaGlue
->GetGrContext(), "No GrContext");
1467 InitializeSkiaCacheLimits();
1475 gfxPlatform::PurgeSkiaFontCache()
1478 if (gfxPlatform::GetPlatform()->GetDefaultContentBackend() == BackendType::SKIA
) {
1479 SkGraphics::PurgeFontCache();
1485 gfxPlatform::PurgeSkiaGPUCache()
1491 mSkiaGlue
->GetGrContext()->freeGpuResources();
1492 // GrContext::flush() doesn't call glFlush. Call it here.
1493 mSkiaGlue
->GetGLContext()->MakeCurrent();
1494 mSkiaGlue
->GetGLContext()->fFlush();
1499 gfxPlatform::HasEnoughTotalSystemMemoryForSkiaGL()
1504 already_AddRefed
<DrawTarget
>
1505 gfxPlatform::CreateDrawTargetForBackend(BackendType aBackend
, const IntSize
& aSize
, SurfaceFormat aFormat
)
1507 // There is a bunch of knowledge in the gfxPlatform heirarchy about how to
1508 // create the best offscreen surface for the current system and situation. We
1509 // can easily take advantage of this for the Cairo backend, so that's what we
1511 // mozilla::gfx::Factory can get away without having all this knowledge for
1512 // now, but this might need to change in the future (using
1513 // CreateOffscreenSurface() and CreateDrawTargetForSurface() for all
1515 if (aBackend
== BackendType::CAIRO
) {
1516 RefPtr
<gfxASurface
> surf
= CreateOffscreenSurface(aSize
, SurfaceFormatToImageFormat(aFormat
));
1517 if (!surf
|| surf
->CairoStatus()) {
1520 return CreateDrawTargetForSurface(surf
, aSize
);
1522 return Factory::CreateDrawTarget(aBackend
, aSize
, aFormat
);
1525 already_AddRefed
<DrawTarget
>
1526 gfxPlatform::CreateOffscreenCanvasDrawTarget(const IntSize
& aSize
, SurfaceFormat aFormat
)
1528 NS_ASSERTION(mPreferredCanvasBackend
!= BackendType::NONE
, "No backend.");
1529 RefPtr
<DrawTarget
> target
= CreateDrawTargetForBackend(mPreferredCanvasBackend
, aSize
, aFormat
);
1531 mFallbackCanvasBackend
== BackendType::NONE
) {
1532 return target
.forget();
1536 // On Windows, the fallback backend (Cairo) should use its image backend.
1537 return Factory::CreateDrawTarget(mFallbackCanvasBackend
, aSize
, aFormat
);
1539 return CreateDrawTargetForBackend(mFallbackCanvasBackend
, aSize
, aFormat
);
1543 already_AddRefed
<DrawTarget
>
1544 gfxPlatform::CreateOffscreenContentDrawTarget(const IntSize
& aSize
,
1545 SurfaceFormat aFormat
,
1548 BackendType backend
= (aFallback
) ? mSoftwareBackend
: mContentBackend
;
1549 NS_ASSERTION(backend
!= BackendType::NONE
, "No backend.");
1550 return CreateDrawTargetForBackend(backend
, aSize
, aFormat
);
1553 already_AddRefed
<DrawTarget
>
1554 gfxPlatform::CreateSimilarSoftwareDrawTarget(DrawTarget
* aDT
,
1555 const IntSize
& aSize
,
1556 SurfaceFormat aFormat
)
1558 RefPtr
<DrawTarget
> dt
;
1560 if (Factory::DoesBackendSupportDataDrawtarget(aDT
->GetBackendType())) {
1561 dt
= aDT
->CreateSimilarDrawTarget(aSize
, aFormat
);
1564 BackendType backendType
= BackendType::SKIA
;
1566 BackendType backendType
= BackendType::CAIRO
;
1568 dt
= Factory::CreateDrawTarget(backendType
, aSize
, aFormat
);
1574 /* static */ already_AddRefed
<DrawTarget
>
1575 gfxPlatform::CreateDrawTargetForData(unsigned char* aData
,
1576 const IntSize
& aSize
,
1578 SurfaceFormat aFormat
,
1579 bool aUninitialized
)
1581 BackendType backendType
= gfxVars::ContentBackend();
1582 NS_ASSERTION(backendType
!= BackendType::NONE
, "No backend.");
1584 if (!Factory::DoesBackendSupportDataDrawtarget(backendType
)) {
1586 backendType
= BackendType::SKIA
;
1588 backendType
= BackendType::CAIRO
;
1592 RefPtr
<DrawTarget
> dt
= Factory::CreateDrawTargetForData(backendType
,
1600 /* static */ BackendType
1601 gfxPlatform::BackendTypeForName(const nsCString
& aName
)
1603 if (aName
.EqualsLiteral("cairo"))
1604 return BackendType::CAIRO
;
1605 if (aName
.EqualsLiteral("skia"))
1606 return BackendType::SKIA
;
1607 if (aName
.EqualsLiteral("direct2d"))
1608 return BackendType::DIRECT2D
;
1609 if (aName
.EqualsLiteral("direct2d1.1"))
1610 return BackendType::DIRECT2D1_1
;
1611 return BackendType::NONE
;
1615 gfxPlatform::GetFontList(nsAtom
*aLangGroup
,
1616 const nsACString
& aGenericFamily
,
1617 nsTArray
<nsString
>& aListOfFonts
)
1619 gfxPlatformFontList::PlatformFontList()->GetFontList(aLangGroup
,
1626 gfxPlatform::UpdateFontList()
1628 gfxPlatformFontList::PlatformFontList()->UpdateFontList();
1633 gfxPlatform::GetStandardFamilyName(const nsAString
& aFontName
,
1634 nsAString
& aFamilyName
)
1636 gfxPlatformFontList::PlatformFontList()->GetStandardFamilyName(aFontName
,
1642 gfxPlatform::GetDefaultFontName(const nsACString
& aLangGroup
,
1643 const nsACString
& aGenericFamily
)
1645 gfxFontFamily
* fontFamily
= gfxPlatformFontList::PlatformFontList()->
1646 GetDefaultFontFamily(aLangGroup
, aGenericFamily
);
1648 return EmptyString();
1650 nsAutoString result
;
1651 fontFamily
->LocalizedName(result
);
1656 gfxPlatform::DownloadableFontsEnabled()
1658 if (mAllowDownloadableFonts
== UNINITIALIZED_VALUE
) {
1659 mAllowDownloadableFonts
=
1660 Preferences::GetBool(GFX_DOWNLOADABLE_FONTS_ENABLED
, false);
1663 return mAllowDownloadableFonts
;
1667 gfxPlatform::UseCmapsDuringSystemFallback()
1669 if (mFallbackUsesCmaps
== UNINITIALIZED_VALUE
) {
1670 mFallbackUsesCmaps
=
1671 Preferences::GetBool(GFX_PREF_FALLBACK_USE_CMAPS
, false);
1674 return mFallbackUsesCmaps
;
1678 gfxPlatform::OpenTypeSVGEnabled()
1680 if (mOpenTypeSVGEnabled
== UNINITIALIZED_VALUE
) {
1681 mOpenTypeSVGEnabled
=
1682 Preferences::GetBool(GFX_PREF_OPENTYPE_SVG
, false);
1685 return mOpenTypeSVGEnabled
> 0;
1689 gfxPlatform::WordCacheCharLimit()
1691 if (mWordCacheCharLimit
== UNINITIALIZED_VALUE
) {
1692 mWordCacheCharLimit
=
1693 Preferences::GetInt(GFX_PREF_WORD_CACHE_CHARLIMIT
, 32);
1694 if (mWordCacheCharLimit
< 0) {
1695 mWordCacheCharLimit
= 32;
1699 return uint32_t(mWordCacheCharLimit
);
1703 gfxPlatform::WordCacheMaxEntries()
1705 if (mWordCacheMaxEntries
== UNINITIALIZED_VALUE
) {
1706 mWordCacheMaxEntries
=
1707 Preferences::GetInt(GFX_PREF_WORD_CACHE_MAXENTRIES
, 10000);
1708 if (mWordCacheMaxEntries
< 0) {
1709 mWordCacheMaxEntries
= 10000;
1713 return uint32_t(mWordCacheMaxEntries
);
1717 gfxPlatform::UseGraphiteShaping()
1719 if (mGraphiteShapingEnabled
== UNINITIALIZED_VALUE
) {
1720 mGraphiteShapingEnabled
=
1721 Preferences::GetBool(GFX_PREF_GRAPHITE_SHAPING
, false);
1724 return mGraphiteShapingEnabled
;
1728 gfxPlatform::IsFontFormatSupported(uint32_t aFormatFlags
)
1730 // check for strange format flags
1731 MOZ_ASSERT(!(aFormatFlags
& gfxUserFontSet::FLAG_FORMAT_NOT_USED
),
1732 "strange font format hint set");
1734 // accept "common" formats that we support on all platforms
1735 if (aFormatFlags
& gfxUserFontSet::FLAG_FORMATS_COMMON
) {
1739 // reject all other formats, known and unknown
1740 if (aFormatFlags
!= 0) {
1744 // no format hint set, need to look at data
1749 gfxPlatform::LookupLocalFont(const nsAString
& aFontName
,
1754 return gfxPlatformFontList::PlatformFontList()->LookupLocalFont(aFontName
,
1761 gfxPlatform::MakePlatformFont(const nsAString
& aFontName
,
1765 const uint8_t* aFontData
,
1768 return gfxPlatformFontList::PlatformFontList()->MakePlatformFont(aFontName
,
1776 mozilla::layers::DiagnosticTypes
1777 gfxPlatform::GetLayerDiagnosticTypes()
1779 mozilla::layers::DiagnosticTypes type
= DiagnosticTypes::NO_DIAGNOSTIC
;
1780 if (gfxPrefs::DrawLayerBorders()) {
1781 type
|= mozilla::layers::DiagnosticTypes::LAYER_BORDERS
;
1783 if (gfxPrefs::DrawTileBorders()) {
1784 type
|= mozilla::layers::DiagnosticTypes::TILE_BORDERS
;
1786 if (gfxPrefs::DrawBigImageBorders()) {
1787 type
|= mozilla::layers::DiagnosticTypes::BIGIMAGE_BORDERS
;
1789 if (gfxPrefs::FlashLayerBorders()) {
1790 type
|= mozilla::layers::DiagnosticTypes::FLASH_BORDERS
;
1796 gfxPlatform::GetBackendPrefs()
1798 BackendPrefsData data
;
1800 data
.mCanvasBitmask
= BackendTypeBit(BackendType::CAIRO
);
1801 data
.mContentBitmask
= BackendTypeBit(BackendType::CAIRO
);
1803 data
.mCanvasBitmask
|= BackendTypeBit(BackendType::SKIA
);
1804 data
.mContentBitmask
|= BackendTypeBit(BackendType::SKIA
);
1806 data
.mCanvasDefault
= BackendType::CAIRO
;
1807 data
.mContentDefault
= BackendType::CAIRO
;
1809 return mozilla::Move(data
);
1813 gfxPlatform::InitBackendPrefs(BackendPrefsData
&& aPrefsData
)
1815 mPreferredCanvasBackend
= GetCanvasBackendPref(aPrefsData
.mCanvasBitmask
);
1816 if (mPreferredCanvasBackend
== BackendType::NONE
) {
1817 mPreferredCanvasBackend
= aPrefsData
.mCanvasDefault
;
1820 if (mPreferredCanvasBackend
== BackendType::DIRECT2D1_1
) {
1821 // Falling back to D2D 1.0 won't help us here. When D2D 1.1 DT creation
1822 // fails it means the surface was too big or there's something wrong with
1823 // the device. D2D 1.0 will encounter a similar situation.
1824 mFallbackCanvasBackend
=
1825 GetCanvasBackendPref(aPrefsData
.mCanvasBitmask
&
1826 ~(BackendTypeBit(mPreferredCanvasBackend
) | BackendTypeBit(BackendType::DIRECT2D
)));
1828 mFallbackCanvasBackend
=
1829 GetCanvasBackendPref(aPrefsData
.mCanvasBitmask
& ~BackendTypeBit(mPreferredCanvasBackend
));
1833 mContentBackendBitmask
= aPrefsData
.mContentBitmask
;
1834 mContentBackend
= GetContentBackendPref(mContentBackendBitmask
);
1835 if (mContentBackend
== BackendType::NONE
) {
1836 mContentBackend
= aPrefsData
.mContentDefault
;
1837 // mContentBackendBitmask is our canonical reference for supported
1838 // backends so we need to add the default if we are using it and
1839 // overriding the prefs.
1840 mContentBackendBitmask
|= BackendTypeBit(aPrefsData
.mContentDefault
);
1843 uint32_t swBackendBits
= BackendTypeBit(BackendType::SKIA
) |
1844 BackendTypeBit(BackendType::CAIRO
);
1845 mSoftwareBackend
= GetContentBackendPref(swBackendBits
);
1847 if (XRE_IsParentProcess()) {
1848 gfxVars::SetContentBackend(mContentBackend
);
1849 gfxVars::SetSoftwareBackend(mSoftwareBackend
);
1853 /* static */ BackendType
1854 gfxPlatform::GetCanvasBackendPref(uint32_t aBackendBitmask
)
1856 return GetBackendPref("gfx.canvas.azure.backends", aBackendBitmask
);
1859 /* static */ BackendType
1860 gfxPlatform::GetContentBackendPref(uint32_t &aBackendBitmask
)
1862 return GetBackendPref("gfx.content.azure.backends", aBackendBitmask
);
1865 /* static */ BackendType
1866 gfxPlatform::GetBackendPref(const char* aBackendPrefName
, uint32_t &aBackendBitmask
)
1868 nsTArray
<nsCString
> backendList
;
1869 nsAutoCString prefString
;
1870 if (NS_SUCCEEDED(Preferences::GetCString(aBackendPrefName
, prefString
))) {
1871 ParseString(prefString
, ',', backendList
);
1874 uint32_t allowedBackends
= 0;
1875 BackendType result
= BackendType::NONE
;
1876 for (uint32_t i
= 0; i
< backendList
.Length(); ++i
) {
1877 BackendType type
= BackendTypeForName(backendList
[i
]);
1878 if (BackendTypeBit(type
) & aBackendBitmask
) {
1879 allowedBackends
|= BackendTypeBit(type
);
1880 if (result
== BackendType::NONE
) {
1886 aBackendBitmask
= allowedBackends
;
1891 gfxPlatform::InSafeMode()
1893 static bool sSafeModeInitialized
= false;
1894 static bool sInSafeMode
= false;
1896 if (!sSafeModeInitialized
) {
1897 sSafeModeInitialized
= true;
1898 nsCOMPtr
<nsIXULRuntime
> xr
= do_GetService("@mozilla.org/xre/runtime;1");
1900 xr
->GetInSafeMode(&sInSafeMode
);
1907 gfxPlatform::OffMainThreadCompositingEnabled()
1909 return UsesOffMainThreadCompositing();
1913 gfxPlatform::GetCMSMode()
1915 if (!gCMSInitialized
) {
1916 int32_t mode
= gfxPrefs::CMSMode();
1917 if (mode
>= 0 && mode
< eCMSMode_AllCount
) {
1918 gCMSMode
= static_cast<eCMSMode
>(mode
);
1921 bool enableV4
= gfxPrefs::CMSEnableV4();
1923 qcms_enable_iccv4();
1925 gCMSInitialized
= true;
1931 gfxPlatform::GetRenderingIntent()
1933 // gfxPrefs.h is using 0 as the default for the rendering
1934 // intent preference, based on that being the value for
1935 // QCMS_INTENT_DEFAULT. Assert here to catch if that ever
1936 // changes and we can then figure out what to do about it.
1937 MOZ_ASSERT(QCMS_INTENT_DEFAULT
== 0);
1939 /* Try to query the pref system for a rendering intent. */
1940 int32_t pIntent
= gfxPrefs::CMSRenderingIntent();
1941 if ((pIntent
< QCMS_INTENT_MIN
) || (pIntent
> QCMS_INTENT_MAX
)) {
1942 /* If the pref is out of range, use embedded profile. */
1949 gfxPlatform::TransformPixel(const Color
& in
, Color
& out
, qcms_transform
*transform
)
1953 /* we want the bytes in RGB order */
1954 #ifdef IS_LITTLE_ENDIAN
1955 /* ABGR puts the bytes in |RGBA| order on little endian */
1956 uint32_t packed
= in
.ToABGR();
1957 qcms_transform_data(transform
,
1958 (uint8_t *)&packed
, (uint8_t *)&packed
,
1960 out
= Color::FromABGR(packed
);
1962 /* ARGB puts the bytes in |ARGB| order on big endian */
1963 uint32_t packed
= in
.UnusualToARGB();
1964 /* add one to move past the alpha byte */
1965 qcms_transform_data(transform
,
1966 (uint8_t *)&packed
+ 1, (uint8_t *)&packed
+ 1,
1968 out
= Color::UnusualFromARGB(packed
);
1972 else if (&out
!= &in
)
1977 gfxPlatform::GetPlatformCMSOutputProfile(void *&mem
, size_t &size
)
1984 gfxPlatform::GetCMSOutputProfileData(void *&mem
, size_t &size
)
1986 nsAutoCString fname
;
1987 Preferences::GetCString("gfx.color_management.display_profile", fname
);
1988 if (!fname
.IsEmpty()) {
1989 qcms_data_from_path(fname
.get(), &mem
, &size
);
1992 gfxPlatform::GetPlatform()->GetPlatformCMSOutputProfile(mem
, size
);
1997 gfxPlatform::CreateCMSOutputProfile()
1999 if (!gCMSOutputProfile
) {
2000 /* Determine if we're using the internal override to force sRGB as
2001 an output profile for reftests. See Bug 452125.
2003 Note that we don't normally (outside of tests) set a
2004 default value of this preference, which means nsIPrefBranch::GetBoolPref
2005 will typically throw (and leave its out-param untouched).
2007 if (Preferences::GetBool(GFX_PREF_CMS_FORCE_SRGB
, false)) {
2008 gCMSOutputProfile
= GetCMSsRGBProfile();
2011 if (!gCMSOutputProfile
) {
2012 void* mem
= nullptr;
2015 GetCMSOutputProfileData(mem
, size
);
2016 if ((mem
!= nullptr) && (size
> 0)) {
2017 gCMSOutputProfile
= qcms_profile_from_memory(mem
, size
);
2022 /* Determine if the profile looks bogus. If so, close the profile
2023 * and use sRGB instead. See bug 460629, */
2024 if (gCMSOutputProfile
&& qcms_profile_is_bogus(gCMSOutputProfile
)) {
2025 NS_ASSERTION(gCMSOutputProfile
!= GetCMSsRGBProfile(),
2026 "Builtin sRGB profile tagged as bogus!!!");
2027 qcms_profile_release(gCMSOutputProfile
);
2028 gCMSOutputProfile
= nullptr;
2031 if (!gCMSOutputProfile
) {
2032 gCMSOutputProfile
= GetCMSsRGBProfile();
2034 /* Precache the LUT16 Interpolations for the output profile. See
2035 bug 444661 for details. */
2036 qcms_profile_precache_output_transform(gCMSOutputProfile
);
2041 gfxPlatform::GetCMSOutputProfile()
2043 return gCMSOutputProfile
;
2047 gfxPlatform::GetCMSsRGBProfile()
2049 if (!gCMSsRGBProfile
) {
2051 /* Create the profile using qcms. */
2052 gCMSsRGBProfile
= qcms_profile_sRGB();
2054 return gCMSsRGBProfile
;
2058 gfxPlatform::GetCMSRGBTransform()
2060 if (!gCMSRGBTransform
) {
2061 qcms_profile
*inProfile
, *outProfile
;
2062 outProfile
= GetCMSOutputProfile();
2063 inProfile
= GetCMSsRGBProfile();
2065 if (!inProfile
|| !outProfile
)
2068 gCMSRGBTransform
= qcms_transform_create(inProfile
, QCMS_DATA_RGB_8
,
2069 outProfile
, QCMS_DATA_RGB_8
,
2070 QCMS_INTENT_PERCEPTUAL
);
2073 return gCMSRGBTransform
;
2077 gfxPlatform::GetCMSInverseRGBTransform()
2079 if (!gCMSInverseRGBTransform
) {
2080 qcms_profile
*inProfile
, *outProfile
;
2081 inProfile
= GetCMSOutputProfile();
2082 outProfile
= GetCMSsRGBProfile();
2084 if (!inProfile
|| !outProfile
)
2087 gCMSInverseRGBTransform
= qcms_transform_create(inProfile
, QCMS_DATA_RGB_8
,
2088 outProfile
, QCMS_DATA_RGB_8
,
2089 QCMS_INTENT_PERCEPTUAL
);
2092 return gCMSInverseRGBTransform
;
2096 gfxPlatform::GetCMSRGBATransform()
2098 if (!gCMSRGBATransform
) {
2099 qcms_profile
*inProfile
, *outProfile
;
2100 outProfile
= GetCMSOutputProfile();
2101 inProfile
= GetCMSsRGBProfile();
2103 if (!inProfile
|| !outProfile
)
2106 gCMSRGBATransform
= qcms_transform_create(inProfile
, QCMS_DATA_RGBA_8
,
2107 outProfile
, QCMS_DATA_RGBA_8
,
2108 QCMS_INTENT_PERCEPTUAL
);
2111 return gCMSRGBATransform
;
2114 /* Shuts down various transforms and profiles for CMS. */
2115 static void ShutdownCMS()
2118 if (gCMSRGBTransform
) {
2119 qcms_transform_release(gCMSRGBTransform
);
2120 gCMSRGBTransform
= nullptr;
2122 if (gCMSInverseRGBTransform
) {
2123 qcms_transform_release(gCMSInverseRGBTransform
);
2124 gCMSInverseRGBTransform
= nullptr;
2126 if (gCMSRGBATransform
) {
2127 qcms_transform_release(gCMSRGBATransform
);
2128 gCMSRGBATransform
= nullptr;
2130 if (gCMSOutputProfile
) {
2131 qcms_profile_release(gCMSOutputProfile
);
2133 // handle the aliased case
2134 if (gCMSsRGBProfile
== gCMSOutputProfile
)
2135 gCMSsRGBProfile
= nullptr;
2136 gCMSOutputProfile
= nullptr;
2138 if (gCMSsRGBProfile
) {
2139 qcms_profile_release(gCMSsRGBProfile
);
2140 gCMSsRGBProfile
= nullptr;
2143 // Reset the state variables
2144 gCMSMode
= eCMSMode_Off
;
2145 gCMSInitialized
= false;
2148 // default SetupClusterBoundaries, based on Unicode properties;
2149 // platform subclasses may override if they wish
2151 gfxPlatform::SetupClusterBoundaries(gfxTextRun
*aTextRun
, const char16_t
*aString
)
2153 if (aTextRun
->GetFlags() & gfx::ShapedTextFlags::TEXT_IS_8BIT
) {
2154 // 8-bit text doesn't have clusters.
2155 // XXX is this true in all languages???
2156 // behdad: don't think so. Czech for example IIRC has a
2158 // jfkthame: but that's not expected to behave as a grapheme cluster
2159 // for selection/editing/etc.
2163 aTextRun
->SetupClusterBoundaries(0, aString
, aTextRun
->GetLength());
2167 gfxPlatform::GetBidiNumeralOption()
2169 if (mBidiNumeralOption
== UNINITIALIZED_VALUE
) {
2170 mBidiNumeralOption
= Preferences::GetInt(BIDI_NUMERAL_PREF
, 0);
2172 return mBidiNumeralOption
;
2176 gfxPlatform::FlushFontAndWordCaches()
2178 gfxFontCache
*fontCache
= gfxFontCache::GetCache();
2180 fontCache
->AgeAllGenerations();
2181 fontCache
->FlushShapedWordCaches();
2184 gfxPlatform::PurgeSkiaFontCache();
2188 gfxPlatform::ForceGlobalReflow()
2190 MOZ_ASSERT(NS_IsMainThread());
2191 if (XRE_IsParentProcess()) {
2192 // Modify a preference that will trigger reflow everywhere (in all
2193 // content processes, as well as the parent).
2194 static const char kPrefName
[] = "font.internaluseonly.changed";
2195 bool fontInternalChange
= Preferences::GetBool(kPrefName
, false);
2196 Preferences::SetBool(kPrefName
, !fontInternalChange
);
2198 // Send a notification that will be observed by PresShells in this
2200 nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService();
2202 obs
->NotifyObservers(nullptr, "font-info-updated", nullptr);
2208 gfxPlatform::FontsPrefsChanged(const char *aPref
)
2210 NS_ASSERTION(aPref
!= nullptr, "null preference");
2211 if (!strcmp(GFX_DOWNLOADABLE_FONTS_ENABLED
, aPref
)) {
2212 mAllowDownloadableFonts
= UNINITIALIZED_VALUE
;
2213 } else if (!strcmp(GFX_PREF_FALLBACK_USE_CMAPS
, aPref
)) {
2214 mFallbackUsesCmaps
= UNINITIALIZED_VALUE
;
2215 } else if (!strcmp(GFX_PREF_WORD_CACHE_CHARLIMIT
, aPref
)) {
2216 mWordCacheCharLimit
= UNINITIALIZED_VALUE
;
2217 FlushFontAndWordCaches();
2218 } else if (!strcmp(GFX_PREF_WORD_CACHE_MAXENTRIES
, aPref
)) {
2219 mWordCacheMaxEntries
= UNINITIALIZED_VALUE
;
2220 FlushFontAndWordCaches();
2221 } else if (!strcmp(GFX_PREF_GRAPHITE_SHAPING
, aPref
)) {
2222 mGraphiteShapingEnabled
= UNINITIALIZED_VALUE
;
2223 FlushFontAndWordCaches();
2224 } else if (!strcmp(BIDI_NUMERAL_PREF
, aPref
)) {
2225 mBidiNumeralOption
= UNINITIALIZED_VALUE
;
2226 } else if (!strcmp(GFX_PREF_OPENTYPE_SVG
, aPref
)) {
2227 mOpenTypeSVGEnabled
= UNINITIALIZED_VALUE
;
2228 gfxFontCache::GetCache()->AgeAllGenerations();
2229 gfxFontCache::GetCache()->NotifyGlyphsChanged();
2235 gfxPlatform::GetLog(eGfxLog aWhichLog
)
2237 // logs shared across gfx
2238 static LazyLogModule
sFontlistLog("fontlist");
2239 static LazyLogModule
sFontInitLog("fontinit");
2240 static LazyLogModule
sTextrunLog("textrun");
2241 static LazyLogModule
sTextrunuiLog("textrunui");
2242 static LazyLogModule
sCmapDataLog("cmapdata");
2243 static LazyLogModule
sTextPerfLog("textperf");
2245 switch (aWhichLog
) {
2246 case eGfxLog_fontlist
:
2247 return sFontlistLog
;
2248 case eGfxLog_fontinit
:
2249 return sFontInitLog
;
2250 case eGfxLog_textrun
:
2252 case eGfxLog_textrunui
:
2253 return sTextrunuiLog
;
2254 case eGfxLog_cmapdata
:
2255 return sCmapDataLog
;
2256 case eGfxLog_textperf
:
2257 return sTextPerfLog
;
2260 MOZ_ASSERT_UNREACHABLE("Unexpected log type");
2264 RefPtr
<mozilla::gfx::DrawTarget
>
2265 gfxPlatform::ScreenReferenceDrawTarget()
2267 return (mScreenReferenceDrawTarget
)
2268 ? mScreenReferenceDrawTarget
2269 : gPlatform
->CreateOffscreenContentDrawTarget(
2270 IntSize(1, 1), SurfaceFormat::B8G8R8A8
, true);
2273 mozilla::gfx::SurfaceFormat
2274 gfxPlatform::Optimal2DFormatForContent(gfxContentType aContent
)
2277 case gfxContentType::COLOR
:
2278 switch (GetOffscreenFormat()) {
2279 case SurfaceFormat::A8R8G8B8_UINT32
:
2280 return mozilla::gfx::SurfaceFormat::B8G8R8A8
;
2281 case SurfaceFormat::X8R8G8B8_UINT32
:
2282 return mozilla::gfx::SurfaceFormat::B8G8R8X8
;
2283 case SurfaceFormat::R5G6B5_UINT16
:
2284 return mozilla::gfx::SurfaceFormat::R5G6B5_UINT16
;
2286 NS_NOTREACHED("unknown gfxImageFormat for gfxContentType::COLOR");
2287 return mozilla::gfx::SurfaceFormat::B8G8R8A8
;
2289 case gfxContentType::ALPHA
:
2290 return mozilla::gfx::SurfaceFormat::A8
;
2291 case gfxContentType::COLOR_ALPHA
:
2292 return mozilla::gfx::SurfaceFormat::B8G8R8A8
;
2294 NS_NOTREACHED("unknown gfxContentType");
2295 return mozilla::gfx::SurfaceFormat::B8G8R8A8
;
2300 gfxPlatform::OptimalFormatForContent(gfxContentType aContent
)
2303 case gfxContentType::COLOR
:
2304 return GetOffscreenFormat();
2305 case gfxContentType::ALPHA
:
2306 return SurfaceFormat::A8
;
2307 case gfxContentType::COLOR_ALPHA
:
2308 return SurfaceFormat::A8R8G8B8_UINT32
;
2310 NS_NOTREACHED("unknown gfxContentType");
2311 return SurfaceFormat::A8R8G8B8_UINT32
;
2316 * There are a number of layers acceleration (or layers in general) preferences
2317 * that should be consistent for the lifetime of the application (bug 840967).
2318 * As such, we will evaluate them all as soon as one of them is evaluated
2319 * and remember the values. Changing these preferences during the run will
2320 * not have any effect until we restart.
2322 static mozilla::Atomic
<bool> sLayersSupportsHardwareVideoDecoding(false);
2323 static bool sLayersHardwareVideoDecodingFailed
= false;
2324 static bool sBufferRotationCheckPref
= true;
2326 static mozilla::Atomic
<bool> sLayersAccelerationPrefsInitialized(false);
2328 void VideoDecodingFailedChangedCallback(const char* aPref
, void*)
2330 sLayersHardwareVideoDecodingFailed
= Preferences::GetBool(aPref
, false);
2331 gfxPlatform::GetPlatform()->UpdateCanUseHardwareVideoDecoding();
2335 gfxPlatform::UpdateCanUseHardwareVideoDecoding()
2337 if (XRE_IsParentProcess()) {
2338 gfxVars::SetCanUseHardwareVideoDecoding(CanUseHardwareVideoDecoding());
2343 gfxPlatform::InitAcceleration()
2345 if (sLayersAccelerationPrefsInitialized
) {
2349 InitCompositorAccelerationPrefs();
2351 // If this is called for the first time on a non-main thread, we're screwed.
2352 // At the moment there's no explicit guarantee that the main thread calls
2353 // this before the compositor thread, but let's at least make the assumption
2355 MOZ_ASSERT(NS_IsMainThread(), "can only initialize prefs on the main thread");
2357 gfxPrefs::GetSingleton();
2359 nsCOMPtr
<nsIGfxInfo
> gfxInfo
= services::GetGfxInfo();
2360 nsCString discardFailureId
;
2363 if (XRE_IsParentProcess()) {
2364 gfxVars::SetBrowserTabsRemoteAutostart(BrowserTabsRemoteAutostart());
2365 gfxVars::SetOffscreenFormat(GetOffscreenFormat());
2366 gfxVars::SetRequiresAcceleratedGLContextForCompositorOGL(
2367 RequiresAcceleratedGLContextForCompositorOGL());
2369 if (NS_SUCCEEDED(gfxInfo
->GetFeatureStatus(nsIGfxInfo::FEATURE_D3D11_KEYED_MUTEX
,
2370 discardFailureId
, &status
))) {
2371 gfxVars::SetAllowD3D11KeyedMutex(status
== nsIGfxInfo::FEATURE_STATUS_OK
);
2373 // If we couldn't properly evaluate the status, err on the side
2374 // of caution and give this functionality to the user.
2375 gfxCriticalNote
<< "Cannot evaluate keyed mutex feature status";
2376 gfxVars::SetAllowD3D11KeyedMutex(true);
2381 if (Preferences::GetBool("media.hardware-video-decoding.enabled", false) &&
2383 Preferences::GetBool("media.wmf.dxva.enabled", true) &&
2385 NS_SUCCEEDED(gfxInfo
->GetFeatureStatus(nsIGfxInfo::FEATURE_HARDWARE_VIDEO_DECODING
,
2386 discardFailureId
, &status
))) {
2387 if (status
== nsIGfxInfo::FEATURE_STATUS_OK
|| gfxPrefs::HardwareVideoDecodingForceEnabled()) {
2388 sLayersSupportsHardwareVideoDecoding
= true;
2392 sLayersAccelerationPrefsInitialized
= true;
2394 if (XRE_IsParentProcess()) {
2395 Preferences::RegisterCallbackAndCall(VideoDecodingFailedChangedCallback
,
2396 "media.hardware-video-decoding.failed");
2397 InitGPUProcessPrefs();
2402 gfxPlatform::InitGPUProcessPrefs()
2404 // We want to hide this from about:support, so only set a default if the
2405 // pref is known to be true.
2406 if (!gfxPrefs::GPUProcessEnabled() && !gfxPrefs::GPUProcessForceEnabled()) {
2410 FeatureState
& gpuProc
= gfxConfig::GetFeature(Feature::GPU_PROCESS
);
2412 // We require E10S - otherwise, there is very little benefit to the GPU
2413 // process, since the UI process must still use acceleration for
2415 if (!BrowserTabsRemoteAutostart()) {
2416 gpuProc
.DisableByDefault(
2417 FeatureStatus::Unavailable
,
2418 "Multi-process mode is not enabled",
2419 NS_LITERAL_CSTRING("FEATURE_FAILURE_NO_E10S"));
2421 gpuProc
.SetDefaultFromPref(
2422 gfxPrefs::GetGPUProcessEnabledPrefName(),
2424 gfxPrefs::GetGPUProcessEnabledPrefDefault());
2427 if (gfxPrefs::GPUProcessForceEnabled()) {
2428 gpuProc
.UserForceEnable("User force-enabled via pref");
2432 gpuProc
.ForceDisable(
2433 FeatureStatus::Blocked
,
2434 "Headless mode is enabled",
2435 NS_LITERAL_CSTRING("FEATURE_FAILURE_HEADLESS_MODE"));
2439 gpuProc
.ForceDisable(
2440 FeatureStatus::Blocked
,
2441 "Safe-mode is enabled",
2442 NS_LITERAL_CSTRING("FEATURE_FAILURE_SAFE_MODE"));
2445 if (gfxPrefs::LayerScopeEnabled()) {
2446 gpuProc
.ForceDisable(
2447 FeatureStatus::Blocked
,
2448 "LayerScope does not work in the GPU process",
2449 NS_LITERAL_CSTRING("FEATURE_FAILURE_LAYERSCOPE"));
2455 gfxPlatform::InitCompositorAccelerationPrefs()
2457 const char *acceleratedEnv
= PR_GetEnv("MOZ_ACCELERATED");
2459 FeatureState
& feature
= gfxConfig::GetFeature(Feature::HW_COMPOSITING
);
2461 // Base value - does the platform allow acceleration?
2462 if (feature
.SetDefault(AccelerateLayersByDefault(),
2463 FeatureStatus::Blocked
,
2464 "Acceleration blocked by platform"))
2466 if (gfxPrefs::LayersAccelerationDisabledDoNotUseDirectly()) {
2467 feature
.UserDisable("Disabled by pref",
2468 NS_LITERAL_CSTRING("FEATURE_FAILURE_COMP_PREF"));
2469 } else if (acceleratedEnv
&& *acceleratedEnv
== '0') {
2470 feature
.UserDisable("Disabled by envvar",
2471 NS_LITERAL_CSTRING("FEATURE_FAILURE_COMP_ENV"));
2474 if (acceleratedEnv
&& *acceleratedEnv
== '1') {
2475 feature
.UserEnable("Enabled by envvar");
2479 // This has specific meaning elsewhere, so we always record it.
2480 if (gfxPrefs::LayersAccelerationForceEnabledDoNotUseDirectly()) {
2481 feature
.UserForceEnable("Force-enabled by pref");
2484 // Safe and headless modes override everything.
2486 feature
.ForceDisable(FeatureStatus::Blocked
, "Acceleration blocked by safe-mode",
2487 NS_LITERAL_CSTRING("FEATURE_FAILURE_COMP_SAFEMODE"));
2490 feature
.ForceDisable(FeatureStatus::Blocked
, "Acceleration blocked by headless mode",
2491 NS_LITERAL_CSTRING("FEATURE_FAILURE_COMP_HEADLESSMODE"));
2496 gfxPlatform::WebRenderPrefEnabled()
2498 return gfxPrefs::WebRenderAll() || gfxPrefs::WebRenderEnabledDoNotUseDirectly();
2502 gfxPlatform::WebRenderEnvvarEnabled()
2504 const char* env
= PR_GetEnv("MOZ_WEBRENDER");
2505 return (env
&& *env
== '1');
2509 gfxPlatform::InitWebRenderConfig()
2511 bool prefEnabled
= WebRenderPrefEnabled();
2513 ScopedGfxFeatureReporter
reporter("WR", prefEnabled
);
2514 if (!XRE_IsParentProcess()) {
2515 // The parent process runs through all the real decision-making code
2516 // later in this function. For other processes we still want to report
2517 // the state of the feature for crash reports.
2518 if (gfxVars::UseWebRender()) {
2519 reporter
.SetSuccessful();
2524 FeatureState
& featureWebRender
= gfxConfig::GetFeature(Feature::WEBRENDER
);
2526 featureWebRender
.DisableByDefault(
2527 FeatureStatus::OptIn
,
2528 "WebRender is an opt-in feature",
2529 NS_LITERAL_CSTRING("FEATURE_FAILURE_DEFAULT_OFF"));
2532 featureWebRender
.UserEnable("Enabled by pref");
2533 } else if (WebRenderEnvvarEnabled()) {
2534 featureWebRender
.UserEnable("Enabled by envvar");
2537 // HW_COMPOSITING being disabled implies interfacing with the GPU might break
2538 if (!gfxConfig::IsEnabled(Feature::HW_COMPOSITING
)) {
2539 featureWebRender
.ForceDisable(
2540 FeatureStatus::Unavailable
,
2541 "Hardware compositing is disabled",
2542 NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBRENDER_NEED_HWCOMP"));
2545 // WebRender relies on the GPU process when on Windows
2547 if (!gfxConfig::IsEnabled(Feature::GPU_PROCESS
)) {
2548 featureWebRender
.ForceDisable(
2549 FeatureStatus::Unavailable
,
2550 "GPU Process is disabled",
2551 NS_LITERAL_CSTRING("FEATURE_FAILURE_GPU_PROCESS_DISABLED"));
2556 featureWebRender
.ForceDisable(
2557 FeatureStatus::Unavailable
,
2558 "Safe-mode is enabled",
2559 NS_LITERAL_CSTRING("FEATURE_FAILURE_SAFE_MODE"));
2562 #ifndef MOZ_BUILD_WEBRENDER
2563 featureWebRender
.ForceDisable(
2564 FeatureStatus::Unavailable
,
2565 "Build doesn't include WebRender",
2566 NS_LITERAL_CSTRING("FEATURE_FAILURE_NO_WEBRENDER"));
2570 if (Preferences::GetBool("gfx.webrender.force-angle", false)) {
2571 if (!gfxConfig::IsEnabled(Feature::D3D11_HW_ANGLE
)) {
2572 featureWebRender
.ForceDisable(
2573 FeatureStatus::Unavailable
,
2574 "ANGLE is disabled",
2575 NS_LITERAL_CSTRING("FEATURE_FAILURE_ANGLE_DISABLED"));
2577 gfxVars::SetUseWebRenderANGLE(gfxConfig::IsEnabled(Feature::WEBRENDER
));
2582 if (Preferences::GetBool("gfx.webrender.program-binary", false)) {
2583 gfx::gfxVars::SetUseWebRenderProgramBinary(gfxConfig::IsEnabled(Feature::WEBRENDER
));
2586 #ifdef MOZ_WIDGET_ANDROID
2587 featureWebRender
.ForceDisable(
2588 FeatureStatus::Unavailable
,
2589 "WebRender not ready for use on Android",
2590 NS_LITERAL_CSTRING("FEATURE_FAILURE_ANDROID"));
2593 // gfxFeature is not usable in the GPU process, so we use gfxVars to transmit this feature
2594 if (gfxConfig::IsEnabled(Feature::WEBRENDER
)) {
2595 gfxVars::SetUseWebRender(true);
2596 reporter
.SetSuccessful();
2598 if (XRE_IsParentProcess()) {
2599 Preferences::RegisterPrefixCallbackAndCall(WebRenderDebugPrefChangeCallback
,
2605 if (Preferences::GetBool("gfx.webrender.dcomp-win.enabled", false)) {
2606 // XXX relax win version to windows 8.
2607 if (IsWin10OrLater() &&
2608 gfxVars::UseWebRender() &&
2609 gfxVars::UseWebRenderANGLE()) {
2610 gfxVars::SetUseWebRenderDCompWin(true);
2617 gfxPlatform::InitOMTPConfig()
2619 ScopedGfxFeatureReporter
reporter("OMTP");
2621 FeatureState
& omtp
= gfxConfig::GetFeature(Feature::OMTP
);
2622 int32_t paintWorkerCount
= PaintThread::CalculatePaintWorkerCount();
2624 if (!XRE_IsParentProcess()) {
2625 // The parent process runs through all the real decision-making code
2626 // later in this function. For other processes we still want to report
2627 // the state of the feature for crash reports.
2628 if (gfxVars::UseOMTP()) {
2629 reporter
.SetSuccessful(paintWorkerCount
);
2634 omtp
.SetDefaultFromPref(
2635 "layers.omtp.enabled",
2637 Preferences::GetBool("layers.omtp.enabled", false, PrefValueKind::Default
));
2639 if (mContentBackend
== BackendType::CAIRO
) {
2640 omtp
.ForceDisable(FeatureStatus::Broken
, "OMTP is not supported when using cairo",
2641 NS_LITERAL_CSTRING("FEATURE_FAILURE_COMP_PREF"));
2645 omtp
.ForceDisable(FeatureStatus::Blocked
, "OMTP blocked by safe-mode",
2646 NS_LITERAL_CSTRING("FEATURE_FAILURE_COMP_SAFEMODE"));
2647 } else if (gfxPlatform::UsesTiling() && gfxPrefs::TileEdgePaddingEnabled()) {
2648 omtp
.ForceDisable(FeatureStatus::Blocked
, "OMTP does not yet support tiling with edge padding",
2649 NS_LITERAL_CSTRING("FEATURE_FAILURE_OMTP_TILING"));
2652 if (omtp
.IsEnabled()) {
2653 gfxVars::SetUseOMTP(true);
2654 reporter
.SetSuccessful(paintWorkerCount
);
2659 gfxPlatform::CanUseHardwareVideoDecoding()
2661 // this function is called from the compositor thread, so it is not
2662 // safe to init the prefs etc. from here.
2663 MOZ_ASSERT(sLayersAccelerationPrefsInitialized
);
2664 return sLayersSupportsHardwareVideoDecoding
&& !sLayersHardwareVideoDecodingFailed
;
2668 gfxPlatform::AccelerateLayersByDefault()
2670 #if defined(MOZ_GL_PROVIDER) || defined(MOZ_WIDGET_UIKIT)
2678 gfxPlatform::BufferRotationEnabled()
2680 MutexAutoLock
autoLock(*gGfxPlatformPrefsLock
);
2682 return sBufferRotationCheckPref
&& gfxPrefs::BufferRotationEnabled();
2686 gfxPlatform::DisableBufferRotation()
2688 MutexAutoLock
autoLock(*gGfxPlatformPrefsLock
);
2690 sBufferRotationCheckPref
= false;
2694 gfxPlatform::UsesOffMainThreadCompositing()
2696 if (XRE_GetProcessType() == GeckoProcessType_GPU
) {
2700 static bool firstTime
= true;
2701 static bool result
= false;
2704 MOZ_ASSERT(sLayersAccelerationPrefsInitialized
);
2706 gfxVars::BrowserTabsRemoteAutostart() ||
2707 !gfxPrefs::LayersOffMainThreadCompositionForceDisabled();
2708 #if defined(MOZ_WIDGET_GTK)
2709 // Linux users who chose OpenGL are being grandfathered in to OMTC
2710 result
|= gfxPrefs::LayersAccelerationForceEnabledDoNotUseDirectly();
2720 gfxPlatform::UsesTiling() const
2722 return gfxPrefs::LayersTilesEnabled();
2726 * The preference "layout.frame_rate" has 3 meanings depending on the value:
2728 * -1 = Auto (default), use hardware vsync or software vsync @ 60 hz if hw vsync fails.
2729 * 0 = ASAP mode - used during talos testing.
2730 * X = Software vsync at a rate of X times per second.
2732 already_AddRefed
<mozilla::gfx::VsyncSource
>
2733 gfxPlatform::CreateHardwareVsyncSource()
2735 RefPtr
<mozilla::gfx::VsyncSource
> softwareVsync
= new SoftwareVsyncSource();
2736 return softwareVsync
.forget();
2740 gfxPlatform::IsInLayoutAsapMode()
2742 // There are 2 modes of ASAP mode.
2743 // 1 is that the refresh driver and compositor are in lock step
2744 // the second is that the compositor goes ASAP and the refresh driver
2745 // goes at whatever the configurated rate is. This only checks the version
2746 // talos uses, which is the refresh driver and compositor are in lockstep.
2747 return gfxPrefs::LayoutFrameRate() == 0;
2751 gfxPlatform::ForceSoftwareVsync()
2753 return gfxPrefs::LayoutFrameRate() > 0;
2757 gfxPlatform::GetSoftwareVsyncRate()
2759 int preferenceRate
= gfxPrefs::LayoutFrameRate();
2760 if (preferenceRate
<= 0) {
2761 return gfxPlatform::GetDefaultFrameRate();
2763 return preferenceRate
;
2767 gfxPlatform::GetDefaultFrameRate()
2773 gfxPlatform::GetAzureBackendInfo(mozilla::widget::InfoObject
& aObj
)
2775 if (gfxConfig::IsEnabled(Feature::GPU_PROCESS
)) {
2776 aObj
.DefineProperty("AzureCanvasBackend (UI Process)", GetBackendName(mPreferredCanvasBackend
));
2777 aObj
.DefineProperty("AzureFallbackCanvasBackend (UI Process)", GetBackendName(mFallbackCanvasBackend
));
2778 aObj
.DefineProperty("AzureContentBackend (UI Process)", GetBackendName(mContentBackend
));
2780 // Assume content process' backend prefs.
2781 BackendPrefsData data
= GetBackendPrefs();
2782 BackendType canvasBackend
= GetCanvasBackendPref(data
.mCanvasBitmask
);
2783 if (canvasBackend
== BackendType::NONE
) {
2784 canvasBackend
= data
.mCanvasDefault
;
2786 BackendType contentBackend
= GetContentBackendPref(data
.mContentBitmask
);
2787 if (contentBackend
== BackendType::NONE
) {
2788 contentBackend
= data
.mContentDefault
;
2790 aObj
.DefineProperty("AzureCanvasBackend", GetBackendName(canvasBackend
));
2791 aObj
.DefineProperty("AzureContentBackend", GetBackendName(contentBackend
));
2793 aObj
.DefineProperty("AzureCanvasBackend", GetBackendName(mPreferredCanvasBackend
));
2794 aObj
.DefineProperty("AzureFallbackCanvasBackend", GetBackendName(mFallbackCanvasBackend
));
2795 aObj
.DefineProperty("AzureContentBackend", GetBackendName(mContentBackend
));
2798 aObj
.DefineProperty("AzureCanvasAccelerated", AllowOpenGLCanvas());
2802 gfxPlatform::GetApzSupportInfo(mozilla::widget::InfoObject
& aObj
)
2804 if (!gfxPlatform::AsyncPanZoomEnabled()) {
2808 if (SupportsApzWheelInput()) {
2809 aObj
.DefineProperty("ApzWheelInput", 1);
2812 if (SupportsApzTouchInput()) {
2813 aObj
.DefineProperty("ApzTouchInput", 1);
2816 if (SupportsApzDragInput()) {
2817 aObj
.DefineProperty("ApzDragInput", 1);
2820 if (SupportsApzKeyboardInput() && !gfxPrefs::AccessibilityBrowseWithCaret()) {
2821 aObj
.DefineProperty("ApzKeyboardInput", 1);
2824 if (SupportsApzAutoscrolling()) {
2825 aObj
.DefineProperty("ApzAutoscrollInput", 1);
2830 gfxPlatform::GetTilesSupportInfo(mozilla::widget::InfoObject
& aObj
)
2832 if (!gfxPrefs::LayersTilesEnabled()) {
2836 IntSize tileSize
= gfxVars::TileSize();
2837 aObj
.DefineProperty("TileHeight", tileSize
.height
);
2838 aObj
.DefineProperty("TileWidth", tileSize
.width
);
2842 gfxPlatform::AsyncPanZoomEnabled()
2844 #if !defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_WIDGET_UIKIT)
2845 // For XUL applications (everything but Firefox on Android)
2846 // we only want to use APZ when E10S is enabled. If
2847 // we ever get input events off the main thread we can consider relaxing
2848 // this requirement.
2849 if (!BrowserTabsRemoteAutostart()) {
2853 #ifdef MOZ_WIDGET_ANDROID
2856 if (!gfxPrefs::SingletonExists()) {
2857 // Make sure the gfxPrefs has been initialized before reading from it.
2858 MOZ_ASSERT(NS_IsMainThread());
2859 gfxPrefs::GetSingleton();
2861 return gfxPrefs::AsyncPanZoomEnabledDoNotUseDirectly();
2866 gfxPlatform::PerfWarnings()
2868 return gfxPrefs::PerfWarnings();
2872 gfxPlatform::GetAcceleratedCompositorBackends(nsTArray
<LayersBackend
>& aBackends
)
2874 if (gfxConfig::IsEnabled(Feature::OPENGL_COMPOSITING
)) {
2875 aBackends
.AppendElement(LayersBackend::LAYERS_OPENGL
);
2878 static int tell_me_once
= 0;
2879 if (!tell_me_once
) {
2880 NS_WARNING("OpenGL-accelerated layers are not supported on this system");
2883 #ifdef MOZ_WIDGET_ANDROID
2884 MOZ_CRASH("OpenGL-accelerated layers are a hard requirement on this platform. "
2885 "Cannot continue without support for them");
2891 gfxPlatform::GetCompositorBackends(bool useAcceleration
, nsTArray
<mozilla::layers::LayersBackend
>& aBackends
)
2893 if (useAcceleration
) {
2894 GetAcceleratedCompositorBackends(aBackends
);
2896 aBackends
.AppendElement(LayersBackend::LAYERS_BASIC
);
2900 gfxPlatform::NotifyCompositorCreated(LayersBackend aBackend
)
2902 if (mCompositorBackend
== aBackend
) {
2906 if (mCompositorBackend
!= LayersBackend::LAYERS_NONE
) {
2907 gfxCriticalNote
<< "Compositors might be mixed ("
2908 << int(mCompositorBackend
) << "," << int(aBackend
) << ")";
2911 // Set the backend before we notify so it's available immediately.
2912 mCompositorBackend
= aBackend
;
2914 // Notify that we created a compositor, so telemetry can update.
2915 NS_DispatchToMainThread(
2916 NS_NewRunnableFunction("gfxPlatform::NotifyCompositorCreated", [] {
2917 if (nsCOMPtr
<nsIObserverService
> obsvc
= services::GetObserverService()) {
2918 obsvc
->NotifyObservers(nullptr, "compositor:created", nullptr);
2924 gfxPlatform::NotifyGPUProcessDisabled()
2926 if (gfxConfig::IsEnabled(Feature::WEBRENDER
)) {
2927 gfxConfig::GetFeature(Feature::WEBRENDER
).ForceDisable(
2928 FeatureStatus::Unavailable
,
2929 "GPU Process is disabled",
2930 NS_LITERAL_CSTRING("FEATURE_FAILURE_GPU_PROCESS_DISABLED"));
2931 gfxVars::SetUseWebRender(false);
2936 gfxPlatform::FetchAndImportContentDeviceData()
2938 MOZ_ASSERT(XRE_IsContentProcess());
2940 if (gContentDeviceInitData
) {
2941 ImportContentDeviceData(*gContentDeviceInitData
);
2945 mozilla::dom::ContentChild
* cc
= mozilla::dom::ContentChild::GetSingleton();
2947 mozilla::gfx::ContentDeviceData data
;
2948 cc
->SendGetGraphicsDeviceInitData(&data
);
2950 ImportContentDeviceData(data
);
2954 gfxPlatform::ImportContentDeviceData(const mozilla::gfx::ContentDeviceData
& aData
)
2956 MOZ_ASSERT(XRE_IsContentProcess());
2958 const DevicePrefs
& prefs
= aData
.prefs();
2959 gfxConfig::Inherit(Feature::HW_COMPOSITING
, prefs
.hwCompositing());
2960 gfxConfig::Inherit(Feature::OPENGL_COMPOSITING
, prefs
.oglCompositing());
2964 gfxPlatform::BuildContentDeviceData(mozilla::gfx::ContentDeviceData
* aOut
)
2966 MOZ_ASSERT(XRE_IsParentProcess());
2968 // Make sure our settings are synchronized from the GPU process.
2969 GPUProcessManager::Get()->EnsureGPUReady();
2971 aOut
->prefs().hwCompositing() = gfxConfig::GetValue(Feature::HW_COMPOSITING
);
2972 aOut
->prefs().oglCompositing() = gfxConfig::GetValue(Feature::OPENGL_COMPOSITING
);
2976 gfxPlatform::ImportGPUDeviceData(const mozilla::gfx::GPUDeviceData
& aData
)
2978 MOZ_ASSERT(XRE_IsParentProcess());
2980 gfxConfig::ImportChange(Feature::OPENGL_COMPOSITING
, aData
.oglCompositing());
2981 gfxConfig::ImportChange(Feature::ADVANCED_LAYERS
, aData
.advancedLayers());
2985 gfxPlatform::SupportsApzTouchInput() const
2987 return dom::TouchEvent::PrefEnabled(nullptr);
2991 gfxPlatform::SupportsApzDragInput() const
2993 return gfxPrefs::APZDragEnabled();
2997 gfxPlatform::SupportsApzKeyboardInput() const
2999 return gfxPrefs::APZKeyboardEnabled();
3003 gfxPlatform::SupportsApzAutoscrolling() const
3005 return gfxPrefs::APZAutoscrollEnabled();
3009 gfxPlatform::InitOpenGLConfig()
3012 // Don't enable by default on Windows, since it could show up in about:support even
3013 // though it'll never get used. Only attempt if user enables the pref
3014 if (!Preferences::GetBool("layers.prefer-opengl")){
3019 FeatureState
& openGLFeature
= gfxConfig::GetFeature(Feature::OPENGL_COMPOSITING
);
3021 // Check to see hw comp supported
3022 if (!gfxConfig::IsEnabled(Feature::HW_COMPOSITING
)) {
3023 openGLFeature
.DisableByDefault(FeatureStatus::Unavailable
, "Hardware compositing is disabled",
3024 NS_LITERAL_CSTRING("FEATURE_FAILURE_OPENGL_NEED_HWCOMP"));
3029 openGLFeature
.SetDefaultFromPref(
3030 gfxPrefs::GetLayersPreferOpenGLPrefName(),
3032 gfxPrefs::GetLayersPreferOpenGLPrefDefault());
3034 openGLFeature
.EnableByDefault();
3037 // When layers acceleration is force-enabled, enable it even for blacklisted
3039 if (gfxPrefs::LayersAccelerationForceEnabledDoNotUseDirectly()) {
3040 openGLFeature
.UserForceEnable("Force-enabled by pref");
3045 nsCString failureId
;
3046 if (!IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_OPENGL_LAYERS
, &message
, failureId
)) {
3047 openGLFeature
.Disable(FeatureStatus::Blacklisted
, message
.get(), failureId
);
3052 gfxPlatform::IsGfxInfoStatusOkay(int32_t aFeature
, nsCString
* aOutMessage
, nsCString
& aFailureId
)
3054 nsCOMPtr
<nsIGfxInfo
> gfxInfo
= services::GetGfxInfo();
3060 if (NS_SUCCEEDED(gfxInfo
->GetFeatureStatus(aFeature
, aFailureId
, &status
)) &&
3061 status
!= nsIGfxInfo::FEATURE_STATUS_OK
)
3063 aOutMessage
->AssignLiteral("#BLOCKLIST_");
3064 aOutMessage
->AppendASCII(aFailureId
.get());