📄 d3dsaver.cpp
字号:
}
return hr;
}
//-----------------------------------------------------------------------------
// Name: FindNextLowerMode()
// Desc:
//-----------------------------------------------------------------------------
BOOL CD3DScreensaver::FindNextLowerMode( D3DDeviceInfo* pD3DDeviceInfo )
{
DWORD iModeCur = pD3DDeviceInfo->dwCurrentMode;
D3DModeInfo* pD3DModeInfoCur = &pD3DDeviceInfo->modes[iModeCur];
DWORD dwWidthCur = pD3DModeInfoCur->Width;
DWORD dwHeightCur = pD3DModeInfoCur->Height;
DWORD dwNumPixelsCur = dwWidthCur * dwHeightCur;
D3DFORMAT d3dfmtCur = pD3DModeInfoCur->Format;
BOOL b32BitCur = (d3dfmtCur == D3DFMT_A8R8G8B8 ||
d3dfmtCur == D3DFMT_X8R8G8B8);
DWORD iModeNew;
D3DModeInfo* pD3DModeInfoNew;
DWORD dwWidthNew;
DWORD dwHeightNew;
DWORD dwNumPixelsNew;
D3DFORMAT d3dfmtNew = D3DFMT_UNKNOWN;
BOOL b32BitNew;
DWORD dwWidthBest = 0;
DWORD dwHeightBest = 0;
DWORD dwNumPixelsBest = 0;
BOOL b32BitBest = FALSE;
DWORD iModeBest = 0xffff;
for( iModeNew = 0; iModeNew < pD3DDeviceInfo->dwNumModes; iModeNew++ )
{
// Don't pick the same mode we currently have
if( iModeNew == iModeCur )
continue;
// Get info about new mode
pD3DModeInfoNew = &pD3DDeviceInfo->modes[iModeNew];
dwWidthNew = pD3DModeInfoNew->Width;
dwHeightNew = pD3DModeInfoNew->Height;
dwNumPixelsNew = dwWidthNew * dwHeightNew;
d3dfmtNew = pD3DModeInfoNew->Format;
b32BitNew = (d3dfmtNew == D3DFMT_A8R8G8B8 ||
d3dfmtNew == D3DFMT_X8R8G8B8);
// If we're currently 32-bit and new mode is same width/height and 16-bit, take it
if( b32BitCur &&
!b32BitNew &&
pD3DModeInfoNew->Width == dwWidthCur &&
pD3DModeInfoNew->Height == dwHeightCur)
{
pD3DDeviceInfo->dwCurrentMode = iModeNew;
return TRUE;
}
// If new mode is smaller than current mode, see if it's our best so far
if( dwNumPixelsNew < dwNumPixelsCur )
{
// If current best is 32-bit, new mode needs to be bigger to be best
if( b32BitBest && (dwNumPixelsNew < dwNumPixelsBest ) )
continue;
// If new mode is bigger or equal to best, make it the best
if( (dwNumPixelsNew > dwNumPixelsBest) ||
(!b32BitBest && b32BitNew) )
{
dwWidthBest = dwWidthNew;
dwHeightBest = dwHeightNew;
dwNumPixelsBest = dwNumPixelsNew;
iModeBest = iModeNew;
b32BitBest = b32BitNew;
}
}
}
if( iModeBest == 0xffff )
return FALSE; // no smaller mode found
pD3DDeviceInfo->dwCurrentMode = iModeBest;
return TRUE;
}
//-----------------------------------------------------------------------------
// Name: CreateWindowedRenderUnit()
// Desc:
//-----------------------------------------------------------------------------
HRESULT CD3DScreensaver::CreateWindowedRenderUnit( RenderUnit* pRenderUnit )
{
HRESULT hr;
UINT iAdapter = pRenderUnit->iAdapter;
D3DAdapterInfo* pD3DAdapterInfo = m_Adapters[iAdapter];
DWORD iMonitor = pD3DAdapterInfo->iMonitor;
D3DDeviceInfo* pD3DDeviceInfo;
D3DDEVTYPE curType;
// Find the best device for the primary adapter. Use HAL
// if it's there, otherwise SW, otherwise REF.
pD3DAdapterInfo->dwCurrentDevice = 0xffff; // unless we find something better
curType = D3DDEVTYPE_FORCE_DWORD;
for( DWORD iDevice = 0; iDevice < pD3DAdapterInfo->dwNumDevices; iDevice++)
{
pD3DDeviceInfo = &pD3DAdapterInfo->devices[iDevice];
if( pD3DDeviceInfo->DeviceType == D3DDEVTYPE_HAL && !pD3DAdapterInfo->bDisableHW &&
pD3DDeviceInfo->bCanDoWindowed )
{
pD3DAdapterInfo->dwCurrentDevice = iDevice;
curType = D3DDEVTYPE_HAL;
break;
}
else if( pD3DDeviceInfo->DeviceType == D3DDEVTYPE_SW &&
pD3DDeviceInfo->bCanDoWindowed )
{
pD3DAdapterInfo->dwCurrentDevice = iDevice;
curType = D3DDEVTYPE_SW;
// but keep looking
}
else if( pD3DDeviceInfo->DeviceType == D3DDEVTYPE_REF && m_bAllowRef && curType != D3DDEVTYPE_SW )
{
pD3DAdapterInfo->dwCurrentDevice = iDevice;
curType = D3DDEVTYPE_REF;
// but keep looking
}
}
if( pD3DAdapterInfo->dwCurrentDevice == 0xffff )
return D3DAPPERR_NOHARDWAREDEVICE;
pD3DDeviceInfo = &pD3DAdapterInfo->devices[pD3DAdapterInfo->dwCurrentDevice];
D3DWindowedModeInfo D3DWindowedModeInfo;
D3DWindowedModeInfo.DisplayFormat = pD3DAdapterInfo->d3ddmDesktop.Format;
D3DWindowedModeInfo.BackBufferFormat = pD3DAdapterInfo->d3ddmDesktop.Format;
if( FAILED( CheckWindowedFormat( iAdapter, &D3DWindowedModeInfo ) ) )
{
D3DWindowedModeInfo.BackBufferFormat = D3DFMT_A8R8G8B8;
if( FAILED( CheckWindowedFormat( iAdapter, &D3DWindowedModeInfo ) ) )
{
D3DWindowedModeInfo.BackBufferFormat = D3DFMT_X8R8G8B8;
if( FAILED( CheckWindowedFormat( iAdapter, &D3DWindowedModeInfo ) ) )
{
D3DWindowedModeInfo.BackBufferFormat = D3DFMT_A1R5G5B5;
if( FAILED( CheckWindowedFormat( iAdapter, &D3DWindowedModeInfo ) ) )
{
D3DWindowedModeInfo.BackBufferFormat = D3DFMT_R5G6B5;
if( FAILED( CheckWindowedFormat( iAdapter, &D3DWindowedModeInfo ) ) )
{
return E_FAIL;
}
}
}
}
}
pRenderUnit->DeviceType = pD3DDeviceInfo->DeviceType;
pRenderUnit->dwBehavior = D3DWindowedModeInfo.dwBehavior;
pRenderUnit->iMonitor = iMonitor;
pRenderUnit->d3dpp.BackBufferWidth = 0;
pRenderUnit->d3dpp.BackBufferHeight = 0;
pRenderUnit->d3dpp.Windowed = TRUE;
pRenderUnit->d3dpp.FullScreen_RefreshRateInHz = 0;
pRenderUnit->d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
pRenderUnit->d3dpp.BackBufferFormat = D3DWindowedModeInfo.BackBufferFormat;
pRenderUnit->d3dpp.AutoDepthStencilFormat = D3DWindowedModeInfo.DepthStencilFormat;
pRenderUnit->d3dpp.BackBufferCount = 1;
pRenderUnit->d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
pRenderUnit->d3dpp.SwapEffect = m_SwapEffectWindowed;
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,
pRenderUnit->dwBehavior, &pRenderUnit->d3dpp, &pRenderUnit->pd3dDevice );
if ( FAILED(hr) )
{
return hr;
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: UpdateDeviceStats()
// Desc: Store device description
//-----------------------------------------------------------------------------
VOID CD3DScreensaver::UpdateDeviceStats()
{
DWORD iRenderUnit;
RenderUnit* pRenderUnit;
for( iRenderUnit = 0; iRenderUnit < m_dwNumRenderUnits; iRenderUnit++ )
{
pRenderUnit = &m_RenderUnits[iRenderUnit];
if( pRenderUnit->DeviceType == D3DDEVTYPE_REF )
lstrcpy( pRenderUnit->strDeviceStats, TEXT("REF") );
else if( pRenderUnit->DeviceType == D3DDEVTYPE_HAL )
lstrcpy( pRenderUnit->strDeviceStats, TEXT("HAL") );
else if( pRenderUnit->DeviceType == D3DDEVTYPE_SW )
lstrcpy( pRenderUnit->strDeviceStats, TEXT("SW") );
if( pRenderUnit->dwBehavior & D3DCREATE_HARDWARE_VERTEXPROCESSING &&
pRenderUnit->dwBehavior & D3DCREATE_PUREDEVICE )
{
if( pRenderUnit->DeviceType == D3DDEVTYPE_HAL )
lstrcat( pRenderUnit->strDeviceStats, TEXT(" (pure hw vp)") );
else
lstrcat( pRenderUnit->strDeviceStats, TEXT(" (simulated pure hw vp)") );
}
else if( pRenderUnit->dwBehavior & D3DCREATE_HARDWARE_VERTEXPROCESSING )
{
if( pRenderUnit->DeviceType == D3DDEVTYPE_HAL )
lstrcat( pRenderUnit->strDeviceStats, TEXT(" (hw vp)") );
else
lstrcat( pRenderUnit->strDeviceStats, TEXT(" (simulated hw vp)") );
}
else if( pRenderUnit->dwBehavior & D3DCREATE_MIXED_VERTEXPROCESSING )
{
if( pRenderUnit->DeviceType == D3DDEVTYPE_HAL )
lstrcat( pRenderUnit->strDeviceStats, TEXT(" (mixed vp)") );
else
lstrcat( pRenderUnit->strDeviceStats, TEXT(" (simulated mixed vp)") );
}
else if( pRenderUnit->dwBehavior & D3DCREATE_SOFTWARE_VERTEXPROCESSING )
{
lstrcat( pRenderUnit->strDeviceStats, TEXT(" (sw vp)") );
}
if( pRenderUnit->DeviceType == 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( pRenderUnit->strDeviceStats, TEXT(": ") );
const int cchDesc = sizeof(m_Adapters[pRenderUnit->iAdapter]->d3dAdapterIdentifier.Description);
TCHAR szDescription[cchDesc];
DXUtil_ConvertAnsiStringToGenericCch( szDescription,
m_Adapters[pRenderUnit->iAdapter]->d3dAdapterIdentifier.Description, cchDesc );
lstrcat( pRenderUnit->strDeviceStats, szDescription );
int maxAppend = sizeof(m_strDeviceStats) / sizeof(TCHAR) -
lstrlen( m_strDeviceStats ) - 1;
_tcsncat( m_strDeviceStats, szDescription, maxAppend );
}
}
}
//-----------------------------------------------------------------------------
// Name: SwitchToRenderUnit()
// Desc: Updates internal variables and notifies client that we are switching
// to a new RenderUnit / D3D device.
//-----------------------------------------------------------------------------
VOID CD3DScreensaver::SwitchToRenderUnit( UINT iRenderUnit )
{
RenderUnit* pRenderUnit = &m_RenderUnits[iRenderUnit];
MonitorInfo* pMonitorInfo = &m_Monitors[pRenderUnit->iMonitor];
m_pd3dDevice = pRenderUnit->pd3dDevice;
if( !m_bWindowed )
m_rcRenderCurDevice = pMonitorInfo->rcScreen;
if( m_pd3dDevice != NULL )
{
// Store render target surface desc
LPDIRECT3DSURFACE9 pBackBuffer;
m_pd3dDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer );
pBackBuffer->GetDesc( &m_d3dsdBackBuffer );
pBackBuffer->Release();
}
lstrcpy( m_strDeviceStats, pRenderUnit->strDeviceStats );
lstrcpy( m_strFrameStats, pRenderUnit->strFrameStats );
// Notify the client to switch to this device
SetDevice(iRenderUnit);
}
//-----------------------------------------------------------------------------
// Name: BuildProjectionMatrix()
// Desc: This function sets up an appropriate projection matrix to support
// rendering the appropriate parts of the scene to each screen.
//-----------------------------------------------------------------------------
VOID CD3DScreensaver::BuildProjectionMatrix( FLOAT fNear, FLOAT fFar, D3DXMATRIX* pMatrix )
{
D3DXMATRIX mat;
INT cx, cy;
INT dx, dy;
INT dd;
FLOAT l,r,t,b;
if( m_bAllScreensSame )
{
cx = (m_rcRenderCurDevice.right + m_rcRenderCurDevice.left) / 2;
cy = (m_rcRenderCurDevice.bottom + m_rcRenderCurDevice.top) / 2;
dx = m_rcRenderCurDevice.right - m_rcRenderCurDevice.left;
dy = m_rcRenderCurDevice.bottom - m_rcRenderCurDevice.top;
}
else
{
cx = (m_rcRenderTotal.right + m_rcRenderTotal.left) / 2;
cy = (m_rcRenderTotal.bottom + m_rcRenderTotal.top) / 2;
dx = m_rcRenderTotal.right - m_rcRenderTotal.left;
dy = m_rcRenderTotal.bottom - m_rcRenderTotal.top;
}
dd = (dx > dy ? dy : dx);
l = FLOAT(m_rcRenderCurDevice.left - cx) / (FLOAT)(dd);
r = FLOAT(m_rcRenderCurDevice.right - cx) / (FLOAT)(dd);
t = FLOAT(m_rcRenderCurDevice.top - cy) / (FLOAT)(dd);
b = FLOAT(m_rcRenderCurDevice.bottom - cy) / (FLOAT)(dd);
l = fNear * l;
r = fNear * r;
t = fNear * t;
b = fNear * b;
D3DXMatrixPerspectiveOffCenterLH( &mat, l, r, t, b, fNear, fFar );
*pMatrix = mat;
}
//-----------------------------------------------------------------------------
// Name: SetProjectionMatrix()
// Desc: This function sets up an appropriate projection matrix to support
// rendering the appropriate parts of the scene to each screen.
//-----------------------------------------------------------------------------
HRESULT CD3DScreensaver::SetProjectionMatrix( FLOAT fNear, FLOAT fFar )
{
D3DXMATRIX mat;
BuildProjectionMatrix( fNear, fFar, &mat );
return m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &mat );
}
//-----------------------------------------------------------------------------
// Name: SortModesCallback()
// Desc: Callback function for sorting display modes (used by BuildDeviceList).
//-------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -