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.

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

mercurial