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/FontPropertyTypes.h"
7 #include "mozilla/RDDProcessManager.h"
8 #include "mozilla/image/ImageMemoryReporter.h"
9 #include "mozilla/layers/CompositorManagerChild.h"
10 #include "mozilla/layers/CompositorThread.h"
11 #include "mozilla/layers/ImageBridgeChild.h"
12 #include "mozilla/layers/ISurfaceAllocator.h" // for GfxMemoryImageReporter
13 #include "mozilla/layers/CompositorBridgeChild.h"
14 #include "mozilla/layers/RemoteTextureMap.h"
15 #include "mozilla/webrender/RenderThread.h"
16 #include "mozilla/webrender/WebRenderAPI.h"
17 #include "mozilla/webrender/webrender_ffi.h"
18 #include "mozilla/gfx/BuildConstants.h"
19 #include "mozilla/gfx/gfxConfigManager.h"
20 #include "mozilla/gfx/gfxVars.h"
21 #include "mozilla/gfx/GPUProcessManager.h"
22 #include "mozilla/gfx/GraphicsMessages.h"
23 #include "mozilla/gfx/CanvasManagerChild.h"
24 #include "mozilla/gfx/CanvasManagerParent.h"
25 #include "mozilla/ClearOnShutdown.h"
26 #include "mozilla/EnumTypeTraits.h"
27 #include "mozilla/StaticPrefs_accessibility.h"
28 #include "mozilla/StaticPrefs_apz.h"
29 #include "mozilla/StaticPrefs_bidi.h"
30 #include "mozilla/StaticPrefs_canvas.h"
31 #include "mozilla/StaticPrefs_gfx.h"
32 #include "mozilla/StaticPrefs_layout.h"
33 #include "mozilla/StaticPrefs_layers.h"
34 #include "mozilla/StaticPrefs_media.h"
35 #include "mozilla/StaticPrefs_privacy.h"
36 #include "mozilla/StaticPrefs_webgl.h"
37 #include "mozilla/StaticPrefs_widget.h"
38 #include "mozilla/Telemetry.h"
39 #include "mozilla/TimeStamp.h"
40 #include "mozilla/Unused.h"
41 #include "mozilla/IntegerPrintfMacros.h"
42 #include "mozilla/Base64.h"
43 #include "mozilla/VsyncDispatcher.h"
45 #include "mozilla/Logging.h"
46 #include "mozilla/Components.h"
47 #include "nsAppRunner.h"
48 #include "nsAppDirectoryServiceDefs.h"
49 #include "nsCSSProps.h"
51 #include "gfxCrashReporterUtils.h"
52 #include "gfxPlatform.h"
56 #include "gfxTextRun.h"
57 #include "gfxUserFontSet.h"
58 #include "gfxConfig.h"
59 #include "GfxDriverInfo.h"
60 #include "VRProcessManager.h"
65 # define getpid _getpid
70 #include "nsXULAppAPI.h"
71 #include "nsIXULAppInfo.h"
72 #include "nsDirectoryServiceUtils.h"
73 #include "nsDirectoryServiceDefs.h"
76 # include "gfxWindowsPlatform.h"
77 # include "mozilla/widget/WinWindowOcclusionTracker.h"
78 #elif defined(XP_MACOSX)
79 # include "gfxPlatformMac.h"
80 # include "gfxQuartzSurface.h"
81 # include "nsCocoaFeatures.h"
82 #elif defined(MOZ_WIDGET_GTK)
83 # include "gfxPlatformGtk.h"
84 #elif defined(ANDROID)
85 # include "gfxAndroidPlatform.h"
87 #if defined(MOZ_WIDGET_ANDROID)
88 # include "mozilla/jni/Utils.h" // for IsFennec
92 # include "mozilla/WindowsVersion.h"
93 # include "WinUtils.h"
96 #include "nsGkAtoms.h"
97 #include "gfxPlatformFontList.h"
98 #include "gfxContext.h"
99 #include "gfxImageSurface.h"
100 #include "nsUnicodeProperties.h"
101 #include "harfbuzz/hb.h"
102 #include "gfxGraphiteShaper.h"
103 #include "gfx2DGlue.h"
104 #include "gfxGradientCache.h"
105 #include "gfxUtils.h" // for NextPowerOfTwo
106 #include "gfxFontMissingGlyphs.h"
108 #include "nsExceptionHandler.h"
109 #include "nsServiceManagerUtils.h"
110 #include "nsTArray.h"
111 #include "nsIObserverService.h"
112 #include "mozilla/widget/Screen.h"
113 #include "mozilla/widget/ScreenManager.h"
114 #include "MainThreadUtils.h"
116 #include "nsWeakReference.h"
121 #include "imgITools.h"
125 #include "GLContext.h"
126 #include "GLContextProvider.h"
127 #include "mozilla/gfx/Logging.h"
130 # pragma GCC diagnostic push
131 # pragma GCC diagnostic ignored "-Wshadow"
133 #include "skia/include/core/SkGraphics.h"
134 #ifdef MOZ_ENABLE_FREETYPE
135 # include "skia/include/ports/SkTypeface_cairo.h"
137 #include "mozilla/gfx/SkMemoryReporter.h"
139 # pragma GCC diagnostic pop // -Wshadow
141 static const uint32_t kDefaultGlyphCacheSize
= -1;
143 #include "mozilla/Preferences.h"
144 #include "mozilla/Assertions.h"
145 #include "mozilla/Atomics.h"
146 #include "mozilla/Attributes.h"
147 #include "mozilla/Mutex.h"
149 #include "nsAlgorithm.h"
150 #include "nsIGfxInfo.h"
151 #include "nsIXULRuntime.h"
152 #include "VsyncSource.h"
153 #include "SoftwareVsyncSource.h"
154 #include "nscore.h" // for NS_FREE_PERMANENT_DATA
155 #include "mozilla/dom/ContentChild.h"
156 #include "mozilla/dom/ContentParent.h"
157 #include "mozilla/dom/TouchEvent.h"
159 #include "VRManager.h"
160 #include "VRManagerChild.h"
161 #include "mozilla/gfx/GPUParent.h"
162 #include "prsystem.h"
164 #include "mozilla/gfx/2D.h"
165 #include "mozilla/gfx/SourceSurfaceCairo.h"
167 using namespace mozilla
;
168 using namespace mozilla::layers
;
169 using namespace mozilla::gl
;
170 using namespace mozilla::gfx
;
172 gfxPlatform
* gPlatform
= nullptr;
173 static bool gEverInitialized
= false;
175 const ContentDeviceData
* gContentDeviceInitData
= nullptr;
177 Atomic
<bool, MemoryOrdering::ReleaseAcquire
> gfxPlatform::gCMSInitialized
;
178 CMSMode
gfxPlatform::gCMSMode
= CMSMode::Off
;
180 // These two may point to the same profile
181 qcms_profile
* gfxPlatform::gCMSOutputProfile
= nullptr;
182 qcms_profile
* gfxPlatform::gCMSsRGBProfile
= nullptr;
184 qcms_transform
* gfxPlatform::gCMSRGBTransform
= nullptr;
185 qcms_transform
* gfxPlatform::gCMSInverseRGBTransform
= nullptr;
186 qcms_transform
* gfxPlatform::gCMSRGBATransform
= nullptr;
187 qcms_transform
* gfxPlatform::gCMSBGRATransform
= nullptr;
189 /// This override of the LogForwarder, initially used for the critical graphics
190 /// errors, is sending the log to the crash annotations as well, but only
191 /// if the capacity set with the method below is >= 2. We always retain the
192 /// very first critical message, and the latest capacity-1 messages are
193 /// rotated through. Note that we don't expect the total number of times
194 /// this gets called to be large - it is meant for critical errors only.
196 class CrashStatsLogForwarder
: public mozilla::gfx::LogForwarder
{
198 explicit CrashStatsLogForwarder(CrashReporter::Annotation 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 CrashReporter::Annotation mCrashCriticalKey
;
214 uint32_t mMaxCapacity
;
216 Mutex mMutex MOZ_UNANNOTATED
;
219 CrashStatsLogForwarder::CrashStatsLogForwarder(CrashReporter::Annotation aKey
)
221 mCrashCriticalKey(aKey
),
224 mMutex("CrashStatsLogForwarder") {}
226 void CrashStatsLogForwarder::SetCircularBufferSize(uint32_t aCapacity
) {
227 MutexAutoLock
lock(mMutex
);
229 mMaxCapacity
= aCapacity
;
230 mBuffer
.reserve(static_cast<size_t>(aCapacity
));
233 LoggingRecord
CrashStatsLogForwarder::LoggingRecordCopy() {
234 MutexAutoLock
lock(mMutex
);
238 bool CrashStatsLogForwarder::UpdateStringsVector(const std::string
& aString
) {
239 // We want at least the first one and the last one. Otherwise, no point.
240 if (mMaxCapacity
< 2) {
245 MOZ_ASSERT(mIndex
>= 0);
247 // index will count 0, 1, 2, ..., max-1, 1, 2, ..., max-1, 1, 2, ...
248 int32_t index
= mIndex
? (mIndex
- 1) % (mMaxCapacity
- 1) + 1 : 0;
249 MOZ_ASSERT(index
>= 0 && index
< (int32_t)mMaxCapacity
);
250 MOZ_ASSERT(index
<= mIndex
&& index
<= (int32_t)mBuffer
.size());
252 double tStamp
= (TimeStamp::NowLoRes() - TimeStamp::ProcessCreation())
253 .ToSecondsSigDigits();
255 // Checking for index >= mBuffer.size(), rather than index == mBuffer.size()
256 // just out of paranoia, but we know index <= mBuffer.size().
257 LoggingRecordEntry
newEntry(mIndex
, aString
, tStamp
);
258 if (index
>= static_cast<int32_t>(mBuffer
.size())) {
259 mBuffer
.push_back(newEntry
);
261 mBuffer
[index
] = newEntry
;
266 void CrashStatsLogForwarder::UpdateCrashReport() {
267 std::stringstream message
;
268 std::string logAnnotation
;
270 switch (XRE_GetProcessType()) {
271 case GeckoProcessType_Default
:
272 logAnnotation
= "|[";
274 case GeckoProcessType_Content
:
275 logAnnotation
= "|[C";
277 case GeckoProcessType_GPU
:
278 logAnnotation
= "|[G";
281 logAnnotation
= "|[X";
285 for (auto& it
: mBuffer
) {
286 message
<< logAnnotation
<< Get
<0>(it
) << "]" << Get
<1>(it
)
287 << " (t=" << Get
<2>(it
) << ") ";
290 nsCString
reportString(message
.str().c_str());
292 CrashReporter::AnnotateCrashReport(mCrashCriticalKey
, reportString
);
294 if (annotated
!= NS_OK
) {
295 printf("Crash Annotation %s: %s",
296 CrashReporter::AnnotationToString(mCrashCriticalKey
),
297 message
.str().c_str());
301 class LogForwarderEvent
: public Runnable
{
302 virtual ~LogForwarderEvent() = default;
305 NS_INLINE_DECL_REFCOUNTING_INHERITED(LogForwarderEvent
, Runnable
)
307 explicit LogForwarderEvent(const nsCString
& aMessage
)
308 : mozilla::Runnable("LogForwarderEvent"), mMessage(aMessage
) {}
310 NS_IMETHOD
Run() override
{
311 MOZ_ASSERT(NS_IsMainThread() &&
312 (XRE_IsContentProcess() || XRE_IsGPUProcess()));
314 if (XRE_IsContentProcess()) {
315 dom::ContentChild
* cc
= dom::ContentChild::GetSingleton();
316 Unused
<< cc
->SendGraphicsError(mMessage
);
317 } else if (XRE_IsGPUProcess()) {
318 GPUParent
* gp
= GPUParent::GetSingleton();
319 Unused
<< gp
->SendGraphicsError(mMessage
);
329 void CrashStatsLogForwarder::Log(const std::string
& aString
) {
330 MutexAutoLock
lock(mMutex
);
332 if (UpdateStringsVector(aString
)) {
336 // Add it to the parent strings
337 if (!XRE_IsParentProcess()) {
338 nsCString
stringToSend(aString
.c_str());
339 if (NS_IsMainThread()) {
340 if (XRE_IsContentProcess()) {
341 dom::ContentChild
* cc
= dom::ContentChild::GetSingleton();
342 Unused
<< cc
->SendGraphicsError(stringToSend
);
343 } else if (XRE_IsGPUProcess()) {
344 GPUParent
* gp
= GPUParent::GetSingleton();
345 Unused
<< gp
->SendGraphicsError(stringToSend
);
348 nsCOMPtr
<nsIRunnable
> r1
= new LogForwarderEvent(stringToSend
);
349 NS_DispatchToMainThread(r1
);
354 class CrashTelemetryEvent
: public Runnable
{
355 virtual ~CrashTelemetryEvent() = default;
358 NS_INLINE_DECL_REFCOUNTING_INHERITED(CrashTelemetryEvent
, Runnable
)
360 explicit CrashTelemetryEvent(uint32_t aReason
)
361 : mozilla::Runnable("CrashTelemetryEvent"), mReason(aReason
) {}
363 NS_IMETHOD
Run() override
{
364 MOZ_ASSERT(NS_IsMainThread());
365 Telemetry::Accumulate(Telemetry::GFX_CRASH
, mReason
);
373 void CrashStatsLogForwarder::CrashAction(LogReason aReason
) {
374 #ifndef RELEASE_OR_BETA
375 // Non-release builds crash by default, but will use telemetry
376 // if this environment variable is present.
377 static bool useTelemetry
= gfxEnv::GfxDevCrashTelemetry();
379 // Release builds use telemetry by default, but will crash instead
380 // if this environment variable is present.
381 static bool useTelemetry
= !gfxEnv::GfxDevCrashMozCrash();
385 // The callers need to assure that aReason is in the range
386 // that the telemetry call below supports.
387 if (NS_IsMainThread()) {
388 Telemetry::Accumulate(Telemetry::GFX_CRASH
, (uint32_t)aReason
);
390 nsCOMPtr
<nsIRunnable
> r1
= new CrashTelemetryEvent((uint32_t)aReason
);
391 NS_DispatchToMainThread(r1
);
394 // ignoring aReason, we can get the information we need from the stack
395 MOZ_CRASH("GFX_CRASH");
399 #define GFX_DOWNLOADABLE_FONTS_ENABLED "gfx.downloadable_fonts.enabled"
401 #define GFX_PREF_FALLBACK_USE_CMAPS \
402 "gfx.font_rendering.fallback.always_use_cmaps"
404 #define GFX_PREF_OPENTYPE_SVG "gfx.font_rendering.opentype_svg.enabled"
406 #define GFX_PREF_WORD_CACHE_CHARLIMIT "gfx.font_rendering.wordcache.charlimit"
407 #define GFX_PREF_WORD_CACHE_MAXENTRIES "gfx.font_rendering.wordcache.maxentries"
409 #define GFX_PREF_GRAPHITE_SHAPING "gfx.font_rendering.graphite.enabled"
410 #if defined(XP_MACOSX)
411 # define GFX_PREF_CORETEXT_SHAPING "gfx.font_rendering.coretext.enabled"
414 #define FONT_VARIATIONS_PREF "layout.css.font-variations.enabled"
416 static const char* kObservedPrefs
[] = {"gfx.downloadable_fonts.",
417 "gfx.font_rendering.", nullptr};
419 static void FontPrefChanged(const char* aPref
, void* aData
) {
421 NS_ASSERTION(gfxPlatform::GetPlatform(), "the singleton instance has gone");
422 gfxPlatform::GetPlatform()->FontsPrefsChanged(aPref
);
425 void gfxPlatform::OnMemoryPressure(layers::MemoryPressureReason aWhy
) {
426 Factory::PurgeAllCaches();
427 gfxGradientCache::PurgeAllCaches();
428 gfxFontMissingGlyphs::Purge();
429 PurgeSkiaFontCache();
430 if (XRE_IsParentProcess()) {
431 layers::CompositorManagerChild
* manager
=
432 CompositorManagerChild::GetInstance();
434 manager
->SendNotifyMemoryPressure();
439 gfxPlatform::gfxPlatform()
440 : mHasVariationFontSupport(false),
441 mAzureCanvasBackendCollector(this, &gfxPlatform::GetAzureBackendInfo
),
442 mApzSupportCollector(this, &gfxPlatform::GetApzSupportInfo
),
443 mFrameStatsCollector(this, &gfxPlatform::GetFrameStats
),
444 mCMSInfoCollector(this, &gfxPlatform::GetCMSSupportInfo
),
445 mDisplayInfoCollector(this, &gfxPlatform::GetDisplayInfo
),
446 mOverlayInfoCollector(this, &gfxPlatform::GetOverlayInfo
),
447 mCompositorBackend(layers::LayersBackend::LAYERS_NONE
),
449 mAllowDownloadableFonts
= UNINITIALIZED_VALUE
;
451 InitBackendPrefs(GetBackendPrefs());
452 VRManager::ManagerInit();
455 gfxPlatform
* gfxPlatform::GetPlatform() {
457 MOZ_RELEASE_ASSERT(!XRE_IsContentProcess(),
458 "Content Process should have called InitChild() before "
459 "first GetPlatform()");
465 bool gfxPlatform::Initialized() { return !!gPlatform
; }
468 void gfxPlatform::InitChild(const ContentDeviceData
& aData
) {
469 MOZ_ASSERT(XRE_IsContentProcess());
470 MOZ_RELEASE_ASSERT(!gPlatform
,
471 "InitChild() should be called before first GetPlatform()");
472 // Make the provided initial ContentDeviceData available to the init
473 // routines, so they don't have to do a sync request from the parent.
474 gContentDeviceInitData
= &aData
;
476 gContentDeviceInitData
= nullptr;
479 #define WR_DEBUG_PREF "gfx.webrender.debug"
481 static void SwapIntervalPrefChangeCallback(const char* aPrefName
, void*) {
482 bool egl
= Preferences::GetBool("gfx.swap-interval.egl", false);
483 bool glx
= Preferences::GetBool("gfx.swap-interval.glx", false);
484 gfxVars::SetSwapIntervalEGL(egl
);
485 gfxVars::SetSwapIntervalGLX(glx
);
488 static void WebRendeProfilerUIPrefChangeCallback(const char* aPrefName
, void*) {
490 if (NS_SUCCEEDED(Preferences::GetCString("gfx.webrender.debug.profiler-ui",
492 gfxVars::SetWebRenderProfilerUI(uiString
);
496 // List of boolean dynamic parameter for WebRender.
498 // The parameters in this list are:
500 // - The BoolParameter enum variant (see webrender_api/src/lib.rs)
501 // - A default value.
502 #define WR_BOOL_PARAMETER_LIST(_) \
503 _("gfx.webrender.batched-texture-uploads", \
504 wr::BoolParameter::BatchedUploads, true) \
505 _("gfx.webrender.draw-calls-for-texture-copy", \
506 wr::BoolParameter::DrawCallsForTextureCopy, true) \
507 _("gfx.webrender.pbo-uploads", wr::BoolParameter::PboUploads, true) \
508 _("gfx.webrender.multithreading", wr::BoolParameter::Multithreading, true)
510 static void WebRenderBoolParameterChangeCallback(const char*, void*) {
513 #define WR_BOOL_PARAMETER(name, key, default_val) \
514 if (Preferences::GetBool(name, default_val)) { \
515 bits |= 1 << (uint32_t)key; \
518 WR_BOOL_PARAMETER_LIST(WR_BOOL_PARAMETER
)
519 #undef WR_BOOL_PARAMETER
521 gfx::gfxVars::SetWebRenderBoolParameters(bits
);
524 static void RegisterWebRenderBoolParamCallback() {
525 #define WR_BOOL_PARAMETER(name, _key, _default_val) \
526 Preferences::RegisterCallback(WebRenderBoolParameterChangeCallback, name);
528 WR_BOOL_PARAMETER_LIST(WR_BOOL_PARAMETER
)
529 #undef WR_BOOL_PARAMETER
531 WebRenderBoolParameterChangeCallback(nullptr, nullptr);
534 static void WebRenderDebugPrefChangeCallback(const char* aPrefName
, void*) {
535 wr::DebugFlags flags
{0};
536 #define GFX_WEBRENDER_DEBUG(suffix, bit) \
537 if (Preferences::GetBool(WR_DEBUG_PREF suffix, false)) { \
541 GFX_WEBRENDER_DEBUG(".profiler", wr::DebugFlags::PROFILER_DBG
)
542 GFX_WEBRENDER_DEBUG(".render-targets", wr::DebugFlags::RENDER_TARGET_DBG
)
543 GFX_WEBRENDER_DEBUG(".texture-cache", wr::DebugFlags::TEXTURE_CACHE_DBG
)
544 GFX_WEBRENDER_DEBUG(".gpu-time-queries", wr::DebugFlags::GPU_TIME_QUERIES
)
545 GFX_WEBRENDER_DEBUG(".gpu-sample-queries", wr::DebugFlags::GPU_SAMPLE_QUERIES
)
546 GFX_WEBRENDER_DEBUG(".disable-batching", wr::DebugFlags::DISABLE_BATCHING
)
547 GFX_WEBRENDER_DEBUG(".epochs", wr::DebugFlags::EPOCHS
)
548 GFX_WEBRENDER_DEBUG(".smart-profiler", wr::DebugFlags::SMART_PROFILER
)
549 GFX_WEBRENDER_DEBUG(".echo-driver-messages",
550 wr::DebugFlags::ECHO_DRIVER_MESSAGES
)
551 GFX_WEBRENDER_DEBUG(".show-overdraw", wr::DebugFlags::SHOW_OVERDRAW
)
552 GFX_WEBRENDER_DEBUG(".gpu-cache", wr::DebugFlags::GPU_CACHE_DBG
)
553 GFX_WEBRENDER_DEBUG(".texture-cache.clear-evicted",
554 wr::DebugFlags::TEXTURE_CACHE_DBG_CLEAR_EVICTED
)
555 GFX_WEBRENDER_DEBUG(".picture-caching", wr::DebugFlags::PICTURE_CACHING_DBG
)
556 GFX_WEBRENDER_DEBUG(".force-picture-invalidation",
557 wr::DebugFlags::FORCE_PICTURE_INVALIDATION
)
558 GFX_WEBRENDER_DEBUG(".primitives", wr::DebugFlags::PRIMITIVE_DBG
)
559 // Bit 18 is for the zoom display, which requires the mouse position and thus
560 // currently only works in wrench.
561 GFX_WEBRENDER_DEBUG(".small-screen", wr::DebugFlags::SMALL_SCREEN
)
562 GFX_WEBRENDER_DEBUG(".disable-opaque-pass",
563 wr::DebugFlags::DISABLE_OPAQUE_PASS
)
564 GFX_WEBRENDER_DEBUG(".disable-alpha-pass", wr::DebugFlags::DISABLE_ALPHA_PASS
)
565 GFX_WEBRENDER_DEBUG(".disable-clip-masks", wr::DebugFlags::DISABLE_CLIP_MASKS
)
566 GFX_WEBRENDER_DEBUG(".disable-text-prims", wr::DebugFlags::DISABLE_TEXT_PRIMS
)
567 GFX_WEBRENDER_DEBUG(".disable-gradient-prims",
568 wr::DebugFlags::DISABLE_GRADIENT_PRIMS
)
569 GFX_WEBRENDER_DEBUG(".obscure-images", wr::DebugFlags::OBSCURE_IMAGES
)
570 GFX_WEBRENDER_DEBUG(".glyph-flashing", wr::DebugFlags::GLYPH_FLASHING
)
571 GFX_WEBRENDER_DEBUG(".capture-profiler", wr::DebugFlags::PROFILER_CAPTURE
)
572 GFX_WEBRENDER_DEBUG(".window-visibility",
573 wr::DebugFlags::WINDOW_VISIBILITY_DBG
)
574 #undef GFX_WEBRENDER_DEBUG
576 gfx::gfxVars::SetWebRenderDebugFlags(flags
.bits
);
579 static void WebRenderQualityPrefChangeCallback(const char* aPref
, void*) {
580 gfxPlatform::GetPlatform()->UpdateForceSubpixelAAWherePossible();
583 static void WebRenderBatchingPrefChangeCallback(const char* aPrefName
, void*) {
584 uint32_t count
= Preferences::GetUint(
585 StaticPrefs::GetPrefName_gfx_webrender_batching_lookback(), 10);
587 gfx::gfxVars::SetWebRenderBatchingLookback(count
);
590 static void WebRenderBlobTileSizePrefChangeCallback(const char* aPrefName
,
592 uint32_t tileSize
= Preferences::GetUint(
593 StaticPrefs::GetPrefName_gfx_webrender_blob_tile_size(), 256);
594 gfx::gfxVars::SetWebRenderBlobTileSize(tileSize
);
597 static void WebRenderUploadThresholdPrefChangeCallback(const char* aPrefName
,
599 int value
= Preferences::GetInt(
600 StaticPrefs::GetPrefName_gfx_webrender_batched_upload_threshold(),
603 gfxVars::SetWebRenderBatchedUploadThreshold(value
);
606 static uint32_t GetSkiaGlyphCacheSize() {
607 // Only increase font cache size on non-android to save memory.
608 #if !defined(MOZ_WIDGET_ANDROID)
609 // 10mb as the default pref cache size on desktop due to talos perf tweaking.
610 // Chromium uses 20mb and skia default uses 2mb.
611 // We don't need to change the font cache count since we usually
612 // cache thrash due to asian character sets in talos.
613 // Only increase memory on the content process
615 StaticPrefs::gfx_content_skia_font_cache_size_AtStartup() * 1024 * 1024;
616 if (mozilla::BrowserTabsRemoteAutostart()) {
617 return XRE_IsContentProcess() ? cacheSize
: kDefaultGlyphCacheSize
;
622 return kDefaultGlyphCacheSize
;
623 #endif // MOZ_WIDGET_ANDROID
626 class WebRenderMemoryReporter final
: public nsIMemoryReporter
{
629 NS_DECL_NSIMEMORYREPORTER
632 ~WebRenderMemoryReporter() = default;
635 // Memory reporter for WebRender.
637 // The reporting within WebRender is manual and incomplete. We could do a much
638 // more thorough job by depending on the malloc_size_of crate, but integrating
639 // that into WebRender is tricky [1].
641 // So the idea is to start with manual reporting for the large allocations
642 // detected by DMD, and see how much that can cover in practice (which may
643 // require a few rounds of iteration). If that approach turns out to be
644 // fundamentally insufficient, we can either duplicate more of the
645 // malloc_size_of functionality in WebRender, or deal with the complexity of a
646 // gecko-only crate dependency.
648 // [1] See https://bugzilla.mozilla.org/show_bug.cgi?id=1480293#c1
649 struct WebRenderMemoryReporterHelper
{
650 WebRenderMemoryReporterHelper(nsIHandleReportCallback
* aCallback
,
652 : mCallback(aCallback
), mData(aData
) {}
653 nsCOMPtr
<nsIHandleReportCallback
> mCallback
;
654 nsCOMPtr
<nsISupports
> mData
;
656 void Report(size_t aBytes
, const char* aName
) const {
657 nsPrintfCString
path("explicit/gfx/webrender/%s", aName
);
658 nsCString
desc("CPU heap memory used by WebRender"_ns
);
659 ReportInternal(aBytes
, path
, desc
, nsIMemoryReporter::KIND_HEAP
);
662 void ReportTexture(size_t aBytes
, const char* aName
) const {
663 nsPrintfCString
path("gfx/webrender/textures/%s", aName
);
664 nsCString
desc("GPU texture memory used by WebRender"_ns
);
665 ReportInternal(aBytes
, path
, desc
, nsIMemoryReporter::KIND_OTHER
);
668 void ReportTotalGPUBytes(size_t aBytes
) const {
669 nsCString
path("gfx/webrender/total-gpu-bytes"_ns
);
670 nsCString
desc(nsLiteralCString(
671 "Total GPU bytes used by WebRender (should match textures/ sum)"));
672 ReportInternal(aBytes
, path
, desc
, nsIMemoryReporter::KIND_OTHER
);
675 void ReportInternal(size_t aBytes
, nsACString
& aPath
, nsACString
& aDesc
,
676 int32_t aKind
) const {
677 // Generally, memory reporters pass the empty string as the process name to
678 // indicate "current process". However, if we're using a GPU process, the
679 // measurements will actually take place in that process, and it's easier to
680 // just note that here rather than trying to invoke the memory reporter in
682 nsAutoCString processName
;
683 if (gfxConfig::IsEnabled(Feature::GPU_PROCESS
)) {
684 GPUParent::GetGPUProcessName(processName
);
687 mCallback
->Callback(processName
, aPath
, aKind
,
688 nsIMemoryReporter::UNITS_BYTES
, aBytes
, aDesc
, mData
);
692 static void FinishAsyncMemoryReport() {
693 nsCOMPtr
<nsIMemoryReporterManager
> imgr
=
694 do_GetService("@mozilla.org/memory-reporter-manager;1");
701 // (For some reason, clang-format gets the second macro right, but totally mangles the first).
702 #define REPORT_INTERNER(id) \
703 helper.Report(aReport.interning.interners.id, \
704 "interning/" #id "/interners");
707 #define REPORT_DATA_STORE(id) \
708 helper.Report(aReport.interning.data_stores.id, \
709 "interning/" #id "/data-stores");
711 NS_IMPL_ISUPPORTS(WebRenderMemoryReporter
, nsIMemoryReporter
)
714 WebRenderMemoryReporter::CollectReports(nsIHandleReportCallback
* aHandleReport
,
715 nsISupports
* aData
, bool aAnonymize
) {
716 MOZ_ASSERT(XRE_IsParentProcess());
717 MOZ_ASSERT(NS_IsMainThread());
718 layers::CompositorManagerChild
* manager
=
719 CompositorManagerChild::GetInstance();
721 FinishAsyncMemoryReport();
725 WebRenderMemoryReporterHelper
helper(aHandleReport
, aData
);
726 manager
->SendReportMemory(
727 [=](wr::MemoryReport aReport
) {
729 helper
.Report(aReport
.clip_stores
, "clip-stores");
730 helper
.Report(aReport
.gpu_cache_metadata
, "gpu-cache/metadata");
731 helper
.Report(aReport
.gpu_cache_cpu_mirror
, "gpu-cache/cpu-mirror");
732 helper
.Report(aReport
.render_tasks
, "render-tasks");
733 helper
.Report(aReport
.hit_testers
, "hit-testers");
734 helper
.Report(aReport
.fonts
, "resource-cache/fonts");
735 helper
.Report(aReport
.weak_fonts
, "resource-cache/weak-fonts");
736 helper
.Report(aReport
.images
, "resource-cache/images");
737 helper
.Report(aReport
.rasterized_blobs
,
738 "resource-cache/rasterized-blobs");
739 helper
.Report(aReport
.texture_cache_structures
,
740 "texture-cache/structures");
741 helper
.Report(aReport
.shader_cache
, "shader-cache");
742 helper
.Report(aReport
.display_list
, "display-list");
743 helper
.Report(aReport
.swgl
, "swgl");
744 helper
.Report(aReport
.upload_staging_memory
, "upload-stagin-memory");
746 WEBRENDER_FOR_EACH_INTERNER(REPORT_INTERNER
);
747 WEBRENDER_FOR_EACH_INTERNER(REPORT_DATA_STORE
);
750 helper
.ReportTexture(aReport
.gpu_cache_textures
, "gpu-cache");
751 helper
.ReportTexture(aReport
.vertex_data_textures
, "vertex-data");
752 helper
.ReportTexture(aReport
.render_target_textures
, "render-targets");
753 helper
.ReportTexture(aReport
.depth_target_textures
, "depth-targets");
754 helper
.ReportTexture(aReport
.picture_tile_textures
, "picture-tiles");
755 helper
.ReportTexture(aReport
.atlas_textures
, "texture-cache/atlas");
756 helper
.ReportTexture(aReport
.standalone_textures
,
757 "texture-cache/standalone");
758 helper
.ReportTexture(aReport
.texture_upload_pbos
,
759 "texture-upload-pbos");
760 helper
.ReportTexture(aReport
.swap_chain
, "swap-chains");
761 helper
.ReportTexture(aReport
.render_texture_hosts
,
762 "render-texture-hosts");
763 helper
.ReportTexture(aReport
.upload_staging_textures
,
764 "upload-staging-textures");
766 FinishAsyncMemoryReport();
768 [](mozilla::ipc::ResponseRejectReason
&& aReason
) {
769 FinishAsyncMemoryReport();
775 #undef REPORT_INTERNER
776 #undef REPORT_DATA_STORE
778 void gfxPlatform::Init() {
779 MOZ_RELEASE_ASSERT(!XRE_IsGPUProcess(), "GFX: Not allowed in GPU process.");
780 MOZ_RELEASE_ASSERT(!XRE_IsRDDProcess(), "GFX: Not allowed in RDD process.");
781 MOZ_RELEASE_ASSERT(NS_IsMainThread(), "GFX: Not in main thread.");
783 if (gEverInitialized
) {
784 MOZ_CRASH("Already started???");
786 gEverInitialized
= true;
788 gfxVars::Initialize();
792 if (XRE_IsParentProcess()) {
793 GPUProcessManager::Initialize();
794 RDDProcessManager::Initialize();
796 nsCOMPtr
<nsIFile
> file
;
797 nsresult rv
= NS_GetSpecialDirectory(NS_GRE_DIR
, getter_AddRefs(file
));
799 gfxVars::SetGREDirectory(nsString());
803 gfxVars::SetGREDirectory(nsString(path
));
807 if (XRE_IsParentProcess()) {
808 nsCOMPtr
<nsIFile
> profDir
;
809 nsresult rv
= NS_GetSpecialDirectory(NS_APP_PROFILE_DIR_STARTUP
,
810 getter_AddRefs(profDir
));
812 gfxVars::SetProfDirectory(nsString());
815 profDir
->GetPath(path
);
816 gfxVars::SetProfDirectory(nsString(path
));
820 Preferences::GetCString("layers.windowrecording.path", path
);
821 gfxVars::SetLayersWindowRecordingPath(path
);
824 gfxVars::SetFxREmbedded(true);
828 // Drop a note in the crash report if we end up forcing an option that could
829 // destabilize things. New items should be appended at the end (of an
830 // existing or in a new section), so that we don't have to know the version to
831 // interpret these cryptic strings.
833 nsAutoCString forcedPrefs
;
835 forcedPrefs
.AppendPrintf(
836 "FP(D%d%d", StaticPrefs::gfx_direct2d_disabled_AtStartup(),
837 StaticPrefs::gfx_direct2d_force_enabled_AtStartup());
839 forcedPrefs
.AppendPrintf(
841 StaticPrefs::layers_amd_switchable_gfx_enabled_AtStartup(),
842 StaticPrefs::layers_acceleration_disabled_AtStartup_DoNotUseDirectly(),
844 layers_acceleration_force_enabled_AtStartup_DoNotUseDirectly(),
845 StaticPrefs::layers_d3d11_force_warp_AtStartup());
847 forcedPrefs
.AppendPrintf(
848 "-W%d%d%d%d%d%d%d%d", StaticPrefs::webgl_angle_force_d3d11(),
849 StaticPrefs::webgl_angle_force_warp(), StaticPrefs::webgl_disabled(),
850 StaticPrefs::webgl_disable_angle(), StaticPrefs::webgl_dxgl_enabled(),
851 StaticPrefs::webgl_force_enabled(),
852 StaticPrefs::webgl_force_layers_readback(),
853 StaticPrefs::webgl_msaa_force());
854 // Prefs that don't fit into any of the other sections
855 forcedPrefs
.AppendPrintf("-T%d%d%d) ",
856 StaticPrefs::gfx_android_rgb16_force_AtStartup(),
857 StaticPrefs::gfx_canvas_accelerated(),
858 StaticPrefs::layers_force_shmem_tiles_AtStartup());
859 ScopedGfxFeatureReporter::AppNote(forcedPrefs
);
864 /* Initialize the GfxInfo service.
865 * Note: we can't call functions on GfxInfo that depend
866 * on gPlatform until after it has been initialized
867 * below. GfxInfo initialization annotates our
868 * crash reports so we want to do it before
869 * we try to load any drivers and do device detection
870 * incase that code crashes. See bug #591561. */
871 nsCOMPtr
<nsIGfxInfo
> gfxInfo
;
872 /* this currently will only succeed on Windows */
873 gfxInfo
= components::GfxInfo::Service();
875 if (XRE_IsParentProcess()) {
876 // Some gfxVars must be initialized prior gPlatform for coherent results.
877 gfxVars::SetDXInterop2Blocked(IsDXInterop2Blocked());
878 gfxVars::SetDXNV12Blocked(IsDXNV12Blocked());
879 gfxVars::SetDXP010Blocked(IsDXP010Blocked());
880 gfxVars::SetDXP016Blocked(IsDXP016Blocked());
884 gPlatform
= new gfxWindowsPlatform
;
885 #elif defined(XP_MACOSX)
886 gPlatform
= new gfxPlatformMac
;
887 #elif defined(MOZ_WIDGET_GTK)
888 gPlatform
= new gfxPlatformGtk
;
889 #elif defined(ANDROID)
890 gPlatform
= new gfxAndroidPlatform
;
892 # error "No gfxPlatform implementation available"
894 gPlatform
->PopulateScreenInfo();
895 gPlatform
->InitAcceleration();
896 gPlatform
->InitWebRenderConfig();
898 gPlatform
->InitHardwareVideoConfig();
899 gPlatform
->InitWebGLConfig();
900 gPlatform
->InitWebGPUConfig();
901 gPlatform
->InitWindowOcclusionConfig();
903 // When using WebRender, we defer initialization of the D3D11 devices until
904 // the (rare) cases where they're used. Note that the GPU process where
905 // WebRender runs doesn't initialize gfxPlatform and performs explicit
906 // initialization of the bits it needs.
909 || (UseWebRender() && XRE_IsParentProcess() &&
910 !gfxConfig::IsEnabled(Feature::GPU_PROCESS
) &&
912 gfx_webrender_enabled_no_gpu_process_with_angle_win_AtStartup())
915 gPlatform
->EnsureDevicesInitialized();
918 if (gfxConfig::IsEnabled(Feature::GPU_PROCESS
)) {
919 GPUProcessManager
* gpu
= GPUProcessManager::Get();
920 Unused
<< gpu
->LaunchGPUProcess();
923 if (XRE_IsParentProcess()) {
924 nsAutoCString allowlist
;
925 Preferences::GetCString("gfx.offscreencanvas.domain-allowlist", allowlist
);
926 gfxVars::SetOffscreenCanvasDomainAllowlist(allowlist
);
928 // Create the global vsync source and dispatcher.
929 RefPtr
<VsyncSource
> vsyncSource
=
930 gfxPlatform::ForceSoftwareVsync()
931 ? gPlatform
->GetSoftwareVsyncSource()
932 : gPlatform
->GetGlobalHardwareVsyncSource();
933 gPlatform
->mVsyncDispatcher
= new VsyncDispatcher(vsyncSource
);
935 // Listen for layout.frame_rate pref changes.
936 Preferences::RegisterCallback(
937 gfxPlatform::ReInitFrameRate
,
938 nsDependentCString(StaticPrefs::GetPrefName_layout_frame_rate()));
939 Preferences::RegisterCallback(
940 gfxPlatform::ReInitFrameRate
,
942 StaticPrefs::GetPrefName_privacy_resistFingerprinting()));
945 // Create the sRGB to output display profile transforms. They can be accessed
946 // off the main thread so we want to avoid a race condition.
950 #ifdef MOZ_ENABLE_FREETYPE
951 SkInitCairoFT(gPlatform
->FontHintingEnabled());
956 gPlatform
->mHasVariationFontSupport
= gPlatform
->CheckVariationFontSupport();
958 // This *create* the platform font list instance, but may not *initialize* it
959 // yet if the gfx.font-list.lazy-init.enabled pref is set. The first *use*
960 // of the list will ensure it is initialized.
961 if (!gPlatform
->CreatePlatformFontList()) {
962 MOZ_CRASH("Could not initialize gfxPlatformFontList");
965 gPlatform
->mScreenReferenceDrawTarget
=
966 gPlatform
->CreateOffscreenContentDrawTarget(IntSize(1, 1),
967 SurfaceFormat::B8G8R8A8
);
968 if (!gPlatform
->mScreenReferenceDrawTarget
||
969 !gPlatform
->mScreenReferenceDrawTarget
->IsValid()) {
970 // If TDR is detected, create a draw target with software backend
971 // and it should be replaced later when the process gets the device
972 // reset notification.
973 if (!gPlatform
->DidRenderingDeviceReset()) {
974 gfxCriticalError() << "Could not initialize mScreenReferenceDrawTarget";
978 if (NS_FAILED(gfxFontCache::Init())) {
979 MOZ_CRASH("Could not initialize gfxFontCache");
982 Preferences::RegisterPrefixCallbacks(FontPrefChanged
, kObservedPrefs
);
984 GLContext::PlatformStartup();
986 // Listen to memory pressure event so we can purge DrawTarget caches
987 gPlatform
->mMemoryPressureObserver
=
988 layers::MemoryPressureObserver::Create(gPlatform
);
990 // Request the imgITools service, implicitly initializing ImageLib.
991 nsCOMPtr
<imgITools
> imgTools
= do_GetService("@mozilla.org/image/tools;1");
993 MOZ_CRASH("Could not initialize ImageLib");
996 RegisterStrongMemoryReporter(new GfxMemoryImageReporter());
997 if (XRE_IsParentProcess() && UseWebRender()) {
998 RegisterStrongAsyncMemoryReporter(new WebRenderMemoryReporter());
1001 RegisterStrongMemoryReporter(new SkMemoryReporter());
1003 uint32_t skiaCacheSize
= GetSkiaGlyphCacheSize();
1004 if (skiaCacheSize
!= kDefaultGlyphCacheSize
) {
1005 SkGraphics::SetFontCacheLimit(skiaCacheSize
);
1011 if (XRE_IsParentProcess()) {
1012 Preferences::Unlock(FONT_VARIATIONS_PREF
);
1013 if (!gPlatform
->HasVariationFontSupport()) {
1014 // Ensure variation fonts are disabled and the pref is locked.
1015 Preferences::SetBool(FONT_VARIATIONS_PREF
, false, PrefValueKind::Default
);
1016 Preferences::SetBool(FONT_VARIATIONS_PREF
, false);
1017 Preferences::Lock(FONT_VARIATIONS_PREF
);
1021 if (XRE_IsParentProcess()) {
1025 nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService();
1027 obs
->NotifyObservers(nullptr, "gfx-features-ready", nullptr);
1031 void gfxPlatform::ReportTelemetry() {
1032 MOZ_RELEASE_ASSERT(XRE_IsParentProcess(),
1033 "GFX: Only allowed to be called from parent process.");
1035 nsCOMPtr
<nsIGfxInfo
> gfxInfo
= components::GfxInfo::Service();
1038 auto& screenManager
= widget::ScreenManager::GetSingleton();
1039 const uint32_t screenCount
= screenManager
.CurrentScreenList().Length();
1040 RefPtr
<widget::Screen
> primaryScreen
= screenManager
.GetPrimaryScreen();
1041 const LayoutDeviceIntRect rect
= primaryScreen
->GetRect();
1043 Telemetry::ScalarSet(Telemetry::ScalarID::GFX_DISPLAY_COUNT
, screenCount
);
1044 Telemetry::ScalarSet(Telemetry::ScalarID::GFX_DISPLAY_PRIMARY_HEIGHT
,
1045 uint32_t(rect
.Height()));
1046 Telemetry::ScalarSet(Telemetry::ScalarID::GFX_DISPLAY_PRIMARY_WIDTH
,
1047 uint32_t(rect
.Width()));
1050 nsString adapterDesc
;
1051 gfxInfo
->GetAdapterDescription(adapterDesc
);
1052 Telemetry::ScalarSet(Telemetry::ScalarID::GFX_ADAPTER_DESCRIPTION
,
1055 nsString adapterVendorId
;
1056 gfxInfo
->GetAdapterVendorID(adapterVendorId
);
1057 Telemetry::ScalarSet(Telemetry::ScalarID::GFX_ADAPTER_VENDOR_ID
,
1060 nsString adapterDeviceId
;
1061 gfxInfo
->GetAdapterDeviceID(adapterDeviceId
);
1062 Telemetry::ScalarSet(Telemetry::ScalarID::GFX_ADAPTER_DEVICE_ID
,
1065 nsString adapterSubsystemId
;
1066 gfxInfo
->GetAdapterSubsysID(adapterSubsystemId
);
1067 Telemetry::ScalarSet(Telemetry::ScalarID::GFX_ADAPTER_SUBSYSTEM_ID
,
1068 adapterSubsystemId
);
1070 uint32_t adapterRam
= 0;
1071 gfxInfo
->GetAdapterRAM(&adapterRam
);
1072 Telemetry::ScalarSet(Telemetry::ScalarID::GFX_ADAPTER_RAM
, adapterRam
);
1074 nsString adapterDriver
;
1075 gfxInfo
->GetAdapterDriver(adapterDriver
);
1076 Telemetry::ScalarSet(Telemetry::ScalarID::GFX_ADAPTER_DRIVER_FILES
,
1079 nsString adapterDriverVendor
;
1080 gfxInfo
->GetAdapterDriverVendor(adapterDriverVendor
);
1081 Telemetry::ScalarSet(Telemetry::ScalarID::GFX_ADAPTER_DRIVER_VENDOR
,
1082 adapterDriverVendor
);
1084 nsString adapterDriverVersion
;
1085 gfxInfo
->GetAdapterDriverVersion(adapterDriverVersion
);
1086 Telemetry::ScalarSet(Telemetry::ScalarID::GFX_ADAPTER_DRIVER_VERSION
,
1087 adapterDriverVersion
);
1089 nsString adapterDriverDate
;
1090 gfxInfo
->GetAdapterDriverDate(adapterDriverDate
);
1091 Telemetry::ScalarSet(Telemetry::ScalarID::GFX_ADAPTER_DRIVER_DATE
,
1094 Telemetry::ScalarSet(Telemetry::ScalarID::GFX_HEADLESS
, IsHeadless());
1097 static bool IsFeatureSupported(long aFeature
, bool aDefault
) {
1098 nsCOMPtr
<nsIGfxInfo
> gfxInfo
= components::GfxInfo::Service();
1101 if (!NS_SUCCEEDED(gfxInfo
->GetFeatureStatus(aFeature
, blockId
, &status
))) {
1104 return status
== nsIGfxInfo::FEATURE_STATUS_OK
;
1108 bool gfxPlatform::IsDXInterop2Blocked() {
1109 return !IsFeatureSupported(nsIGfxInfo::FEATURE_DX_INTEROP2
, false);
1113 bool gfxPlatform::IsDXNV12Blocked() {
1114 return !IsFeatureSupported(nsIGfxInfo::FEATURE_DX_NV12
, false);
1118 bool gfxPlatform::IsDXP010Blocked() {
1119 return !IsFeatureSupported(nsIGfxInfo::FEATURE_DX_P010
, false);
1123 bool gfxPlatform::IsDXP016Blocked() {
1124 return !IsFeatureSupported(nsIGfxInfo::FEATURE_DX_P016
, false);
1128 int32_t gfxPlatform::MaxTextureSize() {
1129 // Make sure we don't completely break rendering because of a typo in the
1131 const int32_t kMinSizePref
= 2048;
1134 StaticPrefs::gfx_max_texture_size_AtStartup_DoNotUseDirectly());
1138 int32_t gfxPlatform::MaxAllocSize() {
1139 // Make sure we don't completely break rendering because of a typo in the
1141 const int32_t kMinAllocPref
= 10000000;
1142 return std::max(kMinAllocPref
,
1143 StaticPrefs::gfx_max_alloc_size_AtStartup_DoNotUseDirectly());
1147 void gfxPlatform::InitMoz2DLogging() {
1148 auto fwd
= new CrashStatsLogForwarder(
1149 CrashReporter::Annotation::GraphicsCriticalError
);
1150 fwd
->SetCircularBufferSize(StaticPrefs::gfx_logging_crash_length_AtStartup());
1152 mozilla::gfx::Config cfg
;
1153 cfg
.mLogForwarder
= fwd
;
1154 cfg
.mMaxTextureSize
= gfxPlatform::MaxTextureSize();
1155 cfg
.mMaxAllocSize
= gfxPlatform::MaxAllocSize();
1157 gfx::Factory::Init(cfg
);
1161 bool gfxPlatform::IsHeadless() {
1162 static bool initialized
= false;
1163 static bool headless
= false;
1166 headless
= PR_GetEnv("MOZ_HEADLESS");
1172 bool gfxPlatform::UseWebRender() { return gfx::gfxVars::UseWebRender(); }
1175 bool gfxPlatform::UseRemoteCanvas() {
1176 return XRE_IsContentProcess() && gfx::gfxVars::RemoteCanvasEnabled();
1180 bool gfxPlatform::IsBackendAccelerated(
1181 const mozilla::gfx::BackendType aBackendType
) {
1182 return aBackendType
== BackendType::DIRECT2D
||
1183 aBackendType
== BackendType::DIRECT2D1_1
;
1187 bool gfxPlatform::CanMigrateMacGPUs() {
1188 int32_t pMigration
= StaticPrefs::gfx_compositor_gpu_migration();
1190 bool forceDisable
= pMigration
== 0;
1191 bool forceEnable
= pMigration
== 2;
1193 return forceEnable
|| !forceDisable
;
1196 static bool sLayersIPCIsUp
= false;
1199 void gfxPlatform::InitNullMetadata() {
1200 ScrollMetadata::sNullMetadata
= new ScrollMetadata();
1201 ClearOnShutdown(&ScrollMetadata::sNullMetadata
);
1204 void gfxPlatform::Shutdown() {
1205 // In some cases, gPlatform may not be created but Shutdown() called,
1206 // e.g., during xpcshell tests.
1211 MOZ_ASSERT(!sLayersIPCIsUp
);
1213 // These may be called before the corresponding subsystems have actually
1214 // started up. That's OK, they can handle it.
1215 gfxFontCache::Shutdown();
1216 gfxGradientCache::Shutdown();
1217 gfxAlphaBoxBlur::ShutdownBlurCache();
1218 gfxGraphiteShaper::Shutdown();
1219 gfxPlatformFontList::Shutdown();
1220 gfxFontMissingGlyphs::Shutdown();
1222 // Free the various non-null transforms and loaded profiles
1225 Preferences::UnregisterPrefixCallbacks(FontPrefChanged
, kObservedPrefs
);
1227 NS_ASSERTION(gPlatform
->mMemoryPressureObserver
,
1228 "mMemoryPressureObserver has already gone");
1229 if (gPlatform
->mMemoryPressureObserver
) {
1230 gPlatform
->mMemoryPressureObserver
->Unregister();
1231 gPlatform
->mMemoryPressureObserver
= nullptr;
1234 if (XRE_IsParentProcess()) {
1235 if (gPlatform
->mGlobalHardwareVsyncSource
) {
1236 gPlatform
->mGlobalHardwareVsyncSource
->Shutdown();
1238 if (gPlatform
->mSoftwareVsyncSource
&&
1239 gPlatform
->mSoftwareVsyncSource
!=
1240 gPlatform
->mGlobalHardwareVsyncSource
) {
1241 gPlatform
->mSoftwareVsyncSource
->Shutdown();
1245 gPlatform
->mGlobalHardwareVsyncSource
= nullptr;
1246 gPlatform
->mSoftwareVsyncSource
= nullptr;
1247 gPlatform
->mVsyncDispatcher
= nullptr;
1249 // Shut down the default GL context provider.
1250 GLContextProvider::Shutdown();
1253 // The above shutdown calls operate on the available context providers on
1254 // most platforms. Windows is a "special snowflake", though, and has three
1255 // context providers available, so we have to shut all of them down.
1256 // We should only support the default GL provider on Windows; then, this
1257 // could go away. Unfortunately, we currently support WGL (the default) for
1258 // WebGL on Optimus.
1259 GLContextProviderEGL::Shutdown();
1262 if (XRE_IsParentProcess()) {
1263 GPUProcessManager::Shutdown();
1264 VRProcessManager::Shutdown();
1265 RDDProcessManager::Shutdown();
1268 gfx::Factory::ShutDown();
1269 gfxVars::Shutdown();
1270 gfxFont::DestroySingletons();
1272 gfxConfig::Shutdown();
1274 gPlatform
->WillShutdown();
1277 gPlatform
= nullptr;
1281 void gfxPlatform::InitLayersIPC() {
1282 if (sLayersIPCIsUp
) {
1285 sLayersIPCIsUp
= true;
1287 if (XRE_IsParentProcess()) {
1289 if (gfxConfig::IsEnabled(gfx::Feature::WINDOW_OCCLUSION
)) {
1290 widget::WinWindowOcclusionTracker::Ensure();
1293 if (!gfxConfig::IsEnabled(Feature::GPU_PROCESS
) && UseWebRender()) {
1294 RemoteTextureMap::Init();
1295 wr::RenderThread::Start(GPUProcessManager::Get()->AllocateNamespace());
1296 image::ImageMemoryReporter::InitForWebRender();
1299 layers::CompositorThreadHolder::Start();
1304 void gfxPlatform::ShutdownLayersIPC() {
1305 if (!sLayersIPCIsUp
) {
1308 sLayersIPCIsUp
= false;
1310 if (XRE_IsContentProcess()) {
1311 gfx::VRManagerChild::ShutDown();
1312 gfx::CanvasManagerChild::Shutdown();
1314 if (StaticPrefs::layers_child_process_shutdown()) {
1315 layers::CompositorManagerChild::Shutdown();
1316 layers::ImageBridgeChild::ShutDown();
1319 } else if (XRE_IsParentProcess()) {
1320 gfx::VRManagerChild::ShutDown();
1321 gfx::CanvasManagerChild::Shutdown();
1322 layers::CompositorManagerChild::Shutdown();
1323 layers::ImageBridgeChild::ShutDown();
1324 // This could be running on either the Compositor or the Renderer thread.
1325 gfx::CanvasManagerParent::Shutdown();
1326 RemoteTextureMap::Shutdown();
1327 // This has to happen after shutting down the child protocols.
1328 layers::CompositorThreadHolder::Shutdown();
1329 image::ImageMemoryReporter::ShutdownForWebRender();
1330 // There is a case that RenderThread exists when UseWebRender() is
1331 // false. This could happen when WebRender was fallbacked to compositor.
1332 if (wr::RenderThread::Get()) {
1333 wr::RenderThread::ShutDown();
1335 Preferences::UnregisterCallback(WebRenderDebugPrefChangeCallback
,
1337 Preferences::UnregisterCallback(WebRendeProfilerUIPrefChangeCallback
,
1338 "gfx.webrender.debug.profiler-ui");
1339 Preferences::UnregisterCallback(
1340 WebRenderBlobTileSizePrefChangeCallback
,
1342 StaticPrefs::GetPrefName_gfx_webrender_blob_tile_size()));
1345 widget::WinWindowOcclusionTracker::ShutDown();
1348 // TODO: There are other kind of processes and we should make sure gfx
1349 // stuff is either not created there or shut down properly.
1353 void gfxPlatform::WillShutdown() {
1354 // Destoy these first in case they depend on backend-specific resources.
1355 // Otherwise, the backend's destructor would be called before the
1356 // base gfxPlatform destructor.
1357 mScreenReferenceSurface
= nullptr;
1358 mScreenReferenceDrawTarget
= nullptr;
1360 // Always clear out the Skia font cache here, in case it is referencing any
1361 // SharedFTFaces that would otherwise outlive destruction of the FT_Library
1363 SkGraphics::PurgeFontCache();
1365 // The cairo folks think we should only clean up in debug builds,
1366 // but we're generally in the habit of trying to shut down as
1367 // cleanly as possible even in production code, so call this
1368 // cairo_debug_* function unconditionally.
1370 // because cairo can assert and thus crash on shutdown, don't do this in
1372 #ifdef NS_FREE_PERMANENT_DATA
1373 cairo_debug_reset_static_data();
1377 gfxPlatform::~gfxPlatform() = default;
1380 already_AddRefed
<DrawTarget
> gfxPlatform::CreateDrawTargetForSurface(
1381 gfxASurface
* aSurface
, const IntSize
& aSize
) {
1382 SurfaceFormat format
= aSurface
->GetSurfaceFormat();
1383 RefPtr
<DrawTarget
> drawTarget
= Factory::CreateDrawTargetForCairoSurface(
1384 aSurface
->CairoSurface(), aSize
, &format
);
1386 gfxWarning() << "gfxPlatform::CreateDrawTargetForSurface failed in "
1387 "CreateDrawTargetForCairoSurface";
1390 return drawTarget
.forget();
1393 cairo_user_data_key_t kSourceSurface
;
1396 * Record the backend that was used to construct the SourceSurface.
1397 * When getting the cached SourceSurface for a gfxASurface/DrawTarget pair,
1398 * we check to make sure the DrawTarget's backend matches the backend
1399 * for the cached SourceSurface, and only use it if they match. This
1400 * can avoid expensive and unnecessary readbacks.
1402 struct SourceSurfaceUserData
{
1403 RefPtr
<SourceSurface
> mSrcSurface
;
1404 BackendType mBackendType
;
1407 static void SourceBufferDestroy(void* srcSurfUD
) {
1408 delete static_cast<SourceSurfaceUserData
*>(srcSurfUD
);
1411 UserDataKey kThebesSurface
;
1413 struct DependentSourceSurfaceUserData
{
1414 RefPtr
<gfxASurface
> mSurface
;
1417 static void SourceSurfaceDestroyed(void* aData
) {
1418 delete static_cast<DependentSourceSurfaceUserData
*>(aData
);
1421 void gfxPlatform::ClearSourceSurfaceForSurface(gfxASurface
* aSurface
) {
1422 aSurface
->SetData(&kSourceSurface
, nullptr, nullptr);
1426 already_AddRefed
<SourceSurface
> gfxPlatform::GetSourceSurfaceForSurface(
1427 RefPtr
<DrawTarget
> aTarget
, gfxASurface
* aSurface
, bool aIsPlugin
) {
1428 if (!aSurface
->CairoSurface() || aSurface
->CairoStatus()) {
1433 aTarget
= gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
1436 void* userData
= aSurface
->GetData(&kSourceSurface
);
1439 SourceSurfaceUserData
* surf
= static_cast<SourceSurfaceUserData
*>(userData
);
1441 if (surf
->mSrcSurface
->IsValid() &&
1442 surf
->mBackendType
== aTarget
->GetBackendType()) {
1443 RefPtr
<SourceSurface
> srcSurface(surf
->mSrcSurface
);
1444 return srcSurface
.forget();
1446 // We can just continue here as when setting new user data the destroy
1447 // function will be called for the old user data.
1450 SurfaceFormat format
= aSurface
->GetSurfaceFormat();
1452 if (aTarget
->GetBackendType() == BackendType::CAIRO
) {
1453 // If we're going to be used with a CAIRO DrawTarget, then just create a
1454 // SourceSurfaceCairo since we don't know the underlying type of the CAIRO
1455 // DrawTarget and can't pick a better surface type. Doing this also avoids
1456 // readback of aSurface's surface into memory if, for example, aSurface
1457 // wraps an xlib cairo surface (which can be important to avoid a major
1460 // We return here regardless of whether CreateSourceSurfaceFromNativeSurface
1461 // succeeds or not since we don't expect to be able to do any better below
1464 // Note that the returned SourceSurfaceCairo holds a strong reference to
1465 // the cairo_surface_t* that it wraps, which essencially means it holds a
1466 // strong reference to aSurface since aSurface shares its
1467 // cairo_surface_t*'s reference count variable. As a result we can't cache
1468 // srcBuffer on aSurface (see below) since aSurface would then hold a
1469 // strong reference back to srcBuffer, creating a reference loop and a
1470 // memory leak. Not caching is fine since wrapping is cheap enough (no
1471 // copying) so we can just wrap again next time we're called.
1472 return Factory::CreateSourceSurfaceForCairoSurface(
1473 aSurface
->CairoSurface(), aSurface
->GetSize(), format
);
1476 RefPtr
<SourceSurface
> srcBuffer
;
1478 // Currently no other DrawTarget types implement
1479 // CreateSourceSurfaceFromNativeSurface
1482 // If aSurface wraps data, we can create a SourceSurfaceRawData that wraps
1483 // the same data, then optimize it for aTarget:
1484 RefPtr
<DataSourceSurface
> surf
= GetWrappedDataSourceSurface(aSurface
);
1486 srcBuffer
= aIsPlugin
1487 ? aTarget
->OptimizeSourceSurfaceForUnknownAlpha(surf
)
1488 : aTarget
->OptimizeSourceSurface(surf
);
1490 if (srcBuffer
== surf
) {
1491 // GetWrappedDataSourceSurface returns a SourceSurface that holds a
1492 // strong reference to aSurface since it wraps aSurface's data and
1493 // needs it to stay alive. As a result we can't cache srcBuffer on
1494 // aSurface (below) since aSurface would then hold a strong reference
1495 // back to srcBuffer, creating a reference loop and a memory leak. Not
1496 // caching is fine since wrapping is cheap enough (no copying) so we
1497 // can just wrap again next time we're called.
1499 // Note that the check below doesn't catch this since srcBuffer will be
1500 // a SourceSurfaceRawData object (even if aSurface is not a
1501 // gfxImageSurface object), which is why we need this separate check.
1502 return srcBuffer
.forget();
1508 MOZ_ASSERT(aTarget
->GetBackendType() != BackendType::CAIRO
,
1509 "We already tried CreateSourceSurfaceFromNativeSurface with a "
1510 "DrawTargetCairo above");
1511 // We've run out of performant options. We now try creating a SourceSurface
1512 // using a temporary DrawTargetCairo and then optimizing it to aTarget's
1513 // actual type. The CreateSourceSurfaceFromNativeSurface() call will
1514 // likely create a DataSourceSurface (possibly involving copying and/or
1515 // readback), and the OptimizeSourceSurface may well copy again and upload
1516 // to the GPU. So, while this code path is rarely hit, hitting it may be
1518 srcBuffer
= Factory::CreateSourceSurfaceForCairoSurface(
1519 aSurface
->CairoSurface(), aSurface
->GetSize(), format
);
1521 srcBuffer
= aTarget
->OptimizeSourceSurface(srcBuffer
);
1529 if ((srcBuffer
->GetType() == SurfaceType::CAIRO
&&
1530 static_cast<SourceSurfaceCairo
*>(srcBuffer
.get())->GetSurface() ==
1531 aSurface
->CairoSurface()) ||
1532 (srcBuffer
->GetType() == SurfaceType::CAIRO_IMAGE
&&
1533 static_cast<DataSourceSurfaceCairo
*>(srcBuffer
.get())->GetSurface() ==
1534 aSurface
->CairoSurface())) {
1535 // See the "Note that the returned SourceSurfaceCairo..." comment above.
1536 return srcBuffer
.forget();
1539 // Add user data to aSurface so we can cache lookups in the future.
1540 auto* srcSurfUD
= new SourceSurfaceUserData
;
1541 srcSurfUD
->mBackendType
= aTarget
->GetBackendType();
1542 srcSurfUD
->mSrcSurface
= srcBuffer
;
1543 aSurface
->SetData(&kSourceSurface
, srcSurfUD
, SourceBufferDestroy
);
1545 return srcBuffer
.forget();
1548 already_AddRefed
<DataSourceSurface
> gfxPlatform::GetWrappedDataSourceSurface(
1549 gfxASurface
* aSurface
) {
1550 RefPtr
<gfxImageSurface
> image
= aSurface
->GetAsImageSurface();
1554 RefPtr
<DataSourceSurface
> result
= Factory::CreateWrappingDataSourceSurface(
1555 image
->Data(), image
->Stride(), image
->GetSize(),
1556 ImageFormatToSurfaceFormat(image
->Format()));
1562 // If we wrapped the underlying data of aSurface, then we need to add user
1563 // data to make sure aSurface stays alive until we are done with the data.
1564 auto* srcSurfUD
= new DependentSourceSurfaceUserData
;
1565 srcSurfUD
->mSurface
= aSurface
;
1566 result
->AddUserData(&kThebesSurface
, srcSurfUD
, SourceSurfaceDestroyed
);
1568 return result
.forget();
1571 void gfxPlatform::PopulateScreenInfo() {
1572 nsCOMPtr
<nsIScreenManager
> manager
=
1573 do_GetService("@mozilla.org/gfx/screenmanager;1");
1574 MOZ_ASSERT(manager
, "failed to get nsIScreenManager");
1576 nsCOMPtr
<nsIScreen
> screen
;
1577 manager
->GetPrimaryScreen(getter_AddRefs(screen
));
1579 // This can happen in xpcshell, for instance
1583 screen
->GetColorDepth(&mScreenDepth
);
1584 if (XRE_IsParentProcess()) {
1585 gfxVars::SetScreenDepth(mScreenDepth
);
1589 screen
->GetRect(&left
, &top
, &mScreenSize
.width
, &mScreenSize
.height
);
1592 bool gfxPlatform::SupportsAzureContentForDrawTarget(DrawTarget
* aTarget
) {
1593 if (!aTarget
|| !aTarget
->IsValid()) {
1597 return SupportsAzureContentForType(aTarget
->GetBackendType());
1600 void gfxPlatform::PurgeSkiaFontCache() {
1601 if (gfxPlatform::GetPlatform()->GetDefaultContentBackend() ==
1602 BackendType::SKIA
) {
1603 SkGraphics::PurgeFontCache();
1607 already_AddRefed
<DrawTarget
> gfxPlatform::CreateDrawTargetForBackend(
1608 BackendType aBackend
, const IntSize
& aSize
, SurfaceFormat aFormat
) {
1609 // There is a bunch of knowledge in the gfxPlatform heirarchy about how to
1610 // create the best offscreen surface for the current system and situation. We
1611 // can easily take advantage of this for the Cairo backend, so that's what we
1613 // mozilla::gfx::Factory can get away without having all this knowledge for
1614 // now, but this might need to change in the future (using
1615 // CreateOffscreenSurface() and CreateDrawTargetForSurface() for all
1617 if (aBackend
== BackendType::CAIRO
) {
1618 RefPtr
<gfxASurface
> surf
=
1619 CreateOffscreenSurface(aSize
, SurfaceFormatToImageFormat(aFormat
));
1620 if (!surf
|| surf
->CairoStatus()) {
1623 return CreateDrawTargetForSurface(surf
, aSize
);
1625 return Factory::CreateDrawTarget(aBackend
, aSize
, aFormat
);
1628 already_AddRefed
<DrawTarget
> gfxPlatform::CreateOffscreenCanvasDrawTarget(
1629 const IntSize
& aSize
, SurfaceFormat aFormat
) {
1630 NS_ASSERTION(mPreferredCanvasBackend
!= BackendType::NONE
, "No backend.");
1632 // If we are using remote canvas we don't want to use acceleration in
1633 // canvas DrawTargets we are not remoting, so we always use the fallback
1635 if (!gfxPlatform::UseRemoteCanvas() ||
1636 !gfxPlatform::IsBackendAccelerated(mPreferredCanvasBackend
)) {
1637 RefPtr
<DrawTarget
> target
=
1638 CreateDrawTargetForBackend(mPreferredCanvasBackend
, aSize
, aFormat
);
1639 if (target
|| mFallbackCanvasBackend
== BackendType::NONE
) {
1640 return target
.forget();
1645 // On Windows, the fallback backend (Cairo) should use its image backend.
1646 return Factory::CreateDrawTarget(mFallbackCanvasBackend
, aSize
, aFormat
);
1648 return CreateDrawTargetForBackend(mFallbackCanvasBackend
, aSize
, aFormat
);
1652 already_AddRefed
<DrawTarget
> gfxPlatform::CreateOffscreenContentDrawTarget(
1653 const IntSize
& aSize
, SurfaceFormat aFormat
, bool aFallback
) {
1654 BackendType backend
= (aFallback
) ? mSoftwareBackend
: mContentBackend
;
1655 NS_ASSERTION(backend
!= BackendType::NONE
, "No backend.");
1656 RefPtr
<DrawTarget
> dt
= CreateDrawTargetForBackend(backend
, aSize
, aFormat
);
1662 // We'd prefer this to take proper care and return a CaptureDT, but for the
1663 // moment since we can't and this means we're going to be drawing on the main
1664 // thread force it's initialization. See bug 1526045 and bug 1521368.
1665 dt
->ClearRect(gfx::Rect());
1666 if (!dt
->IsValid()) {
1672 already_AddRefed
<DrawTarget
> gfxPlatform::CreateSimilarSoftwareDrawTarget(
1673 DrawTarget
* aDT
, const IntSize
& aSize
, SurfaceFormat aFormat
) {
1674 RefPtr
<DrawTarget
> dt
;
1676 if (Factory::DoesBackendSupportDataDrawtarget(aDT
->GetBackendType())) {
1677 dt
= aDT
->CreateSimilarDrawTarget(aSize
, aFormat
);
1679 BackendType backendType
= BackendType::SKIA
;
1680 dt
= Factory::CreateDrawTarget(backendType
, aSize
, aFormat
);
1687 already_AddRefed
<DrawTarget
> gfxPlatform::CreateDrawTargetForData(
1688 unsigned char* aData
, const IntSize
& aSize
, int32_t aStride
,
1689 SurfaceFormat aFormat
, bool aUninitialized
) {
1690 BackendType backendType
= gfxVars::ContentBackend();
1691 NS_ASSERTION(backendType
!= BackendType::NONE
, "No backend.");
1693 if (!Factory::DoesBackendSupportDataDrawtarget(backendType
)) {
1694 backendType
= BackendType::SKIA
;
1697 RefPtr
<DrawTarget
> dt
= Factory::CreateDrawTargetForData(
1698 backendType
, aData
, aSize
, aStride
, aFormat
, aUninitialized
);
1704 BackendType
gfxPlatform::BackendTypeForName(const nsCString
& aName
) {
1705 if (aName
.EqualsLiteral("cairo")) return BackendType::CAIRO
;
1706 if (aName
.EqualsLiteral("skia")) return BackendType::SKIA
;
1707 if (aName
.EqualsLiteral("direct2d")) return BackendType::DIRECT2D
;
1708 if (aName
.EqualsLiteral("direct2d1.1")) return BackendType::DIRECT2D1_1
;
1709 return BackendType::NONE
;
1712 nsresult
gfxPlatform::GetFontList(nsAtom
* aLangGroup
,
1713 const nsACString
& aGenericFamily
,
1714 nsTArray
<nsString
>& aListOfFonts
) {
1715 gfxPlatformFontList::PlatformFontList()->GetFontList(
1716 aLangGroup
, aGenericFamily
, aListOfFonts
);
1720 nsresult
gfxPlatform::UpdateFontList(bool aFullRebuild
) {
1721 gfxPlatformFontList::PlatformFontList()->UpdateFontList(aFullRebuild
);
1725 void gfxPlatform::GetStandardFamilyName(const nsCString
& aFontName
,
1726 nsACString
& aFamilyName
) {
1727 gfxPlatformFontList::PlatformFontList()->GetStandardFamilyName(aFontName
,
1731 nsAutoCString
gfxPlatform::GetDefaultFontName(
1732 const nsACString
& aLangGroup
, const nsACString
& aGenericFamily
) {
1733 // To benefit from Return Value Optimization, all paths here must return
1734 // this one variable:
1735 nsAutoCString result
;
1737 auto* pfl
= gfxPlatformFontList::PlatformFontList();
1738 FamilyAndGeneric fam
= pfl
->GetDefaultFontFamily(aLangGroup
, aGenericFamily
);
1739 if (!pfl
->GetLocalizedFamilyName(fam
.mFamily
, result
)) {
1740 NS_WARNING("missing default font-family name");
1746 bool gfxPlatform::DownloadableFontsEnabled() {
1747 if (mAllowDownloadableFonts
== UNINITIALIZED_VALUE
) {
1748 mAllowDownloadableFonts
=
1749 Preferences::GetBool(GFX_DOWNLOADABLE_FONTS_ENABLED
, false);
1752 return mAllowDownloadableFonts
;
1755 bool gfxPlatform::UseCmapsDuringSystemFallback() {
1756 return StaticPrefs::gfx_font_rendering_fallback_always_use_cmaps();
1759 bool gfxPlatform::OpenTypeSVGEnabled() {
1760 return StaticPrefs::gfx_font_rendering_opentype_svg_enabled();
1763 uint32_t gfxPlatform::WordCacheCharLimit() {
1764 return StaticPrefs::gfx_font_rendering_wordcache_charlimit();
1767 uint32_t gfxPlatform::WordCacheMaxEntries() {
1768 return StaticPrefs::gfx_font_rendering_wordcache_maxentries();
1771 bool gfxPlatform::UseGraphiteShaping() {
1772 return StaticPrefs::gfx_font_rendering_graphite_enabled();
1775 bool gfxPlatform::IsFontFormatSupported(uint32_t aFormatFlags
) {
1776 // check for strange format flags
1777 MOZ_ASSERT(!(aFormatFlags
& gfxUserFontSet::FLAG_FORMAT_NOT_USED
),
1778 "strange font format hint set");
1780 // accept "common" formats that we support on all platforms
1781 if (aFormatFlags
& gfxUserFontSet::FLAG_FORMATS_COMMON
) {
1785 // reject all other formats, known and unknown
1786 if (aFormatFlags
!= 0) {
1790 // no format hint set, need to look at data
1794 gfxFontGroup
* gfxPlatform::CreateFontGroup(
1795 nsPresContext
* aPresContext
, const StyleFontFamilyList
& aFontFamilyList
,
1796 const gfxFontStyle
* aStyle
, nsAtom
* aLanguage
, bool aExplicitLanguage
,
1797 gfxTextPerfMetrics
* aTextPerf
, gfxUserFontSet
* aUserFontSet
,
1798 gfxFloat aDevToCssSize
) const {
1799 return new gfxFontGroup(aPresContext
, aFontFamilyList
, aStyle
, aLanguage
,
1800 aExplicitLanguage
, aTextPerf
, aUserFontSet
,
1804 gfxFontEntry
* gfxPlatform::LookupLocalFont(nsPresContext
* aPresContext
,
1805 const nsACString
& aFontName
,
1806 WeightRange aWeightForEntry
,
1807 StretchRange aStretchForEntry
,
1808 SlantStyleRange aStyleForEntry
) {
1809 return gfxPlatformFontList::PlatformFontList()->LookupLocalFont(
1810 aPresContext
, aFontName
, aWeightForEntry
, aStretchForEntry
,
1814 gfxFontEntry
* gfxPlatform::MakePlatformFont(const nsACString
& aFontName
,
1815 WeightRange aWeightForEntry
,
1816 StretchRange aStretchForEntry
,
1817 SlantStyleRange aStyleForEntry
,
1818 const uint8_t* aFontData
,
1820 return gfxPlatformFontList::PlatformFontList()->MakePlatformFont(
1821 aFontName
, aWeightForEntry
, aStretchForEntry
, aStyleForEntry
, aFontData
,
1825 BackendPrefsData
gfxPlatform::GetBackendPrefs() const {
1826 BackendPrefsData data
;
1828 data
.mCanvasBitmask
= BackendTypeBit(BackendType::SKIA
);
1829 data
.mContentBitmask
= BackendTypeBit(BackendType::SKIA
);
1831 #ifdef MOZ_WIDGET_GTK
1832 data
.mCanvasBitmask
|= BackendTypeBit(BackendType::CAIRO
);
1833 data
.mContentBitmask
|= BackendTypeBit(BackendType::CAIRO
);
1836 data
.mCanvasDefault
= BackendType::SKIA
;
1837 data
.mContentDefault
= BackendType::SKIA
;
1842 void gfxPlatform::InitBackendPrefs(BackendPrefsData
&& aPrefsData
) {
1843 mPreferredCanvasBackend
= GetCanvasBackendPref(aPrefsData
.mCanvasBitmask
);
1844 if (mPreferredCanvasBackend
== BackendType::NONE
) {
1845 mPreferredCanvasBackend
= aPrefsData
.mCanvasDefault
;
1848 if (mPreferredCanvasBackend
== BackendType::DIRECT2D1_1
) {
1849 // Falling back to D2D 1.0 won't help us here. When D2D 1.1 DT creation
1850 // fails it means the surface was too big or there's something wrong with
1851 // the device. D2D 1.0 will encounter a similar situation.
1852 mFallbackCanvasBackend
= GetCanvasBackendPref(
1853 aPrefsData
.mCanvasBitmask
& ~(BackendTypeBit(mPreferredCanvasBackend
) |
1854 BackendTypeBit(BackendType::DIRECT2D
)));
1856 mFallbackCanvasBackend
= GetCanvasBackendPref(
1857 aPrefsData
.mCanvasBitmask
& ~BackendTypeBit(mPreferredCanvasBackend
));
1860 mContentBackendBitmask
= aPrefsData
.mContentBitmask
;
1861 mContentBackend
= GetContentBackendPref(mContentBackendBitmask
);
1862 if (mContentBackend
== BackendType::NONE
) {
1863 mContentBackend
= aPrefsData
.mContentDefault
;
1864 // mContentBackendBitmask is our canonical reference for supported
1865 // backends so we need to add the default if we are using it and
1866 // overriding the prefs.
1867 mContentBackendBitmask
|= BackendTypeBit(aPrefsData
.mContentDefault
);
1870 uint32_t swBackendBits
= BackendTypeBit(BackendType::SKIA
);
1871 #ifdef MOZ_WIDGET_GTK
1872 swBackendBits
|= BackendTypeBit(BackendType::CAIRO
);
1874 mSoftwareBackend
= GetContentBackendPref(swBackendBits
);
1875 if (mSoftwareBackend
== BackendType::NONE
) {
1876 mSoftwareBackend
= BackendType::SKIA
;
1879 // If we don't have a fallback canvas backend then use the same software
1880 // fallback as content.
1881 if (mFallbackCanvasBackend
== BackendType::NONE
) {
1882 mFallbackCanvasBackend
= mSoftwareBackend
;
1885 if (XRE_IsParentProcess()) {
1886 gfxVars::SetContentBackend(mContentBackend
);
1887 gfxVars::SetSoftwareBackend(mSoftwareBackend
);
1892 BackendType
gfxPlatform::GetCanvasBackendPref(uint32_t aBackendBitmask
) {
1893 return GetBackendPref("gfx.canvas.azure.backends", aBackendBitmask
);
1897 BackendType
gfxPlatform::GetContentBackendPref(uint32_t& aBackendBitmask
) {
1898 return GetBackendPref("gfx.content.azure.backends", aBackendBitmask
);
1902 BackendType
gfxPlatform::GetBackendPref(const char* aBackendPrefName
,
1903 uint32_t& aBackendBitmask
) {
1904 nsTArray
<nsCString
> backendList
;
1905 nsAutoCString prefString
;
1906 if (NS_SUCCEEDED(Preferences::GetCString(aBackendPrefName
, prefString
))) {
1907 ParseString(prefString
, ',', backendList
);
1910 uint32_t allowedBackends
= 0;
1911 BackendType result
= BackendType::NONE
;
1912 for (uint32_t i
= 0; i
< backendList
.Length(); ++i
) {
1913 BackendType type
= BackendTypeForName(backendList
[i
]);
1914 if (BackendTypeBit(type
) & aBackendBitmask
) {
1915 allowedBackends
|= BackendTypeBit(type
);
1916 if (result
== BackendType::NONE
) {
1922 aBackendBitmask
= allowedBackends
;
1926 bool gfxPlatform::InSafeMode() {
1927 static bool sSafeModeInitialized
= false;
1928 static bool sInSafeMode
= false;
1930 if (!sSafeModeInitialized
) {
1931 sSafeModeInitialized
= true;
1932 nsCOMPtr
<nsIXULRuntime
> xr
= do_GetService("@mozilla.org/xre/runtime;1");
1934 xr
->GetInSafeMode(&sInSafeMode
);
1940 bool gfxPlatform::OffMainThreadCompositingEnabled() {
1941 return UsesOffMainThreadCompositing();
1944 void gfxPlatform::SetCMSModeOverride(CMSMode aMode
) {
1945 MOZ_ASSERT(gCMSInitialized
);
1949 int gfxPlatform::GetRenderingIntent() {
1950 // StaticPrefList.yaml is using 0 as the default for the rendering
1951 // intent preference, based on that being the value for
1952 // QCMS_INTENT_DEFAULT. Assert here to catch if that ever
1953 // changes and we can then figure out what to do about it.
1954 MOZ_ASSERT(QCMS_INTENT_DEFAULT
== 0);
1956 /* Try to query the pref system for a rendering intent. */
1957 int32_t pIntent
= StaticPrefs::gfx_color_management_rendering_intent();
1958 if ((pIntent
< QCMS_INTENT_MIN
) || (pIntent
> QCMS_INTENT_MAX
)) {
1959 /* If the pref is out of range, use embedded profile. */
1965 DeviceColor
gfxPlatform::TransformPixel(const sRGBColor
& in
,
1966 qcms_transform
* transform
) {
1968 /* we want the bytes in RGB order */
1969 #ifdef IS_LITTLE_ENDIAN
1970 /* ABGR puts the bytes in |RGBA| order on little endian */
1971 uint32_t packed
= in
.ToABGR();
1972 qcms_transform_data(transform
, (uint8_t*)&packed
, (uint8_t*)&packed
, 1);
1973 auto out
= DeviceColor::FromABGR(packed
);
1975 /* ARGB puts the bytes in |ARGB| order on big endian */
1976 uint32_t packed
= in
.UnusualToARGB();
1977 /* add one to move past the alpha byte */
1978 qcms_transform_data(transform
, (uint8_t*)&packed
+ 1, (uint8_t*)&packed
+ 1,
1980 auto out
= DeviceColor::UnusualFromARGB(packed
);
1985 return DeviceColor(in
.r
, in
.g
, in
.b
, in
.a
);
1988 nsTArray
<uint8_t> gfxPlatform::GetPlatformCMSOutputProfileData() {
1989 return GetPrefCMSOutputProfileData();
1992 nsTArray
<uint8_t> gfxPlatform::GetPrefCMSOutputProfileData() {
1993 nsAutoCString fname
;
1994 Preferences::GetCString("gfx.color_management.display_profile", fname
);
1996 if (fname
.IsEmpty()) {
1997 return nsTArray
<uint8_t>();
2000 void* mem
= nullptr;
2002 qcms_data_from_path(fname
.get(), &mem
, &size
);
2004 nsTArray
<uint8_t> result
;
2007 result
.AppendElements(static_cast<uint8_t*>(mem
), size
);
2014 const mozilla::gfx::ContentDeviceData
* gfxPlatform::GetInitContentDeviceData() {
2015 return gContentDeviceInitData
;
2018 CMSMode
GfxColorManagementMode() {
2019 const auto mode
= StaticPrefs::gfx_color_management_mode();
2020 if (mode
>= 0 && mode
< UnderlyingValue(CMSMode::AllCount
)) {
2021 return CMSMode(mode
);
2023 return CMSMode::Off
;
2026 void gfxPlatform::InitializeCMS() {
2027 if (gCMSInitialized
) {
2031 if (XRE_IsGPUProcess()) {
2032 // Colors in the GPU process should already be managed, so we don't need to
2033 // perform color management there.
2034 gCMSInitialized
= true;
2038 MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread(),
2039 "CMS should be initialized on the main thread");
2040 if (MOZ_UNLIKELY(!NS_IsMainThread())) {
2044 gCMSMode
= GfxColorManagementMode();
2046 gCMSsRGBProfile
= qcms_profile_sRGB();
2048 /* Determine if we're using the internal override to force sRGB as
2049 an output profile for reftests. See Bug 452125.
2051 Note that we don't normally (outside of tests) set a default value
2052 of this preference, which means nsIPrefBranch::GetBoolPref will
2053 typically throw (and leave its out-param untouched).
2055 if (StaticPrefs::gfx_color_management_force_srgb() ||
2056 StaticPrefs::gfx_color_management_native_srgb()) {
2057 gCMSOutputProfile
= gCMSsRGBProfile
;
2060 if (!gCMSOutputProfile
) {
2061 nsTArray
<uint8_t> outputProfileData
=
2062 gfxPlatform::GetPlatform()->GetPlatformCMSOutputProfileData();
2063 if (!outputProfileData
.IsEmpty()) {
2064 gCMSOutputProfile
= qcms_profile_from_memory(outputProfileData
.Elements(),
2065 outputProfileData
.Length());
2069 /* Determine if the profile looks bogus. If so, close the profile
2070 * and use sRGB instead. See bug 460629, */
2071 if (gCMSOutputProfile
&& qcms_profile_is_bogus(gCMSOutputProfile
)) {
2072 NS_ASSERTION(gCMSOutputProfile
!= gCMSsRGBProfile
,
2073 "Builtin sRGB profile tagged as bogus!!!");
2074 qcms_profile_release(gCMSOutputProfile
);
2075 gCMSOutputProfile
= nullptr;
2078 if (!gCMSOutputProfile
) {
2079 gCMSOutputProfile
= gCMSsRGBProfile
;
2082 /* Precache the LUT16 Interpolations for the output profile. See
2083 bug 444661 for details. */
2084 qcms_profile_precache_output_transform(gCMSOutputProfile
);
2086 // Create the RGB transform.
2088 qcms_transform_create(gCMSsRGBProfile
, QCMS_DATA_RGB_8
, gCMSOutputProfile
,
2089 QCMS_DATA_RGB_8
, QCMS_INTENT_PERCEPTUAL
);
2092 gCMSInverseRGBTransform
=
2093 qcms_transform_create(gCMSOutputProfile
, QCMS_DATA_RGB_8
, gCMSsRGBProfile
,
2094 QCMS_DATA_RGB_8
, QCMS_INTENT_PERCEPTUAL
);
2096 // The RGBA transform.
2097 gCMSRGBATransform
= qcms_transform_create(gCMSsRGBProfile
, QCMS_DATA_RGBA_8
,
2098 gCMSOutputProfile
, QCMS_DATA_RGBA_8
,
2099 QCMS_INTENT_PERCEPTUAL
);
2101 // And the BGRA one.
2102 gCMSBGRATransform
= qcms_transform_create(gCMSsRGBProfile
, QCMS_DATA_BGRA_8
,
2103 gCMSOutputProfile
, QCMS_DATA_BGRA_8
,
2104 QCMS_INTENT_PERCEPTUAL
);
2106 // FIXME: We only enable iccv4 after we create the platform profile, to
2107 // wallpaper over bug 1697787.
2109 // This should happen ideally right after setting gCMSMode.
2110 if (StaticPrefs::gfx_color_management_enablev4()) {
2111 qcms_enable_iccv4();
2114 gCMSInitialized
= true;
2117 qcms_transform
* gfxPlatform::GetCMSOSRGBATransform() {
2118 switch (SurfaceFormat::OS_RGBA
) {
2119 case SurfaceFormat::B8G8R8A8
:
2120 return GetCMSBGRATransform();
2121 case SurfaceFormat::R8G8B8A8
:
2122 return GetCMSRGBATransform();
2124 // We do not support color management with big endian.
2129 qcms_data_type
gfxPlatform::GetCMSOSRGBAType() {
2130 switch (SurfaceFormat::OS_RGBA
) {
2131 case SurfaceFormat::B8G8R8A8
:
2132 return QCMS_DATA_BGRA_8
;
2133 case SurfaceFormat::R8G8B8A8
:
2134 return QCMS_DATA_RGBA_8
;
2136 // We do not support color management with big endian.
2137 return QCMS_DATA_RGBA_8
;
2141 /* Shuts down various transforms and profiles for CMS. */
2142 void gfxPlatform::ShutdownCMS() {
2143 if (gCMSRGBTransform
) {
2144 qcms_transform_release(gCMSRGBTransform
);
2145 gCMSRGBTransform
= nullptr;
2147 if (gCMSInverseRGBTransform
) {
2148 qcms_transform_release(gCMSInverseRGBTransform
);
2149 gCMSInverseRGBTransform
= nullptr;
2151 if (gCMSRGBATransform
) {
2152 qcms_transform_release(gCMSRGBATransform
);
2153 gCMSRGBATransform
= nullptr;
2155 if (gCMSBGRATransform
) {
2156 qcms_transform_release(gCMSBGRATransform
);
2157 gCMSBGRATransform
= nullptr;
2159 if (gCMSOutputProfile
) {
2160 qcms_profile_release(gCMSOutputProfile
);
2162 // handle the aliased case
2163 if (gCMSsRGBProfile
== gCMSOutputProfile
) {
2164 gCMSsRGBProfile
= nullptr;
2166 gCMSOutputProfile
= nullptr;
2168 if (gCMSsRGBProfile
) {
2169 qcms_profile_release(gCMSsRGBProfile
);
2170 gCMSsRGBProfile
= nullptr;
2173 // Reset the state variables
2174 gCMSMode
= CMSMode::Off
;
2175 gCMSInitialized
= false;
2178 uint32_t gfxPlatform::GetBidiNumeralOption() {
2179 return StaticPrefs::bidi_numeral();
2183 void gfxPlatform::FlushFontAndWordCaches() {
2184 gfxFontCache
* fontCache
= gfxFontCache::GetCache();
2189 gfxPlatform::PurgeSkiaFontCache();
2193 void gfxPlatform::ForceGlobalReflow(NeedsReframe aNeedsReframe
,
2194 BroadcastToChildren aBroadcastToChildren
) {
2195 MOZ_ASSERT(NS_IsMainThread());
2196 const bool reframe
= aNeedsReframe
== NeedsReframe::Yes
;
2197 // Send a notification that will be observed by PresShells in this process
2199 if (nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService()) {
2200 char16_t needsReframe
[] = {char16_t(reframe
), 0};
2201 obs
->NotifyObservers(nullptr, "font-info-updated", needsReframe
);
2203 if (XRE_IsParentProcess() &&
2204 aBroadcastToChildren
== BroadcastToChildren::Yes
) {
2205 // Propagate the change to child processes.
2206 for (auto* process
:
2207 dom::ContentParent::AllProcesses(dom::ContentParent::eLive
)) {
2208 Unused
<< process
->SendForceGlobalReflow(reframe
);
2213 void gfxPlatform::FontsPrefsChanged(const char* aPref
) {
2214 NS_ASSERTION(aPref
!= nullptr, "null preference");
2215 if (!strcmp(GFX_DOWNLOADABLE_FONTS_ENABLED
, aPref
)) {
2216 mAllowDownloadableFonts
= UNINITIALIZED_VALUE
;
2217 } else if (!strcmp(GFX_PREF_WORD_CACHE_CHARLIMIT
, aPref
) ||
2218 !strcmp(GFX_PREF_WORD_CACHE_MAXENTRIES
, aPref
) ||
2219 !strcmp(GFX_PREF_GRAPHITE_SHAPING
, aPref
)) {
2220 FlushFontAndWordCaches();
2222 #if defined(XP_MACOSX)
2223 !strcmp(GFX_PREF_CORETEXT_SHAPING
, aPref
) ||
2225 !strcmp("gfx.font_rendering.ahem_antialias_none", aPref
)) {
2226 FlushFontAndWordCaches();
2227 } else if (!strcmp(GFX_PREF_OPENTYPE_SVG
, aPref
)) {
2228 gfxFontCache::GetCache()->AgeAllGenerations();
2229 gfxFontCache::GetCache()->NotifyGlyphsChanged();
2233 mozilla::LogModule
* gfxPlatform::GetLog(eGfxLog aWhichLog
) {
2234 // logs shared across gfx
2235 static LazyLogModule
sFontlistLog("fontlist");
2236 static LazyLogModule
sFontInitLog("fontinit");
2237 static LazyLogModule
sTextrunLog("textrun");
2238 static LazyLogModule
sTextrunuiLog("textrunui");
2239 static LazyLogModule
sCmapDataLog("cmapdata");
2240 static LazyLogModule
sTextPerfLog("textperf");
2242 switch (aWhichLog
) {
2243 case eGfxLog_fontlist
:
2244 return sFontlistLog
;
2245 case eGfxLog_fontinit
:
2246 return sFontInitLog
;
2247 case eGfxLog_textrun
:
2249 case eGfxLog_textrunui
:
2250 return sTextrunuiLog
;
2251 case eGfxLog_cmapdata
:
2252 return sCmapDataLog
;
2253 case eGfxLog_textperf
:
2254 return sTextPerfLog
;
2257 MOZ_ASSERT_UNREACHABLE("Unexpected log type");
2261 RefPtr
<mozilla::gfx::DrawTarget
> gfxPlatform::ScreenReferenceDrawTarget() {
2262 return (mScreenReferenceDrawTarget
)
2263 ? mScreenReferenceDrawTarget
2264 : gPlatform
->CreateOffscreenContentDrawTarget(
2265 IntSize(1, 1), SurfaceFormat::B8G8R8A8
, true);
2268 mozilla::gfx::SurfaceFormat
gfxPlatform::Optimal2DFormatForContent(
2269 gfxContentType aContent
) {
2271 case gfxContentType::COLOR
:
2272 switch (GetOffscreenFormat()) {
2273 case SurfaceFormat::A8R8G8B8_UINT32
:
2274 return mozilla::gfx::SurfaceFormat::B8G8R8A8
;
2275 case SurfaceFormat::X8R8G8B8_UINT32
:
2276 return mozilla::gfx::SurfaceFormat::B8G8R8X8
;
2277 case SurfaceFormat::R5G6B5_UINT16
:
2278 return mozilla::gfx::SurfaceFormat::R5G6B5_UINT16
;
2280 MOZ_ASSERT_UNREACHABLE(
2281 "unknown gfxImageFormat for "
2282 "gfxContentType::COLOR");
2283 return mozilla::gfx::SurfaceFormat::B8G8R8A8
;
2285 case gfxContentType::ALPHA
:
2286 return mozilla::gfx::SurfaceFormat::A8
;
2287 case gfxContentType::COLOR_ALPHA
:
2288 return mozilla::gfx::SurfaceFormat::B8G8R8A8
;
2290 MOZ_ASSERT_UNREACHABLE("unknown gfxContentType");
2291 return mozilla::gfx::SurfaceFormat::B8G8R8A8
;
2295 gfxImageFormat
gfxPlatform::OptimalFormatForContent(gfxContentType aContent
) {
2297 case gfxContentType::COLOR
:
2298 return GetOffscreenFormat();
2299 case gfxContentType::ALPHA
:
2300 return SurfaceFormat::A8
;
2301 case gfxContentType::COLOR_ALPHA
:
2302 return SurfaceFormat::A8R8G8B8_UINT32
;
2304 MOZ_ASSERT_UNREACHABLE("unknown gfxContentType");
2305 return SurfaceFormat::A8R8G8B8_UINT32
;
2310 * There are a number of layers acceleration (or layers in general) preferences
2311 * that should be consistent for the lifetime of the application (bug 840967).
2312 * As such, we will evaluate them all as soon as one of them is evaluated
2313 * and remember the values. Changing these preferences during the run will
2314 * not have any effect until we restart.
2316 static mozilla::Atomic
<bool> sLayersSupportsHardwareVideoDecoding(false);
2317 static bool sLayersHardwareVideoDecodingFailed
= false;
2319 static mozilla::Atomic
<bool> sLayersAccelerationPrefsInitialized(false);
2321 static void VideoDecodingFailedChangedCallback(const char* aPref
, void*) {
2322 sLayersHardwareVideoDecodingFailed
= Preferences::GetBool(aPref
, false);
2323 gfxPlatform::GetPlatform()->UpdateCanUseHardwareVideoDecoding();
2326 void gfxPlatform::UpdateCanUseHardwareVideoDecoding() {
2327 if (XRE_IsParentProcess()) {
2328 gfxVars::SetCanUseHardwareVideoDecoding(CanUseHardwareVideoDecoding());
2332 void gfxPlatform::UpdateForceSubpixelAAWherePossible() {
2333 bool forceSubpixelAAWherePossible
=
2334 StaticPrefs::gfx_webrender_quality_force_subpixel_aa_where_possible();
2335 gfxVars::SetForceSubpixelAAWherePossible(forceSubpixelAAWherePossible
);
2338 void gfxPlatform::InitAcceleration() {
2339 if (sLayersAccelerationPrefsInitialized
) {
2343 InitCompositorAccelerationPrefs();
2345 // If this is called for the first time on a non-main thread, we're screwed.
2346 // At the moment there's no explicit guarantee that the main thread calls
2347 // this before the compositor thread, but let's at least make the assumption
2349 MOZ_ASSERT(NS_IsMainThread(), "can only initialize prefs on the main thread");
2351 nsCOMPtr
<nsIGfxInfo
> gfxInfo
= components::GfxInfo::Service();
2352 nsCString discardFailureId
;
2355 if (XRE_IsParentProcess()) {
2356 gfxVars::SetBrowserTabsRemoteAutostart(BrowserTabsRemoteAutostart());
2357 gfxVars::SetOffscreenFormat(GetOffscreenFormat());
2358 gfxVars::SetRequiresAcceleratedGLContextForCompositorOGL(
2359 RequiresAcceleratedGLContextForCompositorOGL());
2362 gfxInfo
->GetFeatureStatus(nsIGfxInfo::FEATURE_D3D11_KEYED_MUTEX
,
2363 discardFailureId
, &status
))) {
2364 gfxVars::SetAllowD3D11KeyedMutex(status
== nsIGfxInfo::FEATURE_STATUS_OK
);
2366 // If we couldn't properly evaluate the status, err on the side
2367 // of caution and give this functionality to the user.
2368 gfxCriticalNote
<< "Cannot evaluate keyed mutex feature status";
2369 gfxVars::SetAllowD3D11KeyedMutex(true);
2371 if (StaticPrefs::gfx_direct3d11_use_double_buffering() &&
2373 gfxVars::SetUseDoubleBufferingWithCompositor(true);
2378 if (Preferences::GetBool("media.hardware-video-decoding.enabled", false) &&
2380 Preferences::GetBool("media.wmf.dxva.enabled", true) &&
2383 gfxInfo
->GetFeatureStatus(nsIGfxInfo::FEATURE_HARDWARE_VIDEO_DECODING
,
2384 discardFailureId
, &status
))) {
2385 if (status
== nsIGfxInfo::FEATURE_STATUS_OK
||
2387 StaticPrefs::media_ffmpeg_vaapi_enabled() ||
2389 StaticPrefs::media_hardware_video_decoding_force_enabled_AtStartup()) {
2390 sLayersSupportsHardwareVideoDecoding
= true;
2395 sLayersSupportsHardwareVideoDecoding
=
2396 gfxPlatformGtk::GetPlatform()->InitVAAPIConfig(
2397 sLayersSupportsHardwareVideoDecoding
);
2400 sLayersAccelerationPrefsInitialized
= true;
2402 if (XRE_IsParentProcess()) {
2403 Preferences::RegisterCallbackAndCall(
2404 VideoDecodingFailedChangedCallback
,
2405 "media.hardware-video-decoding.failed");
2406 InitGPUProcessPrefs();
2408 gfxVars::SetRemoteCanvasEnabled(StaticPrefs::gfx_canvas_remote() &&
2409 gfxConfig::IsEnabled(Feature::GPU_PROCESS
));
2413 void gfxPlatform::InitGPUProcessPrefs() {
2414 // We want to hide this from about:support, so only set a default if the
2415 // pref is known to be true.
2416 if (!StaticPrefs::layers_gpu_process_enabled_AtStartup() &&
2417 !StaticPrefs::layers_gpu_process_force_enabled_AtStartup()) {
2421 FeatureState
& gpuProc
= gfxConfig::GetFeature(Feature::GPU_PROCESS
);
2423 // We require E10S - otherwise, there is very little benefit to the GPU
2424 // process, since the UI process must still use acceleration for
2426 if (!BrowserTabsRemoteAutostart()) {
2427 gpuProc
.DisableByDefault(FeatureStatus::Unavailable
,
2428 "Multi-process mode is not enabled",
2429 "FEATURE_FAILURE_NO_E10S"_ns
);
2431 gpuProc
.SetDefaultFromPref(
2432 StaticPrefs::GetPrefName_layers_gpu_process_enabled(), true,
2433 StaticPrefs::GetPrefDefault_layers_gpu_process_enabled());
2436 if (StaticPrefs::layers_gpu_process_force_enabled_AtStartup()) {
2437 gpuProc
.UserForceEnable("User force-enabled via pref");
2441 nsCString failureId
;
2442 if (!gfxPlatform::IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_GPU_PROCESS
,
2443 &message
, failureId
)) {
2444 gpuProc
.Disable(FeatureStatus::Blocklisted
, message
.get(), failureId
);
2449 gpuProc
.ForceDisable(FeatureStatus::Blocked
, "Headless mode is enabled",
2450 "FEATURE_FAILURE_HEADLESS_MODE"_ns
);
2454 gpuProc
.ForceDisable(FeatureStatus::Blocked
, "Safe-mode is enabled",
2455 "FEATURE_FAILURE_SAFE_MODE"_ns
);
2459 InitPlatformGPUProcessPrefs();
2462 void gfxPlatform::InitCompositorAccelerationPrefs() {
2463 const char* acceleratedEnv
= PR_GetEnv("MOZ_ACCELERATED");
2465 FeatureState
& feature
= gfxConfig::GetFeature(Feature::HW_COMPOSITING
);
2467 // Base value - does the platform allow acceleration?
2468 if (feature
.SetDefault(AccelerateLayersByDefault(), FeatureStatus::Blocked
,
2469 "Acceleration blocked by platform")) {
2471 layers_acceleration_disabled_AtStartup_DoNotUseDirectly()) {
2472 feature
.UserDisable("Disabled by layers.acceleration.disabled=true",
2473 "FEATURE_FAILURE_COMP_PREF"_ns
);
2474 } else if (acceleratedEnv
&& *acceleratedEnv
== '0') {
2475 feature
.UserDisable("Disabled by envvar", "FEATURE_FAILURE_COMP_ENV"_ns
);
2478 if (acceleratedEnv
&& *acceleratedEnv
== '1') {
2479 feature
.UserEnable("Enabled by envvar");
2483 // This has specific meaning elsewhere, so we always record it.
2485 layers_acceleration_force_enabled_AtStartup_DoNotUseDirectly()) {
2486 feature
.UserForceEnable("Force-enabled by pref");
2489 // Safe, headless, and record/replay modes override everything.
2491 feature
.ForceDisable(FeatureStatus::Blocked
,
2492 "Acceleration blocked by safe-mode",
2493 "FEATURE_FAILURE_COMP_SAFEMODE"_ns
);
2496 feature
.ForceDisable(FeatureStatus::Blocked
,
2497 "Acceleration blocked by headless mode",
2498 "FEATURE_FAILURE_COMP_HEADLESSMODE"_ns
);
2503 bool gfxPlatform::WebRenderPrefEnabled() {
2504 return StaticPrefs::gfx_webrender_all_AtStartup() ||
2505 StaticPrefs::gfx_webrender_enabled_AtStartup_DoNotUseDirectly();
2509 bool gfxPlatform::WebRenderEnvvarEnabled() {
2510 const char* env
= PR_GetEnv("MOZ_WEBRENDER");
2511 return (env
&& *env
== '1');
2514 /* static */ const char* gfxPlatform::WebRenderResourcePathOverride() {
2515 const char* resourcePath
= PR_GetEnv("WR_RESOURCE_PATH");
2516 if (!resourcePath
|| resourcePath
[0] == '\0') {
2519 return resourcePath
;
2522 void gfxPlatform::InitWebRenderConfig() {
2523 bool prefEnabled
= WebRenderPrefEnabled();
2524 bool envvarEnabled
= WebRenderEnvvarEnabled();
2526 // WR? WR+ => means WR was enabled via gfx.webrender.all.qualified on
2527 // qualified hardware
2528 // WR! WR+ => means WR was enabled via gfx.webrender.{all,enabled} or
2529 // envvar, possibly on unqualified hardware
2530 // In all cases WR- means WR was not enabled, for one of many possible
2531 // reasons. Prior to bug 1523788 landing the gfx.webrender.{all,enabled}
2532 // prefs only worked on Nightly so keep that in mind when looking at older
2534 ScopedGfxFeatureReporter
reporter("WR", prefEnabled
|| envvarEnabled
);
2535 if (!XRE_IsParentProcess()) {
2536 // The parent process runs through all the real decision-making code
2537 // later in this function. For other processes we still want to report
2538 // the state of the feature for crash reports.
2539 if (gfxVars::UseWebRender()) {
2540 reporter
.SetSuccessful();
2545 // Update the gfxConfig feature states.
2546 gfxConfigManager manager
;
2548 manager
.ConfigureWebRender();
2550 bool hasHardware
= gfxConfig::IsEnabled(Feature::WEBRENDER
);
2551 bool hasSoftware
= gfxConfig::IsEnabled(Feature::WEBRENDER_SOFTWARE
);
2552 bool hasWebRender
= hasHardware
|| hasSoftware
;
2554 #ifdef MOZ_WIDGET_GTK
2555 // We require a hardware driver to back the GL context unless the user forced
2557 if (!gfxConfig::IsForcedOnByUser(Feature::WEBRENDER
) &&
2558 StaticPrefs::gfx_webrender_reject_software_driver_AtStartup()) {
2559 gfxVars::SetWebRenderRequiresHardwareDriver(true);
2564 if (gfxConfig::IsEnabled(Feature::WEBRENDER_ANGLE
)) {
2565 gfxVars::SetUseWebRenderANGLE(hasWebRender
);
2569 if (gfxConfig::IsEnabled(Feature::WEBRENDER_SHADER_CACHE
)) {
2570 gfxVars::SetUseWebRenderProgramBinaryDisk(hasWebRender
);
2573 gfxVars::SetUseWebRenderOptimizedShaders(
2574 gfxConfig::IsEnabled(Feature::WEBRENDER_OPTIMIZED_SHADERS
));
2576 gfxVars::SetUseSoftwareWebRender(!hasHardware
&& hasSoftware
);
2578 Preferences::RegisterPrefixCallbackAndCall(SwapIntervalPrefChangeCallback
,
2579 "gfx.swap-interval");
2581 // gfxFeature is not usable in the GPU process, so we use gfxVars to transmit
2584 gfxVars::SetUseWebRender(true);
2585 reporter
.SetSuccessful();
2587 Preferences::RegisterPrefixCallbackAndCall(WebRenderDebugPrefChangeCallback
,
2590 RegisterWebRenderBoolParamCallback();
2592 Preferences::RegisterPrefixCallbackAndCall(
2593 WebRendeProfilerUIPrefChangeCallback
,
2594 "gfx.webrender.debug.profiler-ui");
2595 Preferences::RegisterCallback(
2596 WebRenderQualityPrefChangeCallback
,
2599 GetPrefName_gfx_webrender_quality_force_subpixel_aa_where_possible()));
2601 Preferences::RegisterCallback(
2602 WebRenderBatchingPrefChangeCallback
,
2604 StaticPrefs::GetPrefName_gfx_webrender_batching_lookback()));
2606 Preferences::RegisterCallbackAndCall(
2607 WebRenderBlobTileSizePrefChangeCallback
,
2609 StaticPrefs::GetPrefName_gfx_webrender_blob_tile_size()));
2611 Preferences::RegisterCallbackAndCall(
2612 WebRenderUploadThresholdPrefChangeCallback
,
2614 StaticPrefs::GetPrefName_gfx_webrender_batched_upload_threshold()));
2616 if (WebRenderResourcePathOverride()) {
2617 CrashReporter::AnnotateCrashReport(
2618 CrashReporter::Annotation::IsWebRenderResourcePathOverridden
, true);
2621 UpdateForceSubpixelAAWherePossible();
2625 if (gfxConfig::IsEnabled(Feature::WEBRENDER_DCOMP_PRESENT
)) {
2626 gfxVars::SetUseWebRenderDCompWin(true);
2628 if (StaticPrefs::gfx_webrender_software_d3d11_AtStartup()) {
2629 gfxVars::SetAllowSoftwareWebRenderD3D11(true);
2632 bool useVideoOverlay
= false;
2633 if (StaticPrefs::gfx_webrender_dcomp_video_overlay_win_AtStartup()) {
2634 if (IsWin10AnniversaryUpdateOrLater() &&
2635 gfxConfig::IsEnabled(Feature::WEBRENDER_COMPOSITOR
)) {
2636 MOZ_ASSERT(gfxConfig::IsEnabled(Feature::WEBRENDER_DCOMP_PRESENT
));
2637 useVideoOverlay
= true;
2640 if (useVideoOverlay
&&
2642 gfx_webrender_dcomp_video_overlay_win_force_enabled_AtStartup()) {
2643 nsCString failureId
;
2645 const nsCOMPtr
<nsIGfxInfo
> gfxInfo
= components::GfxInfo::Service();
2646 if (NS_FAILED(gfxInfo
->GetFeatureStatus(nsIGfxInfo::FEATURE_VIDEO_OVERLAY
,
2647 failureId
, &status
))) {
2648 FeatureState
& feature
= gfxConfig::GetFeature(Feature::VIDEO_OVERLAY
);
2649 feature
.DisableByDefault(FeatureStatus::BlockedNoGfxInfo
,
2650 "gfxInfo is broken",
2651 "FEATURE_FAILURE_WR_NO_GFX_INFO"_ns
);
2652 useVideoOverlay
= false;
2654 if (status
!= nsIGfxInfo::FEATURE_ALLOW_ALWAYS
) {
2655 FeatureState
& feature
= gfxConfig::GetFeature(Feature::VIDEO_OVERLAY
);
2656 feature
.DisableByDefault(FeatureStatus::Blocked
,
2657 "Blocklisted by gfxInfo", failureId
);
2658 useVideoOverlay
= false;
2664 if (useVideoOverlay
) {
2665 FeatureState
& feature
= gfxConfig::GetFeature(Feature::VIDEO_OVERLAY
);
2666 feature
.EnableByDefault();
2667 gfxVars::SetUseWebRenderDCompVideoOverlayWin(true);
2670 bool useHwVideoZeroCopy
= false;
2671 if (StaticPrefs::media_wmf_zero_copy_nv12_textures_AtStartup()) {
2672 // XXX relax limitation to Windows 8.1
2673 if (IsWin10OrLater() && hasHardware
) {
2674 useHwVideoZeroCopy
= true;
2677 if (useHwVideoZeroCopy
&&
2679 media_wmf_zero_copy_nv12_textures_force_enabled_AtStartup()) {
2680 nsCString failureId
;
2682 const nsCOMPtr
<nsIGfxInfo
> gfxInfo
= components::GfxInfo::Service();
2683 if (NS_FAILED(gfxInfo
->GetFeatureStatus(
2684 nsIGfxInfo::FEATURE_HW_DECODED_VIDEO_ZERO_COPY
, failureId
,
2686 FeatureState
& feature
=
2687 gfxConfig::GetFeature(Feature::HW_DECODED_VIDEO_ZERO_COPY
);
2688 feature
.DisableByDefault(FeatureStatus::BlockedNoGfxInfo
,
2689 "gfxInfo is broken",
2690 "FEATURE_FAILURE_WR_NO_GFX_INFO"_ns
);
2691 useHwVideoZeroCopy
= false;
2693 if (status
!= nsIGfxInfo::FEATURE_ALLOW_ALWAYS
) {
2694 FeatureState
& feature
=
2695 gfxConfig::GetFeature(Feature::HW_DECODED_VIDEO_ZERO_COPY
);
2696 feature
.DisableByDefault(FeatureStatus::Blocked
,
2697 "Blocklisted by gfxInfo", failureId
);
2698 useHwVideoZeroCopy
= false;
2704 if (useHwVideoZeroCopy
) {
2705 FeatureState
& feature
=
2706 gfxConfig::GetFeature(Feature::HW_DECODED_VIDEO_ZERO_COPY
);
2707 feature
.EnableByDefault();
2708 gfxVars::SetHwDecodedVideoZeroCopy(true);
2711 bool reuseDecoderDevice
= false;
2712 if (StaticPrefs::gfx_direct3d11_reuse_decoder_device_AtStartup()) {
2713 reuseDecoderDevice
= true;
2715 if (reuseDecoderDevice
&&
2717 gfx_direct3d11_reuse_decoder_device_force_enabled_AtStartup()) {
2718 nsCString failureId
;
2720 const nsCOMPtr
<nsIGfxInfo
> gfxInfo
= components::GfxInfo::Service();
2721 if (NS_FAILED(gfxInfo
->GetFeatureStatus(
2722 nsIGfxInfo::FEATURE_REUSE_DECODER_DEVICE
, failureId
, &status
))) {
2723 FeatureState
& feature
=
2724 gfxConfig::GetFeature(Feature::REUSE_DECODER_DEVICE
);
2725 feature
.DisableByDefault(FeatureStatus::BlockedNoGfxInfo
,
2726 "gfxInfo is broken",
2727 "FEATURE_FAILURE_WR_NO_GFX_INFO"_ns
);
2728 reuseDecoderDevice
= false;
2730 if (status
!= nsIGfxInfo::FEATURE_ALLOW_ALWAYS
) {
2731 FeatureState
& feature
=
2732 gfxConfig::GetFeature(Feature::REUSE_DECODER_DEVICE
);
2733 feature
.DisableByDefault(FeatureStatus::Blocked
,
2734 "Blocklisted by gfxInfo", failureId
);
2735 reuseDecoderDevice
= false;
2741 if (reuseDecoderDevice
) {
2742 FeatureState
& feature
=
2743 gfxConfig::GetFeature(Feature::REUSE_DECODER_DEVICE
);
2744 feature
.EnableByDefault();
2745 gfxVars::SetReuseDecoderDevice(true);
2748 if (Preferences::GetBool("gfx.webrender.flip-sequential", false)) {
2749 if (UseWebRender() && gfxVars::UseWebRenderANGLE()) {
2750 gfxVars::SetUseWebRenderFlipSequentialWin(true);
2753 if (Preferences::GetBool("gfx.webrender.triple-buffering.enabled", false)) {
2754 if (gfxVars::UseWebRenderDCompWin() ||
2755 gfxVars::UseWebRenderFlipSequentialWin()) {
2756 gfxVars::SetUseWebRenderTripleBufferingWin(true);
2761 if (gfxConfig::IsEnabled(Feature::WEBRENDER_COMPOSITOR
)) {
2762 gfxVars::SetUseWebRenderCompositor(true);
2765 Telemetry::ScalarSet(
2766 Telemetry::ScalarID::GFX_OS_COMPOSITOR
,
2767 gfx::gfxConfig::IsEnabled(gfx::Feature::WEBRENDER_COMPOSITOR
));
2769 if (gfxConfig::IsEnabled(Feature::WEBRENDER_PARTIAL
)) {
2770 gfxVars::SetWebRenderMaxPartialPresentRects(
2771 StaticPrefs::gfx_webrender_max_partial_present_rects_AtStartup());
2774 // Set features that affect WR's RendererOptions
2775 gfxVars::SetUseGLSwizzle(
2776 IsFeatureSupported(nsIGfxInfo::FEATURE_GL_SWIZZLE
, true));
2777 gfxVars::SetUseWebRenderScissoredCacheClears(IsFeatureSupported(
2778 nsIGfxInfo::FEATURE_WEBRENDER_SCISSORED_CACHE_CLEARS
, true));
2780 // The RemoveShaderCacheFromDiskIfNecessary() needs to be called after
2781 // WebRenderConfig initialization.
2782 gfxUtils::RemoveShaderCacheFromDiskIfNecessary();
2785 void gfxPlatform::InitHardwareVideoConfig() {
2786 if (!XRE_IsParentProcess()) {
2791 nsCString failureId
;
2793 FeatureState
& featureVP8
= gfxConfig::GetFeature(Feature::VP8_HW_DECODE
);
2794 #ifndef MOZ_WIDGET_GTK
2795 featureVP8
.EnableByDefault();
2798 if (!IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_VP8_HW_DECODE
, &message
,
2800 featureVP8
.Disable(FeatureStatus::Blocklisted
, message
.get(), failureId
);
2803 gfxVars::SetUseVP8HwDecode(featureVP8
.IsEnabled());
2805 FeatureState
& featureVP9
= gfxConfig::GetFeature(Feature::VP9_HW_DECODE
);
2806 #ifndef MOZ_WIDGET_GTK
2807 featureVP9
.EnableByDefault();
2809 if (!IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_VP9_HW_DECODE
, &message
,
2811 featureVP9
.Disable(FeatureStatus::Blocklisted
, message
.get(), failureId
);
2814 gfxVars::SetUseVP9HwDecode(featureVP9
.IsEnabled());
2817 void gfxPlatform::InitWebGLConfig() {
2818 // Depends on InitWebRenderConfig() for UseWebRender().
2820 if (!XRE_IsParentProcess()) return;
2822 const nsCOMPtr
<nsIGfxInfo
> gfxInfo
= components::GfxInfo::Service();
2824 const auto IsFeatureOk
= [&](const int32_t feature
) {
2825 nsCString discardFailureId
;
2827 MOZ_RELEASE_ASSERT(NS_SUCCEEDED(
2828 gfxInfo
->GetFeatureStatus(feature
, discardFailureId
, &status
)));
2829 return (status
== nsIGfxInfo::FEATURE_STATUS_OK
);
2832 gfxVars::SetAllowWebgl2(IsFeatureOk(nsIGfxInfo::FEATURE_WEBGL2
));
2833 gfxVars::SetWebglAllowWindowsNativeGl(
2834 IsFeatureOk(nsIGfxInfo::FEATURE_WEBGL_OPENGL
));
2835 gfxVars::SetAllowWebglAccelAngle(
2836 IsFeatureOk(nsIGfxInfo::FEATURE_WEBGL_ANGLE
));
2839 // Avoid crash for Intel HD Graphics 3000 on OSX. (Bug 1413269)
2840 nsString vendorID
, deviceID
;
2841 gfxInfo
->GetAdapterVendorID(vendorID
);
2842 gfxInfo
->GetAdapterDeviceID(deviceID
);
2843 if (vendorID
.EqualsLiteral("0x8086") &&
2844 (deviceID
.EqualsLiteral("0x0116") ||
2845 deviceID
.EqualsLiteral("0x0126"))) {
2846 gfxVars::SetWebglAllowCoreProfile(false);
2850 bool allowWebGLOop
=
2851 IsFeatureOk(nsIGfxInfo::FEATURE_ALLOW_WEBGL_OUT_OF_PROCESS
);
2852 gfxVars::SetAllowWebglOop(allowWebGLOop
);
2854 bool threadsafeGL
= IsFeatureOk(nsIGfxInfo::FEATURE_THREADSAFE_GL
);
2855 threadsafeGL
|= StaticPrefs::webgl_threadsafe_gl_force_enabled_AtStartup();
2856 threadsafeGL
&= !StaticPrefs::webgl_threadsafe_gl_force_disabled_AtStartup();
2857 gfxVars::SetSupportsThreadsafeGL(threadsafeGL
);
2860 // Don't enable robust buffer access on Adreno 630 devices.
2861 // It causes the linking of some shaders to fail. See bug 1485441.
2862 nsAutoString renderer
;
2863 gfxInfo
->GetAdapterDeviceID(renderer
);
2864 if (renderer
.Find("Adreno (TM) 630") != -1) {
2865 gfxVars::SetAllowEglRbab(false);
2869 if (kIsWayland
|| kIsX11
) {
2870 nsCString discardFailureId
;
2872 FeatureState
& feature
=
2873 gfxConfig::GetFeature(Feature::DMABUF_SURFACE_EXPORT
);
2875 gfxInfo
->GetFeatureStatus(nsIGfxInfo::FEATURE_DMABUF_SURFACE_EXPORT
,
2876 discardFailureId
, &status
)) ||
2877 status
!= nsIGfxInfo::FEATURE_STATUS_OK
) {
2878 feature
.DisableByDefault(FeatureStatus::Blocked
, "Blocklisted by gfxInfo",
2880 gfxVars::SetUseDMABufSurfaceExport(false);
2882 feature
.EnableByDefault();
2887 void gfxPlatform::InitWebGPUConfig() {
2888 if (!XRE_IsParentProcess()) {
2892 FeatureState
& feature
= gfxConfig::GetFeature(Feature::WEBGPU
);
2893 feature
.SetDefaultFromPref("dom.webgpu.enabled", true, false);
2896 nsCString failureId
;
2897 if (!IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_WEBGPU
, &message
, failureId
)) {
2898 feature
.Disable(FeatureStatus::Blocklisted
, message
.get(), failureId
);
2901 #ifdef RELEASE_OR_BETA
2902 feature
.ForceDisable(FeatureStatus::Blocked
,
2903 "WebGPU cannot be enabled in release or beta",
2904 "WEBGPU_DISABLE_RELEASE_OR_BETA"_ns
);
2906 if (StaticPrefs::gfx_webgpu_force_enabled_AtStartup()) {
2907 feature
.UserForceEnable("Force-enabled by pref");
2911 gfxVars::SetAllowWebGPU(feature
.IsEnabled());
2915 static void WindowOcclusionPrefChangeCallback(const char* aPref
, void*) {
2916 const char* env
= PR_GetEnv("MOZ_WINDOW_OCCLUSION");
2918 // env has a higher priority than pref.
2922 FeatureState
& feature
= gfxConfig::GetFeature(Feature::WINDOW_OCCLUSION
);
2924 StaticPrefs::widget_windows_window_occlusion_tracking_enabled();
2926 printf_stderr("Dynamically enable window occlusion %d\n", enabled
);
2928 // Update feature before calling WinUtils::EnableWindowOcclusion()
2930 feature
.UserEnable("User enabled by pref");
2932 feature
.UserDisable("User disabled via pref",
2933 "FEATURE_FAILURE_PREF_DISABLED"_ns
);
2935 widget::WinUtils::EnableWindowOcclusion(enabled
);
2939 void gfxPlatform::InitWindowOcclusionConfig() {
2940 if (!XRE_IsParentProcess()) {
2944 FeatureState
& feature
= gfxConfig::GetFeature(Feature::WINDOW_OCCLUSION
);
2945 feature
.SetDefaultFromPref(
2947 GetPrefName_widget_windows_window_occlusion_tracking_enabled(),
2950 GetPrefDefault_widget_windows_window_occlusion_tracking_enabled());
2952 const char* env
= PR_GetEnv("MOZ_WINDOW_OCCLUSION");
2955 feature
.UserForceEnable("Force enabled by envvar");
2957 feature
.UserDisable("Force disabled by envvar",
2958 "FEATURE_FAILURE_OCCL_ENV"_ns
);
2962 Preferences::RegisterCallback(
2963 WindowOcclusionPrefChangeCallback
,
2966 GetPrefName_widget_windows_window_occlusion_tracking_enabled()));
2970 bool gfxPlatform::CanUseHardwareVideoDecoding() {
2971 // this function is called from the compositor thread, so it is not
2972 // safe to init the prefs etc. from here.
2973 MOZ_ASSERT(sLayersAccelerationPrefsInitialized
);
2974 return sLayersSupportsHardwareVideoDecoding
&&
2975 !sLayersHardwareVideoDecodingFailed
;
2978 bool gfxPlatform::AccelerateLayersByDefault() {
2979 #if defined(MOZ_GL_PROVIDER) || defined(MOZ_WIDGET_UIKIT)
2987 bool gfxPlatform::UsesOffMainThreadCompositing() {
2988 if (XRE_GetProcessType() == GeckoProcessType_GPU
) {
2992 static bool firstTime
= true;
2993 static bool result
= false;
2996 MOZ_ASSERT(sLayersAccelerationPrefsInitialized
);
2997 result
= gfxVars::BrowserTabsRemoteAutostart() ||
2999 layers_offmainthreadcomposition_force_disabled_AtStartup();
3000 #if defined(MOZ_WIDGET_GTK)
3001 // Linux users who chose OpenGL are being included in OMTC
3002 result
|= StaticPrefs::
3003 layers_acceleration_force_enabled_AtStartup_DoNotUseDirectly();
3012 RefPtr
<mozilla::VsyncDispatcher
> gfxPlatform::GetGlobalVsyncDispatcher() {
3013 MOZ_ASSERT(mVsyncDispatcher
,
3014 "mVsyncDispatcher should have been initialized by ReInitFrameRate "
3015 "during gfxPlatform init");
3016 MOZ_ASSERT(XRE_IsParentProcess());
3017 return mVsyncDispatcher
;
3020 already_AddRefed
<mozilla::gfx::VsyncSource
>
3021 gfxPlatform::GetGlobalHardwareVsyncSource() {
3022 if (!mGlobalHardwareVsyncSource
) {
3023 mGlobalHardwareVsyncSource
= CreateGlobalHardwareVsyncSource();
3025 return do_AddRef(mGlobalHardwareVsyncSource
);
3029 * The preference "layout.frame_rate" has 3 meanings depending on the value:
3031 * -1 = Auto (default), use hardware vsync or software vsync @ 60 hz if hw
3033 * 0 = ASAP mode - used during talos testing.
3034 * X = Software vsync at a rate of X times per second.
3036 already_AddRefed
<mozilla::gfx::VsyncSource
>
3037 gfxPlatform::GetSoftwareVsyncSource() {
3038 if (!mSoftwareVsyncSource
) {
3039 double rateInMS
= 1000.0 / (double)gfxPlatform::GetSoftwareVsyncRate();
3040 mSoftwareVsyncSource
= new mozilla::gfx::SoftwareVsyncSource(
3041 TimeDuration::FromMilliseconds(rateInMS
));
3043 return do_AddRef(mSoftwareVsyncSource
);
3047 bool gfxPlatform::IsInLayoutAsapMode() {
3048 // There are 2 modes of ASAP mode.
3049 // 1 is that the refresh driver and compositor are in lock step
3050 // the second is that the compositor goes ASAP and the refresh driver
3051 // goes at whatever the configurated rate is. This only checks the version
3052 // talos uses, which is the refresh driver and compositor are in lockstep.
3053 // Ignore privacy_resistFingerprinting to preserve ASAP mode there.
3054 return StaticPrefs::layout_frame_rate() == 0;
3057 static int LayoutFrameRateFromPrefs() {
3058 auto val
= StaticPrefs::layout_frame_rate();
3059 if (StaticPrefs::privacy_resistFingerprinting()) {
3066 bool gfxPlatform::ForceSoftwareVsync() {
3067 return LayoutFrameRateFromPrefs() > 0;
3071 int gfxPlatform::GetSoftwareVsyncRate() {
3072 int preferenceRate
= LayoutFrameRateFromPrefs();
3073 if (preferenceRate
<= 0) {
3074 return gfxPlatform::GetDefaultFrameRate();
3076 return preferenceRate
;
3080 int gfxPlatform::GetDefaultFrameRate() { return 60; }
3083 void gfxPlatform::ReInitFrameRate(const char* aPrefIgnored
,
3084 void* aDataIgnored
) {
3085 MOZ_RELEASE_ASSERT(XRE_IsParentProcess());
3087 if (gPlatform
->mSoftwareVsyncSource
) {
3088 // Update the rate of the existing software vsync source.
3089 double rateInMS
= 1000.0 / (double)gfxPlatform::GetSoftwareVsyncRate();
3090 gPlatform
->mSoftwareVsyncSource
->SetVsyncRate(
3091 TimeDuration::FromMilliseconds(rateInMS
));
3094 // Swap out the dispatcher's underlying source.
3095 RefPtr
<VsyncSource
> vsyncSource
=
3096 gfxPlatform::ForceSoftwareVsync()
3097 ? gPlatform
->GetSoftwareVsyncSource()
3098 : gPlatform
->GetGlobalHardwareVsyncSource();
3099 gPlatform
->mVsyncDispatcher
->SetVsyncSource(vsyncSource
);
3102 const char* gfxPlatform::GetAzureCanvasBackend() const {
3103 BackendType backend
{};
3105 if (gfxConfig::IsEnabled(Feature::GPU_PROCESS
)) {
3106 // Assume content process' backend prefs.
3107 BackendPrefsData data
= GetBackendPrefs();
3108 backend
= GetCanvasBackendPref(data
.mCanvasBitmask
);
3109 if (backend
== BackendType::NONE
) {
3110 backend
= data
.mCanvasDefault
;
3113 backend
= mPreferredCanvasBackend
;
3116 return GetBackendName(backend
);
3119 const char* gfxPlatform::GetAzureContentBackend() const {
3120 BackendType backend
{};
3122 if (gfxConfig::IsEnabled(Feature::GPU_PROCESS
)) {
3123 // Assume content process' backend prefs.
3124 BackendPrefsData data
= GetBackendPrefs();
3125 backend
= GetContentBackendPref(data
.mContentBitmask
);
3126 if (backend
== BackendType::NONE
) {
3127 backend
= data
.mContentDefault
;
3130 backend
= mContentBackend
;
3133 return GetBackendName(backend
);
3136 void gfxPlatform::GetAzureBackendInfo(mozilla::widget::InfoObject
& aObj
) {
3137 if (gfxConfig::IsEnabled(Feature::GPU_PROCESS
)) {
3138 aObj
.DefineProperty("AzureCanvasBackend (UI Process)",
3139 GetBackendName(mPreferredCanvasBackend
));
3140 aObj
.DefineProperty("AzureFallbackCanvasBackend (UI Process)",
3141 GetBackendName(mFallbackCanvasBackend
));
3142 aObj
.DefineProperty("AzureContentBackend (UI Process)",
3143 GetBackendName(mContentBackend
));
3145 aObj
.DefineProperty("AzureFallbackCanvasBackend",
3146 GetBackendName(mFallbackCanvasBackend
));
3149 aObj
.DefineProperty("AzureCanvasBackend", GetAzureCanvasBackend());
3150 aObj
.DefineProperty("AzureContentBackend", GetAzureContentBackend());
3153 void gfxPlatform::GetApzSupportInfo(mozilla::widget::InfoObject
& aObj
) {
3154 if (!gfxPlatform::AsyncPanZoomEnabled()) {
3158 if (SupportsApzWheelInput()) {
3159 aObj
.DefineProperty("ApzWheelInput", 1);
3162 if (SupportsApzTouchInput()) {
3163 aObj
.DefineProperty("ApzTouchInput", 1);
3166 if (SupportsApzDragInput()) {
3167 aObj
.DefineProperty("ApzDragInput", 1);
3170 if (SupportsApzKeyboardInput() &&
3171 !StaticPrefs::accessibility_browsewithcaret()) {
3172 aObj
.DefineProperty("ApzKeyboardInput", 1);
3175 if (SupportsApzAutoscrolling()) {
3176 aObj
.DefineProperty("ApzAutoscrollInput", 1);
3179 if (SupportsApzZooming()) {
3180 aObj
.DefineProperty("ApzZoomingInput", 1);
3184 void gfxPlatform::GetFrameStats(mozilla::widget::InfoObject
& aObj
) {
3186 for (FrameStats
& f
: mFrameStats
) {
3187 nsPrintfCString
name("Slow Frame #%02u", ++i
);
3189 nsPrintfCString
value(
3191 "(%s) CONTENT_FRAME_TIME %d - Transaction start %f, main-thread time "
3192 "%f, full paint time %f, Skipped composites %u, Composite start %f, "
3193 "Resource upload time %f, GPU cache upload time %f, Render time %f, "
3194 "Composite time %f",
3195 f
.id().mId
, f
.url().get(), f
.contentFrameTime(),
3196 (f
.transactionStart() - f
.refreshStart()).ToMilliseconds(),
3197 (f
.fwdTime() - f
.transactionStart()).ToMilliseconds(),
3199 ? (f
.sceneBuiltTime() - f
.transactionStart()).ToMilliseconds()
3201 f
.skippedComposites(),
3202 (f
.compositeStart() - f
.refreshStart()).ToMilliseconds(),
3203 f
.resourceUploadTime(), f
.gpuCacheUploadTime(),
3204 (f
.compositeEnd() - f
.renderStart()).ToMilliseconds(),
3205 (f
.compositeEnd() - f
.compositeStart()).ToMilliseconds());
3206 aObj
.DefineProperty(name
.get(), value
.get());
3210 void gfxPlatform::GetCMSSupportInfo(mozilla::widget::InfoObject
& aObj
) {
3211 nsTArray
<uint8_t> outputProfileData
=
3212 gfxPlatform::GetPlatform()->GetPlatformCMSOutputProfileData();
3213 if (outputProfileData
.IsEmpty()) {
3214 nsPrintfCString
msg("Empty profile data");
3215 aObj
.DefineProperty("CMSOutputProfile", msg
.get());
3219 // Some profiles can be quite large. We don't want to include giant profiles
3220 // by default in about:support. For now, we only accept less than 8kiB.
3221 const size_t kMaxProfileSize
= 8192;
3222 if (outputProfileData
.Length() >= kMaxProfileSize
) {
3223 nsPrintfCString
msg("%zu bytes, too large", outputProfileData
.Length());
3224 aObj
.DefineProperty("CMSOutputProfile", msg
.get());
3228 nsString encodedProfile
;
3230 Base64Encode(reinterpret_cast<const char*>(outputProfileData
.Elements()),
3231 outputProfileData
.Length(), encodedProfile
);
3232 if (!NS_SUCCEEDED(rv
)) {
3233 nsPrintfCString
msg("base64 encode failed 0x%08x",
3234 static_cast<uint32_t>(rv
));
3235 aObj
.DefineProperty("CMSOutputProfile", msg
.get());
3239 aObj
.DefineProperty("CMSOutputProfile", encodedProfile
);
3242 void gfxPlatform::GetDisplayInfo(mozilla::widget::InfoObject
& aObj
) {
3243 auto& screens
= widget::ScreenManager::GetSingleton().CurrentScreenList();
3244 aObj
.DefineProperty("DisplayCount", screens
.Length());
3247 for (auto& screen
: screens
) {
3248 const LayoutDeviceIntRect rect
= screen
->GetRect();
3249 nsPrintfCString
value("%dx%d@%dHz scales:%f|%f", rect
.width
, rect
.height
,
3250 screen
->GetRefreshRate(),
3251 screen
->GetContentsScaleFactor(),
3252 screen
->GetDefaultCSSScaleFactor());
3254 aObj
.DefineProperty(nsPrintfCString("Display%zu", i
++).get(),
3255 NS_ConvertUTF8toUTF16(value
));
3258 // Platform display info is only currently used for about:support and getting
3259 // it might fail in a child process anyway.
3260 if (XRE_IsParentProcess()) {
3261 GetPlatformDisplayInfo(aObj
);
3265 void gfxPlatform::GetOverlayInfo(mozilla::widget::InfoObject
& aObj
) {
3266 if (mOverlayInfo
.isNothing()) {
3270 auto toString
= [](mozilla::layers::OverlaySupportType aType
) -> const char* {
3272 case mozilla::layers::OverlaySupportType::None
:
3274 case mozilla::layers::OverlaySupportType::Software
:
3276 case mozilla::layers::OverlaySupportType::Direct
:
3278 case mozilla::layers::OverlaySupportType::Scaling
:
3281 MOZ_ASSERT_UNREACHABLE("Unexpected to be called");
3283 MOZ_CRASH("Incomplete switch");
3286 nsPrintfCString
value("NV12=%s YUV2=%s BGRA8=%s RGB10A2=%s",
3287 toString(mOverlayInfo
.ref().mNv12Overlay
),
3288 toString(mOverlayInfo
.ref().mYuy2Overlay
),
3289 toString(mOverlayInfo
.ref().mBgra8Overlay
),
3290 toString(mOverlayInfo
.ref().mRgb10a2Overlay
));
3292 aObj
.DefineProperty("OverlaySupport", NS_ConvertUTF8toUTF16(value
));
3295 class FrameStatsComparator
{
3297 bool Equals(const FrameStats
& aA
, const FrameStats
& aB
) const {
3298 return aA
.contentFrameTime() == aB
.contentFrameTime();
3300 // Reverse the condition here since we want the array sorted largest to
3302 bool LessThan(const FrameStats
& aA
, const FrameStats
& aB
) const {
3303 return aA
.contentFrameTime() > aB
.contentFrameTime();
3307 void gfxPlatform::NotifyFrameStats(nsTArray
<FrameStats
>&& aFrameStats
) {
3308 if (!StaticPrefs::gfx_logging_slow_frames_enabled_AtStartup()) {
3312 FrameStatsComparator comp
;
3313 for (FrameStats
& f
: aFrameStats
) {
3314 mFrameStats
.InsertElementSorted(f
, comp
);
3316 if (mFrameStats
.Length() > 10) {
3317 mFrameStats
.SetLength(10);
3322 uint32_t gfxPlatform::TargetFrameRate() {
3323 if (gPlatform
&& gPlatform
->mVsyncDispatcher
) {
3324 return round(1000.0 /
3325 gPlatform
->mVsyncDispatcher
->GetVsyncRate().ToMilliseconds());
3331 bool gfxPlatform::UseDesktopZoomingScrollbars() {
3332 return StaticPrefs::apz_allow_zooming() &&
3333 !StaticPrefs::apz_force_disable_desktop_zooming_scrollbars();
3337 bool gfxPlatform::AsyncPanZoomEnabled() {
3338 #if !defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_WIDGET_UIKIT)
3339 // For XUL applications (everything but Firefox on Android)
3340 // we only want to use APZ when E10S is enabled. If
3341 // we ever get input events off the main thread we can consider relaxing
3342 // this requirement.
3343 if (!BrowserTabsRemoteAutostart()) {
3347 #ifdef MOZ_WIDGET_ANDROID
3350 // If Fission is enabled, OOP iframes require APZ for hittest. So, we
3351 // need to forcibly enable APZ in that case for avoiding users confused.
3352 if (FissionAutostart()) {
3355 return StaticPrefs::
3356 layers_async_pan_zoom_enabled_AtStartup_DoNotUseDirectly();
3361 bool gfxPlatform::PerfWarnings() {
3362 return StaticPrefs::gfx_perf_warnings_enabled();
3365 void gfxPlatform::NotifyCompositorCreated(LayersBackend aBackend
) {
3366 if (mCompositorBackend
== aBackend
) {
3370 if (mCompositorBackend
!= LayersBackend::LAYERS_NONE
) {
3371 gfxCriticalNote
<< "Compositors might be mixed (" << int(mCompositorBackend
)
3372 << "," << int(aBackend
) << ")";
3375 // Set the backend before we notify so it's available immediately.
3376 mCompositorBackend
= aBackend
;
3378 if (XRE_IsParentProcess()) {
3379 Telemetry::ScalarSet(
3380 Telemetry::ScalarID::GFX_COMPOSITOR
,
3381 NS_ConvertUTF8toUTF16(GetLayersBackendName(mCompositorBackend
)));
3383 nsCString geckoVersion
;
3384 nsCOMPtr
<nsIXULAppInfo
> app
= do_GetService("@mozilla.org/xre/app-info;1");
3386 app
->GetVersion(geckoVersion
);
3388 Telemetry::ScalarSet(Telemetry::ScalarID::GFX_LAST_COMPOSITOR_GECKO_VERSION
,
3389 NS_ConvertASCIItoUTF16(geckoVersion
));
3391 Telemetry::ScalarSet(
3392 Telemetry::ScalarID::GFX_FEATURE_WEBRENDER
,
3393 NS_ConvertUTF8toUTF16(gfxConfig::GetFeature(gfx::Feature::WEBRENDER
)
3394 .GetStatusAndFailureIdString()));
3397 // Notify that we created a compositor, so telemetry can update.
3398 NS_DispatchToMainThread(
3399 NS_NewRunnableFunction("gfxPlatform::NotifyCompositorCreated", [] {
3400 if (nsCOMPtr
<nsIObserverService
> obsvc
=
3401 services::GetObserverService()) {
3402 obsvc
->NotifyObservers(nullptr, "compositor:created", nullptr);
3408 bool gfxPlatform::FallbackFromAcceleration(FeatureStatus aStatus
,
3409 const char* aMessage
,
3410 const nsACString
& aFailureId
,
3411 bool aCrashAfterFinalFallback
) {
3412 // We always want to ensure (Hardware) WebRender is disabled.
3413 if (gfxConfig::IsEnabled(Feature::WEBRENDER
)) {
3414 gfxConfig::GetFeature(Feature::WEBRENDER
)
3415 .ForceDisable(aStatus
, aMessage
, aFailureId
);
3418 // Determine whether or not we are allowed to use Software WebRender in
3419 // fallback without the GPU process. Either the pref is false, or the feature
3420 // is enabled and we are currently still using it.
3421 bool swglFallbackAllowed
=
3423 gfx_webrender_fallback_software_requires_gpu_process_AtStartup() ||
3424 gfxConfig::IsEnabled(Feature::GPU_PROCESS
);
3427 // Before we disable D3D11 and HW_COMPOSITING, we should check if we can
3428 // fallback from WebRender to Software WebRender + D3D11 compositing.
3429 if (StaticPrefs::gfx_webrender_fallback_software_d3d11_AtStartup() &&
3430 swglFallbackAllowed
&& gfxVars::AllowSoftwareWebRenderD3D11() &&
3431 gfxConfig::IsEnabled(Feature::WEBRENDER_SOFTWARE
) &&
3432 gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING
) &&
3433 gfxVars::UseWebRender() && !gfxVars::UseSoftwareWebRender()) {
3434 // Fallback to Software WebRender + D3D11 compositing.
3435 gfxCriticalNote
<< "Fallback WR to SW-WR + D3D11";
3436 gfxVars::SetUseSoftwareWebRender(true);
3440 if (StaticPrefs::gfx_webrender_fallback_software_d3d11_AtStartup() &&
3441 swglFallbackAllowed
&& gfxVars::AllowSoftwareWebRenderD3D11() &&
3442 gfxVars::UseSoftwareWebRender()) {
3443 // Fallback from Software WebRender + D3D11 to Software WebRender.
3444 gfxCriticalNote
<< "Fallback SW-WR + D3D11 to SW-WR";
3445 gfxVars::SetAllowSoftwareWebRenderD3D11(false);
3449 // We aren't using Software WebRender + D3D11 compositing, so turn off the
3451 if (gfxConfig::IsEnabled(Feature::DIRECT2D
)) {
3452 gfxConfig::GetFeature(Feature::DIRECT2D
)
3453 .ForceDisable(aStatus
, aMessage
, aFailureId
);
3455 if (gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING
)) {
3456 gfxConfig::GetFeature(Feature::D3D11_COMPOSITING
)
3457 .ForceDisable(aStatus
, aMessage
, aFailureId
);
3459 if (StaticPrefs::gfx_webrender_fallback_software_AtStartup() &&
3460 swglFallbackAllowed
&&
3461 gfxConfig::IsEnabled(Feature::WEBRENDER_SOFTWARE
) &&
3462 !gfxVars::UseWebRender()) {
3463 // Fallback from D3D11 to Software WebRender.
3464 gfxCriticalNote
<< "Fallback D3D11 to SW-WR";
3465 gfxVars::SetUseWebRender(true);
3466 gfxVars::SetUseSoftwareWebRender(true);
3472 #ifndef MOZ_WIDGET_ANDROID
3473 // Non-Android wants to fallback to Software WebRender or Basic. Android wants
3474 // to fallback to OpenGL.
3475 if (gfxConfig::IsEnabled(Feature::HW_COMPOSITING
)) {
3476 gfxConfig::GetFeature(Feature::HW_COMPOSITING
)
3477 .ForceDisable(aStatus
, aMessage
, aFailureId
);
3481 if (!gfxVars::UseWebRender()) {
3482 // We were not using WebRender in the first place, and we have disabled
3483 // all forms of accelerated compositing.
3487 if (StaticPrefs::gfx_webrender_fallback_software_AtStartup() &&
3488 swglFallbackAllowed
&&
3489 gfxConfig::IsEnabled(Feature::WEBRENDER_SOFTWARE
) &&
3490 !gfxVars::UseSoftwareWebRender()) {
3491 // Fallback from WebRender to Software WebRender.
3492 gfxCriticalNote
<< "Fallback WR to SW-WR";
3493 gfxVars::SetUseSoftwareWebRender(true);
3497 MOZ_ASSERT(gfxVars::UseWebRender());
3499 if (!gfxVars::UseSoftwareWebRender()) {
3500 // Software WebRender may be disabled due to a startup issue with the
3501 // blocklist, despite it being our only fallback option based on the prefs.
3502 // If WebRender is unable to be initialized, this means that user would
3503 // otherwise get stuck with WebRender. As such, force a switch to Software
3504 // WebRender in this case.
3505 gfxCriticalNoteOnce
<< "Fallback WR to SW-WR, forced";
3506 gfxVars::SetUseSoftwareWebRender(true);
3510 if (aCrashAfterFinalFallback
) {
3511 MOZ_CRASH("Fallback configurations exhausted");
3514 // Continue using Software WebRender (disabled fallback to Basic).
3515 gfxCriticalNoteOnce
<< "Fallback remains SW-WR";
3520 void gfxPlatform::DisableGPUProcess() {
3521 gfxVars::SetRemoteCanvasEnabled(false);
3523 RemoteTextureMap::Init();
3524 if (gfxVars::UseWebRender()) {
3525 // We need to initialize the parent process to prepare for WebRender if we
3526 // did not end up disabling it, despite losing the GPU process.
3527 wr::RenderThread::Start(GPUProcessManager::Get()->AllocateNamespace());
3528 image::ImageMemoryReporter::InitForWebRender();
3532 void gfxPlatform::FetchAndImportContentDeviceData() {
3533 MOZ_ASSERT(XRE_IsContentProcess());
3535 if (gContentDeviceInitData
) {
3536 ImportContentDeviceData(*gContentDeviceInitData
);
3540 mozilla::dom::ContentChild
* cc
= mozilla::dom::ContentChild::GetSingleton();
3542 mozilla::gfx::ContentDeviceData data
;
3543 cc
->SendGetGraphicsDeviceInitData(&data
);
3545 ImportContentDeviceData(data
);
3548 void gfxPlatform::ImportContentDeviceData(
3549 const mozilla::gfx::ContentDeviceData
& aData
) {
3550 MOZ_ASSERT(XRE_IsContentProcess());
3552 const DevicePrefs
& prefs
= aData
.prefs();
3553 gfxConfig::Inherit(Feature::HW_COMPOSITING
, prefs
.hwCompositing());
3554 gfxConfig::Inherit(Feature::OPENGL_COMPOSITING
, prefs
.oglCompositing());
3557 void gfxPlatform::BuildContentDeviceData(
3558 mozilla::gfx::ContentDeviceData
* aOut
) {
3559 MOZ_ASSERT(XRE_IsParentProcess());
3561 // Make sure our settings are synchronized from the GPU process.
3562 GPUProcessManager::Get()->EnsureGPUReady();
3564 aOut
->prefs().hwCompositing() = gfxConfig::GetValue(Feature::HW_COMPOSITING
);
3565 aOut
->prefs().oglCompositing() =
3566 gfxConfig::GetValue(Feature::OPENGL_COMPOSITING
);
3569 void gfxPlatform::ImportGPUDeviceData(
3570 const mozilla::gfx::GPUDeviceData
& aData
) {
3571 MOZ_ASSERT(XRE_IsParentProcess());
3573 gfxConfig::ImportChange(Feature::OPENGL_COMPOSITING
, aData
.oglCompositing());
3576 bool gfxPlatform::SupportsApzTouchInput() const {
3577 return dom::TouchEvent::PrefEnabled(nullptr);
3580 bool gfxPlatform::SupportsApzDragInput() const {
3581 return StaticPrefs::apz_drag_enabled();
3584 bool gfxPlatform::SupportsApzKeyboardInput() const {
3585 return StaticPrefs::apz_keyboard_enabled_AtStartup();
3588 bool gfxPlatform::SupportsApzAutoscrolling() const {
3589 return StaticPrefs::apz_autoscroll_enabled();
3592 bool gfxPlatform::SupportsApzZooming() const {
3593 return StaticPrefs::apz_allow_zooming();
3596 void gfxPlatform::InitOpenGLConfig() {
3598 // Don't enable by default on Windows, since it could show up in about:support
3599 // even though it'll never get used. Only attempt if user enables the pref
3600 if (!Preferences::GetBool("layers.prefer-opengl")) {
3605 FeatureState
& openGLFeature
=
3606 gfxConfig::GetFeature(Feature::OPENGL_COMPOSITING
);
3608 // Check to see hw comp supported
3609 if (!gfxConfig::IsEnabled(Feature::HW_COMPOSITING
)) {
3610 openGLFeature
.DisableByDefault(FeatureStatus::Unavailable
,
3611 "Hardware compositing is disabled",
3612 "FEATURE_FAILURE_OPENGL_NEED_HWCOMP"_ns
);
3617 openGLFeature
.SetDefaultFromPref(
3618 StaticPrefs::GetPrefName_layers_prefer_opengl(), true,
3619 StaticPrefs::GetPrefDefault_layers_prefer_opengl());
3621 openGLFeature
.EnableByDefault();
3624 // When layers acceleration is force-enabled, enable it even for blocklisted
3627 layers_acceleration_force_enabled_AtStartup_DoNotUseDirectly()) {
3628 openGLFeature
.UserForceEnable("Force-enabled by pref");
3633 nsCString failureId
;
3634 if (!IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_OPENGL_LAYERS
, &message
,
3636 openGLFeature
.Disable(FeatureStatus::Blocklisted
, message
.get(), failureId
);
3640 bool gfxPlatform::IsGfxInfoStatusOkay(int32_t aFeature
, nsCString
* aOutMessage
,
3641 nsCString
& aFailureId
) {
3642 nsCOMPtr
<nsIGfxInfo
> gfxInfo
= components::GfxInfo::Service();
3648 if (NS_SUCCEEDED(gfxInfo
->GetFeatureStatus(aFeature
, aFailureId
, &status
)) &&
3649 status
!= nsIGfxInfo::FEATURE_STATUS_OK
) {
3650 aOutMessage
->AssignLiteral("#BLOCKLIST_");
3651 aOutMessage
->AppendASCII(aFailureId
.get());