|
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/. */ |
|
6 |
|
7 #include "mozilla/ArrayUtils.h" |
|
8 |
|
9 #include "gfxWindowsPlatform.h" |
|
10 |
|
11 #include "gfxImageSurface.h" |
|
12 #include "gfxWindowsSurface.h" |
|
13 |
|
14 #include "nsUnicharUtils.h" |
|
15 |
|
16 #include "mozilla/Preferences.h" |
|
17 #include "mozilla/WindowsVersion.h" |
|
18 #include "nsServiceManagerUtils.h" |
|
19 #include "nsTArray.h" |
|
20 |
|
21 #include "nsIWindowsRegKey.h" |
|
22 #include "nsIFile.h" |
|
23 #include "plbase64.h" |
|
24 #include "nsIXULRuntime.h" |
|
25 |
|
26 #include "nsIGfxInfo.h" |
|
27 |
|
28 #include "gfxCrashReporterUtils.h" |
|
29 |
|
30 #include "gfxGDIFontList.h" |
|
31 #include "gfxGDIFont.h" |
|
32 |
|
33 #include "mozilla/layers/CompositorParent.h" // for CompositorParent::IsInCompositorThread |
|
34 #include "DeviceManagerD3D9.h" |
|
35 |
|
36 #include "WinUtils.h" |
|
37 |
|
38 #ifdef CAIRO_HAS_DWRITE_FONT |
|
39 #include "gfxDWriteFontList.h" |
|
40 #include "gfxDWriteFonts.h" |
|
41 #include "gfxDWriteCommon.h" |
|
42 #include <dwrite.h> |
|
43 #endif |
|
44 |
|
45 #include "gfxUserFontSet.h" |
|
46 #include "nsWindowsHelpers.h" |
|
47 #include "gfx2DGlue.h" |
|
48 |
|
49 #include <string> |
|
50 |
|
51 #ifdef CAIRO_HAS_D2D_SURFACE |
|
52 #include "gfxD2DSurface.h" |
|
53 |
|
54 #include <d3d10_1.h> |
|
55 |
|
56 #include "mozilla/gfx/2D.h" |
|
57 |
|
58 #include "nsMemory.h" |
|
59 #endif |
|
60 |
|
61 #include <d3d11.h> |
|
62 |
|
63 #include "nsIMemoryReporter.h" |
|
64 #include <winternl.h> |
|
65 #include "d3dkmtQueryStatistics.h" |
|
66 |
|
67 #include "SurfaceCache.h" |
|
68 #include "gfxPrefs.h" |
|
69 |
|
70 using namespace mozilla; |
|
71 using namespace mozilla::gfx; |
|
72 using namespace mozilla::layers; |
|
73 using namespace mozilla::widget; |
|
74 using namespace mozilla::image; |
|
75 |
|
76 #ifdef CAIRO_HAS_D2D_SURFACE |
|
77 |
|
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 }; |
|
83 |
|
84 class GfxD2DSurfaceReporter MOZ_FINAL : public nsIMemoryReporter |
|
85 { |
|
86 public: |
|
87 NS_DECL_ISUPPORTS |
|
88 |
|
89 NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport, |
|
90 nsISupports* aData) |
|
91 { |
|
92 nsresult rv; |
|
93 |
|
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); |
|
99 |
|
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); |
|
107 |
|
108 return NS_OK; |
|
109 } |
|
110 }; |
|
111 |
|
112 NS_IMPL_ISUPPORTS(GfxD2DSurfaceReporter, nsIMemoryReporter) |
|
113 |
|
114 #endif |
|
115 |
|
116 class GfxD2DVramReporter MOZ_FINAL : public nsIMemoryReporter |
|
117 { |
|
118 public: |
|
119 NS_DECL_ISUPPORTS |
|
120 |
|
121 NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport, |
|
122 nsISupports* aData) |
|
123 { |
|
124 nsresult rv; |
|
125 |
|
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); |
|
131 |
|
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); |
|
137 |
|
138 return NS_OK; |
|
139 } |
|
140 }; |
|
141 |
|
142 NS_IMPL_ISUPPORTS(GfxD2DVramReporter, nsIMemoryReporter) |
|
143 |
|
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" |
|
146 |
|
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" |
|
153 |
|
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; |
|
162 |
|
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 } |
|
169 |
|
170 return result; |
|
171 } |
|
172 |
|
173 public: |
|
174 NS_DECL_ISUPPORTS |
|
175 |
|
176 NS_IMETHOD |
|
177 CollectReports(nsIMemoryReporterCallback* aCb, |
|
178 nsISupports* aClosure) |
|
179 { |
|
180 HANDLE ProcessHandle = GetCurrentProcess(); |
|
181 |
|
182 int64_t dedicatedBytesUsed = 0; |
|
183 int64_t sharedBytesUsed = 0; |
|
184 int64_t committedBytesUsed = 0; |
|
185 IDXGIAdapter *DXGIAdapter; |
|
186 |
|
187 HMODULE gdi32Handle; |
|
188 PFND3DKMTQS queryD3DKMTStatistics; |
|
189 |
|
190 // GPU memory reporting is not available before Windows 7 |
|
191 if (!IsWin7OrLater()) |
|
192 return NS_OK; |
|
193 |
|
194 if (gdi32Handle = LoadLibrary(TEXT("gdi32.dll"))) |
|
195 queryD3DKMTStatistics = (PFND3DKMTQS)GetProcAddress(gdi32Handle, "D3DKMTQueryStatistics"); |
|
196 |
|
197 if (queryD3DKMTStatistics && GetDXGIAdapter(&DXGIAdapter)) { |
|
198 // Most of this block is understood thanks to wj32's work on Process Hacker |
|
199 |
|
200 DXGI_ADAPTER_DESC adapterDesc; |
|
201 D3DKMTQS queryStatistics; |
|
202 |
|
203 DXGIAdapter->GetDesc(&adapterDesc); |
|
204 DXGIAdapter->Release(); |
|
205 |
|
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 } |
|
213 |
|
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; |
|
220 |
|
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; |
|
226 |
|
227 if (NT_SUCCESS(queryD3DKMTStatistics(&queryStatistics))) { |
|
228 bool aperture; |
|
229 |
|
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; |
|
235 |
|
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 } |
|
256 |
|
257 FreeLibrary(gdi32Handle); |
|
258 |
|
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) |
|
267 |
|
268 REPORT("gpu-committed", committedBytesUsed, |
|
269 "Memory committed by the Windows graphics system."); |
|
270 |
|
271 REPORT("gpu-dedicated", dedicatedBytesUsed, |
|
272 "Out-of-process memory allocated for this process in a " |
|
273 "physical GPU adapter's memory."); |
|
274 |
|
275 REPORT("gpu-shared", sharedBytesUsed, |
|
276 "In-process memory that is shared with the GPU."); |
|
277 |
|
278 #undef REPORT |
|
279 |
|
280 return NS_OK; |
|
281 } |
|
282 }; |
|
283 |
|
284 NS_IMPL_ISUPPORTS(GPUAdapterReporter, nsIMemoryReporter) |
|
285 |
|
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 } |
|
293 |
|
294 gfxWindowsPlatform::gfxWindowsPlatform() |
|
295 : mD3D11DeviceInitialized(false) |
|
296 , mPrefFonts(50) |
|
297 { |
|
298 mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE; |
|
299 mUseClearTypeAlways = UNINITIALIZED_VALUE; |
|
300 |
|
301 mUsingGDIFonts = false; |
|
302 |
|
303 /* |
|
304 * Initialize COM |
|
305 */ |
|
306 CoInitialize(nullptr); |
|
307 |
|
308 #ifdef CAIRO_HAS_D2D_SURFACE |
|
309 RegisterStrongMemoryReporter(new GfxD2DSurfaceReporter()); |
|
310 mD2DDevice = nullptr; |
|
311 #endif |
|
312 RegisterStrongMemoryReporter(new GfxD2DVramReporter()); |
|
313 |
|
314 UpdateRenderMode(); |
|
315 |
|
316 RegisterStrongMemoryReporter(new GPUAdapterReporter()); |
|
317 } |
|
318 |
|
319 gfxWindowsPlatform::~gfxWindowsPlatform() |
|
320 { |
|
321 mDeviceManager = nullptr; |
|
322 |
|
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 |
|
330 |
|
331 mozilla::gfx::Factory::D2DCleanup(); |
|
332 |
|
333 /* |
|
334 * Uninitialize COM |
|
335 */ |
|
336 CoUninitialize(); |
|
337 } |
|
338 |
|
339 double |
|
340 gfxWindowsPlatform::GetDPIScale() |
|
341 { |
|
342 return WinUtils::LogToPhysFactor(); |
|
343 } |
|
344 |
|
345 void |
|
346 gfxWindowsPlatform::UpdateRenderMode() |
|
347 { |
|
348 /* Pick the default render mode for |
|
349 * desktop. |
|
350 */ |
|
351 mRenderMode = RENDER_GDI; |
|
352 |
|
353 bool isVistaOrHigher = IsVistaOrLater(); |
|
354 |
|
355 bool safeMode = false; |
|
356 nsCOMPtr<nsIXULRuntime> xr = do_GetService("@mozilla.org/xre/runtime;1"); |
|
357 if (xr) |
|
358 xr->GetInSafeMode(&safeMode); |
|
359 |
|
360 mUseDirectWrite = Preferences::GetBool("gfx.font_rendering.directwrite.enabled", false); |
|
361 |
|
362 #ifdef CAIRO_HAS_D2D_SURFACE |
|
363 bool d2dDisabled = false; |
|
364 bool d2dForceEnabled = false; |
|
365 bool d2dBlocked = false; |
|
366 |
|
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 } |
|
376 |
|
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(); |
|
381 |
|
382 bool tryD2D = d2dForceEnabled || (!d2dBlocked && !gfxPrefs::LayersPreferD3D9()); |
|
383 |
|
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 } |
|
389 |
|
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 |
|
400 |
|
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"); |
|
408 |
|
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)); |
|
420 |
|
421 if (SUCCEEDED(hr) && factory) { |
|
422 mDWriteFactory = factory; |
|
423 factory->Release(); |
|
424 hr = mDWriteFactory->CreateTextAnalyzer( |
|
425 getter_AddRefs(mDWriteAnalyzer)); |
|
426 } |
|
427 |
|
428 SetupClearTypeParams(); |
|
429 |
|
430 if (hr == S_OK) |
|
431 reporter.SetSuccessful(); |
|
432 } |
|
433 } |
|
434 #endif |
|
435 |
|
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 } |
|
450 |
|
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; |
|
463 |
|
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)); |
|
471 |
|
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); |
|
478 |
|
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 } |
|
484 |
|
485 return device ? S_OK : hr; |
|
486 } |
|
487 #endif |
|
488 |
|
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); |
|
495 |
|
496 if (SUCCEEDED(device->GetDeviceRemovedReason())) { |
|
497 return; |
|
498 } |
|
499 mD2DDevice = nullptr; |
|
500 |
|
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 } |
|
505 |
|
506 mozilla::ScopedGfxFeatureReporter reporter("D2D", aAttemptForce); |
|
507 |
|
508 nsRefPtr<ID3D10Device1> device; |
|
509 |
|
510 int supportedFeatureLevelsCount = ArrayLength(kSupportedFeatureLevels); |
|
511 // If we're not running in Metro don't allow DX9.3 |
|
512 if (!IsRunningInWindowsMetro()) { |
|
513 supportedFeatureLevelsCount--; |
|
514 } |
|
515 |
|
516 nsRefPtr<IDXGIAdapter1> adapter1 = GetDXGIAdapter(); |
|
517 |
|
518 if (!adapter1) { |
|
519 // Unable to create adapter, abort acceleration. |
|
520 return; |
|
521 } |
|
522 |
|
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; |
|
529 |
|
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 } |
|
539 |
|
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 } |
|
551 |
|
552 if (!mD2DDevice && aAttemptForce) { |
|
553 mD2DDevice = cairo_d2d_create_device(); |
|
554 } |
|
555 |
|
556 if (mD2DDevice) { |
|
557 reporter.SetSuccessful(); |
|
558 mozilla::gfx::Factory::SetDirect3D10Device(cairo_d2d_device_get_device(mD2DDevice)); |
|
559 } |
|
560 #endif |
|
561 } |
|
562 |
|
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; |
|
585 |
|
586 if (NS_SUCCEEDED(pfl->InitFontList())) { |
|
587 return pfl; |
|
588 } |
|
589 |
|
590 gfxPlatformFontList::Shutdown(); |
|
591 return nullptr; |
|
592 } |
|
593 |
|
594 already_AddRefed<gfxASurface> |
|
595 gfxWindowsPlatform::CreateOffscreenSurface(const IntSize& size, |
|
596 gfxContentType contentType) |
|
597 { |
|
598 nsRefPtr<gfxASurface> surf = nullptr; |
|
599 |
|
600 #ifdef CAIRO_HAS_WIN32_SURFACE |
|
601 if (mRenderMode == RENDER_GDI) |
|
602 surf = new gfxWindowsSurface(ThebesIntSize(size), |
|
603 OptimalFormatForContent(contentType)); |
|
604 #endif |
|
605 |
|
606 #ifdef CAIRO_HAS_D2D_SURFACE |
|
607 if (mRenderMode == RENDER_DIRECT2D) |
|
608 surf = new gfxD2DSurface(ThebesIntSize(size), |
|
609 OptimalFormatForContent(contentType)); |
|
610 #endif |
|
611 |
|
612 if (!surf || surf->CairoStatus()) { |
|
613 surf = new gfxImageSurface(ThebesIntSize(size), |
|
614 OptimalFormatForContent(contentType)); |
|
615 } |
|
616 |
|
617 return surf.forget(); |
|
618 } |
|
619 |
|
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 |
|
631 |
|
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 } |
|
640 |
|
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); |
|
646 |
|
647 NativeFont nativeFont; |
|
648 nativeFont.mType = NativeFontType::DWRITE_FONT_FACE; |
|
649 nativeFont.mFont = font->GetFontFace(); |
|
650 |
|
651 if (aTarget->GetType() == BackendType::CAIRO) { |
|
652 return Factory::CreateScaledFontWithCairo(nativeFont, |
|
653 font->GetAdjustedSize(), |
|
654 font->GetCairoScaledFont()); |
|
655 } |
|
656 |
|
657 return Factory::CreateScaledFontForNativeFont(nativeFont, |
|
658 font->GetAdjustedSize()); |
|
659 } |
|
660 |
|
661 NS_ASSERTION(aFont->GetType() == gfxFont::FONT_TYPE_GDI, |
|
662 "Fonts on windows should be GDI or DWrite!"); |
|
663 |
|
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; |
|
669 |
|
670 if (aTarget->GetType() == BackendType::CAIRO) { |
|
671 return Factory::CreateScaledFontWithCairo(nativeFont, |
|
672 aFont->GetAdjustedSize(), |
|
673 aFont->GetCairoScaledFont()); |
|
674 } |
|
675 |
|
676 return Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize()); |
|
677 } |
|
678 |
|
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 } |
|
688 |
|
689 RefPtr<ID3D10Texture2D> texture = |
|
690 static_cast<ID3D10Texture2D*>(aTarget->GetNativeSurface(NativeSurfaceType::D3D10_TEXTURE)); |
|
691 |
|
692 if (!texture) { |
|
693 return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget); |
|
694 } |
|
695 |
|
696 aTarget->Flush(); |
|
697 |
|
698 nsRefPtr<gfxASurface> surf = |
|
699 new gfxD2DSurface(texture, ContentForFormat(aTarget->GetFormat())); |
|
700 |
|
701 // shouldn't this hold a reference? |
|
702 surf->SetData(&kDrawTarget, aTarget, nullptr); |
|
703 return surf.forget(); |
|
704 } |
|
705 #endif |
|
706 |
|
707 return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget); |
|
708 } |
|
709 |
|
710 nsresult |
|
711 gfxWindowsPlatform::GetFontList(nsIAtom *aLangGroup, |
|
712 const nsACString& aGenericFamily, |
|
713 nsTArray<nsString>& aListOfFonts) |
|
714 { |
|
715 gfxPlatformFontList::PlatformFontList()->GetFontList(aLangGroup, aGenericFamily, aListOfFonts); |
|
716 |
|
717 return NS_OK; |
|
718 } |
|
719 |
|
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 } |
|
727 |
|
728 nsresult |
|
729 gfxWindowsPlatform::UpdateFontList() |
|
730 { |
|
731 gfxPlatformFontList::PlatformFontList()->UpdateFontList(); |
|
732 |
|
733 return NS_OK; |
|
734 } |
|
735 |
|
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"; |
|
772 |
|
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); |
|
780 |
|
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; |
|
791 |
|
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 } |
|
949 |
|
950 // Arial Unicode MS has lots of glyphs for obscure characters, |
|
951 // use it as a last resort |
|
952 aFontList.AppendElement(kFontArialUnicodeMS); |
|
953 } |
|
954 |
|
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 }; |
|
967 |
|
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 } |
|
983 |
|
984 nsresult |
|
985 gfxWindowsPlatform::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName) |
|
986 { |
|
987 gfxPlatformFontList::PlatformFontList()->GetStandardFamilyName(aFontName, aFamilyName); |
|
988 return NS_OK; |
|
989 } |
|
990 |
|
991 gfxFontGroup * |
|
992 gfxWindowsPlatform::CreateFontGroup(const nsAString &aFamilies, |
|
993 const gfxFontStyle *aStyle, |
|
994 gfxUserFontSet *aUserFontSet) |
|
995 { |
|
996 return new gfxFontGroup(aFamilies, aStyle, aUserFontSet); |
|
997 } |
|
998 |
|
999 gfxFontEntry* |
|
1000 gfxWindowsPlatform::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry, |
|
1001 const nsAString& aFontName) |
|
1002 { |
|
1003 return gfxPlatformFontList::PlatformFontList()->LookupLocalFont(aProxyEntry, |
|
1004 aFontName); |
|
1005 } |
|
1006 |
|
1007 gfxFontEntry* |
|
1008 gfxWindowsPlatform::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry, |
|
1009 const uint8_t *aFontData, uint32_t aLength) |
|
1010 { |
|
1011 return gfxPlatformFontList::PlatformFontList()->MakePlatformFont(aProxyEntry, |
|
1012 aFontData, |
|
1013 aLength); |
|
1014 } |
|
1015 |
|
1016 bool |
|
1017 gfxWindowsPlatform::IsFontFormatSupported(nsIURI *aFontURI, uint32_t aFormatFlags) |
|
1018 { |
|
1019 // check for strange format flags |
|
1020 NS_ASSERTION(!(aFormatFlags & gfxUserFontSet::FLAG_FORMAT_NOT_USED), |
|
1021 "strange font format hint set"); |
|
1022 |
|
1023 // accept supported formats |
|
1024 if (aFormatFlags & (gfxUserFontSet::FLAG_FORMAT_WOFF | |
|
1025 gfxUserFontSet::FLAG_FORMAT_OPENTYPE | |
|
1026 gfxUserFontSet::FLAG_FORMAT_TRUETYPE)) { |
|
1027 return true; |
|
1028 } |
|
1029 |
|
1030 // reject all other formats, known and unknown |
|
1031 if (aFormatFlags != 0) { |
|
1032 return false; |
|
1033 } |
|
1034 |
|
1035 // no format hint set, need to look at data |
|
1036 return true; |
|
1037 } |
|
1038 |
|
1039 gfxFontFamily * |
|
1040 gfxWindowsPlatform::FindFontFamily(const nsAString& aName) |
|
1041 { |
|
1042 return gfxPlatformFontList::PlatformFontList()->FindFamily(aName); |
|
1043 } |
|
1044 |
|
1045 gfxFontEntry * |
|
1046 gfxWindowsPlatform::FindFontEntry(const nsAString& aName, const gfxFontStyle& aFontStyle) |
|
1047 { |
|
1048 nsRefPtr<gfxFontFamily> ff = FindFontFamily(aName); |
|
1049 if (!ff) |
|
1050 return nullptr; |
|
1051 |
|
1052 bool aNeedsBold; |
|
1053 return ff->FindFontForStyle(aFontStyle, aNeedsBold); |
|
1054 } |
|
1055 |
|
1056 void |
|
1057 gfxWindowsPlatform::GetPlatformCMSOutputProfile(void* &mem, size_t &mem_size) |
|
1058 { |
|
1059 WCHAR str[MAX_PATH]; |
|
1060 DWORD size = MAX_PATH; |
|
1061 BOOL res; |
|
1062 |
|
1063 mem = nullptr; |
|
1064 mem_size = 0; |
|
1065 |
|
1066 HDC dc = GetDC(nullptr); |
|
1067 if (!dc) |
|
1068 return; |
|
1069 |
|
1070 #if _MSC_VER |
|
1071 __try { |
|
1072 res = GetICMProfileW(dc, &size, (LPWSTR)&str); |
|
1073 } __except(GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION) { |
|
1074 res = FALSE; |
|
1075 } |
|
1076 #else |
|
1077 res = GetICMProfileW(dc, &size, (LPWSTR)&str); |
|
1078 #endif |
|
1079 |
|
1080 ReleaseDC(nullptr, dc); |
|
1081 if (!res) |
|
1082 return; |
|
1083 |
|
1084 #ifdef _WIN32 |
|
1085 qcms_data_from_unicode_path(str, &mem, &mem_size); |
|
1086 |
|
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 |
|
1094 } |
|
1095 |
|
1096 bool |
|
1097 gfxWindowsPlatform::GetPrefFontEntries(const nsCString& aKey, nsTArray<nsRefPtr<gfxFontEntry> > *array) |
|
1098 { |
|
1099 return mPrefFonts.Get(aKey, array); |
|
1100 } |
|
1101 |
|
1102 void |
|
1103 gfxWindowsPlatform::SetPrefFontEntries(const nsCString& aKey, nsTArray<nsRefPtr<gfxFontEntry> >& array) |
|
1104 { |
|
1105 mPrefFonts.Put(aKey, array); |
|
1106 } |
|
1107 |
|
1108 bool |
|
1109 gfxWindowsPlatform::UseClearTypeForDownloadableFonts() |
|
1110 { |
|
1111 if (mUseClearTypeForDownloadableFonts == UNINITIALIZED_VALUE) { |
|
1112 mUseClearTypeForDownloadableFonts = Preferences::GetBool(GFX_DOWNLOADABLE_FONTS_USE_CLEARTYPE, true); |
|
1113 } |
|
1114 |
|
1115 return mUseClearTypeForDownloadableFonts; |
|
1116 } |
|
1117 |
|
1118 bool |
|
1119 gfxWindowsPlatform::UseClearTypeAlways() |
|
1120 { |
|
1121 if (mUseClearTypeAlways == UNINITIALIZED_VALUE) { |
|
1122 mUseClearTypeAlways = Preferences::GetBool(GFX_USE_CLEARTYPE_ALWAYS, false); |
|
1123 } |
|
1124 |
|
1125 return mUseClearTypeAlways; |
|
1126 } |
|
1127 |
|
1128 void |
|
1129 gfxWindowsPlatform::GetDLLVersion(char16ptr_t aDLLPath, nsAString& aVersion) |
|
1130 { |
|
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; |
|
1136 |
|
1137 if (versInfoSize == 0 || |
|
1138 !versionInfo.AppendElements(uint32_t(versInfoSize))) |
|
1139 { |
|
1140 return; |
|
1141 } |
|
1142 |
|
1143 if (!GetFileVersionInfoW(aDLLPath, 0, versInfoSize, |
|
1144 LPBYTE(versionInfo.Elements()))) |
|
1145 { |
|
1146 return; |
|
1147 } |
|
1148 |
|
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) |
|
1155 { |
|
1156 return; |
|
1157 } |
|
1158 |
|
1159 DWORD fileVersMS = fileInfo->dwFileVersionMS; |
|
1160 DWORD fileVersLS = fileInfo->dwFileVersionLS; |
|
1161 |
|
1162 vers[0] = HIWORD(fileVersMS); |
|
1163 vers[1] = LOWORD(fileVersMS); |
|
1164 vers[2] = HIWORD(fileVersLS); |
|
1165 vers[3] = LOWORD(fileVersLS); |
|
1166 |
|
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)); |
|
1170 } |
|
1171 |
|
1172 void |
|
1173 gfxWindowsPlatform::GetCleartypeParams(nsTArray<ClearTypeParameterInfo>& aParams) |
|
1174 { |
|
1175 HKEY hKey, subKey; |
|
1176 DWORD i, rv, size, type; |
|
1177 WCHAR displayName[256], subkeyName[256]; |
|
1178 |
|
1179 aParams.Clear(); |
|
1180 |
|
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); |
|
1185 |
|
1186 if (rv != ERROR_SUCCESS) { |
|
1187 return; |
|
1188 } |
|
1189 |
|
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; |
|
1197 } |
|
1198 |
|
1199 ClearTypeParameterInfo ctinfo; |
|
1200 ctinfo.displayName.Assign(displayName); |
|
1201 |
|
1202 DWORD subrv, value; |
|
1203 bool foundData = false; |
|
1204 |
|
1205 swprintf_s(subkeyName, ArrayLength(subkeyName), |
|
1206 L"Software\\Microsoft\\Avalon.Graphics\\%s", displayName); |
|
1207 |
|
1208 // subkey for gamma, pixel structure |
|
1209 subrv = RegOpenKeyExW(HKEY_LOCAL_MACHINE, |
|
1210 subkeyName, 0, KEY_QUERY_VALUE, &subKey); |
|
1211 |
|
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; |
|
1219 } |
|
1220 |
|
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; |
|
1227 } |
|
1228 |
|
1229 RegCloseKey(subKey); |
|
1230 } |
|
1231 |
|
1232 // subkey for cleartype level, enhanced contrast |
|
1233 subrv = RegOpenKeyExW(HKEY_CURRENT_USER, |
|
1234 subkeyName, 0, KEY_QUERY_VALUE, &subKey); |
|
1235 |
|
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; |
|
1243 } |
|
1244 |
|
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; |
|
1251 } |
|
1252 |
|
1253 RegCloseKey(subKey); |
|
1254 } |
|
1255 |
|
1256 if (foundData) { |
|
1257 aParams.AppendElement(ctinfo); |
|
1258 } |
|
1259 } |
|
1260 |
|
1261 RegCloseKey(hKey); |
|
1262 } |
|
1263 |
|
1264 void |
|
1265 gfxWindowsPlatform::FontsPrefsChanged(const char *aPref) |
|
1266 { |
|
1267 bool clearTextFontCaches = true; |
|
1268 |
|
1269 gfxPlatform::FontsPrefsChanged(aPref); |
|
1270 |
|
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; |
|
1282 } |
|
1283 |
|
1284 if (clearTextFontCaches) { |
|
1285 gfxFontCache *fc = gfxFontCache::GetCache(); |
|
1286 if (fc) { |
|
1287 fc->Flush(); |
|
1288 } |
|
1289 } |
|
1290 } |
|
1291 |
|
1292 #define ENHANCED_CONTRAST_REGISTRY_KEY \ |
|
1293 HKEY_CURRENT_USER, "Software\\Microsoft\\Avalon.Graphics\\DISPLAY1\\EnhancedContrastLevel" |
|
1294 |
|
1295 void |
|
1296 gfxWindowsPlatform::SetupClearTypeParams() |
|
1297 { |
|
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); |
|
1311 } |
|
1312 } |
|
1313 |
|
1314 if (NS_SUCCEEDED(Preferences::GetInt(GFX_CLEARTYPE_PARAMS_CONTRAST, &value))) { |
|
1315 if (value >= 0 && value <= 1000) { |
|
1316 contrast = FLOAT(value / 100.0); |
|
1317 } |
|
1318 } |
|
1319 |
|
1320 if (NS_SUCCEEDED(Preferences::GetInt(GFX_CLEARTYPE_PARAMS_LEVEL, &value))) { |
|
1321 if (value >= 0 && value <= 100) { |
|
1322 level = FLOAT(value / 100.0); |
|
1323 } |
|
1324 } |
|
1325 |
|
1326 if (NS_SUCCEEDED(Preferences::GetInt(GFX_CLEARTYPE_PARAMS_STRUCTURE, &value))) { |
|
1327 if (value >= 0 && value <= 2) { |
|
1328 geometry = value; |
|
1329 } |
|
1330 } |
|
1331 |
|
1332 if (NS_SUCCEEDED(Preferences::GetInt(GFX_CLEARTYPE_PARAMS_MODE, &value))) { |
|
1333 if (value >= 0 && value <= 5) { |
|
1334 mode = value; |
|
1335 } |
|
1336 } |
|
1337 |
|
1338 cairo_dwrite_set_cleartype_params(gamma, contrast, level, geometry, mode); |
|
1339 |
|
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; |
|
1351 } |
|
1352 |
|
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) |
|
1363 { |
|
1364 contrast = defaultRenderingParams->GetEnhancedContrast(); |
|
1365 RegCloseKey(hKey); |
|
1366 } else { |
|
1367 contrast = 1.0; |
|
1368 } |
|
1369 } |
|
1370 |
|
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(); |
|
1375 } |
|
1376 |
|
1377 if (level < 0.0 || level > 1.0) { |
|
1378 level = defaultRenderingParams->GetClearTypeLevel(); |
|
1379 } |
|
1380 |
|
1381 DWRITE_PIXEL_GEOMETRY dwriteGeometry = |
|
1382 static_cast<DWRITE_PIXEL_GEOMETRY>(geometry); |
|
1383 DWRITE_RENDERING_MODE renderMode = |
|
1384 static_cast<DWRITE_RENDERING_MODE>(mode); |
|
1385 |
|
1386 if (dwriteGeometry < DWRITE_PIXEL_GEOMETRY_FLAT || |
|
1387 dwriteGeometry > DWRITE_PIXEL_GEOMETRY_BGR) { |
|
1388 dwriteGeometry = defaultRenderingParams->GetPixelGeometry(); |
|
1389 } |
|
1390 |
|
1391 if (renderMode < DWRITE_RENDERING_MODE_DEFAULT || |
|
1392 renderMode > DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC) { |
|
1393 renderMode = defaultRenderingParams->GetRenderingMode(); |
|
1394 } |
|
1395 |
|
1396 mRenderingParams[TEXT_RENDERING_NO_CLEARTYPE] = defaultRenderingParams; |
|
1397 |
|
1398 GetDWriteFactory()->CreateCustomRenderingParams(gamma, contrast, level, |
|
1399 dwriteGeometry, renderMode, |
|
1400 getter_AddRefs(mRenderingParams[TEXT_RENDERING_NORMAL])); |
|
1401 |
|
1402 GetDWriteFactory()->CreateCustomRenderingParams(gamma, contrast, level, |
|
1403 dwriteGeometry, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC, |
|
1404 getter_AddRefs(mRenderingParams[TEXT_RENDERING_GDI_CLASSIC])); |
|
1405 } |
|
1406 #endif |
|
1407 } |
|
1408 |
|
1409 void |
|
1410 gfxWindowsPlatform::OnDeviceManagerDestroy(DeviceManagerD3D9* aDeviceManager) |
|
1411 { |
|
1412 if (aDeviceManager == mDeviceManager) { |
|
1413 mDeviceManager = nullptr; |
|
1414 } |
|
1415 } |
|
1416 |
|
1417 IDirect3DDevice9* |
|
1418 gfxWindowsPlatform::GetD3D9Device() |
|
1419 { |
|
1420 DeviceManagerD3D9* manager = GetD3D9DeviceManager(); |
|
1421 return manager ? manager->device() : nullptr; |
|
1422 } |
|
1423 |
|
1424 DeviceManagerD3D9* |
|
1425 gfxWindowsPlatform::GetD3D9DeviceManager() |
|
1426 { |
|
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; |
|
1436 } |
|
1437 } |
|
1438 |
|
1439 return mDeviceManager; |
|
1440 } |
|
1441 |
|
1442 ID3D11Device* |
|
1443 gfxWindowsPlatform::GetD3D11Device() |
|
1444 { |
|
1445 if (mD3D11DeviceInitialized) { |
|
1446 return mD3D11Device; |
|
1447 } |
|
1448 |
|
1449 mD3D11DeviceInitialized = true; |
|
1450 |
|
1451 nsModuleHandle d3d11Module(LoadLibrarySystem32(L"d3d11.dll")); |
|
1452 decltype(D3D11CreateDevice)* d3d11CreateDevice = (decltype(D3D11CreateDevice)*) |
|
1453 GetProcAddress(d3d11Module, "D3D11CreateDevice"); |
|
1454 |
|
1455 if (!d3d11CreateDevice) { |
|
1456 return nullptr; |
|
1457 } |
|
1458 |
|
1459 nsTArray<D3D_FEATURE_LEVEL> featureLevels; |
|
1460 if (IsWin8OrLater()) { |
|
1461 featureLevels.AppendElement(D3D_FEATURE_LEVEL_11_1); |
|
1462 } |
|
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); |
|
1467 |
|
1468 RefPtr<IDXGIAdapter1> adapter = GetDXGIAdapter(); |
|
1469 |
|
1470 if (!adapter) { |
|
1471 return nullptr; |
|
1472 } |
|
1473 |
|
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); |
|
1478 |
|
1479 // We leak these everywhere and we need them our entire runtime anyway, let's |
|
1480 // leak it here as well. |
|
1481 d3d11Module.disown(); |
|
1482 |
|
1483 return mD3D11Device; |
|
1484 } |
|
1485 |
|
1486 bool |
|
1487 gfxWindowsPlatform::IsOptimus() |
|
1488 { |
|
1489 return GetModuleHandleA("nvumdshim.dll"); |
|
1490 } |
|
1491 |
|
1492 int |
|
1493 gfxWindowsPlatform::GetScreenDepth() const |
|
1494 { |
|
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; |
|
1499 |
|
1500 HDC hdc = GetDC(nullptr); |
|
1501 if (!hdc) |
|
1502 return 24; |
|
1503 |
|
1504 int depth = GetDeviceCaps(hdc, BITSPIXEL) * |
|
1505 GetDeviceCaps(hdc, PLANES); |
|
1506 |
|
1507 ReleaseDC(nullptr, hdc); |
|
1508 |
|
1509 return depth; |
|
1510 } |
|
1511 |
|
1512 IDXGIAdapter1* |
|
1513 gfxWindowsPlatform::GetDXGIAdapter() |
|
1514 { |
|
1515 if (mAdapter) { |
|
1516 return mAdapter; |
|
1517 } |
|
1518 |
|
1519 nsModuleHandle dxgiModule(LoadLibrarySystem32(L"dxgi.dll")); |
|
1520 decltype(CreateDXGIFactory1)* createDXGIFactory1 = (decltype(CreateDXGIFactory1)*) |
|
1521 GetProcAddress(dxgiModule, "CreateDXGIFactory1"); |
|
1522 |
|
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)); |
|
1529 |
|
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; |
|
1534 } |
|
1535 |
|
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; |
|
1541 } |
|
1542 } |
|
1543 |
|
1544 // We leak this module everywhere, we might as well do so here as well. |
|
1545 dxgiModule.disown(); |
|
1546 |
|
1547 return mAdapter; |
|
1548 } |