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/. */
7 #define FORCE_PR_LOG /* Allow logging in the release build */
10 #include "mozilla/layers/AsyncTransactionTracker.h" // for AsyncTransactionTracker
11 #include "mozilla/layers/CompositorChild.h"
12 #include "mozilla/layers/CompositorParent.h"
13 #include "mozilla/layers/ImageBridgeChild.h"
14 #include "mozilla/layers/SharedBufferManagerChild.h"
15 #include "mozilla/layers/ISurfaceAllocator.h" // for GfxMemoryImageReporter
19 #include "gfxPlatform.h"
24 #define getpid _getpid
29 #include "nsXULAppAPI.h"
30 #include "nsDirectoryServiceUtils.h"
31 #include "nsDirectoryServiceDefs.h"
34 #include "gfxWindowsPlatform.h"
35 #include "gfxD2DSurface.h"
36 #elif defined(XP_MACOSX)
37 #include "gfxPlatformMac.h"
38 #include "gfxQuartzSurface.h"
39 #elif defined(MOZ_WIDGET_GTK)
40 #include "gfxPlatformGtk.h"
41 #elif defined(MOZ_WIDGET_QT)
42 #include "gfxQtPlatform.h"
43 #elif defined(ANDROID)
44 #include "gfxAndroidPlatform.h"
47 #include "nsGkAtoms.h"
48 #include "gfxPlatformFontList.h"
49 #include "gfxContext.h"
50 #include "gfxImageSurface.h"
51 #include "nsUnicodeProperties.h"
52 #include "harfbuzz/hb.h"
53 #include "gfxGraphiteShaper.h"
54 #include "gfx2DGlue.h"
55 #include "gfxGradientCache.h"
57 #include "nsUnicodeRange.h"
58 #include "nsServiceManagerUtils.h"
60 #include "nsILocaleService.h"
61 #include "nsIObserverService.h"
62 #include "MainThreadUtils.h"
64 #include "nsWeakReference.h"
71 #include "GLContext.h"
72 #include "GLContextProvider.h"
74 #ifdef MOZ_WIDGET_ANDROID
75 #include "TexturePoolOGL.h"
78 #include "mozilla/Hal.h"
80 #include "skia/SkGraphics.h"
82 #include "SkiaGLGlue.h"
84 class mozilla::gl::SkiaGLGlue
: public GenericAtomicRefCounted
{
88 #include "mozilla/Preferences.h"
89 #include "mozilla/Assertions.h"
90 #include "mozilla/Attributes.h"
91 #include "mozilla/Mutex.h"
93 #include "nsIGfxInfo.h"
94 #include "nsIXULRuntime.h"
98 #ifdef MOZ_WIDGET_GONK
101 void ShutdownTileCache();
105 using namespace mozilla
;
106 using namespace mozilla::layers
;
108 gfxPlatform
*gPlatform
= nullptr;
109 static bool gEverInitialized
= false;
111 static Mutex
* gGfxPlatformPrefsLock
= nullptr;
113 // These two may point to the same profile
114 static qcms_profile
*gCMSOutputProfile
= nullptr;
115 static qcms_profile
*gCMSsRGBProfile
= nullptr;
117 static qcms_transform
*gCMSRGBTransform
= nullptr;
118 static qcms_transform
*gCMSInverseRGBTransform
= nullptr;
119 static qcms_transform
*gCMSRGBATransform
= nullptr;
121 static bool gCMSInitialized
= false;
122 static eCMSMode gCMSMode
= eCMSMode_Off
;
124 static bool gCMSIntentInitialized
= false;
125 static int gCMSIntent
= QCMS_INTENT_DEFAULT
;
128 static void ShutdownCMS();
130 #include "mozilla/gfx/2D.h"
131 #include "mozilla/gfx/SourceSurfaceCairo.h"
132 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 MOZ_FINAL
: public nsIObserver
,
137 public nsSupportsWeakReference
139 ~SRGBOverrideObserver() {}
145 NS_IMPL_ISUPPORTS(SRGBOverrideObserver
, nsIObserver
, nsISupportsWeakReference
)
147 #define GFX_DOWNLOADABLE_FONTS_ENABLED "gfx.downloadable_fonts.enabled"
149 #define GFX_PREF_FALLBACK_USE_CMAPS "gfx.font_rendering.fallback.always_use_cmaps"
151 #define GFX_PREF_OPENTYPE_SVG "gfx.font_rendering.opentype_svg.enabled"
153 #define GFX_PREF_WORD_CACHE_CHARLIMIT "gfx.font_rendering.wordcache.charlimit"
154 #define GFX_PREF_WORD_CACHE_MAXENTRIES "gfx.font_rendering.wordcache.maxentries"
156 #define GFX_PREF_GRAPHITE_SHAPING "gfx.font_rendering.graphite.enabled"
158 #define BIDI_NUMERAL_PREF "bidi.numeral"
160 #define GFX_PREF_CMS_FORCE_SRGB "gfx.color_management.force_srgb"
163 SRGBOverrideObserver::Observe(nsISupports
*aSubject
,
165 const char16_t
* someData
)
167 NS_ASSERTION(NS_strcmp(someData
,
168 MOZ_UTF16(GFX_PREF_CMS_FORCE_SRGB
)) == 0,
169 "Restarting CMS on wrong pref!");
174 static const char* kObservedPrefs
[] = {
175 "gfx.downloadable_fonts.",
176 "gfx.font_rendering.",
181 class FontPrefsObserver MOZ_FINAL
: public nsIObserver
183 ~FontPrefsObserver() {}
189 NS_IMPL_ISUPPORTS(FontPrefsObserver
, nsIObserver
)
192 FontPrefsObserver::Observe(nsISupports
*aSubject
,
194 const char16_t
*someData
)
197 NS_ERROR("font pref observer code broken");
198 return NS_ERROR_UNEXPECTED
;
200 NS_ASSERTION(gfxPlatform::GetPlatform(), "the singleton instance has gone");
201 gfxPlatform::GetPlatform()->FontsPrefsChanged(NS_ConvertUTF16toUTF8(someData
).get());
206 class MemoryPressureObserver MOZ_FINAL
: public nsIObserver
208 ~MemoryPressureObserver() {}
214 NS_IMPL_ISUPPORTS(MemoryPressureObserver
, nsIObserver
)
217 MemoryPressureObserver::Observe(nsISupports
*aSubject
,
219 const char16_t
*someData
)
221 NS_ASSERTION(strcmp(aTopic
, "memory-pressure") == 0, "unexpected event topic");
222 Factory::PurgeAllCaches();
223 gfxGradientCache::PurgeAllCaches();
225 gfxPlatform::GetPlatform()->PurgeSkiaCache();
229 // this needs to match the list of pref font.default.xx entries listed in all.js!
230 // the order *must* match the order in eFontPrefLang
231 static const char *gPrefLangNames
[] = {
262 gfxPlatform::gfxPlatform()
263 : mAzureCanvasBackendCollector(MOZ_THIS_IN_INITIALIZER_LIST(),
264 &gfxPlatform::GetAzureBackendInfo
)
266 mAllowDownloadableFonts
= UNINITIALIZED_VALUE
;
267 mFallbackUsesCmaps
= UNINITIALIZED_VALUE
;
269 mWordCacheCharLimit
= UNINITIALIZED_VALUE
;
270 mWordCacheMaxEntries
= UNINITIALIZED_VALUE
;
271 mGraphiteShapingEnabled
= UNINITIALIZED_VALUE
;
272 mOpenTypeSVGEnabled
= UNINITIALIZED_VALUE
;
273 mBidiNumeralOption
= UNINITIALIZED_VALUE
;
277 uint32_t canvasMask
= BackendTypeBit(BackendType::CAIRO
) | BackendTypeBit(BackendType::SKIA
);
278 uint32_t contentMask
= BackendTypeBit(BackendType::CAIRO
);
279 InitBackendPrefs(canvasMask
, BackendType::CAIRO
,
280 contentMask
, BackendType::CAIRO
);
281 mTotalSystemMemory
= mozilla::hal::GetTotalSystemMemory();
285 gfxPlatform::GetPlatform()
293 void RecordingPrefChanged(const char *aPrefName
, void *aClosure
)
295 if (Preferences::GetBool("gfx.2d.recording", false)) {
296 nsAutoCString fileName
;
297 nsAdoptingString prefFileName
= Preferences::GetString("gfx.2d.recordingfile");
300 fileName
.Append(NS_ConvertUTF16toUTF8(prefFileName
));
302 nsCOMPtr
<nsIFile
> tmpFile
;
303 if (NS_FAILED(NS_GetSpecialDirectory(NS_OS_TEMP_DIR
, getter_AddRefs(tmpFile
)))) {
306 fileName
.AppendPrintf("moz2drec_%i_%i.aer", XRE_GetProcessType(), getpid());
308 nsresult rv
= tmpFile
->AppendNative(fileName
);
312 rv
= tmpFile
->GetNativePath(fileName
);
317 gPlatform
->mRecorder
= Factory::CreateEventRecorderForFile(fileName
.BeginReading());
318 printf_stderr("Recording to %s\n", fileName
.get());
319 Factory::SetGlobalEventRecorder(gPlatform
->mRecorder
);
321 Factory::SetGlobalEventRecorder(nullptr);
328 if (gEverInitialized
) {
329 NS_RUNTIMEABORT("Already started???");
331 gEverInitialized
= true;
333 // Initialize the preferences by creating the singleton.
334 gfxPrefs::GetSingleton();
336 gGfxPlatformPrefsLock
= new Mutex("gfxPlatform::gGfxPlatformPrefsLock");
338 /* Initialize the GfxInfo service.
339 * Note: we can't call functions on GfxInfo that depend
340 * on gPlatform until after it has been initialized
341 * below. GfxInfo initialization annotates our
342 * crash reports so we want to do it before
343 * we try to load any drivers and do device detection
344 * incase that code crashes. See bug #591561. */
345 nsCOMPtr
<nsIGfxInfo
> gfxInfo
;
346 /* this currently will only succeed on Windows */
347 gfxInfo
= do_GetService("@mozilla.org/gfx/info;1");
350 gPlatform
= new gfxWindowsPlatform
;
351 #elif defined(XP_MACOSX)
352 gPlatform
= new gfxPlatformMac
;
353 #elif defined(MOZ_WIDGET_GTK)
354 gPlatform
= new gfxPlatformGtk
;
355 #elif defined(MOZ_WIDGET_QT)
356 gPlatform
= new gfxQtPlatform
;
357 #elif defined(ANDROID)
358 gPlatform
= new gfxAndroidPlatform
;
360 #error "No gfxPlatform implementation available"
364 mozilla::gl::GLContext::StaticInit();
371 #if defined(XP_MACOSX) || defined(XP_WIN) || defined(ANDROID) // temporary, until this is implemented on others
372 rv
= gfxPlatformFontList::Init();
374 NS_RUNTIMEABORT("Could not initialize gfxPlatformFontList");
378 gPlatform
->mScreenReferenceSurface
=
379 gPlatform
->CreateOffscreenSurface(IntSize(1, 1),
380 gfxContentType::COLOR_ALPHA
);
381 if (!gPlatform
->mScreenReferenceSurface
) {
382 NS_RUNTIMEABORT("Could not initialize mScreenReferenceSurface");
385 gPlatform
->mScreenReferenceDrawTarget
=
386 gPlatform
->CreateOffscreenContentDrawTarget(IntSize(1, 1),
387 SurfaceFormat::B8G8R8A8
);
388 if (!gPlatform
->mScreenReferenceDrawTarget
) {
389 NS_RUNTIMEABORT("Could not initialize mScreenReferenceDrawTarget");
392 rv
= gfxFontCache::Init();
394 NS_RUNTIMEABORT("Could not initialize gfxFontCache");
397 /* Create and register our CMS Override observer. */
398 gPlatform
->mSRGBOverrideObserver
= new SRGBOverrideObserver();
399 Preferences::AddWeakObserver(gPlatform
->mSRGBOverrideObserver
, GFX_PREF_CMS_FORCE_SRGB
);
401 gPlatform
->mFontPrefsObserver
= new FontPrefsObserver();
402 Preferences::AddStrongObservers(gPlatform
->mFontPrefsObserver
, kObservedPrefs
);
404 mozilla::gl::GLContext::PlatformStartup();
406 #ifdef MOZ_WIDGET_ANDROID
408 mozilla::gl::TexturePoolOGL::Init();
411 #ifdef MOZ_WIDGET_GONK
412 mozilla::layers::InitGralloc();
415 Preferences::RegisterCallbackAndCall(RecordingPrefChanged
, "gfx.2d.recording", nullptr);
417 CreateCMSOutputProfile();
419 // Listen to memory pressure event so we can purge DrawTarget caches
420 nsCOMPtr
<nsIObserverService
> obs
= mozilla::services::GetObserverService();
422 gPlatform
->mMemoryPressureObserver
= new MemoryPressureObserver();
423 obs
->AddObserver(gPlatform
->mMemoryPressureObserver
, "memory-pressure", false);
426 RegisterStrongMemoryReporter(new GfxMemoryImageReporter());
429 static bool sLayersIPCIsUp
= false;
432 gfxPlatform::Shutdown()
438 MOZ_ASSERT(!sLayersIPCIsUp
);
440 // These may be called before the corresponding subsystems have actually
441 // started up. That's OK, they can handle it.
442 gfxFontCache::Shutdown();
443 gfxFontGroup::Shutdown();
444 gfxGradientCache::Shutdown();
445 gfxAlphaBoxBlur::ShutdownBlurCache();
446 gfxGraphiteShaper::Shutdown();
447 gfxPlatformFontList::Shutdown();
450 // Free the various non-null transforms and loaded profiles
453 // In some cases, gPlatform may not be created but Shutdown() called,
454 // e.g., during xpcshell tests.
456 /* Unregister our CMS Override callback. */
457 NS_ASSERTION(gPlatform
->mSRGBOverrideObserver
, "mSRGBOverrideObserver has alreay gone");
458 Preferences::RemoveObserver(gPlatform
->mSRGBOverrideObserver
, GFX_PREF_CMS_FORCE_SRGB
);
459 gPlatform
->mSRGBOverrideObserver
= nullptr;
461 NS_ASSERTION(gPlatform
->mFontPrefsObserver
, "mFontPrefsObserver has alreay gone");
462 Preferences::RemoveObservers(gPlatform
->mFontPrefsObserver
, kObservedPrefs
);
463 gPlatform
->mFontPrefsObserver
= nullptr;
465 NS_ASSERTION(gPlatform
->mMemoryPressureObserver
, "mMemoryPressureObserver has already gone");
466 nsCOMPtr
<nsIObserverService
> obs
= mozilla::services::GetObserverService();
468 obs
->RemoveObserver(gPlatform
->mMemoryPressureObserver
, "memory-pressure");
471 gPlatform
->mMemoryPressureObserver
= nullptr;
472 gPlatform
->mSkiaGlue
= nullptr;
475 #ifdef MOZ_WIDGET_ANDROID
476 // Shut down the texture pool
477 mozilla::gl::TexturePoolOGL::Shutdown();
480 // Shut down the default GL context provider.
481 mozilla::gl::GLContextProvider::Shutdown();
484 // The above shutdown calls operate on the available context providers on
485 // most platforms. Windows is a "special snowflake", though, and has three
486 // context providers available, so we have to shut all of them down.
487 // We should only support the default GL provider on Windows; then, this
488 // could go away. Unfortunately, we currently support WGL (the default) for
490 mozilla::gl::GLContextProviderEGL::Shutdown();
493 delete gGfxPlatformPrefsLock
;
495 gfxPrefs::DestroySingleton();
496 gfxFont::DestroySingletons();
503 gfxPlatform::InitLayersIPC()
505 if (sLayersIPCIsUp
) {
508 sLayersIPCIsUp
= true;
510 AsyncTransactionTrackersHolder::Initialize();
512 if (XRE_GetProcessType() == GeckoProcessType_Default
)
514 mozilla::layers::CompositorParent::StartUp();
515 #ifndef MOZ_WIDGET_GONK
516 if (gfxPrefs::AsyncVideoEnabled()) {
517 mozilla::layers::ImageBridgeChild::StartUp();
520 mozilla::layers::ImageBridgeChild::StartUp();
521 SharedBufferManagerChild::StartUp();
527 gfxPlatform::ShutdownLayersIPC()
529 if (!sLayersIPCIsUp
) {
532 sLayersIPCIsUp
= false;
534 if (XRE_GetProcessType() == GeckoProcessType_Default
)
536 // This must happen after the shutdown of media and widgets, which
537 // are triggered by the NS_XPCOM_SHUTDOWN_OBSERVER_ID notification.
538 layers::ImageBridgeChild::ShutDown();
539 #ifdef MOZ_WIDGET_GONK
540 layers::SharedBufferManagerChild::ShutDown();
543 layers::CompositorParent::ShutDown();
547 gfxPlatform::~gfxPlatform()
549 mScreenReferenceSurface
= nullptr;
550 mScreenReferenceDrawTarget
= nullptr;
552 // The cairo folks think we should only clean up in debug builds,
553 // but we're generally in the habit of trying to shut down as
554 // cleanly as possible even in production code, so call this
555 // cairo_debug_* function unconditionally.
557 // because cairo can assert and thus crash on shutdown, don't do this in release builds
558 #if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING) || defined(NS_TRACE_MALLOC) || defined(MOZ_VALGRIND)
560 // must do Skia cleanup before Cairo cleanup, because Skia may be referencing
561 // Cairo objects e.g. through SkCairoFTTypeface
566 cairo_debug_reset_static_data();
571 cairo_user_data_key_t kDrawTarget
;
573 TemporaryRef
<DrawTarget
>
574 gfxPlatform::CreateDrawTargetForSurface(gfxASurface
*aSurface
, const IntSize
& aSize
)
576 SurfaceFormat format
= Optimal2DFormatForContent(aSurface
->GetContentType());
577 RefPtr
<DrawTarget
> drawTarget
= Factory::CreateDrawTargetForCairoSurface(aSurface
->CairoSurface(), aSize
, &format
);
578 aSurface
->SetData(&kDrawTarget
, drawTarget
, nullptr);
579 return drawTarget
.forget();
582 // This is a temporary function used by ContentClient to build a DrawTarget
583 // around the gfxASurface. This should eventually be replaced by plumbing
584 // the DrawTarget through directly
585 TemporaryRef
<DrawTarget
>
586 gfxPlatform::CreateDrawTargetForUpdateSurface(gfxASurface
*aSurface
, const IntSize
& aSize
)
589 // this is a bit of a hack that assumes that the buffer associated with the CGContext
590 // will live around long enough that nothing bad will happen.
591 if (aSurface
->GetType() == gfxSurfaceType::Quartz
) {
592 return Factory::CreateDrawTargetForCairoCGContext(static_cast<gfxQuartzSurface
*>(aSurface
)->GetCGContext(), aSize
);
600 cairo_user_data_key_t kSourceSurface
;
603 * Record the backend that was used to construct the SourceSurface.
604 * When getting the cached SourceSurface for a gfxASurface/DrawTarget pair,
605 * we check to make sure the DrawTarget's backend matches the backend
606 * for the cached SourceSurface, and only use it if they match. This
607 * can avoid expensive and unnecessary readbacks.
609 struct SourceSurfaceUserData
611 RefPtr
<SourceSurface
> mSrcSurface
;
612 BackendType mBackendType
;
615 void SourceBufferDestroy(void *srcSurfUD
)
617 delete static_cast<SourceSurfaceUserData
*>(srcSurfUD
);
620 UserDataKey kThebesSurface
;
622 struct DependentSourceSurfaceUserData
624 nsRefPtr
<gfxASurface
> mSurface
;
627 void SourceSurfaceDestroyed(void *aData
)
629 delete static_cast<DependentSourceSurfaceUserData
*>(aData
);
633 gfxPlatform::ClearSourceSurfaceForSurface(gfxASurface
*aSurface
)
635 aSurface
->SetData(&kSourceSurface
, nullptr, nullptr);
638 /* static */ TemporaryRef
<SourceSurface
>
639 gfxPlatform::GetSourceSurfaceForSurface(DrawTarget
*aTarget
, gfxASurface
*aSurface
)
641 if (!aSurface
->CairoSurface() || aSurface
->CairoStatus()) {
646 aTarget
= gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
652 void *userData
= aSurface
->GetData(&kSourceSurface
);
655 SourceSurfaceUserData
*surf
= static_cast<SourceSurfaceUserData
*>(userData
);
657 if (surf
->mSrcSurface
->IsValid() && surf
->mBackendType
== aTarget
->GetBackendType()) {
658 return surf
->mSrcSurface
;
660 // We can just continue here as when setting new user data the destroy
661 // function will be called for the old user data.
664 SurfaceFormat format
;
665 if (aSurface
->GetContentType() == gfxContentType::ALPHA
) {
666 format
= SurfaceFormat::A8
;
667 } else if (aSurface
->GetContentType() == gfxContentType::COLOR
) {
668 format
= SurfaceFormat::B8G8R8X8
;
670 format
= SurfaceFormat::B8G8R8A8
;
673 if (aTarget
->GetBackendType() == BackendType::CAIRO
) {
674 // If we're going to be used with a CAIRO DrawTarget, then just create a
675 // SourceSurfaceCairo since we don't know the underlying type of the CAIRO
676 // DrawTarget and can't pick a better surface type. Doing this also avoids
677 // readback of aSurface's surface into memory if, for example, aSurface
678 // wraps an xlib cairo surface (which can be important to avoid a major
681 surf
.mFormat
= format
;
682 surf
.mType
= NativeSurfaceType::CAIRO_SURFACE
;
683 surf
.mSurface
= aSurface
->CairoSurface();
684 surf
.mSize
= ToIntSize(aSurface
->GetSize());
685 // We return here regardless of whether CreateSourceSurfaceFromNativeSurface
686 // succeeds or not since we don't expect to be able to do any better below
689 // Note that the returned SourceSurfaceCairo holds a strong reference to
690 // the cairo_surface_t* that it wraps, which essencially means it holds a
691 // strong reference to aSurface since aSurface shares its
692 // cairo_surface_t*'s reference count variable. As a result we can't cache
693 // srcBuffer on aSurface (see below) since aSurface would then hold a
694 // strong reference back to srcBuffer, creating a reference loop and a
695 // memory leak. Not caching is fine since wrapping is cheap enough (no
696 // copying) so we can just wrap again next time we're called.
697 return aTarget
->CreateSourceSurfaceFromNativeSurface(surf
);
700 RefPtr
<SourceSurface
> srcBuffer
;
703 if (aSurface
->GetType() == gfxSurfaceType::D2D
&&
704 format
!= SurfaceFormat::A8
) {
706 surf
.mFormat
= format
;
707 surf
.mType
= NativeSurfaceType::D3D10_TEXTURE
;
708 surf
.mSurface
= static_cast<gfxD2DSurface
*>(aSurface
)->GetTexture();
709 surf
.mSize
= ToIntSize(aSurface
->GetSize());
710 mozilla::gfx::DrawTarget
*dt
= static_cast<mozilla::gfx::DrawTarget
*>(aSurface
->GetData(&kDrawTarget
));
714 srcBuffer
= aTarget
->CreateSourceSurfaceFromNativeSurface(surf
);
717 // Currently no other DrawTarget types implement CreateSourceSurfaceFromNativeSurface
720 // If aSurface wraps data, we can create a SourceSurfaceRawData that wraps
721 // the same data, then optimize it for aTarget:
722 RefPtr
<DataSourceSurface
> surf
= GetWrappedDataSourceSurface(aSurface
);
724 srcBuffer
= aTarget
->OptimizeSourceSurface(surf
);
725 if (srcBuffer
== surf
) {
726 // GetWrappedDataSourceSurface returns a SourceSurface that holds a
727 // strong reference to aSurface since it wraps aSurface's data and
728 // needs it to stay alive. As a result we can't cache srcBuffer on
729 // aSurface (below) since aSurface would then hold a strong reference
730 // back to srcBuffer, creating a reference loop and a memory leak. Not
731 // caching is fine since wrapping is cheap enough (no copying) so we
732 // can just wrap again next time we're called.
734 // Note that the check below doesn't catch this since srcBuffer will be a
735 // SourceSurfaceRawData object (even if aSurface is not a gfxImageSurface
736 // object), which is why we need this separate check.
737 return srcBuffer
.forget();
743 MOZ_ASSERT(aTarget
->GetBackendType() != BackendType::CAIRO
,
744 "We already tried CreateSourceSurfaceFromNativeSurface with a "
745 "DrawTargetCairo above");
746 // We've run out of performant options. We now try creating a SourceSurface
747 // using a temporary DrawTargetCairo and then optimizing it to aTarget's
748 // actual type. The CreateSourceSurfaceFromNativeSurface() call will
749 // likely create a DataSourceSurface (possibly involving copying and/or
750 // readback), and the OptimizeSourceSurface may well copy again and upload
751 // to the GPU. So, while this code path is rarely hit, hitting it may be
754 surf
.mFormat
= format
;
755 surf
.mType
= NativeSurfaceType::CAIRO_SURFACE
;
756 surf
.mSurface
= aSurface
->CairoSurface();
757 surf
.mSize
= ToIntSize(aSurface
->GetSize());
758 RefPtr
<DrawTarget
> drawTarget
=
759 Factory::CreateDrawTarget(BackendType::CAIRO
, IntSize(1, 1), format
);
760 srcBuffer
= drawTarget
->CreateSourceSurfaceFromNativeSurface(surf
);
762 srcBuffer
= aTarget
->OptimizeSourceSurface(srcBuffer
);
770 if ((srcBuffer
->GetType() == SurfaceType::CAIRO
&&
771 static_cast<SourceSurfaceCairo
*>(srcBuffer
.get())->GetSurface() ==
772 aSurface
->CairoSurface()) ||
773 (srcBuffer
->GetType() == SurfaceType::CAIRO_IMAGE
&&
774 static_cast<DataSourceSurfaceCairo
*>(srcBuffer
.get())->GetSurface() ==
775 aSurface
->CairoSurface())) {
776 // See the "Note that the returned SourceSurfaceCairo..." comment above.
777 return srcBuffer
.forget();
780 // Add user data to aSurface so we can cache lookups in the future.
781 SourceSurfaceUserData
*srcSurfUD
= new SourceSurfaceUserData
;
782 srcSurfUD
->mBackendType
= aTarget
->GetBackendType();
783 srcSurfUD
->mSrcSurface
= srcBuffer
;
784 aSurface
->SetData(&kSourceSurface
, srcSurfUD
, SourceBufferDestroy
);
786 return srcBuffer
.forget();
789 TemporaryRef
<DataSourceSurface
>
790 gfxPlatform::GetWrappedDataSourceSurface(gfxASurface
* aSurface
)
792 nsRefPtr
<gfxImageSurface
> image
= aSurface
->GetAsImageSurface();
796 RefPtr
<DataSourceSurface
> result
=
797 Factory::CreateWrappingDataSourceSurface(image
->Data(),
799 ToIntSize(image
->GetSize()),
800 ImageFormatToSurfaceFormat(image
->Format()));
806 // If we wrapped the underlying data of aSurface, then we need to add user data
807 // to make sure aSurface stays alive until we are done with the data.
808 DependentSourceSurfaceUserData
*srcSurfUD
= new DependentSourceSurfaceUserData
;
809 srcSurfUD
->mSurface
= aSurface
;
810 result
->AddUserData(&kThebesSurface
, srcSurfUD
, SourceSurfaceDestroyed
);
812 return result
.forget();
815 TemporaryRef
<ScaledFont
>
816 gfxPlatform::GetScaledFontForFont(DrawTarget
* aTarget
, gfxFont
*aFont
)
818 NativeFont nativeFont
;
819 nativeFont
.mType
= NativeFontType::CAIRO_FONT_FACE
;
820 nativeFont
.mFont
= aFont
->GetCairoScaledFont();
821 RefPtr
<ScaledFont
> scaledFont
=
822 Factory::CreateScaledFontForNativeFont(nativeFont
,
823 aFont
->GetAdjustedSize());
828 gfxPlatform::SupportsAzureContentForDrawTarget(DrawTarget
* aTarget
)
834 return SupportsAzureContentForType(aTarget
->GetBackendType());
838 gfxPlatform::UseAcceleratedSkiaCanvas()
840 return gfxPrefs::CanvasAzureAccelerated() &&
841 mPreferredCanvasBackend
== BackendType::SKIA
;
845 gfxPlatform::InitializeSkiaCacheLimits()
847 if (UseAcceleratedSkiaCanvas()) {
848 bool usingDynamicCache
= gfxPrefs::CanvasSkiaGLDynamicCache();
849 int cacheItemLimit
= gfxPrefs::CanvasSkiaGLCacheItems();
850 int cacheSizeLimit
= gfxPrefs::CanvasSkiaGLCacheSize();
852 // Prefs are in megabytes, but we want the sizes in bytes
853 cacheSizeLimit
*= 1024*1024;
855 if (usingDynamicCache
) {
856 if (mTotalSystemMemory
< 512*1024*1024) {
857 // We need a very minimal cache on anything smaller than 512mb.
858 // Note the large jump as we cross 512mb (from 2mb to 32mb).
859 cacheSizeLimit
= 2*1024*1024;
860 } else if (mTotalSystemMemory
> 0) {
861 cacheSizeLimit
= mTotalSystemMemory
/ 16;
866 printf_stderr("Determined SkiaGL cache limits: Size %i, Items: %i\n", cacheSizeLimit
, cacheItemLimit
);
870 mSkiaGlue
->GetGrContext()->setResourceCacheLimits(cacheItemLimit
, cacheSizeLimit
);
875 mozilla::gl::SkiaGLGlue
*
876 gfxPlatform::GetSkiaGLGlue()
880 /* Dummy context. We always draw into a FBO.
882 * FIXME: This should be stored in TLS or something, since there needs to be one for each thread using it. As it
883 * stands, this only works on the main thread.
885 mozilla::gl::SurfaceCaps caps
= mozilla::gl::SurfaceCaps::ForRGBA();
886 nsRefPtr
<mozilla::gl::GLContext
> glContext
= mozilla::gl::GLContextProvider::CreateOffscreen(gfxIntSize(16, 16), caps
);
888 printf_stderr("Failed to create GLContext for SkiaGL!\n");
891 mSkiaGlue
= new mozilla::gl::SkiaGLGlue(glContext
);
892 MOZ_ASSERT(mSkiaGlue
->GetGrContext(), "No GrContext");
893 InitializeSkiaCacheLimits();
901 gfxPlatform::PurgeSkiaCache()
907 mSkiaGlue
->GetGrContext()->freeGpuResources();
908 // GrContext::flush() doesn't call glFlush. Call it here.
909 mSkiaGlue
->GetGLContext()->MakeCurrent();
910 mSkiaGlue
->GetGLContext()->fFlush();
915 gfxPlatform::HasEnoughTotalSystemMemoryForSkiaGL()
917 #ifdef MOZ_WIDGET_GONK
918 if (mTotalSystemMemory
< 250*1024*1024) {
925 TemporaryRef
<DrawTarget
>
926 gfxPlatform::CreateDrawTargetForBackend(BackendType aBackend
, const IntSize
& aSize
, SurfaceFormat aFormat
)
928 // There is a bunch of knowledge in the gfxPlatform heirarchy about how to
929 // create the best offscreen surface for the current system and situation. We
930 // can easily take advantage of this for the Cairo backend, so that's what we
932 // mozilla::gfx::Factory can get away without having all this knowledge for
933 // now, but this might need to change in the future (using
934 // CreateOffscreenSurface() and CreateDrawTargetForSurface() for all
936 if (aBackend
== BackendType::CAIRO
) {
937 nsRefPtr
<gfxASurface
> surf
= CreateOffscreenSurface(aSize
,
938 ContentForFormat(aFormat
));
939 if (!surf
|| surf
->CairoStatus()) {
943 return CreateDrawTargetForSurface(surf
, aSize
);
945 return Factory::CreateDrawTarget(aBackend
, aSize
, aFormat
);
949 TemporaryRef
<DrawTarget
>
950 gfxPlatform::CreateOffscreenCanvasDrawTarget(const IntSize
& aSize
, SurfaceFormat aFormat
)
952 NS_ASSERTION(mPreferredCanvasBackend
!= BackendType::NONE
, "No backend.");
953 RefPtr
<DrawTarget
> target
= CreateDrawTargetForBackend(mPreferredCanvasBackend
, aSize
, aFormat
);
955 mFallbackCanvasBackend
== BackendType::NONE
) {
956 return target
.forget();
959 return CreateDrawTargetForBackend(mFallbackCanvasBackend
, aSize
, aFormat
);
962 TemporaryRef
<DrawTarget
>
963 gfxPlatform::CreateOffscreenContentDrawTarget(const IntSize
& aSize
, SurfaceFormat aFormat
)
965 NS_ASSERTION(mPreferredCanvasBackend
!= BackendType::NONE
, "No backend.");
966 return CreateDrawTargetForBackend(mContentBackend
, aSize
, aFormat
);
969 TemporaryRef
<DrawTarget
>
970 gfxPlatform::CreateDrawTargetForData(unsigned char* aData
, const IntSize
& aSize
, int32_t aStride
, SurfaceFormat aFormat
)
972 NS_ASSERTION(mContentBackend
!= BackendType::NONE
, "No backend.");
974 RefPtr
<DrawTarget
> dt
= Factory::CreateDrawTargetForData(mContentBackend
,
978 // Factory::CreateDrawTargetForData does not support mContentBackend; retry
979 // with BackendType::CAIRO:
980 dt
= Factory::CreateDrawTargetForData(BackendType::CAIRO
,
987 /* static */ BackendType
988 gfxPlatform::BackendTypeForName(const nsCString
& aName
)
990 if (aName
.EqualsLiteral("cairo"))
991 return BackendType::CAIRO
;
992 if (aName
.EqualsLiteral("skia"))
993 return BackendType::SKIA
;
994 if (aName
.EqualsLiteral("direct2d"))
995 return BackendType::DIRECT2D
;
996 if (aName
.EqualsLiteral("cg"))
997 return BackendType::COREGRAPHICS
;
998 return BackendType::NONE
;
1002 gfxPlatform::GetFontList(nsIAtom
*aLangGroup
,
1003 const nsACString
& aGenericFamily
,
1004 nsTArray
<nsString
>& aListOfFonts
)
1006 return NS_ERROR_NOT_IMPLEMENTED
;
1010 gfxPlatform::UpdateFontList()
1012 return NS_ERROR_NOT_IMPLEMENTED
;
1016 gfxPlatform::DownloadableFontsEnabled()
1018 if (mAllowDownloadableFonts
== UNINITIALIZED_VALUE
) {
1019 mAllowDownloadableFonts
=
1020 Preferences::GetBool(GFX_DOWNLOADABLE_FONTS_ENABLED
, false);
1023 return mAllowDownloadableFonts
;
1027 gfxPlatform::UseCmapsDuringSystemFallback()
1029 if (mFallbackUsesCmaps
== UNINITIALIZED_VALUE
) {
1030 mFallbackUsesCmaps
=
1031 Preferences::GetBool(GFX_PREF_FALLBACK_USE_CMAPS
, false);
1034 return mFallbackUsesCmaps
;
1038 gfxPlatform::OpenTypeSVGEnabled()
1040 if (mOpenTypeSVGEnabled
== UNINITIALIZED_VALUE
) {
1041 mOpenTypeSVGEnabled
=
1042 Preferences::GetBool(GFX_PREF_OPENTYPE_SVG
, false);
1045 return mOpenTypeSVGEnabled
> 0;
1049 gfxPlatform::WordCacheCharLimit()
1051 if (mWordCacheCharLimit
== UNINITIALIZED_VALUE
) {
1052 mWordCacheCharLimit
=
1053 Preferences::GetInt(GFX_PREF_WORD_CACHE_CHARLIMIT
, 32);
1054 if (mWordCacheCharLimit
< 0) {
1055 mWordCacheCharLimit
= 32;
1059 return uint32_t(mWordCacheCharLimit
);
1063 gfxPlatform::WordCacheMaxEntries()
1065 if (mWordCacheMaxEntries
== UNINITIALIZED_VALUE
) {
1066 mWordCacheMaxEntries
=
1067 Preferences::GetInt(GFX_PREF_WORD_CACHE_MAXENTRIES
, 10000);
1068 if (mWordCacheMaxEntries
< 0) {
1069 mWordCacheMaxEntries
= 10000;
1073 return uint32_t(mWordCacheMaxEntries
);
1077 gfxPlatform::UseGraphiteShaping()
1079 if (mGraphiteShapingEnabled
== UNINITIALIZED_VALUE
) {
1080 mGraphiteShapingEnabled
=
1081 Preferences::GetBool(GFX_PREF_GRAPHITE_SHAPING
, false);
1084 return mGraphiteShapingEnabled
;
1088 gfxPlatform::MakePlatformFont(const gfxProxyFontEntry
*aProxyEntry
,
1089 const uint8_t *aFontData
,
1092 // Default implementation does not handle activating downloaded fonts;
1093 // just free the data and return.
1094 // Platforms that support @font-face must override this,
1095 // using the data to instantiate the font, and taking responsibility
1096 // for freeing it when no longer required.
1098 NS_Free((void*)aFontData
);
1104 AppendGenericFontFromPref(nsString
& aFonts
, nsIAtom
*aLangGroup
, const char *aGenericName
)
1106 NS_ENSURE_TRUE_VOID(Preferences::GetRootBranch());
1108 nsAutoCString prefName
, langGroupString
;
1110 aLangGroup
->ToUTF8String(langGroupString
);
1112 nsAutoCString genericDotLang
;
1114 genericDotLang
.Assign(aGenericName
);
1116 prefName
.AssignLiteral("font.default.");
1117 prefName
.Append(langGroupString
);
1118 genericDotLang
= Preferences::GetCString(prefName
.get());
1121 genericDotLang
.Append('.');
1122 genericDotLang
.Append(langGroupString
);
1124 // fetch font.name.xxx value
1125 prefName
.AssignLiteral("font.name.");
1126 prefName
.Append(genericDotLang
);
1127 nsAdoptingString nameValue
= Preferences::GetString(prefName
.get());
1129 if (!aFonts
.IsEmpty())
1130 aFonts
.AppendLiteral(", ");
1131 aFonts
+= nameValue
;
1134 // fetch font.name-list.xxx value
1135 prefName
.AssignLiteral("font.name-list.");
1136 prefName
.Append(genericDotLang
);
1137 nsAdoptingString nameListValue
= Preferences::GetString(prefName
.get());
1138 if (nameListValue
&& !nameListValue
.Equals(nameValue
)) {
1139 if (!aFonts
.IsEmpty())
1140 aFonts
.AppendLiteral(", ");
1141 aFonts
+= nameListValue
;
1146 gfxPlatform::GetPrefFonts(nsIAtom
*aLanguage
, nsString
& aFonts
, bool aAppendUnicode
)
1150 AppendGenericFontFromPref(aFonts
, aLanguage
, nullptr);
1152 AppendGenericFontFromPref(aFonts
, nsGkAtoms::Unicode
, nullptr);
1155 bool gfxPlatform::ForEachPrefFont(eFontPrefLang aLangArray
[], uint32_t aLangArrayLen
, PrefFontCallback aCallback
,
1158 NS_ENSURE_TRUE(Preferences::GetRootBranch(), false);
1161 for (i
= 0; i
< aLangArrayLen
; i
++) {
1162 eFontPrefLang prefLang
= aLangArray
[i
];
1163 const char *langGroup
= GetPrefLangName(prefLang
);
1165 nsAutoCString prefName
;
1167 prefName
.AssignLiteral("font.default.");
1168 prefName
.Append(langGroup
);
1169 nsAdoptingCString genericDotLang
= Preferences::GetCString(prefName
.get());
1171 genericDotLang
.Append('.');
1172 genericDotLang
.Append(langGroup
);
1174 // fetch font.name.xxx value
1175 prefName
.AssignLiteral("font.name.");
1176 prefName
.Append(genericDotLang
);
1177 nsAdoptingCString nameValue
= Preferences::GetCString(prefName
.get());
1179 if (!aCallback(prefLang
, NS_ConvertUTF8toUTF16(nameValue
), aClosure
))
1183 // fetch font.name-list.xxx value
1184 prefName
.AssignLiteral("font.name-list.");
1185 prefName
.Append(genericDotLang
);
1186 nsAdoptingCString nameListValue
= Preferences::GetCString(prefName
.get());
1187 if (nameListValue
&& !nameListValue
.Equals(nameValue
)) {
1188 const char kComma
= ',';
1189 const char *p
, *p_end
;
1190 nsAutoCString
list(nameListValue
);
1191 list
.BeginReading(p
);
1192 list
.EndReading(p_end
);
1194 while (nsCRT::IsAsciiSpace(*p
)) {
1200 const char *start
= p
;
1201 while (++p
!= p_end
&& *p
!= kComma
)
1203 nsAutoCString
fontName(Substring(start
, p
));
1204 fontName
.CompressWhitespace(false, true);
1205 if (!aCallback(prefLang
, NS_ConvertUTF8toUTF16(fontName
), aClosure
))
1216 gfxPlatform::GetFontPrefLangFor(const char* aLang
)
1218 if (!aLang
|| !aLang
[0]) {
1219 return eFontPrefLang_Others
;
1221 for (uint32_t i
= 0; i
< ArrayLength(gPrefLangNames
); ++i
) {
1222 if (!PL_strcasecmp(gPrefLangNames
[i
], aLang
)) {
1223 return eFontPrefLang(i
);
1226 return eFontPrefLang_Others
;
1230 gfxPlatform::GetFontPrefLangFor(nsIAtom
*aLang
)
1233 return eFontPrefLang_Others
;
1235 aLang
->ToUTF8String(lang
);
1236 return GetFontPrefLangFor(lang
.get());
1240 gfxPlatform::GetPrefLangName(eFontPrefLang aLang
)
1242 if (uint32_t(aLang
) < ArrayLength(gPrefLangNames
)) {
1243 return gPrefLangNames
[uint32_t(aLang
)];
1249 gfxPlatform::GetFontPrefLangFor(uint8_t aUnicodeRange
)
1251 switch (aUnicodeRange
) {
1252 case kRangeSetLatin
: return eFontPrefLang_Western
;
1253 case kRangeCyrillic
: return eFontPrefLang_Cyrillic
;
1254 case kRangeGreek
: return eFontPrefLang_Greek
;
1255 case kRangeHebrew
: return eFontPrefLang_Hebrew
;
1256 case kRangeArabic
: return eFontPrefLang_Arabic
;
1257 case kRangeThai
: return eFontPrefLang_Thai
;
1258 case kRangeKorean
: return eFontPrefLang_Korean
;
1259 case kRangeJapanese
: return eFontPrefLang_Japanese
;
1260 case kRangeSChinese
: return eFontPrefLang_ChineseCN
;
1261 case kRangeTChinese
: return eFontPrefLang_ChineseTW
;
1262 case kRangeDevanagari
: return eFontPrefLang_Devanagari
;
1263 case kRangeTamil
: return eFontPrefLang_Tamil
;
1264 case kRangeArmenian
: return eFontPrefLang_Armenian
;
1265 case kRangeBengali
: return eFontPrefLang_Bengali
;
1266 case kRangeCanadian
: return eFontPrefLang_Canadian
;
1267 case kRangeEthiopic
: return eFontPrefLang_Ethiopic
;
1268 case kRangeGeorgian
: return eFontPrefLang_Georgian
;
1269 case kRangeGujarati
: return eFontPrefLang_Gujarati
;
1270 case kRangeGurmukhi
: return eFontPrefLang_Gurmukhi
;
1271 case kRangeKhmer
: return eFontPrefLang_Khmer
;
1272 case kRangeMalayalam
: return eFontPrefLang_Malayalam
;
1273 case kRangeOriya
: return eFontPrefLang_Oriya
;
1274 case kRangeTelugu
: return eFontPrefLang_Telugu
;
1275 case kRangeKannada
: return eFontPrefLang_Kannada
;
1276 case kRangeSinhala
: return eFontPrefLang_Sinhala
;
1277 case kRangeTibetan
: return eFontPrefLang_Tibetan
;
1278 case kRangeSetCJK
: return eFontPrefLang_CJKSet
;
1279 default: return eFontPrefLang_Others
;
1284 gfxPlatform::IsLangCJK(eFontPrefLang aLang
)
1287 case eFontPrefLang_Japanese
:
1288 case eFontPrefLang_ChineseTW
:
1289 case eFontPrefLang_ChineseCN
:
1290 case eFontPrefLang_ChineseHK
:
1291 case eFontPrefLang_Korean
:
1292 case eFontPrefLang_CJKSet
:
1299 mozilla::layers::DiagnosticTypes
1300 gfxPlatform::GetLayerDiagnosticTypes()
1302 mozilla::layers::DiagnosticTypes type
= DiagnosticTypes::NO_DIAGNOSTIC
;
1303 if (gfxPrefs::DrawLayerBorders()) {
1304 type
|= mozilla::layers::DiagnosticTypes::LAYER_BORDERS
;
1306 if (gfxPrefs::DrawTileBorders()) {
1307 type
|= mozilla::layers::DiagnosticTypes::TILE_BORDERS
;
1309 if (gfxPrefs::DrawBigImageBorders()) {
1310 type
|= mozilla::layers::DiagnosticTypes::BIGIMAGE_BORDERS
;
1312 if (gfxPrefs::FlashLayerBorders()) {
1313 type
|= mozilla::layers::DiagnosticTypes::FLASH_BORDERS
;
1319 gfxPlatform::GetLangPrefs(eFontPrefLang aPrefLangs
[], uint32_t &aLen
, eFontPrefLang aCharLang
, eFontPrefLang aPageLang
)
1321 if (IsLangCJK(aCharLang
)) {
1322 AppendCJKPrefLangs(aPrefLangs
, aLen
, aCharLang
, aPageLang
);
1324 AppendPrefLang(aPrefLangs
, aLen
, aCharLang
);
1327 AppendPrefLang(aPrefLangs
, aLen
, eFontPrefLang_Others
);
1331 gfxPlatform::AppendCJKPrefLangs(eFontPrefLang aPrefLangs
[], uint32_t &aLen
, eFontPrefLang aCharLang
, eFontPrefLang aPageLang
)
1333 // prefer the lang specified by the page *if* CJK
1334 if (IsLangCJK(aPageLang
)) {
1335 AppendPrefLang(aPrefLangs
, aLen
, aPageLang
);
1338 // if not set up, set up the default CJK order, based on accept lang settings and locale
1339 if (mCJKPrefLangs
.Length() == 0) {
1342 eFontPrefLang tempPrefLangs
[kMaxLenPrefLangList
];
1343 uint32_t tempLen
= 0;
1345 // Add the CJK pref fonts from accept languages, the order should be same order
1346 nsAdoptingCString list
= Preferences::GetLocalizedCString("intl.accept_languages");
1347 if (!list
.IsEmpty()) {
1348 const char kComma
= ',';
1349 const char *p
, *p_end
;
1350 list
.BeginReading(p
);
1351 list
.EndReading(p_end
);
1353 while (nsCRT::IsAsciiSpace(*p
)) {
1359 const char *start
= p
;
1360 while (++p
!= p_end
&& *p
!= kComma
)
1362 nsAutoCString
lang(Substring(start
, p
));
1363 lang
.CompressWhitespace(false, true);
1364 eFontPrefLang fpl
= gfxPlatform::GetFontPrefLangFor(lang
.get());
1366 case eFontPrefLang_Japanese
:
1367 case eFontPrefLang_Korean
:
1368 case eFontPrefLang_ChineseCN
:
1369 case eFontPrefLang_ChineseHK
:
1370 case eFontPrefLang_ChineseTW
:
1371 AppendPrefLang(tempPrefLangs
, tempLen
, fpl
);
1380 do { // to allow 'break' to abort this block if a call fails
1382 nsCOMPtr
<nsILocaleService
> ls
=
1383 do_GetService(NS_LOCALESERVICE_CONTRACTID
, &rv
);
1387 nsCOMPtr
<nsILocale
> appLocale
;
1388 rv
= ls
->GetApplicationLocale(getter_AddRefs(appLocale
));
1394 GetCategory(NS_LITERAL_STRING(NSILOCALE_MESSAGE
), localeStr
);
1398 const nsAString
& lang
= Substring(localeStr
, 0, 2);
1399 if (lang
.EqualsLiteral("ja")) {
1400 AppendPrefLang(tempPrefLangs
, tempLen
, eFontPrefLang_Japanese
);
1401 } else if (lang
.EqualsLiteral("zh")) {
1402 const nsAString
& region
= Substring(localeStr
, 3, 2);
1403 if (region
.EqualsLiteral("CN")) {
1404 AppendPrefLang(tempPrefLangs
, tempLen
, eFontPrefLang_ChineseCN
);
1405 } else if (region
.EqualsLiteral("TW")) {
1406 AppendPrefLang(tempPrefLangs
, tempLen
, eFontPrefLang_ChineseTW
);
1407 } else if (region
.EqualsLiteral("HK")) {
1408 AppendPrefLang(tempPrefLangs
, tempLen
, eFontPrefLang_ChineseHK
);
1410 } else if (lang
.EqualsLiteral("ko")) {
1411 AppendPrefLang(tempPrefLangs
, tempLen
, eFontPrefLang_Korean
);
1415 // last resort... (the order is same as old gfx.)
1416 AppendPrefLang(tempPrefLangs
, tempLen
, eFontPrefLang_Japanese
);
1417 AppendPrefLang(tempPrefLangs
, tempLen
, eFontPrefLang_Korean
);
1418 AppendPrefLang(tempPrefLangs
, tempLen
, eFontPrefLang_ChineseCN
);
1419 AppendPrefLang(tempPrefLangs
, tempLen
, eFontPrefLang_ChineseHK
);
1420 AppendPrefLang(tempPrefLangs
, tempLen
, eFontPrefLang_ChineseTW
);
1422 // copy into the cached array
1424 for (j
= 0; j
< tempLen
; j
++) {
1425 mCJKPrefLangs
.AppendElement(tempPrefLangs
[j
]);
1429 // append in cached CJK langs
1430 uint32_t i
, numCJKlangs
= mCJKPrefLangs
.Length();
1432 for (i
= 0; i
< numCJKlangs
; i
++) {
1433 AppendPrefLang(aPrefLangs
, aLen
, (eFontPrefLang
) (mCJKPrefLangs
[i
]));
1439 gfxPlatform::AppendPrefLang(eFontPrefLang aPrefLangs
[], uint32_t& aLen
, eFontPrefLang aAddLang
)
1441 if (aLen
>= kMaxLenPrefLangList
) return;
1445 while (i
< aLen
&& aPrefLangs
[i
] != aAddLang
) {
1450 aPrefLangs
[aLen
] = aAddLang
;
1456 gfxPlatform::InitBackendPrefs(uint32_t aCanvasBitmask
, BackendType aCanvasDefault
,
1457 uint32_t aContentBitmask
, BackendType aContentDefault
)
1459 mPreferredCanvasBackend
= GetCanvasBackendPref(aCanvasBitmask
);
1460 if (mPreferredCanvasBackend
== BackendType::NONE
) {
1461 mPreferredCanvasBackend
= aCanvasDefault
;
1463 mFallbackCanvasBackend
=
1464 GetCanvasBackendPref(aCanvasBitmask
& ~BackendTypeBit(mPreferredCanvasBackend
));
1466 mContentBackendBitmask
= aContentBitmask
;
1467 mContentBackend
= GetContentBackendPref(mContentBackendBitmask
);
1468 if (mContentBackend
== BackendType::NONE
) {
1469 mContentBackend
= aContentDefault
;
1470 // mContentBackendBitmask is our canonical reference for supported
1471 // backends so we need to add the default if we are using it and
1472 // overriding the prefs.
1473 mContentBackendBitmask
|= BackendTypeBit(aContentDefault
);
1477 /* static */ BackendType
1478 gfxPlatform::GetCanvasBackendPref(uint32_t aBackendBitmask
)
1480 return GetBackendPref("gfx.canvas.azure.backends", aBackendBitmask
);
1483 /* static */ BackendType
1484 gfxPlatform::GetContentBackendPref(uint32_t &aBackendBitmask
)
1486 return GetBackendPref("gfx.content.azure.backends", aBackendBitmask
);
1489 /* static */ BackendType
1490 gfxPlatform::GetBackendPref(const char* aBackendPrefName
, uint32_t &aBackendBitmask
)
1492 nsTArray
<nsCString
> backendList
;
1493 nsCString prefString
;
1494 if (NS_SUCCEEDED(Preferences::GetCString(aBackendPrefName
, &prefString
))) {
1495 ParseString(prefString
, ',', backendList
);
1498 uint32_t allowedBackends
= 0;
1499 BackendType result
= BackendType::NONE
;
1500 for (uint32_t i
= 0; i
< backendList
.Length(); ++i
) {
1501 BackendType type
= BackendTypeForName(backendList
[i
]);
1502 if (BackendTypeBit(type
) & aBackendBitmask
) {
1503 allowedBackends
|= BackendTypeBit(type
);
1504 if (result
== BackendType::NONE
) {
1510 aBackendBitmask
= allowedBackends
;
1515 gfxPlatform::OffMainThreadCompositingEnabled()
1517 return UsesOffMainThreadCompositing();
1521 gfxPlatform::GetCMSMode()
1523 if (gCMSInitialized
== false) {
1524 gCMSInitialized
= true;
1526 int32_t mode
= gfxPrefs::CMSMode();
1527 if (mode
>= 0 && mode
< eCMSMode_AllCount
) {
1528 gCMSMode
= static_cast<eCMSMode
>(mode
);
1531 bool enableV4
= gfxPrefs::CMSEnableV4();
1533 qcms_enable_iccv4();
1540 gfxPlatform::GetRenderingIntent()
1542 if (!gCMSIntentInitialized
) {
1543 gCMSIntentInitialized
= true;
1545 // gfxPrefs.h is using 0 as the default for the rendering
1546 // intent preference, based on that being the value for
1547 // QCMS_INTENT_DEFAULT. Assert here to catch if that ever
1548 // changes and we can then figure out what to do about it.
1549 MOZ_ASSERT(QCMS_INTENT_DEFAULT
== 0);
1551 /* Try to query the pref system for a rendering intent. */
1552 int32_t pIntent
= gfxPrefs::CMSRenderingIntent();
1553 if ((pIntent
>= QCMS_INTENT_MIN
) && (pIntent
<= QCMS_INTENT_MAX
)) {
1554 gCMSIntent
= pIntent
;
1556 /* If the pref is out of range, use embedded profile. */
1564 gfxPlatform::TransformPixel(const gfxRGBA
& in
, gfxRGBA
& out
, qcms_transform
*transform
)
1568 /* we want the bytes in RGB order */
1569 #ifdef IS_LITTLE_ENDIAN
1570 /* ABGR puts the bytes in |RGBA| order on little endian */
1571 uint32_t packed
= in
.Packed(gfxRGBA::PACKED_ABGR
);
1572 qcms_transform_data(transform
,
1573 (uint8_t *)&packed
, (uint8_t *)&packed
,
1576 new (&out
) gfxRGBA(packed
, gfxRGBA::PACKED_ABGR
);
1578 /* ARGB puts the bytes in |ARGB| order on big endian */
1579 uint32_t packed
= in
.Packed(gfxRGBA::PACKED_ARGB
);
1580 /* add one to move past the alpha byte */
1581 qcms_transform_data(transform
,
1582 (uint8_t *)&packed
+ 1, (uint8_t *)&packed
+ 1,
1585 new (&out
) gfxRGBA(packed
, gfxRGBA::PACKED_ARGB
);
1589 else if (&out
!= &in
)
1594 gfxPlatform::GetPlatformCMSOutputProfile(void *&mem
, size_t &size
)
1601 gfxPlatform::GetCMSOutputProfileData(void *&mem
, size_t &size
)
1603 nsAdoptingCString fname
= Preferences::GetCString("gfx.color_management.display_profile");
1604 if (!fname
.IsEmpty()) {
1605 qcms_data_from_path(fname
, &mem
, &size
);
1608 gfxPlatform::GetPlatform()->GetPlatformCMSOutputProfile(mem
, size
);
1613 gfxPlatform::CreateCMSOutputProfile()
1615 if (!gCMSOutputProfile
) {
1616 /* Determine if we're using the internal override to force sRGB as
1617 an output profile for reftests. See Bug 452125.
1619 Note that we don't normally (outside of tests) set a
1620 default value of this preference, which means nsIPrefBranch::GetBoolPref
1621 will typically throw (and leave its out-param untouched).
1623 if (Preferences::GetBool(GFX_PREF_CMS_FORCE_SRGB
, false)) {
1624 gCMSOutputProfile
= GetCMSsRGBProfile();
1627 if (!gCMSOutputProfile
) {
1628 void* mem
= nullptr;
1631 GetCMSOutputProfileData(mem
, size
);
1632 if ((mem
!= nullptr) && (size
> 0)) {
1633 gCMSOutputProfile
= qcms_profile_from_memory(mem
, size
);
1638 /* Determine if the profile looks bogus. If so, close the profile
1639 * and use sRGB instead. See bug 460629, */
1640 if (gCMSOutputProfile
&& qcms_profile_is_bogus(gCMSOutputProfile
)) {
1641 NS_ASSERTION(gCMSOutputProfile
!= GetCMSsRGBProfile(),
1642 "Builtin sRGB profile tagged as bogus!!!");
1643 qcms_profile_release(gCMSOutputProfile
);
1644 gCMSOutputProfile
= nullptr;
1647 if (!gCMSOutputProfile
) {
1648 gCMSOutputProfile
= GetCMSsRGBProfile();
1650 /* Precache the LUT16 Interpolations for the output profile. See
1651 bug 444661 for details. */
1652 qcms_profile_precache_output_transform(gCMSOutputProfile
);
1657 gfxPlatform::GetCMSOutputProfile()
1659 return gCMSOutputProfile
;
1663 gfxPlatform::GetCMSsRGBProfile()
1665 if (!gCMSsRGBProfile
) {
1667 /* Create the profile using qcms. */
1668 gCMSsRGBProfile
= qcms_profile_sRGB();
1670 return gCMSsRGBProfile
;
1674 gfxPlatform::GetCMSRGBTransform()
1676 if (!gCMSRGBTransform
) {
1677 qcms_profile
*inProfile
, *outProfile
;
1678 outProfile
= GetCMSOutputProfile();
1679 inProfile
= GetCMSsRGBProfile();
1681 if (!inProfile
|| !outProfile
)
1684 gCMSRGBTransform
= qcms_transform_create(inProfile
, QCMS_DATA_RGB_8
,
1685 outProfile
, QCMS_DATA_RGB_8
,
1686 QCMS_INTENT_PERCEPTUAL
);
1689 return gCMSRGBTransform
;
1693 gfxPlatform::GetCMSInverseRGBTransform()
1695 if (!gCMSInverseRGBTransform
) {
1696 qcms_profile
*inProfile
, *outProfile
;
1697 inProfile
= GetCMSOutputProfile();
1698 outProfile
= GetCMSsRGBProfile();
1700 if (!inProfile
|| !outProfile
)
1703 gCMSInverseRGBTransform
= qcms_transform_create(inProfile
, QCMS_DATA_RGB_8
,
1704 outProfile
, QCMS_DATA_RGB_8
,
1705 QCMS_INTENT_PERCEPTUAL
);
1708 return gCMSInverseRGBTransform
;
1712 gfxPlatform::GetCMSRGBATransform()
1714 if (!gCMSRGBATransform
) {
1715 qcms_profile
*inProfile
, *outProfile
;
1716 outProfile
= GetCMSOutputProfile();
1717 inProfile
= GetCMSsRGBProfile();
1719 if (!inProfile
|| !outProfile
)
1722 gCMSRGBATransform
= qcms_transform_create(inProfile
, QCMS_DATA_RGBA_8
,
1723 outProfile
, QCMS_DATA_RGBA_8
,
1724 QCMS_INTENT_PERCEPTUAL
);
1727 return gCMSRGBATransform
;
1730 /* Shuts down various transforms and profiles for CMS. */
1731 static void ShutdownCMS()
1734 if (gCMSRGBTransform
) {
1735 qcms_transform_release(gCMSRGBTransform
);
1736 gCMSRGBTransform
= nullptr;
1738 if (gCMSInverseRGBTransform
) {
1739 qcms_transform_release(gCMSInverseRGBTransform
);
1740 gCMSInverseRGBTransform
= nullptr;
1742 if (gCMSRGBATransform
) {
1743 qcms_transform_release(gCMSRGBATransform
);
1744 gCMSRGBATransform
= nullptr;
1746 if (gCMSOutputProfile
) {
1747 qcms_profile_release(gCMSOutputProfile
);
1749 // handle the aliased case
1750 if (gCMSsRGBProfile
== gCMSOutputProfile
)
1751 gCMSsRGBProfile
= nullptr;
1752 gCMSOutputProfile
= nullptr;
1754 if (gCMSsRGBProfile
) {
1755 qcms_profile_release(gCMSsRGBProfile
);
1756 gCMSsRGBProfile
= nullptr;
1759 // Reset the state variables
1761 gCMSMode
= eCMSMode_Off
;
1762 gCMSInitialized
= false;
1765 // default SetupClusterBoundaries, based on Unicode properties;
1766 // platform subclasses may override if they wish
1768 gfxPlatform::SetupClusterBoundaries(gfxTextRun
*aTextRun
, const char16_t
*aString
)
1770 if (aTextRun
->GetFlags() & gfxTextRunFactory::TEXT_IS_8BIT
) {
1771 // 8-bit text doesn't have clusters.
1772 // XXX is this true in all languages???
1773 // behdad: don't think so. Czech for example IIRC has a
1775 // jfkthame: but that's not expected to behave as a grapheme cluster
1776 // for selection/editing/etc.
1780 aTextRun
->SetupClusterBoundaries(0, aString
, aTextRun
->GetLength());
1784 gfxPlatform::GetBidiNumeralOption()
1786 if (mBidiNumeralOption
== UNINITIALIZED_VALUE
) {
1787 mBidiNumeralOption
= Preferences::GetInt(BIDI_NUMERAL_PREF
, 0);
1789 return mBidiNumeralOption
;
1793 FlushFontAndWordCaches()
1795 gfxFontCache
*fontCache
= gfxFontCache::GetCache();
1797 fontCache
->AgeAllGenerations();
1798 fontCache
->FlushShapedWordCaches();
1803 gfxPlatform::FontsPrefsChanged(const char *aPref
)
1805 NS_ASSERTION(aPref
!= nullptr, "null preference");
1806 if (!strcmp(GFX_DOWNLOADABLE_FONTS_ENABLED
, aPref
)) {
1807 mAllowDownloadableFonts
= UNINITIALIZED_VALUE
;
1808 } else if (!strcmp(GFX_PREF_FALLBACK_USE_CMAPS
, aPref
)) {
1809 mFallbackUsesCmaps
= UNINITIALIZED_VALUE
;
1810 } else if (!strcmp(GFX_PREF_WORD_CACHE_CHARLIMIT
, aPref
)) {
1811 mWordCacheCharLimit
= UNINITIALIZED_VALUE
;
1812 FlushFontAndWordCaches();
1813 } else if (!strcmp(GFX_PREF_WORD_CACHE_MAXENTRIES
, aPref
)) {
1814 mWordCacheMaxEntries
= UNINITIALIZED_VALUE
;
1815 FlushFontAndWordCaches();
1816 } else if (!strcmp(GFX_PREF_GRAPHITE_SHAPING
, aPref
)) {
1817 mGraphiteShapingEnabled
= UNINITIALIZED_VALUE
;
1818 FlushFontAndWordCaches();
1819 } else if (!strcmp(BIDI_NUMERAL_PREF
, aPref
)) {
1820 mBidiNumeralOption
= UNINITIALIZED_VALUE
;
1821 } else if (!strcmp(GFX_PREF_OPENTYPE_SVG
, aPref
)) {
1822 mOpenTypeSVGEnabled
= UNINITIALIZED_VALUE
;
1823 gfxFontCache::GetCache()->AgeAllGenerations();
1829 gfxPlatform::GetLog(eGfxLog aWhichLog
)
1831 // logs shared across gfx
1833 static PRLogModuleInfo
*sFontlistLog
= nullptr;
1834 static PRLogModuleInfo
*sFontInitLog
= nullptr;
1835 static PRLogModuleInfo
*sTextrunLog
= nullptr;
1836 static PRLogModuleInfo
*sTextrunuiLog
= nullptr;
1837 static PRLogModuleInfo
*sCmapDataLog
= nullptr;
1838 static PRLogModuleInfo
*sTextPerfLog
= nullptr;
1840 // Assume that if one is initialized, all are initialized
1841 if (!sFontlistLog
) {
1842 sFontlistLog
= PR_NewLogModule("fontlist");
1843 sFontInitLog
= PR_NewLogModule("fontinit");
1844 sTextrunLog
= PR_NewLogModule("textrun");
1845 sTextrunuiLog
= PR_NewLogModule("textrunui");
1846 sCmapDataLog
= PR_NewLogModule("cmapdata");
1847 sTextPerfLog
= PR_NewLogModule("textperf");
1850 switch (aWhichLog
) {
1851 case eGfxLog_fontlist
:
1852 return sFontlistLog
;
1854 case eGfxLog_fontinit
:
1855 return sFontInitLog
;
1857 case eGfxLog_textrun
:
1860 case eGfxLog_textrunui
:
1861 return sTextrunuiLog
;
1863 case eGfxLog_cmapdata
:
1864 return sCmapDataLog
;
1866 case eGfxLog_textperf
:
1867 return sTextPerfLog
;
1880 gfxPlatform::GetScreenDepth() const
1882 NS_WARNING("GetScreenDepth not implemented on this platform -- returning 0!");
1886 mozilla::gfx::SurfaceFormat
1887 gfxPlatform::Optimal2DFormatForContent(gfxContentType aContent
)
1890 case gfxContentType::COLOR
:
1891 switch (GetOffscreenFormat()) {
1892 case gfxImageFormat::ARGB32
:
1893 return mozilla::gfx::SurfaceFormat::B8G8R8A8
;
1894 case gfxImageFormat::RGB24
:
1895 return mozilla::gfx::SurfaceFormat::B8G8R8X8
;
1896 case gfxImageFormat::RGB16_565
:
1897 return mozilla::gfx::SurfaceFormat::R5G6B5
;
1899 NS_NOTREACHED("unknown gfxImageFormat for gfxContentType::COLOR");
1900 return mozilla::gfx::SurfaceFormat::B8G8R8A8
;
1902 case gfxContentType::ALPHA
:
1903 return mozilla::gfx::SurfaceFormat::A8
;
1904 case gfxContentType::COLOR_ALPHA
:
1905 return mozilla::gfx::SurfaceFormat::B8G8R8A8
;
1907 NS_NOTREACHED("unknown gfxContentType");
1908 return mozilla::gfx::SurfaceFormat::B8G8R8A8
;
1913 gfxPlatform::OptimalFormatForContent(gfxContentType aContent
)
1916 case gfxContentType::COLOR
:
1917 return GetOffscreenFormat();
1918 case gfxContentType::ALPHA
:
1919 return gfxImageFormat::A8
;
1920 case gfxContentType::COLOR_ALPHA
:
1921 return gfxImageFormat::ARGB32
;
1923 NS_NOTREACHED("unknown gfxContentType");
1924 return gfxImageFormat::ARGB32
;
1929 * There are a number of layers acceleration (or layers in general) preferences
1930 * that should be consistent for the lifetime of the application (bug 840967).
1931 * As such, we will evaluate them all as soon as one of them is evaluated
1932 * and remember the values. Changing these preferences during the run will
1933 * not have any effect until we restart.
1935 static bool sLayersSupportsD3D9
= false;
1936 static bool sLayersSupportsD3D11
= false;
1937 static bool sBufferRotationCheckPref
= true;
1938 static bool sPrefBrowserTabsRemoteAutostart
= false;
1940 static bool sLayersAccelerationPrefsInitialized
= false;
1943 InitLayersAccelerationPrefs()
1945 if (!sLayersAccelerationPrefsInitialized
)
1947 // If this is called for the first time on a non-main thread, we're screwed.
1948 // At the moment there's no explicit guarantee that the main thread calls
1949 // this before the compositor thread, but let's at least make the assumption
1951 MOZ_ASSERT(NS_IsMainThread(), "can only initialize prefs on the main thread");
1953 gfxPrefs::GetSingleton();
1954 sPrefBrowserTabsRemoteAutostart
= BrowserTabsRemoteAutostart();
1957 if (gfxPrefs::LayersAccelerationForceEnabled()) {
1958 sLayersSupportsD3D9
= true;
1959 sLayersSupportsD3D11
= true;
1961 nsCOMPtr
<nsIGfxInfo
> gfxInfo
= do_GetService("@mozilla.org/gfx/info;1");
1964 if (NS_SUCCEEDED(gfxInfo
->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS
, &status
))) {
1965 if (status
== nsIGfxInfo::FEATURE_STATUS_OK
) {
1966 sLayersSupportsD3D9
= true;
1969 if (NS_SUCCEEDED(gfxInfo
->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS
, &status
))) {
1970 if (status
== nsIGfxInfo::FEATURE_STATUS_OK
) {
1971 sLayersSupportsD3D11
= true;
1978 sLayersAccelerationPrefsInitialized
= true;
1983 gfxPlatform::CanUseDirect3D9()
1985 // this function is called from the compositor thread, so it is not
1986 // safe to init the prefs etc. from here.
1987 MOZ_ASSERT(sLayersAccelerationPrefsInitialized
);
1988 return sLayersSupportsD3D9
;
1992 gfxPlatform::CanUseDirect3D11()
1994 // this function is called from the compositor thread, so it is not
1995 // safe to init the prefs etc. from here.
1996 MOZ_ASSERT(sLayersAccelerationPrefsInitialized
);
1997 return sLayersSupportsD3D11
;
2001 gfxPlatform::BufferRotationEnabled()
2003 MutexAutoLock
autoLock(*gGfxPlatformPrefsLock
);
2005 return sBufferRotationCheckPref
&& gfxPrefs::BufferRotationEnabled();
2009 gfxPlatform::DisableBufferRotation()
2011 MutexAutoLock
autoLock(*gGfxPlatformPrefsLock
);
2013 sBufferRotationCheckPref
= false;
2016 TemporaryRef
<ScaledFont
>
2017 gfxPlatform::GetScaledFontForFontWithCairoSkia(DrawTarget
* aTarget
, gfxFont
* aFont
)
2019 NativeFont nativeFont
;
2020 if (aTarget
->GetBackendType() == BackendType::CAIRO
|| aTarget
->GetBackendType() == BackendType::SKIA
) {
2021 nativeFont
.mType
= NativeFontType::CAIRO_FONT_FACE
;
2022 nativeFont
.mFont
= aFont
->GetCairoScaledFont();
2023 return Factory::CreateScaledFontForNativeFont(nativeFont
, aFont
->GetAdjustedSize());
2030 gfxPlatform::UsesOffMainThreadCompositing()
2032 InitLayersAccelerationPrefs();
2033 static bool firstTime
= true;
2034 static bool result
= false;
2038 sPrefBrowserTabsRemoteAutostart
||
2039 gfxPrefs::LayersOffMainThreadCompositionEnabled() ||
2040 gfxPrefs::LayersOffMainThreadCompositionForceEnabled() ||
2041 gfxPrefs::LayersOffMainThreadCompositionTestingEnabled();
2042 #if defined(MOZ_WIDGET_GTK)
2043 // Linux users who chose OpenGL are being grandfathered in to OMTC
2044 result
|= gfxPrefs::LayersAccelerationForceEnabled();
2046 #if !defined(NIGHTLY_BUILD)
2047 // Yeah, these two env vars do the same thing.
2048 // I'm told that one of them is enabled on some test slaves config,
2049 // so be slightly careful if you think you can remove one of them.
2050 result
&= PR_GetEnv("MOZ_USE_OMTC") || PR_GetEnv("MOZ_OMTC_ENABLED");