gfx/thebes/gfxPlatform.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/thebes/gfxPlatform.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,2082 @@
     1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     1.5 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#ifdef MOZ_LOGGING
    1.10 +#define FORCE_PR_LOG /* Allow logging in the release build */
    1.11 +#endif
    1.12 +
    1.13 +#include "mozilla/layers/CompositorChild.h"
    1.14 +#include "mozilla/layers/CompositorParent.h"
    1.15 +#include "mozilla/layers/ImageBridgeChild.h"
    1.16 +#include "mozilla/layers/ISurfaceAllocator.h"     // for GfxMemoryImageReporter
    1.17 +
    1.18 +#include "prlog.h"
    1.19 +
    1.20 +#include "gfxPlatform.h"
    1.21 +#include "gfxPrefs.h"
    1.22 +
    1.23 +#ifdef XP_WIN
    1.24 +#include <process.h>
    1.25 +#define getpid _getpid
    1.26 +#else
    1.27 +#include <unistd.h>
    1.28 +#endif
    1.29 +
    1.30 +#include "nsXULAppAPI.h"
    1.31 +#include "nsDirectoryServiceUtils.h"
    1.32 +#include "nsDirectoryServiceDefs.h"
    1.33 +
    1.34 +#if defined(XP_WIN)
    1.35 +#include "gfxWindowsPlatform.h"
    1.36 +#include "gfxD2DSurface.h"
    1.37 +#elif defined(XP_MACOSX)
    1.38 +#include "gfxPlatformMac.h"
    1.39 +#include "gfxQuartzSurface.h"
    1.40 +#elif defined(MOZ_WIDGET_GTK)
    1.41 +#include "gfxPlatformGtk.h"
    1.42 +#elif defined(MOZ_WIDGET_QT)
    1.43 +#include "gfxQtPlatform.h"
    1.44 +#elif defined(ANDROID)
    1.45 +#include "gfxAndroidPlatform.h"
    1.46 +#endif
    1.47 +
    1.48 +#include "nsGkAtoms.h"
    1.49 +#include "gfxPlatformFontList.h"
    1.50 +#include "gfxContext.h"
    1.51 +#include "gfxImageSurface.h"
    1.52 +#include "nsUnicodeProperties.h"
    1.53 +#include "harfbuzz/hb.h"
    1.54 +#include "gfxGraphiteShaper.h"
    1.55 +#include "gfx2DGlue.h"
    1.56 +#include "gfxGradientCache.h"
    1.57 +
    1.58 +#include "nsUnicodeRange.h"
    1.59 +#include "nsServiceManagerUtils.h"
    1.60 +#include "nsTArray.h"
    1.61 +#include "nsILocaleService.h"
    1.62 +#include "nsIObserverService.h"
    1.63 +#include "MainThreadUtils.h"
    1.64 +
    1.65 +#include "nsWeakReference.h"
    1.66 +
    1.67 +#include "cairo.h"
    1.68 +#include "qcms.h"
    1.69 +
    1.70 +#include "plstr.h"
    1.71 +#include "nsCRT.h"
    1.72 +#include "GLContext.h"
    1.73 +#include "GLContextProvider.h"
    1.74 +
    1.75 +#ifdef MOZ_WIDGET_ANDROID
    1.76 +#include "TexturePoolOGL.h"
    1.77 +#endif
    1.78 +
    1.79 +#include "mozilla/Hal.h"
    1.80 +#ifdef USE_SKIA
    1.81 +#include "skia/SkGraphics.h"
    1.82 +
    1.83 +#include "SkiaGLGlue.h"
    1.84 +#else
    1.85 +class mozilla::gl::SkiaGLGlue : public GenericAtomicRefCounted {
    1.86 +};
    1.87 +#endif
    1.88 +
    1.89 +#include "mozilla/Preferences.h"
    1.90 +#include "mozilla/Assertions.h"
    1.91 +#include "mozilla/Attributes.h"
    1.92 +#include "mozilla/Mutex.h"
    1.93 +
    1.94 +#include "nsIGfxInfo.h"
    1.95 +#include "nsIXULRuntime.h"
    1.96 +
    1.97 +#ifdef MOZ_WIDGET_GONK
    1.98 +namespace mozilla {
    1.99 +namespace layers {
   1.100 +void InitGralloc();
   1.101 +}
   1.102 +}
   1.103 +#endif
   1.104 +
   1.105 +using namespace mozilla;
   1.106 +using namespace mozilla::layers;
   1.107 +
   1.108 +gfxPlatform *gPlatform = nullptr;
   1.109 +static bool gEverInitialized = false;
   1.110 +
   1.111 +static Mutex* gGfxPlatformPrefsLock = nullptr;
   1.112 +
   1.113 +// These two may point to the same profile
   1.114 +static qcms_profile *gCMSOutputProfile = nullptr;
   1.115 +static qcms_profile *gCMSsRGBProfile = nullptr;
   1.116 +
   1.117 +static qcms_transform *gCMSRGBTransform = nullptr;
   1.118 +static qcms_transform *gCMSInverseRGBTransform = nullptr;
   1.119 +static qcms_transform *gCMSRGBATransform = nullptr;
   1.120 +
   1.121 +static bool gCMSInitialized = false;
   1.122 +static eCMSMode gCMSMode = eCMSMode_Off;
   1.123 +
   1.124 +static bool gCMSIntentInitialized = false;
   1.125 +static int gCMSIntent = QCMS_INTENT_DEFAULT;
   1.126 +
   1.127 +
   1.128 +static void ShutdownCMS();
   1.129 +
   1.130 +#include "mozilla/gfx/2D.h"
   1.131 +using namespace mozilla::gfx;
   1.132 +
   1.133 +/* Class to listen for pref changes so that chrome code can dynamically
   1.134 +   force sRGB as an output profile. See Bug #452125. */
   1.135 +class SRGBOverrideObserver MOZ_FINAL : public nsIObserver,
   1.136 +                                       public nsSupportsWeakReference
   1.137 +{
   1.138 +public:
   1.139 +    NS_DECL_ISUPPORTS
   1.140 +    NS_DECL_NSIOBSERVER
   1.141 +};
   1.142 +
   1.143 +NS_IMPL_ISUPPORTS(SRGBOverrideObserver, nsIObserver, nsISupportsWeakReference)
   1.144 +
   1.145 +#define GFX_DOWNLOADABLE_FONTS_ENABLED "gfx.downloadable_fonts.enabled"
   1.146 +
   1.147 +#define GFX_PREF_HARFBUZZ_SCRIPTS "gfx.font_rendering.harfbuzz.scripts"
   1.148 +#define HARFBUZZ_SCRIPTS_DEFAULT  mozilla::unicode::SHAPING_DEFAULT
   1.149 +#define GFX_PREF_FALLBACK_USE_CMAPS  "gfx.font_rendering.fallback.always_use_cmaps"
   1.150 +
   1.151 +#define GFX_PREF_OPENTYPE_SVG "gfx.font_rendering.opentype_svg.enabled"
   1.152 +
   1.153 +#define GFX_PREF_WORD_CACHE_CHARLIMIT "gfx.font_rendering.wordcache.charlimit"
   1.154 +#define GFX_PREF_WORD_CACHE_MAXENTRIES "gfx.font_rendering.wordcache.maxentries"
   1.155 +
   1.156 +#define GFX_PREF_GRAPHITE_SHAPING "gfx.font_rendering.graphite.enabled"
   1.157 +
   1.158 +#define BIDI_NUMERAL_PREF "bidi.numeral"
   1.159 +
   1.160 +#define GFX_PREF_CMS_FORCE_SRGB "gfx.color_management.force_srgb"
   1.161 +
   1.162 +NS_IMETHODIMP
   1.163 +SRGBOverrideObserver::Observe(nsISupports *aSubject,
   1.164 +                              const char *aTopic,
   1.165 +                              const char16_t* someData)
   1.166 +{
   1.167 +    NS_ASSERTION(NS_strcmp(someData,
   1.168 +                           MOZ_UTF16(GFX_PREF_CMS_FORCE_SRGB)) == 0,
   1.169 +                 "Restarting CMS on wrong pref!");
   1.170 +    ShutdownCMS();
   1.171 +    return NS_OK;
   1.172 +}
   1.173 +
   1.174 +static const char* kObservedPrefs[] = {
   1.175 +    "gfx.downloadable_fonts.",
   1.176 +    "gfx.font_rendering.",
   1.177 +    BIDI_NUMERAL_PREF,
   1.178 +    nullptr
   1.179 +};
   1.180 +
   1.181 +class FontPrefsObserver MOZ_FINAL : public nsIObserver
   1.182 +{
   1.183 +public:
   1.184 +    NS_DECL_ISUPPORTS
   1.185 +    NS_DECL_NSIOBSERVER
   1.186 +};
   1.187 +
   1.188 +NS_IMPL_ISUPPORTS(FontPrefsObserver, nsIObserver)
   1.189 +
   1.190 +NS_IMETHODIMP
   1.191 +FontPrefsObserver::Observe(nsISupports *aSubject,
   1.192 +                           const char *aTopic,
   1.193 +                           const char16_t *someData)
   1.194 +{
   1.195 +    if (!someData) {
   1.196 +        NS_ERROR("font pref observer code broken");
   1.197 +        return NS_ERROR_UNEXPECTED;
   1.198 +    }
   1.199 +    NS_ASSERTION(gfxPlatform::GetPlatform(), "the singleton instance has gone");
   1.200 +    gfxPlatform::GetPlatform()->FontsPrefsChanged(NS_ConvertUTF16toUTF8(someData).get());
   1.201 +
   1.202 +    return NS_OK;
   1.203 +}
   1.204 +
   1.205 +class MemoryPressureObserver MOZ_FINAL : public nsIObserver
   1.206 +{
   1.207 +public:
   1.208 +    NS_DECL_ISUPPORTS
   1.209 +    NS_DECL_NSIOBSERVER
   1.210 +};
   1.211 +
   1.212 +NS_IMPL_ISUPPORTS(MemoryPressureObserver, nsIObserver)
   1.213 +
   1.214 +NS_IMETHODIMP
   1.215 +MemoryPressureObserver::Observe(nsISupports *aSubject,
   1.216 +                                const char *aTopic,
   1.217 +                                const char16_t *someData)
   1.218 +{
   1.219 +    NS_ASSERTION(strcmp(aTopic, "memory-pressure") == 0, "unexpected event topic");
   1.220 +    Factory::PurgeAllCaches();
   1.221 +
   1.222 +    gfxPlatform::GetPlatform()->PurgeSkiaCache();
   1.223 +    return NS_OK;
   1.224 +}
   1.225 +
   1.226 +// this needs to match the list of pref font.default.xx entries listed in all.js!
   1.227 +// the order *must* match the order in eFontPrefLang
   1.228 +static const char *gPrefLangNames[] = {
   1.229 +    "x-western",
   1.230 +    "x-central-euro",
   1.231 +    "ja",
   1.232 +    "zh-TW",
   1.233 +    "zh-CN",
   1.234 +    "zh-HK",
   1.235 +    "ko",
   1.236 +    "x-cyrillic",
   1.237 +    "x-baltic",
   1.238 +    "el",
   1.239 +    "tr",
   1.240 +    "th",
   1.241 +    "he",
   1.242 +    "ar",
   1.243 +    "x-devanagari",
   1.244 +    "x-tamil",
   1.245 +    "x-armn",
   1.246 +    "x-beng",
   1.247 +    "x-cans",
   1.248 +    "x-ethi",
   1.249 +    "x-geor",
   1.250 +    "x-gujr",
   1.251 +    "x-guru",
   1.252 +    "x-khmr",
   1.253 +    "x-mlym",
   1.254 +    "x-orya",
   1.255 +    "x-telu",
   1.256 +    "x-knda",
   1.257 +    "x-sinh",
   1.258 +    "x-tibt",
   1.259 +    "x-unicode",
   1.260 +};
   1.261 +
   1.262 +gfxPlatform::gfxPlatform()
   1.263 +  : mAzureCanvasBackendCollector(MOZ_THIS_IN_INITIALIZER_LIST(),
   1.264 +                                 &gfxPlatform::GetAzureBackendInfo)
   1.265 +{
   1.266 +    mUseHarfBuzzScripts = UNINITIALIZED_VALUE;
   1.267 +    mAllowDownloadableFonts = UNINITIALIZED_VALUE;
   1.268 +    mFallbackUsesCmaps = UNINITIALIZED_VALUE;
   1.269 +
   1.270 +    mWordCacheCharLimit = UNINITIALIZED_VALUE;
   1.271 +    mWordCacheMaxEntries = UNINITIALIZED_VALUE;
   1.272 +    mGraphiteShapingEnabled = UNINITIALIZED_VALUE;
   1.273 +    mOpenTypeSVGEnabled = UNINITIALIZED_VALUE;
   1.274 +    mBidiNumeralOption = UNINITIALIZED_VALUE;
   1.275 +
   1.276 +    mLayersPreferMemoryOverShmem = XRE_GetProcessType() == GeckoProcessType_Default;
   1.277 +
   1.278 +    mSkiaGlue = nullptr;
   1.279 +
   1.280 +    uint32_t canvasMask = BackendTypeBit(BackendType::CAIRO) | BackendTypeBit(BackendType::SKIA);
   1.281 +    uint32_t contentMask = BackendTypeBit(BackendType::CAIRO);
   1.282 +    InitBackendPrefs(canvasMask, BackendType::CAIRO,
   1.283 +                     contentMask, BackendType::CAIRO);
   1.284 +}
   1.285 +
   1.286 +gfxPlatform*
   1.287 +gfxPlatform::GetPlatform()
   1.288 +{
   1.289 +    if (!gPlatform) {
   1.290 +        Init();
   1.291 +    }
   1.292 +    return gPlatform;
   1.293 +}
   1.294 +
   1.295 +void RecordingPrefChanged(const char *aPrefName, void *aClosure)
   1.296 +{
   1.297 +  if (Preferences::GetBool("gfx.2d.recording", false)) {
   1.298 +    nsAutoCString fileName;
   1.299 +    nsAdoptingString prefFileName = Preferences::GetString("gfx.2d.recordingfile");
   1.300 +
   1.301 +    if (prefFileName) {
   1.302 +      fileName.Append(NS_ConvertUTF16toUTF8(prefFileName));
   1.303 +    } else {
   1.304 +      nsCOMPtr<nsIFile> tmpFile;
   1.305 +      if (NS_FAILED(NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tmpFile)))) {
   1.306 +        return;
   1.307 +      }
   1.308 +      fileName.AppendPrintf("moz2drec_%i_%i.aer", XRE_GetProcessType(), getpid());
   1.309 +
   1.310 +      nsresult rv = tmpFile->AppendNative(fileName);
   1.311 +      if (NS_FAILED(rv))
   1.312 +        return;
   1.313 +
   1.314 +      rv = tmpFile->GetNativePath(fileName);
   1.315 +      if (NS_FAILED(rv))
   1.316 +        return;
   1.317 +    }
   1.318 +
   1.319 +    gPlatform->mRecorder = Factory::CreateEventRecorderForFile(fileName.BeginReading());
   1.320 +    printf_stderr("Recording to %s\n", fileName.get());
   1.321 +    Factory::SetGlobalEventRecorder(gPlatform->mRecorder);
   1.322 +  } else {
   1.323 +    Factory::SetGlobalEventRecorder(nullptr);
   1.324 +  }
   1.325 +}
   1.326 +
   1.327 +void
   1.328 +gfxPlatform::Init()
   1.329 +{
   1.330 +    if (gEverInitialized) {
   1.331 +        NS_RUNTIMEABORT("Already started???");
   1.332 +    }
   1.333 +    gEverInitialized = true;
   1.334 +
   1.335 +    // Initialize the preferences by creating the singleton.
   1.336 +    gfxPrefs::GetSingleton();
   1.337 +
   1.338 +    gGfxPlatformPrefsLock = new Mutex("gfxPlatform::gGfxPlatformPrefsLock");
   1.339 +
   1.340 +    /* Initialize the GfxInfo service.
   1.341 +     * Note: we can't call functions on GfxInfo that depend
   1.342 +     * on gPlatform until after it has been initialized
   1.343 +     * below. GfxInfo initialization annotates our
   1.344 +     * crash reports so we want to do it before
   1.345 +     * we try to load any drivers and do device detection
   1.346 +     * incase that code crashes. See bug #591561. */
   1.347 +    nsCOMPtr<nsIGfxInfo> gfxInfo;
   1.348 +    /* this currently will only succeed on Windows */
   1.349 +    gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
   1.350 +
   1.351 +#if defined(XP_WIN)
   1.352 +    gPlatform = new gfxWindowsPlatform;
   1.353 +#elif defined(XP_MACOSX)
   1.354 +    gPlatform = new gfxPlatformMac;
   1.355 +#elif defined(MOZ_WIDGET_GTK)
   1.356 +    gPlatform = new gfxPlatformGtk;
   1.357 +#elif defined(MOZ_WIDGET_QT)
   1.358 +    gPlatform = new gfxQtPlatform;
   1.359 +#elif defined(ANDROID)
   1.360 +    gPlatform = new gfxAndroidPlatform;
   1.361 +#else
   1.362 +    #error "No gfxPlatform implementation available"
   1.363 +#endif
   1.364 +
   1.365 +#ifdef DEBUG
   1.366 +    mozilla::gl::GLContext::StaticInit();
   1.367 +#endif
   1.368 +
   1.369 +    bool useOffMainThreadCompositing = OffMainThreadCompositionRequired() ||
   1.370 +                                       GetPrefLayersOffMainThreadCompositionEnabled();
   1.371 +
   1.372 +    if (!OffMainThreadCompositionRequired()) {
   1.373 +      useOffMainThreadCompositing &= GetPlatform()->SupportsOffMainThreadCompositing();
   1.374 +    }
   1.375 +
   1.376 +    if (useOffMainThreadCompositing && (XRE_GetProcessType() == GeckoProcessType_Default)) {
   1.377 +        CompositorParent::StartUp();
   1.378 +        if (gfxPrefs::AsyncVideoEnabled()) {
   1.379 +            ImageBridgeChild::StartUp();
   1.380 +        }
   1.381 +    }
   1.382 +
   1.383 +    nsresult rv;
   1.384 +
   1.385 +#if defined(XP_MACOSX) || defined(XP_WIN) || defined(ANDROID) // temporary, until this is implemented on others
   1.386 +    rv = gfxPlatformFontList::Init();
   1.387 +    if (NS_FAILED(rv)) {
   1.388 +        NS_RUNTIMEABORT("Could not initialize gfxPlatformFontList");
   1.389 +    }
   1.390 +#endif
   1.391 +
   1.392 +    gPlatform->mScreenReferenceSurface =
   1.393 +        gPlatform->CreateOffscreenSurface(IntSize(1, 1),
   1.394 +                                          gfxContentType::COLOR_ALPHA);
   1.395 +    if (!gPlatform->mScreenReferenceSurface) {
   1.396 +        NS_RUNTIMEABORT("Could not initialize mScreenReferenceSurface");
   1.397 +    }
   1.398 +
   1.399 +    gPlatform->mScreenReferenceDrawTarget =
   1.400 +        gPlatform->CreateOffscreenContentDrawTarget(IntSize(1, 1),
   1.401 +                                                    SurfaceFormat::B8G8R8A8);
   1.402 +    if (!gPlatform->mScreenReferenceDrawTarget) {
   1.403 +      NS_RUNTIMEABORT("Could not initialize mScreenReferenceDrawTarget");
   1.404 +    }
   1.405 +
   1.406 +    rv = gfxFontCache::Init();
   1.407 +    if (NS_FAILED(rv)) {
   1.408 +        NS_RUNTIMEABORT("Could not initialize gfxFontCache");
   1.409 +    }
   1.410 +
   1.411 +    /* Create and register our CMS Override observer. */
   1.412 +    gPlatform->mSRGBOverrideObserver = new SRGBOverrideObserver();
   1.413 +    Preferences::AddWeakObserver(gPlatform->mSRGBOverrideObserver, GFX_PREF_CMS_FORCE_SRGB);
   1.414 +
   1.415 +    gPlatform->mFontPrefsObserver = new FontPrefsObserver();
   1.416 +    Preferences::AddStrongObservers(gPlatform->mFontPrefsObserver, kObservedPrefs);
   1.417 +
   1.418 +    mozilla::gl::GLContext::PlatformStartup();
   1.419 +
   1.420 +#ifdef MOZ_WIDGET_ANDROID
   1.421 +    // Texture pool init
   1.422 +    mozilla::gl::TexturePoolOGL::Init();
   1.423 +#endif
   1.424 +
   1.425 +#ifdef MOZ_WIDGET_GONK
   1.426 +    mozilla::layers::InitGralloc();
   1.427 +#endif
   1.428 +
   1.429 +    Preferences::RegisterCallbackAndCall(RecordingPrefChanged, "gfx.2d.recording", nullptr);
   1.430 +
   1.431 +    CreateCMSOutputProfile();
   1.432 +
   1.433 +    // Listen to memory pressure event so we can purge DrawTarget caches
   1.434 +    nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   1.435 +    if (obs) {
   1.436 +        gPlatform->mMemoryPressureObserver = new MemoryPressureObserver();
   1.437 +        obs->AddObserver(gPlatform->mMemoryPressureObserver, "memory-pressure", false);
   1.438 +    }
   1.439 +
   1.440 +    RegisterStrongMemoryReporter(new GfxMemoryImageReporter());
   1.441 +}
   1.442 +
   1.443 +void
   1.444 +gfxPlatform::Shutdown()
   1.445 +{
   1.446 +    // These may be called before the corresponding subsystems have actually
   1.447 +    // started up. That's OK, they can handle it.
   1.448 +    gfxFontCache::Shutdown();
   1.449 +    gfxFontGroup::Shutdown();
   1.450 +    gfxGradientCache::Shutdown();
   1.451 +    gfxGraphiteShaper::Shutdown();
   1.452 +#if defined(XP_MACOSX) || defined(XP_WIN) // temporary, until this is implemented on others
   1.453 +    gfxPlatformFontList::Shutdown();
   1.454 +#endif
   1.455 +
   1.456 +    // Free the various non-null transforms and loaded profiles
   1.457 +    ShutdownCMS();
   1.458 +
   1.459 +    // In some cases, gPlatform may not be created but Shutdown() called,
   1.460 +    // e.g., during xpcshell tests.
   1.461 +    if (gPlatform) {
   1.462 +        /* Unregister our CMS Override callback. */
   1.463 +        NS_ASSERTION(gPlatform->mSRGBOverrideObserver, "mSRGBOverrideObserver has alreay gone");
   1.464 +        Preferences::RemoveObserver(gPlatform->mSRGBOverrideObserver, GFX_PREF_CMS_FORCE_SRGB);
   1.465 +        gPlatform->mSRGBOverrideObserver = nullptr;
   1.466 +
   1.467 +        NS_ASSERTION(gPlatform->mFontPrefsObserver, "mFontPrefsObserver has alreay gone");
   1.468 +        Preferences::RemoveObservers(gPlatform->mFontPrefsObserver, kObservedPrefs);
   1.469 +        gPlatform->mFontPrefsObserver = nullptr;
   1.470 +
   1.471 +        NS_ASSERTION(gPlatform->mMemoryPressureObserver, "mMemoryPressureObserver has already gone");
   1.472 +        nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   1.473 +        if (obs) {
   1.474 +            obs->RemoveObserver(gPlatform->mMemoryPressureObserver, "memory-pressure");
   1.475 +        }
   1.476 +
   1.477 +        gPlatform->mMemoryPressureObserver = nullptr;
   1.478 +        gPlatform->mSkiaGlue = nullptr;
   1.479 +    }
   1.480 +
   1.481 +#ifdef MOZ_WIDGET_ANDROID
   1.482 +    // Shut down the texture pool
   1.483 +    mozilla::gl::TexturePoolOGL::Shutdown();
   1.484 +#endif
   1.485 +
   1.486 +    // Shut down the default GL context provider.
   1.487 +    mozilla::gl::GLContextProvider::Shutdown();
   1.488 +
   1.489 +#if defined(XP_WIN)
   1.490 +    // The above shutdown calls operate on the available context providers on
   1.491 +    // most platforms.  Windows is a "special snowflake", though, and has three
   1.492 +    // context providers available, so we have to shut all of them down.
   1.493 +    // We should only support the default GL provider on Windows; then, this
   1.494 +    // could go away. Unfortunately, we currently support WGL (the default) for
   1.495 +    // WebGL on Optimus.
   1.496 +    mozilla::gl::GLContextProviderEGL::Shutdown();
   1.497 +#endif
   1.498 +
   1.499 +    delete gGfxPlatformPrefsLock;
   1.500 +
   1.501 +    gfxPrefs::DestroySingleton();
   1.502 +    gfxFont::DestroySingletons();
   1.503 +
   1.504 +    delete gPlatform;
   1.505 +    gPlatform = nullptr;
   1.506 +}
   1.507 +
   1.508 +gfxPlatform::~gfxPlatform()
   1.509 +{
   1.510 +    mScreenReferenceSurface = nullptr;
   1.511 +    mScreenReferenceDrawTarget = nullptr;
   1.512 +
   1.513 +    // The cairo folks think we should only clean up in debug builds,
   1.514 +    // but we're generally in the habit of trying to shut down as
   1.515 +    // cleanly as possible even in production code, so call this
   1.516 +    // cairo_debug_* function unconditionally.
   1.517 +    //
   1.518 +    // because cairo can assert and thus crash on shutdown, don't do this in release builds
   1.519 +#if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING) || defined(NS_TRACE_MALLOC) || defined(MOZ_VALGRIND)
   1.520 +#ifdef USE_SKIA
   1.521 +    // must do Skia cleanup before Cairo cleanup, because Skia may be referencing
   1.522 +    // Cairo objects e.g. through SkCairoFTTypeface
   1.523 +    SkGraphics::Term();
   1.524 +#endif
   1.525 +
   1.526 +#if MOZ_TREE_CAIRO
   1.527 +    cairo_debug_reset_static_data();
   1.528 +#endif
   1.529 +#endif
   1.530 +}
   1.531 +
   1.532 +bool
   1.533 +gfxPlatform::PreferMemoryOverShmem() const {
   1.534 +  MOZ_ASSERT(!CompositorParent::IsInCompositorThread());
   1.535 +  return mLayersPreferMemoryOverShmem;
   1.536 +}
   1.537 +
   1.538 +already_AddRefed<gfxASurface>
   1.539 +gfxPlatform::CreateOffscreenImageSurface(const gfxIntSize& aSize,
   1.540 +                                         gfxContentType aContentType)
   1.541 +{
   1.542 +  nsRefPtr<gfxASurface> newSurface;
   1.543 +  newSurface = new gfxImageSurface(aSize, OptimalFormatForContent(aContentType));
   1.544 +
   1.545 +  return newSurface.forget();
   1.546 +}
   1.547 +
   1.548 +already_AddRefed<gfxASurface>
   1.549 +gfxPlatform::OptimizeImage(gfxImageSurface *aSurface,
   1.550 +                           gfxImageFormat format)
   1.551 +{
   1.552 +    IntSize surfaceSize = aSurface->GetSize().ToIntSize();
   1.553 +
   1.554 +#ifdef XP_WIN
   1.555 +    if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() ==
   1.556 +        gfxWindowsPlatform::RENDER_DIRECT2D) {
   1.557 +        return nullptr;
   1.558 +    }
   1.559 +#endif
   1.560 +    nsRefPtr<gfxASurface> optSurface = CreateOffscreenSurface(surfaceSize, gfxASurface::ContentFromFormat(format));
   1.561 +    if (!optSurface || optSurface->CairoStatus() != 0)
   1.562 +        return nullptr;
   1.563 +
   1.564 +    gfxContext tmpCtx(optSurface);
   1.565 +    tmpCtx.SetOperator(gfxContext::OPERATOR_SOURCE);
   1.566 +    tmpCtx.SetSource(aSurface);
   1.567 +    tmpCtx.Paint();
   1.568 +
   1.569 +    return optSurface.forget();
   1.570 +}
   1.571 +
   1.572 +cairo_user_data_key_t kDrawTarget;
   1.573 +
   1.574 +RefPtr<DrawTarget>
   1.575 +gfxPlatform::CreateDrawTargetForSurface(gfxASurface *aSurface, const IntSize& aSize)
   1.576 +{
   1.577 +  SurfaceFormat format = Optimal2DFormatForContent(aSurface->GetContentType());
   1.578 +  RefPtr<DrawTarget> drawTarget = Factory::CreateDrawTargetForCairoSurface(aSurface->CairoSurface(), aSize, &format);
   1.579 +  aSurface->SetData(&kDrawTarget, drawTarget, nullptr);
   1.580 +  return drawTarget;
   1.581 +}
   1.582 +
   1.583 +// This is a temporary function used by ContentClient to build a DrawTarget
   1.584 +// around the gfxASurface. This should eventually be replaced by plumbing
   1.585 +// the DrawTarget through directly
   1.586 +RefPtr<DrawTarget>
   1.587 +gfxPlatform::CreateDrawTargetForUpdateSurface(gfxASurface *aSurface, const IntSize& aSize)
   1.588 +{
   1.589 +#ifdef XP_MACOSX
   1.590 +  // this is a bit of a hack that assumes that the buffer associated with the CGContext
   1.591 +  // will live around long enough that nothing bad will happen.
   1.592 +  if (aSurface->GetType() == gfxSurfaceType::Quartz) {
   1.593 +    return Factory::CreateDrawTargetForCairoCGContext(static_cast<gfxQuartzSurface*>(aSurface)->GetCGContext(), aSize);
   1.594 +  }
   1.595 +#endif
   1.596 +  MOZ_CRASH();
   1.597 +  return nullptr;
   1.598 +}
   1.599 +
   1.600 +
   1.601 +cairo_user_data_key_t kSourceSurface;
   1.602 +
   1.603 +/**
   1.604 + * Record the backend that was used to construct the SourceSurface.
   1.605 + * When getting the cached SourceSurface for a gfxASurface/DrawTarget pair,
   1.606 + * we check to make sure the DrawTarget's backend matches the backend
   1.607 + * for the cached SourceSurface, and only use it if they match. This
   1.608 + * can avoid expensive and unnecessary readbacks.
   1.609 + */
   1.610 +struct SourceSurfaceUserData
   1.611 +{
   1.612 +  RefPtr<SourceSurface> mSrcSurface;
   1.613 +  BackendType mBackendType;
   1.614 +};
   1.615 +
   1.616 +void SourceBufferDestroy(void *srcSurfUD)
   1.617 +{
   1.618 +  delete static_cast<SourceSurfaceUserData*>(srcSurfUD);
   1.619 +}
   1.620 +
   1.621 +UserDataKey kThebesSurface;
   1.622 +
   1.623 +struct DependentSourceSurfaceUserData
   1.624 +{
   1.625 +  nsRefPtr<gfxASurface> mSurface;
   1.626 +};
   1.627 +
   1.628 +void SourceSurfaceDestroyed(void *aData)
   1.629 +{
   1.630 +  delete static_cast<DependentSourceSurfaceUserData*>(aData);
   1.631 +}
   1.632 +
   1.633 +#if MOZ_TREE_CAIRO
   1.634 +void SourceSnapshotDetached(cairo_surface_t *nullSurf)
   1.635 +{
   1.636 +  gfxImageSurface* origSurf =
   1.637 +    static_cast<gfxImageSurface*>(cairo_surface_get_user_data(nullSurf, &kSourceSurface));
   1.638 +
   1.639 +  origSurf->SetData(&kSourceSurface, nullptr, nullptr);
   1.640 +}
   1.641 +#else
   1.642 +void SourceSnapshotDetached(void *nullSurf)
   1.643 +{
   1.644 +  gfxImageSurface* origSurf = static_cast<gfxImageSurface*>(nullSurf);
   1.645 +  origSurf->SetData(&kSourceSurface, nullptr, nullptr);
   1.646 +}
   1.647 +#endif
   1.648 +
   1.649 +void
   1.650 +gfxPlatform::ClearSourceSurfaceForSurface(gfxASurface *aSurface)
   1.651 +{
   1.652 +  aSurface->SetData(&kSourceSurface, nullptr, nullptr);
   1.653 +}
   1.654 +
   1.655 +static TemporaryRef<DataSourceSurface>
   1.656 +CopySurface(gfxASurface* aSurface)
   1.657 +{
   1.658 +  const nsIntSize size = aSurface->GetSize();
   1.659 +  gfxImageFormat format = gfxPlatform::GetPlatform()->OptimalFormatForContent(aSurface->GetContentType());
   1.660 +  RefPtr<DataSourceSurface> data =
   1.661 +    Factory::CreateDataSourceSurface(ToIntSize(size),
   1.662 +                                     ImageFormatToSurfaceFormat(format));
   1.663 +  if (!data) {
   1.664 +    return nullptr;
   1.665 +  }
   1.666 +
   1.667 +  DataSourceSurface::MappedSurface map;
   1.668 +  DebugOnly<bool> result = data->Map(DataSourceSurface::WRITE, &map);
   1.669 +  MOZ_ASSERT(result, "Should always succeed mapping raw data surfaces!");
   1.670 +
   1.671 +  nsRefPtr<gfxImageSurface> image = new gfxImageSurface(map.mData, size, map.mStride, format);
   1.672 +  nsRefPtr<gfxContext> ctx = new gfxContext(image);
   1.673 +
   1.674 +  ctx->SetSource(aSurface);
   1.675 +  ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
   1.676 +  ctx->Paint();
   1.677 +
   1.678 +  data->Unmap();
   1.679 +
   1.680 +  return data;
   1.681 +}
   1.682 +
   1.683 +RefPtr<SourceSurface>
   1.684 +gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurface)
   1.685 +{
   1.686 +  if (!aSurface->CairoSurface() || aSurface->CairoStatus()) {
   1.687 +    return nullptr;
   1.688 +  }
   1.689 +
   1.690 +  if (!aTarget) {
   1.691 +    if (ScreenReferenceDrawTarget()) {
   1.692 +      aTarget = ScreenReferenceDrawTarget();
   1.693 +    } else {
   1.694 +      return nullptr;
   1.695 +    }
   1.696 +  }
   1.697 +
   1.698 +  void *userData = aSurface->GetData(&kSourceSurface);
   1.699 +
   1.700 +  if (userData) {
   1.701 +    SourceSurfaceUserData *surf = static_cast<SourceSurfaceUserData*>(userData);
   1.702 +
   1.703 +    if (surf->mSrcSurface->IsValid() && surf->mBackendType == aTarget->GetType()) {
   1.704 +      return surf->mSrcSurface;
   1.705 +    }
   1.706 +    // We can just continue here as when setting new user data the destroy
   1.707 +    // function will be called for the old user data.
   1.708 +  }
   1.709 +
   1.710 +  SurfaceFormat format;
   1.711 +  if (aSurface->GetContentType() == gfxContentType::ALPHA) {
   1.712 +    format = SurfaceFormat::A8;
   1.713 +  } else if (aSurface->GetContentType() == gfxContentType::COLOR) {
   1.714 +    format = SurfaceFormat::B8G8R8X8;
   1.715 +  } else {
   1.716 +    format = SurfaceFormat::B8G8R8A8;
   1.717 +  }
   1.718 +
   1.719 +  RefPtr<SourceSurface> srcBuffer;
   1.720 +
   1.721 +#ifdef XP_WIN
   1.722 +  if (aSurface->GetType() == gfxSurfaceType::D2D &&
   1.723 +      format != SurfaceFormat::A8) {
   1.724 +    NativeSurface surf;
   1.725 +    surf.mFormat = format;
   1.726 +    surf.mType = NativeSurfaceType::D3D10_TEXTURE;
   1.727 +    surf.mSurface = static_cast<gfxD2DSurface*>(aSurface)->GetTexture();
   1.728 +    surf.mSize = ToIntSize(aSurface->GetSize());
   1.729 +    mozilla::gfx::DrawTarget *dt = static_cast<mozilla::gfx::DrawTarget*>(aSurface->GetData(&kDrawTarget));
   1.730 +    if (dt) {
   1.731 +      dt->Flush();
   1.732 +    }
   1.733 +    srcBuffer = aTarget->CreateSourceSurfaceFromNativeSurface(surf);
   1.734 +  } else
   1.735 +#endif
   1.736 +  if (aSurface->CairoSurface() && aTarget->GetType() == BackendType::CAIRO) {
   1.737 +    // If this is an xlib cairo surface we don't want to fetch it into memory
   1.738 +    // because this is a major slow down.
   1.739 +    NativeSurface surf;
   1.740 +    surf.mFormat = format;
   1.741 +    surf.mType = NativeSurfaceType::CAIRO_SURFACE;
   1.742 +    surf.mSurface = aSurface->CairoSurface();
   1.743 +    surf.mSize = ToIntSize(aSurface->GetSize());
   1.744 +    srcBuffer = aTarget->CreateSourceSurfaceFromNativeSurface(surf);
   1.745 +
   1.746 +    if (srcBuffer) {
   1.747 +      // It's cheap enough to make a new one so we won't keep it around and
   1.748 +      // keeping it creates a cycle.
   1.749 +      return srcBuffer;
   1.750 +    }
   1.751 +  }
   1.752 +
   1.753 +  if (!srcBuffer) {
   1.754 +    nsRefPtr<gfxImageSurface> imgSurface = aSurface->GetAsImageSurface();
   1.755 +
   1.756 +    RefPtr<DataSourceSurface> dataSurf;
   1.757 +
   1.758 +    if (imgSurface) {
   1.759 +      dataSurf = GetWrappedDataSourceSurface(aSurface);
   1.760 +    } else {
   1.761 +      dataSurf = CopySurface(aSurface);
   1.762 +    }
   1.763 +
   1.764 +    if (!dataSurf) {
   1.765 +      return nullptr;
   1.766 +    }
   1.767 +
   1.768 +    srcBuffer = aTarget->OptimizeSourceSurface(dataSurf);
   1.769 +
   1.770 +    if (imgSurface && srcBuffer == dataSurf) {
   1.771 +      // Our wrapping surface will hold a reference to its image surface. We cause
   1.772 +      // a reference cycle if we add it to the cache. And caching it is pretty
   1.773 +      // pointless since we'll just wrap it again next use.
   1.774 +     return srcBuffer;
   1.775 +    }
   1.776 +  }
   1.777 +
   1.778 +  // Add user data to aSurface so we can cache lookups in the future.
   1.779 +  SourceSurfaceUserData *srcSurfUD = new SourceSurfaceUserData;
   1.780 +  srcSurfUD->mBackendType = aTarget->GetType();
   1.781 +  srcSurfUD->mSrcSurface = srcBuffer;
   1.782 +  aSurface->SetData(&kSourceSurface, srcSurfUD, SourceBufferDestroy);
   1.783 +
   1.784 +  return srcBuffer;
   1.785 +}
   1.786 +
   1.787 +RefPtr<DataSourceSurface>
   1.788 +gfxPlatform::GetWrappedDataSourceSurface(gfxASurface* aSurface)
   1.789 +{
   1.790 +  nsRefPtr<gfxImageSurface> image = aSurface->GetAsImageSurface();
   1.791 +  if (!image) {
   1.792 +    return nullptr;
   1.793 +  }
   1.794 +  RefPtr<DataSourceSurface> result =
   1.795 +    Factory::CreateWrappingDataSourceSurface(image->Data(),
   1.796 +                                             image->Stride(),
   1.797 +                                             ToIntSize(image->GetSize()),
   1.798 +                                             ImageFormatToSurfaceFormat(image->Format()));
   1.799 +
   1.800 +  if (!result) {
   1.801 +    return nullptr;
   1.802 +  }
   1.803 +
   1.804 +  // If we wrapped the underlying data of aSurface, then we need to add user data
   1.805 +  // to make sure aSurface stays alive until we are done with the data.
   1.806 +  DependentSourceSurfaceUserData *srcSurfUD = new DependentSourceSurfaceUserData;
   1.807 +  srcSurfUD->mSurface = aSurface;
   1.808 +  result->AddUserData(&kThebesSurface, srcSurfUD, SourceSurfaceDestroyed);
   1.809 +
   1.810 +  return result;
   1.811 +}
   1.812 +
   1.813 +TemporaryRef<ScaledFont>
   1.814 +gfxPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
   1.815 +{
   1.816 +  NativeFont nativeFont;
   1.817 +  nativeFont.mType = NativeFontType::CAIRO_FONT_FACE;
   1.818 +  nativeFont.mFont = aFont->GetCairoScaledFont();
   1.819 +  RefPtr<ScaledFont> scaledFont =
   1.820 +    Factory::CreateScaledFontForNativeFont(nativeFont,
   1.821 +                                           aFont->GetAdjustedSize());
   1.822 +  return scaledFont;
   1.823 +}
   1.824 +
   1.825 +cairo_user_data_key_t kDrawSourceSurface;
   1.826 +static void
   1.827 +DataSourceSurfaceDestroy(void *dataSourceSurface)
   1.828 +{
   1.829 +  static_cast<DataSourceSurface*>(dataSourceSurface)->Release();
   1.830 +}
   1.831 +
   1.832 +cairo_user_data_key_t kDrawTargetForSurface;
   1.833 +static void
   1.834 +DataDrawTargetDestroy(void *aTarget)
   1.835 +{
   1.836 +  static_cast<DrawTarget*>(aTarget)->Release();
   1.837 +}
   1.838 +
   1.839 +bool
   1.840 +gfxPlatform::SupportsAzureContentForDrawTarget(DrawTarget* aTarget)
   1.841 +{
   1.842 +  if (!aTarget) {
   1.843 +    return false;
   1.844 +  }
   1.845 +
   1.846 +  return SupportsAzureContentForType(aTarget->GetType());
   1.847 +}
   1.848 +
   1.849 +bool
   1.850 +gfxPlatform::UseAcceleratedSkiaCanvas()
   1.851 +{
   1.852 +  return gfxPrefs::CanvasAzureAccelerated() &&
   1.853 +         mPreferredCanvasBackend == BackendType::SKIA;
   1.854 +}
   1.855 +
   1.856 +void
   1.857 +gfxPlatform::InitializeSkiaCacheLimits()
   1.858 +{
   1.859 +  if (UseAcceleratedSkiaCanvas()) {
   1.860 +    bool usingDynamicCache = gfxPrefs::CanvasSkiaGLDynamicCache();
   1.861 +    int cacheItemLimit = gfxPrefs::CanvasSkiaGLCacheItems();
   1.862 +    int cacheSizeLimit = gfxPrefs::CanvasSkiaGLCacheSize();
   1.863 +
   1.864 +    // Prefs are in megabytes, but we want the sizes in bytes
   1.865 +    cacheSizeLimit *= 1024*1024;
   1.866 +
   1.867 +    if (usingDynamicCache) {
   1.868 +      uint32_t totalMemory = mozilla::hal::GetTotalSystemMemory();
   1.869 +
   1.870 +      if (totalMemory <= 256*1024*1024) {
   1.871 +        // We need a very minimal cache on 256 meg devices
   1.872 +        cacheSizeLimit = 2*1024*1024;
   1.873 +      } else if (totalMemory > 0) {
   1.874 +        cacheSizeLimit = totalMemory / 16;
   1.875 +      }
   1.876 +    }
   1.877 +
   1.878 +  #ifdef DEBUG
   1.879 +    printf_stderr("Determined SkiaGL cache limits: Size %i, Items: %i\n", cacheSizeLimit, cacheItemLimit);
   1.880 +  #endif
   1.881 +
   1.882 +#ifdef USE_SKIA_GPU
   1.883 +    mSkiaGlue->GetGrContext()->setTextureCacheLimits(cacheItemLimit, cacheSizeLimit);
   1.884 +#endif
   1.885 +  }
   1.886 +}
   1.887 +
   1.888 +mozilla::gl::SkiaGLGlue*
   1.889 +gfxPlatform::GetSkiaGLGlue()
   1.890 +{
   1.891 +#ifdef USE_SKIA_GPU
   1.892 +  if (!mSkiaGlue) {
   1.893 +    /* Dummy context. We always draw into a FBO.
   1.894 +     *
   1.895 +     * FIXME: This should be stored in TLS or something, since there needs to be one for each thread using it. As it
   1.896 +     * stands, this only works on the main thread.
   1.897 +     */
   1.898 +    mozilla::gfx::SurfaceCaps caps = mozilla::gfx::SurfaceCaps::ForRGBA();
   1.899 +    nsRefPtr<mozilla::gl::GLContext> glContext = mozilla::gl::GLContextProvider::CreateOffscreen(gfxIntSize(16, 16), caps);
   1.900 +    if (!glContext) {
   1.901 +      printf_stderr("Failed to create GLContext for SkiaGL!\n");
   1.902 +      return nullptr;
   1.903 +    }
   1.904 +    mSkiaGlue = new mozilla::gl::SkiaGLGlue(glContext);
   1.905 +    MOZ_ASSERT(mSkiaGlue->GetGrContext(), "No GrContext");
   1.906 +    InitializeSkiaCacheLimits();
   1.907 +  }
   1.908 +#endif
   1.909 +
   1.910 +  return mSkiaGlue;
   1.911 +}
   1.912 +
   1.913 +void
   1.914 +gfxPlatform::PurgeSkiaCache()
   1.915 +{
   1.916 +#ifdef USE_SKIA_GPU
   1.917 +  if (!mSkiaGlue)
   1.918 +      return;
   1.919 +
   1.920 +  mSkiaGlue->GetGrContext()->freeGpuResources();
   1.921 +#endif
   1.922 +}
   1.923 +
   1.924 +already_AddRefed<gfxASurface>
   1.925 +gfxPlatform::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
   1.926 +{
   1.927 +  if (aTarget->GetType() == BackendType::CAIRO) {
   1.928 +    cairo_surface_t* csurf =
   1.929 +      static_cast<cairo_surface_t*>(aTarget->GetNativeSurface(NativeSurfaceType::CAIRO_SURFACE));
   1.930 +    if (csurf) {
   1.931 +      return gfxASurface::Wrap(csurf);
   1.932 +    }
   1.933 +  }
   1.934 +
   1.935 +  // The semantics of this part of the function are sort of weird. If we
   1.936 +  // don't have direct support for the backend, we snapshot the first time
   1.937 +  // and then return the snapshotted surface for the lifetime of the draw
   1.938 +  // target. Sometimes it seems like this works out, but it seems like it
   1.939 +  // might result in no updates ever.
   1.940 +  RefPtr<SourceSurface> source = aTarget->Snapshot();
   1.941 +  RefPtr<DataSourceSurface> data = source->GetDataSurface();
   1.942 +
   1.943 +  if (!data) {
   1.944 +    return nullptr;
   1.945 +  }
   1.946 +
   1.947 +  IntSize size = data->GetSize();
   1.948 +  gfxImageFormat format = SurfaceFormatToImageFormat(data->GetFormat());
   1.949 +
   1.950 +
   1.951 +  nsRefPtr<gfxASurface> surf =
   1.952 +    new gfxImageSurface(data->GetData(), gfxIntSize(size.width, size.height),
   1.953 +                        data->Stride(), format);
   1.954 +
   1.955 +  if (surf->CairoStatus()) {
   1.956 +    return nullptr;
   1.957 +  }
   1.958 +
   1.959 +  surf->SetData(&kDrawSourceSurface, data.forget().drop(), DataSourceSurfaceDestroy);
   1.960 +  // keep the draw target alive as long as we need its data
   1.961 +  aTarget->AddRef();
   1.962 +  surf->SetData(&kDrawTargetForSurface, aTarget, DataDrawTargetDestroy);
   1.963 +
   1.964 +  return surf.forget();
   1.965 +}
   1.966 +
   1.967 +RefPtr<DrawTarget>
   1.968 +gfxPlatform::CreateDrawTargetForBackend(BackendType aBackend, const IntSize& aSize, SurfaceFormat aFormat)
   1.969 +{
   1.970 +  // There is a bunch of knowledge in the gfxPlatform heirarchy about how to
   1.971 +  // create the best offscreen surface for the current system and situation. We
   1.972 +  // can easily take advantage of this for the Cairo backend, so that's what we
   1.973 +  // do.
   1.974 +  // mozilla::gfx::Factory can get away without having all this knowledge for
   1.975 +  // now, but this might need to change in the future (using
   1.976 +  // CreateOffscreenSurface() and CreateDrawTargetForSurface() for all
   1.977 +  // backends).
   1.978 +  if (aBackend == BackendType::CAIRO) {
   1.979 +    nsRefPtr<gfxASurface> surf = CreateOffscreenSurface(aSize,
   1.980 +                                                        ContentForFormat(aFormat));
   1.981 +    if (!surf || surf->CairoStatus()) {
   1.982 +      return nullptr;
   1.983 +    }
   1.984 +
   1.985 +    return CreateDrawTargetForSurface(surf, aSize);
   1.986 +  } else {
   1.987 +    return Factory::CreateDrawTarget(aBackend, aSize, aFormat);
   1.988 +  }
   1.989 +}
   1.990 +
   1.991 +RefPtr<DrawTarget>
   1.992 +gfxPlatform::CreateOffscreenCanvasDrawTarget(const IntSize& aSize, SurfaceFormat aFormat)
   1.993 +{
   1.994 +  NS_ASSERTION(mPreferredCanvasBackend != BackendType::NONE, "No backend.");
   1.995 +  RefPtr<DrawTarget> target = CreateDrawTargetForBackend(mPreferredCanvasBackend, aSize, aFormat);
   1.996 +  if (target ||
   1.997 +      mFallbackCanvasBackend == BackendType::NONE) {
   1.998 +    return target;
   1.999 +  }
  1.1000 +
  1.1001 +  return CreateDrawTargetForBackend(mFallbackCanvasBackend, aSize, aFormat);
  1.1002 +}
  1.1003 +
  1.1004 +RefPtr<DrawTarget>
  1.1005 +gfxPlatform::CreateOffscreenContentDrawTarget(const IntSize& aSize, SurfaceFormat aFormat)
  1.1006 +{
  1.1007 +  NS_ASSERTION(mPreferredCanvasBackend != BackendType::NONE, "No backend.");
  1.1008 +  return CreateDrawTargetForBackend(mContentBackend, aSize, aFormat);
  1.1009 +}
  1.1010 +
  1.1011 +RefPtr<DrawTarget>
  1.1012 +gfxPlatform::CreateDrawTargetForData(unsigned char* aData, const IntSize& aSize, int32_t aStride, SurfaceFormat aFormat)
  1.1013 +{
  1.1014 +  NS_ASSERTION(mContentBackend != BackendType::NONE, "No backend.");
  1.1015 +  if (mContentBackend == BackendType::CAIRO) {
  1.1016 +    nsRefPtr<gfxImageSurface> image = new gfxImageSurface(aData, gfxIntSize(aSize.width, aSize.height), aStride, SurfaceFormatToImageFormat(aFormat));
  1.1017 +    return Factory::CreateDrawTargetForCairoSurface(image->CairoSurface(), aSize);
  1.1018 +  }
  1.1019 +  return Factory::CreateDrawTargetForData(mContentBackend, aData, aSize, aStride, aFormat);
  1.1020 +}
  1.1021 +
  1.1022 +/* static */ BackendType
  1.1023 +gfxPlatform::BackendTypeForName(const nsCString& aName)
  1.1024 +{
  1.1025 +  if (aName.EqualsLiteral("cairo"))
  1.1026 +    return BackendType::CAIRO;
  1.1027 +  if (aName.EqualsLiteral("skia"))
  1.1028 +    return BackendType::SKIA;
  1.1029 +  if (aName.EqualsLiteral("direct2d"))
  1.1030 +    return BackendType::DIRECT2D;
  1.1031 +  if (aName.EqualsLiteral("cg"))
  1.1032 +    return BackendType::COREGRAPHICS;
  1.1033 +  return BackendType::NONE;
  1.1034 +}
  1.1035 +
  1.1036 +nsresult
  1.1037 +gfxPlatform::GetFontList(nsIAtom *aLangGroup,
  1.1038 +                         const nsACString& aGenericFamily,
  1.1039 +                         nsTArray<nsString>& aListOfFonts)
  1.1040 +{
  1.1041 +    return NS_ERROR_NOT_IMPLEMENTED;
  1.1042 +}
  1.1043 +
  1.1044 +nsresult
  1.1045 +gfxPlatform::UpdateFontList()
  1.1046 +{
  1.1047 +    return NS_ERROR_NOT_IMPLEMENTED;
  1.1048 +}
  1.1049 +
  1.1050 +bool
  1.1051 +gfxPlatform::DownloadableFontsEnabled()
  1.1052 +{
  1.1053 +    if (mAllowDownloadableFonts == UNINITIALIZED_VALUE) {
  1.1054 +        mAllowDownloadableFonts =
  1.1055 +            Preferences::GetBool(GFX_DOWNLOADABLE_FONTS_ENABLED, false);
  1.1056 +    }
  1.1057 +
  1.1058 +    return mAllowDownloadableFonts;
  1.1059 +}
  1.1060 +
  1.1061 +bool
  1.1062 +gfxPlatform::UseCmapsDuringSystemFallback()
  1.1063 +{
  1.1064 +    if (mFallbackUsesCmaps == UNINITIALIZED_VALUE) {
  1.1065 +        mFallbackUsesCmaps =
  1.1066 +            Preferences::GetBool(GFX_PREF_FALLBACK_USE_CMAPS, false);
  1.1067 +    }
  1.1068 +
  1.1069 +    return mFallbackUsesCmaps;
  1.1070 +}
  1.1071 +
  1.1072 +bool
  1.1073 +gfxPlatform::OpenTypeSVGEnabled()
  1.1074 +{
  1.1075 +    if (mOpenTypeSVGEnabled == UNINITIALIZED_VALUE) {
  1.1076 +        mOpenTypeSVGEnabled =
  1.1077 +            Preferences::GetBool(GFX_PREF_OPENTYPE_SVG, false);
  1.1078 +    }
  1.1079 +
  1.1080 +    return mOpenTypeSVGEnabled > 0;
  1.1081 +}
  1.1082 +
  1.1083 +uint32_t
  1.1084 +gfxPlatform::WordCacheCharLimit()
  1.1085 +{
  1.1086 +    if (mWordCacheCharLimit == UNINITIALIZED_VALUE) {
  1.1087 +        mWordCacheCharLimit =
  1.1088 +            Preferences::GetInt(GFX_PREF_WORD_CACHE_CHARLIMIT, 32);
  1.1089 +        if (mWordCacheCharLimit < 0) {
  1.1090 +            mWordCacheCharLimit = 32;
  1.1091 +        }
  1.1092 +    }
  1.1093 +
  1.1094 +    return uint32_t(mWordCacheCharLimit);
  1.1095 +}
  1.1096 +
  1.1097 +uint32_t
  1.1098 +gfxPlatform::WordCacheMaxEntries()
  1.1099 +{
  1.1100 +    if (mWordCacheMaxEntries == UNINITIALIZED_VALUE) {
  1.1101 +        mWordCacheMaxEntries =
  1.1102 +            Preferences::GetInt(GFX_PREF_WORD_CACHE_MAXENTRIES, 10000);
  1.1103 +        if (mWordCacheMaxEntries < 0) {
  1.1104 +            mWordCacheMaxEntries = 10000;
  1.1105 +        }
  1.1106 +    }
  1.1107 +
  1.1108 +    return uint32_t(mWordCacheMaxEntries);
  1.1109 +}
  1.1110 +
  1.1111 +bool
  1.1112 +gfxPlatform::UseGraphiteShaping()
  1.1113 +{
  1.1114 +    if (mGraphiteShapingEnabled == UNINITIALIZED_VALUE) {
  1.1115 +        mGraphiteShapingEnabled =
  1.1116 +            Preferences::GetBool(GFX_PREF_GRAPHITE_SHAPING, false);
  1.1117 +    }
  1.1118 +
  1.1119 +    return mGraphiteShapingEnabled;
  1.1120 +}
  1.1121 +
  1.1122 +bool
  1.1123 +gfxPlatform::UseHarfBuzzForScript(int32_t aScriptCode)
  1.1124 +{
  1.1125 +    if (mUseHarfBuzzScripts == UNINITIALIZED_VALUE) {
  1.1126 +        mUseHarfBuzzScripts = Preferences::GetInt(GFX_PREF_HARFBUZZ_SCRIPTS, HARFBUZZ_SCRIPTS_DEFAULT);
  1.1127 +    }
  1.1128 +
  1.1129 +    int32_t shapingType = mozilla::unicode::ScriptShapingType(aScriptCode);
  1.1130 +
  1.1131 +    return (mUseHarfBuzzScripts & shapingType) != 0;
  1.1132 +}
  1.1133 +
  1.1134 +gfxFontEntry*
  1.1135 +gfxPlatform::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
  1.1136 +                              const uint8_t *aFontData,
  1.1137 +                              uint32_t aLength)
  1.1138 +{
  1.1139 +    // Default implementation does not handle activating downloaded fonts;
  1.1140 +    // just free the data and return.
  1.1141 +    // Platforms that support @font-face must override this,
  1.1142 +    // using the data to instantiate the font, and taking responsibility
  1.1143 +    // for freeing it when no longer required.
  1.1144 +    if (aFontData) {
  1.1145 +        NS_Free((void*)aFontData);
  1.1146 +    }
  1.1147 +    return nullptr;
  1.1148 +}
  1.1149 +
  1.1150 +static void
  1.1151 +AppendGenericFontFromPref(nsString& aFonts, nsIAtom *aLangGroup, const char *aGenericName)
  1.1152 +{
  1.1153 +    NS_ENSURE_TRUE_VOID(Preferences::GetRootBranch());
  1.1154 +
  1.1155 +    nsAutoCString prefName, langGroupString;
  1.1156 +
  1.1157 +    aLangGroup->ToUTF8String(langGroupString);
  1.1158 +
  1.1159 +    nsAutoCString genericDotLang;
  1.1160 +    if (aGenericName) {
  1.1161 +        genericDotLang.Assign(aGenericName);
  1.1162 +    } else {
  1.1163 +        prefName.AssignLiteral("font.default.");
  1.1164 +        prefName.Append(langGroupString);
  1.1165 +        genericDotLang = Preferences::GetCString(prefName.get());
  1.1166 +    }
  1.1167 +
  1.1168 +    genericDotLang.AppendLiteral(".");
  1.1169 +    genericDotLang.Append(langGroupString);
  1.1170 +
  1.1171 +    // fetch font.name.xxx value
  1.1172 +    prefName.AssignLiteral("font.name.");
  1.1173 +    prefName.Append(genericDotLang);
  1.1174 +    nsAdoptingString nameValue = Preferences::GetString(prefName.get());
  1.1175 +    if (nameValue) {
  1.1176 +        if (!aFonts.IsEmpty())
  1.1177 +            aFonts.AppendLiteral(", ");
  1.1178 +        aFonts += nameValue;
  1.1179 +    }
  1.1180 +
  1.1181 +    // fetch font.name-list.xxx value
  1.1182 +    prefName.AssignLiteral("font.name-list.");
  1.1183 +    prefName.Append(genericDotLang);
  1.1184 +    nsAdoptingString nameListValue = Preferences::GetString(prefName.get());
  1.1185 +    if (nameListValue && !nameListValue.Equals(nameValue)) {
  1.1186 +        if (!aFonts.IsEmpty())
  1.1187 +            aFonts.AppendLiteral(", ");
  1.1188 +        aFonts += nameListValue;
  1.1189 +    }
  1.1190 +}
  1.1191 +
  1.1192 +void
  1.1193 +gfxPlatform::GetPrefFonts(nsIAtom *aLanguage, nsString& aFonts, bool aAppendUnicode)
  1.1194 +{
  1.1195 +    aFonts.Truncate();
  1.1196 +
  1.1197 +    AppendGenericFontFromPref(aFonts, aLanguage, nullptr);
  1.1198 +    if (aAppendUnicode)
  1.1199 +        AppendGenericFontFromPref(aFonts, nsGkAtoms::Unicode, nullptr);
  1.1200 +}
  1.1201 +
  1.1202 +bool gfxPlatform::ForEachPrefFont(eFontPrefLang aLangArray[], uint32_t aLangArrayLen, PrefFontCallback aCallback,
  1.1203 +                                    void *aClosure)
  1.1204 +{
  1.1205 +    NS_ENSURE_TRUE(Preferences::GetRootBranch(), false);
  1.1206 +
  1.1207 +    uint32_t    i;
  1.1208 +    for (i = 0; i < aLangArrayLen; i++) {
  1.1209 +        eFontPrefLang prefLang = aLangArray[i];
  1.1210 +        const char *langGroup = GetPrefLangName(prefLang);
  1.1211 +
  1.1212 +        nsAutoCString prefName;
  1.1213 +
  1.1214 +        prefName.AssignLiteral("font.default.");
  1.1215 +        prefName.Append(langGroup);
  1.1216 +        nsAdoptingCString genericDotLang = Preferences::GetCString(prefName.get());
  1.1217 +
  1.1218 +        genericDotLang.AppendLiteral(".");
  1.1219 +        genericDotLang.Append(langGroup);
  1.1220 +
  1.1221 +        // fetch font.name.xxx value
  1.1222 +        prefName.AssignLiteral("font.name.");
  1.1223 +        prefName.Append(genericDotLang);
  1.1224 +        nsAdoptingCString nameValue = Preferences::GetCString(prefName.get());
  1.1225 +        if (nameValue) {
  1.1226 +            if (!aCallback(prefLang, NS_ConvertUTF8toUTF16(nameValue), aClosure))
  1.1227 +                return false;
  1.1228 +        }
  1.1229 +
  1.1230 +        // fetch font.name-list.xxx value
  1.1231 +        prefName.AssignLiteral("font.name-list.");
  1.1232 +        prefName.Append(genericDotLang);
  1.1233 +        nsAdoptingCString nameListValue = Preferences::GetCString(prefName.get());
  1.1234 +        if (nameListValue && !nameListValue.Equals(nameValue)) {
  1.1235 +            const char kComma = ',';
  1.1236 +            const char *p, *p_end;
  1.1237 +            nsAutoCString list(nameListValue);
  1.1238 +            list.BeginReading(p);
  1.1239 +            list.EndReading(p_end);
  1.1240 +            while (p < p_end) {
  1.1241 +                while (nsCRT::IsAsciiSpace(*p)) {
  1.1242 +                    if (++p == p_end)
  1.1243 +                        break;
  1.1244 +                }
  1.1245 +                if (p == p_end)
  1.1246 +                    break;
  1.1247 +                const char *start = p;
  1.1248 +                while (++p != p_end && *p != kComma)
  1.1249 +                    /* nothing */ ;
  1.1250 +                nsAutoCString fontName(Substring(start, p));
  1.1251 +                fontName.CompressWhitespace(false, true);
  1.1252 +                if (!aCallback(prefLang, NS_ConvertUTF8toUTF16(fontName), aClosure))
  1.1253 +                    return false;
  1.1254 +                p++;
  1.1255 +            }
  1.1256 +        }
  1.1257 +    }
  1.1258 +
  1.1259 +    return true;
  1.1260 +}
  1.1261 +
  1.1262 +eFontPrefLang
  1.1263 +gfxPlatform::GetFontPrefLangFor(const char* aLang)
  1.1264 +{
  1.1265 +    if (!aLang || !aLang[0]) {
  1.1266 +        return eFontPrefLang_Others;
  1.1267 +    }
  1.1268 +    for (uint32_t i = 0; i < ArrayLength(gPrefLangNames); ++i) {
  1.1269 +        if (!PL_strcasecmp(gPrefLangNames[i], aLang)) {
  1.1270 +            return eFontPrefLang(i);
  1.1271 +        }
  1.1272 +    }
  1.1273 +    return eFontPrefLang_Others;
  1.1274 +}
  1.1275 +
  1.1276 +eFontPrefLang
  1.1277 +gfxPlatform::GetFontPrefLangFor(nsIAtom *aLang)
  1.1278 +{
  1.1279 +    if (!aLang)
  1.1280 +        return eFontPrefLang_Others;
  1.1281 +    nsAutoCString lang;
  1.1282 +    aLang->ToUTF8String(lang);
  1.1283 +    return GetFontPrefLangFor(lang.get());
  1.1284 +}
  1.1285 +
  1.1286 +const char*
  1.1287 +gfxPlatform::GetPrefLangName(eFontPrefLang aLang)
  1.1288 +{
  1.1289 +    if (uint32_t(aLang) < ArrayLength(gPrefLangNames)) {
  1.1290 +        return gPrefLangNames[uint32_t(aLang)];
  1.1291 +    }
  1.1292 +    return nullptr;
  1.1293 +}
  1.1294 +
  1.1295 +eFontPrefLang
  1.1296 +gfxPlatform::GetFontPrefLangFor(uint8_t aUnicodeRange)
  1.1297 +{
  1.1298 +    switch (aUnicodeRange) {
  1.1299 +        case kRangeSetLatin:   return eFontPrefLang_Western;
  1.1300 +        case kRangeCyrillic:   return eFontPrefLang_Cyrillic;
  1.1301 +        case kRangeGreek:      return eFontPrefLang_Greek;
  1.1302 +        case kRangeTurkish:    return eFontPrefLang_Turkish;
  1.1303 +        case kRangeHebrew:     return eFontPrefLang_Hebrew;
  1.1304 +        case kRangeArabic:     return eFontPrefLang_Arabic;
  1.1305 +        case kRangeBaltic:     return eFontPrefLang_Baltic;
  1.1306 +        case kRangeThai:       return eFontPrefLang_Thai;
  1.1307 +        case kRangeKorean:     return eFontPrefLang_Korean;
  1.1308 +        case kRangeJapanese:   return eFontPrefLang_Japanese;
  1.1309 +        case kRangeSChinese:   return eFontPrefLang_ChineseCN;
  1.1310 +        case kRangeTChinese:   return eFontPrefLang_ChineseTW;
  1.1311 +        case kRangeDevanagari: return eFontPrefLang_Devanagari;
  1.1312 +        case kRangeTamil:      return eFontPrefLang_Tamil;
  1.1313 +        case kRangeArmenian:   return eFontPrefLang_Armenian;
  1.1314 +        case kRangeBengali:    return eFontPrefLang_Bengali;
  1.1315 +        case kRangeCanadian:   return eFontPrefLang_Canadian;
  1.1316 +        case kRangeEthiopic:   return eFontPrefLang_Ethiopic;
  1.1317 +        case kRangeGeorgian:   return eFontPrefLang_Georgian;
  1.1318 +        case kRangeGujarati:   return eFontPrefLang_Gujarati;
  1.1319 +        case kRangeGurmukhi:   return eFontPrefLang_Gurmukhi;
  1.1320 +        case kRangeKhmer:      return eFontPrefLang_Khmer;
  1.1321 +        case kRangeMalayalam:  return eFontPrefLang_Malayalam;
  1.1322 +        case kRangeOriya:      return eFontPrefLang_Oriya;
  1.1323 +        case kRangeTelugu:     return eFontPrefLang_Telugu;
  1.1324 +        case kRangeKannada:    return eFontPrefLang_Kannada;
  1.1325 +        case kRangeSinhala:    return eFontPrefLang_Sinhala;
  1.1326 +        case kRangeTibetan:    return eFontPrefLang_Tibetan;
  1.1327 +        case kRangeSetCJK:     return eFontPrefLang_CJKSet;
  1.1328 +        default:               return eFontPrefLang_Others;
  1.1329 +    }
  1.1330 +}
  1.1331 +
  1.1332 +bool
  1.1333 +gfxPlatform::IsLangCJK(eFontPrefLang aLang)
  1.1334 +{
  1.1335 +    switch (aLang) {
  1.1336 +        case eFontPrefLang_Japanese:
  1.1337 +        case eFontPrefLang_ChineseTW:
  1.1338 +        case eFontPrefLang_ChineseCN:
  1.1339 +        case eFontPrefLang_ChineseHK:
  1.1340 +        case eFontPrefLang_Korean:
  1.1341 +        case eFontPrefLang_CJKSet:
  1.1342 +            return true;
  1.1343 +        default:
  1.1344 +            return false;
  1.1345 +    }
  1.1346 +}
  1.1347 +
  1.1348 +mozilla::layers::DiagnosticTypes
  1.1349 +gfxPlatform::GetLayerDiagnosticTypes()
  1.1350 +{
  1.1351 +  mozilla::layers::DiagnosticTypes type = DIAGNOSTIC_NONE;
  1.1352 +  if (gfxPrefs::DrawLayerBorders()) {
  1.1353 +    type |= mozilla::layers::DIAGNOSTIC_LAYER_BORDERS;
  1.1354 +  }
  1.1355 +  if (gfxPrefs::DrawTileBorders()) {
  1.1356 +    type |= mozilla::layers::DIAGNOSTIC_TILE_BORDERS;
  1.1357 +  }
  1.1358 +  if (gfxPrefs::DrawBigImageBorders()) {
  1.1359 +    type |= mozilla::layers::DIAGNOSTIC_BIGIMAGE_BORDERS;
  1.1360 +  }
  1.1361 +  if (gfxPrefs::FlashLayerBorders()) {
  1.1362 +    type |= mozilla::layers::DIAGNOSTIC_FLASH_BORDERS;
  1.1363 +  }
  1.1364 +  return type;
  1.1365 +}
  1.1366 +
  1.1367 +void
  1.1368 +gfxPlatform::GetLangPrefs(eFontPrefLang aPrefLangs[], uint32_t &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang)
  1.1369 +{
  1.1370 +    if (IsLangCJK(aCharLang)) {
  1.1371 +        AppendCJKPrefLangs(aPrefLangs, aLen, aCharLang, aPageLang);
  1.1372 +    } else {
  1.1373 +        AppendPrefLang(aPrefLangs, aLen, aCharLang);
  1.1374 +    }
  1.1375 +
  1.1376 +    AppendPrefLang(aPrefLangs, aLen, eFontPrefLang_Others);
  1.1377 +}
  1.1378 +
  1.1379 +void
  1.1380 +gfxPlatform::AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], uint32_t &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang)
  1.1381 +{
  1.1382 +    // prefer the lang specified by the page *if* CJK
  1.1383 +    if (IsLangCJK(aPageLang)) {
  1.1384 +        AppendPrefLang(aPrefLangs, aLen, aPageLang);
  1.1385 +    }
  1.1386 +
  1.1387 +    // if not set up, set up the default CJK order, based on accept lang settings and locale
  1.1388 +    if (mCJKPrefLangs.Length() == 0) {
  1.1389 +
  1.1390 +        // temp array
  1.1391 +        eFontPrefLang tempPrefLangs[kMaxLenPrefLangList];
  1.1392 +        uint32_t tempLen = 0;
  1.1393 +
  1.1394 +        // Add the CJK pref fonts from accept languages, the order should be same order
  1.1395 +        nsAdoptingCString list = Preferences::GetLocalizedCString("intl.accept_languages");
  1.1396 +        if (!list.IsEmpty()) {
  1.1397 +            const char kComma = ',';
  1.1398 +            const char *p, *p_end;
  1.1399 +            list.BeginReading(p);
  1.1400 +            list.EndReading(p_end);
  1.1401 +            while (p < p_end) {
  1.1402 +                while (nsCRT::IsAsciiSpace(*p)) {
  1.1403 +                    if (++p == p_end)
  1.1404 +                        break;
  1.1405 +                }
  1.1406 +                if (p == p_end)
  1.1407 +                    break;
  1.1408 +                const char *start = p;
  1.1409 +                while (++p != p_end && *p != kComma)
  1.1410 +                    /* nothing */ ;
  1.1411 +                nsAutoCString lang(Substring(start, p));
  1.1412 +                lang.CompressWhitespace(false, true);
  1.1413 +                eFontPrefLang fpl = gfxPlatform::GetFontPrefLangFor(lang.get());
  1.1414 +                switch (fpl) {
  1.1415 +                    case eFontPrefLang_Japanese:
  1.1416 +                    case eFontPrefLang_Korean:
  1.1417 +                    case eFontPrefLang_ChineseCN:
  1.1418 +                    case eFontPrefLang_ChineseHK:
  1.1419 +                    case eFontPrefLang_ChineseTW:
  1.1420 +                        AppendPrefLang(tempPrefLangs, tempLen, fpl);
  1.1421 +                        break;
  1.1422 +                    default:
  1.1423 +                        break;
  1.1424 +                }
  1.1425 +                p++;
  1.1426 +            }
  1.1427 +        }
  1.1428 +
  1.1429 +        do { // to allow 'break' to abort this block if a call fails
  1.1430 +            nsresult rv;
  1.1431 +            nsCOMPtr<nsILocaleService> ls =
  1.1432 +                do_GetService(NS_LOCALESERVICE_CONTRACTID, &rv);
  1.1433 +            if (NS_FAILED(rv))
  1.1434 +                break;
  1.1435 +
  1.1436 +            nsCOMPtr<nsILocale> appLocale;
  1.1437 +            rv = ls->GetApplicationLocale(getter_AddRefs(appLocale));
  1.1438 +            if (NS_FAILED(rv))
  1.1439 +                break;
  1.1440 +
  1.1441 +            nsString localeStr;
  1.1442 +            rv = appLocale->
  1.1443 +                GetCategory(NS_LITERAL_STRING(NSILOCALE_MESSAGE), localeStr);
  1.1444 +            if (NS_FAILED(rv))
  1.1445 +                break;
  1.1446 +
  1.1447 +            const nsAString& lang = Substring(localeStr, 0, 2);
  1.1448 +            if (lang.EqualsLiteral("ja")) {
  1.1449 +                AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
  1.1450 +            } else if (lang.EqualsLiteral("zh")) {
  1.1451 +                const nsAString& region = Substring(localeStr, 3, 2);
  1.1452 +                if (region.EqualsLiteral("CN")) {
  1.1453 +                    AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
  1.1454 +                } else if (region.EqualsLiteral("TW")) {
  1.1455 +                    AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
  1.1456 +                } else if (region.EqualsLiteral("HK")) {
  1.1457 +                    AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
  1.1458 +                }
  1.1459 +            } else if (lang.EqualsLiteral("ko")) {
  1.1460 +                AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
  1.1461 +            }
  1.1462 +        } while (0);
  1.1463 +
  1.1464 +        // last resort... (the order is same as old gfx.)
  1.1465 +        AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
  1.1466 +        AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
  1.1467 +        AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
  1.1468 +        AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
  1.1469 +        AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
  1.1470 +
  1.1471 +        // copy into the cached array
  1.1472 +        uint32_t j;
  1.1473 +        for (j = 0; j < tempLen; j++) {
  1.1474 +            mCJKPrefLangs.AppendElement(tempPrefLangs[j]);
  1.1475 +        }
  1.1476 +    }
  1.1477 +
  1.1478 +    // append in cached CJK langs
  1.1479 +    uint32_t  i, numCJKlangs = mCJKPrefLangs.Length();
  1.1480 +
  1.1481 +    for (i = 0; i < numCJKlangs; i++) {
  1.1482 +        AppendPrefLang(aPrefLangs, aLen, (eFontPrefLang) (mCJKPrefLangs[i]));
  1.1483 +    }
  1.1484 +
  1.1485 +}
  1.1486 +
  1.1487 +void
  1.1488 +gfxPlatform::AppendPrefLang(eFontPrefLang aPrefLangs[], uint32_t& aLen, eFontPrefLang aAddLang)
  1.1489 +{
  1.1490 +    if (aLen >= kMaxLenPrefLangList) return;
  1.1491 +
  1.1492 +    // make sure
  1.1493 +    uint32_t  i = 0;
  1.1494 +    while (i < aLen && aPrefLangs[i] != aAddLang) {
  1.1495 +        i++;
  1.1496 +    }
  1.1497 +
  1.1498 +    if (i == aLen) {
  1.1499 +        aPrefLangs[aLen] = aAddLang;
  1.1500 +        aLen++;
  1.1501 +    }
  1.1502 +}
  1.1503 +
  1.1504 +void
  1.1505 +gfxPlatform::InitBackendPrefs(uint32_t aCanvasBitmask, BackendType aCanvasDefault,
  1.1506 +                              uint32_t aContentBitmask, BackendType aContentDefault)
  1.1507 +{
  1.1508 +    mPreferredCanvasBackend = GetCanvasBackendPref(aCanvasBitmask);
  1.1509 +    if (mPreferredCanvasBackend == BackendType::NONE) {
  1.1510 +        mPreferredCanvasBackend = aCanvasDefault;
  1.1511 +    }
  1.1512 +    mFallbackCanvasBackend =
  1.1513 +        GetCanvasBackendPref(aCanvasBitmask & ~BackendTypeBit(mPreferredCanvasBackend));
  1.1514 +
  1.1515 +    mContentBackendBitmask = aContentBitmask;
  1.1516 +    mContentBackend = GetContentBackendPref(mContentBackendBitmask);
  1.1517 +    if (mContentBackend == BackendType::NONE) {
  1.1518 +        mContentBackend = aContentDefault;
  1.1519 +        // mContentBackendBitmask is our canonical reference for supported
  1.1520 +        // backends so we need to add the default if we are using it and
  1.1521 +        // overriding the prefs.
  1.1522 +        mContentBackendBitmask |= BackendTypeBit(aContentDefault);
  1.1523 +    }
  1.1524 +}
  1.1525 +
  1.1526 +/* static */ BackendType
  1.1527 +gfxPlatform::GetCanvasBackendPref(uint32_t aBackendBitmask)
  1.1528 +{
  1.1529 +    return GetBackendPref("gfx.canvas.azure.backends", aBackendBitmask);
  1.1530 +}
  1.1531 +
  1.1532 +/* static */ BackendType
  1.1533 +gfxPlatform::GetContentBackendPref(uint32_t &aBackendBitmask)
  1.1534 +{
  1.1535 +    return GetBackendPref("gfx.content.azure.backends", aBackendBitmask);
  1.1536 +}
  1.1537 +
  1.1538 +/* static */ BackendType
  1.1539 +gfxPlatform::GetBackendPref(const char* aBackendPrefName, uint32_t &aBackendBitmask)
  1.1540 +{
  1.1541 +    nsTArray<nsCString> backendList;
  1.1542 +    nsCString prefString;
  1.1543 +    if (NS_SUCCEEDED(Preferences::GetCString(aBackendPrefName, &prefString))) {
  1.1544 +        ParseString(prefString, ',', backendList);
  1.1545 +    }
  1.1546 +
  1.1547 +    uint32_t allowedBackends = 0;
  1.1548 +    BackendType result = BackendType::NONE;
  1.1549 +    for (uint32_t i = 0; i < backendList.Length(); ++i) {
  1.1550 +        BackendType type = BackendTypeForName(backendList[i]);
  1.1551 +        if (BackendTypeBit(type) & aBackendBitmask) {
  1.1552 +            allowedBackends |= BackendTypeBit(type);
  1.1553 +            if (result == BackendType::NONE) {
  1.1554 +                result = type;
  1.1555 +            }
  1.1556 +        }
  1.1557 +    }
  1.1558 +
  1.1559 +    aBackendBitmask = allowedBackends;
  1.1560 +    return result;
  1.1561 +}
  1.1562 +
  1.1563 +bool
  1.1564 +gfxPlatform::OffMainThreadCompositingEnabled()
  1.1565 +{
  1.1566 +  return XRE_GetProcessType() == GeckoProcessType_Default ?
  1.1567 +    CompositorParent::CompositorLoop() != nullptr :
  1.1568 +    CompositorChild::ChildProcessHasCompositor();
  1.1569 +}
  1.1570 +
  1.1571 +eCMSMode
  1.1572 +gfxPlatform::GetCMSMode()
  1.1573 +{
  1.1574 +    if (gCMSInitialized == false) {
  1.1575 +        gCMSInitialized = true;
  1.1576 +
  1.1577 +        int32_t mode = gfxPrefs::CMSMode();
  1.1578 +        if (mode >= 0 && mode < eCMSMode_AllCount) {
  1.1579 +            gCMSMode = static_cast<eCMSMode>(mode);
  1.1580 +        }
  1.1581 +
  1.1582 +        bool enableV4 = gfxPrefs::CMSEnableV4();
  1.1583 +        if (enableV4) {
  1.1584 +            qcms_enable_iccv4();
  1.1585 +        }
  1.1586 +    }
  1.1587 +    return gCMSMode;
  1.1588 +}
  1.1589 +
  1.1590 +int
  1.1591 +gfxPlatform::GetRenderingIntent()
  1.1592 +{
  1.1593 +    if (!gCMSIntentInitialized) {
  1.1594 +        gCMSIntentInitialized = true;
  1.1595 +
  1.1596 +        // gfxPrefs.h is using 0 as the default for the rendering
  1.1597 +        // intent preference, based on that being the value for
  1.1598 +        // QCMS_INTENT_DEFAULT.  Assert here to catch if that ever
  1.1599 +        // changes and we can then figure out what to do about it.
  1.1600 +        MOZ_ASSERT(QCMS_INTENT_DEFAULT == 0);
  1.1601 +
  1.1602 +        /* Try to query the pref system for a rendering intent. */
  1.1603 +        int32_t pIntent = gfxPrefs::CMSRenderingIntent();
  1.1604 +        if ((pIntent >= QCMS_INTENT_MIN) && (pIntent <= QCMS_INTENT_MAX)) {
  1.1605 +            gCMSIntent = pIntent;
  1.1606 +        } else {
  1.1607 +            /* If the pref is out of range, use embedded profile. */
  1.1608 +            gCMSIntent = -1;
  1.1609 +        }
  1.1610 +    }
  1.1611 +    return gCMSIntent;
  1.1612 +}
  1.1613 +
  1.1614 +void
  1.1615 +gfxPlatform::TransformPixel(const gfxRGBA& in, gfxRGBA& out, qcms_transform *transform)
  1.1616 +{
  1.1617 +
  1.1618 +    if (transform) {
  1.1619 +        /* we want the bytes in RGB order */
  1.1620 +#ifdef IS_LITTLE_ENDIAN
  1.1621 +        /* ABGR puts the bytes in |RGBA| order on little endian */
  1.1622 +        uint32_t packed = in.Packed(gfxRGBA::PACKED_ABGR);
  1.1623 +        qcms_transform_data(transform,
  1.1624 +                       (uint8_t *)&packed, (uint8_t *)&packed,
  1.1625 +                       1);
  1.1626 +        out.~gfxRGBA();
  1.1627 +        new (&out) gfxRGBA(packed, gfxRGBA::PACKED_ABGR);
  1.1628 +#else
  1.1629 +        /* ARGB puts the bytes in |ARGB| order on big endian */
  1.1630 +        uint32_t packed = in.Packed(gfxRGBA::PACKED_ARGB);
  1.1631 +        /* add one to move past the alpha byte */
  1.1632 +        qcms_transform_data(transform,
  1.1633 +                       (uint8_t *)&packed + 1, (uint8_t *)&packed + 1,
  1.1634 +                       1);
  1.1635 +        out.~gfxRGBA();
  1.1636 +        new (&out) gfxRGBA(packed, gfxRGBA::PACKED_ARGB);
  1.1637 +#endif
  1.1638 +    }
  1.1639 +
  1.1640 +    else if (&out != &in)
  1.1641 +        out = in;
  1.1642 +}
  1.1643 +
  1.1644 +void
  1.1645 +gfxPlatform::GetPlatformCMSOutputProfile(void *&mem, size_t &size)
  1.1646 +{
  1.1647 +    mem = nullptr;
  1.1648 +    size = 0;
  1.1649 +}
  1.1650 +
  1.1651 +void
  1.1652 +gfxPlatform::GetCMSOutputProfileData(void *&mem, size_t &size)
  1.1653 +{
  1.1654 +    nsAdoptingCString fname = Preferences::GetCString("gfx.color_management.display_profile");
  1.1655 +    if (!fname.IsEmpty()) {
  1.1656 +        qcms_data_from_path(fname, &mem, &size);
  1.1657 +    }
  1.1658 +    else {
  1.1659 +        gfxPlatform::GetPlatform()->GetPlatformCMSOutputProfile(mem, size);
  1.1660 +    }
  1.1661 +}
  1.1662 +
  1.1663 +void
  1.1664 +gfxPlatform::CreateCMSOutputProfile()
  1.1665 +{
  1.1666 +    if (!gCMSOutputProfile) {
  1.1667 +        /* Determine if we're using the internal override to force sRGB as
  1.1668 +           an output profile for reftests. See Bug 452125.
  1.1669 +
  1.1670 +           Note that we don't normally (outside of tests) set a
  1.1671 +           default value of this preference, which means nsIPrefBranch::GetBoolPref
  1.1672 +           will typically throw (and leave its out-param untouched).
  1.1673 +         */
  1.1674 +        if (Preferences::GetBool(GFX_PREF_CMS_FORCE_SRGB, false)) {
  1.1675 +            gCMSOutputProfile = GetCMSsRGBProfile();
  1.1676 +        }
  1.1677 +
  1.1678 +        if (!gCMSOutputProfile) {
  1.1679 +            void* mem = nullptr;
  1.1680 +            size_t size = 0;
  1.1681 +
  1.1682 +            GetCMSOutputProfileData(mem, size);
  1.1683 +            if ((mem != nullptr) && (size > 0)) {
  1.1684 +                gCMSOutputProfile = qcms_profile_from_memory(mem, size);
  1.1685 +                free(mem);
  1.1686 +            }
  1.1687 +        }
  1.1688 +
  1.1689 +        /* Determine if the profile looks bogus. If so, close the profile
  1.1690 +         * and use sRGB instead. See bug 460629, */
  1.1691 +        if (gCMSOutputProfile && qcms_profile_is_bogus(gCMSOutputProfile)) {
  1.1692 +            NS_ASSERTION(gCMSOutputProfile != GetCMSsRGBProfile(),
  1.1693 +                         "Builtin sRGB profile tagged as bogus!!!");
  1.1694 +            qcms_profile_release(gCMSOutputProfile);
  1.1695 +            gCMSOutputProfile = nullptr;
  1.1696 +        }
  1.1697 +
  1.1698 +        if (!gCMSOutputProfile) {
  1.1699 +            gCMSOutputProfile = GetCMSsRGBProfile();
  1.1700 +        }
  1.1701 +        /* Precache the LUT16 Interpolations for the output profile. See
  1.1702 +           bug 444661 for details. */
  1.1703 +        qcms_profile_precache_output_transform(gCMSOutputProfile);
  1.1704 +    }
  1.1705 +}
  1.1706 +
  1.1707 +qcms_profile *
  1.1708 +gfxPlatform::GetCMSOutputProfile()
  1.1709 +{
  1.1710 +    return gCMSOutputProfile;
  1.1711 +}
  1.1712 +
  1.1713 +qcms_profile *
  1.1714 +gfxPlatform::GetCMSsRGBProfile()
  1.1715 +{
  1.1716 +    if (!gCMSsRGBProfile) {
  1.1717 +
  1.1718 +        /* Create the profile using qcms. */
  1.1719 +        gCMSsRGBProfile = qcms_profile_sRGB();
  1.1720 +    }
  1.1721 +    return gCMSsRGBProfile;
  1.1722 +}
  1.1723 +
  1.1724 +qcms_transform *
  1.1725 +gfxPlatform::GetCMSRGBTransform()
  1.1726 +{
  1.1727 +    if (!gCMSRGBTransform) {
  1.1728 +        qcms_profile *inProfile, *outProfile;
  1.1729 +        outProfile = GetCMSOutputProfile();
  1.1730 +        inProfile = GetCMSsRGBProfile();
  1.1731 +
  1.1732 +        if (!inProfile || !outProfile)
  1.1733 +            return nullptr;
  1.1734 +
  1.1735 +        gCMSRGBTransform = qcms_transform_create(inProfile, QCMS_DATA_RGB_8,
  1.1736 +                                              outProfile, QCMS_DATA_RGB_8,
  1.1737 +                                             QCMS_INTENT_PERCEPTUAL);
  1.1738 +    }
  1.1739 +
  1.1740 +    return gCMSRGBTransform;
  1.1741 +}
  1.1742 +
  1.1743 +qcms_transform *
  1.1744 +gfxPlatform::GetCMSInverseRGBTransform()
  1.1745 +{
  1.1746 +    if (!gCMSInverseRGBTransform) {
  1.1747 +        qcms_profile *inProfile, *outProfile;
  1.1748 +        inProfile = GetCMSOutputProfile();
  1.1749 +        outProfile = GetCMSsRGBProfile();
  1.1750 +
  1.1751 +        if (!inProfile || !outProfile)
  1.1752 +            return nullptr;
  1.1753 +
  1.1754 +        gCMSInverseRGBTransform = qcms_transform_create(inProfile, QCMS_DATA_RGB_8,
  1.1755 +                                                     outProfile, QCMS_DATA_RGB_8,
  1.1756 +                                                     QCMS_INTENT_PERCEPTUAL);
  1.1757 +    }
  1.1758 +
  1.1759 +    return gCMSInverseRGBTransform;
  1.1760 +}
  1.1761 +
  1.1762 +qcms_transform *
  1.1763 +gfxPlatform::GetCMSRGBATransform()
  1.1764 +{
  1.1765 +    if (!gCMSRGBATransform) {
  1.1766 +        qcms_profile *inProfile, *outProfile;
  1.1767 +        outProfile = GetCMSOutputProfile();
  1.1768 +        inProfile = GetCMSsRGBProfile();
  1.1769 +
  1.1770 +        if (!inProfile || !outProfile)
  1.1771 +            return nullptr;
  1.1772 +
  1.1773 +        gCMSRGBATransform = qcms_transform_create(inProfile, QCMS_DATA_RGBA_8,
  1.1774 +                                               outProfile, QCMS_DATA_RGBA_8,
  1.1775 +                                               QCMS_INTENT_PERCEPTUAL);
  1.1776 +    }
  1.1777 +
  1.1778 +    return gCMSRGBATransform;
  1.1779 +}
  1.1780 +
  1.1781 +/* Shuts down various transforms and profiles for CMS. */
  1.1782 +static void ShutdownCMS()
  1.1783 +{
  1.1784 +
  1.1785 +    if (gCMSRGBTransform) {
  1.1786 +        qcms_transform_release(gCMSRGBTransform);
  1.1787 +        gCMSRGBTransform = nullptr;
  1.1788 +    }
  1.1789 +    if (gCMSInverseRGBTransform) {
  1.1790 +        qcms_transform_release(gCMSInverseRGBTransform);
  1.1791 +        gCMSInverseRGBTransform = nullptr;
  1.1792 +    }
  1.1793 +    if (gCMSRGBATransform) {
  1.1794 +        qcms_transform_release(gCMSRGBATransform);
  1.1795 +        gCMSRGBATransform = nullptr;
  1.1796 +    }
  1.1797 +    if (gCMSOutputProfile) {
  1.1798 +        qcms_profile_release(gCMSOutputProfile);
  1.1799 +
  1.1800 +        // handle the aliased case
  1.1801 +        if (gCMSsRGBProfile == gCMSOutputProfile)
  1.1802 +            gCMSsRGBProfile = nullptr;
  1.1803 +        gCMSOutputProfile = nullptr;
  1.1804 +    }
  1.1805 +    if (gCMSsRGBProfile) {
  1.1806 +        qcms_profile_release(gCMSsRGBProfile);
  1.1807 +        gCMSsRGBProfile = nullptr;
  1.1808 +    }
  1.1809 +
  1.1810 +    // Reset the state variables
  1.1811 +    gCMSIntent = -2;
  1.1812 +    gCMSMode = eCMSMode_Off;
  1.1813 +    gCMSInitialized = false;
  1.1814 +}
  1.1815 +
  1.1816 +// default SetupClusterBoundaries, based on Unicode properties;
  1.1817 +// platform subclasses may override if they wish
  1.1818 +void
  1.1819 +gfxPlatform::SetupClusterBoundaries(gfxTextRun *aTextRun, const char16_t *aString)
  1.1820 +{
  1.1821 +    if (aTextRun->GetFlags() & gfxTextRunFactory::TEXT_IS_8BIT) {
  1.1822 +        // 8-bit text doesn't have clusters.
  1.1823 +        // XXX is this true in all languages???
  1.1824 +        // behdad: don't think so.  Czech for example IIRC has a
  1.1825 +        // 'ch' grapheme.
  1.1826 +        // jfkthame: but that's not expected to behave as a grapheme cluster
  1.1827 +        // for selection/editing/etc.
  1.1828 +        return;
  1.1829 +    }
  1.1830 +
  1.1831 +    aTextRun->SetupClusterBoundaries(0, aString, aTextRun->GetLength());
  1.1832 +}
  1.1833 +
  1.1834 +int32_t
  1.1835 +gfxPlatform::GetBidiNumeralOption()
  1.1836 +{
  1.1837 +    if (mBidiNumeralOption == UNINITIALIZED_VALUE) {
  1.1838 +        mBidiNumeralOption = Preferences::GetInt(BIDI_NUMERAL_PREF, 0);
  1.1839 +    }
  1.1840 +    return mBidiNumeralOption;
  1.1841 +}
  1.1842 +
  1.1843 +static void
  1.1844 +FlushFontAndWordCaches()
  1.1845 +{
  1.1846 +    gfxFontCache *fontCache = gfxFontCache::GetCache();
  1.1847 +    if (fontCache) {
  1.1848 +        fontCache->AgeAllGenerations();
  1.1849 +        fontCache->FlushShapedWordCaches();
  1.1850 +    }
  1.1851 +}
  1.1852 +
  1.1853 +void
  1.1854 +gfxPlatform::FontsPrefsChanged(const char *aPref)
  1.1855 +{
  1.1856 +    NS_ASSERTION(aPref != nullptr, "null preference");
  1.1857 +    if (!strcmp(GFX_DOWNLOADABLE_FONTS_ENABLED, aPref)) {
  1.1858 +        mAllowDownloadableFonts = UNINITIALIZED_VALUE;
  1.1859 +    } else if (!strcmp(GFX_PREF_FALLBACK_USE_CMAPS, aPref)) {
  1.1860 +        mFallbackUsesCmaps = UNINITIALIZED_VALUE;
  1.1861 +    } else if (!strcmp(GFX_PREF_WORD_CACHE_CHARLIMIT, aPref)) {
  1.1862 +        mWordCacheCharLimit = UNINITIALIZED_VALUE;
  1.1863 +        FlushFontAndWordCaches();
  1.1864 +    } else if (!strcmp(GFX_PREF_WORD_CACHE_MAXENTRIES, aPref)) {
  1.1865 +        mWordCacheMaxEntries = UNINITIALIZED_VALUE;
  1.1866 +        FlushFontAndWordCaches();
  1.1867 +    } else if (!strcmp(GFX_PREF_GRAPHITE_SHAPING, aPref)) {
  1.1868 +        mGraphiteShapingEnabled = UNINITIALIZED_VALUE;
  1.1869 +        FlushFontAndWordCaches();
  1.1870 +    } else if (!strcmp(GFX_PREF_HARFBUZZ_SCRIPTS, aPref)) {
  1.1871 +        mUseHarfBuzzScripts = UNINITIALIZED_VALUE;
  1.1872 +        FlushFontAndWordCaches();
  1.1873 +    } else if (!strcmp(BIDI_NUMERAL_PREF, aPref)) {
  1.1874 +        mBidiNumeralOption = UNINITIALIZED_VALUE;
  1.1875 +    } else if (!strcmp(GFX_PREF_OPENTYPE_SVG, aPref)) {
  1.1876 +        mOpenTypeSVGEnabled = UNINITIALIZED_VALUE;
  1.1877 +        gfxFontCache::GetCache()->AgeAllGenerations();
  1.1878 +    }
  1.1879 +}
  1.1880 +
  1.1881 +
  1.1882 +PRLogModuleInfo*
  1.1883 +gfxPlatform::GetLog(eGfxLog aWhichLog)
  1.1884 +{
  1.1885 +    // logs shared across gfx
  1.1886 +#ifdef PR_LOGGING
  1.1887 +    static PRLogModuleInfo *sFontlistLog = nullptr;
  1.1888 +    static PRLogModuleInfo *sFontInitLog = nullptr;
  1.1889 +    static PRLogModuleInfo *sTextrunLog = nullptr;
  1.1890 +    static PRLogModuleInfo *sTextrunuiLog = nullptr;
  1.1891 +    static PRLogModuleInfo *sCmapDataLog = nullptr;
  1.1892 +    static PRLogModuleInfo *sTextPerfLog = nullptr;
  1.1893 +
  1.1894 +    // Assume that if one is initialized, all are initialized
  1.1895 +    if (!sFontlistLog) {
  1.1896 +        sFontlistLog = PR_NewLogModule("fontlist");
  1.1897 +        sFontInitLog = PR_NewLogModule("fontinit");
  1.1898 +        sTextrunLog = PR_NewLogModule("textrun");
  1.1899 +        sTextrunuiLog = PR_NewLogModule("textrunui");
  1.1900 +        sCmapDataLog = PR_NewLogModule("cmapdata");
  1.1901 +        sTextPerfLog = PR_NewLogModule("textperf");
  1.1902 +    }
  1.1903 +
  1.1904 +    switch (aWhichLog) {
  1.1905 +    case eGfxLog_fontlist:
  1.1906 +        return sFontlistLog;
  1.1907 +        break;
  1.1908 +    case eGfxLog_fontinit:
  1.1909 +        return sFontInitLog;
  1.1910 +        break;
  1.1911 +    case eGfxLog_textrun:
  1.1912 +        return sTextrunLog;
  1.1913 +        break;
  1.1914 +    case eGfxLog_textrunui:
  1.1915 +        return sTextrunuiLog;
  1.1916 +        break;
  1.1917 +    case eGfxLog_cmapdata:
  1.1918 +        return sCmapDataLog;
  1.1919 +        break;
  1.1920 +    case eGfxLog_textperf:
  1.1921 +        return sTextPerfLog;
  1.1922 +        break;
  1.1923 +    default:
  1.1924 +        break;
  1.1925 +    }
  1.1926 +
  1.1927 +    return nullptr;
  1.1928 +#else
  1.1929 +    return nullptr;
  1.1930 +#endif
  1.1931 +}
  1.1932 +
  1.1933 +int
  1.1934 +gfxPlatform::GetScreenDepth() const
  1.1935 +{
  1.1936 +    NS_WARNING("GetScreenDepth not implemented on this platform -- returning 0!");
  1.1937 +    return 0;
  1.1938 +}
  1.1939 +
  1.1940 +mozilla::gfx::SurfaceFormat
  1.1941 +gfxPlatform::Optimal2DFormatForContent(gfxContentType aContent)
  1.1942 +{
  1.1943 +  switch (aContent) {
  1.1944 +  case gfxContentType::COLOR:
  1.1945 +    switch (GetOffscreenFormat()) {
  1.1946 +    case gfxImageFormat::ARGB32:
  1.1947 +      return mozilla::gfx::SurfaceFormat::B8G8R8A8;
  1.1948 +    case gfxImageFormat::RGB24:
  1.1949 +      return mozilla::gfx::SurfaceFormat::B8G8R8X8;
  1.1950 +    case gfxImageFormat::RGB16_565:
  1.1951 +      return mozilla::gfx::SurfaceFormat::R5G6B5;
  1.1952 +    default:
  1.1953 +      NS_NOTREACHED("unknown gfxImageFormat for gfxContentType::COLOR");
  1.1954 +      return mozilla::gfx::SurfaceFormat::B8G8R8A8;
  1.1955 +    }
  1.1956 +  case gfxContentType::ALPHA:
  1.1957 +    return mozilla::gfx::SurfaceFormat::A8;
  1.1958 +  case gfxContentType::COLOR_ALPHA:
  1.1959 +    return mozilla::gfx::SurfaceFormat::B8G8R8A8;
  1.1960 +  default:
  1.1961 +    NS_NOTREACHED("unknown gfxContentType");
  1.1962 +    return mozilla::gfx::SurfaceFormat::B8G8R8A8;
  1.1963 +  }
  1.1964 +}
  1.1965 +
  1.1966 +gfxImageFormat
  1.1967 +gfxPlatform::OptimalFormatForContent(gfxContentType aContent)
  1.1968 +{
  1.1969 +  switch (aContent) {
  1.1970 +  case gfxContentType::COLOR:
  1.1971 +    return GetOffscreenFormat();
  1.1972 +  case gfxContentType::ALPHA:
  1.1973 +    return gfxImageFormat::A8;
  1.1974 +  case gfxContentType::COLOR_ALPHA:
  1.1975 +    return gfxImageFormat::ARGB32;
  1.1976 +  default:
  1.1977 +    NS_NOTREACHED("unknown gfxContentType");
  1.1978 +    return gfxImageFormat::ARGB32;
  1.1979 +  }
  1.1980 +}
  1.1981 +
  1.1982 +/**
  1.1983 + * There are a number of layers acceleration (or layers in general) preferences
  1.1984 + * that should be consistent for the lifetime of the application (bug 840967).
  1.1985 + * As such, we will evaluate them all as soon as one of them is evaluated
  1.1986 + * and remember the values.  Changing these preferences during the run will
  1.1987 + * not have any effect until we restart.
  1.1988 + */
  1.1989 +static bool sLayersSupportsD3D9 = false;
  1.1990 +static bool sBufferRotationCheckPref = true;
  1.1991 +static bool sPrefBrowserTabsRemoteAutostart = false;
  1.1992 +
  1.1993 +static bool sLayersAccelerationPrefsInitialized = false;
  1.1994 +
  1.1995 +void
  1.1996 +InitLayersAccelerationPrefs()
  1.1997 +{
  1.1998 +  if (!sLayersAccelerationPrefsInitialized)
  1.1999 +  {
  1.2000 +    // If this is called for the first time on a non-main thread, we're screwed.
  1.2001 +    // At the moment there's no explicit guarantee that the main thread calls
  1.2002 +    // this before the compositor thread, but let's at least make the assumption
  1.2003 +    // explicit.
  1.2004 +    MOZ_ASSERT(NS_IsMainThread(), "can only initialize prefs on the main thread");
  1.2005 +
  1.2006 +    sPrefBrowserTabsRemoteAutostart = Preferences::GetBool("browser.tabs.remote.autostart", false);
  1.2007 +
  1.2008 +#ifdef XP_WIN
  1.2009 +    if (gfxPrefs::LayersAccelerationForceEnabled()) {
  1.2010 +      sLayersSupportsD3D9 = true;
  1.2011 +    } else {
  1.2012 +      nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
  1.2013 +      if (gfxInfo) {
  1.2014 +        int32_t status;
  1.2015 +        if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS, &status))) {
  1.2016 +          if (status == nsIGfxInfo::FEATURE_NO_INFO) {
  1.2017 +            sLayersSupportsD3D9 = true;
  1.2018 +          }
  1.2019 +        }
  1.2020 +      }
  1.2021 +    }
  1.2022 +#endif
  1.2023 +
  1.2024 +    sLayersAccelerationPrefsInitialized = true;
  1.2025 +  }
  1.2026 +}
  1.2027 +
  1.2028 +bool
  1.2029 +gfxPlatform::GetPrefLayersOffMainThreadCompositionEnabled()
  1.2030 +{
  1.2031 +  InitLayersAccelerationPrefs();
  1.2032 +  return gfxPrefs::LayersOffMainThreadCompositionEnabled() ||
  1.2033 +         gfxPrefs::LayersOffMainThreadCompositionForceEnabled() ||
  1.2034 +         gfxPrefs::LayersOffMainThreadCompositionTestingEnabled();
  1.2035 +}
  1.2036 +
  1.2037 +bool gfxPlatform::OffMainThreadCompositionRequired()
  1.2038 +{
  1.2039 +  InitLayersAccelerationPrefs();
  1.2040 +#if defined(MOZ_WIDGET_GTK) && defined(NIGHTLY_BUILD)
  1.2041 +  // Linux users who chose OpenGL are being grandfathered in to OMTC
  1.2042 +  return sPrefBrowserTabsRemoteAutostart ||
  1.2043 +         gfxPrefs::LayersAccelerationForceEnabled();
  1.2044 +#else
  1.2045 +  return sPrefBrowserTabsRemoteAutostart;
  1.2046 +#endif
  1.2047 +}
  1.2048 +
  1.2049 +bool
  1.2050 +gfxPlatform::CanUseDirect3D9()
  1.2051 +{
  1.2052 +  // this function is called from the compositor thread, so it is not
  1.2053 +  // safe to init the prefs etc. from here.
  1.2054 +  MOZ_ASSERT(sLayersAccelerationPrefsInitialized);
  1.2055 +  return sLayersSupportsD3D9;
  1.2056 +}
  1.2057 +
  1.2058 +bool
  1.2059 +gfxPlatform::BufferRotationEnabled()
  1.2060 +{
  1.2061 +  MutexAutoLock autoLock(*gGfxPlatformPrefsLock);
  1.2062 +
  1.2063 +  return sBufferRotationCheckPref && gfxPrefs::BufferRotationEnabled();
  1.2064 +}
  1.2065 +
  1.2066 +void
  1.2067 +gfxPlatform::DisableBufferRotation()
  1.2068 +{
  1.2069 +  MutexAutoLock autoLock(*gGfxPlatformPrefsLock);
  1.2070 +
  1.2071 +  sBufferRotationCheckPref = false;
  1.2072 +}
  1.2073 +
  1.2074 +TemporaryRef<ScaledFont>
  1.2075 +gfxPlatform::GetScaledFontForFontWithCairoSkia(DrawTarget* aTarget, gfxFont* aFont)
  1.2076 +{
  1.2077 +    NativeFont nativeFont;
  1.2078 +    if (aTarget->GetType() == BackendType::CAIRO || aTarget->GetType() == BackendType::SKIA) {
  1.2079 +        nativeFont.mType = NativeFontType::CAIRO_FONT_FACE;
  1.2080 +        nativeFont.mFont = aFont->GetCairoScaledFont();
  1.2081 +        return Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
  1.2082 +    }
  1.2083 +
  1.2084 +    return nullptr;
  1.2085 +}

mercurial