- removed the hard screen resolution switch that still was present on Windows and cleaned up the entire video backend code from the remaining support code for this.

Like Linux and macOS this will only support borderless fullscreen in the active desktop resolution now, which is what modern systems need.
The list of discrete resolutions has been removed as it makes no sense anymore with a fixed video mode - all the other scaling options remain active, though.
This commit is contained in:
Christoph Oelckers 2018-06-17 16:19:14 +02:00
commit b65b83edb3
28 changed files with 143 additions and 1826 deletions

View file

@ -11,35 +11,33 @@ public:
SystemFrameBuffer() {}
// Actually, hMonitor is a HMONITOR, but it's passed as a void * as there
// look to be some cross-platform bits in the way.
SystemFrameBuffer(void *hMonitor, int width, int height, int bits, int refreshHz, bool fullscreen, bool bgra);
SystemFrameBuffer(void *hMonitor, bool fullscreen);
virtual ~SystemFrameBuffer();
void SetVSync (bool vsync);
void SwapBuffers();
void NewRefreshRate ();
int GetClientWidth();
int GetClientHeight();
int GetTrueHeight();
bool IsFullscreen();
void InitializeState();
protected:
void PositionWindow();
void ResetGammaTable();
void SetGammaTable(uint16_t * tbl);
float m_Gamma, m_Brightness, m_Contrast;
uint16_t m_origGamma[768];
bool m_supportsGamma;
bool m_Fullscreen, m_Bgra;
int m_Width, m_Height, m_Bits, m_RefreshHz;
bool m_Fullscreen;
char m_displayDeviceNameBuffer[32/*CCHDEVICENAME*/]; // do not use windows.h constants here!
char *m_displayDeviceName;
void *m_Monitor;
int SwapInterval;
friend class Win32GLVideo;

View file

