forked from Mirrors/openclonk
Fix issues with resolution switching on Linux
* Engine would always open up in Fullscreen and then switch to Windowed instead of just starting up as Windowed. * Could not change resolution because bit depth or refresh rate did not match * handle RefreshRate==0 as "any", just like windows * Remember refresh rate in combo box that enumerates all the modes and propagate to video mode setting instead of assuming all modes have the same refresh rate. * Report bit depth as 32 even if SDL tells us it's 24. Other parts of the code require it to be equal to 32, but 24 works just fine. * Changing from fullscreen to windowed when "Screen" was selected in resolution combo box (i.e. iXRes==-1) makes the window tiny (0x0 pixels).directional-lights
parent
f37eda9508
commit
561651b715
|
@ -1063,28 +1063,33 @@ void C4StartupOptionsDlg::OnGfxResComboFill(C4GUI::ComboBox_FillCB *pFiller)
|
|||
pFiller->ClearEntries();
|
||||
pFiller->AddEntry(LoadResStr("IDS_MNU_DEFAULTRESOLUTION"), -1);
|
||||
// fill with all possible resolutions
|
||||
int32_t idx = 0, iXRes, iYRes, iBitDepth;
|
||||
while (Application.GetIndexedDisplayMode(idx++, &iXRes, &iYRes, &iBitDepth, NULL, Config.Graphics.Monitor))
|
||||
int32_t idx = 0, iXRes, iYRes, iBitDepth, iRefreshRate;
|
||||
while (Application.GetIndexedDisplayMode(idx++, &iXRes, &iYRes, &iBitDepth, &iRefreshRate, Config.Graphics.Monitor))
|
||||
#ifdef _WIN32 // why only WIN32?
|
||||
if (iBitDepth == C4Draw::COLOR_DEPTH)
|
||||
#endif
|
||||
{
|
||||
StdStrBuf sGfxString = GetGfxResString(iXRes, iYRes);
|
||||
if (!pFiller->FindEntry(sGfxString.getData()))
|
||||
pFiller->AddEntry(sGfxString.getData(), iXRes + (uint32_t(iYRes)<<16));
|
||||
pFiller->AddEntry(sGfxString.getData(), iXRes + (uint32_t(iYRes) << 12) + (uint32_t(iRefreshRate) << 24));
|
||||
}
|
||||
}
|
||||
|
||||
bool C4StartupOptionsDlg::OnGfxResComboSelChange(C4GUI::ComboBox *pForCombo, int32_t idNewSelection)
|
||||
{
|
||||
// get new resolution from string
|
||||
int iResX=(idNewSelection & 0xffff), iResY=(uint32_t(idNewSelection) & 0xffff0000) >> 16;
|
||||
int iResX=(idNewSelection & 0xfff), iResY=(uint32_t(idNewSelection) >> 12) & 0xfff, iRefreshRate = (uint32_t(idNewSelection) >> 24) & 0xff;
|
||||
if (idNewSelection == -1)
|
||||
{
|
||||
iResX = iResY = -1;
|
||||
iRefreshRate = 0;
|
||||
}
|
||||
|
||||
// different than current?
|
||||
if (iResX == Config.Graphics.ResX && iResY == Config.Graphics.ResY) return true;
|
||||
if (iResX == Config.Graphics.ResX && iResY == Config.Graphics.ResY && iRefreshRate == Config.Graphics.RefreshRate) return true;
|
||||
|
||||
// try setting it
|
||||
if (!TryNewResolution(iResX, iResY))
|
||||
if (!TryNewResolution(iResX, iResY, iRefreshRate))
|
||||
{
|
||||
// didn't work or declined by user
|
||||
return true; // do not change label, because dialog might hae been recreated!
|
||||
|
@ -1093,9 +1098,10 @@ bool C4StartupOptionsDlg::OnGfxResComboSelChange(C4GUI::ComboBox *pForCombo, int
|
|||
return true;
|
||||
}
|
||||
|
||||
bool C4StartupOptionsDlg::TryNewResolution(int32_t iResX, int32_t iResY)
|
||||
bool C4StartupOptionsDlg::TryNewResolution(int32_t iResX, int32_t iResY, int32_t iRefreshRate)
|
||||
{
|
||||
int32_t iOldResX = Config.Graphics.ResX, iOldResY = Config.Graphics.ResY;
|
||||
int32_t iOldRefreshRate = Config.Graphics.RefreshRate;
|
||||
int32_t iOldFontSize = Config.General.RXFontSize;
|
||||
C4GUI::Screen *pScreen = GetScreen();
|
||||
// resolution change may imply font size change
|
||||
|
@ -1105,7 +1111,7 @@ bool C4StartupOptionsDlg::TryNewResolution(int32_t iResX, int32_t iResY)
|
|||
else if (iResY > 800)
|
||||
iNewFontSize = 16;
|
||||
// call application to set it
|
||||
if (!Application.SetVideoMode(iResX, iResY, Config.Graphics.RefreshRate, Config.Graphics.Monitor, true))
|
||||
if (!Application.SetVideoMode(iResX, iResY, iRefreshRate, 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);
|
||||
|
@ -1121,17 +1127,19 @@ bool C4StartupOptionsDlg::TryNewResolution(int32_t iResX, int32_t iResY)
|
|||
// Set new resolution in config before dialog recreation so that the initial combo box value is correct (#230)
|
||||
Config.Graphics.ResX = iResX;
|
||||
Config.Graphics.ResY = iResY;
|
||||
Config.Graphics.RefreshRate = iRefreshRate;
|
||||
// since the resolution was changed, everything needs to be moved around a bit
|
||||
RecreateDialog(false);
|
||||
// Now set old resolution again to make sure config is restored even if the program is closed during the confirmation dialog
|
||||
Config.Graphics.ResX = iOldResX;
|
||||
Config.Graphics.ResY = iOldResY;
|
||||
Config.Graphics.RefreshRate = iOldRefreshRate;
|
||||
// Show confirmation dialog
|
||||
ResChangeConfirmDlg *pConfirmDlg = new ResChangeConfirmDlg();
|
||||
if (!pScreen->ShowModalDlg(pConfirmDlg, true))
|
||||
{
|
||||
// abort: Restore screen, if this was not some program abort
|
||||
if (Application.SetVideoMode(iOldResX, iOldResY, Config.Graphics.RefreshRate, Config.Graphics.Monitor, !Config.Graphics.Windowed))
|
||||
if (Application.SetVideoMode(iOldResX, iOldResY, iOldRefreshRate, Config.Graphics.Monitor, !Config.Graphics.Windowed))
|
||||
{
|
||||
if (iNewFontSize != iOldFontSize) Application.SetGameFont(Config.General.RXFontName, iOldFontSize);
|
||||
RecreateDialog(false);
|
||||
|
@ -1142,6 +1150,7 @@ bool C4StartupOptionsDlg::TryNewResolution(int32_t iResX, int32_t iResY)
|
|||
// resolution may be kept!
|
||||
Config.Graphics.ResX = iResX;
|
||||
Config.Graphics.ResY = iResY;
|
||||
Config.Graphics.RefreshRate = iRefreshRate;
|
||||
if(Config.Graphics.Windowed)
|
||||
Application.SetVideoMode(Application.GetConfigWidth(), Application.GetConfigHeight(), Config.Graphics.RefreshRate, Config.Graphics.Monitor, false);
|
||||
return true;
|
||||
|
|
|
@ -130,7 +130,7 @@ private:
|
|||
bool OnGfxResComboSelChange(C4GUI::ComboBox *pForCombo, int32_t idNewSelection);
|
||||
void OnGfxMSComboFill(C4GUI::ComboBox_FillCB *pFiller);
|
||||
bool OnGfxMSComboSelChange(C4GUI::ComboBox *pForCombo, int32_t idNewSelection);
|
||||
bool TryNewResolution(int32_t iResX, int32_t iResY);
|
||||
bool TryNewResolution(int32_t iResX, int32_t iResY, int32_t iRefreshRate);
|
||||
StdStrBuf GetGfxResString(int32_t iResX, int32_t iResY); // convert resolution to string to be displayed in resolution choice combobox
|
||||
const char * GetWindowedName(int32_t mode = -1);
|
||||
|
||||
|
|
|
@ -326,6 +326,16 @@ void C4AbstractApp::HandleSDLEvent(SDL_Event& e)
|
|||
|
||||
static int modeCount = 0;
|
||||
|
||||
static int bits_per_pixel(int format)
|
||||
{
|
||||
// C4Draw::BITS_PER_PIXEL is 32, and other parts of the code expect
|
||||
// the mode's bpp to match exactly. 24 is fully compatible, so just
|
||||
// pretend it's 32 in that case to adhere to the expected interface.
|
||||
int bbp = SDL_BITSPERPIXEL(format);
|
||||
if (bbp == 24) bbp = 32;
|
||||
return bbp;
|
||||
}
|
||||
|
||||
bool C4AbstractApp::GetIndexedDisplayMode(int32_t iIndex, int32_t *piXRes, int32_t *piYRes, int32_t *piBitDepth, int32_t *piRefreshRate, uint32_t iMonitor)
|
||||
{
|
||||
if (!modeCount)
|
||||
|
@ -340,7 +350,7 @@ bool C4AbstractApp::GetIndexedDisplayMode(int32_t iIndex, int32_t *piXRes, int32
|
|||
SDL_GetDisplayMode(iMonitor, iIndex, &mode);
|
||||
*piXRes = mode.w;
|
||||
*piYRes = mode.h;
|
||||
*piBitDepth = SDL_BITSPERPIXEL(mode.format);
|
||||
*piBitDepth = bits_per_pixel(mode.format);
|
||||
if (piRefreshRate) *piRefreshRate = mode.refresh_rate;
|
||||
return true;
|
||||
}
|
||||
|
@ -350,6 +360,21 @@ bool C4AbstractApp::SetVideoMode(int iXRes, int iYRes, unsigned int RefreshRate,
|
|||
int res;
|
||||
if (!fFullScreen)
|
||||
{
|
||||
if (iXRes == -1)
|
||||
{
|
||||
SDL_DisplayMode desktop_mode;
|
||||
res = SDL_GetDesktopDisplayMode(iMonitor, &desktop_mode);
|
||||
if (res)
|
||||
{
|
||||
Error(SDL_GetError());
|
||||
LogF("SDL_GetDesktopDisplayMode: %s", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
iXRes = desktop_mode.w;
|
||||
iYRes = desktop_mode.h;
|
||||
}
|
||||
|
||||
res = SDL_SetWindowFullscreen(pWindow->window, 0);
|
||||
if (res)
|
||||
{
|
||||
|
@ -357,11 +382,9 @@ bool C4AbstractApp::SetVideoMode(int iXRes, int iYRes, unsigned int RefreshRate,
|
|||
LogF("SDL_SetWindowFullscreen: %s", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
if (iXRes != -1)
|
||||
pWindow->SetSize(iXRes, iYRes);
|
||||
C4Rect r;
|
||||
pWindow->GetSize(&r);
|
||||
OnResolutionChanged(r.Wdt, r.Hgt);
|
||||
|
||||
pWindow->SetSize(iXRes, iYRes);
|
||||
OnResolutionChanged(iXRes, iYRes);
|
||||
return true;
|
||||
}
|
||||
SDL_DisplayMode mode;
|
||||
|
@ -384,16 +407,19 @@ bool C4AbstractApp::SetVideoMode(int iXRes, int iYRes, unsigned int RefreshRate,
|
|||
OnResolutionChanged(mode.w, mode.h);
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < modeCount; ++i)
|
||||
{
|
||||
res = SDL_GetDisplayMode(iMonitor, i, &mode);
|
||||
|
||||
if (res)
|
||||
{
|
||||
Error(SDL_GetError());
|
||||
LogF("SDL_GetDisplayMode: %s", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
if (mode.w == iXRes && mode.h == iYRes && mode.refresh_rate == RefreshRate && SDL_BITSPERPIXEL(mode.format) == C4Draw::COLOR_DEPTH)
|
||||
|
||||
if (mode.w == iXRes && mode.h == iYRes && (RefreshRate == 0 || mode.refresh_rate == RefreshRate) && bits_per_pixel(mode.format) == C4Draw::COLOR_DEPTH)
|
||||
{
|
||||
res = SDL_SetWindowDisplayMode(pWindow->window, &mode);
|
||||
if (res)
|
||||
|
|
|
@ -83,7 +83,7 @@ C4Window * C4Window::Init(WindowKind windowKind, C4AbstractApp * pApp, const cha
|
|||
uint32_t flags = SDL_WINDOW_OPENGL;
|
||||
if (windowKind == W_Fullscreen && size->Wdt == -1)
|
||||
flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
else if (windowKind == W_Fullscreen)
|
||||
else if (windowKind == W_Fullscreen && !Config.Graphics.Windowed)
|
||||
flags |= SDL_WINDOW_FULLSCREEN;
|
||||
window = SDL_CreateWindow(Title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, size->Wdt, size->Hgt, flags);
|
||||
if (!window)
|
||||
|
|
Loading…
Reference in New Issue