LCOV - code coverage report
Current view: top level - gfx/thebes - gfxPlatform.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 469 1156 40.6 %
Date: 2017-07-14 16:53:18 Functions: 75 159 47.2 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       5             : 
       6             : #include "mozilla/layers/CompositorManagerChild.h"
       7             : #include "mozilla/layers/CompositorThread.h"
       8             : #include "mozilla/layers/ImageBridgeChild.h"
       9             : #include "mozilla/layers/ISurfaceAllocator.h"     // for GfxMemoryImageReporter
      10             : #include "mozilla/webrender/RenderThread.h"
      11             : #include "mozilla/layers/PaintThread.h"
      12             : #include "mozilla/gfx/gfxVars.h"
      13             : #include "mozilla/gfx/GPUProcessManager.h"
      14             : #include "mozilla/gfx/GraphicsMessages.h"
      15             : #include "mozilla/ClearOnShutdown.h"
      16             : #include "mozilla/Telemetry.h"
      17             : #include "mozilla/TimeStamp.h"
      18             : #include "mozilla/Unused.h"
      19             : 
      20             : #include "mozilla/Logging.h"
      21             : #include "mozilla/Services.h"
      22             : 
      23             : #include "gfxCrashReporterUtils.h"
      24             : #include "gfxPlatform.h"
      25             : #include "gfxPrefs.h"
      26             : #include "gfxEnv.h"
      27             : #include "gfxTextRun.h"
      28             : #include "gfxConfig.h"
      29             : #include "MediaPrefs.h"
      30             : 
      31             : #ifdef XP_WIN
      32             : #include <process.h>
      33             : #define getpid _getpid
      34             : #else
      35             : #include <unistd.h>
      36             : #endif
      37             : 
      38             : #include "nsXULAppAPI.h"
      39             : #include "nsDirectoryServiceUtils.h"
      40             : #include "nsDirectoryServiceDefs.h"
      41             : 
      42             : #if defined(XP_WIN)
      43             : #include "gfxWindowsPlatform.h"
      44             : #elif defined(XP_MACOSX)
      45             : #include "gfxPlatformMac.h"
      46             : #include "gfxQuartzSurface.h"
      47             : #elif defined(MOZ_WIDGET_GTK)
      48             : #include "gfxPlatformGtk.h"
      49             : #elif defined(ANDROID)
      50             : #include "gfxAndroidPlatform.h"
      51             : #endif
      52             : 
      53             : #ifdef XP_WIN
      54             : #include "mozilla/WindowsVersion.h"
      55             : #include "mozilla/gfx/DeviceManagerDx.h"
      56             : #endif
      57             : 
      58             : #include "nsGkAtoms.h"
      59             : #include "gfxPlatformFontList.h"
      60             : #include "gfxContext.h"
      61             : #include "gfxImageSurface.h"
      62             : #include "nsUnicodeProperties.h"
      63             : #include "harfbuzz/hb.h"
      64             : #include "gfxGraphiteShaper.h"
      65             : #include "gfx2DGlue.h"
      66             : #include "gfxGradientCache.h"
      67             : #include "gfxUtils.h" // for NextPowerOfTwo
      68             : 
      69             : #include "nsUnicodeRange.h"
      70             : #include "nsServiceManagerUtils.h"
      71             : #include "nsTArray.h"
      72             : #include "nsIObserverService.h"
      73             : #include "nsIScreenManager.h"
      74             : #include "FrameMetrics.h"
      75             : #include "MainThreadUtils.h"
      76             : #ifdef MOZ_CRASHREPORTER
      77             : #include "nsExceptionHandler.h"
      78             : #endif
      79             : 
      80             : #include "nsWeakReference.h"
      81             : 
      82             : #include "cairo.h"
      83             : #include "qcms.h"
      84             : 
      85             : #include "imgITools.h"
      86             : 
      87             : #include "plstr.h"
      88             : #include "nsCRT.h"
      89             : #include "GLContext.h"
      90             : #include "GLContextProvider.h"
      91             : #include "mozilla/gfx/Logging.h"
      92             : 
      93             : #ifdef MOZ_WIDGET_ANDROID
      94             : #include "TexturePoolOGL.h"
      95             : #endif
      96             : 
      97             : #ifdef USE_SKIA
      98             : # ifdef __GNUC__
      99             : #  pragma GCC diagnostic push
     100             : #  pragma GCC diagnostic ignored "-Wshadow"
     101             : # endif
     102             : # include "skia/include/core/SkGraphics.h"
     103             : # ifdef USE_SKIA_GPU
     104             : #  include "skia/include/gpu/GrContext.h"
     105             : #  include "skia/include/gpu/gl/GrGLInterface.h"
     106             : #  include "SkiaGLGlue.h"
     107             : # endif
     108             : # ifdef MOZ_ENABLE_FREETYPE
     109             : #  include "skia/include/ports/SkTypeface_cairo.h"
     110             : # endif
     111             : # ifdef __GNUC__
     112             : #  pragma GCC diagnostic pop // -Wshadow
     113             : # endif
     114             : static const uint32_t kDefaultGlyphCacheSize = -1;
     115             : 
     116             : #endif
     117             : 
     118             : #if !defined(USE_SKIA) || !defined(USE_SKIA_GPU)
     119             : class mozilla::gl::SkiaGLGlue : public GenericAtomicRefCounted {
     120             : };
     121             : #endif
     122             : 
     123             : #include "mozilla/Preferences.h"
     124             : #include "mozilla/Assertions.h"
     125             : #include "mozilla/Atomics.h"
     126             : #include "mozilla/Attributes.h"
     127             : #include "mozilla/Mutex.h"
     128             : 
     129             : #include "nsAlgorithm.h"
     130             : #include "nsIGfxInfo.h"
     131             : #include "nsIXULRuntime.h"
     132             : #include "VsyncSource.h"
     133             : #include "SoftwareVsyncSource.h"
     134             : #include "nscore.h" // for NS_FREE_PERMANENT_DATA
     135             : #include "mozilla/dom/ContentChild.h"
     136             : #include "mozilla/dom/TouchEvent.h"
     137             : #include "gfxVR.h"
     138             : #include "VRManagerChild.h"
     139             : #include "mozilla/gfx/GPUParent.h"
     140             : #include "mozilla/layers/MemoryReportingMLGPU.h"
     141             : #include "prsystem.h"
     142             : 
     143             : namespace mozilla {
     144             : namespace layers {
     145             : void ShutdownTileCache();
     146             : } // namespace layers
     147             : } // namespace mozilla
     148             : 
     149             : using namespace mozilla;
     150             : using namespace mozilla::layers;
     151             : using namespace mozilla::gl;
     152             : using namespace mozilla::gfx;
     153             : 
     154             : gfxPlatform *gPlatform = nullptr;
     155             : static bool gEverInitialized = false;
     156             : 
     157             : const ContentDeviceData* gContentDeviceInitData = nullptr;
     158             : 
     159             : static Mutex* gGfxPlatformPrefsLock = nullptr;
     160             : 
     161             : // These two may point to the same profile
     162             : static qcms_profile *gCMSOutputProfile = nullptr;
     163             : static qcms_profile *gCMSsRGBProfile = nullptr;
     164             : 
     165             : static qcms_transform *gCMSRGBTransform = nullptr;
     166             : static qcms_transform *gCMSInverseRGBTransform = nullptr;
     167             : static qcms_transform *gCMSRGBATransform = nullptr;
     168             : 
     169             : static bool gCMSInitialized = false;
     170             : static eCMSMode gCMSMode = eCMSMode_Off;
     171             : 
     172             : static void ShutdownCMS();
     173             : 
     174             : #include "mozilla/gfx/2D.h"
     175             : #include "mozilla/gfx/SourceSurfaceCairo.h"
     176             : using namespace mozilla::gfx;
     177             : 
     178             : /* Class to listen for pref changes so that chrome code can dynamically
     179             :    force sRGB as an output profile. See Bug #452125. */
     180           3 : class SRGBOverrideObserver final : public nsIObserver,
     181             :                                    public nsSupportsWeakReference
     182             : {
     183           0 :     ~SRGBOverrideObserver() = default;
     184             : public:
     185             :     NS_DECL_ISUPPORTS
     186             :     NS_DECL_NSIOBSERVER
     187             : };
     188             : 
     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.
     195             : 
     196           0 : class CrashStatsLogForwarder: public mozilla::gfx::LogForwarder
     197             : {
     198             : public:
     199             :   explicit CrashStatsLogForwarder(const char* aKey);
     200             :   void Log(const std::string& aString) override;
     201             :   void CrashAction(LogReason aReason) override;
     202             :   bool UpdateStringsVector(const std::string& aString) override;
     203             : 
     204             :   LoggingRecord LoggingRecordCopy() override;
     205             : 
     206             :   void SetCircularBufferSize(uint32_t aCapacity);
     207             : 
     208             : private:
     209             :   // Helper for the Log()
     210             :   void UpdateCrashReport();
     211             : 
     212             : private:
     213             :   LoggingRecord mBuffer;
     214             :   nsCString mCrashCriticalKey;
     215             :   uint32_t mMaxCapacity;
     216             :   int32_t mIndex;
     217             :   Mutex mMutex;
     218             : };
     219             : 
     220           3 : CrashStatsLogForwarder::CrashStatsLogForwarder(const char* aKey)
     221             :   : mBuffer()
     222             :   , mCrashCriticalKey(aKey)
     223             :   , mMaxCapacity(0)
     224             :   , mIndex(-1)
     225           3 :   , mMutex("CrashStatsLogForwarder")
     226             : {
     227           3 : }
     228             : 
     229           3 : void CrashStatsLogForwarder::SetCircularBufferSize(uint32_t aCapacity)
     230             : {
     231           6 :   MutexAutoLock lock(mMutex);
     232             : 
     233           3 :   mMaxCapacity = aCapacity;
     234           3 :   mBuffer.reserve(static_cast<size_t>(aCapacity));
     235           3 : }
     236             : 
     237             : LoggingRecord
     238           0 : CrashStatsLogForwarder::LoggingRecordCopy()
     239             : {
     240           0 :   MutexAutoLock lock(mMutex);
     241           0 :   return mBuffer;
     242             : }
     243             : 
     244             : bool
     245           0 : CrashStatsLogForwarder::UpdateStringsVector(const std::string& aString)
     246             : {
     247             :   // We want at least the first one and the last one.  Otherwise, no point.
     248           0 :   if (mMaxCapacity < 2) {
     249           0 :     return false;
     250             :   }
     251             : 
     252           0 :   mIndex += 1;
     253           0 :   MOZ_ASSERT(mIndex >= 0);
     254             : 
     255             :   // index will count 0, 1, 2, ..., max-1, 1, 2, ..., max-1, 1, 2, ...
     256           0 :   int32_t index = mIndex ? (mIndex-1) % (mMaxCapacity-1) + 1 : 0;
     257           0 :   MOZ_ASSERT(index >= 0 && index < (int32_t)mMaxCapacity);
     258           0 :   MOZ_ASSERT(index <= mIndex && index <= (int32_t)mBuffer.size());
     259             : 
     260           0 :   double tStamp = (TimeStamp::NowLoRes() - TimeStamp::ProcessCreation()).ToSecondsSigDigits();
     261             : 
     262             :   // Checking for index >= mBuffer.size(), rather than index == mBuffer.size()
     263             :   // just out of paranoia, but we know index <= mBuffer.size().
     264           0 :   LoggingRecordEntry newEntry(mIndex,aString,tStamp);
     265           0 :   if (index >= static_cast<int32_t>(mBuffer.size())) {
     266           0 :     mBuffer.push_back(newEntry);
     267             :   } else {
     268           0 :     mBuffer[index] = newEntry;
     269             :   }
     270           0 :   return true;
     271             : }
     272             : 
     273           0 : void CrashStatsLogForwarder::UpdateCrashReport()
     274             : {
     275           0 :   std::stringstream message;
     276           0 :   std::string logAnnotation;
     277             : 
     278           0 :   switch (XRE_GetProcessType()) {
     279             :   case GeckoProcessType_Default:
     280           0 :     logAnnotation = "|[";
     281           0 :     break;
     282             :   case GeckoProcessType_Content:
     283           0 :     logAnnotation = "|[C";
     284           0 :     break;
     285             :   case GeckoProcessType_GPU:
     286           0 :     logAnnotation = "|[G";
     287           0 :     break;
     288             :   default:
     289           0 :     logAnnotation = "|[X";
     290           0 :     break;
     291             :   }
     292             : 
     293           0 :   for (auto& it : mBuffer) {
     294           0 :     message << logAnnotation << Get<0>(it) << "]" << Get<1>(it) << " (t=" << Get<2>(it) << ") ";
     295             :   }
     296             : 
     297             : #ifdef MOZ_CRASHREPORTER
     298           0 :   nsCString reportString(message.str().c_str());
     299           0 :   nsresult annotated = CrashReporter::AnnotateCrashReport(mCrashCriticalKey, reportString);
     300             : #else
     301             :   nsresult annotated = NS_ERROR_NOT_IMPLEMENTED;
     302             : #endif
     303           0 :   if (annotated != NS_OK) {
     304           0 :     printf("Crash Annotation %s: %s",
     305           0 :            mCrashCriticalKey.get(), message.str().c_str());
     306             :   }
     307           0 : }
     308             : 
     309             : class LogForwarderEvent : public Runnable
     310             : {
     311           0 :   ~LogForwarderEvent() override = default;
     312             : 
     313             :   NS_DECL_ISUPPORTS_INHERITED
     314             : 
     315           0 :   explicit LogForwarderEvent(const nsCString& aMessage)
     316           0 :     : mozilla::Runnable("LogForwarderEvent")
     317           0 :     , mMessage(aMessage)
     318             :   {
     319           0 :   }
     320             : 
     321           0 :   NS_IMETHOD Run() override {
     322           0 :     MOZ_ASSERT(NS_IsMainThread() && (XRE_IsContentProcess() || XRE_IsGPUProcess()));
     323             : 
     324           0 :     if (XRE_IsContentProcess()) {
     325           0 :       dom::ContentChild* cc = dom::ContentChild::GetSingleton();
     326           0 :       Unused << cc->SendGraphicsError(mMessage);
     327           0 :     } else if (XRE_IsGPUProcess()) {
     328           0 :       GPUParent* gp = GPUParent::GetSingleton();
     329           0 :       Unused << gp->SendGraphicsError(mMessage);
     330             :     }
     331             : 
     332           0 :     return NS_OK;
     333             :   }
     334             : 
     335             : protected:
     336             :   nsCString mMessage;
     337             : };
     338             : 
     339           0 : NS_IMPL_ISUPPORTS_INHERITED0(LogForwarderEvent, Runnable);
     340             : 
     341           0 : void CrashStatsLogForwarder::Log(const std::string& aString)
     342             : {
     343           0 :   MutexAutoLock lock(mMutex);
     344             : 
     345           0 :   if (UpdateStringsVector(aString)) {
     346           0 :     UpdateCrashReport();
     347             :   }
     348             : 
     349             :   // Add it to the parent strings
     350           0 :   if (!XRE_IsParentProcess()) {
     351           0 :     nsCString stringToSend(aString.c_str());
     352           0 :     if (NS_IsMainThread()) {
     353           0 :       if (XRE_IsContentProcess()) {
     354           0 :         dom::ContentChild* cc = dom::ContentChild::GetSingleton();
     355           0 :         Unused << cc->SendGraphicsError(stringToSend);
     356           0 :       } else if (XRE_IsGPUProcess()) {
     357           0 :         GPUParent* gp = GPUParent::GetSingleton();
     358           0 :         Unused << gp->SendGraphicsError(stringToSend);
     359             :       }
     360             :     } else {
     361           0 :       nsCOMPtr<nsIRunnable> r1 = new LogForwarderEvent(stringToSend);
     362           0 :       NS_DispatchToMainThread(r1);
     363             :     }
     364             :   }
     365           0 : }
     366             : 
     367             : class CrashTelemetryEvent : public Runnable
     368             : {
     369           0 :   ~CrashTelemetryEvent() override = default;
     370             : 
     371             :   NS_DECL_ISUPPORTS_INHERITED
     372             : 
     373           0 :   explicit CrashTelemetryEvent(uint32_t aReason)
     374           0 :     : mozilla::Runnable("CrashTelemetryEvent")
     375           0 :     , mReason(aReason)
     376             :   {
     377           0 :   }
     378             : 
     379           0 :   NS_IMETHOD Run() override {
     380           0 :     MOZ_ASSERT(NS_IsMainThread());
     381           0 :     Telemetry::Accumulate(Telemetry::GFX_CRASH, mReason);
     382           0 :     return NS_OK;
     383             :   }
     384             : 
     385             : protected:
     386             :   uint32_t mReason;
     387             : };
     388             : 
     389           0 : NS_IMPL_ISUPPORTS_INHERITED0(CrashTelemetryEvent, Runnable);
     390             : 
     391             : void
     392           0 : CrashStatsLogForwarder::CrashAction(LogReason aReason)
     393             : {
     394             : #ifndef RELEASE_OR_BETA
     395             :   // Non-release builds crash by default, but will use telemetry
     396             :   // if this environment variable is present.
     397           0 :   static bool useTelemetry = gfxEnv::GfxDevCrashTelemetry();
     398             : #else
     399             :   // Release builds use telemetry by default, but will crash instead
     400             :   // if this environment variable is present.
     401             :   static bool useTelemetry = !gfxEnv::GfxDevCrashMozCrash();
     402             : #endif
     403             : 
     404           0 :   if (useTelemetry) {
     405             :     // The callers need to assure that aReason is in the range
     406             :     // that the telemetry call below supports.
     407           0 :     if (NS_IsMainThread()) {
     408           0 :       Telemetry::Accumulate(Telemetry::GFX_CRASH, (uint32_t)aReason);
     409             :     } else {
     410           0 :       nsCOMPtr<nsIRunnable> r1 = new CrashTelemetryEvent((uint32_t)aReason);
     411           0 :       NS_DispatchToMainThread(r1);
     412             :     }
     413             :   } else {
     414             :     // ignoring aReason, we can get the information we need from the stack
     415           0 :     MOZ_CRASH("GFX_CRASH");
     416             :   }
     417           0 : }
     418             : 
     419          39 : NS_IMPL_ISUPPORTS(SRGBOverrideObserver, nsIObserver, nsISupportsWeakReference)
     420             : 
     421             : #define GFX_DOWNLOADABLE_FONTS_ENABLED "gfx.downloadable_fonts.enabled"
     422             : 
     423             : #define GFX_PREF_FALLBACK_USE_CMAPS  "gfx.font_rendering.fallback.always_use_cmaps"
     424             : 
     425             : #define GFX_PREF_OPENTYPE_SVG "gfx.font_rendering.opentype_svg.enabled"
     426             : 
     427             : #define GFX_PREF_WORD_CACHE_CHARLIMIT "gfx.font_rendering.wordcache.charlimit"
     428             : #define GFX_PREF_WORD_CACHE_MAXENTRIES "gfx.font_rendering.wordcache.maxentries"
     429             : 
     430             : #define GFX_PREF_GRAPHITE_SHAPING "gfx.font_rendering.graphite.enabled"
     431             : 
     432             : #define BIDI_NUMERAL_PREF "bidi.numeral"
     433             : 
     434             : #define GFX_PREF_CMS_FORCE_SRGB "gfx.color_management.force_srgb"
     435             : 
     436             : NS_IMETHODIMP
     437           0 : SRGBOverrideObserver::Observe(nsISupports *aSubject,
     438             :                               const char *aTopic,
     439             :                               const char16_t* someData)
     440             : {
     441           0 :     NS_ASSERTION(NS_strcmp(someData,
     442             :                            (u"" GFX_PREF_CMS_FORCE_SRGB)) == 0,
     443             :                  "Restarting CMS on wrong pref!");
     444           0 :     ShutdownCMS();
     445             :     // Update current cms profile.
     446           0 :     gfxPlatform::CreateCMSOutputProfile();
     447           0 :     return NS_OK;
     448             : }
     449             : 
     450             : static const char* kObservedPrefs[] = {
     451             :     "gfx.downloadable_fonts.",
     452             :     "gfx.font_rendering.",
     453             :     BIDI_NUMERAL_PREF,
     454             :     nullptr
     455             : };
     456             : 
     457           3 : class FontPrefsObserver final : public nsIObserver
     458             : {
     459             :     ~FontPrefsObserver() = default;
     460             : public:
     461             :     NS_DECL_ISUPPORTS
     462             :     NS_DECL_NSIOBSERVER
     463             : };
     464             : 
     465          84 : NS_IMPL_ISUPPORTS(FontPrefsObserver, nsIObserver)
     466             : 
     467             : NS_IMETHODIMP
     468           0 : FontPrefsObserver::Observe(nsISupports *aSubject,
     469             :                            const char *aTopic,
     470             :                            const char16_t *someData)
     471             : {
     472           0 :     if (!someData) {
     473           0 :         NS_ERROR("font pref observer code broken");
     474           0 :         return NS_ERROR_UNEXPECTED;
     475             :     }
     476           0 :     NS_ASSERTION(gfxPlatform::GetPlatform(), "the singleton instance has gone");
     477           0 :     gfxPlatform::GetPlatform()->FontsPrefsChanged(NS_ConvertUTF16toUTF8(someData).get());
     478             : 
     479           0 :     return NS_OK;
     480             : }
     481             : 
     482           3 : class MemoryPressureObserver final : public nsIObserver
     483             : {
     484             :     ~MemoryPressureObserver() = default;
     485             : public:
     486             :     NS_DECL_ISUPPORTS
     487             :     NS_DECL_NSIOBSERVER
     488             : };
     489             : 
     490          15 : NS_IMPL_ISUPPORTS(MemoryPressureObserver, nsIObserver)
     491             : 
     492             : NS_IMETHODIMP
     493           0 : MemoryPressureObserver::Observe(nsISupports *aSubject,
     494             :                                 const char *aTopic,
     495             :                                 const char16_t *someData)
     496             : {
     497           0 :     NS_ASSERTION(strcmp(aTopic, "memory-pressure") == 0, "unexpected event topic");
     498           0 :     Factory::PurgeAllCaches();
     499           0 :     gfxGradientCache::PurgeAllCaches();
     500             : 
     501           0 :     gfxPlatform::PurgeSkiaFontCache();
     502           0 :     gfxPlatform::GetPlatform()->PurgeSkiaGPUCache();
     503           0 :     return NS_OK;
     504             : }
     505             : 
     506           3 : gfxPlatform::gfxPlatform()
     507             :   : mAzureCanvasBackendCollector(this, &gfxPlatform::GetAzureBackendInfo)
     508             :   , mApzSupportCollector(this, &gfxPlatform::GetApzSupportInfo)
     509             :   , mTilesInfoCollector(this, &gfxPlatform::GetTilesSupportInfo)
     510             :   , mCompositorBackend(layers::LayersBackend::LAYERS_NONE)
     511           3 :   , mScreenDepth(0)
     512             : {
     513           3 :     mAllowDownloadableFonts = UNINITIALIZED_VALUE;
     514           3 :     mFallbackUsesCmaps = UNINITIALIZED_VALUE;
     515             : 
     516           3 :     mWordCacheCharLimit = UNINITIALIZED_VALUE;
     517           3 :     mWordCacheMaxEntries = UNINITIALIZED_VALUE;
     518           3 :     mGraphiteShapingEnabled = UNINITIALIZED_VALUE;
     519           3 :     mOpenTypeSVGEnabled = UNINITIALIZED_VALUE;
     520           3 :     mBidiNumeralOption = UNINITIALIZED_VALUE;
     521             : 
     522           3 :     mSkiaGlue = nullptr;
     523             : 
     524           3 :     uint32_t canvasMask = BackendTypeBit(BackendType::CAIRO);
     525           3 :     uint32_t contentMask = BackendTypeBit(BackendType::CAIRO);
     526             : #ifdef USE_SKIA
     527           3 :     canvasMask |= BackendTypeBit(BackendType::SKIA);
     528           3 :     contentMask |= BackendTypeBit(BackendType::SKIA);
     529             : #endif
     530             :     InitBackendPrefs(canvasMask, BackendType::CAIRO,
     531           3 :                      contentMask, BackendType::CAIRO);
     532             : 
     533           3 :     mTotalSystemMemory = PR_GetPhysicalMemorySize();
     534             : 
     535           3 :     VRManager::ManagerInit();
     536           3 : }
     537             : 
     538             : gfxPlatform*
     539        1138 : gfxPlatform::GetPlatform()
     540             : {
     541        1138 :     if (!gPlatform) {
     542           1 :         MOZ_RELEASE_ASSERT(!XRE_IsContentProcess(),
     543             :                            "Content Process should have called InitChild() before first GetPlatform()");
     544           1 :         Init();
     545             :     }
     546        1138 :     return gPlatform;
     547             : }
     548             : 
     549             : bool
     550           4 : gfxPlatform::Initialized()
     551             : {
     552           4 :   return !!gPlatform;
     553             : }
     554             : 
     555             : /* static */ void
     556           2 : gfxPlatform::InitChild(const ContentDeviceData& aData)
     557             : {
     558           2 :   MOZ_ASSERT(XRE_IsContentProcess());
     559           2 :   MOZ_RELEASE_ASSERT(!gPlatform,
     560             :                      "InitChild() should be called before first GetPlatform()");
     561             :   // Make the provided initial ContentDeviceData available to the init
     562             :   // routines, so they don't have to do a sync request from the parent.
     563           2 :   gContentDeviceInitData = &aData;
     564           2 :   Init();
     565           2 :   gContentDeviceInitData = nullptr;
     566           2 : }
     567             : 
     568           3 : void RecordingPrefChanged(const char *aPrefName, void *aClosure)
     569             : {
     570           3 :   if (Preferences::GetBool("gfx.2d.recording", false)) {
     571           0 :     nsAutoCString fileName;
     572           0 :     nsAdoptingString prefFileName = Preferences::GetString("gfx.2d.recordingfile");
     573             : 
     574           0 :     if (prefFileName) {
     575           0 :       fileName.Append(NS_ConvertUTF16toUTF8(prefFileName));
     576             :     } else {
     577           0 :       nsCOMPtr<nsIFile> tmpFile;
     578           0 :       if (NS_FAILED(NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tmpFile)))) {
     579           0 :         return;
     580             :       }
     581           0 :       fileName.AppendPrintf("moz2drec_%i_%i.aer", XRE_GetProcessType(), getpid());
     582             : 
     583           0 :       nsresult rv = tmpFile->AppendNative(fileName);
     584           0 :       if (NS_FAILED(rv))
     585           0 :         return;
     586             : 
     587           0 :       rv = tmpFile->GetNativePath(fileName);
     588           0 :       if (NS_FAILED(rv))
     589           0 :         return;
     590             :     }
     591             : 
     592           0 :     gPlatform->mRecorder = Factory::CreateEventRecorderForFile(fileName.BeginReading());
     593           0 :     printf_stderr("Recording to %s\n", fileName.get());
     594           0 :     Factory::SetGlobalEventRecorder(gPlatform->mRecorder);
     595             :   } else {
     596           3 :     Factory::SetGlobalEventRecorder(nullptr);
     597             :   }
     598             : }
     599             : 
     600             : #if defined(USE_SKIA)
     601           3 : static uint32_t GetSkiaGlyphCacheSize()
     602             : {
     603             :     // Only increase font cache size on non-android to save memory.
     604             : #if !defined(MOZ_WIDGET_ANDROID)
     605             :     // 10mb as the default pref cache size on desktop due to talos perf tweaking.
     606             :     // Chromium uses 20mb and skia default uses 2mb.
     607             :     // We don't need to change the font cache count since we usually
     608             :     // cache thrash due to asian character sets in talos.
     609             :     // Only increase memory on the content proces
     610           3 :     uint32_t cacheSize = gfxPrefs::SkiaContentFontCacheSize() * 1024 * 1024;
     611           3 :     if (mozilla::BrowserTabsRemoteAutostart()) {
     612           3 :       return XRE_IsContentProcess() ? cacheSize : kDefaultGlyphCacheSize;
     613             :     }
     614             : 
     615           0 :     return cacheSize;
     616             : #else
     617             :     return kDefaultGlyphCacheSize;
     618             : #endif // MOZ_WIDGET_ANDROID
     619             : }
     620             : #endif
     621             : 
     622             : void
     623           3 : gfxPlatform::Init()
     624             : {
     625           3 :     MOZ_RELEASE_ASSERT(!XRE_IsGPUProcess(), "GFX: Not allowed in GPU process.");
     626           3 :     MOZ_RELEASE_ASSERT(NS_IsMainThread(), "GFX: Not in main thread.");
     627             : 
     628           3 :     if (gEverInitialized) {
     629           0 :         MOZ_CRASH("Already started???");
     630             :     }
     631           3 :     gEverInitialized = true;
     632             : 
     633             :     // Initialize the preferences by creating the singleton.
     634           3 :     gfxPrefs::GetSingleton();
     635           3 :     MediaPrefs::GetSingleton();
     636           3 :     gfxVars::Initialize();
     637             : 
     638           3 :     gfxConfig::Init();
     639             : 
     640           3 :     if (XRE_IsParentProcess()) {
     641           1 :       GPUProcessManager::Initialize();
     642             : 
     643           1 :       if (Preferences::GetBool("media.wmf.skip-blacklist")) {
     644           0 :         gfxVars::SetPDMWMFDisableD3D11Dlls(nsCString());
     645           0 :         gfxVars::SetPDMWMFDisableD3D9Dlls(nsCString());
     646             :       } else {
     647           1 :         gfxVars::SetPDMWMFDisableD3D11Dlls(Preferences::GetCString("media.wmf.disable-d3d11-for-dlls"));
     648           1 :         gfxVars::SetPDMWMFDisableD3D9Dlls(Preferences::GetCString("media.wmf.disable-d3d9-for-dlls"));
     649             :       }
     650             : 
     651           2 :       nsCOMPtr<nsIFile> file;
     652           1 :       nsresult rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(file));
     653           1 :       if (NS_FAILED(rv)) {
     654           0 :         gfxVars::SetGREDirectory(nsCString());
     655             :       } else {
     656           2 :         nsAutoCString nativePath;
     657           1 :         file->GetNativePath(nativePath);
     658           1 :         gfxVars::SetGREDirectory(nsCString(nativePath));
     659             :       }
     660             :     }
     661             : 
     662             :     // Drop a note in the crash report if we end up forcing an option that could
     663             :     // destabilize things.  New items should be appended at the end (of an existing
     664             :     // or in a new section), so that we don't have to know the version to interpret
     665             :     // these cryptic strings.
     666             :     {
     667           6 :       nsAutoCString forcedPrefs;
     668             :       // D2D prefs
     669           6 :       forcedPrefs.AppendPrintf("FP(D%d%d",
     670           3 :                                gfxPrefs::Direct2DDisabled(),
     671           6 :                                gfxPrefs::Direct2DForceEnabled());
     672             :       // Layers prefs
     673          12 :       forcedPrefs.AppendPrintf("-L%d%d%d%d",
     674           3 :                                gfxPrefs::LayersAMDSwitchableGfxEnabled(),
     675           3 :                                gfxPrefs::LayersAccelerationDisabledDoNotUseDirectly(),
     676           3 :                                gfxPrefs::LayersAccelerationForceEnabledDoNotUseDirectly(),
     677           6 :                                gfxPrefs::LayersD3D11ForceWARP());
     678             :       // WebGL prefs
     679          24 :       forcedPrefs.AppendPrintf("-W%d%d%d%d%d%d%d%d",
     680           3 :                                gfxPrefs::WebGLANGLEForceD3D11(),
     681           3 :                                gfxPrefs::WebGLANGLEForceWARP(),
     682           3 :                                gfxPrefs::WebGLDisabled(),
     683           3 :                                gfxPrefs::WebGLDisableANGLE(),
     684           3 :                                gfxPrefs::WebGLDXGLEnabled(),
     685           3 :                                gfxPrefs::WebGLForceEnabled(),
     686           3 :                                gfxPrefs::WebGLForceLayersReadback(),
     687           6 :                                gfxPrefs::WebGLForceMSAA());
     688             :       // Prefs that don't fit into any of the other sections
     689           9 :       forcedPrefs.AppendPrintf("-T%d%d%d) ",
     690           3 :                                gfxPrefs::AndroidRGB16Force(),
     691           3 :                                gfxPrefs::CanvasAzureAccelerated(),
     692           6 :                                gfxPrefs::ForceShmemTiles());
     693           3 :       ScopedGfxFeatureReporter::AppNote(forcedPrefs);
     694             :     }
     695             : 
     696           3 :     InitMoz2DLogging();
     697             : 
     698           3 :     gGfxPlatformPrefsLock = new Mutex("gfxPlatform::gGfxPlatformPrefsLock");
     699             : 
     700             :     /* Initialize the GfxInfo service.
     701             :      * Note: we can't call functions on GfxInfo that depend
     702             :      * on gPlatform until after it has been initialized
     703             :      * below. GfxInfo initialization annotates our
     704             :      * crash reports so we want to do it before
     705             :      * we try to load any drivers and do device detection
     706             :      * incase that code crashes. See bug #591561. */
     707           6 :     nsCOMPtr<nsIGfxInfo> gfxInfo;
     708             :     /* this currently will only succeed on Windows */
     709           3 :     gfxInfo = services::GetGfxInfo();
     710             : 
     711             : #if defined(XP_WIN)
     712             :     gPlatform = new gfxWindowsPlatform;
     713             : #elif defined(XP_MACOSX)
     714             :     gPlatform = new gfxPlatformMac;
     715             : #elif defined(MOZ_WIDGET_GTK)
     716           3 :     gPlatform = new gfxPlatformGtk;
     717             : #elif defined(ANDROID)
     718             :     gPlatform = new gfxAndroidPlatform;
     719             : #else
     720             :     #error "No gfxPlatform implementation available"
     721             : #endif
     722           3 :     gPlatform->InitAcceleration();
     723           3 :     gPlatform->InitWebRenderConfig();
     724           3 :     gPlatform->InitOMTPConfig();
     725             : 
     726           3 :     if (gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
     727           0 :       GPUProcessManager* gpu = GPUProcessManager::Get();
     728           0 :       gpu->LaunchGPUProcess();
     729             :     }
     730             : 
     731             : #ifdef USE_SKIA
     732           3 :     SkGraphics::Init();
     733             : #  ifdef MOZ_ENABLE_FREETYPE
     734           3 :     SkInitCairoFT(gPlatform->FontHintingEnabled());
     735             : #  endif
     736             : #endif
     737             : 
     738             : #ifdef MOZ_GL_DEBUG
     739           3 :     GLContext::StaticInit();
     740             : #endif
     741             : 
     742           3 :     InitLayersIPC();
     743             : 
     744           3 :     gPlatform->PopulateScreenInfo();
     745           3 :     gPlatform->ComputeTileSize();
     746             : 
     747             :     nsresult rv;
     748           3 :     rv = gfxPlatformFontList::Init();
     749           3 :     if (NS_FAILED(rv)) {
     750           0 :         MOZ_CRASH("Could not initialize gfxPlatformFontList");
     751             :     }
     752             : 
     753           3 :     gPlatform->mScreenReferenceSurface =
     754          12 :         gPlatform->CreateOffscreenSurface(IntSize(1, 1),
     755          12 :                                           SurfaceFormat::A8R8G8B8_UINT32);
     756           3 :     if (!gPlatform->mScreenReferenceSurface) {
     757           0 :         MOZ_CRASH("Could not initialize mScreenReferenceSurface");
     758             :     }
     759             : 
     760           3 :     gPlatform->mScreenReferenceDrawTarget =
     761           9 :         gPlatform->CreateOffscreenContentDrawTarget(IntSize(1, 1),
     762           9 :                                                     SurfaceFormat::B8G8R8A8);
     763           6 :     if (!gPlatform->mScreenReferenceDrawTarget ||
     764           3 :         !gPlatform->mScreenReferenceDrawTarget->IsValid()) {
     765           0 :       MOZ_CRASH("Could not initialize mScreenReferenceDrawTarget");
     766             :     }
     767             : 
     768           3 :     rv = gfxFontCache::Init();
     769           3 :     if (NS_FAILED(rv)) {
     770           0 :         MOZ_CRASH("Could not initialize gfxFontCache");
     771             :     }
     772             : 
     773             : #ifdef MOZ_ENABLE_FREETYPE
     774           3 :     Factory::SetFTLibrary(gPlatform->GetFTLibrary());
     775             : #endif
     776             : 
     777             :     /* Create and register our CMS Override observer. */
     778           3 :     gPlatform->mSRGBOverrideObserver = new SRGBOverrideObserver();
     779           3 :     Preferences::AddWeakObserver(gPlatform->mSRGBOverrideObserver, GFX_PREF_CMS_FORCE_SRGB);
     780             : 
     781           3 :     gPlatform->mFontPrefsObserver = new FontPrefsObserver();
     782           3 :     Preferences::AddStrongObservers(gPlatform->mFontPrefsObserver, kObservedPrefs);
     783             : 
     784           3 :     GLContext::PlatformStartup();
     785             : 
     786             : #ifdef MOZ_WIDGET_ANDROID
     787             :     // Texture pool init
     788             :     TexturePoolOGL::Init();
     789             : #endif
     790             : 
     791           3 :     Preferences::RegisterCallbackAndCall(RecordingPrefChanged, "gfx.2d.recording");
     792             : 
     793           3 :     CreateCMSOutputProfile();
     794             : 
     795             :     // Listen to memory pressure event so we can purge DrawTarget caches
     796           6 :     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
     797           3 :     if (obs) {
     798           3 :         gPlatform->mMemoryPressureObserver = new MemoryPressureObserver();
     799           3 :         obs->AddObserver(gPlatform->mMemoryPressureObserver, "memory-pressure", false);
     800             :     }
     801             : 
     802             :     // Request the imgITools service, implicitly initializing ImageLib.
     803           6 :     nsCOMPtr<imgITools> imgTools = do_GetService("@mozilla.org/image/tools;1");
     804           3 :     if (!imgTools) {
     805           0 :       MOZ_CRASH("Could not initialize ImageLib");
     806             :     }
     807             : 
     808           3 :     RegisterStrongMemoryReporter(new GfxMemoryImageReporter());
     809           3 :     mlg::InitializeMemoryReporters();
     810             : 
     811           3 :     if (XRE_IsParentProcess()) {
     812           1 :       if (gfxPlatform::ForceSoftwareVsync()) {
     813           0 :         gPlatform->mVsyncSource = (gPlatform)->gfxPlatform::CreateHardwareVsyncSource();
     814             :       } else {
     815           1 :         gPlatform->mVsyncSource = gPlatform->CreateHardwareVsyncSource();
     816             :       }
     817             :     }
     818             : 
     819             : #ifdef USE_SKIA
     820           3 :     uint32_t skiaCacheSize = GetSkiaGlyphCacheSize();
     821           3 :     if (skiaCacheSize != kDefaultGlyphCacheSize) {
     822           2 :       SkGraphics::SetFontCacheLimit(skiaCacheSize);
     823             :     }
     824             : #endif
     825             : 
     826           3 :     InitNullMetadata();
     827           3 :     InitOpenGLConfig();
     828             : 
     829           3 :     if (XRE_IsParentProcess()) {
     830           1 :       gfxVars::SetDXInterop2Blocked(IsDXInterop2Blocked());
     831             :     }
     832             : 
     833           3 :     if (obs) {
     834           3 :       obs->NotifyObservers(nullptr, "gfx-features-ready", nullptr);
     835             :     }
     836           3 : }
     837             : 
     838             : /* static*/ bool
     839           1 : gfxPlatform::IsDXInterop2Blocked()
     840             : {
     841           2 :   nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
     842           2 :   nsCString blockId;
     843             :   int32_t status;
     844           1 :   if (!NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DX_INTEROP2,
     845             :                                               blockId, &status))) {
     846           0 :     return true;
     847             :   }
     848           1 :   return status != nsIGfxInfo::FEATURE_STATUS_OK;
     849             : }
     850             : 
     851             : /* static */ int32_t
     852         159 : gfxPlatform::MaxTextureSize()
     853             : {
     854             :   // Make sure we don't completely break rendering because of a typo in the
     855             :   // pref or whatnot.
     856         159 :   const int32_t kMinSizePref = 2048;
     857         159 :   return std::max(kMinSizePref, gfxPrefs::MaxTextureSizeDoNotUseDirectly());
     858             : }
     859             : 
     860             : /* static */ int32_t
     861           3 : gfxPlatform::MaxAllocSize()
     862             : {
     863             :   // Make sure we don't completely break rendering because of a typo in the
     864             :   // pref or whatnot.
     865           3 :   const int32_t kMinAllocPref = 10000000;
     866           3 :   return std::max(kMinAllocPref, gfxPrefs::MaxAllocSizeDoNotUseDirectly());
     867             : }
     868             : 
     869             : /* static */ void
     870           3 : gfxPlatform::InitMoz2DLogging()
     871             : {
     872           3 :   auto fwd = new CrashStatsLogForwarder("GraphicsCriticalError");
     873           3 :   fwd->SetCircularBufferSize(gfxPrefs::GfxLoggingCrashLength());
     874             : 
     875           3 :   mozilla::gfx::Config cfg;
     876           3 :   cfg.mLogForwarder = fwd;
     877           3 :   cfg.mMaxTextureSize = gfxPlatform::MaxTextureSize();
     878           3 :   cfg.mMaxAllocSize = gfxPlatform::MaxAllocSize();
     879             : 
     880           3 :   gfx::Factory::Init(cfg);
     881           3 : }
     882             : 
     883             : /* static */ bool
     884          37 : gfxPlatform::IsHeadless()
     885             : {
     886             :     static bool initialized = false;
     887             :     static bool headless = false;
     888          37 :     if (!initialized) {
     889           3 :       initialized = true;
     890           3 :       headless = PR_GetEnv("MOZ_HEADLESS");
     891             :     }
     892          37 :     return headless;
     893             : }
     894             : 
     895             : static bool sLayersIPCIsUp = false;
     896             : 
     897             : /* static */ void
     898           3 : gfxPlatform::InitNullMetadata()
     899             : {
     900           3 :   ScrollMetadata::sNullMetadata = new ScrollMetadata();
     901           3 :   ClearOnShutdown(&ScrollMetadata::sNullMetadata);
     902           3 : }
     903             : 
     904             : void
     905           0 : gfxPlatform::Shutdown()
     906             : {
     907             :     // In some cases, gPlatform may not be created but Shutdown() called,
     908             :     // e.g., during xpcshell tests.
     909           0 :     if (!gPlatform) {
     910           0 :       return;
     911             :     }
     912             : 
     913           0 :     MOZ_ASSERT(!sLayersIPCIsUp);
     914             : 
     915             :     // These may be called before the corresponding subsystems have actually
     916             :     // started up. That's OK, they can handle it.
     917           0 :     gfxFontCache::Shutdown();
     918           0 :     gfxGradientCache::Shutdown();
     919           0 :     gfxAlphaBoxBlur::ShutdownBlurCache();
     920           0 :     gfxGraphiteShaper::Shutdown();
     921           0 :     gfxPlatformFontList::Shutdown();
     922           0 :     ShutdownTileCache();
     923             : 
     924             :     // Free the various non-null transforms and loaded profiles
     925           0 :     ShutdownCMS();
     926             : 
     927             :     /* Unregister our CMS Override callback. */
     928           0 :     NS_ASSERTION(gPlatform->mSRGBOverrideObserver, "mSRGBOverrideObserver has alreay gone");
     929           0 :     Preferences::RemoveObserver(gPlatform->mSRGBOverrideObserver, GFX_PREF_CMS_FORCE_SRGB);
     930           0 :     gPlatform->mSRGBOverrideObserver = nullptr;
     931             : 
     932           0 :     NS_ASSERTION(gPlatform->mFontPrefsObserver, "mFontPrefsObserver has alreay gone");
     933           0 :     Preferences::RemoveObservers(gPlatform->mFontPrefsObserver, kObservedPrefs);
     934           0 :     gPlatform->mFontPrefsObserver = nullptr;
     935             : 
     936           0 :     NS_ASSERTION(gPlatform->mMemoryPressureObserver, "mMemoryPressureObserver has already gone");
     937           0 :     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
     938           0 :     if (obs) {
     939           0 :         obs->RemoveObserver(gPlatform->mMemoryPressureObserver, "memory-pressure");
     940             :     }
     941             : 
     942           0 :     gPlatform->mMemoryPressureObserver = nullptr;
     943           0 :     gPlatform->mSkiaGlue = nullptr;
     944             : 
     945           0 :     if (XRE_IsParentProcess()) {
     946           0 :       gPlatform->mVsyncSource->Shutdown();
     947             :     }
     948             : 
     949           0 :     gPlatform->mVsyncSource = nullptr;
     950             : 
     951             : #ifdef MOZ_WIDGET_ANDROID
     952             :     // Shut down the texture pool
     953             :     TexturePoolOGL::Shutdown();
     954             : #endif
     955             : 
     956             :     // Shut down the default GL context provider.
     957           0 :     GLContextProvider::Shutdown();
     958             : 
     959             : #if defined(XP_WIN)
     960             :     // The above shutdown calls operate on the available context providers on
     961             :     // most platforms.  Windows is a "special snowflake", though, and has three
     962             :     // context providers available, so we have to shut all of them down.
     963             :     // We should only support the default GL provider on Windows; then, this
     964             :     // could go away. Unfortunately, we currently support WGL (the default) for
     965             :     // WebGL on Optimus.
     966             :     GLContextProviderEGL::Shutdown();
     967             : #endif
     968             : 
     969           0 :     if (XRE_IsParentProcess()) {
     970           0 :       GPUProcessManager::Shutdown();
     971             :     }
     972             : 
     973           0 :     gfx::Factory::ShutDown();
     974             : 
     975           0 :     delete gGfxPlatformPrefsLock;
     976             : 
     977           0 :     gfxVars::Shutdown();
     978           0 :     gfxPrefs::DestroySingleton();
     979           0 :     gfxFont::DestroySingletons();
     980             : 
     981           0 :     gfxConfig::Shutdown();
     982             : 
     983           0 :     gPlatform->WillShutdown();
     984             : 
     985           0 :     delete gPlatform;
     986           0 :     gPlatform = nullptr;
     987             : }
     988             : 
     989             : /* static */ void
     990           3 : gfxPlatform::InitLayersIPC()
     991             : {
     992           3 :   if (sLayersIPCIsUp) {
     993           0 :     return;
     994             :   }
     995           3 :   sLayersIPCIsUp = true;
     996             : 
     997           3 :   if (XRE_IsContentProcess()) {
     998           2 :     if (gfxVars::UseOMTP()) {
     999           0 :       layers::PaintThread::Start();
    1000             :     }
    1001           1 :   } else if (XRE_IsParentProcess()) {
    1002           1 :     if (gfxVars::UseWebRender()) {
    1003           0 :       wr::RenderThread::Start();
    1004             :     }
    1005             : 
    1006           1 :     layers::CompositorThreadHolder::Start();
    1007             :   }
    1008             : }
    1009             : 
    1010             : /* static */ void
    1011           0 : gfxPlatform::ShutdownLayersIPC()
    1012             : {
    1013           0 :     if (!sLayersIPCIsUp) {
    1014           0 :       return;
    1015             :     }
    1016           0 :     sLayersIPCIsUp = false;
    1017             : 
    1018           0 :     if (XRE_IsContentProcess()) {
    1019           0 :         gfx::VRManagerChild::ShutDown();
    1020             :         // cf bug 1215265.
    1021           0 :         if (gfxPrefs::ChildProcessShutdown()) {
    1022           0 :           layers::CompositorManagerChild::Shutdown();
    1023           0 :           layers::ImageBridgeChild::ShutDown();
    1024             :         }
    1025             : 
    1026           0 :         if (gfxVars::UseOMTP()) {
    1027           0 :           layers::PaintThread::Shutdown();
    1028             :         }
    1029           0 :     } else if (XRE_IsParentProcess()) {
    1030           0 :         gfx::VRManagerChild::ShutDown();
    1031           0 :         layers::CompositorManagerChild::Shutdown();
    1032           0 :         layers::ImageBridgeChild::ShutDown();
    1033             :         // This has to happen after shutting down the child protocols.
    1034           0 :         layers::CompositorThreadHolder::Shutdown();
    1035           0 :         if (gfxVars::UseWebRender()) {
    1036           0 :           wr::RenderThread::ShutDown();
    1037             :         }
    1038             : 
    1039             :     } else {
    1040             :       // TODO: There are other kind of processes and we should make sure gfx
    1041             :       // stuff is either not created there or shut down properly.
    1042             :     }
    1043             : }
    1044             : 
    1045             : void
    1046           0 : gfxPlatform::WillShutdown()
    1047             : {
    1048             :     // Destoy these first in case they depend on backend-specific resources.
    1049             :     // Otherwise, the backend's destructor would be called before the
    1050             :     // base gfxPlatform destructor.
    1051           0 :     mScreenReferenceSurface = nullptr;
    1052           0 :     mScreenReferenceDrawTarget = nullptr;
    1053           0 : }
    1054             : 
    1055           0 : gfxPlatform::~gfxPlatform()
    1056             : {
    1057             :     // The cairo folks think we should only clean up in debug builds,
    1058             :     // but we're generally in the habit of trying to shut down as
    1059             :     // cleanly as possible even in production code, so call this
    1060             :     // cairo_debug_* function unconditionally.
    1061             :     //
    1062             :     // because cairo can assert and thus crash on shutdown, don't do this in release builds
    1063             : #ifdef NS_FREE_PERMANENT_DATA
    1064             : #ifdef USE_SKIA
    1065             :     // must do Skia cleanup before Cairo cleanup, because Skia may be referencing
    1066             :     // Cairo objects e.g. through SkCairoFTTypeface
    1067           0 :     SkGraphics::PurgeFontCache();
    1068             : #endif
    1069             : 
    1070             : #if MOZ_TREE_CAIRO
    1071           0 :     cairo_debug_reset_static_data();
    1072             : #endif
    1073             : #endif
    1074           0 : }
    1075             : 
    1076             : /* static */ already_AddRefed<DrawTarget>
    1077           0 : gfxPlatform::CreateDrawTargetForSurface(gfxASurface *aSurface, const IntSize& aSize)
    1078             : {
    1079           0 :   SurfaceFormat format = aSurface->GetSurfaceFormat();
    1080           0 :   RefPtr<DrawTarget> drawTarget = Factory::CreateDrawTargetForCairoSurface(aSurface->CairoSurface(), aSize, &format);
    1081           0 :   if (!drawTarget) {
    1082           0 :     gfxWarning() << "gfxPlatform::CreateDrawTargetForSurface failed in CreateDrawTargetForCairoSurface";
    1083           0 :     return nullptr;
    1084             :   }
    1085           0 :   return drawTarget.forget();
    1086             : }
    1087             : 
    1088             : cairo_user_data_key_t kSourceSurface;
    1089             : 
    1090             : /**
    1091             :  * Record the backend that was used to construct the SourceSurface.
    1092             :  * When getting the cached SourceSurface for a gfxASurface/DrawTarget pair,
    1093             :  * we check to make sure the DrawTarget's backend matches the backend
    1094             :  * for the cached SourceSurface, and only use it if they match. This
    1095             :  * can avoid expensive and unnecessary readbacks.
    1096             :  */
    1097           0 : struct SourceSurfaceUserData
    1098             : {
    1099             :   RefPtr<SourceSurface> mSrcSurface;
    1100             :   BackendType mBackendType;
    1101             : };
    1102             : 
    1103           0 : void SourceBufferDestroy(void *srcSurfUD)
    1104             : {
    1105           0 :   delete static_cast<SourceSurfaceUserData*>(srcSurfUD);
    1106           0 : }
    1107             : 
    1108             : UserDataKey kThebesSurface;
    1109             : 
    1110           0 : struct DependentSourceSurfaceUserData
    1111             : {
    1112             :   RefPtr<gfxASurface> mSurface;
    1113             : };
    1114             : 
    1115           0 : void SourceSurfaceDestroyed(void *aData)
    1116             : {
    1117           0 :   delete static_cast<DependentSourceSurfaceUserData*>(aData);
    1118           0 : }
    1119             : 
    1120             : void
    1121           0 : gfxPlatform::ClearSourceSurfaceForSurface(gfxASurface *aSurface)
    1122             : {
    1123           0 :   aSurface->SetData(&kSourceSurface, nullptr, nullptr);
    1124           0 : }
    1125             : 
    1126             : /* static */ already_AddRefed<SourceSurface>
    1127           0 : gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget,
    1128             :                                         gfxASurface *aSurface,
    1129             :                                         bool aIsPlugin)
    1130             : {
    1131           0 :   if (!aSurface->CairoSurface() || aSurface->CairoStatus()) {
    1132           0 :     return nullptr;
    1133             :   }
    1134             : 
    1135           0 :   if (!aTarget) {
    1136           0 :     aTarget = gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
    1137             :   }
    1138             : 
    1139           0 :   void *userData = aSurface->GetData(&kSourceSurface);
    1140             : 
    1141           0 :   if (userData) {
    1142           0 :     SourceSurfaceUserData *surf = static_cast<SourceSurfaceUserData*>(userData);
    1143             : 
    1144           0 :     if (surf->mSrcSurface->IsValid() && surf->mBackendType == aTarget->GetBackendType()) {
    1145           0 :       RefPtr<SourceSurface> srcSurface(surf->mSrcSurface);
    1146           0 :       return srcSurface.forget();
    1147             :     }
    1148             :     // We can just continue here as when setting new user data the destroy
    1149             :     // function will be called for the old user data.
    1150             :   }
    1151             : 
    1152           0 :   SurfaceFormat format = aSurface->GetSurfaceFormat();
    1153             : 
    1154           0 :   if (aTarget->GetBackendType() == BackendType::CAIRO) {
    1155             :     // If we're going to be used with a CAIRO DrawTarget, then just create a
    1156             :     // SourceSurfaceCairo since we don't know the underlying type of the CAIRO
    1157             :     // DrawTarget and can't pick a better surface type. Doing this also avoids
    1158             :     // readback of aSurface's surface into memory if, for example, aSurface
    1159             :     // wraps an xlib cairo surface (which can be important to avoid a major
    1160             :     // slowdown).
    1161             :     //
    1162             :     // We return here regardless of whether CreateSourceSurfaceFromNativeSurface
    1163             :     // succeeds or not since we don't expect to be able to do any better below
    1164             :     // if it fails.
    1165             :     //
    1166             :     // Note that the returned SourceSurfaceCairo holds a strong reference to
    1167             :     // the cairo_surface_t* that it wraps, which essencially means it holds a
    1168             :     // strong reference to aSurface since aSurface shares its
    1169             :     // cairo_surface_t*'s reference count variable. As a result we can't cache
    1170             :     // srcBuffer on aSurface (see below) since aSurface would then hold a
    1171             :     // strong reference back to srcBuffer, creating a reference loop and a
    1172             :     // memory leak. Not caching is fine since wrapping is cheap enough (no
    1173             :     // copying) so we can just wrap again next time we're called.
    1174             :     return Factory::CreateSourceSurfaceForCairoSurface(aSurface->CairoSurface(),
    1175           0 :                                                        aSurface->GetSize(), format);
    1176             :   }
    1177             : 
    1178           0 :   RefPtr<SourceSurface> srcBuffer;
    1179             : 
    1180             :   // Currently no other DrawTarget types implement CreateSourceSurfaceFromNativeSurface
    1181             : 
    1182           0 :   if (!srcBuffer) {
    1183             :     // If aSurface wraps data, we can create a SourceSurfaceRawData that wraps
    1184             :     // the same data, then optimize it for aTarget:
    1185           0 :     RefPtr<DataSourceSurface> surf = GetWrappedDataSourceSurface(aSurface);
    1186           0 :     if (surf) {
    1187           0 :       srcBuffer = aIsPlugin ? aTarget->OptimizeSourceSurfaceForUnknownAlpha(surf)
    1188           0 :                             : aTarget->OptimizeSourceSurface(surf);
    1189             : 
    1190           0 :       if (srcBuffer == surf) {
    1191             :         // GetWrappedDataSourceSurface returns a SourceSurface that holds a
    1192             :         // strong reference to aSurface since it wraps aSurface's data and
    1193             :         // needs it to stay alive. As a result we can't cache srcBuffer on
    1194             :         // aSurface (below) since aSurface would then hold a strong reference
    1195             :         // back to srcBuffer, creating a reference loop and a memory leak. Not
    1196             :         // caching is fine since wrapping is cheap enough (no copying) so we
    1197             :         // can just wrap again next time we're called.
    1198             :         //
    1199             :         // Note that the check below doesn't catch this since srcBuffer will be a
    1200             :         // SourceSurfaceRawData object (even if aSurface is not a gfxImageSurface
    1201             :         // object), which is why we need this separate check.
    1202           0 :         return srcBuffer.forget();
    1203             :       }
    1204             :     }
    1205             :   }
    1206             : 
    1207           0 :   if (!srcBuffer) {
    1208           0 :     MOZ_ASSERT(aTarget->GetBackendType() != BackendType::CAIRO,
    1209             :                "We already tried CreateSourceSurfaceFromNativeSurface with a "
    1210             :                "DrawTargetCairo above");
    1211             :     // We've run out of performant options. We now try creating a SourceSurface
    1212             :     // using a temporary DrawTargetCairo and then optimizing it to aTarget's
    1213             :     // actual type. The CreateSourceSurfaceFromNativeSurface() call will
    1214             :     // likely create a DataSourceSurface (possibly involving copying and/or
    1215             :     // readback), and the OptimizeSourceSurface may well copy again and upload
    1216             :     // to the GPU. So, while this code path is rarely hit, hitting it may be
    1217             :     // very slow.
    1218           0 :     srcBuffer = Factory::CreateSourceSurfaceForCairoSurface(aSurface->CairoSurface(),
    1219           0 :                                                             aSurface->GetSize(), format);
    1220           0 :     if (srcBuffer) {
    1221           0 :       srcBuffer = aTarget->OptimizeSourceSurface(srcBuffer);
    1222             :     }
    1223             :   }
    1224             : 
    1225           0 :   if (!srcBuffer) {
    1226           0 :     return nullptr;
    1227             :   }
    1228             : 
    1229           0 :   if ((srcBuffer->GetType() == SurfaceType::CAIRO &&
    1230           0 :        static_cast<SourceSurfaceCairo*>(srcBuffer.get())->GetSurface() ==
    1231           0 :          aSurface->CairoSurface()) ||
    1232           0 :       (srcBuffer->GetType() == SurfaceType::CAIRO_IMAGE &&
    1233           0 :        static_cast<DataSourceSurfaceCairo*>(srcBuffer.get())->GetSurface() ==
    1234           0 :          aSurface->CairoSurface())) {
    1235             :     // See the "Note that the returned SourceSurfaceCairo..." comment above.
    1236           0 :     return srcBuffer.forget();
    1237             :   }
    1238             : 
    1239             :   // Add user data to aSurface so we can cache lookups in the future.
    1240           0 :   auto *srcSurfUD = new SourceSurfaceUserData;
    1241           0 :   srcSurfUD->mBackendType = aTarget->GetBackendType();
    1242           0 :   srcSurfUD->mSrcSurface = srcBuffer;
    1243           0 :   aSurface->SetData(&kSourceSurface, srcSurfUD, SourceBufferDestroy);
    1244             : 
    1245           0 :   return srcBuffer.forget();
    1246             : }
    1247             : 
    1248             : already_AddRefed<DataSourceSurface>
    1249           0 : gfxPlatform::GetWrappedDataSourceSurface(gfxASurface* aSurface)
    1250             : {
    1251           0 :   RefPtr<gfxImageSurface> image = aSurface->GetAsImageSurface();
    1252           0 :   if (!image) {
    1253           0 :     return nullptr;
    1254             :   }
    1255             :   RefPtr<DataSourceSurface> result =
    1256           0 :     Factory::CreateWrappingDataSourceSurface(image->Data(),
    1257             :                                              image->Stride(),
    1258           0 :                                              image->GetSize(),
    1259           0 :                                              ImageFormatToSurfaceFormat(image->Format()));
    1260             : 
    1261           0 :   if (!result) {
    1262           0 :     return nullptr;
    1263             :   }
    1264             : 
    1265             :   // If we wrapped the underlying data of aSurface, then we need to add user data
    1266             :   // to make sure aSurface stays alive until we are done with the data.
    1267           0 :   auto *srcSurfUD = new DependentSourceSurfaceUserData;
    1268           0 :   srcSurfUD->mSurface = aSurface;
    1269           0 :   result->AddUserData(&kThebesSurface, srcSurfUD, SourceSurfaceDestroyed);
    1270             : 
    1271           0 :   return result.forget();
    1272             : }
    1273             : 
    1274             : already_AddRefed<ScaledFont>
    1275           0 : gfxPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
    1276             : {
    1277             :   NativeFont nativeFont;
    1278           0 :   nativeFont.mType = NativeFontType::CAIRO_FONT_FACE;
    1279           0 :   nativeFont.mFont = aFont->GetCairoScaledFont();
    1280             :   return Factory::CreateScaledFontForNativeFont(nativeFont,
    1281             :                                                 aFont->GetUnscaledFont(),
    1282           0 :                                                 aFont->GetAdjustedSize());
    1283             : }
    1284             : 
    1285             : void
    1286           3 : gfxPlatform::ComputeTileSize()
    1287             : {
    1288             :   // The tile size should be picked in the parent processes
    1289             :   // and sent to the child processes over IPDL GetTileSize.
    1290           3 :   if (!XRE_IsParentProcess()) {
    1291           2 :     return;
    1292             :   }
    1293             : 
    1294           1 :   int32_t w = gfxPrefs::LayersTileWidth();
    1295           1 :   int32_t h = gfxPrefs::LayersTileHeight();
    1296             : 
    1297           1 :   if (gfxPrefs::LayersTilesAdjust()) {
    1298           1 :     gfx::IntSize screenSize = GetScreenSize();
    1299           1 :     if (screenSize.width > 0) {
    1300             :       // Choose a size so that there are between 2 and 4 tiles per screen width.
    1301             :       // FIXME: we should probably make sure this is within the max texture size,
    1302             :       // but I think everything should at least support 1024
    1303           1 :       w = h = clamped(int32_t(RoundUpPow2(screenSize.width)) / 4, 256, 1024);
    1304             :     }
    1305             :   }
    1306             : 
    1307             :   // Don't allow changing the tile size after we've set it.
    1308             :   // Right now the code assumes that the tile size doesn't change.
    1309           1 :   MOZ_ASSERT(gfxVars::TileSize().width == -1 &&
    1310             :              gfxVars::TileSize().height == -1);
    1311             : 
    1312           1 :   gfxVars::SetTileSize(IntSize(w, h));
    1313             : }
    1314             : 
    1315             : void
    1316           3 : gfxPlatform::PopulateScreenInfo()
    1317             : {
    1318           6 :   nsCOMPtr<nsIScreenManager> manager = do_GetService("@mozilla.org/gfx/screenmanager;1");
    1319           3 :   MOZ_ASSERT(manager, "failed to get nsIScreenManager");
    1320             : 
    1321           6 :   nsCOMPtr<nsIScreen> screen;
    1322           3 :   manager->GetPrimaryScreen(getter_AddRefs(screen));
    1323           3 :   if (!screen) {
    1324             :     // This can happen in xpcshell, for instance
    1325           0 :     return;
    1326             :   }
    1327             : 
    1328           3 :   screen->GetColorDepth(&mScreenDepth);
    1329           3 :   if (XRE_IsParentProcess()) {
    1330           1 :     gfxVars::SetScreenDepth(mScreenDepth);
    1331             :   }
    1332             : 
    1333             :   int left, top;
    1334           3 :   screen->GetRect(&left, &top, &mScreenSize.width, &mScreenSize.height);
    1335             : }
    1336             : 
    1337             : bool
    1338           0 : gfxPlatform::SupportsAzureContentForDrawTarget(DrawTarget* aTarget)
    1339             : {
    1340           0 :   if (!aTarget || !aTarget->IsValid()) {
    1341           0 :     return false;
    1342             :   }
    1343             : 
    1344             : #ifdef USE_SKIA_GPU
    1345             :  // Skia content rendering doesn't support GPU acceleration, so we can't
    1346             :  // use the same backend if the current backend is accelerated.
    1347           0 :  if ((aTarget->GetType() == DrawTargetType::HARDWARE_RASTER)
    1348           0 :      && (aTarget->GetBackendType() ==  BackendType::SKIA))
    1349             :  {
    1350           0 :   return false;
    1351             :  }
    1352             : #endif
    1353             : 
    1354           0 :   return SupportsAzureContentForType(aTarget->GetBackendType());
    1355             : }
    1356             : 
    1357           0 : bool gfxPlatform::AllowOpenGLCanvas()
    1358             : {
    1359             :   // For now, only allow Skia+OpenGL, unless it's blocked.
    1360             :   // Allow acceleration on Skia if the preference is set, unless it's blocked
    1361             :   // as long as we have the accelerated layers
    1362             : 
    1363             :   // The compositor backend is only set correctly in the parent process,
    1364             :   // so we let content process always assume correct compositor backend.
    1365             :   // The callers have to do the right thing.
    1366           0 :   bool correctBackend = !XRE_IsParentProcess() ||
    1367           0 :     ((mCompositorBackend == LayersBackend::LAYERS_OPENGL) &&
    1368           0 :      (GetContentBackendFor(mCompositorBackend) == BackendType::SKIA));
    1369             : 
    1370           0 :   if (gfxPrefs::CanvasAzureAccelerated() && correctBackend) {
    1371           0 :     nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
    1372             :     int32_t status;
    1373           0 :     nsCString discardFailureId;
    1374           0 :     return !gfxInfo ||
    1375           0 :       (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_CANVAS2D_ACCELERATION,
    1376             :                                               discardFailureId,
    1377           0 :                                               &status)) &&
    1378           0 :        status == nsIGfxInfo::FEATURE_STATUS_OK);
    1379             :   }
    1380           0 :   return false;
    1381             : }
    1382             : 
    1383             : void
    1384           0 : gfxPlatform::InitializeSkiaCacheLimits()
    1385             : {
    1386           0 :   if (AllowOpenGLCanvas()) {
    1387             : #ifdef USE_SKIA_GPU
    1388           0 :     bool usingDynamicCache = gfxPrefs::CanvasSkiaGLDynamicCache();
    1389           0 :     int cacheItemLimit = gfxPrefs::CanvasSkiaGLCacheItems();
    1390           0 :     uint64_t cacheSizeLimit = std::max(gfxPrefs::CanvasSkiaGLCacheSize(), (int32_t)0);
    1391             : 
    1392             :     // Prefs are in megabytes, but we want the sizes in bytes
    1393           0 :     cacheSizeLimit *= 1024*1024;
    1394             : 
    1395           0 :     if (usingDynamicCache) {
    1396           0 :       if (mTotalSystemMemory < 512*1024*1024) {
    1397             :         // We need a very minimal cache on anything smaller than 512mb.
    1398             :         // Note the large jump as we cross 512mb (from 2mb to 32mb).
    1399           0 :         cacheSizeLimit = 2*1024*1024;
    1400           0 :       } else if (mTotalSystemMemory > 0) {
    1401           0 :         cacheSizeLimit = mTotalSystemMemory / 16;
    1402             :       }
    1403             :     }
    1404             : 
    1405             :     // Ensure cache size doesn't overflow on 32-bit platforms.
    1406           0 :     cacheSizeLimit = std::min(cacheSizeLimit, (uint64_t)SIZE_MAX);
    1407             : 
    1408             :   #ifdef DEBUG
    1409           0 :     printf_stderr("Determined SkiaGL cache limits: Size %" PRIu64 ", Items: %i\n", cacheSizeLimit, cacheItemLimit);
    1410             :   #endif
    1411             : 
    1412           0 :     mSkiaGlue->GetGrContext()->setResourceCacheLimits(cacheItemLimit, (size_t)cacheSizeLimit);
    1413             : #endif
    1414             :   }
    1415           0 : }
    1416             : 
    1417             : SkiaGLGlue*
    1418           0 : gfxPlatform::GetSkiaGLGlue()
    1419             : {
    1420             : #ifdef USE_SKIA_GPU
    1421             :   // Check the accelerated Canvas is enabled for the first time,
    1422             :   // because the callers should check it before using.
    1423           0 :   if (!mSkiaGlue && !AllowOpenGLCanvas()) {
    1424           0 :     return nullptr;
    1425             :   }
    1426             : 
    1427           0 :   if (!mSkiaGlue) {
    1428             :     /* Dummy context. We always draw into a FBO.
    1429             :      *
    1430             :      * FIXME: This should be stored in TLS or something, since there needs to be one for each thread using it. As it
    1431             :      * stands, this only works on the main thread.
    1432             :      */
    1433           0 :     RefPtr<GLContext> glContext;
    1434           0 :     nsCString discardFailureId;
    1435           0 :     glContext = GLContextProvider::CreateHeadless(CreateContextFlags::REQUIRE_COMPAT_PROFILE |
    1436             :                                                   CreateContextFlags::ALLOW_OFFLINE_RENDERER,
    1437           0 :                                                   &discardFailureId);
    1438           0 :     if (!glContext) {
    1439           0 :       printf_stderr("Failed to create GLContext for SkiaGL!\n");
    1440           0 :       return nullptr;
    1441             :     }
    1442           0 :     mSkiaGlue = new SkiaGLGlue(glContext);
    1443           0 :     MOZ_ASSERT(mSkiaGlue->GetGrContext(), "No GrContext");
    1444           0 :     InitializeSkiaCacheLimits();
    1445             :   }
    1446             : #endif
    1447             : 
    1448           0 :   return mSkiaGlue;
    1449             : }
    1450             : 
    1451             : void
    1452           3 : gfxPlatform::PurgeSkiaFontCache()
    1453             : {
    1454             : #ifdef USE_SKIA
    1455           3 :   if (gfxPlatform::GetPlatform()->GetDefaultContentBackend() == BackendType::SKIA) {
    1456           3 :     SkGraphics::PurgeFontCache();
    1457             :   }
    1458             : #endif
    1459           3 : }
    1460             : 
    1461             : void
    1462           0 : gfxPlatform::PurgeSkiaGPUCache()
    1463             : {
    1464             : #ifdef USE_SKIA_GPU
    1465           0 :   if (!mSkiaGlue)
    1466           0 :       return;
    1467             : 
    1468           0 :   mSkiaGlue->GetGrContext()->freeGpuResources();
    1469             :   // GrContext::flush() doesn't call glFlush. Call it here.
    1470           0 :   mSkiaGlue->GetGLContext()->MakeCurrent();
    1471           0 :   mSkiaGlue->GetGLContext()->fFlush();
    1472             : #endif
    1473             : }
    1474             : 
    1475             : bool
    1476           0 : gfxPlatform::HasEnoughTotalSystemMemoryForSkiaGL()
    1477             : {
    1478           0 :   return true;
    1479             : }
    1480             : 
    1481             : already_AddRefed<DrawTarget>
    1482          22 : gfxPlatform::CreateDrawTargetForBackend(BackendType aBackend, const IntSize& aSize, SurfaceFormat aFormat)
    1483             : {
    1484             :   // There is a bunch of knowledge in the gfxPlatform heirarchy about how to
    1485             :   // create the best offscreen surface for the current system and situation. We
    1486             :   // can easily take advantage of this for the Cairo backend, so that's what we
    1487             :   // do.
    1488             :   // mozilla::gfx::Factory can get away without having all this knowledge for
    1489             :   // now, but this might need to change in the future (using
    1490             :   // CreateOffscreenSurface() and CreateDrawTargetForSurface() for all
    1491             :   // backends).
    1492          22 :   if (aBackend == BackendType::CAIRO) {
    1493           0 :     RefPtr<gfxASurface> surf = CreateOffscreenSurface(aSize, SurfaceFormatToImageFormat(aFormat));
    1494           0 :     if (!surf || surf->CairoStatus()) {
    1495           0 :       return nullptr;
    1496             :     }
    1497           0 :     return CreateDrawTargetForSurface(surf, aSize);
    1498             :   }
    1499          22 :   return Factory::CreateDrawTarget(aBackend, aSize, aFormat);
    1500             : }
    1501             : 
    1502             : already_AddRefed<DrawTarget>
    1503           0 : gfxPlatform::CreateOffscreenCanvasDrawTarget(const IntSize& aSize, SurfaceFormat aFormat)
    1504             : {
    1505           0 :   NS_ASSERTION(mPreferredCanvasBackend != BackendType::NONE, "No backend.");
    1506           0 :   RefPtr<DrawTarget> target = CreateDrawTargetForBackend(mPreferredCanvasBackend, aSize, aFormat);
    1507           0 :   if (target ||
    1508           0 :       mFallbackCanvasBackend == BackendType::NONE) {
    1509           0 :     return target.forget();
    1510             :   }
    1511             : 
    1512             : #ifdef XP_WIN
    1513             :   // On Windows, the fallback backend (Cairo) should use its image backend.
    1514             :   return Factory::CreateDrawTarget(mFallbackCanvasBackend, aSize, aFormat);
    1515             : #else
    1516           0 :   return CreateDrawTargetForBackend(mFallbackCanvasBackend, aSize, aFormat);
    1517             : #endif
    1518             : }
    1519             : 
    1520             : already_AddRefed<DrawTarget>
    1521           4 : gfxPlatform::CreateOffscreenContentDrawTarget(const IntSize& aSize, SurfaceFormat aFormat)
    1522             : {
    1523           4 :   NS_ASSERTION(mContentBackend != BackendType::NONE, "No backend.");
    1524           4 :   return CreateDrawTargetForBackend(mContentBackend, aSize, aFormat);
    1525             : }
    1526             : 
    1527             : already_AddRefed<DrawTarget>
    1528           0 : gfxPlatform::CreateSimilarSoftwareDrawTarget(DrawTarget* aDT,
    1529             :                                              const IntSize& aSize,
    1530             :                                              SurfaceFormat aFormat)
    1531             : {
    1532           0 :   RefPtr<DrawTarget> dt;
    1533             : 
    1534           0 :   if (Factory::DoesBackendSupportDataDrawtarget(aDT->GetBackendType())) {
    1535           0 :     dt = aDT->CreateSimilarDrawTarget(aSize, aFormat);
    1536             :   } else {
    1537             : #ifdef USE_SKIA
    1538           0 :     BackendType backendType = BackendType::SKIA;
    1539             : #else
    1540             :     BackendType backendType = BackendType::CAIRO;
    1541             : #endif
    1542           0 :     dt = Factory::CreateDrawTarget(backendType, aSize, aFormat);
    1543             :   }
    1544             : 
    1545           0 :   return dt.forget();
    1546             : }
    1547             : 
    1548             : /* static */ already_AddRefed<DrawTarget>
    1549          27 : gfxPlatform::CreateDrawTargetForData(unsigned char* aData,
    1550             :                                      const IntSize& aSize,
    1551             :                                      int32_t aStride,
    1552             :                                      SurfaceFormat aFormat,
    1553             :                                      bool aUninitialized)
    1554             : {
    1555          27 :   BackendType backendType = gfxVars::ContentBackend();
    1556          27 :   NS_ASSERTION(backendType != BackendType::NONE, "No backend.");
    1557             : 
    1558          27 :   if (!Factory::DoesBackendSupportDataDrawtarget(backendType)) {
    1559             : #ifdef USE_SKIA
    1560           0 :     backendType = BackendType::SKIA;
    1561             : #else
    1562             :     backendType = BackendType::CAIRO;
    1563             : #endif
    1564             :   }
    1565             : 
    1566          54 :   RefPtr<DrawTarget> dt = Factory::CreateDrawTargetForData(backendType,
    1567             :                                                            aData, aSize,
    1568             :                                                            aStride, aFormat,
    1569          54 :                                                            aUninitialized);
    1570             : 
    1571          54 :   return dt.forget();
    1572             : }
    1573             : 
    1574             : /* static */ BackendType
    1575          24 : gfxPlatform::BackendTypeForName(const nsCString& aName)
    1576             : {
    1577          24 :   if (aName.EqualsLiteral("cairo"))
    1578           0 :     return BackendType::CAIRO;
    1579          24 :   if (aName.EqualsLiteral("skia"))
    1580          24 :     return BackendType::SKIA;
    1581           0 :   if (aName.EqualsLiteral("direct2d"))
    1582           0 :     return BackendType::DIRECT2D;
    1583           0 :   if (aName.EqualsLiteral("direct2d1.1"))
    1584           0 :     return BackendType::DIRECT2D1_1;
    1585           0 :   return BackendType::NONE;
    1586             : }
    1587             : 
    1588             : nsresult
    1589           0 : gfxPlatform::GetFontList(nsIAtom *aLangGroup,
    1590             :                          const nsACString& aGenericFamily,
    1591             :                          nsTArray<nsString>& aListOfFonts)
    1592             : {
    1593           0 :     gfxPlatformFontList::PlatformFontList()->GetFontList(aLangGroup,
    1594             :                                                          aGenericFamily,
    1595           0 :                                                          aListOfFonts);
    1596           0 :     return NS_OK;
    1597             : }
    1598             : 
    1599             : nsresult
    1600           0 : gfxPlatform::UpdateFontList()
    1601             : {
    1602           0 :     gfxPlatformFontList::PlatformFontList()->UpdateFontList();
    1603           0 :     return NS_OK;
    1604             : }
    1605             : 
    1606             : nsresult
    1607           0 : gfxPlatform::GetStandardFamilyName(const nsAString& aFontName,
    1608             :                                    nsAString& aFamilyName)
    1609             : {
    1610           0 :     gfxPlatformFontList::PlatformFontList()->GetStandardFamilyName(aFontName,
    1611           0 :                                                                    aFamilyName);
    1612           0 :     return NS_OK;
    1613             : }
    1614             : 
    1615             : nsString
    1616           0 : gfxPlatform::GetDefaultFontName(const nsACString& aLangGroup,
    1617             :                                 const nsACString& aGenericFamily)
    1618             : {
    1619             :     gfxFontFamily* fontFamily = gfxPlatformFontList::PlatformFontList()->
    1620           0 :         GetDefaultFontFamily(aLangGroup, aGenericFamily);
    1621           0 :     if (!fontFamily) {
    1622           0 :       return EmptyString();
    1623             :     }
    1624           0 :     nsAutoString result;
    1625           0 :     fontFamily->LocalizedName(result);
    1626           0 :     return result;
    1627             : }
    1628             : 
    1629             : bool
    1630          13 : gfxPlatform::DownloadableFontsEnabled()
    1631             : {
    1632          13 :     if (mAllowDownloadableFonts == UNINITIALIZED_VALUE) {
    1633           2 :         mAllowDownloadableFonts =
    1634           2 :             Preferences::GetBool(GFX_DOWNLOADABLE_FONTS_ENABLED, false);
    1635             :     }
    1636             : 
    1637          13 :     return mAllowDownloadableFonts;
    1638             : }
    1639             : 
    1640             : bool
    1641           0 : gfxPlatform::UseCmapsDuringSystemFallback()
    1642             : {
    1643           0 :     if (mFallbackUsesCmaps == UNINITIALIZED_VALUE) {
    1644           0 :         mFallbackUsesCmaps =
    1645           0 :             Preferences::GetBool(GFX_PREF_FALLBACK_USE_CMAPS, false);
    1646             :     }
    1647             : 
    1648           0 :     return mFallbackUsesCmaps;
    1649             : }
    1650             : 
    1651             : bool
    1652          92 : gfxPlatform::OpenTypeSVGEnabled()
    1653             : {
    1654          92 :     if (mOpenTypeSVGEnabled == UNINITIALIZED_VALUE) {
    1655           2 :         mOpenTypeSVGEnabled =
    1656           2 :             Preferences::GetBool(GFX_PREF_OPENTYPE_SVG, false);
    1657             :     }
    1658             : 
    1659          92 :     return mOpenTypeSVGEnabled > 0;
    1660             : }
    1661             : 
    1662             : uint32_t
    1663         122 : gfxPlatform::WordCacheCharLimit()
    1664             : {
    1665         122 :     if (mWordCacheCharLimit == UNINITIALIZED_VALUE) {
    1666           2 :         mWordCacheCharLimit =
    1667           2 :             Preferences::GetInt(GFX_PREF_WORD_CACHE_CHARLIMIT, 32);
    1668           2 :         if (mWordCacheCharLimit < 0) {
    1669           0 :             mWordCacheCharLimit = 32;
    1670             :         }
    1671             :     }
    1672             : 
    1673         122 :     return uint32_t(mWordCacheCharLimit);
    1674             : }
    1675             : 
    1676             : uint32_t
    1677         127 : gfxPlatform::WordCacheMaxEntries()
    1678             : {
    1679         127 :     if (mWordCacheMaxEntries == UNINITIALIZED_VALUE) {
    1680           2 :         mWordCacheMaxEntries =
    1681           2 :             Preferences::GetInt(GFX_PREF_WORD_CACHE_MAXENTRIES, 10000);
    1682           2 :         if (mWordCacheMaxEntries < 0) {
    1683           0 :             mWordCacheMaxEntries = 10000;
    1684             :         }
    1685             :     }
    1686             : 
    1687         127 :     return uint32_t(mWordCacheMaxEntries);
    1688             : }
    1689             : 
    1690             : bool
    1691           0 : gfxPlatform::UseGraphiteShaping()
    1692             : {
    1693           0 :     if (mGraphiteShapingEnabled == UNINITIALIZED_VALUE) {
    1694           0 :         mGraphiteShapingEnabled =
    1695           0 :             Preferences::GetBool(GFX_PREF_GRAPHITE_SHAPING, false);
    1696             :     }
    1697             : 
    1698           0 :     return mGraphiteShapingEnabled;
    1699             : }
    1700             : 
    1701             : gfxFontEntry*
    1702           0 : gfxPlatform::LookupLocalFont(const nsAString& aFontName,
    1703             :                              uint16_t aWeight,
    1704             :                              int16_t aStretch,
    1705             :                              uint8_t aStyle)
    1706             : {
    1707           0 :     return gfxPlatformFontList::PlatformFontList()->LookupLocalFont(aFontName,
    1708             :                                                                     aWeight,
    1709             :                                                                     aStretch,
    1710           0 :                                                                     aStyle);
    1711             : }
    1712             : 
    1713             : gfxFontEntry*
    1714           0 : gfxPlatform::MakePlatformFont(const nsAString& aFontName,
    1715             :                               uint16_t aWeight,
    1716             :                               int16_t aStretch,
    1717             :                               uint8_t aStyle,
    1718             :                               const uint8_t* aFontData,
    1719             :                               uint32_t aLength)
    1720             : {
    1721           0 :     return gfxPlatformFontList::PlatformFontList()->MakePlatformFont(aFontName,
    1722             :                                                                      aWeight,
    1723             :                                                                      aStretch,
    1724             :                                                                      aStyle,
    1725             :                                                                      aFontData,
    1726           0 :                                                                      aLength);
    1727             : }
    1728             : 
    1729             : mozilla::layers::DiagnosticTypes
    1730          29 : gfxPlatform::GetLayerDiagnosticTypes()
    1731             : {
    1732          29 :   mozilla::layers::DiagnosticTypes type = DiagnosticTypes::NO_DIAGNOSTIC;
    1733          29 :   if (gfxPrefs::DrawLayerBorders()) {
    1734           0 :     type |= mozilla::layers::DiagnosticTypes::LAYER_BORDERS;
    1735             :   }
    1736          29 :   if (gfxPrefs::DrawTileBorders()) {
    1737           0 :     type |= mozilla::layers::DiagnosticTypes::TILE_BORDERS;
    1738             :   }
    1739          29 :   if (gfxPrefs::DrawBigImageBorders()) {
    1740           0 :     type |= mozilla::layers::DiagnosticTypes::BIGIMAGE_BORDERS;
    1741             :   }
    1742          29 :   if (gfxPrefs::FlashLayerBorders()) {
    1743           0 :     type |= mozilla::layers::DiagnosticTypes::FLASH_BORDERS;
    1744             :   }
    1745          29 :   return type;
    1746             : }
    1747             : 
    1748             : void
    1749           6 : gfxPlatform::InitBackendPrefs(uint32_t aCanvasBitmask, BackendType aCanvasDefault,
    1750             :                               uint32_t aContentBitmask, BackendType aContentDefault)
    1751             : {
    1752           6 :     mPreferredCanvasBackend = GetCanvasBackendPref(aCanvasBitmask);
    1753           6 :     if (mPreferredCanvasBackend == BackendType::NONE) {
    1754           0 :         mPreferredCanvasBackend = aCanvasDefault;
    1755             :     }
    1756             : 
    1757           6 :     if (mPreferredCanvasBackend == BackendType::DIRECT2D1_1) {
    1758             :       // Falling back to D2D 1.0 won't help us here. When D2D 1.1 DT creation
    1759             :       // fails it means the surface was too big or there's something wrong with
    1760             :       // the device. D2D 1.0 will encounter a similar situation.
    1761           0 :       mFallbackCanvasBackend =
    1762           0 :           GetCanvasBackendPref(aCanvasBitmask &
    1763           0 :                                ~(BackendTypeBit(mPreferredCanvasBackend) | BackendTypeBit(BackendType::DIRECT2D)));
    1764             :     } else {
    1765           6 :       mFallbackCanvasBackend =
    1766           6 :           GetCanvasBackendPref(aCanvasBitmask & ~BackendTypeBit(mPreferredCanvasBackend));
    1767             :     }
    1768             : 
    1769             : 
    1770           6 :     mContentBackendBitmask = aContentBitmask;
    1771           6 :     mContentBackend = GetContentBackendPref(mContentBackendBitmask);
    1772           6 :     if (mContentBackend == BackendType::NONE) {
    1773           0 :         mContentBackend = aContentDefault;
    1774             :         // mContentBackendBitmask is our canonical reference for supported
    1775             :         // backends so we need to add the default if we are using it and
    1776             :         // overriding the prefs.
    1777           0 :         mContentBackendBitmask |= BackendTypeBit(aContentDefault);
    1778             :     }
    1779             : 
    1780          12 :     uint32_t swBackendBits = BackendTypeBit(BackendType::SKIA) |
    1781          12 :                              BackendTypeBit(BackendType::CAIRO);
    1782           6 :     mSoftwareBackend = GetContentBackendPref(swBackendBits);
    1783             : 
    1784           6 :     if (XRE_IsParentProcess()) {
    1785           2 :         gfxVars::SetContentBackend(mContentBackend);
    1786           2 :         gfxVars::SetSoftwareBackend(mSoftwareBackend);
    1787             :     }
    1788           6 : }
    1789             : 
    1790             : /* static */ BackendType
    1791          12 : gfxPlatform::GetCanvasBackendPref(uint32_t aBackendBitmask)
    1792             : {
    1793          12 :     return GetBackendPref("gfx.canvas.azure.backends", aBackendBitmask);
    1794             : }
    1795             : 
    1796             : /* static */ BackendType
    1797          12 : gfxPlatform::GetContentBackendPref(uint32_t &aBackendBitmask)
    1798             : {
    1799          12 :     return GetBackendPref("gfx.content.azure.backends", aBackendBitmask);
    1800             : }
    1801             : 
    1802             : /* static */ BackendType
    1803          24 : gfxPlatform::GetBackendPref(const char* aBackendPrefName, uint32_t &aBackendBitmask)
    1804             : {
    1805          48 :     nsTArray<nsCString> backendList;
    1806          48 :     nsCString prefString;
    1807          24 :     if (NS_SUCCEEDED(Preferences::GetCString(aBackendPrefName, &prefString))) {
    1808          24 :         ParseString(prefString, ',', backendList);
    1809             :     }
    1810             : 
    1811          24 :     uint32_t allowedBackends = 0;
    1812          24 :     BackendType result = BackendType::NONE;
    1813          48 :     for (uint32_t i = 0; i < backendList.Length(); ++i) {
    1814          24 :         BackendType type = BackendTypeForName(backendList[i]);
    1815          24 :         if (BackendTypeBit(type) & aBackendBitmask) {
    1816          18 :             allowedBackends |= BackendTypeBit(type);
    1817          18 :             if (result == BackendType::NONE) {
    1818          18 :                 result = type;
    1819             :             }
    1820             :         }
    1821             :     }
    1822             : 
    1823          24 :     aBackendBitmask = allowedBackends;
    1824          48 :     return result;
    1825             : }
    1826             : 
    1827             : bool
    1828           4 : gfxPlatform::InSafeMode()
    1829             : {
    1830             :   static bool sSafeModeInitialized = false;
    1831             :   static bool sInSafeMode = false;
    1832             : 
    1833           4 :   if (!sSafeModeInitialized) {
    1834           3 :     sSafeModeInitialized = true;
    1835           6 :     nsCOMPtr<nsIXULRuntime> xr = do_GetService("@mozilla.org/xre/runtime;1");
    1836           3 :     if (xr) {
    1837           3 :       xr->GetInSafeMode(&sInSafeMode);
    1838             :     }
    1839             :   }
    1840           4 :   return sInSafeMode;
    1841             : }
    1842             : 
    1843             : bool
    1844           0 : gfxPlatform::OffMainThreadCompositingEnabled()
    1845             : {
    1846           0 :   return UsesOffMainThreadCompositing();
    1847             : }
    1848             : 
    1849             : eCMSMode
    1850         341 : gfxPlatform::GetCMSMode()
    1851             : {
    1852         341 :     if (!gCMSInitialized) {
    1853           2 :         int32_t mode = gfxPrefs::CMSMode();
    1854           2 :         if (mode >= 0 && mode < eCMSMode_AllCount) {
    1855           2 :             gCMSMode = static_cast<eCMSMode>(mode);
    1856             :         }
    1857             : 
    1858           2 :         bool enableV4 = gfxPrefs::CMSEnableV4();
    1859           2 :         if (enableV4) {
    1860           0 :             qcms_enable_iccv4();
    1861             :         }
    1862           2 :         gCMSInitialized = true;
    1863             :     }
    1864         341 :     return gCMSMode;
    1865             : }
    1866             : 
    1867             : int
    1868          31 : gfxPlatform::GetRenderingIntent()
    1869             : {
    1870             :   // gfxPrefs.h is using 0 as the default for the rendering
    1871             :   // intent preference, based on that being the value for
    1872             :   // QCMS_INTENT_DEFAULT.  Assert here to catch if that ever
    1873             :   // changes and we can then figure out what to do about it.
    1874             :   MOZ_ASSERT(QCMS_INTENT_DEFAULT == 0);
    1875             : 
    1876             :   /* Try to query the pref system for a rendering intent. */
    1877          31 :   int32_t pIntent = gfxPrefs::CMSRenderingIntent();
    1878          31 :   if ((pIntent < QCMS_INTENT_MIN) || (pIntent > QCMS_INTENT_MAX)) {
    1879             :     /* If the pref is out of range, use embedded profile. */
    1880           0 :     pIntent = -1;
    1881             :   }
    1882          31 :   return pIntent;
    1883             : }
    1884             : 
    1885             : void
    1886           0 : gfxPlatform::TransformPixel(const Color& in, Color& out, qcms_transform *transform)
    1887             : {
    1888             : 
    1889           0 :     if (transform) {
    1890             :         /* we want the bytes in RGB order */
    1891             : #ifdef IS_LITTLE_ENDIAN
    1892             :         /* ABGR puts the bytes in |RGBA| order on little endian */
    1893           0 :         uint32_t packed = in.ToABGR();
    1894             :         qcms_transform_data(transform,
    1895             :                        (uint8_t *)&packed, (uint8_t *)&packed,
    1896           0 :                        1);
    1897           0 :         out = Color::FromABGR(packed);
    1898             : #else
    1899             :         /* ARGB puts the bytes in |ARGB| order on big endian */
    1900             :         uint32_t packed = in.UnusualToARGB();
    1901             :         /* add one to move past the alpha byte */
    1902             :         qcms_transform_data(transform,
    1903             :                        (uint8_t *)&packed + 1, (uint8_t *)&packed + 1,
    1904             :                        1);
    1905             :         out = Color::UnusualFromARGB(packed);
    1906             : #endif
    1907             :     }
    1908             : 
    1909           0 :     else if (&out != &in)
    1910           0 :         out = in;
    1911           0 : }
    1912             : 
    1913             : void
    1914           0 : gfxPlatform::GetPlatformCMSOutputProfile(void *&mem, size_t &size)
    1915             : {
    1916           0 :     mem = nullptr;
    1917           0 :     size = 0;
    1918           0 : }
    1919             : 
    1920             : void
    1921           3 : gfxPlatform::GetCMSOutputProfileData(void *&mem, size_t &size)
    1922             : {
    1923           6 :     nsAdoptingCString fname = Preferences::GetCString("gfx.color_management.display_profile");
    1924           3 :     if (!fname.IsEmpty()) {
    1925           0 :         qcms_data_from_path(fname, &mem, &size);
    1926             :     }
    1927             :     else {
    1928           3 :         gfxPlatform::GetPlatform()->GetPlatformCMSOutputProfile(mem, size);
    1929             :     }
    1930           3 : }
    1931             : 
    1932             : void
    1933           3 : gfxPlatform::CreateCMSOutputProfile()
    1934             : {
    1935           3 :     if (!gCMSOutputProfile) {
    1936             :         /* Determine if we're using the internal override to force sRGB as
    1937             :            an output profile for reftests. See Bug 452125.
    1938             : 
    1939             :            Note that we don't normally (outside of tests) set a
    1940             :            default value of this preference, which means nsIPrefBranch::GetBoolPref
    1941             :            will typically throw (and leave its out-param untouched).
    1942             :          */
    1943           3 :         if (Preferences::GetBool(GFX_PREF_CMS_FORCE_SRGB, false)) {
    1944           0 :             gCMSOutputProfile = GetCMSsRGBProfile();
    1945             :         }
    1946             : 
    1947           3 :         if (!gCMSOutputProfile) {
    1948           3 :             void* mem = nullptr;
    1949           3 :             size_t size = 0;
    1950             : 
    1951           3 :             GetCMSOutputProfileData(mem, size);
    1952           3 :             if ((mem != nullptr) && (size > 0)) {
    1953           0 :                 gCMSOutputProfile = qcms_profile_from_memory(mem, size);
    1954           0 :                 free(mem);
    1955             :             }
    1956             :         }
    1957             : 
    1958             :         /* Determine if the profile looks bogus. If so, close the profile
    1959             :          * and use sRGB instead. See bug 460629, */
    1960           3 :         if (gCMSOutputProfile && qcms_profile_is_bogus(gCMSOutputProfile)) {
    1961           0 :             NS_ASSERTION(gCMSOutputProfile != GetCMSsRGBProfile(),
    1962             :                          "Builtin sRGB profile tagged as bogus!!!");
    1963           0 :             qcms_profile_release(gCMSOutputProfile);
    1964           0 :             gCMSOutputProfile = nullptr;
    1965             :         }
    1966             : 
    1967           3 :         if (!gCMSOutputProfile) {
    1968           3 :             gCMSOutputProfile = GetCMSsRGBProfile();
    1969             :         }
    1970             :         /* Precache the LUT16 Interpolations for the output profile. See
    1971             :            bug 444661 for details. */
    1972           3 :         qcms_profile_precache_output_transform(gCMSOutputProfile);
    1973             :     }
    1974           3 : }
    1975             : 
    1976             : qcms_profile *
    1977          16 : gfxPlatform::GetCMSOutputProfile()
    1978             : {
    1979          16 :     return gCMSOutputProfile;
    1980             : }
    1981             : 
    1982             : qcms_profile *
    1983           3 : gfxPlatform::GetCMSsRGBProfile()
    1984             : {
    1985           3 :     if (!gCMSsRGBProfile) {
    1986             : 
    1987             :         /* Create the profile using qcms. */
    1988           3 :         gCMSsRGBProfile = qcms_profile_sRGB();
    1989             :     }
    1990           3 :     return gCMSsRGBProfile;
    1991             : }
    1992             : 
    1993             : qcms_transform *
    1994           0 : gfxPlatform::GetCMSRGBTransform()
    1995             : {
    1996           0 :     if (!gCMSRGBTransform) {
    1997             :         qcms_profile *inProfile, *outProfile;
    1998           0 :         outProfile = GetCMSOutputProfile();
    1999           0 :         inProfile = GetCMSsRGBProfile();
    2000             : 
    2001           0 :         if (!inProfile || !outProfile)
    2002           0 :             return nullptr;
    2003             : 
    2004           0 :         gCMSRGBTransform = qcms_transform_create(inProfile, QCMS_DATA_RGB_8,
    2005             :                                               outProfile, QCMS_DATA_RGB_8,
    2006             :                                              QCMS_INTENT_PERCEPTUAL);
    2007             :     }
    2008             : 
    2009           0 :     return gCMSRGBTransform;
    2010             : }
    2011             : 
    2012             : qcms_transform *
    2013           0 : gfxPlatform::GetCMSInverseRGBTransform()
    2014             : {
    2015           0 :     if (!gCMSInverseRGBTransform) {
    2016             :         qcms_profile *inProfile, *outProfile;
    2017           0 :         inProfile = GetCMSOutputProfile();
    2018           0 :         outProfile = GetCMSsRGBProfile();
    2019             : 
    2020           0 :         if (!inProfile || !outProfile)
    2021           0 :             return nullptr;
    2022             : 
    2023           0 :         gCMSInverseRGBTransform = qcms_transform_create(inProfile, QCMS_DATA_RGB_8,
    2024             :                                                      outProfile, QCMS_DATA_RGB_8,
    2025             :                                                      QCMS_INTENT_PERCEPTUAL);
    2026             :     }
    2027             : 
    2028           0 :     return gCMSInverseRGBTransform;
    2029             : }
    2030             : 
    2031             : qcms_transform *
    2032           0 : gfxPlatform::GetCMSRGBATransform()
    2033             : {
    2034           0 :     if (!gCMSRGBATransform) {
    2035             :         qcms_profile *inProfile, *outProfile;
    2036           0 :         outProfile = GetCMSOutputProfile();
    2037           0 :         inProfile = GetCMSsRGBProfile();
    2038             : 
    2039           0 :         if (!inProfile || !outProfile)
    2040           0 :             return nullptr;
    2041             : 
    2042           0 :         gCMSRGBATransform = qcms_transform_create(inProfile, QCMS_DATA_RGBA_8,
    2043             :                                                outProfile, QCMS_DATA_RGBA_8,
    2044             :                                                QCMS_INTENT_PERCEPTUAL);
    2045             :     }
    2046             : 
    2047           0 :     return gCMSRGBATransform;
    2048             : }
    2049             : 
    2050             : /* Shuts down various transforms and profiles for CMS. */
    2051           0 : static void ShutdownCMS()
    2052             : {
    2053             : 
    2054           0 :     if (gCMSRGBTransform) {
    2055           0 :         qcms_transform_release(gCMSRGBTransform);
    2056           0 :         gCMSRGBTransform = nullptr;
    2057             :     }
    2058           0 :     if (gCMSInverseRGBTransform) {
    2059           0 :         qcms_transform_release(gCMSInverseRGBTransform);
    2060           0 :         gCMSInverseRGBTransform = nullptr;
    2061             :     }
    2062           0 :     if (gCMSRGBATransform) {
    2063           0 :         qcms_transform_release(gCMSRGBATransform);
    2064           0 :         gCMSRGBATransform = nullptr;
    2065             :     }
    2066           0 :     if (gCMSOutputProfile) {
    2067           0 :         qcms_profile_release(gCMSOutputProfile);
    2068             : 
    2069             :         // handle the aliased case
    2070           0 :         if (gCMSsRGBProfile == gCMSOutputProfile)
    2071           0 :             gCMSsRGBProfile = nullptr;
    2072           0 :         gCMSOutputProfile = nullptr;
    2073             :     }
    2074           0 :     if (gCMSsRGBProfile) {
    2075           0 :         qcms_profile_release(gCMSsRGBProfile);
    2076           0 :         gCMSsRGBProfile = nullptr;
    2077             :     }
    2078             : 
    2079             :     // Reset the state variables
    2080           0 :     gCMSMode = eCMSMode_Off;
    2081           0 :     gCMSInitialized = false;
    2082           0 : }
    2083             : 
    2084             : // default SetupClusterBoundaries, based on Unicode properties;
    2085             : // platform subclasses may override if they wish
    2086             : void
    2087           0 : gfxPlatform::SetupClusterBoundaries(gfxTextRun *aTextRun, const char16_t *aString)
    2088             : {
    2089           0 :     if (aTextRun->GetFlags() & gfx::ShapedTextFlags::TEXT_IS_8BIT) {
    2090             :         // 8-bit text doesn't have clusters.
    2091             :         // XXX is this true in all languages???
    2092             :         // behdad: don't think so.  Czech for example IIRC has a
    2093             :         // 'ch' grapheme.
    2094             :         // jfkthame: but that's not expected to behave as a grapheme cluster
    2095             :         // for selection/editing/etc.
    2096           0 :         return;
    2097             :     }
    2098             : 
    2099           0 :     aTextRun->SetupClusterBoundaries(0, aString, aTextRun->GetLength());
    2100             : }
    2101             : 
    2102             : int32_t
    2103          71 : gfxPlatform::GetBidiNumeralOption()
    2104             : {
    2105          71 :     if (mBidiNumeralOption == UNINITIALIZED_VALUE) {
    2106           2 :         mBidiNumeralOption = Preferences::GetInt(BIDI_NUMERAL_PREF, 0);
    2107             :     }
    2108          71 :     return mBidiNumeralOption;
    2109             : }
    2110             : 
    2111             : /* static */ void
    2112           0 : gfxPlatform::FlushFontAndWordCaches()
    2113             : {
    2114           0 :     gfxFontCache *fontCache = gfxFontCache::GetCache();
    2115           0 :     if (fontCache) {
    2116           0 :         fontCache->AgeAllGenerations();
    2117           0 :         fontCache->FlushShapedWordCaches();
    2118             :     }
    2119             : 
    2120           0 :     gfxPlatform::PurgeSkiaFontCache();
    2121           0 : }
    2122             : 
    2123             : void
    2124           0 : gfxPlatform::FontsPrefsChanged(const char *aPref)
    2125             : {
    2126           0 :     NS_ASSERTION(aPref != nullptr, "null preference");
    2127           0 :     if (!strcmp(GFX_DOWNLOADABLE_FONTS_ENABLED, aPref)) {
    2128           0 :         mAllowDownloadableFonts = UNINITIALIZED_VALUE;
    2129           0 :     } else if (!strcmp(GFX_PREF_FALLBACK_USE_CMAPS, aPref)) {
    2130           0 :         mFallbackUsesCmaps = UNINITIALIZED_VALUE;
    2131           0 :     } else if (!strcmp(GFX_PREF_WORD_CACHE_CHARLIMIT, aPref)) {
    2132           0 :         mWordCacheCharLimit = UNINITIALIZED_VALUE;
    2133           0 :         FlushFontAndWordCaches();
    2134           0 :     } else if (!strcmp(GFX_PREF_WORD_CACHE_MAXENTRIES, aPref)) {
    2135           0 :         mWordCacheMaxEntries = UNINITIALIZED_VALUE;
    2136           0 :         FlushFontAndWordCaches();
    2137           0 :     } else if (!strcmp(GFX_PREF_GRAPHITE_SHAPING, aPref)) {
    2138           0 :         mGraphiteShapingEnabled = UNINITIALIZED_VALUE;
    2139           0 :         FlushFontAndWordCaches();
    2140           0 :     } else if (!strcmp(BIDI_NUMERAL_PREF, aPref)) {
    2141           0 :         mBidiNumeralOption = UNINITIALIZED_VALUE;
    2142           0 :     } else if (!strcmp(GFX_PREF_OPENTYPE_SVG, aPref)) {
    2143           0 :         mOpenTypeSVGEnabled = UNINITIALIZED_VALUE;
    2144           0 :         gfxFontCache::GetCache()->AgeAllGenerations();
    2145           0 :         gfxFontCache::GetCache()->NotifyGlyphsChanged();
    2146             :     }
    2147           0 : }
    2148             : 
    2149             : 
    2150             : mozilla::LogModule*
    2151         444 : gfxPlatform::GetLog(eGfxLog aWhichLog)
    2152             : {
    2153             :     // logs shared across gfx
    2154             :     static LazyLogModule sFontlistLog("fontlist");
    2155             :     static LazyLogModule sFontInitLog("fontinit");
    2156             :     static LazyLogModule sTextrunLog("textrun");
    2157             :     static LazyLogModule sTextrunuiLog("textrunui");
    2158             :     static LazyLogModule sCmapDataLog("cmapdata");
    2159             :     static LazyLogModule sTextPerfLog("textperf");
    2160             : 
    2161         444 :     switch (aWhichLog) {
    2162             :     case eGfxLog_fontlist:
    2163         269 :         return sFontlistLog;
    2164             :     case eGfxLog_fontinit:
    2165           5 :         return sFontInitLog;
    2166             :     case eGfxLog_textrun:
    2167           2 :         return sTextrunLog;
    2168             :     case eGfxLog_textrunui:
    2169         140 :         return sTextrunuiLog;
    2170             :     case eGfxLog_cmapdata:
    2171           0 :         return sCmapDataLog;
    2172             :     case eGfxLog_textperf:
    2173          28 :         return sTextPerfLog;
    2174             :     }
    2175             : 
    2176           0 :     MOZ_ASSERT_UNREACHABLE("Unexpected log type");
    2177             :     return nullptr;
    2178             : }
    2179             : 
    2180             : mozilla::gfx::SurfaceFormat
    2181           5 : gfxPlatform::Optimal2DFormatForContent(gfxContentType aContent)
    2182             : {
    2183           5 :   switch (aContent) {
    2184             :   case gfxContentType::COLOR:
    2185           3 :     switch (GetOffscreenFormat()) {
    2186             :     case SurfaceFormat::A8R8G8B8_UINT32:
    2187           0 :       return mozilla::gfx::SurfaceFormat::B8G8R8A8;
    2188             :     case SurfaceFormat::X8R8G8B8_UINT32:
    2189           3 :       return mozilla::gfx::SurfaceFormat::B8G8R8X8;
    2190             :     case SurfaceFormat::R5G6B5_UINT16:
    2191           0 :       return mozilla::gfx::SurfaceFormat::R5G6B5_UINT16;
    2192             :     default:
    2193           0 :       NS_NOTREACHED("unknown gfxImageFormat for gfxContentType::COLOR");
    2194           0 :       return mozilla::gfx::SurfaceFormat::B8G8R8A8;
    2195             :     }
    2196             :   case gfxContentType::ALPHA:
    2197           0 :     return mozilla::gfx::SurfaceFormat::A8;
    2198             :   case gfxContentType::COLOR_ALPHA:
    2199           2 :     return mozilla::gfx::SurfaceFormat::B8G8R8A8;
    2200             :   default:
    2201           0 :     NS_NOTREACHED("unknown gfxContentType");
    2202           0 :     return mozilla::gfx::SurfaceFormat::B8G8R8A8;
    2203             :   }
    2204             : }
    2205             : 
    2206             : gfxImageFormat
    2207           0 : gfxPlatform::OptimalFormatForContent(gfxContentType aContent)
    2208             : {
    2209           0 :   switch (aContent) {
    2210             :   case gfxContentType::COLOR:
    2211           0 :     return GetOffscreenFormat();
    2212             :   case gfxContentType::ALPHA:
    2213           0 :     return SurfaceFormat::A8;
    2214             :   case gfxContentType::COLOR_ALPHA:
    2215           0 :     return SurfaceFormat::A8R8G8B8_UINT32;
    2216             :   default:
    2217           0 :     NS_NOTREACHED("unknown gfxContentType");
    2218           0 :     return SurfaceFormat::A8R8G8B8_UINT32;
    2219             :   }
    2220             : }
    2221             : 
    2222             : /**
    2223             :  * There are a number of layers acceleration (or layers in general) preferences
    2224             :  * that should be consistent for the lifetime of the application (bug 840967).
    2225             :  * As such, we will evaluate them all as soon as one of them is evaluated
    2226             :  * and remember the values.  Changing these preferences during the run will
    2227             :  * not have any effect until we restart.
    2228             :  */
    2229             : static mozilla::Atomic<bool> sLayersSupportsHardwareVideoDecoding(false);
    2230             : static bool sLayersHardwareVideoDecodingFailed = false;
    2231             : static bool sBufferRotationCheckPref = true;
    2232             : 
    2233             : static mozilla::Atomic<bool> sLayersAccelerationPrefsInitialized(false);
    2234             : 
    2235           1 : void VideoDecodingFailedChangedCallback(const char* aPref, void*)
    2236             : {
    2237           1 :   sLayersHardwareVideoDecodingFailed = Preferences::GetBool(aPref, false);
    2238           1 :   gfxPlatform::GetPlatform()->UpdateCanUseHardwareVideoDecoding();
    2239           1 : }
    2240             : 
    2241             : void
    2242           1 : gfxPlatform::UpdateCanUseHardwareVideoDecoding()
    2243             : {
    2244           1 :   if (XRE_IsParentProcess()) {
    2245           1 :     gfxVars::SetCanUseHardwareVideoDecoding(CanUseHardwareVideoDecoding());
    2246             :   }
    2247           1 : }
    2248             : 
    2249             : void
    2250           3 : gfxPlatform::InitAcceleration()
    2251             : {
    2252           3 :   if (sLayersAccelerationPrefsInitialized) {
    2253           0 :     return;
    2254             :   }
    2255             : 
    2256           3 :   InitCompositorAccelerationPrefs();
    2257             : 
    2258             :   // If this is called for the first time on a non-main thread, we're screwed.
    2259             :   // At the moment there's no explicit guarantee that the main thread calls
    2260             :   // this before the compositor thread, but let's at least make the assumption
    2261             :   // explicit.
    2262           3 :   MOZ_ASSERT(NS_IsMainThread(), "can only initialize prefs on the main thread");
    2263             : 
    2264           3 :   gfxPrefs::GetSingleton();
    2265             : 
    2266           3 :   if (XRE_IsParentProcess()) {
    2267           1 :     gfxVars::SetBrowserTabsRemoteAutostart(BrowserTabsRemoteAutostart());
    2268           1 :     gfxVars::SetOffscreenFormat(GetOffscreenFormat());
    2269             :     gfxVars::SetRequiresAcceleratedGLContextForCompositorOGL(
    2270           1 :               RequiresAcceleratedGLContextForCompositorOGL());
    2271             :   }
    2272             : 
    2273           6 :   nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
    2274           6 :   nsCString discardFailureId;
    2275             :   int32_t status;
    2276             : 
    2277           6 :   if (Preferences::GetBool("media.hardware-video-decoding.enabled", false) &&
    2278             : #ifdef XP_WIN
    2279             :     Preferences::GetBool("media.windows-media-foundation.use-dxva", true) &&
    2280             : #endif
    2281           3 :       NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_HARDWARE_VIDEO_DECODING,
    2282             :                                                discardFailureId, &status))) {
    2283           3 :       if (status == nsIGfxInfo::FEATURE_STATUS_OK || gfxPrefs::HardwareVideoDecodingForceEnabled()) {
    2284           3 :         sLayersSupportsHardwareVideoDecoding = true;
    2285             :       }
    2286             :   }
    2287             : 
    2288           3 :   sLayersAccelerationPrefsInitialized = true;
    2289             : 
    2290           3 :   if (XRE_IsParentProcess()) {
    2291             :     Preferences::RegisterCallbackAndCall(VideoDecodingFailedChangedCallback,
    2292           1 :                                          "media.hardware-video-decoding.failed");
    2293           1 :     InitGPUProcessPrefs();
    2294             :   }
    2295             : }
    2296             : 
    2297             : void
    2298           1 : gfxPlatform::InitGPUProcessPrefs()
    2299             : {
    2300             :   // We want to hide this from about:support, so only set a default if the
    2301             :   // pref is known to be true.
    2302           1 :   if (!gfxPrefs::GPUProcessEnabled() && !gfxPrefs::GPUProcessForceEnabled()) {
    2303           1 :     return;
    2304             :   }
    2305             : 
    2306           0 :   FeatureState& gpuProc = gfxConfig::GetFeature(Feature::GPU_PROCESS);
    2307             : 
    2308             :   // We require E10S - otherwise, there is very little benefit to the GPU
    2309             :   // process, since the UI process must still use acceleration for
    2310             :   // performance.
    2311           0 :   if (!BrowserTabsRemoteAutostart()) {
    2312           0 :     gpuProc.DisableByDefault(
    2313             :       FeatureStatus::Unavailable,
    2314             :       "Multi-process mode is not enabled",
    2315           0 :       NS_LITERAL_CSTRING("FEATURE_FAILURE_NO_E10S"));
    2316             :   } else {
    2317           0 :     gpuProc.SetDefaultFromPref(
    2318             :       gfxPrefs::GetGPUProcessEnabledPrefName(),
    2319             :       true,
    2320           0 :       gfxPrefs::GetGPUProcessEnabledPrefDefault());
    2321             :   }
    2322             : 
    2323           0 :   if (gfxPrefs::GPUProcessForceEnabled()) {
    2324           0 :     gpuProc.UserForceEnable("User force-enabled via pref");
    2325             :   }
    2326             : 
    2327           0 :   if (InSafeMode()) {
    2328           0 :     gpuProc.ForceDisable(
    2329             :       FeatureStatus::Blocked,
    2330             :       "Safe-mode is enabled",
    2331           0 :       NS_LITERAL_CSTRING("FEATURE_FAILURE_SAFE_MODE"));
    2332           0 :     return;
    2333             :   }
    2334           0 :   if (gfxPrefs::LayerScopeEnabled()) {
    2335           0 :     gpuProc.ForceDisable(
    2336             :       FeatureStatus::Blocked,
    2337             :       "LayerScope does not work in the GPU process",
    2338           0 :       NS_LITERAL_CSTRING("FEATURE_FAILURE_LAYERSCOPE"));
    2339           0 :     return;
    2340             :   }
    2341             : }
    2342             : 
    2343             : void
    2344           3 : gfxPlatform::InitCompositorAccelerationPrefs()
    2345             : {
    2346           3 :   const char *acceleratedEnv = PR_GetEnv("MOZ_ACCELERATED");
    2347             : 
    2348           3 :   FeatureState& feature = gfxConfig::GetFeature(Feature::HW_COMPOSITING);
    2349             : 
    2350             :   // Base value - does the platform allow acceleration?
    2351           3 :   if (feature.SetDefault(AccelerateLayersByDefault(),
    2352             :                          FeatureStatus::Blocked,
    2353             :                          "Acceleration blocked by platform"))
    2354             :   {
    2355           0 :     if (gfxPrefs::LayersAccelerationDisabledDoNotUseDirectly()) {
    2356           0 :       feature.UserDisable("Disabled by pref",
    2357           0 :                           NS_LITERAL_CSTRING("FEATURE_FAILURE_COMP_PREF"));
    2358           0 :     } else if (acceleratedEnv && *acceleratedEnv == '0') {
    2359           0 :       feature.UserDisable("Disabled by envvar",
    2360           0 :                           NS_LITERAL_CSTRING("FEATURE_FAILURE_COMP_ENV"));
    2361             :     }
    2362             :   } else {
    2363           3 :     if (acceleratedEnv && *acceleratedEnv == '1') {
    2364           0 :       feature.UserEnable("Enabled by envvar");
    2365             :     }
    2366             :   }
    2367             : 
    2368             :   // This has specific meaning elsewhere, so we always record it.
    2369           3 :   if (gfxPrefs::LayersAccelerationForceEnabledDoNotUseDirectly()) {
    2370           0 :     feature.UserForceEnable("Force-enabled by pref");
    2371             :   }
    2372             : 
    2373             :   // Safe mode trumps everything.
    2374           3 :   if (InSafeMode()) {
    2375           0 :     feature.ForceDisable(FeatureStatus::Blocked, "Acceleration blocked by safe-mode",
    2376           0 :                          NS_LITERAL_CSTRING("FEATURE_FAILURE_COMP_SAFEMODE"));
    2377             :   }
    2378           3 : }
    2379             : 
    2380             : void
    2381           3 : gfxPlatform::InitWebRenderConfig()
    2382             : {
    2383           3 :   bool prefEnabled = Preferences::GetBool("gfx.webrender.enabled", false);
    2384             : 
    2385           4 :   ScopedGfxFeatureReporter reporter("WR", prefEnabled);
    2386           3 :   if (!XRE_IsParentProcess()) {
    2387             :     // The parent process runs through all the real decision-making code
    2388             :     // later in this function. For other processes we still want to report
    2389             :     // the state of the feature for crash reports.
    2390           2 :     if (gfxVars::UseWebRender()) {
    2391           0 :       reporter.SetSuccessful();
    2392             :     }
    2393           2 :     return;
    2394             :   }
    2395             : 
    2396           1 :   FeatureState& featureWebRender = gfxConfig::GetFeature(Feature::WEBRENDER);
    2397             : 
    2398           1 :   featureWebRender.DisableByDefault(
    2399             :       FeatureStatus::OptIn,
    2400             :       "WebRender is an opt-in feature",
    2401           2 :       NS_LITERAL_CSTRING("FEATURE_FAILURE_DEFAULT_OFF"));
    2402             : 
    2403           1 :   if (prefEnabled) {
    2404           0 :     featureWebRender.UserEnable("Enabled by pref");
    2405             :   } else {
    2406           1 :     const char* env = PR_GetEnv("MOZ_WEBRENDER");
    2407           1 :     if (env && *env == '1') {
    2408           0 :       featureWebRender.UserEnable("Enabled by envvar");
    2409             :     }
    2410             :   }
    2411             : 
    2412             :   // WebRender relies on the GPU process when on Windows
    2413             : #ifdef XP_WIN
    2414             :   if (!gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
    2415             :     featureWebRender.ForceDisable(
    2416             :       FeatureStatus::Unavailable,
    2417             :       "GPU Process is disabled",
    2418             :       NS_LITERAL_CSTRING("FEATURE_FAILURE_GPU_PROCESS_DISABLED"));
    2419             :   }
    2420             : #endif
    2421             : 
    2422           1 :   if (InSafeMode()) {
    2423           0 :     featureWebRender.ForceDisable(
    2424             :       FeatureStatus::Unavailable,
    2425             :       "Safe-mode is enabled",
    2426           0 :       NS_LITERAL_CSTRING("FEATURE_FAILURE_SAFE_MODE"));
    2427             :   }
    2428             : 
    2429             : #ifndef MOZ_BUILD_WEBRENDER
    2430             :   featureWebRender.ForceDisable(
    2431             :     FeatureStatus::Unavailable,
    2432             :     "Build doesn't include WebRender",
    2433             :     NS_LITERAL_CSTRING("FEATURE_FAILURE_NO_WEBRENDER"));
    2434             : #endif
    2435             : 
    2436             : #ifdef XP_WIN
    2437             :   if (Preferences::GetBool("gfx.webrender.force-angle", false)) {
    2438             :     if (!gfxConfig::IsEnabled(Feature::D3D11_HW_ANGLE)) {
    2439             :       featureWebRender.ForceDisable(
    2440             :         FeatureStatus::Unavailable,
    2441             :         "ANGLE is disabled",
    2442             :         NS_LITERAL_CSTRING("FEATURE_FAILURE_ANGLE_DISABLED"));
    2443             :     } else {
    2444             :       gfxVars::SetUseWebRenderANGLE(gfxConfig::IsEnabled(Feature::WEBRENDER));
    2445             :     }
    2446             :   }
    2447             : #endif
    2448             : 
    2449             :   // gfxFeature is not usable in the GPU process, so we use gfxVars to transmit this feature
    2450           1 :   if (gfxConfig::IsEnabled(Feature::WEBRENDER)) {
    2451           0 :     gfxVars::SetUseWebRender(true);
    2452           0 :     reporter.SetSuccessful();
    2453             :   }
    2454             : }
    2455             : 
    2456             : void
    2457           3 : gfxPlatform::InitOMTPConfig()
    2458             : {
    2459           3 :   bool prefEnabled = Preferences::GetBool("layers.omtp.enabled", false);
    2460             : 
    2461             :   // We don't want to report anything for this feature when turned off, as it is still early in development
    2462           3 :   if (!prefEnabled) {
    2463           6 :     return;
    2464             :   }
    2465             : 
    2466           0 :   ScopedGfxFeatureReporter reporter("OMTP", prefEnabled);
    2467             : 
    2468           0 :   if (!XRE_IsParentProcess()) {
    2469             :     // The parent process runs through all the real decision-making code
    2470             :     // later in this function. For other processes we still want to report
    2471             :     // the state of the feature for crash reports.
    2472           0 :     if (gfxVars::UseOMTP()) {
    2473           0 :       reporter.SetSuccessful();
    2474             :     }
    2475           0 :     return;
    2476             :   }
    2477             : 
    2478           0 :   FeatureState& featureOMTP = gfxConfig::GetFeature(Feature::OMTP);
    2479             : 
    2480           0 :   featureOMTP.DisableByDefault(
    2481             :       FeatureStatus::OptIn,
    2482             :       "OMTP is an opt-in feature",
    2483           0 :       NS_LITERAL_CSTRING("FEATURE_FAILURE_DEFAULT_OFF"));
    2484             : 
    2485           0 :   featureOMTP.UserEnable("Enabled by pref");
    2486             : 
    2487           0 :   if (InSafeMode()) {
    2488           0 :     featureOMTP.ForceDisable(FeatureStatus::Blocked, "OMTP blocked by safe-mode",
    2489           0 :                          NS_LITERAL_CSTRING("FEATURE_FAILURE_COMP_SAFEMODE"));
    2490             :   }
    2491             : 
    2492           0 :   if (gfxConfig::IsEnabled(Feature::OMTP)) {
    2493           0 :     gfxVars::SetUseOMTP(true);
    2494           0 :     reporter.SetSuccessful();
    2495             :   }
    2496             : }
    2497             : 
    2498             : bool
    2499           1 : gfxPlatform::CanUseHardwareVideoDecoding()
    2500             : {
    2501             :   // this function is called from the compositor thread, so it is not
    2502             :   // safe to init the prefs etc. from here.
    2503           1 :   MOZ_ASSERT(sLayersAccelerationPrefsInitialized);
    2504           1 :   return sLayersSupportsHardwareVideoDecoding && !sLayersHardwareVideoDecodingFailed;
    2505             : }
    2506             : 
    2507             : bool
    2508           0 : gfxPlatform::AccelerateLayersByDefault()
    2509             : {
    2510             : #if defined(MOZ_GL_PROVIDER) || defined(MOZ_WIDGET_UIKIT)
    2511             :   return true;
    2512             : #else
    2513           0 :   return false;
    2514             : #endif
    2515             : }
    2516             : 
    2517             : bool
    2518          77 : gfxPlatform::BufferRotationEnabled()
    2519             : {
    2520         154 :   MutexAutoLock autoLock(*gGfxPlatformPrefsLock);
    2521             : 
    2522         154 :   return sBufferRotationCheckPref && gfxPrefs::BufferRotationEnabled();
    2523             : }
    2524             : 
    2525             : void
    2526           0 : gfxPlatform::DisableBufferRotation()
    2527             : {
    2528           0 :   MutexAutoLock autoLock(*gGfxPlatformPrefsLock);
    2529             : 
    2530           0 :   sBufferRotationCheckPref = false;
    2531           0 : }
    2532             : 
    2533             : already_AddRefed<ScaledFont>
    2534           0 : gfxPlatform::GetScaledFontForFontWithCairoSkia(DrawTarget* aTarget, gfxFont* aFont)
    2535             : {
    2536             :     NativeFont nativeFont;
    2537           0 :     nativeFont.mType = NativeFontType::CAIRO_FONT_FACE;
    2538           0 :     nativeFont.mFont = aFont->GetCairoScaledFont();
    2539             :     return Factory::CreateScaledFontForNativeFont(nativeFont,
    2540             :                                                   aFont->GetUnscaledFont(),
    2541           0 :                                                   aFont->GetAdjustedSize());
    2542             : }
    2543             : 
    2544             : /* static */ bool
    2545           2 : gfxPlatform::UsesOffMainThreadCompositing()
    2546             : {
    2547           2 :   if (XRE_GetProcessType() == GeckoProcessType_GPU) {
    2548           0 :     return true;
    2549             :   }
    2550             : 
    2551             :   static bool firstTime = true;
    2552             :   static bool result = false;
    2553             : 
    2554           2 :   if (firstTime) {
    2555           1 :     MOZ_ASSERT(sLayersAccelerationPrefsInitialized);
    2556           1 :     result =
    2557           1 :       gfxVars::BrowserTabsRemoteAutostart() ||
    2558           0 :       !gfxPrefs::LayersOffMainThreadCompositionForceDisabled();
    2559             : #if defined(MOZ_WIDGET_GTK)
    2560             :     // Linux users who chose OpenGL are being grandfathered in to OMTC
    2561           1 :     result |= gfxPrefs::LayersAccelerationForceEnabledDoNotUseDirectly();
    2562             : 
    2563             : #endif
    2564           1 :     firstTime = false;
    2565             :   }
    2566             : 
    2567           2 :   return result;
    2568             : }
    2569             : 
    2570             : /***
    2571             :  * The preference "layout.frame_rate" has 3 meanings depending on the value:
    2572             :  *
    2573             :  * -1 = Auto (default), use hardware vsync or software vsync @ 60 hz if hw vsync fails.
    2574             :  *  0 = ASAP mode - used during talos testing.
    2575             :  *  X = Software vsync at a rate of X times per second.
    2576             :  */
    2577             : already_AddRefed<mozilla::gfx::VsyncSource>
    2578           1 : gfxPlatform::CreateHardwareVsyncSource()
    2579             : {
    2580           2 :   RefPtr<mozilla::gfx::VsyncSource> softwareVsync = new SoftwareVsyncSource();
    2581           2 :   return softwareVsync.forget();
    2582             : }
    2583             : 
    2584             : /* static */ bool
    2585           3 : gfxPlatform::IsInLayoutAsapMode()
    2586             : {
    2587             :   // There are 2 modes of ASAP mode.
    2588             :   // 1 is that the refresh driver and compositor are in lock step
    2589             :   // the second is that the compositor goes ASAP and the refresh driver
    2590             :   // goes at whatever the configurated rate is. This only checks the version
    2591             :   // talos uses, which is the refresh driver and compositor are in lockstep.
    2592           3 :   return gfxPrefs::LayoutFrameRate() == 0;
    2593             : }
    2594             : 
    2595             : /* static */ bool
    2596           1 : gfxPlatform::ForceSoftwareVsync()
    2597             : {
    2598           1 :   return gfxPrefs::LayoutFrameRate() > 0;
    2599             : }
    2600             : 
    2601             : /* static */ int
    2602           1 : gfxPlatform::GetSoftwareVsyncRate()
    2603             : {
    2604           1 :   int preferenceRate = gfxPrefs::LayoutFrameRate();
    2605           1 :   if (preferenceRate <= 0) {
    2606           1 :     return gfxPlatform::GetDefaultFrameRate();
    2607             :   }
    2608           0 :   return preferenceRate;
    2609             : }
    2610             : 
    2611             : /* static */ int
    2612           4 : gfxPlatform::GetDefaultFrameRate()
    2613             : {
    2614           4 :   return 60;
    2615             : }
    2616             : 
    2617             : void
    2618           0 : gfxPlatform::GetAzureBackendInfo(mozilla::widget::InfoObject& aObj)
    2619             : {
    2620           0 :   if (gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
    2621           0 :     aObj.DefineProperty("AzureCanvasBackend (UI Process)", GetBackendName(mPreferredCanvasBackend));
    2622           0 :     aObj.DefineProperty("AzureFallbackCanvasBackend (UI Process)", GetBackendName(mFallbackCanvasBackend));
    2623           0 :     aObj.DefineProperty("AzureContentBackend (UI Process)", GetBackendName(mContentBackend));
    2624             : 
    2625           0 :     if (gfxConfig::IsEnabled(gfx::Feature::DIRECT2D)) {
    2626           0 :       aObj.DefineProperty("AzureCanvasBackend", "Direct2D 1.1");
    2627           0 :       aObj.DefineProperty("AzureContentBackend", "Direct2D 1.1");
    2628             :     }
    2629             :   } else {
    2630           0 :     aObj.DefineProperty("AzureCanvasBackend", GetBackendName(mPreferredCanvasBackend));
    2631           0 :     aObj.DefineProperty("AzureFallbackCanvasBackend", GetBackendName(mFallbackCanvasBackend));
    2632           0 :     aObj.DefineProperty("AzureContentBackend", GetBackendName(mContentBackend));
    2633             :   }
    2634             : 
    2635           0 :   aObj.DefineProperty("AzureCanvasAccelerated", AllowOpenGLCanvas());
    2636           0 : }
    2637             : 
    2638             : void
    2639           0 : gfxPlatform::GetApzSupportInfo(mozilla::widget::InfoObject& aObj)
    2640             : {
    2641           0 :   if (!gfxPlatform::AsyncPanZoomEnabled()) {
    2642           0 :     return;
    2643             :   }
    2644             : 
    2645           0 :   if (SupportsApzWheelInput()) {
    2646           0 :     aObj.DefineProperty("ApzWheelInput", 1);
    2647             :   }
    2648             : 
    2649           0 :   if (SupportsApzTouchInput()) {
    2650           0 :     aObj.DefineProperty("ApzTouchInput", 1);
    2651             :   }
    2652             : 
    2653           0 :   if (SupportsApzDragInput()) {
    2654           0 :     aObj.DefineProperty("ApzDragInput", 1);
    2655             :   }
    2656             : 
    2657           0 :   if (SupportsApzKeyboardInput() && !gfxPrefs::AccessibilityBrowseWithCaret()) {
    2658           0 :     aObj.DefineProperty("ApzKeyboardInput", 1);
    2659             :   }
    2660             : }
    2661             : 
    2662             : void
    2663           0 : gfxPlatform::GetTilesSupportInfo(mozilla::widget::InfoObject& aObj)
    2664             : {
    2665           0 :   if (!gfxPrefs::LayersTilesEnabled()) {
    2666           0 :     return;
    2667             :   }
    2668             : 
    2669           0 :   IntSize tileSize = gfxVars::TileSize();
    2670           0 :   aObj.DefineProperty("TileHeight", tileSize.height);
    2671           0 :   aObj.DefineProperty("TileWidth", tileSize.width);
    2672             : }
    2673             : 
    2674             : /*static*/ bool
    2675         649 : gfxPlatform::AsyncPanZoomEnabled()
    2676             : {
    2677             : #if !defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_WIDGET_UIKIT)
    2678             :   // For XUL applications (everything but Firefox on Android)
    2679             :   // we only want to use APZ when E10S is enabled. If
    2680             :   // we ever get input events off the main thread we can consider relaxing
    2681             :   // this requirement.
    2682         649 :   if (!BrowserTabsRemoteAutostart()) {
    2683           0 :     return false;
    2684             :   }
    2685             : #endif
    2686             : #ifdef MOZ_WIDGET_ANDROID
    2687             :   return true;
    2688             : #else
    2689         649 :   if (!gfxPrefs::SingletonExists()) {
    2690             :     // Make sure the gfxPrefs has been initialized before reading from it.
    2691           0 :     MOZ_ASSERT(NS_IsMainThread());
    2692           0 :     gfxPrefs::GetSingleton();
    2693             :   }
    2694         649 :   return gfxPrefs::AsyncPanZoomEnabledDoNotUseDirectly();
    2695             : #endif
    2696             : }
    2697             : 
    2698             : /*static*/ bool
    2699           0 : gfxPlatform::PerfWarnings()
    2700             : {
    2701           0 :   return gfxPrefs::PerfWarnings();
    2702             : }
    2703             : 
    2704             : void
    2705           0 : gfxPlatform::GetAcceleratedCompositorBackends(nsTArray<LayersBackend>& aBackends)
    2706             : {
    2707           0 :   if (gfxConfig::IsEnabled(Feature::OPENGL_COMPOSITING)) {
    2708           0 :     aBackends.AppendElement(LayersBackend::LAYERS_OPENGL);
    2709             :   }
    2710             :   else {
    2711             :     static int tell_me_once = 0;
    2712           0 :     if (!tell_me_once) {
    2713           0 :       NS_WARNING("OpenGL-accelerated layers are not supported on this system");
    2714           0 :       tell_me_once = 1;
    2715             :     }
    2716             : #ifdef MOZ_WIDGET_ANDROID
    2717             :     MOZ_CRASH("OpenGL-accelerated layers are a hard requirement on this platform. "
    2718             :               "Cannot continue without support for them");
    2719             : #endif
    2720             :   }
    2721           0 : }
    2722             : 
    2723             : void
    2724           1 : gfxPlatform::GetCompositorBackends(bool useAcceleration, nsTArray<mozilla::layers::LayersBackend>& aBackends)
    2725             : {
    2726           1 :   if (useAcceleration) {
    2727           0 :     GetAcceleratedCompositorBackends(aBackends);
    2728             :   }
    2729           1 :   aBackends.AppendElement(LayersBackend::LAYERS_BASIC);
    2730           1 : }
    2731             : 
    2732             : void
    2733           1 : gfxPlatform::NotifyCompositorCreated(LayersBackend aBackend)
    2734             : {
    2735           1 :   if (mCompositorBackend == aBackend) {
    2736           0 :     return;
    2737             :   }
    2738             : 
    2739           1 :   if (mCompositorBackend != LayersBackend::LAYERS_NONE) {
    2740           0 :     gfxCriticalNote << "Compositors might be mixed ("
    2741           0 :       << int(mCompositorBackend) << "," << int(aBackend) << ")";
    2742             :   }
    2743             : 
    2744             :   // Set the backend before we notify so it's available immediately.
    2745           1 :   mCompositorBackend = aBackend;
    2746             : 
    2747             :   // Notify that we created a compositor, so telemetry can update.
    2748           2 :   NS_DispatchToMainThread(
    2749           3 :     NS_NewRunnableFunction("gfxPlatform::NotifyCompositorCreated", [] {
    2750           2 :       if (nsCOMPtr<nsIObserverService> obsvc = services::GetObserverService()) {
    2751           1 :         obsvc->NotifyObservers(nullptr, "compositor:created", nullptr);
    2752             :       }
    2753           2 :     }));
    2754             : }
    2755             : 
    2756             : /* static */ void
    2757           0 : gfxPlatform::NotifyGPUProcessDisabled()
    2758             : {
    2759           0 :   if (gfxConfig::IsEnabled(Feature::WEBRENDER)) {
    2760           0 :     gfxConfig::GetFeature(Feature::WEBRENDER).ForceDisable(
    2761             :       FeatureStatus::Unavailable,
    2762             :       "GPU Process is disabled",
    2763           0 :       NS_LITERAL_CSTRING("FEATURE_FAILURE_GPU_PROCESS_DISABLED"));
    2764           0 :     gfxVars::SetUseWebRender(false);
    2765             :   }
    2766           0 : }
    2767             : 
    2768             : void
    2769           0 : gfxPlatform::FetchAndImportContentDeviceData()
    2770             : {
    2771           0 :   MOZ_ASSERT(XRE_IsContentProcess());
    2772             : 
    2773           0 :   if (gContentDeviceInitData) {
    2774           0 :     ImportContentDeviceData(*gContentDeviceInitData);
    2775           0 :     return;
    2776             :   }
    2777             : 
    2778           0 :   mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton();
    2779             : 
    2780           0 :   mozilla::gfx::ContentDeviceData data;
    2781           0 :   cc->SendGetGraphicsDeviceInitData(&data);
    2782             : 
    2783           0 :   ImportContentDeviceData(data);
    2784             : }
    2785             : 
    2786             : void
    2787           0 : gfxPlatform::ImportContentDeviceData(const mozilla::gfx::ContentDeviceData& aData)
    2788             : {
    2789           0 :   MOZ_ASSERT(XRE_IsContentProcess());
    2790             : 
    2791           0 :   const DevicePrefs& prefs = aData.prefs();
    2792           0 :   gfxConfig::Inherit(Feature::HW_COMPOSITING, prefs.hwCompositing());
    2793           0 :   gfxConfig::Inherit(Feature::OPENGL_COMPOSITING, prefs.oglCompositing());
    2794           0 : }
    2795             : 
    2796             : void
    2797           2 : gfxPlatform::BuildContentDeviceData(mozilla::gfx::ContentDeviceData* aOut)
    2798             : {
    2799           2 :   MOZ_ASSERT(XRE_IsParentProcess());
    2800             : 
    2801             :   // Make sure our settings are synchronized from the GPU process.
    2802           2 :   GPUProcessManager::Get()->EnsureGPUReady();
    2803             : 
    2804           2 :   aOut->prefs().hwCompositing() = gfxConfig::GetValue(Feature::HW_COMPOSITING);
    2805           2 :   aOut->prefs().oglCompositing() = gfxConfig::GetValue(Feature::OPENGL_COMPOSITING);
    2806           2 : }
    2807             : 
    2808             : void
    2809           0 : gfxPlatform::ImportGPUDeviceData(const mozilla::gfx::GPUDeviceData& aData)
    2810             : {
    2811           0 :   MOZ_ASSERT(XRE_IsParentProcess());
    2812             : 
    2813           0 :   gfxConfig::ImportChange(Feature::OPENGL_COMPOSITING, aData.oglCompositing());
    2814           0 :   gfxConfig::ImportChange(Feature::ADVANCED_LAYERS, aData.advancedLayers());
    2815           0 : }
    2816             : 
    2817             : bool
    2818           0 : gfxPlatform::SupportsApzTouchInput() const
    2819             : {
    2820           0 :   return dom::TouchEvent::PrefEnabled(nullptr);
    2821             : }
    2822             : 
    2823             : bool
    2824           0 : gfxPlatform::SupportsApzDragInput() const
    2825             : {
    2826           0 :   return gfxPrefs::APZDragEnabled();
    2827             : }
    2828             : 
    2829             : bool
    2830           0 : gfxPlatform::SupportsApzKeyboardInput() const
    2831             : {
    2832           0 :   return gfxPrefs::APZKeyboardEnabled();
    2833             : }
    2834             : 
    2835             : void
    2836           3 : gfxPlatform::InitOpenGLConfig()
    2837             : {
    2838             :   #ifdef XP_WIN
    2839             :   // Don't enable by default on Windows, since it could show up in about:support even
    2840             :   // though it'll never get used. Only attempt if user enables the pref
    2841             :   if (!Preferences::GetBool("layers.prefer-opengl")){
    2842             :     return;
    2843             :   }
    2844             :   #endif
    2845             : 
    2846           3 :   FeatureState& openGLFeature = gfxConfig::GetFeature(Feature::OPENGL_COMPOSITING);
    2847             : 
    2848             :   // Check to see hw comp supported
    2849           3 :   if (!gfxConfig::IsEnabled(Feature::HW_COMPOSITING)) {
    2850           3 :     openGLFeature.DisableByDefault(FeatureStatus::Unavailable, "Hardware compositing is disabled",
    2851           6 :                            NS_LITERAL_CSTRING("FEATURE_FAILURE_OPENGL_NEED_HWCOMP"));
    2852           6 :     return;
    2853             :   }
    2854             : 
    2855             :   #ifdef XP_WIN
    2856             :   openGLFeature.SetDefaultFromPref(
    2857             :     gfxPrefs::GetLayersPreferOpenGLPrefName(),
    2858             :     true,
    2859             :     gfxPrefs::GetLayersPreferOpenGLPrefDefault());
    2860             :   #else
    2861           0 :     openGLFeature.EnableByDefault();
    2862             :   #endif
    2863             : 
    2864             :   // When layers acceleration is force-enabled, enable it even for blacklisted
    2865             :   // devices.
    2866           0 :   if (gfxPrefs::LayersAccelerationForceEnabledDoNotUseDirectly()) {
    2867           0 :     openGLFeature.UserForceEnable("Force-enabled by pref");
    2868           0 :     return;
    2869             :   }
    2870             : 
    2871           0 :   nsCString message;
    2872           0 :   nsCString failureId;
    2873           0 :   if (!IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_OPENGL_LAYERS, &message, failureId)) {
    2874           0 :     openGLFeature.Disable(FeatureStatus::Blacklisted, message.get(), failureId);
    2875             :   }
    2876             : }
    2877             : 
    2878             : bool
    2879           0 : gfxPlatform::IsGfxInfoStatusOkay(int32_t aFeature, nsCString* aOutMessage, nsCString& aFailureId)
    2880             : {
    2881           0 :   nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
    2882           0 :   if (!gfxInfo) {
    2883           0 :     return true;
    2884             :   }
    2885             : 
    2886             :   int32_t status;
    2887           0 :   if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(aFeature, aFailureId, &status)) &&
    2888           0 :       status != nsIGfxInfo::FEATURE_STATUS_OK)
    2889             :   {
    2890           0 :     aOutMessage->AssignLiteral("#BLOCKLIST_");
    2891           0 :     aOutMessage->AppendASCII(aFailureId.get());
    2892           0 :     return false;
    2893             :   }
    2894             : 
    2895           0 :   return true;
    2896             : }

Generated by: LCOV version 1.13