mirror of
https://bitbucket.org/CPMADevs/cnq3
synced 2025-01-21 07:40:48 +00:00
improved multi-monitor support and added r_monitor
only apply hw gamma ramps where and when needed fixed the start-up console window staying visible when starting in full-screen black window background to avoid the white flashes when hw gamma is enabled
This commit is contained in:
parent
569247745b
commit
e0d55dc63c
9 changed files with 255 additions and 75 deletions
|
@ -2252,7 +2252,6 @@ void Com_Init( char *commandLine )
|
|||
#ifndef DEDICATED
|
||||
CL_Init();
|
||||
#endif
|
||||
Sys_ShowConsole( com_viewlog->integer, qfalse );
|
||||
}
|
||||
|
||||
// set com_frameTime so that if a map is started on the
|
||||
|
@ -2279,6 +2278,10 @@ void Com_Init( char *commandLine )
|
|||
CL_StartHunkUsers();
|
||||
#endif
|
||||
|
||||
// moved to fix the console window staying visible when starting the game in full-screen mode
|
||||
if ( !com_dedicated->integer )
|
||||
Sys_ShowConsole( com_viewlog->integer, qfalse );
|
||||
|
||||
// make sure single player is off by default
|
||||
Cvar_Set( "sv_singlePlayer", "0" );
|
||||
|
||||
|
|
|
@ -46,6 +46,18 @@ float Com_Clamp( float min, float max, float value )
|
|||
}
|
||||
|
||||
|
||||
int Com_ClampInt( int min, int max, int value )
|
||||
{
|
||||
if ( value < min ) {
|
||||
return min;
|
||||
}
|
||||
if ( value > max ) {
|
||||
return max;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
const char* COM_SkipPath( const char* pathname )
|
||||
{
|
||||
const char* last = pathname;
|
||||
|
|
|
@ -508,6 +508,7 @@ void QDECL Com_Printf( const char* msg, ... );
|
|||
void QDECL Com_sprintf (char *dest, int size, const char *fmt, ...);
|
||||
|
||||
float Com_Clamp( float min, float max, float value );
|
||||
int Com_ClampInt( int min, int max, int value );
|
||||
|
||||
const char* COM_SkipPath( const char* pathname );
|
||||
void COM_StripExtension( const char* in, char* out, int destsize );
|
||||
|
|
|
@ -32,17 +32,16 @@ extern "C" {
|
|||
|
||||
typedef struct
|
||||
{
|
||||
HDC hDC; // handle to device context
|
||||
HGLRC hGLRC; // handle to GL rendering context
|
||||
HINSTANCE hinstOpenGL; // HINSTANCE for the OpenGL library
|
||||
|
||||
int desktopWidth, desktopHeight, desktopBPP;
|
||||
|
||||
qbool cdsFullscreen;
|
||||
qbool pixelFormatSet;
|
||||
int nPendingPF;
|
||||
|
||||
qbool gammaRampSet; // qtrue if our custom ramp is active
|
||||
// The main window's rendering context is the only one we can ever keep around
|
||||
// because the window class has the CS_OWNDC style set (for OpenGL).
|
||||
HDC hDC;
|
||||
HGLRC hGLRC;
|
||||
HINSTANCE hinstOpenGL;
|
||||
int desktopWidth, desktopHeight, desktopBPP;
|
||||
qbool cdsFullscreen;
|
||||
qbool pixelFormatSet;
|
||||
int nPendingPF;
|
||||
qbool gammaRampSet; // qtrue if our custom ramp is active
|
||||
} glwstate_t;
|
||||
|
||||
extern glwstate_t glw_state;
|
||||
|
|
|
@ -464,7 +464,7 @@ static qbool GLW_CreateWindow( int width, int height, int colorbits )
|
|||
wc.hInstance = g_wv.hInstance;
|
||||
wc.hIcon = LoadIcon( g_wv.hInstance, MAKEINTRESOURCE(IDI_ICON1));
|
||||
wc.hCursor = LoadCursor (NULL,IDC_ARROW);
|
||||
wc.hbrBackground = (HBRUSH)COLOR_GRAYTEXT;
|
||||
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
||||
wc.lpszMenuName = 0;
|
||||
wc.lpszClassName = CLIENT_WINDOW_TITLE;
|
||||
|
||||
|
@ -475,55 +475,55 @@ static qbool GLW_CreateWindow( int width, int height, int colorbits )
|
|||
ri.Printf( PRINT_DEVELOPER, "...registered window class\n" );
|
||||
}
|
||||
|
||||
|
||||
RECT r;
|
||||
int x, y, w, h;
|
||||
|
||||
//
|
||||
// create the HWND if one does not already exist
|
||||
//
|
||||
if ( !g_wv.hWnd )
|
||||
{
|
||||
//
|
||||
// compute width and height
|
||||
//
|
||||
RECT r;
|
||||
r.left = 0;
|
||||
r.top = 0;
|
||||
r.right = width;
|
||||
r.bottom = height;
|
||||
|
||||
int style = WS_VISIBLE | WS_SYSMENU;
|
||||
int style = WS_VISIBLE | WS_CLIPCHILDREN;
|
||||
int exstyle;
|
||||
|
||||
if ( glInfo.isFullscreen )
|
||||
{
|
||||
style |= WS_POPUP;
|
||||
// WS_BORDER fixes the single black flash that happens when reloading a map
|
||||
// right after switching from windowed mode to full-screen
|
||||
style |= WS_POPUP | WS_BORDER;
|
||||
exstyle = WS_EX_TOPMOST;
|
||||
}
|
||||
else
|
||||
{
|
||||
style |= WS_OVERLAPPED | WS_BORDER | WS_CAPTION;
|
||||
style |= WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU;
|
||||
exstyle = 0;
|
||||
AdjustWindowRect( &r, style, FALSE );
|
||||
}
|
||||
|
||||
w = r.right - r.left;
|
||||
h = r.bottom - r.top;
|
||||
const int w = r.right - r.left;
|
||||
const int h = r.bottom - r.top;
|
||||
|
||||
if ( glInfo.isFullscreen )
|
||||
WIN_GetStartUpMonitorIndex();
|
||||
const RECT monRect = g_wv.monitorRects[g_wv.monitor];
|
||||
|
||||
int dx = 0;
|
||||
int dy = 0;
|
||||
|
||||
if ( !glInfo.isFullscreen )
|
||||
{
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
const cvar_t* vid_xpos = ri.Cvar_Get( "vid_xpos", "", 0 );
|
||||
const cvar_t* vid_ypos = ri.Cvar_Get( "vid_ypos", "", 0 );
|
||||
x = vid_xpos->integer;
|
||||
y = vid_ypos->integer;
|
||||
dx = ri.Cvar_Get( "vid_xpos", "0", 0 )->integer;
|
||||
dy = ri.Cvar_Get( "vid_ypos", "0", 0 )->integer;
|
||||
dx = Com_ClampInt( 0, max( 0, monRect.right - monRect.left - w ), dx );
|
||||
dy = Com_ClampInt( 0, max( 0, monRect.bottom - monRect.top - h ), dy );
|
||||
}
|
||||
|
||||
g_wv.hWnd = CreateWindowEx( exstyle, CLIENT_WINDOW_TITLE, CLIENT_WINDOW_TITLE, style,
|
||||
const int x = monRect.left + dx;
|
||||
const int y = monRect.top + dy;
|
||||
|
||||
g_wv.hWnd = CreateWindowEx( exstyle, CLIENT_WINDOW_TITLE, " "CLIENT_WINDOW_TITLE, style,
|
||||
x, y, w, h, NULL, NULL, g_wv.hInstance, NULL );
|
||||
|
||||
if ( !g_wv.hWnd )
|
||||
|
@ -842,15 +842,66 @@ static void GLW_CheckHardwareGamma()
|
|||
}
|
||||
|
||||
|
||||
static void GLW_UpdateGammaMonitorInfo()
|
||||
{
|
||||
const int screenCount = GetSystemMetrics( SM_CMONITORS );
|
||||
if ( screenCount <= 1 )
|
||||
{
|
||||
g_wv.hGammaMonitor = NULL;
|
||||
g_wv.gammaMonitorName[0] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
RECT rect;
|
||||
GetWindowRect( g_wv.hWnd, &rect );
|
||||
const HMONITOR hMonitor = MonitorFromRect( &rect, MONITOR_DEFAULTTONEAREST );
|
||||
|
||||
MONITORINFOEX info;
|
||||
ZeroMemory( &info, sizeof( info ) );
|
||||
info.cbSize = sizeof( MONITORINFOEX );
|
||||
if ( GetMonitorInfo( hMonitor, &info ) )
|
||||
{
|
||||
g_wv.hGammaMonitor = hMonitor;
|
||||
Q_strncpyz( g_wv.gammaMonitorName, info.szDevice, sizeof( g_wv.gammaMonitorName ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void GLW_RestoreGammaRamp( HDC hDC )
|
||||
{
|
||||
if ( SetDeviceGammaRamp( hDC, s_oldHardwareGamma ) )
|
||||
glw_state.gammaRampSet = qfalse;
|
||||
}
|
||||
|
||||
|
||||
void GLW_RestoreGamma()
|
||||
{
|
||||
if (!glConfig.deviceSupportsGamma || !glw_state.gammaRampSet)
|
||||
return;
|
||||
|
||||
HDC hDC = GetDC( GetDesktopWindow() );
|
||||
if ( SetDeviceGammaRamp( hDC, s_oldHardwareGamma ) )
|
||||
glw_state.gammaRampSet = qfalse;
|
||||
ReleaseDC( GetDesktopWindow(), hDC );
|
||||
if ( g_wv.hGammaMonitor )
|
||||
{
|
||||
const HDC hDC = CreateDC( "DISPLAY", g_wv.gammaMonitorName, NULL, NULL );
|
||||
GLW_RestoreGammaRamp( hDC );
|
||||
DeleteDC( hDC );
|
||||
}
|
||||
else
|
||||
{
|
||||
GLW_RestoreGammaRamp( glw_state.hDC );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void GLW_SetGammaRamp( HDC hDC, LPVOID lpRamp )
|
||||
{
|
||||
if ( SetDeviceGammaRamp( hDC, lpRamp ) )
|
||||
{
|
||||
glw_state.gammaRampSet = qtrue;
|
||||
}
|
||||
else
|
||||
{
|
||||
Com_Printf( "SetDeviceGammaRamp failed.\n" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -879,10 +930,16 @@ void GLimp_SetGamma( unsigned char red[256], unsigned char green[256], unsigned
|
|||
}
|
||||
}
|
||||
|
||||
if ( SetDeviceGammaRamp( glw_state.hDC, table ) ) {
|
||||
glw_state.gammaRampSet = qtrue;
|
||||
} else {
|
||||
Com_Printf( "SetDeviceGammaRamp failed.\n" );
|
||||
GLW_UpdateGammaMonitorInfo();
|
||||
if ( g_wv.hGammaMonitor )
|
||||
{
|
||||
const HDC hDC = CreateDC( "DISPLAY", g_wv.gammaMonitorName, NULL, NULL );
|
||||
GLW_SetGammaRamp( hDC, table );
|
||||
DeleteDC( hDC );
|
||||
}
|
||||
else
|
||||
{
|
||||
GLW_SetGammaRamp( glw_state.hDC, table );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1088,3 +1145,14 @@ void GLimp_WakeRenderer( void *data ) {
|
|||
WaitForSingleObject( renderActiveEvent, INFINITE );
|
||||
}
|
||||
|
||||
|
||||
void WIN_UpdateHardwareGammaRamp( qbool enable )
|
||||
{
|
||||
if ( !glConfig.deviceSupportsGamma )
|
||||
return;
|
||||
|
||||
if ( enable )
|
||||
R_SetColorMappings();
|
||||
else
|
||||
GLW_RestoreGamma();
|
||||
}
|
||||
|
|
|
@ -38,6 +38,9 @@ qbool IN_ProcessMessage( UINT msg, WPARAM wParam, LPARAM lParam ); // returns tr
|
|||
void IN_Frame();
|
||||
void IN_Shutdown();
|
||||
|
||||
void WIN_GetStartUpMonitorIndex();
|
||||
void WIN_GetMonitorIndexFromMainWindow();
|
||||
void WIN_UpdateHardwareGammaRamp( qbool enable );
|
||||
|
||||
void SNDDMA_Activate();
|
||||
|
||||
|
@ -45,6 +48,8 @@ LRESULT CALLBACK MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
|
|||
|
||||
void GLW_RestoreGamma();
|
||||
|
||||
#define MAX_MONITOR_COUNT 16
|
||||
|
||||
typedef struct
|
||||
{
|
||||
HWND hWnd;
|
||||
|
@ -54,7 +59,16 @@ typedef struct
|
|||
|
||||
// when we get a windows message, we store the time off
|
||||
// so keyboard processing can know the exact time of an event
|
||||
unsigned sysMsgTime;
|
||||
unsigned sysMsgTime;
|
||||
|
||||
HMONITOR hGammaMonitor;
|
||||
char gammaMonitorName[CCHDEVICENAME];
|
||||
|
||||
RECT monitorRects[MAX_MONITOR_COUNT];
|
||||
HMONITOR hMonitors[MAX_MONITOR_COUNT];
|
||||
int monitor; // index of the monitor currently used for display
|
||||
int primaryMonitor;
|
||||
int monitorCount;
|
||||
} WinVars_t;
|
||||
|
||||
extern WinVars_t g_wv;
|
||||
|
|
|
@ -559,7 +559,81 @@ void Sys_Init()
|
|||
///////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
static int WinMainImpl( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
|
||||
static BOOL CALLBACK WIN_MonitorEnumCallback( HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData )
|
||||
{
|
||||
if ( lprcMonitor )
|
||||
{
|
||||
g_wv.monitorRects[g_wv.monitorCount] = *lprcMonitor;
|
||||
g_wv.hMonitors[g_wv.monitorCount] = hMonitor;
|
||||
g_wv.monitorCount++;
|
||||
}
|
||||
|
||||
if ( g_wv.monitorCount >= MAX_MONITOR_COUNT )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void WIN_GetMonitorList()
|
||||
{
|
||||
EnumDisplayMonitors( NULL, NULL, &WIN_MonitorEnumCallback, 0 );
|
||||
|
||||
const POINT zero = { 0, 0 };
|
||||
const HMONITOR hMonitor = MonitorFromPoint( zero, MONITOR_DEFAULTTOPRIMARY );
|
||||
for ( int i = 0; i < g_wv.monitorCount; i++ )
|
||||
{
|
||||
if ( hMonitor == g_wv.hMonitors[i] )
|
||||
{
|
||||
g_wv.primaryMonitor = i;
|
||||
g_wv.monitor = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void WIN_GetStartUpMonitorIndex()
|
||||
{
|
||||
static qbool called = qfalse;
|
||||
|
||||
if ( called )
|
||||
return;
|
||||
|
||||
called = qtrue;
|
||||
|
||||
// r_monitor is the 1-based monitor index the user asks for
|
||||
const int monitor = Cvar_Get( "r_monitor", "0", CVAR_ARCHIVE )->integer;
|
||||
if ( monitor <= 0 || monitor > g_wv.monitorCount )
|
||||
{
|
||||
g_wv.monitor = g_wv.primaryMonitor;
|
||||
return;
|
||||
}
|
||||
|
||||
g_wv.monitor = monitor - 1;
|
||||
}
|
||||
|
||||
|
||||
void WIN_GetMonitorIndexFromMainWindow()
|
||||
{
|
||||
const HMONITOR hMonitor = MonitorFromWindow( g_wv.hWnd, MONITOR_DEFAULTTONEAREST );
|
||||
for ( int i = 0; i < g_wv.monitorCount; i++ )
|
||||
{
|
||||
if ( hMonitor == g_wv.hMonitors[i] )
|
||||
{
|
||||
g_wv.monitor = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
int WINAPI WinMainImpl( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
|
||||
{
|
||||
// should never get a previous instance in Win32
|
||||
if ( hPrevInstance )
|
||||
|
@ -567,6 +641,8 @@ static int WinMainImpl( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCm
|
|||
|
||||
g_wv.hInstance = hInstance;
|
||||
|
||||
WIN_GetMonitorList();
|
||||
|
||||
// done before Com/Sys_Init since we need this for error output
|
||||
Sys_CreateConsole();
|
||||
|
||||
|
|
|
@ -294,14 +294,12 @@ LONG WINAPI InputLineWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
|
|||
*/
|
||||
void Sys_CreateConsole( void )
|
||||
{
|
||||
HDC hDC;
|
||||
WNDCLASS wc;
|
||||
RECT rect;
|
||||
const int desiredw = 540;
|
||||
const int desiredh = 450;
|
||||
const char *DEDCLASS = "Q3 WinConsole";
|
||||
int nHeight;
|
||||
int swidth, sheight;
|
||||
int DEDSTYLE = WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX;
|
||||
const DWORD DEDSTYLE = WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX;
|
||||
|
||||
WNDCLASS wc;
|
||||
memset( &wc, 0, sizeof( wc ) );
|
||||
|
||||
wc.style = 0;
|
||||
|
@ -318,25 +316,30 @@ void Sys_CreateConsole( void )
|
|||
if ( !RegisterClass (&wc) )
|
||||
return;
|
||||
|
||||
RECT rect;
|
||||
rect.left = 0;
|
||||
rect.right = 540;
|
||||
rect.right = desiredw;
|
||||
rect.top = 0;
|
||||
rect.bottom = 450;
|
||||
rect.bottom = desiredh;
|
||||
AdjustWindowRect( &rect, DEDSTYLE, FALSE );
|
||||
|
||||
hDC = GetDC( GetDesktopWindow() );
|
||||
swidth = GetDeviceCaps( hDC, HORZRES );
|
||||
sheight = GetDeviceCaps( hDC, VERTRES );
|
||||
ReleaseDC( GetDesktopWindow(), hDC );
|
||||
const RECT monRect = g_wv.monitorRects[g_wv.monitor];
|
||||
const int swidth = monRect.right - monRect.left;
|
||||
const int sheight = monRect.bottom - monRect.top;
|
||||
const int x = monRect.left + (swidth - desiredw) / 2;
|
||||
const int y = monRect.top + (sheight - desiredh) / 2;
|
||||
const int w = rect.right - rect.left + 1;
|
||||
const int h = rect.bottom - rect.top + 1;
|
||||
|
||||
s_wcd.windowWidth = rect.right - rect.left + 1;
|
||||
s_wcd.windowHeight = rect.bottom - rect.top + 1;
|
||||
s_wcd.windowWidth = w;
|
||||
s_wcd.windowHeight = h;
|
||||
|
||||
s_wcd.hWnd = CreateWindowEx( 0,
|
||||
DEDCLASS,
|
||||
CONSOLE_WINDOW_TITLE,
|
||||
" "CONSOLE_WINDOW_TITLE,
|
||||
DEDSTYLE,
|
||||
( swidth - 600 ) / 2, ( sheight - 450 ) / 2 , rect.right - rect.left + 1, rect.bottom - rect.top + 1,
|
||||
x, y,
|
||||
w, h,
|
||||
NULL,
|
||||
NULL,
|
||||
g_wv.hInstance,
|
||||
|
@ -350,8 +353,8 @@ void Sys_CreateConsole( void )
|
|||
//
|
||||
// create fonts
|
||||
//
|
||||
hDC = GetDC( s_wcd.hWnd );
|
||||
nHeight = -MulDiv( 8, GetDeviceCaps( hDC, LOGPIXELSY), 72);
|
||||
const HDC hDC = GetDC( s_wcd.hWnd );
|
||||
const int nHeight = -MulDiv( 8, GetDeviceCaps( hDC, LOGPIXELSY ), 72 );
|
||||
|
||||
s_wcd.hfBufferFont = CreateFont( nHeight,
|
||||
0,
|
||||
|
|
|
@ -86,6 +86,8 @@ static void VID_AppActivate( BOOL fActive, BOOL minimize )
|
|||
// we don't want to act like we're active if we're minimized
|
||||
g_wv.activeApp = (fActive && !g_wv.isMinimized);
|
||||
|
||||
WIN_UpdateHardwareGammaRamp( g_wv.activeApp );
|
||||
|
||||
// minimize/restore mouse-capture on demand
|
||||
IN_Activate( g_wv.activeApp );
|
||||
}
|
||||
|
@ -272,25 +274,27 @@ LRESULT CALLBACK MainWndProc (
|
|||
{
|
||||
if (!r_fullscreen->integer )
|
||||
{
|
||||
int xPos = (short)LOWORD(lParam); // horizontal position
|
||||
int yPos = (short)HIWORD(lParam); // vertical position
|
||||
WIN_GetMonitorIndexFromMainWindow();
|
||||
|
||||
RECT r;
|
||||
r.left = 0;
|
||||
r.top = 0;
|
||||
r.right = 1;
|
||||
r.bottom = 1;
|
||||
|
||||
AdjustWindowRect( &r, GetWindowLong( hWnd, GWL_STYLE ), FALSE );
|
||||
|
||||
Cvar_SetValue( "vid_xpos", xPos + r.left );
|
||||
Cvar_SetValue( "vid_ypos", yPos + r.top );
|
||||
const RECT monRect = g_wv.monitorRects[g_wv.monitor];
|
||||
const int x = LOWORD( lParam );
|
||||
const int y = HIWORD( lParam );
|
||||
Cvar_SetValue( "vid_xpos", x + r.left - monRect.left );
|
||||
Cvar_SetValue( "vid_ypos", y + r.top - monRect.top );
|
||||
vid_xpos->modified = qfalse;
|
||||
vid_ypos->modified = qfalse;
|
||||
if ( g_wv.activeApp )
|
||||
{
|
||||
IN_Activate (qtrue);
|
||||
}
|
||||
// @TODO: fix this broken mess
|
||||
if ( g_wv.activeApp )
|
||||
{
|
||||
IN_Activate (qtrue);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue