// EnumD3D.cpp: implementation of the CEnumD3D class. // ////////////////////////////////////////////////////////////////////// #include "EnumD3D.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// D3DAdapterInfo CEnumD3D::m_Adapters[10]; DWORD CEnumD3D::m_dwNumAdapters; DWORD CEnumD3D::m_dwAdapter; BOOL CEnumD3D::m_bWindowed; LPDIRECT3D8 CEnumD3D::m_pD3D; BOOL CEnumD3D::m_bUseDepthBuffer; long CEnumD3D::m_dwMinDepthBits; long CEnumD3D::m_dwMinStencilBits; long CEnumD3D::m_nAdapter; long CEnumD3D::m_nDevice; long CEnumD3D::m_nMode; int SortModesCallback( const VOID* arg1, const VOID* arg2 ) { D3DDISPLAYMODE* p1 = (D3DDISPLAYMODE*)arg1; D3DDISPLAYMODE* p2 = (D3DDISPLAYMODE*)arg2; if( p1->Format > p2->Format ) return -1; if( p1->Format < p2->Format ) return +1; if( p1->Width < p2->Width ) return -1; if( p1->Width > p2->Width ) return +1; if( p1->Height < p2->Height ) return -1; if( p1->Height > p2->Height ) return +1; return 0; } CEnumD3D::CEnumD3D() { m_bUseDepthBuffer=true; m_nAdapter=m_nDevice=m_nMode=0; } CEnumD3D::~CEnumD3D() { } HRESULT CEnumD3D::Enum() { /* const TCHAR* strDeviceDescs[] = { "HAL", "REF" }; const D3DDEVTYPE DeviceTypes[] = { D3DDEVTYPE_HAL, D3DDEVTYPE_REF }; LPDIRECT3D8 pd3d=Direct3DCreate8(D3D_SDK_VERSION); List m_AdapterInfo; const int cDeviceTypes=2; for(int cAdapter=0;cAdapterGetAdapterCount();cAdapter++) { D3DAdapterInfo AddAdapter; pd3d->GetAdapterIdentifier(cAdapter,0,&AddAdapter.d3dAdapterIdentifier); pd3d->GetAdapterDisplayMode(cAdapter,&AddAdapter.d3ddmDesktop); AddAdapter.dwCurrentDevice=0; AddAdapter.dwNumDevices=0; List ModeList; List PixelFormatList; int cTotalMode=pd3d->GetAdapterModeCount(cAdapter); for(int cMode=0;cModeEnumAdapterModes(cAdapter,cMode,&DisplayMode); if(DisplayMode.Width < 640 || DisplayMode.Height<400) continue; for(int cAlreadyMode=0;cAlreadyModeGetDeviceCaps(cAdapter,DeviceTypes[cDevice],&AddDevice.d3dCaps); AddDevice.strDesc=strDeviceDescs[cDevice]; AddDevice.dwNumModes=0; AddDevice.dwCurrentMode=0; AddDevice.bCanDoWindowed=FALSE; AddDevice.bWindowed=FALSE; AddDevice.MultiSampleType=D3DMULTISAMPLE_NONE; BOOL bFormatConfirmed[20]; DWORD dwBehavior[20]; D3DFORMAT fmtDepthStencil[20]; for(int cFormat=0;cFormatCheckDeviceType( cAdapter, AddDevice.DeviceType,PixelFormatList[cFormat],PixelFormatList[cFormat],FALSE))) { continue; } if(AddDevice.DeviceType=D3DDEVTYPE_HAL) { // 3D Ä«µå´Â ´Þ·ÁÀÖ°í// } if( AddDevice.d3dCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) { if( AddDevice.d3dCaps.DevCaps & D3DDEVCAPS_PUREDEVICE) { dwBehavior[cFormat]=D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE; // Confirmed is true when ConfirmDevice's Return value Succeeded// bFormatConfirmed[cFormat]=TRUE; } if(bFormatConfirmed[cFormat]==FALSE) { dwBehavior[cFormat]=D3DCREATE_HARDWARE_VERTEXPROCESSING; // Confirmed is true when ConfirmDevice's Return value Succeeded// bFormatConfirmed[cFormat]=TRUE; } if(bFormatConfirmed[cFormat]==FALSE) { dwBehavior[cFormat]=D3DCREATE_MIXED_VERTEXPROCESSING; // Confirmed is true when ConfirmDevice's Return value Succeeded// bFormatConfirmed[cFormat]=TRUE; } } if(bFormatConfirmed[cFormat]==FALSE) { dwBehavior[cFormat]=D3DCREATE_SOFTWARE_VERTEXPROCESSING; // Confirmed is true when ConfirmDevice's Return value Succeeded// bFormatConfirmed[cFormat]=TRUE; } if( bFormatConfirmed[cFormat] && m_bUseDepthBuffer) { if(!FindDepthStencilFormat(cAdapter,AddDevice.DeviceType,PixelFormatList[cFormat],&fmtDepthStencil[cFormat])) { bFormatConfirmed[cFormat]=FALSE; } } } for(int cMode=0;cMode 0 ) AddAdapter.dwNumDevices++; } m_AdapterInfo.Add(AddAdapter); } return S_OK; */ m_pD3D=Direct3DCreate8(D3D_SDK_VERSION); const DWORD dwNumDeviceTypes = 2; const TCHAR* strDeviceDescs[] = { "HAL", "REF" }; const D3DDEVTYPE DeviceTypes[] = { D3DDEVTYPE_HAL, D3DDEVTYPE_REF }; BOOL bHALExists = FALSE; BOOL bHALIsWindowedCompatible = FALSE; BOOL bHALIsDesktopCompatible = FALSE; BOOL bHALIsSampleCompatible = FALSE; // Loop through all the adapters on the system (usually, there's just one // unless more than one graphics card is present). m_dwNumAdapters=0; for( UINT iAdapter = 0; iAdapter < m_pD3D->GetAdapterCount(); iAdapter++ ) { // Fill in adapter info D3DAdapterInfo* pAdapter = &m_Adapters[m_dwNumAdapters]; m_pD3D->GetAdapterIdentifier( iAdapter, 0, &pAdapter->d3dAdapterIdentifier ); m_pD3D->GetAdapterDisplayMode( iAdapter, &pAdapter->d3ddmDesktop ); pAdapter->dwNumDevices = 0; pAdapter->dwCurrentDevice = 0; // Enumerate all display modes on this adapter D3DDISPLAYMODE modes[100]; D3DFORMAT formats[20]; DWORD dwNumFormats = 0; DWORD dwNumModes = 0; DWORD dwNumAdapterModes = m_pD3D->GetAdapterModeCount( iAdapter ); // Add the adapter's current desktop format to the list of formats formats[dwNumFormats++] = pAdapter->d3ddmDesktop.Format; for( UINT iMode = 0; iMode < dwNumAdapterModes; iMode++ ) { // Get the display mode attributes D3DDISPLAYMODE DisplayMode; m_pD3D->EnumAdapterModes( iAdapter, iMode, &DisplayMode ); // Filter out low-resolution modes if( DisplayMode.Width < 640 || DisplayMode.Height < 400 ) continue; // Check if the mode already exists (to filter out refresh rates) for( DWORD m=0L; mdevices[pAdapter->dwNumDevices]; pDevice->DeviceType = DeviceTypes[iDevice]; m_pD3D->GetDeviceCaps( iAdapter, DeviceTypes[iDevice], &pDevice->d3dCaps ); pDevice->strDesc = strDeviceDescs[iDevice]; pDevice->dwNumModes = 0; pDevice->dwCurrentMode = 0; pDevice->bCanDoWindowed = FALSE; pDevice->bWindowed = FALSE; pDevice->MultiSampleType = D3DMULTISAMPLE_NONE; // Examine each format supported by the adapter to see if it will // work with this device and meets the needs of the application. BOOL bFormatConfirmed[20]; DWORD dwBehavior[20]; D3DFORMAT fmtDepthStencil[20]; for( DWORD f=0; fCheckDeviceType( iAdapter, pDevice->DeviceType, formats[f], formats[f], FALSE ) ) ) continue; if( pDevice->DeviceType == D3DDEVTYPE_HAL ) { // This system has a HAL device bHALExists = TRUE; if( pDevice->d3dCaps.Caps2 & D3DCAPS2_CANRENDERWINDOWED ) { // HAL can run in a window for some mode bHALIsWindowedCompatible = TRUE; if( f == 0 ) { // HAL can run in a window for the current desktop mode bHALIsDesktopCompatible = TRUE; } } } // Confirm the device/format for HW vertex processing if( pDevice->d3dCaps.DevCaps&D3DDEVCAPS_HWTRANSFORMANDLIGHT ) { if( pDevice->d3dCaps.DevCaps&D3DDEVCAPS_PUREDEVICE ) { /* dwBehavior[f] = D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE; */ dwBehavior[f] = D3DCREATE_HARDWARE_VERTEXPROCESSING; if( SUCCEEDED( ConfirmDevice( &pDevice->d3dCaps, dwBehavior[f], formats[f] ) ) ) bFormatConfirmed[f] = FALSE; } if ( FALSE == bFormatConfirmed[f] ) { dwBehavior[f] = D3DCREATE_HARDWARE_VERTEXPROCESSING; if( SUCCEEDED( ConfirmDevice( &pDevice->d3dCaps, dwBehavior[f], formats[f] ) ) ) bFormatConfirmed[f] = TRUE; } if ( FALSE == bFormatConfirmed[f] ) { dwBehavior[f] = D3DCREATE_MIXED_VERTEXPROCESSING; if( SUCCEEDED( ConfirmDevice( &pDevice->d3dCaps, dwBehavior[f], formats[f] ) ) ) bFormatConfirmed[f] = TRUE; } } // Confirm the device/format for SW vertex processing if( FALSE == bFormatConfirmed[f] ) { dwBehavior[f] = D3DCREATE_SOFTWARE_VERTEXPROCESSING; if( SUCCEEDED( ConfirmDevice( &pDevice->d3dCaps, dwBehavior[f], formats[f] ) ) ) bFormatConfirmed[f] = TRUE; } // Find a suitable depth/stencil buffer format for this device/format if( bFormatConfirmed[f]) { if( !FindDepthStencilFormat( iAdapter, pDevice->DeviceType, formats[f], &fmtDepthStencil[f] ) ) { bFormatConfirmed[f] = FALSE; } } } // Add all enumerated display modes with confirmed formats to the // device's list of valid modes for( DWORD m=0L; mmodes[pDevice->dwNumModes].Width = modes[m].Width; pDevice->modes[pDevice->dwNumModes].Height = modes[m].Height; pDevice->modes[pDevice->dwNumModes].Format = modes[m].Format; pDevice->modes[pDevice->dwNumModes].dwBehavior = dwBehavior[f]; pDevice->modes[pDevice->dwNumModes].DepthStencilFormat = fmtDepthStencil[f]; pDevice->dwNumModes++; if( pDevice->DeviceType == D3DDEVTYPE_HAL ) bHALIsSampleCompatible = TRUE; } } } } // Select any 640x480 mode for default (but prefer a 16-bit mode) for( m=0; mdwNumModes; m++ ) { if( pDevice->modes[m].Width==640 && pDevice->modes[m].Height==480 ) { pDevice->dwCurrentMode = m; if( pDevice->modes[m].Format == D3DFMT_R5G6B5 || pDevice->modes[m].Format == D3DFMT_X1R5G5B5 || pDevice->modes[m].Format == D3DFMT_A1R5G5B5 ) { break; } } } // Check if the device is compatible with the desktop display mode // (which was added initially as formats[0]) if( bFormatConfirmed[0] && (pDevice->d3dCaps.Caps2 & D3DCAPS2_CANRENDERWINDOWED) ) { pDevice->bCanDoWindowed = TRUE; pDevice->bWindowed = TRUE; } // If valid modes were found, keep this device if( pDevice->dwNumModes > 0 ) pAdapter->dwNumDevices++; } // If valid devices were found, keep this adapter if( pAdapter->dwNumDevices > 0 ) m_dwNumAdapters++; } // Return an error if no compatible devices were found if( 0L == m_dwNumAdapters ) return S_OK; // Pick a default device that can render into a window // (This code assumes that the HAL device comes before the REF // device in the device array). m_pD3D->Release(); for( DWORD a=0; aCheckDeviceFormat( iAdapter, DeviceType, TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16 ) ) ) { if( SUCCEEDED( m_pD3D->CheckDepthStencilMatch( iAdapter, DeviceType, TargetFormat, TargetFormat, D3DFMT_D16 ) ) ) { *pDepthStencilFormat = D3DFMT_D16; return TRUE; } } } if( m_dwMinDepthBits <= 15 && m_dwMinStencilBits <= 1 ) { if( SUCCEEDED( m_pD3D->CheckDeviceFormat( iAdapter, DeviceType, TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D15S1 ) ) ) { if( SUCCEEDED( m_pD3D->CheckDepthStencilMatch( iAdapter, DeviceType, TargetFormat, TargetFormat, D3DFMT_D15S1 ) ) ) { *pDepthStencilFormat = D3DFMT_D15S1; return TRUE; } } } if( m_dwMinDepthBits <= 24 && m_dwMinStencilBits == 0 ) { if( SUCCEEDED( m_pD3D->CheckDeviceFormat( iAdapter, DeviceType, TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24X8 ) ) ) { if( SUCCEEDED( m_pD3D->CheckDepthStencilMatch( iAdapter, DeviceType, TargetFormat, TargetFormat, D3DFMT_D24X8 ) ) ) { *pDepthStencilFormat = D3DFMT_D24X8; return TRUE; } } } if( m_dwMinDepthBits <= 24 && m_dwMinStencilBits <= 8 ) { if( SUCCEEDED( m_pD3D->CheckDeviceFormat( iAdapter, DeviceType, TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24S8 ) ) ) { if( SUCCEEDED( m_pD3D->CheckDepthStencilMatch( iAdapter, DeviceType, TargetFormat, TargetFormat, D3DFMT_D24S8 ) ) ) { *pDepthStencilFormat = D3DFMT_D24S8; return TRUE; } } } if( m_dwMinDepthBits <= 24 && m_dwMinStencilBits <= 4 ) { if( SUCCEEDED( m_pD3D->CheckDeviceFormat( iAdapter, DeviceType, TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24X4S4 ) ) ) { if( SUCCEEDED( m_pD3D->CheckDepthStencilMatch( iAdapter, DeviceType, TargetFormat, TargetFormat, D3DFMT_D24X4S4 ) ) ) { *pDepthStencilFormat = D3DFMT_D24X4S4; return TRUE; } } } if( m_dwMinDepthBits <= 32 && m_dwMinStencilBits == 0 ) { if( SUCCEEDED( m_pD3D->CheckDeviceFormat( iAdapter, DeviceType, TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D32 ) ) ) { if( SUCCEEDED( m_pD3D->CheckDepthStencilMatch( iAdapter, DeviceType, TargetFormat, TargetFormat, D3DFMT_D32 ) ) ) { *pDepthStencilFormat = D3DFMT_D32; return TRUE; } } } return FALSE; } HRESULT CEnumD3D::ConfirmDevice(D3DCAPS8 *, DWORD, D3DFORMAT) { return S_OK; }