gfxPlatform.cpp 74 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478
  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. #include "mozilla/layers/CompositorBridgeChild.h"
  6. #include "mozilla/layers/CompositorThread.h"
  7. #include "mozilla/layers/ImageBridgeChild.h"
  8. #include "mozilla/layers/ISurfaceAllocator.h" // for GfxMemoryImageReporter
  9. #include "mozilla/gfx/gfxVars.h"
  10. #include "mozilla/gfx/GPUProcessManager.h"
  11. #include "mozilla/gfx/GraphicsMessages.h"
  12. #include "mozilla/ClearOnShutdown.h"
  13. #include "mozilla/TimeStamp.h"
  14. #include "mozilla/Unused.h"
  15. #include "mozilla/Logging.h"
  16. #include "mozilla/Services.h"
  17. #include "gfxPlatform.h"
  18. #include "gfxPrefs.h"
  19. #include "gfxEnv.h"
  20. #include "gfxTextRun.h"
  21. #include "gfxConfig.h"
  22. #include "MediaPrefs.h"
  23. #ifdef XP_WIN
  24. #include <process.h>
  25. #define getpid _getpid
  26. #else
  27. #include <unistd.h>
  28. #endif
  29. #include "nsXULAppAPI.h"
  30. #include "nsDirectoryServiceUtils.h"
  31. #include "nsDirectoryServiceDefs.h"
  32. #if defined(XP_WIN)
  33. #include "gfxWindowsPlatform.h"
  34. #elif defined(MOZ_WIDGET_GTK)
  35. #include "gfxPlatformGtk.h"
  36. #elif defined(ANDROID)
  37. #include "gfxAndroidPlatform.h"
  38. #endif
  39. #ifdef XP_WIN
  40. #include "mozilla/WindowsVersion.h"
  41. #endif
  42. #include "nsGkAtoms.h"
  43. #include "gfxPlatformFontList.h"
  44. #include "gfxContext.h"
  45. #include "gfxImageSurface.h"
  46. #include "nsUnicodeProperties.h"
  47. #include "harfbuzz/hb.h"
  48. #include "gfxGraphiteShaper.h"
  49. #include "gfx2DGlue.h"
  50. #include "gfxGradientCache.h"
  51. #include "gfxUtils.h" // for NextPowerOfTwo
  52. #include "nsUnicodeRange.h"
  53. #include "nsServiceManagerUtils.h"
  54. #include "nsTArray.h"
  55. #include "nsILocaleService.h"
  56. #include "nsIObserverService.h"
  57. #include "nsIScreenManager.h"
  58. #include "FrameMetrics.h"
  59. #include "MainThreadUtils.h"
  60. #include "nsWeakReference.h"
  61. #include "cairo.h"
  62. #include "qcms.h"
  63. #include "imgITools.h"
  64. #include "plstr.h"
  65. #include "nsCRT.h"
  66. #include "GLContext.h"
  67. #include "GLContextProvider.h"
  68. #include "mozilla/gfx/Logging.h"
  69. #if defined(MOZ_WIDGET_GTK)
  70. #include "gfxPlatformGtk.h" // xxx - for UseFcFontList
  71. #endif
  72. #ifdef USE_SKIA
  73. # ifdef __GNUC__
  74. # pragma GCC diagnostic push
  75. # pragma GCC diagnostic ignored "-Wshadow"
  76. # endif
  77. # include "skia/include/core/SkGraphics.h"
  78. # ifdef USE_SKIA_GPU
  79. # include "skia/include/gpu/GrContext.h"
  80. # include "skia/include/gpu/gl/GrGLInterface.h"
  81. # include "SkiaGLGlue.h"
  82. # endif
  83. # ifdef MOZ_ENABLE_FREETYPE
  84. # include "skia/include/ports/SkTypeface_cairo.h"
  85. # endif
  86. # ifdef __GNUC__
  87. # pragma GCC diagnostic pop // -Wshadow
  88. # endif
  89. static const uint32_t kDefaultGlyphCacheSize = -1;
  90. #endif
  91. #if !defined(USE_SKIA) || !defined(USE_SKIA_GPU)
  92. class mozilla::gl::SkiaGLGlue : public GenericAtomicRefCounted {
  93. };
  94. #endif
  95. #include "mozilla/Preferences.h"
  96. #include "mozilla/Assertions.h"
  97. #include "mozilla/Atomics.h"
  98. #include "mozilla/Attributes.h"
  99. #include "mozilla/Mutex.h"
  100. #include "nsAlgorithm.h"
  101. #include "nsIGfxInfo.h"
  102. #include "nsIXULRuntime.h"
  103. #include "VsyncSource.h"
  104. #include "SoftwareVsyncSource.h"
  105. #include "nscore.h" // for NS_FREE_PERMANENT_DATA
  106. #include "mozilla/dom/ContentChild.h"
  107. #include "mozilla/gfx/GPUParent.h"
  108. #include "prsystem.h"
  109. namespace mozilla {
  110. namespace layers {
  111. void ShutdownTileCache();
  112. } // namespace layers
  113. } // namespace mozilla
  114. using namespace mozilla;
  115. using namespace mozilla::layers;
  116. using namespace mozilla::gl;
  117. using namespace mozilla::gfx;
  118. gfxPlatform *gPlatform = nullptr;
  119. static bool gEverInitialized = false;
  120. static Mutex* gGfxPlatformPrefsLock = nullptr;
  121. // These two may point to the same profile
  122. static qcms_profile *gCMSOutputProfile = nullptr;
  123. static qcms_profile *gCMSsRGBProfile = nullptr;
  124. static bool gCMSRGBTransformFailed = false;
  125. static qcms_transform *gCMSRGBTransform = nullptr;
  126. static qcms_transform *gCMSInverseRGBTransform = nullptr;
  127. static qcms_transform *gCMSRGBATransform = nullptr;
  128. static bool gCMSInitialized = false;
  129. static eCMSMode gCMSMode = eCMSMode_Off;
  130. static void ShutdownCMS();
  131. #include "mozilla/gfx/2D.h"
  132. #include "mozilla/gfx/SourceSurfaceCairo.h"
  133. using namespace mozilla::gfx;
  134. /* Class to listen for pref changes so that chrome code can dynamically
  135. force sRGB as an output profile. See Bug #452125. */
  136. class SRGBOverrideObserver final : public nsIObserver,
  137. public nsSupportsWeakReference
  138. {
  139. ~SRGBOverrideObserver() {}
  140. public:
  141. NS_DECL_ISUPPORTS
  142. NS_DECL_NSIOBSERVER
  143. };
  144. /// This override of the LogForwarder, initially used for the critical graphics
  145. /// errors, is sending the log to the crash annotations as well, but only
  146. /// if the capacity set with the method below is >= 2. We always retain the
  147. /// very first critical message, and the latest capacity-1 messages are
  148. /// rotated through. Note that we don't expect the total number of times
  149. /// this gets called to be large - it is meant for critical errors only.
  150. class CrashStatsLogForwarder: public mozilla::gfx::LogForwarder
  151. {
  152. public:
  153. explicit CrashStatsLogForwarder(const char* aKey);
  154. virtual void Log(const std::string& aString) override;
  155. virtual void CrashAction(LogReason aReason) override;
  156. virtual bool UpdateStringsVector(const std::string& aString) override;
  157. virtual LoggingRecord LoggingRecordCopy() override;
  158. void SetCircularBufferSize(uint32_t aCapacity);
  159. private:
  160. // Helper for the Log()
  161. void UpdateCrashReport();
  162. private:
  163. LoggingRecord mBuffer;
  164. nsCString mCrashCriticalKey;
  165. uint32_t mMaxCapacity;
  166. int32_t mIndex;
  167. Mutex mMutex;
  168. };
  169. CrashStatsLogForwarder::CrashStatsLogForwarder(const char* aKey)
  170. : mBuffer()
  171. , mCrashCriticalKey(aKey)
  172. , mMaxCapacity(0)
  173. , mIndex(-1)
  174. , mMutex("CrashStatsLogForwarder")
  175. {
  176. }
  177. void CrashStatsLogForwarder::SetCircularBufferSize(uint32_t aCapacity)
  178. {
  179. MutexAutoLock lock(mMutex);
  180. mMaxCapacity = aCapacity;
  181. mBuffer.reserve(static_cast<size_t>(aCapacity));
  182. }
  183. LoggingRecord
  184. CrashStatsLogForwarder::LoggingRecordCopy()
  185. {
  186. MutexAutoLock lock(mMutex);
  187. return mBuffer;
  188. }
  189. bool
  190. CrashStatsLogForwarder::UpdateStringsVector(const std::string& aString)
  191. {
  192. // We want at least the first one and the last one. Otherwise, no point.
  193. if (mMaxCapacity < 2) {
  194. return false;
  195. }
  196. mIndex += 1;
  197. MOZ_ASSERT(mIndex >= 0);
  198. // index will count 0, 1, 2, ..., max-1, 1, 2, ..., max-1, 1, 2, ...
  199. int32_t index = mIndex ? (mIndex-1) % (mMaxCapacity-1) + 1 : 0;
  200. MOZ_ASSERT(index >= 0 && index < (int32_t)mMaxCapacity);
  201. MOZ_ASSERT(index <= mIndex && index <= (int32_t)mBuffer.size());
  202. bool ignored;
  203. double tStamp = (TimeStamp::NowLoRes()-TimeStamp::ProcessCreation(ignored)).ToSecondsSigDigits();
  204. // Checking for index >= mBuffer.size(), rather than index == mBuffer.size()
  205. // just out of paranoia, but we know index <= mBuffer.size().
  206. LoggingRecordEntry newEntry(mIndex,aString,tStamp);
  207. if (index >= static_cast<int32_t>(mBuffer.size())) {
  208. mBuffer.push_back(newEntry);
  209. } else {
  210. mBuffer[index] = newEntry;
  211. }
  212. return true;
  213. }
  214. void CrashStatsLogForwarder::UpdateCrashReport()
  215. {
  216. std::stringstream message;
  217. std::string logAnnotation;
  218. switch (XRE_GetProcessType()) {
  219. case GeckoProcessType_Default:
  220. logAnnotation = "|[";
  221. break;
  222. case GeckoProcessType_Content:
  223. logAnnotation = "|[C";
  224. break;
  225. case GeckoProcessType_GPU:
  226. logAnnotation = "|[G";
  227. break;
  228. default:
  229. logAnnotation = "|[X";
  230. break;
  231. }
  232. for (LoggingRecord::iterator it = mBuffer.begin(); it != mBuffer.end(); ++it) {
  233. message << logAnnotation << Get<0>(*it) << "]" << Get<1>(*it) << " (t=" << Get<2>(*it) << ") ";
  234. }
  235. nsresult annotated = NS_ERROR_NOT_IMPLEMENTED;
  236. if (annotated != NS_OK) {
  237. printf("Crash Annotation %s: %s",
  238. mCrashCriticalKey.get(), message.str().c_str());
  239. }
  240. }
  241. class LogForwarderEvent : public Runnable
  242. {
  243. virtual ~LogForwarderEvent() {}
  244. NS_DECL_ISUPPORTS_INHERITED
  245. explicit LogForwarderEvent(const nsCString& aMessage) : mMessage(aMessage) {}
  246. NS_IMETHOD Run() override {
  247. MOZ_ASSERT(NS_IsMainThread() && (XRE_IsContentProcess() || XRE_IsGPUProcess()));
  248. if (XRE_IsContentProcess()) {
  249. dom::ContentChild* cc = dom::ContentChild::GetSingleton();
  250. Unused << cc->SendGraphicsError(mMessage);
  251. } else if (XRE_IsGPUProcess()) {
  252. GPUParent* gp = GPUParent::GetSingleton();
  253. Unused << gp->SendGraphicsError(mMessage);
  254. }
  255. return NS_OK;
  256. }
  257. protected:
  258. nsCString mMessage;
  259. };
  260. NS_IMPL_ISUPPORTS_INHERITED0(LogForwarderEvent, Runnable);
  261. void CrashStatsLogForwarder::Log(const std::string& aString)
  262. {
  263. MutexAutoLock lock(mMutex);
  264. if (UpdateStringsVector(aString)) {
  265. UpdateCrashReport();
  266. }
  267. // Add it to the parent strings
  268. if (!XRE_IsParentProcess()) {
  269. nsCString stringToSend(aString.c_str());
  270. if (NS_IsMainThread()) {
  271. if (XRE_IsContentProcess()) {
  272. dom::ContentChild* cc = dom::ContentChild::GetSingleton();
  273. Unused << cc->SendGraphicsError(stringToSend);
  274. } else if (XRE_IsGPUProcess()) {
  275. GPUParent* gp = GPUParent::GetSingleton();
  276. Unused << gp->SendGraphicsError(stringToSend);
  277. }
  278. } else {
  279. nsCOMPtr<nsIRunnable> r1 = new LogForwarderEvent(stringToSend);
  280. NS_DispatchToMainThread(r1);
  281. }
  282. }
  283. }
  284. void
  285. CrashStatsLogForwarder::CrashAction(LogReason aReason)
  286. {
  287. MOZ_CRASH("GFX_CRASH");
  288. }
  289. NS_IMPL_ISUPPORTS(SRGBOverrideObserver, nsIObserver, nsISupportsWeakReference)
  290. #define GFX_DOWNLOADABLE_FONTS_ENABLED "gfx.downloadable_fonts.enabled"
  291. #define GFX_PREF_FALLBACK_USE_CMAPS "gfx.font_rendering.fallback.always_use_cmaps"
  292. #define GFX_PREF_OPENTYPE_SVG "gfx.font_rendering.opentype_svg.enabled"
  293. #define GFX_PREF_WORD_CACHE_CHARLIMIT "gfx.font_rendering.wordcache.charlimit"
  294. #define GFX_PREF_WORD_CACHE_MAXENTRIES "gfx.font_rendering.wordcache.maxentries"
  295. #define GFX_PREF_GRAPHITE_SHAPING "gfx.font_rendering.graphite.enabled"
  296. #define BIDI_NUMERAL_PREF "bidi.numeral"
  297. #define GFX_PREF_CMS_FORCE_SRGB "gfx.color_management.force_srgb"
  298. NS_IMETHODIMP
  299. SRGBOverrideObserver::Observe(nsISupports *aSubject,
  300. const char *aTopic,
  301. const char16_t* someData)
  302. {
  303. NS_ASSERTION(NS_strcmp(someData,
  304. (u"" GFX_PREF_CMS_FORCE_SRGB)) == 0,
  305. "Restarting CMS on wrong pref!");
  306. ShutdownCMS();
  307. // Update current cms profile.
  308. gfxPlatform::CreateCMSOutputProfile();
  309. return NS_OK;
  310. }
  311. static const char* kObservedPrefs[] = {
  312. "gfx.downloadable_fonts.",
  313. "gfx.font_rendering.",
  314. BIDI_NUMERAL_PREF,
  315. nullptr
  316. };
  317. class FontPrefsObserver final : public nsIObserver
  318. {
  319. ~FontPrefsObserver() {}
  320. public:
  321. NS_DECL_ISUPPORTS
  322. NS_DECL_NSIOBSERVER
  323. };
  324. NS_IMPL_ISUPPORTS(FontPrefsObserver, nsIObserver)
  325. NS_IMETHODIMP
  326. FontPrefsObserver::Observe(nsISupports *aSubject,
  327. const char *aTopic,
  328. const char16_t *someData)
  329. {
  330. if (!someData) {
  331. NS_ERROR("font pref observer code broken");
  332. return NS_ERROR_UNEXPECTED;
  333. }
  334. NS_ASSERTION(gfxPlatform::GetPlatform(), "the singleton instance has gone");
  335. gfxPlatform::GetPlatform()->FontsPrefsChanged(NS_ConvertUTF16toUTF8(someData).get());
  336. return NS_OK;
  337. }
  338. class MemoryPressureObserver final : public nsIObserver
  339. {
  340. ~MemoryPressureObserver() {}
  341. public:
  342. NS_DECL_ISUPPORTS
  343. NS_DECL_NSIOBSERVER
  344. };
  345. NS_IMPL_ISUPPORTS(MemoryPressureObserver, nsIObserver)
  346. NS_IMETHODIMP
  347. MemoryPressureObserver::Observe(nsISupports *aSubject,
  348. const char *aTopic,
  349. const char16_t *someData)
  350. {
  351. NS_ASSERTION(strcmp(aTopic, "memory-pressure") == 0, "unexpected event topic");
  352. Factory::PurgeAllCaches();
  353. gfxGradientCache::PurgeAllCaches();
  354. gfxPlatform::PurgeSkiaFontCache();
  355. gfxPlatform::GetPlatform()->PurgeSkiaGPUCache();
  356. return NS_OK;
  357. }
  358. gfxPlatform::gfxPlatform()
  359. : mAzureCanvasBackendCollector(this, &gfxPlatform::GetAzureBackendInfo)
  360. , mApzSupportCollector(this, &gfxPlatform::GetApzSupportInfo)
  361. , mTilesInfoCollector(this, &gfxPlatform::GetTilesSupportInfo)
  362. , mCompositorBackend(layers::LayersBackend::LAYERS_NONE)
  363. , mScreenDepth(0)
  364. , mDeviceCounter(0)
  365. {
  366. mAllowDownloadableFonts = UNINITIALIZED_VALUE;
  367. mFallbackUsesCmaps = UNINITIALIZED_VALUE;
  368. mWordCacheCharLimit = UNINITIALIZED_VALUE;
  369. mWordCacheMaxEntries = UNINITIALIZED_VALUE;
  370. mGraphiteShapingEnabled = UNINITIALIZED_VALUE;
  371. mOpenTypeSVGEnabled = UNINITIALIZED_VALUE;
  372. mBidiNumeralOption = UNINITIALIZED_VALUE;
  373. mSkiaGlue = nullptr;
  374. uint32_t canvasMask = BackendTypeBit(BackendType::CAIRO);
  375. uint32_t contentMask = BackendTypeBit(BackendType::CAIRO);
  376. #ifdef USE_SKIA
  377. canvasMask |= BackendTypeBit(BackendType::SKIA);
  378. contentMask |= BackendTypeBit(BackendType::SKIA);
  379. #endif
  380. InitBackendPrefs(canvasMask, BackendType::CAIRO,
  381. contentMask, BackendType::CAIRO);
  382. mTotalSystemMemory = PR_GetPhysicalMemorySize();
  383. }
  384. gfxPlatform*
  385. gfxPlatform::GetPlatform()
  386. {
  387. if (!gPlatform) {
  388. Init();
  389. }
  390. return gPlatform;
  391. }
  392. bool
  393. gfxPlatform::Initialized()
  394. {
  395. return !!gPlatform;
  396. }
  397. void RecordingPrefChanged(const char *aPrefName, void *aClosure)
  398. {
  399. if (Preferences::GetBool("gfx.2d.recording", false)) {
  400. nsAutoCString fileName;
  401. nsAdoptingString prefFileName = Preferences::GetString("gfx.2d.recordingfile");
  402. if (prefFileName) {
  403. fileName.Append(NS_ConvertUTF16toUTF8(prefFileName));
  404. } else {
  405. nsCOMPtr<nsIFile> tmpFile;
  406. if (NS_FAILED(NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tmpFile)))) {
  407. return;
  408. }
  409. fileName.AppendPrintf("moz2drec_%i_%i.aer", XRE_GetProcessType(), getpid());
  410. nsresult rv = tmpFile->AppendNative(fileName);
  411. if (NS_FAILED(rv))
  412. return;
  413. rv = tmpFile->GetNativePath(fileName);
  414. if (NS_FAILED(rv))
  415. return;
  416. }
  417. gPlatform->mRecorder = Factory::CreateEventRecorderForFile(fileName.BeginReading());
  418. printf_stderr("Recording to %s\n", fileName.get());
  419. Factory::SetGlobalEventRecorder(gPlatform->mRecorder);
  420. } else {
  421. Factory::SetGlobalEventRecorder(nullptr);
  422. }
  423. }
  424. #if defined(USE_SKIA)
  425. static uint32_t GetSkiaGlyphCacheSize()
  426. {
  427. // 10mb as the default cache size on desktop due to talos perf tweaking.
  428. // Chromium uses 20mb and skia default uses 2mb.
  429. // We don't need to change the font cache count since we usually
  430. // cache thrash due to asian character sets in talos.
  431. // Only increase memory on the content proces
  432. uint32_t cacheSize = 10 * 1024 * 1024;
  433. if (mozilla::BrowserTabsRemoteAutostart()) {
  434. return XRE_IsContentProcess() ? cacheSize : kDefaultGlyphCacheSize;
  435. }
  436. return cacheSize;
  437. }
  438. #endif
  439. void
  440. gfxPlatform::Init()
  441. {
  442. MOZ_RELEASE_ASSERT(!XRE_IsGPUProcess(), "GFX: Not allowed in GPU process.");
  443. MOZ_RELEASE_ASSERT(NS_IsMainThread(), "GFX: Not in main thread.");
  444. if (gEverInitialized) {
  445. NS_RUNTIMEABORT("Already started???");
  446. }
  447. gEverInitialized = true;
  448. // Initialize the preferences by creating the singleton.
  449. gfxPrefs::GetSingleton();
  450. MediaPrefs::GetSingleton();
  451. gfxVars::Initialize();
  452. gfxConfig::Init();
  453. if (XRE_IsParentProcess()) {
  454. GPUProcessManager::Initialize();
  455. if (Preferences::GetBool("media.wmf.skip-blacklist")) {
  456. gfxVars::SetPDMWMFDisableD3D11Dlls(nsCString());
  457. gfxVars::SetPDMWMFDisableD3D9Dlls(nsCString());
  458. } else {
  459. gfxVars::SetPDMWMFDisableD3D11Dlls(Preferences::GetCString("media.wmf.disable-d3d11-for-dlls"));
  460. gfxVars::SetPDMWMFDisableD3D9Dlls(Preferences::GetCString("media.wmf.disable-d3d9-for-dlls"));
  461. }
  462. }
  463. InitMoz2DLogging();
  464. gGfxPlatformPrefsLock = new Mutex("gfxPlatform::gGfxPlatformPrefsLock");
  465. /* Initialize the GfxInfo service.
  466. * Note: we can't call functions on GfxInfo that depend
  467. * on gPlatform until after it has been initialized
  468. * below. GfxInfo initialization annotates our
  469. * crash reports so we want to do it before
  470. * we try to load any drivers and do device detection
  471. * incase that code crashes. See bug #591561. */
  472. nsCOMPtr<nsIGfxInfo> gfxInfo;
  473. /* this currently will only succeed on Windows */
  474. gfxInfo = services::GetGfxInfo();
  475. #if defined(XP_WIN)
  476. gPlatform = new gfxWindowsPlatform;
  477. #elif defined(MOZ_WIDGET_GTK)
  478. gPlatform = new gfxPlatformGtk;
  479. #elif defined(ANDROID)
  480. gPlatform = new gfxAndroidPlatform;
  481. #else
  482. #error "No gfxPlatform implementation available"
  483. #endif
  484. gPlatform->InitAcceleration();
  485. if (gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
  486. GPUProcessManager* gpu = GPUProcessManager::Get();
  487. gpu->LaunchGPUProcess();
  488. }
  489. if (XRE_IsParentProcess()) {
  490. if (gfxPlatform::ForceSoftwareVsync()) {
  491. gPlatform->mVsyncSource = (gPlatform)->gfxPlatform::CreateHardwareVsyncSource();
  492. } else {
  493. gPlatform->mVsyncSource = gPlatform->CreateHardwareVsyncSource();
  494. }
  495. }
  496. #ifdef USE_SKIA
  497. SkGraphics::Init();
  498. # ifdef MOZ_ENABLE_FREETYPE
  499. SkInitCairoFT(gPlatform->FontHintingEnabled());
  500. # endif
  501. #endif
  502. #ifdef MOZ_GL_DEBUG
  503. GLContext::StaticInit();
  504. #endif
  505. InitLayersIPC();
  506. gPlatform->PopulateScreenInfo();
  507. gPlatform->ComputeTileSize();
  508. nsresult rv;
  509. bool usePlatformFontList = true;
  510. #if defined(MOZ_WIDGET_GTK)
  511. usePlatformFontList = gfxPlatformGtk::UseFcFontList();
  512. #endif
  513. if (usePlatformFontList) {
  514. rv = gfxPlatformFontList::Init();
  515. if (NS_FAILED(rv)) {
  516. NS_RUNTIMEABORT("Could not initialize gfxPlatformFontList");
  517. }
  518. }
  519. gPlatform->mScreenReferenceSurface =
  520. gPlatform->CreateOffscreenSurface(IntSize(1, 1),
  521. SurfaceFormat::A8R8G8B8_UINT32);
  522. if (!gPlatform->mScreenReferenceSurface) {
  523. NS_RUNTIMEABORT("Could not initialize mScreenReferenceSurface");
  524. }
  525. gPlatform->mScreenReferenceDrawTarget =
  526. gPlatform->CreateOffscreenContentDrawTarget(IntSize(1, 1),
  527. SurfaceFormat::B8G8R8A8);
  528. if (!gPlatform->mScreenReferenceDrawTarget ||
  529. !gPlatform->mScreenReferenceDrawTarget->IsValid()) {
  530. NS_RUNTIMEABORT("Could not initialize mScreenReferenceDrawTarget");
  531. }
  532. rv = gfxFontCache::Init();
  533. if (NS_FAILED(rv)) {
  534. NS_RUNTIMEABORT("Could not initialize gfxFontCache");
  535. }
  536. /* Create and register our CMS Override observer. */
  537. gPlatform->mSRGBOverrideObserver = new SRGBOverrideObserver();
  538. Preferences::AddWeakObserver(gPlatform->mSRGBOverrideObserver, GFX_PREF_CMS_FORCE_SRGB);
  539. gPlatform->mFontPrefsObserver = new FontPrefsObserver();
  540. Preferences::AddStrongObservers(gPlatform->mFontPrefsObserver, kObservedPrefs);
  541. GLContext::PlatformStartup();
  542. Preferences::RegisterCallbackAndCall(RecordingPrefChanged, "gfx.2d.recording", nullptr);
  543. CreateCMSOutputProfile();
  544. // Listen to memory pressure event so we can purge DrawTarget caches
  545. nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
  546. if (obs) {
  547. gPlatform->mMemoryPressureObserver = new MemoryPressureObserver();
  548. obs->AddObserver(gPlatform->mMemoryPressureObserver, "memory-pressure", false);
  549. }
  550. // Request the imgITools service, implicitly initializing ImageLib.
  551. nsCOMPtr<imgITools> imgTools = do_GetService("@mozilla.org/image/tools;1");
  552. if (!imgTools) {
  553. NS_RUNTIMEABORT("Could not initialize ImageLib");
  554. }
  555. RegisterStrongMemoryReporter(new GfxMemoryImageReporter());
  556. #ifdef USE_SKIA
  557. uint32_t skiaCacheSize = GetSkiaGlyphCacheSize();
  558. if (skiaCacheSize != kDefaultGlyphCacheSize) {
  559. SkGraphics::SetFontCacheLimit(skiaCacheSize);
  560. }
  561. #endif
  562. InitNullMetadata();
  563. InitOpenGLConfig();
  564. if (obs) {
  565. obs->NotifyObservers(nullptr, "gfx-features-ready", nullptr);
  566. }
  567. }
  568. /* static */ void
  569. gfxPlatform::InitMoz2DLogging()
  570. {
  571. auto fwd = new CrashStatsLogForwarder("GraphicsCriticalError");
  572. fwd->SetCircularBufferSize(gfxPrefs::GfxLoggingCrashLength());
  573. mozilla::gfx::Config cfg;
  574. cfg.mLogForwarder = fwd;
  575. cfg.mMaxTextureSize = gfxPrefs::MaxTextureSize();
  576. cfg.mMaxAllocSize = gfxPrefs::MaxAllocSize();
  577. gfx::Factory::Init(cfg);
  578. }
  579. static bool sLayersIPCIsUp = false;
  580. /* static */ void
  581. gfxPlatform::InitNullMetadata()
  582. {
  583. ScrollMetadata::sNullMetadata = new ScrollMetadata();
  584. ClearOnShutdown(&ScrollMetadata::sNullMetadata);
  585. }
  586. void
  587. gfxPlatform::Shutdown()
  588. {
  589. // In some cases, gPlatform may not be created but Shutdown() called,
  590. // e.g., during xpcshell tests.
  591. if (!gPlatform) {
  592. return;
  593. }
  594. MOZ_ASSERT(!sLayersIPCIsUp);
  595. // These may be called before the corresponding subsystems have actually
  596. // started up. That's OK, they can handle it.
  597. gfxFontCache::Shutdown();
  598. gfxFontGroup::Shutdown();
  599. gfxGradientCache::Shutdown();
  600. gfxAlphaBoxBlur::ShutdownBlurCache();
  601. gfxGraphiteShaper::Shutdown();
  602. gfxPlatformFontList::Shutdown();
  603. ShutdownTileCache();
  604. // Free the various non-null transforms and loaded profiles
  605. ShutdownCMS();
  606. /* Unregister our CMS Override callback. */
  607. NS_ASSERTION(gPlatform->mSRGBOverrideObserver, "mSRGBOverrideObserver has alreay gone");
  608. Preferences::RemoveObserver(gPlatform->mSRGBOverrideObserver, GFX_PREF_CMS_FORCE_SRGB);
  609. gPlatform->mSRGBOverrideObserver = nullptr;
  610. NS_ASSERTION(gPlatform->mFontPrefsObserver, "mFontPrefsObserver has alreay gone");
  611. Preferences::RemoveObservers(gPlatform->mFontPrefsObserver, kObservedPrefs);
  612. gPlatform->mFontPrefsObserver = nullptr;
  613. NS_ASSERTION(gPlatform->mMemoryPressureObserver, "mMemoryPressureObserver has already gone");
  614. nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
  615. if (obs) {
  616. obs->RemoveObserver(gPlatform->mMemoryPressureObserver, "memory-pressure");
  617. }
  618. gPlatform->mMemoryPressureObserver = nullptr;
  619. gPlatform->mSkiaGlue = nullptr;
  620. if (XRE_IsParentProcess()) {
  621. gPlatform->mVsyncSource->Shutdown();
  622. }
  623. gPlatform->mVsyncSource = nullptr;
  624. // Shut down the default GL context provider.
  625. GLContextProvider::Shutdown();
  626. #if defined(XP_WIN)
  627. // The above shutdown calls operate on the available context providers on
  628. // most platforms. Windows is a "special snowflake", though, and has three
  629. // context providers available, so we have to shut all of them down.
  630. // We should only support the default GL provider on Windows; then, this
  631. // could go away. Unfortunately, we currently support WGL (the default) for
  632. // WebGL on Optimus.
  633. GLContextProviderEGL::Shutdown();
  634. #endif
  635. if (XRE_IsParentProcess()) {
  636. GPUProcessManager::Shutdown();
  637. }
  638. gfx::Factory::ShutDown();
  639. delete gGfxPlatformPrefsLock;
  640. gfxVars::Shutdown();
  641. gfxPrefs::DestroySingleton();
  642. gfxFont::DestroySingletons();
  643. gfxConfig::Shutdown();
  644. gPlatform->WillShutdown();
  645. delete gPlatform;
  646. gPlatform = nullptr;
  647. }
  648. /* static */ void
  649. gfxPlatform::InitLayersIPC()
  650. {
  651. if (sLayersIPCIsUp) {
  652. return;
  653. }
  654. sLayersIPCIsUp = true;
  655. if (XRE_IsParentProcess())
  656. {
  657. layers::CompositorThreadHolder::Start();
  658. }
  659. }
  660. /* static */ void
  661. gfxPlatform::ShutdownLayersIPC()
  662. {
  663. if (!sLayersIPCIsUp) {
  664. return;
  665. }
  666. sLayersIPCIsUp = false;
  667. if (XRE_IsContentProcess()) {
  668. // cf bug 1215265.
  669. if (gfxPrefs::ChildProcessShutdown()) {
  670. layers::CompositorBridgeChild::ShutDown();
  671. layers::ImageBridgeChild::ShutDown();
  672. }
  673. } else if (XRE_IsParentProcess()) {
  674. layers::CompositorBridgeChild::ShutDown();
  675. layers::ImageBridgeChild::ShutDown();
  676. // This has to happen after shutting down the child protocols.
  677. layers::CompositorThreadHolder::Shutdown();
  678. } else {
  679. // TODO: There are other kind of processes and we should make sure gfx
  680. // stuff is either not created there or shut down properly.
  681. }
  682. }
  683. void
  684. gfxPlatform::WillShutdown()
  685. {
  686. // Destoy these first in case they depend on backend-specific resources.
  687. // Otherwise, the backend's destructor would be called before the
  688. // base gfxPlatform destructor.
  689. mScreenReferenceSurface = nullptr;
  690. mScreenReferenceDrawTarget = nullptr;
  691. }
  692. gfxPlatform::~gfxPlatform()
  693. {
  694. // The cairo folks think we should only clean up in debug builds,
  695. // but we're generally in the habit of trying to shut down as
  696. // cleanly as possible even in production code, so call this
  697. // cairo_debug_* function unconditionally.
  698. //
  699. // because cairo can assert and thus crash on shutdown, don't do this in release builds
  700. #ifdef NS_FREE_PERMANENT_DATA
  701. #ifdef USE_SKIA
  702. // must do Skia cleanup before Cairo cleanup, because Skia may be referencing
  703. // Cairo objects e.g. through SkCairoFTTypeface
  704. SkGraphics::PurgeFontCache();
  705. #endif
  706. #if MOZ_TREE_CAIRO
  707. cairo_debug_reset_static_data();
  708. #endif
  709. #endif
  710. }
  711. /* static */ already_AddRefed<DrawTarget>
  712. gfxPlatform::CreateDrawTargetForSurface(gfxASurface *aSurface, const IntSize& aSize)
  713. {
  714. SurfaceFormat format = aSurface->GetSurfaceFormat();
  715. RefPtr<DrawTarget> drawTarget = Factory::CreateDrawTargetForCairoSurface(aSurface->CairoSurface(), aSize, &format);
  716. if (!drawTarget) {
  717. gfxWarning() << "gfxPlatform::CreateDrawTargetForSurface failed in CreateDrawTargetForCairoSurface";
  718. return nullptr;
  719. }
  720. return drawTarget.forget();
  721. }
  722. cairo_user_data_key_t kSourceSurface;
  723. /**
  724. * Record the backend that was used to construct the SourceSurface.
  725. * When getting the cached SourceSurface for a gfxASurface/DrawTarget pair,
  726. * we check to make sure the DrawTarget's backend matches the backend
  727. * for the cached SourceSurface, and only use it if they match. This
  728. * can avoid expensive and unnecessary readbacks.
  729. */
  730. struct SourceSurfaceUserData
  731. {
  732. RefPtr<SourceSurface> mSrcSurface;
  733. BackendType mBackendType;
  734. };
  735. void SourceBufferDestroy(void *srcSurfUD)
  736. {
  737. delete static_cast<SourceSurfaceUserData*>(srcSurfUD);
  738. }
  739. UserDataKey kThebesSurface;
  740. struct DependentSourceSurfaceUserData
  741. {
  742. RefPtr<gfxASurface> mSurface;
  743. };
  744. void SourceSurfaceDestroyed(void *aData)
  745. {
  746. delete static_cast<DependentSourceSurfaceUserData*>(aData);
  747. }
  748. void
  749. gfxPlatform::ClearSourceSurfaceForSurface(gfxASurface *aSurface)
  750. {
  751. aSurface->SetData(&kSourceSurface, nullptr, nullptr);
  752. }
  753. /* static */ already_AddRefed<SourceSurface>
  754. gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget,
  755. gfxASurface *aSurface,
  756. bool aIsPlugin)
  757. {
  758. if (!aSurface->CairoSurface() || aSurface->CairoStatus()) {
  759. return nullptr;
  760. }
  761. if (!aTarget) {
  762. aTarget = gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
  763. }
  764. void *userData = aSurface->GetData(&kSourceSurface);
  765. if (userData) {
  766. SourceSurfaceUserData *surf = static_cast<SourceSurfaceUserData*>(userData);
  767. if (surf->mSrcSurface->IsValid() && surf->mBackendType == aTarget->GetBackendType()) {
  768. RefPtr<SourceSurface> srcSurface(surf->mSrcSurface);
  769. return srcSurface.forget();
  770. }
  771. // We can just continue here as when setting new user data the destroy
  772. // function will be called for the old user data.
  773. }
  774. SurfaceFormat format = aSurface->GetSurfaceFormat();
  775. if (aTarget->GetBackendType() == BackendType::CAIRO) {
  776. // If we're going to be used with a CAIRO DrawTarget, then just create a
  777. // SourceSurfaceCairo since we don't know the underlying type of the CAIRO
  778. // DrawTarget and can't pick a better surface type. Doing this also avoids
  779. // readback of aSurface's surface into memory if, for example, aSurface
  780. // wraps an xlib cairo surface (which can be important to avoid a major
  781. // slowdown).
  782. //
  783. // We return here regardless of whether CreateSourceSurfaceFromNativeSurface
  784. // succeeds or not since we don't expect to be able to do any better below
  785. // if it fails.
  786. //
  787. // Note that the returned SourceSurfaceCairo holds a strong reference to
  788. // the cairo_surface_t* that it wraps, which essencially means it holds a
  789. // strong reference to aSurface since aSurface shares its
  790. // cairo_surface_t*'s reference count variable. As a result we can't cache
  791. // srcBuffer on aSurface (see below) since aSurface would then hold a
  792. // strong reference back to srcBuffer, creating a reference loop and a
  793. // memory leak. Not caching is fine since wrapping is cheap enough (no
  794. // copying) so we can just wrap again next time we're called.
  795. return Factory::CreateSourceSurfaceForCairoSurface(aSurface->CairoSurface(),
  796. aSurface->GetSize(), format);
  797. }
  798. RefPtr<SourceSurface> srcBuffer;
  799. // Currently no other DrawTarget types implement CreateSourceSurfaceFromNativeSurface
  800. if (!srcBuffer) {
  801. // If aSurface wraps data, we can create a SourceSurfaceRawData that wraps
  802. // the same data, then optimize it for aTarget:
  803. RefPtr<DataSourceSurface> surf = GetWrappedDataSourceSurface(aSurface);
  804. if (surf) {
  805. srcBuffer = aIsPlugin ? aTarget->OptimizeSourceSurfaceForUnknownAlpha(surf)
  806. : aTarget->OptimizeSourceSurface(surf);
  807. if (srcBuffer == surf) {
  808. // GetWrappedDataSourceSurface returns a SourceSurface that holds a
  809. // strong reference to aSurface since it wraps aSurface's data and
  810. // needs it to stay alive. As a result we can't cache srcBuffer on
  811. // aSurface (below) since aSurface would then hold a strong reference
  812. // back to srcBuffer, creating a reference loop and a memory leak. Not
  813. // caching is fine since wrapping is cheap enough (no copying) so we
  814. // can just wrap again next time we're called.
  815. //
  816. // Note that the check below doesn't catch this since srcBuffer will be a
  817. // SourceSurfaceRawData object (even if aSurface is not a gfxImageSurface
  818. // object), which is why we need this separate check.
  819. return srcBuffer.forget();
  820. }
  821. }
  822. }
  823. if (!srcBuffer) {
  824. MOZ_ASSERT(aTarget->GetBackendType() != BackendType::CAIRO,
  825. "We already tried CreateSourceSurfaceFromNativeSurface with a "
  826. "DrawTargetCairo above");
  827. // We've run out of performant options. We now try creating a SourceSurface
  828. // using a temporary DrawTargetCairo and then optimizing it to aTarget's
  829. // actual type. The CreateSourceSurfaceFromNativeSurface() call will
  830. // likely create a DataSourceSurface (possibly involving copying and/or
  831. // readback), and the OptimizeSourceSurface may well copy again and upload
  832. // to the GPU. So, while this code path is rarely hit, hitting it may be
  833. // very slow.
  834. srcBuffer = Factory::CreateSourceSurfaceForCairoSurface(aSurface->CairoSurface(),
  835. aSurface->GetSize(), format);
  836. if (srcBuffer) {
  837. srcBuffer = aTarget->OptimizeSourceSurface(srcBuffer);
  838. }
  839. }
  840. if (!srcBuffer) {
  841. return nullptr;
  842. }
  843. if ((srcBuffer->GetType() == SurfaceType::CAIRO &&
  844. static_cast<SourceSurfaceCairo*>(srcBuffer.get())->GetSurface() ==
  845. aSurface->CairoSurface()) ||
  846. (srcBuffer->GetType() == SurfaceType::CAIRO_IMAGE &&
  847. static_cast<DataSourceSurfaceCairo*>(srcBuffer.get())->GetSurface() ==
  848. aSurface->CairoSurface())) {
  849. // See the "Note that the returned SourceSurfaceCairo..." comment above.
  850. return srcBuffer.forget();
  851. }
  852. // Add user data to aSurface so we can cache lookups in the future.
  853. SourceSurfaceUserData *srcSurfUD = new SourceSurfaceUserData;
  854. srcSurfUD->mBackendType = aTarget->GetBackendType();
  855. srcSurfUD->mSrcSurface = srcBuffer;
  856. aSurface->SetData(&kSourceSurface, srcSurfUD, SourceBufferDestroy);
  857. return srcBuffer.forget();
  858. }
  859. already_AddRefed<DataSourceSurface>
  860. gfxPlatform::GetWrappedDataSourceSurface(gfxASurface* aSurface)
  861. {
  862. RefPtr<gfxImageSurface> image = aSurface->GetAsImageSurface();
  863. if (!image) {
  864. return nullptr;
  865. }
  866. RefPtr<DataSourceSurface> result =
  867. Factory::CreateWrappingDataSourceSurface(image->Data(),
  868. image->Stride(),
  869. image->GetSize(),
  870. ImageFormatToSurfaceFormat(image->Format()));
  871. if (!result) {
  872. return nullptr;
  873. }
  874. // If we wrapped the underlying data of aSurface, then we need to add user data
  875. // to make sure aSurface stays alive until we are done with the data.
  876. DependentSourceSurfaceUserData *srcSurfUD = new DependentSourceSurfaceUserData;
  877. srcSurfUD->mSurface = aSurface;
  878. result->AddUserData(&kThebesSurface, srcSurfUD, SourceSurfaceDestroyed);
  879. return result.forget();
  880. }
  881. already_AddRefed<ScaledFont>
  882. gfxPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
  883. {
  884. NativeFont nativeFont;
  885. nativeFont.mType = NativeFontType::CAIRO_FONT_FACE;
  886. nativeFont.mFont = aFont->GetCairoScaledFont();
  887. return Factory::CreateScaledFontForNativeFont(nativeFont,
  888. aFont->GetAdjustedSize());
  889. }
  890. void
  891. gfxPlatform::ComputeTileSize()
  892. {
  893. // The tile size should be picked in the parent processes
  894. // and sent to the child processes over IPDL GetTileSize.
  895. if (!XRE_IsParentProcess()) {
  896. return;
  897. }
  898. int32_t w = gfxPrefs::LayersTileWidth();
  899. int32_t h = gfxPrefs::LayersTileHeight();
  900. if (gfxPrefs::LayersTilesAdjust()) {
  901. gfx::IntSize screenSize = GetScreenSize();
  902. if (screenSize.width > 0) {
  903. // Choose a size so that there are between 2 and 4 tiles per screen width.
  904. // FIXME: we should probably make sure this is within the max texture size,
  905. // but I think everything should at least support 1024
  906. w = h = clamped(int32_t(RoundUpPow2(screenSize.width)) / 4, 256, 1024);
  907. }
  908. }
  909. // Don't allow changing the tile size after we've set it.
  910. // Right now the code assumes that the tile size doesn't change.
  911. MOZ_ASSERT(gfxVars::TileSize().width == -1 &&
  912. gfxVars::TileSize().height == -1);
  913. gfxVars::SetTileSize(IntSize(w, h));
  914. }
  915. void
  916. gfxPlatform::PopulateScreenInfo()
  917. {
  918. nsCOMPtr<nsIScreenManager> manager = do_GetService("@mozilla.org/gfx/screenmanager;1");
  919. MOZ_ASSERT(manager, "failed to get nsIScreenManager");
  920. nsCOMPtr<nsIScreen> screen;
  921. manager->GetPrimaryScreen(getter_AddRefs(screen));
  922. if (!screen) {
  923. // This can happen in xpcshell, for instance
  924. return;
  925. }
  926. screen->GetColorDepth(&mScreenDepth);
  927. int left, top;
  928. screen->GetRect(&left, &top, &mScreenSize.width, &mScreenSize.height);
  929. }
  930. bool
  931. gfxPlatform::SupportsAzureContentForDrawTarget(DrawTarget* aTarget)
  932. {
  933. if (!aTarget || !aTarget->IsValid()) {
  934. return false;
  935. }
  936. #ifdef USE_SKIA_GPU
  937. // Skia content rendering doesn't support GPU acceleration, so we can't
  938. // use the same backend if the current backend is accelerated.
  939. if ((aTarget->GetType() == DrawTargetType::HARDWARE_RASTER)
  940. && (aTarget->GetBackendType() == BackendType::SKIA))
  941. {
  942. return false;
  943. }
  944. #endif
  945. return SupportsAzureContentForType(aTarget->GetBackendType());
  946. }
  947. bool gfxPlatform::AllowOpenGLCanvas()
  948. {
  949. // For now, only allow Skia+OpenGL, unless it's blocked.
  950. // Allow acceleration on Skia if the preference is set, unless it's blocked
  951. // as long as we have the accelerated layers
  952. // The compositor backend is only set correctly in the parent process,
  953. // so we let content process always assume correct compositor backend.
  954. // The callers have to do the right thing.
  955. bool correctBackend = !XRE_IsParentProcess() ||
  956. ((mCompositorBackend == LayersBackend::LAYERS_OPENGL) &&
  957. (GetContentBackendFor(mCompositorBackend) == BackendType::SKIA));
  958. if (gfxPrefs::CanvasAzureAccelerated() && correctBackend) {
  959. nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
  960. int32_t status;
  961. nsCString discardFailureId;
  962. return !gfxInfo ||
  963. (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_CANVAS2D_ACCELERATION,
  964. discardFailureId,
  965. &status)) &&
  966. status == nsIGfxInfo::FEATURE_STATUS_OK);
  967. }
  968. return false;
  969. }
  970. void
  971. gfxPlatform::InitializeSkiaCacheLimits()
  972. {
  973. if (AllowOpenGLCanvas()) {
  974. #ifdef USE_SKIA_GPU
  975. bool usingDynamicCache = gfxPrefs::CanvasSkiaGLDynamicCache();
  976. int cacheItemLimit = gfxPrefs::CanvasSkiaGLCacheItems();
  977. uint64_t cacheSizeLimit = std::max(gfxPrefs::CanvasSkiaGLCacheSize(), (int32_t)0);
  978. // Prefs are in megabytes, but we want the sizes in bytes
  979. cacheSizeLimit *= 1024*1024;
  980. if (usingDynamicCache) {
  981. if (mTotalSystemMemory < 512*1024*1024) {
  982. // We need a very minimal cache on anything smaller than 512mb.
  983. // Note the large jump as we cross 512mb (from 2mb to 32mb).
  984. cacheSizeLimit = 2*1024*1024;
  985. } else if (mTotalSystemMemory > 0) {
  986. cacheSizeLimit = mTotalSystemMemory / 16;
  987. }
  988. }
  989. // Ensure cache size doesn't overflow on 32-bit platforms.
  990. cacheSizeLimit = std::min(cacheSizeLimit, (uint64_t)SIZE_MAX);
  991. #ifdef DEBUG
  992. printf_stderr("Determined SkiaGL cache limits: Size %" PRIu64 ", Items: %i\n", cacheSizeLimit, cacheItemLimit);
  993. #endif
  994. mSkiaGlue->GetGrContext()->setResourceCacheLimits(cacheItemLimit, (size_t)cacheSizeLimit);
  995. #endif
  996. }
  997. }
  998. SkiaGLGlue*
  999. gfxPlatform::GetSkiaGLGlue()
  1000. {
  1001. #ifdef USE_SKIA_GPU
  1002. // Check the accelerated Canvas is enabled for the first time,
  1003. // because the callers should check it before using.
  1004. if (!mSkiaGlue && !AllowOpenGLCanvas()) {
  1005. return nullptr;
  1006. }
  1007. if (!mSkiaGlue) {
  1008. /* Dummy context. We always draw into a FBO.
  1009. *
  1010. * FIXME: This should be stored in TLS or something, since there needs to be one for each thread using it. As it
  1011. * stands, this only works on the main thread.
  1012. */
  1013. RefPtr<GLContext> glContext;
  1014. nsCString discardFailureId;
  1015. glContext = GLContextProvider::CreateHeadless(CreateContextFlags::REQUIRE_COMPAT_PROFILE |
  1016. CreateContextFlags::ALLOW_OFFLINE_RENDERER,
  1017. &discardFailureId);
  1018. if (!glContext) {
  1019. printf_stderr("Failed to create GLContext for SkiaGL!\n");
  1020. return nullptr;
  1021. }
  1022. mSkiaGlue = new SkiaGLGlue(glContext);
  1023. MOZ_ASSERT(mSkiaGlue->GetGrContext(), "No GrContext");
  1024. InitializeSkiaCacheLimits();
  1025. }
  1026. #endif
  1027. return mSkiaGlue;
  1028. }
  1029. void
  1030. gfxPlatform::PurgeSkiaFontCache()
  1031. {
  1032. #ifdef USE_SKIA
  1033. if (gfxPlatform::GetPlatform()->GetDefaultContentBackend() == BackendType::SKIA) {
  1034. SkGraphics::PurgeFontCache();
  1035. }
  1036. #endif
  1037. }
  1038. void
  1039. gfxPlatform::PurgeSkiaGPUCache()
  1040. {
  1041. #ifdef USE_SKIA_GPU
  1042. if (!mSkiaGlue)
  1043. return;
  1044. mSkiaGlue->GetGrContext()->freeGpuResources();
  1045. // GrContext::flush() doesn't call glFlush. Call it here.
  1046. mSkiaGlue->GetGLContext()->MakeCurrent();
  1047. mSkiaGlue->GetGLContext()->fFlush();
  1048. #endif
  1049. }
  1050. bool
  1051. gfxPlatform::HasEnoughTotalSystemMemoryForSkiaGL()
  1052. {
  1053. return true;
  1054. }
  1055. already_AddRefed<DrawTarget>
  1056. gfxPlatform::CreateDrawTargetForBackend(BackendType aBackend, const IntSize& aSize, SurfaceFormat aFormat)
  1057. {
  1058. // There is a bunch of knowledge in the gfxPlatform heirarchy about how to
  1059. // create the best offscreen surface for the current system and situation. We
  1060. // can easily take advantage of this for the Cairo backend, so that's what we
  1061. // do.
  1062. // mozilla::gfx::Factory can get away without having all this knowledge for
  1063. // now, but this might need to change in the future (using
  1064. // CreateOffscreenSurface() and CreateDrawTargetForSurface() for all
  1065. // backends).
  1066. if (aBackend == BackendType::CAIRO) {
  1067. RefPtr<gfxASurface> surf = CreateOffscreenSurface(aSize, SurfaceFormatToImageFormat(aFormat));
  1068. if (!surf || surf->CairoStatus()) {
  1069. return nullptr;
  1070. }
  1071. return CreateDrawTargetForSurface(surf, aSize);
  1072. } else {
  1073. return Factory::CreateDrawTarget(aBackend, aSize, aFormat);
  1074. }
  1075. }
  1076. already_AddRefed<DrawTarget>
  1077. gfxPlatform::CreateOffscreenCanvasDrawTarget(const IntSize& aSize, SurfaceFormat aFormat)
  1078. {
  1079. NS_ASSERTION(mPreferredCanvasBackend != BackendType::NONE, "No backend.");
  1080. RefPtr<DrawTarget> target = CreateDrawTargetForBackend(mPreferredCanvasBackend, aSize, aFormat);
  1081. if (target ||
  1082. mFallbackCanvasBackend == BackendType::NONE) {
  1083. return target.forget();
  1084. }
  1085. #ifdef XP_WIN
  1086. // On Windows, the fallback backend (Cairo) should use its image backend.
  1087. return Factory::CreateDrawTarget(mFallbackCanvasBackend, aSize, aFormat);
  1088. #else
  1089. return CreateDrawTargetForBackend(mFallbackCanvasBackend, aSize, aFormat);
  1090. #endif
  1091. }
  1092. already_AddRefed<DrawTarget>
  1093. gfxPlatform::CreateOffscreenContentDrawTarget(const IntSize& aSize, SurfaceFormat aFormat)
  1094. {
  1095. NS_ASSERTION(mPreferredCanvasBackend != BackendType::NONE, "No backend.");
  1096. return CreateDrawTargetForBackend(mContentBackend, aSize, aFormat);
  1097. }
  1098. already_AddRefed<DrawTarget>
  1099. gfxPlatform::CreateSimilarSoftwareDrawTarget(DrawTarget* aDT,
  1100. const IntSize& aSize,
  1101. SurfaceFormat aFormat)
  1102. {
  1103. RefPtr<DrawTarget> dt;
  1104. if (Factory::DoesBackendSupportDataDrawtarget(aDT->GetBackendType())) {
  1105. dt = aDT->CreateSimilarDrawTarget(aSize, aFormat);
  1106. } else {
  1107. dt = Factory::CreateDrawTarget(BackendType::SKIA, aSize, aFormat);
  1108. }
  1109. return dt.forget();
  1110. }
  1111. /* static */ already_AddRefed<DrawTarget>
  1112. gfxPlatform::CreateDrawTargetForData(unsigned char* aData, const IntSize& aSize, int32_t aStride, SurfaceFormat aFormat)
  1113. {
  1114. BackendType backendType = gfxVars::ContentBackend();
  1115. NS_ASSERTION(backendType != BackendType::NONE, "No backend.");
  1116. if (!Factory::DoesBackendSupportDataDrawtarget(backendType)) {
  1117. backendType = BackendType::CAIRO;
  1118. }
  1119. RefPtr<DrawTarget> dt = Factory::CreateDrawTargetForData(backendType,
  1120. aData, aSize,
  1121. aStride, aFormat);
  1122. return dt.forget();
  1123. }
  1124. /* static */ BackendType
  1125. gfxPlatform::BackendTypeForName(const nsCString& aName)
  1126. {
  1127. if (aName.EqualsLiteral("cairo"))
  1128. return BackendType::CAIRO;
  1129. if (aName.EqualsLiteral("skia"))
  1130. return BackendType::SKIA;
  1131. if (aName.EqualsLiteral("direct2d"))
  1132. return BackendType::DIRECT2D;
  1133. if (aName.EqualsLiteral("direct2d1.1"))
  1134. return BackendType::DIRECT2D1_1;
  1135. return BackendType::NONE;
  1136. }
  1137. nsresult
  1138. gfxPlatform::GetFontList(nsIAtom *aLangGroup,
  1139. const nsACString& aGenericFamily,
  1140. nsTArray<nsString>& aListOfFonts)
  1141. {
  1142. gfxPlatformFontList::PlatformFontList()->GetFontList(aLangGroup,
  1143. aGenericFamily,
  1144. aListOfFonts);
  1145. return NS_OK;
  1146. }
  1147. nsresult
  1148. gfxPlatform::UpdateFontList()
  1149. {
  1150. gfxPlatformFontList::PlatformFontList()->UpdateFontList();
  1151. return NS_OK;
  1152. }
  1153. nsresult
  1154. gfxPlatform::GetStandardFamilyName(const nsAString& aFontName,
  1155. nsAString& aFamilyName)
  1156. {
  1157. gfxPlatformFontList::PlatformFontList()->GetStandardFamilyName(aFontName,
  1158. aFamilyName);
  1159. return NS_OK;
  1160. }
  1161. bool
  1162. gfxPlatform::DownloadableFontsEnabled()
  1163. {
  1164. if (mAllowDownloadableFonts == UNINITIALIZED_VALUE) {
  1165. mAllowDownloadableFonts =
  1166. Preferences::GetBool(GFX_DOWNLOADABLE_FONTS_ENABLED, false);
  1167. }
  1168. return mAllowDownloadableFonts;
  1169. }
  1170. bool
  1171. gfxPlatform::UseCmapsDuringSystemFallback()
  1172. {
  1173. if (mFallbackUsesCmaps == UNINITIALIZED_VALUE) {
  1174. mFallbackUsesCmaps =
  1175. Preferences::GetBool(GFX_PREF_FALLBACK_USE_CMAPS, false);
  1176. }
  1177. return mFallbackUsesCmaps;
  1178. }
  1179. bool
  1180. gfxPlatform::OpenTypeSVGEnabled()
  1181. {
  1182. if (mOpenTypeSVGEnabled == UNINITIALIZED_VALUE) {
  1183. mOpenTypeSVGEnabled =
  1184. Preferences::GetBool(GFX_PREF_OPENTYPE_SVG, false);
  1185. }
  1186. return mOpenTypeSVGEnabled > 0;
  1187. }
  1188. uint32_t
  1189. gfxPlatform::WordCacheCharLimit()
  1190. {
  1191. if (mWordCacheCharLimit == UNINITIALIZED_VALUE) {
  1192. mWordCacheCharLimit =
  1193. Preferences::GetInt(GFX_PREF_WORD_CACHE_CHARLIMIT, 32);
  1194. if (mWordCacheCharLimit < 0) {
  1195. mWordCacheCharLimit = 32;
  1196. }
  1197. }
  1198. return uint32_t(mWordCacheCharLimit);
  1199. }
  1200. uint32_t
  1201. gfxPlatform::WordCacheMaxEntries()
  1202. {
  1203. if (mWordCacheMaxEntries == UNINITIALIZED_VALUE) {
  1204. mWordCacheMaxEntries =
  1205. Preferences::GetInt(GFX_PREF_WORD_CACHE_MAXENTRIES, 10000);
  1206. if (mWordCacheMaxEntries < 0) {
  1207. mWordCacheMaxEntries = 10000;
  1208. }
  1209. }
  1210. return uint32_t(mWordCacheMaxEntries);
  1211. }
  1212. bool
  1213. gfxPlatform::UseGraphiteShaping()
  1214. {
  1215. if (mGraphiteShapingEnabled == UNINITIALIZED_VALUE) {
  1216. mGraphiteShapingEnabled =
  1217. Preferences::GetBool(GFX_PREF_GRAPHITE_SHAPING, false);
  1218. }
  1219. return mGraphiteShapingEnabled;
  1220. }
  1221. gfxFontEntry*
  1222. gfxPlatform::LookupLocalFont(const nsAString& aFontName,
  1223. uint16_t aWeight,
  1224. int16_t aStretch,
  1225. uint8_t aStyle)
  1226. {
  1227. return gfxPlatformFontList::PlatformFontList()->LookupLocalFont(aFontName,
  1228. aWeight,
  1229. aStretch,
  1230. aStyle);
  1231. }
  1232. gfxFontEntry*
  1233. gfxPlatform::MakePlatformFont(const nsAString& aFontName,
  1234. uint16_t aWeight,
  1235. int16_t aStretch,
  1236. uint8_t aStyle,
  1237. const uint8_t* aFontData,
  1238. uint32_t aLength)
  1239. {
  1240. return gfxPlatformFontList::PlatformFontList()->MakePlatformFont(aFontName,
  1241. aWeight,
  1242. aStretch,
  1243. aStyle,
  1244. aFontData,
  1245. aLength);
  1246. }
  1247. mozilla::layers::DiagnosticTypes
  1248. gfxPlatform::GetLayerDiagnosticTypes()
  1249. {
  1250. mozilla::layers::DiagnosticTypes type = DiagnosticTypes::NO_DIAGNOSTIC;
  1251. if (gfxPrefs::DrawLayerBorders()) {
  1252. type |= mozilla::layers::DiagnosticTypes::LAYER_BORDERS;
  1253. }
  1254. if (gfxPrefs::DrawTileBorders()) {
  1255. type |= mozilla::layers::DiagnosticTypes::TILE_BORDERS;
  1256. }
  1257. if (gfxPrefs::DrawBigImageBorders()) {
  1258. type |= mozilla::layers::DiagnosticTypes::BIGIMAGE_BORDERS;
  1259. }
  1260. if (gfxPrefs::FlashLayerBorders()) {
  1261. type |= mozilla::layers::DiagnosticTypes::FLASH_BORDERS;
  1262. }
  1263. return type;
  1264. }
  1265. void
  1266. gfxPlatform::InitBackendPrefs(uint32_t aCanvasBitmask, BackendType aCanvasDefault,
  1267. uint32_t aContentBitmask, BackendType aContentDefault)
  1268. {
  1269. mPreferredCanvasBackend = GetCanvasBackendPref(aCanvasBitmask);
  1270. if (mPreferredCanvasBackend == BackendType::NONE) {
  1271. mPreferredCanvasBackend = aCanvasDefault;
  1272. }
  1273. if (mPreferredCanvasBackend == BackendType::DIRECT2D1_1) {
  1274. // Falling back to D2D 1.0 won't help us here. When D2D 1.1 DT creation
  1275. // fails it means the surface was too big or there's something wrong with
  1276. // the device. D2D 1.0 will encounter a similar situation.
  1277. mFallbackCanvasBackend =
  1278. GetCanvasBackendPref(aCanvasBitmask &
  1279. ~(BackendTypeBit(mPreferredCanvasBackend) | BackendTypeBit(BackendType::DIRECT2D)));
  1280. } else {
  1281. mFallbackCanvasBackend =
  1282. GetCanvasBackendPref(aCanvasBitmask & ~BackendTypeBit(mPreferredCanvasBackend));
  1283. }
  1284. mContentBackendBitmask = aContentBitmask;
  1285. mContentBackend = GetContentBackendPref(mContentBackendBitmask);
  1286. if (mContentBackend == BackendType::NONE) {
  1287. mContentBackend = aContentDefault;
  1288. // mContentBackendBitmask is our canonical reference for supported
  1289. // backends so we need to add the default if we are using it and
  1290. // overriding the prefs.
  1291. mContentBackendBitmask |= BackendTypeBit(aContentDefault);
  1292. }
  1293. if (XRE_IsParentProcess()) {
  1294. gfxVars::SetContentBackend(mContentBackend);
  1295. }
  1296. }
  1297. /* static */ BackendType
  1298. gfxPlatform::GetCanvasBackendPref(uint32_t aBackendBitmask)
  1299. {
  1300. return GetBackendPref("gfx.canvas.azure.backends", aBackendBitmask);
  1301. }
  1302. /* static */ BackendType
  1303. gfxPlatform::GetContentBackendPref(uint32_t &aBackendBitmask)
  1304. {
  1305. return GetBackendPref("gfx.content.azure.backends", aBackendBitmask);
  1306. }
  1307. /* static */ BackendType
  1308. gfxPlatform::GetBackendPref(const char* aBackendPrefName, uint32_t &aBackendBitmask)
  1309. {
  1310. nsTArray<nsCString> backendList;
  1311. nsCString prefString;
  1312. if (NS_SUCCEEDED(Preferences::GetCString(aBackendPrefName, &prefString))) {
  1313. ParseString(prefString, ',', backendList);
  1314. }
  1315. uint32_t allowedBackends = 0;
  1316. BackendType result = BackendType::NONE;
  1317. for (uint32_t i = 0; i < backendList.Length(); ++i) {
  1318. BackendType type = BackendTypeForName(backendList[i]);
  1319. if (BackendTypeBit(type) & aBackendBitmask) {
  1320. allowedBackends |= BackendTypeBit(type);
  1321. if (result == BackendType::NONE) {
  1322. result = type;
  1323. }
  1324. }
  1325. }
  1326. aBackendBitmask = allowedBackends;
  1327. return result;
  1328. }
  1329. bool
  1330. gfxPlatform::InSafeMode()
  1331. {
  1332. static bool sSafeModeInitialized = false;
  1333. static bool sInSafeMode = false;
  1334. if (!sSafeModeInitialized) {
  1335. sSafeModeInitialized = true;
  1336. nsCOMPtr<nsIXULRuntime> xr = do_GetService("@mozilla.org/xre/runtime;1");
  1337. if (xr) {
  1338. xr->GetInSafeMode(&sInSafeMode);
  1339. }
  1340. }
  1341. return sInSafeMode;
  1342. }
  1343. bool
  1344. gfxPlatform::OffMainThreadCompositingEnabled()
  1345. {
  1346. return UsesOffMainThreadCompositing();
  1347. }
  1348. eCMSMode
  1349. gfxPlatform::GetCMSMode()
  1350. {
  1351. if (!gCMSInitialized) {
  1352. int32_t mode = gfxPrefs::CMSMode();
  1353. if (mode >= 0 && mode < eCMSMode_AllCount) {
  1354. gCMSMode = static_cast<eCMSMode>(mode);
  1355. }
  1356. bool enableV4 = gfxPrefs::CMSEnableV4();
  1357. if (enableV4) {
  1358. qcms_enable_iccv4();
  1359. }
  1360. gCMSInitialized = true;
  1361. }
  1362. return gCMSMode;
  1363. }
  1364. int
  1365. gfxPlatform::GetRenderingIntent()
  1366. {
  1367. // gfxPrefs.h is using 0 as the default for the rendering
  1368. // intent preference, based on that being the value for
  1369. // QCMS_INTENT_DEFAULT. Assert here to catch if that ever
  1370. // changes and we can then figure out what to do about it.
  1371. MOZ_ASSERT(QCMS_INTENT_DEFAULT == 0);
  1372. /* Try to query the pref system for a rendering intent. */
  1373. int32_t pIntent = gfxPrefs::CMSRenderingIntent();
  1374. if ((pIntent < QCMS_INTENT_MIN) || (pIntent > QCMS_INTENT_MAX)) {
  1375. /* If the pref is out of range, use embedded profile. */
  1376. pIntent = -1;
  1377. }
  1378. return pIntent;
  1379. }
  1380. void
  1381. gfxPlatform::TransformPixel(const Color& in, Color& out, qcms_transform *transform)
  1382. {
  1383. if (transform) {
  1384. /* we want the bytes in RGB order */
  1385. #ifdef IS_LITTLE_ENDIAN
  1386. /* ABGR puts the bytes in |RGBA| order on little endian */
  1387. uint32_t packed = in.ToABGR();
  1388. qcms_transform_data(transform,
  1389. (uint8_t *)&packed, (uint8_t *)&packed,
  1390. 1);
  1391. out = Color::FromABGR(packed);
  1392. #else
  1393. /* ARGB puts the bytes in |ARGB| order on big endian */
  1394. uint32_t packed = in.UnusualToARGB();
  1395. /* add one to move past the alpha byte */
  1396. qcms_transform_data(transform,
  1397. (uint8_t *)&packed + 1, (uint8_t *)&packed + 1,
  1398. 1);
  1399. out = Color::UnusualFromARGB(packed);
  1400. #endif
  1401. }
  1402. else if (&out != &in)
  1403. out = in;
  1404. }
  1405. void
  1406. gfxPlatform::GetPlatformCMSOutputProfile(void *&mem, size_t &size)
  1407. {
  1408. mem = nullptr;
  1409. size = 0;
  1410. }
  1411. void
  1412. gfxPlatform::GetCMSOutputProfileData(void *&mem, size_t &size)
  1413. {
  1414. nsAdoptingCString fname = Preferences::GetCString("gfx.color_management.display_profile");
  1415. if (!fname.IsEmpty()) {
  1416. qcms_data_from_path(fname, &mem, &size);
  1417. }
  1418. else {
  1419. gfxPlatform::GetPlatform()->GetPlatformCMSOutputProfile(mem, size);
  1420. }
  1421. }
  1422. void
  1423. gfxPlatform::CreateCMSOutputProfile()
  1424. {
  1425. if (!gCMSOutputProfile) {
  1426. /* Determine if we're using the internal override to force sRGB as
  1427. an output profile for reftests. See Bug 452125.
  1428. Note that we don't normally (outside of tests) set a
  1429. default value of this preference, which means nsIPrefBranch::GetBoolPref
  1430. will typically throw (and leave its out-param untouched).
  1431. */
  1432. if (Preferences::GetBool(GFX_PREF_CMS_FORCE_SRGB, false)) {
  1433. gCMSOutputProfile = GetCMSsRGBProfile();
  1434. }
  1435. if (!gCMSOutputProfile) {
  1436. void* mem = nullptr;
  1437. size_t size = 0;
  1438. GetCMSOutputProfileData(mem, size);
  1439. if ((mem != nullptr) && (size > 0)) {
  1440. gCMSOutputProfile = qcms_profile_from_memory(mem, size);
  1441. free(mem);
  1442. }
  1443. }
  1444. /* Determine if the profile looks bogus. If so, close the profile
  1445. * and use sRGB instead. See bug 460629, */
  1446. if (gCMSOutputProfile && qcms_profile_is_bogus(gCMSOutputProfile)) {
  1447. NS_ASSERTION(gCMSOutputProfile != GetCMSsRGBProfile(),
  1448. "Builtin sRGB profile tagged as bogus!!!");
  1449. qcms_profile_release(gCMSOutputProfile);
  1450. gCMSOutputProfile = nullptr;
  1451. }
  1452. if (!gCMSOutputProfile) {
  1453. gCMSOutputProfile = GetCMSsRGBProfile();
  1454. }
  1455. /* Precache the LUT16 Interpolations for the output profile. See
  1456. bug 444661 for details. */
  1457. qcms_profile_precache_output_transform(gCMSOutputProfile);
  1458. }
  1459. }
  1460. qcms_profile *
  1461. gfxPlatform::GetCMSOutputProfile()
  1462. {
  1463. return gCMSOutputProfile;
  1464. }
  1465. qcms_profile *
  1466. gfxPlatform::GetCMSsRGBProfile()
  1467. {
  1468. if (!gCMSsRGBProfile) {
  1469. /* Create the profile using qcms. */
  1470. gCMSsRGBProfile = qcms_profile_sRGB();
  1471. }
  1472. return gCMSsRGBProfile;
  1473. }
  1474. qcms_transform *
  1475. gfxPlatform::GetCMSRGBTransform()
  1476. {
  1477. if (!gCMSRGBTransform && !gCMSRGBTransformFailed) {
  1478. qcms_profile *inProfile, *outProfile;
  1479. outProfile = GetCMSOutputProfile();
  1480. inProfile = GetCMSsRGBProfile();
  1481. if (!inProfile || !outProfile)
  1482. return nullptr;
  1483. gCMSRGBTransform = qcms_transform_create(inProfile, QCMS_DATA_RGB_8,
  1484. outProfile, QCMS_DATA_RGB_8,
  1485. QCMS_INTENT_PERCEPTUAL);
  1486. if (!gCMSRGBTransform) {
  1487. gCMSRGBTransformFailed = true;
  1488. }
  1489. }
  1490. return gCMSRGBTransform;
  1491. }
  1492. qcms_transform *
  1493. gfxPlatform::GetCMSInverseRGBTransform()
  1494. {
  1495. if (!gCMSInverseRGBTransform) {
  1496. qcms_profile *inProfile, *outProfile;
  1497. inProfile = GetCMSOutputProfile();
  1498. outProfile = GetCMSsRGBProfile();
  1499. if (!inProfile || !outProfile)
  1500. return nullptr;
  1501. gCMSInverseRGBTransform = qcms_transform_create(inProfile, QCMS_DATA_RGB_8,
  1502. outProfile, QCMS_DATA_RGB_8,
  1503. QCMS_INTENT_PERCEPTUAL);
  1504. }
  1505. return gCMSInverseRGBTransform;
  1506. }
  1507. qcms_transform *
  1508. gfxPlatform::GetCMSRGBATransform()
  1509. {
  1510. if (!gCMSRGBATransform) {
  1511. qcms_profile *inProfile, *outProfile;
  1512. outProfile = GetCMSOutputProfile();
  1513. inProfile = GetCMSsRGBProfile();
  1514. if (!inProfile || !outProfile)
  1515. return nullptr;
  1516. gCMSRGBATransform = qcms_transform_create(inProfile, QCMS_DATA_RGBA_8,
  1517. outProfile, QCMS_DATA_RGBA_8,
  1518. QCMS_INTENT_PERCEPTUAL);
  1519. }
  1520. return gCMSRGBATransform;
  1521. }
  1522. /* Shuts down various transforms and profiles for CMS. */
  1523. static void ShutdownCMS()
  1524. {
  1525. if (gCMSRGBTransform) {
  1526. qcms_transform_release(gCMSRGBTransform);
  1527. gCMSRGBTransform = nullptr;
  1528. }
  1529. if (gCMSInverseRGBTransform) {
  1530. qcms_transform_release(gCMSInverseRGBTransform);
  1531. gCMSInverseRGBTransform = nullptr;
  1532. }
  1533. if (gCMSRGBATransform) {
  1534. qcms_transform_release(gCMSRGBATransform);
  1535. gCMSRGBATransform = nullptr;
  1536. }
  1537. if (gCMSOutputProfile) {
  1538. qcms_profile_release(gCMSOutputProfile);
  1539. // handle the aliased case
  1540. if (gCMSsRGBProfile == gCMSOutputProfile)
  1541. gCMSsRGBProfile = nullptr;
  1542. gCMSOutputProfile = nullptr;
  1543. }
  1544. if (gCMSsRGBProfile) {
  1545. qcms_profile_release(gCMSsRGBProfile);
  1546. gCMSsRGBProfile = nullptr;
  1547. }
  1548. // Reset the state variables
  1549. gCMSMode = eCMSMode_Off;
  1550. gCMSInitialized = false;
  1551. }
  1552. // default SetupClusterBoundaries, based on Unicode properties;
  1553. // platform subclasses may override if they wish
  1554. void
  1555. gfxPlatform::SetupClusterBoundaries(gfxTextRun *aTextRun, const char16_t *aString)
  1556. {
  1557. if (aTextRun->GetFlags() & gfxTextRunFactory::TEXT_IS_8BIT) {
  1558. // 8-bit text doesn't have clusters.
  1559. // XXX is this true in all languages???
  1560. // behdad: don't think so. Czech for example IIRC has a
  1561. // 'ch' grapheme.
  1562. // jfkthame: but that's not expected to behave as a grapheme cluster
  1563. // for selection/editing/etc.
  1564. return;
  1565. }
  1566. aTextRun->SetupClusterBoundaries(0, aString, aTextRun->GetLength());
  1567. }
  1568. int32_t
  1569. gfxPlatform::GetBidiNumeralOption()
  1570. {
  1571. if (mBidiNumeralOption == UNINITIALIZED_VALUE) {
  1572. mBidiNumeralOption = Preferences::GetInt(BIDI_NUMERAL_PREF, 0);
  1573. }
  1574. return mBidiNumeralOption;
  1575. }
  1576. /* static */ void
  1577. gfxPlatform::FlushFontAndWordCaches()
  1578. {
  1579. gfxFontCache *fontCache = gfxFontCache::GetCache();
  1580. if (fontCache) {
  1581. fontCache->AgeAllGenerations();
  1582. fontCache->FlushShapedWordCaches();
  1583. }
  1584. gfxPlatform::PurgeSkiaFontCache();
  1585. }
  1586. void
  1587. gfxPlatform::FontsPrefsChanged(const char *aPref)
  1588. {
  1589. NS_ASSERTION(aPref != nullptr, "null preference");
  1590. if (!strcmp(GFX_DOWNLOADABLE_FONTS_ENABLED, aPref)) {
  1591. mAllowDownloadableFonts = UNINITIALIZED_VALUE;
  1592. } else if (!strcmp(GFX_PREF_FALLBACK_USE_CMAPS, aPref)) {
  1593. mFallbackUsesCmaps = UNINITIALIZED_VALUE;
  1594. } else if (!strcmp(GFX_PREF_WORD_CACHE_CHARLIMIT, aPref)) {
  1595. mWordCacheCharLimit = UNINITIALIZED_VALUE;
  1596. FlushFontAndWordCaches();
  1597. } else if (!strcmp(GFX_PREF_WORD_CACHE_MAXENTRIES, aPref)) {
  1598. mWordCacheMaxEntries = UNINITIALIZED_VALUE;
  1599. FlushFontAndWordCaches();
  1600. } else if (!strcmp(GFX_PREF_GRAPHITE_SHAPING, aPref)) {
  1601. mGraphiteShapingEnabled = UNINITIALIZED_VALUE;
  1602. FlushFontAndWordCaches();
  1603. } else if (!strcmp(BIDI_NUMERAL_PREF, aPref)) {
  1604. mBidiNumeralOption = UNINITIALIZED_VALUE;
  1605. } else if (!strcmp(GFX_PREF_OPENTYPE_SVG, aPref)) {
  1606. mOpenTypeSVGEnabled = UNINITIALIZED_VALUE;
  1607. gfxFontCache::GetCache()->AgeAllGenerations();
  1608. }
  1609. }
  1610. mozilla::LogModule*
  1611. gfxPlatform::GetLog(eGfxLog aWhichLog)
  1612. {
  1613. // logs shared across gfx
  1614. static LazyLogModule sFontlistLog("fontlist");
  1615. static LazyLogModule sFontInitLog("fontinit");
  1616. static LazyLogModule sTextrunLog("textrun");
  1617. static LazyLogModule sTextrunuiLog("textrunui");
  1618. static LazyLogModule sCmapDataLog("cmapdata");
  1619. static LazyLogModule sTextPerfLog("textperf");
  1620. switch (aWhichLog) {
  1621. case eGfxLog_fontlist:
  1622. return sFontlistLog;
  1623. case eGfxLog_fontinit:
  1624. return sFontInitLog;
  1625. case eGfxLog_textrun:
  1626. return sTextrunLog;
  1627. case eGfxLog_textrunui:
  1628. return sTextrunuiLog;
  1629. case eGfxLog_cmapdata:
  1630. return sCmapDataLog;
  1631. case eGfxLog_textperf:
  1632. return sTextPerfLog;
  1633. }
  1634. MOZ_ASSERT_UNREACHABLE("Unexpected log type");
  1635. return nullptr;
  1636. }
  1637. mozilla::gfx::SurfaceFormat
  1638. gfxPlatform::Optimal2DFormatForContent(gfxContentType aContent)
  1639. {
  1640. switch (aContent) {
  1641. case gfxContentType::COLOR:
  1642. switch (GetOffscreenFormat()) {
  1643. case SurfaceFormat::A8R8G8B8_UINT32:
  1644. return mozilla::gfx::SurfaceFormat::B8G8R8A8;
  1645. case SurfaceFormat::X8R8G8B8_UINT32:
  1646. return mozilla::gfx::SurfaceFormat::B8G8R8X8;
  1647. case SurfaceFormat::R5G6B5_UINT16:
  1648. return mozilla::gfx::SurfaceFormat::R5G6B5_UINT16;
  1649. default:
  1650. NS_NOTREACHED("unknown gfxImageFormat for gfxContentType::COLOR");
  1651. return mozilla::gfx::SurfaceFormat::B8G8R8A8;
  1652. }
  1653. case gfxContentType::ALPHA:
  1654. return mozilla::gfx::SurfaceFormat::A8;
  1655. case gfxContentType::COLOR_ALPHA:
  1656. return mozilla::gfx::SurfaceFormat::B8G8R8A8;
  1657. default:
  1658. NS_NOTREACHED("unknown gfxContentType");
  1659. return mozilla::gfx::SurfaceFormat::B8G8R8A8;
  1660. }
  1661. }
  1662. gfxImageFormat
  1663. gfxPlatform::OptimalFormatForContent(gfxContentType aContent)
  1664. {
  1665. switch (aContent) {
  1666. case gfxContentType::COLOR:
  1667. return GetOffscreenFormat();
  1668. case gfxContentType::ALPHA:
  1669. return SurfaceFormat::A8;
  1670. case gfxContentType::COLOR_ALPHA:
  1671. return SurfaceFormat::A8R8G8B8_UINT32;
  1672. default:
  1673. NS_NOTREACHED("unknown gfxContentType");
  1674. return SurfaceFormat::A8R8G8B8_UINT32;
  1675. }
  1676. }
  1677. /**
  1678. * There are a number of layers acceleration (or layers in general) preferences
  1679. * that should be consistent for the lifetime of the application (bug 840967).
  1680. * As such, we will evaluate them all as soon as one of them is evaluated
  1681. * and remember the values. Changing these preferences during the run will
  1682. * not have any effect until we restart.
  1683. */
  1684. static mozilla::Atomic<bool> sLayersSupportsHardwareVideoDecoding(false);
  1685. static bool sLayersHardwareVideoDecodingFailed = false;
  1686. static bool sBufferRotationCheckPref = true;
  1687. static mozilla::Atomic<bool> sLayersAccelerationPrefsInitialized(false);
  1688. void VideoDecodingFailedChangedCallback(const char* aPref, void*)
  1689. {
  1690. sLayersHardwareVideoDecodingFailed = Preferences::GetBool(aPref, false);
  1691. gfxPlatform::GetPlatform()->UpdateCanUseHardwareVideoDecoding();
  1692. }
  1693. void
  1694. gfxPlatform::UpdateCanUseHardwareVideoDecoding()
  1695. {
  1696. if (XRE_IsParentProcess()) {
  1697. gfxVars::SetCanUseHardwareVideoDecoding(CanUseHardwareVideoDecoding());
  1698. }
  1699. }
  1700. void
  1701. gfxPlatform::InitAcceleration()
  1702. {
  1703. if (sLayersAccelerationPrefsInitialized) {
  1704. return;
  1705. }
  1706. InitCompositorAccelerationPrefs();
  1707. // If this is called for the first time on a non-main thread, we're screwed.
  1708. // At the moment there's no explicit guarantee that the main thread calls
  1709. // this before the compositor thread, but let's at least make the assumption
  1710. // explicit.
  1711. MOZ_ASSERT(NS_IsMainThread(), "can only initialize prefs on the main thread");
  1712. gfxPrefs::GetSingleton();
  1713. if (XRE_IsParentProcess()) {
  1714. gfxVars::SetBrowserTabsRemoteAutostart(BrowserTabsRemoteAutostart());
  1715. gfxVars::SetOffscreenFormat(GetOffscreenFormat());
  1716. gfxVars::SetRequiresAcceleratedGLContextForCompositorOGL(
  1717. RequiresAcceleratedGLContextForCompositorOGL());
  1718. }
  1719. nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
  1720. nsCString discardFailureId;
  1721. int32_t status;
  1722. if (Preferences::GetBool("media.hardware-video-decoding.enabled", false) &&
  1723. #ifdef XP_WIN
  1724. Preferences::GetBool("media.windows-media-foundation.use-dxva", true) &&
  1725. #endif
  1726. NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_HARDWARE_VIDEO_DECODING,
  1727. discardFailureId, &status))) {
  1728. if (status == nsIGfxInfo::FEATURE_STATUS_OK || gfxPrefs::HardwareVideoDecodingForceEnabled()) {
  1729. sLayersSupportsHardwareVideoDecoding = true;
  1730. }
  1731. }
  1732. sLayersAccelerationPrefsInitialized = true;
  1733. if (XRE_IsParentProcess()) {
  1734. Preferences::RegisterCallbackAndCall(VideoDecodingFailedChangedCallback,
  1735. "media.hardware-video-decoding.failed",
  1736. nullptr,
  1737. Preferences::ExactMatch);
  1738. InitGPUProcessPrefs();
  1739. }
  1740. }
  1741. void
  1742. gfxPlatform::InitGPUProcessPrefs()
  1743. {
  1744. // We want to hide this from about:support, so only set a default if the
  1745. // pref is known to be true.
  1746. if (!gfxPrefs::GPUProcessDevEnabled() && !gfxPrefs::GPUProcessDevForceEnabled()) {
  1747. return;
  1748. }
  1749. FeatureState& gpuProc = gfxConfig::GetFeature(Feature::GPU_PROCESS);
  1750. gpuProc.SetDefaultFromPref(
  1751. gfxPrefs::GetGPUProcessDevEnabledPrefName(),
  1752. true,
  1753. gfxPrefs::GetGPUProcessDevEnabledPrefDefault());
  1754. if (gfxPrefs::GPUProcessDevForceEnabled()) {
  1755. gpuProc.UserForceEnable("User force-enabled via pref");
  1756. }
  1757. // We require E10S - otherwise, there is very little benefit to the GPU
  1758. // process, since the UI process must still use acceleration for
  1759. // performance.
  1760. if (!BrowserTabsRemoteAutostart()) {
  1761. gpuProc.ForceDisable(
  1762. FeatureStatus::Unavailable,
  1763. "Multi-process mode is not enabled",
  1764. NS_LITERAL_CSTRING("FEATURE_FAILURE_NO_E10S"));
  1765. return;
  1766. }
  1767. if (InSafeMode()) {
  1768. gpuProc.ForceDisable(
  1769. FeatureStatus::Blocked,
  1770. "Safe-mode is enabled",
  1771. NS_LITERAL_CSTRING("FEATURE_FAILURE_SAFE_MODE"));
  1772. return;
  1773. }
  1774. if (gfxPrefs::LayerScopeEnabled()) {
  1775. gpuProc.ForceDisable(
  1776. FeatureStatus::Blocked,
  1777. "LayerScope does not work in the GPU process",
  1778. NS_LITERAL_CSTRING("FEATURE_FAILURE_LAYERSCOPE"));
  1779. return;
  1780. }
  1781. }
  1782. void
  1783. gfxPlatform::InitCompositorAccelerationPrefs()
  1784. {
  1785. const char *acceleratedEnv = PR_GetEnv("MOZ_ACCELERATED");
  1786. FeatureState& feature = gfxConfig::GetFeature(Feature::HW_COMPOSITING);
  1787. // Base value - does the platform allow acceleration?
  1788. if (feature.SetDefault(AccelerateLayersByDefault(),
  1789. FeatureStatus::Blocked,
  1790. "Acceleration blocked by platform"))
  1791. {
  1792. if (!gfxPrefs::LayersAccelerationEnabledDoNotUseDirectly()) {
  1793. feature.UserDisable("Disabled by pref",
  1794. NS_LITERAL_CSTRING("FEATURE_FAILURE_COMP_PREF"));
  1795. } else if (acceleratedEnv && *acceleratedEnv == '0') {
  1796. feature.UserDisable("Disabled by envvar",
  1797. NS_LITERAL_CSTRING("FEATURE_FAILURE_COMP_ENV"));
  1798. }
  1799. } else {
  1800. if (acceleratedEnv && *acceleratedEnv == '1') {
  1801. feature.UserEnable("Enabled by envvar");
  1802. }
  1803. }
  1804. // This has specific meaning elsewhere, so we always record it.
  1805. if (gfxPrefs::LayersAccelerationEnabledDoNotUseDirectly() &&
  1806. gfxPrefs::LayersAccelerationForceEnabledDoNotUseDirectly()) {
  1807. feature.UserForceEnable("Force-enabled by prefs");
  1808. }
  1809. // Safe mode trumps everything.
  1810. if (InSafeMode()) {
  1811. feature.ForceDisable(FeatureStatus::Blocked, "Acceleration blocked by safe-mode",
  1812. NS_LITERAL_CSTRING("FEATURE_FAILURE_COMP_SAFEMODE"));
  1813. }
  1814. }
  1815. bool
  1816. gfxPlatform::CanUseHardwareVideoDecoding()
  1817. {
  1818. // this function is called from the compositor thread, so it is not
  1819. // safe to init the prefs etc. from here.
  1820. MOZ_ASSERT(sLayersAccelerationPrefsInitialized);
  1821. return sLayersSupportsHardwareVideoDecoding && !sLayersHardwareVideoDecodingFailed;
  1822. }
  1823. bool
  1824. gfxPlatform::AccelerateLayersByDefault()
  1825. {
  1826. // Note: add any new platform defines here that should get HWA by default.
  1827. #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_UIKIT)
  1828. return true;
  1829. #elif defined(MOZ_GL_PROVIDER)
  1830. // GL provider manually declared
  1831. return true;
  1832. #else
  1833. return false;
  1834. #endif
  1835. }
  1836. bool
  1837. gfxPlatform::BufferRotationEnabled()
  1838. {
  1839. MutexAutoLock autoLock(*gGfxPlatformPrefsLock);
  1840. return sBufferRotationCheckPref && gfxPrefs::BufferRotationEnabled();
  1841. }
  1842. void
  1843. gfxPlatform::DisableBufferRotation()
  1844. {
  1845. MutexAutoLock autoLock(*gGfxPlatformPrefsLock);
  1846. sBufferRotationCheckPref = false;
  1847. }
  1848. already_AddRefed<ScaledFont>
  1849. gfxPlatform::GetScaledFontForFontWithCairoSkia(DrawTarget* aTarget, gfxFont* aFont)
  1850. {
  1851. NativeFont nativeFont;
  1852. if (aTarget->GetBackendType() == BackendType::CAIRO || aTarget->GetBackendType() == BackendType::SKIA) {
  1853. nativeFont.mType = NativeFontType::CAIRO_FONT_FACE;
  1854. nativeFont.mFont = aFont->GetCairoScaledFont();
  1855. return Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
  1856. }
  1857. return nullptr;
  1858. }
  1859. /* static */ bool
  1860. gfxPlatform::UsesOffMainThreadCompositing()
  1861. {
  1862. if (XRE_GetProcessType() == GeckoProcessType_GPU) {
  1863. return true;
  1864. }
  1865. static bool firstTime = true;
  1866. static bool result = false;
  1867. if (firstTime) {
  1868. MOZ_ASSERT(sLayersAccelerationPrefsInitialized);
  1869. result =
  1870. gfxVars::BrowserTabsRemoteAutostart() ||
  1871. !gfxPrefs::LayersOffMainThreadCompositionForceDisabled();
  1872. #if defined(MOZ_WIDGET_GTK)
  1873. // Linux users who chose OpenGL are being grandfathered in to OMTC
  1874. result |= gfxPrefs::LayersAccelerationForceEnabledDoNotUseDirectly();
  1875. #endif
  1876. firstTime = false;
  1877. }
  1878. return result;
  1879. }
  1880. /***
  1881. * The preference "layout.frame_rate" has 3 meanings depending on the value:
  1882. *
  1883. * -1 = Auto (default), use hardware vsync or software vsync @ 60 hz if hw vsync fails.
  1884. * 0 = ASAP mode - used during talos testing.
  1885. * X = Software vsync at a rate of X times per second.
  1886. */
  1887. already_AddRefed<mozilla::gfx::VsyncSource>
  1888. gfxPlatform::CreateHardwareVsyncSource()
  1889. {
  1890. RefPtr<mozilla::gfx::VsyncSource> softwareVsync = new SoftwareVsyncSource();
  1891. return softwareVsync.forget();
  1892. }
  1893. /* static */ bool
  1894. gfxPlatform::IsInLayoutAsapMode()
  1895. {
  1896. // There are 2 modes of ASAP mode.
  1897. // 1 is that the refresh driver and compositor are in lock step
  1898. // the second is that the compositor goes ASAP and the refresh driver
  1899. // goes at whatever the configurated rate is. This only checks the version
  1900. // talos uses, which is the refresh driver and compositor are in lockstep.
  1901. return gfxPrefs::LayoutFrameRate() == 0;
  1902. }
  1903. /* static */ bool
  1904. gfxPlatform::ForceSoftwareVsync()
  1905. {
  1906. return gfxPrefs::LayoutFrameRate() > 0;
  1907. }
  1908. /* static */ int
  1909. gfxPlatform::GetSoftwareVsyncRate()
  1910. {
  1911. int preferenceRate = gfxPrefs::LayoutFrameRate();
  1912. if (preferenceRate <= 0) {
  1913. return gfxPlatform::GetDefaultFrameRate();
  1914. }
  1915. return preferenceRate;
  1916. }
  1917. /* static */ int
  1918. gfxPlatform::GetDefaultFrameRate()
  1919. {
  1920. return 60;
  1921. }
  1922. void
  1923. gfxPlatform::GetApzSupportInfo(mozilla::widget::InfoObject& aObj)
  1924. {
  1925. if (!gfxPlatform::AsyncPanZoomEnabled()) {
  1926. return;
  1927. }
  1928. if (SupportsApzWheelInput()) {
  1929. aObj.DefineProperty("ApzWheelInput", 1);
  1930. }
  1931. if (SupportsApzTouchInput()) {
  1932. aObj.DefineProperty("ApzTouchInput", 1);
  1933. }
  1934. if (SupportsApzDragInput()) {
  1935. aObj.DefineProperty("ApzDragInput", 1);
  1936. }
  1937. }
  1938. void
  1939. gfxPlatform::GetTilesSupportInfo(mozilla::widget::InfoObject& aObj)
  1940. {
  1941. if (!gfxPrefs::LayersTilesEnabled()) {
  1942. return;
  1943. }
  1944. IntSize tileSize = gfxVars::TileSize();
  1945. aObj.DefineProperty("TileHeight", tileSize.height);
  1946. aObj.DefineProperty("TileWidth", tileSize.width);
  1947. }
  1948. /*static*/ bool
  1949. gfxPlatform::AsyncPanZoomEnabled()
  1950. {
  1951. #if !defined(MOZ_WIDGET_UIKIT)
  1952. // For XUL applications (everything but Firefox on Android) we only want
  1953. // to use APZ when E10S is enabled or when the user explicitly enable it.
  1954. if (BrowserTabsRemoteAutostart() || gfxPrefs::APZDesktopEnabled()) {
  1955. return gfxPrefs::AsyncPanZoomEnabledDoNotUseDirectly();
  1956. } else {
  1957. return false;
  1958. }
  1959. #else
  1960. return gfxPrefs::AsyncPanZoomEnabledDoNotUseDirectly();
  1961. #endif
  1962. }
  1963. /*static*/ bool
  1964. gfxPlatform::PerfWarnings()
  1965. {
  1966. return gfxPrefs::PerfWarnings();
  1967. }
  1968. void
  1969. gfxPlatform::GetAcceleratedCompositorBackends(nsTArray<LayersBackend>& aBackends)
  1970. {
  1971. if (gfxConfig::IsEnabled(Feature::OPENGL_COMPOSITING)) {
  1972. aBackends.AppendElement(LayersBackend::LAYERS_OPENGL);
  1973. }
  1974. else {
  1975. static int tell_me_once = 0;
  1976. if (!tell_me_once) {
  1977. NS_WARNING("OpenGL-accelerated layers are not supported on this system");
  1978. tell_me_once = 1;
  1979. }
  1980. }
  1981. }
  1982. void
  1983. gfxPlatform::GetCompositorBackends(bool useAcceleration, nsTArray<mozilla::layers::LayersBackend>& aBackends)
  1984. {
  1985. if (useAcceleration) {
  1986. GetAcceleratedCompositorBackends(aBackends);
  1987. }
  1988. aBackends.AppendElement(LayersBackend::LAYERS_BASIC);
  1989. }
  1990. void
  1991. gfxPlatform::NotifyCompositorCreated(LayersBackend aBackend)
  1992. {
  1993. if (mCompositorBackend == aBackend) {
  1994. return;
  1995. }
  1996. if (mCompositorBackend != LayersBackend::LAYERS_NONE) {
  1997. gfxCriticalNote << "Compositors might be mixed ("
  1998. << int(mCompositorBackend) << "," << int(aBackend) << ")";
  1999. }
  2000. // Set the backend before we notify so it's available immediately.
  2001. mCompositorBackend = aBackend;
  2002. }
  2003. void
  2004. gfxPlatform::FetchAndImportContentDeviceData()
  2005. {
  2006. MOZ_ASSERT(XRE_IsContentProcess());
  2007. mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton();
  2008. mozilla::gfx::ContentDeviceData data;
  2009. cc->SendGetGraphicsDeviceInitData(&data);
  2010. ImportContentDeviceData(data);
  2011. }
  2012. void
  2013. gfxPlatform::ImportContentDeviceData(const mozilla::gfx::ContentDeviceData& aData)
  2014. {
  2015. MOZ_ASSERT(XRE_IsContentProcess());
  2016. const DevicePrefs& prefs = aData.prefs();
  2017. gfxConfig::Inherit(Feature::HW_COMPOSITING, prefs.hwCompositing());
  2018. gfxConfig::Inherit(Feature::OPENGL_COMPOSITING, prefs.oglCompositing());
  2019. }
  2020. void
  2021. gfxPlatform::BuildContentDeviceData(mozilla::gfx::ContentDeviceData* aOut)
  2022. {
  2023. MOZ_ASSERT(XRE_IsParentProcess());
  2024. // Make sure our settings are synchronized from the GPU process.
  2025. GPUProcessManager::Get()->EnsureGPUReady();
  2026. aOut->prefs().hwCompositing() = gfxConfig::GetValue(Feature::HW_COMPOSITING);
  2027. aOut->prefs().oglCompositing() = gfxConfig::GetValue(Feature::OPENGL_COMPOSITING);
  2028. }
  2029. void
  2030. gfxPlatform::ImportGPUDeviceData(const mozilla::gfx::GPUDeviceData& aData)
  2031. {
  2032. MOZ_ASSERT(XRE_IsParentProcess());
  2033. gfxConfig::ImportChange(Feature::OPENGL_COMPOSITING, aData.oglCompositing());
  2034. }
  2035. bool
  2036. gfxPlatform::SupportsApzDragInput() const
  2037. {
  2038. return gfxPrefs::APZDragEnabled();
  2039. }
  2040. void
  2041. gfxPlatform::BumpDeviceCounter()
  2042. {
  2043. mDeviceCounter++;
  2044. }
  2045. void
  2046. gfxPlatform::InitOpenGLConfig()
  2047. {
  2048. #ifdef XP_WIN
  2049. // Don't enable by default on Windows, since it could show up in about:support even
  2050. // though it'll never get used. Only attempt if user enables the pref
  2051. if (!Preferences::GetBool("layers.prefer-opengl")){
  2052. return;
  2053. }
  2054. #endif
  2055. FeatureState& openGLFeature = gfxConfig::GetFeature(Feature::OPENGL_COMPOSITING);
  2056. // Check to see hw comp supported
  2057. if (!gfxConfig::IsEnabled(Feature::HW_COMPOSITING)) {
  2058. openGLFeature.DisableByDefault(FeatureStatus::Unavailable, "Hardware compositing is disabled",
  2059. NS_LITERAL_CSTRING("FEATURE_FAILURE_OPENGL_NEED_HWCOMP"));
  2060. return;
  2061. }
  2062. #ifdef XP_WIN
  2063. openGLFeature.SetDefaultFromPref(
  2064. gfxPrefs::GetLayersPreferOpenGLPrefName(),
  2065. true,
  2066. gfxPrefs::GetLayersPreferOpenGLPrefDefault());
  2067. #else
  2068. openGLFeature.EnableByDefault();
  2069. #endif
  2070. // When layers acceleration is force-enabled, enable it even for blacklisted
  2071. // devices.
  2072. if (gfxPrefs::LayersAccelerationForceEnabledDoNotUseDirectly()) {
  2073. openGLFeature.UserForceEnable("Force-enabled by pref");
  2074. return;
  2075. }
  2076. nsCString message;
  2077. nsCString failureId;
  2078. if (!IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_OPENGL_LAYERS, &message, failureId)) {
  2079. openGLFeature.Disable(FeatureStatus::Blacklisted, message.get(), failureId);
  2080. }
  2081. }
  2082. bool
  2083. gfxPlatform::IsGfxInfoStatusOkay(int32_t aFeature, nsCString* aOutMessage, nsCString& aFailureId)
  2084. {
  2085. nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
  2086. if (!gfxInfo) {
  2087. return true;
  2088. }
  2089. int32_t status;
  2090. if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(aFeature, aFailureId, &status)) &&
  2091. status != nsIGfxInfo::FEATURE_STATUS_OK)
  2092. {
  2093. aOutMessage->AssignLiteral("#BLOCKLIST_");
  2094. aOutMessage->AppendASCII(aFailureId.get());
  2095. return false;
  2096. }
  2097. return true;
  2098. }