📄 xd3d.cpp
字号:
// it's the programmer's (or user's) fault!
if (hr != D3DAPPERR_MEDIANOTFOUND &&
hr != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) &&
pdi->DevType == D3DDEVTYPE_HAL)
{
// request a reference device
if (FindBestWindowedMode(false, true))
{
// main window must not be topmost to show an error message...
SetWindowPos(m_hWndRender,
HWND_NOTOPMOST,
m_rcWindow.left,
m_rcWindow.top,
(m_rcWindow.right - m_rcWindow.left),
(m_rcWindow.bottom - m_rcWindow.top),
SWP_SHOWWINDOW);
// ...in which we let the user know we are switching
DisplayErrorMsg(hr, MSGWARN_SWITCHEDTOREF);
// try again
hr = InitializeEnvironment();
}
}
return hr;
}
//-----------------------------------------------------------------------------
// ResetEnvironment(): signals the app it must invalidate all video memory
// objects and render the current frame if paused, then resets the device. The
// backbuffer description is saved.
//-----------------------------------------------------------------------------
HRESULT CXD3D::ResetEnvironment()
{
HRESULT hr;
// invalidate any resources thatt cannot survive the reset
if (m_bDeviceObjectsRestored)
{
m_bDeviceObjectsRestored = false;
InvalidateDeviceObjects();
}
if (FAILED(hr = m_pd3dDevice->Reset(&m_d3dpp)))
return hr;
// restore (re-create) resources
if (FAILED(hr = RestoreDeviceObjects()))
{
InvalidateDeviceObjects();
return hr;
}
m_bDeviceObjectsRestored = true;
return S_OK;
}
//-----------------------------------------------------------------------------
// RenderEnvironment(): tests for coop level, possibly resets the environment
// and issues the app defined FrameMove and Render that will actually draw the
// scene.
//-----------------------------------------------------------------------------
HRESULT CXD3D::RenderEnvironment()
{
HRESULT hr;
if (m_bDeviceLost)
{
// test the cooperative level to see if it's okay to render
if (FAILED(hr = m_pd3dDevice->TestCooperativeLevel()))
{
// if the device was truly lost, (i.e., a fullscreen device just
// lost focus), wait until we get it back
if (hr == D3DERR_DEVICELOST)
return S_OK;
// eventually, we will get this return value, indicating
// that we can reset the device
if (hr == D3DERR_DEVICENOTRESET)
{
// if we are windowed, read the desktop mode and use the same
// format for the back buffer UNTESTED WITH THE NEW SETTINGS CLASS!!!
if (m_bWindowed)
{
m_pd3d->GetAdapterDisplayMode(Settings.GetAdapterInfo()->AdapterOrdinal,
&Settings.GetDisplayMode());
m_d3dpp.BackBufferFormat = Settings.GetDisplayMode().Format;
}
// ...before resetting the device
if (FAILED(hr = ResetEnvironment()))
return hr;
}
return hr;
}
// we have a device
m_bDeviceLost = false;
}
// setup the app's timers
FLOAT fTime = DXUtil_Timer(TIMER_GETAPPTIME);
FLOAT fElapsedTime = DXUtil_Timer(TIMER_GETELAPSEDTIME);
// skip rendering if no time elapsed (the application is paused)
if (fElapsedTime == 0.0f)
return S_OK;
// store the time
m_fTime = fTime;
m_fElapsedTime = fElapsedTime;
// move the scene
if (FAILED(hr = FrameMove()))
return hr;
// render the scene as normal
if( FAILED(hr = Render()))
return hr;
// update the FPS
UpdateStats();
// present the next buffer in the swap chain
if(m_pd3dDevice->Present(NULL, NULL, NULL, NULL) == D3DERR_DEVICELOST)
m_bDeviceLost = true;
return S_OK;
}
//-----------------------------------------------------------------------------
// CleanupEnvironment(): cleanup device objects
//-----------------------------------------------------------------------------
void CXD3D::CleanupEnvironment()
{
if (m_pd3dDevice != NULL)
{
if (m_bDeviceObjectsRestored)
{
m_bDeviceObjectsRestored = false;
InvalidateDeviceObjects();
}
if (m_bDeviceObjectsInited)
{
m_bDeviceObjectsInited = false;
DeleteDeviceObjects();
}
if (m_pd3dDevice->Release() > 0)
DisplayErrorMsg(D3DAPPERR_NONZEROREFCOUNT, MSGERR_CANNOTCONTINUE);
m_pd3dDevice = NULL;
}
}
//-----------------------------------------------------------------------------
// UpdateStats()
//-----------------------------------------------------------------------------
void CXD3D::UpdateStats()
{
// keep track of the frame count
static float fLastTime = 0.0f;
static DWORD dwFrames = 0;
float fTime = DXUtil_Timer(TIMER_GETABSOLUTETIME);
++dwFrames;
// let a full second elapse before updating the scene stats
if (fTime - fLastTime <= 1.0f)
return;
m_fFPS = dwFrames / (fTime - fLastTime);
fLastTime = fTime;
dwFrames = 0;
const int nMax = UBOUND(m_strFrameStats);
_sntprintf(m_strFrameStats, nMax, _T("%.02f fps"), m_fFPS);
m_strFrameStats[nMax - 1] = TEXT('\0');
}
//-----------------------------------------------------------------------------
// Pause(): toggles the active state of the app and resets the timer
//-----------------------------------------------------------------------------
void CXD3D::Pause(bool bPause)
{
static DWORD dwAppPausedCount = 0;
dwAppPausedCount += BSCALE(bPause);
m_bActive = dwAppPausedCount == 0;
// handle the first pause request (of many, nestable pause requests) and
// stop the scene from animating
if (bPause && dwAppPausedCount == 1)
DXUtil_Timer(TIMER_STOP);
// restart the timer
if (dwAppPausedCount == 0)
DXUtil_Timer(TIMER_START);
}
//-----------------------------------------------------------------------------
// Name: DisplayErrorMsg()
//-----------------------------------------------------------------------------
HRESULT CXD3D::DisplayErrorMsg(HRESULT hr, DWORD dwType)
{
static bool s_bFatalErrorReported = false;
TCHAR strMsg[512];
// If a fatal error message has already been reported, the app
// is already shutting down, so don't show more error messages.
if (s_bFatalErrorReported)
return hr;
switch(hr)
{
case D3DAPPERR_NODIRECT3D:
_tcscpy(strMsg,
_T("Could not initialize Direct3D; check that the\n")
_T("latest version of DirectX is correctly installed\n")
_T("on your system."));
break;
case D3DAPPERR_NOCOMPATIBLEDEVICES:
_tcscpy(strMsg,
_T("Could not find any compatible Direct3D devices."));
break;
case D3DAPPERR_NOWINDOWABLEDEVICES:
_tcscpy(strMsg,
_T("Cannot run in a desktop window with the current\n")
_T("display settings; change your desktop settings\n")
_T("to a 16- or 32-bit display mode and retry."));
break;
case D3DAPPERR_NOHARDWAREDEVICE:
_tcscpy(strMsg,
_T("No hardware-accelerated Direct3D devices found."));
break;
case D3DAPPERR_HALNOTCOMPATIBLE:
_tcscpy(strMsg,
_T("This application requires functionality not\n")
_T("available on your Direct3D hardware accelerator."));
break;
case D3DAPPERR_NOWINDOW:
_tcscpy(strMsg,
_T("No window to render to was supplied.\n"));
break;
case D3DAPPERR_NOWINDOWEDHAL:
_tcscpy(strMsg,
_T("Your Direct3D hardware accelerator cannot render\n")
_T("into a window.\n"));
break;
case D3DAPPERR_NODESKTOPHAL:
_tcscpy(strMsg,
_T("Your Direct3D hardware accelerator cannot render\n")
_T("into a window with the current desktop display\n")
_T("settings."));
break;
case D3DAPPERR_NOHALTHISMODE:
_tcscpy(strMsg,
_T("This application requires functionality that is\n")
_T("not available on your Direct3D hardware accelerator\n")
_T("with the current desktop display settings.\n"));
break;
case D3DAPPERR_MEDIANOTFOUND:
case HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND):
_tcscpy(strMsg, _T("Could not load required media."));
break;
case D3DAPPERR_RESETFAILED:
_tcscpy(strMsg, _T("Could not reset the Direct3D device."));
break;
case D3DAPPERR_INITFAILED:
_tcscpy(strMsg, _T("Could not initialize the Direct3D device."));
break;
case D3DAPPERR_NONZEROREFCOUNT:
_tcscpy(strMsg,
_T("A D3D object has a non-zero reference count\n")
_T("(meaning things were not properly cleaned up)."));
break;
case D3DAPPERR_NULLREFDEVICE:
_tcscpy(strMsg,
_T("Warning: Nothing will be rendered.\n")
_T("The reference rendering device was selected, but\n")
_T("your computer only has a reduced-functionality\n")
_T("reference device installed. Install the DirectX\n")
_T("SDK to get the full reference device.\n"));
break;
case E_OUTOFMEMORY:
_tcscpy(strMsg, _T("Not enough memory."));
break;
case D3DERR_OUTOFVIDEOMEMORY:
_tcscpy(strMsg, _T("Not enough video memory."));
break;
default:
_tcscpy(strMsg, _T("Unknown Direct3D error."));
}
if (dwType == MSGWARN_SWITCHEDTOREF)
{
_tcscat(strMsg,
_T("\n\nSwitching to the reference rasterizer, a\n")
_T("software device that implements the entire\n")
_T("Direct3D feature set, but runs very slowly."));
}
if (dwType == MSGERR_CANNOTCONTINUE)
{
s_bFatalErrorReported = true;
_tcscat(strMsg, _T("\n\nDirect3D cannot continue."));
}
MessageBox(NULL, strMsg, "Direct3D", MB_ICONWARNING | MB_OK);
// close the window
if (s_bFatalErrorReported && m_hWndRender) SendMessage(m_hWndRender, WM_CLOSE, 0, 0);
return hr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -