📄 dx8enumeration.cpp
字号:
#include <TChar.h>
#include <stdio.h>
#include "DX8Prerequisites.h"
#include "DX8Enumeration.h"
#include "../../Main/QLogManager.h"
using namespace QGE::VISUAL;
//-----------------------------------------------------------------------------
// Name: SortModesCallback()
// Desc: Callback function for sorting display modes (used by BuildDeviceList).
//-----------------------------------------------------------------------------
static int SortModesCallback( const VOID* arg1, const VOID* arg2 )
{
D3DDISPLAYMODE* p1 = (D3DDISPLAYMODE*)arg1;
D3DDISPLAYMODE* p2 = (D3DDISPLAYMODE*)arg2;
if( p1->Format > p2->Format ) return -1;
if( p1->Format < p2->Format ) return +1;
if( p1->Width < p2->Width ) return -1;
if( p1->Width > p2->Width ) return +1;
if( p1->Height < p2->Height ) return -1;
if( p1->Height > p2->Height ) return +1;
return 0;
}
DX8Enumeration::DX8Enumeration(LPDIRECT3D8 pd3d,Bool bDepthStencil,Bool bMixedVP,Int32 minDepthBits,Int32 minStencilBits) :
m_pd3d(pd3d),
m_bDepthStencil(bDepthStencil),
m_bMixedVertexProcessing(bMixedVP),
m_dwMinDepthBits(minDepthBits),
m_dwMinStencilBits(minStencilBits),
m_dwNumAdapters(0)
{
}
HRESULT DX8Enumeration::BuildDeviceList()
{
if( m_pd3d==NULL )
return E_FAIL;
const DWORD dwNumDeviceType = 2;
const TCHAR* strDeviceDes[] = { _T("HAL"),_T("REF") };
const D3DDEVTYPE DeviceTypes[] ={ D3DDEVTYPE_HAL, D3DDEVTYPE_REF };
BOOL bHAL_Exists = FALSE;
BOOL bHAL_Windowed_Compatible = FALSE;
BOOL bHAL_Desktop_Compatible = FALSE;
BOOL bHAL_Sample_Compatible = FALSE;
for( UINT iAdapterCount=0; iAdapterCount<m_pd3d->GetAdapterCount();++iAdapterCount )
{
//填冲Adapter结构
D3DAdapterInfo* pAdapter = &m_Adapters[m_dwNumAdapters];
m_pd3d->GetAdapterIdentifier(iAdapterCount,D3DENUM_NO_WHQL_LEVEL,&pAdapter->d3dAdapterIdentifier);
m_pd3d->GetAdapterDisplayMode(iAdapterCount,&pAdapter->d3ddmDesktop);
pAdapter->dwNumDevices = 0;
pAdapter->dwCurrentDevice = 0;
//枚举所有显示模式
D3DDISPLAYMODE modes[100];
D3DFORMAT formats[20];
DWORD dwNumModes = 0;
DWORD dwNumFormats = 0;
DWORD dwNumAdpaterModes = m_pd3d->GetAdapterModeCount(iAdapterCount);
formats[dwNumFormats] = pAdapter->d3ddmDesktop.Format;
//枚举该Adapter的所有模式
for( UINT iModeCount=0;iModeCount<dwNumAdpaterModes;++iModeCount)
{
//枚举显示模式
D3DDISPLAYMODE DisplayMode;
m_pd3d->EnumAdapterModes(iAdapterCount,iModeCount,&DisplayMode);
//去除分辨率太低的模式
if( DisplayMode.Width <600 || DisplayMode.Height <400 )
continue;
//判断是否重复
for( DWORD i=0;i<dwNumModes;++i )
{
if( (modes[i].Width == DisplayMode.Width) &&
(modes[i].Height == DisplayMode.Height) &&
(modes[i].Format == DisplayMode.Format) )
break;
}
if( i == dwNumModes ) //找到新模式
{
modes[dwNumModes].Width = DisplayMode.Width;
modes[dwNumModes].Height = DisplayMode.Height;
modes[dwNumModes].Format = DisplayMode.Format;
modes[dwNumModes].RefreshRate = DisplayMode.RefreshRate;
dwNumModes++;
//判断该模式的Format是否已存在
for( DWORD j=0;j<dwNumFormats;++j)
{
if( formats[j] == DisplayMode.Format )
break;
}
if( j==dwNumFormats ) //找到新模式
{
formats[dwNumFormats++] = DisplayMode.Format;
}
}
}
//排序
qsort(modes,dwNumModes,sizeof(D3DDISPLAYMODE),SortModesCallback);
//将Device添加到Adpater,HAL or REF
for( UINT iDeviceCount=0; iDeviceCount<dwNumDeviceType;++iDeviceCount)
{
//填充DeviceInfo结构
D3DDeviceInfo* pDevice = &pAdapter->devices[pAdapter->dwNumDevices];
pDevice->DeviceType = DeviceTypes[iDeviceCount];
m_pd3d->GetDeviceCaps(iAdapterCount,pDevice->DeviceType,&pDevice->d3dCaps);
pDevice->strDesc = strDeviceDes[iDeviceCount];
pDevice->dwNumModes = 0;
pDevice->dwCurrentMode = 0;
pDevice->bCanDoWindowed =FALSE;
pDevice->bWindowed = FALSE;
pDevice->MultiSampleTypeFullscreen = D3DMULTISAMPLE_NONE;
pDevice->MultiSampleTypeWindowed = D3DMULTISAMPLE_NONE;
//检查所有的Formats是否可以在该DeviceType(HAL or REF)下正常工作
BOOL bFormatsConfirmed[20];
DWORD dwBehavior[20];
D3DFORMAT fmtDepthStencil[20];
for( DWORD i=0;i<dwNumFormats;++i)
{
bFormatsConfirmed[i] = FALSE;
fmtDepthStencil[i] = D3DFMT_UNKNOWN;
//如果不能工作,跳过
if( FAILED( m_pd3d->CheckDeviceType(iAdapterCount,
pDevice->DeviceType,formats[i],formats[i],FALSE)) )
continue;
if( pDevice->DeviceType == D3DDEVTYPE_HAL )
bHAL_Exists = TRUE;
if( pDevice->d3dCaps.Caps2 & D3DCAPS2_CANRENDERWINDOWED )
{
bHAL_Windowed_Compatible = TRUE;
if( i==0 ) //第一个是Desktop的Format
{
bHAL_Desktop_Compatible = true;
}
}
//最后判断顶点渲染模式
if( pDevice->d3dCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ) //使用HARDWARE_VP
{
if( m_bMixedVertexProcessing )
{
dwBehavior[i] = D3DCREATE_MIXED_VERTEXPROCESSING;
bFormatsConfirmed[i] = TRUE;
}
else
{
if( pDevice->d3dCaps.DevCaps & D3DDEVCAPS_PUREDEVICE )
{
dwBehavior[i] = D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE;
bFormatsConfirmed[i] = TRUE;
}
else
{
dwBehavior[i] = D3DCREATE_HARDWARE_VERTEXPROCESSING;
bFormatsConfirmed[i] = TRUE;
}
}
}
else //使用SOFTWARE_VP
{
dwBehavior[i] = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
bFormatsConfirmed[i] = TRUE;
}
//设置合适的Depth/Stencil Buffer
if( m_bDepthStencil )
{
if( !FindDepthStencilFormat( iAdapterCount, pDevice->DeviceType,
formats[i], &fmtDepthStencil[i] ) )
{
bFormatsConfirmed[i] = FALSE;
}
}
}
//将所有有效的Display Modes和Formats填充入Device中的列表
for( DWORD j=0;j<dwNumModes;++j )
{
for( DWORD k=0;k<dwNumFormats;++k )
{
if( modes[j].Format == formats[k] )
{
if( bFormatsConfirmed[k] )
{
pDevice->modes[pDevice->dwNumModes].Width = modes[j].Width;
pDevice->modes[pDevice->dwNumModes].Height = modes[j].Height;
pDevice->modes[pDevice->dwNumModes].dwBehavior = dwBehavior[k];
pDevice->modes[pDevice->dwNumModes].DepthStencilFormat = fmtDepthStencil[k];
pDevice->modes[pDevice->dwNumModes].Format = modes[j].Format;
pDevice->dwNumModes++;
if( pDevice->DeviceType == D3DDEVTYPE_HAL )
bHAL_Sample_Compatible = TRUE;
}
}
}
}
//寻找640*480作为默认
for( DWORD k=0;k<pDevice->dwNumModes;++k )
{
if( pDevice->modes[k].Width ==640 && pDevice->modes[k].Height== 480 )
{
pDevice->dwCurrentMode = k;
if( pDevice->modes[k].Format == D3DFMT_R5G6B5 ||
pDevice->modes[k].Format == D3DFMT_X1R5G5B5 ||
pDevice->modes[k].Format == D3DFMT_A1R5G5B5 )
{
break;
}
}
}
//可在窗口模式下
if( bFormatsConfirmed[0] && (pDevice->d3dCaps.Caps2 & D3DCAPS2_CANRENDERWINDOWED) )
{
pDevice->bCanDoWindowed = TRUE;
pDevice->bWindowed = TRUE;
}
//该DeviceType模式有效
if( pDevice->dwNumModes >0 )
pAdapter->dwNumDevices++;
}
if( pAdapter->dwNumDevices >0 )
++m_dwNumAdapters;
//记录
#ifdef QDEBUG
Char buf[512];
sprintf(buf,"Find Adapter:%s;Device[HAL]->Modes:%d;Device[REF]->Modes:%d",
pAdapter->d3dAdapterIdentifier.Description,pAdapter->devices[0].dwNumModes,pAdapter->devices[1].dwNumModes);
LOGBOREME(buf);
#endif
}
//无效
if( 0L == m_dwNumAdapters )
return D3DAPPERR_NOCOMPATIBLEDEVICES;
//选择第一个作为默认
m_CurrentAdapter = 0;
return S_OK;
}
BOOL DX8Enumeration::FindDepthStencilFormat( UINT iAdapter, D3DDEVTYPE DeviceType,
D3DFORMAT TargetFormat, D3DFORMAT* pDepthStencilFormat )
{
if( m_dwMinDepthBits <= 16 && m_dwMinStencilBits == 0 )
{
if( SUCCEEDED( m_pd3d->CheckDeviceFormat( iAdapter, DeviceType,
TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16 ) ) )
{
if( SUCCEEDED( m_pd3d->CheckDepthStencilMatch( iAdapter, DeviceType,
TargetFormat, TargetFormat, D3DFMT_D16 ) ) )
{
*pDepthStencilFormat = D3DFMT_D16;
return TRUE;
}
}
}
if( m_dwMinDepthBits <= 15 && m_dwMinStencilBits <= 1 )
{
if( SUCCEEDED( m_pd3d->CheckDeviceFormat( iAdapter, DeviceType,
TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D15S1 ) ) )
{
if( SUCCEEDED( m_pd3d->CheckDepthStencilMatch( iAdapter, DeviceType,
TargetFormat, TargetFormat, D3DFMT_D15S1 ) ) )
{
*pDepthStencilFormat = D3DFMT_D15S1;
return TRUE;
}
}
}
if( m_dwMinDepthBits <= 24 && m_dwMinStencilBits == 0 )
{
if( SUCCEEDED( m_pd3d->CheckDeviceFormat( iAdapter, DeviceType,
TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24X8 ) ) )
{
if( SUCCEEDED( m_pd3d->CheckDepthStencilMatch( iAdapter, DeviceType,
TargetFormat, TargetFormat, D3DFMT_D24X8 ) ) )
{
*pDepthStencilFormat = D3DFMT_D24X8;
return TRUE;
}
}
}
if( m_dwMinDepthBits <= 24 && m_dwMinStencilBits <= 8 )
{
if( SUCCEEDED( m_pd3d->CheckDeviceFormat( iAdapter, DeviceType,
TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24S8 ) ) )
{
if( SUCCEEDED( m_pd3d->CheckDepthStencilMatch( iAdapter, DeviceType,
TargetFormat, TargetFormat, D3DFMT_D24S8 ) ) )
{
*pDepthStencilFormat = D3DFMT_D24S8;
return TRUE;
}
}
}
if( m_dwMinDepthBits <= 24 && m_dwMinStencilBits <= 4 )
{
if( SUCCEEDED( m_pd3d->CheckDeviceFormat( iAdapter, DeviceType,
TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24X4S4 ) ) )
{
if( SUCCEEDED( m_pd3d->CheckDepthStencilMatch( iAdapter, DeviceType,
TargetFormat, TargetFormat, D3DFMT_D24X4S4 ) ) )
{
*pDepthStencilFormat = D3DFMT_D24X4S4;
return TRUE;
}
}
}
if( m_dwMinDepthBits <= 32 && m_dwMinStencilBits == 0 )
{
if( SUCCEEDED( m_pd3d->CheckDeviceFormat( iAdapter, DeviceType,
TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D32 ) ) )
{
if( SUCCEEDED( m_pd3d->CheckDepthStencilMatch( iAdapter, DeviceType,
TargetFormat, TargetFormat, D3DFMT_D32 ) ) )
{
*pDepthStencilFormat = D3DFMT_D32;
return TRUE;
}
}
}
return FALSE;
}
inline D3DAdapterInfo& DX8Enumeration::GetAdapter(Int32 idx) const
{
return (D3DAdapterInfo&)m_Adapters[idx];
}
inline Int32 DX8Enumeration::GetAdapterNum() const
{
return m_dwNumAdapters;
}
inline D3DAdapterInfo& DX8Enumeration::GetCurrentAdapter() const
{
return (D3DAdapterInfo&)m_Adapters[m_CurrentAdapter];
}
inline Int32 DX8Enumeration::GetCurrentAdapterIdx() const
{
return m_CurrentAdapter;
}
inline void DX8Enumeration::SetCurrentAdapterIdx(Int32 idx)
{
if( idx < m_dwNumAdapters )
m_CurrentAdapter = idx;
}
inline Bool DX8Enumeration::IsUseDepthStencilBuffer()
{
return m_bDepthStencil;
}
inline void DX8Enumeration::UseDepthStencilBuffer(Bool use)
{
m_bDepthStencil = use;
}
inline Bool DX8Enumeration::IsMixedVertexProcessing()
{
return m_bMixedVertexProcessing;
}
inline void DX8Enumeration::UseMixedVertexProcessing(Bool use)
{
m_bMixedVertexProcessing = use;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -