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