📄 xd3d.cpp
字号:
//-----------------------------------------------------------------------------
// XD3D.cpp: custom Direct3D (CXD3D) Implementation file
//-----------------------------------------------------------------------------
#include "stdafx.h"
#include "XD3D.h"
//-----------------------------------------------------------------------------
// CXD3D Constructor
//-----------------------------------------------------------------------------
CXD3D::CXD3D()
{
m_bActive = false;
m_bStartFullscreen = false;
m_bShowCursor = true;
m_bClipCursor = true;
m_bWindowed = true;
m_bIgnoreSizeChange = false;
m_bDeviceLost = false;
m_bDeviceObjectsInited = false;
m_bDeviceObjectsRestored = false;
m_fTime = 0.0f;
m_fElapsedTime = 0.0f;
m_fFPS = 0.0f;
m_strDeviceStats[0] = _T('\0');
m_strFrameStats[0] = _T('\0');
m_hWndRender = NULL;
m_hWndFocus = NULL;
m_pd3d = NULL;
m_pd3dDevice = NULL;
m_dwCreateFlags = 0L;
Pause(true); // until we're ready to render
}
//-----------------------------------------------------------------------------
// CreateD3D(): provided m_hWnd has been initialised, it instantiates the d3d
// object, chooses initial d3d settings and initializes the d3d stuff.
//-----------------------------------------------------------------------------
HRESULT CXD3D::CreateD3D()
{
HRESULT hr;
// check for a window to render to
if (m_hWndRender == NULL)
return DisplayErrorMsg(D3DAPPERR_NOWINDOW, MSGERR_CANNOTCONTINUE);
// instantiate a D3D Object
if ((m_pd3d = Direct3DCreate9(D3D_SDK_VERSION)) == NULL)
return DisplayErrorMsg(D3DAPPERR_NODIRECT3D, MSGERR_CANNOTCONTINUE);
// build a list of D3D adapters, modes and devices
if (FAILED(hr = Enumeration.Enumerate(m_pd3d)))
{
SAFE_RELEASE(m_pd3d);
return DisplayErrorMsg(hr, MSGERR_CANNOTCONTINUE);
}
// use the device window as the focus window, unless otherwise specified
if (m_hWndFocus == NULL) m_hWndFocus = m_hWndRender;
// save some window properties into class members
m_dwWindowStyle = GetWindowLong(m_hWndRender, GWL_STYLE);
GetWindowRect(m_hWndRender, &m_rcWindow);
GetClientRect(m_hWndRender, &m_rcClient);
// choose the best settings to render
if (FAILED(hr = ChooseInitialSettings()))
{
SAFE_RELEASE(m_pd3d);
return DisplayErrorMsg(hr, MSGERR_CANNOTCONTINUE);
}
// initialize the timer
DXUtil_Timer(TIMER_START);
// initialize the app's custom (pre-device creation) stuff
if (FAILED(hr = OneTimeSceneInit()))
{
SAFE_RELEASE(m_pd3d);
return DisplayErrorMsg(hr, MSGERR_CANNOTCONTINUE);
}
// initialize the 3D environment, creating the device
if (FAILED(hr = InitializeEnvironment()))
{
SAFE_RELEASE(m_pd3d);
return DisplayErrorMsg(hr, MSGERR_CANNOTCONTINUE);
}
// D3D is ready to go so unpause it
Pause(false);
return S_OK;
}
//-----------------------------------------------------------------------------
// FindBestFullscreenMode(): Adjust settings with the best available fullscreen
// mode, subject to the HAL and REF constraints; returns false if no such mode
// can be found.
//-----------------------------------------------------------------------------
bool CXD3D::FindBestFullscreenMode(bool bHAL, bool bREF)
{
// for fullscreen, default to the first HAL device combo that supports the
// current desktop display mode, to any display mode if HAL is incompatible
// with the desktop mode, or to a non-HAL if no HAL is available
D3DDISPLAYMODE dmDesktop;
D3DDISPLAYMODE dmDesktopBest;
D3DDISPLAYMODE dmBest;
// fortunately for us, D3DFMT_UNKNOWN == 0
ZeroMemory(&dmDesktopBest, sizeof(D3DDISPLAYMODE));
ZeroMemory(&dmBest, sizeof(D3DDISPLAYMODE));
// 'best' storage
AdapterInfo* paiBest = NULL;
DeviceInfo* pdiBest = NULL;
DeviceCombo* pdcBest = NULL;
// iterators
AdapterInfo* pai;
DeviceInfo* pdi;
DeviceCombo* pdc;
// success flags
bool bBetter, bBest;
UINT i, j, k;
// traverse the adpater infos
for (i = 0; i < Enumeration.AdapterInfos.Length(); i++)
{
pai = &Enumeration.AdapterInfos[i];
// get the current display mode of each adapter
m_pd3d->GetAdapterDisplayMode(pai->AdapterOrdinal, &dmDesktop);
// traverse device infos on each adapter info
for (j = 0; j < pai->DeviceInfos.Length(); j++)
{
pdi = &pai->DeviceInfos[j];
// skip devices with other than the requested type
if (bHAL && pdi->DevType != D3DDEVTYPE_HAL)
continue;
if (bREF && pdi->DevType != D3DDEVTYPE_REF)
continue;
// traverse device combos for each device info
for (k = 0; k < pdi->DeviceCombos.Length(); k++)
{
pdc = &pdi->DeviceCombos[k];
// skip the windowed combos
if (pdc->Windowed)
continue;
// this device combo is 'better' than the current best if:
// (a) there's no best yet;
// (b) it's a HAL and the current best is not;
// (c) it's a HAL matching the desktop's format, while the
// current best does not;
// (d) it's a HAL and both the display and backbuffer formats
// match the desktop's, in which case it is also the best
bBetter = pdcBest == NULL ||
pdc->DevType == D3DDEVTYPE_HAL &&
pdcBest->DevType != D3DDEVTYPE_HAL ||
pdc->DevType == D3DDEVTYPE_HAL &&
pdc->DisplayFormat == dmDesktop.Format &&
pdcBest->DisplayFormat != dmDesktop.Format;
bBest = pdc->DevType == D3DDEVTYPE_HAL &&
pdc->DisplayFormat == dmDesktop.Format &&
pdc->BackBufferFormat == dmDesktop.Format;
bBetter |= bBest;
if (bBetter)
{
// make it the best so far
dmDesktopBest = dmDesktop;
paiBest = pai;
pdiBest = pdi;
pdcBest = pdc;
// this one looks great -- take it
if (bBest)
goto DoneSearchingFDC;
}
}
}
}
DoneSearchingFDC:
// no suitable dc found!
if (pdcBest == NULL)
return false;
// now we need to find a display mode on the best ai that uses the best
// dc's display format and is as close to the best desktop display mode
// as possible
D3DDISPLAYMODE dm;
for (i = 0; i < paiBest->DisplayModes.Length(); i++)
{
dm = paiBest->DisplayModes[i];
// formats must match
if (dm.Format != dmDesktopBest.Format)
continue;
// compare other properties
if (dm.Width == dmDesktopBest.Width &&
dm.Height == dmDesktopBest.Height &&
dm.RefreshRate == dmDesktopBest.RefreshRate)
{
// perfect match, break out
dmBest = dm;
break;
}
else if (dm.Width == dmDesktopBest.Width &&
dm.Height == dmDesktopBest.Height &&
dm.RefreshRate > dmBest.RefreshRate)
{
// faster
dmBest = dm;
}
else if (dm.Width == dmDesktopBest.Width)
{
// same width
dmBest = dm;
}
else if (dmBest.Width == 0)
{
// we don't have anything better yet
dmBest = dm;
}
}
// save these settings
Settings.Windowed = 0;
Settings.AdapterInfos[0] = paiBest;
// index to the best dm within the ai
Settings.ndm[0] = paiBest->DisplayModes.Find(dm);
// indices to the best di and dc
if (bBest)
{
Settings.ndi[0] = j;
Settings.ndc[0] = k;
}
else
{
// retract to the 'better' di and dc
Settings.ndi[0] = (UINT)paiBest->DeviceInfos.Find(*pdiBest);
Settings.ndc[0] = (UINT)pdiBest->DeviceCombos.Find(*pdcBest);
}
return true;
}
//-----------------------------------------------------------------------------
// FindBestWindowedMode(): adjusts settings with best available windowed mode,
// subject to the HAL and REF constraints; returns false if no such mode can be
// found.
//-----------------------------------------------------------------------------
bool CXD3D::FindBestWindowedMode(bool bHAL, bool bREF)
{
// get the display mode of the primary adapter, which is assumed to be
// where the window will appear
D3DDISPLAYMODE dm;
m_pd3d->GetAdapterDisplayMode(0, &dm);
// 'best' storage
AdapterInfo* paiBest = NULL;
DeviceInfo* pdiBest = NULL;
DeviceCombo* pdcBest = NULL;
// iterators
AdapterInfo* pai;
DeviceInfo* pdi;
DeviceCombo* pdc;
// success flags
bool bBetter, bBest;
UINT i, j, k;
// traverse the enumerated adapters information
for (i = 0; i < Enumeration.AdapterInfos.Length(); i++)
{
pai = &Enumeration.AdapterInfos[i];
// for each adapter, traverse the device infos
for (j = 0; j < pai->DeviceInfos.Length(); j++)
{
pdi = &pai->DeviceInfos[j];
// skip according to the requirements
if (bHAL && pdi->DevType != D3DDEVTYPE_HAL)
continue;
if (bREF && pdi->DevType != D3DDEVTYPE_REF)
continue;
// traverse device combos for this device
for (k = 0; k < pdi->DeviceCombos.Length(); k++)
{
pdc = &pdi->DeviceCombos[k];
// skip the non-windowed or distinct format combos
if (!pdc->Windowed)
continue;
if (pdc->DisplayFormat != dm.Format)
continue;
// this device combo is better than the current best if:
// (a) there's no best yet;
// (b) it's a HAL and the current best is not;
// (c) it's a HAL with matching backbuffer and display
// formats, in which case is also the best
bBetter = pdcBest == NULL ||
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -