// Set the video mode. RString RageDisplay_D3D::TryVideoMode( const VideoModeParams &_p, bool &bNewDeviceOut ) { VideoModeParams p = _p; LOG->Warn( "RageDisplay_D3D::TryVideoMode( %d, %d, %d, %d, %d, %d )", p.windowed, p.width, p.height, p.bpp, p.rate, p.vsync ); if( FindBackBufferType( p.windowed, p.bpp ) == D3DFMT_UNKNOWN ) // no possible back buffer formats return ssprintf( "FindBackBufferType(%i,%i) failed", p.windowed, p.bpp ); // failed to set mode /* Set up and display the window before setting up D3D. If we don't do this, * then setting up a fullscreen window (when we're not coming from windowed) * causes all other windows on the system to be resized to the new resolution. */ GraphicsWindow::CreateGraphicsWindow( p ); SetPresentParametersFromVideoModeParams( p, &g_d3dpp ); // Display the window immediately, so we don't display the desktop ... while( 1 ) { // Try the video mode. RString sErr = SetD3DParams( bNewDeviceOut ); if( sErr.empty() ) break; /* It failed. We're probably selecting a video mode that isn't supported. * If we're fullscreen, search the mode list and find the nearest lower mode. */ if( p.windowed || !D3DReduceParams( &g_d3dpp ) ) return sErr; // Store the new settings we're about to try. p.height = g_d3dpp.BackBufferHeight; p.width = g_d3dpp.BackBufferWidth; if( g_d3dpp.FullScreen_RefreshRateInHz == D3DPRESENT_RATE_DEFAULT ) p.rate = REFRESH_DEFAULT; else p.rate = g_d3dpp.FullScreen_RefreshRateInHz; } /* Call this again after changing the display mode. If we're going to a window * from fullscreen, the first call can't set a larger window than the old * fullscreen resolution or set the window position. */ GraphicsWindow::CreateGraphicsWindow( p ); ResolutionChanged(); return RString(); // mode change successful }
/* Set the video mode. */ CString RageDisplay_D3D::TryVideoMode( VideoModeParams p, bool &bNewDeviceOut ) { if( FindBackBufferType( p.windowed, p.bpp ) == D3DFMT_UNKNOWN ) // no possible back buffer formats return ssprintf( "FindBackBufferType(%i,%i) failed", p.windowed, p.bpp ); // failed to set mode #if !defined(XBOX) if( GraphicsWindow::GetHwnd() == NULL ) GraphicsWindow::CreateGraphicsWindow( p ); #else p.windowed = false; #endif /* Set up and display the window before setting up D3D. If we don't do this, * then setting up a fullscreen window (when we're not coming from windowed) * causes all other windows on the system to be resized to the new resolution. */ GraphicsWindow::ConfigureGraphicsWindow( p ); ZeroMemory( &g_d3dpp, sizeof(g_d3dpp) ); g_d3dpp.BackBufferWidth = p.width; g_d3dpp.BackBufferHeight = p.height; g_d3dpp.BackBufferFormat = FindBackBufferType( p.windowed, p.bpp ); g_d3dpp.BackBufferCount = 1; g_d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; g_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; #if !defined(XBOX) g_d3dpp.hDeviceWindow = GraphicsWindow::GetHwnd(); #else g_d3dpp.hDeviceWindow = NULL; #endif g_d3dpp.Windowed = p.windowed; g_d3dpp.EnableAutoDepthStencil = TRUE; g_d3dpp.AutoDepthStencilFormat = D3DFMT_D16; if(p.windowed) g_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; else g_d3dpp.PresentationInterval = p.vsync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; #if !defined(XBOX) g_d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; if( !p.windowed && p.rate != REFRESH_DEFAULT ) g_d3dpp.FullScreen_RefreshRateInHz = p.rate; #else if( XGetVideoStandard() == XC_VIDEO_STANDARD_PAL_I ) { /* Get supported video flags. */ DWORD VideoFlags = XGetVideoFlags(); /* Set pal60 if available. */ if( VideoFlags & XC_VIDEO_FLAGS_PAL_60Hz ) g_d3dpp.FullScreen_RefreshRateInHz = 60; else g_d3dpp.FullScreen_RefreshRateInHz = 50; } else g_d3dpp.FullScreen_RefreshRateInHz = 60; #endif g_d3dpp.Flags = 0; LOG->Trace( "Present Parameters: %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d", g_d3dpp.BackBufferWidth, g_d3dpp.BackBufferHeight, g_d3dpp.BackBufferFormat, g_d3dpp.BackBufferCount, g_d3dpp.MultiSampleType, g_d3dpp.SwapEffect, g_d3dpp.hDeviceWindow, g_d3dpp.Windowed, g_d3dpp.EnableAutoDepthStencil, g_d3dpp.AutoDepthStencilFormat, g_d3dpp.Flags, g_d3dpp.FullScreen_RefreshRateInHz, g_d3dpp.PresentationInterval ); #if defined(XBOX) if( D3D__pDevice ) g_pd3dDevice = D3D__pDevice; #endif /* Display the window immediately, so we don't display the desktop ... */ while( 1 ) { /* Try the video mode. */ CString sErr = SetD3DParams( bNewDeviceOut ); if( sErr.empty() ) break; /* It failed. We're probably selecting a video mode that isn't supported. * If we're fullscreen, search the mode list and find the nearest lower * mode. */ if( p.windowed || !D3DReduceParams( &g_d3dpp ) ) return sErr; /* Store the new settings we're about to try. */ p.height = g_d3dpp.BackBufferHeight; p.width = g_d3dpp.BackBufferWidth; if( g_d3dpp.FullScreen_RefreshRateInHz == D3DPRESENT_RATE_DEFAULT ) p.rate = REFRESH_DEFAULT; else p.rate = g_d3dpp.FullScreen_RefreshRateInHz; } /* Call this again after changing the display mode. If we're going to a window * from fullscreen, the first call can't set a larger window than the old fullscreen * resolution or set the window position. */ GraphicsWindow::ConfigureGraphicsWindow( p ); GraphicsWindow::SetVideoModeParams( p ); ResolutionChanged(); this->SetDefaultRenderStates(); /* Palettes were lost by Reset(), so mark them unloaded. */ g_TexResourceToPaletteIndex.clear(); return ""; // mode change successful }
bool CWinSystemWin32::ChangeResolution(const RESOLUTION_INFO& res, bool forceChange /*= false*/) { const MONITOR_DETAILS* details = GetMonitor(res.iScreen); if (!details) return false; DEVMODEW sDevMode; ZeroMemory(&sDevMode, sizeof(sDevMode)); sDevMode.dmSize = sizeof(sDevMode); // If we can't read the current resolution or any detail of the resolution is different than res if (!EnumDisplaySettingsW(details->DeviceNameW.c_str(), ENUM_CURRENT_SETTINGS, &sDevMode) || sDevMode.dmPelsWidth != res.iWidth || sDevMode.dmPelsHeight != res.iHeight || sDevMode.dmDisplayFrequency != (int)res.fRefreshRate || ((sDevMode.dmDisplayFlags & DM_INTERLACED) && !(res.dwFlags & D3DPRESENTFLAG_INTERLACED)) || (!(sDevMode.dmDisplayFlags & DM_INTERLACED) && (res.dwFlags & D3DPRESENTFLAG_INTERLACED)) || forceChange) { ZeroMemory(&sDevMode, sizeof(sDevMode)); sDevMode.dmSize = sizeof(sDevMode); sDevMode.dmDriverExtra = 0; sDevMode.dmPelsWidth = res.iWidth; sDevMode.dmPelsHeight = res.iHeight; sDevMode.dmDisplayFrequency = (int)res.fRefreshRate; sDevMode.dmDisplayFlags = (res.dwFlags & D3DPRESENTFLAG_INTERLACED) ? DM_INTERLACED : 0; sDevMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS; LONG rc = DISP_CHANGE_SUCCESSFUL; bool bResChanged = false; // Windows 8 refresh rate workaround for 24.0, 48.0 and 60.0 Hz if (CSysInfo::IsWindowsVersionAtLeast(CSysInfo::WindowsVersionWin8) && (res.fRefreshRate == 24.0 || res.fRefreshRate == 48.0 || res.fRefreshRate == 60.0)) { CLog::Log(LOGDEBUG, "%s : Using Windows 8+ workaround for refresh rate %d Hz", __FUNCTION__, (int)res.fRefreshRate); // Get current resolution stored in registry DEVMODEW sDevModeRegistry; ZeroMemory(&sDevModeRegistry, sizeof(sDevModeRegistry)); sDevModeRegistry.dmSize = sizeof(sDevModeRegistry); if (EnumDisplaySettingsW(details->DeviceNameW.c_str(), ENUM_REGISTRY_SETTINGS, &sDevModeRegistry)) { // Set requested mode in registry without actually changing resolution rc = ChangeDisplaySettingsExW(details->DeviceNameW.c_str(), &sDevMode, NULL, CDS_UPDATEREGISTRY | CDS_NORESET, NULL); if (rc == DISP_CHANGE_SUCCESSFUL) { // Change resolution based on registry setting rc = ChangeDisplaySettingsExW(details->DeviceNameW.c_str(), NULL, NULL, CDS_FULLSCREEN, NULL); if (rc == DISP_CHANGE_SUCCESSFUL) bResChanged = true; else CLog::Log(LOGERROR, "%s : ChangeDisplaySettingsEx (W8+ change resolution) failed with %d, using fallback", __FUNCTION__, rc); // Restore registry with original values sDevModeRegistry.dmSize = sizeof(sDevModeRegistry); sDevModeRegistry.dmDriverExtra = 0; sDevModeRegistry.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS; rc = ChangeDisplaySettingsExW(details->DeviceNameW.c_str(), &sDevModeRegistry, NULL, CDS_UPDATEREGISTRY | CDS_NORESET, NULL); if (rc != DISP_CHANGE_SUCCESSFUL) CLog::Log(LOGERROR, "%s : ChangeDisplaySettingsEx (W8+ restore registry) failed with %d", __FUNCTION__, rc); } else CLog::Log(LOGERROR, "%s : ChangeDisplaySettingsEx (W8+ set registry) failed with %d, using fallback", __FUNCTION__, rc); } else CLog::Log(LOGERROR, "%s : Unable to retrieve registry settings for Windows 8+ workaround, using fallback", __FUNCTION__); } // Standard resolution change/fallback for Windows 8+ workaround if (!bResChanged) { // CDS_FULLSCREEN is for temporary fullscreen mode and prevents icons and windows from moving // to fit within the new dimensions of the desktop rc = ChangeDisplaySettingsExW(details->DeviceNameW.c_str(), &sDevMode, NULL, CDS_FULLSCREEN, NULL); if (rc == DISP_CHANGE_SUCCESSFUL) bResChanged = true; else CLog::Log(LOGERROR, "%s : ChangeDisplaySettingsEx failed with %d", __FUNCTION__, rc); } if (bResChanged) ResolutionChanged(); return bResChanged; } // nothing to do, return success return true; }
//----------------------------------------------------------------------------- // Name: DialogProc // Desc: Handle window messages in the dialog. //----------------------------------------------------------------------------- INT_PTR CD3DSettingsDialog::DialogProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam ) { UNREFERENCED_PARAMETER( lParam ); switch( msg ) { case WM_INITDIALOG: { m_hDlg = hDlg; // Fill adapter combo box. Updating the selected adapter will trigger // updates of the rest of the dialog. for( UINT iai = 0; iai < m_pEnumeration->m_pAdapterInfoList->Count(); iai++ ) { D3DAdapterInfo* pAdapterInfo; pAdapterInfo = (D3DAdapterInfo*)m_pEnumeration->m_pAdapterInfoList->GetPtr(iai); TCHAR strDescription[512]; DXUtil_ConvertAnsiStringToGenericCch( strDescription, pAdapterInfo->AdapterIdentifier.Description, 512 ); ComboBoxAdd( IDC_ADAPTER_COMBO, pAdapterInfo, strDescription ); if( pAdapterInfo->AdapterOrdinal == m_d3dSettings.AdapterOrdinal() ) ComboBoxSelect( IDC_ADAPTER_COMBO, pAdapterInfo ); } if( !ComboBoxSomethingSelected( IDC_ADAPTER_COMBO ) && ComboBoxCount( IDC_ADAPTER_COMBO ) > 0 ) { ComboBoxSelectIndex( IDC_ADAPTER_COMBO, 0 ); } } return TRUE; case WM_COMMAND: switch( LOWORD(wParam) ) { case IDOK: EndDialog( hDlg, IDOK ); break; case IDCANCEL: EndDialog( hDlg, IDCANCEL ); break; case IDC_ADAPTER_COMBO: if( CBN_SELCHANGE == HIWORD(wParam) ) AdapterChanged(); break; case IDC_DEVICE_COMBO: if( CBN_SELCHANGE == HIWORD(wParam) ) DeviceChanged(); break; case IDC_ADAPTERFORMAT_COMBO: if( CBN_SELCHANGE == HIWORD(wParam) ) AdapterFormatChanged(); break; case IDC_RESOLUTION_COMBO: if( CBN_SELCHANGE == HIWORD(wParam) ) ResolutionChanged(); break; case IDC_REFRESHRATE_COMBO: if( CBN_SELCHANGE == HIWORD(wParam) ) RefreshRateChanged(); break; case IDC_BACKBUFFERFORMAT_COMBO: if( CBN_SELCHANGE == HIWORD(wParam) ) BackBufferFormatChanged(); break; case IDC_DEPTHSTENCILBUFFERFORMAT_COMBO: if( CBN_SELCHANGE == HIWORD(wParam) ) DepthStencilBufferFormatChanged(); break; case IDC_MULTISAMPLE_COMBO: if( CBN_SELCHANGE == HIWORD(wParam) ) MultisampleTypeChanged(); break; case IDC_MULTISAMPLE_QUALITY_COMBO: if( CBN_SELCHANGE == HIWORD(wParam) ) MultisampleQualityChanged(); break; case IDC_VERTEXPROCESSING_COMBO: if( CBN_SELCHANGE == HIWORD(wParam) ) VertexProcessingChanged(); break; case IDC_PRESENTINTERVAL_COMBO: if( CBN_SELCHANGE == HIWORD(wParam) ) PresentIntervalChanged(); break; case IDC_WINDOW: case IDC_FULLSCREEN: WindowedFullscreenChanged(); break; } return TRUE; default: return FALSE; } }