Path: blob/master/src/java.desktop/windows/native/libawt/java2d/d3d/D3DPipelineManager.cpp
41159 views
/*1* Copyright (c) 2007, 2016, 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}174175UINT D3DPipelineManager::GetAdapterOrdinalForScreen(jint gdiScreen)176{177HMONITOR mHnd = AwtWin32GraphicsDevice::GetMonitor(gdiScreen);178if (mHnd == (HMONITOR)0) {179return D3DADAPTER_DEFAULT;180}181return GetAdapterOrdinalByHmon((HMONITOR)mHnd);182}183184// static185HRESULT D3DPipelineManager::HandleAdaptersChange(HMONITOR *pHMONITORs, UINT monNum)186{187HRESULT res = S_OK;188BOOL bResetD3D = FALSE, bFound;189190D3DPipelineManager *pMgr = D3DPipelineManager::GetInstance();191RETURN_STATUS_IF_NULL(pHMONITORs, E_FAIL);192if (pMgr == NULL) {193// NULL pMgr is valid when the pipeline is not enabled or if it hasn't194// been created yet195return S_OK;196}197RETURN_STATUS_IF_NULL(pMgr->pAdapters, E_FAIL);198RETURN_STATUS_IF_NULL(pMgr->pd3d9, E_FAIL);199200J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::HandleAdaptersChange");201202if (monNum != pMgr->adapterCount) {203J2dTraceLn2(J2D_TRACE_VERBOSE,204" number of adapters changed (old=%d, new=%d)",205pMgr->adapterCount, monNum);206bResetD3D = TRUE;207} else {208for (UINT i = 0; i < pMgr->adapterCount; i++) {209HMONITOR hMon = pMgr->pd3d9->GetAdapterMonitor(i);210if (hMon == (HMONITOR)0x0) {211J2dTraceLn1(J2D_TRACE_VERBOSE, " adapter %d: removed", i);212bResetD3D = TRUE;213break;214}215bFound = FALSE;216for (UINT mon = 0; mon < monNum; mon++) {217if (pHMONITORs[mon] == hMon) {218J2dTraceLn3(J2D_TRACE_VERBOSE,219" adapter %d: found hmnd[%d]=0x%x", i, mon, hMon);220bFound = TRUE;221break;222}223}224if (!bFound) {225J2dTraceLn2(J2D_TRACE_VERBOSE,226" adapter %d: could not find hmnd=0x%x "\227"in the list of new hmnds", i, hMon);228bResetD3D = TRUE;229break;230}231}232}233234if (bResetD3D) {235J2dTraceLn(J2D_TRACE_VERBOSE, " adapters changed: resetting d3d");236pMgr->ReleaseD3D();237res = pMgr->InitD3D();238}239return res;240}241242HRESULT D3DPipelineManager::HandleLostDevices()243{244J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::HandleLostDevices()");245BOOL bAllClear = TRUE;246247HWND hwnd = GetCurrentFocusWindow();248if (hwnd != defaultFocusWindow) {249// we're in full-screen mode250WINDOWPLACEMENT wp;251::ZeroMemory(&wp, sizeof(WINDOWPLACEMENT));252wp.length = sizeof(WINDOWPLACEMENT);253::GetWindowPlacement(hwnd, &wp);254255// Only attempt to restore the devices if we're in full-screen mode256// and the fs window is active; sleep otherwise.257// Restoring a window while minimized causes problems on Vista:258// sometimes we restore the window too quickly and it pops up back from259// minimized state when the device is restored.260//261// WARNING: this is a sleep on the Toolkit thread! We may reconsider262// this if we find any issues later.263if ((wp.showCmd & SW_SHOWMINNOACTIVE) && !(wp.showCmd & SW_SHOWNORMAL)){264static DWORD prevCallTime = 0;265J2dTraceLn(J2D_TRACE_VERBOSE, " fs focus window is minimized");266DWORD currentTime = ::GetTickCount();267if ((currentTime - prevCallTime) < 100) {268J2dTraceLn(J2D_TRACE_VERBOSE, " tight loop detected, sleep");269::Sleep(100);270}271prevCallTime = currentTime;272return D3DERR_DEVICELOST;273}274}275if (pAdapters != NULL) {276for (UINT i = 0; i < adapterCount; i++) {277if (pAdapters[i].pd3dContext != NULL) {278J2dTraceLn1(J2D_TRACE_VERBOSE,279" HandleLostDevices: checking adapter %d", i);280D3DContext *d3dc = pAdapters[i].pd3dContext;281if (FAILED(d3dc->CheckAndResetDevice())) {282bAllClear = FALSE;283}284}285}286}287return bAllClear ? S_OK : D3DERR_DEVICELOST;288}289290HRESULT D3DPipelineManager::InitAdapters()291{292HRESULT res = E_FAIL;293294J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::InitAdapters()");295if (pAdapters != NULL) {296ReleaseAdapters();297}298299adapterCount = pd3d9->GetAdapterCount();300pAdapters = new D3DAdapter[adapterCount];301if (pAdapters == NULL) {302J2dRlsTraceLn(J2D_TRACE_ERROR, "InitAdapters: out of memory");303adapterCount = 0;304return E_FAIL;305}306ZeroMemory(pAdapters, adapterCount * sizeof(D3DAdapter));307308res = CheckAdaptersInfo();309RETURN_STATUS_IF_FAILED(res);310311currentFSFocusAdapter = -1;312if (CreateDefaultFocusWindow() == 0) {313return E_FAIL;314}315316return S_OK;317}318319// static320HRESULT321D3DPipelineManager::CheckOSVersion()322{323// require Windows XP or newer client-class OS324if (IS_WINVER_ATLEAST(5, 1) &&325!D3DPPLM_OsVersionMatches(OS_WINSERV_2008R2|OS_WINSERV_2008|326OS_WINSERV_2003))327{328J2dTraceLn(J2D_TRACE_INFO,329"D3DPPLM::CheckOSVersion: Windows XP or newer client-classs"\330" OS detected, passed");331return S_OK;332}333J2dRlsTraceLn(J2D_TRACE_ERROR,334"D3DPPLM::CheckOSVersion: Windows 2000 or earlier (or a "\335"server) OS detected, failed");336if (bNoHwCheck) {337J2dRlsTraceLn(J2D_TRACE_WARNING,338" OS check overridden via J2D_D3D_NO_HWCHECK");339return S_OK;340}341return E_FAIL;342}343344// static345HRESULT346D3DPipelineManager::GDICheckForBadHardware()347{348DISPLAY_DEVICE dd;349dd.cb = sizeof(DISPLAY_DEVICE);350351int failedDevices = 0;352int attachedDevices = 0;353int i = 0;354WCHAR *id;355WCHAR vendorId[5];356WCHAR deviceId[5];357DWORD dwDId, dwVId;358359J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::GDICheckForBadHardware");360361// i<20 is to guard against buggy drivers362while (EnumDisplayDevices(NULL, i, &dd, 0) && i < 20) {363if (dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) {364attachedDevices++;365id = dd.DeviceID;366if (wcslen(id) > 21) {367// get vendor ID368wcsncpy(vendorId, id+8, 4);369int args1 = swscanf(vendorId, L"%X", &dwVId);370371// get device ID372wcsncpy(deviceId, id+17, 4);373int args2 = swscanf(deviceId, L"%X", &dwDId);374375if (args1 == 1 && args2 == 1) {376J2dTraceLn2(J2D_TRACE_VERBOSE,377" device: vendorID=0x%04x, deviceId=0x%04x",378dwVId, dwDId);379// since we don't have a driver version here we will380// just ask to ignore the version for now; bad hw381// entries with specific drivers information will be382// processed later when d3d is initialized and we can383// obtain a driver version384if (FAILED(CheckForBadHardware(dwVId, dwDId, MAX_VERSION))){385failedDevices++;386}387}388}389}390391i++;392}393394if (failedDevices == attachedDevices) {395J2dRlsTraceLn(J2D_TRACE_ERROR,396"D3DPPLM::GDICheckForBadHardware: no suitable devices found");397return E_FAIL;398}399400return S_OK;401}402403BOOL D3DPPLM_OsVersionMatches(USHORT osInfo) {404static USHORT currentOS = OS_UNDEFINED;405406if (currentOS == OS_UNDEFINED) {407BOOL bVersOk;408OSVERSIONINFOEX osvi;409410ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));411osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);412413bVersOk = GetVersionEx((OSVERSIONINFO *) &osvi);414415J2dRlsTrace(J2D_TRACE_INFO, "[I] OS Version = ");416if (bVersOk && osvi.dwPlatformId == VER_PLATFORM_WIN32_NT &&417osvi.dwMajorVersion > 4)418{419if (osvi.dwMajorVersion >= 6 && osvi.dwMinorVersion == 0) {420if (osvi.wProductType == VER_NT_WORKSTATION) {421J2dRlsTrace(J2D_TRACE_INFO, "OS_VISTA\n");422currentOS = OS_VISTA;423} else {424J2dRlsTrace(J2D_TRACE_INFO, "OS_WINSERV_2008\n");425currentOS = OS_WINSERV_2008;426}427} else if (osvi.dwMajorVersion >= 6 && osvi.dwMinorVersion >= 1) {428if (osvi.wProductType == VER_NT_WORKSTATION) {429J2dRlsTrace(J2D_TRACE_INFO, "OS_WINDOWS7 or newer\n");430currentOS = OS_WINDOWS7;431} else {432J2dRlsTrace(J2D_TRACE_INFO, "OS_WINSERV_2008R2 or newer\n");433currentOS = OS_WINSERV_2008R2;434}435} else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) {436if (osvi.wProductType == VER_NT_WORKSTATION) {437J2dRlsTrace(J2D_TRACE_INFO, "OS_WINXP_64\n");438currentOS = OS_WINXP_64;439} else {440J2dRlsTrace(J2D_TRACE_INFO, "OS_WINSERV_2003\n");441currentOS = OS_WINSERV_2003;442}443} else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) {444J2dRlsTrace(J2D_TRACE_INFO, "OS_WINXP ");445currentOS = OS_WINXP;446if (osvi.wSuiteMask & VER_SUITE_PERSONAL) {447J2dRlsTrace(J2D_TRACE_INFO, "Home\n");448} else {449J2dRlsTrace(J2D_TRACE_INFO, "Pro\n");450}451} else {452J2dRlsTrace2(J2D_TRACE_INFO,453"OS_UNKNOWN: dwMajorVersion=%d dwMinorVersion=%d\n",454osvi.dwMajorVersion, osvi.dwMinorVersion);455currentOS = OS_UNKNOWN;456}457} else {458if (bVersOk) {459J2dRlsTrace2(J2D_TRACE_INFO,460"OS_UNKNOWN: dwPlatformId=%d dwMajorVersion=%d\n",461osvi.dwPlatformId, osvi.dwMajorVersion);462} else {463J2dRlsTrace(J2D_TRACE_INFO,"OS_UNKNOWN: GetVersionEx failed\n");464}465currentOS = OS_UNKNOWN;466}467}468return (currentOS & osInfo);469}470471// static472HRESULT473D3DPipelineManager::CheckForBadHardware(DWORD vId, DWORD dId, LONGLONG version)474{475DWORD vendorId, deviceId;476UINT adapterInfo = 0;477478J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::CheckForBadHardware");479480while ((vendorId = badHardware[adapterInfo].VendorId) != 0x0000 &&481(deviceId = badHardware[adapterInfo].DeviceId) != 0x0000)482{483if (vendorId == vId && (deviceId == dId || deviceId == ALL_DEVICEIDS)) {484LONGLONG goodVersion = badHardware[adapterInfo].DriverVersion;485USHORT osInfo = badHardware[adapterInfo].OsInfo;486// the hardware check fails if:487// - we have an entry for this OS and488// - hardware is bad for all driver versions (NO_VERSION), or489// we have a driver version which is older than the490// minimum required for this OS491if (D3DPPLM_OsVersionMatches(osInfo) &&492(goodVersion == NO_VERSION || version < goodVersion))493{494J2dRlsTraceLn2(J2D_TRACE_ERROR,495"D3DPPLM::CheckForBadHardware: found matching "\496"hardware: VendorId=0x%04x DeviceId=0x%04x",497vendorId, deviceId);498if (goodVersion != NO_VERSION) {499// this was a match by the driver version500LARGE_INTEGER li;501li.QuadPart = goodVersion;502J2dRlsTraceLn(J2D_TRACE_ERROR,503" bad driver found, device disabled");504J2dRlsTraceLn4(J2D_TRACE_ERROR,505" update your driver to at "\506"least version %d.%d.%d.%d",507HIWORD(li.HighPart), LOWORD(li.HighPart),508HIWORD(li.LowPart), LOWORD(li.LowPart));509} else {510// this was a match by the device (no good driver for this511// device)512J2dRlsTraceLn(J2D_TRACE_ERROR,513"D3DPPLM::CheckForBadHardware: bad hardware "\514"found, device disabled");515}516if (!bNoHwCheck) {517return D3DERR_INVALIDDEVICE;518}519J2dRlsTraceLn(J2D_TRACE_WARNING, " Warning: hw/driver match "\520"overridden (via J2D_D3D_NO_HWCHECK)");521}522}523adapterInfo++;524}525526return S_OK;527}528529HRESULT D3DPipelineManager::CheckAdaptersInfo()530{531D3DADAPTER_IDENTIFIER9 aid;532UINT failedAdaptersCount = 0;533534J2dRlsTraceLn(J2D_TRACE_INFO, "CheckAdaptersInfo");535J2dRlsTraceLn(J2D_TRACE_INFO, "------------------");536for (UINT Adapter = 0; Adapter < adapterCount; Adapter++) {537538if (FAILED(pd3d9->GetAdapterIdentifier(Adapter, 0, &aid))) {539pAdapters[Adapter].state = CONTEXT_INIT_FAILED;540failedAdaptersCount++;541continue;542}543544J2dRlsTraceLn1(J2D_TRACE_INFO, "Adapter Ordinal : %d", Adapter);545J2dRlsTraceLn1(J2D_TRACE_INFO, "Adapter Handle : 0x%x",546pd3d9->GetAdapterMonitor(Adapter));547J2dRlsTraceLn1(J2D_TRACE_INFO, "Description : %s",548aid.Description);549J2dRlsTraceLn2(J2D_TRACE_INFO, "GDI Name, Driver : %s, %s",550aid.DeviceName, aid.Driver);551J2dRlsTraceLn1(J2D_TRACE_INFO, "Vendor Id : 0x%04x",552aid.VendorId);553J2dRlsTraceLn1(J2D_TRACE_INFO, "Device Id : 0x%04x",554aid.DeviceId);555J2dRlsTraceLn1(J2D_TRACE_INFO, "SubSys Id : 0x%x",556aid.SubSysId);557J2dRlsTraceLn4(J2D_TRACE_INFO, "Driver Version : %d.%d.%d.%d",558HIWORD(aid.DriverVersion.HighPart),559LOWORD(aid.DriverVersion.HighPart),560HIWORD(aid.DriverVersion.LowPart),561LOWORD(aid.DriverVersion.LowPart));562J2dRlsTrace3(J2D_TRACE_INFO,563"[I] GUID : {%08X-%04X-%04X-",564aid.DeviceIdentifier.Data1,565aid.DeviceIdentifier.Data2,566aid.DeviceIdentifier.Data3);567J2dRlsTrace4(J2D_TRACE_INFO, "%02X%02X-%02X%02X",568aid.DeviceIdentifier.Data4[0],569aid.DeviceIdentifier.Data4[1],570aid.DeviceIdentifier.Data4[2],571aid.DeviceIdentifier.Data4[3]);572J2dRlsTrace4(J2D_TRACE_INFO, "%02X%02X%02X%02X}\n",573aid.DeviceIdentifier.Data4[4],574aid.DeviceIdentifier.Data4[5],575aid.DeviceIdentifier.Data4[6],576aid.DeviceIdentifier.Data4[7]);577578if (FAILED(CheckForBadHardware(aid.VendorId, aid.DeviceId,579aid.DriverVersion.QuadPart)) ||580FAILED(CheckDeviceCaps(Adapter)) ||581FAILED(D3DEnabledOnAdapter(Adapter)))582{583pAdapters[Adapter].state = CONTEXT_INIT_FAILED;584failedAdaptersCount++;585}586J2dRlsTraceLn(J2D_TRACE_INFO, "------------------");587}588589if (failedAdaptersCount == adapterCount) {590J2dRlsTraceLn(J2D_TRACE_ERROR,591"D3DPPLM::CheckAdaptersInfo: no suitable adapters found");592return E_FAIL;593}594595return S_OK;596}597598D3DDEVTYPE D3DPipelineManager::SelectDeviceType()599{600char *pRas = getenv("J2D_D3D_RASTERIZER");601D3DDEVTYPE dtype = D3DDEVTYPE_HAL;602if (pRas != NULL) {603J2dRlsTrace(J2D_TRACE_WARNING, "[W] D3DPPLM::SelectDeviceType: ");604if (strncmp(pRas, "ref", 3) == 0 || strncmp(pRas, "rgb", 3) == 0) {605J2dRlsTrace(J2D_TRACE_WARNING, "ref rasterizer selected");606dtype = D3DDEVTYPE_REF;607} else if (strncmp(pRas, "hal",3) == 0 || strncmp(pRas, "tnl",3) == 0) {608J2dRlsTrace(J2D_TRACE_WARNING, "hal rasterizer selected");609dtype = D3DDEVTYPE_HAL;610} else if (strncmp(pRas, "nul", 3) == 0) {611J2dRlsTrace(J2D_TRACE_WARNING, "nullref rasterizer selected");612dtype = D3DDEVTYPE_NULLREF;613} else {614J2dRlsTrace1(J2D_TRACE_WARNING,615"unknown rasterizer: %s, only (ref|hal|nul) "\616"supported, hal selected instead", pRas);617}618J2dRlsTrace(J2D_TRACE_WARNING, "\n");619}620return dtype;621}622623#define CHECK_CAP(FLAG, CAP) \624do { \625if (!((FLAG)&CAP)) { \626J2dRlsTraceLn2(J2D_TRACE_ERROR, \627"D3DPPLM::CheckDeviceCaps: adapter %d: Failed "\628"(cap %s not supported)", \629adapter, #CAP); \630return E_FAIL; \631} \632} while (0)633634HRESULT D3DPipelineManager::CheckDeviceCaps(UINT adapter)635{636HRESULT res;637D3DCAPS9 d3dCaps;638639J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::CheckDeviceCaps");640641res = pd3d9->GetDeviceCaps(adapter, devType, &d3dCaps);642RETURN_STATUS_IF_FAILED(res);643644CHECK_CAP(d3dCaps.DevCaps, D3DDEVCAPS_DRAWPRIMTLVERTEX);645646// by requiring hardware tnl we are hoping for better drivers quality647if (!IsD3DForced()) {648// fail if not hw tnl unless d3d was forced649CHECK_CAP(d3dCaps.DevCaps, D3DDEVCAPS_HWTRANSFORMANDLIGHT);650}651if (d3dCaps.DeviceType == D3DDEVTYPE_HAL) {652CHECK_CAP(d3dCaps.DevCaps, D3DDEVCAPS_HWRASTERIZATION);653}654655CHECK_CAP(d3dCaps.RasterCaps, D3DPRASTERCAPS_SCISSORTEST);656657CHECK_CAP(d3dCaps.Caps3, D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD);658659CHECK_CAP(d3dCaps.PrimitiveMiscCaps, D3DPMISCCAPS_CULLNONE);660CHECK_CAP(d3dCaps.PrimitiveMiscCaps, D3DPMISCCAPS_BLENDOP);661CHECK_CAP(d3dCaps.PrimitiveMiscCaps, D3DPMISCCAPS_MASKZ);662663CHECK_CAP(d3dCaps.ZCmpCaps, D3DPCMPCAPS_ALWAYS);664CHECK_CAP(d3dCaps.ZCmpCaps, D3DPCMPCAPS_LESS);665666CHECK_CAP(d3dCaps.SrcBlendCaps, D3DPBLENDCAPS_ZERO);667CHECK_CAP(d3dCaps.SrcBlendCaps, D3DPBLENDCAPS_ONE);668CHECK_CAP(d3dCaps.SrcBlendCaps, D3DPBLENDCAPS_SRCALPHA);669CHECK_CAP(d3dCaps.SrcBlendCaps, D3DPBLENDCAPS_DESTALPHA);670CHECK_CAP(d3dCaps.SrcBlendCaps, D3DPBLENDCAPS_INVSRCALPHA);671CHECK_CAP(d3dCaps.SrcBlendCaps, D3DPBLENDCAPS_INVDESTALPHA);672673CHECK_CAP(d3dCaps.DestBlendCaps, D3DPBLENDCAPS_ZERO);674CHECK_CAP(d3dCaps.DestBlendCaps, D3DPBLENDCAPS_ONE);675CHECK_CAP(d3dCaps.DestBlendCaps, D3DPBLENDCAPS_SRCALPHA);676CHECK_CAP(d3dCaps.DestBlendCaps, D3DPBLENDCAPS_DESTALPHA);677CHECK_CAP(d3dCaps.DestBlendCaps, D3DPBLENDCAPS_INVSRCALPHA);678CHECK_CAP(d3dCaps.DestBlendCaps, D3DPBLENDCAPS_INVDESTALPHA);679680CHECK_CAP(d3dCaps.TextureAddressCaps, D3DPTADDRESSCAPS_CLAMP);681CHECK_CAP(d3dCaps.TextureAddressCaps, D3DPTADDRESSCAPS_WRAP);682683CHECK_CAP(d3dCaps.TextureOpCaps, D3DTEXOPCAPS_MODULATE);684685if (d3dCaps.PixelShaderVersion < D3DPS_VERSION(2,0) && !IsD3DForced()) {686J2dRlsTraceLn1(J2D_TRACE_ERROR,687"D3DPPLM::CheckDeviceCaps: adapter %d: Failed "\688"(pixel shaders 2.0 required)", adapter);689return E_FAIL;690}691692J2dRlsTraceLn1(J2D_TRACE_INFO,693"D3DPPLM::CheckDeviceCaps: adapter %d: Passed", adapter);694return S_OK;695}696697698HRESULT D3DPipelineManager::D3DEnabledOnAdapter(UINT adapter)699{700HRESULT res;701D3DDISPLAYMODE dm;702703res = pd3d9->GetAdapterDisplayMode(adapter, &dm);704RETURN_STATUS_IF_FAILED(res);705706res = pd3d9->CheckDeviceType(adapter, devType, dm.Format, dm.Format, TRUE);707if (FAILED(res)) {708J2dRlsTraceLn1(J2D_TRACE_ERROR,709"D3DPPLM::D3DEnabledOnAdapter: no " \710"suitable d3d device on adapter %d", adapter);711}712713return res;714}715716UINT D3DPipelineManager::GetAdapterOrdinalByHmon(HMONITOR hMon)717{718UINT ret = D3DADAPTER_DEFAULT;719720if (pd3d9 != NULL) {721UINT adapterCount = pd3d9->GetAdapterCount();722for (UINT adapter = 0; adapter < adapterCount; adapter++) {723HMONITOR hm = pd3d9->GetAdapterMonitor(adapter);724if (hm == hMon) {725ret = adapter;726break;727}728}729}730return ret;731}732733D3DFORMAT734D3DPipelineManager::GetMatchingDepthStencilFormat(UINT adapterOrdinal,735D3DFORMAT adapterFormat,736D3DFORMAT renderTargetFormat)737{738static D3DFORMAT formats[] =739{ D3DFMT_D16, D3DFMT_D32, D3DFMT_D24S8, D3DFMT_D24X8 };740D3DFORMAT newFormat = D3DFMT_UNKNOWN;741HRESULT res;742for (int i = 0; i < 4; i++) {743res = pd3d9->CheckDeviceFormat(adapterOrdinal,744devType, adapterFormat, D3DUSAGE_DEPTHSTENCIL,745D3DRTYPE_SURFACE, formats[i]);746if (FAILED(res)) continue;747748res = pd3d9->CheckDepthStencilMatch(adapterOrdinal,749devType, adapterFormat, renderTargetFormat, formats[i]);750if (FAILED(res)) continue;751newFormat = formats[i];752break;753}754return newFormat;755}756757HWND D3DPipelineManager::CreateDefaultFocusWindow()758{759UINT adapterOrdinal = D3DADAPTER_DEFAULT;760761J2dTraceLn1(J2D_TRACE_INFO,762"D3DPPLM::CreateDefaultFocusWindow: adapter=%d",763adapterOrdinal);764765if (defaultFocusWindow != 0) {766J2dRlsTraceLn(J2D_TRACE_WARNING,767"D3DPPLM::CreateDefaultFocusWindow: "\768"existing default focus window!");769return defaultFocusWindow;770}771772WNDCLASS wc;773ZeroMemory(&wc, sizeof(WNDCLASS));774wc.hInstance = GetModuleHandle(NULL);775wc.lpfnWndProc = DefWindowProc;776wc.lpszClassName = L"D3DFocusWindow";777if (RegisterClass(&wc) == 0) {778J2dRlsTraceLn(J2D_TRACE_ERROR,779"D3DPPLM::CreateDefaultFocusWindow: "\780"error registering window class");781return 0;782}783784MONITORINFO mi;785ZeroMemory(&mi, sizeof(MONITORINFO));786mi.cbSize = sizeof(MONITORINFO);787HMONITOR hMon = pd3d9->GetAdapterMonitor(adapterOrdinal);788if (hMon == 0 || !GetMonitorInfo(hMon, (LPMONITORINFO)&mi)) {789J2dRlsTraceLn1(J2D_TRACE_ERROR,790"D3DPPLM::CreateDefaultFocusWindow: "\791"error getting monitor info for adapter=%d", adapterOrdinal);792return 0;793}794795HWND hWnd = CreateWindow(L"D3DFocusWindow", L"D3DFocusWindow", WS_POPUP,796mi.rcMonitor.left, mi.rcMonitor.top, 1, 1,797NULL, NULL, GetModuleHandle(NULL), NULL);798if (hWnd == 0) {799J2dRlsTraceLn(J2D_TRACE_ERROR,800"D3DPPLM::CreateDefaultFocusWindow: CreateWindow failed");801} else {802J2dTraceLn2(J2D_TRACE_INFO,803" Created default focus window %x for adapter %d",804hWnd, adapterOrdinal);805defaultFocusWindow = hWnd;806}807return hWnd;808}809810HWND D3DPipelineManager::GetCurrentFocusWindow()811{812J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::GetCurrentFocusWindow");813if (currentFSFocusAdapter < 0) {814J2dTraceLn1(J2D_TRACE_VERBOSE,815" no fs windows, using default focus window=0x%x",816defaultFocusWindow);817return defaultFocusWindow;818}819J2dTraceLn1(J2D_TRACE_VERBOSE, " using fs window=0x%x",820pAdapters[currentFSFocusAdapter].fsFocusWindow);821return pAdapters[currentFSFocusAdapter].fsFocusWindow;822}823824HWND D3DPipelineManager::SetFSFocusWindow(UINT adapterOrdinal, HWND hWnd)825{826J2dTraceLn2(J2D_TRACE_INFO,"D3DPPLM::SetFSFocusWindow hwnd=0x%x adapter=%d",827hWnd, adapterOrdinal);828829HWND prev = pAdapters[adapterOrdinal].fsFocusWindow;830pAdapters[adapterOrdinal].fsFocusWindow = hWnd;831if (currentFSFocusAdapter < 0) {832J2dTraceLn(J2D_TRACE_VERBOSE, " first full-screen window");833// first fs window834currentFSFocusAdapter = adapterOrdinal;835// REMIND: we might want to reset the rest of the context here as well836// like we do when the an adapter exits fs mode; currently they will837// be reset sometime later838} else {839// there's already a fs window840if (currentFSFocusAdapter == adapterOrdinal) {841// it's current fs window => we're exiting fs mode on this adapter;842// look for a new fs focus window843if (hWnd == 0) {844UINT i;845currentFSFocusAdapter = -1;846for (i = 0; i < adapterCount; i++) {847if (pAdapters[i].fsFocusWindow != 0) {848J2dTraceLn1(J2D_TRACE_VERBOSE,849" adapter %d is still in fs mode", i);850currentFSFocusAdapter = i;851break;852}853}854// we have to reset all devices any time current focus device855// exits fs mode, and also to prevent some of them being left in856// a lost state when the last device exits fs - when non-last857// adapters exit fs mode they would not be able to create the858// device and will be put in a lost state forever859HRESULT res;860J2dTraceLn(J2D_TRACE_VERBOSE,861" adapter exited full-screen, reset all adapters");862for (i = 0; i < adapterCount; i++) {863if (pAdapters[i].pd3dContext != NULL) {864res = pAdapters[i].pd3dContext->ResetContext();865D3DRQ_MarkLostIfNeeded(res,866D3DRQ_GetCurrentDestination());867}868}869} else {870J2dTraceLn1(J2D_TRACE_WARNING,871"D3DPM::SetFSFocusWindow: setting the fs "\872"window again for adapter %d", adapterOrdinal);873}874}875}876return prev;877}878879HRESULT D3DPipelineManager::GetD3DContext(UINT adapterOrdinal,880D3DContext **ppd3dContext)881{882J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::GetD3DContext");883884HRESULT res = S_OK;885if (adapterOrdinal < 0 || adapterOrdinal >= adapterCount ||886pAdapters == NULL ||887pAdapters[adapterOrdinal].state == CONTEXT_INIT_FAILED)888{889J2dRlsTraceLn1(J2D_TRACE_ERROR,890"D3DPPLM::GetD3DContext: invalid parameters or "\891"failed init for adapter %d", adapterOrdinal);892*ppd3dContext = NULL;893return E_FAIL;894}895896if (pAdapters[adapterOrdinal].state == CONTEXT_NOT_INITED) {897D3DContext *pCtx = NULL;898899if (pAdapters[adapterOrdinal].pd3dContext != NULL) {900J2dTraceLn1(J2D_TRACE_ERROR, " non-null context in "\901"uninitialized adapter %d", adapterOrdinal);902res = E_FAIL;903} else {904J2dTraceLn1(J2D_TRACE_VERBOSE,905" initializing context for adapter %d",adapterOrdinal);906907if (SUCCEEDED(res = D3DEnabledOnAdapter(adapterOrdinal))) {908res = D3DContext::CreateInstance(pd3d9, adapterOrdinal, &pCtx);909if (FAILED(res)) {910J2dRlsTraceLn1(J2D_TRACE_ERROR,911"D3DPPLM::GetD3DContext: failed to create context "\912"for adapter=%d", adapterOrdinal);913}914} else {915J2dRlsTraceLn1(J2D_TRACE_ERROR,916"D3DPPLM::GetContext: no d3d on adapter %d",adapterOrdinal);917}918}919pAdapters[adapterOrdinal].state =920SUCCEEDED(res) ? CONTEXT_CREATED : CONTEXT_INIT_FAILED;921pAdapters[adapterOrdinal].pd3dContext = pCtx;922}923*ppd3dContext = pAdapters[adapterOrdinal].pd3dContext;924return res;925}926927928//==============================================================929// D3DInitializer930//==============================================================931932D3DInitializer D3DInitializer::theInstance;933934D3DInitializer::D3DInitializer()935: bComInitialized(false), pAdapterIniters(NULL)936{937}938939D3DInitializer::~D3DInitializer()940{941if (pAdapterIniters) {942delete[] pAdapterIniters;943}944}945946void D3DInitializer::InitImpl()947{948J2dRlsTraceLn(J2D_TRACE_INFO, "D3DInitializer::InitImpl");949if (SUCCEEDED(::CoInitialize(NULL))) {950bComInitialized = true;951}952D3DPipelineManager *pMgr = D3DPipelineManager::CreateInstance();953if (pMgr != NULL) {954// init adapters if we are preloading955if (AwtToolkit::GetInstance().GetPreloadThread().OnPreloadThread()) {956UINT adapterCount = pMgr->adapterCount;957958pAdapterIniters = new D3DAdapterInitializer[adapterCount];959for (UINT i=0; i<adapterCount; i++) {960pAdapterIniters[i].setAdapter(i);961AwtToolkit::GetInstance().GetPreloadThread().AddAction(&pAdapterIniters[i]);962}963}964}965}966967void D3DInitializer::CleanImpl(bool reInit)968{969J2dRlsTraceLn1(J2D_TRACE_INFO, "D3DInitializer::CleanImpl (%s)",970reInit ? "RELAUNCH" : "normal");971D3DPipelineManager::DeleteInstance();972if (bComInitialized) {973CoUninitialize();974}975}976977978void D3DInitializer::D3DAdapterInitializer::InitImpl()979{980J2dRlsTraceLn1(J2D_TRACE_INFO, "D3DAdapterInitializer::InitImpl(%d) started", adapter);981982D3DPipelineManager *pMgr = D3DPipelineManager::GetInstance();983if (pMgr == NULL) {984return;985}986987D3DContext *pd3dContext;988pMgr->GetD3DContext(adapter, &pd3dContext);989990J2dRlsTraceLn1(J2D_TRACE_INFO, "D3DAdapterInitializer::InitImpl(%d) finished", adapter);991}992993void D3DInitializer::D3DAdapterInitializer::CleanImpl(bool reInit)994{995// nothing to do - D3DPipelineManager cleans adapters996}997998999extern "C" {1000/*1001* Export function to start D3D preloading1002* (called from java/javaw - see src/windows/bin/java-md.c)1003*/1004__declspec(dllexport) int preloadD3D()1005{1006J2dRlsTraceLn(J2D_TRACE_INFO, "AWT warmup: preloadD3D");1007AwtToolkit::GetInstance().GetPreloadThread().AddAction(&D3DInitializer::GetInstance());1008return 1;1009}10101011}1012101310141015