📄 d3dapp.cpp
字号:
// Desc: Reset the device if the client area size has changed.
//-----------------------------------------------------------------------------
HRESULT CD3DApplication::HandlePossibleSizeChange()
{
HRESULT hr = S_OK;
RECT rcClientOld;
rcClientOld = m_rcWindowClient;
if( m_bIgnoreSizeChange )
return S_OK;
// Update window properties
GetWindowRect( m_hWnd, &m_rcWindowBounds );
GetClientRect( m_hWnd, &m_rcWindowClient );
if( rcClientOld.right - rcClientOld.left !=
m_rcWindowClient.right - m_rcWindowClient.left ||
rcClientOld.bottom - rcClientOld.top !=
m_rcWindowClient.bottom - m_rcWindowClient.top)
{
// A new window size will require a new backbuffer
// size, so the 3D structures must be changed accordingly.
Pause( true );
m_d3dpp.BackBufferWidth = m_rcWindowClient.right - m_rcWindowClient.left;
m_d3dpp.BackBufferHeight = m_rcWindowClient.bottom - m_rcWindowClient.top;
if( m_pd3dDevice != NULL )
{
// Reset the 3D environment
if( FAILED( hr = Reset3DEnvironment() ) )
{
if( hr != D3DERR_OUTOFVIDEOMEMORY )
hr = D3DAPPERR_RESETFAILED;
DisplayErrorMsg( hr, MSGERR_APPMUSTEXIT );
}
}
Pause( false );
}
return hr;
}
//-----------------------------------------------------------------------------
// Name: Initialize3DEnvironment()
// Desc:
//-----------------------------------------------------------------------------
HRESULT CD3DApplication::Initialize3DEnvironment()
{
HRESULT hr;
D3DAdapterInfo* pAdapterInfo = m_d3dSettings.PAdapterInfo();
D3DDeviceInfo* pDeviceInfo = m_d3dSettings.PDeviceInfo();
m_bWindowed = m_d3dSettings.IsWindowed;
// Prepare window for possible windowed/fullscreen change
AdjustWindowForChange();
// Set up the presentation parameters
BuildPresentParamsFromSettings();
if( pDeviceInfo->Caps.PrimitiveMiscCaps & D3DPMISCCAPS_NULLREFERENCE )
{
// Warn user about null ref device that can't render anything
DisplayErrorMsg( D3DAPPERR_NULLREFDEVICE, 0 );
}
DWORD behaviorFlags;
if (m_d3dSettings.GetVertexProcessingType() == SOFTWARE_VP)
behaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
else if (m_d3dSettings.GetVertexProcessingType() == MIXED_VP)
behaviorFlags = D3DCREATE_MIXED_VERTEXPROCESSING;
else if (m_d3dSettings.GetVertexProcessingType() == HARDWARE_VP)
behaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
else if (m_d3dSettings.GetVertexProcessingType() == PURE_HARDWARE_VP)
behaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE;
else
behaviorFlags = 0; // TODO: throw exception
// Create the device
hr = m_pD3D->CreateDevice( m_d3dSettings.AdapterOrdinal(), pDeviceInfo->DevType,
m_hWndFocus, behaviorFlags, &m_d3dpp,
&m_pd3dDevice );
if( SUCCEEDED(hr) )
{
// When moving from fullscreen to windowed mode, it is important to
// adjust the window size after recreating the device rather than
// beforehand to ensure that you get the window size you want. For
// example, when switching from 640x480 fullscreen to windowed with
// a 1000x600 window on a 1024x768 desktop, it is impossible to set
// the window size to 1000x600 until after the display mode has
// changed to 1024x768, because windows cannot be larger than the
// desktop.
if( m_bWindowed )
{
SetWindowPos( m_hWnd, HWND_NOTOPMOST,
m_rcWindowBounds.left, m_rcWindowBounds.top,
( m_rcWindowBounds.right - m_rcWindowBounds.left ),
( m_rcWindowBounds.bottom - m_rcWindowBounds.top ),
SWP_SHOWWINDOW );
}
// Store device Caps
m_pd3dDevice->GetDeviceCaps( &m_d3dCaps );
m_dwCreateFlags = behaviorFlags;
// Store device description
if( pDeviceInfo->DevType == D3DDEVTYPE_REF )
lstrcpy( m_strDeviceStats, TEXT("REF") );
else if( pDeviceInfo->DevType == D3DDEVTYPE_HAL )
lstrcpy( m_strDeviceStats, TEXT("HAL") );
else if( pDeviceInfo->DevType == D3DDEVTYPE_SW )
lstrcpy( m_strDeviceStats, TEXT("SW") );
if( behaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING &&
behaviorFlags & D3DCREATE_PUREDEVICE )
{
if( pDeviceInfo->DevType == D3DDEVTYPE_HAL )
lstrcat( m_strDeviceStats, TEXT(" (pure hw vp)") );
else
lstrcat( m_strDeviceStats, TEXT(" (simulated pure hw vp)") );
}
else if( behaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING )
{
if( pDeviceInfo->DevType == D3DDEVTYPE_HAL )
lstrcat( m_strDeviceStats, TEXT(" (hw vp)") );
else
lstrcat( m_strDeviceStats, TEXT(" (simulated hw vp)") );
}
else if( behaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING )
{
if( pDeviceInfo->DevType == D3DDEVTYPE_HAL )
lstrcat( m_strDeviceStats, TEXT(" (mixed vp)") );
else
lstrcat( m_strDeviceStats, TEXT(" (simulated mixed vp)") );
}
else if( behaviorFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING )
{
lstrcat( m_strDeviceStats, TEXT(" (sw vp)") );
}
if( pDeviceInfo->DevType == D3DDEVTYPE_HAL )
{
// Be sure not to overflow m_strDeviceStats when appending the adapter
// description, since it can be long. Note that the adapter description
// is initially CHAR and must be converted to TCHAR.
lstrcat( m_strDeviceStats, TEXT(": ") );
const int cchDesc = sizeof(pAdapterInfo->AdapterIdentifier.Description);
TCHAR szDescription[cchDesc];
DXUtil_ConvertAnsiStringToGenericCch( szDescription,
pAdapterInfo->AdapterIdentifier.Description, cchDesc );
int maxAppend = sizeof(m_strDeviceStats) / sizeof(TCHAR) -
lstrlen( m_strDeviceStats ) - 1;
_tcsncat( m_strDeviceStats, szDescription, maxAppend );
}
// Store render target surface desc
LPDIRECT3DSURFACE9 pBackBuffer = NULL;
m_pd3dDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer );
pBackBuffer->GetDesc( &m_d3dsdBackBuffer );
pBackBuffer->Release();
// Set up the fullscreen cursor
if( m_bShowCursorWhenFullscreen && !m_bWindowed )
{
HCURSOR hCursor;
#ifdef _WIN64
hCursor = (HCURSOR)GetClassLongPtr( m_hWnd, GCLP_HCURSOR );
#else
hCursor = (HCURSOR)ULongToHandle( GetClassLong( m_hWnd, GCL_HCURSOR ) );
#endif
D3DUtil_SetDeviceCursor( m_pd3dDevice, hCursor, true );
m_pd3dDevice->ShowCursor( true );
}
// Confine cursor to fullscreen window
if( m_bClipCursorWhenFullscreen )
{
if (!m_bWindowed )
{
RECT rcWindow;
GetWindowRect( m_hWnd, &rcWindow );
ClipCursor( &rcWindow );
}
else
{
ClipCursor( NULL );
}
}
// Initialize the app's device-dependent objects
hr = InitDeviceObjects();
if( FAILED(hr) )
{
DeleteDeviceObjects();
}
else
{
m_bDeviceObjectsInited = true;
hr = RestoreDeviceObjects();
if( FAILED(hr) )
{
InvalidateDeviceObjects();
}
else
{
m_bDeviceObjectsRestored = true;
return S_OK;
}
}
// Cleanup before we try again
Cleanup3DEnvironment();
}
// If that failed, fall back to the reference rasterizer
if( hr != D3DAPPERR_MEDIANOTFOUND &&
hr != HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ) &&
pDeviceInfo->DevType == D3DDEVTYPE_HAL )
{
if (FindBestWindowedMode(false, true))
{
m_bWindowed = true;
AdjustWindowForChange();
// Make sure main window isn't topmost, so error message is visible
SetWindowPos( m_hWnd, HWND_NOTOPMOST,
m_rcWindowBounds.left, m_rcWindowBounds.top,
( m_rcWindowBounds.right - m_rcWindowBounds.left ),
( m_rcWindowBounds.bottom - m_rcWindowBounds.top ),
SWP_SHOWWINDOW );
// Let the user know we are switching from HAL to the reference rasterizer
DisplayErrorMsg( hr, MSGWARN_SWITCHEDTOREF );
hr = Initialize3DEnvironment();
}
}
return hr;
}
//-----------------------------------------------------------------------------
// Name: BuildPresentParamsFromSettings()
// Desc:
//-----------------------------------------------------------------------------
void CD3DApplication::BuildPresentParamsFromSettings()
{
m_d3dpp.Windowed = m_d3dSettings.IsWindowed;
m_d3dpp.BackBufferCount = 1;
m_d3dpp.MultiSampleType = m_d3dSettings.MultisampleType();
m_d3dpp.MultiSampleQuality = m_d3dSettings.MultisampleQuality();
m_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
m_d3dpp.EnableAutoDepthStencil = m_d3dEnumeration.AppUsesDepthBuffer;
m_d3dpp.hDeviceWindow = m_hWnd;
if( m_d3dEnumeration.AppUsesDepthBuffer )
{
m_d3dpp.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
m_d3dpp.AutoDepthStencilFormat = m_d3dSettings.DepthStencilBufferFormat();
}
else
{
m_d3dpp.Flags = 0;
}
if( m_bWindowed )
{
m_d3dpp.BackBufferWidth = m_rcWindowClient.right - m_rcWindowClient.left;
m_d3dpp.BackBufferHeight = m_rcWindowClient.bottom - m_rcWindowClient.top;
m_d3dpp.BackBufferFormat = m_d3dSettings.PDeviceCombo()->BackBufferFormat;
m_d3dpp.FullScreen_RefreshRateInHz = 0;
m_d3dpp.PresentationInterval = m_d3dSettings.PresentInterval();
}
else
{
m_d3dpp.BackBufferWidth = m_d3dSettings.DisplayMode().Width;
m_d3dpp.BackBufferHeight = m_d3dSettings.DisplayMode().Height;
m_d3dpp.BackBufferFormat = m_d3dSettings.PDeviceCombo()->BackBufferFormat;
m_d3dpp.FullScreen_RefreshRateInHz = m_d3dSettings.Fullscreen_DisplayMode.RefreshRate;
m_d3dpp.PresentationInterval = m_d3dSettings.PresentInterval();
}
}
//-----------------------------------------------------------------------------
// Name: Reset3DEnvironment()
// Desc:
//-----------------------------------------------------------------------------
HRESULT CD3DApplication::Reset3DEnvironment()
{
HRESULT hr;
// Release all vidmem objects
if( m_bDeviceObjectsRestored )
{
m_bDeviceObjectsRestored = false;
InvalidateDeviceObjects();
}
// Reset the device
if( FAILED( hr = m_pd3dDevice->Reset( &m_d3dpp ) ) )
return hr;
// Store render target surface desc
LPDIRECT3DSURFACE9 pBackBuffer;
m_pd3dDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer );
pBackBuffer->GetDesc( &m_d3dsdBackBuffer );
pBackBuffer->Release();
// Set up the fullscreen cursor
if( m_bShowCursorWhenFullscreen && !m_bWindowed )
{
HCURSOR hCursor;
#ifdef _WIN64
hCursor = (HCURSOR)GetClassLongPtr( m_hWnd, GCLP_HCURSOR );
#else
hCursor = (HCURSOR)ULongToHandle( GetClassLong( m_hWnd, GCL_HCURSOR ) );
#endif
D3DUtil_SetDeviceCursor( m_pd3dDevice, hCursor, true );
m_pd3dDevice->ShowCursor( true );
}
// Confine cursor to fullscreen window
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -