mirror of
https://github.com/Shpoike/Quakespasm.git
synced 2025-02-03 06:20:57 +00:00
5a2a7d96a7
* key.c (Key_ClearStates): Instead of clearing all key's down state and repeat count, run KeyEvent(k,false) keys in down state, which will already clear those states for them. This also helps getting rid of several actions bound to keypad keys. Minor cleanups. * gl_vidsdl.c (ClearAllStates): Removed code triggering every key with a release event, because we just changed Key_ClearStates() to do that for the necessary keys. * in_sdl.c: Minor cleanups. Made K_KP_5 to send '5' when not in game mode, regardless of the numlock status. Moved prev_gamekey to top level and call SDL_EnableUNICODE() correctly. git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@686 af15c1b1-3010-417e-b628-4374ebc0bcbd
1798 lines
41 KiB
C
1798 lines
41 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 Ozkan Sezer and Steven Atkinson
|
|
|
|
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"
|
|
#include "SDL.h"
|
|
|
|
#define MAX_MODE_LIST 600 //johnfitz -- was 30
|
|
#define VID_ROW_SIZE 3
|
|
#define WARP_WIDTH 320
|
|
#define WARP_HEIGHT 200
|
|
#define MAXWIDTH 10000
|
|
#define MAXHEIGHT 10000
|
|
#define BASEWIDTH 320
|
|
#define BASEHEIGHT 200
|
|
|
|
#define SDL_DEFAULT_FLAGS SDL_OPENGL
|
|
|
|
typedef struct {
|
|
modestate_t type;
|
|
int width;
|
|
int height;
|
|
int modenum;
|
|
int dib;
|
|
int fullscreen;
|
|
int bpp;
|
|
// int refreshrate; //johnfitz
|
|
int halfscreen;
|
|
char modedesc[17];
|
|
} vmode_t;
|
|
|
|
#if 0
|
|
typedef struct {
|
|
int width;
|
|
int height;
|
|
} lmode_t;
|
|
|
|
static lmode_t lowresmodes[] = {
|
|
{320, 200},
|
|
{320, 240},
|
|
{400, 300},
|
|
{512, 384},
|
|
};
|
|
#endif
|
|
|
|
static const char *gl_vendor;
|
|
static const char *gl_renderer;
|
|
static const char *gl_version;
|
|
static const char *gl_extensions;
|
|
|
|
static vmode_t modelist[MAX_MODE_LIST];
|
|
static int nummodes;
|
|
static vmode_t badmode;
|
|
|
|
static qboolean vid_initialized = false;
|
|
static qboolean windowed;
|
|
static qboolean vid_canalttab = false;
|
|
static qboolean vid_toggle_works = true;
|
|
|
|
static SDL_Surface *draw_context;
|
|
|
|
static qboolean vid_locked = false; //johnfitz
|
|
static qboolean vid_changed = false;
|
|
|
|
static int vid_modenum = NO_MODE;
|
|
static int vid_realmode;
|
|
static int vid_default = MODE_WINDOWED;
|
|
static qboolean fullsbardraw = 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 const char *VID_GetModeDescription (int mode);
|
|
static void ClearAllStates (void);
|
|
static void VID_UpdateWindowStatus (void);
|
|
static void GL_Init (void);
|
|
static void GL_SetupState (void); //johnfitz
|
|
|
|
viddef_t vid; // global video state
|
|
modestate_t modestate = MODE_WINDOWED;
|
|
qboolean scr_skipupdate;
|
|
|
|
qboolean isPermedia = false;
|
|
qboolean isIntelVideo = false; //johnfitz -- intel video workarounds from Baker
|
|
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
|
|
int gl_stencilbits; //johnfitz
|
|
|
|
PFNGLMULTITEXCOORD2FARBPROC GL_MTexCoord2fFunc = NULL; //johnfitz
|
|
PFNGLACTIVETEXTUREARBPROC GL_SelectTextureFunc = NULL; //johnfitz
|
|
|
|
//====================================
|
|
|
|
//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_refreshrate = {"vid_refreshrate", "60", CVAR_ARCHIVE};
|
|
static cvar_t vid_vsync = {"vid_vsync", "0", CVAR_ARCHIVE};
|
|
//johnfitz
|
|
|
|
cvar_t vid_gamma = {"gamma", "1", CVAR_ARCHIVE}; //johnfitz -- moved here from view.c
|
|
|
|
//==========================================================================
|
|
//
|
|
// HARDWARE GAMMA -- johnfitz
|
|
//
|
|
//==========================================================================
|
|
|
|
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];
|
|
|
|
static int vid_gammaworks;
|
|
|
|
/*
|
|
================
|
|
VID_Gamma_SetGamma -- apply gamma correction
|
|
================
|
|
*/
|
|
static void VID_Gamma_SetGamma (void)
|
|
{
|
|
if (draw_context && vid_gammaworks)
|
|
{
|
|
if (SDL_SetGammaRamp(&vid_gamma_red[0], &vid_gamma_green[0], &vid_gamma_blue[0]) == -1)
|
|
Con_Printf ("VID_Gamma_SetGamma: failed on SDL_SetGammaRamp\n");
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
VID_Gamma_Restore -- restore system gamma
|
|
================
|
|
*/
|
|
static void VID_Gamma_Restore (void)
|
|
{
|
|
if (draw_context && vid_gammaworks)
|
|
{
|
|
if (SDL_SetGammaRamp(&vid_sysgamma_red[0], &vid_sysgamma_green[0], &vid_sysgamma_blue[0]) == -1)
|
|
Con_Printf ("VID_Gamma_Restore: failed on SDL_SetGammaRamp\n");
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
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)
|
|
{
|
|
static float oldgamma;
|
|
int i;
|
|
|
|
if (vid_gamma.value == oldgamma)
|
|
return;
|
|
|
|
oldgamma = vid_gamma.value;
|
|
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
vid_gamma_red[i] =
|
|
CLAMP(0, (int) (255 * pow ((i+0.5)/255.5, vid_gamma.value) + 0.5), 255) << 8;
|
|
vid_gamma_green[i] = vid_gamma_red[i];
|
|
vid_gamma_blue[i] = vid_gamma_red[i];
|
|
}
|
|
|
|
VID_Gamma_SetGamma ();
|
|
}
|
|
|
|
/*
|
|
================
|
|
VID_Gamma_Init -- call on init
|
|
================
|
|
*/
|
|
static void VID_Gamma_Init (void)
|
|
{
|
|
vid_gammaworks = false;
|
|
|
|
if (SDL_GetGammaRamp (&vid_sysgamma_red[0], &vid_sysgamma_green[0], &vid_sysgamma_blue[0]) != -1)
|
|
vid_gammaworks = true;
|
|
|
|
Cvar_RegisterVariable (&vid_gamma);
|
|
Cvar_SetCallback (&vid_gamma, VID_Gamma_f);
|
|
}
|
|
|
|
/*
|
|
================
|
|
VID_SetMode
|
|
================
|
|
*/
|
|
static int VID_SetMode (int modenum)
|
|
{
|
|
int temp;
|
|
Uint32 flags = SDL_DEFAULT_FLAGS;
|
|
char caption[50];
|
|
|
|
// TODO: check if video mode is supported using SDL_VideoModeOk
|
|
if ((windowed && (modenum != 0)) ||
|
|
(!windowed && (modenum < 1)) ||
|
|
(!windowed && (modenum >= nummodes)))
|
|
{
|
|
Sys_Error ("Bad video mode\n");
|
|
}
|
|
|
|
// 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 ();
|
|
|
|
// set vertical sync
|
|
if (gl_swap_control)
|
|
{
|
|
if (SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, (vid_vsync.value) ? 1 : 0) == -1)
|
|
Con_Printf ("Unable to set swap control\n");
|
|
}
|
|
|
|
if (modelist[modenum].type == MODE_WINDOWED)
|
|
{
|
|
modestate = MODE_WINDOWED;
|
|
}
|
|
else if (modelist[modenum].type == MODE_FULLSCREEN_DEFAULT)
|
|
{
|
|
flags |= SDL_FULLSCREEN;
|
|
modestate = MODE_FULLSCREEN_DEFAULT;
|
|
}
|
|
else
|
|
{
|
|
Sys_Error ("VID_SetMode: Bad mode type in modelist");
|
|
}
|
|
|
|
draw_context = SDL_SetVideoMode(modelist[modenum].width,
|
|
modelist[modenum].height,
|
|
modelist[modenum].bpp, flags);
|
|
if (!draw_context)
|
|
{
|
|
Sys_Error ("Couldn't set video mode");
|
|
}
|
|
|
|
sprintf(caption, "QuakeSpasm %1.2f.%d", (float)FITZQUAKE_VERSION, QUAKESPASM_VER_PATCH);
|
|
SDL_WM_SetCaption(caption, caption);
|
|
|
|
vid.width = modelist[modenum].width;
|
|
vid.height = modelist[modenum].height;
|
|
vid.conwidth = vid.width & 0xFFFFFFF8;
|
|
vid.conheight = vid.conwidth * vid.height / vid.width;
|
|
vid.numpages = 2;
|
|
vid.type = modelist[modenum].type;
|
|
|
|
VID_UpdateWindowStatus ();
|
|
|
|
CDAudio_Resume ();
|
|
BGM_Resume ();
|
|
scr_disabled_for_loading = temp;
|
|
|
|
vid_modenum = modenum;
|
|
|
|
// fix the leftover Alt from any Alt-Tab or the like that switched us away
|
|
ClearAllStates ();
|
|
|
|
Con_SafePrintf ("Video mode %s initialized\n", VID_GetModeDescription (vid_modenum));
|
|
|
|
vid.recalc_refdef = 1;
|
|
|
|
// with SDL, this needs to be done every time the render context is recreated, so I moved it here
|
|
TexMgr_ReloadImages ();
|
|
GL_SetupState ();
|
|
|
|
// 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 i;
|
|
|
|
if (vid_locked || !vid_changed)
|
|
return;
|
|
|
|
//
|
|
// decide which mode to set
|
|
//
|
|
if (vid_fullscreen.value)
|
|
{
|
|
for (i = 1; i < nummodes; i++)
|
|
{
|
|
if (modelist[i].width == (int)vid_width.value &&
|
|
modelist[i].height == (int)vid_height.value &&
|
|
modelist[i].bpp == (int)vid_bpp.value)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i == nummodes)
|
|
{
|
|
Con_Printf ("%dx%dx%d is not a valid fullscreen mode\n",
|
|
(int)vid_width.value,
|
|
(int)vid_height.value,
|
|
(int)vid_bpp.value);
|
|
return;
|
|
}
|
|
|
|
windowed = false;
|
|
vid_default = i;
|
|
}
|
|
else //not fullscreen
|
|
{
|
|
if (vid_width.value < 320)
|
|
{
|
|
Con_Printf ("Window width can't be less than 320\n");
|
|
return;
|
|
}
|
|
|
|
if (vid_height.value < 200)
|
|
{
|
|
Con_Printf ("Window height can't be less than 200\n");
|
|
return;
|
|
}
|
|
|
|
modelist[0].width = (int)vid_width.value;
|
|
modelist[0].height = (int)vid_height.value;
|
|
sprintf (modelist[0].modedesc, "%dx%dx%d",
|
|
modelist[0].width,
|
|
modelist[0].height,
|
|
modelist[0].bpp);
|
|
|
|
windowed = true;
|
|
vid_default = 0;
|
|
}
|
|
//
|
|
// set new mode
|
|
//
|
|
VID_SetMode (vid_default);
|
|
|
|
vid_canalttab = true;
|
|
|
|
//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
|
|
//
|
|
Cvar_SetValueQuick (&vid_width, modelist[vid_default].width);
|
|
Cvar_SetValueQuick (&vid_height, modelist[vid_default].height);
|
|
Cvar_SetValueQuick (&vid_bpp, modelist[vid_default].bpp);
|
|
Cvar_SetQuick (&vid_fullscreen, (windowed) ? "0" : "1");
|
|
}
|
|
|
|
/*
|
|
================
|
|
VID_Test -- johnfitz -- like vid_restart, but asks for confirmation after switching modes
|
|
================
|
|
*/
|
|
static void VID_Test (void)
|
|
{
|
|
vmode_t oldmode;
|
|
|
|
if (vid_locked || !vid_changed)
|
|
return;
|
|
//
|
|
// now try the switch
|
|
//
|
|
oldmode = modelist[vid_default];
|
|
|
|
VID_Restart ();
|
|
SCR_UpdateScreen ();
|
|
|
|
//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, oldmode.width);
|
|
Cvar_SetValueQuick (&vid_height, oldmode.height);
|
|
Cvar_SetValueQuick (&vid_bpp, oldmode.bpp);
|
|
Cvar_SetQuick (&vid_fullscreen, (oldmode.type == MODE_WINDOWED) ? "0" : "1");
|
|
VID_Restart ();
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
VID_Unlock -- johnfitz
|
|
================
|
|
*/
|
|
static void VID_Unlock (void)
|
|
{
|
|
vid_locked = false;
|
|
|
|
//sync up cvars in case they were changed during the lock
|
|
Cvar_SetValueQuick (&vid_width, modelist[vid_default].width);
|
|
Cvar_SetValueQuick (&vid_height, modelist[vid_default].height);
|
|
Cvar_SetValueQuick (&vid_bpp, modelist[vid_default].bpp);
|
|
Cvar_SetQuick (&vid_fullscreen, (windowed) ? "0" : "1");
|
|
}
|
|
|
|
/*
|
|
================
|
|
VID_UpdateWindowStatus
|
|
================
|
|
*/
|
|
static void VID_UpdateWindowStatus (void)
|
|
{
|
|
// IN_UpdateClipCursor ();
|
|
}
|
|
|
|
//==============================================================================
|
|
//
|
|
// OPENGL STUFF
|
|
//
|
|
//==============================================================================
|
|
|
|
/*
|
|
===============
|
|
GL_MakeNiceExtensionsList -- johnfitz
|
|
===============
|
|
*/
|
|
static char *GL_MakeNiceExtensionsList (const char *in)
|
|
{
|
|
char *copy, *token, *out;
|
|
int i, count;
|
|
|
|
//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)
|
|
{
|
|
static char *gl_extensions_nice = NULL;
|
|
|
|
if (!gl_extensions_nice)
|
|
gl_extensions_nice = GL_MakeNiceExtensionsList (gl_extensions);
|
|
|
|
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 -- johnfitz
|
|
===============
|
|
*/
|
|
static void GL_CheckExtensions (void)
|
|
{
|
|
int swap_control;
|
|
|
|
//
|
|
// multitexture
|
|
//
|
|
if (COM_CheckParm("-nomtex"))
|
|
Con_Warning ("Mutitexture disabled at command line\n");
|
|
else if (strstr(gl_extensions, "GL_ARB_multitexture"))
|
|
{
|
|
GL_MTexCoord2fFunc = (PFNGLMULTITEXCOORD2FARBPROC) SDL_GL_GetProcAddress("glMultiTexCoord2fARB");
|
|
GL_SelectTextureFunc = (PFNGLACTIVETEXTUREARBPROC) SDL_GL_GetProcAddress("glActiveTextureARB");
|
|
if (GL_MTexCoord2fFunc && GL_SelectTextureFunc)
|
|
{
|
|
Con_Printf("FOUND: ARB_multitexture\n");
|
|
TEXTURE0 = GL_TEXTURE0_ARB;
|
|
TEXTURE1 = GL_TEXTURE1_ARB;
|
|
gl_mtexable = true;
|
|
}
|
|
else
|
|
{
|
|
Con_Warning ("Couldn't link to multitexture functions\n");
|
|
}
|
|
}
|
|
else if (strstr(gl_extensions, "GL_SGIS_multitexture"))
|
|
{
|
|
GL_MTexCoord2fFunc = (PFNGLMULTITEXCOORD2FARBPROC) SDL_GL_GetProcAddress("glMTexCoord2fSGIS");
|
|
GL_SelectTextureFunc = (PFNGLACTIVETEXTUREARBPROC) SDL_GL_GetProcAddress("glSelectTextureSGIS");
|
|
if (GL_MTexCoord2fFunc && GL_SelectTextureFunc)
|
|
{
|
|
Con_Printf("FOUND: SGIS_multitexture\n");
|
|
TEXTURE0 = TEXTURE0_SGIS;
|
|
TEXTURE1 = TEXTURE1_SGIS;
|
|
gl_mtexable = true;
|
|
}
|
|
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 (strstr(gl_extensions, "GL_ARB_texture_env_combine"))
|
|
{
|
|
Con_Printf("FOUND: ARB_texture_env_combine\n");
|
|
gl_texture_env_combine = true;
|
|
}
|
|
else if (strstr(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 (strstr(gl_extensions, "GL_ARB_texture_env_add"))
|
|
{
|
|
Con_Printf("FOUND: ARB_texture_env_add\n");
|
|
gl_texture_env_add = true;
|
|
}
|
|
else if (strstr(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 (strstr(gl_extensions, "GL_EXT_swap_control"))
|
|
{
|
|
if (SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 0) == -1)
|
|
{
|
|
Con_Warning ("vertical sync not supported (SDL_GL_SetAttribute failed)\n");
|
|
}
|
|
else
|
|
{
|
|
if (SDL_GL_GetAttribute(SDL_GL_SWAP_CONTROL, &swap_control) == -1)
|
|
{
|
|
Con_Warning ("vertical sync not supported (SDL_GL_GetAttribute failed). Make sure you don't have vertical sync disabled in your driver settings.\n");
|
|
}
|
|
else if (swap_control == -1)
|
|
{
|
|
// TODO: check if this is correct - I don't know what SDL returns if vertical sync is disabled
|
|
Con_Warning ("vertical sync not supported (swap interval is -1.) Make sure you don't have vertical sync disabled in your driver settings.\n");
|
|
}
|
|
else
|
|
{
|
|
Con_Printf("FOUND: GL_EXT_swap_control\n");
|
|
gl_swap_control = true;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Con_Warning ("vertical sync not supported (extension not found)\n");
|
|
}
|
|
|
|
//
|
|
// anisotropic filtering
|
|
//
|
|
if (strstr(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");
|
|
}
|
|
}
|
|
|
|
/*
|
|
===============
|
|
GL_SetupState -- johnfitz
|
|
|
|
does all the stuff from GL_Init that needs to be done every time a new GL render context is created
|
|
GL_Init will still do the stuff that only needs to be done once
|
|
===============
|
|
*/
|
|
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);
|
|
|
|
GL_CheckExtensions (); //johnfitz
|
|
|
|
Cmd_AddCommand ("gl_info", GL_Info_f); //johnfitz
|
|
|
|
Cvar_RegisterVariable (&vid_vsync); //johnfitz
|
|
if (gl_swap_control)
|
|
Cvar_SetCallback (&vid_vsync, VID_Changed_f);
|
|
|
|
if (SDL_strncasecmp(gl_renderer,"PowerVR",7)==0)
|
|
fullsbardraw = true;
|
|
if (SDL_strncasecmp(gl_renderer,"Permedia",8)==0)
|
|
isPermedia = true;
|
|
//johnfitz -- intel video workarounds from Baker
|
|
if (!strcmp(gl_vendor, "Intel"))
|
|
{
|
|
Con_Printf ("Intel Display Adapter detected\n");
|
|
isIntelVideo = true;
|
|
}
|
|
//johnfitz
|
|
|
|
#if 0
|
|
//johnfitz -- confirm presence of stencil buffer
|
|
glGetIntegerv(GL_STENCIL_BITS, &gl_stencilbits);
|
|
if(!gl_stencilbits)
|
|
Con_Warning ("Could not create stencil buffer\n");
|
|
else
|
|
Con_Printf ("%i bit stencil buffer\n", gl_stencilbits);
|
|
#endif
|
|
|
|
GL_SetupState (); //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)
|
|
SDL_GL_SwapBuffers();
|
|
|
|
if (fullsbardraw)
|
|
Sbar_Changed();
|
|
}
|
|
|
|
|
|
void VID_Shutdown (void)
|
|
{
|
|
if (vid_initialized)
|
|
{
|
|
vid_canalttab = false;
|
|
VID_Gamma_Shutdown (); //johnfitz
|
|
|
|
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
|
draw_context = NULL;
|
|
|
|
PL_VID_Shutdown();
|
|
}
|
|
}
|
|
|
|
//==========================================================================
|
|
|
|
/*
|
|
===================================================================
|
|
|
|
MAIN WINDOW
|
|
|
|
===================================================================
|
|
*/
|
|
|
|
/*
|
|
================
|
|
ClearAllStates
|
|
================
|
|
*/
|
|
static void ClearAllStates (void)
|
|
{
|
|
Key_ClearStates ();
|
|
IN_ClearStates ();
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
//
|
|
// COMMANDS
|
|
//
|
|
//==========================================================================
|
|
|
|
/*
|
|
=================
|
|
VID_NumModes
|
|
=================
|
|
*/
|
|
static int VID_NumModes (void)
|
|
{
|
|
return nummodes;
|
|
}
|
|
|
|
|
|
/*
|
|
=================
|
|
VID_GetModePtr
|
|
=================
|
|
*/
|
|
static vmode_t *VID_GetModePtr (int modenum)
|
|
{
|
|
if ((modenum >= 0) && (modenum < nummodes))
|
|
return &modelist[modenum];
|
|
else
|
|
return &badmode;
|
|
}
|
|
|
|
|
|
/*
|
|
=================
|
|
VID_GetModeDescription
|
|
=================
|
|
*/
|
|
static const char *VID_GetModeDescription (int mode)
|
|
{
|
|
const char *pinfo;
|
|
vmode_t *pv;
|
|
|
|
if ((mode < 0) || (mode >= nummodes))
|
|
return NULL;
|
|
|
|
pv = VID_GetModePtr (mode);
|
|
pinfo = pv->modedesc;
|
|
|
|
return pinfo;
|
|
}
|
|
|
|
// KJB: Added this to return the mode driver name in description for console
|
|
/*
|
|
=================
|
|
VID_GetExtModeDescription
|
|
=================
|
|
*/
|
|
static const char *VID_GetExtModeDescription (int mode)
|
|
{
|
|
static char pinfo[40];
|
|
vmode_t *pv;
|
|
|
|
if ((mode < 0) || (mode >= nummodes))
|
|
return NULL;
|
|
|
|
pv = VID_GetModePtr (mode);
|
|
if (modelist[mode].type == MODE_FULLSCREEN_DEFAULT)
|
|
{
|
|
sprintf(pinfo,"%s fullscreen", pv->modedesc);
|
|
}
|
|
else
|
|
{
|
|
if (modestate == MODE_WINDOWED)
|
|
sprintf(pinfo, "%s windowed", pv->modedesc);
|
|
else
|
|
sprintf(pinfo, "windowed");
|
|
}
|
|
|
|
return pinfo;
|
|
}
|
|
|
|
/*
|
|
=================
|
|
VID_DescribeCurrentMode_f
|
|
=================
|
|
*/
|
|
static void VID_DescribeCurrentMode_f (void)
|
|
{
|
|
Con_Printf ("%s\n", VID_GetExtModeDescription (vid_modenum));
|
|
}
|
|
|
|
/*
|
|
=================
|
|
VID_DescribeModes_f -- johnfitz -- changed formatting, and added refresh rates after each mode.
|
|
=================
|
|
*/
|
|
static void VID_DescribeModes_f (void)
|
|
{
|
|
vmode_t *pv;
|
|
int i, lnummodes;
|
|
int lastwidth, lastheight, lastbpp, count;
|
|
|
|
lnummodes = VID_NumModes ();
|
|
lastwidth = lastheight = lastbpp = count = 0;
|
|
|
|
for (i = 1; i < lnummodes; i++)
|
|
{
|
|
pv = VID_GetModePtr (i);
|
|
if (lastwidth != pv->width || lastheight != pv->height || lastbpp != pv->bpp)
|
|
{
|
|
if (count > 0)
|
|
Con_SafePrintf ("\n");
|
|
Con_SafePrintf (" %4i x %4i x %i", pv->width, pv->height, pv->bpp);
|
|
lastwidth = pv->width;
|
|
lastheight = pv->height;
|
|
lastbpp = pv->bpp;
|
|
count++;
|
|
}
|
|
}
|
|
Con_Printf ("\n%i modes\n", count);
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
// INIT
|
|
//
|
|
//==========================================================================
|
|
|
|
/*
|
|
=================
|
|
VID_InitDIB
|
|
=================
|
|
*/
|
|
static void VID_InitDIB (void)
|
|
{
|
|
const SDL_VideoInfo *info;
|
|
int i;
|
|
|
|
modelist[0].type = MODE_WINDOWED;
|
|
|
|
modelist[0].width = vid_width.value;
|
|
modelist[0].height = vid_height.value;
|
|
|
|
i = COM_CheckParm("-width");
|
|
if (i && i < com_argc-1)
|
|
{
|
|
modelist[0].width = Q_atoi(com_argv[i+1]);
|
|
|
|
if (!COM_CheckParm("-height"))
|
|
modelist[0].height = modelist[0].width * 3 / 4;
|
|
}
|
|
|
|
i = COM_CheckParm("-height");
|
|
if (i && i < com_argc-1)
|
|
{
|
|
modelist[0].height = Q_atoi(com_argv[i+1]);
|
|
|
|
if (!COM_CheckParm("-width"))
|
|
modelist[0].width = modelist[0].height * 4 / 3;
|
|
}
|
|
|
|
if (modelist[0].width < 320)
|
|
modelist[0].width = 320;
|
|
|
|
if (modelist[0].height < 200) //johnfitz -- was 240
|
|
modelist[0].height = 200; //johnfitz -- was 240
|
|
|
|
info = SDL_GetVideoInfo();
|
|
modelist[0].bpp = info->vfmt->BitsPerPixel;
|
|
|
|
sprintf (modelist[0].modedesc, "%dx%dx%d", //johnfitz -- added bpp
|
|
modelist[0].width,
|
|
modelist[0].height,
|
|
modelist[0].bpp); //johnfitz -- added bpp
|
|
|
|
modelist[0].modenum = MODE_WINDOWED;
|
|
modelist[0].dib = 1;
|
|
modelist[0].fullscreen = 0;
|
|
modelist[0].halfscreen = 0;
|
|
|
|
nummodes = 1;
|
|
}
|
|
|
|
/*
|
|
=================
|
|
VID_InitFullDIB
|
|
=================
|
|
*/
|
|
static void VID_InitFullDIB (void)
|
|
{
|
|
SDL_PixelFormat format;
|
|
SDL_Rect **modes;
|
|
Uint32 flags;
|
|
int i, j, k, modenum, originalnummodes, existingmode;
|
|
int bpps[3] = {16, 24, 32}; // enumerate >8 bpp modes
|
|
|
|
originalnummodes = nummodes;
|
|
modenum = 0;
|
|
format.palette = NULL;
|
|
|
|
// enumerate fullscreen modes
|
|
flags = SDL_DEFAULT_FLAGS | SDL_FULLSCREEN;
|
|
for (i = 0; i < 3; 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].type = MODE_FULLSCREEN_DEFAULT;
|
|
modelist[nummodes].width = modes[j]->w;
|
|
modelist[nummodes].height = modes[j]->h;
|
|
modelist[nummodes].modenum = 0;
|
|
modelist[nummodes].halfscreen = 0;
|
|
modelist[nummodes].dib = 1;
|
|
modelist[nummodes].fullscreen = 1;
|
|
modelist[nummodes].bpp = bpps[i];
|
|
|
|
sprintf (modelist[nummodes].modedesc, "%dx%dx%d",
|
|
modelist[nummodes].width,
|
|
modelist[nummodes].height,
|
|
modelist[nummodes].bpp);
|
|
|
|
// if the width is more than twice the height, reduce it by half because this
|
|
// is probably a dual-screen monitor
|
|
if (!COM_CheckParm("-noadjustaspect"))
|
|
{
|
|
if (modelist[nummodes].width > (modelist[nummodes].height << 1))
|
|
{
|
|
modelist[nummodes].width >>= 1;
|
|
modelist[nummodes].halfscreen = 1;
|
|
sprintf (modelist[nummodes].modedesc, "%dx%dx%d",
|
|
modelist[nummodes].width,
|
|
modelist[nummodes].height,
|
|
modelist[nummodes].bpp);
|
|
}
|
|
}
|
|
|
|
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++;
|
|
}
|
|
}
|
|
modenum++;
|
|
}
|
|
|
|
if (nummodes == originalnummodes)
|
|
Con_SafePrintf ("No fullscreen DIB modes found\n");
|
|
}
|
|
|
|
/*
|
|
===================
|
|
VID_Init
|
|
===================
|
|
*/
|
|
void VID_Init (void)
|
|
{
|
|
static char vid_center[] = "SDL_VIDEO_CENTERED=center";
|
|
const SDL_VideoInfo *info;
|
|
int i, existingmode;
|
|
int width, height, bpp;
|
|
int p;
|
|
const char *read_vars[] = { "vid_fullscreen",
|
|
"vid_width",
|
|
"vid_height",
|
|
"vid_bpp" };
|
|
#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_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_RegisterVariable (&vid_refreshrate); //johnfitz
|
|
|
|
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);
|
|
|
|
if (SDL_InitSubSystem(SDL_INIT_VIDEO) == -1)
|
|
Sys_Error("Could not initialize SDL Video");
|
|
|
|
putenv (vid_center); /* SDL_putenv is problematic in versions <= 1.2.9 */
|
|
|
|
if (CFG_OpenConfig("config.cfg") == 0)
|
|
{
|
|
CFG_ReadCvars(read_vars, num_readvars);
|
|
CFG_CloseConfig();
|
|
}
|
|
CFG_ReadCvarOverrides(read_vars, num_readvars);
|
|
|
|
VID_InitDIB();
|
|
VID_InitFullDIB();
|
|
|
|
if (COM_CheckParm("-window") || COM_CheckParm("-w"))
|
|
{
|
|
Cvar_SetQuick (&vid_fullscreen, "0");
|
|
}
|
|
else if (COM_CheckParm("-fullscreen") || COM_CheckParm("-f"))
|
|
{
|
|
Cvar_SetQuick (&vid_fullscreen, "1");
|
|
}
|
|
|
|
if (!vid_fullscreen.value)
|
|
{
|
|
windowed = true;
|
|
vid_default = MODE_WINDOWED;
|
|
}
|
|
else
|
|
{
|
|
windowed = false;
|
|
vid_default = NO_MODE;
|
|
|
|
width = vid_width.value;
|
|
height = vid_height.value;
|
|
bpp = vid_bpp.value;
|
|
|
|
if (COM_CheckParm("-current"))
|
|
{
|
|
info = SDL_GetVideoInfo();
|
|
width = info->current_w;
|
|
height = info->current_h;
|
|
bpp = info->vfmt->BitsPerPixel;
|
|
}
|
|
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 they want to force it, add the specified mode to the list
|
|
if (COM_CheckParm("-force") && (nummodes < MAX_MODE_LIST))
|
|
{
|
|
modelist[nummodes].type = MODE_FULLSCREEN_DEFAULT;
|
|
modelist[nummodes].width = width;
|
|
modelist[nummodes].height = height;
|
|
modelist[nummodes].modenum = 0;
|
|
modelist[nummodes].halfscreen = 0;
|
|
modelist[nummodes].dib = 1;
|
|
modelist[nummodes].fullscreen = 1;
|
|
modelist[nummodes].bpp = bpp;
|
|
sprintf (modelist[nummodes].modedesc, "%dx%dx%d",
|
|
modelist[nummodes].width,
|
|
modelist[nummodes].height,
|
|
modelist[nummodes].bpp);
|
|
|
|
for (i=nummodes, existingmode = 0 ; i<nummodes ; i++)
|
|
{
|
|
if ((modelist[nummodes].width == modelist[i].width) &&
|
|
(modelist[nummodes].height == modelist[i].height) &&
|
|
(modelist[nummodes].bpp == modelist[i].bpp))
|
|
{
|
|
existingmode = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!existingmode)
|
|
{
|
|
nummodes++;
|
|
}
|
|
}
|
|
|
|
// Try to find a mode with matching width, height and bpp
|
|
if (vid_default == NO_MODE)
|
|
{
|
|
for (i = 1; i < nummodes; i++)
|
|
{
|
|
if ((modelist[i].width == width) &&
|
|
(modelist[i].height == height) &&
|
|
(modelist[i].bpp == bpp))
|
|
{
|
|
vid_default = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Try to find a mode with matching width and height
|
|
if (vid_default == NO_MODE)
|
|
{
|
|
for (i = 1; i < nummodes; i++)
|
|
{
|
|
if ((modelist[i].width == width) &&
|
|
(modelist[i].height == height))
|
|
{
|
|
vid_default = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Try to find a mode with matching width
|
|
if (vid_default == NO_MODE)
|
|
{
|
|
for (i = 1; i < nummodes; i++)
|
|
{
|
|
if (modelist[i].width == width)
|
|
{
|
|
vid_default = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Still no luck? Default to windowed mode
|
|
if (vid_default == NO_MODE)
|
|
{
|
|
Cvar_SetQuick (&vid_fullscreen, "0");
|
|
windowed = true;
|
|
vid_default = MODE_WINDOWED;
|
|
}
|
|
}
|
|
|
|
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 (vid_default);
|
|
|
|
GL_Init ();
|
|
|
|
//johnfitz -- removed code creating "glquake" subdirectory
|
|
|
|
vid_realmode = vid_modenum;
|
|
|
|
vid_menucmdfn = VID_Menu_f; //johnfitz
|
|
vid_menudrawfn = VID_MenuDraw;
|
|
vid_menukeyfn = VID_MenuKey;
|
|
|
|
strcpy (badmode.modedesc, "Bad mode");
|
|
vid_canalttab = true;
|
|
|
|
if (COM_CheckParm("-fullsbar"))
|
|
fullsbardraw = true;
|
|
|
|
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)
|
|
{
|
|
S_ClearBuffer ();
|
|
|
|
if (!vid_toggle_works)
|
|
goto vrestart;
|
|
if (SDL_WM_ToggleFullScreen(draw_context) == 1)
|
|
{
|
|
qboolean was_changed = vid_changed;
|
|
|
|
Sbar_Changed (); // Sbar seems to need refreshing
|
|
windowed = !windowed;
|
|
if (vid.type == MODE_FULLSCREEN_DEFAULT)
|
|
vid.type = MODE_WINDOWED;
|
|
else
|
|
vid.type = MODE_FULLSCREEN_DEFAULT;
|
|
|
|
// since we succeeded, ignore the vid_fullscreen
|
|
// callback function setting vid_changed to true.
|
|
was_changed = vid_changed;
|
|
Cvar_SetQuick (&vid_fullscreen, vid_fullscreen.value ? "0" : "1");
|
|
vid_changed = was_changed;
|
|
}
|
|
else
|
|
{
|
|
vid_toggle_works = false;
|
|
Con_Printf ("ToggleFullScreen failed, attempting VID_Restart\n");
|
|
vrestart:
|
|
Cvar_SetQuick (&vid_fullscreen, vid_fullscreen.value ? "0" : "1");
|
|
Cbuf_AddText ("vid_restart\n");
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
VID_SyncCvars -- johnfitz -- set vid cvars to match current video mode
|
|
================
|
|
*/
|
|
void VID_SyncCvars (void)
|
|
{
|
|
int swap_control;
|
|
|
|
Cvar_SetValueQuick (&vid_width, modelist[vid_default].width);
|
|
Cvar_SetValueQuick (&vid_height, modelist[vid_default].height);
|
|
Cvar_SetValueQuick (&vid_bpp, modelist[vid_default].bpp);
|
|
Cvar_SetQuick (&vid_fullscreen, (windowed) ? "0" : "1");
|
|
|
|
if (SDL_GL_GetAttribute(SDL_GL_SWAP_CONTROL, &swap_control) == 0)
|
|
Cvar_SetQuick (&vid_vsync, (swap_control > 0)? "1" : "0");
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
// NEW VIDEO MENU -- johnfitz
|
|
//
|
|
//==========================================================================
|
|
|
|
#define VIDEO_OPTIONS_ITEMS 7
|
|
static int video_cursor_table[] = {48, 56, 64, 72, 80, 96, 104};
|
|
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[4];
|
|
static int vid_menu_numbpps = 0;
|
|
|
|
#if 0
|
|
static int vid_menu_rates[20];
|
|
static int vid_menu_numrates = 0;
|
|
#endif
|
|
|
|
/*
|
|
================
|
|
VID_Menu_Init
|
|
================
|
|
*/
|
|
static void VID_Menu_Init (void)
|
|
{
|
|
int i, j, h, w;
|
|
|
|
for (i = 1; i < nummodes; i++) //start i at mode 1 because 0 is windowed mode
|
|
{
|
|
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 = 1; i < nummodes; i++) //start i at mode 1 because 0 is windowed mode
|
|
{
|
|
//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, then updates refreshrate list
|
|
================
|
|
*/
|
|
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_Menu_ChooseNextRate
|
|
|
|
chooses next refresh rate in order, then updates vid_refreshrate cvar
|
|
================
|
|
*/
|
|
static void VID_Menu_ChooseNextRate (int dir)
|
|
{
|
|
#if 0 /* not implemented for SDL */
|
|
int i;
|
|
|
|
if (vid_menu_numrates)
|
|
{
|
|
for (i = 0; i < vid_menu_numrates; i++)
|
|
{
|
|
if (vid_menu_rates[i] == vid_refreshrate.value)
|
|
break;
|
|
}
|
|
|
|
if (i == vid_menu_numrates) //can't find it in list
|
|
{
|
|
i = 0;
|
|
}
|
|
else
|
|
{
|
|
i += dir;
|
|
if (i >= vid_menu_numrates)
|
|
i = 0;
|
|
else if (i < 0)
|
|
i = vid_menu_numrates-1;
|
|
}
|
|
|
|
Cvar_SetValueQuick (&vid_refreshrate, (float)vid_menu_rates[i]);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
================
|
|
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 0:
|
|
VID_Menu_ChooseNextMode (1);
|
|
break;
|
|
case 1:
|
|
VID_Menu_ChooseNextBpp (1);
|
|
break;
|
|
case 2:
|
|
VID_Menu_ChooseNextRate (1);
|
|
break;
|
|
case 3:
|
|
Cbuf_AddText ("toggle vid_fullscreen\n");
|
|
break;
|
|
case 4:
|
|
Cbuf_AddText ("toggle vid_vsync\n"); // kristian
|
|
break;
|
|
case 5:
|
|
case 6:
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case K_RIGHTARROW:
|
|
S_LocalSound ("misc/menu3.wav");
|
|
switch (video_options_cursor)
|
|
{
|
|
case 0:
|
|
VID_Menu_ChooseNextMode (-1);
|
|
break;
|
|
case 1:
|
|
VID_Menu_ChooseNextBpp (-1);
|
|
break;
|
|
case 2:
|
|
VID_Menu_ChooseNextRate (-1);
|
|
break;
|
|
case 3:
|
|
Cbuf_AddText ("toggle vid_fullscreen\n");
|
|
break;
|
|
case 4:
|
|
Cbuf_AddText ("toggle vid_vsync\n");
|
|
break;
|
|
case 5:
|
|
case 6:
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case K_ENTER:
|
|
m_entersound = true;
|
|
switch (video_options_cursor)
|
|
{
|
|
case 0:
|
|
VID_Menu_ChooseNextMode (1);
|
|
break;
|
|
case 1:
|
|
VID_Menu_ChooseNextBpp (1);
|
|
break;
|
|
case 2:
|
|
VID_Menu_ChooseNextRate (1);
|
|
break;
|
|
case 3:
|
|
Cbuf_AddText ("toggle vid_fullscreen\n");
|
|
break;
|
|
case 4:
|
|
Cbuf_AddText ("toggle vid_vsync\n");
|
|
break;
|
|
case 5:
|
|
Cbuf_AddText ("vid_test\n");
|
|
break;
|
|
case 6:
|
|
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 = 0;
|
|
qpic_t *p;
|
|
const char *title;
|
|
|
|
M_DrawTransPic (16, 4, Draw_CachePic ("gfx/qplaque.lmp"));
|
|
|
|
//p = Draw_CachePic ("gfx/vidmodes.lmp");
|
|
p = Draw_CachePic ("gfx/p_option.lmp");
|
|
M_DrawPic ( (320-p->width)/2, 4, p);
|
|
|
|
// title
|
|
title = "Video Options";
|
|
M_PrintWhite ((320-8*strlen(title))/2, 32, title);
|
|
|
|
// options
|
|
M_Print (16, video_cursor_table[i], " Video mode");
|
|
M_Print (184, video_cursor_table[i], va("%ix%i", (int)vid_width.value, (int)vid_height.value));
|
|
i++;
|
|
|
|
M_Print (16, video_cursor_table[i], " Color depth");
|
|
M_Print (184, video_cursor_table[i], va("%i", (int)vid_bpp.value));
|
|
i++;
|
|
|
|
M_Print (16, video_cursor_table[i], " Refresh rate");
|
|
// refresh rates not implemented -- kristian
|
|
// M_Print (184, video_cursor_table[i], va("%i Hz", (int)vid_refreshrate.value));
|
|
M_Print (184, video_cursor_table[i], "N/A");
|
|
i++;
|
|
|
|
M_Print (16, video_cursor_table[i], " Fullscreen");
|
|
M_DrawCheckbox (184, video_cursor_table[i], (int)vid_fullscreen.value);
|
|
i++;
|
|
|
|
// added vsync to the video menu -- kristian
|
|
M_Print (16, video_cursor_table[i], " Vertical Sync");
|
|
if (gl_swap_control)
|
|
M_DrawCheckbox (184, video_cursor_table[i], (int)vid_vsync.value);
|
|
else
|
|
M_Print (184, video_cursor_table[i], "N/A");
|
|
|
|
i++;
|
|
|
|
M_Print (16, video_cursor_table[i], " Test changes");
|
|
i++;
|
|
|
|
M_Print (16, video_cursor_table[i], " Apply changes");
|
|
|
|
// cursor
|
|
M_DrawCharacter (168, video_cursor_table[video_options_cursor], 12+((int)(realtime*4)&1));
|
|
|
|
// notes "345678901234567890123456789012345678"
|
|
// M_Print (16, 172, "Windowed modes always use the desk- ");
|
|
// M_Print (16, 180, "top color depth, and can never be ");
|
|
// M_Print (16, 188, "larger than the desktop resolution. ");
|
|
}
|
|
|
|
/*
|
|
================
|
|
VID_Menu_f
|
|
================
|
|
*/
|
|
static void VID_Menu_f (void)
|
|
{
|
|
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 ();
|
|
}
|
|
|