DriveHQ Start Menu
Cloud Drive Mapping
Folder Sync
Cloud Backup
True Drop Box
FTP/SFTP Hosting
Group Account
DriveHQ Start Menu
Online File Server
My Storage
|
Manage Shares
|
Publishes
|
Drop Boxes
|
Group Account
WebDAV Drive Mapping
Cloud Drive Home
|
WebDAV Guide
|
Drive Mapping Tool
|
Drive Mapping URL
Complete Data Backup
Backup Guide
|
Online Backup Tool
|
Cloud-to-Cloud Backup
FTP, Email & Web Service
FTP Home
|
FTP Hosting FAQ
|
Email Hosting
|
EmailManager
|
Web Hosting
Help & Resources
About
|
Enterprise Service
|
Partnership
|
Comparisons
|
Support
Quick Links
Security and Privacy
Download Software
Service Manual
Use Cases
Group Account
Online Help
Blog
Contact
Cloud Surveillance
Sign Up
Login
Features
Business Features
Online File Server
FTP Hosting
Cloud Drive Mapping
Cloud File Backup
Email Backup & Hosting
Cloud File Sharing
Folder Synchronization
Group Management
True Drop Box
Full-text Search
AD Integration/SSO
Mobile Access
IP Camera & DVR Solution
More...
Personal Features
Personal Cloud Drive
Backup All Devices
Mobile APPs
Personal Web Hosting
Sub-Account (for Kids)
Home/PC/Kids Monitoring
More...
Software
DriveHQ Drive Mapping Tool
DriveHQ FileManager
DriveHQ Online Backup
DriveHQ Mobile Apps
Pricing
Business Plans & Pricing
Personal Plans & Pricing
Price Comparison with Others
Feature Comparison with Others
Install Mobile App
Sign up
Creating account...
Invalid character in username! Only 0-9, a-z, A-Z, _, -, . allowed.
Username is required!
Invalid email address!
E-mail is required!
Password is required!
Password is invalid!
Password and confirmation do not match.
Confirm password is required!
I accept
Membership Agreement
Please read the Membership Agreement and check "I accept"!
Free Quick Sign-up
Sign-up Page
Log in
Signing in...
Username or e-mail address is required!
Password is required!
Keep me logged in
Quick Login
Forgot Password
Up
Upload
Download
Share
Publish
New Folder
New File
Copy
Cut
Delete
Paste
Rate
Upgrade
Rotate
Effect
Edit
Slide
History
//-------------------------------------------------------------------------------------- // File: DXUTEnum.cpp // // Enumerates D3D adapters, devices, modes, etc. // // Copyright (c) Microsoft Corporation. All rights reserved. //-------------------------------------------------------------------------------------- //#include "DXUT.h" #include "DarkPuzzle.h" #undef min // use __min instead #undef max // use __max instead //-------------------------------------------------------------------------------------- // Forward declarations //-------------------------------------------------------------------------------------- extern void DXUTGetCallbackD3D9DeviceAcceptable( LPDXUTCALLBACKISD3D9DEVICEACCEPTABLE* ppCallbackIsDeviceAcceptable, void** ppUserContext ); extern void DXUTGetCallbackD3D10DeviceAcceptable( LPDXUTCALLBACKISD3D10DEVICEACCEPTABLE* ppCallbackIsDeviceAcceptable, void** ppUserContext ); HRESULT DXUTFindValidD3D9DeviceSettings( DXUTD3D9DeviceSettings* pOut, DXUTD3D9DeviceSettings* pIn, DXUTMatchOptions* pMatchOptions, DXUTD3D9DeviceSettings* pOptimal ); void DXUTBuildOptimalD3D9DeviceSettings( DXUTD3D9DeviceSettings* pOptimalDeviceSettings, DXUTD3D9DeviceSettings* pDeviceSettingsIn, DXUTMatchOptions* pMatchOptions ); bool DXUTDoesD3D9DeviceComboMatchPreserveOptions( CD3D9EnumDeviceSettingsCombo* pDeviceSettingsCombo, DXUTD3D9DeviceSettings* pDeviceSettingsIn, DXUTMatchOptions* pMatchOptions ); float DXUTRankD3D9DeviceCombo( CD3D9EnumDeviceSettingsCombo* pDeviceSettingsCombo, DXUTD3D9DeviceSettings* pOptimalDeviceSettings, D3DDISPLAYMODE* pAdapterDesktopDisplayMode ); void DXUTBuildValidD3D9DeviceSettings( DXUTD3D9DeviceSettings* pValidDeviceSettings, CD3D9EnumDeviceSettingsCombo* pBestDeviceSettingsCombo, DXUTD3D9DeviceSettings* pDeviceSettingsIn, DXUTMatchOptions* pMatchOptions ); HRESULT DXUTFindValidD3D9Resolution( CD3D9EnumDeviceSettingsCombo* pBestDeviceSettingsCombo, D3DDISPLAYMODE displayModeIn, D3DDISPLAYMODE* pBestDisplayMode ); HRESULT DXUTFindValidD3D10DeviceSettings( DXUTD3D10DeviceSettings* pOut, DXUTD3D10DeviceSettings* pIn, DXUTMatchOptions* pMatchOptions, DXUTD3D10DeviceSettings* pOptimal ); void DXUTBuildOptimalD3D10DeviceSettings( DXUTD3D10DeviceSettings* pOptimalDeviceSettings, DXUTD3D10DeviceSettings* pDeviceSettingsIn, DXUTMatchOptions* pMatchOptions ); bool DXUTDoesD3D10DeviceComboMatchPreserveOptions( CD3D10EnumDeviceSettingsCombo* pDeviceSettingsCombo, DXUTD3D10DeviceSettings* pDeviceSettingsIn, DXUTMatchOptions* pMatchOptions ); float DXUTRankD3D10DeviceCombo( CD3D10EnumDeviceSettingsCombo* pDeviceSettingsCombo, DXUTD3D10DeviceSettings* pOptimalDeviceSettings, DXGI_MODE_DESC* pAdapterDisplayMode ); void DXUTBuildValidD3D10DeviceSettings( DXUTD3D10DeviceSettings* pValidDeviceSettings, CD3D10EnumDeviceSettingsCombo* pBestDeviceSettingsCombo, DXUTD3D10DeviceSettings* pDeviceSettingsIn, DXUTMatchOptions* pMatchOptions ); HRESULT DXUTFindValidD3D10Resolution( CD3D10EnumDeviceSettingsCombo* pBestDeviceSettingsCombo, DXGI_MODE_DESC displayModeIn, DXGI_MODE_DESC* pBestDisplayMode ); static int __cdecl SortModesCallback( const void* arg1, const void* arg2 ); //====================================================================================== //====================================================================================== // General Direct3D section //====================================================================================== //====================================================================================== //-------------------------------------------------------------------------------------- // This function tries to find valid device settings based upon the input device settings // struct and the match options. For each device setting a match option in the // DXUTMatchOptions struct specifies how the function makes decisions. For example, if // the caller wants a HAL device with a back buffer format of D3DFMT_A2B10G10R10 but the // HAL device on the system does not support D3DFMT_A2B10G10R10 however a REF device is // installed that does, then the function has a choice to either use REF or to change to // a back buffer format to compatible with the HAL device. The match options lets the // caller control how these choices are made. // // Each match option must be one of the following types: // DXUTMT_IGNORE_INPUT: Uses the closest valid value to a default // DXUTMT_PRESERVE_INPUT: Uses the input without change, but may cause no valid device to be found // DXUTMT_CLOSEST_TO_INPUT: Uses the closest valid value to the input // // If pMatchOptions is NULL then, all of the match options are assumed to be DXUTMT_IGNORE_INPUT. // The function returns failure if no valid device settings can be found otherwise // the function returns success and the valid device settings are written to pOut. //-------------------------------------------------------------------------------------- HRESULT WINAPI DXUTFindValidDeviceSettings( DXUTDeviceSettings* pOut, DXUTDeviceSettings* pIn, DXUTMatchOptions* pMatchOptions ) { HRESULT hr = S_OK; if( pOut == NULL ) return DXUT_ERR_MSGBOX( L"DXUTFindValidDeviceSettings", E_INVALIDARG ); // Default to DXUTMT_IGNORE_INPUT for everything unless pMatchOptions isn't NULL DXUTMatchOptions defaultMatchOptions; if( NULL == pMatchOptions ) { ZeroMemory( &defaultMatchOptions, sizeof(DXUTMatchOptions) ); pMatchOptions = &defaultMatchOptions; } bool bAppSupportsD3D9 = DXUTDoesAppSupportD3D9(); bool bAppSupportsD3D10 = DXUTDoesAppSupportD3D10(); if( !bAppSupportsD3D9 && !bAppSupportsD3D10 ) { bAppSupportsD3D9 = true; bAppSupportsD3D10 = true; } bool bAvoidD3D9 = false; bool bAvoidD3D10 = false; if( pMatchOptions->eAPIVersion == DXUTMT_PRESERVE_INPUT && pIn && pIn->ver == DXUT_D3D10_DEVICE ) bAvoidD3D9 = true; if( pMatchOptions->eAPIVersion == DXUTMT_PRESERVE_INPUT && pIn && pIn->ver == DXUT_D3D9_DEVICE ) bAvoidD3D10 = true; bool bPreferD3D9 = false; if( pMatchOptions->eAPIVersion != DXUTMT_IGNORE_INPUT && pIn && pIn->ver == DXUT_D3D9_DEVICE ) bPreferD3D9 = true; // Build an optimal device settings structure based upon the match // options. If the match option is set to ignore, then a optimal default value is used. // The default value may not exist on the system, but later this will be taken // into account. bool bFoundValidD3D10 = false; bool bFoundValidD3D9 = false; DXUTDeviceSettings validDeviceSettings; CopyMemory( &validDeviceSettings, pIn, sizeof(DXUTDeviceSettings) ); DXUTDeviceSettings optimalDeviceSettings; if( bAppSupportsD3D10 && !bPreferD3D9 && !bAvoidD3D10 ) { bool bD3D10Available = DXUTIsD3D10Available(); if( bD3D10Available ) { // Force an enumeration with the IsDeviceAcceptable callback DXUTGetD3D10Enumeration( false ); DXUTD3D10DeviceSettings d3d10In; ZeroMemory( &d3d10In, sizeof(DXUTD3D10DeviceSettings) ); if( pIn ) { if( pIn->ver == DXUT_D3D9_DEVICE ) DXUTConvertDeviceSettings9to10( &pIn->d3d9, &d3d10In ); else d3d10In = pIn->d3d10; } optimalDeviceSettings.ver = DXUT_D3D10_DEVICE; DXUTBuildOptimalD3D10DeviceSettings( &optimalDeviceSettings.d3d10, &d3d10In, pMatchOptions ); validDeviceSettings.ver = DXUT_D3D10_DEVICE; hr = DXUTFindValidD3D10DeviceSettings( &validDeviceSettings.d3d10, &d3d10In, pMatchOptions, &optimalDeviceSettings.d3d10 ); if( SUCCEEDED(hr) ) bFoundValidD3D10 = true; } else { if( bAvoidD3D9 ) hr = DXUTERR_NOCOMPATIBLEDEVICES; else hr = DXUTERR_NODIRECT3D; } } if( bAppSupportsD3D9 && !bFoundValidD3D10 && !bAvoidD3D9 ) { // Force an enumeration with the IsDeviceAcceptable callback DXUTGetD3D9Enumeration( false ); DXUTD3D9DeviceSettings d3d9In; ZeroMemory( &d3d9In, sizeof(DXUTD3D9DeviceSettings) ); if( pIn ) { if( pIn->ver == DXUT_D3D10_DEVICE ) DXUTConvertDeviceSettings10to9( &pIn->d3d10, &d3d9In ); else d3d9In = pIn->d3d9; } optimalDeviceSettings.ver = DXUT_D3D9_DEVICE; DXUTBuildOptimalD3D9DeviceSettings( &optimalDeviceSettings.d3d9, &d3d9In, pMatchOptions ); validDeviceSettings.ver = DXUT_D3D9_DEVICE; hr = DXUTFindValidD3D9DeviceSettings( &validDeviceSettings.d3d9, &d3d9In, pMatchOptions, &optimalDeviceSettings.d3d9 ); if( SUCCEEDED(hr) ) bFoundValidD3D9 = true; } if( bFoundValidD3D10 || bFoundValidD3D9 ) { *pOut = validDeviceSettings; return S_OK; } else { return DXUT_ERR( L"DXUTFindValidDeviceSettings", hr ); } } //====================================================================================== //====================================================================================== // Direct3D 9 section //====================================================================================== //====================================================================================== CD3D9Enumeration* g_pDXUTD3D9Enumeration = NULL; HRESULT WINAPI DXUTCreateD3D9Enumeration() { if( g_pDXUTD3D9Enumeration == NULL ) { g_pDXUTD3D9Enumeration = new CD3D9Enumeration(); if( NULL == g_pDXUTD3D9Enumeration ) return E_OUTOFMEMORY; } return S_OK; } void WINAPI DXUTDestroyD3D9Enumeration() { SAFE_DELETE( g_pDXUTD3D9Enumeration ); } class DXUTMemoryHelperD3D9Enum { public: DXUTMemoryHelperD3D9Enum() { DXUTCreateD3D9Enumeration(); } ~DXUTMemoryHelperD3D9Enum() { DXUTDestroyD3D9Enumeration(); } }; //-------------------------------------------------------------------------------------- CD3D9Enumeration* WINAPI DXUTGetD3D9Enumeration( bool bForceEnumerate ) { // Using an static class with accessor function to allow control of the construction order static DXUTMemoryHelperD3D9Enum d3d9enumMemory; if( g_pDXUTD3D9Enumeration && ( !g_pDXUTD3D9Enumeration->HasEnumerated() || bForceEnumerate ) ) { LPDXUTCALLBACKISD3D9DEVICEACCEPTABLE pCallbackIsDeviceAcceptable; void* pUserContext; DXUTGetCallbackD3D9DeviceAcceptable( &pCallbackIsDeviceAcceptable, &pUserContext ); g_pDXUTD3D9Enumeration->Enumerate( pCallbackIsDeviceAcceptable, pUserContext ); } return g_pDXUTD3D9Enumeration; } //-------------------------------------------------------------------------------------- CD3D9Enumeration::CD3D9Enumeration() { m_bHasEnumerated = false; m_pD3D = NULL; m_IsD3D9DeviceAcceptableFunc = NULL; m_pIsD3D9DeviceAcceptableFuncUserContext = NULL; m_bRequirePostPixelShaderBlending = true; m_nMinWidth = 640; m_nMinHeight = 480; m_nMaxWidth = UINT_MAX; m_nMaxHeight = UINT_MAX; m_nRefreshMin = 0; m_nRefreshMax = UINT_MAX; m_nMultisampleQualityMax = 0xFFFF; ResetPossibleDepthStencilFormats(); ResetPossibleMultisampleTypeList(); ResetPossiblePresentIntervalList(); SetPossibleVertexProcessingList( true, true, true, false ); } //-------------------------------------------------------------------------------------- CD3D9Enumeration::~CD3D9Enumeration() { ClearAdapterInfoList(); } //-------------------------------------------------------------------------------------- // Enumerate for each adapter all of the supported display modes, // device types, adapter formats, back buffer formats, window/full screen support, // depth stencil formats, multisampling types/qualities, and presentations intervals. // // For each combination of device type (HAL/REF), adapter format, back buffer format, and // IsWindowed it will call the app's ConfirmDevice callback. This allows the app // to reject or allow that combination based on its caps/etc. It also allows the // app to change the BehaviorFlags. The BehaviorFlags defaults non-pure HWVP // if supported otherwise it will default to SWVP, however the app can change this // through the ConfirmDevice callback. //-------------------------------------------------------------------------------------- HRESULT CD3D9Enumeration::Enumerate( LPDXUTCALLBACKISD3D9DEVICEACCEPTABLE IsD3D9DeviceAcceptableFunc, void* pIsD3D9DeviceAcceptableFuncUserContext ) { CDXUTPerfEventGenerator eventGenerator( DXUT_PERFEVENTCOLOR, L"DXUT D3D9 Enumeration" ); IDirect3D9* pD3D = DXUTGetD3D9Object(); if( pD3D == NULL ) { pD3D = DXUTGetD3D9Object(); if( pD3D == NULL ) return DXUTERR_NODIRECT3D; } m_bHasEnumerated = true; m_pD3D = pD3D; m_IsD3D9DeviceAcceptableFunc = IsD3D9DeviceAcceptableFunc; m_pIsD3D9DeviceAcceptableFuncUserContext = pIsD3D9DeviceAcceptableFuncUserContext; HRESULT hr; ClearAdapterInfoList(); CGrowableArray
adapterFormatList; const D3DFORMAT allowedAdapterFormatArray[] = { D3DFMT_X8R8G8B8, D3DFMT_X1R5G5B5, D3DFMT_R5G6B5, D3DFMT_A2R10G10B10 }; const UINT allowedAdapterFormatArrayCount = sizeof(allowedAdapterFormatArray) / sizeof(allowedAdapterFormatArray[0]); UINT numAdapters = pD3D->GetAdapterCount(); for (UINT adapterOrdinal = 0; adapterOrdinal < numAdapters; adapterOrdinal++) { CD3D9EnumAdapterInfo* pAdapterInfo = new CD3D9EnumAdapterInfo; if( pAdapterInfo == NULL ) return E_OUTOFMEMORY; pAdapterInfo->AdapterOrdinal = adapterOrdinal; pD3D->GetAdapterIdentifier(adapterOrdinal, 0, &pAdapterInfo->AdapterIdentifier); // Get list of all display modes on this adapter. // Also build a temporary list of all display adapter formats. adapterFormatList.RemoveAll(); for( UINT iFormatList = 0; iFormatList < allowedAdapterFormatArrayCount; iFormatList++ ) { D3DFORMAT allowedAdapterFormat = allowedAdapterFormatArray[iFormatList]; UINT numAdapterModes = pD3D->GetAdapterModeCount( adapterOrdinal, allowedAdapterFormat ); for (UINT mode = 0; mode < numAdapterModes; mode++) { D3DDISPLAYMODE displayMode; pD3D->EnumAdapterModes( adapterOrdinal, allowedAdapterFormat, mode, &displayMode ); if( displayMode.Width < m_nMinWidth || displayMode.Height < m_nMinHeight || displayMode.Width > m_nMaxWidth || displayMode.Height > m_nMaxHeight || displayMode.RefreshRate < m_nRefreshMin || displayMode.RefreshRate > m_nRefreshMax ) { continue; } pAdapterInfo->displayModeList.Add( displayMode ); if( !adapterFormatList.Contains(displayMode.Format) ) adapterFormatList.Add( displayMode.Format ); } } D3DDISPLAYMODE displayMode; pD3D->GetAdapterDisplayMode( adapterOrdinal, &displayMode ); if( !adapterFormatList.Contains(displayMode.Format) ) adapterFormatList.Add( displayMode.Format ); // Sort displaymode list qsort( pAdapterInfo->displayModeList.GetData(), pAdapterInfo->displayModeList.GetSize(), sizeof( D3DDISPLAYMODE ), SortModesCallback ); // Get info for each device on this adapter if( FAILED( EnumerateDevices( pAdapterInfo, &adapterFormatList ) ) ) { delete pAdapterInfo; continue; } // If at least one device on this adapter is available and compatible // with the app, add the adapterInfo to the list if( pAdapterInfo->deviceInfoList.GetSize() > 0 ) { hr = m_AdapterInfoList.Add( pAdapterInfo ); if( FAILED(hr) ) return hr; } else delete pAdapterInfo; } // // Check for 2 or more adapters with the same name. Append the name // with some instance number if that's the case to help distinguish // them. // bool bUniqueDesc = true; CD3D9EnumAdapterInfo* pAdapterInfo; for( int i=0; i
AdapterIdentifier.Description, pAdapterInfo2->AdapterIdentifier.Description ) == 0 ) { bUniqueDesc = false; break; } } if( !bUniqueDesc ) break; } for( int i=0; i
AdapterIdentifier.Description, -1, pAdapterInfo->szUniqueDescription, 100 ); pAdapterInfo->szUniqueDescription[100] = 0; if( !bUniqueDesc ) { WCHAR sz[100]; StringCchPrintf( sz, 100, L" (#%d)", pAdapterInfo->AdapterOrdinal ); StringCchCat( pAdapterInfo->szUniqueDescription, 256, sz ); } } return S_OK; } //-------------------------------------------------------------------------------------- // Enumerates D3D devices for a particular adapter. //-------------------------------------------------------------------------------------- HRESULT CD3D9Enumeration::EnumerateDevices( CD3D9EnumAdapterInfo* pAdapterInfo, CGrowableArray
* pAdapterFormatList ) { HRESULT hr; const D3DDEVTYPE devTypeArray[] = { D3DDEVTYPE_HAL, D3DDEVTYPE_SW, D3DDEVTYPE_REF }; const UINT devTypeArrayCount = sizeof(devTypeArray) / sizeof(devTypeArray[0]); // Enumerate each Direct3D device type for( UINT iDeviceType = 0; iDeviceType < devTypeArrayCount; iDeviceType++ ) { CD3D9EnumDeviceInfo* pDeviceInfo = new CD3D9EnumDeviceInfo; if( pDeviceInfo == NULL ) return E_OUTOFMEMORY; // Fill struct w/ AdapterOrdinal and D3DDEVTYPE pDeviceInfo->AdapterOrdinal = pAdapterInfo->AdapterOrdinal; pDeviceInfo->DeviceType = devTypeArray[iDeviceType]; // Store device caps if( FAILED( hr = m_pD3D->GetDeviceCaps( pAdapterInfo->AdapterOrdinal, pDeviceInfo->DeviceType, &pDeviceInfo->Caps ) ) ) { delete pDeviceInfo; continue; } if( pDeviceInfo->DeviceType != D3DDEVTYPE_HAL ) { // Create a temp device to verify that it is really possible to create a REF device // [the developer DirectX redist has to be installed] D3DDISPLAYMODE Mode; m_pD3D->GetAdapterDisplayMode(0, &Mode); D3DPRESENT_PARAMETERS pp; ZeroMemory( &pp, sizeof(D3DPRESENT_PARAMETERS) ); pp.BackBufferWidth = 1; pp.BackBufferHeight = 1; pp.BackBufferFormat = Mode.Format; pp.BackBufferCount = 1; pp.SwapEffect = D3DSWAPEFFECT_COPY; pp.Windowed = TRUE; pp.hDeviceWindow = DXUTGetHWNDFocus(); IDirect3DDevice9 *pDevice = NULL; if( FAILED( hr = m_pD3D->CreateDevice( pAdapterInfo->AdapterOrdinal, pDeviceInfo->DeviceType, DXUTGetHWNDFocus(), D3DCREATE_HARDWARE_VERTEXPROCESSING, &pp, &pDevice ) ) ) { delete pDeviceInfo; continue; } SAFE_RELEASE( pDevice ); } // Get info for each devicecombo on this device if( FAILED( hr = EnumerateDeviceCombos( pAdapterInfo, pDeviceInfo, pAdapterFormatList ) ) ) { delete pDeviceInfo; continue; } // If at least one devicecombo for this device is found, // add the deviceInfo to the list if (pDeviceInfo->deviceSettingsComboList.GetSize() > 0 ) pAdapterInfo->deviceInfoList.Add( pDeviceInfo ); else delete pDeviceInfo; } return S_OK; } //-------------------------------------------------------------------------------------- // Enumerates DeviceCombos for a particular device. //-------------------------------------------------------------------------------------- HRESULT CD3D9Enumeration::EnumerateDeviceCombos( CD3D9EnumAdapterInfo* pAdapterInfo, CD3D9EnumDeviceInfo* pDeviceInfo, CGrowableArray
* pAdapterFormatList ) { const D3DFORMAT backBufferFormatArray[] = { D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8, D3DFMT_A2R10G10B10, D3DFMT_R5G6B5, D3DFMT_A1R5G5B5, D3DFMT_X1R5G5B5 }; const UINT backBufferFormatArrayCount = sizeof(backBufferFormatArray) / sizeof(backBufferFormatArray[0]); // See which adapter formats are supported by this device for( int iFormat=0; iFormat
GetSize(); iFormat++ ) { D3DFORMAT adapterFormat = pAdapterFormatList->GetAt(iFormat); for( UINT iBackBufferFormat = 0; iBackBufferFormat < backBufferFormatArrayCount; iBackBufferFormat++ ) { D3DFORMAT backBufferFormat = backBufferFormatArray[iBackBufferFormat]; for( int nWindowed = 0; nWindowed < 2; nWindowed++) { if( !nWindowed && pAdapterInfo->displayModeList.GetSize() == 0 ) continue; if (FAILED( m_pD3D->CheckDeviceType( pAdapterInfo->AdapterOrdinal, pDeviceInfo->DeviceType, adapterFormat, backBufferFormat, nWindowed ))) { continue; } if( m_bRequirePostPixelShaderBlending ) { // If the backbuffer format doesn't support D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING // then alpha test, pixel fog, render-target blending, color write enable, and dithering. // are not supported. if( FAILED( m_pD3D->CheckDeviceFormat( pAdapterInfo->AdapterOrdinal, pDeviceInfo->DeviceType, adapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, D3DRTYPE_TEXTURE, backBufferFormat ) ) ) { continue; } } // If an application callback function has been provided, make sure this device // is acceptable to the app. if( m_IsD3D9DeviceAcceptableFunc != NULL ) { if( !m_IsD3D9DeviceAcceptableFunc( &pDeviceInfo->Caps, adapterFormat, backBufferFormat, FALSE != nWindowed, m_pIsD3D9DeviceAcceptableFuncUserContext ) ) continue; } // At this point, we have an adapter/device/adapterformat/backbufferformat/iswindowed // DeviceCombo that is supported by the system and acceptable to the app. We still // need to find one or more suitable depth/stencil buffer format, // multisample type, and present interval. CD3D9EnumDeviceSettingsCombo* pDeviceCombo = new CD3D9EnumDeviceSettingsCombo; if( pDeviceCombo == NULL ) return E_OUTOFMEMORY; pDeviceCombo->AdapterOrdinal = pAdapterInfo->AdapterOrdinal; pDeviceCombo->DeviceType = pDeviceInfo->DeviceType; pDeviceCombo->AdapterFormat = adapterFormat; pDeviceCombo->BackBufferFormat = backBufferFormat; pDeviceCombo->Windowed = (nWindowed != 0); BuildDepthStencilFormatList( pDeviceCombo ); BuildMultiSampleTypeList( pDeviceCombo ); if (pDeviceCombo->multiSampleTypeList.GetSize() == 0) { delete pDeviceCombo; continue; } BuildDSMSConflictList( pDeviceCombo ); BuildPresentIntervalList(pDeviceInfo, pDeviceCombo ); pDeviceCombo->pAdapterInfo = pAdapterInfo; pDeviceCombo->pDeviceInfo = pDeviceInfo; if( FAILED( pDeviceInfo->deviceSettingsComboList.Add( pDeviceCombo ) ) ) delete pDeviceCombo; } } } return S_OK; } //-------------------------------------------------------------------------------------- // Adds all depth/stencil formats that are compatible with the device // and app to the given D3DDeviceCombo. //-------------------------------------------------------------------------------------- void CD3D9Enumeration::BuildDepthStencilFormatList( CD3D9EnumDeviceSettingsCombo* pDeviceCombo ) { D3DFORMAT depthStencilFmt; for( int idsf = 0; idsf < m_DepthStencilPossibleList.GetSize(); idsf++ ) { depthStencilFmt = m_DepthStencilPossibleList.GetAt(idsf); if (SUCCEEDED(m_pD3D->CheckDeviceFormat(pDeviceCombo->AdapterOrdinal, pDeviceCombo->DeviceType, pDeviceCombo->AdapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFmt))) { if (SUCCEEDED(m_pD3D->CheckDepthStencilMatch(pDeviceCombo->AdapterOrdinal, pDeviceCombo->DeviceType, pDeviceCombo->AdapterFormat, pDeviceCombo->BackBufferFormat, depthStencilFmt))) { pDeviceCombo->depthStencilFormatList.Add( depthStencilFmt ); } } } } //-------------------------------------------------------------------------------------- // Adds all multisample types that are compatible with the device and app to // the given D3DDeviceCombo. //-------------------------------------------------------------------------------------- void CD3D9Enumeration::BuildMultiSampleTypeList( CD3D9EnumDeviceSettingsCombo* pDeviceCombo ) { D3DMULTISAMPLE_TYPE msType; DWORD msQuality; for( int imst = 0; imst < m_MultiSampleTypeList.GetSize(); imst++ ) { msType = m_MultiSampleTypeList.GetAt(imst); if( SUCCEEDED( m_pD3D->CheckDeviceMultiSampleType( pDeviceCombo->AdapterOrdinal, pDeviceCombo->DeviceType, pDeviceCombo->BackBufferFormat, pDeviceCombo->Windowed, msType, &msQuality ) ) ) { pDeviceCombo->multiSampleTypeList.Add( msType ); if( msQuality > m_nMultisampleQualityMax + 1 ) msQuality = m_nMultisampleQualityMax + 1; pDeviceCombo->multiSampleQualityList.Add( msQuality ); } } } //-------------------------------------------------------------------------------------- // Find any conflicts between the available depth/stencil formats and // multisample types. //-------------------------------------------------------------------------------------- void CD3D9Enumeration::BuildDSMSConflictList( CD3D9EnumDeviceSettingsCombo* pDeviceCombo ) { CD3D9EnumDSMSConflict DSMSConflict; for( int iDS=0; iDS
depthStencilFormatList.GetSize(); iDS++ ) { D3DFORMAT dsFmt = pDeviceCombo->depthStencilFormatList.GetAt(iDS); for( int iMS=0; iMS
multiSampleTypeList.GetSize(); iMS++ ) { D3DMULTISAMPLE_TYPE msType = pDeviceCombo->multiSampleTypeList.GetAt(iMS); if( FAILED( m_pD3D->CheckDeviceMultiSampleType( pDeviceCombo->AdapterOrdinal, pDeviceCombo->DeviceType, dsFmt, pDeviceCombo->Windowed, msType, NULL ) ) ) { DSMSConflict.DSFormat = dsFmt; DSMSConflict.MSType = msType; pDeviceCombo->DSMSConflictList.Add( DSMSConflict ); } } } } //-------------------------------------------------------------------------------------- // Adds all present intervals that are compatible with the device and app // to the given D3DDeviceCombo. //-------------------------------------------------------------------------------------- void CD3D9Enumeration::BuildPresentIntervalList( CD3D9EnumDeviceInfo* pDeviceInfo, CD3D9EnumDeviceSettingsCombo* pDeviceCombo ) { UINT pi; for( int ipi = 0; ipi < m_PresentIntervalList.GetSize(); ipi++ ) { pi = m_PresentIntervalList.GetAt(ipi); if( pDeviceCombo->Windowed ) { if( pi == D3DPRESENT_INTERVAL_TWO || pi == D3DPRESENT_INTERVAL_THREE || pi == D3DPRESENT_INTERVAL_FOUR ) { // These intervals are not supported in windowed mode. continue; } } // Note that D3DPRESENT_INTERVAL_DEFAULT is zero, so you // can't do a caps check for it -- it is always available. if( pi == D3DPRESENT_INTERVAL_DEFAULT || (pDeviceInfo->Caps.PresentationIntervals & pi) ) { pDeviceCombo->presentIntervalList.Add( pi ); } } } //-------------------------------------------------------------------------------------- // Release all the allocated CD3D9EnumAdapterInfo objects and empty the list //-------------------------------------------------------------------------------------- void CD3D9Enumeration::ClearAdapterInfoList() { CD3D9EnumAdapterInfo* pAdapterInfo; for( int i=0; i
* CD3D9Enumeration::GetAdapterInfoList() { return &m_AdapterInfoList; } //-------------------------------------------------------------------------------------- CD3D9EnumAdapterInfo* CD3D9Enumeration::GetAdapterInfo( UINT AdapterOrdinal ) { for( int iAdapter=0; iAdapter
AdapterOrdinal == AdapterOrdinal ) return pAdapterInfo; } return NULL; } //-------------------------------------------------------------------------------------- CD3D9EnumDeviceInfo* CD3D9Enumeration::GetDeviceInfo( UINT AdapterOrdinal, D3DDEVTYPE DeviceType ) { CD3D9EnumAdapterInfo* pAdapterInfo = GetAdapterInfo( AdapterOrdinal ); if( pAdapterInfo ) { for( int iDeviceInfo=0; iDeviceInfo
deviceInfoList.GetSize(); iDeviceInfo++ ) { CD3D9EnumDeviceInfo* pDeviceInfo = pAdapterInfo->deviceInfoList.GetAt(iDeviceInfo); if( pDeviceInfo->DeviceType == DeviceType ) return pDeviceInfo; } } return NULL; } //-------------------------------------------------------------------------------------- // //-------------------------------------------------------------------------------------- CD3D9EnumDeviceSettingsCombo* CD3D9Enumeration::GetDeviceSettingsCombo( UINT AdapterOrdinal, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, BOOL bWindowed ) { CD3D9EnumDeviceInfo* pDeviceInfo = GetDeviceInfo( AdapterOrdinal, DeviceType ); if( pDeviceInfo ) { for( int iDeviceCombo=0; iDeviceCombo
deviceSettingsComboList.GetSize(); iDeviceCombo++ ) { CD3D9EnumDeviceSettingsCombo* pDeviceSettingsCombo = pDeviceInfo->deviceSettingsComboList.GetAt(iDeviceCombo); if( pDeviceSettingsCombo->AdapterFormat == AdapterFormat && pDeviceSettingsCombo->BackBufferFormat == BackBufferFormat && pDeviceSettingsCombo->Windowed == bWindowed ) return pDeviceSettingsCombo; } } return NULL; } //-------------------------------------------------------------------------------------- // Returns the number of color channel bits in the specified D3DFORMAT //-------------------------------------------------------------------------------------- UINT WINAPI DXUTGetD3D9ColorChannelBits( D3DFORMAT fmt ) { switch( fmt ) { case D3DFMT_R8G8B8: return 8; case D3DFMT_A8R8G8B8: return 8; case D3DFMT_X8R8G8B8: return 8; case D3DFMT_R5G6B5: return 5; case D3DFMT_X1R5G5B5: return 5; case D3DFMT_A1R5G5B5: return 5; case D3DFMT_A4R4G4B4: return 4; case D3DFMT_R3G3B2: return 2; case D3DFMT_A8R3G3B2: return 2; case D3DFMT_X4R4G4B4: return 4; case D3DFMT_A2B10G10R10: return 10; case D3DFMT_A8B8G8R8: return 8; case D3DFMT_A2R10G10B10: return 10; case D3DFMT_A16B16G16R16: return 16; default: return 0; } } //-------------------------------------------------------------------------------------- // Returns the number of alpha channel bits in the specified D3DFORMAT //-------------------------------------------------------------------------------------- UINT WINAPI DXUTGetAlphaChannelBits( D3DFORMAT fmt ) { switch( fmt ) { case D3DFMT_R8G8B8: return 0; case D3DFMT_A8R8G8B8: return 8; case D3DFMT_X8R8G8B8: return 0; case D3DFMT_R5G6B5: return 0; case D3DFMT_X1R5G5B5: return 0; case D3DFMT_A1R5G5B5: return 1; case D3DFMT_A4R4G4B4: return 4; case D3DFMT_R3G3B2: return 0; case D3DFMT_A8R3G3B2: return 8; case D3DFMT_X4R4G4B4: return 0; case D3DFMT_A2B10G10R10: return 2; case D3DFMT_A8B8G8R8: return 8; case D3DFMT_A2R10G10B10: return 2; case D3DFMT_A16B16G16R16: return 16; default: return 0; } } //-------------------------------------------------------------------------------------- // Returns the number of depth bits in the specified D3DFORMAT //-------------------------------------------------------------------------------------- UINT WINAPI DXUTGetDepthBits( D3DFORMAT fmt ) { switch( fmt ) { case D3DFMT_D32F_LOCKABLE: case D3DFMT_D32: return 32; case D3DFMT_D24X8: case D3DFMT_D24S8: case D3DFMT_D24X4S4: case D3DFMT_D24FS8: return 24; case D3DFMT_D16_LOCKABLE: case D3DFMT_D16: return 16; case D3DFMT_D15S1: return 15; default: return 0; } } //-------------------------------------------------------------------------------------- // Returns the number of stencil bits in the specified D3DFORMAT //-------------------------------------------------------------------------------------- UINT WINAPI DXUTGetStencilBits( D3DFORMAT fmt ) { switch( fmt ) { case D3DFMT_D16_LOCKABLE: case D3DFMT_D16: case D3DFMT_D32F_LOCKABLE: case D3DFMT_D32: case D3DFMT_D24X8: return 0; case D3DFMT_D15S1: return 1; case D3DFMT_D24X4S4: return 4; case D3DFMT_D24S8: case D3DFMT_D24FS8: return 8; default: return 0; } } //-------------------------------------------------------------------------------------- // Used to sort D3DDISPLAYMODEs //-------------------------------------------------------------------------------------- static int __cdecl SortModesCallback( const void* arg1, const void* arg2 ) { D3DDISPLAYMODE* pdm1 = (D3DDISPLAYMODE*)arg1; D3DDISPLAYMODE* pdm2 = (D3DDISPLAYMODE*)arg2; if (pdm1->Width > pdm2->Width) return 1; if (pdm1->Width < pdm2->Width) return -1; if (pdm1->Height > pdm2->Height) return 1; if (pdm1->Height < pdm2->Height) return -1; if (pdm1->Format > pdm2->Format) return 1; if (pdm1->Format < pdm2->Format) return -1; if (pdm1->RefreshRate > pdm2->RefreshRate) return 1; if (pdm1->RefreshRate < pdm2->RefreshRate) return -1; return 0; } //-------------------------------------------------------------------------------------- CD3D9EnumAdapterInfo::~CD3D9EnumAdapterInfo( void ) { CD3D9EnumDeviceInfo* pDeviceInfo; for( int i=0; i
* CD3D9Enumeration::GetPossibleDepthStencilFormatList() { return &m_DepthStencilPossibleList; } //-------------------------------------------------------------------------------------- CGrowableArray
* CD3D9Enumeration::GetPossibleMultisampleTypeList() { return &m_MultiSampleTypeList; } //-------------------------------------------------------------------------------------- void CD3D9Enumeration::ResetPossibleMultisampleTypeList() { m_MultiSampleTypeList.RemoveAll(); m_MultiSampleTypeList.Add( D3DMULTISAMPLE_NONE ); m_MultiSampleTypeList.Add( D3DMULTISAMPLE_NONMASKABLE ); m_MultiSampleTypeList.Add( D3DMULTISAMPLE_2_SAMPLES ); m_MultiSampleTypeList.Add( D3DMULTISAMPLE_3_SAMPLES ); m_MultiSampleTypeList.Add( D3DMULTISAMPLE_4_SAMPLES ); m_MultiSampleTypeList.Add( D3DMULTISAMPLE_5_SAMPLES ); m_MultiSampleTypeList.Add( D3DMULTISAMPLE_6_SAMPLES ); m_MultiSampleTypeList.Add( D3DMULTISAMPLE_7_SAMPLES ); m_MultiSampleTypeList.Add( D3DMULTISAMPLE_8_SAMPLES ); m_MultiSampleTypeList.Add( D3DMULTISAMPLE_9_SAMPLES ); m_MultiSampleTypeList.Add( D3DMULTISAMPLE_10_SAMPLES ); m_MultiSampleTypeList.Add( D3DMULTISAMPLE_11_SAMPLES ); m_MultiSampleTypeList.Add( D3DMULTISAMPLE_12_SAMPLES ); m_MultiSampleTypeList.Add( D3DMULTISAMPLE_13_SAMPLES ); m_MultiSampleTypeList.Add( D3DMULTISAMPLE_14_SAMPLES ); m_MultiSampleTypeList.Add( D3DMULTISAMPLE_15_SAMPLES ); m_MultiSampleTypeList.Add( D3DMULTISAMPLE_16_SAMPLES ); } //-------------------------------------------------------------------------------------- void CD3D9Enumeration::GetPossibleVertexProcessingList( bool* pbSoftwareVP, bool* pbHardwareVP, bool* pbPureHarewareVP, bool* pbMixedVP ) { *pbSoftwareVP = m_bSoftwareVP; *pbHardwareVP = m_bHardwareVP; *pbPureHarewareVP = m_bPureHarewareVP; *pbMixedVP = m_bMixedVP; } //-------------------------------------------------------------------------------------- void CD3D9Enumeration::SetPossibleVertexProcessingList( bool bSoftwareVP, bool bHardwareVP, bool bPureHarewareVP, bool bMixedVP ) { m_bSoftwareVP = bSoftwareVP; m_bHardwareVP = bHardwareVP; m_bPureHarewareVP = bPureHarewareVP; m_bMixedVP = bMixedVP; } //-------------------------------------------------------------------------------------- CGrowableArray
* CD3D9Enumeration::GetPossiblePresentIntervalList() { return &m_PresentIntervalList; } //-------------------------------------------------------------------------------------- void CD3D9Enumeration::ResetPossiblePresentIntervalList() { m_PresentIntervalList.RemoveAll(); m_PresentIntervalList.Add( D3DPRESENT_INTERVAL_IMMEDIATE ); m_PresentIntervalList.Add( D3DPRESENT_INTERVAL_DEFAULT ); m_PresentIntervalList.Add( D3DPRESENT_INTERVAL_ONE ); m_PresentIntervalList.Add( D3DPRESENT_INTERVAL_TWO ); m_PresentIntervalList.Add( D3DPRESENT_INTERVAL_THREE ); m_PresentIntervalList.Add( D3DPRESENT_INTERVAL_FOUR ); } //-------------------------------------------------------------------------------------- void CD3D9Enumeration::SetResolutionMinMax( UINT nMinWidth, UINT nMinHeight, UINT nMaxWidth, UINT nMaxHeight ) { m_nMinWidth = nMinWidth; m_nMinHeight = nMinHeight; m_nMaxWidth = nMaxWidth; m_nMaxHeight = nMaxHeight; } //-------------------------------------------------------------------------------------- void CD3D9Enumeration::SetRefreshMinMax( UINT nMin, UINT nMax ) { m_nRefreshMin = nMin; m_nRefreshMax = nMax; } //-------------------------------------------------------------------------------------- void CD3D9Enumeration::SetMultisampleQualityMax( UINT nMax ) { if( nMax > 0xFFFF ) nMax = 0xFFFF; m_nMultisampleQualityMax = nMax; } //-------------------------------------------------------------------------------------- HRESULT DXUTFindValidD3D9DeviceSettings( DXUTD3D9DeviceSettings* pOut, DXUTD3D9DeviceSettings* pIn, DXUTMatchOptions* pMatchOptions, DXUTD3D9DeviceSettings* pOptimal ) { // Find the best combination of: // Adapter Ordinal // Device Type // Adapter Format // Back Buffer Format // Windowed // given what's available on the system and the match options combined with the device settings input. // This combination of settings is encapsulated by the CD3D9EnumDeviceSettingsCombo class. float fBestRanking = -1.0f; CD3D9EnumDeviceSettingsCombo* pBestDeviceSettingsCombo = NULL; D3DDISPLAYMODE adapterDesktopDisplayMode; IDirect3D9* pD3D = DXUTGetD3D9Object(); CD3D9Enumeration* pd3dEnum = DXUTGetD3D9Enumeration( false ); CGrowableArray
* pAdapterList = pd3dEnum->GetAdapterInfoList(); for( int iAdapter=0; iAdapter
GetSize(); iAdapter++ ) { CD3D9EnumAdapterInfo* pAdapterInfo = pAdapterList->GetAt(iAdapter); // Get the desktop display mode of adapter pD3D->GetAdapterDisplayMode( pAdapterInfo->AdapterOrdinal, &adapterDesktopDisplayMode ); // Enum all the device types supported by this adapter to find the best device settings for( int iDeviceInfo=0; iDeviceInfo
deviceInfoList.GetSize(); iDeviceInfo++ ) { CD3D9EnumDeviceInfo* pDeviceInfo = pAdapterInfo->deviceInfoList.GetAt(iDeviceInfo); // Enum all the device settings combinations. A device settings combination is // a unique set of an adapter format, back buffer format, and IsWindowed. for( int iDeviceCombo=0; iDeviceCombo
deviceSettingsComboList.GetSize(); iDeviceCombo++ ) { CD3D9EnumDeviceSettingsCombo* pDeviceSettingsCombo = pDeviceInfo->deviceSettingsComboList.GetAt(iDeviceCombo); // If windowed mode the adapter format has to be the same as the desktop // display mode format so skip any that don't match if (pDeviceSettingsCombo->Windowed && (pDeviceSettingsCombo->AdapterFormat != adapterDesktopDisplayMode.Format)) continue; // Skip any combo that doesn't meet the preserve match options if( false == DXUTDoesD3D9DeviceComboMatchPreserveOptions( pDeviceSettingsCombo, pIn, pMatchOptions ) ) continue; // Get a ranking number that describes how closely this device combo matches the optimal combo float fCurRanking = DXUTRankD3D9DeviceCombo( pDeviceSettingsCombo, pOptimal, &adapterDesktopDisplayMode ); // If this combo better matches the input device settings then save it if( fCurRanking > fBestRanking ) { pBestDeviceSettingsCombo = pDeviceSettingsCombo; fBestRanking = fCurRanking; } } } } // If no best device combination was found then fail if( pBestDeviceSettingsCombo == NULL ) return DXUTERR_NOCOMPATIBLEDEVICES; // Using the best device settings combo found, build valid device settings taking heed of // the match options and the input device settings DXUTD3D9DeviceSettings validDeviceSettings; DXUTBuildValidD3D9DeviceSettings( &validDeviceSettings, pBestDeviceSettingsCombo, pIn, pMatchOptions ); *pOut = validDeviceSettings; return S_OK; } //-------------------------------------------------------------------------------------- // Internal helper function to build a D3D9 device settings structure based upon the match // options. If the match option is set to ignore, then a optimal default value is used. // The default value may not exist on the system, but later this will be taken // into account. //-------------------------------------------------------------------------------------- void DXUTBuildOptimalD3D9DeviceSettings( DXUTD3D9DeviceSettings* pOptimalDeviceSettings, DXUTD3D9DeviceSettings* pDeviceSettingsIn, DXUTMatchOptions* pMatchOptions ) { IDirect3D9* pD3D = DXUTGetD3D9Object(); D3DDISPLAYMODE adapterDesktopDisplayMode; ZeroMemory( pOptimalDeviceSettings, sizeof(DXUTD3D9DeviceSettings) ); //--------------------- // Adapter ordinal //--------------------- if( pMatchOptions->eAdapterOrdinal == DXUTMT_IGNORE_INPUT ) pOptimalDeviceSettings->AdapterOrdinal = D3DADAPTER_DEFAULT; else pOptimalDeviceSettings->AdapterOrdinal = pDeviceSettingsIn->AdapterOrdinal; //--------------------- // Device type //--------------------- if( pMatchOptions->eDeviceType == DXUTMT_IGNORE_INPUT ) pOptimalDeviceSettings->DeviceType = D3DDEVTYPE_HAL; else pOptimalDeviceSettings->DeviceType = pDeviceSettingsIn->DeviceType; //--------------------- // Windowed //--------------------- if( pMatchOptions->eWindowed == DXUTMT_IGNORE_INPUT ) pOptimalDeviceSettings->pp.Windowed = TRUE; else pOptimalDeviceSettings->pp.Windowed = pDeviceSettingsIn->pp.Windowed; //--------------------- // Adapter format //--------------------- if( pMatchOptions->eAdapterFormat == DXUTMT_IGNORE_INPUT ) { // If windowed, default to the desktop display mode // If fullscreen, default to the desktop display mode for quick mode change or // default to D3DFMT_X8R8G8B8 if the desktop display mode is < 32bit pD3D->GetAdapterDisplayMode( pOptimalDeviceSettings->AdapterOrdinal, &adapterDesktopDisplayMode ); if( pOptimalDeviceSettings->pp.Windowed || DXUTGetD3D9ColorChannelBits(adapterDesktopDisplayMode.Format) >= 8 ) pOptimalDeviceSettings->AdapterFormat = adapterDesktopDisplayMode.Format; else pOptimalDeviceSettings->AdapterFormat = D3DFMT_X8R8G8B8; } else { pOptimalDeviceSettings->AdapterFormat = pDeviceSettingsIn->AdapterFormat; } //--------------------- // Vertex processing //--------------------- if( pMatchOptions->eVertexProcessing == DXUTMT_IGNORE_INPUT ) pOptimalDeviceSettings->BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING; else pOptimalDeviceSettings->BehaviorFlags = pDeviceSettingsIn->BehaviorFlags; //--------------------- // Resolution //--------------------- if( pMatchOptions->eResolution == DXUTMT_IGNORE_INPUT ) { // If windowed, default to 640x480 // If fullscreen, default to the desktop res for quick mode change if( pOptimalDeviceSettings->pp.Windowed ) { pOptimalDeviceSettings->pp.BackBufferWidth = 640; pOptimalDeviceSettings->pp.BackBufferHeight = 480; } else { pD3D->GetAdapterDisplayMode( pOptimalDeviceSettings->AdapterOrdinal, &adapterDesktopDisplayMode ); pOptimalDeviceSettings->pp.BackBufferWidth = adapterDesktopDisplayMode.Width; pOptimalDeviceSettings->pp.BackBufferHeight = adapterDesktopDisplayMode.Height; } } else { pOptimalDeviceSettings->pp.BackBufferWidth = pDeviceSettingsIn->pp.BackBufferWidth; pOptimalDeviceSettings->pp.BackBufferHeight = pDeviceSettingsIn->pp.BackBufferHeight; } //--------------------- // Back buffer format //--------------------- if( pMatchOptions->eBackBufferFormat == DXUTMT_IGNORE_INPUT ) pOptimalDeviceSettings->pp.BackBufferFormat = pOptimalDeviceSettings->AdapterFormat; // Default to match the adapter format else pOptimalDeviceSettings->pp.BackBufferFormat = pDeviceSettingsIn->pp.BackBufferFormat; //--------------------- // Back buffer count //--------------------- if( pMatchOptions->eBackBufferCount == DXUTMT_IGNORE_INPUT ) pOptimalDeviceSettings->pp.BackBufferCount = 1; // Default to double buffering. Causes less latency than triple buffering else pOptimalDeviceSettings->pp.BackBufferCount = pDeviceSettingsIn->pp.BackBufferCount; //--------------------- // Multisample //--------------------- if( pMatchOptions->eMultiSample == DXUTMT_IGNORE_INPUT ) { // Default to no multisampling pOptimalDeviceSettings->pp.MultiSampleType = D3DMULTISAMPLE_NONE; pOptimalDeviceSettings->pp.MultiSampleQuality = 0; } else { pOptimalDeviceSettings->pp.MultiSampleType = pDeviceSettingsIn->pp.MultiSampleType; pOptimalDeviceSettings->pp.MultiSampleQuality = pDeviceSettingsIn->pp.MultiSampleQuality; } //--------------------- // Swap effect //--------------------- if( pMatchOptions->eSwapEffect == DXUTMT_IGNORE_INPUT ) pOptimalDeviceSettings->pp.SwapEffect = D3DSWAPEFFECT_DISCARD; else pOptimalDeviceSettings->pp.SwapEffect = pDeviceSettingsIn->pp.SwapEffect; //--------------------- // Depth stencil //--------------------- if( pMatchOptions->eDepthFormat == DXUTMT_IGNORE_INPUT && pMatchOptions->eStencilFormat == DXUTMT_IGNORE_INPUT ) { UINT nBackBufferBits = DXUTGetD3D9ColorChannelBits( pOptimalDeviceSettings->pp.BackBufferFormat ); if( nBackBufferBits >= 8 ) pOptimalDeviceSettings->pp.AutoDepthStencilFormat = D3DFMT_D32; else pOptimalDeviceSettings->pp.AutoDepthStencilFormat = D3DFMT_D16; } else { pOptimalDeviceSettings->pp.AutoDepthStencilFormat = pDeviceSettingsIn->pp.AutoDepthStencilFormat; } //--------------------- // Present flags //--------------------- if( pMatchOptions->ePresentFlags == DXUTMT_IGNORE_INPUT ) pOptimalDeviceSettings->pp.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL; else pOptimalDeviceSettings->pp.Flags = pDeviceSettingsIn->pp.Flags; //--------------------- // Refresh rate //--------------------- if( pMatchOptions->eRefreshRate == DXUTMT_IGNORE_INPUT ) pOptimalDeviceSettings->pp.FullScreen_RefreshRateInHz = 0; else pOptimalDeviceSettings->pp.FullScreen_RefreshRateInHz = pDeviceSettingsIn->pp.FullScreen_RefreshRateInHz; //--------------------- // Present interval //--------------------- if( pMatchOptions->ePresentInterval == DXUTMT_IGNORE_INPUT ) { // For windowed and fullscreen, default to D3DPRESENT_INTERVAL_DEFAULT // which will wait for the vertical retrace period to prevent tearing. // For benchmarking, use D3DPRESENT_INTERVAL_IMMEDIATE which will // will wait not for the vertical retrace period but may introduce tearing. pOptimalDeviceSettings->pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; } else { pOptimalDeviceSettings->pp.PresentationInterval = pDeviceSettingsIn->pp.PresentationInterval; } } //-------------------------------------------------------------------------------------- // Returns false for any CD3D9EnumDeviceSettingsCombo that doesn't meet the preserve // match options against the input pDeviceSettingsIn. //-------------------------------------------------------------------------------------- bool DXUTDoesD3D9DeviceComboMatchPreserveOptions( CD3D9EnumDeviceSettingsCombo* pDeviceSettingsCombo, DXUTD3D9DeviceSettings* pDeviceSettingsIn, DXUTMatchOptions* pMatchOptions ) { //--------------------- // Adapter ordinal //--------------------- if( pMatchOptions->eAdapterOrdinal == DXUTMT_PRESERVE_INPUT && (pDeviceSettingsCombo->AdapterOrdinal != pDeviceSettingsIn->AdapterOrdinal) ) return false; //--------------------- // Device type //--------------------- if( pMatchOptions->eDeviceType == DXUTMT_PRESERVE_INPUT && (pDeviceSettingsCombo->DeviceType != pDeviceSettingsIn->DeviceType) ) return false; //--------------------- // Windowed //--------------------- if( pMatchOptions->eWindowed == DXUTMT_PRESERVE_INPUT && (pDeviceSettingsCombo->Windowed != pDeviceSettingsIn->pp.Windowed) ) return false; //--------------------- // Adapter format //--------------------- if( pMatchOptions->eAdapterFormat == DXUTMT_PRESERVE_INPUT && (pDeviceSettingsCombo->AdapterFormat != pDeviceSettingsIn->AdapterFormat) ) return false; //--------------------- // Vertex processing //--------------------- // If keep VP and input has HWVP, then skip if this combo doesn't have HWTL if( pMatchOptions->eVertexProcessing == DXUTMT_PRESERVE_INPUT && ((pDeviceSettingsIn->BehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING) != 0) && ((pDeviceSettingsCombo->pDeviceInfo->Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0) ) return false; //--------------------- // Resolution //--------------------- // If keep resolution then check that width and height supported by this combo if( pMatchOptions->eResolution == DXUTMT_PRESERVE_INPUT ) { bool bFound = false; for( int i=0; i< pDeviceSettingsCombo->pAdapterInfo->displayModeList.GetSize(); i++ ) { D3DDISPLAYMODE displayMode = pDeviceSettingsCombo->pAdapterInfo->displayModeList.GetAt( i ); if( displayMode.Format != pDeviceSettingsCombo->AdapterFormat ) continue; // Skip this display mode if it doesn't match the combo's adapter format if( displayMode.Width == pDeviceSettingsIn->pp.BackBufferWidth && displayMode.Height == pDeviceSettingsIn->pp.BackBufferHeight ) { bFound = true; break; } } // If the width and height are not supported by this combo, return false if( !bFound ) return false; } //--------------------- // Back buffer format //--------------------- if( pMatchOptions->eBackBufferFormat == DXUTMT_PRESERVE_INPUT && pDeviceSettingsCombo->BackBufferFormat != pDeviceSettingsIn->pp.BackBufferFormat ) return false; //--------------------- // Back buffer count //--------------------- // No caps for the back buffer count //--------------------- // Multisample //--------------------- if( pMatchOptions->eMultiSample == DXUTMT_PRESERVE_INPUT ) { bool bFound = false; for( int i=0; i
multiSampleTypeList.GetSize(); i++ ) { D3DMULTISAMPLE_TYPE msType = pDeviceSettingsCombo->multiSampleTypeList.GetAt(i); DWORD msQuality = pDeviceSettingsCombo->multiSampleQualityList.GetAt(i); if( msType == pDeviceSettingsIn->pp.MultiSampleType && msQuality > pDeviceSettingsIn->pp.MultiSampleQuality ) { bFound = true; break; } } // If multisample type/quality not supported by this combo, then return false if( !bFound ) return false; } //--------------------- // Swap effect //--------------------- // No caps for swap effects //--------------------- // Depth stencil //--------------------- // If keep depth stencil format then check that the depth stencil format is supported by this combo if( pMatchOptions->eDepthFormat == DXUTMT_PRESERVE_INPUT && pMatchOptions->eStencilFormat == DXUTMT_PRESERVE_INPUT ) { if( pDeviceSettingsIn->pp.AutoDepthStencilFormat != D3DFMT_UNKNOWN && !pDeviceSettingsCombo->depthStencilFormatList.Contains( pDeviceSettingsIn->pp.AutoDepthStencilFormat ) ) return false; } // If keep depth format then check that the depth format is supported by this combo if( pMatchOptions->eDepthFormat == DXUTMT_PRESERVE_INPUT && pDeviceSettingsIn->pp.AutoDepthStencilFormat != D3DFMT_UNKNOWN ) { bool bFound = false; UINT dwDepthBits = DXUTGetDepthBits( pDeviceSettingsIn->pp.AutoDepthStencilFormat ); for( int i=0; i
depthStencilFormatList.GetSize(); i++ ) { D3DFORMAT depthStencilFmt = pDeviceSettingsCombo->depthStencilFormatList.GetAt(i); UINT dwCurDepthBits = DXUTGetDepthBits( depthStencilFmt ); if( dwCurDepthBits - dwDepthBits == 0) bFound = true; } if( !bFound ) return false; } // If keep depth format then check that the depth format is supported by this combo if( pMatchOptions->eStencilFormat == DXUTMT_PRESERVE_INPUT && pDeviceSettingsIn->pp.AutoDepthStencilFormat != D3DFMT_UNKNOWN ) { bool bFound = false; UINT dwStencilBits = DXUTGetStencilBits( pDeviceSettingsIn->pp.AutoDepthStencilFormat ); for( int i=0; i
depthStencilFormatList.GetSize(); i++ ) { D3DFORMAT depthStencilFmt = pDeviceSettingsCombo->depthStencilFormatList.GetAt(i); UINT dwCurStencilBits = DXUTGetStencilBits( depthStencilFmt ); if( dwCurStencilBits - dwStencilBits == 0) bFound = true; } if( !bFound ) return false; } //--------------------- // Present flags //--------------------- // No caps for the present flags //--------------------- // Refresh rate //--------------------- // If keep refresh rate then check that the resolution is supported by this combo if( pMatchOptions->eRefreshRate == DXUTMT_PRESERVE_INPUT ) { bool bFound = false; for( int i=0; i
pAdapterInfo->displayModeList.GetSize(); i++ ) { D3DDISPLAYMODE displayMode = pDeviceSettingsCombo->pAdapterInfo->displayModeList.GetAt( i ); if( displayMode.Format != pDeviceSettingsCombo->AdapterFormat ) continue; if( displayMode.RefreshRate == pDeviceSettingsIn->pp.FullScreen_RefreshRateInHz ) { bFound = true; break; } } // If refresh rate not supported by this combo, then return false if( !bFound ) return false; } //--------------------- // Present interval //--------------------- // If keep present interval then check that the present interval is supported by this combo if( pMatchOptions->ePresentInterval == DXUTMT_PRESERVE_INPUT && !pDeviceSettingsCombo->presentIntervalList.Contains( pDeviceSettingsIn->pp.PresentationInterval ) ) return false; return true; } //-------------------------------------------------------------------------------------- // Returns a ranking number that describes how closely this device // combo matches the optimal combo based on the match options and the optimal device settings //-------------------------------------------------------------------------------------- float DXUTRankD3D9DeviceCombo( CD3D9EnumDeviceSettingsCombo* pDeviceSettingsCombo, DXUTD3D9DeviceSettings* pOptimalDeviceSettings, D3DDISPLAYMODE* pAdapterDesktopDisplayMode ) { float fCurRanking = 0.0f; // Arbitrary weights. Gives preference to the ordinal, device type, and windowed const float fAdapterOrdinalWeight = 1000.0f; const float fDeviceTypeWeight = 100.0f; const float fWindowWeight = 10.0f; const float fAdapterFormatWeight = 1.0f; const float fVertexProcessingWeight = 1.0f; const float fResolutionWeight = 1.0f; const float fBackBufferFormatWeight = 1.0f; const float fMultiSampleWeight = 1.0f; const float fDepthStencilWeight = 1.0f; const float fRefreshRateWeight = 1.0f; const float fPresentIntervalWeight = 1.0f; //--------------------- // Adapter ordinal //--------------------- if( pDeviceSettingsCombo->AdapterOrdinal == pOptimalDeviceSettings->AdapterOrdinal ) fCurRanking += fAdapterOrdinalWeight; //--------------------- // Device type //--------------------- if( pDeviceSettingsCombo->DeviceType == pOptimalDeviceSettings->DeviceType ) fCurRanking += fDeviceTypeWeight; // Slightly prefer HAL if( pDeviceSettingsCombo->DeviceType == D3DDEVTYPE_HAL ) fCurRanking += 0.1f; //--------------------- // Windowed //--------------------- if( pDeviceSettingsCombo->Windowed == pOptimalDeviceSettings->pp.Windowed ) fCurRanking += fWindowWeight; //--------------------- // Adapter format //--------------------- if( pDeviceSettingsCombo->AdapterFormat == pOptimalDeviceSettings->AdapterFormat ) { fCurRanking += fAdapterFormatWeight; } else { int nBitDepthDelta = abs( (long) DXUTGetD3D9ColorChannelBits(pDeviceSettingsCombo->AdapterFormat) - (long) DXUTGetD3D9ColorChannelBits(pOptimalDeviceSettings->AdapterFormat) ); float fScale = __max(0.9f - (float)nBitDepthDelta*0.2f, 0.0f); fCurRanking += fScale * fAdapterFormatWeight; } if( !pDeviceSettingsCombo->Windowed ) { // Slightly prefer when it matches the desktop format or is D3DFMT_X8R8G8B8 bool bAdapterOptimalMatch; if( DXUTGetD3D9ColorChannelBits(pAdapterDesktopDisplayMode->Format) >= 8 ) bAdapterOptimalMatch = (pDeviceSettingsCombo->AdapterFormat == pAdapterDesktopDisplayMode->Format); else bAdapterOptimalMatch = (pDeviceSettingsCombo->AdapterFormat == D3DFMT_X8R8G8B8); if( bAdapterOptimalMatch ) fCurRanking += 0.1f; } //--------------------- // Vertex processing //--------------------- if( (pOptimalDeviceSettings->BehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING) != 0 || (pOptimalDeviceSettings->BehaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING) != 0 ) { if( (pDeviceSettingsCombo->pDeviceInfo->Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) != 0 ) fCurRanking += fVertexProcessingWeight; } // Slightly prefer HW T&L if( (pDeviceSettingsCombo->pDeviceInfo->Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) != 0 ) fCurRanking += 0.1f; //--------------------- // Resolution //--------------------- bool bResolutionFound = false; for( int idm = 0; idm < pDeviceSettingsCombo->pAdapterInfo->displayModeList.GetSize(); idm++ ) { D3DDISPLAYMODE displayMode = pDeviceSettingsCombo->pAdapterInfo->displayModeList.GetAt( idm ); if( displayMode.Format != pDeviceSettingsCombo->AdapterFormat ) continue; if( displayMode.Width == pOptimalDeviceSettings->pp.BackBufferWidth && displayMode.Height == pOptimalDeviceSettings->pp.BackBufferHeight ) bResolutionFound = true; } if( bResolutionFound ) fCurRanking += fResolutionWeight; //--------------------- // Back buffer format //--------------------- if( pDeviceSettingsCombo->BackBufferFormat == pOptimalDeviceSettings->pp.BackBufferFormat ) { fCurRanking += fBackBufferFormatWeight; } else { int nBitDepthDelta = abs( (long) DXUTGetD3D9ColorChannelBits(pDeviceSettingsCombo->BackBufferFormat) - (long) DXUTGetD3D9ColorChannelBits(pOptimalDeviceSettings->pp.BackBufferFormat) ); float fScale = __max(0.9f - (float)nBitDepthDelta*0.2f, 0.0f); fCurRanking += fScale * fBackBufferFormatWeight; } // Check if this back buffer format is the same as // the adapter format since this is preferred. bool bAdapterMatchesBB = (pDeviceSettingsCombo->BackBufferFormat == pDeviceSettingsCombo->AdapterFormat); if( bAdapterMatchesBB ) fCurRanking += 0.1f; //--------------------- // Back buffer count //--------------------- // No caps for the back buffer count //--------------------- // Multisample //--------------------- bool bMultiSampleFound = false; for( int i=0; i
multiSampleTypeList.GetSize(); i++ ) { D3DMULTISAMPLE_TYPE msType = pDeviceSettingsCombo->multiSampleTypeList.GetAt(i); DWORD msQuality = pDeviceSettingsCombo->multiSampleQualityList.GetAt(i); if( msType == pOptimalDeviceSettings->pp.MultiSampleType && msQuality > pOptimalDeviceSettings->pp.MultiSampleQuality ) { bMultiSampleFound = true; break; } } if( bMultiSampleFound ) fCurRanking += fMultiSampleWeight; //--------------------- // Swap effect //--------------------- // No caps for swap effects //--------------------- // Depth stencil //--------------------- if( pDeviceSettingsCombo->depthStencilFormatList.Contains( pOptimalDeviceSettings->pp.AutoDepthStencilFormat ) ) fCurRanking += fDepthStencilWeight; //--------------------- // Present flags //--------------------- // No caps for the present flags //--------------------- // Refresh rate //--------------------- bool bRefreshFound = false; for( int idm = 0; idm < pDeviceSettingsCombo->pAdapterInfo->displayModeList.GetSize(); idm++ ) { D3DDISPLAYMODE displayMode = pDeviceSettingsCombo->pAdapterInfo->displayModeList.GetAt( idm ); if( displayMode.Format != pDeviceSettingsCombo->AdapterFormat ) continue; if( displayMode.RefreshRate == pOptimalDeviceSettings->pp.FullScreen_RefreshRateInHz ) bRefreshFound = true; } if( bRefreshFound ) fCurRanking += fRefreshRateWeight; //--------------------- // Present interval //--------------------- // If keep present interval then check that the present interval is supported by this combo if( pDeviceSettingsCombo->presentIntervalList.Contains( pOptimalDeviceSettings->pp.PresentationInterval ) ) fCurRanking += fPresentIntervalWeight; return fCurRanking; } //-------------------------------------------------------------------------------------- // Builds valid device settings using the match options, the input device settings, and the // best device settings combo found. //-------------------------------------------------------------------------------------- void DXUTBuildValidD3D9DeviceSettings( DXUTD3D9DeviceSettings* pValidDeviceSettings, CD3D9EnumDeviceSettingsCombo* pBestDeviceSettingsCombo, DXUTD3D9DeviceSettings* pDeviceSettingsIn, DXUTMatchOptions* pMatchOptions ) { IDirect3D9* pD3D = DXUTGetD3D9Object(); D3DDISPLAYMODE adapterDesktopDisplayMode; pD3D->GetAdapterDisplayMode( pBestDeviceSettingsCombo->AdapterOrdinal, &adapterDesktopDisplayMode ); // For each setting pick the best, taking into account the match options and // what's supported by the device //--------------------- // Adapter Ordinal //--------------------- // Just using pBestDeviceSettingsCombo->AdapterOrdinal //--------------------- // Device Type //--------------------- // Just using pBestDeviceSettingsCombo->DeviceType //--------------------- // Windowed //--------------------- // Just using pBestDeviceSettingsCombo->Windowed //--------------------- // Adapter Format //--------------------- // Just using pBestDeviceSettingsCombo->AdapterFormat //--------------------- // Vertex processing //--------------------- DWORD dwBestBehaviorFlags = 0; if( pMatchOptions->eVertexProcessing == DXUTMT_PRESERVE_INPUT ) { dwBestBehaviorFlags = pDeviceSettingsIn->BehaviorFlags; } else if( pMatchOptions->eVertexProcessing == DXUTMT_IGNORE_INPUT ) { // The framework defaults to HWVP if available otherwise use SWVP if ((pBestDeviceSettingsCombo->pDeviceInfo->Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) != 0) dwBestBehaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING; else dwBestBehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING; } else // if( pMatchOptions->eVertexProcessing == DXUTMT_CLOSEST_TO_INPUT ) { // Default to input, and fallback to SWVP if HWVP not available dwBestBehaviorFlags = pDeviceSettingsIn->BehaviorFlags; if ((pBestDeviceSettingsCombo->pDeviceInfo->Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0 && ( (dwBestBehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING) != 0 || (dwBestBehaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING) != 0) ) { dwBestBehaviorFlags &= ~D3DCREATE_HARDWARE_VERTEXPROCESSING; dwBestBehaviorFlags &= ~D3DCREATE_MIXED_VERTEXPROCESSING; dwBestBehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING; } // One of these must be selected if( (dwBestBehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING) == 0 && (dwBestBehaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING) == 0 && (dwBestBehaviorFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING) == 0 ) { if ((pBestDeviceSettingsCombo->pDeviceInfo->Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) != 0) dwBestBehaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING; else dwBestBehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING; } } //--------------------- // Resolution //--------------------- D3DDISPLAYMODE bestDisplayMode; if( pMatchOptions->eResolution == DXUTMT_PRESERVE_INPUT ) { bestDisplayMode.Width = pDeviceSettingsIn->pp.BackBufferWidth; bestDisplayMode.Height = pDeviceSettingsIn->pp.BackBufferHeight; } else { D3DDISPLAYMODE displayModeIn; if( pMatchOptions->eResolution == DXUTMT_CLOSEST_TO_INPUT && pDeviceSettingsIn ) { displayModeIn.Width = pDeviceSettingsIn->pp.BackBufferWidth; displayModeIn.Height = pDeviceSettingsIn->pp.BackBufferHeight; } else // if( pMatchOptions->eResolution == DXUTMT_IGNORE_INPUT ) { if( pBestDeviceSettingsCombo->Windowed ) { // The framework defaults to 640x480 for windowed displayModeIn.Width = 640; displayModeIn.Height = 480; } else { // The framework defaults to desktop resolution for fullscreen to try to avoid slow mode change displayModeIn.Width = adapterDesktopDisplayMode.Width; displayModeIn.Height = adapterDesktopDisplayMode.Height; } } // Call a helper function to find the closest valid display mode to the optimal DXUTFindValidD3D9Resolution( pBestDeviceSettingsCombo, displayModeIn, &bestDisplayMode ); } //--------------------- // Back Buffer Format //--------------------- // Just using pBestDeviceSettingsCombo->BackBufferFormat //--------------------- // Back buffer count //--------------------- UINT bestBackBufferCount; if( pMatchOptions->eBackBufferCount == DXUTMT_PRESERVE_INPUT ) { bestBackBufferCount = pDeviceSettingsIn->pp.BackBufferCount; } else if( pMatchOptions->eBackBufferCount == DXUTMT_IGNORE_INPUT ) { // Default to double buffering. Causes less latency than triple buffering bestBackBufferCount = 1; } else // if( pMatchOptions->eBackBufferCount == DXUTMT_CLOSEST_TO_INPUT ) { bestBackBufferCount = pDeviceSettingsIn->pp.BackBufferCount; if( bestBackBufferCount > 3 ) bestBackBufferCount = 3; if( bestBackBufferCount < 1 ) bestBackBufferCount = 1; } //--------------------- // Multisample //--------------------- D3DMULTISAMPLE_TYPE bestMultiSampleType; DWORD bestMultiSampleQuality; if( pDeviceSettingsIn && pDeviceSettingsIn->pp.SwapEffect != D3DSWAPEFFECT_DISCARD ) { // Swap effect is not set to discard so multisampling has to off bestMultiSampleType = D3DMULTISAMPLE_NONE; bestMultiSampleQuality = 0; } else { if( pMatchOptions->eMultiSample == DXUTMT_PRESERVE_INPUT ) { bestMultiSampleType = pDeviceSettingsIn->pp.MultiSampleType; bestMultiSampleQuality = pDeviceSettingsIn->pp.MultiSampleQuality; } else if( pMatchOptions->eMultiSample == DXUTMT_IGNORE_INPUT ) { // Default to no multisampling (always supported) bestMultiSampleType = D3DMULTISAMPLE_NONE; bestMultiSampleQuality = 0; } else if( pMatchOptions->eMultiSample == DXUTMT_CLOSEST_TO_INPUT ) { // Default to no multisampling (always supported) bestMultiSampleType = D3DMULTISAMPLE_NONE; bestMultiSampleQuality = 0; for( int i=0; i < pBestDeviceSettingsCombo->multiSampleTypeList.GetSize(); i++ ) { D3DMULTISAMPLE_TYPE type = pBestDeviceSettingsCombo->multiSampleTypeList.GetAt(i); DWORD qualityLevels = pBestDeviceSettingsCombo->multiSampleQualityList.GetAt(i); // Check whether supported type is closer to the input than our current best if( abs(type - pDeviceSettingsIn->pp.MultiSampleType) < abs(bestMultiSampleType - pDeviceSettingsIn->pp.MultiSampleType) ) { bestMultiSampleType = type; bestMultiSampleQuality = __min( qualityLevels - 1, pDeviceSettingsIn->pp.MultiSampleQuality ); } } } else { // Error case bestMultiSampleType = D3DMULTISAMPLE_NONE; bestMultiSampleQuality = 0; } } //--------------------- // Swap effect //--------------------- D3DSWAPEFFECT bestSwapEffect; if( pMatchOptions->eSwapEffect == DXUTMT_PRESERVE_INPUT ) { bestSwapEffect = pDeviceSettingsIn->pp.SwapEffect; } else if( pMatchOptions->eSwapEffect == DXUTMT_IGNORE_INPUT ) { bestSwapEffect = D3DSWAPEFFECT_DISCARD; } else // if( pMatchOptions->eSwapEffect == DXUTMT_CLOSEST_TO_INPUT ) { bestSwapEffect = pDeviceSettingsIn->pp.SwapEffect; // Swap effect has to be one of these 3 if( bestSwapEffect != D3DSWAPEFFECT_DISCARD && bestSwapEffect != D3DSWAPEFFECT_FLIP && bestSwapEffect != D3DSWAPEFFECT_COPY ) { bestSwapEffect = D3DSWAPEFFECT_DISCARD; } } //--------------------- // Depth stencil //--------------------- D3DFORMAT bestDepthStencilFormat; bool bestEnableAutoDepthStencil; CGrowableArray< int > depthStencilRanking; depthStencilRanking.SetSize( pBestDeviceSettingsCombo->depthStencilFormatList.GetSize() ); UINT dwBackBufferBitDepth = DXUTGetD3D9ColorChannelBits( pBestDeviceSettingsCombo->BackBufferFormat ); UINT dwInputDepthBitDepth = 0; if( pDeviceSettingsIn ) dwInputDepthBitDepth = DXUTGetDepthBits( pDeviceSettingsIn->pp.AutoDepthStencilFormat ); for( int i=0; i
depthStencilFormatList.GetSize(); i++ ) { D3DFORMAT curDepthStencilFmt = pBestDeviceSettingsCombo->depthStencilFormatList.GetAt(i); DWORD dwCurDepthBitDepth = DXUTGetDepthBits( curDepthStencilFmt ); int nRanking; if( pMatchOptions->eDepthFormat == DXUTMT_PRESERVE_INPUT ) { // Need to match bit depth of input if(dwCurDepthBitDepth == dwInputDepthBitDepth) nRanking = 0; else nRanking = 10000; } else if( pMatchOptions->eDepthFormat == DXUTMT_IGNORE_INPUT ) { // Prefer match of backbuffer bit depth nRanking = abs((int)dwCurDepthBitDepth - (int)dwBackBufferBitDepth*4); } else // if( pMatchOptions->eDepthFormat == DXUTMT_CLOSEST_TO_INPUT ) { // Prefer match of input depth format bit depth nRanking = abs((int)dwCurDepthBitDepth - (int)dwInputDepthBitDepth); } depthStencilRanking.Add( nRanking ); } UINT dwInputStencilBitDepth = 0; if( pDeviceSettingsIn ) dwInputStencilBitDepth = DXUTGetStencilBits( pDeviceSettingsIn->pp.AutoDepthStencilFormat ); for( int i=0; i
depthStencilFormatList.GetSize(); i++ ) { D3DFORMAT curDepthStencilFmt = pBestDeviceSettingsCombo->depthStencilFormatList.GetAt(i); int nRanking = depthStencilRanking.GetAt(i); DWORD dwCurStencilBitDepth = DXUTGetStencilBits( curDepthStencilFmt ); if( pMatchOptions->eStencilFormat == DXUTMT_PRESERVE_INPUT ) { // Need to match bit depth of input if(dwCurStencilBitDepth == dwInputStencilBitDepth) nRanking += 0; else nRanking += 10000; } else if( pMatchOptions->eStencilFormat == DXUTMT_IGNORE_INPUT ) { // Prefer 0 stencil bit depth nRanking += dwCurStencilBitDepth; } else // if( pMatchOptions->eStencilFormat == DXUTMT_CLOSEST_TO_INPUT ) { // Prefer match of input stencil format bit depth nRanking += abs((int)dwCurStencilBitDepth - (int)dwInputStencilBitDepth); } depthStencilRanking.SetAt( i, nRanking ); } int nBestRanking = 100000; int nBestIndex = -1; for( int i=0; i
depthStencilFormatList.GetSize(); i++ ) { int nRanking = depthStencilRanking.GetAt(i); if( nRanking < nBestRanking ) { nBestRanking = nRanking; nBestIndex = i; } } if( nBestIndex >= 0 ) { bestDepthStencilFormat = pBestDeviceSettingsCombo->depthStencilFormatList.GetAt(nBestIndex); bestEnableAutoDepthStencil = true; } else { bestDepthStencilFormat = D3DFMT_UNKNOWN; bestEnableAutoDepthStencil = false; } //--------------------- // Present flags //--------------------- DWORD dwBestFlags; if( pMatchOptions->ePresentFlags == DXUTMT_PRESERVE_INPUT ) { dwBestFlags = pDeviceSettingsIn->pp.Flags; } else if( pMatchOptions->ePresentFlags == DXUTMT_IGNORE_INPUT ) { dwBestFlags = 0; if( bestEnableAutoDepthStencil ) dwBestFlags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL; } else // if( pMatchOptions->ePresentFlags == DXUTMT_CLOSEST_TO_INPUT ) { dwBestFlags = pDeviceSettingsIn->pp.Flags; if( bestEnableAutoDepthStencil ) dwBestFlags |= D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL; } //--------------------- // Refresh rate //--------------------- if( pBestDeviceSettingsCombo->Windowed ) { // Must be 0 for windowed bestDisplayMode.RefreshRate = 0; } else { if( pMatchOptions->eRefreshRate == DXUTMT_PRESERVE_INPUT ) { bestDisplayMode.RefreshRate = pDeviceSettingsIn->pp.FullScreen_RefreshRateInHz; } else { UINT refreshRateMatch; if( pMatchOptions->eRefreshRate == DXUTMT_CLOSEST_TO_INPUT ) { refreshRateMatch = pDeviceSettingsIn->pp.FullScreen_RefreshRateInHz; } else // if( pMatchOptions->eRefreshRate == DXUTMT_IGNORE_INPUT ) { refreshRateMatch = adapterDesktopDisplayMode.RefreshRate; } bestDisplayMode.RefreshRate = 0; if( refreshRateMatch != 0 ) { int nBestRefreshRanking = 100000; CGrowableArray
* pDisplayModeList = &pBestDeviceSettingsCombo->pAdapterInfo->displayModeList; for( int iDisplayMode=0; iDisplayMode
GetSize(); iDisplayMode++ ) { D3DDISPLAYMODE displayMode = pDisplayModeList->GetAt(iDisplayMode); if( displayMode.Format != pBestDeviceSettingsCombo->AdapterFormat || displayMode.Height != bestDisplayMode.Height || displayMode.Width != bestDisplayMode.Width ) continue; // Skip display modes that don't match // Find the delta between the current refresh rate and the optimal refresh rate int nCurRanking = abs((int)displayMode.RefreshRate - (int)refreshRateMatch); if( nCurRanking < nBestRefreshRanking ) { bestDisplayMode.RefreshRate = displayMode.RefreshRate; nBestRefreshRanking = nCurRanking; // Stop if perfect match found if( nBestRefreshRanking == 0 ) break; } } } } } //--------------------- // Present interval //--------------------- UINT bestPresentInterval; if( pMatchOptions->ePresentInterval == DXUTMT_PRESERVE_INPUT ) { bestPresentInterval = pDeviceSettingsIn->pp.PresentationInterval; } else if( pMatchOptions->ePresentInterval == DXUTMT_IGNORE_INPUT ) { // For windowed and fullscreen, default to D3DPRESENT_INTERVAL_DEFAULT // which will wait for the vertical retrace period to prevent tearing. // For benchmarking, use D3DPRESENT_INTERVAL_DEFAULT which will // will wait not for the vertical retrace period but may introduce tearing. bestPresentInterval = D3DPRESENT_INTERVAL_DEFAULT; } else // if( pMatchOptions->ePresentInterval == DXUTMT_CLOSEST_TO_INPUT ) { if( pBestDeviceSettingsCombo->presentIntervalList.Contains( pDeviceSettingsIn->pp.PresentationInterval ) ) { bestPresentInterval = pDeviceSettingsIn->pp.PresentationInterval; } else { bestPresentInterval = D3DPRESENT_INTERVAL_DEFAULT; } } // Fill the device settings struct ZeroMemory( pValidDeviceSettings, sizeof(DXUTD3D9DeviceSettings) ); pValidDeviceSettings->AdapterOrdinal = pBestDeviceSettingsCombo->AdapterOrdinal; pValidDeviceSettings->DeviceType = pBestDeviceSettingsCombo->DeviceType; pValidDeviceSettings->AdapterFormat = pBestDeviceSettingsCombo->AdapterFormat; pValidDeviceSettings->BehaviorFlags = dwBestBehaviorFlags; pValidDeviceSettings->pp.BackBufferWidth = bestDisplayMode.Width; pValidDeviceSettings->pp.BackBufferHeight = bestDisplayMode.Height; pValidDeviceSettings->pp.BackBufferFormat = pBestDeviceSettingsCombo->BackBufferFormat; pValidDeviceSettings->pp.BackBufferCount = bestBackBufferCount; pValidDeviceSettings->pp.MultiSampleType = bestMultiSampleType; pValidDeviceSettings->pp.MultiSampleQuality = bestMultiSampleQuality; pValidDeviceSettings->pp.SwapEffect = bestSwapEffect; pValidDeviceSettings->pp.hDeviceWindow = pBestDeviceSettingsCombo->Windowed ? DXUTGetHWNDDeviceWindowed() : DXUTGetHWNDDeviceFullScreen(); pValidDeviceSettings->pp.Windowed = pBestDeviceSettingsCombo->Windowed; pValidDeviceSettings->pp.EnableAutoDepthStencil = bestEnableAutoDepthStencil; pValidDeviceSettings->pp.AutoDepthStencilFormat = bestDepthStencilFormat; pValidDeviceSettings->pp.Flags = dwBestFlags; pValidDeviceSettings->pp.FullScreen_RefreshRateInHz = bestDisplayMode.RefreshRate; pValidDeviceSettings->pp.PresentationInterval = bestPresentInterval; } //-------------------------------------------------------------------------------------- // Internal helper function to find the closest allowed display mode to the optimal //-------------------------------------------------------------------------------------- HRESULT DXUTFindValidD3D9Resolution( CD3D9EnumDeviceSettingsCombo* pBestDeviceSettingsCombo, D3DDISPLAYMODE displayModeIn, D3DDISPLAYMODE* pBestDisplayMode ) { D3DDISPLAYMODE bestDisplayMode; ZeroMemory( &bestDisplayMode, sizeof(D3DDISPLAYMODE) ); if( pBestDeviceSettingsCombo->Windowed ) { // In windowed mode, all resolutions are valid but restritions still apply // on the size of the window. See DXUTChangeD3D9Device() for details *pBestDisplayMode = displayModeIn; } else { int nBestRanking = 100000; int nCurRanking; CGrowableArray
* pDisplayModeList = &pBestDeviceSettingsCombo->pAdapterInfo->displayModeList; for( int iDisplayMode=0; iDisplayMode
GetSize(); iDisplayMode++ ) { D3DDISPLAYMODE displayMode = pDisplayModeList->GetAt(iDisplayMode); // Skip display modes that don't match the combo's adapter format if( displayMode.Format != pBestDeviceSettingsCombo->AdapterFormat ) continue; // Find the delta between the current width/height and the optimal width/height nCurRanking = abs((int)displayMode.Width - (int)displayModeIn.Width) + abs((int)displayMode.Height- (int)displayModeIn.Height); if( nCurRanking < nBestRanking ) { bestDisplayMode = displayMode; nBestRanking = nCurRanking; // Stop if perfect match found if( nBestRanking == 0 ) break; } } if( bestDisplayMode.Width == 0 ) { *pBestDisplayMode = displayModeIn; return E_FAIL; // No valid display modes found } *pBestDisplayMode = bestDisplayMode; } return S_OK; } //====================================================================================== //====================================================================================== // Direct3D 10 section //====================================================================================== //====================================================================================== CD3D10Enumeration* g_pDXUTD3D10Enumeration = NULL; HRESULT WINAPI DXUTCreateD3D10Enumeration() { if( g_pDXUTD3D10Enumeration == NULL ) { g_pDXUTD3D10Enumeration = new CD3D10Enumeration(); if( NULL == g_pDXUTD3D10Enumeration ) return E_OUTOFMEMORY; } return S_OK; } void WINAPI DXUTDestroyD3D10Enumeration() { SAFE_DELETE( g_pDXUTD3D10Enumeration ); } class DXUTMemoryHelperD3D10Enum { public: DXUTMemoryHelperD3D10Enum() { DXUTCreateD3D10Enumeration(); } ~DXUTMemoryHelperD3D10Enum() { DXUTDestroyD3D10Enumeration(); } }; //-------------------------------------------------------------------------------------- CD3D10Enumeration* WINAPI DXUTGetD3D10Enumeration( bool bForceEnumerate, bool bEnumerateAllAdapterFormats ) { // Using an static class with accessor function to allow control of the construction order static DXUTMemoryHelperD3D10Enum d3d10enumMemory; if( g_pDXUTD3D10Enumeration && ( !g_pDXUTD3D10Enumeration->HasEnumerated() || bForceEnumerate ) ) { g_pDXUTD3D10Enumeration->SetEnumerateAllAdapterFormats( bEnumerateAllAdapterFormats, false ); LPDXUTCALLBACKISD3D10DEVICEACCEPTABLE pCallbackIsDeviceAcceptable; void* pUserContext; DXUTGetCallbackD3D10DeviceAcceptable( &pCallbackIsDeviceAcceptable, &pUserContext ); g_pDXUTD3D10Enumeration->Enumerate( pCallbackIsDeviceAcceptable, pUserContext ); } return g_pDXUTD3D10Enumeration; } //-------------------------------------------------------------------------------------- CD3D10Enumeration::CD3D10Enumeration() { m_bHasEnumerated = false; m_IsD3D10DeviceAcceptableFunc = NULL; m_pIsD3D10DeviceAcceptableFuncUserContext = NULL; m_nMinWidth = 640; m_nMinHeight = 480; m_nMaxWidth = UINT_MAX; m_nMaxHeight = UINT_MAX; m_bEnumerateAllAdapterFormats = false; m_nRefreshMin = 0; m_nRefreshMax = UINT_MAX; ResetPossibleDepthStencilFormats(); } //-------------------------------------------------------------------------------------- CD3D10Enumeration::~CD3D10Enumeration() { ClearAdapterInfoList(); } //-------------------------------------------------------------------------------------- // Enumerate for each adapter all of the supported display modes, // device types, adapter formats, back buffer formats, window/full screen support, // depth stencil formats, multisampling types/qualities, and presentations intervals. // // For each combination of device type (HAL/REF), adapter format, back buffer format, and // IsWindowed it will call the app's ConfirmDevice callback. This allows the app // to reject or allow that combination based on its caps/etc. It also allows the // app to change the BehaviorFlags. The BehaviorFlags defaults non-pure HWVP // if supported otherwise it will default to SWVP, however the app can change this // through the ConfirmDevice callback. //-------------------------------------------------------------------------------------- HRESULT CD3D10Enumeration::Enumerate( LPDXUTCALLBACKISD3D10DEVICEACCEPTABLE IsD3D10DeviceAcceptableFunc, void* pIsD3D10DeviceAcceptableFuncUserContext ) { CDXUTPerfEventGenerator eventGenerator( DXUT_PERFEVENTCOLOR, L"DXUT D3D10 Enumeration" ); HRESULT hr; IDXGIFactory* pFactory = DXUTGetDXGIFactory(); if( pFactory == NULL ) return E_FAIL; m_bHasEnumerated = true; m_IsD3D10DeviceAcceptableFunc = IsD3D10DeviceAcceptableFunc; m_pIsD3D10DeviceAcceptableFuncUserContext = pIsD3D10DeviceAcceptableFuncUserContext; ClearAdapterInfoList(); for( int index = 0; ; ++index ) { IDXGIAdapter *pAdapter = NULL; hr = pFactory->EnumAdapters( index, &pAdapter ); if( FAILED(hr) ) // DXGIERR_NOT_FOUND is expected when the end of the list is hit break; CD3D10EnumAdapterInfo *pAdapterInfo = new CD3D10EnumAdapterInfo; if( !pAdapterInfo ) { SAFE_RELEASE( pAdapter ); return E_OUTOFMEMORY; } ZeroMemory( pAdapterInfo, sizeof(CD3D10EnumAdapterInfo) ); pAdapterInfo->AdapterOrdinal = index; pAdapter->GetDesc( &pAdapterInfo->AdapterDesc ); pAdapterInfo->m_pAdapter = pAdapter; // Enumerate the device driver types on the adapter. hr = EnumerateDevices( pAdapterInfo ); if( FAILED( hr ) ) { delete pAdapterInfo; continue; } hr = EnumerateOutputs( pAdapterInfo ); if( FAILED( hr ) || pAdapterInfo->outputInfoList.GetSize() <= 0 ) { delete pAdapterInfo; continue; } // Get info for each devicecombo on this device if( FAILED( hr = EnumerateDeviceCombos( pFactory, pAdapterInfo ) ) ) { delete pAdapterInfo; continue; } hr = m_AdapterInfoList.Add( pAdapterInfo ); if( FAILED( hr ) ) { delete pAdapterInfo; return hr; } } // // Check for 2 or more adapters with the same name. Append the name // with some instance number if that's the case to help distinguish // them. // bool bUniqueDesc = true; CD3D10EnumAdapterInfo* pAdapterInfo; for( int i = 0; i < m_AdapterInfoList.GetSize(); i++ ) { CD3D10EnumAdapterInfo* pAdapterInfo1 = m_AdapterInfoList.GetAt(i); for( int j = i+1; j < m_AdapterInfoList.GetSize(); j++ ) { CD3D10EnumAdapterInfo* pAdapterInfo2 = m_AdapterInfoList.GetAt(j); if( wcsncmp( pAdapterInfo1->AdapterDesc.Description, pAdapterInfo2->AdapterDesc.Description, DXGI_MAX_DEVICE_IDENTIFIER_STRING ) == 0 ) { bUniqueDesc = false; break; } } if( !bUniqueDesc ) break; } for( int i = 0; i < m_AdapterInfoList.GetSize(); i++ ) { pAdapterInfo = m_AdapterInfoList.GetAt(i); StringCchCopy( pAdapterInfo->szUniqueDescription, 100, pAdapterInfo->AdapterDesc.Description ); if( !bUniqueDesc ) { WCHAR sz[100]; StringCchPrintf( sz, 100, L" (#%d)", pAdapterInfo->AdapterOrdinal ); StringCchCat( pAdapterInfo->szUniqueDescription, DXGI_MAX_DEVICE_IDENTIFIER_STRING, sz ); } } return S_OK; } //-------------------------------------------------------------------------------------- HRESULT CD3D10Enumeration::EnumerateOutputs( CD3D10EnumAdapterInfo* pAdapterInfo ) { HRESULT hr; IDXGIOutput *pOutput; for( int iOutput = 0; ; ++iOutput ) { pOutput = NULL; hr = pAdapterInfo->m_pAdapter->EnumOutputs( iOutput, &pOutput ); if( DXGI_ERROR_NOT_FOUND == hr ) { return S_OK; } else if (FAILED(hr)) { return hr; //Something bad happened. } else //Success! { CD3D10EnumOutputInfo *pOutputInfo = new CD3D10EnumOutputInfo; if( !pOutputInfo ) { SAFE_RELEASE( pOutput ); return E_OUTOFMEMORY; } ZeroMemory( pOutputInfo, sizeof(CD3D10EnumOutputInfo) ); pOutput->GetDesc( &pOutputInfo->Desc ); pOutputInfo->Output = iOutput; pOutputInfo->m_pOutput = pOutput; EnumerateDisplayModes( pOutputInfo ); if( pOutputInfo->displayModeList.GetSize() <= 0 ) { // If this output has no valid display mode, do not save it. delete pOutputInfo; continue; } hr = pAdapterInfo->outputInfoList.Add( pOutputInfo ); if( FAILED(hr) ) { delete pOutputInfo; return hr; } } } } //-------------------------------------------------------------------------------------- HRESULT CD3D10Enumeration::EnumerateDisplayModes( CD3D10EnumOutputInfo *pOutputInfo ) { HRESULT hr = S_OK; const DXGI_FORMAT allowedAdapterFormatArray[] = { DXGI_FORMAT_R8G8B8A8_UNORM, //This is DXUT's preferred mode DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, }; int allowedAdapterFormatArrayCount = sizeof(allowedAdapterFormatArray) / sizeof(allowedAdapterFormatArray[0]); // The fast path only enumerates R8G8B8A8_UNORM modes if( !m_bEnumerateAllAdapterFormats ) allowedAdapterFormatArrayCount = 1; for( int f = 0; f < allowedAdapterFormatArrayCount; ++f ) { // Fast-path: Try to grab at least 512 modes. // This is to avoid calling GetDisplayModeList more times than necessary. // GetDisplayModeList is an expensive call. UINT NumModes = 512; DXGI_MODE_DESC *pDesc = new DXGI_MODE_DESC[ NumModes ]; assert( pDesc ); if( !pDesc ) return E_OUTOFMEMORY; hr = pOutputInfo->m_pOutput->GetDisplayModeList(allowedAdapterFormatArray[f], 0, &NumModes, pDesc ); if( DXGI_ERROR_NOT_FOUND == hr ) { SAFE_DELETE_ARRAY( pDesc ); NumModes = 0; break; } else if( MAKE_DXGI_HRESULT( 34 ) == hr && DXGI_FORMAT_R8G8B8A8_UNORM == allowedAdapterFormatArray[f] ) { // DXGI cannot enumerate display modes over a remote session. Therefore, create a fake display // mode for the current screen resolution for the remote session. if( 0 != GetSystemMetrics(0x1000) ) // SM_REMOTESESSION { DEVMODE DevMode; DevMode.dmSize = sizeof(DEVMODE); if( EnumDisplaySettings( NULL, ENUM_CURRENT_SETTINGS, &DevMode ) ) { NumModes = 1; pDesc[0].Width = DevMode.dmPelsWidth; pDesc[0].Height = DevMode.dmPelsHeight; pDesc[0].Format = DXGI_FORMAT_R8G8B8A8_UNORM; pDesc[0].RefreshRate.Numerator = 60; pDesc[0].RefreshRate.Denominator = 1; pDesc[0].ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE; pDesc[0].Scaling = DXGI_MODE_SCALING_CENTERED; hr = S_OK; } } } else if( DXGI_ERROR_MORE_DATA == hr ) { // Slow path. There were more than 512 modes. SAFE_DELETE_ARRAY( pDesc ); hr = pOutputInfo->m_pOutput->GetDisplayModeList(allowedAdapterFormatArray[f], 0, &NumModes, NULL ); if( FAILED(hr) ) { NumModes = 0; break; } DXGI_MODE_DESC *pDesc = new DXGI_MODE_DESC[ NumModes ]; assert( pDesc ); if( !pDesc ) return E_OUTOFMEMORY; hr = pOutputInfo->m_pOutput->GetDisplayModeList(allowedAdapterFormatArray[f], 0, &NumModes, pDesc ); if( FAILED(hr) ) { SAFE_DELETE_ARRAY( pDesc ); NumModes = 0; break; } } if( 0 == NumModes && 0 == f ) { // No R8G8B8A8_UNORM modes! // Abort the fast-path if we're on it allowedAdapterFormatArrayCount = sizeof(allowedAdapterFormatArray) / sizeof(allowedAdapterFormatArray[0]); SAFE_DELETE_ARRAY( pDesc ); continue; } if( SUCCEEDED( hr ) ) { for( UINT m=0; m
displayModeList.Add( pDesc[m] ); } } SAFE_DELETE_ARRAY( pDesc ); } return hr; } //-------------------------------------------------------------------------------------- HRESULT CD3D10Enumeration::EnumerateDevices( CD3D10EnumAdapterInfo *pAdapterInfo ) { HRESULT hr; const D3D10_DRIVER_TYPE devTypeArray[] = { D3D10_DRIVER_TYPE_HARDWARE, D3D10_DRIVER_TYPE_REFERENCE, }; const UINT devTypeArrayCount = sizeof(devTypeArray) / sizeof(devTypeArray[0]); // Enumerate each Direct3D device type for( UINT iDeviceType = 0; iDeviceType < devTypeArrayCount; iDeviceType++ ) { CD3D10EnumDeviceInfo* pDeviceInfo = new CD3D10EnumDeviceInfo; if( pDeviceInfo == NULL ) return E_OUTOFMEMORY; // Fill struct w/ AdapterOrdinal and D3DX10_DRIVER_TYPE pDeviceInfo->AdapterOrdinal = pAdapterInfo->AdapterOrdinal; pDeviceInfo->DeviceType = devTypeArray[iDeviceType]; // Call D3D10CreateDevice to ensure that this is a D3D10 device. ID3D10Device *pd3dDevice = NULL; IDXGIAdapter* pAdapter = NULL; if( devTypeArray[iDeviceType] == D3D10_DRIVER_TYPE_HARDWARE ) pAdapter = pAdapterInfo->m_pAdapter; hr = DXUT_Dynamic_D3D10CreateDevice( pAdapter, devTypeArray[iDeviceType], (HMODULE)0, 0, NULL, D3D10_SDK_VERSION, &pd3dDevice ); if( FAILED( hr ) ) { delete pDeviceInfo; continue; } if( devTypeArray[iDeviceType] != D3D10_DRIVER_TYPE_HARDWARE ) { IDXGIDevice* pDXGIDev = NULL; hr = pd3dDevice->QueryInterface( __uuidof( IDXGIDevice ), (LPVOID*)&pDXGIDev ); if( SUCCEEDED(hr) && pDXGIDev ) { SAFE_RELEASE( pAdapterInfo->m_pAdapter ); pDXGIDev->GetAdapter( &pAdapterInfo->m_pAdapter ); } SAFE_RELEASE( pDXGIDev ); } SAFE_RELEASE( pd3dDevice ); pAdapterInfo->deviceInfoList.Add( pDeviceInfo ); } return S_OK; } //-------------------------------------------------------------------------------------- HRESULT CD3D10Enumeration::EnumerateDeviceCombos( IDXGIFactory *pFactory, CD3D10EnumAdapterInfo* pAdapterInfo ) { // Iterate through each combination of device driver type, output, // adapter format, and backbuffer format to build the adapter's device combo list. // for( int output = 0; output < pAdapterInfo->outputInfoList.GetSize(); ++output ) { CD3D10EnumOutputInfo *pOutputInfo = pAdapterInfo->outputInfoList.GetAt( output ); for( int device = 0; device < pAdapterInfo->deviceInfoList.GetSize(); ++device ) { CD3D10EnumDeviceInfo *pDeviceInfo = pAdapterInfo->deviceInfoList.GetAt( device ); const DXGI_FORMAT backBufferFormatArray[] = { DXGI_FORMAT_R8G8B8A8_UNORM, //This is DXUT's preferred mode DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, }; const UINT backBufferFormatArrayCount = sizeof(backBufferFormatArray) / sizeof(backBufferFormatArray[0]); for( UINT iBackBufferFormat = 0; iBackBufferFormat < backBufferFormatArrayCount; iBackBufferFormat++ ) { DXGI_FORMAT backBufferFormat = backBufferFormatArray[iBackBufferFormat]; for( int nWindowed = 0; nWindowed < 2; nWindowed++ ) { if( !nWindowed && pOutputInfo->displayModeList.GetSize() == 0 ) continue; // determine if there are any modes for this particular format UINT iModes = 0; for( int i=0; i
displayModeList.GetSize(); i++ ) { if( backBufferFormat == pOutputInfo->displayModeList.GetAt(i).Format ) iModes ++; } if( 0 == iModes ) continue; // If an application callback function has been provided, make sure this device // is acceptable to the app. if( m_IsD3D10DeviceAcceptableFunc != NULL ) { if( !m_IsD3D10DeviceAcceptableFunc( pAdapterInfo->AdapterOrdinal, output, pDeviceInfo->DeviceType, backBufferFormat, FALSE != nWindowed, m_pIsD3D10DeviceAcceptableFuncUserContext ) ) continue; } // At this point, we have an adapter/device/backbufferformat/iswindowed // DeviceCombo that is supported by the system. We still // need to find one or more suitable depth/stencil buffer format, // multisample type, and present interval. CD3D10EnumDeviceSettingsCombo* pDeviceCombo = new CD3D10EnumDeviceSettingsCombo; if( pDeviceCombo == NULL ) return E_OUTOFMEMORY; pDeviceCombo->AdapterOrdinal = pDeviceInfo->AdapterOrdinal; pDeviceCombo->DeviceType = pDeviceInfo->DeviceType; pDeviceCombo->BackBufferFormat = backBufferFormat; pDeviceCombo->Windowed = (nWindowed != 0); pDeviceCombo->Output = pOutputInfo->Output; pDeviceCombo->pAdapterInfo = pAdapterInfo; pDeviceCombo->pDeviceInfo = pDeviceInfo; pDeviceCombo->pOutputInfo = pOutputInfo; BuildMultiSampleQualityList( backBufferFormat, pDeviceCombo ); if( FAILED( pAdapterInfo->deviceSettingsComboList.Add( pDeviceCombo ) ) ) delete pDeviceCombo; } } } } return S_OK; } //-------------------------------------------------------------------------------------- // Release all the allocated CD3D10EnumAdapterInfo objects and empty the list //-------------------------------------------------------------------------------------- void CD3D10Enumeration::ClearAdapterInfoList() { CD3D10EnumAdapterInfo* pAdapterInfo; for( int i=0; i
Enumerate( pCallbackIsDeviceAcceptable, pUserContext ); } } //-------------------------------------------------------------------------------------- void CD3D10Enumeration::BuildMultiSampleQualityList( DXGI_FORMAT fmt, CD3D10EnumDeviceSettingsCombo* pDeviceCombo ) { ID3D10Device* pd3dDevice = NULL; IDXGIAdapter* pAdapter = NULL; if( pDeviceCombo->DeviceType == D3D10_DRIVER_TYPE_HARDWARE ) DXUTGetDXGIFactory()->EnumAdapters( pDeviceCombo->pAdapterInfo->AdapterOrdinal, &pAdapter ); if( FAILED( DXUT_Dynamic_D3D10CreateDevice( pAdapter, pDeviceCombo->DeviceType, (HMODULE)0, 0, NULL, D3D10_SDK_VERSION, &pd3dDevice ) ) ) return; for( int i = 1; i <= D3D10_MAX_MULTISAMPLE_SAMPLE_COUNT ; ++i ) { UINT Quality; if( SUCCEEDED( pd3dDevice->CheckMultisampleQualityLevels( fmt, i, &Quality ) ) && Quality > 0 ) { pDeviceCombo->multiSampleCountList.Add( i ); pDeviceCombo->multiSampleQualityList.Add( Quality ); } } SAFE_RELEASE( pd3dDevice ); } //-------------------------------------------------------------------------------------- // Call GetAdapterInfoList() after Enumerate() to get a STL vector of // CD3D10EnumAdapterInfo* //-------------------------------------------------------------------------------------- CGrowableArray
* CD3D10Enumeration::GetAdapterInfoList() { return &m_AdapterInfoList; } //-------------------------------------------------------------------------------------- CD3D10EnumAdapterInfo* CD3D10Enumeration::GetAdapterInfo( UINT AdapterOrdinal ) { for( int iAdapter = 0; iAdapter < m_AdapterInfoList.GetSize(); iAdapter++ ) { CD3D10EnumAdapterInfo* pAdapterInfo = m_AdapterInfoList.GetAt( iAdapter ); if( pAdapterInfo->AdapterOrdinal == AdapterOrdinal ) return pAdapterInfo; } return NULL; } //-------------------------------------------------------------------------------------- CD3D10EnumDeviceInfo* CD3D10Enumeration::GetDeviceInfo( UINT AdapterOrdinal, D3D10_DRIVER_TYPE DeviceType ) { CD3D10EnumAdapterInfo* pAdapterInfo = GetAdapterInfo( AdapterOrdinal ); if( pAdapterInfo ) { for( int iDeviceInfo = 0; iDeviceInfo < pAdapterInfo->deviceInfoList.GetSize(); iDeviceInfo++ ) { CD3D10EnumDeviceInfo* pDeviceInfo = pAdapterInfo->deviceInfoList.GetAt( iDeviceInfo ); if( pDeviceInfo->DeviceType == DeviceType ) return pDeviceInfo; } } return NULL; } //-------------------------------------------------------------------------------------- CD3D10EnumOutputInfo* CD3D10Enumeration::GetOutputInfo( UINT AdapterOrdinal, UINT Output ) { CD3D10EnumAdapterInfo *pAdapterInfo = GetAdapterInfo( AdapterOrdinal ); if( pAdapterInfo && pAdapterInfo->outputInfoList.GetSize() > int(Output) ) { return pAdapterInfo->outputInfoList.GetAt( Output ); } return NULL; } //-------------------------------------------------------------------------------------- CD3D10EnumDeviceSettingsCombo* CD3D10Enumeration::GetDeviceSettingsCombo( UINT AdapterOrdinal, D3D10_DRIVER_TYPE DeviceType, UINT Output, DXGI_FORMAT BackBufferFormat, BOOL Windowed ) { CD3D10EnumAdapterInfo* pAdapterInfo = GetAdapterInfo( AdapterOrdinal ); if( pAdapterInfo ) { for( int iDeviceCombo = 0; iDeviceCombo < pAdapterInfo->deviceSettingsComboList.GetSize(); iDeviceCombo++ ) { CD3D10EnumDeviceSettingsCombo* pDeviceSettingsCombo = pAdapterInfo->deviceSettingsComboList.GetAt(iDeviceCombo); if( pDeviceSettingsCombo->BackBufferFormat == BackBufferFormat && pDeviceSettingsCombo->Windowed == Windowed ) return pDeviceSettingsCombo; } } return NULL; } //-------------------------------------------------------------------------------------- CD3D10EnumOutputInfo::~CD3D10EnumOutputInfo( void ) { SAFE_RELEASE( m_pOutput ); displayModeList.RemoveAll(); } //-------------------------------------------------------------------------------------- CD3D10EnumDeviceInfo::~CD3D10EnumDeviceInfo() { } //-------------------------------------------------------------------------------------- CD3D10EnumAdapterInfo::~CD3D10EnumAdapterInfo( void ) { for( int i=0; i < outputInfoList.GetSize(); i++ ) { CD3D10EnumOutputInfo* pOutputInfo = outputInfoList.GetAt(i); delete pOutputInfo; } outputInfoList.RemoveAll(); for( int i = 0; i < deviceInfoList.GetSize(); ++i ) { CD3D10EnumDeviceInfo* pDeviceInfo = deviceInfoList.GetAt(i); delete pDeviceInfo; } deviceInfoList.RemoveAll(); for( int i = 0; i < deviceSettingsComboList.GetSize(); ++i ) { CD3D10EnumDeviceSettingsCombo* pDeviceCombo = deviceSettingsComboList.GetAt(i); delete pDeviceCombo; } deviceSettingsComboList.RemoveAll(); SAFE_RELEASE( m_pAdapter ); } //-------------------------------------------------------------------------------------- // Returns the number of color channel bits in the specified DXGI_FORMAT //-------------------------------------------------------------------------------------- UINT WINAPI DXUTGetDXGIColorChannelBits( DXGI_FORMAT fmt ) { switch( fmt ) { case DXGI_FORMAT_R32G32B32A32_TYPELESS: case DXGI_FORMAT_R32G32B32A32_FLOAT: case DXGI_FORMAT_R32G32B32A32_UINT: case DXGI_FORMAT_R32G32B32A32_SINT: case DXGI_FORMAT_R32G32B32_TYPELESS: case DXGI_FORMAT_R32G32B32_FLOAT: case DXGI_FORMAT_R32G32B32_UINT: case DXGI_FORMAT_R32G32B32_SINT: return 32; case DXGI_FORMAT_R16G16B16A16_TYPELESS: case DXGI_FORMAT_R16G16B16A16_FLOAT: case DXGI_FORMAT_R16G16B16A16_UNORM: case DXGI_FORMAT_R16G16B16A16_UINT: case DXGI_FORMAT_R16G16B16A16_SNORM: case DXGI_FORMAT_R16G16B16A16_SINT: return 16; case DXGI_FORMAT_R10G10B10A2_TYPELESS: case DXGI_FORMAT_R10G10B10A2_UNORM: case DXGI_FORMAT_R10G10B10A2_UINT: return 10; case DXGI_FORMAT_R8G8B8A8_TYPELESS: case DXGI_FORMAT_R8G8B8A8_UNORM: case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: case DXGI_FORMAT_R8G8B8A8_UINT: case DXGI_FORMAT_R8G8B8A8_SNORM: case DXGI_FORMAT_R8G8B8A8_SINT: return 8; case DXGI_FORMAT_B5G6R5_UNORM: case DXGI_FORMAT_B5G5R5A1_UNORM: return 5; default: return 0; } } //-------------------------------------------------------------------------------------- HRESULT DXUTFindValidD3D10DeviceSettings( DXUTD3D10DeviceSettings* pOut, DXUTD3D10DeviceSettings* pIn, DXUTMatchOptions* pMatchOptions, DXUTD3D10DeviceSettings* pOptimal ) { // Find the best combination of: // Adapter Ordinal // Device Type // Back Buffer Format // Windowed // given what's available on the system and the match options combined with the device settings input. // This combination of settings is encapsulated by the CD3D10EnumDeviceSettingsCombo class. float fBestRanking = -1.0f; CD3D10EnumDeviceSettingsCombo* pBestDeviceSettingsCombo = NULL; DXGI_MODE_DESC adapterDisplayMode; CD3D10Enumeration* pd3dEnum = DXUTGetD3D10Enumeration(); CGrowableArray
* pAdapterList = pd3dEnum->GetAdapterInfoList(); for( int iAdapter=0; iAdapter
GetSize(); iAdapter++ ) { CD3D10EnumAdapterInfo* pAdapterInfo = pAdapterList->GetAt(iAdapter); // Get the desktop display mode of adapter DXUTGetD3D10AdapterDisplayMode( pAdapterInfo->AdapterOrdinal, 0, &adapterDisplayMode ); // Enum all the device settings combinations. A device settings combination is // a unique set of an adapter format, back buffer format, and IsWindowed. for( int iDeviceCombo=0; iDeviceCombo < pAdapterInfo->deviceSettingsComboList.GetSize(); iDeviceCombo++ ) { CD3D10EnumDeviceSettingsCombo* pDeviceSettingsCombo = pAdapterInfo->deviceSettingsComboList.GetAt(iDeviceCombo); // Skip any combo that doesn't meet the preserve match options if( false == DXUTDoesD3D10DeviceComboMatchPreserveOptions( pDeviceSettingsCombo, pIn, pMatchOptions ) ) continue; // Get a ranking number that describes how closely this device combo matches the optimal combo float fCurRanking = DXUTRankD3D10DeviceCombo( pDeviceSettingsCombo, pOptimal, &adapterDisplayMode ); // If this combo better matches the input device settings then save it if( fCurRanking > fBestRanking ) { pBestDeviceSettingsCombo = pDeviceSettingsCombo; fBestRanking = fCurRanking; } } } // If no best device combination was found then fail if( pBestDeviceSettingsCombo == NULL ) return DXUTERR_NOCOMPATIBLEDEVICES; // Using the best device settings combo found, build valid device settings taking heed of // the match options and the input device settings DXUTD3D10DeviceSettings validDeviceSettings; DXUTBuildValidD3D10DeviceSettings( &validDeviceSettings, pBestDeviceSettingsCombo, pIn, pMatchOptions ); *pOut = validDeviceSettings; return S_OK; } //-------------------------------------------------------------------------------------- // Internal helper function to build a D3D10 device settings structure based upon the match // options. If the match option is set to ignore, then a optimal default value is used. // The default value may not exist on the system, but later this will be taken // into account. //-------------------------------------------------------------------------------------- void DXUTBuildOptimalD3D10DeviceSettings( DXUTD3D10DeviceSettings* pOptimalDeviceSettings, DXUTD3D10DeviceSettings* pDeviceSettingsIn, DXUTMatchOptions* pMatchOptions ) { ZeroMemory( pOptimalDeviceSettings, sizeof(DXUTD3D10DeviceSettings) ); // Retrieve the desktop display mode. DXGI_MODE_DESC adapterDesktopDisplayMode = { 640, 480, { 60, 1 }, DXGI_FORMAT_R8G8B8A8_UNORM }; DXUTGetD3D10AdapterDisplayMode( pOptimalDeviceSettings->AdapterOrdinal, 0, &adapterDesktopDisplayMode ); //--------------------- // Adapter ordinal //--------------------- if( pMatchOptions->eAdapterOrdinal == DXUTMT_IGNORE_INPUT ) pOptimalDeviceSettings->AdapterOrdinal = 0; else pOptimalDeviceSettings->AdapterOrdinal = pDeviceSettingsIn->AdapterOrdinal; //--------------------- // Device type //--------------------- if( pMatchOptions->eDeviceType == DXUTMT_IGNORE_INPUT ) pOptimalDeviceSettings->DriverType = D3D10_DRIVER_TYPE_HARDWARE; else pOptimalDeviceSettings->DriverType = pDeviceSettingsIn->DriverType; //--------------------- // Windowed //--------------------- if( pMatchOptions->eWindowed == DXUTMT_IGNORE_INPUT ) pOptimalDeviceSettings->sd.Windowed = TRUE; else pOptimalDeviceSettings->sd.Windowed = pDeviceSettingsIn->sd.Windowed; //--------------------- // Output # //--------------------- if( pMatchOptions->eOutput == DXUTMT_IGNORE_INPUT ) pOptimalDeviceSettings->Output = 0; else pOptimalDeviceSettings->Output = pDeviceSettingsIn->Output; //--------------------- // Create flags //--------------------- pOptimalDeviceSettings->CreateFlags = pDeviceSettingsIn->CreateFlags; //--------------------- // Resolution //--------------------- if( pMatchOptions->eResolution == DXUTMT_IGNORE_INPUT ) { // If windowed, default to 640x480 // If fullscreen, default to the desktop res for quick mode change if( pOptimalDeviceSettings->sd.Windowed ) { pOptimalDeviceSettings->sd.BufferDesc.Width = 640; pOptimalDeviceSettings->sd.BufferDesc.Height = 480; } else { pOptimalDeviceSettings->sd.BufferDesc.Width = adapterDesktopDisplayMode.Width; pOptimalDeviceSettings->sd.BufferDesc.Height = adapterDesktopDisplayMode.Height; } } else { pOptimalDeviceSettings->sd.BufferDesc.Width = pDeviceSettingsIn->sd.BufferDesc.Width; pOptimalDeviceSettings->sd.BufferDesc.Height = pDeviceSettingsIn->sd.BufferDesc.Height; } //--------------------- // Back buffer format //--------------------- if( pMatchOptions->eBackBufferFormat == DXUTMT_IGNORE_INPUT ) pOptimalDeviceSettings->sd.BufferDesc.Format = adapterDesktopDisplayMode.Format; // Default to match the adapter format else pOptimalDeviceSettings->sd.BufferDesc.Format = pDeviceSettingsIn->sd.BufferDesc.Format; //--------------------- // Back buffer usage //--------------------- pOptimalDeviceSettings->sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; //--------------------- // Back buffer count //--------------------- if( pMatchOptions->eBackBufferCount == DXUTMT_IGNORE_INPUT ) pOptimalDeviceSettings->sd.BufferCount = 2; // Default to triple buffering for perf gain else pOptimalDeviceSettings->sd.BufferCount = pDeviceSettingsIn->sd.BufferCount; //--------------------- // Multisample //--------------------- if( pMatchOptions->eMultiSample == DXUTMT_IGNORE_INPUT ) { // Default to no multisampling pOptimalDeviceSettings->sd.SampleDesc.Count = 0; pOptimalDeviceSettings->sd.SampleDesc.Quality = 0; } else { pOptimalDeviceSettings->sd.SampleDesc.Count = pDeviceSettingsIn->sd.SampleDesc.Count; pOptimalDeviceSettings->sd.SampleDesc.Quality = pDeviceSettingsIn->sd.SampleDesc.Quality; } //--------------------- // Swap effect //--------------------- if( pMatchOptions->eSwapEffect == DXUTMT_IGNORE_INPUT ) pOptimalDeviceSettings->sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; else pOptimalDeviceSettings->sd.SwapEffect = pDeviceSettingsIn->sd.SwapEffect; //--------------------- // Depth stencil //--------------------- if( pMatchOptions->eDepthFormat == DXUTMT_IGNORE_INPUT && pMatchOptions->eStencilFormat == DXUTMT_IGNORE_INPUT ) { pOptimalDeviceSettings->AutoCreateDepthStencil = TRUE; pOptimalDeviceSettings->AutoDepthStencilFormat = DXGI_FORMAT_D32_FLOAT; } else { pOptimalDeviceSettings->AutoCreateDepthStencil = pDeviceSettingsIn->AutoCreateDepthStencil; pOptimalDeviceSettings->AutoDepthStencilFormat = pDeviceSettingsIn->AutoDepthStencilFormat; } //--------------------- // Present flags //--------------------- if( pMatchOptions->ePresentFlags == DXUTMT_IGNORE_INPUT ) pOptimalDeviceSettings->PresentFlags = 0; else pOptimalDeviceSettings->PresentFlags = pDeviceSettingsIn->PresentFlags; //--------------------- // Refresh rate //--------------------- if( pMatchOptions->eRefreshRate == DXUTMT_IGNORE_INPUT ) { pOptimalDeviceSettings->sd.BufferDesc.RefreshRate.Numerator = 60; pOptimalDeviceSettings->sd.BufferDesc.RefreshRate.Denominator = 1; } else pOptimalDeviceSettings->sd.BufferDesc.RefreshRate = pDeviceSettingsIn->sd.BufferDesc.RefreshRate; //--------------------- // Present interval //--------------------- if( pMatchOptions->ePresentInterval == DXUTMT_IGNORE_INPUT ) { // For windowed and fullscreen, default to 1 which will // wait for the vertical retrace period to prevent tearing. // For benchmarking, use 0 which will not wait for the // vertical retrace period but may introduce tearing. pOptimalDeviceSettings->SyncInterval = 1; } else { pOptimalDeviceSettings->SyncInterval = pDeviceSettingsIn->SyncInterval; } } //-------------------------------------------------------------------------------------- // Returns false for any CD3D9EnumDeviceSettingsCombo that doesn't meet the preserve // match options against the input pDeviceSettingsIn. //-------------------------------------------------------------------------------------- bool DXUTDoesD3D10DeviceComboMatchPreserveOptions( CD3D10EnumDeviceSettingsCombo* pDeviceSettingsCombo, DXUTD3D10DeviceSettings* pDeviceSettingsIn, DXUTMatchOptions* pMatchOptions ) { //--------------------- // Adapter ordinal //--------------------- if( pMatchOptions->eAdapterOrdinal == DXUTMT_PRESERVE_INPUT && (pDeviceSettingsCombo->AdapterOrdinal != pDeviceSettingsIn->AdapterOrdinal) ) return false; //--------------------- // Device type //--------------------- if( pMatchOptions->eDeviceType == DXUTMT_PRESERVE_INPUT && (pDeviceSettingsCombo->DeviceType != pDeviceSettingsIn->DriverType) ) return false; //--------------------- // Windowed //--------------------- if( pMatchOptions->eWindowed == DXUTMT_PRESERVE_INPUT && (pDeviceSettingsCombo->Windowed != pDeviceSettingsIn->sd.Windowed) ) return false; //--------------------- // Output //--------------------- if( pMatchOptions->eOutput == DXUTMT_PRESERVE_INPUT && (pDeviceSettingsCombo->Output != pDeviceSettingsIn->Output ) ) return false; //--------------------- // Resolution //--------------------- // If keep resolution then check that width and height supported by this combo if( pMatchOptions->eResolution == DXUTMT_PRESERVE_INPUT ) { bool bFound = false; for( int i=0; i< pDeviceSettingsCombo->pOutputInfo->displayModeList.GetSize(); i++ ) { DXGI_MODE_DESC displayMode = pDeviceSettingsCombo->pOutputInfo->displayModeList.GetAt( i ); if( displayMode.Width == pDeviceSettingsIn->sd.BufferDesc.Width && displayMode.Height == pDeviceSettingsIn->sd.BufferDesc.Height ) { bFound = true; break; } } // If the width and height are not supported by this combo, return false if( !bFound ) return false; } //--------------------- // Back buffer format //--------------------- if( pMatchOptions->eBackBufferFormat == DXUTMT_PRESERVE_INPUT && pDeviceSettingsCombo->BackBufferFormat != pDeviceSettingsIn->sd.BufferDesc.Format ) return false; //--------------------- // Back buffer count //--------------------- // No caps for the back buffer count //--------------------- // Multisample //--------------------- if( pMatchOptions->eMultiSample == DXUTMT_PRESERVE_INPUT ) { bool bFound = false; for( int i=0; i
multiSampleCountList.GetSize(); i++ ) { UINT Count = pDeviceSettingsCombo->multiSampleCountList.GetAt(i); UINT Quality = pDeviceSettingsCombo->multiSampleQualityList.GetAt(i); if( Count == pDeviceSettingsIn->sd.SampleDesc.Count && Quality > pDeviceSettingsIn->sd.SampleDesc.Quality ) { bFound = true; break; } } // If multisample type/quality not supported by this combo, then return false if( !bFound ) return false; } //--------------------- // Swap effect //--------------------- // No caps for swap effects //--------------------- // Depth stencil //--------------------- // No caps for depth stencil //--------------------- // Present flags //--------------------- // No caps for the present flags //--------------------- // Refresh rate //--------------------- // If keep refresh rate then check that the resolution is supported by this combo if( pMatchOptions->eRefreshRate == DXUTMT_PRESERVE_INPUT ) { bool bFound = false; for( int i=0; i
pOutputInfo->displayModeList.GetSize(); i++ ) { DXGI_MODE_DESC displayMode = pDeviceSettingsCombo->pOutputInfo->displayModeList.GetAt( i ); if( fabs( float(displayMode.RefreshRate.Numerator) / displayMode.RefreshRate.Denominator - float(pDeviceSettingsIn->sd.BufferDesc.RefreshRate.Numerator) / pDeviceSettingsIn->sd.BufferDesc.RefreshRate.Denominator ) < 0.1f ) { bFound = true; break; } } // If refresh rate not supported by this combo, then return false if( !bFound ) return false; } //--------------------- // Present interval //--------------------- // No caps for present interval return true; } //-------------------------------------------------------------------------------------- // Returns a ranking number that describes how closely this device // combo matches the optimal combo based on the match options and the optimal device settings //-------------------------------------------------------------------------------------- float DXUTRankD3D10DeviceCombo( CD3D10EnumDeviceSettingsCombo* pDeviceSettingsCombo, DXUTD3D10DeviceSettings* pOptimalDeviceSettings, DXGI_MODE_DESC* pAdapterDisplayMode ) { float fCurRanking = 0.0f; // Arbitrary weights. Gives preference to the ordinal, device type, and windowed const float fAdapterOrdinalWeight = 1000.0f; const float fAdapterOutputWeight = 500.0f; const float fDeviceTypeWeight = 100.0f; const float fWindowWeight = 10.0f; const float fResolutionWeight = 1.0f; const float fBackBufferFormatWeight = 1.0f; const float fMultiSampleWeight = 1.0f; const float fRefreshRateWeight = 1.0f; //--------------------- // Adapter ordinal //--------------------- if( pDeviceSettingsCombo->AdapterOrdinal == pOptimalDeviceSettings->AdapterOrdinal ) fCurRanking += fAdapterOrdinalWeight; //--------------------- // Adapter ordinal //--------------------- if( pDeviceSettingsCombo->Output == pOptimalDeviceSettings->Output ) fCurRanking += fAdapterOutputWeight; //--------------------- // Device type //--------------------- if( pDeviceSettingsCombo->DeviceType == pOptimalDeviceSettings->DriverType ) fCurRanking += fDeviceTypeWeight; // Slightly prefer HAL if( pDeviceSettingsCombo->DeviceType == D3DDEVTYPE_HAL ) fCurRanking += 0.1f; //--------------------- // Windowed //--------------------- if( pDeviceSettingsCombo->Windowed == pOptimalDeviceSettings->sd.Windowed ) fCurRanking += fWindowWeight; //--------------------- // Resolution //--------------------- bool bResolutionFound = false; for( int idm = 0; idm < pDeviceSettingsCombo->pOutputInfo->displayModeList.GetSize(); idm++ ) { DXGI_MODE_DESC displayMode = pDeviceSettingsCombo->pOutputInfo->displayModeList.GetAt( idm ); if( displayMode.Width == pOptimalDeviceSettings->sd.BufferDesc.Width && displayMode.Height == pOptimalDeviceSettings->sd.BufferDesc.Height ) bResolutionFound = true; } if( bResolutionFound ) fCurRanking += fResolutionWeight; //--------------------- // Back buffer format //--------------------- if( pDeviceSettingsCombo->BackBufferFormat == pOptimalDeviceSettings->sd.BufferDesc.Format ) { fCurRanking += fBackBufferFormatWeight; } else { int nBitDepthDelta = abs( (long) DXUTGetDXGIColorChannelBits(pDeviceSettingsCombo->BackBufferFormat) - (long) DXUTGetDXGIColorChannelBits(pOptimalDeviceSettings->sd.BufferDesc.Format) ); float fScale = __max(0.9f - (float)nBitDepthDelta*0.2f, 0.0f); fCurRanking += fScale * fBackBufferFormatWeight; } //--------------------- // Back buffer count //--------------------- // No caps for the back buffer count //--------------------- // Multisample //--------------------- bool bMultiSampleFound = false; for( int i=0; i
multiSampleCountList.GetSize(); i++ ) { UINT Count = pDeviceSettingsCombo->multiSampleCountList.GetAt(i); UINT Quality = pDeviceSettingsCombo->multiSampleQualityList.GetAt(i); if( Count == pOptimalDeviceSettings->sd.SampleDesc.Count && Quality > pOptimalDeviceSettings->sd.SampleDesc.Quality ) { bMultiSampleFound = true; break; } } if( bMultiSampleFound ) fCurRanking += fMultiSampleWeight; //--------------------- // Swap effect //--------------------- // No caps for swap effects //--------------------- // Depth stencil //--------------------- // No caps for swap effects //--------------------- // Present flags //--------------------- // No caps for the present flags //--------------------- // Refresh rate //--------------------- bool bRefreshFound = false; for( int idm = 0; idm < pDeviceSettingsCombo->pOutputInfo->displayModeList.GetSize(); idm++ ) { DXGI_MODE_DESC displayMode = pDeviceSettingsCombo->pOutputInfo->displayModeList.GetAt( idm ); if( fabs( float(displayMode.RefreshRate.Numerator)/displayMode.RefreshRate.Denominator - float(pOptimalDeviceSettings->sd.BufferDesc.RefreshRate.Numerator)/pOptimalDeviceSettings->sd.BufferDesc.RefreshRate.Denominator ) < 0.1f ) bRefreshFound = true; } if( bRefreshFound ) fCurRanking += fRefreshRateWeight; //--------------------- // Present interval //--------------------- // No caps for the present flags return fCurRanking; } //-------------------------------------------------------------------------------------- // Builds valid device settings using the match options, the input device settings, and the // best device settings combo found. //-------------------------------------------------------------------------------------- void DXUTBuildValidD3D10DeviceSettings( DXUTD3D10DeviceSettings* pValidDeviceSettings, CD3D10EnumDeviceSettingsCombo* pBestDeviceSettingsCombo, DXUTD3D10DeviceSettings* pDeviceSettingsIn, DXUTMatchOptions* pMatchOptions ) { DXGI_MODE_DESC adapterDisplayMode; DXUTGetD3D10AdapterDisplayMode( pBestDeviceSettingsCombo->AdapterOrdinal, pBestDeviceSettingsCombo->Output, &adapterDisplayMode ); // For each setting pick the best, taking into account the match options and // what's supported by the device //--------------------- // Adapter Ordinal //--------------------- // Just using pBestDeviceSettingsCombo->AdapterOrdinal //--------------------- // Device Type //--------------------- // Just using pBestDeviceSettingsCombo->DeviceType //--------------------- // Windowed //--------------------- // Just using pBestDeviceSettingsCombo->Windowed //--------------------- // Output //--------------------- // Just using pBestDeviceSettingsCombo->Output //--------------------- // Resolution //--------------------- DXGI_MODE_DESC bestDisplayMode; if( pMatchOptions->eResolution == DXUTMT_PRESERVE_INPUT ) { bestDisplayMode.Width = pDeviceSettingsIn->sd.BufferDesc.Width; bestDisplayMode.Height = pDeviceSettingsIn->sd.BufferDesc.Height; } else { DXGI_MODE_DESC displayModeIn; if( pMatchOptions->eResolution == DXUTMT_CLOSEST_TO_INPUT && pDeviceSettingsIn ) { displayModeIn.Width = pDeviceSettingsIn->sd.BufferDesc.Width; displayModeIn.Height = pDeviceSettingsIn->sd.BufferDesc.Height; } else // if( pMatchOptions->eResolution == DXUTMT_IGNORE_INPUT ) { if( pBestDeviceSettingsCombo->Windowed ) { // The framework defaults to 640x480 for windowed displayModeIn.Width = 640; displayModeIn.Height = 480; } else { // The framework defaults to desktop resolution for fullscreen to try to avoid slow mode change displayModeIn.Width = adapterDisplayMode.Width; displayModeIn.Height = adapterDisplayMode.Height; } } // Call a helper function to find the closest valid display mode to the optimal DXUTFindValidD3D10Resolution( pBestDeviceSettingsCombo, displayModeIn, &bestDisplayMode ); } //--------------------- // Back Buffer Format //--------------------- // Just using pBestDeviceSettingsCombo->BackBufferFormat //--------------------- // Back Buffer usage //--------------------- // Just using pDeviceSettingsIn->sd.BackBufferUsage | DXGI_USAGE_RENDERTARGETOUTPUT //--------------------- // Back buffer count //--------------------- UINT bestBackBufferCount; if( pMatchOptions->eBackBufferCount == DXUTMT_PRESERVE_INPUT ) { bestBackBufferCount = pDeviceSettingsIn->sd.BufferCount; } else if( pMatchOptions->eBackBufferCount == DXUTMT_IGNORE_INPUT ) { // The framework defaults to triple buffering bestBackBufferCount = 2; } else // if( pMatchOptions->eBackBufferCount == DXUTMT_CLOSEST_TO_INPUT ) { bestBackBufferCount = pDeviceSettingsIn->sd.BufferCount; if( bestBackBufferCount > 3 ) bestBackBufferCount = 3; if( bestBackBufferCount < 1 ) bestBackBufferCount = 1; } //--------------------- // Multisample //--------------------- UINT bestMultiSampleCount; UINT bestMultiSampleQuality; if( pDeviceSettingsIn && pDeviceSettingsIn->sd.SwapEffect != DXGI_SWAP_EFFECT_DISCARD ) { // Swap effect is not set to discard so multisampling has to off bestMultiSampleCount = 1; bestMultiSampleQuality = 0; } else { if( pMatchOptions->eMultiSample == DXUTMT_PRESERVE_INPUT ) { bestMultiSampleCount = pDeviceSettingsIn->sd.SampleDesc.Count; bestMultiSampleQuality = pDeviceSettingsIn->sd.SampleDesc.Quality; } else if( pMatchOptions->eMultiSample == DXUTMT_IGNORE_INPUT ) { // Default to no multisampling (always supported) bestMultiSampleCount = 1; bestMultiSampleQuality = 0; } else if( pMatchOptions->eMultiSample == DXUTMT_CLOSEST_TO_INPUT ) { // Default to no multisampling (always supported) bestMultiSampleCount = 1; bestMultiSampleQuality = 0; for( int i=0; i < pBestDeviceSettingsCombo->multiSampleCountList.GetSize(); i++ ) { UINT Count = pBestDeviceSettingsCombo->multiSampleCountList.GetAt(i); UINT Quality = pBestDeviceSettingsCombo->multiSampleQualityList.GetAt(i); // Check whether supported type is closer to the input than our current best if( labs(Count - pDeviceSettingsIn->sd.SampleDesc.Count) < labs(bestMultiSampleCount - pDeviceSettingsIn->sd.SampleDesc.Count) ) { bestMultiSampleCount = Count; bestMultiSampleQuality = __min( Quality - 1, pDeviceSettingsIn->sd.SampleDesc.Quality ); } } } else { // Error case bestMultiSampleCount = 1; bestMultiSampleQuality = 0; } } //--------------------- // Swap effect //--------------------- DXGI_SWAP_EFFECT bestSwapEffect; if( pMatchOptions->eSwapEffect == DXUTMT_PRESERVE_INPUT ) { bestSwapEffect = pDeviceSettingsIn->sd.SwapEffect; } else if( pMatchOptions->eSwapEffect == DXUTMT_IGNORE_INPUT ) { bestSwapEffect = DXGI_SWAP_EFFECT_DISCARD; } else // if( pMatchOptions->eSwapEffect == DXUTMT_CLOSEST_TO_INPUT ) { bestSwapEffect = pDeviceSettingsIn->sd.SwapEffect; // Swap effect has to be one of these 2 if( bestSwapEffect != DXGI_SWAP_EFFECT_DISCARD && bestSwapEffect != DXGI_SWAP_EFFECT_SEQUENTIAL ) { bestSwapEffect = DXGI_SWAP_EFFECT_DISCARD; } } //--------------------- // Depth stencil //--------------------- DXGI_FORMAT bestDepthStencilFormat; bool bestEnableAutoDepthStencil; if( pMatchOptions->eDepthFormat == DXUTMT_IGNORE_INPUT && pMatchOptions->eStencilFormat == DXUTMT_IGNORE_INPUT ) { bestEnableAutoDepthStencil = true; bestDepthStencilFormat = DXGI_FORMAT_D32_FLOAT; } else { bestEnableAutoDepthStencil = pDeviceSettingsIn->AutoCreateDepthStencil; bestDepthStencilFormat = pDeviceSettingsIn->AutoDepthStencilFormat; } //--------------------- // Present flags //--------------------- //--------------------- // Refresh rate //--------------------- if( pBestDeviceSettingsCombo->Windowed ) { // Must be 0 for windowed bestDisplayMode.RefreshRate.Numerator = 60; bestDisplayMode.RefreshRate.Denominator = 1; } else { if( pMatchOptions->eRefreshRate == DXUTMT_PRESERVE_INPUT ) { bestDisplayMode.RefreshRate = pDeviceSettingsIn->sd.BufferDesc.RefreshRate; } else { DXGI_RATIONAL refreshRateMatch; if( pMatchOptions->eRefreshRate == DXUTMT_CLOSEST_TO_INPUT ) { refreshRateMatch = pDeviceSettingsIn->sd.BufferDesc.RefreshRate; } else // if( pMatchOptions->eRefreshRate == DXUTMT_IGNORE_INPUT ) { refreshRateMatch = adapterDisplayMode.RefreshRate; } // Default to 60 in case no matching mode is found bestDisplayMode.RefreshRate.Numerator = 60; bestDisplayMode.RefreshRate.Denominator = 1; // if( refreshRateMatch != 0 ) { float fBestRefreshRanking = 100000.0f; CGrowableArray
* pDisplayModeList = &pBestDeviceSettingsCombo->pOutputInfo->displayModeList; for( int iDisplayMode=0; iDisplayMode
GetSize(); iDisplayMode++ ) { DXGI_MODE_DESC displayMode = pDisplayModeList->GetAt(iDisplayMode); if( displayMode.Height != bestDisplayMode.Height || displayMode.Width != bestDisplayMode.Width ) continue; // Skip display modes that don't match // Find the delta between the current refresh rate and the optimal refresh rate float fCurRanking = abs(float(displayMode.RefreshRate.Numerator)/displayMode.RefreshRate.Denominator - float(refreshRateMatch.Numerator)/refreshRateMatch.Denominator); if( fCurRanking < fBestRefreshRanking ) { bestDisplayMode.RefreshRate = displayMode.RefreshRate; fBestRefreshRanking = fCurRanking; // Stop if good-enough match found if( fBestRefreshRanking < 0.1f ) break; } } } } } //--------------------- // Present interval //--------------------- UINT32 bestPresentInterval; if( pMatchOptions->ePresentInterval == DXUTMT_PRESERVE_INPUT ) { bestPresentInterval = pDeviceSettingsIn->SyncInterval; } else if( pMatchOptions->ePresentInterval == DXUTMT_IGNORE_INPUT ) { // For windowed and fullscreen, default to 1 which will wait for // the vertical retrace period to prevent tearing. For benchmarking, // use 0 which will will wait not for the vertical retrace period // but may introduce tearing. // The reference driver does not support v-syncing and will // produce _com_error exceptions when the sync interval is // anything but 0. bestPresentInterval = ( D3D10_DRIVER_TYPE_REFERENCE == pBestDeviceSettingsCombo->DeviceType ) ? 0 : 1; } else // if( pMatchOptions->ePresentInterval == DXUTMT_CLOSEST_TO_INPUT ) { bestPresentInterval = pDeviceSettingsIn->SyncInterval; } // Fill the device settings struct ZeroMemory( pValidDeviceSettings, sizeof(DXUTD3D10DeviceSettings) ); pValidDeviceSettings->AdapterOrdinal = pBestDeviceSettingsCombo->AdapterOrdinal; pValidDeviceSettings->Output = pBestDeviceSettingsCombo->Output; pValidDeviceSettings->DriverType = pBestDeviceSettingsCombo->DeviceType; pValidDeviceSettings->sd.BufferDesc.Width = bestDisplayMode.Width; pValidDeviceSettings->sd.BufferDesc.Height = bestDisplayMode.Height; pValidDeviceSettings->sd.BufferDesc.Format = pBestDeviceSettingsCombo->BackBufferFormat; pValidDeviceSettings->sd.BufferUsage = pDeviceSettingsIn->sd.BufferUsage | DXGI_USAGE_RENDER_TARGET_OUTPUT; pValidDeviceSettings->sd.BufferCount = bestBackBufferCount; pValidDeviceSettings->sd.SampleDesc.Count = bestMultiSampleCount; pValidDeviceSettings->sd.SampleDesc.Quality = bestMultiSampleQuality; pValidDeviceSettings->sd.SwapEffect = bestSwapEffect; pValidDeviceSettings->sd.OutputWindow = pBestDeviceSettingsCombo->Windowed ? DXUTGetHWNDDeviceWindowed() : DXUTGetHWNDDeviceFullScreen(); pValidDeviceSettings->sd.Windowed = pBestDeviceSettingsCombo->Windowed; pValidDeviceSettings->sd.BufferDesc.RefreshRate = bestDisplayMode.RefreshRate; pValidDeviceSettings->sd.Flags = 0; pValidDeviceSettings->SyncInterval = bestPresentInterval; pValidDeviceSettings->AutoCreateDepthStencil = bestEnableAutoDepthStencil; pValidDeviceSettings->AutoDepthStencilFormat = bestDepthStencilFormat; pValidDeviceSettings->CreateFlags = pDeviceSettingsIn->CreateFlags; } //-------------------------------------------------------------------------------------- // Internal helper function to find the closest allowed display mode to the optimal //-------------------------------------------------------------------------------------- HRESULT DXUTFindValidD3D10Resolution( CD3D10EnumDeviceSettingsCombo* pBestDeviceSettingsCombo, DXGI_MODE_DESC displayModeIn, DXGI_MODE_DESC* pBestDisplayMode ) { DXGI_MODE_DESC bestDisplayMode; ZeroMemory( &bestDisplayMode, sizeof(bestDisplayMode) ); if( pBestDeviceSettingsCombo->Windowed ) { *pBestDisplayMode = displayModeIn; // If our client rect size is smaller than our backbuffer size, use that size. // This would happen when we specify a windowed resolution larger than the screen. MONITORINFO Info; Info.cbSize = sizeof(MONITORINFO); GetMonitorInfo( pBestDeviceSettingsCombo->pOutputInfo->Desc.Monitor, &Info ); UINT Width = Info.rcWork.right - Info.rcWork.left; UINT Height = Info.rcWork.bottom - Info.rcWork.top; RECT rcClient = Info.rcWork; AdjustWindowRect( &rcClient, GetWindowLong( DXUTGetHWNDDeviceWindowed(), GWL_STYLE ), FALSE ); Width = Width - ( rcClient.right - rcClient.left - Width ); Height = Height - ( rcClient.bottom - rcClient.top - Height ); pBestDisplayMode->Width = __min( pBestDisplayMode->Width, Width ); pBestDisplayMode->Height = __min( pBestDisplayMode->Height, Height ); } else { int nBestRanking = 100000; int nCurRanking; CGrowableArray
* pDisplayModeList = &pBestDeviceSettingsCombo->pOutputInfo->displayModeList; for( int iDisplayMode=0; iDisplayMode
GetSize(); iDisplayMode++ ) { DXGI_MODE_DESC displayMode = pDisplayModeList->GetAt(iDisplayMode); // Find the delta between the current width/height and the optimal width/height nCurRanking = abs((int)displayMode.Width - (int)displayModeIn.Width) + abs((int)displayMode.Height- (int)displayModeIn.Height); if( nCurRanking < nBestRanking ) { bestDisplayMode = displayMode; nBestRanking = nCurRanking; // Stop if perfect match found if( nBestRanking == 0 ) break; } } if( bestDisplayMode.Width == 0 ) { *pBestDisplayMode = displayModeIn; return E_FAIL; // No valid display modes found } *pBestDisplayMode = bestDisplayMode; } return S_OK; } //-------------------------------------------------------------------------------------- // Returns the DXGI_MODE_DESC struct for a given adapter and output //-------------------------------------------------------------------------------------- HRESULT WINAPI DXUTGetD3D10AdapterDisplayMode( UINT AdapterOrdinal, UINT nOutput, DXGI_MODE_DESC *pModeDesc ) { if( !pModeDesc ) return E_INVALIDARG; CD3D10Enumeration *pD3DEnum = DXUTGetD3D10Enumeration(); CD3D10EnumOutputInfo *pOutputInfo = pD3DEnum->GetOutputInfo( AdapterOrdinal, nOutput ); if( pOutputInfo ) { pModeDesc->Width = 640; pModeDesc->Height = 480; pModeDesc->RefreshRate.Numerator = 60; pModeDesc->RefreshRate.Denominator = 1; pModeDesc->Format = DXGI_FORMAT_R8G8B8A8_UNORM; pModeDesc->Scaling = DXGI_MODE_SCALING_UNSPECIFIED; pModeDesc->ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; DXGI_OUTPUT_DESC Desc; pOutputInfo->m_pOutput->GetDesc( &Desc ); pModeDesc->Width = Desc.DesktopCoordinates.right - Desc.DesktopCoordinates.left; pModeDesc->Height = Desc.DesktopCoordinates.bottom - Desc.DesktopCoordinates.top; } // TODO: verify this is needed if( pModeDesc->Format == DXGI_FORMAT_B8G8R8A8_UNORM ) pModeDesc->Format = DXGI_FORMAT_R8G8B8A8_UNORM; return S_OK; }
DXUTenum.cpp
Page URL
File URL
Prev
7/10
Next
Download
( 153 KB )
Note: The DriveHQ service banners will NOT be displayed if the file owner is a paid member.
Comments
Total ratings:
0
Average rating:
Not Rated
Would you like to comment?
Join DriveHQ
for a free account, or
Logon
if you are already a member.