📄 dxutenum.cpp
字号:
//--------------------------------------------------------------------------------------
// File: DXUTEnum.cpp
//
// Enumerates D3D adapters, devices, modes, etc.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//--------------------------------------------------------------------------------------
#include "DXUT.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->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<D3DFORMAT> 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 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -