123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478 |
- /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #include "mozilla/layers/CompositorBridgeChild.h"
- #include "mozilla/layers/CompositorThread.h"
- #include "mozilla/layers/ImageBridgeChild.h"
- #include "mozilla/layers/ISurfaceAllocator.h" // for GfxMemoryImageReporter
- #include "mozilla/gfx/gfxVars.h"
- #include "mozilla/gfx/GPUProcessManager.h"
- #include "mozilla/gfx/GraphicsMessages.h"
- #include "mozilla/ClearOnShutdown.h"
- #include "mozilla/TimeStamp.h"
- #include "mozilla/Unused.h"
- #include "mozilla/Logging.h"
- #include "mozilla/Services.h"
- #include "gfxPlatform.h"
- #include "gfxPrefs.h"
- #include "gfxEnv.h"
- #include "gfxTextRun.h"
- #include "gfxConfig.h"
- #include "MediaPrefs.h"
- #ifdef XP_WIN
- #include <process.h>
- #define getpid _getpid
- #else
- #include <unistd.h>
- #endif
- #include "nsXULAppAPI.h"
- #include "nsDirectoryServiceUtils.h"
- #include "nsDirectoryServiceDefs.h"
- #if defined(XP_WIN)
- #include "gfxWindowsPlatform.h"
- #elif defined(MOZ_WIDGET_GTK)
- #include "gfxPlatformGtk.h"
- #elif defined(ANDROID)
- #include "gfxAndroidPlatform.h"
- #endif
- #ifdef XP_WIN
- #include "mozilla/WindowsVersion.h"
- #endif
- #include "nsGkAtoms.h"
- #include "gfxPlatformFontList.h"
- #include "gfxContext.h"
- #include "gfxImageSurface.h"
- #include "nsUnicodeProperties.h"
- #include "harfbuzz/hb.h"
- #include "gfxGraphiteShaper.h"
- #include "gfx2DGlue.h"
- #include "gfxGradientCache.h"
- #include "gfxUtils.h" // for NextPowerOfTwo
- #include "nsUnicodeRange.h"
- #include "nsServiceManagerUtils.h"
- #include "nsTArray.h"
- #include "nsILocaleService.h"
- #include "nsIObserverService.h"
- #include "nsIScreenManager.h"
- #include "FrameMetrics.h"
- #include "MainThreadUtils.h"
- #include "nsWeakReference.h"
- #include "cairo.h"
- #include "qcms.h"
- #include "imgITools.h"
- #include "plstr.h"
- #include "nsCRT.h"
- #include "GLContext.h"
- #include "GLContextProvider.h"
- #include "mozilla/gfx/Logging.h"
- #if defined(MOZ_WIDGET_GTK)
- #include "gfxPlatformGtk.h" // xxx - for UseFcFontList
- #endif
- #ifdef USE_SKIA
- # ifdef __GNUC__
- # pragma GCC diagnostic push
- # pragma GCC diagnostic ignored "-Wshadow"
- # endif
- # include "skia/include/core/SkGraphics.h"
- # ifdef USE_SKIA_GPU
- # include "skia/include/gpu/GrContext.h"
- # include "skia/include/gpu/gl/GrGLInterface.h"
- # include "SkiaGLGlue.h"
- # endif
- # ifdef MOZ_ENABLE_FREETYPE
- # include "skia/include/ports/SkTypeface_cairo.h"
- # endif
- # ifdef __GNUC__
- # pragma GCC diagnostic pop // -Wshadow
- # endif
- static const uint32_t kDefaultGlyphCacheSize = -1;
- #endif
- #if !defined(USE_SKIA) || !defined(USE_SKIA_GPU)
- class mozilla::gl::SkiaGLGlue : public GenericAtomicRefCounted {
- };
- #endif
- #include "mozilla/Preferences.h"
- #include "mozilla/Assertions.h"
- #include "mozilla/Atomics.h"
- #include "mozilla/Attributes.h"
- #include "mozilla/Mutex.h"
- #include "nsAlgorithm.h"
- #include "nsIGfxInfo.h"
- #include "nsIXULRuntime.h"
- #include "VsyncSource.h"
- #include "SoftwareVsyncSource.h"
- #include "nscore.h" // for NS_FREE_PERMANENT_DATA
- #include "mozilla/dom/ContentChild.h"
- #include "mozilla/gfx/GPUParent.h"
- #include "prsystem.h"
- namespace mozilla {
- namespace layers {
- void ShutdownTileCache();
- } // namespace layers
- } // namespace mozilla
- using namespace mozilla;
- using namespace mozilla::layers;
- using namespace mozilla::gl;
- using namespace mozilla::gfx;
- gfxPlatform *gPlatform = nullptr;
- static bool gEverInitialized = false;
- static Mutex* gGfxPlatformPrefsLock = nullptr;
- // These two may point to the same profile
- static qcms_profile *gCMSOutputProfile = nullptr;
- static qcms_profile *gCMSsRGBProfile = nullptr;
- static bool gCMSRGBTransformFailed = false;
- static qcms_transform *gCMSRGBTransform = nullptr;
- static qcms_transform *gCMSInverseRGBTransform = nullptr;
- static qcms_transform *gCMSRGBATransform = nullptr;
- static bool gCMSInitialized = false;
- static eCMSMode gCMSMode = eCMSMode_Off;
- static void ShutdownCMS();
- #include "mozilla/gfx/2D.h"
- #include "mozilla/gfx/SourceSurfaceCairo.h"
- using namespace mozilla::gfx;
- /* Class to listen for pref changes so that chrome code can dynamically
- force sRGB as an output profile. See Bug #452125. */
- class SRGBOverrideObserver final : public nsIObserver,
- public nsSupportsWeakReference
- {
- ~SRGBOverrideObserver() {}
- public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIOBSERVER
- };
- /// This override of the LogForwarder, initially used for the critical graphics
- /// errors, is sending the log to the crash annotations as well, but only
- /// if the capacity set with the method below is >= 2. We always retain the
- /// very first critical message, and the latest capacity-1 messages are
- /// rotated through. Note that we don't expect the total number of times
- /// this gets called to be large - it is meant for critical errors only.
- class CrashStatsLogForwarder: public mozilla::gfx::LogForwarder
- {
- public:
- explicit CrashStatsLogForwarder(const char* aKey);
- virtual void Log(const std::string& aString) override;
- virtual void CrashAction(LogReason aReason) override;
- virtual bool UpdateStringsVector(const std::string& aString) override;
- virtual LoggingRecord LoggingRecordCopy() override;
- void SetCircularBufferSize(uint32_t aCapacity);
- private:
- // Helper for the Log()
- void UpdateCrashReport();
- private:
- LoggingRecord mBuffer;
- nsCString mCrashCriticalKey;
- uint32_t mMaxCapacity;
- int32_t mIndex;
- Mutex mMutex;
- };
- CrashStatsLogForwarder::CrashStatsLogForwarder(const char* aKey)
- : mBuffer()
- , mCrashCriticalKey(aKey)
- , mMaxCapacity(0)
- , mIndex(-1)
- , mMutex("CrashStatsLogForwarder")
- {
- }
- void CrashStatsLogForwarder::SetCircularBufferSize(uint32_t aCapacity)
- {
- MutexAutoLock lock(mMutex);
- mMaxCapacity = aCapacity;
- mBuffer.reserve(static_cast<size_t>(aCapacity));
- }
- LoggingRecord
- CrashStatsLogForwarder::LoggingRecordCopy()
- {
- MutexAutoLock lock(mMutex);
- return mBuffer;
- }
- bool
- CrashStatsLogForwarder::UpdateStringsVector(const std::string& aString)
- {
- // We want at least the first one and the last one. Otherwise, no point.
- if (mMaxCapacity < 2) {
- return false;
- }
- mIndex += 1;
- MOZ_ASSERT(mIndex >= 0);
- // index will count 0, 1, 2, ..., max-1, 1, 2, ..., max-1, 1, 2, ...
- int32_t index = mIndex ? (mIndex-1) % (mMaxCapacity-1) + 1 : 0;
- MOZ_ASSERT(index >= 0 && index < (int32_t)mMaxCapacity);
- MOZ_ASSERT(index <= mIndex && index <= (int32_t)mBuffer.size());
- bool ignored;
- double tStamp = (TimeStamp::NowLoRes()-TimeStamp::ProcessCreation(ignored)).ToSecondsSigDigits();
- // Checking for index >= mBuffer.size(), rather than index == mBuffer.size()
- // just out of paranoia, but we know index <= mBuffer.size().
- LoggingRecordEntry newEntry(mIndex,aString,tStamp);
- if (index >= static_cast<int32_t>(mBuffer.size())) {
- mBuffer.push_back(newEntry);
- } else {
- mBuffer[index] = newEntry;
- }
- return true;
- }
- void CrashStatsLogForwarder::UpdateCrashReport()
- {
- std::stringstream message;
- std::string logAnnotation;
- switch (XRE_GetProcessType()) {
- case GeckoProcessType_Default:
- logAnnotation = "|[";
- break;
- case GeckoProcessType_Content:
- logAnnotation = "|[C";
- break;
- case GeckoProcessType_GPU:
- logAnnotation = "|[G";
- break;
- default:
- logAnnotation = "|[X";
- break;
- }
- for (LoggingRecord::iterator it = mBuffer.begin(); it != mBuffer.end(); ++it) {
- message << logAnnotation << Get<0>(*it) << "]" << Get<1>(*it) << " (t=" << Get<2>(*it) << ") ";
- }
- nsresult annotated = NS_ERROR_NOT_IMPLEMENTED;
- if (annotated != NS_OK) {
- printf("Crash Annotation %s: %s",
- mCrashCriticalKey.get(), message.str().c_str());
- }
- }
- class LogForwarderEvent : public Runnable
- {
- virtual ~LogForwarderEvent() {}
- NS_DECL_ISUPPORTS_INHERITED
- explicit LogForwarderEvent(const nsCString& aMessage) : mMessage(aMessage) {}
- NS_IMETHOD Run() override {
- MOZ_ASSERT(NS_IsMainThread() && (XRE_IsContentProcess() || XRE_IsGPUProcess()));
- if (XRE_IsContentProcess()) {
- dom::ContentChild* cc = dom::ContentChild::GetSingleton();
- Unused << cc->SendGraphicsError(mMessage);
- } else if (XRE_IsGPUProcess()) {
- GPUParent* gp = GPUParent::GetSingleton();
- Unused << gp->SendGraphicsError(mMessage);
- }
- return NS_OK;
- }
- protected:
- nsCString mMessage;
- };
- NS_IMPL_ISUPPORTS_INHERITED0(LogForwarderEvent, Runnable);
- void CrashStatsLogForwarder::Log(const std::string& aString)
- {
- MutexAutoLock lock(mMutex);
- if (UpdateStringsVector(aString)) {
- UpdateCrashReport();
- }
- // Add it to the parent strings
- if (!XRE_IsParentProcess()) {
- nsCString stringToSend(aString.c_str());
- if (NS_IsMainThread()) {
- if (XRE_IsContentProcess()) {
- dom::ContentChild* cc = dom::ContentChild::GetSingleton();
- Unused << cc->SendGraphicsError(stringToSend);
- } else if (XRE_IsGPUProcess()) {
- GPUParent* gp = GPUParent::GetSingleton();
- Unused << gp->SendGraphicsError(stringToSend);
- }
- } else {
- nsCOMPtr<nsIRunnable> r1 = new LogForwarderEvent(stringToSend);
- NS_DispatchToMainThread(r1);
- }
- }
- }
- void
- CrashStatsLogForwarder::CrashAction(LogReason aReason)
- {
- MOZ_CRASH("GFX_CRASH");
- }
- NS_IMPL_ISUPPORTS(SRGBOverrideObserver, nsIObserver, nsISupportsWeakReference)
- #define GFX_DOWNLOADABLE_FONTS_ENABLED "gfx.downloadable_fonts.enabled"
- #define GFX_PREF_FALLBACK_USE_CMAPS "gfx.font_rendering.fallback.always_use_cmaps"
- #define GFX_PREF_OPENTYPE_SVG "gfx.font_rendering.opentype_svg.enabled"
- #define GFX_PREF_WORD_CACHE_CHARLIMIT "gfx.font_rendering.wordcache.charlimit"
- #define GFX_PREF_WORD_CACHE_MAXENTRIES "gfx.font_rendering.wordcache.maxentries"
- #define GFX_PREF_GRAPHITE_SHAPING "gfx.font_rendering.graphite.enabled"
- #define BIDI_NUMERAL_PREF "bidi.numeral"
- #define GFX_PREF_CMS_FORCE_SRGB "gfx.color_management.force_srgb"
- NS_IMETHODIMP
- SRGBOverrideObserver::Observe(nsISupports *aSubject,
- const char *aTopic,
- const char16_t* someData)
- {
- NS_ASSERTION(NS_strcmp(someData,
- (u"" GFX_PREF_CMS_FORCE_SRGB)) == 0,
- "Restarting CMS on wrong pref!");
- ShutdownCMS();
- // Update current cms profile.
- gfxPlatform::CreateCMSOutputProfile();
- return NS_OK;
- }
- static const char* kObservedPrefs[] = {
- "gfx.downloadable_fonts.",
- "gfx.font_rendering.",
- BIDI_NUMERAL_PREF,
- nullptr
- };
- class FontPrefsObserver final : public nsIObserver
- {
- ~FontPrefsObserver() {}
- public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIOBSERVER
- };
- NS_IMPL_ISUPPORTS(FontPrefsObserver, nsIObserver)
- NS_IMETHODIMP
- FontPrefsObserver::Observe(nsISupports *aSubject,
- const char *aTopic,
- const char16_t *someData)
- {
- if (!someData) {
- NS_ERROR("font pref observer code broken");
- return NS_ERROR_UNEXPECTED;
- }
- NS_ASSERTION(gfxPlatform::GetPlatform(), "the singleton instance has gone");
- gfxPlatform::GetPlatform()->FontsPrefsChanged(NS_ConvertUTF16toUTF8(someData).get());
- return NS_OK;
- }
- class MemoryPressureObserver final : public nsIObserver
- {
- ~MemoryPressureObserver() {}
- public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIOBSERVER
- };
- NS_IMPL_ISUPPORTS(MemoryPressureObserver, nsIObserver)
- NS_IMETHODIMP
- MemoryPressureObserver::Observe(nsISupports *aSubject,
- const char *aTopic,
- const char16_t *someData)
- {
- NS_ASSERTION(strcmp(aTopic, "memory-pressure") == 0, "unexpected event topic");
- Factory::PurgeAllCaches();
- gfxGradientCache::PurgeAllCaches();
- gfxPlatform::PurgeSkiaFontCache();
- gfxPlatform::GetPlatform()->PurgeSkiaGPUCache();
- return NS_OK;
- }
- gfxPlatform::gfxPlatform()
- : mAzureCanvasBackendCollector(this, &gfxPlatform::GetAzureBackendInfo)
- , mApzSupportCollector(this, &gfxPlatform::GetApzSupportInfo)
- , mTilesInfoCollector(this, &gfxPlatform::GetTilesSupportInfo)
- , mCompositorBackend(layers::LayersBackend::LAYERS_NONE)
- , mScreenDepth(0)
- , mDeviceCounter(0)
- {
- mAllowDownloadableFonts = UNINITIALIZED_VALUE;
- mFallbackUsesCmaps = UNINITIALIZED_VALUE;
- mWordCacheCharLimit = UNINITIALIZED_VALUE;
- mWordCacheMaxEntries = UNINITIALIZED_VALUE;
- mGraphiteShapingEnabled = UNINITIALIZED_VALUE;
- mOpenTypeSVGEnabled = UNINITIALIZED_VALUE;
- mBidiNumeralOption = UNINITIALIZED_VALUE;
- mSkiaGlue = nullptr;
- uint32_t canvasMask = BackendTypeBit(BackendType::CAIRO);
- uint32_t contentMask = BackendTypeBit(BackendType::CAIRO);
- #ifdef USE_SKIA
- canvasMask |= BackendTypeBit(BackendType::SKIA);
- contentMask |= BackendTypeBit(BackendType::SKIA);
- #endif
- InitBackendPrefs(canvasMask, BackendType::CAIRO,
- contentMask, BackendType::CAIRO);
- mTotalSystemMemory = PR_GetPhysicalMemorySize();
- }
- gfxPlatform*
- gfxPlatform::GetPlatform()
- {
- if (!gPlatform) {
- Init();
- }
- return gPlatform;
- }
- bool
- gfxPlatform::Initialized()
- {
- return !!gPlatform;
- }
- void RecordingPrefChanged(const char *aPrefName, void *aClosure)
- {
- if (Preferences::GetBool("gfx.2d.recording", false)) {
- nsAutoCString fileName;
- nsAdoptingString prefFileName = Preferences::GetString("gfx.2d.recordingfile");
- if (prefFileName) {
- fileName.Append(NS_ConvertUTF16toUTF8(prefFileName));
- } else {
- nsCOMPtr<nsIFile> tmpFile;
- if (NS_FAILED(NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tmpFile)))) {
- return;
- }
- fileName.AppendPrintf("moz2drec_%i_%i.aer", XRE_GetProcessType(), getpid());
- nsresult rv = tmpFile->AppendNative(fileName);
- if (NS_FAILED(rv))
- return;
- rv = tmpFile->GetNativePath(fileName);
- if (NS_FAILED(rv))
- return;
- }
- gPlatform->mRecorder = Factory::CreateEventRecorderForFile(fileName.BeginReading());
- printf_stderr("Recording to %s\n", fileName.get());
- Factory::SetGlobalEventRecorder(gPlatform->mRecorder);
- } else {
- Factory::SetGlobalEventRecorder(nullptr);
- }
- }
- #if defined(USE_SKIA)
- static uint32_t GetSkiaGlyphCacheSize()
- {
- // 10mb as the default cache size on desktop due to talos perf tweaking.
- // Chromium uses 20mb and skia default uses 2mb.
- // We don't need to change the font cache count since we usually
- // cache thrash due to asian character sets in talos.
- // Only increase memory on the content proces
- uint32_t cacheSize = 10 * 1024 * 1024;
- if (mozilla::BrowserTabsRemoteAutostart()) {
- return XRE_IsContentProcess() ? cacheSize : kDefaultGlyphCacheSize;
- }
- return cacheSize;
- }
- #endif
- void
- gfxPlatform::Init()
- {
- MOZ_RELEASE_ASSERT(!XRE_IsGPUProcess(), "GFX: Not allowed in GPU process.");
- MOZ_RELEASE_ASSERT(NS_IsMainThread(), "GFX: Not in main thread.");
- if (gEverInitialized) {
- NS_RUNTIMEABORT("Already started???");
- }
- gEverInitialized = true;
- // Initialize the preferences by creating the singleton.
- gfxPrefs::GetSingleton();
- MediaPrefs::GetSingleton();
- gfxVars::Initialize();
- gfxConfig::Init();
- if (XRE_IsParentProcess()) {
- GPUProcessManager::Initialize();
- if (Preferences::GetBool("media.wmf.skip-blacklist")) {
- gfxVars::SetPDMWMFDisableD3D11Dlls(nsCString());
- gfxVars::SetPDMWMFDisableD3D9Dlls(nsCString());
- } else {
- gfxVars::SetPDMWMFDisableD3D11Dlls(Preferences::GetCString("media.wmf.disable-d3d11-for-dlls"));
- gfxVars::SetPDMWMFDisableD3D9Dlls(Preferences::GetCString("media.wmf.disable-d3d9-for-dlls"));
- }
- }
- InitMoz2DLogging();
- gGfxPlatformPrefsLock = new Mutex("gfxPlatform::gGfxPlatformPrefsLock");
- /* Initialize the GfxInfo service.
- * Note: we can't call functions on GfxInfo that depend
- * on gPlatform until after it has been initialized
- * below. GfxInfo initialization annotates our
- * crash reports so we want to do it before
- * we try to load any drivers and do device detection
- * incase that code crashes. See bug #591561. */
- nsCOMPtr<nsIGfxInfo> gfxInfo;
- /* this currently will only succeed on Windows */
- gfxInfo = services::GetGfxInfo();
- #if defined(XP_WIN)
- gPlatform = new gfxWindowsPlatform;
- #elif defined(MOZ_WIDGET_GTK)
- gPlatform = new gfxPlatformGtk;
- #elif defined(ANDROID)
- gPlatform = new gfxAndroidPlatform;
- #else
- #error "No gfxPlatform implementation available"
- #endif
- gPlatform->InitAcceleration();
- if (gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
- GPUProcessManager* gpu = GPUProcessManager::Get();
- gpu->LaunchGPUProcess();
- }
- if (XRE_IsParentProcess()) {
- if (gfxPlatform::ForceSoftwareVsync()) {
- gPlatform->mVsyncSource = (gPlatform)->gfxPlatform::CreateHardwareVsyncSource();
- } else {
- gPlatform->mVsyncSource = gPlatform->CreateHardwareVsyncSource();
- }
- }
- #ifdef USE_SKIA
- SkGraphics::Init();
- # ifdef MOZ_ENABLE_FREETYPE
- SkInitCairoFT(gPlatform->FontHintingEnabled());
- # endif
- #endif
- #ifdef MOZ_GL_DEBUG
- GLContext::StaticInit();
- #endif
- InitLayersIPC();
- gPlatform->PopulateScreenInfo();
- gPlatform->ComputeTileSize();
- nsresult rv;
- bool usePlatformFontList = true;
- #if defined(MOZ_WIDGET_GTK)
- usePlatformFontList = gfxPlatformGtk::UseFcFontList();
- #endif
- if (usePlatformFontList) {
- rv = gfxPlatformFontList::Init();
- if (NS_FAILED(rv)) {
- NS_RUNTIMEABORT("Could not initialize gfxPlatformFontList");
- }
- }
- gPlatform->mScreenReferenceSurface =
- gPlatform->CreateOffscreenSurface(IntSize(1, 1),
- SurfaceFormat::A8R8G8B8_UINT32);
- if (!gPlatform->mScreenReferenceSurface) {
- NS_RUNTIMEABORT("Could not initialize mScreenReferenceSurface");
- }
- gPlatform->mScreenReferenceDrawTarget =
- gPlatform->CreateOffscreenContentDrawTarget(IntSize(1, 1),
- SurfaceFormat::B8G8R8A8);
- if (!gPlatform->mScreenReferenceDrawTarget ||
- !gPlatform->mScreenReferenceDrawTarget->IsValid()) {
- NS_RUNTIMEABORT("Could not initialize mScreenReferenceDrawTarget");
- }
- rv = gfxFontCache::Init();
- if (NS_FAILED(rv)) {
- NS_RUNTIMEABORT("Could not initialize gfxFontCache");
- }
- /* Create and register our CMS Override observer. */
- gPlatform->mSRGBOverrideObserver = new SRGBOverrideObserver();
- Preferences::AddWeakObserver(gPlatform->mSRGBOverrideObserver, GFX_PREF_CMS_FORCE_SRGB);
- gPlatform->mFontPrefsObserver = new FontPrefsObserver();
- Preferences::AddStrongObservers(gPlatform->mFontPrefsObserver, kObservedPrefs);
- GLContext::PlatformStartup();
- Preferences::RegisterCallbackAndCall(RecordingPrefChanged, "gfx.2d.recording", nullptr);
- CreateCMSOutputProfile();
- // Listen to memory pressure event so we can purge DrawTarget caches
- nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
- if (obs) {
- gPlatform->mMemoryPressureObserver = new MemoryPressureObserver();
- obs->AddObserver(gPlatform->mMemoryPressureObserver, "memory-pressure", false);
- }
- // Request the imgITools service, implicitly initializing ImageLib.
- nsCOMPtr<imgITools> imgTools = do_GetService("@mozilla.org/image/tools;1");
- if (!imgTools) {
- NS_RUNTIMEABORT("Could not initialize ImageLib");
- }
- RegisterStrongMemoryReporter(new GfxMemoryImageReporter());
- #ifdef USE_SKIA
- uint32_t skiaCacheSize = GetSkiaGlyphCacheSize();
- if (skiaCacheSize != kDefaultGlyphCacheSize) {
- SkGraphics::SetFontCacheLimit(skiaCacheSize);
- }
- #endif
- InitNullMetadata();
- InitOpenGLConfig();
- if (obs) {
- obs->NotifyObservers(nullptr, "gfx-features-ready", nullptr);
- }
- }
- /* static */ void
- gfxPlatform::InitMoz2DLogging()
- {
- auto fwd = new CrashStatsLogForwarder("GraphicsCriticalError");
- fwd->SetCircularBufferSize(gfxPrefs::GfxLoggingCrashLength());
- mozilla::gfx::Config cfg;
- cfg.mLogForwarder = fwd;
- cfg.mMaxTextureSize = gfxPrefs::MaxTextureSize();
- cfg.mMaxAllocSize = gfxPrefs::MaxAllocSize();
- gfx::Factory::Init(cfg);
- }
- static bool sLayersIPCIsUp = false;
- /* static */ void
- gfxPlatform::InitNullMetadata()
- {
- ScrollMetadata::sNullMetadata = new ScrollMetadata();
- ClearOnShutdown(&ScrollMetadata::sNullMetadata);
- }
- void
- gfxPlatform::Shutdown()
- {
- // In some cases, gPlatform may not be created but Shutdown() called,
- // e.g., during xpcshell tests.
- if (!gPlatform) {
- return;
- }
- MOZ_ASSERT(!sLayersIPCIsUp);
- // These may be called before the corresponding subsystems have actually
- // started up. That's OK, they can handle it.
- gfxFontCache::Shutdown();
- gfxFontGroup::Shutdown();
- gfxGradientCache::Shutdown();
- gfxAlphaBoxBlur::ShutdownBlurCache();
- gfxGraphiteShaper::Shutdown();
- gfxPlatformFontList::Shutdown();
- ShutdownTileCache();
- // Free the various non-null transforms and loaded profiles
- ShutdownCMS();
- /* Unregister our CMS Override callback. */
- NS_ASSERTION(gPlatform->mSRGBOverrideObserver, "mSRGBOverrideObserver has alreay gone");
- Preferences::RemoveObserver(gPlatform->mSRGBOverrideObserver, GFX_PREF_CMS_FORCE_SRGB);
- gPlatform->mSRGBOverrideObserver = nullptr;
- NS_ASSERTION(gPlatform->mFontPrefsObserver, "mFontPrefsObserver has alreay gone");
- Preferences::RemoveObservers(gPlatform->mFontPrefsObserver, kObservedPrefs);
- gPlatform->mFontPrefsObserver = nullptr;
- NS_ASSERTION(gPlatform->mMemoryPressureObserver, "mMemoryPressureObserver has already gone");
- nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
- if (obs) {
- obs->RemoveObserver(gPlatform->mMemoryPressureObserver, "memory-pressure");
- }
- gPlatform->mMemoryPressureObserver = nullptr;
- gPlatform->mSkiaGlue = nullptr;
- if (XRE_IsParentProcess()) {
- gPlatform->mVsyncSource->Shutdown();
- }
- gPlatform->mVsyncSource = nullptr;
- // Shut down the default GL context provider.
- GLContextProvider::Shutdown();
- #if defined(XP_WIN)
- // The above shutdown calls operate on the available context providers on
- // most platforms. Windows is a "special snowflake", though, and has three
- // context providers available, so we have to shut all of them down.
- // We should only support the default GL provider on Windows; then, this
- // could go away. Unfortunately, we currently support WGL (the default) for
- // WebGL on Optimus.
- GLContextProviderEGL::Shutdown();
- #endif
- if (XRE_IsParentProcess()) {
- GPUProcessManager::Shutdown();
- }
- gfx::Factory::ShutDown();
- delete gGfxPlatformPrefsLock;
- gfxVars::Shutdown();
- gfxPrefs::DestroySingleton();
- gfxFont::DestroySingletons();
- gfxConfig::Shutdown();
- gPlatform->WillShutdown();
- delete gPlatform;
- gPlatform = nullptr;
- }
- /* static */ void
- gfxPlatform::InitLayersIPC()
- {
- if (sLayersIPCIsUp) {
- return;
- }
- sLayersIPCIsUp = true;
- if (XRE_IsParentProcess())
- {
- layers::CompositorThreadHolder::Start();
- }
- }
- /* static */ void
- gfxPlatform::ShutdownLayersIPC()
- {
- if (!sLayersIPCIsUp) {
- return;
- }
- sLayersIPCIsUp = false;
- if (XRE_IsContentProcess()) {
- // cf bug 1215265.
- if (gfxPrefs::ChildProcessShutdown()) {
- layers::CompositorBridgeChild::ShutDown();
- layers::ImageBridgeChild::ShutDown();
- }
- } else if (XRE_IsParentProcess()) {
- layers::CompositorBridgeChild::ShutDown();
- layers::ImageBridgeChild::ShutDown();
- // This has to happen after shutting down the child protocols.
- layers::CompositorThreadHolder::Shutdown();
- } else {
- // TODO: There are other kind of processes and we should make sure gfx
- // stuff is either not created there or shut down properly.
- }
- }
- void
- gfxPlatform::WillShutdown()
- {
- // Destoy these first in case they depend on backend-specific resources.
- // Otherwise, the backend's destructor would be called before the
- // base gfxPlatform destructor.
- mScreenReferenceSurface = nullptr;
- mScreenReferenceDrawTarget = nullptr;
- }
- gfxPlatform::~gfxPlatform()
- {
- // The cairo folks think we should only clean up in debug builds,
- // but we're generally in the habit of trying to shut down as
- // cleanly as possible even in production code, so call this
- // cairo_debug_* function unconditionally.
- //
- // because cairo can assert and thus crash on shutdown, don't do this in release builds
- #ifdef NS_FREE_PERMANENT_DATA
- #ifdef USE_SKIA
- // must do Skia cleanup before Cairo cleanup, because Skia may be referencing
- // Cairo objects e.g. through SkCairoFTTypeface
- SkGraphics::PurgeFontCache();
- #endif
- #if MOZ_TREE_CAIRO
- cairo_debug_reset_static_data();
- #endif
- #endif
- }
- /* static */ already_AddRefed<DrawTarget>
- gfxPlatform::CreateDrawTargetForSurface(gfxASurface *aSurface, const IntSize& aSize)
- {
- SurfaceFormat format = aSurface->GetSurfaceFormat();
- RefPtr<DrawTarget> drawTarget = Factory::CreateDrawTargetForCairoSurface(aSurface->CairoSurface(), aSize, &format);
- if (!drawTarget) {
- gfxWarning() << "gfxPlatform::CreateDrawTargetForSurface failed in CreateDrawTargetForCairoSurface";
- return nullptr;
- }
- return drawTarget.forget();
- }
- cairo_user_data_key_t kSourceSurface;
- /**
- * Record the backend that was used to construct the SourceSurface.
- * When getting the cached SourceSurface for a gfxASurface/DrawTarget pair,
- * we check to make sure the DrawTarget's backend matches the backend
- * for the cached SourceSurface, and only use it if they match. This
- * can avoid expensive and unnecessary readbacks.
- */
- struct SourceSurfaceUserData
- {
- RefPtr<SourceSurface> mSrcSurface;
- BackendType mBackendType;
- };
- void SourceBufferDestroy(void *srcSurfUD)
- {
- delete static_cast<SourceSurfaceUserData*>(srcSurfUD);
- }
- UserDataKey kThebesSurface;
- struct DependentSourceSurfaceUserData
- {
- RefPtr<gfxASurface> mSurface;
- };
- void SourceSurfaceDestroyed(void *aData)
- {
- delete static_cast<DependentSourceSurfaceUserData*>(aData);
- }
- void
- gfxPlatform::ClearSourceSurfaceForSurface(gfxASurface *aSurface)
- {
- aSurface->SetData(&kSourceSurface, nullptr, nullptr);
- }
- /* static */ already_AddRefed<SourceSurface>
- gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget,
- gfxASurface *aSurface,
- bool aIsPlugin)
- {
- if (!aSurface->CairoSurface() || aSurface->CairoStatus()) {
- return nullptr;
- }
- if (!aTarget) {
- aTarget = gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
- }
- void *userData = aSurface->GetData(&kSourceSurface);
- if (userData) {
- SourceSurfaceUserData *surf = static_cast<SourceSurfaceUserData*>(userData);
- if (surf->mSrcSurface->IsValid() && surf->mBackendType == aTarget->GetBackendType()) {
- RefPtr<SourceSurface> srcSurface(surf->mSrcSurface);
- return srcSurface.forget();
- }
- // We can just continue here as when setting new user data the destroy
- // function will be called for the old user data.
- }
- SurfaceFormat format = aSurface->GetSurfaceFormat();
- if (aTarget->GetBackendType() == BackendType::CAIRO) {
- // If we're going to be used with a CAIRO DrawTarget, then just create a
- // SourceSurfaceCairo since we don't know the underlying type of the CAIRO
- // DrawTarget and can't pick a better surface type. Doing this also avoids
- // readback of aSurface's surface into memory if, for example, aSurface
- // wraps an xlib cairo surface (which can be important to avoid a major
- // slowdown).
- //
- // We return here regardless of whether CreateSourceSurfaceFromNativeSurface
- // succeeds or not since we don't expect to be able to do any better below
- // if it fails.
- //
- // Note that the returned SourceSurfaceCairo holds a strong reference to
- // the cairo_surface_t* that it wraps, which essencially means it holds a
- // strong reference to aSurface since aSurface shares its
- // cairo_surface_t*'s reference count variable. As a result we can't cache
- // srcBuffer on aSurface (see below) since aSurface would then hold a
- // strong reference back to srcBuffer, creating a reference loop and a
- // memory leak. Not caching is fine since wrapping is cheap enough (no
- // copying) so we can just wrap again next time we're called.
- return Factory::CreateSourceSurfaceForCairoSurface(aSurface->CairoSurface(),
- aSurface->GetSize(), format);
- }
- RefPtr<SourceSurface> srcBuffer;
- // Currently no other DrawTarget types implement CreateSourceSurfaceFromNativeSurface
- if (!srcBuffer) {
- // If aSurface wraps data, we can create a SourceSurfaceRawData that wraps
- // the same data, then optimize it for aTarget:
- RefPtr<DataSourceSurface> surf = GetWrappedDataSourceSurface(aSurface);
- if (surf) {
- srcBuffer = aIsPlugin ? aTarget->OptimizeSourceSurfaceForUnknownAlpha(surf)
- : aTarget->OptimizeSourceSurface(surf);
- if (srcBuffer == surf) {
- // GetWrappedDataSourceSurface returns a SourceSurface that holds a
- // strong reference to aSurface since it wraps aSurface's data and
- // needs it to stay alive. As a result we can't cache srcBuffer on
- // aSurface (below) since aSurface would then hold a strong reference
- // back to srcBuffer, creating a reference loop and a memory leak. Not
- // caching is fine since wrapping is cheap enough (no copying) so we
- // can just wrap again next time we're called.
- //
- // Note that the check below doesn't catch this since srcBuffer will be a
- // SourceSurfaceRawData object (even if aSurface is not a gfxImageSurface
- // object), which is why we need this separate check.
- return srcBuffer.forget();
- }
- }
- }
- if (!srcBuffer) {
- MOZ_ASSERT(aTarget->GetBackendType() != BackendType::CAIRO,
- "We already tried CreateSourceSurfaceFromNativeSurface with a "
- "DrawTargetCairo above");
- // We've run out of performant options. We now try creating a SourceSurface
- // using a temporary DrawTargetCairo and then optimizing it to aTarget's
- // actual type. The CreateSourceSurfaceFromNativeSurface() call will
- // likely create a DataSourceSurface (possibly involving copying and/or
- // readback), and the OptimizeSourceSurface may well copy again and upload
- // to the GPU. So, while this code path is rarely hit, hitting it may be
- // very slow.
- srcBuffer = Factory::CreateSourceSurfaceForCairoSurface(aSurface->CairoSurface(),
- aSurface->GetSize(), format);
- if (srcBuffer) {
- srcBuffer = aTarget->OptimizeSourceSurface(srcBuffer);
- }
- }
- if (!srcBuffer) {
- return nullptr;
- }
- if ((srcBuffer->GetType() == SurfaceType::CAIRO &&
- static_cast<SourceSurfaceCairo*>(srcBuffer.get())->GetSurface() ==
- aSurface->CairoSurface()) ||
- (srcBuffer->GetType() == SurfaceType::CAIRO_IMAGE &&
- static_cast<DataSourceSurfaceCairo*>(srcBuffer.get())->GetSurface() ==
- aSurface->CairoSurface())) {
- // See the "Note that the returned SourceSurfaceCairo..." comment above.
- return srcBuffer.forget();
- }
- // Add user data to aSurface so we can cache lookups in the future.
- SourceSurfaceUserData *srcSurfUD = new SourceSurfaceUserData;
- srcSurfUD->mBackendType = aTarget->GetBackendType();
- srcSurfUD->mSrcSurface = srcBuffer;
- aSurface->SetData(&kSourceSurface, srcSurfUD, SourceBufferDestroy);
- return srcBuffer.forget();
- }
- already_AddRefed<DataSourceSurface>
- gfxPlatform::GetWrappedDataSourceSurface(gfxASurface* aSurface)
- {
- RefPtr<gfxImageSurface> image = aSurface->GetAsImageSurface();
- if (!image) {
- return nullptr;
- }
- RefPtr<DataSourceSurface> result =
- Factory::CreateWrappingDataSourceSurface(image->Data(),
- image->Stride(),
- image->GetSize(),
- ImageFormatToSurfaceFormat(image->Format()));
- if (!result) {
- return nullptr;
- }
- // If we wrapped the underlying data of aSurface, then we need to add user data
- // to make sure aSurface stays alive until we are done with the data.
- DependentSourceSurfaceUserData *srcSurfUD = new DependentSourceSurfaceUserData;
- srcSurfUD->mSurface = aSurface;
- result->AddUserData(&kThebesSurface, srcSurfUD, SourceSurfaceDestroyed);
- return result.forget();
- }
- already_AddRefed<ScaledFont>
- gfxPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
- {
- NativeFont nativeFont;
- nativeFont.mType = NativeFontType::CAIRO_FONT_FACE;
- nativeFont.mFont = aFont->GetCairoScaledFont();
- return Factory::CreateScaledFontForNativeFont(nativeFont,
- aFont->GetAdjustedSize());
- }
- void
- gfxPlatform::ComputeTileSize()
- {
- // The tile size should be picked in the parent processes
- // and sent to the child processes over IPDL GetTileSize.
- if (!XRE_IsParentProcess()) {
- return;
- }
- int32_t w = gfxPrefs::LayersTileWidth();
- int32_t h = gfxPrefs::LayersTileHeight();
- if (gfxPrefs::LayersTilesAdjust()) {
- gfx::IntSize screenSize = GetScreenSize();
- if (screenSize.width > 0) {
- // Choose a size so that there are between 2 and 4 tiles per screen width.
- // FIXME: we should probably make sure this is within the max texture size,
- // but I think everything should at least support 1024
- w = h = clamped(int32_t(RoundUpPow2(screenSize.width)) / 4, 256, 1024);
- }
- }
- // Don't allow changing the tile size after we've set it.
- // Right now the code assumes that the tile size doesn't change.
- MOZ_ASSERT(gfxVars::TileSize().width == -1 &&
- gfxVars::TileSize().height == -1);
- gfxVars::SetTileSize(IntSize(w, h));
- }
- void
- gfxPlatform::PopulateScreenInfo()
- {
- nsCOMPtr<nsIScreenManager> manager = do_GetService("@mozilla.org/gfx/screenmanager;1");
- MOZ_ASSERT(manager, "failed to get nsIScreenManager");
- nsCOMPtr<nsIScreen> screen;
- manager->GetPrimaryScreen(getter_AddRefs(screen));
- if (!screen) {
- // This can happen in xpcshell, for instance
- return;
- }
- screen->GetColorDepth(&mScreenDepth);
- int left, top;
- screen->GetRect(&left, &top, &mScreenSize.width, &mScreenSize.height);
- }
- bool
- gfxPlatform::SupportsAzureContentForDrawTarget(DrawTarget* aTarget)
- {
- if (!aTarget || !aTarget->IsValid()) {
- return false;
- }
- #ifdef USE_SKIA_GPU
- // Skia content rendering doesn't support GPU acceleration, so we can't
- // use the same backend if the current backend is accelerated.
- if ((aTarget->GetType() == DrawTargetType::HARDWARE_RASTER)
- && (aTarget->GetBackendType() == BackendType::SKIA))
- {
- return false;
- }
- #endif
- return SupportsAzureContentForType(aTarget->GetBackendType());
- }
- bool gfxPlatform::AllowOpenGLCanvas()
- {
- // For now, only allow Skia+OpenGL, unless it's blocked.
- // Allow acceleration on Skia if the preference is set, unless it's blocked
- // as long as we have the accelerated layers
- // The compositor backend is only set correctly in the parent process,
- // so we let content process always assume correct compositor backend.
- // The callers have to do the right thing.
- bool correctBackend = !XRE_IsParentProcess() ||
- ((mCompositorBackend == LayersBackend::LAYERS_OPENGL) &&
- (GetContentBackendFor(mCompositorBackend) == BackendType::SKIA));
- if (gfxPrefs::CanvasAzureAccelerated() && correctBackend) {
- nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
- int32_t status;
- nsCString discardFailureId;
- return !gfxInfo ||
- (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_CANVAS2D_ACCELERATION,
- discardFailureId,
- &status)) &&
- status == nsIGfxInfo::FEATURE_STATUS_OK);
- }
- return false;
- }
- void
- gfxPlatform::InitializeSkiaCacheLimits()
- {
- if (AllowOpenGLCanvas()) {
- #ifdef USE_SKIA_GPU
- bool usingDynamicCache = gfxPrefs::CanvasSkiaGLDynamicCache();
- int cacheItemLimit = gfxPrefs::CanvasSkiaGLCacheItems();
- uint64_t cacheSizeLimit = std::max(gfxPrefs::CanvasSkiaGLCacheSize(), (int32_t)0);
- // Prefs are in megabytes, but we want the sizes in bytes
- cacheSizeLimit *= 1024*1024;
- if (usingDynamicCache) {
- if (mTotalSystemMemory < 512*1024*1024) {
- // We need a very minimal cache on anything smaller than 512mb.
- // Note the large jump as we cross 512mb (from 2mb to 32mb).
- cacheSizeLimit = 2*1024*1024;
- } else if (mTotalSystemMemory > 0) {
- cacheSizeLimit = mTotalSystemMemory / 16;
- }
- }
- // Ensure cache size doesn't overflow on 32-bit platforms.
- cacheSizeLimit = std::min(cacheSizeLimit, (uint64_t)SIZE_MAX);
- #ifdef DEBUG
- printf_stderr("Determined SkiaGL cache limits: Size %" PRIu64 ", Items: %i\n", cacheSizeLimit, cacheItemLimit);
- #endif
- mSkiaGlue->GetGrContext()->setResourceCacheLimits(cacheItemLimit, (size_t)cacheSizeLimit);
- #endif
- }
- }
- SkiaGLGlue*
- gfxPlatform::GetSkiaGLGlue()
- {
- #ifdef USE_SKIA_GPU
- // Check the accelerated Canvas is enabled for the first time,
- // because the callers should check it before using.
- if (!mSkiaGlue && !AllowOpenGLCanvas()) {
- return nullptr;
- }
- if (!mSkiaGlue) {
- /* Dummy context. We always draw into a FBO.
- *
- * FIXME: This should be stored in TLS or something, since there needs to be one for each thread using it. As it
- * stands, this only works on the main thread.
- */
- RefPtr<GLContext> glContext;
- nsCString discardFailureId;
- glContext = GLContextProvider::CreateHeadless(CreateContextFlags::REQUIRE_COMPAT_PROFILE |
- CreateContextFlags::ALLOW_OFFLINE_RENDERER,
- &discardFailureId);
- if (!glContext) {
- printf_stderr("Failed to create GLContext for SkiaGL!\n");
- return nullptr;
- }
- mSkiaGlue = new SkiaGLGlue(glContext);
- MOZ_ASSERT(mSkiaGlue->GetGrContext(), "No GrContext");
- InitializeSkiaCacheLimits();
- }
- #endif
- return mSkiaGlue;
- }
- void
- gfxPlatform::PurgeSkiaFontCache()
- {
- #ifdef USE_SKIA
- if (gfxPlatform::GetPlatform()->GetDefaultContentBackend() == BackendType::SKIA) {
- SkGraphics::PurgeFontCache();
- }
- #endif
- }
- void
- gfxPlatform::PurgeSkiaGPUCache()
- {
- #ifdef USE_SKIA_GPU
- if (!mSkiaGlue)
- return;
- mSkiaGlue->GetGrContext()->freeGpuResources();
- // GrContext::flush() doesn't call glFlush. Call it here.
- mSkiaGlue->GetGLContext()->MakeCurrent();
- mSkiaGlue->GetGLContext()->fFlush();
- #endif
- }
- bool
- gfxPlatform::HasEnoughTotalSystemMemoryForSkiaGL()
- {
- return true;
- }
- already_AddRefed<DrawTarget>
- gfxPlatform::CreateDrawTargetForBackend(BackendType aBackend, const IntSize& aSize, SurfaceFormat aFormat)
- {
- // There is a bunch of knowledge in the gfxPlatform heirarchy about how to
- // create the best offscreen surface for the current system and situation. We
- // can easily take advantage of this for the Cairo backend, so that's what we
- // do.
- // mozilla::gfx::Factory can get away without having all this knowledge for
- // now, but this might need to change in the future (using
- // CreateOffscreenSurface() and CreateDrawTargetForSurface() for all
- // backends).
- if (aBackend == BackendType::CAIRO) {
- RefPtr<gfxASurface> surf = CreateOffscreenSurface(aSize, SurfaceFormatToImageFormat(aFormat));
- if (!surf || surf->CairoStatus()) {
- return nullptr;
- }
- return CreateDrawTargetForSurface(surf, aSize);
- } else {
- return Factory::CreateDrawTarget(aBackend, aSize, aFormat);
- }
- }
- already_AddRefed<DrawTarget>
- gfxPlatform::CreateOffscreenCanvasDrawTarget(const IntSize& aSize, SurfaceFormat aFormat)
- {
- NS_ASSERTION(mPreferredCanvasBackend != BackendType::NONE, "No backend.");
- RefPtr<DrawTarget> target = CreateDrawTargetForBackend(mPreferredCanvasBackend, aSize, aFormat);
- if (target ||
- mFallbackCanvasBackend == BackendType::NONE) {
- return target.forget();
- }
- #ifdef XP_WIN
- // On Windows, the fallback backend (Cairo) should use its image backend.
- return Factory::CreateDrawTarget(mFallbackCanvasBackend, aSize, aFormat);
- #else
- return CreateDrawTargetForBackend(mFallbackCanvasBackend, aSize, aFormat);
- #endif
- }
- already_AddRefed<DrawTarget>
- gfxPlatform::CreateOffscreenContentDrawTarget(const IntSize& aSize, SurfaceFormat aFormat)
- {
- NS_ASSERTION(mPreferredCanvasBackend != BackendType::NONE, "No backend.");
- return CreateDrawTargetForBackend(mContentBackend, aSize, aFormat);
- }
- already_AddRefed<DrawTarget>
- gfxPlatform::CreateSimilarSoftwareDrawTarget(DrawTarget* aDT,
- const IntSize& aSize,
- SurfaceFormat aFormat)
- {
- RefPtr<DrawTarget> dt;
- if (Factory::DoesBackendSupportDataDrawtarget(aDT->GetBackendType())) {
- dt = aDT->CreateSimilarDrawTarget(aSize, aFormat);
- } else {
- dt = Factory::CreateDrawTarget(BackendType::SKIA, aSize, aFormat);
- }
- return dt.forget();
- }
- /* static */ already_AddRefed<DrawTarget>
- gfxPlatform::CreateDrawTargetForData(unsigned char* aData, const IntSize& aSize, int32_t aStride, SurfaceFormat aFormat)
- {
- BackendType backendType = gfxVars::ContentBackend();
- NS_ASSERTION(backendType != BackendType::NONE, "No backend.");
- if (!Factory::DoesBackendSupportDataDrawtarget(backendType)) {
- backendType = BackendType::CAIRO;
- }
- RefPtr<DrawTarget> dt = Factory::CreateDrawTargetForData(backendType,
- aData, aSize,
- aStride, aFormat);
- return dt.forget();
- }
- /* static */ BackendType
- gfxPlatform::BackendTypeForName(const nsCString& aName)
- {
- if (aName.EqualsLiteral("cairo"))
- return BackendType::CAIRO;
- if (aName.EqualsLiteral("skia"))
- return BackendType::SKIA;
- if (aName.EqualsLiteral("direct2d"))
- return BackendType::DIRECT2D;
- if (aName.EqualsLiteral("direct2d1.1"))
- return BackendType::DIRECT2D1_1;
- return BackendType::NONE;
- }
- nsresult
- gfxPlatform::GetFontList(nsIAtom *aLangGroup,
- const nsACString& aGenericFamily,
- nsTArray<nsString>& aListOfFonts)
- {
- gfxPlatformFontList::PlatformFontList()->GetFontList(aLangGroup,
- aGenericFamily,
- aListOfFonts);
- return NS_OK;
- }
- nsresult
- gfxPlatform::UpdateFontList()
- {
- gfxPlatformFontList::PlatformFontList()->UpdateFontList();
- return NS_OK;
- }
- nsresult
- gfxPlatform::GetStandardFamilyName(const nsAString& aFontName,
- nsAString& aFamilyName)
- {
- gfxPlatformFontList::PlatformFontList()->GetStandardFamilyName(aFontName,
- aFamilyName);
- return NS_OK;
- }
- bool
- gfxPlatform::DownloadableFontsEnabled()
- {
- if (mAllowDownloadableFonts == UNINITIALIZED_VALUE) {
- mAllowDownloadableFonts =
- Preferences::GetBool(GFX_DOWNLOADABLE_FONTS_ENABLED, false);
- }
- return mAllowDownloadableFonts;
- }
- bool
- gfxPlatform::UseCmapsDuringSystemFallback()
- {
- if (mFallbackUsesCmaps == UNINITIALIZED_VALUE) {
- mFallbackUsesCmaps =
- Preferences::GetBool(GFX_PREF_FALLBACK_USE_CMAPS, false);
- }
- return mFallbackUsesCmaps;
- }
- bool
- gfxPlatform::OpenTypeSVGEnabled()
- {
- if (mOpenTypeSVGEnabled == UNINITIALIZED_VALUE) {
- mOpenTypeSVGEnabled =
- Preferences::GetBool(GFX_PREF_OPENTYPE_SVG, false);
- }
- return mOpenTypeSVGEnabled > 0;
- }
- uint32_t
- gfxPlatform::WordCacheCharLimit()
- {
- if (mWordCacheCharLimit == UNINITIALIZED_VALUE) {
- mWordCacheCharLimit =
- Preferences::GetInt(GFX_PREF_WORD_CACHE_CHARLIMIT, 32);
- if (mWordCacheCharLimit < 0) {
- mWordCacheCharLimit = 32;
- }
- }
- return uint32_t(mWordCacheCharLimit);
- }
- uint32_t
- gfxPlatform::WordCacheMaxEntries()
- {
- if (mWordCacheMaxEntries == UNINITIALIZED_VALUE) {
- mWordCacheMaxEntries =
- Preferences::GetInt(GFX_PREF_WORD_CACHE_MAXENTRIES, 10000);
- if (mWordCacheMaxEntries < 0) {
- mWordCacheMaxEntries = 10000;
- }
- }
- return uint32_t(mWordCacheMaxEntries);
- }
- bool
- gfxPlatform::UseGraphiteShaping()
- {
- if (mGraphiteShapingEnabled == UNINITIALIZED_VALUE) {
- mGraphiteShapingEnabled =
- Preferences::GetBool(GFX_PREF_GRAPHITE_SHAPING, false);
- }
- return mGraphiteShapingEnabled;
- }
- gfxFontEntry*
- gfxPlatform::LookupLocalFont(const nsAString& aFontName,
- uint16_t aWeight,
- int16_t aStretch,
- uint8_t aStyle)
- {
- return gfxPlatformFontList::PlatformFontList()->LookupLocalFont(aFontName,
- aWeight,
- aStretch,
- aStyle);
- }
- gfxFontEntry*
- gfxPlatform::MakePlatformFont(const nsAString& aFontName,
- uint16_t aWeight,
- int16_t aStretch,
- uint8_t aStyle,
- const uint8_t* aFontData,
- uint32_t aLength)
- {
- return gfxPlatformFontList::PlatformFontList()->MakePlatformFont(aFontName,
- aWeight,
- aStretch,
- aStyle,
- aFontData,
- aLength);
- }
- mozilla::layers::DiagnosticTypes
- gfxPlatform::GetLayerDiagnosticTypes()
- {
- mozilla::layers::DiagnosticTypes type = DiagnosticTypes::NO_DIAGNOSTIC;
- if (gfxPrefs::DrawLayerBorders()) {
- type |= mozilla::layers::DiagnosticTypes::LAYER_BORDERS;
- }
- if (gfxPrefs::DrawTileBorders()) {
- type |= mozilla::layers::DiagnosticTypes::TILE_BORDERS;
- }
- if (gfxPrefs::DrawBigImageBorders()) {
- type |= mozilla::layers::DiagnosticTypes::BIGIMAGE_BORDERS;
- }
- if (gfxPrefs::FlashLayerBorders()) {
- type |= mozilla::layers::DiagnosticTypes::FLASH_BORDERS;
- }
- return type;
- }
- void
- gfxPlatform::InitBackendPrefs(uint32_t aCanvasBitmask, BackendType aCanvasDefault,
- uint32_t aContentBitmask, BackendType aContentDefault)
- {
- mPreferredCanvasBackend = GetCanvasBackendPref(aCanvasBitmask);
- if (mPreferredCanvasBackend == BackendType::NONE) {
- mPreferredCanvasBackend = aCanvasDefault;
- }
- if (mPreferredCanvasBackend == BackendType::DIRECT2D1_1) {
- // Falling back to D2D 1.0 won't help us here. When D2D 1.1 DT creation
- // fails it means the surface was too big or there's something wrong with
- // the device. D2D 1.0 will encounter a similar situation.
- mFallbackCanvasBackend =
- GetCanvasBackendPref(aCanvasBitmask &
- ~(BackendTypeBit(mPreferredCanvasBackend) | BackendTypeBit(BackendType::DIRECT2D)));
- } else {
- mFallbackCanvasBackend =
- GetCanvasBackendPref(aCanvasBitmask & ~BackendTypeBit(mPreferredCanvasBackend));
- }
- mContentBackendBitmask = aContentBitmask;
- mContentBackend = GetContentBackendPref(mContentBackendBitmask);
- if (mContentBackend == BackendType::NONE) {
- mContentBackend = aContentDefault;
- // mContentBackendBitmask is our canonical reference for supported
- // backends so we need to add the default if we are using it and
- // overriding the prefs.
- mContentBackendBitmask |= BackendTypeBit(aContentDefault);
- }
- if (XRE_IsParentProcess()) {
- gfxVars::SetContentBackend(mContentBackend);
- }
- }
- /* static */ BackendType
- gfxPlatform::GetCanvasBackendPref(uint32_t aBackendBitmask)
- {
- return GetBackendPref("gfx.canvas.azure.backends", aBackendBitmask);
- }
- /* static */ BackendType
- gfxPlatform::GetContentBackendPref(uint32_t &aBackendBitmask)
- {
- return GetBackendPref("gfx.content.azure.backends", aBackendBitmask);
- }
- /* static */ BackendType
- gfxPlatform::GetBackendPref(const char* aBackendPrefName, uint32_t &aBackendBitmask)
- {
- nsTArray<nsCString> backendList;
- nsCString prefString;
- if (NS_SUCCEEDED(Preferences::GetCString(aBackendPrefName, &prefString))) {
- ParseString(prefString, ',', backendList);
- }
- uint32_t allowedBackends = 0;
- BackendType result = BackendType::NONE;
- for (uint32_t i = 0; i < backendList.Length(); ++i) {
- BackendType type = BackendTypeForName(backendList[i]);
- if (BackendTypeBit(type) & aBackendBitmask) {
- allowedBackends |= BackendTypeBit(type);
- if (result == BackendType::NONE) {
- result = type;
- }
- }
- }
- aBackendBitmask = allowedBackends;
- return result;
- }
- bool
- gfxPlatform::InSafeMode()
- {
- static bool sSafeModeInitialized = false;
- static bool sInSafeMode = false;
- if (!sSafeModeInitialized) {
- sSafeModeInitialized = true;
- nsCOMPtr<nsIXULRuntime> xr = do_GetService("@mozilla.org/xre/runtime;1");
- if (xr) {
- xr->GetInSafeMode(&sInSafeMode);
- }
- }
- return sInSafeMode;
- }
- bool
- gfxPlatform::OffMainThreadCompositingEnabled()
- {
- return UsesOffMainThreadCompositing();
- }
- eCMSMode
- gfxPlatform::GetCMSMode()
- {
- if (!gCMSInitialized) {
- int32_t mode = gfxPrefs::CMSMode();
- if (mode >= 0 && mode < eCMSMode_AllCount) {
- gCMSMode = static_cast<eCMSMode>(mode);
- }
- bool enableV4 = gfxPrefs::CMSEnableV4();
- if (enableV4) {
- qcms_enable_iccv4();
- }
- gCMSInitialized = true;
- }
- return gCMSMode;
- }
- int
- gfxPlatform::GetRenderingIntent()
- {
- // gfxPrefs.h is using 0 as the default for the rendering
- // intent preference, based on that being the value for
- // QCMS_INTENT_DEFAULT. Assert here to catch if that ever
- // changes and we can then figure out what to do about it.
- MOZ_ASSERT(QCMS_INTENT_DEFAULT == 0);
- /* Try to query the pref system for a rendering intent. */
- int32_t pIntent = gfxPrefs::CMSRenderingIntent();
- if ((pIntent < QCMS_INTENT_MIN) || (pIntent > QCMS_INTENT_MAX)) {
- /* If the pref is out of range, use embedded profile. */
- pIntent = -1;
- }
- return pIntent;
- }
- void
- gfxPlatform::TransformPixel(const Color& in, Color& out, qcms_transform *transform)
- {
- if (transform) {
- /* we want the bytes in RGB order */
- #ifdef IS_LITTLE_ENDIAN
- /* ABGR puts the bytes in |RGBA| order on little endian */
- uint32_t packed = in.ToABGR();
- qcms_transform_data(transform,
- (uint8_t *)&packed, (uint8_t *)&packed,
- 1);
- out = Color::FromABGR(packed);
- #else
- /* ARGB puts the bytes in |ARGB| order on big endian */
- uint32_t packed = in.UnusualToARGB();
- /* add one to move past the alpha byte */
- qcms_transform_data(transform,
- (uint8_t *)&packed + 1, (uint8_t *)&packed + 1,
- 1);
- out = Color::UnusualFromARGB(packed);
- #endif
- }
- else if (&out != &in)
- out = in;
- }
- void
- gfxPlatform::GetPlatformCMSOutputProfile(void *&mem, size_t &size)
- {
- mem = nullptr;
- size = 0;
- }
- void
- gfxPlatform::GetCMSOutputProfileData(void *&mem, size_t &size)
- {
- nsAdoptingCString fname = Preferences::GetCString("gfx.color_management.display_profile");
- if (!fname.IsEmpty()) {
- qcms_data_from_path(fname, &mem, &size);
- }
- else {
- gfxPlatform::GetPlatform()->GetPlatformCMSOutputProfile(mem, size);
- }
- }
- void
- gfxPlatform::CreateCMSOutputProfile()
- {
- if (!gCMSOutputProfile) {
- /* Determine if we're using the internal override to force sRGB as
- an output profile for reftests. See Bug 452125.
- Note that we don't normally (outside of tests) set a
- default value of this preference, which means nsIPrefBranch::GetBoolPref
- will typically throw (and leave its out-param untouched).
- */
- if (Preferences::GetBool(GFX_PREF_CMS_FORCE_SRGB, false)) {
- gCMSOutputProfile = GetCMSsRGBProfile();
- }
- if (!gCMSOutputProfile) {
- void* mem = nullptr;
- size_t size = 0;
- GetCMSOutputProfileData(mem, size);
- if ((mem != nullptr) && (size > 0)) {
- gCMSOutputProfile = qcms_profile_from_memory(mem, size);
- free(mem);
- }
- }
- /* Determine if the profile looks bogus. If so, close the profile
- * and use sRGB instead. See bug 460629, */
- if (gCMSOutputProfile && qcms_profile_is_bogus(gCMSOutputProfile)) {
- NS_ASSERTION(gCMSOutputProfile != GetCMSsRGBProfile(),
- "Builtin sRGB profile tagged as bogus!!!");
- qcms_profile_release(gCMSOutputProfile);
- gCMSOutputProfile = nullptr;
- }
- if (!gCMSOutputProfile) {
- gCMSOutputProfile = GetCMSsRGBProfile();
- }
- /* Precache the LUT16 Interpolations for the output profile. See
- bug 444661 for details. */
- qcms_profile_precache_output_transform(gCMSOutputProfile);
- }
- }
- qcms_profile *
- gfxPlatform::GetCMSOutputProfile()
- {
- return gCMSOutputProfile;
- }
- qcms_profile *
- gfxPlatform::GetCMSsRGBProfile()
- {
- if (!gCMSsRGBProfile) {
- /* Create the profile using qcms. */
- gCMSsRGBProfile = qcms_profile_sRGB();
- }
- return gCMSsRGBProfile;
- }
- qcms_transform *
- gfxPlatform::GetCMSRGBTransform()
- {
- if (!gCMSRGBTransform && !gCMSRGBTransformFailed) {
- qcms_profile *inProfile, *outProfile;
- outProfile = GetCMSOutputProfile();
- inProfile = GetCMSsRGBProfile();
- if (!inProfile || !outProfile)
- return nullptr;
- gCMSRGBTransform = qcms_transform_create(inProfile, QCMS_DATA_RGB_8,
- outProfile, QCMS_DATA_RGB_8,
- QCMS_INTENT_PERCEPTUAL);
- if (!gCMSRGBTransform) {
- gCMSRGBTransformFailed = true;
- }
- }
- return gCMSRGBTransform;
- }
- qcms_transform *
- gfxPlatform::GetCMSInverseRGBTransform()
- {
- if (!gCMSInverseRGBTransform) {
- qcms_profile *inProfile, *outProfile;
- inProfile = GetCMSOutputProfile();
- outProfile = GetCMSsRGBProfile();
- if (!inProfile || !outProfile)
- return nullptr;
- gCMSInverseRGBTransform = qcms_transform_create(inProfile, QCMS_DATA_RGB_8,
- outProfile, QCMS_DATA_RGB_8,
- QCMS_INTENT_PERCEPTUAL);
- }
- return gCMSInverseRGBTransform;
- }
- qcms_transform *
- gfxPlatform::GetCMSRGBATransform()
- {
- if (!gCMSRGBATransform) {
- qcms_profile *inProfile, *outProfile;
- outProfile = GetCMSOutputProfile();
- inProfile = GetCMSsRGBProfile();
- if (!inProfile || !outProfile)
- return nullptr;
- gCMSRGBATransform = qcms_transform_create(inProfile, QCMS_DATA_RGBA_8,
- outProfile, QCMS_DATA_RGBA_8,
- QCMS_INTENT_PERCEPTUAL);
- }
- return gCMSRGBATransform;
- }
- /* Shuts down various transforms and profiles for CMS. */
- static void ShutdownCMS()
- {
- if (gCMSRGBTransform) {
- qcms_transform_release(gCMSRGBTransform);
- gCMSRGBTransform = nullptr;
- }
- if (gCMSInverseRGBTransform) {
- qcms_transform_release(gCMSInverseRGBTransform);
- gCMSInverseRGBTransform = nullptr;
- }
- if (gCMSRGBATransform) {
- qcms_transform_release(gCMSRGBATransform);
- gCMSRGBATransform = nullptr;
- }
- if (gCMSOutputProfile) {
- qcms_profile_release(gCMSOutputProfile);
- // handle the aliased case
- if (gCMSsRGBProfile == gCMSOutputProfile)
- gCMSsRGBProfile = nullptr;
- gCMSOutputProfile = nullptr;
- }
- if (gCMSsRGBProfile) {
- qcms_profile_release(gCMSsRGBProfile);
- gCMSsRGBProfile = nullptr;
- }
- // Reset the state variables
- gCMSMode = eCMSMode_Off;
- gCMSInitialized = false;
- }
- // default SetupClusterBoundaries, based on Unicode properties;
- // platform subclasses may override if they wish
- void
- gfxPlatform::SetupClusterBoundaries(gfxTextRun *aTextRun, const char16_t *aString)
- {
- if (aTextRun->GetFlags() & gfxTextRunFactory::TEXT_IS_8BIT) {
- // 8-bit text doesn't have clusters.
- // XXX is this true in all languages???
- // behdad: don't think so. Czech for example IIRC has a
- // 'ch' grapheme.
- // jfkthame: but that's not expected to behave as a grapheme cluster
- // for selection/editing/etc.
- return;
- }
- aTextRun->SetupClusterBoundaries(0, aString, aTextRun->GetLength());
- }
- int32_t
- gfxPlatform::GetBidiNumeralOption()
- {
- if (mBidiNumeralOption == UNINITIALIZED_VALUE) {
- mBidiNumeralOption = Preferences::GetInt(BIDI_NUMERAL_PREF, 0);
- }
- return mBidiNumeralOption;
- }
- /* static */ void
- gfxPlatform::FlushFontAndWordCaches()
- {
- gfxFontCache *fontCache = gfxFontCache::GetCache();
- if (fontCache) {
- fontCache->AgeAllGenerations();
- fontCache->FlushShapedWordCaches();
- }
- gfxPlatform::PurgeSkiaFontCache();
- }
- void
- gfxPlatform::FontsPrefsChanged(const char *aPref)
- {
- NS_ASSERTION(aPref != nullptr, "null preference");
- if (!strcmp(GFX_DOWNLOADABLE_FONTS_ENABLED, aPref)) {
- mAllowDownloadableFonts = UNINITIALIZED_VALUE;
- } else if (!strcmp(GFX_PREF_FALLBACK_USE_CMAPS, aPref)) {
- mFallbackUsesCmaps = UNINITIALIZED_VALUE;
- } else if (!strcmp(GFX_PREF_WORD_CACHE_CHARLIMIT, aPref)) {
- mWordCacheCharLimit = UNINITIALIZED_VALUE;
- FlushFontAndWordCaches();
- } else if (!strcmp(GFX_PREF_WORD_CACHE_MAXENTRIES, aPref)) {
- mWordCacheMaxEntries = UNINITIALIZED_VALUE;
- FlushFontAndWordCaches();
- } else if (!strcmp(GFX_PREF_GRAPHITE_SHAPING, aPref)) {
- mGraphiteShapingEnabled = UNINITIALIZED_VALUE;
- FlushFontAndWordCaches();
- } else if (!strcmp(BIDI_NUMERAL_PREF, aPref)) {
- mBidiNumeralOption = UNINITIALIZED_VALUE;
- } else if (!strcmp(GFX_PREF_OPENTYPE_SVG, aPref)) {
- mOpenTypeSVGEnabled = UNINITIALIZED_VALUE;
- gfxFontCache::GetCache()->AgeAllGenerations();
- }
- }
- mozilla::LogModule*
- gfxPlatform::GetLog(eGfxLog aWhichLog)
- {
- // logs shared across gfx
- static LazyLogModule sFontlistLog("fontlist");
- static LazyLogModule sFontInitLog("fontinit");
- static LazyLogModule sTextrunLog("textrun");
- static LazyLogModule sTextrunuiLog("textrunui");
- static LazyLogModule sCmapDataLog("cmapdata");
- static LazyLogModule sTextPerfLog("textperf");
- switch (aWhichLog) {
- case eGfxLog_fontlist:
- return sFontlistLog;
- case eGfxLog_fontinit:
- return sFontInitLog;
- case eGfxLog_textrun:
- return sTextrunLog;
- case eGfxLog_textrunui:
- return sTextrunuiLog;
- case eGfxLog_cmapdata:
- return sCmapDataLog;
- case eGfxLog_textperf:
- return sTextPerfLog;
- }
- MOZ_ASSERT_UNREACHABLE("Unexpected log type");
- return nullptr;
- }
- mozilla::gfx::SurfaceFormat
- gfxPlatform::Optimal2DFormatForContent(gfxContentType aContent)
- {
- switch (aContent) {
- case gfxContentType::COLOR:
- switch (GetOffscreenFormat()) {
- case SurfaceFormat::A8R8G8B8_UINT32:
- return mozilla::gfx::SurfaceFormat::B8G8R8A8;
- case SurfaceFormat::X8R8G8B8_UINT32:
- return mozilla::gfx::SurfaceFormat::B8G8R8X8;
- case SurfaceFormat::R5G6B5_UINT16:
- return mozilla::gfx::SurfaceFormat::R5G6B5_UINT16;
- default:
- NS_NOTREACHED("unknown gfxImageFormat for gfxContentType::COLOR");
- return mozilla::gfx::SurfaceFormat::B8G8R8A8;
- }
- case gfxContentType::ALPHA:
- return mozilla::gfx::SurfaceFormat::A8;
- case gfxContentType::COLOR_ALPHA:
- return mozilla::gfx::SurfaceFormat::B8G8R8A8;
- default:
- NS_NOTREACHED("unknown gfxContentType");
- return mozilla::gfx::SurfaceFormat::B8G8R8A8;
- }
- }
- gfxImageFormat
- gfxPlatform::OptimalFormatForContent(gfxContentType aContent)
- {
- switch (aContent) {
- case gfxContentType::COLOR:
- return GetOffscreenFormat();
- case gfxContentType::ALPHA:
- return SurfaceFormat::A8;
- case gfxContentType::COLOR_ALPHA:
- return SurfaceFormat::A8R8G8B8_UINT32;
- default:
- NS_NOTREACHED("unknown gfxContentType");
- return SurfaceFormat::A8R8G8B8_UINT32;
- }
- }
- /**
- * There are a number of layers acceleration (or layers in general) preferences
- * that should be consistent for the lifetime of the application (bug 840967).
- * As such, we will evaluate them all as soon as one of them is evaluated
- * and remember the values. Changing these preferences during the run will
- * not have any effect until we restart.
- */
- static mozilla::Atomic<bool> sLayersSupportsHardwareVideoDecoding(false);
- static bool sLayersHardwareVideoDecodingFailed = false;
- static bool sBufferRotationCheckPref = true;
- static mozilla::Atomic<bool> sLayersAccelerationPrefsInitialized(false);
- void VideoDecodingFailedChangedCallback(const char* aPref, void*)
- {
- sLayersHardwareVideoDecodingFailed = Preferences::GetBool(aPref, false);
- gfxPlatform::GetPlatform()->UpdateCanUseHardwareVideoDecoding();
- }
- void
- gfxPlatform::UpdateCanUseHardwareVideoDecoding()
- {
- if (XRE_IsParentProcess()) {
- gfxVars::SetCanUseHardwareVideoDecoding(CanUseHardwareVideoDecoding());
- }
- }
- void
- gfxPlatform::InitAcceleration()
- {
- if (sLayersAccelerationPrefsInitialized) {
- return;
- }
- InitCompositorAccelerationPrefs();
- // If this is called for the first time on a non-main thread, we're screwed.
- // At the moment there's no explicit guarantee that the main thread calls
- // this before the compositor thread, but let's at least make the assumption
- // explicit.
- MOZ_ASSERT(NS_IsMainThread(), "can only initialize prefs on the main thread");
- gfxPrefs::GetSingleton();
- if (XRE_IsParentProcess()) {
- gfxVars::SetBrowserTabsRemoteAutostart(BrowserTabsRemoteAutostart());
- gfxVars::SetOffscreenFormat(GetOffscreenFormat());
- gfxVars::SetRequiresAcceleratedGLContextForCompositorOGL(
- RequiresAcceleratedGLContextForCompositorOGL());
- }
- nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
- nsCString discardFailureId;
- int32_t status;
- if (Preferences::GetBool("media.hardware-video-decoding.enabled", false) &&
- #ifdef XP_WIN
- Preferences::GetBool("media.windows-media-foundation.use-dxva", true) &&
- #endif
- NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_HARDWARE_VIDEO_DECODING,
- discardFailureId, &status))) {
- if (status == nsIGfxInfo::FEATURE_STATUS_OK || gfxPrefs::HardwareVideoDecodingForceEnabled()) {
- sLayersSupportsHardwareVideoDecoding = true;
- }
- }
- sLayersAccelerationPrefsInitialized = true;
- if (XRE_IsParentProcess()) {
- Preferences::RegisterCallbackAndCall(VideoDecodingFailedChangedCallback,
- "media.hardware-video-decoding.failed",
- nullptr,
- Preferences::ExactMatch);
- InitGPUProcessPrefs();
- }
- }
- void
- gfxPlatform::InitGPUProcessPrefs()
- {
- // We want to hide this from about:support, so only set a default if the
- // pref is known to be true.
- if (!gfxPrefs::GPUProcessDevEnabled() && !gfxPrefs::GPUProcessDevForceEnabled()) {
- return;
- }
- FeatureState& gpuProc = gfxConfig::GetFeature(Feature::GPU_PROCESS);
- gpuProc.SetDefaultFromPref(
- gfxPrefs::GetGPUProcessDevEnabledPrefName(),
- true,
- gfxPrefs::GetGPUProcessDevEnabledPrefDefault());
- if (gfxPrefs::GPUProcessDevForceEnabled()) {
- gpuProc.UserForceEnable("User force-enabled via pref");
- }
- // We require E10S - otherwise, there is very little benefit to the GPU
- // process, since the UI process must still use acceleration for
- // performance.
- if (!BrowserTabsRemoteAutostart()) {
- gpuProc.ForceDisable(
- FeatureStatus::Unavailable,
- "Multi-process mode is not enabled",
- NS_LITERAL_CSTRING("FEATURE_FAILURE_NO_E10S"));
- return;
- }
- if (InSafeMode()) {
- gpuProc.ForceDisable(
- FeatureStatus::Blocked,
- "Safe-mode is enabled",
- NS_LITERAL_CSTRING("FEATURE_FAILURE_SAFE_MODE"));
- return;
- }
- if (gfxPrefs::LayerScopeEnabled()) {
- gpuProc.ForceDisable(
- FeatureStatus::Blocked,
- "LayerScope does not work in the GPU process",
- NS_LITERAL_CSTRING("FEATURE_FAILURE_LAYERSCOPE"));
- return;
- }
- }
- void
- gfxPlatform::InitCompositorAccelerationPrefs()
- {
- const char *acceleratedEnv = PR_GetEnv("MOZ_ACCELERATED");
- FeatureState& feature = gfxConfig::GetFeature(Feature::HW_COMPOSITING);
- // Base value - does the platform allow acceleration?
- if (feature.SetDefault(AccelerateLayersByDefault(),
- FeatureStatus::Blocked,
- "Acceleration blocked by platform"))
- {
- if (!gfxPrefs::LayersAccelerationEnabledDoNotUseDirectly()) {
- feature.UserDisable("Disabled by pref",
- NS_LITERAL_CSTRING("FEATURE_FAILURE_COMP_PREF"));
- } else if (acceleratedEnv && *acceleratedEnv == '0') {
- feature.UserDisable("Disabled by envvar",
- NS_LITERAL_CSTRING("FEATURE_FAILURE_COMP_ENV"));
- }
- } else {
- if (acceleratedEnv && *acceleratedEnv == '1') {
- feature.UserEnable("Enabled by envvar");
- }
- }
- // This has specific meaning elsewhere, so we always record it.
- if (gfxPrefs::LayersAccelerationEnabledDoNotUseDirectly() &&
- gfxPrefs::LayersAccelerationForceEnabledDoNotUseDirectly()) {
- feature.UserForceEnable("Force-enabled by prefs");
- }
- // Safe mode trumps everything.
- if (InSafeMode()) {
- feature.ForceDisable(FeatureStatus::Blocked, "Acceleration blocked by safe-mode",
- NS_LITERAL_CSTRING("FEATURE_FAILURE_COMP_SAFEMODE"));
- }
- }
- bool
- gfxPlatform::CanUseHardwareVideoDecoding()
- {
- // this function is called from the compositor thread, so it is not
- // safe to init the prefs etc. from here.
- MOZ_ASSERT(sLayersAccelerationPrefsInitialized);
- return sLayersSupportsHardwareVideoDecoding && !sLayersHardwareVideoDecodingFailed;
- }
- bool
- gfxPlatform::AccelerateLayersByDefault()
- {
- // Note: add any new platform defines here that should get HWA by default.
- #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_UIKIT)
- return true;
- #elif defined(MOZ_GL_PROVIDER)
- // GL provider manually declared
- return true;
- #else
- return false;
- #endif
- }
- bool
- gfxPlatform::BufferRotationEnabled()
- {
- MutexAutoLock autoLock(*gGfxPlatformPrefsLock);
- return sBufferRotationCheckPref && gfxPrefs::BufferRotationEnabled();
- }
- void
- gfxPlatform::DisableBufferRotation()
- {
- MutexAutoLock autoLock(*gGfxPlatformPrefsLock);
- sBufferRotationCheckPref = false;
- }
- already_AddRefed<ScaledFont>
- gfxPlatform::GetScaledFontForFontWithCairoSkia(DrawTarget* aTarget, gfxFont* aFont)
- {
- NativeFont nativeFont;
- if (aTarget->GetBackendType() == BackendType::CAIRO || aTarget->GetBackendType() == BackendType::SKIA) {
- nativeFont.mType = NativeFontType::CAIRO_FONT_FACE;
- nativeFont.mFont = aFont->GetCairoScaledFont();
- return Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
- }
- return nullptr;
- }
- /* static */ bool
- gfxPlatform::UsesOffMainThreadCompositing()
- {
- if (XRE_GetProcessType() == GeckoProcessType_GPU) {
- return true;
- }
- static bool firstTime = true;
- static bool result = false;
- if (firstTime) {
- MOZ_ASSERT(sLayersAccelerationPrefsInitialized);
- result =
- gfxVars::BrowserTabsRemoteAutostart() ||
- !gfxPrefs::LayersOffMainThreadCompositionForceDisabled();
- #if defined(MOZ_WIDGET_GTK)
- // Linux users who chose OpenGL are being grandfathered in to OMTC
- result |= gfxPrefs::LayersAccelerationForceEnabledDoNotUseDirectly();
- #endif
- firstTime = false;
- }
- return result;
- }
- /***
- * The preference "layout.frame_rate" has 3 meanings depending on the value:
- *
- * -1 = Auto (default), use hardware vsync or software vsync @ 60 hz if hw vsync fails.
- * 0 = ASAP mode - used during talos testing.
- * X = Software vsync at a rate of X times per second.
- */
- already_AddRefed<mozilla::gfx::VsyncSource>
- gfxPlatform::CreateHardwareVsyncSource()
- {
- RefPtr<mozilla::gfx::VsyncSource> softwareVsync = new SoftwareVsyncSource();
- return softwareVsync.forget();
- }
- /* static */ bool
- gfxPlatform::IsInLayoutAsapMode()
- {
- // There are 2 modes of ASAP mode.
- // 1 is that the refresh driver and compositor are in lock step
- // the second is that the compositor goes ASAP and the refresh driver
- // goes at whatever the configurated rate is. This only checks the version
- // talos uses, which is the refresh driver and compositor are in lockstep.
- return gfxPrefs::LayoutFrameRate() == 0;
- }
- /* static */ bool
- gfxPlatform::ForceSoftwareVsync()
- {
- return gfxPrefs::LayoutFrameRate() > 0;
- }
- /* static */ int
- gfxPlatform::GetSoftwareVsyncRate()
- {
- int preferenceRate = gfxPrefs::LayoutFrameRate();
- if (preferenceRate <= 0) {
- return gfxPlatform::GetDefaultFrameRate();
- }
- return preferenceRate;
- }
- /* static */ int
- gfxPlatform::GetDefaultFrameRate()
- {
- return 60;
- }
- void
- gfxPlatform::GetApzSupportInfo(mozilla::widget::InfoObject& aObj)
- {
- if (!gfxPlatform::AsyncPanZoomEnabled()) {
- return;
- }
- if (SupportsApzWheelInput()) {
- aObj.DefineProperty("ApzWheelInput", 1);
- }
- if (SupportsApzTouchInput()) {
- aObj.DefineProperty("ApzTouchInput", 1);
- }
- if (SupportsApzDragInput()) {
- aObj.DefineProperty("ApzDragInput", 1);
- }
- }
- void
- gfxPlatform::GetTilesSupportInfo(mozilla::widget::InfoObject& aObj)
- {
- if (!gfxPrefs::LayersTilesEnabled()) {
- return;
- }
- IntSize tileSize = gfxVars::TileSize();
- aObj.DefineProperty("TileHeight", tileSize.height);
- aObj.DefineProperty("TileWidth", tileSize.width);
- }
- /*static*/ bool
- gfxPlatform::AsyncPanZoomEnabled()
- {
- #if !defined(MOZ_WIDGET_UIKIT)
- // For XUL applications (everything but Firefox on Android) we only want
- // to use APZ when E10S is enabled or when the user explicitly enable it.
- if (BrowserTabsRemoteAutostart() || gfxPrefs::APZDesktopEnabled()) {
- return gfxPrefs::AsyncPanZoomEnabledDoNotUseDirectly();
- } else {
- return false;
- }
- #else
- return gfxPrefs::AsyncPanZoomEnabledDoNotUseDirectly();
- #endif
- }
- /*static*/ bool
- gfxPlatform::PerfWarnings()
- {
- return gfxPrefs::PerfWarnings();
- }
- void
- gfxPlatform::GetAcceleratedCompositorBackends(nsTArray<LayersBackend>& aBackends)
- {
- if (gfxConfig::IsEnabled(Feature::OPENGL_COMPOSITING)) {
- aBackends.AppendElement(LayersBackend::LAYERS_OPENGL);
- }
- else {
- static int tell_me_once = 0;
- if (!tell_me_once) {
- NS_WARNING("OpenGL-accelerated layers are not supported on this system");
- tell_me_once = 1;
- }
- }
- }
- void
- gfxPlatform::GetCompositorBackends(bool useAcceleration, nsTArray<mozilla::layers::LayersBackend>& aBackends)
- {
- if (useAcceleration) {
- GetAcceleratedCompositorBackends(aBackends);
- }
- aBackends.AppendElement(LayersBackend::LAYERS_BASIC);
- }
- void
- gfxPlatform::NotifyCompositorCreated(LayersBackend aBackend)
- {
- if (mCompositorBackend == aBackend) {
- return;
- }
- if (mCompositorBackend != LayersBackend::LAYERS_NONE) {
- gfxCriticalNote << "Compositors might be mixed ("
- << int(mCompositorBackend) << "," << int(aBackend) << ")";
- }
- // Set the backend before we notify so it's available immediately.
- mCompositorBackend = aBackend;
- }
- void
- gfxPlatform::FetchAndImportContentDeviceData()
- {
- MOZ_ASSERT(XRE_IsContentProcess());
- mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton();
- mozilla::gfx::ContentDeviceData data;
- cc->SendGetGraphicsDeviceInitData(&data);
- ImportContentDeviceData(data);
- }
- void
- gfxPlatform::ImportContentDeviceData(const mozilla::gfx::ContentDeviceData& aData)
- {
- MOZ_ASSERT(XRE_IsContentProcess());
- const DevicePrefs& prefs = aData.prefs();
- gfxConfig::Inherit(Feature::HW_COMPOSITING, prefs.hwCompositing());
- gfxConfig::Inherit(Feature::OPENGL_COMPOSITING, prefs.oglCompositing());
- }
- void
- gfxPlatform::BuildContentDeviceData(mozilla::gfx::ContentDeviceData* aOut)
- {
- MOZ_ASSERT(XRE_IsParentProcess());
- // Make sure our settings are synchronized from the GPU process.
- GPUProcessManager::Get()->EnsureGPUReady();
- aOut->prefs().hwCompositing() = gfxConfig::GetValue(Feature::HW_COMPOSITING);
- aOut->prefs().oglCompositing() = gfxConfig::GetValue(Feature::OPENGL_COMPOSITING);
- }
- void
- gfxPlatform::ImportGPUDeviceData(const mozilla::gfx::GPUDeviceData& aData)
- {
- MOZ_ASSERT(XRE_IsParentProcess());
- gfxConfig::ImportChange(Feature::OPENGL_COMPOSITING, aData.oglCompositing());
- }
- bool
- gfxPlatform::SupportsApzDragInput() const
- {
- return gfxPrefs::APZDragEnabled();
- }
- void
- gfxPlatform::BumpDeviceCounter()
- {
- mDeviceCounter++;
- }
- void
- gfxPlatform::InitOpenGLConfig()
- {
- #ifdef XP_WIN
- // Don't enable by default on Windows, since it could show up in about:support even
- // though it'll never get used. Only attempt if user enables the pref
- if (!Preferences::GetBool("layers.prefer-opengl")){
- return;
- }
- #endif
- FeatureState& openGLFeature = gfxConfig::GetFeature(Feature::OPENGL_COMPOSITING);
- // Check to see hw comp supported
- if (!gfxConfig::IsEnabled(Feature::HW_COMPOSITING)) {
- openGLFeature.DisableByDefault(FeatureStatus::Unavailable, "Hardware compositing is disabled",
- NS_LITERAL_CSTRING("FEATURE_FAILURE_OPENGL_NEED_HWCOMP"));
- return;
- }
- #ifdef XP_WIN
- openGLFeature.SetDefaultFromPref(
- gfxPrefs::GetLayersPreferOpenGLPrefName(),
- true,
- gfxPrefs::GetLayersPreferOpenGLPrefDefault());
- #else
- openGLFeature.EnableByDefault();
- #endif
- // When layers acceleration is force-enabled, enable it even for blacklisted
- // devices.
- if (gfxPrefs::LayersAccelerationForceEnabledDoNotUseDirectly()) {
- openGLFeature.UserForceEnable("Force-enabled by pref");
- return;
- }
- nsCString message;
- nsCString failureId;
- if (!IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_OPENGL_LAYERS, &message, failureId)) {
- openGLFeature.Disable(FeatureStatus::Blacklisted, message.get(), failureId);
- }
- }
- bool
- gfxPlatform::IsGfxInfoStatusOkay(int32_t aFeature, nsCString* aOutMessage, nsCString& aFailureId)
- {
- nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
- if (!gfxInfo) {
- return true;
- }
- int32_t status;
- if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(aFeature, aFailureId, &status)) &&
- status != nsIGfxInfo::FEATURE_STATUS_OK)
- {
- aOutMessage->AssignLiteral("#BLOCKLIST_");
- aOutMessage->AppendASCII(aFailureId.get());
- return false;
- }
- return true;
- }
|