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 
  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 // static
 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 
 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
 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 
 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 
 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
 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
 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 
 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
 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 
 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 
 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 
 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 
 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 
 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
 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 
 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 
 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 
 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 
 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 
 970 D3DInitializer::D3DInitializer()
 971     : bComInitialized(false), pAdapterIniters(NULL)
 972 {
 973 }
 974 
 975 D3DInitializer::~D3DInitializer()
 976 {
 977     if (pAdapterIniters) {
 978         delete[] pAdapterIniters;
 979     }
 980 }
 981 
 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 
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 
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 
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  */
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