mirror of
https://github.com/Shpoike/Quakespasm.git
synced 2024-11-10 15:31:39 +00:00
1b6abd0e04
1. Remove Key_IgnoreTextInput(), and simple always send a Char_Event when we receive TEXTINPUT (SDL2) or the unicode field of a KEYDOWN event is filled (SDL1.). 2. Remove handling of K_KP_* in the menu/console, since they cannot be relied on to not also send text (see issue described above). The handling of K_KP_ENTER can stay, since we do know that it never sends text. 3. Remove the interpretation hack for the numpad, since it will no longer be needed (and doesn't currently work for SDL2 anyway); if a numpad key generates text we will handle it (because of "1"), if not then it will simply be if ignored (because of "2”). git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@1110 af15c1b1-3010-417e-b628-4374ebc0bcbd
1890 lines
45 KiB
C
1890 lines
45 KiB
C
/*
|
|
Copyright (C) 1996-2001 Id Software, Inc.
|
|
Copyright (C) 2002-2009 John Fitzgibbons and others
|
|
Copyright (C) 2007-2008 Kristian Duske
|
|
Copyright (C) 2010-2014 QuakeSpasm developers
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
// gl_vidsdl.c -- SDL GL vid component
|
|
|
|
#include "quakedef.h"
|
|
#include "cfgfile.h"
|
|
#include "bgmusic.h"
|
|
#include "resource.h"
|
|
#if defined(SDL_FRAMEWORK) || defined(NO_SDL_CONFIG)
|
|
#if defined(USE_SDL2)
|
|
#include <SDL2/SDL.h>
|
|
#else
|
|
#include <SDL/SDL.h>
|
|
#endif
|
|
#else
|
|
#include "SDL.h"
|
|
#endif
|
|
|
|
#define MAX_MODE_LIST 600 //johnfitz -- was 30
|
|
#define MAX_BPPS_LIST 5
|
|
#define WARP_WIDTH 320
|
|
#define WARP_HEIGHT 200
|
|
#define MAXWIDTH 10000
|
|
#define MAXHEIGHT 10000
|
|
|
|
#define DEFAULT_SDL_FLAGS SDL_OPENGL
|
|
|
|
typedef struct {
|
|
int width;
|
|
int height;
|
|
int bpp;
|
|
} vmode_t;
|
|
|
|
static const char *gl_vendor;
|
|
static const char *gl_renderer;
|
|
static const char *gl_version;
|
|
static int gl_version_major;
|
|
static int gl_version_minor;
|
|
static const char *gl_extensions;
|
|
static char * gl_extensions_nice;
|
|
|
|
static vmode_t modelist[MAX_MODE_LIST];
|
|
static int nummodes;
|
|
|
|
static qboolean vid_initialized = false;
|
|
|
|
#if defined(USE_SDL2)
|
|
static SDL_Window *draw_context;
|
|
static SDL_GLContext gl_context;
|
|
#else
|
|
static SDL_Surface *draw_context;
|
|
#endif
|
|
|
|
static qboolean vid_locked = false; //johnfitz
|
|
static qboolean vid_changed = false;
|
|
|
|
static void VID_Menu_Init (void); //johnfitz
|
|
static void VID_Menu_f (void); //johnfitz
|
|
static void VID_MenuDraw (void);
|
|
static void VID_MenuKey (int key);
|
|
|
|
static void ClearAllStates (void);
|
|
static void GL_Init (void);
|
|
static void GL_SetupState (void); //johnfitz
|
|
|
|
viddef_t vid; // global video state
|
|
modestate_t modestate = MS_UNINIT;
|
|
qboolean scr_skipupdate;
|
|
|
|
qboolean gl_mtexable = false;
|
|
qboolean gl_texture_env_combine = false; //johnfitz
|
|
qboolean gl_texture_env_add = false; //johnfitz
|
|
qboolean gl_swap_control = false; //johnfitz
|
|
qboolean gl_anisotropy_able = false; //johnfitz
|
|
float gl_max_anisotropy; //johnfitz
|
|
qboolean gl_texture_NPOT = false; //ericw
|
|
qboolean gl_vbo_able = false; //ericw
|
|
GLint gl_max_texture_units = 0; //ericw
|
|
|
|
PFNGLMULTITEXCOORD2FARBPROC GL_MTexCoord2fFunc = NULL; //johnfitz
|
|
PFNGLACTIVETEXTUREARBPROC GL_SelectTextureFunc = NULL; //johnfitz
|
|
PFNGLCLIENTACTIVETEXTUREARBPROC GL_ClientActiveTextureFunc = NULL; //ericw
|
|
PFNGLBINDBUFFERARBPROC GL_BindBufferFunc = NULL; //ericw
|
|
PFNGLBUFFERDATAARBPROC GL_BufferDataFunc = NULL; //ericw
|
|
PFNGLDELETEBUFFERSARBPROC GL_DeleteBuffersFunc = NULL; //ericw
|
|
PFNGLGENBUFFERSARBPROC GL_GenBuffersFunc = NULL; //ericw
|
|
|
|
//====================================
|
|
|
|
//johnfitz -- new cvars
|
|
static cvar_t vid_fullscreen = {"vid_fullscreen", "0", CVAR_ARCHIVE}; // QuakeSpasm, was "1"
|
|
static cvar_t vid_width = {"vid_width", "800", CVAR_ARCHIVE}; // QuakeSpasm, was 640
|
|
static cvar_t vid_height = {"vid_height", "600", CVAR_ARCHIVE}; // QuakeSpasm, was 480
|
|
static cvar_t vid_bpp = {"vid_bpp", "16", CVAR_ARCHIVE};
|
|
static cvar_t vid_vsync = {"vid_vsync", "0", CVAR_ARCHIVE};
|
|
static cvar_t vid_fsaa = {"vid_fsaa", "0", CVAR_ARCHIVE}; // QuakeSpasm
|
|
//johnfitz
|
|
|
|
cvar_t vid_gamma = {"gamma", "1", CVAR_ARCHIVE}; //johnfitz -- moved here from view.c
|
|
|
|
//==========================================================================
|
|
//
|
|
// HARDWARE GAMMA -- johnfitz
|
|
//
|
|
//==========================================================================
|
|
|
|
#define USE_GAMMA_RAMPS 0
|
|
|
|
#if USE_GAMMA_RAMPS
|
|
static unsigned short vid_gamma_red[256];
|
|
static unsigned short vid_gamma_green[256];
|
|
static unsigned short vid_gamma_blue[256];
|
|
|
|
static unsigned short vid_sysgamma_red[256];
|
|
static unsigned short vid_sysgamma_green[256];
|
|
static unsigned short vid_sysgamma_blue[256];
|
|
#endif
|
|
|
|
static qboolean gammaworks = false; // whether hw-gamma works
|
|
static int fsaa;
|
|
|
|
/*
|
|
================
|
|
VID_Gamma_SetGamma -- apply gamma correction
|
|
================
|
|
*/
|
|
static void VID_Gamma_SetGamma (void)
|
|
{
|
|
if (draw_context && gammaworks)
|
|
{
|
|
float value;
|
|
|
|
if (vid_gamma.value > (1.0f / GAMMA_MAX))
|
|
value = 1.0f / vid_gamma.value;
|
|
else
|
|
value = GAMMA_MAX;
|
|
|
|
#if defined(USE_SDL2)
|
|
# if USE_GAMMA_RAMPS
|
|
if (SDL_SetWindowGammaRamp(draw_context, vid_gamma_red, vid_gamma_green, vid_gamma_blue) != 0)
|
|
Con_Printf ("VID_Gamma_SetGamma: failed on SDL_SetWindowGammaRamp\n");
|
|
# else
|
|
if (SDL_SetWindowBrightness(draw_context, value) != 0)
|
|
Con_Printf ("VID_Gamma_SetGamma: failed on SDL_SetWindowBrightness\n");
|
|
# endif
|
|
#else /* USE_SDL2 */
|
|
# if USE_GAMMA_RAMPS
|
|
if (SDL_SetGammaRamp(vid_gamma_red, vid_gamma_green, vid_gamma_blue) == -1)
|
|
Con_Printf ("VID_Gamma_SetGamma: failed on SDL_SetGammaRamp\n");
|
|
# else
|
|
if (SDL_SetGamma(value,value,value) == -1)
|
|
Con_Printf ("VID_Gamma_SetGamma: failed on SDL_SetGamma\n");
|
|
# endif
|
|
#endif /* USE_SDL2 */
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
VID_Gamma_Restore -- restore system gamma
|
|
================
|
|
*/
|
|
static void VID_Gamma_Restore (void)
|
|
{
|
|
if (draw_context && gammaworks)
|
|
{
|
|
#if defined(USE_SDL2)
|
|
# if USE_GAMMA_RAMPS
|
|
if (SDL_SetWindowGammaRamp(draw_context, vid_sysgamma_red, vid_sysgamma_green, vid_sysgamma_blue) != 0)
|
|
Con_Printf ("VID_Gamma_Restore: failed on SDL_SetWindowGammaRamp\n");
|
|
# else
|
|
if (SDL_SetWindowBrightness(draw_context, 1) != 0)
|
|
Con_Printf ("VID_Gamma_Restore: failed on SDL_SetWindowBrightness\n");
|
|
# endif
|
|
#else /* USE_SDL2 */
|
|
# if USE_GAMMA_RAMPS
|
|
if (SDL_SetGammaRamp(vid_sysgamma_red, vid_sysgamma_green, vid_sysgamma_blue) == -1)
|
|
Con_Printf ("VID_Gamma_Restore: failed on SDL_SetGammaRamp\n");
|
|
# else
|
|
if (SDL_SetGamma(1, 1, 1) == -1)
|
|
Con_Printf ("VID_Gamma_Restore: failed on SDL_SetGamma\n");
|
|
# endif
|
|
#endif /* USE_SDL2 */
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
VID_Gamma_Shutdown -- called on exit
|
|
================
|
|
*/
|
|
static void VID_Gamma_Shutdown (void)
|
|
{
|
|
VID_Gamma_Restore ();
|
|
}
|
|
|
|
/*
|
|
================
|
|
VID_Gamma_f -- callback when the cvar changes
|
|
================
|
|
*/
|
|
static void VID_Gamma_f (cvar_t *var)
|
|
{
|
|
#if USE_GAMMA_RAMPS
|
|
int i;
|
|
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
vid_gamma_red[i] =
|
|
CLAMP(0, (int) (255 * pow((i + 0.5)/255.5, var->value) + 0.5), 255) << 8;
|
|
vid_gamma_green[i] = vid_gamma_red[i];
|
|
vid_gamma_blue[i] = vid_gamma_red[i];
|
|
}
|
|
#endif
|
|
VID_Gamma_SetGamma ();
|
|
}
|
|
|
|
/*
|
|
================
|
|
VID_Gamma_Init -- call on init
|
|
================
|
|
*/
|
|
static void VID_Gamma_Init (void)
|
|
{
|
|
#if defined(USE_SDL2)
|
|
# if USE_GAMMA_RAMPS
|
|
gammaworks = (SDL_GetWindowGammaRamp(draw_context, vid_sysgamma_red, vid_sysgamma_green, vid_sysgamma_blue) == 0);
|
|
if (gammaworks)
|
|
gammaworks = (SDL_SetWindowGammaRamp(draw_context, vid_sysgamma_red, vid_sysgamma_green, vid_sysgamma_blue) == 0);
|
|
# else
|
|
gammaworks = (SDL_SetWindowBrightness(draw_context, 1) == 0);
|
|
# endif
|
|
#else /* USE_SDL2 */
|
|
# if USE_GAMMA_RAMPS
|
|
gammaworks = (SDL_GetGammaRamp(vid_sysgamma_red, vid_sysgamma_green, vid_sysgamma_blue) == 0);
|
|
if (gammaworks)
|
|
gammaworks = (SDL_SetGammaRamp(vid_sysgamma_red, vid_sysgamma_green, vid_sysgamma_blue) == 0);
|
|
# else
|
|
gammaworks = (SDL_SetGamma(1, 1, 1) == 0);
|
|
# endif
|
|
#endif /* USE_SDL2 */
|
|
|
|
if (!gammaworks)
|
|
Con_SafePrintf("gamma adjustment not available\n");
|
|
|
|
Cvar_RegisterVariable (&vid_gamma);
|
|
Cvar_SetCallback (&vid_gamma, VID_Gamma_f);
|
|
}
|
|
|
|
/*
|
|
======================
|
|
VID_GetCurrentWidth
|
|
======================
|
|
*/
|
|
static int VID_GetCurrentWidth (void)
|
|
{
|
|
#if defined(USE_SDL2)
|
|
int w = 0, h = 0;
|
|
SDL_GetWindowSize(draw_context, &w, &h);
|
|
return w;
|
|
#else
|
|
return draw_context->w;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
=======================
|
|
VID_GetCurrentHeight
|
|
=======================
|
|
*/
|
|
static int VID_GetCurrentHeight (void)
|
|
{
|
|
#if defined(USE_SDL2)
|
|
int w = 0, h = 0;
|
|
SDL_GetWindowSize(draw_context, &w, &h);
|
|
return h;
|
|
#else
|
|
return draw_context->h;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
====================
|
|
VID_GetCurrentBPP
|
|
====================
|
|
*/
|
|
static int VID_GetCurrentBPP (void)
|
|
{
|
|
#if defined(USE_SDL2)
|
|
const Uint32 pixelFormat = SDL_GetWindowPixelFormat(draw_context);
|
|
return SDL_BITSPERPIXEL(pixelFormat);
|
|
#else
|
|
return draw_context->format->BitsPerPixel;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
====================
|
|
VID_GetFullscreen
|
|
====================
|
|
*/
|
|
static qboolean VID_GetFullscreen (void)
|
|
{
|
|
#if defined(USE_SDL2)
|
|
return (SDL_GetWindowFlags(draw_context) & SDL_WINDOW_FULLSCREEN) != 0;
|
|
#else
|
|
return (draw_context->flags & SDL_FULLSCREEN) != 0;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
====================
|
|
VID_GetVSync
|
|
====================
|
|
*/
|
|
static qboolean VID_GetVSync (void)
|
|
{
|
|
#if defined(USE_SDL2)
|
|
return SDL_GL_GetSwapInterval() == 1;
|
|
#else
|
|
int swap_control;
|
|
if (SDL_GL_GetAttribute(SDL_GL_SWAP_CONTROL, &swap_control) == 0)
|
|
return swap_control > 0;
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
====================
|
|
VID_GetWindow
|
|
|
|
used by pl_win.c
|
|
====================
|
|
*/
|
|
void *VID_GetWindow (void)
|
|
{
|
|
#if defined(USE_SDL2)
|
|
return draw_context;
|
|
#else
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
====================
|
|
VID_HasMouseOrInputFocus
|
|
====================
|
|
*/
|
|
qboolean VID_HasMouseOrInputFocus (void)
|
|
{
|
|
#if defined(USE_SDL2)
|
|
return (SDL_GetWindowFlags(draw_context) & (SDL_WINDOW_MOUSE_FOCUS | SDL_WINDOW_INPUT_FOCUS)) != 0;
|
|
#else
|
|
return (SDL_GetAppState() & (SDL_APPMOUSEFOCUS | SDL_APPINPUTFOCUS)) != 0;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
====================
|
|
VID_IsMinimized
|
|
====================
|
|
*/
|
|
qboolean VID_IsMinimized (void)
|
|
{
|
|
#if defined(USE_SDL2)
|
|
return !(SDL_GetWindowFlags(draw_context) & SDL_WINDOW_SHOWN);
|
|
#else
|
|
/* SDL_APPACTIVE in SDL 1.x means "not minimized" */
|
|
return !(SDL_GetAppState() & SDL_APPACTIVE);
|
|
#endif
|
|
}
|
|
|
|
#if defined(USE_SDL2)
|
|
/*
|
|
================
|
|
VID_SDL2_GetDisplayMode
|
|
|
|
Returns a pointer to a statically allocated SDL_DisplayMode structure
|
|
if there is one with the requested params on the default display.
|
|
Otherwise returns NULL.
|
|
|
|
This is passed to SDL_SetWindowDisplayMode to specify a pixel format
|
|
with the requested bpp. If we didn't care about bpp we could just pass NULL.
|
|
================
|
|
*/
|
|
static SDL_DisplayMode *VID_SDL2_GetDisplayMode(int width, int height, int bpp)
|
|
{
|
|
static SDL_DisplayMode mode;
|
|
const int sdlmodes = SDL_GetNumDisplayModes(0);
|
|
int i;
|
|
|
|
for (i = 0; i < sdlmodes; i++)
|
|
{
|
|
if (SDL_GetDisplayMode(0, i, &mode) == 0
|
|
&& mode.w == width && mode.h == height
|
|
&& SDL_BITSPERPIXEL(mode.format) == bpp)
|
|
{
|
|
return &mode;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
#endif /* USE_SDL2 */
|
|
|
|
/*
|
|
================
|
|
VID_ValidMode
|
|
================
|
|
*/
|
|
static qboolean VID_ValidMode (int width, int height, int bpp, qboolean fullscreen)
|
|
{
|
|
if (width < 320)
|
|
return false;
|
|
|
|
if (height < 200)
|
|
return false;
|
|
|
|
#if defined(USE_SDL2)
|
|
if (fullscreen && VID_SDL2_GetDisplayMode(width, height, bpp) == NULL)
|
|
bpp = 0;
|
|
#else
|
|
{
|
|
Uint32 flags = DEFAULT_SDL_FLAGS;
|
|
if (fullscreen)
|
|
flags |= SDL_FULLSCREEN;
|
|
|
|
bpp = SDL_VideoModeOK(width, height, bpp, flags);
|
|
}
|
|
#endif
|
|
|
|
switch (bpp)
|
|
{
|
|
case 16:
|
|
case 24:
|
|
case 32:
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
================
|
|
VID_SetMode
|
|
================
|
|
*/
|
|
static int VID_SetMode (int width, int height, int bpp, qboolean fullscreen)
|
|
{
|
|
int temp;
|
|
Uint32 flags;
|
|
char caption[50];
|
|
int depthbits;
|
|
int fsaa_obtained;
|
|
|
|
// so Con_Printfs don't mess us up by forcing vid and snd updates
|
|
temp = scr_disabled_for_loading;
|
|
scr_disabled_for_loading = true;
|
|
|
|
CDAudio_Pause ();
|
|
BGM_Pause ();
|
|
|
|
/* z-buffer depth */
|
|
if (bpp == 16)
|
|
depthbits = 16;
|
|
else depthbits = 24;
|
|
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, depthbits);
|
|
|
|
/* fsaa */
|
|
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, fsaa > 0 ? 1 : 0);
|
|
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, fsaa);
|
|
|
|
q_snprintf(caption, sizeof(caption), "QuakeSpasm %1.2f.%d", (float)QUAKESPASM_VERSION, QUAKESPASM_VER_PATCH);
|
|
|
|
#if defined(USE_SDL2)
|
|
/* Create the window if needed, hidden */
|
|
if (!draw_context)
|
|
{
|
|
flags = SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN;
|
|
|
|
draw_context = SDL_CreateWindow (caption, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, flags);
|
|
if (!draw_context) { // scale back fsaa
|
|
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
|
|
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
|
|
draw_context = SDL_CreateWindow (caption, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, flags);
|
|
}
|
|
if (!draw_context) { // scale back SDL_GL_DEPTH_SIZE
|
|
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
|
|
draw_context = SDL_CreateWindow (caption, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, flags);
|
|
}
|
|
if (!draw_context)
|
|
Sys_Error ("Couldn't create window");
|
|
|
|
gl_context = SDL_GL_CreateContext (draw_context);
|
|
if (!gl_context)
|
|
Sys_Error ("Couldn't create GL context");
|
|
}
|
|
|
|
/* Ensure the window is not fullscreen */
|
|
if (VID_GetFullscreen ())
|
|
{
|
|
if (SDL_SetWindowFullscreen (draw_context, 0) != 0)
|
|
Sys_Error("Couldn't set fullscreen state mode");
|
|
}
|
|
|
|
/* Set window size and display mode */
|
|
SDL_SetWindowSize (draw_context, width, height);
|
|
SDL_SetWindowPosition (draw_context, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
|
|
SDL_SetWindowDisplayMode (draw_context, VID_SDL2_GetDisplayMode(width, height, bpp));
|
|
|
|
/* Make window fullscreen if needed, and show the window */
|
|
if (fullscreen)
|
|
{
|
|
if (SDL_SetWindowFullscreen (draw_context, SDL_WINDOW_FULLSCREEN) != 0)
|
|
Sys_Error ("Couldn't set fullscreen state mode");
|
|
}
|
|
|
|
SDL_ShowWindow (draw_context);
|
|
|
|
gl_swap_control = true;
|
|
if (SDL_GL_SetSwapInterval ((vid_vsync.value) ? 1 : 0) == -1)
|
|
gl_swap_control = false;
|
|
|
|
#else /* !defined(USE_SDL2) */
|
|
|
|
flags = DEFAULT_SDL_FLAGS;
|
|
if (fullscreen)
|
|
flags |= SDL_FULLSCREEN;
|
|
|
|
gl_swap_control = true;
|
|
if (SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, (vid_vsync.value) ? 1 : 0) == -1)
|
|
gl_swap_control = false;
|
|
|
|
bpp = SDL_VideoModeOK(width, height, bpp, flags);
|
|
|
|
draw_context = SDL_SetVideoMode(width, height, bpp, flags);
|
|
if (!draw_context) { // scale back fsaa
|
|
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
|
|
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
|
|
draw_context = SDL_SetVideoMode(width, height, bpp, flags);
|
|
}
|
|
if (!draw_context) { // scale back SDL_GL_DEPTH_SIZE
|
|
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
|
|
draw_context = SDL_SetVideoMode(width, height, bpp, flags);
|
|
if (!draw_context)
|
|
Sys_Error ("Couldn't set video mode");
|
|
}
|
|
|
|
SDL_WM_SetCaption(caption, caption);
|
|
#endif /* !defined(USE_SDL2) */
|
|
|
|
vid.width = VID_GetCurrentWidth();
|
|
vid.height = VID_GetCurrentHeight();
|
|
vid.conwidth = vid.width & 0xFFFFFFF8;
|
|
vid.conheight = vid.conwidth * vid.height / vid.width;
|
|
vid.numpages = 2;
|
|
|
|
// read the obtained z-buffer depth
|
|
if (SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &depthbits) == -1)
|
|
depthbits = 0;
|
|
|
|
// read obtained fsaa samples
|
|
if (SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &fsaa_obtained) == -1)
|
|
fsaa_obtained = 0;
|
|
|
|
modestate = VID_GetFullscreen() ? MS_FULLSCREEN : MS_WINDOWED;
|
|
|
|
CDAudio_Resume ();
|
|
BGM_Resume ();
|
|
scr_disabled_for_loading = temp;
|
|
|
|
// fix the leftover Alt from any Alt-Tab or the like that switched us away
|
|
ClearAllStates ();
|
|
|
|
Con_SafePrintf ("Video mode %dx%dx%d (%d-bit z-buffer, %dx FSAA) initialized\n",
|
|
VID_GetCurrentWidth(),
|
|
VID_GetCurrentHeight(),
|
|
VID_GetCurrentBPP(),
|
|
depthbits,
|
|
fsaa_obtained);
|
|
|
|
vid.recalc_refdef = 1;
|
|
|
|
// no pending changes
|
|
vid_changed = false;
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
===================
|
|
VID_Changed_f -- kristian -- notify us that a value has changed that requires a vid_restart
|
|
===================
|
|
*/
|
|
static void VID_Changed_f (cvar_t *var)
|
|
{
|
|
vid_changed = true;
|
|
}
|
|
|
|
/*
|
|
===================
|
|
VID_Restart -- johnfitz -- change video modes on the fly
|
|
===================
|
|
*/
|
|
static void VID_Restart (void)
|
|
{
|
|
int width, height, bpp;
|
|
qboolean fullscreen;
|
|
|
|
if (vid_locked || !vid_changed)
|
|
return;
|
|
|
|
width = (int)vid_width.value;
|
|
height = (int)vid_height.value;
|
|
bpp = (int)vid_bpp.value;
|
|
fullscreen = vid_fullscreen.value ? true : false;
|
|
|
|
//
|
|
// validate new mode
|
|
//
|
|
if (!VID_ValidMode (width, height, bpp, fullscreen))
|
|
{
|
|
Con_Printf ("%dx%dx%d %s is not a valid mode\n",
|
|
width, height, bpp, fullscreen? "fullscreen" : "windowed");
|
|
return;
|
|
}
|
|
|
|
//
|
|
// set new mode
|
|
//
|
|
VID_SetMode (width, height, bpp, fullscreen);
|
|
|
|
GL_Init ();
|
|
TexMgr_ReloadImages ();
|
|
GL_BuildVBOs ();
|
|
GL_SetupState ();
|
|
|
|
//warpimages needs to be recalculated
|
|
TexMgr_RecalcWarpImageSize ();
|
|
|
|
//conwidth and conheight need to be recalculated
|
|
vid.conwidth = (scr_conwidth.value > 0) ? (int)scr_conwidth.value : (scr_conscale.value > 0) ? (int)(vid.width/scr_conscale.value) : vid.width;
|
|
vid.conwidth = CLAMP (320, vid.conwidth, vid.width);
|
|
vid.conwidth &= 0xFFFFFFF8;
|
|
vid.conheight = vid.conwidth * vid.height / vid.width;
|
|
//
|
|
// keep cvars in line with actual mode
|
|
//
|
|
VID_SyncCvars();
|
|
//
|
|
// update mouse grab
|
|
//
|
|
if (key_dest == key_console || key_dest == key_menu)
|
|
{
|
|
if (modestate == MS_WINDOWED)
|
|
IN_Deactivate(true);
|
|
else if (modestate == MS_FULLSCREEN)
|
|
IN_Activate();
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
VID_Test -- johnfitz -- like vid_restart, but asks for confirmation after switching modes
|
|
================
|
|
*/
|
|
static void VID_Test (void)
|
|
{
|
|
int old_width, old_height, old_bpp, old_fullscreen;
|
|
|
|
if (vid_locked || !vid_changed)
|
|
return;
|
|
//
|
|
// now try the switch
|
|
//
|
|
old_width = VID_GetCurrentWidth();
|
|
old_height = VID_GetCurrentHeight();
|
|
old_bpp = VID_GetCurrentBPP();
|
|
old_fullscreen = VID_GetFullscreen() ? true : false;
|
|
|
|
VID_Restart ();
|
|
|
|
//pop up confirmation dialoge
|
|
if (!SCR_ModalMessage("Would you like to keep this\nvideo mode? (y/n)\n", 5.0f))
|
|
{
|
|
//revert cvars and mode
|
|
Cvar_SetValueQuick (&vid_width, old_width);
|
|
Cvar_SetValueQuick (&vid_height, old_height);
|
|
Cvar_SetValueQuick (&vid_bpp, old_bpp);
|
|
Cvar_SetQuick (&vid_fullscreen, old_fullscreen ? "1" : "0");
|
|
VID_Restart ();
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
VID_Unlock -- johnfitz
|
|
================
|
|
*/
|
|
static void VID_Unlock (void)
|
|
{
|
|
vid_locked = false;
|
|
VID_SyncCvars();
|
|
}
|
|
|
|
//==============================================================================
|
|
//
|
|
// OPENGL STUFF
|
|
//
|
|
//==============================================================================
|
|
|
|
/*
|
|
===============
|
|
GL_MakeNiceExtensionsList -- johnfitz
|
|
===============
|
|
*/
|
|
static char *GL_MakeNiceExtensionsList (const char *in)
|
|
{
|
|
char *copy, *token, *out;
|
|
int i, count;
|
|
|
|
if (!in) return Z_Strdup("(none)");
|
|
|
|
//each space will be replaced by 4 chars, so count the spaces before we malloc
|
|
for (i = 0, count = 1; i < (int) strlen(in); i++)
|
|
{
|
|
if (in[i] == ' ')
|
|
count++;
|
|
}
|
|
|
|
out = (char *) Z_Malloc (strlen(in) + count*3 + 1); //usually about 1-2k
|
|
out[0] = 0;
|
|
|
|
copy = (char *) Z_Strdup(in);
|
|
for (token = strtok(copy, " "); token; token = strtok(NULL, " "))
|
|
{
|
|
strcat(out, "\n ");
|
|
strcat(out, token);
|
|
}
|
|
|
|
Z_Free (copy);
|
|
return out;
|
|
}
|
|
|
|
/*
|
|
===============
|
|
GL_Info_f -- johnfitz
|
|
===============
|
|
*/
|
|
static void GL_Info_f (void)
|
|
{
|
|
Con_SafePrintf ("GL_VENDOR: %s\n", gl_vendor);
|
|
Con_SafePrintf ("GL_RENDERER: %s\n", gl_renderer);
|
|
Con_SafePrintf ("GL_VERSION: %s\n", gl_version);
|
|
Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions_nice);
|
|
}
|
|
|
|
/*
|
|
===============
|
|
GL_CheckExtensions
|
|
===============
|
|
*/
|
|
static qboolean GL_ParseExtensionList (const char *list, const char *name)
|
|
{
|
|
const char *start;
|
|
const char *where, *terminator;
|
|
|
|
if (!list || !name || !*name)
|
|
return false;
|
|
if (strchr(name, ' ') != NULL)
|
|
return false; // extension names must not have spaces
|
|
|
|
start = list;
|
|
while (1) {
|
|
where = strstr (start, name);
|
|
if (!where)
|
|
break;
|
|
terminator = where + strlen (name);
|
|
if (where == start || where[-1] == ' ')
|
|
if (*terminator == ' ' || *terminator == '\0')
|
|
return true;
|
|
start = terminator;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static void GL_CheckExtensions (void)
|
|
{
|
|
int swap_control;
|
|
|
|
// ARB_vertex_buffer_object
|
|
//
|
|
if (COM_CheckParm("-novbo"))
|
|
Con_Warning ("Vertex buffer objects disabled at command line\n");
|
|
else if (gl_version_major < 1 || (gl_version_major == 1 && gl_version_minor < 5))
|
|
Con_Warning ("OpenGL version < 1.5, skipping ARB_vertex_buffer_object check\n");
|
|
else
|
|
{
|
|
GL_BindBufferFunc = (PFNGLBINDBUFFERARBPROC) SDL_GL_GetProcAddress("glBindBufferARB");
|
|
GL_BufferDataFunc = (PFNGLBUFFERDATAARBPROC) SDL_GL_GetProcAddress("glBufferDataARB");
|
|
GL_DeleteBuffersFunc = (PFNGLDELETEBUFFERSARBPROC) SDL_GL_GetProcAddress("glDeleteBuffersARB");
|
|
GL_GenBuffersFunc = (PFNGLGENBUFFERSARBPROC) SDL_GL_GetProcAddress("glGenBuffersARB");
|
|
if (GL_BindBufferFunc && GL_BufferDataFunc && GL_DeleteBuffersFunc && GL_GenBuffersFunc)
|
|
{
|
|
Con_Printf("FOUND: ARB_vertex_buffer_object\n");
|
|
gl_vbo_able = true;
|
|
}
|
|
else
|
|
{
|
|
Con_Warning ("ARB_vertex_buffer_object not available\n");
|
|
}
|
|
}
|
|
|
|
// multitexture
|
|
//
|
|
if (COM_CheckParm("-nomtex"))
|
|
Con_Warning ("Mutitexture disabled at command line\n");
|
|
else if (GL_ParseExtensionList(gl_extensions, "GL_ARB_multitexture"))
|
|
{
|
|
GL_MTexCoord2fFunc = (PFNGLMULTITEXCOORD2FARBPROC) SDL_GL_GetProcAddress("glMultiTexCoord2fARB");
|
|
GL_SelectTextureFunc = (PFNGLACTIVETEXTUREARBPROC) SDL_GL_GetProcAddress("glActiveTextureARB");
|
|
GL_ClientActiveTextureFunc = (PFNGLCLIENTACTIVETEXTUREARBPROC) SDL_GL_GetProcAddress("glClientActiveTextureARB");
|
|
if (GL_MTexCoord2fFunc && GL_SelectTextureFunc && GL_ClientActiveTextureFunc)
|
|
{
|
|
Con_Printf("FOUND: ARB_multitexture\n");
|
|
gl_mtexable = true;
|
|
|
|
glGetIntegerv(GL_MAX_TEXTURE_UNITS, &gl_max_texture_units);
|
|
Con_Printf("GL_MAX_TEXTURE_UNITS: %d\n", (int)gl_max_texture_units);
|
|
}
|
|
else
|
|
{
|
|
Con_Warning ("Couldn't link to multitexture functions\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Con_Warning ("multitexture not supported (extension not found)\n");
|
|
}
|
|
|
|
// texture_env_combine
|
|
//
|
|
if (COM_CheckParm("-nocombine"))
|
|
Con_Warning ("texture_env_combine disabled at command line\n");
|
|
else if (GL_ParseExtensionList(gl_extensions, "GL_ARB_texture_env_combine"))
|
|
{
|
|
Con_Printf("FOUND: ARB_texture_env_combine\n");
|
|
gl_texture_env_combine = true;
|
|
}
|
|
else if (GL_ParseExtensionList(gl_extensions, "GL_EXT_texture_env_combine"))
|
|
{
|
|
Con_Printf("FOUND: EXT_texture_env_combine\n");
|
|
gl_texture_env_combine = true;
|
|
}
|
|
else
|
|
{
|
|
Con_Warning ("texture_env_combine not supported\n");
|
|
}
|
|
|
|
// texture_env_add
|
|
//
|
|
if (COM_CheckParm("-noadd"))
|
|
Con_Warning ("texture_env_add disabled at command line\n");
|
|
else if (GL_ParseExtensionList(gl_extensions, "GL_ARB_texture_env_add"))
|
|
{
|
|
Con_Printf("FOUND: ARB_texture_env_add\n");
|
|
gl_texture_env_add = true;
|
|
}
|
|
else if (GL_ParseExtensionList(gl_extensions, "GL_EXT_texture_env_add"))
|
|
{
|
|
Con_Printf("FOUND: EXT_texture_env_add\n");
|
|
gl_texture_env_add = true;
|
|
}
|
|
else
|
|
{
|
|
Con_Warning ("texture_env_add not supported\n");
|
|
}
|
|
|
|
// swap control
|
|
//
|
|
if (!gl_swap_control)
|
|
{
|
|
#if defined(USE_SDL2)
|
|
Con_Warning ("vertical sync not supported (SDL_GL_SetSwapInterval failed)\n");
|
|
#else
|
|
Con_Warning ("vertical sync not supported (SDL_GL_SetAttribute failed)\n");
|
|
#endif
|
|
}
|
|
#if defined(USE_SDL2)
|
|
else if ((swap_control = SDL_GL_GetSwapInterval()) == -1)
|
|
#else
|
|
else if (SDL_GL_GetAttribute(SDL_GL_SWAP_CONTROL, &swap_control) == -1)
|
|
#endif
|
|
{
|
|
gl_swap_control = false;
|
|
#if defined(USE_SDL2)
|
|
Con_Warning ("vertical sync not supported (SDL_GL_GetSwapInterval failed)\n");
|
|
#else
|
|
Con_Warning ("vertical sync not supported (SDL_GL_GetAttribute failed)\n");
|
|
#endif
|
|
}
|
|
else if ((vid_vsync.value && swap_control != 1) || (!vid_vsync.value && swap_control != 0))
|
|
{
|
|
gl_swap_control = false;
|
|
Con_Warning ("vertical sync not supported (swap_control doesn't match vid_vsync)\n");
|
|
}
|
|
else
|
|
{
|
|
#if defined(USE_SDL2)
|
|
Con_Printf("FOUND: SDL_GL_SetSwapInterval\n");
|
|
#else
|
|
Con_Printf("FOUND: SDL_GL_SWAP_CONTROL\n");
|
|
#endif
|
|
}
|
|
|
|
// anisotropic filtering
|
|
//
|
|
if (GL_ParseExtensionList(gl_extensions, "GL_EXT_texture_filter_anisotropic"))
|
|
{
|
|
float test1,test2;
|
|
GLuint tex;
|
|
|
|
// test to make sure we really have control over it
|
|
// 1.0 and 2.0 should always be legal values
|
|
glGenTextures(1, &tex);
|
|
glBindTexture (GL_TEXTURE_2D, tex);
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
|
|
glGetTexParameterfv (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &test1);
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2.0f);
|
|
glGetTexParameterfv (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &test2);
|
|
glDeleteTextures(1, &tex);
|
|
|
|
if (test1 == 1 && test2 == 2)
|
|
{
|
|
Con_Printf("FOUND: EXT_texture_filter_anisotropic\n");
|
|
gl_anisotropy_able = true;
|
|
}
|
|
else
|
|
{
|
|
Con_Warning ("anisotropic filtering locked by driver. Current driver setting is %f\n", test1);
|
|
}
|
|
|
|
//get max value either way, so the menu and stuff know it
|
|
glGetFloatv (GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max_anisotropy);
|
|
if (gl_max_anisotropy < 2)
|
|
{
|
|
gl_anisotropy_able = false;
|
|
gl_max_anisotropy = 1;
|
|
Con_Warning ("anisotropic filtering broken: disabled\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
gl_max_anisotropy = 1;
|
|
Con_Warning ("texture_filter_anisotropic not supported\n");
|
|
}
|
|
|
|
// texture_non_power_of_two
|
|
//
|
|
if (COM_CheckParm("-notexturenpot"))
|
|
Con_Warning ("texture_non_power_of_two disabled at command line\n");
|
|
else if (GL_ParseExtensionList(gl_extensions, "GL_ARB_texture_non_power_of_two"))
|
|
{
|
|
Con_Printf("FOUND: GL_ARB_texture_non_power_of_two\n");
|
|
gl_texture_NPOT = true;
|
|
}
|
|
else
|
|
{
|
|
Con_Warning ("texture_non_power_of_two not supported\n");
|
|
}
|
|
}
|
|
|
|
/*
|
|
===============
|
|
GL_SetupState -- johnfitz
|
|
|
|
does all the stuff from GL_Init that needs to be done every time a new GL render context is created
|
|
===============
|
|
*/
|
|
static void GL_SetupState (void)
|
|
{
|
|
glClearColor (0.15,0.15,0.15,0); //johnfitz -- originally 1,0,0,0
|
|
glCullFace(GL_BACK); //johnfitz -- glquake used CCW with backwards culling -- let's do it right
|
|
glFrontFace(GL_CW); //johnfitz -- glquake used CCW with backwards culling -- let's do it right
|
|
glEnable(GL_TEXTURE_2D);
|
|
glEnable(GL_ALPHA_TEST);
|
|
glAlphaFunc(GL_GREATER, 0.666);
|
|
glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
|
|
glShadeModel (GL_FLAT);
|
|
glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); //johnfitz
|
|
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
glDepthRange (0, 1); //johnfitz -- moved here becuase gl_ztrick is gone.
|
|
glDepthFunc (GL_LEQUAL); //johnfitz -- moved here becuase gl_ztrick is gone.
|
|
}
|
|
|
|
/*
|
|
===============
|
|
GL_Init
|
|
===============
|
|
*/
|
|
static void GL_Init (void)
|
|
{
|
|
gl_vendor = (const char *) glGetString (GL_VENDOR);
|
|
gl_renderer = (const char *) glGetString (GL_RENDERER);
|
|
gl_version = (const char *) glGetString (GL_VERSION);
|
|
gl_extensions = (const char *) glGetString (GL_EXTENSIONS);
|
|
|
|
if (gl_version == NULL || sscanf(gl_version, "%d.%d", &gl_version_major, &gl_version_minor) < 2)
|
|
{
|
|
gl_version_major = 0;
|
|
gl_version_minor = 0;
|
|
}
|
|
|
|
if (gl_extensions_nice != NULL)
|
|
Z_Free (gl_extensions_nice);
|
|
gl_extensions_nice = GL_MakeNiceExtensionsList (gl_extensions);
|
|
|
|
GL_CheckExtensions (); //johnfitz
|
|
|
|
//johnfitz -- intel video workarounds from Baker
|
|
if (!strcmp(gl_vendor, "Intel"))
|
|
{
|
|
Con_Printf ("Intel Display Adapter detected, enabling gl_clear\n");
|
|
Cbuf_AddText ("gl_clear 1");
|
|
}
|
|
//johnfitz
|
|
}
|
|
|
|
/*
|
|
=================
|
|
GL_BeginRendering -- sets values of glx, gly, glwidth, glheight
|
|
=================
|
|
*/
|
|
void GL_BeginRendering (int *x, int *y, int *width, int *height)
|
|
{
|
|
*x = *y = 0;
|
|
*width = vid.width;
|
|
*height = vid.height;
|
|
}
|
|
|
|
/*
|
|
=================
|
|
GL_EndRendering
|
|
=================
|
|
*/
|
|
void GL_EndRendering (void)
|
|
{
|
|
if (!scr_skipupdate)
|
|
{
|
|
#if defined(USE_SDL2)
|
|
SDL_GL_SwapWindow(draw_context);
|
|
#else
|
|
SDL_GL_SwapBuffers();
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
void VID_Shutdown (void)
|
|
{
|
|
if (vid_initialized)
|
|
{
|
|
VID_Gamma_Shutdown (); //johnfitz
|
|
|
|
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
|
draw_context = NULL;
|
|
#if defined(USE_SDL2)
|
|
gl_context = NULL;
|
|
#endif
|
|
PL_VID_Shutdown();
|
|
}
|
|
}
|
|
|
|
/*
|
|
===================================================================
|
|
|
|
MAIN WINDOW
|
|
|
|
===================================================================
|
|
*/
|
|
|
|
/*
|
|
================
|
|
ClearAllStates
|
|
================
|
|
*/
|
|
static void ClearAllStates (void)
|
|
{
|
|
Key_ClearStates ();
|
|
IN_ClearStates ();
|
|
}
|
|
|
|
|
|
//==========================================================================
|
|
//
|
|
// COMMANDS
|
|
//
|
|
//==========================================================================
|
|
|
|
/*
|
|
=================
|
|
VID_DescribeCurrentMode_f
|
|
=================
|
|
*/
|
|
static void VID_DescribeCurrentMode_f (void)
|
|
{
|
|
if (draw_context)
|
|
Con_Printf("%dx%dx%d %s\n",
|
|
VID_GetCurrentWidth(),
|
|
VID_GetCurrentHeight(),
|
|
VID_GetCurrentBPP(),
|
|
VID_GetFullscreen() ? "fullscreen" : "windowed");
|
|
}
|
|
|
|
/*
|
|
=================
|
|
VID_DescribeModes_f -- johnfitz -- changed formatting, and added refresh rates after each mode.
|
|
=================
|
|
*/
|
|
static void VID_DescribeModes_f (void)
|
|
{
|
|
int i;
|
|
int lastwidth, lastheight, lastbpp, count;
|
|
|
|
lastwidth = lastheight = lastbpp = count = 0;
|
|
|
|
for (i = 0; i < nummodes; i++)
|
|
{
|
|
if (lastwidth != modelist[i].width || lastheight != modelist[i].height || lastbpp != modelist[i].bpp)
|
|
{
|
|
if (count > 0)
|
|
Con_SafePrintf ("\n");
|
|
Con_SafePrintf (" %4i x %4i x %i", modelist[i].width, modelist[i].height, modelist[i].bpp);
|
|
lastwidth = modelist[i].width;
|
|
lastheight = modelist[i].height;
|
|
lastbpp = modelist[i].bpp;
|
|
count++;
|
|
}
|
|
}
|
|
Con_Printf ("\n%i modes\n", count);
|
|
}
|
|
|
|
/*
|
|
===================
|
|
VID_FSAA_f -- ericw -- warn that vid_fsaa requires engine restart
|
|
===================
|
|
*/
|
|
static void VID_FSAA_f (cvar_t *var)
|
|
{
|
|
// don't print the warning if vid_fsaa is set during startup
|
|
if (vid_initialized)
|
|
Con_Printf("%s %d requires engine restart to take effect\n", var->name, (int)var->value);
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
// INIT
|
|
//
|
|
//==========================================================================
|
|
|
|
/*
|
|
=================
|
|
VID_InitModelist
|
|
=================
|
|
*/
|
|
static void VID_InitModelist (void)
|
|
{
|
|
#if defined(USE_SDL2)
|
|
const int sdlmodes = SDL_GetNumDisplayModes(0);
|
|
int i;
|
|
|
|
nummodes = 0;
|
|
for (i = 0; i < sdlmodes; i++)
|
|
{
|
|
SDL_DisplayMode mode;
|
|
|
|
if (nummodes >= MAX_MODE_LIST)
|
|
break;
|
|
if (SDL_GetDisplayMode(0, i, &mode) == 0)
|
|
{
|
|
modelist[nummodes].width = mode.w;
|
|
modelist[nummodes].height = mode.h;
|
|
modelist[nummodes].bpp = SDL_BITSPERPIXEL(mode.format);
|
|
nummodes++;
|
|
}
|
|
}
|
|
#else /* !defined(USE_SDL2) */
|
|
SDL_PixelFormat format;
|
|
SDL_Rect **modes;
|
|
Uint32 flags;
|
|
int i, j, k, originalnummodes, existingmode;
|
|
int bpps[] = {16, 24, 32}; // enumerate >8 bpp modes
|
|
|
|
originalnummodes = nummodes = 0;
|
|
format.palette = NULL;
|
|
|
|
// enumerate fullscreen modes
|
|
flags = DEFAULT_SDL_FLAGS | SDL_FULLSCREEN;
|
|
for (i = 0; i < (int)(sizeof(bpps)/sizeof(bpps[0])); i++)
|
|
{
|
|
if (nummodes >= MAX_MODE_LIST)
|
|
break;
|
|
|
|
format.BitsPerPixel = bpps[i];
|
|
modes = SDL_ListModes(&format, flags);
|
|
|
|
if (modes == (SDL_Rect **)0 || modes == (SDL_Rect **)-1)
|
|
continue;
|
|
|
|
for (j = 0; modes[j]; j++)
|
|
{
|
|
if (modes[j]->w > MAXWIDTH || modes[j]->h > MAXHEIGHT || nummodes >= MAX_MODE_LIST)
|
|
continue;
|
|
|
|
modelist[nummodes].width = modes[j]->w;
|
|
modelist[nummodes].height = modes[j]->h;
|
|
modelist[nummodes].bpp = bpps[i];
|
|
|
|
for (k=originalnummodes, existingmode = 0 ; k < nummodes ; k++)
|
|
{
|
|
if ((modelist[nummodes].width == modelist[k].width) &&
|
|
(modelist[nummodes].height == modelist[k].height) &&
|
|
(modelist[nummodes].bpp == modelist[k].bpp))
|
|
{
|
|
existingmode = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!existingmode)
|
|
{
|
|
nummodes++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (nummodes == originalnummodes)
|
|
Con_SafePrintf ("No fullscreen DIB modes found\n");
|
|
#endif /* !defined(USE_SDL2) */
|
|
}
|
|
|
|
/*
|
|
===================
|
|
VID_Init
|
|
===================
|
|
*/
|
|
void VID_Init (void)
|
|
{
|
|
static char vid_center[] = "SDL_VIDEO_CENTERED=center";
|
|
int p, width, height, bpp, display_width, display_height, display_bpp;
|
|
qboolean fullscreen;
|
|
const char *read_vars[] = { "vid_fullscreen",
|
|
"vid_width",
|
|
"vid_height",
|
|
"vid_bpp",
|
|
"vid_vsync",
|
|
"vid_fsaa" };
|
|
#define num_readvars ( sizeof(read_vars)/sizeof(read_vars[0]) )
|
|
|
|
Cvar_RegisterVariable (&vid_fullscreen); //johnfitz
|
|
Cvar_RegisterVariable (&vid_width); //johnfitz
|
|
Cvar_RegisterVariable (&vid_height); //johnfitz
|
|
Cvar_RegisterVariable (&vid_bpp); //johnfitz
|
|
Cvar_RegisterVariable (&vid_vsync); //johnfitz
|
|
Cvar_RegisterVariable (&vid_fsaa); //QuakeSpasm
|
|
Cvar_SetCallback (&vid_fullscreen, VID_Changed_f);
|
|
Cvar_SetCallback (&vid_width, VID_Changed_f);
|
|
Cvar_SetCallback (&vid_height, VID_Changed_f);
|
|
Cvar_SetCallback (&vid_bpp, VID_Changed_f);
|
|
Cvar_SetCallback (&vid_vsync, VID_Changed_f);
|
|
Cvar_SetCallback (&vid_fsaa, VID_FSAA_f);
|
|
|
|
Cmd_AddCommand ("vid_unlock", VID_Unlock); //johnfitz
|
|
Cmd_AddCommand ("vid_restart", VID_Restart); //johnfitz
|
|
Cmd_AddCommand ("vid_test", VID_Test); //johnfitz
|
|
Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f);
|
|
Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f);
|
|
|
|
putenv (vid_center); /* SDL_putenv is problematic in versions <= 1.2.9 */
|
|
|
|
if (SDL_InitSubSystem(SDL_INIT_VIDEO) == -1)
|
|
Sys_Error("Could not initialize SDL Video");
|
|
|
|
#if defined(USE_SDL2)
|
|
{
|
|
SDL_DisplayMode mode;
|
|
if (SDL_GetDesktopDisplayMode(0, &mode) != 0)
|
|
Sys_Error("Could not get desktop display mode");
|
|
|
|
display_width = mode.w;
|
|
display_height = mode.h;
|
|
display_bpp = SDL_BITSPERPIXEL(mode.format);
|
|
}
|
|
#else
|
|
{
|
|
const SDL_VideoInfo *info = SDL_GetVideoInfo();
|
|
display_width = info->current_w;
|
|
display_height = info->current_h;
|
|
display_bpp = info->vfmt->BitsPerPixel;
|
|
}
|
|
#endif
|
|
|
|
Cvar_SetValueQuick (&vid_bpp, (float)display_bpp);
|
|
|
|
if (CFG_OpenConfig("config.cfg") == 0)
|
|
{
|
|
CFG_ReadCvars(read_vars, num_readvars);
|
|
CFG_CloseConfig();
|
|
}
|
|
CFG_ReadCvarOverrides(read_vars, num_readvars);
|
|
|
|
VID_InitModelist();
|
|
|
|
width = (int)vid_width.value;
|
|
height = (int)vid_height.value;
|
|
bpp = (int)vid_bpp.value;
|
|
fullscreen = (int)vid_fullscreen.value;
|
|
fsaa = (int)vid_fsaa.value;
|
|
|
|
if (COM_CheckParm("-current"))
|
|
{
|
|
width = display_width;
|
|
height = display_height;
|
|
bpp = display_bpp;
|
|
fullscreen = true;
|
|
}
|
|
else
|
|
{
|
|
p = COM_CheckParm("-width");
|
|
if (p && p < com_argc-1)
|
|
{
|
|
width = Q_atoi(com_argv[p+1]);
|
|
|
|
if(!COM_CheckParm("-height"))
|
|
height = width * 3 / 4;
|
|
}
|
|
|
|
p = COM_CheckParm("-height");
|
|
if (p && p < com_argc-1)
|
|
{
|
|
height = Q_atoi(com_argv[p+1]);
|
|
|
|
if(!COM_CheckParm("-width"))
|
|
width = height * 4 / 3;
|
|
}
|
|
|
|
p = COM_CheckParm("-bpp");
|
|
if (p && p < com_argc-1)
|
|
bpp = Q_atoi(com_argv[p+1]);
|
|
|
|
if (COM_CheckParm("-window") || COM_CheckParm("-w"))
|
|
fullscreen = false;
|
|
else if (COM_CheckParm("-fullscreen") || COM_CheckParm("-f"))
|
|
fullscreen = true;
|
|
}
|
|
|
|
p = COM_CheckParm ("-fsaa");
|
|
if (p && p < com_argc-1)
|
|
fsaa = atoi(com_argv[p+1]);
|
|
|
|
if (!VID_ValidMode(width, height, bpp, fullscreen))
|
|
{
|
|
width = (int)vid_width.value;
|
|
height = (int)vid_height.value;
|
|
bpp = (int)vid_bpp.value;
|
|
fullscreen = (int)vid_fullscreen.value;
|
|
}
|
|
|
|
if (!VID_ValidMode(width, height, bpp, fullscreen))
|
|
{
|
|
width = 640;
|
|
height = 480;
|
|
bpp = display_bpp;
|
|
fullscreen = false;
|
|
}
|
|
|
|
vid_initialized = true;
|
|
|
|
vid.maxwarpwidth = WARP_WIDTH;
|
|
vid.maxwarpheight = WARP_HEIGHT;
|
|
vid.colormap = host_colormap;
|
|
vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
|
|
|
|
// set window icon
|
|
PL_SetWindowIcon();
|
|
|
|
VID_SetMode (width, height, bpp, fullscreen);
|
|
|
|
GL_Init ();
|
|
GL_SetupState ();
|
|
Cmd_AddCommand ("gl_info", GL_Info_f); //johnfitz
|
|
|
|
//johnfitz -- removed code creating "glquake" subdirectory
|
|
|
|
vid_menucmdfn = VID_Menu_f; //johnfitz
|
|
vid_menudrawfn = VID_MenuDraw;
|
|
vid_menukeyfn = VID_MenuKey;
|
|
|
|
VID_Gamma_Init(); //johnfitz
|
|
VID_Menu_Init(); //johnfitz
|
|
|
|
//QuakeSpasm: current vid settings should override config file settings.
|
|
//so we have to lock the vid mode from now until after all config files are read.
|
|
vid_locked = true;
|
|
}
|
|
|
|
// new proc by S.A., called by alt-return key binding.
|
|
void VID_Toggle (void)
|
|
{
|
|
static qboolean vid_toggle_works = true;
|
|
qboolean toggleWorked;
|
|
|
|
S_ClearBuffer ();
|
|
|
|
if (!vid_toggle_works)
|
|
goto vrestart;
|
|
else if (gl_vbo_able)
|
|
{
|
|
// disabling the fast path because with SDL 1.2 it invalidates VBOs (using them
|
|
// causes a crash, sugesting that the fullscreen toggle created a new GL context,
|
|
// although texture objects remain valid for some reason).
|
|
//
|
|
// SDL2 does promise window resizes / fullscreen changes preserve the GL context,
|
|
// so we could use the fast path with SDL2. --ericw
|
|
vid_toggle_works = false;
|
|
goto vrestart;
|
|
}
|
|
|
|
#if defined(USE_SDL2)
|
|
toggleWorked = SDL_SetWindowFullscreen(draw_context, VID_GetFullscreen() ? 0 : SDL_WINDOW_FULLSCREEN) == 0;
|
|
#else
|
|
toggleWorked = SDL_WM_ToggleFullScreen(draw_context) == 1;
|
|
#endif
|
|
|
|
if (toggleWorked)
|
|
{
|
|
Sbar_Changed (); // Sbar seems to need refreshing
|
|
|
|
modestate = VID_GetFullscreen() ? MS_FULLSCREEN : MS_WINDOWED;
|
|
|
|
VID_SyncCvars();
|
|
|
|
// update mouse grab
|
|
if (key_dest == key_console || key_dest == key_menu)
|
|
{
|
|
if (modestate == MS_WINDOWED)
|
|
IN_Deactivate(true);
|
|
else if (modestate == MS_FULLSCREEN)
|
|
IN_Activate();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
vid_toggle_works = false;
|
|
Con_DPrintf ("SDL_WM_ToggleFullScreen failed, attempting VID_Restart\n");
|
|
vrestart:
|
|
Cvar_SetQuick (&vid_fullscreen, VID_GetFullscreen() ? "0" : "1");
|
|
Cbuf_AddText ("vid_restart\n");
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
VID_SyncCvars -- johnfitz -- set vid cvars to match current video mode
|
|
================
|
|
*/
|
|
void VID_SyncCvars (void)
|
|
{
|
|
if (draw_context)
|
|
{
|
|
Cvar_SetValueQuick (&vid_width, VID_GetCurrentWidth());
|
|
Cvar_SetValueQuick (&vid_height, VID_GetCurrentHeight());
|
|
Cvar_SetValueQuick (&vid_bpp, VID_GetCurrentBPP());
|
|
Cvar_SetQuick (&vid_fullscreen, VID_GetFullscreen() ? "1" : "0");
|
|
Cvar_SetQuick (&vid_vsync, VID_GetVSync() ? "1" : "0");
|
|
}
|
|
|
|
vid_changed = false;
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
// NEW VIDEO MENU -- johnfitz
|
|
//
|
|
//==========================================================================
|
|
|
|
enum {
|
|
VID_OPT_MODE,
|
|
VID_OPT_BPP,
|
|
VID_OPT_FULLSCREEN,
|
|
VID_OPT_VSYNC,
|
|
VID_OPT_TEST,
|
|
VID_OPT_APPLY,
|
|
VIDEO_OPTIONS_ITEMS
|
|
};
|
|
|
|
static int video_options_cursor = 0;
|
|
|
|
typedef struct {
|
|
int width,height;
|
|
} vid_menu_mode;
|
|
|
|
//TODO: replace these fixed-length arrays with hunk_allocated buffers
|
|
static vid_menu_mode vid_menu_modes[MAX_MODE_LIST];
|
|
static int vid_menu_nummodes = 0;
|
|
|
|
static int vid_menu_bpps[MAX_BPPS_LIST];
|
|
static int vid_menu_numbpps = 0;
|
|
|
|
/*
|
|
================
|
|
VID_Menu_Init
|
|
================
|
|
*/
|
|
static void VID_Menu_Init (void)
|
|
{
|
|
int i, j, h, w;
|
|
|
|
for (i = 0; i < nummodes; i++)
|
|
{
|
|
w = modelist[i].width;
|
|
h = modelist[i].height;
|
|
|
|
for (j = 0; j < vid_menu_nummodes; j++)
|
|
{
|
|
if (vid_menu_modes[j].width == w &&
|
|
vid_menu_modes[j].height == h)
|
|
break;
|
|
}
|
|
|
|
if (j == vid_menu_nummodes)
|
|
{
|
|
vid_menu_modes[j].width = w;
|
|
vid_menu_modes[j].height = h;
|
|
vid_menu_nummodes++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
VID_Menu_RebuildBppList
|
|
|
|
regenerates bpp list based on current vid_width and vid_height
|
|
================
|
|
*/
|
|
static void VID_Menu_RebuildBppList (void)
|
|
{
|
|
int i, j, b;
|
|
|
|
vid_menu_numbpps = 0;
|
|
|
|
for (i = 0; i < nummodes; i++)
|
|
{
|
|
if (vid_menu_numbpps >= MAX_BPPS_LIST)
|
|
break;
|
|
|
|
//bpp list is limited to bpps available with current width/height
|
|
if (modelist[i].width != vid_width.value ||
|
|
modelist[i].height != vid_height.value)
|
|
continue;
|
|
|
|
b = modelist[i].bpp;
|
|
|
|
for (j = 0; j < vid_menu_numbpps; j++)
|
|
{
|
|
if (vid_menu_bpps[j] == b)
|
|
break;
|
|
}
|
|
|
|
if (j == vid_menu_numbpps)
|
|
{
|
|
vid_menu_bpps[j] = b;
|
|
vid_menu_numbpps++;
|
|
}
|
|
}
|
|
|
|
//if there are no valid fullscreen bpps for this width/height, just pick one
|
|
if (vid_menu_numbpps == 0)
|
|
{
|
|
Cvar_SetValueQuick (&vid_bpp, (float)modelist[0].bpp);
|
|
return;
|
|
}
|
|
|
|
//if vid_bpp is not in the new list, change vid_bpp
|
|
for (i = 0; i < vid_menu_numbpps; i++)
|
|
if (vid_menu_bpps[i] == (int)(vid_bpp.value))
|
|
break;
|
|
|
|
if (i == vid_menu_numbpps)
|
|
Cvar_SetValueQuick (&vid_bpp, (float)vid_menu_bpps[0]);
|
|
}
|
|
|
|
/*
|
|
================
|
|
VID_Menu_ChooseNextMode
|
|
|
|
chooses next resolution in order, then updates vid_width and
|
|
vid_height cvars, then updates bpp and refreshrate lists
|
|
================
|
|
*/
|
|
static void VID_Menu_ChooseNextMode (int dir)
|
|
{
|
|
int i;
|
|
|
|
if (vid_menu_nummodes)
|
|
{
|
|
for (i = 0; i < vid_menu_nummodes; i++)
|
|
{
|
|
if (vid_menu_modes[i].width == vid_width.value &&
|
|
vid_menu_modes[i].height == vid_height.value)
|
|
break;
|
|
}
|
|
|
|
if (i == vid_menu_nummodes) //can't find it in list, so it must be a custom windowed res
|
|
{
|
|
i = 0;
|
|
}
|
|
else
|
|
{
|
|
i += dir;
|
|
if (i >= vid_menu_nummodes)
|
|
i = 0;
|
|
else if (i < 0)
|
|
i = vid_menu_nummodes-1;
|
|
}
|
|
|
|
Cvar_SetValueQuick (&vid_width, (float)vid_menu_modes[i].width);
|
|
Cvar_SetValueQuick (&vid_height, (float)vid_menu_modes[i].height);
|
|
VID_Menu_RebuildBppList ();
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
VID_Menu_ChooseNextBpp
|
|
|
|
chooses next bpp in order, then updates vid_bpp cvar
|
|
================
|
|
*/
|
|
static void VID_Menu_ChooseNextBpp (int dir)
|
|
{
|
|
int i;
|
|
|
|
if (vid_menu_numbpps)
|
|
{
|
|
for (i = 0; i < vid_menu_numbpps; i++)
|
|
{
|
|
if (vid_menu_bpps[i] == vid_bpp.value)
|
|
break;
|
|
}
|
|
|
|
if (i == vid_menu_numbpps) //can't find it in list
|
|
{
|
|
i = 0;
|
|
}
|
|
else
|
|
{
|
|
i += dir;
|
|
if (i >= vid_menu_numbpps)
|
|
i = 0;
|
|
else if (i < 0)
|
|
i = vid_menu_numbpps-1;
|
|
}
|
|
|
|
Cvar_SetValueQuick (&vid_bpp, (float)vid_menu_bpps[i]);
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
VID_MenuKey
|
|
================
|
|
*/
|
|
static void VID_MenuKey (int key)
|
|
{
|
|
switch (key)
|
|
{
|
|
case K_ESCAPE:
|
|
VID_SyncCvars (); //sync cvars before leaving menu. FIXME: there are other ways to leave menu
|
|
S_LocalSound ("misc/menu1.wav");
|
|
M_Menu_Options_f ();
|
|
break;
|
|
|
|
case K_UPARROW:
|
|
S_LocalSound ("misc/menu1.wav");
|
|
video_options_cursor--;
|
|
if (video_options_cursor < 0)
|
|
video_options_cursor = VIDEO_OPTIONS_ITEMS-1;
|
|
break;
|
|
|
|
case K_DOWNARROW:
|
|
S_LocalSound ("misc/menu1.wav");
|
|
video_options_cursor++;
|
|
if (video_options_cursor >= VIDEO_OPTIONS_ITEMS)
|
|
video_options_cursor = 0;
|
|
break;
|
|
|
|
case K_LEFTARROW:
|
|
S_LocalSound ("misc/menu3.wav");
|
|
switch (video_options_cursor)
|
|
{
|
|
case VID_OPT_MODE:
|
|
VID_Menu_ChooseNextMode (1);
|
|
break;
|
|
case VID_OPT_BPP:
|
|
VID_Menu_ChooseNextBpp (1);
|
|
break;
|
|
case VID_OPT_FULLSCREEN:
|
|
Cbuf_AddText ("toggle vid_fullscreen\n");
|
|
break;
|
|
case VID_OPT_VSYNC:
|
|
Cbuf_AddText ("toggle vid_vsync\n"); // kristian
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case K_RIGHTARROW:
|
|
S_LocalSound ("misc/menu3.wav");
|
|
switch (video_options_cursor)
|
|
{
|
|
case VID_OPT_MODE:
|
|
VID_Menu_ChooseNextMode (-1);
|
|
break;
|
|
case VID_OPT_BPP:
|
|
VID_Menu_ChooseNextBpp (-1);
|
|
break;
|
|
case VID_OPT_FULLSCREEN:
|
|
Cbuf_AddText ("toggle vid_fullscreen\n");
|
|
break;
|
|
case VID_OPT_VSYNC:
|
|
Cbuf_AddText ("toggle vid_vsync\n");
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case K_ENTER:
|
|
case K_KP_ENTER:
|
|
m_entersound = true;
|
|
switch (video_options_cursor)
|
|
{
|
|
case VID_OPT_MODE:
|
|
VID_Menu_ChooseNextMode (1);
|
|
break;
|
|
case VID_OPT_BPP:
|
|
VID_Menu_ChooseNextBpp (1);
|
|
break;
|
|
case VID_OPT_FULLSCREEN:
|
|
Cbuf_AddText ("toggle vid_fullscreen\n");
|
|
break;
|
|
case VID_OPT_VSYNC:
|
|
Cbuf_AddText ("toggle vid_vsync\n");
|
|
break;
|
|
case VID_OPT_TEST:
|
|
Cbuf_AddText ("vid_test\n");
|
|
break;
|
|
case VID_OPT_APPLY:
|
|
Cbuf_AddText ("vid_restart\n");
|
|
key_dest = key_game;
|
|
m_state = m_none;
|
|
IN_Activate();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
VID_MenuDraw
|
|
================
|
|
*/
|
|
static void VID_MenuDraw (void)
|
|
{
|
|
int i, y;
|
|
qpic_t *p;
|
|
const char *title;
|
|
|
|
y = 4;
|
|
|
|
// plaque
|
|
p = Draw_CachePic ("gfx/qplaque.lmp");
|
|
M_DrawTransPic (16, y, p);
|
|
|
|
//p = Draw_CachePic ("gfx/vidmodes.lmp");
|
|
p = Draw_CachePic ("gfx/p_option.lmp");
|
|
M_DrawPic ( (320-p->width)/2, y, p);
|
|
|
|
y += 28;
|
|
|
|
// title
|
|
title = "Video Options";
|
|
M_PrintWhite ((320-8*strlen(title))/2, y, title);
|
|
|
|
y += 16;
|
|
|
|
// options
|
|
for (i = 0; i < VIDEO_OPTIONS_ITEMS; i++)
|
|
{
|
|
switch (i)
|
|
{
|
|
case VID_OPT_MODE:
|
|
M_Print (16, y, " Video mode");
|
|
M_Print (184, y, va("%ix%i", (int)vid_width.value, (int)vid_height.value));
|
|
break;
|
|
case VID_OPT_BPP:
|
|
M_Print (16, y, " Color depth");
|
|
M_Print (184, y, va("%i", (int)vid_bpp.value));
|
|
break;
|
|
case VID_OPT_FULLSCREEN:
|
|
M_Print (16, y, " Fullscreen");
|
|
M_DrawCheckbox (184, y, (int)vid_fullscreen.value);
|
|
break;
|
|
case VID_OPT_VSYNC:
|
|
M_Print (16, y, " Vertical sync");
|
|
if (gl_swap_control)
|
|
M_DrawCheckbox (184, y, (int)vid_vsync.value);
|
|
else
|
|
M_Print (184, y, "N/A");
|
|
break;
|
|
case VID_OPT_TEST:
|
|
y += 8; //separate the test and apply items
|
|
M_Print (16, y, " Test changes");
|
|
break;
|
|
case VID_OPT_APPLY:
|
|
M_Print (16, y, " Apply changes");
|
|
break;
|
|
}
|
|
|
|
if (video_options_cursor == i)
|
|
M_DrawCharacter (168, y, 12+((int)(realtime*4)&1));
|
|
|
|
y += 8;
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
VID_Menu_f
|
|
================
|
|
*/
|
|
static void VID_Menu_f (void)
|
|
{
|
|
IN_Deactivate(modestate == MS_WINDOWED);
|
|
key_dest = key_menu;
|
|
m_state = m_video;
|
|
m_entersound = true;
|
|
|
|
//set all the cvars to match the current mode when entering the menu
|
|
VID_SyncCvars ();
|
|
|
|
//set up bpp and rate lists based on current cvars
|
|
VID_Menu_RebuildBppList ();
|
|
}
|
|
|