Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/native/sun/java2d/d3d/D3DPipelineManager.cpp
32288 views
/*1* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include "D3DBadHardware.h"26#include "D3DPipelineManager.h"27#include "D3DRenderQueue.h"28#include "WindowsFlags.h"29#include "awt_Win32GraphicsDevice.h"3031// state of the adapter prior to initialization32#define CONTEXT_NOT_INITED 033// this state is set if adapter initialization had failed34#define CONTEXT_INIT_FAILED (-1)35// this state is set if adapter was successfully created36#define CONTEXT_CREATED 13738static BOOL bNoHwCheck = (getenv("J2D_D3D_NO_HWCHECK") != NULL);3940D3DPipelineManager *D3DPipelineManager::pMgr = NULL;414243D3DPipelineManager * D3DPipelineManager::CreateInstance(void)44{45if (!IsD3DEnabled() ||46FAILED((D3DPipelineManager::CheckOSVersion())) ||47FAILED((D3DPipelineManager::GDICheckForBadHardware())))48{49return NULL;50}5152if (pMgr == NULL) {53pMgr = new D3DPipelineManager();54if (FAILED(pMgr->InitD3D())) {55SAFE_DELETE(pMgr);56}57} else {58// this should never happen so to be on the safe side do not59// use this unexpected pointer, do not try to release it, just null60// it out and fail safely61J2dRlsTraceLn1(J2D_TRACE_ERROR,62"D3DPPLM::CreateInstance: unexpected instance: 0x%x,"\63" abort.", pMgr);64pMgr = NULL;65}66return pMgr;67}6869void D3DPipelineManager::DeleteInstance()70{71J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::DeleteInstance()");72SAFE_DELETE(pMgr);73}7475D3DPipelineManager * D3DPipelineManager::GetInstance(void)76{77return pMgr;78}7980D3DPipelineManager::D3DPipelineManager(void)81{82pd3d9 = NULL;83hLibD3D9 = NULL;84pAdapters = NULL;85adapterCount = 0;86currentFSFocusAdapter = -1;87defaultFocusWindow = 0;88devType = SelectDeviceType();89}9091D3DPipelineManager::~D3DPipelineManager(void)92{93J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::~D3DPipelineManager()");94ReleaseD3D();95}9697HRESULT D3DPipelineManager::ReleaseD3D(void)98{99J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::ReleaseD3D()");100101ReleaseAdapters();102103SAFE_RELEASE(pd3d9);104105if (hLibD3D9 != NULL) {106::FreeLibrary(hLibD3D9);107hLibD3D9 = NULL;108}109110return S_OK;111}112113// Creates a Direct3D9 object and initializes adapters.114// If succeeded, returns S_OK, otherwise returns the error code.115HRESULT D3DPipelineManager::InitD3D(void)116{117typedef IDirect3D9 * WINAPI FnDirect3DCreate9(UINT SDKVersion);118119hLibD3D9 = JDK_LoadSystemLibrary("d3d9.dll");120if (hLibD3D9 == NULL) {121J2dRlsTraceLn(J2D_TRACE_ERROR, "InitD3D: no d3d9.dll");122return E_FAIL;123}124125FnDirect3DCreate9 *d3dcreate9 = NULL;126d3dcreate9 = (FnDirect3DCreate9*)127::GetProcAddress(hLibD3D9, "Direct3DCreate9");128if (d3dcreate9 == NULL) {129J2dRlsTraceLn(J2D_TRACE_ERROR, "InitD3D: no Direct3DCreate9");130::FreeLibrary(hLibD3D9);131return E_FAIL;132}133134pd3d9 = d3dcreate9(D3D_SDK_VERSION);135if (pd3d9 == NULL) {136J2dRlsTraceLn(J2D_TRACE_ERROR,137"InitD3D: unable to create IDirect3D9 object");138::FreeLibrary(hLibD3D9);139return E_FAIL;140}141142HRESULT res;143if (FAILED(res = InitAdapters())) {144J2dRlsTraceLn(J2D_TRACE_ERROR, "InitD3D: failed to init adapters");145ReleaseD3D();146return res;147}148149return S_OK;150}151152HRESULT D3DPipelineManager::ReleaseAdapters()153{154J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::ReleaseAdapters()");155156D3DRQ_ResetCurrentContextAndDestination();157if (pAdapters != NULL) {158for (UINT i = 0; i < adapterCount; i++) {159if (pAdapters[i].pd3dContext != NULL) {160delete pAdapters[i].pd3dContext;161}162}163delete[] pAdapters;164pAdapters = NULL;165}166if (defaultFocusWindow != 0) {167DestroyWindow(defaultFocusWindow);168UnregisterClass(L"D3DFocusWindow", GetModuleHandle(NULL));169defaultFocusWindow = 0;170}171currentFSFocusAdapter = -1;172return S_OK;173}174175// static176void D3DPipelineManager::NotifyAdapterEventListeners(UINT adapter,177jint eventType)178{179HMONITOR hMon;180int gdiScreen;181D3DPipelineManager *pMgr;182183// fix for 6946559: if d3d preloading fails jmv may be NULL184if (jvm == NULL) {185return;186}187188JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);189RETURN_IF_NULL(env);190191pMgr = D3DPipelineManager::GetInstance();192RETURN_IF_NULL(pMgr);193hMon = pMgr->pd3d9->GetAdapterMonitor(adapter);194195/*196* If we don't have devices initialized yet, no sense to clear them.197*/198if (!Devices::GetInstance()){199return;200}201202gdiScreen = AwtWin32GraphicsDevice::GetScreenFromHMONITOR(hMon);203204JNU_CallStaticMethodByName(env, NULL,205"sun/java2d/pipe/hw/AccelDeviceEventNotifier",206"eventOccured", "(II)V",207gdiScreen, eventType);208}209210UINT D3DPipelineManager::GetAdapterOrdinalForScreen(jint gdiScreen)211{212HMONITOR mHnd = AwtWin32GraphicsDevice::GetMonitor(gdiScreen);213if (mHnd == (HMONITOR)0) {214return D3DADAPTER_DEFAULT;215}216return GetAdapterOrdinalByHmon((HMONITOR)mHnd);217}218219// static220HRESULT D3DPipelineManager::HandleAdaptersChange(HMONITOR *pHMONITORs, UINT monNum)221{222HRESULT res = S_OK;223BOOL bResetD3D = FALSE, bFound;224225D3DPipelineManager *pMgr = D3DPipelineManager::GetInstance();226RETURN_STATUS_IF_NULL(pHMONITORs, E_FAIL);227if (pMgr == NULL) {228// NULL pMgr is valid when the pipeline is not enabled or if it hasn't229// been created yet230return S_OK;231}232RETURN_STATUS_IF_NULL(pMgr->pAdapters, E_FAIL);233RETURN_STATUS_IF_NULL(pMgr->pd3d9, E_FAIL);234235J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::HandleAdaptersChange");236237if (monNum != pMgr->adapterCount) {238J2dTraceLn2(J2D_TRACE_VERBOSE,239" number of adapters changed (old=%d, new=%d)",240pMgr->adapterCount, monNum);241bResetD3D = TRUE;242} else {243for (UINT i = 0; i < pMgr->adapterCount; i++) {244HMONITOR hMon = pMgr->pd3d9->GetAdapterMonitor(i);245if (hMon == (HMONITOR)0x0) {246J2dTraceLn1(J2D_TRACE_VERBOSE, " adapter %d: removed", i);247bResetD3D = TRUE;248break;249}250bFound = FALSE;251for (UINT mon = 0; mon < monNum; mon++) {252if (pHMONITORs[mon] == hMon) {253J2dTraceLn3(J2D_TRACE_VERBOSE,254" adapter %d: found hmnd[%d]=0x%x", i, mon, hMon);255bFound = TRUE;256break;257}258}259if (!bFound) {260J2dTraceLn2(J2D_TRACE_VERBOSE,261" adapter %d: could not find hmnd=0x%x "\262"in the list of new hmnds", i, hMon);263bResetD3D = TRUE;264break;265}266}267}268269if (bResetD3D) {270J2dTraceLn(J2D_TRACE_VERBOSE, " adapters changed: resetting d3d");271pMgr->ReleaseD3D();272res = pMgr->InitD3D();273}274return res;275}276277HRESULT D3DPipelineManager::HandleLostDevices()278{279J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::HandleLostDevices()");280BOOL bAllClear = TRUE;281282HWND hwnd = GetCurrentFocusWindow();283if (hwnd != defaultFocusWindow) {284// we're in full-screen mode285WINDOWPLACEMENT wp;286::ZeroMemory(&wp, sizeof(WINDOWPLACEMENT));287wp.length = sizeof(WINDOWPLACEMENT);288::GetWindowPlacement(hwnd, &wp);289290// Only attempt to restore the devices if we're in full-screen mode291// and the fs window is active; sleep otherwise.292// Restoring a window while minimized causes problems on Vista:293// sometimes we restore the window too quickly and it pops up back from294// minimized state when the device is restored.295//296// WARNING: this is a sleep on the Toolkit thread! We may reconsider297// this if we find any issues later.298if ((wp.showCmd & SW_SHOWMINNOACTIVE) && !(wp.showCmd & SW_SHOWNORMAL)){299static DWORD prevCallTime = 0;300J2dTraceLn(J2D_TRACE_VERBOSE, " fs focus window is minimized");301DWORD currentTime = ::GetTickCount();302if ((currentTime - prevCallTime) < 100) {303J2dTraceLn(J2D_TRACE_VERBOSE, " tight loop detected, sleep");304::Sleep(100);305}306prevCallTime = currentTime;307return D3DERR_DEVICELOST;308}309}310if (pAdapters != NULL) {311for (UINT i = 0; i < adapterCount; i++) {312if (pAdapters[i].pd3dContext != NULL) {313J2dTraceLn1(J2D_TRACE_VERBOSE,314" HandleLostDevices: checking adapter %d", i);315D3DContext *d3dc = pAdapters[i].pd3dContext;316if (FAILED(d3dc->CheckAndResetDevice())) {317bAllClear = FALSE;318}319}320}321}322return bAllClear ? S_OK : D3DERR_DEVICELOST;323}324325HRESULT D3DPipelineManager::InitAdapters()326{327HRESULT res = E_FAIL;328329J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::InitAdapters()");330if (pAdapters != NULL) {331ReleaseAdapters();332}333334adapterCount = pd3d9->GetAdapterCount();335pAdapters = new D3DAdapter[adapterCount];336if (pAdapters == NULL) {337J2dRlsTraceLn(J2D_TRACE_ERROR, "InitAdapters: out of memory");338adapterCount = 0;339return E_FAIL;340}341ZeroMemory(pAdapters, adapterCount * sizeof(D3DAdapter));342343res = CheckAdaptersInfo();344RETURN_STATUS_IF_FAILED(res);345346currentFSFocusAdapter = -1;347if (CreateDefaultFocusWindow() == 0) {348return E_FAIL;349}350351return S_OK;352}353354// static355HRESULT356D3DPipelineManager::CheckOSVersion()357{358// require Windows XP or newer client-class OS359if (IS_WINVER_ATLEAST(5, 1) &&360!D3DPPLM_OsVersionMatches(OS_WINSERV_2008R2|OS_WINSERV_2008|361OS_WINSERV_2003))362{363J2dTraceLn(J2D_TRACE_INFO,364"D3DPPLM::CheckOSVersion: Windows XP or newer client-classs"\365" OS detected, passed");366return S_OK;367}368J2dRlsTraceLn(J2D_TRACE_ERROR,369"D3DPPLM::CheckOSVersion: Windows 2000 or earlier (or a "\370"server) OS detected, failed");371if (bNoHwCheck) {372J2dRlsTraceLn(J2D_TRACE_WARNING,373" OS check overridden via J2D_D3D_NO_HWCHECK");374return S_OK;375}376return E_FAIL;377}378379// static380HRESULT381D3DPipelineManager::GDICheckForBadHardware()382{383DISPLAY_DEVICE dd;384dd.cb = sizeof(DISPLAY_DEVICE);385386int failedDevices = 0;387int attachedDevices = 0;388int i = 0;389WCHAR *id;390WCHAR vendorId[5];391WCHAR deviceId[5];392DWORD dwDId, dwVId;393394J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::GDICheckForBadHardware");395396// i<20 is to guard against buggy drivers397while (EnumDisplayDevices(NULL, i, &dd, 0) && i < 20) {398if (dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) {399attachedDevices++;400id = dd.DeviceID;401if (wcslen(id) > 21) {402// get vendor ID403wcsncpy(vendorId, id+8, 4);404int args1 = swscanf(vendorId, L"%X", &dwVId);405406// get device ID407wcsncpy(deviceId, id+17, 4);408int args2 = swscanf(deviceId, L"%X", &dwDId);409410if (args1 == 1 && args2 == 1) {411J2dTraceLn2(J2D_TRACE_VERBOSE,412" device: vendorID=0x%04x, deviceId=0x%04x",413dwVId, dwDId);414// since we don't have a driver version here we will415// just ask to ignore the version for now; bad hw416// entries with specific drivers information will be417// processed later when d3d is initialized and we can418// obtain a driver version419if (FAILED(CheckForBadHardware(dwVId, dwDId, MAX_VERSION))){420failedDevices++;421}422}423}424}425426i++;427}428429if (failedDevices == attachedDevices) {430J2dRlsTraceLn(J2D_TRACE_ERROR,431"D3DPPLM::GDICheckForBadHardware: no suitable devices found");432return E_FAIL;433}434435return S_OK;436}437438BOOL D3DPPLM_OsVersionMatches(USHORT osInfo) {439static USHORT currentOS = OS_UNDEFINED;440441if (currentOS == OS_UNDEFINED) {442BOOL bVersOk;443OSVERSIONINFOEX osvi;444445ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));446osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);447448bVersOk = GetVersionEx((OSVERSIONINFO *) &osvi);449450J2dRlsTrace(J2D_TRACE_INFO, "[I] OS Version = ");451if (bVersOk && osvi.dwPlatformId == VER_PLATFORM_WIN32_NT &&452osvi.dwMajorVersion > 4)453{454if (osvi.dwMajorVersion >= 6 && osvi.dwMinorVersion == 0) {455if (osvi.wProductType == VER_NT_WORKSTATION) {456J2dRlsTrace(J2D_TRACE_INFO, "OS_VISTA\n");457currentOS = OS_VISTA;458} else {459J2dRlsTrace(J2D_TRACE_INFO, "OS_WINSERV_2008\n");460currentOS = OS_WINSERV_2008;461}462} else if (osvi.dwMajorVersion >= 6 && osvi.dwMinorVersion >= 1) {463if (osvi.wProductType == VER_NT_WORKSTATION) {464J2dRlsTrace(J2D_TRACE_INFO, "OS_WINDOWS7 or newer\n");465currentOS = OS_WINDOWS7;466} else {467J2dRlsTrace(J2D_TRACE_INFO, "OS_WINSERV_2008R2 or newer\n");468currentOS = OS_WINSERV_2008R2;469}470} else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) {471if (osvi.wProductType == VER_NT_WORKSTATION) {472J2dRlsTrace(J2D_TRACE_INFO, "OS_WINXP_64\n");473currentOS = OS_WINXP_64;474} else {475J2dRlsTrace(J2D_TRACE_INFO, "OS_WINSERV_2003\n");476currentOS = OS_WINSERV_2003;477}478} else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) {479J2dRlsTrace(J2D_TRACE_INFO, "OS_WINXP ");480currentOS = OS_WINXP;481if (osvi.wSuiteMask & VER_SUITE_PERSONAL) {482J2dRlsTrace(J2D_TRACE_INFO, "Home\n");483} else {484J2dRlsTrace(J2D_TRACE_INFO, "Pro\n");485}486} else {487J2dRlsTrace2(J2D_TRACE_INFO,488"OS_UNKNOWN: dwMajorVersion=%d dwMinorVersion=%d\n",489osvi.dwMajorVersion, osvi.dwMinorVersion);490currentOS = OS_UNKNOWN;491}492} else {493if (bVersOk) {494J2dRlsTrace2(J2D_TRACE_INFO,495"OS_UNKNOWN: dwPlatformId=%d dwMajorVersion=%d\n",496osvi.dwPlatformId, osvi.dwMajorVersion);497} else {498J2dRlsTrace(J2D_TRACE_INFO,"OS_UNKNOWN: GetVersionEx failed\n");499}500currentOS = OS_UNKNOWN;501}502}503return (currentOS & osInfo);504}505506// static507HRESULT508D3DPipelineManager::CheckForBadHardware(DWORD vId, DWORD dId, LONGLONG version)509{510DWORD vendorId, deviceId;511UINT adapterInfo = 0;512513J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::CheckForBadHardware");514515while ((vendorId = badHardware[adapterInfo].VendorId) != 0x0000 &&516(deviceId = badHardware[adapterInfo].DeviceId) != 0x0000)517{518if (vendorId == vId && (deviceId == dId || deviceId == ALL_DEVICEIDS)) {519LONGLONG goodVersion = badHardware[adapterInfo].DriverVersion;520USHORT osInfo = badHardware[adapterInfo].OsInfo;521// the hardware check fails if:522// - we have an entry for this OS and523// - hardware is bad for all driver versions (NO_VERSION), or524// we have a driver version which is older than the525// minimum required for this OS526if (D3DPPLM_OsVersionMatches(osInfo) &&527(goodVersion == NO_VERSION || version < goodVersion))528{529J2dRlsTraceLn2(J2D_TRACE_ERROR,530"D3DPPLM::CheckForBadHardware: found matching "\531"hardware: VendorId=0x%04x DeviceId=0x%04x",532vendorId, deviceId);533if (goodVersion != NO_VERSION) {534// this was a match by the driver version535LARGE_INTEGER li;536li.QuadPart = goodVersion;537J2dRlsTraceLn(J2D_TRACE_ERROR,538" bad driver found, device disabled");539J2dRlsTraceLn4(J2D_TRACE_ERROR,540" update your driver to at "\541"least version %d.%d.%d.%d",542HIWORD(li.HighPart), LOWORD(li.HighPart),543HIWORD(li.LowPart), LOWORD(li.LowPart));544} else {545// this was a match by the device (no good driver for this546// device)547J2dRlsTraceLn(J2D_TRACE_ERROR,548"D3DPPLM::CheckForBadHardware: bad hardware "\549"found, device disabled");550}551if (!bNoHwCheck) {552return D3DERR_INVALIDDEVICE;553}554J2dRlsTraceLn(J2D_TRACE_WARNING, " Warning: hw/driver match "\555"overridden (via J2D_D3D_NO_HWCHECK)");556}557}558adapterInfo++;559}560561return S_OK;562}563564HRESULT D3DPipelineManager::CheckAdaptersInfo()565{566D3DADAPTER_IDENTIFIER9 aid;567UINT failedAdaptersCount = 0;568569J2dRlsTraceLn(J2D_TRACE_INFO, "CheckAdaptersInfo");570J2dRlsTraceLn(J2D_TRACE_INFO, "------------------");571for (UINT Adapter = 0; Adapter < adapterCount; Adapter++) {572573if (FAILED(pd3d9->GetAdapterIdentifier(Adapter, 0, &aid))) {574pAdapters[Adapter].state = CONTEXT_INIT_FAILED;575failedAdaptersCount++;576continue;577}578579J2dRlsTraceLn1(J2D_TRACE_INFO, "Adapter Ordinal : %d", Adapter);580J2dRlsTraceLn1(J2D_TRACE_INFO, "Adapter Handle : 0x%x",581pd3d9->GetAdapterMonitor(Adapter));582J2dRlsTraceLn1(J2D_TRACE_INFO, "Description : %s",583aid.Description);584J2dRlsTraceLn2(J2D_TRACE_INFO, "GDI Name, Driver : %s, %s",585aid.DeviceName, aid.Driver);586J2dRlsTraceLn1(J2D_TRACE_INFO, "Vendor Id : 0x%04x",587aid.VendorId);588J2dRlsTraceLn1(J2D_TRACE_INFO, "Device Id : 0x%04x",589aid.DeviceId);590J2dRlsTraceLn1(J2D_TRACE_INFO, "SubSys Id : 0x%x",591aid.SubSysId);592J2dRlsTraceLn4(J2D_TRACE_INFO, "Driver Version : %d.%d.%d.%d",593HIWORD(aid.DriverVersion.HighPart),594LOWORD(aid.DriverVersion.HighPart),595HIWORD(aid.DriverVersion.LowPart),596LOWORD(aid.DriverVersion.LowPart));597J2dRlsTrace3(J2D_TRACE_INFO,598"[I] GUID : {%08X-%04X-%04X-",599aid.DeviceIdentifier.Data1,600aid.DeviceIdentifier.Data2,601aid.DeviceIdentifier.Data3);602J2dRlsTrace4(J2D_TRACE_INFO, "%02X%02X-%02X%02X",603aid.DeviceIdentifier.Data4[0],604aid.DeviceIdentifier.Data4[1],605aid.DeviceIdentifier.Data4[2],606aid.DeviceIdentifier.Data4[3]);607J2dRlsTrace4(J2D_TRACE_INFO, "%02X%02X%02X%02X}\n",608aid.DeviceIdentifier.Data4[4],609aid.DeviceIdentifier.Data4[5],610aid.DeviceIdentifier.Data4[6],611aid.DeviceIdentifier.Data4[7]);612613if (FAILED(CheckForBadHardware(aid.VendorId, aid.DeviceId,614aid.DriverVersion.QuadPart)) ||615FAILED(CheckDeviceCaps(Adapter)) ||616FAILED(D3DEnabledOnAdapter(Adapter)))617{618pAdapters[Adapter].state = CONTEXT_INIT_FAILED;619failedAdaptersCount++;620}621J2dRlsTraceLn(J2D_TRACE_INFO, "------------------");622}623624if (failedAdaptersCount == adapterCount) {625J2dRlsTraceLn(J2D_TRACE_ERROR,626"D3DPPLM::CheckAdaptersInfo: no suitable adapters found");627return E_FAIL;628}629630return S_OK;631}632633D3DDEVTYPE D3DPipelineManager::SelectDeviceType()634{635char *pRas = getenv("J2D_D3D_RASTERIZER");636D3DDEVTYPE dtype = D3DDEVTYPE_HAL;637if (pRas != NULL) {638J2dRlsTrace(J2D_TRACE_WARNING, "[W] D3DPPLM::SelectDeviceType: ");639if (strncmp(pRas, "ref", 3) == 0 || strncmp(pRas, "rgb", 3) == 0) {640J2dRlsTrace(J2D_TRACE_WARNING, "ref rasterizer selected");641dtype = D3DDEVTYPE_REF;642} else if (strncmp(pRas, "hal",3) == 0 || strncmp(pRas, "tnl",3) == 0) {643J2dRlsTrace(J2D_TRACE_WARNING, "hal rasterizer selected");644dtype = D3DDEVTYPE_HAL;645} else if (strncmp(pRas, "nul", 3) == 0) {646J2dRlsTrace(J2D_TRACE_WARNING, "nullref rasterizer selected");647dtype = D3DDEVTYPE_NULLREF;648} else {649J2dRlsTrace1(J2D_TRACE_WARNING,650"unknown rasterizer: %s, only (ref|hal|nul) "\651"supported, hal selected instead", pRas);652}653J2dRlsTrace(J2D_TRACE_WARNING, "\n");654}655return dtype;656}657658#define CHECK_CAP(FLAG, CAP) \659do { \660if (!((FLAG)&CAP)) { \661J2dRlsTraceLn2(J2D_TRACE_ERROR, \662"D3DPPLM::CheckDeviceCaps: adapter %d: Failed "\663"(cap %s not supported)", \664adapter, #CAP); \665return E_FAIL; \666} \667} while (0)668669HRESULT D3DPipelineManager::CheckDeviceCaps(UINT adapter)670{671HRESULT res;672D3DCAPS9 d3dCaps;673674J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::CheckDeviceCaps");675676res = pd3d9->GetDeviceCaps(adapter, devType, &d3dCaps);677RETURN_STATUS_IF_FAILED(res);678679CHECK_CAP(d3dCaps.DevCaps, D3DDEVCAPS_DRAWPRIMTLVERTEX);680681// by requiring hardware tnl we are hoping for better drivers quality682if (!IsD3DForced()) {683// fail if not hw tnl unless d3d was forced684CHECK_CAP(d3dCaps.DevCaps, D3DDEVCAPS_HWTRANSFORMANDLIGHT);685}686if (d3dCaps.DeviceType == D3DDEVTYPE_HAL) {687CHECK_CAP(d3dCaps.DevCaps, D3DDEVCAPS_HWRASTERIZATION);688}689690CHECK_CAP(d3dCaps.RasterCaps, D3DPRASTERCAPS_SCISSORTEST);691692CHECK_CAP(d3dCaps.Caps3, D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD);693694CHECK_CAP(d3dCaps.PrimitiveMiscCaps, D3DPMISCCAPS_CULLNONE);695CHECK_CAP(d3dCaps.PrimitiveMiscCaps, D3DPMISCCAPS_BLENDOP);696CHECK_CAP(d3dCaps.PrimitiveMiscCaps, D3DPMISCCAPS_MASKZ);697698CHECK_CAP(d3dCaps.ZCmpCaps, D3DPCMPCAPS_ALWAYS);699CHECK_CAP(d3dCaps.ZCmpCaps, D3DPCMPCAPS_LESS);700701CHECK_CAP(d3dCaps.SrcBlendCaps, D3DPBLENDCAPS_ZERO);702CHECK_CAP(d3dCaps.SrcBlendCaps, D3DPBLENDCAPS_ONE);703CHECK_CAP(d3dCaps.SrcBlendCaps, D3DPBLENDCAPS_SRCALPHA);704CHECK_CAP(d3dCaps.SrcBlendCaps, D3DPBLENDCAPS_DESTALPHA);705CHECK_CAP(d3dCaps.SrcBlendCaps, D3DPBLENDCAPS_INVSRCALPHA);706CHECK_CAP(d3dCaps.SrcBlendCaps, D3DPBLENDCAPS_INVDESTALPHA);707708CHECK_CAP(d3dCaps.DestBlendCaps, D3DPBLENDCAPS_ZERO);709CHECK_CAP(d3dCaps.DestBlendCaps, D3DPBLENDCAPS_ONE);710CHECK_CAP(d3dCaps.DestBlendCaps, D3DPBLENDCAPS_SRCALPHA);711CHECK_CAP(d3dCaps.DestBlendCaps, D3DPBLENDCAPS_DESTALPHA);712CHECK_CAP(d3dCaps.DestBlendCaps, D3DPBLENDCAPS_INVSRCALPHA);713CHECK_CAP(d3dCaps.DestBlendCaps, D3DPBLENDCAPS_INVDESTALPHA);714715CHECK_CAP(d3dCaps.TextureAddressCaps, D3DPTADDRESSCAPS_CLAMP);716CHECK_CAP(d3dCaps.TextureAddressCaps, D3DPTADDRESSCAPS_WRAP);717718CHECK_CAP(d3dCaps.TextureOpCaps, D3DTEXOPCAPS_MODULATE);719720if (d3dCaps.PixelShaderVersion < D3DPS_VERSION(2,0) && !IsD3DForced()) {721J2dRlsTraceLn1(J2D_TRACE_ERROR,722"D3DPPLM::CheckDeviceCaps: adapter %d: Failed "\723"(pixel shaders 2.0 required)", adapter);724return E_FAIL;725}726727J2dRlsTraceLn1(J2D_TRACE_INFO,728"D3DPPLM::CheckDeviceCaps: adapter %d: Passed", adapter);729return S_OK;730}731732733HRESULT D3DPipelineManager::D3DEnabledOnAdapter(UINT adapter)734{735HRESULT res;736D3DDISPLAYMODE dm;737738res = pd3d9->GetAdapterDisplayMode(adapter, &dm);739RETURN_STATUS_IF_FAILED(res);740741res = pd3d9->CheckDeviceType(adapter, devType, dm.Format, dm.Format, TRUE);742if (FAILED(res)) {743J2dRlsTraceLn1(J2D_TRACE_ERROR,744"D3DPPLM::D3DEnabledOnAdapter: no " \745"suitable d3d device on adapter %d", adapter);746}747748return res;749}750751UINT D3DPipelineManager::GetAdapterOrdinalByHmon(HMONITOR hMon)752{753UINT ret = D3DADAPTER_DEFAULT;754755if (pd3d9 != NULL) {756UINT adapterCount = pd3d9->GetAdapterCount();757for (UINT adapter = 0; adapter < adapterCount; adapter++) {758HMONITOR hm = pd3d9->GetAdapterMonitor(adapter);759if (hm == hMon) {760ret = adapter;761break;762}763}764}765return ret;766}767768D3DFORMAT769D3DPipelineManager::GetMatchingDepthStencilFormat(UINT adapterOrdinal,770D3DFORMAT adapterFormat,771D3DFORMAT renderTargetFormat)772{773static D3DFORMAT formats[] =774{ D3DFMT_D16, D3DFMT_D32, D3DFMT_D24S8, D3DFMT_D24X8 };775D3DFORMAT newFormat = D3DFMT_UNKNOWN;776HRESULT res;777for (int i = 0; i < 4; i++) {778res = pd3d9->CheckDeviceFormat(adapterOrdinal,779devType, adapterFormat, D3DUSAGE_DEPTHSTENCIL,780D3DRTYPE_SURFACE, formats[i]);781if (FAILED(res)) continue;782783res = pd3d9->CheckDepthStencilMatch(adapterOrdinal,784devType, adapterFormat, renderTargetFormat, formats[i]);785if (FAILED(res)) continue;786newFormat = formats[i];787break;788}789return newFormat;790}791792HWND D3DPipelineManager::CreateDefaultFocusWindow()793{794UINT adapterOrdinal = D3DADAPTER_DEFAULT;795796J2dTraceLn1(J2D_TRACE_INFO,797"D3DPPLM::CreateDefaultFocusWindow: adapter=%d",798adapterOrdinal);799800if (defaultFocusWindow != 0) {801J2dRlsTraceLn(J2D_TRACE_WARNING,802"D3DPPLM::CreateDefaultFocusWindow: "\803"existing default focus window!");804return defaultFocusWindow;805}806807WNDCLASS wc;808ZeroMemory(&wc, sizeof(WNDCLASS));809wc.hInstance = GetModuleHandle(NULL);810wc.lpfnWndProc = DefWindowProc;811wc.lpszClassName = L"D3DFocusWindow";812if (RegisterClass(&wc) == 0) {813J2dRlsTraceLn(J2D_TRACE_ERROR,814"D3DPPLM::CreateDefaultFocusWindow: "\815"error registering window class");816return 0;817}818819MONITORINFO mi;820ZeroMemory(&mi, sizeof(MONITORINFO));821mi.cbSize = sizeof(MONITORINFO);822HMONITOR hMon = pd3d9->GetAdapterMonitor(adapterOrdinal);823if (hMon == 0 || !GetMonitorInfo(hMon, (LPMONITORINFO)&mi)) {824J2dRlsTraceLn1(J2D_TRACE_ERROR,825"D3DPPLM::CreateDefaultFocusWindow: "\826"error getting monitor info for adapter=%d", adapterOrdinal);827return 0;828}829830HWND hWnd = CreateWindow(L"D3DFocusWindow", L"D3DFocusWindow", WS_POPUP,831mi.rcMonitor.left, mi.rcMonitor.top, 1, 1,832NULL, NULL, GetModuleHandle(NULL), NULL);833if (hWnd == 0) {834J2dRlsTraceLn(J2D_TRACE_ERROR,835"D3DPPLM::CreateDefaultFocusWindow: CreateWindow failed");836} else {837J2dTraceLn2(J2D_TRACE_INFO,838" Created default focus window %x for adapter %d",839hWnd, adapterOrdinal);840defaultFocusWindow = hWnd;841}842return hWnd;843}844845HWND D3DPipelineManager::GetCurrentFocusWindow()846{847J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::GetCurrentFocusWindow");848if (currentFSFocusAdapter < 0) {849J2dTraceLn1(J2D_TRACE_VERBOSE,850" no fs windows, using default focus window=0x%x",851defaultFocusWindow);852return defaultFocusWindow;853}854J2dTraceLn1(J2D_TRACE_VERBOSE, " using fs window=0x%x",855pAdapters[currentFSFocusAdapter].fsFocusWindow);856return pAdapters[currentFSFocusAdapter].fsFocusWindow;857}858859HWND D3DPipelineManager::SetFSFocusWindow(UINT adapterOrdinal, HWND hWnd)860{861J2dTraceLn2(J2D_TRACE_INFO,"D3DPPLM::SetFSFocusWindow hwnd=0x%x adapter=%d",862hWnd, adapterOrdinal);863864HWND prev = pAdapters[adapterOrdinal].fsFocusWindow;865pAdapters[adapterOrdinal].fsFocusWindow = hWnd;866if (currentFSFocusAdapter < 0) {867J2dTraceLn(J2D_TRACE_VERBOSE, " first full-screen window");868// first fs window869currentFSFocusAdapter = adapterOrdinal;870// REMIND: we might want to reset the rest of the context here as well871// like we do when the an adapter exits fs mode; currently they will872// be reset sometime later873} else {874// there's already a fs window875if (currentFSFocusAdapter == adapterOrdinal) {876// it's current fs window => we're exiting fs mode on this adapter;877// look for a new fs focus window878if (hWnd == 0) {879UINT i;880currentFSFocusAdapter = -1;881for (i = 0; i < adapterCount; i++) {882if (pAdapters[i].fsFocusWindow != 0) {883J2dTraceLn1(J2D_TRACE_VERBOSE,884" adapter %d is still in fs mode", i);885currentFSFocusAdapter = i;886break;887}888}889// we have to reset all devices any time current focus device890// exits fs mode, and also to prevent some of them being left in891// a lost state when the last device exits fs - when non-last892// adapters exit fs mode they would not be able to create the893// device and will be put in a lost state forever894HRESULT res;895J2dTraceLn(J2D_TRACE_VERBOSE,896" adapter exited full-screen, reset all adapters");897for (i = 0; i < adapterCount; i++) {898if (pAdapters[i].pd3dContext != NULL) {899res = pAdapters[i].pd3dContext->ResetContext();900D3DRQ_MarkLostIfNeeded(res,901D3DRQ_GetCurrentDestination());902}903}904} else {905J2dTraceLn1(J2D_TRACE_WARNING,906"D3DPM::SetFSFocusWindow: setting the fs "\907"window again for adapter %d", adapterOrdinal);908}909}910}911return prev;912}913914HRESULT D3DPipelineManager::GetD3DContext(UINT adapterOrdinal,915D3DContext **ppd3dContext)916{917J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::GetD3DContext");918919HRESULT res = S_OK;920if (adapterOrdinal < 0 || adapterOrdinal >= adapterCount ||921pAdapters == NULL ||922pAdapters[adapterOrdinal].state == CONTEXT_INIT_FAILED)923{924J2dRlsTraceLn1(J2D_TRACE_ERROR,925"D3DPPLM::GetD3DContext: invalid parameters or "\926"failed init for adapter %d", adapterOrdinal);927*ppd3dContext = NULL;928return E_FAIL;929}930931if (pAdapters[adapterOrdinal].state == CONTEXT_NOT_INITED) {932D3DContext *pCtx = NULL;933934if (pAdapters[adapterOrdinal].pd3dContext != NULL) {935J2dTraceLn1(J2D_TRACE_ERROR, " non-null context in "\936"uninitialized adapter %d", adapterOrdinal);937res = E_FAIL;938} else {939J2dTraceLn1(J2D_TRACE_VERBOSE,940" initializing context for adapter %d",adapterOrdinal);941942if (SUCCEEDED(res = D3DEnabledOnAdapter(adapterOrdinal))) {943res = D3DContext::CreateInstance(pd3d9, adapterOrdinal, &pCtx);944if (FAILED(res)) {945J2dRlsTraceLn1(J2D_TRACE_ERROR,946"D3DPPLM::GetD3DContext: failed to create context "\947"for adapter=%d", adapterOrdinal);948}949} else {950J2dRlsTraceLn1(J2D_TRACE_ERROR,951"D3DPPLM::GetContext: no d3d on adapter %d",adapterOrdinal);952}953}954pAdapters[adapterOrdinal].state =955SUCCEEDED(res) ? CONTEXT_CREATED : CONTEXT_INIT_FAILED;956pAdapters[adapterOrdinal].pd3dContext = pCtx;957}958*ppd3dContext = pAdapters[adapterOrdinal].pd3dContext;959return res;960}961962963//==============================================================964// D3DInitializer965//==============================================================966967D3DInitializer D3DInitializer::theInstance;968969D3DInitializer::D3DInitializer()970: bComInitialized(false), pAdapterIniters(NULL)971{972}973974D3DInitializer::~D3DInitializer()975{976if (pAdapterIniters) {977delete[] pAdapterIniters;978}979}980981void D3DInitializer::InitImpl()982{983J2dRlsTraceLn(J2D_TRACE_INFO, "D3DInitializer::InitImpl");984if (SUCCEEDED(::CoInitialize(NULL))) {985bComInitialized = true;986}987D3DPipelineManager *pMgr = D3DPipelineManager::CreateInstance();988if (pMgr != NULL) {989// init adapters if we are preloading990if (AwtToolkit::GetInstance().GetPreloadThread().OnPreloadThread()) {991UINT adapterCount = pMgr->adapterCount;992993pAdapterIniters = new D3DAdapterInitializer[adapterCount];994for (UINT i=0; i<adapterCount; i++) {995pAdapterIniters[i].setAdapter(i);996AwtToolkit::GetInstance().GetPreloadThread().AddAction(&pAdapterIniters[i]);997}998}999}1000}10011002void D3DInitializer::CleanImpl(bool reInit)1003{1004J2dRlsTraceLn1(J2D_TRACE_INFO, "D3DInitializer::CleanImpl (%s)",1005reInit ? "RELAUNCH" : "normal");1006D3DPipelineManager::DeleteInstance();1007if (bComInitialized) {1008CoUninitialize();1009}1010}101110121013void D3DInitializer::D3DAdapterInitializer::InitImpl()1014{1015J2dRlsTraceLn1(J2D_TRACE_INFO, "D3DAdapterInitializer::InitImpl(%d) started", adapter);10161017D3DPipelineManager *pMgr = D3DPipelineManager::GetInstance();1018if (pMgr == NULL) {1019return;1020}10211022D3DContext *pd3dContext;1023pMgr->GetD3DContext(adapter, &pd3dContext);10241025J2dRlsTraceLn1(J2D_TRACE_INFO, "D3DAdapterInitializer::InitImpl(%d) finished", adapter);1026}10271028void D3DInitializer::D3DAdapterInitializer::CleanImpl(bool reInit)1029{1030// nothing to do - D3DPipelineManager cleans adapters1031}103210331034extern "C" {1035/*1036* Export function to start D3D preloading1037* (called from java/javaw - see src/windows/bin/java-md.c)1038*/1039__declspec(dllexport) int preloadD3D()1040{1041J2dRlsTraceLn(J2D_TRACE_INFO, "AWT warmup: preloadD3D");1042AwtToolkit::GetInstance().GetPreloadThread().AddAction(&D3DInitializer::GetInstance());1043return 1;1044}10451046}1047104810491050