1 /*
2 * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 #include "D3DBadHardware.h"
27 #include "D3DPipelineManager.h"
28 #include "D3DRenderQueue.h"
29 #include "WindowsFlags.h"
30 #include "awt_Win32GraphicsDevice.h"
31
32 // state of the adapter prior to initialization
33 #define CONTEXT_NOT_INITED 0
34 // this state is set if adapter initialization had failed
35 #define CONTEXT_INIT_FAILED (-1)
36 // this state is set if adapter was successfully created
37 #define CONTEXT_CREATED 1
38
39 static BOOL bNoHwCheck = (getenv("J2D_D3D_NO_HWCHECK") != NULL);
40
41 D3DPipelineManager *D3DPipelineManager::pMgr = NULL;
42
43
CreateInstance(void)44 D3DPipelineManager * D3DPipelineManager::CreateInstance(void)
45 {
46 if (!IsD3DEnabled() ||
47 FAILED((D3DPipelineManager::CheckOSVersion())) ||
48 FAILED((D3DPipelineManager::GDICheckForBadHardware())))
49 {
50 return NULL;
51 }
52
53 if (pMgr == NULL) {
54 pMgr = new D3DPipelineManager();
55 if (FAILED(pMgr->InitD3D())) {
56 SAFE_DELETE(pMgr);
57 }
58 } else {
59 // this should never happen so to be on the safe side do not
60 // use this unexpected pointer, do not try to release it, just null
61 // it out and fail safely
62 J2dRlsTraceLn1(J2D_TRACE_ERROR,
63 "D3DPPLM::CreateInstance: unexpected instance: 0x%x,"\
64 " abort.", pMgr);
65 pMgr = NULL;
66 }
67 return pMgr;
68 }
69
DeleteInstance()70 void D3DPipelineManager::DeleteInstance()
71 {
72 J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::DeleteInstance()");
73 SAFE_DELETE(pMgr);
74 }
75
GetInstance(void)76 D3DPipelineManager * D3DPipelineManager::GetInstance(void)
77 {
78 return pMgr;
79 }
80
D3DPipelineManager(void)81 D3DPipelineManager::D3DPipelineManager(void)
82 {
83 pd3d9 = NULL;
84 hLibD3D9 = NULL;
85 pAdapters = NULL;
86 adapterCount = 0;
87 currentFSFocusAdapter = -1;
88 defaultFocusWindow = 0;
89 devType = SelectDeviceType();
90 }
91
~D3DPipelineManager(void)92 D3DPipelineManager::~D3DPipelineManager(void)
93 {
94 J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::~D3DPipelineManager()");
95 ReleaseD3D();
96 }
97
ReleaseD3D(void)98 HRESULT D3DPipelineManager::ReleaseD3D(void)
99 {
100 J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::ReleaseD3D()");
101
102 ReleaseAdapters();
103
104 SAFE_RELEASE(pd3d9);
105
106 if (hLibD3D9 != NULL) {
107 ::FreeLibrary(hLibD3D9);
108 hLibD3D9 = NULL;
109 }
110
111 return S_OK;
112 }
113
114 // Creates a Direct3D9 object and initializes adapters.
115 // If succeeded, returns S_OK, otherwise returns the error code.
InitD3D(void)116 HRESULT D3DPipelineManager::InitD3D(void)
117 {
118 typedef IDirect3D9 * WINAPI FnDirect3DCreate9(UINT SDKVersion);
119
120 hLibD3D9 = JDK_LoadSystemLibrary("d3d9.dll");
121 if (hLibD3D9 == NULL) {
122 J2dRlsTraceLn(J2D_TRACE_ERROR, "InitD3D: no d3d9.dll");
123 return E_FAIL;
124 }
125
126 FnDirect3DCreate9 *d3dcreate9 = NULL;
127 d3dcreate9 = (FnDirect3DCreate9*)
128 ::GetProcAddress(hLibD3D9, "Direct3DCreate9");
129 if (d3dcreate9 == NULL) {
130 J2dRlsTraceLn(J2D_TRACE_ERROR, "InitD3D: no Direct3DCreate9");
131 ::FreeLibrary(hLibD3D9);
132 return E_FAIL;
133 }
134
135 pd3d9 = d3dcreate9(D3D_SDK_VERSION);
136 if (pd3d9 == NULL) {
137 J2dRlsTraceLn(J2D_TRACE_ERROR,
138 "InitD3D: unable to create IDirect3D9 object");
139 ::FreeLibrary(hLibD3D9);
140 return E_FAIL;
141 }
142
143 HRESULT res;
144 if (FAILED(res = InitAdapters())) {
145 J2dRlsTraceLn(J2D_TRACE_ERROR, "InitD3D: failed to init adapters");
146 ReleaseD3D();
147 return res;
148 }
149
150 return S_OK;
151 }
152
ReleaseAdapters()153 HRESULT D3DPipelineManager::ReleaseAdapters()
154 {
155 J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::ReleaseAdapters()");
156
157 D3DRQ_ResetCurrentContextAndDestination();
158 if (pAdapters != NULL) {
159 for (UINT i = 0; i < adapterCount; i++) {
160 if (pAdapters[i].pd3dContext != NULL) {
161 delete pAdapters[i].pd3dContext;
162 }
163 }
164 delete[] pAdapters;
165 pAdapters = NULL;
166 }
167 if (defaultFocusWindow != 0) {
168 DestroyWindow(defaultFocusWindow);
169 UnregisterClass(L"D3DFocusWindow", GetModuleHandle(NULL));
170 defaultFocusWindow = 0;
171 }
172 currentFSFocusAdapter = -1;
173 return S_OK;
174 }
175
176 // static
NotifyAdapterEventListeners(UINT adapter,jint eventType)177 void D3DPipelineManager::NotifyAdapterEventListeners(UINT adapter,
178 jint eventType)
179 {
180 HMONITOR hMon;
181 int gdiScreen;
182 D3DPipelineManager *pMgr;
183
184 // fix for 6946559: if d3d preloading fails jmv may be NULL
185 if (jvm == NULL) {
186 return;
187 }
188
189 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
190 RETURN_IF_NULL(env);
191
192 pMgr = D3DPipelineManager::GetInstance();
193 RETURN_IF_NULL(pMgr);
194 hMon = pMgr->pd3d9->GetAdapterMonitor(adapter);
195
196 /*
197 * If we don't have devices initialized yet, no sense to clear them.
198 */
199 if (!Devices::GetInstance()){
200 return;
201 }
202
203 gdiScreen = AwtWin32GraphicsDevice::GetScreenFromHMONITOR(hMon);
204
205 JNU_CallStaticMethodByName(env, NULL,
206 "sun/java2d/pipe/hw/AccelDeviceEventNotifier",
207 "eventOccured", "(II)V",
208 gdiScreen, eventType);
209 }
210
GetAdapterOrdinalForScreen(jint gdiScreen)211 UINT D3DPipelineManager::GetAdapterOrdinalForScreen(jint gdiScreen)
212 {
213 HMONITOR mHnd = AwtWin32GraphicsDevice::GetMonitor(gdiScreen);
214 if (mHnd == (HMONITOR)0) {
215 return D3DADAPTER_DEFAULT;
216 }
217 return GetAdapterOrdinalByHmon((HMONITOR)mHnd);
218 }
219
220 // static
HandleAdaptersChange(HMONITOR * pHMONITORs,UINT monNum)221 HRESULT D3DPipelineManager::HandleAdaptersChange(HMONITOR *pHMONITORs, UINT monNum)
222 {
223 HRESULT res = S_OK;
224 BOOL bResetD3D = FALSE, bFound;
225
226 D3DPipelineManager *pMgr = D3DPipelineManager::GetInstance();
227 RETURN_STATUS_IF_NULL(pHMONITORs, E_FAIL);
228 if (pMgr == NULL) {
229 // NULL pMgr is valid when the pipeline is not enabled or if it hasn't
230 // been created yet
231 return S_OK;
232 }
233 RETURN_STATUS_IF_NULL(pMgr->pAdapters, E_FAIL);
234 RETURN_STATUS_IF_NULL(pMgr->pd3d9, E_FAIL);
235
236 J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::HandleAdaptersChange");
237
238 if (monNum != pMgr->adapterCount) {
239 J2dTraceLn2(J2D_TRACE_VERBOSE,
240 " number of adapters changed (old=%d, new=%d)",
241 pMgr->adapterCount, monNum);
242 bResetD3D = TRUE;
243 } else {
244 for (UINT i = 0; i < pMgr->adapterCount; i++) {
245 HMONITOR hMon = pMgr->pd3d9->GetAdapterMonitor(i);
246 if (hMon == (HMONITOR)0x0) {
247 J2dTraceLn1(J2D_TRACE_VERBOSE, " adapter %d: removed", i);
248 bResetD3D = TRUE;
249 break;
250 }
251 bFound = FALSE;
252 for (UINT mon = 0; mon < monNum; mon++) {
253 if (pHMONITORs[mon] == hMon) {
254 J2dTraceLn3(J2D_TRACE_VERBOSE,
255 " adapter %d: found hmnd[%d]=0x%x", i, mon, hMon);
256 bFound = TRUE;
257 break;
258 }
259 }
260 if (!bFound) {
261 J2dTraceLn2(J2D_TRACE_VERBOSE,
262 " adapter %d: could not find hmnd=0x%x "\
263 "in the list of new hmnds", i, hMon);
264 bResetD3D = TRUE;
265 break;
266 }
267 }
268 }
269
270 if (bResetD3D) {
271 J2dTraceLn(J2D_TRACE_VERBOSE, " adapters changed: resetting d3d");
272 pMgr->ReleaseD3D();
273 res = pMgr->InitD3D();
274 }
275 return res;
276 }
277
HandleLostDevices()278 HRESULT D3DPipelineManager::HandleLostDevices()
279 {
280 J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::HandleLostDevices()");
281 BOOL bAllClear = TRUE;
282
283 HWND hwnd = GetCurrentFocusWindow();
284 if (hwnd != defaultFocusWindow) {
285 // we're in full-screen mode
286 WINDOWPLACEMENT wp;
287 ::ZeroMemory(&wp, sizeof(WINDOWPLACEMENT));
288 wp.length = sizeof(WINDOWPLACEMENT);
289 ::GetWindowPlacement(hwnd, &wp);
290
291 // Only attempt to restore the devices if we're in full-screen mode
292 // and the fs window is active; sleep otherwise.
293 // Restoring a window while minimized causes problems on Vista:
294 // sometimes we restore the window too quickly and it pops up back from
295 // minimized state when the device is restored.
296 //
297 // WARNING: this is a sleep on the Toolkit thread! We may reconsider
298 // this if we find any issues later.
299 if ((wp.showCmd & SW_SHOWMINNOACTIVE) && !(wp.showCmd & SW_SHOWNORMAL)){
300 static DWORD prevCallTime = 0;
301 J2dTraceLn(J2D_TRACE_VERBOSE, " fs focus window is minimized");
302 DWORD currentTime = ::GetTickCount();
303 if ((currentTime - prevCallTime) < 100) {
304 J2dTraceLn(J2D_TRACE_VERBOSE, " tight loop detected, sleep");
305 ::Sleep(100);
306 }
307 prevCallTime = currentTime;
308 return D3DERR_DEVICELOST;
309 }
310 }
311 if (pAdapters != NULL) {
312 for (UINT i = 0; i < adapterCount; i++) {
313 if (pAdapters[i].pd3dContext != NULL) {
314 J2dTraceLn1(J2D_TRACE_VERBOSE,
315 " HandleLostDevices: checking adapter %d", i);
316 D3DContext *d3dc = pAdapters[i].pd3dContext;
317 if (FAILED(d3dc->CheckAndResetDevice())) {
318 bAllClear = FALSE;
319 }
320 }
321 }
322 }
323 return bAllClear ? S_OK : D3DERR_DEVICELOST;
324 }
325
InitAdapters()326 HRESULT D3DPipelineManager::InitAdapters()
327 {
328 HRESULT res = E_FAIL;
329
330 J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::InitAdapters()");
331 if (pAdapters != NULL) {
332 ReleaseAdapters();
333 }
334
335 adapterCount = pd3d9->GetAdapterCount();
336 pAdapters = new D3DAdapter[adapterCount];
337 if (pAdapters == NULL) {
338 J2dRlsTraceLn(J2D_TRACE_ERROR, "InitAdapters: out of memory");
339 adapterCount = 0;
340 return E_FAIL;
341 }
342 ZeroMemory(pAdapters, adapterCount * sizeof(D3DAdapter));
343
344 res = CheckAdaptersInfo();
345 RETURN_STATUS_IF_FAILED(res);
346
347 currentFSFocusAdapter = -1;
348 if (CreateDefaultFocusWindow() == 0) {
349 return E_FAIL;
350 }
351
352 return S_OK;
353 }
354
355 // static
356 HRESULT
CheckOSVersion()357 D3DPipelineManager::CheckOSVersion()
358 {
359 // require Windows XP or newer client-class OS
360 if (IS_WINVER_ATLEAST(5, 1) &&
361 !D3DPPLM_OsVersionMatches(OS_WINSERV_2008R2|OS_WINSERV_2008|
362 OS_WINSERV_2003))
363 {
364 J2dTraceLn(J2D_TRACE_INFO,
365 "D3DPPLM::CheckOSVersion: Windows XP or newer client-classs"\
366 " OS detected, passed");
367 return S_OK;
368 }
369 J2dRlsTraceLn(J2D_TRACE_ERROR,
370 "D3DPPLM::CheckOSVersion: Windows 2000 or earlier (or a "\
371 "server) OS detected, failed");
372 if (bNoHwCheck) {
373 J2dRlsTraceLn(J2D_TRACE_WARNING,
374 " OS check overridden via J2D_D3D_NO_HWCHECK");
375 return S_OK;
376 }
377 return E_FAIL;
378 }
379
380 // static
381 HRESULT
GDICheckForBadHardware()382 D3DPipelineManager::GDICheckForBadHardware()
383 {
384 DISPLAY_DEVICE dd;
385 dd.cb = sizeof(DISPLAY_DEVICE);
386
387 int failedDevices = 0;
388 int attachedDevices = 0;
389 int i = 0;
390 WCHAR *id;
391 WCHAR vendorId[5];
392 WCHAR deviceId[5];
393 DWORD dwDId, dwVId;
394
395 J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::GDICheckForBadHardware");
396
397 // i<20 is to guard against buggy drivers
398 while (EnumDisplayDevices(NULL, i, &dd, 0) && i < 20) {
399 if (dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) {
400 attachedDevices++;
401 id = dd.DeviceID;
402 if (wcslen(id) > 21) {
403 // get vendor ID
404 wcsncpy(vendorId, id+8, 4);
405 int args1 = swscanf(vendorId, L"%X", &dwVId);
406
407 // get device ID
408 wcsncpy(deviceId, id+17, 4);
409 int args2 = swscanf(deviceId, L"%X", &dwDId);
410
411 if (args1 == 1 && args2 == 1) {
412 J2dTraceLn2(J2D_TRACE_VERBOSE,
413 " device: vendorID=0x%04x, deviceId=0x%04x",
414 dwVId, dwDId);
415 // since we don't have a driver version here we will
416 // just ask to ignore the version for now; bad hw
417 // entries with specific drivers information will be
418 // processed later when d3d is initialized and we can
419 // obtain a driver version
420 if (FAILED(CheckForBadHardware(dwVId, dwDId, MAX_VERSION))){
421 failedDevices++;
422 }
423 }
424 }
425 }
426
427 i++;
428 }
429
430 if (failedDevices == attachedDevices) {
431 J2dRlsTraceLn(J2D_TRACE_ERROR,
432 "D3DPPLM::GDICheckForBadHardware: no suitable devices found");
433 return E_FAIL;
434 }
435
436 return S_OK;
437 }
438
D3DPPLM_OsVersionMatches(USHORT osInfo)439 BOOL D3DPPLM_OsVersionMatches(USHORT osInfo) {
440 static USHORT currentOS = OS_UNDEFINED;
441
442 if (currentOS == OS_UNDEFINED) {
443 BOOL bVersOk;
444 OSVERSIONINFOEX osvi;
445
446 ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
447 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
448
449 bVersOk = GetVersionEx((OSVERSIONINFO *) &osvi);
450
451 J2dRlsTrace(J2D_TRACE_INFO, "[I] OS Version = ");
452 if (bVersOk && osvi.dwPlatformId == VER_PLATFORM_WIN32_NT &&
453 osvi.dwMajorVersion > 4)
454 {
455 if (osvi.dwMajorVersion >= 6 && osvi.dwMinorVersion == 0) {
456 if (osvi.wProductType == VER_NT_WORKSTATION) {
457 J2dRlsTrace(J2D_TRACE_INFO, "OS_VISTA\n");
458 currentOS = OS_VISTA;
459 } else {
460 J2dRlsTrace(J2D_TRACE_INFO, "OS_WINSERV_2008\n");
461 currentOS = OS_WINSERV_2008;
462 }
463 } else if (osvi.dwMajorVersion >= 6 && osvi.dwMinorVersion >= 1) {
464 if (osvi.wProductType == VER_NT_WORKSTATION) {
465 J2dRlsTrace(J2D_TRACE_INFO, "OS_WINDOWS7 or newer\n");
466 currentOS = OS_WINDOWS7;
467 } else {
468 J2dRlsTrace(J2D_TRACE_INFO, "OS_WINSERV_2008R2 or newer\n");
469 currentOS = OS_WINSERV_2008R2;
470 }
471 } else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) {
472 if (osvi.wProductType == VER_NT_WORKSTATION) {
473 J2dRlsTrace(J2D_TRACE_INFO, "OS_WINXP_64\n");
474 currentOS = OS_WINXP_64;
475 } else {
476 J2dRlsTrace(J2D_TRACE_INFO, "OS_WINSERV_2003\n");
477 currentOS = OS_WINSERV_2003;
478 }
479 } else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) {
480 J2dRlsTrace(J2D_TRACE_INFO, "OS_WINXP ");
481 currentOS = OS_WINXP;
482 if (osvi.wSuiteMask & VER_SUITE_PERSONAL) {
483 J2dRlsTrace(J2D_TRACE_INFO, "Home\n");
484 } else {
485 J2dRlsTrace(J2D_TRACE_INFO, "Pro\n");
486 }
487 } else {
488 J2dRlsTrace2(J2D_TRACE_INFO,
489 "OS_UNKNOWN: dwMajorVersion=%d dwMinorVersion=%d\n",
490 osvi.dwMajorVersion, osvi.dwMinorVersion);
491 currentOS = OS_UNKNOWN;
492 }
493 } else {
494 if (bVersOk) {
495 J2dRlsTrace2(J2D_TRACE_INFO,
496 "OS_UNKNOWN: dwPlatformId=%d dwMajorVersion=%d\n",
497 osvi.dwPlatformId, osvi.dwMajorVersion);
498 } else {
499 J2dRlsTrace(J2D_TRACE_INFO,"OS_UNKNOWN: GetVersionEx failed\n");
500 }
501 currentOS = OS_UNKNOWN;
502 }
503 }
504 return (currentOS & osInfo);
505 }
506
507 // static
508 HRESULT
CheckForBadHardware(DWORD vId,DWORD dId,LONGLONG version)509 D3DPipelineManager::CheckForBadHardware(DWORD vId, DWORD dId, LONGLONG version)
510 {
511 DWORD vendorId, deviceId;
512 UINT adapterInfo = 0;
513
514 J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::CheckForBadHardware");
515
516 while ((vendorId = badHardware[adapterInfo].VendorId) != 0x0000 &&
517 (deviceId = badHardware[adapterInfo].DeviceId) != 0x0000)
518 {
519 if (vendorId == vId && (deviceId == dId || deviceId == ALL_DEVICEIDS)) {
520 LONGLONG goodVersion = badHardware[adapterInfo].DriverVersion;
521 USHORT osInfo = badHardware[adapterInfo].OsInfo;
522 // the hardware check fails if:
523 // - we have an entry for this OS and
524 // - hardware is bad for all driver versions (NO_VERSION), or
525 // we have a driver version which is older than the
526 // minimum required for this OS
527 if (D3DPPLM_OsVersionMatches(osInfo) &&
528 (goodVersion == NO_VERSION || version < goodVersion))
529 {
530 J2dRlsTraceLn2(J2D_TRACE_ERROR,
531 "D3DPPLM::CheckForBadHardware: found matching "\
532 "hardware: VendorId=0x%04x DeviceId=0x%04x",
533 vendorId, deviceId);
534 if (goodVersion != NO_VERSION) {
535 // this was a match by the driver version
536 LARGE_INTEGER li;
537 li.QuadPart = goodVersion;
538 J2dRlsTraceLn(J2D_TRACE_ERROR,
539 " bad driver found, device disabled");
540 J2dRlsTraceLn4(J2D_TRACE_ERROR,
541 " update your driver to at "\
542 "least version %d.%d.%d.%d",
543 HIWORD(li.HighPart), LOWORD(li.HighPart),
544 HIWORD(li.LowPart), LOWORD(li.LowPart));
545 } else {
546 // this was a match by the device (no good driver for this
547 // device)
548 J2dRlsTraceLn(J2D_TRACE_ERROR,
549 "D3DPPLM::CheckForBadHardware: bad hardware "\
550 "found, device disabled");
551 }
552 if (!bNoHwCheck) {
553 return D3DERR_INVALIDDEVICE;
554 }
555 J2dRlsTraceLn(J2D_TRACE_WARNING, " Warning: hw/driver match "\
556 "overridden (via J2D_D3D_NO_HWCHECK)");
557 }
558 }
559 adapterInfo++;
560 }
561
562 return S_OK;
563 }
564
CheckAdaptersInfo()565 HRESULT D3DPipelineManager::CheckAdaptersInfo()
566 {
567 D3DADAPTER_IDENTIFIER9 aid;
568 UINT failedAdaptersCount = 0;
569
570 J2dRlsTraceLn(J2D_TRACE_INFO, "CheckAdaptersInfo");
571 J2dRlsTraceLn(J2D_TRACE_INFO, "------------------");
572 for (UINT Adapter = 0; Adapter < adapterCount; Adapter++) {
573
574 if (FAILED(pd3d9->GetAdapterIdentifier(Adapter, 0, &aid))) {
575 pAdapters[Adapter].state = CONTEXT_INIT_FAILED;
576 failedAdaptersCount++;
577 continue;
578 }
579
580 J2dRlsTraceLn1(J2D_TRACE_INFO, "Adapter Ordinal : %d", Adapter);
581 J2dRlsTraceLn1(J2D_TRACE_INFO, "Adapter Handle : 0x%x",
582 pd3d9->GetAdapterMonitor(Adapter));
583 J2dRlsTraceLn1(J2D_TRACE_INFO, "Description : %s",
584 aid.Description);
585 J2dRlsTraceLn2(J2D_TRACE_INFO, "GDI Name, Driver : %s, %s",
586 aid.DeviceName, aid.Driver);
587 J2dRlsTraceLn1(J2D_TRACE_INFO, "Vendor Id : 0x%04x",
588 aid.VendorId);
589 J2dRlsTraceLn1(J2D_TRACE_INFO, "Device Id : 0x%04x",
590 aid.DeviceId);
591 J2dRlsTraceLn1(J2D_TRACE_INFO, "SubSys Id : 0x%x",
592 aid.SubSysId);
593 J2dRlsTraceLn4(J2D_TRACE_INFO, "Driver Version : %d.%d.%d.%d",
594 HIWORD(aid.DriverVersion.HighPart),
595 LOWORD(aid.DriverVersion.HighPart),
596 HIWORD(aid.DriverVersion.LowPart),
597 LOWORD(aid.DriverVersion.LowPart));
598 J2dRlsTrace3(J2D_TRACE_INFO,
599 "[I] GUID : {%08X-%04X-%04X-",
600 aid.DeviceIdentifier.Data1,
601 aid.DeviceIdentifier.Data2,
602 aid.DeviceIdentifier.Data3);
603 J2dRlsTrace4(J2D_TRACE_INFO, "%02X%02X-%02X%02X",
604 aid.DeviceIdentifier.Data4[0],
605 aid.DeviceIdentifier.Data4[1],
606 aid.DeviceIdentifier.Data4[2],
607 aid.DeviceIdentifier.Data4[3]);
608 J2dRlsTrace4(J2D_TRACE_INFO, "%02X%02X%02X%02X}\n",
609 aid.DeviceIdentifier.Data4[4],
610 aid.DeviceIdentifier.Data4[5],
611 aid.DeviceIdentifier.Data4[6],
612 aid.DeviceIdentifier.Data4[7]);
613
614 if (FAILED(CheckForBadHardware(aid.VendorId, aid.DeviceId,
615 aid.DriverVersion.QuadPart)) ||
616 FAILED(CheckDeviceCaps(Adapter)) ||
617 FAILED(D3DEnabledOnAdapter(Adapter)))
618 {
619 pAdapters[Adapter].state = CONTEXT_INIT_FAILED;
620 failedAdaptersCount++;
621 }
622 J2dRlsTraceLn(J2D_TRACE_INFO, "------------------");
623 }
624
625 if (failedAdaptersCount == adapterCount) {
626 J2dRlsTraceLn(J2D_TRACE_ERROR,
627 "D3DPPLM::CheckAdaptersInfo: no suitable adapters found");
628 return E_FAIL;
629 }
630
631 return S_OK;
632 }
633
SelectDeviceType()634 D3DDEVTYPE D3DPipelineManager::SelectDeviceType()
635 {
636 char *pRas = getenv("J2D_D3D_RASTERIZER");
637 D3DDEVTYPE dtype = D3DDEVTYPE_HAL;
638 if (pRas != NULL) {
639 J2dRlsTrace(J2D_TRACE_WARNING, "[W] D3DPPLM::SelectDeviceType: ");
640 if (strncmp(pRas, "ref", 3) == 0 || strncmp(pRas, "rgb", 3) == 0) {
641 J2dRlsTrace(J2D_TRACE_WARNING, "ref rasterizer selected");
642 dtype = D3DDEVTYPE_REF;
643 } else if (strncmp(pRas, "hal",3) == 0 || strncmp(pRas, "tnl",3) == 0) {
644 J2dRlsTrace(J2D_TRACE_WARNING, "hal rasterizer selected");
645 dtype = D3DDEVTYPE_HAL;
646 } else if (strncmp(pRas, "nul", 3) == 0) {
647 J2dRlsTrace(J2D_TRACE_WARNING, "nullref rasterizer selected");
648 dtype = D3DDEVTYPE_NULLREF;
649 } else {
650 J2dRlsTrace1(J2D_TRACE_WARNING,
651 "unknown rasterizer: %s, only (ref|hal|nul) "\
652 "supported, hal selected instead", pRas);
653 }
654 J2dRlsTrace(J2D_TRACE_WARNING, "\n");
655 }
656 return dtype;
657 }
658
659 #define CHECK_CAP(FLAG, CAP) \
660 do { \
661 if (!((FLAG)&CAP)) { \
662 J2dRlsTraceLn2(J2D_TRACE_ERROR, \
663 "D3DPPLM::CheckDeviceCaps: adapter %d: Failed "\
664 "(cap %s not supported)", \
665 adapter, #CAP); \
666 return E_FAIL; \
667 } \
668 } while (0)
669
CheckDeviceCaps(UINT adapter)670 HRESULT D3DPipelineManager::CheckDeviceCaps(UINT adapter)
671 {
672 HRESULT res;
673 D3DCAPS9 d3dCaps;
674
675 J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::CheckDeviceCaps");
676
677 res = pd3d9->GetDeviceCaps(adapter, devType, &d3dCaps);
678 RETURN_STATUS_IF_FAILED(res);
679
680 CHECK_CAP(d3dCaps.DevCaps, D3DDEVCAPS_DRAWPRIMTLVERTEX);
681
682 // by requiring hardware tnl we are hoping for better drivers quality
683 if (!IsD3DForced()) {
684 // fail if not hw tnl unless d3d was forced
685 CHECK_CAP(d3dCaps.DevCaps, D3DDEVCAPS_HWTRANSFORMANDLIGHT);
686 }
687 if (d3dCaps.DeviceType == D3DDEVTYPE_HAL) {
688 CHECK_CAP(d3dCaps.DevCaps, D3DDEVCAPS_HWRASTERIZATION);
689 }
690
691 CHECK_CAP(d3dCaps.RasterCaps, D3DPRASTERCAPS_SCISSORTEST);
692
693 CHECK_CAP(d3dCaps.Caps3, D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD);
694
695 CHECK_CAP(d3dCaps.PrimitiveMiscCaps, D3DPMISCCAPS_CULLNONE);
696 CHECK_CAP(d3dCaps.PrimitiveMiscCaps, D3DPMISCCAPS_BLENDOP);
697 CHECK_CAP(d3dCaps.PrimitiveMiscCaps, D3DPMISCCAPS_MASKZ);
698
699 CHECK_CAP(d3dCaps.ZCmpCaps, D3DPCMPCAPS_ALWAYS);
700 CHECK_CAP(d3dCaps.ZCmpCaps, D3DPCMPCAPS_LESS);
701
702 CHECK_CAP(d3dCaps.SrcBlendCaps, D3DPBLENDCAPS_ZERO);
703 CHECK_CAP(d3dCaps.SrcBlendCaps, D3DPBLENDCAPS_ONE);
704 CHECK_CAP(d3dCaps.SrcBlendCaps, D3DPBLENDCAPS_SRCALPHA);
705 CHECK_CAP(d3dCaps.SrcBlendCaps, D3DPBLENDCAPS_DESTALPHA);
706 CHECK_CAP(d3dCaps.SrcBlendCaps, D3DPBLENDCAPS_INVSRCALPHA);
707 CHECK_CAP(d3dCaps.SrcBlendCaps, D3DPBLENDCAPS_INVDESTALPHA);
708
709 CHECK_CAP(d3dCaps.DestBlendCaps, D3DPBLENDCAPS_ZERO);
710 CHECK_CAP(d3dCaps.DestBlendCaps, D3DPBLENDCAPS_ONE);
711 CHECK_CAP(d3dCaps.DestBlendCaps, D3DPBLENDCAPS_SRCALPHA);
712 CHECK_CAP(d3dCaps.DestBlendCaps, D3DPBLENDCAPS_DESTALPHA);
713 CHECK_CAP(d3dCaps.DestBlendCaps, D3DPBLENDCAPS_INVSRCALPHA);
714 CHECK_CAP(d3dCaps.DestBlendCaps, D3DPBLENDCAPS_INVDESTALPHA);
715
716 CHECK_CAP(d3dCaps.TextureAddressCaps, D3DPTADDRESSCAPS_CLAMP);
717 CHECK_CAP(d3dCaps.TextureAddressCaps, D3DPTADDRESSCAPS_WRAP);
718
719 CHECK_CAP(d3dCaps.TextureOpCaps, D3DTEXOPCAPS_MODULATE);
720
721 if (d3dCaps.PixelShaderVersion < D3DPS_VERSION(2,0) && !IsD3DForced()) {
722 J2dRlsTraceLn1(J2D_TRACE_ERROR,
723 "D3DPPLM::CheckDeviceCaps: adapter %d: Failed "\
724 "(pixel shaders 2.0 required)", adapter);
725 return E_FAIL;
726 }
727
728 J2dRlsTraceLn1(J2D_TRACE_INFO,
729 "D3DPPLM::CheckDeviceCaps: adapter %d: Passed", adapter);
730 return S_OK;
731 }
732
733
D3DEnabledOnAdapter(UINT adapter)734 HRESULT D3DPipelineManager::D3DEnabledOnAdapter(UINT adapter)
735 {
736 HRESULT res;
737 D3DDISPLAYMODE dm;
738
739 res = pd3d9->GetAdapterDisplayMode(adapter, &dm);
740 RETURN_STATUS_IF_FAILED(res);
741
742 res = pd3d9->CheckDeviceType(adapter, devType, dm.Format, dm.Format, TRUE);
743 if (FAILED(res)) {
744 J2dRlsTraceLn1(J2D_TRACE_ERROR,
745 "D3DPPLM::D3DEnabledOnAdapter: no " \
746 "suitable d3d device on adapter %d", adapter);
747 }
748
749 return res;
750 }
751
GetAdapterOrdinalByHmon(HMONITOR hMon)752 UINT D3DPipelineManager::GetAdapterOrdinalByHmon(HMONITOR hMon)
753 {
754 UINT ret = D3DADAPTER_DEFAULT;
755
756 if (pd3d9 != NULL) {
757 UINT adapterCount = pd3d9->GetAdapterCount();
758 for (UINT adapter = 0; adapter < adapterCount; adapter++) {
759 HMONITOR hm = pd3d9->GetAdapterMonitor(adapter);
760 if (hm == hMon) {
761 ret = adapter;
762 break;
763 }
764 }
765 }
766 return ret;
767 }
768
769 D3DFORMAT
GetMatchingDepthStencilFormat(UINT adapterOrdinal,D3DFORMAT adapterFormat,D3DFORMAT renderTargetFormat)770 D3DPipelineManager::GetMatchingDepthStencilFormat(UINT adapterOrdinal,
771 D3DFORMAT adapterFormat,
772 D3DFORMAT renderTargetFormat)
773 {
774 static D3DFORMAT formats[] =
775 { D3DFMT_D16, D3DFMT_D32, D3DFMT_D24S8, D3DFMT_D24X8 };
776 D3DFORMAT newFormat = D3DFMT_UNKNOWN;
777 HRESULT res;
778 for (int i = 0; i < 4; i++) {
779 res = pd3d9->CheckDeviceFormat(adapterOrdinal,
780 devType, adapterFormat, D3DUSAGE_DEPTHSTENCIL,
781 D3DRTYPE_SURFACE, formats[i]);
782 if (FAILED(res)) continue;
783
784 res = pd3d9->CheckDepthStencilMatch(adapterOrdinal,
785 devType, adapterFormat, renderTargetFormat, formats[i]);
786 if (FAILED(res)) continue;
787 newFormat = formats[i];
788 break;
789 }
790 return newFormat;
791 }
792
CreateDefaultFocusWindow()793 HWND D3DPipelineManager::CreateDefaultFocusWindow()
794 {
795 UINT adapterOrdinal = D3DADAPTER_DEFAULT;
796
797 J2dTraceLn1(J2D_TRACE_INFO,
798 "D3DPPLM::CreateDefaultFocusWindow: adapter=%d",
799 adapterOrdinal);
800
801 if (defaultFocusWindow != 0) {
802 J2dRlsTraceLn(J2D_TRACE_WARNING,
803 "D3DPPLM::CreateDefaultFocusWindow: "\
804 "existing default focus window!");
805 return defaultFocusWindow;
806 }
807
808 WNDCLASS wc;
809 ZeroMemory(&wc, sizeof(WNDCLASS));
810 wc.hInstance = GetModuleHandle(NULL);
811 wc.lpfnWndProc = DefWindowProc;
812 wc.lpszClassName = L"D3DFocusWindow";
813 if (RegisterClass(&wc) == 0) {
814 J2dRlsTraceLn(J2D_TRACE_ERROR,
815 "D3DPPLM::CreateDefaultFocusWindow: "\
816 "error registering window class");
817 return 0;
818 }
819
820 MONITORINFO mi;
821 ZeroMemory(&mi, sizeof(MONITORINFO));
822 mi.cbSize = sizeof(MONITORINFO);
823 HMONITOR hMon = pd3d9->GetAdapterMonitor(adapterOrdinal);
824 if (hMon == 0 || !GetMonitorInfo(hMon, (LPMONITORINFO)&mi)) {
825 J2dRlsTraceLn1(J2D_TRACE_ERROR,
826 "D3DPPLM::CreateDefaultFocusWindow: "\
827 "error getting monitor info for adapter=%d", adapterOrdinal);
828 return 0;
829 }
830
831 HWND hWnd = CreateWindow(L"D3DFocusWindow", L"D3DFocusWindow", WS_POPUP,
832 mi.rcMonitor.left, mi.rcMonitor.top, 1, 1,
833 NULL, NULL, GetModuleHandle(NULL), NULL);
834 if (hWnd == 0) {
835 J2dRlsTraceLn(J2D_TRACE_ERROR,
836 "D3DPPLM::CreateDefaultFocusWindow: CreateWindow failed");
837 } else {
838 J2dTraceLn2(J2D_TRACE_INFO,
839 " Created default focus window %x for adapter %d",
840 hWnd, adapterOrdinal);
841 defaultFocusWindow = hWnd;
842 }
843 return hWnd;
844 }
845
GetCurrentFocusWindow()846 HWND D3DPipelineManager::GetCurrentFocusWindow()
847 {
848 J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::GetCurrentFocusWindow");
849 if (currentFSFocusAdapter < 0) {
850 J2dTraceLn1(J2D_TRACE_VERBOSE,
851 " no fs windows, using default focus window=0x%x",
852 defaultFocusWindow);
853 return defaultFocusWindow;
854 }
855 J2dTraceLn1(J2D_TRACE_VERBOSE, " using fs window=0x%x",
856 pAdapters[currentFSFocusAdapter].fsFocusWindow);
857 return pAdapters[currentFSFocusAdapter].fsFocusWindow;
858 }
859
SetFSFocusWindow(UINT adapterOrdinal,HWND hWnd)860 HWND D3DPipelineManager::SetFSFocusWindow(UINT adapterOrdinal, HWND hWnd)
861 {
862 J2dTraceLn2(J2D_TRACE_INFO,"D3DPPLM::SetFSFocusWindow hwnd=0x%x adapter=%d",
863 hWnd, adapterOrdinal);
864
865 HWND prev = pAdapters[adapterOrdinal].fsFocusWindow;
866 pAdapters[adapterOrdinal].fsFocusWindow = hWnd;
867 if (currentFSFocusAdapter < 0) {
868 J2dTraceLn(J2D_TRACE_VERBOSE, " first full-screen window");
869 // first fs window
870 currentFSFocusAdapter = adapterOrdinal;
871 // REMIND: we might want to reset the rest of the context here as well
872 // like we do when the an adapter exits fs mode; currently they will
873 // be reset sometime later
874 } else {
875 // there's already a fs window
876 if (currentFSFocusAdapter == adapterOrdinal) {
877 // it's current fs window => we're exiting fs mode on this adapter;
878 // look for a new fs focus window
879 if (hWnd == 0) {
880 UINT i;
881 currentFSFocusAdapter = -1;
882 for (i = 0; i < adapterCount; i++) {
883 if (pAdapters[i].fsFocusWindow != 0) {
884 J2dTraceLn1(J2D_TRACE_VERBOSE,
885 " adapter %d is still in fs mode", i);
886 currentFSFocusAdapter = i;
887 break;
888 }
889 }
890 // we have to reset all devices any time current focus device
891 // exits fs mode, and also to prevent some of them being left in
892 // a lost state when the last device exits fs - when non-last
893 // adapters exit fs mode they would not be able to create the
894 // device and will be put in a lost state forever
895 HRESULT res;
896 J2dTraceLn(J2D_TRACE_VERBOSE,
897 " adapter exited full-screen, reset all adapters");
898 for (i = 0; i < adapterCount; i++) {
899 if (pAdapters[i].pd3dContext != NULL) {
900 res = pAdapters[i].pd3dContext->ResetContext();
901 D3DRQ_MarkLostIfNeeded(res,
902 D3DRQ_GetCurrentDestination());
903 }
904 }
905 } else {
906 J2dTraceLn1(J2D_TRACE_WARNING,
907 "D3DPM::SetFSFocusWindow: setting the fs "\
908 "window again for adapter %d", adapterOrdinal);
909 }
910 }
911 }
912 return prev;
913 }
914
GetD3DContext(UINT adapterOrdinal,D3DContext ** ppd3dContext)915 HRESULT D3DPipelineManager::GetD3DContext(UINT adapterOrdinal,
916 D3DContext **ppd3dContext)
917 {
918 J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::GetD3DContext");
919
920 HRESULT res = S_OK;
921 if (adapterOrdinal < 0 || adapterOrdinal >= adapterCount ||
922 pAdapters == NULL ||
923 pAdapters[adapterOrdinal].state == CONTEXT_INIT_FAILED)
924 {
925 J2dRlsTraceLn1(J2D_TRACE_ERROR,
926 "D3DPPLM::GetD3DContext: invalid parameters or "\
927 "failed init for adapter %d", adapterOrdinal);
928 *ppd3dContext = NULL;
929 return E_FAIL;
930 }
931
932 if (pAdapters[adapterOrdinal].state == CONTEXT_NOT_INITED) {
933 D3DContext *pCtx = NULL;
934
935 if (pAdapters[adapterOrdinal].pd3dContext != NULL) {
936 J2dTraceLn1(J2D_TRACE_ERROR, " non-null context in "\
937 "uninitialized adapter %d", adapterOrdinal);
938 res = E_FAIL;
939 } else {
940 J2dTraceLn1(J2D_TRACE_VERBOSE,
941 " initializing context for adapter %d",adapterOrdinal);
942
943 if (SUCCEEDED(res = D3DEnabledOnAdapter(adapterOrdinal))) {
944 res = D3DContext::CreateInstance(pd3d9, adapterOrdinal, &pCtx);
945 if (FAILED(res)) {
946 J2dRlsTraceLn1(J2D_TRACE_ERROR,
947 "D3DPPLM::GetD3DContext: failed to create context "\
948 "for adapter=%d", adapterOrdinal);
949 }
950 } else {
951 J2dRlsTraceLn1(J2D_TRACE_ERROR,
952 "D3DPPLM::GetContext: no d3d on adapter %d",adapterOrdinal);
953 }
954 }
955 pAdapters[adapterOrdinal].state =
956 SUCCEEDED(res) ? CONTEXT_CREATED : CONTEXT_INIT_FAILED;
957 pAdapters[adapterOrdinal].pd3dContext = pCtx;
958 }
959 *ppd3dContext = pAdapters[adapterOrdinal].pd3dContext;
960 return res;
961 }
962
963
964 //==============================================================
965 // D3DInitializer
966 //==============================================================
967
968 D3DInitializer D3DInitializer::theInstance;
969
D3DInitializer()970 D3DInitializer::D3DInitializer()
971 : bComInitialized(false), pAdapterIniters(NULL)
972 {
973 }
974
~D3DInitializer()975 D3DInitializer::~D3DInitializer()
976 {
977 if (pAdapterIniters) {
978 delete[] pAdapterIniters;
979 }
980 }
981
InitImpl()982 void D3DInitializer::InitImpl()
983 {
984 J2dRlsTraceLn(J2D_TRACE_INFO, "D3DInitializer::InitImpl");
985 if (SUCCEEDED(::CoInitialize(NULL))) {
986 bComInitialized = true;
987 }
988 D3DPipelineManager *pMgr = D3DPipelineManager::CreateInstance();
989 if (pMgr != NULL) {
990 // init adapters if we are preloading
991 if (AwtToolkit::GetInstance().GetPreloadThread().OnPreloadThread()) {
992 UINT adapterCount = pMgr->adapterCount;
993
994 pAdapterIniters = new D3DAdapterInitializer[adapterCount];
995 for (UINT i=0; i<adapterCount; i++) {
996 pAdapterIniters[i].setAdapter(i);
997 AwtToolkit::GetInstance().GetPreloadThread().AddAction(&pAdapterIniters[i]);
998 }
999 }
1000 }
1001 }
1002
CleanImpl(bool reInit)1003 void D3DInitializer::CleanImpl(bool reInit)
1004 {
1005 J2dRlsTraceLn1(J2D_TRACE_INFO, "D3DInitializer::CleanImpl (%s)",
1006 reInit ? "RELAUNCH" : "normal");
1007 D3DPipelineManager::DeleteInstance();
1008 if (bComInitialized) {
1009 CoUninitialize();
1010 }
1011 }
1012
1013
InitImpl()1014 void D3DInitializer::D3DAdapterInitializer::InitImpl()
1015 {
1016 J2dRlsTraceLn1(J2D_TRACE_INFO, "D3DAdapterInitializer::InitImpl(%d) started", adapter);
1017
1018 D3DPipelineManager *pMgr = D3DPipelineManager::GetInstance();
1019 if (pMgr == NULL) {
1020 return;
1021 }
1022
1023 D3DContext *pd3dContext;
1024 pMgr->GetD3DContext(adapter, &pd3dContext);
1025
1026 J2dRlsTraceLn1(J2D_TRACE_INFO, "D3DAdapterInitializer::InitImpl(%d) finished", adapter);
1027 }
1028
CleanImpl(bool reInit)1029 void D3DInitializer::D3DAdapterInitializer::CleanImpl(bool reInit)
1030 {
1031 // nothing to do - D3DPipelineManager cleans adapters
1032 }
1033
1034
1035 extern "C" {
1036 /*
1037 * Export function to start D3D preloading
1038 * (called from java/javaw - see src/windows/bin/java-md.c)
1039 */
preloadD3D()1040 __declspec(dllexport) int preloadD3D()
1041 {
1042 J2dRlsTraceLn(J2D_TRACE_INFO, "AWT warmup: preloadD3D");
1043 AwtToolkit::GetInstance().GetPreloadThread().AddAction(&D3DInitializer::GetInstance());
1044 return 1;
1045 }
1046
1047 }
1048
1049