⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xd3d.cpp

📁 MFC+D3D编程:在MFC单文档界面下使用D3D9.0进行编程
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	// 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 + -