HRESULT RacorX5::InitDeviceObjects() { HRESULT hr; if (m_D3DCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) { m_iVP = D3DCREATE_HARDWARE_VERTEXPROCESSING; } else { m_iVP = D3DCREATE_SOFTWARE_VERTEXPROCESSING; } hr = ConfirmDevice(&m_D3DCaps, m_iVP, D3DFMT_UNKNOWN); if (FAILED(hr)) { MessageBox(m_hWnd, L"ConfirmDevice failed!", L"Error", 0); return E_FAIL; } m_dpps.BackBufferWidth = m_iWidth; m_dpps.BackBufferHeight = m_iHeight; m_dpps.BackBufferFormat = D3DFMT_A8R8G8B8; m_dpps.BackBufferCount = 1; m_dpps.MultiSampleType = D3DMULTISAMPLE_NONE; m_dpps.SwapEffect = D3DSWAPEFFECT_DISCARD; m_dpps.hDeviceWindow = m_hWnd; m_dpps.Windowed = m_bWindowed; m_dpps.EnableAutoDepthStencil = TRUE; m_dpps.AutoDepthStencilFormat = D3DFMT_D24S8; m_dpps.Flags = 0; m_dpps.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; m_dpps.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; RestoreDeviceObjects(); return S_OK; }
HRESULT ZFXD3DEnum::EnumCombos(ZFXDEVICEINFO &xDev) { ZFXCOMBOINFO *pCombo; bool bWindowed; bool bFmtCheck=false; xDev.nNumCombo = 0; // all adapter Formats for (UINT nFmt_A=0; nFmt_A<m_nNumFmt; nFmt_A++) { // for all allowed backbuffer formats for (UINT nFmt_B=0; nFmt_B<g_nFormats_B; nFmt_B++) { // check windowed and fullscreen for (UINT n=0; n<2; n++) { if (n==0) bWindowed=true; else bWindowed=false; // valid combo? if (FAILED(m_pD3D->CheckDeviceType( xDev.nAdapter, xDev.d3dDevType, m_fmtAdapter[nFmt_A], g_fmtBackBuffer[nFmt_B], bWindowed))) continue; // at this point we have a valid combo that is supported // by the system. still need to find depth/stencil fmt // and best vertex processing type. pCombo = &xDev.d3dCombo[xDev.nNumCombo]; pCombo->nAdapter = xDev.nAdapter; pCombo->d3dDevType = xDev.d3dDevType; pCombo->bWindowed = bWindowed; pCombo->fmtBackBuffer = g_fmtBackBuffer[nFmt_B]; pCombo->fmtAdapter = m_fmtAdapter[nFmt_A]; // SELECT DEPTH/STENCIL FORMAT // select depth fmt & stencil buffer if (m_nMinStencil) { pCombo->fmtDepthStencil = D3DFMT_D24S8; bFmtCheck = ConfirmDepthFmt(pCombo); if (!bFmtCheck) { pCombo->fmtDepthStencil = D3DFMT_D24X4S4; bFmtCheck = ConfirmDepthFmt(pCombo); } if (!bFmtCheck) { pCombo->fmtDepthStencil = D3DFMT_D15S1; bFmtCheck = ConfirmDepthFmt(pCombo); } } // or without stencil buffer else { if (m_nMinDepth > 24) { pCombo->fmtDepthStencil = D3DFMT_D32; bFmtCheck = ConfirmDepthFmt(pCombo); } if (!bFmtCheck && (m_nMinDepth > 16)) { pCombo->fmtDepthStencil = D3DFMT_D24X8; bFmtCheck = ConfirmDepthFmt(pCombo); } else { pCombo->fmtDepthStencil = D3DFMT_D16; bFmtCheck = ConfirmDepthFmt(pCombo); } } // no suitable fmt => ignore this combo if (!bFmtCheck) continue; // SELECT VERTEX PROCESSING // we have hardware T&L if ((xDev.d3dCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) != 0) { // 1.case: pure device if ( ((xDev.d3dCaps.DevCaps & D3DDEVCAPS_PUREDEVICE)!=0) && (ConfirmDevice(&xDev.d3dCaps, D3DCREATE_PUREDEVICE, pCombo->fmtBackBuffer)==ZFX_OK) ) { pCombo->dwBehavior = D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE; } // 2.case: hardware device else if (ConfirmDevice(&xDev.d3dCaps, D3DCREATE_HARDWARE_VERTEXPROCESSING, pCombo->fmtBackBuffer)==ZFX_OK) { pCombo->dwBehavior = D3DCREATE_HARDWARE_VERTEXPROCESSING; } // 3.case: mixed sw/hw else if (ConfirmDevice(&xDev.d3dCaps, D3DCREATE_MIXED_VERTEXPROCESSING, pCombo->fmtBackBuffer)==ZFX_OK) { pCombo->dwBehavior = D3DCREATE_MIXED_VERTEXPROCESSING; } } // if [HW] // 4.case: must be sw processing else { if (ConfirmDevice(&xDev.d3dCaps, D3DCREATE_SOFTWARE_VERTEXPROCESSING, pCombo->fmtBackBuffer)==ZFX_OK) { pCombo->dwBehavior = D3DCREATE_SOFTWARE_VERTEXPROCESSING; } } // SELECT MULTISAMPLE TYPE DWORD msQuality; for(UINT nMS=g_nMS-1; nMS>=0; nMS--) { if (SUCCEEDED(m_pD3D-> CheckDeviceMultiSampleType( pCombo->nAdapter, pCombo->d3dDevType, pCombo->fmtBackBuffer, pCombo->bWindowed, g_msType[nMS], &msQuality))) { pCombo->msType = g_msType[nMS]; break; } } // for [multisample] // NO WE GOT EVERYTHING WE NEE AND KEEP THIS COMBO xDev.nNumCombo++; } // for [windowed/fullscreen] } // for [BackbufferFormats] } // for [AdapterFormats] return ZFX_OK; }
void BuildList(IDirect3D9* pD3D, GraphicsInfo* pGI) { if(!pD3D) { return; } const DWORD dwNumDeviceTypes = 1; const char* szDeviceDescs[] = {"HAL"}; const D3DDEVTYPE DeviceTypes[] = {D3DDEVTYPE_HAL}; const int MAXNUMDISPLAYMODES = 100; const int MAXNUMFORMATS = 30; bool bHalExists = false; bool bHalIsSampleCompatible = false; int iNumAdapters = pD3D->GetAdapterCount(); if(iNumAdapters <= 0) { return; } int iAdapter = 0; for(; iAdapter < iNumAdapters; ++iAdapter) { AdapterInfo ai; pD3D->GetAdapterIdentifier(iAdapter, 0, &ai.AdapterIdentifier); ai.dwCurrentDevice = 0; D3DDISPLAYMODE DisplayModes[MAXNUMDISPLAYMODES]; // of this adpater D3DFORMAT Formats[MAXNUMFORMATS]; // of this adpater DWORD dwNumDisplayModes = 0; // of this adpater DWORD dwNumFormats = 0; // of this adpater DWORD dwNumAdapterModes = pD3D->GetAdapterModeCount(iAdapter, 0); DWORD dwAdapterMode = 0; for(; dwAdapterMode < dwNumAdapterModes; ++dwAdapterMode) // 填充显示模式和格式的数组 { D3DDISPLAYMODE dm; pD3D->EnumAdapterModes(iAdapter, dwAdapterMode, &dm); // 只要分辨率大于等于640*480的16bits高彩(565)、24bits真彩、32bits真彩 if(dm.Width < 640 || dm.Height < 480 || (dm.Format != D3DFMT_R5G6B5 && dm.Format != D3DFMT_R8G8B8 && dm.Format != D3DFMT_A8R8G8B8)) // && dm.Format != D3DFMT_X1R5G5B5 && dm.Format != FMT_A1R5G5B5 && dm.Format != D3DFMT_R8G8B8 && dm.Format != D3DFMT_A8R8G8B8D3D) { continue; } DWORD m = 0; for(; m < dwNumDisplayModes; ++m) { if(DisplayModes[m].Width == dm.Width && DisplayModes[m].Height == dm.Height && DisplayModes[m].Format == dm.Format) { if(DisplayModes[m].RefreshRate < dm.RefreshRate) { DisplayModes[m].RefreshRate = dm.RefreshRate; } break; } } // 找到了一个新的显示模式 if(m == dwNumDisplayModes) { DisplayModes[m].Width = dm.Width; DisplayModes[m].Height = dm.Height; DisplayModes[m].Format = dm.Format; DisplayModes[m].RefreshRate = dm.RefreshRate; ++dwNumDisplayModes; DWORD f = 0; for(; f < dwNumFormats; ++f) { if(Formats[f] == dm.Format) { break; } } // 找到了一个新的格式 if(f == dwNumFormats) { Formats[dwNumFormats++] = dm.Format; } } } qsort(DisplayModes, dwNumDisplayModes, sizeof(D3DDISPLAYMODE), SortModesCallback); // We have already get all display formats wanted int iDevice = 0; for(; iDevice < dwNumDeviceTypes; ++iDevice) { DeviceInfo di; di.DeviceType = DeviceTypes[iDevice]; pD3D->GetDeviceCaps(iAdapter, DeviceTypes[iDevice], &di.Caps); di.sDesc = string(szDeviceDescs[iDevice]); di.dwCurrentMode = 0; di.MultiSampleType = D3DMULTISAMPLE_NONE; // Here is not correct! bool bFormatConfirmed[MAXNUMFORMATS]; DWORD dwBehaviors[MAXNUMFORMATS]; D3DFORMAT DepthStencilFormats[MAXNUMFORMATS]; DWORD f = 0; for(; f < dwNumFormats; ++f) // 检查格式是否合适并填充DepthStencilFormats数组 { bFormatConfirmed[f] = false; DepthStencilFormats[f] = D3DFMT_UNKNOWN; if(FAILED(pD3D->CheckDeviceType(iAdapter, di.DeviceType, Formats[f], Formats[f], NULL))) { continue; } if(di.DeviceType == D3DDEVTYPE_HAL) { bHalExists = true; } if(di.Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) { if(di.Caps.DevCaps & D3DDEVCAPS_PUREDEVICE) { dwBehaviors[f] = D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE; if(SUCCEEDED(ConfirmDevice(&di.Caps, dwBehaviors[f], Formats[f]))) { bFormatConfirmed[f] = true; } } if(!bFormatConfirmed[f]) { dwBehaviors[f] = D3DCREATE_HARDWARE_VERTEXPROCESSING; if(SUCCEEDED(ConfirmDevice(&di.Caps, dwBehaviors[f], Formats[f]))) { bFormatConfirmed[f] = true; } } if(!bFormatConfirmed[f]) { dwBehaviors[f] = D3DCREATE_MIXED_VERTEXPROCESSING; if(SUCCEEDED(ConfirmDevice(&di.Caps, dwBehaviors[f], Formats[f]))) { bFormatConfirmed[f] = true; } } } if(!bFormatConfirmed[f]) { dwBehaviors[f] = D3DCREATE_SOFTWARE_VERTEXPROCESSING; if(SUCCEEDED(ConfirmDevice(&di.Caps, dwBehaviors[f], Formats[f]))) { bFormatConfirmed[f] = true; } } if(bFormatConfirmed[f]) { if(!FindDepthStencilFormat(pD3D, pGI->m_dwDepthBits, pGI->m_dwStencilBits, iAdapter, di.DeviceType, Formats[f], &DepthStencilFormats[f])) { bFormatConfirmed[f] = false; } } } // 检查是否找到了合适的格式 for(f = 0; f < dwNumFormats; ++f) { if(bFormatConfirmed[f]) { break; } } if(f == dwNumFormats) { throw GameError("[BuildList] No valid format detected!"); } DWORD d = 0; for(; d < dwNumDisplayModes; ++d) { DWORD f = 0; for(; f < dwNumFormats; ++f) { if(DisplayModes[d].Format == Formats[f]) { if(bFormatConfirmed[f]) { ModeInfo mi; mi.Width = DisplayModes[d].Width; mi.Height = DisplayModes[d].Height; mi.Format = DisplayModes[d].Format; mi.RefreshRate = DisplayModes[d].RefreshRate; mi.dwBehavior = dwBehaviors[f]; mi.DepthStencilFormat = DepthStencilFormats[f]; di.vtModes.push_back(mi); if(di.DeviceType == D3DDEVTYPE_HAL) { bHalIsSampleCompatible = true; } } } } } bool bSizeValid = false; for(d = 0; d < di.vtModes.size(); ++d) { if(di.vtModes[d].Width >= pGI->m_dwWidth && di.vtModes[d].Height >= pGI->m_dwHeight) { di.dwCurrentMode = d; bSizeValid = true; if(di.vtModes[d].Format == D3DFMT_R5G6B5) { break; } } } if(!bSizeValid) { throw GameError("[BuildList] Default display mode for menu invalid!"); } if(di.vtModes.size() > 0) { ai.vtDevices.push_back(di); } } if(ai.vtDevices.size() > 0) { pGI->m_vtAdapters.push_back(ai); } } if(pGI->m_vtAdapters.size() <= 0) { throw GameError("[BuildList] No compatible devices!"); } }