gfx/thebes/gfxWindowsPlatform.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 /* vim: set ts=8 sts=4 et sw=4 tw=80: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "mozilla/ArrayUtils.h"
     9 #include "gfxWindowsPlatform.h"
    11 #include "gfxImageSurface.h"
    12 #include "gfxWindowsSurface.h"
    14 #include "nsUnicharUtils.h"
    16 #include "mozilla/Preferences.h"
    17 #include "mozilla/WindowsVersion.h"
    18 #include "nsServiceManagerUtils.h"
    19 #include "nsTArray.h"
    21 #include "nsIWindowsRegKey.h"
    22 #include "nsIFile.h"
    23 #include "plbase64.h"
    24 #include "nsIXULRuntime.h"
    26 #include "nsIGfxInfo.h"
    28 #include "gfxCrashReporterUtils.h"
    30 #include "gfxGDIFontList.h"
    31 #include "gfxGDIFont.h"
    33 #include "mozilla/layers/CompositorParent.h"   // for CompositorParent::IsInCompositorThread
    34 #include "DeviceManagerD3D9.h"
    36 #include "WinUtils.h"
    38 #ifdef CAIRO_HAS_DWRITE_FONT
    39 #include "gfxDWriteFontList.h"
    40 #include "gfxDWriteFonts.h"
    41 #include "gfxDWriteCommon.h"
    42 #include <dwrite.h>
    43 #endif
    45 #include "gfxUserFontSet.h"
    46 #include "nsWindowsHelpers.h"
    47 #include "gfx2DGlue.h"
    49 #include <string>
    51 #ifdef CAIRO_HAS_D2D_SURFACE
    52 #include "gfxD2DSurface.h"
    54 #include <d3d10_1.h>
    56 #include "mozilla/gfx/2D.h"
    58 #include "nsMemory.h"
    59 #endif
    61 #include <d3d11.h>
    63 #include "nsIMemoryReporter.h"
    64 #include <winternl.h>
    65 #include "d3dkmtQueryStatistics.h"
    67 #include "SurfaceCache.h"
    68 #include "gfxPrefs.h"
    70 using namespace mozilla;
    71 using namespace mozilla::gfx;
    72 using namespace mozilla::layers;
    73 using namespace mozilla::widget;
    74 using namespace mozilla::image;
    76 #ifdef CAIRO_HAS_D2D_SURFACE
    78 static const char *kFeatureLevelPref =
    79   "gfx.direct3d.last_used_feature_level_idx";
    80 static const int kSupportedFeatureLevels[] =
    81   { D3D10_FEATURE_LEVEL_10_1, D3D10_FEATURE_LEVEL_10_0,
    82     D3D10_FEATURE_LEVEL_9_3 };
    84 class GfxD2DSurfaceReporter MOZ_FINAL : public nsIMemoryReporter
    85 {
    86 public:
    87     NS_DECL_ISUPPORTS
    89     NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
    90                               nsISupports* aData)
    91     {
    92         nsresult rv;
    94         int64_t amount = cairo_d2d_get_image_surface_cache_usage();
    95         rv = MOZ_COLLECT_REPORT(
    96             "gfx-d2d-surface-cache", KIND_OTHER, UNITS_BYTES, amount,
    97             "Memory used by the Direct2D internal surface cache.");
    98         NS_ENSURE_SUCCESS(rv, rv);
   100         cairo_device_t *device =
   101             gfxWindowsPlatform::GetPlatform()->GetD2DDevice();
   102         amount = device ? cairo_d2d_get_surface_vram_usage(device) : 0;
   103         rv = MOZ_COLLECT_REPORT(
   104             "gfx-d2d-surface-vram", KIND_OTHER, UNITS_BYTES, amount,
   105             "Video memory used by D2D surfaces.");
   106         NS_ENSURE_SUCCESS(rv, rv);
   108         return NS_OK;
   109     }
   110 };
   112 NS_IMPL_ISUPPORTS(GfxD2DSurfaceReporter, nsIMemoryReporter)
   114 #endif
   116 class GfxD2DVramReporter MOZ_FINAL : public nsIMemoryReporter
   117 {
   118 public:
   119     NS_DECL_ISUPPORTS
   121     NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
   122                               nsISupports* aData)
   123     {
   124         nsresult rv;
   126         rv = MOZ_COLLECT_REPORT(
   127             "gfx-d2d-vram-draw-target", KIND_OTHER, UNITS_BYTES,
   128             Factory::GetD2DVRAMUsageDrawTarget(),
   129             "Video memory used by D2D DrawTargets.");
   130         NS_ENSURE_SUCCESS(rv, rv);
   132         rv = MOZ_COLLECT_REPORT(
   133             "gfx-d2d-vram-source-surface", KIND_OTHER, UNITS_BYTES,
   134             Factory::GetD2DVRAMUsageSourceSurface(),
   135             "Video memory used by D2D SourceSurfaces.");
   136         NS_ENSURE_SUCCESS(rv, rv);
   138         return NS_OK;
   139     }
   140 };
   142 NS_IMPL_ISUPPORTS(GfxD2DVramReporter, nsIMemoryReporter)
   144 #define GFX_USE_CLEARTYPE_ALWAYS "gfx.font_rendering.cleartype.always_use_for_content"
   145 #define GFX_DOWNLOADABLE_FONTS_USE_CLEARTYPE "gfx.font_rendering.cleartype.use_for_downloadable_fonts"
   147 #define GFX_CLEARTYPE_PARAMS           "gfx.font_rendering.cleartype_params."
   148 #define GFX_CLEARTYPE_PARAMS_GAMMA     "gfx.font_rendering.cleartype_params.gamma"
   149 #define GFX_CLEARTYPE_PARAMS_CONTRAST  "gfx.font_rendering.cleartype_params.enhanced_contrast"
   150 #define GFX_CLEARTYPE_PARAMS_LEVEL     "gfx.font_rendering.cleartype_params.cleartype_level"
   151 #define GFX_CLEARTYPE_PARAMS_STRUCTURE "gfx.font_rendering.cleartype_params.pixel_structure"
   152 #define GFX_CLEARTYPE_PARAMS_MODE      "gfx.font_rendering.cleartype_params.rendering_mode"
   154 class GPUAdapterReporter : public nsIMemoryReporter
   155 {
   156     // Callers must Release the DXGIAdapter after use or risk mem-leak
   157     static bool GetDXGIAdapter(IDXGIAdapter **DXGIAdapter)
   158     {
   159         ID3D10Device1 *D2D10Device;
   160         IDXGIDevice *DXGIDevice;
   161         bool result = false;
   163         if (D2D10Device = mozilla::gfx::Factory::GetDirect3D10Device()) {
   164             if (D2D10Device->QueryInterface(__uuidof(IDXGIDevice), (void **)&DXGIDevice) == S_OK) {
   165                 result = (DXGIDevice->GetAdapter(DXGIAdapter) == S_OK);
   166                 DXGIDevice->Release();
   167             }
   168         }
   170         return result;
   171     }
   173 public:
   174     NS_DECL_ISUPPORTS
   176     NS_IMETHOD
   177     CollectReports(nsIMemoryReporterCallback* aCb,
   178                    nsISupports* aClosure)
   179     {
   180         HANDLE ProcessHandle = GetCurrentProcess();
   182         int64_t dedicatedBytesUsed = 0;
   183         int64_t sharedBytesUsed = 0;
   184         int64_t committedBytesUsed = 0;
   185         IDXGIAdapter *DXGIAdapter;
   187         HMODULE gdi32Handle;
   188         PFND3DKMTQS queryD3DKMTStatistics;
   190         // GPU memory reporting is not available before Windows 7
   191         if (!IsWin7OrLater()) 
   192             return NS_OK;
   194         if (gdi32Handle = LoadLibrary(TEXT("gdi32.dll")))
   195             queryD3DKMTStatistics = (PFND3DKMTQS)GetProcAddress(gdi32Handle, "D3DKMTQueryStatistics");
   197         if (queryD3DKMTStatistics && GetDXGIAdapter(&DXGIAdapter)) {
   198             // Most of this block is understood thanks to wj32's work on Process Hacker
   200             DXGI_ADAPTER_DESC adapterDesc;
   201             D3DKMTQS queryStatistics;
   203             DXGIAdapter->GetDesc(&adapterDesc);
   204             DXGIAdapter->Release();
   206             memset(&queryStatistics, 0, sizeof(D3DKMTQS));
   207             queryStatistics.Type = D3DKMTQS_PROCESS;
   208             queryStatistics.AdapterLuid = adapterDesc.AdapterLuid;
   209             queryStatistics.hProcess = ProcessHandle;
   210             if (NT_SUCCESS(queryD3DKMTStatistics(&queryStatistics))) {
   211                 committedBytesUsed = queryStatistics.QueryResult.ProcessInfo.SystemMemory.BytesAllocated;
   212             }
   214             memset(&queryStatistics, 0, sizeof(D3DKMTQS));
   215             queryStatistics.Type = D3DKMTQS_ADAPTER;
   216             queryStatistics.AdapterLuid = adapterDesc.AdapterLuid;
   217             if (NT_SUCCESS(queryD3DKMTStatistics(&queryStatistics))) {
   218                 ULONG i;
   219                 ULONG segmentCount = queryStatistics.QueryResult.AdapterInfo.NbSegments;
   221                 for (i = 0; i < segmentCount; i++) {
   222                     memset(&queryStatistics, 0, sizeof(D3DKMTQS));
   223                     queryStatistics.Type = D3DKMTQS_SEGMENT;
   224                     queryStatistics.AdapterLuid = adapterDesc.AdapterLuid;
   225                     queryStatistics.QuerySegment.SegmentId = i;
   227                     if (NT_SUCCESS(queryD3DKMTStatistics(&queryStatistics))) {
   228                         bool aperture;
   230                         // SegmentInformation has a different definition in Win7 than later versions
   231                         if (!IsWin8OrLater())
   232                             aperture = queryStatistics.QueryResult.SegmentInfoWin7.Aperture;
   233                         else
   234                             aperture = queryStatistics.QueryResult.SegmentInfoWin8.Aperture;
   236                         memset(&queryStatistics, 0, sizeof(D3DKMTQS));
   237                         queryStatistics.Type = D3DKMTQS_PROCESS_SEGMENT;
   238                         queryStatistics.AdapterLuid = adapterDesc.AdapterLuid;
   239                         queryStatistics.hProcess = ProcessHandle;
   240                         queryStatistics.QueryProcessSegment.SegmentId = i;
   241                         if (NT_SUCCESS(queryD3DKMTStatistics(&queryStatistics))) {
   242                             ULONGLONG bytesCommitted;
   243                             if (!IsWin8OrLater())
   244                                 bytesCommitted = queryStatistics.QueryResult.ProcessSegmentInfo.Win7.BytesCommitted;
   245                             else
   246                                 bytesCommitted = queryStatistics.QueryResult.ProcessSegmentInfo.Win8.BytesCommitted;
   247                             if (aperture)
   248                                 sharedBytesUsed += bytesCommitted;
   249                             else
   250                                 dedicatedBytesUsed += bytesCommitted;
   251                         }
   252                     }
   253                 }
   254             }
   255         }
   257         FreeLibrary(gdi32Handle);
   259 #define REPORT(_path, _amount, _desc)                                         \
   260     do {                                                                      \
   261       nsresult rv;                                                            \
   262       rv = aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path),           \
   263                          KIND_OTHER, UNITS_BYTES, _amount,                    \
   264                          NS_LITERAL_CSTRING(_desc), aClosure);                \
   265       NS_ENSURE_SUCCESS(rv, rv);                                              \
   266     } while (0)
   268         REPORT("gpu-committed", committedBytesUsed,
   269                "Memory committed by the Windows graphics system.");
   271         REPORT("gpu-dedicated", dedicatedBytesUsed,
   272                "Out-of-process memory allocated for this process in a "
   273                "physical GPU adapter's memory.");
   275         REPORT("gpu-shared", sharedBytesUsed,
   276                "In-process memory that is shared with the GPU.");
   278 #undef REPORT
   280         return NS_OK;
   281     }
   282 };
   284 NS_IMPL_ISUPPORTS(GPUAdapterReporter, nsIMemoryReporter)
   286 static __inline void
   287 BuildKeyNameFromFontName(nsAString &aName)
   288 {
   289     if (aName.Length() >= LF_FACESIZE)
   290         aName.Truncate(LF_FACESIZE - 1);
   291     ToLowerCase(aName);
   292 }
   294 gfxWindowsPlatform::gfxWindowsPlatform()
   295   : mD3D11DeviceInitialized(false)
   296   , mPrefFonts(50)
   297 {
   298     mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
   299     mUseClearTypeAlways = UNINITIALIZED_VALUE;
   301     mUsingGDIFonts = false;
   303     /* 
   304      * Initialize COM 
   305      */ 
   306     CoInitialize(nullptr); 
   308 #ifdef CAIRO_HAS_D2D_SURFACE
   309     RegisterStrongMemoryReporter(new GfxD2DSurfaceReporter());
   310     mD2DDevice = nullptr;
   311 #endif
   312     RegisterStrongMemoryReporter(new GfxD2DVramReporter());
   314     UpdateRenderMode();
   316     RegisterStrongMemoryReporter(new GPUAdapterReporter());
   317 }
   319 gfxWindowsPlatform::~gfxWindowsPlatform()
   320 {
   321     mDeviceManager = nullptr;
   323     // not calling FT_Done_FreeType because cairo may still hold references to
   324     // these FT_Faces.  See bug 458169.
   325 #ifdef CAIRO_HAS_D2D_SURFACE
   326     if (mD2DDevice) {
   327         cairo_release_device(mD2DDevice);
   328     }
   329 #endif
   331     mozilla::gfx::Factory::D2DCleanup();
   333     /* 
   334      * Uninitialize COM 
   335      */ 
   336     CoUninitialize();
   337 }
   339 double
   340 gfxWindowsPlatform::GetDPIScale()
   341 {
   342   return WinUtils::LogToPhysFactor();
   343 }
   345 void
   346 gfxWindowsPlatform::UpdateRenderMode()
   347 {
   348 /* Pick the default render mode for
   349  * desktop.
   350  */
   351     mRenderMode = RENDER_GDI;
   353     bool isVistaOrHigher = IsVistaOrLater();
   355     bool safeMode = false;
   356     nsCOMPtr<nsIXULRuntime> xr = do_GetService("@mozilla.org/xre/runtime;1");
   357     if (xr)
   358       xr->GetInSafeMode(&safeMode);
   360     mUseDirectWrite = Preferences::GetBool("gfx.font_rendering.directwrite.enabled", false);
   362 #ifdef CAIRO_HAS_D2D_SURFACE
   363     bool d2dDisabled = false;
   364     bool d2dForceEnabled = false;
   365     bool d2dBlocked = false;
   367     nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
   368     if (gfxInfo) {
   369         int32_t status;
   370         if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT2D, &status))) {
   371             if (status != nsIGfxInfo::FEATURE_NO_INFO) {
   372                 d2dBlocked = true;
   373             }
   374         }
   375     }
   377     // These will only be evaluated once, and any subsequent changes to
   378     // the preferences will be ignored until restart.
   379     d2dDisabled = gfxPrefs::Direct2DDisabled();
   380     d2dForceEnabled = gfxPrefs::Direct2DForceEnabled();
   382     bool tryD2D = d2dForceEnabled || (!d2dBlocked && !gfxPrefs::LayersPreferD3D9());
   384     // Do not ever try if d2d is explicitly disabled,
   385     // or if we're not using DWrite fonts.
   386     if (d2dDisabled || mUsingGDIFonts) {
   387         tryD2D = false;
   388     }
   390     if (isVistaOrHigher  && !safeMode && tryD2D) {
   391         VerifyD2DDevice(d2dForceEnabled);
   392         if (mD2DDevice) {
   393             mRenderMode = RENDER_DIRECT2D;
   394             mUseDirectWrite = true;
   395         }
   396     } else {
   397         mD2DDevice = nullptr;
   398     }
   399 #endif
   401 #ifdef CAIRO_HAS_DWRITE_FONT
   402     // Enable when it's preffed on -and- we're using Vista or higher. Or when
   403     // we're going to use D2D.
   404     if (!mDWriteFactory && (mUseDirectWrite && isVistaOrHigher)) {
   405         mozilla::ScopedGfxFeatureReporter reporter("DWrite");
   406         decltype(DWriteCreateFactory)* createDWriteFactory = (decltype(DWriteCreateFactory)*)
   407             GetProcAddress(LoadLibraryW(L"dwrite.dll"), "DWriteCreateFactory");
   409         if (createDWriteFactory) {
   410             /**
   411              * I need a direct pointer to be able to cast to IUnknown**, I also
   412              * need to remember to release this because the nsRefPtr will
   413              * AddRef it.
   414              */
   415             IDWriteFactory *factory;
   416             HRESULT hr = createDWriteFactory(
   417                 DWRITE_FACTORY_TYPE_SHARED,
   418                 __uuidof(IDWriteFactory),
   419                 reinterpret_cast<IUnknown**>(&factory));
   421             if (SUCCEEDED(hr) && factory) {
   422                 mDWriteFactory = factory;
   423                 factory->Release();
   424                 hr = mDWriteFactory->CreateTextAnalyzer(
   425                     getter_AddRefs(mDWriteAnalyzer));
   426             }
   428             SetupClearTypeParams();
   430             if (hr == S_OK)
   431               reporter.SetSuccessful();
   432         }
   433     }
   434 #endif
   436     uint32_t canvasMask = BackendTypeBit(BackendType::CAIRO);
   437     uint32_t contentMask = BackendTypeBit(BackendType::CAIRO);
   438     BackendType defaultBackend = BackendType::CAIRO;
   439     if (mRenderMode == RENDER_DIRECT2D) {
   440       canvasMask |= BackendTypeBit(BackendType::DIRECT2D);
   441       contentMask |= BackendTypeBit(BackendType::DIRECT2D);
   442       defaultBackend = BackendType::DIRECT2D;
   443     } else {
   444       canvasMask |= BackendTypeBit(BackendType::SKIA);
   445     }
   446     contentMask |= BackendTypeBit(BackendType::SKIA);
   447     InitBackendPrefs(canvasMask, defaultBackend,
   448                      contentMask, defaultBackend);
   449 }
   451 #ifdef CAIRO_HAS_D2D_SURFACE
   452 HRESULT
   453 gfxWindowsPlatform::CreateDevice(nsRefPtr<IDXGIAdapter1> &adapter1,
   454                                  int featureLevelIndex)
   455 {
   456   nsModuleHandle d3d10module(LoadLibrarySystem32(L"d3d10_1.dll"));
   457   if (!d3d10module)
   458     return E_FAIL;
   459   decltype(D3D10CreateDevice1)* createD3DDevice =
   460     (decltype(D3D10CreateDevice1)*) GetProcAddress(d3d10module, "D3D10CreateDevice1");
   461   if (!createD3DDevice)
   462     return E_FAIL;
   464   nsRefPtr<ID3D10Device1> device;
   465   HRESULT hr =
   466     createD3DDevice(adapter1, D3D10_DRIVER_TYPE_HARDWARE, nullptr,
   467                     D3D10_CREATE_DEVICE_BGRA_SUPPORT |
   468                     D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
   469                     static_cast<D3D10_FEATURE_LEVEL1>(kSupportedFeatureLevels[featureLevelIndex]),
   470                     D3D10_1_SDK_VERSION, getter_AddRefs(device));
   472   // If we fail here, the DirectX version or video card probably
   473   // changed.  We previously could use 10.1 but now we can't
   474   // anymore.  Revert back to doing a 10.0 check first before
   475   // the 10.1 check.
   476   if (device) {
   477     mD2DDevice = cairo_d2d_create_device_from_d3d10device(device);
   479     // Setup a pref for future launch optimizaitons when in main process.
   480     if (XRE_GetProcessType() == GeckoProcessType_Default) {
   481       Preferences::SetInt(kFeatureLevelPref, featureLevelIndex);
   482     }
   483   }
   485   return device ? S_OK : hr;
   486 }
   487 #endif
   489 void
   490 gfxWindowsPlatform::VerifyD2DDevice(bool aAttemptForce)
   491 {
   492 #ifdef CAIRO_HAS_D2D_SURFACE
   493     if (mD2DDevice) {
   494         ID3D10Device1 *device = cairo_d2d_device_get_device(mD2DDevice);
   496         if (SUCCEEDED(device->GetDeviceRemovedReason())) {
   497             return;
   498         }
   499         mD2DDevice = nullptr;
   501         // Surface cache needs to be invalidated since it may contain vector
   502         // images rendered with our old, broken D2D device.
   503         SurfaceCache::DiscardAll();
   504     }
   506     mozilla::ScopedGfxFeatureReporter reporter("D2D", aAttemptForce);
   508     nsRefPtr<ID3D10Device1> device;
   510     int supportedFeatureLevelsCount = ArrayLength(kSupportedFeatureLevels);
   511     // If we're not running in Metro don't allow DX9.3
   512     if (!IsRunningInWindowsMetro()) {
   513       supportedFeatureLevelsCount--;
   514     }
   516     nsRefPtr<IDXGIAdapter1> adapter1 = GetDXGIAdapter();
   518     if (!adapter1) {
   519       // Unable to create adapter, abort acceleration.
   520       return;
   521     }
   523     // It takes a lot of time (5-10% of startup time or ~100ms) to do both
   524     // a createD3DDevice on D3D10_FEATURE_LEVEL_10_0.  We therefore store
   525     // the last used feature level to go direct to that.
   526     int featureLevelIndex = Preferences::GetInt(kFeatureLevelPref, 0);
   527     if (featureLevelIndex >= supportedFeatureLevelsCount || featureLevelIndex < 0)
   528       featureLevelIndex = 0;
   530     // Start with the last used feature level, and move to lower DX versions
   531     // until we find one that works.
   532     HRESULT hr = E_FAIL;
   533     for (int i = featureLevelIndex; i < supportedFeatureLevelsCount; i++) {
   534       hr = CreateDevice(adapter1, i);
   535       // If it succeeded we found the first available feature level
   536       if (SUCCEEDED(hr))
   537         break;
   538     }
   540     // If we succeeded in creating a device, try for a newer device
   541     // that we haven't tried yet.
   542     if (SUCCEEDED(hr)) {
   543       for (int i = featureLevelIndex - 1; i >= 0; i--) {
   544         hr = CreateDevice(adapter1, i);
   545         // If it failed then we don't have new hardware
   546         if (FAILED(hr)) {
   547           break;
   548         }
   549       }
   550     }
   552     if (!mD2DDevice && aAttemptForce) {
   553         mD2DDevice = cairo_d2d_create_device();
   554     }
   556     if (mD2DDevice) {
   557         reporter.SetSuccessful();
   558         mozilla::gfx::Factory::SetDirect3D10Device(cairo_d2d_device_get_device(mD2DDevice));
   559     }
   560 #endif
   561 }
   563 gfxPlatformFontList*
   564 gfxWindowsPlatform::CreatePlatformFontList()
   565 {
   566     mUsingGDIFonts = false;
   567     gfxPlatformFontList *pfl;
   568 #ifdef CAIRO_HAS_DWRITE_FONT
   569     // bug 630201 - older pre-RTM versions of Direct2D/DirectWrite cause odd
   570     // crashers so blacklist them altogether
   571     if (IsNotWin7PreRTM() && GetDWriteFactory()) {
   572         pfl = new gfxDWriteFontList();
   573         if (NS_SUCCEEDED(pfl->InitFontList())) {
   574             return pfl;
   575         }
   576         // DWrite font initialization failed! Don't know why this would happen,
   577         // but apparently it can - see bug 594865.
   578         // So we're going to fall back to GDI fonts & rendering.
   579         gfxPlatformFontList::Shutdown();
   580         SetRenderMode(RENDER_GDI);
   581     }
   582 #endif
   583     pfl = new gfxGDIFontList();
   584     mUsingGDIFonts = true;
   586     if (NS_SUCCEEDED(pfl->InitFontList())) {
   587         return pfl;
   588     }
   590     gfxPlatformFontList::Shutdown();
   591     return nullptr;
   592 }
   594 already_AddRefed<gfxASurface>
   595 gfxWindowsPlatform::CreateOffscreenSurface(const IntSize& size,
   596                                            gfxContentType contentType)
   597 {
   598     nsRefPtr<gfxASurface> surf = nullptr;
   600 #ifdef CAIRO_HAS_WIN32_SURFACE
   601     if (mRenderMode == RENDER_GDI)
   602         surf = new gfxWindowsSurface(ThebesIntSize(size),
   603                                      OptimalFormatForContent(contentType));
   604 #endif
   606 #ifdef CAIRO_HAS_D2D_SURFACE
   607     if (mRenderMode == RENDER_DIRECT2D)
   608         surf = new gfxD2DSurface(ThebesIntSize(size),
   609                                  OptimalFormatForContent(contentType));
   610 #endif
   612     if (!surf || surf->CairoStatus()) {
   613         surf = new gfxImageSurface(ThebesIntSize(size),
   614                                    OptimalFormatForContent(contentType));
   615     }
   617     return surf.forget();
   618 }
   620 already_AddRefed<gfxASurface>
   621 gfxWindowsPlatform::CreateOffscreenImageSurface(const gfxIntSize& aSize,
   622                                                 gfxContentType aContentType)
   623 {
   624 #ifdef CAIRO_HAS_D2D_SURFACE
   625     if (mRenderMode == RENDER_DIRECT2D) {
   626         nsRefPtr<gfxASurface> surface =
   627           new gfxImageSurface(aSize, OptimalFormatForContent(aContentType));
   628         return surface.forget();
   629     }
   630 #endif
   632     nsRefPtr<gfxASurface> surface = CreateOffscreenSurface(aSize.ToIntSize(),
   633                                                            aContentType);
   634 #ifdef DEBUG
   635     nsRefPtr<gfxImageSurface> imageSurface = surface->GetAsImageSurface();
   636     NS_ASSERTION(imageSurface, "Surface cannot be converted to a gfxImageSurface");
   637 #endif
   638     return surface.forget();
   639 }
   641 TemporaryRef<ScaledFont>
   642 gfxWindowsPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
   643 {
   644     if (aFont->GetType() == gfxFont::FONT_TYPE_DWRITE) {
   645         gfxDWriteFont *font = static_cast<gfxDWriteFont*>(aFont);
   647         NativeFont nativeFont;
   648         nativeFont.mType = NativeFontType::DWRITE_FONT_FACE;
   649         nativeFont.mFont = font->GetFontFace();
   651         if (aTarget->GetType() == BackendType::CAIRO) {
   652           return Factory::CreateScaledFontWithCairo(nativeFont,
   653                                                     font->GetAdjustedSize(),
   654                                                     font->GetCairoScaledFont());
   655         }
   657         return Factory::CreateScaledFontForNativeFont(nativeFont,
   658                                                       font->GetAdjustedSize());
   659     }
   661     NS_ASSERTION(aFont->GetType() == gfxFont::FONT_TYPE_GDI,
   662         "Fonts on windows should be GDI or DWrite!");
   664     NativeFont nativeFont;
   665     nativeFont.mType = NativeFontType::GDI_FONT_FACE;
   666     LOGFONT lf;
   667     GetObject(static_cast<gfxGDIFont*>(aFont)->GetHFONT(), sizeof(LOGFONT), &lf);
   668     nativeFont.mFont = &lf;
   670     if (aTarget->GetType() == BackendType::CAIRO) {
   671       return Factory::CreateScaledFontWithCairo(nativeFont,
   672                                                 aFont->GetAdjustedSize(),
   673                                                 aFont->GetCairoScaledFont());
   674     }
   676     return Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
   677 }
   679 already_AddRefed<gfxASurface>
   680 gfxWindowsPlatform::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
   681 {
   682 #ifdef XP_WIN
   683   if (aTarget->GetType() == BackendType::DIRECT2D) {
   684     if (!GetD2DDevice()) {
   685       // We no longer have a D2D device, can't do this.
   686       return nullptr;
   687     }
   689     RefPtr<ID3D10Texture2D> texture =
   690       static_cast<ID3D10Texture2D*>(aTarget->GetNativeSurface(NativeSurfaceType::D3D10_TEXTURE));
   692     if (!texture) {
   693       return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget);
   694     }
   696     aTarget->Flush();
   698     nsRefPtr<gfxASurface> surf =
   699       new gfxD2DSurface(texture, ContentForFormat(aTarget->GetFormat()));
   701     // shouldn't this hold a reference?
   702     surf->SetData(&kDrawTarget, aTarget, nullptr);
   703     return surf.forget();
   704   }
   705 #endif
   707   return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget);
   708 }
   710 nsresult
   711 gfxWindowsPlatform::GetFontList(nsIAtom *aLangGroup,
   712                                 const nsACString& aGenericFamily,
   713                                 nsTArray<nsString>& aListOfFonts)
   714 {
   715     gfxPlatformFontList::PlatformFontList()->GetFontList(aLangGroup, aGenericFamily, aListOfFonts);
   717     return NS_OK;
   718 }
   720 static void
   721 RemoveCharsetFromFontSubstitute(nsAString &aName)
   722 {
   723     int32_t comma = aName.FindChar(char16_t(','));
   724     if (comma >= 0)
   725         aName.Truncate(comma);
   726 }
   728 nsresult
   729 gfxWindowsPlatform::UpdateFontList()
   730 {
   731     gfxPlatformFontList::PlatformFontList()->UpdateFontList();
   733     return NS_OK;
   734 }
   736 static const char kFontAparajita[] = "Aparajita";
   737 static const char kFontArabicTypesetting[] = "Arabic Typesetting";
   738 static const char kFontArial[] = "Arial";
   739 static const char kFontArialUnicodeMS[] = "Arial Unicode MS";
   740 static const char kFontCambria[] = "Cambria";
   741 static const char kFontCambriaMath[] = "Cambria Math";
   742 static const char kFontEbrima[] = "Ebrima";
   743 static const char kFontEstrangeloEdessa[] = "Estrangelo Edessa";
   744 static const char kFontEuphemia[] = "Euphemia";
   745 static const char kFontGabriola[] = "Gabriola";
   746 static const char kFontJavaneseText[] = "Javanese Text";
   747 static const char kFontKhmerUI[] = "Khmer UI";
   748 static const char kFontLaoUI[] = "Lao UI";
   749 static const char kFontLeelawadeeUI[] = "Leelawadee UI";
   750 static const char kFontLucidaSansUnicode[] = "Lucida Sans Unicode";
   751 static const char kFontMVBoli[] = "MV Boli";
   752 static const char kFontMalgunGothic[] = "Malgun Gothic";
   753 static const char kFontMicrosoftJhengHei[] = "Microsoft JhengHei";
   754 static const char kFontMicrosoftNewTaiLue[] = "Microsoft New Tai Lue";
   755 static const char kFontMicrosoftPhagsPa[] = "Microsoft PhagsPa";
   756 static const char kFontMicrosoftTaiLe[] = "Microsoft Tai Le";
   757 static const char kFontMicrosoftUighur[] = "Microsoft Uighur";
   758 static const char kFontMicrosoftYaHei[] = "Microsoft YaHei";
   759 static const char kFontMicrosoftYiBaiti[] = "Microsoft Yi Baiti";
   760 static const char kFontMeiryo[] = "Meiryo";
   761 static const char kFontMongolianBaiti[] = "Mongolian Baiti";
   762 static const char kFontMyanmarText[] = "Myanmar Text";
   763 static const char kFontNirmalaUI[] = "Nirmala UI";
   764 static const char kFontNyala[] = "Nyala";
   765 static const char kFontPlantagenetCherokee[] = "Plantagenet Cherokee";
   766 static const char kFontSegoeUI[] = "Segoe UI";
   767 static const char kFontSegoeUISymbol[] = "Segoe UI Symbol";
   768 static const char kFontSylfaen[] = "Sylfaen";
   769 static const char kFontTraditionalArabic[] = "Traditional Arabic";
   770 static const char kFontUtsaah[] = "Utsaah";
   771 static const char kFontYuGothic[] = "Yu Gothic";
   773 void
   774 gfxWindowsPlatform::GetCommonFallbackFonts(const uint32_t aCh,
   775                                            int32_t aRunScript,
   776                                            nsTArray<const char*>& aFontList)
   777 {
   778     // Arial is used as the default fallback for system fallback
   779     aFontList.AppendElement(kFontArial);
   781     if (!IS_IN_BMP(aCh)) {
   782         uint32_t p = aCh >> 16;
   783         if (p == 1) { // SMP plane
   784             aFontList.AppendElement(kFontSegoeUISymbol);
   785             aFontList.AppendElement(kFontEbrima);
   786             aFontList.AppendElement(kFontNirmalaUI);
   787             aFontList.AppendElement(kFontCambriaMath);
   788         }
   789     } else {
   790         uint32_t b = (aCh >> 8) & 0xff;
   792         switch (b) {
   793         case 0x05:
   794             aFontList.AppendElement(kFontEstrangeloEdessa);
   795             aFontList.AppendElement(kFontCambria);
   796             break;
   797         case 0x06:
   798             aFontList.AppendElement(kFontMicrosoftUighur);
   799             break;
   800         case 0x07:
   801             aFontList.AppendElement(kFontEstrangeloEdessa);
   802             aFontList.AppendElement(kFontMVBoli);
   803             aFontList.AppendElement(kFontEbrima);
   804             break;
   805         case 0x09:
   806             aFontList.AppendElement(kFontNirmalaUI);
   807             aFontList.AppendElement(kFontUtsaah);
   808             aFontList.AppendElement(kFontAparajita);
   809             break;
   810         case 0x0e:
   811             aFontList.AppendElement(kFontLaoUI);
   812             break;
   813         case 0x10:
   814             aFontList.AppendElement(kFontMyanmarText);
   815             break;
   816         case 0x11:
   817             aFontList.AppendElement(kFontMalgunGothic);
   818             break;
   819         case 0x12:
   820         case 0x13:
   821             aFontList.AppendElement(kFontNyala);
   822             aFontList.AppendElement(kFontPlantagenetCherokee);
   823             break;
   824         case 0x14:
   825         case 0x15:
   826         case 0x16:
   827             aFontList.AppendElement(kFontEuphemia);
   828             aFontList.AppendElement(kFontSegoeUISymbol);
   829             break;
   830         case 0x17:
   831             aFontList.AppendElement(kFontKhmerUI);
   832             break;
   833         case 0x18:  // Mongolian
   834             aFontList.AppendElement(kFontMongolianBaiti);
   835             aFontList.AppendElement(kFontEuphemia);
   836             break;
   837         case 0x19:
   838             aFontList.AppendElement(kFontMicrosoftTaiLe);
   839             aFontList.AppendElement(kFontMicrosoftNewTaiLue);
   840             aFontList.AppendElement(kFontKhmerUI);
   841             break;
   842             break;
   843         case 0x1a:
   844             aFontList.AppendElement(kFontLeelawadeeUI);
   845             break;
   846         case 0x1c:
   847             aFontList.AppendElement(kFontNirmalaUI);
   848             break;
   849         case 0x20:  // Symbol ranges
   850         case 0x21:
   851         case 0x22:
   852         case 0x23:
   853         case 0x24:
   854         case 0x25:
   855         case 0x26:
   856         case 0x27:
   857         case 0x29:
   858         case 0x2a:
   859         case 0x2b:
   860         case 0x2c:
   861             aFontList.AppendElement(kFontSegoeUI);
   862             aFontList.AppendElement(kFontSegoeUISymbol);
   863             aFontList.AppendElement(kFontCambria);
   864             aFontList.AppendElement(kFontMeiryo);
   865             aFontList.AppendElement(kFontArial);
   866             aFontList.AppendElement(kFontLucidaSansUnicode);
   867             aFontList.AppendElement(kFontEbrima);
   868             break;
   869         case 0x2d:
   870         case 0x2e:
   871         case 0x2f:
   872             aFontList.AppendElement(kFontEbrima);
   873             aFontList.AppendElement(kFontNyala);
   874             aFontList.AppendElement(kFontSegoeUI);
   875             aFontList.AppendElement(kFontSegoeUISymbol);
   876             aFontList.AppendElement(kFontMeiryo);
   877             break;
   878         case 0x28:  // Braille
   879             aFontList.AppendElement(kFontSegoeUISymbol);
   880             break;
   881         case 0x30:
   882         case 0x31:
   883             aFontList.AppendElement(kFontMicrosoftYaHei);
   884             break;
   885         case 0x32:
   886             aFontList.AppendElement(kFontMalgunGothic);
   887             break;
   888         case 0x4d:
   889             aFontList.AppendElement(kFontSegoeUISymbol);
   890             break;
   891         case 0x9f:
   892             aFontList.AppendElement(kFontMicrosoftYaHei);
   893             aFontList.AppendElement(kFontYuGothic);
   894             break;
   895         case 0xa0:  // Yi
   896         case 0xa1:
   897         case 0xa2:
   898         case 0xa3:
   899         case 0xa4:
   900             aFontList.AppendElement(kFontMicrosoftYiBaiti);
   901             aFontList.AppendElement(kFontSegoeUI);
   902             break;
   903         case 0xa5:
   904         case 0xa6:
   905         case 0xa7:
   906             aFontList.AppendElement(kFontEbrima);
   907             aFontList.AppendElement(kFontSegoeUI);
   908             aFontList.AppendElement(kFontCambriaMath);
   909             break;
   910         case 0xa8:
   911              aFontList.AppendElement(kFontMicrosoftPhagsPa);
   912              aFontList.AppendElement(kFontNirmalaUI);
   913              break;
   914         case 0xa9:
   915              aFontList.AppendElement(kFontMalgunGothic);
   916              aFontList.AppendElement(kFontJavaneseText);
   917              break;
   918         case 0xaa:
   919              aFontList.AppendElement(kFontMyanmarText);
   920              break;
   921         case 0xab:
   922              aFontList.AppendElement(kFontEbrima);
   923              aFontList.AppendElement(kFontNyala);
   924              break;
   925         case 0xd7:
   926              aFontList.AppendElement(kFontMalgunGothic);
   927              break;
   928         case 0xfb:
   929             aFontList.AppendElement(kFontMicrosoftUighur);
   930             aFontList.AppendElement(kFontGabriola);
   931             aFontList.AppendElement(kFontSylfaen);
   932             break;
   933         case 0xfc:
   934         case 0xfd:
   935             aFontList.AppendElement(kFontTraditionalArabic);
   936             aFontList.AppendElement(kFontArabicTypesetting);
   937             break;
   938         case 0xfe:
   939             aFontList.AppendElement(kFontTraditionalArabic);
   940             aFontList.AppendElement(kFontMicrosoftJhengHei);
   941            break;
   942        case 0xff:
   943             aFontList.AppendElement(kFontMicrosoftJhengHei);
   944             break;
   945         default:
   946             break;
   947         }
   948     }
   950     // Arial Unicode MS has lots of glyphs for obscure characters,
   951     // use it as a last resort
   952     aFontList.AppendElement(kFontArialUnicodeMS);
   953 }
   955 struct ResolveData {
   956     ResolveData(gfxPlatform::FontResolverCallback aCallback,
   957                 gfxWindowsPlatform *aCaller, const nsAString *aFontName,
   958                 void *aClosure) :
   959         mFoundCount(0), mCallback(aCallback), mCaller(aCaller),
   960         mFontName(aFontName), mClosure(aClosure) {}
   961     uint32_t mFoundCount;
   962     gfxPlatform::FontResolverCallback mCallback;
   963     gfxWindowsPlatform *mCaller;
   964     const nsAString *mFontName;
   965     void *mClosure;
   966 };
   968 nsresult
   969 gfxWindowsPlatform::ResolveFontName(const nsAString& aFontName,
   970                                     FontResolverCallback aCallback,
   971                                     void *aClosure,
   972                                     bool& aAborted)
   973 {
   974     nsAutoString resolvedName;
   975     if (!gfxPlatformFontList::PlatformFontList()->
   976              ResolveFontName(aFontName, resolvedName)) {
   977         aAborted = false;
   978         return NS_OK;
   979     }
   980     aAborted = !(*aCallback)(resolvedName, aClosure);
   981     return NS_OK;
   982 }
   984 nsresult
   985 gfxWindowsPlatform::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName)
   986 {
   987     gfxPlatformFontList::PlatformFontList()->GetStandardFamilyName(aFontName, aFamilyName);
   988     return NS_OK;
   989 }
   991 gfxFontGroup *
   992 gfxWindowsPlatform::CreateFontGroup(const nsAString &aFamilies,
   993                                     const gfxFontStyle *aStyle,
   994                                     gfxUserFontSet *aUserFontSet)
   995 {
   996     return new gfxFontGroup(aFamilies, aStyle, aUserFontSet);
   997 }
   999 gfxFontEntry* 
  1000 gfxWindowsPlatform::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
  1001                                     const nsAString& aFontName)
  1003     return gfxPlatformFontList::PlatformFontList()->LookupLocalFont(aProxyEntry, 
  1004                                                                     aFontName);
  1007 gfxFontEntry* 
  1008 gfxWindowsPlatform::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
  1009                                      const uint8_t *aFontData, uint32_t aLength)
  1011     return gfxPlatformFontList::PlatformFontList()->MakePlatformFont(aProxyEntry,
  1012                                                                      aFontData,
  1013                                                                      aLength);
  1016 bool
  1017 gfxWindowsPlatform::IsFontFormatSupported(nsIURI *aFontURI, uint32_t aFormatFlags)
  1019     // check for strange format flags
  1020     NS_ASSERTION(!(aFormatFlags & gfxUserFontSet::FLAG_FORMAT_NOT_USED),
  1021                  "strange font format hint set");
  1023     // accept supported formats
  1024     if (aFormatFlags & (gfxUserFontSet::FLAG_FORMAT_WOFF     |
  1025                         gfxUserFontSet::FLAG_FORMAT_OPENTYPE | 
  1026                         gfxUserFontSet::FLAG_FORMAT_TRUETYPE)) {
  1027         return true;
  1030     // reject all other formats, known and unknown
  1031     if (aFormatFlags != 0) {
  1032         return false;
  1035     // no format hint set, need to look at data
  1036     return true;
  1039 gfxFontFamily *
  1040 gfxWindowsPlatform::FindFontFamily(const nsAString& aName)
  1042     return gfxPlatformFontList::PlatformFontList()->FindFamily(aName);
  1045 gfxFontEntry *
  1046 gfxWindowsPlatform::FindFontEntry(const nsAString& aName, const gfxFontStyle& aFontStyle)
  1048     nsRefPtr<gfxFontFamily> ff = FindFontFamily(aName);
  1049     if (!ff)
  1050         return nullptr;
  1052     bool aNeedsBold;
  1053     return ff->FindFontForStyle(aFontStyle, aNeedsBold);
  1056 void
  1057 gfxWindowsPlatform::GetPlatformCMSOutputProfile(void* &mem, size_t &mem_size)
  1059     WCHAR str[MAX_PATH];
  1060     DWORD size = MAX_PATH;
  1061     BOOL res;
  1063     mem = nullptr;
  1064     mem_size = 0;
  1066     HDC dc = GetDC(nullptr);
  1067     if (!dc)
  1068         return;
  1070 #if _MSC_VER
  1071     __try {
  1072         res = GetICMProfileW(dc, &size, (LPWSTR)&str);
  1073     } __except(GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION) {
  1074         res = FALSE;
  1076 #else
  1077     res = GetICMProfileW(dc, &size, (LPWSTR)&str);
  1078 #endif
  1080     ReleaseDC(nullptr, dc);
  1081     if (!res)
  1082         return;
  1084 #ifdef _WIN32
  1085     qcms_data_from_unicode_path(str, &mem, &mem_size);
  1087 #ifdef DEBUG_tor
  1088     if (mem_size > 0)
  1089         fprintf(stderr,
  1090                 "ICM profile read from %s successfully\n",
  1091                 NS_ConvertUTF16toUTF8(str).get());
  1092 #endif // DEBUG_tor
  1093 #endif // _WIN32
  1096 bool
  1097 gfxWindowsPlatform::GetPrefFontEntries(const nsCString& aKey, nsTArray<nsRefPtr<gfxFontEntry> > *array)
  1099     return mPrefFonts.Get(aKey, array);
  1102 void
  1103 gfxWindowsPlatform::SetPrefFontEntries(const nsCString& aKey, nsTArray<nsRefPtr<gfxFontEntry> >& array)
  1105     mPrefFonts.Put(aKey, array);
  1108 bool
  1109 gfxWindowsPlatform::UseClearTypeForDownloadableFonts()
  1111     if (mUseClearTypeForDownloadableFonts == UNINITIALIZED_VALUE) {
  1112         mUseClearTypeForDownloadableFonts = Preferences::GetBool(GFX_DOWNLOADABLE_FONTS_USE_CLEARTYPE, true);
  1115     return mUseClearTypeForDownloadableFonts;
  1118 bool
  1119 gfxWindowsPlatform::UseClearTypeAlways()
  1121     if (mUseClearTypeAlways == UNINITIALIZED_VALUE) {
  1122         mUseClearTypeAlways = Preferences::GetBool(GFX_USE_CLEARTYPE_ALWAYS, false);
  1125     return mUseClearTypeAlways;
  1128 void 
  1129 gfxWindowsPlatform::GetDLLVersion(char16ptr_t aDLLPath, nsAString& aVersion)
  1131     DWORD versInfoSize, vers[4] = {0};
  1132     // version info not available case
  1133     aVersion.Assign(NS_LITERAL_STRING("0.0.0.0"));
  1134     versInfoSize = GetFileVersionInfoSizeW(aDLLPath, nullptr);
  1135     nsAutoTArray<BYTE,512> versionInfo;
  1137     if (versInfoSize == 0 ||
  1138         !versionInfo.AppendElements(uint32_t(versInfoSize)))
  1140         return;
  1143     if (!GetFileVersionInfoW(aDLLPath, 0, versInfoSize, 
  1144            LPBYTE(versionInfo.Elements())))
  1146         return;
  1149     UINT len = 0;
  1150     VS_FIXEDFILEINFO *fileInfo = nullptr;
  1151     if (!VerQueryValue(LPBYTE(versionInfo.Elements()), TEXT("\\"),
  1152            (LPVOID *)&fileInfo, &len) ||
  1153         len == 0 ||
  1154         fileInfo == nullptr)
  1156         return;
  1159     DWORD fileVersMS = fileInfo->dwFileVersionMS; 
  1160     DWORD fileVersLS = fileInfo->dwFileVersionLS;
  1162     vers[0] = HIWORD(fileVersMS);
  1163     vers[1] = LOWORD(fileVersMS);
  1164     vers[2] = HIWORD(fileVersLS);
  1165     vers[3] = LOWORD(fileVersLS);
  1167     char buf[256];
  1168     sprintf(buf, "%d.%d.%d.%d", vers[0], vers[1], vers[2], vers[3]);
  1169     aVersion.Assign(NS_ConvertUTF8toUTF16(buf));
  1172 void 
  1173 gfxWindowsPlatform::GetCleartypeParams(nsTArray<ClearTypeParameterInfo>& aParams)
  1175     HKEY  hKey, subKey;
  1176     DWORD i, rv, size, type;
  1177     WCHAR displayName[256], subkeyName[256];
  1179     aParams.Clear();
  1181     // construct subkeys based on HKLM subkeys, assume they are same for HKCU
  1182     rv = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
  1183                        L"Software\\Microsoft\\Avalon.Graphics",
  1184                        0, KEY_READ, &hKey);
  1186     if (rv != ERROR_SUCCESS) {
  1187         return;
  1190     // enumerate over subkeys
  1191     for (i = 0, rv = ERROR_SUCCESS; rv != ERROR_NO_MORE_ITEMS; i++) {
  1192         size = ArrayLength(displayName);
  1193         rv = RegEnumKeyExW(hKey, i, displayName, &size,
  1194                            nullptr, nullptr, nullptr, nullptr);
  1195         if (rv != ERROR_SUCCESS) {
  1196             continue;
  1199         ClearTypeParameterInfo ctinfo;
  1200         ctinfo.displayName.Assign(displayName);
  1202         DWORD subrv, value;
  1203         bool foundData = false;
  1205         swprintf_s(subkeyName, ArrayLength(subkeyName),
  1206                    L"Software\\Microsoft\\Avalon.Graphics\\%s", displayName);
  1208         // subkey for gamma, pixel structure
  1209         subrv = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
  1210                               subkeyName, 0, KEY_QUERY_VALUE, &subKey);
  1212         if (subrv == ERROR_SUCCESS) {
  1213             size = sizeof(value);
  1214             subrv = RegQueryValueExW(subKey, L"GammaLevel", nullptr, &type,
  1215                                      (LPBYTE)&value, &size);
  1216             if (subrv == ERROR_SUCCESS && type == REG_DWORD) {
  1217                 foundData = true;
  1218                 ctinfo.gamma = value;
  1221             size = sizeof(value);
  1222             subrv = RegQueryValueExW(subKey, L"PixelStructure", nullptr, &type,
  1223                                      (LPBYTE)&value, &size);
  1224             if (subrv == ERROR_SUCCESS && type == REG_DWORD) {
  1225                 foundData = true;
  1226                 ctinfo.pixelStructure = value;
  1229             RegCloseKey(subKey);
  1232         // subkey for cleartype level, enhanced contrast
  1233         subrv = RegOpenKeyExW(HKEY_CURRENT_USER,
  1234                               subkeyName, 0, KEY_QUERY_VALUE, &subKey);
  1236         if (subrv == ERROR_SUCCESS) {
  1237             size = sizeof(value);
  1238             subrv = RegQueryValueExW(subKey, L"ClearTypeLevel", nullptr, &type,
  1239                                      (LPBYTE)&value, &size);
  1240             if (subrv == ERROR_SUCCESS && type == REG_DWORD) {
  1241                 foundData = true;
  1242                 ctinfo.clearTypeLevel = value;
  1245             size = sizeof(value);
  1246             subrv = RegQueryValueExW(subKey, L"EnhancedContrastLevel",
  1247                                      nullptr, &type, (LPBYTE)&value, &size);
  1248             if (subrv == ERROR_SUCCESS && type == REG_DWORD) {
  1249                 foundData = true;
  1250                 ctinfo.enhancedContrast = value;
  1253             RegCloseKey(subKey);
  1256         if (foundData) {
  1257             aParams.AppendElement(ctinfo);
  1261     RegCloseKey(hKey);
  1264 void
  1265 gfxWindowsPlatform::FontsPrefsChanged(const char *aPref)
  1267     bool clearTextFontCaches = true;
  1269     gfxPlatform::FontsPrefsChanged(aPref);
  1271     if (!aPref) {
  1272         mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
  1273         mUseClearTypeAlways = UNINITIALIZED_VALUE;
  1274     } else if (!strcmp(GFX_DOWNLOADABLE_FONTS_USE_CLEARTYPE, aPref)) {
  1275         mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
  1276     } else if (!strcmp(GFX_USE_CLEARTYPE_ALWAYS, aPref)) {
  1277         mUseClearTypeAlways = UNINITIALIZED_VALUE;
  1278     } else if (!strncmp(GFX_CLEARTYPE_PARAMS, aPref, strlen(GFX_CLEARTYPE_PARAMS))) {
  1279         SetupClearTypeParams();
  1280     } else {
  1281         clearTextFontCaches = false;
  1284     if (clearTextFontCaches) {    
  1285         gfxFontCache *fc = gfxFontCache::GetCache();
  1286         if (fc) {
  1287             fc->Flush();
  1292 #define ENHANCED_CONTRAST_REGISTRY_KEY \
  1293     HKEY_CURRENT_USER, "Software\\Microsoft\\Avalon.Graphics\\DISPLAY1\\EnhancedContrastLevel"
  1295 void
  1296 gfxWindowsPlatform::SetupClearTypeParams()
  1298 #if CAIRO_HAS_DWRITE_FONT
  1299     if (GetDWriteFactory()) {
  1300         // any missing prefs will default to invalid (-1) and be ignored;
  1301         // out-of-range values will also be ignored
  1302         FLOAT gamma = -1.0;
  1303         FLOAT contrast = -1.0;
  1304         FLOAT level = -1.0;
  1305         int geometry = -1;
  1306         int mode = -1;
  1307         int32_t value;
  1308         if (NS_SUCCEEDED(Preferences::GetInt(GFX_CLEARTYPE_PARAMS_GAMMA, &value))) {
  1309             if (value >= 1000 && value <= 2200) {
  1310                 gamma = FLOAT(value / 1000.0);
  1314         if (NS_SUCCEEDED(Preferences::GetInt(GFX_CLEARTYPE_PARAMS_CONTRAST, &value))) {
  1315             if (value >= 0 && value <= 1000) {
  1316                 contrast = FLOAT(value / 100.0);
  1320         if (NS_SUCCEEDED(Preferences::GetInt(GFX_CLEARTYPE_PARAMS_LEVEL, &value))) {
  1321             if (value >= 0 && value <= 100) {
  1322                 level = FLOAT(value / 100.0);
  1326         if (NS_SUCCEEDED(Preferences::GetInt(GFX_CLEARTYPE_PARAMS_STRUCTURE, &value))) {
  1327             if (value >= 0 && value <= 2) {
  1328                 geometry = value;
  1332         if (NS_SUCCEEDED(Preferences::GetInt(GFX_CLEARTYPE_PARAMS_MODE, &value))) {
  1333             if (value >= 0 && value <= 5) {
  1334                 mode = value;
  1338         cairo_dwrite_set_cleartype_params(gamma, contrast, level, geometry, mode);
  1340         switch (mode) {
  1341         case DWRITE_RENDERING_MODE_ALIASED:
  1342         case DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC:
  1343             mMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
  1344             break;
  1345         case DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL:
  1346             mMeasuringMode = DWRITE_MEASURING_MODE_GDI_NATURAL;
  1347             break;
  1348         default:
  1349             mMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
  1350             break;
  1353         nsRefPtr<IDWriteRenderingParams> defaultRenderingParams;
  1354         GetDWriteFactory()->CreateRenderingParams(getter_AddRefs(defaultRenderingParams));
  1355         // For EnhancedContrast, we override the default if the user has not set it
  1356         // in the registry (by using the ClearType Tuner).
  1357         if (contrast >= 0.0 && contrast <= 10.0) {
  1358 	    contrast = contrast;
  1359         } else {
  1360             HKEY hKey;
  1361             if (RegOpenKeyExA(ENHANCED_CONTRAST_REGISTRY_KEY,
  1362                               0, KEY_READ, &hKey) == ERROR_SUCCESS)
  1364                 contrast = defaultRenderingParams->GetEnhancedContrast();
  1365                 RegCloseKey(hKey);
  1366             } else {
  1367                 contrast = 1.0;
  1371         // For parameters that have not been explicitly set,
  1372         // we copy values from default params (or our overridden value for contrast)
  1373         if (gamma < 1.0 || gamma > 2.2) {
  1374             gamma = defaultRenderingParams->GetGamma();
  1377         if (level < 0.0 || level > 1.0) {
  1378             level = defaultRenderingParams->GetClearTypeLevel();
  1381         DWRITE_PIXEL_GEOMETRY dwriteGeometry =
  1382           static_cast<DWRITE_PIXEL_GEOMETRY>(geometry);
  1383         DWRITE_RENDERING_MODE renderMode =
  1384           static_cast<DWRITE_RENDERING_MODE>(mode);
  1386         if (dwriteGeometry < DWRITE_PIXEL_GEOMETRY_FLAT ||
  1387             dwriteGeometry > DWRITE_PIXEL_GEOMETRY_BGR) {
  1388             dwriteGeometry = defaultRenderingParams->GetPixelGeometry();
  1391         if (renderMode < DWRITE_RENDERING_MODE_DEFAULT ||
  1392             renderMode > DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC) {
  1393             renderMode = defaultRenderingParams->GetRenderingMode();
  1396         mRenderingParams[TEXT_RENDERING_NO_CLEARTYPE] = defaultRenderingParams;
  1398         GetDWriteFactory()->CreateCustomRenderingParams(gamma, contrast, level,
  1399 	    dwriteGeometry, renderMode,
  1400             getter_AddRefs(mRenderingParams[TEXT_RENDERING_NORMAL]));
  1402         GetDWriteFactory()->CreateCustomRenderingParams(gamma, contrast, level,
  1403 	    dwriteGeometry, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC,
  1404             getter_AddRefs(mRenderingParams[TEXT_RENDERING_GDI_CLASSIC]));
  1406 #endif
  1409 void
  1410 gfxWindowsPlatform::OnDeviceManagerDestroy(DeviceManagerD3D9* aDeviceManager)
  1412   if (aDeviceManager == mDeviceManager) {
  1413     mDeviceManager = nullptr;
  1417 IDirect3DDevice9*
  1418 gfxWindowsPlatform::GetD3D9Device()
  1420   DeviceManagerD3D9* manager = GetD3D9DeviceManager();
  1421   return manager ? manager->device() : nullptr;
  1424 DeviceManagerD3D9*
  1425 gfxWindowsPlatform::GetD3D9DeviceManager()
  1427   // We should only create the d3d9 device on the compositor thread
  1428   // or we don't have a compositor thread.
  1429   if (!mDeviceManager &&
  1430       (CompositorParent::IsInCompositorThread() ||
  1431        !CompositorParent::CompositorLoop())) {
  1432     mDeviceManager = new DeviceManagerD3D9();
  1433     if (!mDeviceManager->Init()) {
  1434       NS_WARNING("Could not initialise device manager");
  1435       mDeviceManager = nullptr;
  1439   return mDeviceManager;
  1442 ID3D11Device*
  1443 gfxWindowsPlatform::GetD3D11Device()
  1445   if (mD3D11DeviceInitialized) {
  1446     return mD3D11Device;
  1449   mD3D11DeviceInitialized = true;
  1451   nsModuleHandle d3d11Module(LoadLibrarySystem32(L"d3d11.dll"));
  1452   decltype(D3D11CreateDevice)* d3d11CreateDevice = (decltype(D3D11CreateDevice)*)
  1453     GetProcAddress(d3d11Module, "D3D11CreateDevice");
  1455   if (!d3d11CreateDevice) {
  1456     return nullptr;
  1459   nsTArray<D3D_FEATURE_LEVEL> featureLevels;
  1460   if (IsWin8OrLater()) {
  1461     featureLevels.AppendElement(D3D_FEATURE_LEVEL_11_1);
  1463   featureLevels.AppendElement(D3D_FEATURE_LEVEL_11_0);
  1464   featureLevels.AppendElement(D3D_FEATURE_LEVEL_10_1);
  1465   featureLevels.AppendElement(D3D_FEATURE_LEVEL_10_0);
  1466   featureLevels.AppendElement(D3D_FEATURE_LEVEL_9_3);
  1468   RefPtr<IDXGIAdapter1> adapter = GetDXGIAdapter();
  1470   if (!adapter) {
  1471     return nullptr;
  1474   HRESULT hr = d3d11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
  1475                                  D3D11_CREATE_DEVICE_BGRA_SUPPORT,
  1476                                  featureLevels.Elements(), featureLevels.Length(),
  1477                                  D3D11_SDK_VERSION, byRef(mD3D11Device), nullptr, nullptr);
  1479   // We leak these everywhere and we need them our entire runtime anyway, let's
  1480   // leak it here as well.
  1481   d3d11Module.disown();
  1483   return mD3D11Device;
  1486 bool
  1487 gfxWindowsPlatform::IsOptimus()
  1489   return GetModuleHandleA("nvumdshim.dll");
  1492 int
  1493 gfxWindowsPlatform::GetScreenDepth() const
  1495     // if the system doesn't have all displays with the same
  1496     // pixel format, just return 24 and move on with life.
  1497     if (!GetSystemMetrics(SM_SAMEDISPLAYFORMAT))
  1498         return 24;
  1500     HDC hdc = GetDC(nullptr);
  1501     if (!hdc)
  1502         return 24;
  1504     int depth = GetDeviceCaps(hdc, BITSPIXEL) *
  1505                 GetDeviceCaps(hdc, PLANES);
  1507     ReleaseDC(nullptr, hdc);
  1509     return depth;
  1512 IDXGIAdapter1*
  1513 gfxWindowsPlatform::GetDXGIAdapter()
  1515   if (mAdapter) {
  1516     return mAdapter;
  1519   nsModuleHandle dxgiModule(LoadLibrarySystem32(L"dxgi.dll"));
  1520   decltype(CreateDXGIFactory1)* createDXGIFactory1 = (decltype(CreateDXGIFactory1)*)
  1521     GetProcAddress(dxgiModule, "CreateDXGIFactory1");
  1523   // Try to use a DXGI 1.1 adapter in order to share resources
  1524   // across processes.
  1525   if (createDXGIFactory1) {
  1526     nsRefPtr<IDXGIFactory1> factory1;
  1527     HRESULT hr = createDXGIFactory1(__uuidof(IDXGIFactory1),
  1528                                     getter_AddRefs(factory1));
  1530     if (FAILED(hr) || !factory1) {
  1531       // This seems to happen with some people running the iZ3D driver.
  1532       // They won't get acceleration.
  1533       return nullptr;
  1536     hr = factory1->EnumAdapters1(0, byRef(mAdapter));
  1537     if (FAILED(hr)) {
  1538       // We should return and not accelerate if we can't obtain
  1539       // an adapter.
  1540       return nullptr;
  1544   // We leak this module everywhere, we might as well do so here as well.
  1545   dxgiModule.disown();
  1547   return mAdapter;

mercurial