📄 d3dsaver.cpp
字号:
m_hrError = D3DAPPERR_NOPREVIEW;
else
m_hrError = D3DAPPERR_CREATEDEVICEFAILED;
}
}
}
// Once all mode changes are done, (re-)determine coordinates of all
// screens, and make sure windows still cover each screen
for( iMonitor = 0; iMonitor < m_dwNumMonitors; iMonitor++ )
{
pMonitorInfo = &m_Monitors[iMonitor];
monitorInfo.cbSize = sizeof(MONITORINFO);
GetMonitorInfo( pMonitorInfo->hMonitor, &monitorInfo );
pMonitorInfo->rcScreen = monitorInfo.rcMonitor;
if( !m_bWindowed )
{
SetWindowPos( pMonitorInfo->hWnd, HWND_TOPMOST, monitorInfo.rcMonitor.left,
monitorInfo.rcMonitor.top, monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left,
monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top, SWP_NOACTIVATE );
}
}
// For fullscreen, determine bounds of the virtual screen containing all
// screens that are rendering. Don't just use SM_XVIRTUALSCREEN, because
// we don't want to count screens that are just black
if( !m_bWindowed )
{
for( iRenderUnit = 0; iRenderUnit < m_dwNumRenderUnits; iRenderUnit++ )
{
pRenderUnit = &m_RenderUnits[iRenderUnit];
pMonitorInfo = &m_Monitors[pRenderUnit->iMonitor];
UnionRect( &m_rcRenderTotal, &m_rcRenderTotal, &pMonitorInfo->rcScreen );
}
}
if( !m_bErrorMode )
{
// Initialize D3D devices for all render units
for( iRenderUnit = 0; iRenderUnit < m_dwNumRenderUnits; iRenderUnit++ )
{
pRenderUnit = &m_RenderUnits[iRenderUnit];
SwitchToRenderUnit( iRenderUnit );
if ( FAILED(hr = InitDeviceObjects() ) )
{
m_bErrorMode = TRUE;
m_hrError = D3DAPPERR_INITDEVICEOBJECTSFAILED;
}
else
{
pRenderUnit->bDeviceObjectsInited = TRUE;
if ( FAILED(hr = RestoreDeviceObjects() ) )
{
m_bErrorMode = TRUE;
m_hrError = D3DAPPERR_INITDEVICEOBJECTSFAILED;
}
else
{
pRenderUnit->bDeviceObjectsRestored = TRUE;
}
}
}
UpdateDeviceStats();
}
// Make sure all those display changes don't count as user mouse moves
m_dwSaverMouseMoveCount = 0;
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: GetBestAdapter()
// Desc: To decide which adapter to use, loop through monitors until you find
// one whose adapter has a compatible HAL. If none, use the first
// monitor that has an compatible SW device.
//-----------------------------------------------------------------------------
BOOL CD3DScreensaver::GetBestAdapter( DWORD* piAdapter )
{
DWORD iAdapterBest = NO_ADAPTER;
DWORD iAdapter;
DWORD iMonitor;
MonitorInfo* pMonitorInfo;
D3DAdapterInfo* pD3DAdapterInfo;
for( iMonitor = 0; iMonitor < m_dwNumMonitors; iMonitor++ )
{
pMonitorInfo = &m_Monitors[iMonitor];
iAdapter = pMonitorInfo->iAdapter;
if( iAdapter == NO_ADAPTER )
continue;
pD3DAdapterInfo = m_Adapters[iAdapter];
if( pD3DAdapterInfo->bHasAppCompatHAL )
{
iAdapterBest = iAdapter;
break;
}
if( pD3DAdapterInfo->bHasAppCompatSW )
{
iAdapterBest = iAdapter;
// but keep looking...
}
}
*piAdapter = iAdapterBest;
return (iAdapterBest != NO_ADAPTER);
}
//-----------------------------------------------------------------------------
// Name: CreateFullscreenRenderUnit()
// Desc:
//-----------------------------------------------------------------------------
HRESULT CD3DScreensaver::CreateFullscreenRenderUnit( RenderUnit* pRenderUnit )
{
HRESULT hr;
UINT iAdapter = pRenderUnit->iAdapter;
D3DAdapterInfo* pD3DAdapterInfo = m_Adapters[iAdapter];
DWORD iMonitor = pD3DAdapterInfo->iMonitor;
D3DDeviceInfo* pD3DDeviceInfo;
D3DModeInfo* pD3DModeInfo;
DWORD dwCurrentDevice;
D3DDEVTYPE curType;
if( iAdapter >= m_dwNumAdapters )
return E_FAIL;
if( pD3DAdapterInfo->dwNumDevices == 0 )
return E_FAIL;
// Find the best device for the adapter. Use HAL
// if it's there, otherwise SW, otherwise REF.
dwCurrentDevice = 0xffff;
curType = D3DDEVTYPE_FORCE_DWORD;
for( DWORD iDevice = 0; iDevice < pD3DAdapterInfo->dwNumDevices; iDevice++)
{
pD3DDeviceInfo = &pD3DAdapterInfo->devices[iDevice];
if( pD3DDeviceInfo->DeviceType == D3DDEVTYPE_HAL && !pD3DAdapterInfo->bDisableHW )
{
dwCurrentDevice = iDevice;
curType = D3DDEVTYPE_HAL;
break; // stop looking
}
else if( pD3DDeviceInfo->DeviceType == D3DDEVTYPE_SW )
{
dwCurrentDevice = iDevice;
curType = D3DDEVTYPE_SW;
// but keep looking
}
else if( pD3DDeviceInfo->DeviceType == D3DDEVTYPE_REF && m_bAllowRef && curType != D3DDEVTYPE_SW )
{
dwCurrentDevice = iDevice;
curType = D3DDEVTYPE_REF;
// but keep looking
}
}
if( dwCurrentDevice == 0xffff )
return D3DAPPERR_NOHARDWAREDEVICE;
pD3DDeviceInfo = &pD3DAdapterInfo->devices[dwCurrentDevice];
pD3DDeviceInfo->dwCurrentMode = 0xffff;
if( pD3DAdapterInfo->dwUserPrefWidth != 0 )
{
// Try to find mode that matches user preference
for( DWORD iMode = 0; iMode < pD3DDeviceInfo->dwNumModes; iMode++)
{
pD3DModeInfo = &pD3DDeviceInfo->modes[iMode];
if( pD3DModeInfo->Width == pD3DAdapterInfo->dwUserPrefWidth &&
pD3DModeInfo->Height == pD3DAdapterInfo->dwUserPrefHeight &&
pD3DModeInfo->Format == pD3DAdapterInfo->d3dfmtUserPrefFormat )
{
pD3DDeviceInfo->dwCurrentMode = iMode;
break;
}
}
}
// If user-preferred mode is not specified or not found,
// use "Automatic" technique:
if( pD3DDeviceInfo->dwCurrentMode == 0xffff )
{
if( pD3DDeviceInfo->DeviceType == D3DDEVTYPE_SW )
{
// If using a SW rast then try to find a low resolution and 16-bpp.
BOOL bFound16BitMode = FALSE;
DWORD dwSmallestHeight = 0;
pD3DDeviceInfo->dwCurrentMode = 0; // unless we find something better
for( DWORD iMode = 0; iMode < pD3DDeviceInfo->dwNumModes; iMode++)
{
pD3DModeInfo = &pD3DDeviceInfo->modes[iMode];
// Skip 640x400 because 640x480 is better
if( pD3DModeInfo->Height == 400 )
continue;
if( pD3DModeInfo->Height < dwSmallestHeight ||
(pD3DModeInfo->Height == dwSmallestHeight && !bFound16BitMode) )
{
dwSmallestHeight = pD3DModeInfo->Height;
pD3DDeviceInfo->dwCurrentMode = iMode;
bFound16BitMode = FALSE;
if( ( pD3DModeInfo->Format == D3DFMT_R5G6B5 ||
pD3DModeInfo->Format == D3DFMT_X1R5G5B5 ||
pD3DModeInfo->Format == D3DFMT_A1R5G5B5 ||
pD3DModeInfo->Format == D3DFMT_A4R4G4B4 ||
pD3DModeInfo->Format == D3DFMT_X4R4G4B4 ) )
{
bFound16BitMode = TRUE;
}
}
}
}
else
{
// Try to find mode matching desktop resolution and 32-bpp.
BOOL bMatchedSize = FALSE;
BOOL bGot32Bit = FALSE;
pD3DDeviceInfo->dwCurrentMode = 0; // unless we find something better
for( DWORD iMode = 0; iMode < pD3DDeviceInfo->dwNumModes; iMode++)
{
pD3DModeInfo = &pD3DDeviceInfo->modes[iMode];
if( pD3DModeInfo->Width == pD3DAdapterInfo->d3ddmDesktop.Width &&
pD3DModeInfo->Height == pD3DAdapterInfo->d3ddmDesktop.Height )
{
if( !bMatchedSize )
pD3DDeviceInfo->dwCurrentMode = iMode;
bMatchedSize = TRUE;
if( !bGot32Bit &&
( pD3DModeInfo->Format == D3DFMT_X8R8G8B8 ||
pD3DModeInfo->Format == D3DFMT_A8R8G8B8 ) )
{
pD3DDeviceInfo->dwCurrentMode = iMode;
bGot32Bit = TRUE;
break;
}
}
}
}
}
// If desktop mode not found, pick highest mode available
if( pD3DDeviceInfo->dwCurrentMode == 0xffff )
{
DWORD dwWidthMax = 0;
DWORD dwHeightMax = 0;
DWORD dwBppMax = 0;
DWORD dwWidthCur = 0;
DWORD dwHeightCur = 0;
DWORD dwBppCur = 0;
for( DWORD iMode = 0; iMode < pD3DDeviceInfo->dwNumModes; iMode++)
{
pD3DModeInfo = &pD3DDeviceInfo->modes[iMode];
dwWidthCur = pD3DModeInfo->Width;
dwHeightCur = pD3DModeInfo->Height;
if( pD3DModeInfo->Format == D3DFMT_X8R8G8B8 ||
pD3DModeInfo->Format == D3DFMT_A8R8G8B8 )
{
dwBppCur = 32;
}
else
{
dwBppCur = 16;
}
if( dwWidthCur > dwWidthMax ||
dwHeightCur > dwHeightMax ||
dwWidthCur == dwWidthMax && dwHeightCur == dwHeightMax && dwBppCur > dwBppMax )
{
dwWidthMax = dwWidthCur;
dwHeightMax = dwHeightCur;
dwBppMax = dwBppCur;
pD3DDeviceInfo->dwCurrentMode = iMode;
}
}
}
// Try to create the D3D device, falling back to lower-res modes if it fails
BOOL bAtLeastOneFailure = FALSE;
for( ; ; )
{
pD3DModeInfo = &pD3DDeviceInfo->modes[pD3DDeviceInfo->dwCurrentMode];
pRenderUnit->DeviceType = pD3DDeviceInfo->DeviceType;
pRenderUnit->dwBehavior = pD3DModeInfo->dwBehavior;
pRenderUnit->iMonitor = iMonitor;
pRenderUnit->d3dpp.BackBufferFormat = pD3DModeInfo->Format;
pRenderUnit->d3dpp.BackBufferWidth = pD3DModeInfo->Width;
pRenderUnit->d3dpp.BackBufferHeight = pD3DModeInfo->Height;
pRenderUnit->d3dpp.Windowed = FALSE;
pRenderUnit->d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
pRenderUnit->d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
pRenderUnit->d3dpp.AutoDepthStencilFormat = pD3DModeInfo->DepthStencilFormat;
pRenderUnit->d3dpp.BackBufferCount = 1;
pRenderUnit->d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
pRenderUnit->d3dpp.SwapEffect = m_SwapEffectFullscreen;
pRenderUnit->d3dpp.hDeviceWindow = pD3DAdapterInfo->hWndDevice;
pRenderUnit->d3dpp.EnableAutoDepthStencil = m_bUseDepthBuffer;
pRenderUnit->d3dpp.Flags = 0;
// Create device
hr = m_pD3D->CreateDevice( iAdapter, pRenderUnit->DeviceType,
m_hWnd, // (this is the focus window)
pRenderUnit->dwBehavior, &pRenderUnit->d3dpp,
&pRenderUnit->pd3dDevice );
if( SUCCEEDED( hr ) )
{
// Give the client app an opportunity to reject this mode
// due to not enough video memory, or any other reason
if( SUCCEEDED( hr = ConfirmMode( pRenderUnit->pd3dDevice ) ) )
break;
else
SAFE_RELEASE( pRenderUnit->pd3dDevice );
}
// If we get here, remember that CreateDevice or ConfirmMode failed, so
// we can change the default mode next time
bAtLeastOneFailure = TRUE;
if( !FindNextLowerMode( pD3DDeviceInfo ) )
break;
}
if( SUCCEEDED( hr ) && bAtLeastOneFailure && m_strRegPath[0] != TEXT('\0') )
{
// Record the mode that succeeded in the registry so we can
// default to it next time
TCHAR strKey[100];
HKEY hkeyParent;
HKEY hkey;
pD3DAdapterInfo->dwUserPrefWidth = pRenderUnit->d3dpp.BackBufferWidth;
pD3DAdapterInfo->dwUserPrefHeight = pRenderUnit->d3dpp.BackBufferHeight;
pD3DAdapterInfo->d3dfmtUserPrefFormat = pRenderUnit->d3dpp.BackBufferFormat;
if( ERROR_SUCCESS == RegCreateKeyEx( HKEY_CURRENT_USER, m_strRegPath,
0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeyParent, NULL ) )
{
wsprintf( strKey, TEXT("Screen %d"), iMonitor + 1 );
if( ERROR_SUCCESS == RegCreateKeyEx( hkeyParent, strKey,
0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL ) )
{
RegSetValueEx( hkey, TEXT("Width"), NULL, REG_DWORD,
(BYTE*)&pD3DAdapterInfo->dwUserPrefWidth, sizeof(DWORD) );
RegSetValueEx( hkey, TEXT("Height"), NULL, REG_DWORD,
(BYTE*)&pD3DAdapterInfo->dwUserPrefHeight, sizeof(DWORD) );
RegSetValueEx( hkey, TEXT("Format"), NULL, REG_DWORD,
(BYTE*)&pD3DAdapterInfo->d3dfmtUserPrefFormat, sizeof(DWORD) );
RegSetValueEx( hkey, TEXT("Adapter ID"), NULL, REG_BINARY,
(BYTE*)&pD3DAdapterInfo->d3dAdapterIdentifier.DeviceIdentifier, sizeof(GUID) );
RegCloseKey( hkey );
}
RegCloseKey( hkeyParent );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -