Support resizing windows + improve fullscreen for SDL2

By implementing GLimp_SetScreenParms() and enhancing the
event handling
This commit is contained in:
Daniel Gibson 2013-01-03 05:50:51 +01:00
parent 19effdad2c
commit d6c32cd49b
3 changed files with 218 additions and 7 deletions

View file

@ -53,7 +53,13 @@ idCVar r_skipIntelWorkarounds( "r_skipIntelWorkarounds", "0", CVAR_RENDERER | CV
idCVar r_multiSamples( "r_multiSamples", "0", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "number of antialiasing samples" ); idCVar r_multiSamples( "r_multiSamples", "0", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "number of antialiasing samples" );
idCVar r_vidMode( "r_vidMode", "0", CVAR_ARCHIVE | CVAR_RENDERER | CVAR_INTEGER, "fullscreen video mode number" ); idCVar r_vidMode( "r_vidMode", "0", CVAR_ARCHIVE | CVAR_RENDERER | CVAR_INTEGER, "fullscreen video mode number" );
idCVar r_displayRefresh( "r_displayRefresh", "0", CVAR_RENDERER | CVAR_INTEGER | CVAR_NOCHEAT, "optional display refresh rate option for vid mode", 0.0f, 240.0f ); idCVar r_displayRefresh( "r_displayRefresh", "0", CVAR_RENDERER | CVAR_INTEGER | CVAR_NOCHEAT, "optional display refresh rate option for vid mode", 0.0f, 240.0f );
#ifdef WIN32
idCVar r_fullscreen( "r_fullscreen", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "0 = windowed, 1 = full screen on monitor 1, 2 = full screen on monitor 2, etc" ); idCVar r_fullscreen( "r_fullscreen", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "0 = windowed, 1 = full screen on monitor 1, 2 = full screen on monitor 2, etc" );
#else
// DG: add mode -2 for SDL, also defaulting to windowed mode, as that causes less trouble on linux
idCVar r_fullscreen( "r_fullscreen", "0", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "-2 = use current monitor, -1 = (reserved), 0 = windowed, 1 = full screen on monitor 1, 2 = full screen on monitor 2, etc" );
// DG end
#endif
idCVar r_customWidth( "r_customWidth", "1280", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "custom screen width. set r_vidMode to -1 to activate" ); idCVar r_customWidth( "r_customWidth", "1280", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "custom screen width. set r_vidMode to -1 to activate" );
idCVar r_customHeight( "r_customHeight", "720", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "custom screen height. set r_vidMode to -1 to activate" ); idCVar r_customHeight( "r_customHeight", "720", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "custom screen height. set r_vidMode to -1 to activate" );
idCVar r_windowX( "r_windowX", "0", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "Non-fullscreen parameter" ); idCVar r_windowX( "r_windowX", "0", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "Non-fullscreen parameter" );

View file

@ -5,6 +5,7 @@ Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
Copyright (C) 2012 dhewg (dhewm3) Copyright (C) 2012 dhewg (dhewm3)
Copyright (C) 2012 Robert Beckebans Copyright (C) 2012 Robert Beckebans
Copyright (C) 2013 Daniel Gibson
This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code"). This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
@ -28,9 +29,10 @@ If you have questions concerning this license or the applicable additional terms
=========================================================================== ===========================================================================
*/ */
#include "../../idlib/precompiled.h"
#include <SDL.h> #include <SDL.h>
#include "../../idlib/precompiled.h"
#include "renderer/tr_local.h" #include "renderer/tr_local.h"
#include "sdl_local.h" #include "sdl_local.h"
#include "../posix/posix_public.h" #include "../posix/posix_public.h"
@ -58,6 +60,13 @@ If you have questions concerning this license or the applicable additional terms
// DG end // DG end
#endif #endif
// DG: those are needed for moving/resizing windows
extern idCVar r_windowX;
extern idCVar r_windowY;
extern idCVar r_windowWidth;
extern idCVar r_windowHeight;
// DG end
const char* kbdNames[] = const char* kbdNames[] =
{ {
"english", "french", "german", "italian", "spanish", "turkish", "norwegian", NULL "english", "french", "german", "italian", "spanish", "turkish", "norwegian", NULL
@ -742,7 +751,28 @@ sysEvent_t Sys_GetEvent()
GLimp_GrabInput( 0 ); GLimp_GrabInput( 0 );
break; break;
// TODO: SDL_WINDOWEVENT_RESIZED // DG: handle resizing and moving of window
case SDL_WINDOWEVENT_RESIZED:
{
int w = ev.window.data1;
int h = ev.window.data2;
r_windowWidth.SetInteger( w );
r_windowHeight.SetInteger( h );
glConfig.nativeScreenWidth = w;
glConfig.nativeScreenHeight = h;
break;
}
case SDL_WINDOWEVENT_MOVED:
{
int x = ev.window.data1;
int y = ev.window.data2;
r_windowX.SetInteger( x );
r_windowY.SetInteger( y );
break;
}
// DG end
} }
return res_none; return res_none;
@ -777,7 +807,16 @@ sysEvent_t Sys_GetEvent()
case SDL_KEYDOWN: case SDL_KEYDOWN:
if( ev.key.keysym.sym == SDLK_RETURN && ( ev.key.keysym.mod & KMOD_ALT ) > 0 ) if( ev.key.keysym.sym == SDLK_RETURN && ( ev.key.keysym.mod & KMOD_ALT ) > 0 )
{ {
cvarSystem->SetCVarBool( "r_fullscreen", !renderSystem->IsFullScreen() ); // DG: go to fullscreen on current display, instead of always first display
int fullscreen = 0;
if( ! renderSystem->IsFullScreen() )
{
// this will be handled as "fullscreen on current window"
// r_fullscreen 1 means "fullscreen on first window" in d3 bfg
fullscreen = -2;
}
cvarSystem->SetCVarInteger( "r_fullscreen", fullscreen );
// DG end
PushConsoleEvent( "vid_restart" ); PushConsoleEvent( "vid_restart" );
return res_none; return res_none;
} }

View file

@ -5,6 +5,7 @@ Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
Copyright (C) 2012 dhewg (dhewm3) Copyright (C) 2012 dhewg (dhewm3)
Copyright (C) 2012 Robert Beckebans Copyright (C) 2012 Robert Beckebans
Copyright (C) 2013 Daniel Gibson
This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code"). This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
@ -89,7 +90,9 @@ bool GLimp_Init( glimpParms_t parms )
GLimp_PreInit(); // DG: make sure SDL is initialized GLimp_PreInit(); // DG: make sure SDL is initialized
Uint32 flags = SDL_WINDOW_OPENGL; // DG: make window resizable
Uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE;
// DG end
if( parms.fullScreen ) if( parms.fullScreen )
flags |= SDL_WINDOW_FULLSCREEN; flags |= SDL_WINDOW_FULLSCREEN;
@ -198,10 +201,34 @@ bool GLimp_Init( glimpParms_t parms )
} }
// RB end // RB end
// DG: set display num for fullscreen
int windowPos = SDL_WINDOWPOS_UNDEFINED;
if( parms.fullScreen > 0 )
{
if( parms.fullScreen > SDL_GetNumVideoDisplays() )
{
common->Warning( "Couldn't set display to num %i because we only have %i displays",
parms.fullScreen, SDL_GetNumVideoDisplays() );
}
else
{
// -1 because SDL starts counting displays at 0, while parms.fullScreen starts at 1
windowPos = SDL_WINDOWPOS_UNDEFINED_DISPLAY( ( parms.fullScreen - 1 ) );
}
}
// TODO: if parms.fullScreen == -1 there should be a borderless window spanning multiple displays
/*
* NOTE that this implicitly handles parms.fullScreen == -2 (from r_fullscreen -2) meaning
* "do fullscreen, but I don't care on what monitor", at least on my box it's the monitor with
* the mouse cursor.
*/
window = SDL_CreateWindow( GAME_NAME, window = SDL_CreateWindow( GAME_NAME,
SDL_WINDOWPOS_UNDEFINED, windowPos,
SDL_WINDOWPOS_UNDEFINED, windowPos,
parms.width, parms.height, flags ); parms.width, parms.height, flags );
// DG end
context = SDL_GL_CreateContext( window ); context = SDL_GL_CreateContext( window );
if( !window ) if( !window )
@ -273,6 +300,113 @@ bool GLimp_Init( glimpParms_t parms )
return true; return true;
} }
/*
===================
Helper functions for GLimp_SetScreenParms()
===================
*/
#if SDL_VERSION_ATLEAST(2, 0, 0)
// SDL1 doesn't support multiple displays
// makes sure the window will be full-screened on the right display and returns the SDL display index
static int ScreenParmsHandleDisplayIndex( glimpParms_t parms )
{
int displayIdx;
if( parms.fullScreen > 0 )
{
displayIdx = parms.fullScreen - 1; // first display for SDL is 0, in parms it's 1
}
else // -2 == use current display
{
displayIdx = SDL_GetWindowDisplay( window );
if( displayIdx < 0 ) // for some reason the display for the window couldn't be detected
displayIdx = 0;
}
if( parms.fullScreen > SDL_GetNumVideoDisplays() )
{
common->Warning( "Can't set fullscreen mode to display number %i, because SDL2 only knows about %i displays!",
parms.fullScreen, SDL_GetNumVideoDisplays() );
return -1;
}
if( parms.fullScreen != glConfig.isFullscreen )
{
// we have to switch to another display
if( glConfig.isFullscreen )
{
// if we're already in fullscreen mode but want to switch to another monitor
// we have to go to windowed mode first to move the window.. SDL-oddity.
SDL_SetWindowFullscreen( window, SDL_FALSE );
}
// select display ; SDL_WINDOWPOS_UNDEFINED_DISPLAY() doesn't work.
int x = SDL_WINDOWPOS_CENTERED_DISPLAY( displayIdx );
// move window to the center of selected display
SDL_SetWindowPosition( window, x, x );
}
return displayIdx;
}
#endif // SDL_VERSION_ATLEAST(2, 0, 0)
static bool SetScreenParmsFullscreen( glimpParms_t parms )
{
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_DisplayMode m = {0};
int displayIdx = ScreenParmsHandleDisplayIndex( parms );
if( displayIdx < 0 )
return false;
// get current mode of display the window should be full-screened on
SDL_GetCurrentDisplayMode( displayIdx, &m );
// change settings in that display mode according to parms
// FIXME: check if refreshrate, width and height are supported?
// m.refresh_rate = parms.displayHz;
m.w = parms.width;
m.h = parms.height;
// set that displaymode
if( SDL_SetWindowDisplayMode( window, &m ) < 0 )
{
common->Warning( "Couldn't set window mode for fullscreen, reason: %s", SDL_GetError() );
return false;
}
// if we're currently not in fullscreen mode, we need to switch to fullscreen
if( !( SDL_GetWindowFlags( window ) & SDL_WINDOW_FULLSCREEN ) )
{
if( SDL_SetWindowFullscreen( window, SDL_TRUE ) < 0 )
{
common->Warning( "Couldn't switch to fullscreen mode, reason: %s!", SDL_GetError() );
return false;
}
}
#else // ! SDL_VERSION_ATLEAST(2, 0, 0) => SDL1.2
// TODO: SDL1.2 fullscreen handling
#endif // SDL_VERSION_ATLEAST(2, 0, 0)
return true;
}
static bool SetScreenParmsWindowed( glimpParms_t parms )
{
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_SetWindowSize( window, parms.width, parms.height );
SDL_SetWindowPosition( window, parms.x, parms.y );
// if we're currently in fullscreen mode, we need to disable that
if( SDL_GetWindowFlags( window ) & SDL_WINDOW_FULLSCREEN )
{
if( SDL_SetWindowFullscreen( window, SDL_FALSE ) < 0 )
{
common->Warning( "Couldn't switch to windowed mode, reason: %s!", SDL_GetError() );
return false;
}
}
#else // SDL 1.2
// TODO: SDL1.2 windowed handling
#endif
return true;
}
/* /*
=================== ===================
@ -281,7 +415,39 @@ GLimp_SetScreenParms
*/ */
bool GLimp_SetScreenParms( glimpParms_t parms ) bool GLimp_SetScreenParms( glimpParms_t parms )
{ {
common->DPrintf( "TODO: GLimp_SetScreenParms\n" ); #if SDL_VERSION_ATLEAST(2, 0, 0)
if( parms.fullScreen > 0 || parms.fullScreen == -2 )
{
if( !SetScreenParmsFullscreen( parms ) )
return false;
}
else if( parms.fullScreen == 0 ) // windowed mode
{
if( !SetScreenParmsWindowed( parms ) )
return false;
}
else
{
common->Warning( "GLimp_SetScreenParms: fullScreen -1 (borderless window for multiple displays) currently unsupported!" );
return false;
}
// Note: the following stuff would also work with SDL1.2
SDL_GL_SetAttribute( SDL_GL_STEREO, parms.stereo ? 1 : 0 );
SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, parms.multiSamples ? 1 : 0 );
SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, parms.multiSamples );
glConfig.isFullscreen = parms.fullScreen;
glConfig.isStereoPixelFormat = parms.stereo;
glConfig.nativeScreenWidth = parms.width;
glConfig.nativeScreenHeight = parms.height;
glConfig.displayFrequency = parms.displayHz;
glConfig.multisamples = parms.multiSamples;
#else // SDL 1.2
common->Printf( "TODO: Implement GLimp_SetScreenParms() for SDL1.2\n" );
#endif
return true; return true;
} }