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_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 );
#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" );
#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_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" );

View file

@ -5,6 +5,7 @@ Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
Copyright (C) 2012 dhewg (dhewm3)
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").
@ -28,9 +29,10 @@ If you have questions concerning this license or the applicable additional terms
===========================================================================
*/
#include "../../idlib/precompiled.h"
#include <SDL.h>
#include "../../idlib/precompiled.h"
#include "renderer/tr_local.h"
#include "sdl_local.h"
#include "../posix/posix_public.h"
@ -58,6 +60,13 @@ If you have questions concerning this license or the applicable additional terms
// DG end
#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[] =
{
"english", "french", "german", "italian", "spanish", "turkish", "norwegian", NULL
@ -742,7 +751,28 @@ sysEvent_t Sys_GetEvent()
GLimp_GrabInput( 0 );
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;
@ -777,7 +807,16 @@ sysEvent_t Sys_GetEvent()
case SDL_KEYDOWN:
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" );
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) 2012 dhewg (dhewm3)
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").
@ -89,7 +90,9 @@ bool GLimp_Init( glimpParms_t parms )
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 )
flags |= SDL_WINDOW_FULLSCREEN;
@ -198,10 +201,34 @@ bool GLimp_Init( glimpParms_t parms )
}
// 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,
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
windowPos,
windowPos,
parms.width, parms.height, flags );
// DG end
context = SDL_GL_CreateContext( window );
if( !window )
@ -273,6 +300,113 @@ bool GLimp_Init( glimpParms_t parms )
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 )
{
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;
}