/*IDirect3D对象枚举Adapter的功能函数:
GetAdapterCount()
GetAdapterDisplayMode
GetAdapterIdentifier //得到适配器描述
CheckDeviceType
GetDeviceCaps //指定设备的性能,主要判断是否支持硬件顶点处理(T&L)
GetAdapterModeCount //得到适配器上指定缓冲格式所有可用的显示模式
EnumAdapterModes //枚举所有显示模式
CheckDeviceFormat
CheckDeviceMultiSampleType
本类是对上述函数的封装使得使用更方便,且提供了这些函数的使用例子。
author:Jesse Cen
date:2014.11.23
*/
//一、D3DCheckAdapter.h文件
#ifndef _D3DCHECKADAPTER_H_
#define _D3DCHECKDISPLAY_H_
#include"D3DUtility.h"
class D3DCheckAdapter
{
private:
D3DCheckAdapter(){};
public:
~D3DCheckAdapter(){};
// 单例
static D3DCheckAdapter* GetInstace();
// 1.检查指定的表面像素格式,是否在指定的适配器类型、适配器像素格式下可用。
// GetAdapterDisplayMode,CheckDeviceType的应用
bool GetBackBufferFormat(IDirect3D9 *pD3D, D3DDEVTYPE deviceType,bool bWindow, D3DFORMAT &fmt);
// 2.根据适配器类型,获取顶点运算(变换和光照运算)的格式
// D3DCAPS9结构体,GetDeviceCaps的应用
bool GetDisplayVertexType(IDirect3D9 *pD3D, D3DDEVTYPEdeviceType, int &nVertexType);
// 3.输出显卡信息,Description描述,厂商型号,Dircet3D的驱动Driver版本号,显卡的唯一标识号:DeviceIdentifier
// GetAdapterCount(),GetAdapterIdentifier的使用。
void PrintDisplayInfo(IDirect3D9 *pD3D);
// 4.输出指定Adapter,显卡像素模式(不会与缓存表面格式做兼容考虑)的显卡适配器模式信息
// GetAdapterModeCount,EnumAdapterModes的使用
void PrintDisplayModeInfo(IDirect3D9 *pD3D, D3DFORMAT fmt);
// 5.对于指定的资源类型,检查资源的使用方式,资源像素格式,在默认的显卡适配器下是否支持
// GetAdapterDisplayMode,CheckDeviceFormat的使用
bool CheckResourceFormat(IDirect3D9 *pD3D, DWORD nSrcUsage,D3DRESOURCETYPE srcType, D3DFORMAT srcFmt);
// 6.对指定的表面像素格式,窗口模式,和显卡像素模式;检查对指定的多重采样类型支持不,且返回质量水平等级
// CheckDeviceMultiSampleType的应用
bool CheckMultiSampleType(IDirect3D9 *pD3D, D3DFORMAT surfaceFmt,bool bWindow, D3DMULTISAMPLE_TYPE eSampleType, DWORD *pQualityLevel);
// 7.根据显卡适配器和目标缓存类型,检查指定深度缓存的格式是否支持
// CheckDepthStencilMatch的应用
bool CheckDepthBufferFormt(IDirect3D9 *pD3D, D3DFORMAT targetBufferFmt, D3DFORMAT depthFmt);
private:
static D3DCheckAdapter* m_pCheckDisplayObj;
};
#endif
//二、 D3DCheckAdapter.cpp文件
#include"D3DCheckAdapter.h"
D3DCheckAdapter*D3DCheckAdapter::m_pCheckDisplayObj = NULL;
D3DCheckAdapter*D3DCheckAdapter::GetInstace()
{
if(m_pCheckDisplayObj != NULL)
{
return m_pCheckDisplayObj;
}
m_pCheckDisplayObj = new D3DCheckAdapter();
return m_pCheckDisplayObj;
}
boolD3DCheckAdapter::GetBackBufferFormat(IDirect3D9 *pD3D, D3DDEVTYPE deviceType,bool bWindow, D3DFORMAT &fmt)
{
if(pD3D == NULL)
{
return false;
}
D3DDISPLAYMODE adapterMode;
pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&adapterMode);
if(D3D_OK != pD3D->CheckDeviceType(D3DADAPTER_DEFAULT,deviceType, adapterMode.Format, fmt, bWindow))
{
fmt = adapterMode.Format;
};
return true;
}
boolD3DCheckAdapter::GetDisplayVertexType(IDirect3D9 *pD3D, D3DDEVTYPE deviceType,int &nVertexType)
{
if(pD3D == NULL)
{
return false;
}
D3DCAPS9 caps;
pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT, deviceType,&caps);
if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
nVertexType = D3DCREATE_HARDWARE_VERTEXPROCESSING;
else
nVertexType = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
return true;
}
static char *print_guid(GUIDid) {
char * str = (char *)malloc(40);
sprintf( str, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
id.Data1, id.Data2, id.Data3,
id.Data4[0], id.Data4[1], id.Data4[2], id.Data4[3],
id.Data4[4], id.Data4[5], id.Data4[6], id.Data4[7] );
return str;
}
voidD3DCheckAdapter::PrintDisplayInfo(IDirect3D9 *pD3D)
{
if(pD3D == NULL)
{
return;
}
D3DADAPTER_IDENTIFIER9 adapterID; // Used to store device info
char strBuffer[2048];
DWORD dwDisplayCount = pD3D->GetAdapterCount();
for(DWORD i = 0; i < dwDisplayCount; i++)
{
if( pD3D->GetAdapterIdentifier( i/*D3DADAPTER_DEFAULT*/, 0,&adapterID ) != D3D_OK )
{
return;
}
_stprintf(strBuffer,_T("Driver: %s\n, Description: %s\n, Device Name: %s\n, Vendor id:%4x\n,Device id: %4x\n, Product: %x\n,\
Version:%x\n, SubVersion: %x\n, Build: %x %d.%d.%d.%d\n,\
SubSysId: %x\n, Revision: %x\n,GUID %s\n, WHQLLevel:%d\n"),
adapterID.Driver, adapterID.Description,adapterID.DeviceName, adapterID.VendorId, adapterID.DeviceId,
HIWORD(adapterID.DriverVersion.HighPart),LOWORD(adapterID.DriverVersion.HighPart),
HIWORD(adapterID.DriverVersion.LowPart),LOWORD(adapterID.DriverVersion.LowPart),
HIWORD(adapterID.DriverVersion.HighPart),LOWORD(adapterID.DriverVersion.HighPart),
HIWORD(adapterID.DriverVersion.LowPart),LOWORD(adapterID.DriverVersion.LowPart),
adapterID.SubSysId, adapterID.Revision,print_guid(adapterID.DeviceIdentifier), adapterID.WHQLLevel);
MessageBox(NULL,strBuffer, "Identity", MB_OK);
}
}
voidD3DCheckAdapter::PrintDisplayModeInfo(IDirect3D9 *pD3D, D3DFORMAT fmt)
{
if(pD3D == NULL)
{
MessageBox(NULL,"GetAdapterModeCount", "GetAdapterModeCount", MB_OK);
return;
}
// 显卡适配器模式的个数,主要是分辨率的差异
DWORD nAdapterModeCount=pD3D->GetAdapterModeCount(D3DADAPTER_DEFAULT, fmt);
if(nAdapterModeCount == 0)
{
char strTips[516];
sprintf_s(strTips, "D3DFMT_格式:%x不支持", fmt);
MessageBox(NULL, strTips, "PrintDisplayModeInfo",MB_OK);
}
for(DWORD i = 0; i < nAdapterModeCount; i++)
{
D3DDISPLAYMODE mode;
if(D3D_OK == pD3D->EnumAdapterModes(D3DADAPTER_DEFAULT,fmt, i,&mode))
{
char strBuffer[1024];
sprintf_s(strBuffer, "D3DDISPLAYMODE info, width:%u,height:%u, freshRate:%u, Format:%d \n",\
mode.Width, mode.Height, mode.RefreshRate,mode.Format);
OutputDebugString(strBuffer);
}
}
}
boolD3DCheckAdapter::CheckResourceFormat(IDirect3D9 *pD3D, DWORD nSrcUsage,D3DRESOURCETYPE srcType, D3DFORMAT srcFmt)
{
if(pD3D == NULL)
{
return false;
}
D3DDISPLAYMODE displayMode;
pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&displayMode);
if(D3D_OK == pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL, displayMode.Format, nSrcUsage, srcType, srcFmt))
{
return true;
}
return false;
}
boolD3DCheckAdapter::CheckMultiSampleType(IDirect3D9 *pD3D, D3DFORMAT surfaceFmt,bool bWindow,
D3DMULTISAMPLE_TYPE eSampleType, DWORD *pQualityLevel)
{
//变量MultiSampleType的值设为D3DMULTISAMPLE_NONMASKABLE,就必须设定成员变量MultiSampleQuality的质量等级值
if( D3D_OK ==pD3D->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT/*caps.AdapterOrdinal*/,
D3DDEVTYPE_HAL/*caps.DeviceType*/,
surfaceFmt,
bWindow,
eSampleType,
pQualityLevel))
{
return true;
}
return false;
};
bool D3DCheckAdapter::CheckDepthBufferFormt(IDirect3D9 *pD3D, D3DFORMAT targetBufferFmt, D3DFORMAT depthFmt)
{
if(pD3D == NULL)
{
return false;
}
D3DDISPLAYMODE mode;
pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &mode);
if(D3D_OK == pD3D->CheckDepthStencilMatch(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, mode.Format, targetBufferFmt, depthFmt))
{
return true;
}
return false;
}
// 三、main.cpp中
IDirect3D9* d3d9 = 0;
d3d9 = ::Direct3DCreate9(D3D_SDK_VERSION);
if( !d3d9 )
{
::MessageBox(0, "Direct3DCreate9() - FAILED", 0,0);
return false;
}
// 1.CheckDeviceFormat,显卡模式和表面会做兼容处理
D3DFORMAT backBufferFormat = D3DFMT_A8R8G8B8;
if(!D3DCheckAdapter::GetInstace()->GetBackBufferFormat(d3d9,deviceType, windowed, backBufferFormat))
{
::MessageBox(0, "getBackBufferFormat - FAILED", 0,0);
return false;
}
// 2.Check Vertex Proccessing Type
int vp = 0;
if(!D3DCheckAdapter::GetInstace()->GetDisplayVertexType(d3d9,deviceType, vp))
{
::MessageBox(0, "getBackBufferFormat - FAILED", 0,0);
return false;
}
// 3.显示显卡的信息
D3DCheckAdapter::GetInstace()->PrintDisplayInfo(d3d9);
// 4.输出显卡适配器模式信息,不会与缓存表面格式做兼容考虑
D3DCheckAdapter::GetInstace()->PrintDisplayModeInfo(d3d9,D3DFMT_X8R8G8B8);
// 5.显卡模式和资源表面会做兼容处理
int nUsageTexture = D3DUSAGE_WRITEONLY;
D3DFORMAT fmtTexture = D3DFMT_A8R8G8B8;
if(!D3DCheckAdapter::GetInstace()->CheckResourceFormat(d3d9,nUsageTexture/*D3DUSAGE_DEPTHSTENCIL*/,
D3DRTYPE_TEXTURE/*D3DRTYPE_SURFACE*/,fmtTexture/*D3DFMT_D15S1*/))
{
::MessageBox(0, "D3DCheckAdapter::GetInstace()->CheckResourceFormatFail", "Texture Resource FMT", 0);
return false;
}
// 6.采样纹理
D3DMULTISAMPLE_TYPE eSampleType = D3DMULTISAMPLE_4_SAMPLES;// 测试结果本机只是支持4,2类型的采样纹理
DWORD dwQualityLevel = 0;
if(!D3DCheckAdapter::GetInstace()->CheckMultiSampleType(d3d9,D3DFMT_A8R8G8B8, windowed, eSampleType,&dwQualityLevel))
{
eSampleType = D3DMULTISAMPLE_NONE;
}
// 7.深度缓存检测
D3DFORMAT depthStencilFmt = D3DFMT_D16/*D3DFMT_D15S1*/;
if(!D3DCheckAdapter::GetInstace()->CheckDepthBufferFormt(d3d9, D3DFMT_A8R8G8B8, depthStencilFmt))
{
::MessageBox(0, "GetInstace()->CheckDepthBufferFormt Fail", "Texture Resource FMT", 0);
return false;
}
// Step 3: Fill out the D3DPRESENT_PARAMETERS structure.
D3DPRESENT_PARAMETERS d3dpp;
d3dpp.BackBufferWidth = width;
d3dpp.BackBufferHeight = height;
d3dpp.BackBufferFormat = backBufferFormat;
d3dpp.BackBufferCount = 1;
d3dpp.MultiSampleType = eSampleType;//D3DMULTISAMPLE_NONE;
d3dpp.MultiSampleQuality = 0; // 不能用dwQualityLevel
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hwnd;
d3dpp.Windowed = windowed;
d3dpp.EnableAutoDepthStencil = true;
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
d3dpp.Flags = 0;
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;