@ -43,10 +43,7 @@
#include "version.h"
#include "swrenderer/r_swrenderer.h"
EXTERN_CVAR (Bool, ticker)
EXTERN_CVAR (Bool, fullscreen)
EXTERN_CVAR (Float, vid_winscale)
EXTERN_CVAR (Bool, win_borderless)
CVAR(Int, win_x, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR(Int, win_y, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
@ -54,8 +51,6 @@ CVAR(Bool, win_maximized, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
extern HWND Window;
bool ForceWindowed;
IVideo *Video;
// do not include GL headers here, only declare the necessary functions.
@ -111,8 +106,6 @@ void I_ShutdownGraphics ()
void I_InitGraphics ()
{
UCVarValue val;
// todo: implement ATI version of this. this only works for nvidia notebooks, for now.
currentgpuswitch = vid_gpuswitch;
if (currentgpuswitch == 1)
@ -135,8 +128,6 @@ void I_InitGraphics ()
// not receive a WM_ACTIVATEAPP message, so both games think they
// are the active app. Huh?
}
val.Bool = !!Args->CheckParm ("-devparm");
ticker.SetGenericRepDefault (val, CVAR_Bool);
Video = gl_CreateVideo();
@ -144,46 +135,12 @@ void I_InitGraphics ()
I_FatalError ("Failed to initialize display");
atterm (I_ShutdownGraphics);
Video->SetWindowedScale (vid_winscale);
}
/** Remaining code is common to Win32 and Linux **/
// VIDEO WRAPPERS ---------------------------------------------------------
DFrameBuffer *I_SetMode (int &width, int &height, DFrameBuffer *old)
{
bool fs = false;
switch (Video->GetDisplayType ())
{
case DISPLAY_WindowOnly:
fs = false;
break;
case DISPLAY_FullscreenOnly:
fs = true;
break;
case DISPLAY_Both:
if (ForceWindowed)
{
fs = false;
}
else
{
fs = fullscreen;
}
break;
}
DFrameBuffer *res = Video->CreateFrameBuffer (width, height, false, fs, old);
//* Right now, CreateFrameBuffer cannot return NULL
if (res == NULL)
{
I_FatalError ("Mode %dx%d is unavailable\n", width, height);
}
//*/
return res;
}
static void GetCenteredPos (int &winx, int &winy, int &winw, int &winh, int &scrwidth, int &scrheight)
{
@ -290,85 +247,6 @@ void I_RestoreWindowedPos ()
}
MoveWindow (Window, winx, winy, winw, winh, TRUE);
if (win_borderless && !Args->CheckParm("-0"))
{
LONG lStyle = GetWindowLong(Window, GWL_STYLE);
lStyle &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU);
SetWindowLong(Window, GWL_STYLE, lStyle);
SetWindowPos(Window, HWND_TOP, 0, 0, scrwidth, scrheight, 0);
}
if (win_maximized && !Args->CheckParm("-0"))
ShowWindow(Window, SW_MAXIMIZE);
}
extern int NewWidth, NewHeight, NewBits, DisplayBits;
CUSTOM_CVAR(Bool, win_borderless, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
// Just reinit the window. Saves a lot of trouble.
if (!fullscreen)
{
NewWidth = screen->VideoWidth;
NewHeight = screen->VideoHeight;
NewBits = DisplayBits;
setmodeneeded = true;
}
}
CUSTOM_CVAR (Bool, fullscreen, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL)
{
NewWidth = screen->VideoWidth;
NewHeight = screen->VideoHeight;
NewBits = DisplayBits;
setmodeneeded = true;
}
CUSTOM_CVAR (Float, vid_winscale, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{
if (self < 1.f)
{
self = 1.f;
}
else if (Video)
{
Video->SetWindowedScale (self);
NewWidth = screen->VideoWidth;
NewHeight = screen->VideoHeight;
NewBits = DisplayBits;
//setmodeneeded = true; // This CVAR doesn't do anything and only causes problems!
}
}
CCMD (vid_listmodes)
{
static const char *ratios[7] = { "", " - 16:9", " - 16:10", " - 17:10", " - 5:4", " - 17:10", " - 21:9" };
int width, height, bits;
bool letterbox;
if (Video == NULL)
{
return;
}
for (bits = 1; bits <= 32; bits++)
{
Video->StartModeIterator (bits, screen->IsFullscreen());
while (Video->NextMode (&width, &height, &letterbox))
{
bool thisMode = (width == DisplayWidth && height == DisplayHeight && bits == DisplayBits);
int ratio = CheckRatio (width, height);
Printf (thisMode ? PRINT_BOLD : PRINT_HIGH,
"%s%4d x%5d x%3d%s%s\n",
thisMode || !IsRatioWidescreen(ratio) ? "" : TEXTCOLOR_GOLD,
width, height, bits,
ratios[ratio],
thisMode || !letterbox ? "" : TEXTCOLOR_BROWN " LB"
);
}
}
}
CCMD (vid_currentmode)
{
Printf ("%dx%dx%d\n", DisplayWidth, DisplayHeight, DisplayBits);
}

View file

@ -37,27 +37,6 @@
#include "i_video.h"
#include "v_video.h"
class IVideo
{
public:
virtual ~IVideo () {}
virtual EDisplayType GetDisplayType () = 0;
virtual void SetWindowedScale (float scale) = 0;
virtual DFrameBuffer *CreateFrameBuffer (int width, int height, bool bgra, bool fs, DFrameBuffer *old) = 0;
virtual void StartModeIterator (int bits, bool fs) = 0;
virtual bool NextMode (int *width, int *height, bool *letterbox) = 0;
virtual bool SetResolution (int width, int height, int bits);
virtual void DumpAdapters();
};
void I_InitGraphics ();
void I_ShutdownGraphics ();
void I_SaveWindowedPos ();
void I_RestoreWindowedPos ();
@ -65,6 +44,4 @@ void I_SetFPSLimit(int limit);
void I_FPSLimit();
extern IVideo *Video;
#endif // __HARDWARE_H__

View file

@ -61,8 +61,6 @@ extern "C" {
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
}
extern int NewWidth, NewHeight, NewBits, DisplayBits;
// these get used before GLEW is initialized so we have to use separate pointers with different names
PFNWGLCHOOSEPIXELFORMATARBPROC myWglChoosePixelFormatARB; // = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
PFNWGLCREATECONTEXTATTRIBSARBPROC myWglCreateContextAttribsARB;
@ -83,10 +81,10 @@ CUSTOM_CVAR(Bool, vr_enable_quadbuffered, false, CVAR_ARCHIVE | CVAR_GLOBALCONFI
Printf("You must restart " GAMENAME " to switch quad stereo mode\n");
}
EXTERN_CVAR(Int, vid_refreshrate)
EXTERN_CVAR(Int, vid_defwidth)
EXTERN_CVAR(Int, vid_defheight)
EXTERN_CVAR(Int, vid_adapter)
EXTERN_CVAR(Bool, fullscreen)
//==========================================================================
@ -101,41 +99,14 @@ public:
Win32GLVideo(int parm);
virtual ~Win32GLVideo();
EDisplayType GetDisplayType() { return DISPLAY_Both; }
void SetWindowedScale(float scale);
void StartModeIterator(int bits, bool fs);
bool NextMode(int *width, int *height, bool *letterbox);
bool GoFullscreen(bool yes);
DFrameBuffer *CreateFrameBuffer (int width, int height, bool bgra, bool fs, DFrameBuffer *old);
virtual bool SetResolution(int width, int height, int bits);
DFrameBuffer *CreateFrameBuffer ();
void DumpAdapters();
bool InitHardware(HWND Window, int multisample);
void Shutdown();
bool SetFullscreen(const char *devicename, int w, int h, int bits, int hz);
HDC m_hDC;
protected:
struct ModeInfo
{
ModeInfo(int inX, int inY, int inBits, int inRealY, int inRefresh)
: next(NULL),
width(inX),
height(inY),
bits(inBits),
refreshHz(inRefresh),
realheight(inRealY)
{}
ModeInfo *next;
int width, height, bits, refreshHz, realheight;
} *m_Modes;
ModeInfo *m_IteratorMode;
int m_IteratorBits;
bool m_IteratorFS;
bool m_IsFullscreen;
int m_trueHeight;
int m_DisplayWidth, m_DisplayHeight, m_DisplayBits, m_DisplayHz;
HMODULE hmRender;
char m_DisplayDeviceBuffer[CCHDEVICENAME];
@ -151,11 +122,7 @@ protected:
bool SetupPixelFormat(int multisample);
void GetDisplayDeviceName();
void MakeModesList();
void AddMode(int x, int y, int bits, int baseHeight, int refreshHz);
void FreeModes();
public:
int GetTrueHeight() { return m_trueHeight; }
};
@ -165,16 +132,11 @@ public:
//
//==========================================================================
Win32GLVideo::Win32GLVideo(int parm) : m_Modes(NULL), m_IsFullscreen(false)
Win32GLVideo::Win32GLVideo(int parm)
{
I_SetWndProc();
m_DisplayWidth = vid_defwidth;
m_DisplayHeight = vid_defheight;
m_DisplayBits = 32;
m_DisplayHz = 60;
GetDisplayDeviceName();
MakeModesList();
SetPixelFormat();
}
@ -187,7 +149,6 @@ Win32GLVideo::Win32GLVideo(int parm) : m_Modes(NULL), m_IsFullscreen(false)
Win32GLVideo::~Win32GLVideo()
{
FreeModes();
if (GLRenderer != NULL) GLRenderer->FlushTextures();
}
@ -197,16 +158,6 @@ Win32GLVideo::~Win32GLVideo()
//
//==========================================================================
void Win32GLVideo::SetWindowedScale(float scale)
{
}
//==========================================================================
//
//
//
//==========================================================================
struct MonitorEnumState
{
int curIdx;
@ -280,227 +231,11 @@ void Win32GLVideo::GetDisplayDeviceName()
//
//==========================================================================
void Win32GLVideo::MakeModesList()
{
ModeInfo *pMode, *nextmode;
DEVMODE dm;
int mode = 0;
memset(&dm, 0, sizeof(DEVMODE));
dm.dmSize = sizeof(DEVMODE);
while (EnumDisplaySettings(m_DisplayDeviceName, mode, &dm))
{
this->AddMode(dm.dmPelsWidth, dm.dmPelsHeight, dm.dmBitsPerPel, dm.dmPelsHeight, dm.dmDisplayFrequency);
++mode;
}
for (pMode = m_Modes; pMode != NULL; pMode = nextmode)
{
nextmode = pMode->next;
if (pMode->realheight == pMode->height && pMode->height * 4/3 == pMode->width)
{
if (pMode->width >= 360)
{
AddMode (pMode->width, pMode->width * 9/16, pMode->bits, pMode->height, pMode->refreshHz);
}
if (pMode->width > 640)
{
AddMode (pMode->width, pMode->width * 10/16, pMode->bits, pMode->height, pMode->refreshHz);
}
}
}
}
//==========================================================================
//
//
//
//==========================================================================
void Win32GLVideo::StartModeIterator(int bits, bool fs)
{
m_IteratorMode = m_Modes;
// I think it's better to ignore the game-side settings of bit depth.
// The GL renderer will always default to 32 bits because 16 bit modes cannot have a stencil buffer.
m_IteratorBits = 32;
m_IteratorFS = fs;
}
//==========================================================================
//
//
//
//==========================================================================
bool Win32GLVideo::NextMode(int *width, int *height, bool *letterbox)
{
if (m_IteratorMode)
{
while (m_IteratorMode && m_IteratorMode->bits != m_IteratorBits)
{
m_IteratorMode = m_IteratorMode->next;
}
if (m_IteratorMode)
{
*width = m_IteratorMode->width;
*height = m_IteratorMode->height;
if (letterbox != NULL) *letterbox = m_IteratorMode->realheight != m_IteratorMode->height;
m_IteratorMode = m_IteratorMode->next;
return true;
}
}
return false;
}
//==========================================================================
//
//
//
//==========================================================================
void Win32GLVideo::AddMode(int x, int y, int bits, int baseHeight, int refreshHz)
{
ModeInfo **probep = &m_Modes;
ModeInfo *probe = m_Modes;
// This mode may have been already added to the list because it is
// enumerated multiple times at different refresh rates. If it's
// not present, add it to the right spot in the list; otherwise, do nothing.
// Modes are sorted first by width, then by height, then by depth. In each
// case the order is ascending.
if (bits < 32) return;
for (; probe != 0; probep = &probe->next, probe = probe->next)
{
if (probe->width != x) continue;
// Width is equal
if (probe->height != y) continue;
// Width is equal
if (probe->realheight != baseHeight) continue;
// Height is equal
if (probe->bits != bits) continue;
// Bits is equal
if (probe->refreshHz > refreshHz) return;
probe->refreshHz = refreshHz;
return;
}
*probep = new ModeInfo (x, y, bits, baseHeight, refreshHz);
(*probep)->next = probe;
}
//==========================================================================
//
//
//
//==========================================================================
void Win32GLVideo::FreeModes()
{
ModeInfo *mode = m_Modes;
while (mode)
{
ModeInfo *tempmode = mode;
mode = mode->next;
delete tempmode;
}
m_Modes = NULL;
}
//==========================================================================
//
//
//
//==========================================================================
bool Win32GLVideo::GoFullscreen(bool yes)
{
m_IsFullscreen = yes;
m_trueHeight = m_DisplayHeight;
if (yes)
{
// If in windowed mode, any height is good.
for (ModeInfo *mode = m_Modes; mode != NULL; mode = mode->next)
{
if (mode->width == m_DisplayWidth && mode->height == m_DisplayHeight)
{
m_trueHeight = mode->realheight;
break;
}
}
}
if (yes)
{
SetFullscreen(m_DisplayDeviceName, m_DisplayWidth, m_trueHeight, m_DisplayBits, m_DisplayHz);
}
else
{
SetFullscreen(m_DisplayDeviceName, 0,0,0,0);
}
return yes;
}
//==========================================================================
//
//
//
//==========================================================================
void V_ClosestResolution(int *width, int *height, int bits);
DFrameBuffer *Win32GLVideo::CreateFrameBuffer(int width, int height, bool bgra, bool fs, DFrameBuffer *old)
DFrameBuffer *Win32GLVideo::CreateFrameBuffer()
{
SystemFrameBuffer *fb;
if (fs)
{
V_ClosestResolution(&width, &height, 32);
}
m_DisplayWidth = width;
m_DisplayHeight = height;
m_DisplayBits = 32;
m_DisplayHz = 60;
if (vid_refreshrate == 0)
{
for (ModeInfo *mode = m_Modes; mode != NULL; mode = mode->next)
{
if (mode->width == m_DisplayWidth && mode->height == m_DisplayHeight && mode->bits == m_DisplayBits)
{
m_DisplayHz = MAX<int>(m_DisplayHz, mode->refreshHz);
}
}
}
else
{
m_DisplayHz = vid_refreshrate;
}
if (old != NULL)
{ // Reuse the old framebuffer if its attributes are the same
fb = static_cast<SystemFrameBuffer *> (old);
if (fb->m_Width == m_DisplayWidth &&
fb->m_Height == m_DisplayHeight &&
fb->m_Bits == m_DisplayBits &&
fb->m_RefreshHz == m_DisplayHz &&
fb->m_Fullscreen == fs &&
fb->m_Bgra == bgra)
{
return old;
}
//old->GetFlash(flashColor, flashAmount);
delete old;
}
fb = new OpenGLFrameBuffer(m_hMonitor, m_DisplayWidth, m_DisplayHeight, m_DisplayBits, m_DisplayHz, fs);
fb = new OpenGLFrameBuffer(m_hMonitor, fullscreen);
return fb;
}
@ -510,26 +245,6 @@ DFrameBuffer *Win32GLVideo::CreateFrameBuffer(int width, int height, bool bgra,
//
//==========================================================================
bool Win32GLVideo::SetResolution (int width, int height, int bits)
{
if (GLRenderer != NULL) GLRenderer->FlushTextures();
I_ShutdownGraphics();
Video = new Win32GLVideo(0);
if (Video == NULL) I_FatalError ("Failed to initialize display");
bits=32;
V_DoModeSetup(width, height, bits);
return true; // We must return true because the old video context no longer exists.
}
//==========================================================================
//
//
//
//==========================================================================
struct DumpAdaptersState
{
unsigned index;
@ -936,84 +651,35 @@ void Win32GLVideo::Shutdown()
if (m_hDC) ReleaseDC(m_Window, m_hDC);
}
//==========================================================================
//
//
//
//==========================================================================
bool Win32GLVideo::SetFullscreen(const char *devicename, int w, int h, int bits, int hz)
void SystemFrameBuffer::PositionWindow()
{
DEVMODE dm;
if (w==0)
{
ChangeDisplaySettingsEx(devicename, 0, 0, 0, 0);
}
else
{
dm.dmSize = sizeof(DEVMODE);
dm.dmSpecVersion = DM_SPECVERSION;//Somebody owes me...
dm.dmDriverExtra = 0;//...1 hour of my life back
dm.dmPelsWidth = w;
dm.dmPelsHeight = h;
dm.dmBitsPerPel = bits;
dm.dmDisplayFrequency = hz;
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
if (DISP_CHANGE_SUCCESSFUL != ChangeDisplaySettingsEx(devicename, &dm, 0, CDS_FULLSCREEN, 0))
{
dm.dmFields &= ~DM_DISPLAYFREQUENCY;
return DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettingsEx(devicename, &dm, 0, CDS_FULLSCREEN, 0);
}
}
return true;
}
//==========================================================================
//
//
//
//==========================================================================
//==========================================================================
//
//
//
//==========================================================================
SystemFrameBuffer::SystemFrameBuffer(void *hMonitor, int width, int height, int bits, int refreshHz, bool fullscreen, bool bgra) : DFrameBuffer(width, height, bgra)
{
m_Width = width;
m_Height = height;
m_Bits = bits;
m_RefreshHz = refreshHz;
m_Fullscreen = fullscreen;
m_Bgra = bgra;
RECT r;
LONG style, exStyle;
static_cast<Win32GLVideo *>(Video)->GoFullscreen(fullscreen);
RECT monRect;
m_displayDeviceName = 0;
int monX = 0, monY = 0;
if (hMonitor)
if (m_Monitor)
{
MONITORINFOEX mi;
mi.cbSize = sizeof mi;
if (GetMonitorInfo(HMONITOR(hMonitor), &mi))
if (GetMonitorInfo(HMONITOR(m_Monitor), &mi))
{
strcpy(m_displayDeviceNameBuffer, mi.szDevice);
m_displayDeviceName = m_displayDeviceNameBuffer;
monX = int(mi.rcMonitor.left);
monY = int(mi.rcMonitor.top);
monRect = mi.rcMonitor;
}
}
ShowWindow (Window, SW_SHOW);
ShowWindow(Window, SW_SHOW);
GetWindowRect(Window, &r);
style = WS_VISIBLE | WS_CLIPSIBLINGS;
exStyle = 0;
@ -1032,7 +698,7 @@ SystemFrameBuffer::SystemFrameBuffer(void *hMonitor, int width, int height, int
if (fullscreen)
{
MoveWindow(Window, monX, monY, width, GetTrueHeight(), FALSE);
MoveWindow(Window, monRect.left, monRect.top, monRect.right-monRect.left, monRect.bottom-monRect.top, FALSE);
// And now, seriously, it IS in the right place. Promise.
}
@ -1041,13 +707,31 @@ SystemFrameBuffer::SystemFrameBuffer(void *hMonitor, int width, int height, int
RECT windowRect;
windowRect.left = r.left;
windowRect.top = r.top;
windowRect.right = windowRect.left + width;
windowRect.bottom = windowRect.top + height;
windowRect.right = windowRect.left + vid_defwidth;
windowRect.bottom = windowRect.top + vid_defheight;
AdjustWindowRectEx(&windowRect, style, FALSE, exStyle);
MoveWindow(Window, windowRect.left, windowRect.top, windowRect.right - windowRect.left, windowRect.bottom - windowRect.top, FALSE);
I_RestoreWindowedPos();
}
SetSize(GetClientWidth(), GetClientHeight());
}
//==========================================================================
//
//
//
//==========================================================================
SystemFrameBuffer::SystemFrameBuffer(void *hMonitor, bool fullscreen) : DFrameBuffer(vid_defwidth, vid_defheight)
{
m_Monitor = hMonitor;
m_Fullscreen = fullscreen;
m_displayDeviceName = 0;
PositionWindow();
if (!static_cast<Win32GLVideo *>(Video)->InitHardware(Window, 0))
{
@ -1096,8 +780,6 @@ SystemFrameBuffer::~SystemFrameBuffer()
ResetGammaTable();
I_SaveWindowedPos();
static_cast<Win32GLVideo *>(Video)->SetFullscreen(m_displayDeviceName, 0,0,0,0);
ShowWindow (Window, SW_SHOW);
SetWindowLong(Window, GWL_STYLE, WS_VISIBLE | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW);
SetWindowLong(Window, GWL_EXSTYLE, WS_EX_WINDOWEDGE);
@ -1184,17 +866,6 @@ void SystemFrameBuffer::SwapBuffers()
//
//==========================================================================
void SystemFrameBuffer::NewRefreshRate ()
{
if (m_Fullscreen)
{
setmodeneeded = true;
NewWidth = screen->VideoWidth;
NewHeight = screen->VideoHeight;
NewBits = DisplayBits;
}
}
int SystemFrameBuffer::GetClientWidth()
{
RECT rect = { 0 };
@ -1209,11 +880,6 @@ int SystemFrameBuffer::GetClientHeight()
return rect.bottom - rect.top;
}
int SystemFrameBuffer::GetTrueHeight()
{
return static_cast<Win32GLVideo *>(Video)->GetTrueHeight();
}
IVideo *gl_CreateVideo()
{
return new Win32GLVideo(0);