win32: Default to current desktop display settings (#484, #493)

Previously, the graphics code tried to set a refresh rate as close to
85 Hz as possible. This led to black screens when the display driver
would report a refresh rate that was not actually supported by the
monitor.
This change also uses the currently set monitor orientation, instead
of always selecting a non-rotated display mode.

Conflicts:

	src/gui/C4StartupOptionsDlg.cpp
stable-5.1
Nicolas Hake 2011-01-20 15:43:19 +01:00
parent b3a34fea69
commit e9d9e7c178
9 changed files with 43 additions and 48 deletions

View File

@ -178,7 +178,7 @@ bool C4Application::DoInit(int argc, char * argv[])
if (!isEditor)
{
if (!SetVideoMode(Config.Graphics.ResX, Config.Graphics.ResY, Config.Graphics.BitDepth, Config.Graphics.Monitor, !Config.Graphics.Windowed))
if (!SetVideoMode(Config.Graphics.ResX, Config.Graphics.ResY, Config.Graphics.BitDepth, Config.Graphics.RefreshRate, Config.Graphics.Monitor, !Config.Graphics.Windowed))
pWindow->SetSize(Config.Graphics.ResX, Config.Graphics.ResY);
}
@ -428,13 +428,13 @@ void C4Application::ParseCommandLine(int argc, char * argv[])
void C4Application::ApplyResolutionConstraints()
{
// Enumerate display modes
int32_t idx = 0, iXRes, iYRes, iBitDepth;
int32_t idx = 0, iXRes, iYRes, iBitDepth, iRefreshRate;
int32_t best_match = -1;
uint32_t best_delta = ~0;
while (GetIndexedDisplayMode(idx++, &iXRes, &iYRes, &iBitDepth, Config.Graphics.Monitor))
while (GetIndexedDisplayMode(idx++, &iXRes, &iYRes, &iBitDepth, &iRefreshRate, Config.Graphics.Monitor))
{
uint32_t delta = std::abs(Config.Graphics.ResX*Config.Graphics.ResY - iXRes*iYRes);
if (!delta && iBitDepth == Config.Graphics.BitDepth)
if (!delta && iBitDepth == Config.Graphics.BitDepth && iRefreshRate == Config.Graphics.RefreshRate)
return; // Exactly the expected mode
if (delta < best_delta)
{
@ -446,12 +446,14 @@ void C4Application::ApplyResolutionConstraints()
if (best_match != -1)
{
// Apply next-best mode
GetIndexedDisplayMode(best_match, &iXRes, &iYRes, &iBitDepth, Config.Graphics.Monitor);
GetIndexedDisplayMode(best_match, &iXRes, &iYRes, &iBitDepth, &iRefreshRate, Config.Graphics.Monitor);
if (iXRes != Config.Graphics.ResX || iYRes != Config.Graphics.ResY)
// Don't warn if only bit depth changes
// Also, lang table not loaded yet
LogF("Warning: The selected resolution %dx%d is not available and has been changed to %dx%d.", Config.Graphics.ResX, Config.Graphics.ResY, iXRes, iYRes);
Config.Graphics.ResX = iXRes; Config.Graphics.ResY = iYRes;
Config.Graphics.BitDepth = iBitDepth;
Config.Graphics.RefreshRate = iRefreshRate;
}
}

View File

@ -118,6 +118,7 @@ void C4ConfigGraphics::CompileFunc(StdCompiler *pComp)
{
pComp->Value(mkNamingAdapt(ResX, "ResolutionX", 800 ,false, true));
pComp->Value(mkNamingAdapt(ResY, "ResolutionY", 600 ,false, true));
pComp->Value(mkNamingAdapt(RefreshRate, "RefreshRate", 0 ));
pComp->Value(mkNamingAdapt(GuiResX, "GuiResolutionX", 800 ,false, true));
pComp->Value(mkNamingAdapt(GuiResY, "GuiResolutionY", 600 ,false, true));
pComp->Value(mkNamingAdapt(ShowAllResolutions, "ShowAllResolutions", 0 ,false, true));

View File

@ -118,6 +118,7 @@ public:
int32_t UpperBoard;
int32_t ShowClock;
int32_t ResX,ResY;
int32_t RefreshRate; // monitor vertical refresh rate
int32_t GuiResX,GuiResY;
int32_t Windowed;
int32_t ShowAllResolutions;

View File

@ -1083,7 +1083,7 @@ void C4StartupOptionsDlg::OnGfxResComboFill(C4GUI::ComboBox_FillCB *pFiller)
pFiller->ClearEntries();
// fill with all possible resolutions
int32_t idx = 0, iXRes, iYRes, iBitDepth;
while (Application.GetIndexedDisplayMode(idx++, &iXRes, &iYRes, &iBitDepth, Config.Graphics.Monitor))
while (Application.GetIndexedDisplayMode(idx++, &iXRes, &iYRes, &iBitDepth, NULL, Config.Graphics.Monitor))
#ifdef _WIN32 // why only WIN32?
if (iBitDepth == Config.Graphics.BitDepth)
if ((iXRes <= 1024 && iXRes>=600 && iYRes>=460) || Config.Graphics.ShowAllResolutions)
@ -1125,7 +1125,7 @@ bool C4StartupOptionsDlg::TryNewResolution(int32_t iResX, int32_t iResY)
else
iNewFontSize = 16;
// call application to set it
if (!Application.SetVideoMode(iResX, iResY,Config.Graphics.BitDepth, Config.Graphics.Monitor,!Config.Graphics.Windowed))
if (!Application.SetVideoMode(iResX, iResY, Config.Graphics.BitDepth, Config.Graphics.RefreshRate, Config.Graphics.Monitor, !Config.Graphics.Windowed))
{
StdCopyStrBuf strChRes(LoadResStr("IDS_MNU_SWITCHRESOLUTION"));
pScreen->ShowMessage(FormatString(LoadResStr("IDS_ERR_SWITCHRES"), Application.GetLastError()).getData(), strChRes.getData(), C4GUI::Ico_Clonk, NULL);
@ -1151,13 +1151,10 @@ bool C4StartupOptionsDlg::TryNewResolution(int32_t iResX, int32_t iResY)
if (!pScreen->ShowModalDlg(pConfirmDlg, true))
{
// abort: Restore screen, if this was not some program abort
if (C4GUI::IsGUIValid())
if (Application.SetVideoMode(iOldResX, iOldResY, Config.Graphics.BitDepth, Config.Graphics.RefreshRate, Config.Graphics.Monitor, !Config.Graphics.Windowed))
{
if (Application.SetVideoMode(iOldResX, iOldResY, Config.Graphics.BitDepth, Config.Graphics.Monitor,!Config.Graphics.Windowed))
{
if (iNewFontSize != iOldFontSize) Application.SetGameFont(Config.General.RXFontName, iOldFontSize);
RecreateDialog(false);
}
if (iNewFontSize != iOldFontSize) Application.SetGameFont(Config.General.RXFontName, iOldFontSize);
RecreateDialog(false);
}
return false;
@ -1200,7 +1197,7 @@ void C4StartupOptionsDlg::OnGfxClrDepthCheck(C4GUI::Element *pCheckBox)
void C4StartupOptionsDlg::OnFullscreenChange(C4GUI::Element *pCheckBox)
{
Config.Graphics.Windowed = !static_cast<C4GUI::CheckBox *>(pCheckBox)->GetChecked();
Application.SetVideoMode(Config.Graphics.ResX, Config.Graphics.ResY, Config.Graphics.BitDepth, Config.Graphics.Monitor, !Config.Graphics.Windowed);
Application.SetVideoMode(Config.Graphics.ResX, Config.Graphics.ResY, Config.Graphics.BitDepth, Config.Graphics.RefreshRate, Config.Graphics.Monitor, !Config.Graphics.Windowed);
}
void C4StartupOptionsDlg::OnGfxAllResolutionsChange(C4GUI::Element *pCheckBox)

View File

@ -2042,7 +2042,7 @@ void CStdGL::TaskIn()
#ifdef _WIN32
if (!Editor && !Config.Graphics.Windowed)
{
Application.SetVideoMode(Config.Graphics.ResX, Config.Graphics.ResY, Config.Graphics.BitDepth, Config.Graphics.Monitor, !Config.Graphics.Windowed);
Application.SetVideoMode(Config.Graphics.ResX, Config.Graphics.ResY, Config.Graphics.BitDepth, Config.Graphics.RefreshRate, Config.Graphics.Monitor, !Config.Graphics.Windowed);
}
#endif
}

View File

@ -90,14 +90,14 @@ void CStdApp::Quit()
fQuitMsgReceived = true;
}
bool CStdApp::GetIndexedDisplayMode(int32_t iIndex, int32_t *piXRes, int32_t *piYRes, int32_t *piBitDepth, uint32_t iMonitor)
bool CStdApp::GetIndexedDisplayMode(int32_t iIndex, int32_t *piXRes, int32_t *piYRes, int32_t *piBitDepth, int32_t *piRefreshRate, uint32_t iMonitor)
{
return false;
}
void CStdApp::RestoreVideoMode() {}
bool CStdApp::SetVideoMode(unsigned int, unsigned int, unsigned int, unsigned int, bool) {}
bool CStdApp::SetVideoMode(unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, bool) {}
// Copy the text to the clipboard or the primary selection
bool CStdApp::Copy(const StdStrBuf & text, bool fClipboard)

View File

@ -298,7 +298,7 @@ BOOL CALLBACK GLMonitorInfoEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lp
return true;
}
bool CStdApp::GetIndexedDisplayMode(int32_t iIndex, int32_t *piXRes, int32_t *piYRes, int32_t *piBitDepth, uint32_t iMonitor)
bool CStdApp::GetIndexedDisplayMode(int32_t iIndex, int32_t *piXRes, int32_t *piYRes, int32_t *piBitDepth, int32_t *piRefreshRate, uint32_t iMonitor)
{
// prepare search struct
DEVMODE dmode;
@ -312,6 +312,7 @@ bool CStdApp::GetIndexedDisplayMode(int32_t iIndex, int32_t *piXRes, int32_t *pi
if (piXRes) *piXRes = dmode.dmPelsWidth;
if (piYRes) *piYRes = dmode.dmPelsHeight;
if (piBitDepth) *piBitDepth = dmode.dmBitsPerPel;
if (piRefreshRate) *piRefreshRate = dmode.dmDisplayFrequency;
return true;
}
@ -319,7 +320,7 @@ void CStdApp::RestoreVideoMode()
{
}
bool CStdApp::SetVideoMode(unsigned int iXRes, unsigned int iYRes, unsigned int iColorDepth, unsigned int iMonitor, bool fFullScreen)
bool CStdApp::SetVideoMode(unsigned int iXRes, unsigned int iYRes, unsigned int iColorDepth, unsigned int iRefreshRate, unsigned int iMonitor, bool fFullScreen)
{
#ifdef USE_DIRECTX
if (pD3D)
@ -354,25 +355,29 @@ bool CStdApp::SetVideoMode(unsigned int iXRes, unsigned int iYRes, unsigned int
StdStrBuf Mon;
if (iMonitor)
Mon.Format("\\\\.\\Display%d", iMonitor+1);
ZeroMemory(&dmode, sizeof(dmode)); dmode.dmSize = sizeof(dmode);
// Get current display settings
if (!EnumDisplaySettings(Mon.getData(), ENUM_CURRENT_SETTINGS, &dmode))
return false;
if (!iRefreshRate)
{
// Default to current
iRefreshRate = dmode.dmDisplayFrequency;
}
int orientation = dmode.dmDisplayOrientation;
// enumerate modes
int i=0;
ZeroMemory(&dmode, sizeof(dmode)); dmode.dmSize = sizeof(dmode);
while (EnumDisplaySettings(Mon.getData(), i++, &dmode))
// size and bit depth is OK?
if (dmode.dmPelsWidth==iXRes && dmode.dmPelsHeight==iYRes && dmode.dmBitsPerPel==iColorDepth && dmode.dmDisplayOrientation==0)
// compare enumerated mode with requested settings
if (dmode.dmPelsWidth==iXRes && dmode.dmPelsHeight==iYRes && dmode.dmBitsPerPel==iColorDepth && dmode.dmDisplayOrientation==orientation && dmode.dmDisplayFrequency==iRefreshRate)
{
// compare with found one
if (fFound)
// try getting a mode that is close to 85Hz, rather than taking the one with highest refresh rate
// (which may set absurd modes on some devices)
if (Abs<int>(85-dmode.dmDisplayFrequency)>Abs<int>(85-dspMode.dmDisplayFrequency))
// the previous one was better
continue;
// choose this one
fFound=true;
dspMode=dmode;
break;
}
if (!fFound) return false;
// change mode
if (!fFullScreen)
{
@ -380,25 +385,14 @@ bool CStdApp::SetVideoMode(unsigned int iXRes, unsigned int iYRes, unsigned int
SetWindowLong(pWindow->hWindow, GWL_STYLE,
GetWindowLong(pWindow->hWindow, GWL_STYLE) | (WS_CAPTION|WS_THICKFRAME|WS_BORDER));
}
// save original display mode
// if a monitor is given, use that
else
{
if (iMonitor)
{
dspMode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
if (ChangeDisplaySettingsEx(Mon.getData(), &dspMode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL)
if (ChangeDisplaySettingsEx(iMonitor ? Mon.getData() : NULL, &dspMode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL)
{
return false;
}
}
else
{
if (ChangeDisplaySettings(&dspMode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
{
return false;
}
}
SetWindowLong(pWindow->hWindow, GWL_STYLE,
GetWindowLong(pWindow->hWindow, GWL_STYLE) & ~ (WS_CAPTION|WS_THICKFRAME|WS_BORDER));
}

View File

@ -381,8 +381,8 @@ public:
}
virtual void Quit();
bool GetIndexedDisplayMode(int32_t iIndex, int32_t *piXRes, int32_t *piYRes, int32_t *piBitDepth, uint32_t iMonitor);
bool SetVideoMode(unsigned int iXRes, unsigned int iYRes, unsigned int iColorDepth, unsigned int iMonitor, bool fFullScreen);
bool GetIndexedDisplayMode(int32_t iIndex, int32_t *piXRes, int32_t *piYRes, int32_t *piBitDepth, int32_t *piRefreshRate, uint32_t iMonitor);
bool SetVideoMode(unsigned int iXRes, unsigned int iYRes, unsigned int iColorDepth, unsigned int iRefreshRate, unsigned int iMonitor, bool fFullScreen);
void RestoreVideoMode();
bool ScheduleProcs(int iTimeout = -1)
{

View File

@ -387,7 +387,7 @@ void CStdApp::HandleXMessage()
pWindow->HandleMessage(event);
}
bool CStdApp::SetVideoMode(unsigned int iXRes, unsigned int iYRes, unsigned int iColorDepth, unsigned int iMonitor, bool fFullScreen)
bool CStdApp::SetVideoMode(unsigned int iXRes, unsigned int iYRes, unsigned int iColorDepth, unsigned int iRefreshRate, unsigned int iMonitor, bool fFullScreen)
{
if (Priv->tasked_out)
return false;
@ -458,7 +458,7 @@ void CStdApp::RestoreVideoMode()
}
}
bool CStdApp::GetIndexedDisplayMode(int32_t iIndex, int32_t *piXRes, int32_t *piYRes, int32_t *piBitDepth, uint32_t iMonitor)
bool CStdApp::GetIndexedDisplayMode(int32_t iIndex, int32_t *piXRes, int32_t *piYRes, int32_t *piBitDepth, int32_t *piRefreshRate, uint32_t iMonitor)
{
if (xf86vmode_major_version < 0) return false;
bool r = false;