Inside3D!
     

Video Mode Change in (Windows) GLQuake

 
Post new topic   Reply to topic    Inside3d Forums Forum Index -> Programming Tutorials
View previous topic :: View next topic  
Author Message
Baker



Joined: 14 Mar 2006
Posts: 1538

PostPosted: Mon Dec 08, 2008 8:42 am    Post subject: Video Mode Change in (Windows) GLQuake Reply with quote




Downloads

1. Changed source files (5) (download)

heavy changes: gl_vidnt.c
very minor changes: host.c, menu.c, menu.h, vid.h

2. Example glquake.exe (download)

Due to the complexity of the changes in gl_vidnt.c you may be better off using a file comparison tool to assist like [free + gpl] WinMerge or another comparison tool (link) to assist adding this in to an engine rather than using the tutorial. Here are some WinMerge screenshots, but there are several file comparison tools that do a good job.

Back to top
View user's profile Send private message
Baker



Joined: 14 Mar 2006
Posts: 1538

PostPosted: Mon Dec 08, 2008 10:54 pm    Post subject: Reply with quote

Adding Video Mode Change To GLQuake

This ranks up there as one of the more complicated things to add to the GLQuake engine. As a result, not many have this but this number is now up at least 6: DarkPlaces, FTEQW, Fitzquake, ezQuake, Qrack, ProQuake 3.99 .. I'm not aware of any others but maybe some other actively developed engine has this or will have in the next version (MHQuake?).

This tutorial is going to be based mostly on the FitzQuake version of video mode [except we aren't going to allow bits-per-pixel mode switching] and partially on the Qrack version. Additionally, this is double initialization where GLQuake will start up and set the video mode possibly twice.

Quote:
Bits per pixel. That requires a lot more work, maybe some time in the future I'll add that into this tutorial but the reason is that you need to clear and reload the textures ... especially the 2D graphics ... and maybe some other fun stuff.


The Basics of What Needs Done

To support video mode switching, we'll need to restructure the fun things that need done once, to be done once. We'll need to restructure things that need done every time you do a mode change for that as well.

In addition, we'll be addressing 2 issues:

1. Increasing max video modes to 600 (was 30).
2. Because it is in this file, fixing the ALT-TAB problem where with some video cards you can gradually get the screen more and more offcenter.

And ...

3. We'll need a menu to control this.
4. We'll need to alter the writing of the cvars to config.

Due to the complexity, I'll upload the changed glquake source files too.

Begin:

Let's hit the easy files first before hitting the big dawg, gl_vidnt.c

1. vid.h

Quote:
Open vid.h and find "extern void (*vid_menukeyfn)(int key);" and add immediately after:

Code:
#ifdef GLQUAKE
extern void (*vid_menucmdfn)(void); //johnfitz
#endif



2. menu.c

Quote:
Locate this: Add the yellow and delete/cut the red text:

Quote:
void (*vid_menucmdfn)(void); //johnfitz
void (*vid_menudrawfn)(void);
void (*vid_menukeyfn)(int key);
enum {m_none, m_main, m_singleplayer, m_load, m_save, m_multiplayer, m_setup, m_net, m_options, m_video, m_keys, m_help, m_quit, m_serialconfig, m_modemconfig, m_lanconfig, m_gameoptions, m_search, m_slist} m_state;


We are moving m_state to menu.h.


3. menu.h

Quote:
Add this to the bottom of menu.h

Quote:
enum {m_none, m_main, m_singleplayer, m_load, m_save, m_multiplayer, m_setup, m_net, m_options, m_video, m_keys, m_help, m_quit, m_serialconfig, m_modemconfig, m_lanconfig, m_gameoptions, m_search, m_slist} m_state;


4. host.c

Quote:
In Host_WriteConfiguration add the yellow text:

Quote:
VID_SyncCvars (); //johnfitz -- write actual current mode to config file, in case cvars were messed with

Key_WriteBindings (f);
Cvar_WriteVariables (f);

fprintf (f, "vid_restart\n");


We need to refresh the vid_width, vid_height, etc. values before writing them to the config. We are hackily adding a vid_restart command to the end of config.cfg.

A better way would be to read the vid_width and vid_height values after reading the configuration file and checking to see if they changed. Maybe.


All the easy files have been done. All that remains is gl_vidnt.c.

Which we will do next time in 18 easy steps!
Back to top
View user's profile Send private message
Baker



Joined: 14 Mar 2006
Posts: 1538

PostPosted: Mon Dec 08, 2008 11:05 pm    Post subject: Reply with quote

gl_vidnt.c

5.1 Locate and make alike:

Quote:
#define MAX_MODE_LIST 600


30 video modes is too few on displays that support a lot of different width x height x bpp x refresh rate hz combinations.

5.2 Locate, add the yellow for refresh rate support:

Quote:
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;


5.3 Find the declaration of cvar_t vid_mode and add the yellow:

These are our supporting cvars and other variables that allow us do this and keep track of things:

Quote:
qboolean gl_mtexable = false;

qboolean video_options_disabled = false;

int desktop_bpp; // query this @ startup and when entering the video menu
void VID_Menu_Init (void); //johnfitz
void VID_Menu_f (void); //johnfitz

qboolean vid_locked = false; //johnfitz
int vid_current_bpp;//R00k

void GL_SetupState (void); //johnfitz

//====================================

//johnfitz -- new cvars
cvar_t vid_fullscreen = {"vid_fullscreen", "1", true};
cvar_t vid_width = {"vid_width", "640", true};
cvar_t vid_height = {"vid_height", "480", true};

int vid_bpp;
cvar_t vid_refreshrate = {"vid_refreshrate", "60", true};
//johnfitz



cvar_t vid_mode = {"vid_mode","0", false};
Back to top
View user's profile Send private message
Baker



Joined: 14 Mar 2006
Posts: 1538

PostPosted: Mon Dec 08, 2008 11:07 pm    Post subject: Reply with quote

5.4 In VID_SetWindowedMode, locate this:

Code:
   if (vid.conheight > modelist[modenum].height)
      vid.conheight = modelist[modenum].height;
   if (vid.conwidth > modelist[modenum].width)
      vid.conwidth = modelist[modenum].width;
   vid.width = vid.conwidth;
   vid.height = vid.conheight;


Replace with this so the console width and height change as needed on restart in windowed mode.

Code:
   //johnfitz -- stuff
   vid.width = modelist[modenum].width;
   vid.height = modelist[modenum].height;
   vid.conwidth = vid.width & 0xFFFFFFF8;
   vid.conheight = vid.conwidth * vid.height / vid.width;
   //johnfitz


5.5 VID_SetFullDIBMode, add the yellow to store refresh rate:

Quote:
gdevmode.dmPelsHeight = modelist[modenum].height;
gdevmode.dmDisplayFrequency = modelist[modenum].refreshrate; //johnfitz -- refreshrate
gdevmode.dmSize = sizeof (gdevmode);


5.6 VID_SetFullDIBMode (again!), comment old old console sizing stuff with /* --- */ and add the yellow. Console sizing again:

Quote:
/* if (vid.conheight > modelist[modenum].height)
vid.conheight = modelist[modenum].height;
if (vid.conwidth > modelist[modenum].width)
vid.conwidth = modelist[modenum].width; */
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;


5.7 VID_SetMode, locate and add the yellow. This restarts the mouse -- particularly important with -dinput command line parameter.

Quote:
VID_SetPalette (palette);

vid.recalc_refdef = 1;

//R00k mouse died on mode change
IN_StartupMouse ();


return true;
}


5.8 Above this:

Code:
/*
================
VID_UpdateWindowStatus
================
*/


Add our new supporting functions for VID_Restart, sync'ing the cvars, and our "VID_Test".

(Your VID_Test won't wait 5 seconds and revert like FitzQuake .. if you want that, borrow the changes to scr_modalmessage in FitzQuake to add a timeout option.)

Code:
/*
===================
VID_Restart -- johnfitz -- change video modes on the fly
===================
*/
void VID_SyncCvars (void);
//void VID_Conwidth_Reset (void);
void VID_Restart (void)
{
   HDC         hdc;
   HGLRC      hrc;
   int         i;
   qboolean   mode_changed = false;
   vmode_t      oldmode;

   if (vid_locked)
      return;

//
// check cvars against current mode
//
   if (vid_fullscreen.value)
   {
      if (modelist[vid_default].type == MS_WINDOWED)
         mode_changed = true;
      else if (modelist[vid_default].refreshrate != (int)vid_refreshrate.value)
         mode_changed = true;
   }
   else
      if (modelist[vid_default].type != MS_WINDOWED)
         mode_changed = true;

   if (modelist[vid_default].width != (int)vid_width.value ||
      modelist[vid_default].height != (int)vid_height.value)
      mode_changed = true;

   if (mode_changed)
   {
//
// decide which mode to set
//
      oldmode = modelist[vid_default];

      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 &&
               modelist[i].refreshrate == (int)vid_refreshrate.value)
            {
               break;
            }
         }

         if (i == nummodes)
         {
            Con_Printf ("%dx%dx%d %dHz is not a valid fullscreen mode\n",
                     (int)vid_width.value,
                     (int)vid_height.value,
                     (int)vid_bpp,
                     (int)vid_refreshrate.value);
            return;
         }

         windowed = false;
         vid_default = i;
      }
      else //not fullscreen
      {
         hdc = GetDC (NULL);
         if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
         {
            Con_Printf ("Can't run windowed on non-RGB desktop\n");
            ReleaseDC (NULL, hdc);
            return;
         }
         ReleaseDC (NULL, hdc);

         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 %dHz",
                modelist[0].width,
                modelist[0].height,
                modelist[0].bpp,
                modelist[0].refreshrate);

         windowed = true;
         vid_default = 0;
      }
//
// destroy current window
//
      hrc = wglGetCurrentContext();
      hdc = wglGetCurrentDC();
      wglMakeCurrent(NULL, NULL);

      vid_canalttab = false;

      if (hdc && dibwindow)
         ReleaseDC (dibwindow, hdc);
      if (modestate == MS_FULLDIB)
         ChangeDisplaySettings (NULL, 0);
      if (maindc && dibwindow)
         ReleaseDC (dibwindow, maindc);
      maindc = NULL;
      if (dibwindow)
         DestroyWindow (dibwindow);
//
// set new mode
//
      VID_SetMode (vid_default, host_basepal);
      maindc = GetDC(mainwindow);
      bSetupPixelFormat(maindc);

      // if bpp changes, recreate render context and reload textures
      if (modelist[vid_default].bpp != oldmode.bpp)
      {
         wglDeleteContext (hrc);
         hrc = wglCreateContext (maindc);
         if (!wglMakeCurrent (maindc, hrc))
            Sys_Error ("VID_Restart: wglMakeCurrent failed");
         
         GL_SetupState ();
      }
      else
         if (!wglMakeCurrent (maindc, hrc))
#if 1
         {
            char szBuf[80];
            LPVOID lpMsgBuf;
            DWORD dw = GetLastError();
            FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL );
            sprintf(szBuf, "VID_Restart: wglMakeCurrent failed with error %d: %s", dw, lpMsgBuf);
             Sys_Error (szBuf);
         }
#else
            Sys_Error ("VID_Restart: wglMakeCurrent failed");
#endif

      vid_canalttab = true;
   }

}

/*
================
VID_Test -- johnfitz -- like vid_restart, but asks for confirmation after switching modes
================
*/
void VID_Test (void)
{
   vmode_t oldmode;
   qboolean   mode_changed = false;

   if (vid_locked)
      return;
//
// check cvars against current mode
//
   if (vid_fullscreen.value)
   {
      if (modelist[vid_default].type == MS_WINDOWED)
         mode_changed = true;
/*      else if (modelist[vid_default].bpp != (int)vid_bpp.value)
         mode_changed = true; */
      else if (modelist[vid_default].refreshrate != (int)vid_refreshrate.value)
         mode_changed = true;
   }
   else
      if (modelist[vid_default].type != MS_WINDOWED)
         mode_changed = true;

   if (modelist[vid_default].width != (int)vid_width.value ||
      modelist[vid_default].height != (int)vid_height.value)
      mode_changed = true;

   if (!mode_changed)
      return;
//
// now try the switch
//
   oldmode = modelist[vid_default];

   VID_Restart ();

   //pop up confirmation dialoge
   if (!SCR_ModalMessage("Would you like to keep this\nvideo mode? (y/n)\n"))
   {
      //revert cvars and mode
      Cvar_Set ("vid_width", va("%i", oldmode.width));
      Cvar_Set ("vid_height", va("%i", oldmode.height));
      Cvar_Set ("vid_bpp", va("%i", oldmode.bpp));
      Cvar_Set ("vid_refreshrate", va("%i", oldmode.refreshrate));
      Cvar_Set ("vid_fullscreen", (oldmode.type == MS_WINDOWED) ? "0" : "1");
      VID_Restart ();
   }
}

/*
================
VID_Unlock -- johnfitz
================
*/
void VID_Unlock (void)
{
   vid_locked = false;

   //sync up cvars in case they were changed during the lock
   Cvar_Set ("vid_width", va("%i", modelist[vid_default].width));
   Cvar_Set ("vid_height", va("%i", modelist[vid_default].height));
   Cvar_Set ("vid_refreshrate", va("%i", modelist[vid_default].refreshrate));
   Cvar_Set ("vid_fullscreen", (windowed) ? "0" : "1");
}
Back to top
View user's profile Send private message
Baker



Joined: 14 Mar 2006
Posts: 1538

PostPosted: Mon Dec 08, 2008 11:20 pm    Post subject: Reply with quote

5.9 Now we need the GL initiation split into 2 pieces, the part that needs done once vs. the setup that needs to occur duriing any video mode switch.

So the Locate GL_Init, Find this and ....

Code:
/*
===============
GL_Init
===============
*/
void GL_Init (void)
{
   gl_vendor = glGetString (GL_VENDOR);
   Con_Printf ("GL_VENDOR: %s\n", gl_vendor);
   gl_renderer = glGetString (GL_RENDERER);
   Con_Printf ("GL_RENDERER: %s\n", gl_renderer);

   gl_version = glGetString (GL_VERSION);
   Con_Printf ("GL_VERSION: %s\n", gl_version);
   gl_extensions = glGetString (GL_EXTENSIONS);
   Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions);

//   Con_Printf ("%s %s\n", gl_renderer, gl_version);

    if (strnicmp(gl_renderer,"PowerVR",7)==0)
         fullsbardraw = true;

    if (strnicmp(gl_renderer,"Permedia",8)==0)
         isPermedia = true;

   CheckTextureExtensions ();
   CheckMultiTextureExtensions ();

   glClearColor (1,0,0,0);
   glCullFace(GL_FRONT);
   glEnable(GL_TEXTURE_2D);

   glEnable(GL_ALPHA_TEST);
   glAlphaFunc(GL_GREATER, 0.666);

   glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
   glShadeModel (GL_FLAT);

   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);

   glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

//   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

#if 0
   CheckArrayExtensions ();

   glEnable (GL_VERTEX_ARRAY_EXT);
   glEnable (GL_TEXTURE_COORD_ARRAY_EXT);
   glVertexPointerEXT (3, GL_FLOAT, 0, 0, &glv.x);
   glTexCoordPointerEXT (2, GL_FLOAT, 0, 0, &glv.s);
   glColorPointerEXT (3, GL_FLOAT, 0, 0, &glv.r);
#endif
}


And replace with this:

Code:
/*
===============
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
===============
*/
void GL_SetupState (void) {
   glClearColor (1,0,0,0);
   glCullFace(GL_FRONT);
   glEnable(GL_TEXTURE_2D);
   glEnable(GL_ALPHA_TEST);
   glAlphaFunc(GL_GREATER, 0.666);
   glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
   glShadeModel (GL_FLAT);
   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);
   glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
}

/*
===============
GL_Init
===============
*/
void GL_Init (void)
{
   gl_vendor = glGetString (GL_VENDOR);
   Con_Printf ("GL_VENDOR: %s\n", gl_vendor);
   gl_renderer = glGetString (GL_RENDERER);
   Con_Printf ("GL_RENDERER: %s\n", gl_renderer);

   gl_version = glGetString (GL_VERSION);
   Con_Printf ("GL_VERSION: %s\n", gl_version);
   gl_extensions = glGetString (GL_EXTENSIONS);
   Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions);

//   Con_Printf ("%s %s\n", gl_renderer, gl_version);

    if (strnicmp(gl_renderer,"PowerVR",7)==0)
         fullsbardraw = true;

    if (strnicmp(gl_renderer,"Permedia",8)==0)
         isPermedia = true;

   CheckTextureExtensions ();
   CheckMultiTextureExtensions ();


#if 0
   CheckArrayExtensions ();

   glEnable (GL_VERTEX_ARRAY_EXT);
   glEnable (GL_TEXTURE_COORD_ARRAY_EXT);
   glVertexPointerEXT (3, GL_FLOAT, 0, 0, &glv.x);
   glTexCoordPointerEXT (2, GL_FLOAT, 0, 0, &glv.s);
   glColorPointerEXT (3, GL_FLOAT, 0, 0, &glv.r);
#endif

   GL_SetupState (); //johnfitz
}


5.10 Find VID_InitDIB and add or match with the yellow:

Quote:
void VID_InitDIB (HINSTANCE hInstance)
{
DEVMODE devmode; //johnfitz
WNDCLASS wc;
HDC hdc;
int i;

/* Register the frame class */
wc.style = 0;
wc.lpfnWndProc = (WNDPROC)MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = 0;
wc.hCursor = LoadCursor (NULL,IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = 0;
wc.lpszClassName = "WinQuake";

if (!RegisterClass (&wc) )
Sys_Error ("Couldn't register window class");

modelist[0].type = MS_WINDOWED;

if (COM_CheckParm("-width"))
modelist[0].width = Q_atoi(com_argv[COM_CheckParm("-width")+1]);
else
modelist[0].width = 640;

if (modelist[0].width < 320)
modelist[0].width = 320;

if (COM_CheckParm("-height"))
modelist[0].height= Q_atoi(com_argv[COM_CheckParm("-height")+1]);
else
modelist[0].height = modelist[0].width * 240/320;

if (modelist[0].height < 200) //johnfitz -- was 240
modelist[0].height = 200; //johnfitz -- was 240

//johnfitz -- get desktop bit depth
hdc = GetDC(NULL);
modelist[0].bpp = desktop_bpp = GetDeviceCaps(hdc, BITSPIXEL);
ReleaseDC(NULL, hdc);
//johnfitz

//johnfitz -- get refreshrate
if (EnumDisplaySettings (NULL, ENUM_CURRENT_SETTINGS, &devmode))
modelist[0].refreshrate = devmode.dmDisplayFrequency;
//johnfitz

sprintf (modelist[0].modedesc, "%dx%dx%d %dHz", //johnfitz -- added bpp, refreshrate
modelist[0].width,
modelist[0].height,
modelist[0].bpp, //johnfitz -- added bpp
modelist[0].refreshrate); //johnfitz -- added refreshrate

modelist[0].modenum = MODE_WINDOWED;
modelist[0].dib = 1;
modelist[0].fullscreen = 0;
modelist[0].halfscreen = 0;
// modelist[0].bpp = 0; // Baker says <--- no! Keep same bpp!


nummodes = 1;
}


5.11 In "VID_InitFullDIB" add or change to the yellow:

This is to support our refreshrate hz.

Quote:
/*
=================
VID_InitFullDIB
=================
*/
void VID_InitFullDIB (HINSTANCE hInstance)
{
DEVMODE devmode;
int i, modenum, cmodes, originalnummodes, existingmode, numlowresmodes;
int j, bpp, done;
BOOL stat;

// enumerate >8 bpp modes
originalnummodes = nummodes;
modenum = 0;

do
{
stat = EnumDisplaySettings (NULL, modenum, &devmode);

if ((devmode.dmBitsPerPel >= 15) &&
(devmode.dmPelsWidth <= MAXWIDTH) &&
(devmode.dmPelsHeight <= MAXHEIGHT) &&
(nummodes < MAX_MODE_LIST))
{
devmode.dmFields = DM_BITSPERPEL |
DM_PELSWIDTH |
DM_PELSHEIGHT |
DM_DISPLAYFREQUENCY; //johnfitz -- refreshrate


if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) ==
DISP_CHANGE_SUCCESSFUL)
{
modelist[nummodes].type = MS_FULLDIB;
modelist[nummodes].width = devmode.dmPelsWidth;
modelist[nummodes].height = devmode.dmPelsHeight;
modelist[nummodes].modenum = 0;
modelist[nummodes].halfscreen = 0;
modelist[nummodes].dib = 1;
modelist[nummodes].fullscreen = 1;
modelist[nummodes].bpp = devmode.dmBitsPerPel;
modelist[nummodes].refreshrate = devmode.dmDisplayFrequency; //johnfitz -- refreshrate
sprintf (modelist[nummodes].modedesc, "%dx%dx%d %dHz", //johnfitz -- refreshrate
devmode.dmPelsWidth,
devmode.dmPelsHeight,
devmode.dmBitsPerPel,
devmode.dmDisplayFrequency); //johnfitz -- refreshrate


// 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 %dHz", //johnfitz -- refreshrate
modelist[nummodes].width,
modelist[nummodes].height,
modelist[nummodes].bpp,
modelist[nummodes].refreshrate); //johnfitz -- refreshrate

}
}

for (i=originalnummodes, existingmode = 0 ; i<nummodes ; i++)
{
if ((modelist[nummodes].width == modelist[i].width) &&
(modelist[nummodes].height == modelist[i].height) &&
(modelist[nummodes].bpp == modelist[i].bpp) &&
(modelist[nummodes].refreshrate == modelist[i].refreshrate)) //johnfitz -- refreshrate

{
existingmode = 1;
break;
}
}

if (!existingmode)
{
nummodes++;
}
}
}

modenum++;
} while (stat);

// see if there are any low-res modes that aren't being reported
numlowresmodes = sizeof(lowresmodes) / sizeof(lowresmodes[0]);
bpp = 16;
done = 0;

do
{
for (j=0 ; (j<numlowresmodes) && (nummodes < MAX_MODE_LIST) ; j++)
{
devmode.dmBitsPerPel = bpp;
devmode.dmPelsWidth = lowresmodes[j].width;
devmode.dmPelsHeight = lowresmodes[j].height;
devmode.dmFields = DM_BITSPERPEL |
DM_PELSWIDTH |
DM_PELSHEIGHT |
DM_DISPLAYFREQUENCY; //johnfitz -- refreshrate;


if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) ==
DISP_CHANGE_SUCCESSFUL)
{
modelist[nummodes].type = MS_FULLDIB;
modelist[nummodes].width = devmode.dmPelsWidth;
modelist[nummodes].height = devmode.dmPelsHeight;
modelist[nummodes].modenum = 0;
modelist[nummodes].halfscreen = 0;
modelist[nummodes].dib = 1;
modelist[nummodes].fullscreen = 1;
modelist[nummodes].bpp = devmode.dmBitsPerPel;
modelist[nummodes].refreshrate = devmode.dmDisplayFrequency; //johnfitz -- refreshrate
sprintf (modelist[nummodes].modedesc, "%dx%dx%d %dHz", //johnfitz -- refreshrate
devmode.dmPelsWidth,
devmode.dmPelsHeight,
devmode.dmBitsPerPel,
devmode.dmDisplayFrequency); //johnfitz -- refreshrate


for (i=originalnummodes, existingmode = 0 ; i<nummodes ; i++)
{
if ((modelist[nummodes].width == modelist[i].width) &&
(modelist[nummodes].height == modelist[i].height) &&
(modelist[nummodes].bpp == modelist[i].bpp) &&
(modelist[nummodes].refreshrate == modelist[i].refreshrate)) //johnfitz -- refreshrate

{
existingmode = 1;
break;
}
}

if (!existingmode)
{
nummodes++;
}
}
}
switch (bpp)
{
case 16:
bpp = 32;
break;

case 32:
bpp = 24;
break;

case 24:
done = 1;
break;
}
} while (!done);

if (nummodes == originalnummodes)
Con_SafePrintf ("No fullscreen DIB modes found\n");
}
Back to top
View user's profile Send private message
Baker



Joined: 14 Mar 2006
Posts: 1538

PostPosted: Mon Dec 08, 2008 11:41 pm    Post subject: Reply with quote

5.12 In VID_Init, add the yellow

Quote:
/*
===================
VID_Init
===================
*/
void VID_Init (unsigned char *palette)
{
int i, existingmode;
int basenummodes, width, height, bpp, findbpp, done;
byte *ptmp;
char gldir[MAX_OSPATH];
HDC hdc;
DEVMODE devmode;

memset(&devmode, 0, sizeof(devmode));

Cvar_RegisterVariable (&vid_fullscreen); //johnfitz
Cvar_RegisterVariable (&vid_width); //johnfitz
Cvar_RegisterVariable (&vid_height); //johnfitz

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



Cvar_RegisterVariable (&vid_mode);
Cvar_RegisterVariable (&vid_wait);
Cvar_RegisterVariable (&vid_nopageflip);
Cvar_RegisterVariable (&_vid_wait_override);
Cvar_RegisterVariable (&_vid_default_mode);
Cvar_RegisterVariable (&_vid_default_mode_win);
Cvar_RegisterVariable (&vid_config_x);
Cvar_RegisterVariable (&vid_config_y);
Cvar_RegisterVariable (&vid_stretch_by_2);
Cvar_RegisterVariable (&_windowed_mouse);
Cvar_RegisterVariable (&gl_ztrick);

Cmd_AddCommand ("vid_nummodes", VID_NumModes_f);
Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f);
Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f);
Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f);

hIcon = LoadIcon (global_hInstance, MAKEINTRESOURCE (IDI_ICON2));

InitCommonControls();

VID_InitDIB (global_hInstance);
basenummodes = nummodes = 1;

VID_InitFullDIB (global_hInstance);

if (COM_CheckParm("-window"))
{
hdc = GetDC (NULL);

if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
{
Sys_Error ("Can't run in non-RGB mode");
}

ReleaseDC (NULL, hdc);

windowed = true;
video_options_disabled = true;
vid_default = MODE_WINDOWED;
}
else
{
if (nummodes == 1)
Sys_Error ("No RGB fullscreen modes available");

windowed = false;

if (COM_CheckParm("-mode"))
{
vid_default = Q_atoi(com_argv[COM_CheckParm("-mode")+1]);
}
else
{
if (COM_CheckParm("-current"))
{
modelist[MODE_FULLSCREEN_DEFAULT].width =
GetSystemMetrics (SM_CXSCREEN);
modelist[MODE_FULLSCREEN_DEFAULT].height =
GetSystemMetrics (SM_CYSCREEN);
vid_default = MODE_FULLSCREEN_DEFAULT;
leavecurrentmode = 1;
}
else
{
if (COM_CheckParm("-width"))
{
width = Q_atoi(com_argv[COM_CheckParm("-width")+1]);
}
else
{
width = 640;
}

if (COM_CheckParm("-bpp"))
{
bpp = Q_atoi(com_argv[COM_CheckParm("-bpp")+1]);
findbpp = 0;
}
else
{
bpp = desktop_bpp; // Baker: match the desktop bpp if not specified, was 15
findbpp = 1;
}

if (COM_CheckParm("-height"))
height = Q_atoi(com_argv[COM_CheckParm("-height")+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 = MS_FULLDIB;
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 %dHz", //johnfitz -- refreshrate
devmode.dmPelsWidth,
devmode.dmPelsHeight,
devmode.dmBitsPerPel,
devmode.dmDisplayFrequency); //johnfitz -- refreshrate


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) &&
(modelist[nummodes].refreshrate == modelist[i].refreshrate)) //johnfitz -- refreshrate

{
existingmode = 1;
break;
}
}

if (!existingmode)
{
nummodes++;
}
}

done = 0;

do
{
if (COM_CheckParm("-height"))
{
height = Q_atoi(com_argv[COM_CheckParm("-height")+1]);

for (i=1, vid_default=0 ; i<nummodes ; i++)
{
if ((modelist[i].width == width) &&
(modelist[i].height == height) &&
(modelist[i].bpp == bpp))
{
vid_default = i;
done = 1;
break;
}
}
}
else
{
for (i=1, vid_default=0 ; i<nummodes ; i++)
{
if ((modelist[i].width == width) && (modelist[i].bpp == bpp))
{
vid_default = i;
done = 1;
break;
}
}
}

if (!done)
{
if (findbpp)
{
switch (bpp)
{
case 15:
bpp = 16;
break;
case 16:
bpp = 32;
break;
case 32:
bpp = 24;
break;
case 24:
done = 1;
break;
}
}
else
{
done = 1;
}
}
} while (!done);

vid_bpp = bpp;


if (!vid_default)
{
Sys_Error ("Specified video mode not available");
}
}
}
}

vid_initialized = true;

if ((i = COM_CheckParm("-conwidth")) != 0)
vid.conwidth = Q_atoi(com_argv[i+1]);
else
vid.conwidth = 640;

vid.conwidth &= 0xfff8; // make it a multiple of eight

if (vid.conwidth < 320)
vid.conwidth = 320;

// pick a conheight that matches with correct aspect
vid.conheight = vid.conwidth*3 / 4;

if ((i = COM_CheckParm("-conheight")) != 0)
vid.conheight = Q_atoi(com_argv[i+1]);
if (vid.conheight < 200)
vid.conheight = 200;

vid.maxwarpwidth = WARP_WIDTH;
vid.maxwarpheight = WARP_HEIGHT;
vid.colormap = host_colormap;
vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));

DestroyWindow (hwnd_dialog);

Check_Gamma(palette);
VID_SetPalette (palette);

VID_SetMode (vid_default, palette);

maindc = GetDC(mainwindow);
bSetupPixelFormat(maindc);

baseRC = wglCreateContext( maindc );
if (!baseRC)
Sys_Error ("Could not initialize GL (wglCreateContext failed).\n\nMake sure you in are 65535 color mode, and try running -window.");
if (!wglMakeCurrent( maindc, baseRC ))
Sys_Error ("wglMakeCurrent failed");

GL_Init ();

sprintf (gldir, "%s/glquake", com_gamedir);
Sys_mkdir (gldir);

vid_realmode = vid_modenum;

// Check for 3DFX Extensions and initialize them.
VID_Init8bitPalette();

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_Menu_Init(); //johnfitz

//johnfitz -- command line vid settings should override config file settings.
//so we have to lock the vid mode from now until after all config files are read.
if (COM_CheckParm("-width") || COM_CheckParm("-height") || COM_CheckParm("-bpp") || COM_CheckParm("-window"))
{
vid_locked = true;
}
//johnfitz

}
Back to top
View user's profile Send private message
Baker



Joined: 14 Mar 2006
Posts: 1538

PostPosted: Mon Dec 08, 2008 11:46 pm    Post subject: Reply with quote

AND FINALLY:

5.13 Find all this code:

Quote:
Code:
//========================================================
// Video menu stuff
//========================================================

extern void M_Menu_Options_f (void);
extern void M_Print (int cx, int cy, char *str);
extern void M_PrintWhite (int cx, int cy, char *str);
extern void M_DrawCharacter (int cx, int line, int num);
extern void M_DrawTransPic (int x, int y, qpic_t *pic);
extern void M_DrawPic (int x, int y, qpic_t *pic);

static int   vid_line, vid_wmodes;

typedef struct
{
   int      modenum;
   char   *desc;
   int      iscur;
} modedesc_t;

#define MAX_COLUMN_SIZE      9
#define MODE_AREA_HEIGHT   (MAX_COLUMN_SIZE + 2)
#define MAX_MODEDESCS      (MAX_COLUMN_SIZE*3)

static modedesc_t   modedescs[MAX_MODEDESCS];

/*
================
VID_MenuDraw
================
*/
void VID_MenuDraw (void)
{
   qpic_t      *p;
   char      *ptr;
   int         lnummodes, i, j, k, column, row, dup, dupmode;
   char      temp[100];
   vmode_t      *pv;

   p = Draw_CachePic ("gfx/vidmodes.lmp");
   M_DrawPic ( (320-p->width)/2, 4, p);

   vid_wmodes = 0;
   lnummodes = VID_NumModes ();
   
   for (i=1 ; (i<lnummodes) && (vid_wmodes < MAX_MODEDESCS) ; i++)
   {
      ptr = VID_GetModeDescription (i);
      pv = VID_GetModePtr (i);

      k = vid_wmodes;

      modedescs[k].modenum = i;
      modedescs[k].desc = ptr;
      modedescs[k].iscur = 0;

      if (i == vid_modenum)
         modedescs[k].iscur = 1;

      vid_wmodes++;

   }

   if (vid_wmodes > 0)
   {
      M_Print (2*8, 36+0*8, "Fullscreen Modes (WIDTHxHEIGHTxBPP)");

      column = 8;
      row = 36+2*8;

      for (i=0 ; i<vid_wmodes ; i++)
      {
         if (modedescs[i].iscur)
            M_PrintWhite (column, row, modedescs[i].desc);
         else
            M_Print (column, row, modedescs[i].desc);

         column += 13*8;

         if ((i % VID_ROW_SIZE) == (VID_ROW_SIZE - 1))
         {
            column = 8;
            row += 8;
         }
      }
   }

   M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*2,
          "Video modes must be set from the");
   M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*3,
          "command line with -width <width>");
   M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*4,
          "and -bpp <bits-per-pixel>");
   M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*6,
          "Select windowed mode with -window");
}


/*
================
VID_MenuKey
================
*/
void VID_MenuKey (int key)
{
   switch (key)
   {
   case K_ESCAPE:
      S_LocalSound ("misc/menu1.wav");
      M_Menu_Options_f ();
      break;

   default:
      break;
   }
}


And replace with our new video menu:

Quote:
Code:



/*
================
VID_SyncCvars -- johnfitz -- set vid cvars to match current video mode
================
*/
extern qboolean vid_consize_ignore_callback;
void VID_SyncCvars (void)
{
   Cvar_Set ("vid_width", va("%i", modelist[vid_default].width));
   Cvar_Set ("vid_height", va("%i", modelist[vid_default].height));
   Cvar_Set ("vid_refreshrate", va("%i", modelist[vid_default].refreshrate));
   Cvar_Set ("vid_fullscreen", (windowed) ? "0" : "1");
}

//==========================================================================
//
//  NEW VIDEO MENU -- johnfitz
//
//==========================================================================

extern void M_Menu_Options_f (void);
extern void M_Print (int cx, int cy, char *str);
extern void M_PrintWhite (int cx, int cy, char *str);
extern void M_DrawCharacter (int cx, int line, int num);
extern void M_DrawTransPic (int x, int y, qpic_t *pic);
extern void M_DrawPic (int x, int y, qpic_t *pic);
extern void M_DrawCheckbox (int x, int y, int on);

extern qboolean   m_entersound;



#define VIDEO_OPTIONS_ITEMS 6
int      video_cursor_table[] = {48, 56, 64, 72, 88, 96};
int      video_options_cursor = 0;

typedef struct {int width,height;} vid_menu_mode;

//TODO: replace these fixed-length arrays with hunk_allocated buffers

vid_menu_mode vid_menu_modes[MAX_MODE_LIST];
int vid_menu_nummodes=0;

//int vid_menu_bpps[4];
//int vid_menu_numbpps=0;

int vid_menu_rates[20];
int vid_menu_numrates=0;

/*
================
VID_Menu_Init
================
*/
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_RebuildRateList

regenerates rate list based on current vid_width, vid_height and vid_bpp
================
*/
void VID_Menu_RebuildRateList (void)
{
   int i,j,r;

   vid_menu_numrates=0;

   for (i=1;i<nummodes;i++) //start i at mode 1 because 0 is windowed mode
   {
      //rate list is limited to rates available with current width/height/bpp
      if (modelist[i].width != vid_width.value ||
         modelist[i].height != vid_height.value /*||
         modelist[i].bpp != vid_bpp.value*/)
         continue;

      r = modelist[i].refreshrate;

      for (j=0;j<vid_menu_numrates;j++)
      {
         if (vid_menu_rates[j] == r)
            break;
      }

      if (j==vid_menu_numrates)
      {
         vid_menu_rates[j] = r;
         vid_menu_numrates++;
      }
   }

   //if vid_refreshrate is not in the new list, change vid_refreshrate
   for (i=0;i<vid_menu_numrates;i++)
      if (vid_menu_rates[i] == (int)(vid_refreshrate.value))
         break;

   if (i==vid_menu_numrates)
      Cvar_Set ("vid_refreshrate",va("%i",vid_menu_rates[0]));
   }

/*
================
VID_Menu_ChooseNextMode

chooses next resolution in order, then updates vid_width and
vid_height cvars, then updates bpp and refreshrate lists
================
*/
void VID_Menu_ChooseNextMode (int dir)
{
   int i;

   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_Set ("vid_width",va("%i",vid_menu_modes[i].width));
   Cvar_Set ("vid_height",va("%i",vid_menu_modes[i].height));
   VID_Menu_RebuildRateList ();
}

/*
================
VID_Menu_ChooseNextRate

chooses next refresh rate in order, then updates vid_refreshrate cvar
================
*/
void VID_Menu_ChooseNextRate (int dir)
{
   int i;

   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_Set ("vid_refreshrate",va("%i",vid_menu_rates[i]));
}

/*
================
VID_MenuKey
================
*/
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:
      case 5:
   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:
         if (vid_bpp == desktop_bpp)
            Cbuf_AddText ("toggle vid_fullscreen\n");
         break;
      case 4:
      case 5:
      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:
         if (vid_bpp == desktop_bpp)
            Cbuf_AddText ("toggle vid_fullscreen\n");

         break;
      case 4:
         Cbuf_AddText ("vid_test\n");
         break;
      case 5:
         Cbuf_AddText ("vid_restart\n");
         break;
      default:
         break;
      }
      break;

   default:
      break;
   }
}

/*
================
VID_MenuDraw
================
*/
void VID_MenuDraw (void)
{
   int i = 0;
   qpic_t *p;
   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 (216, 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 (216, video_cursor_table[i], va("%i [locked]", (int)vid_bpp));
   i++;

   M_Print (16, video_cursor_table[i], "          Refresh rate");
   M_Print (216, video_cursor_table[i], va("%i Hz", (int)vid_refreshrate.value));
   i++;

   M_Print (16, video_cursor_table[i], "            Fullscreen");

   if (vid_bpp == desktop_bpp)
      M_DrawCheckbox (216, video_cursor_table[i], (int)vid_fullscreen.value);
   else
      M_Print (216, video_cursor_table[i], va("%s [locked]", (int)vid_fullscreen.value ? "on" : "off"));

   i++;

   M_Print (16, video_cursor_table[i], "          Test changes");
   i++;

   M_Print (16, video_cursor_table[i], "         Apply changes");

   // cursor
   M_DrawCharacter (200, 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
================
*/
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_RebuildRateList ();
}


And we are done. Compile and run.

I guess the changes to gl_vidnt.c can be done in 13 steps, not 18.

Your new cvars are:

Quote:
vid_width
vid_height
vid_fullscreen

and so forth

Your new commands are vid_restart and vid_test.

To change the video mode, go Options -> Video Mode.

To create an ALT-ENTER like alias, you could create an alias like:

alias fullscreen_toggle "toggle vid_fullscreen; vid_restart"

Except GLQuake doesn't have a toggle command, but you could borrow the toggle command from cvar.c in FitzQuake 0.80 if you wanted.

Then if you wanted ALT-ENTER support, go to keys.c and detect ENTER with a ALT state of down and have it execute "toggle vid_fullscreen; vid_restart"if you like.

Find note, you should really do this as well in gl_vidnt.c. I didn't include it in the above:

r00k wrote:
In my addition to adding alt-enter,
i had to implement this bit
Code:

      case WM_ACTIVATE:
         fActive = LOWORD(wParam);
         fMinimized = (BOOL) HIWORD(wParam);
         AppActivate(!(fActive == WA_INACTIVE), fMinimized);
      // fix the leftover Alt from any Alt-Tab or the like that switched us away
         Key_ClearAllStates();
         //R00k re-init the mouse after alt-tabbing please... (v1.9)
         if (!mouseactive)
         {
            IN_Shutdown ();
            IN_StartupMouse();
            IN_ActivateMouse ();
            IN_HideMouse ();
         }
         break;


Additionally in gl_vidnt.c, really you should add the Nvidia ALT-TAB fix. I forgot to include this in the above:

This keeps the window from drifting off center, a flaw in the Nvidia OpenGL drivers.
AppActivate in gl_vidnt.c wrote:
if (fActive) {
if (modestate == MS_FULLDIB) {
IN_ActivateMouse ();
IN_HideMouse ();
if (vid_canalttab && vid_wassuspended) {
vid_wassuspended = false;
ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN);
ShowWindow(mainwindow, SW_SHOWNORMAL);

// Baker 3.80x - Fix for alt-tab bug in NVidia drivers from JoeQuake
MoveWindow (mainwindow, 0, 0, gdevmode.dmPelsWidth, gdevmode.dmPelsHeight, false);

}
} else if ((modestate == MS_WINDOWED) && _windowed_mouse.value && key_dest == key_game) {
IN_ActivateMouse ();
IN_HideMouse ();
}
}


THE END
Back to top
View user's profile Send private message
Spike



Joined: 05 Nov 2004
Posts: 944
Location: UK

PostPosted: Tue Dec 09, 2008 3:19 am    Post subject: Reply with quote

'uknown command: toggle'.

other than that, an ATI driver will 90% bug on you. Not instantly, but perhaps after a few map changes.
Run it windowed and just change the framebuffer size, and the next textures that are loaded (next map?) will be corrupted.

This is the method that carmack reported that *all* cards bugged out on in one way or another.

A more reliable way is to compleatly shut down the opengl renderer, and create a fresh new context. You'll need to load new textures, but quake doesn't really use anything that matters.
_________________
What's a signature?
Back to top
View user's profile Send private message Visit poster's website
metlslime



Joined: 05 Feb 2008
Posts: 177

PostPosted: Tue Dec 09, 2008 3:44 am    Post subject: Reply with quote

Spike wrote:
This is the method that carmack reported that *all* cards bugged out on in one way or another. A more reliable way is to compleatly shut down the opengl renderer, and create a fresh new context.


Baker, I think Spike is referring to the bug you yourself reported to me, where your (Intel?) card would report "wglMakeCurrent failed" when you tried to switch just resolution, but it worked if you also changed color depth. I sent you a patch that addressed it, but as you mentioned above, you can't really create a new context without a good way to reload textures, which isn't available in stock glquake.
Back to top
View user's profile Send private message
Baker



Joined: 14 Mar 2006
Posts: 1538

PostPosted: Tue Dec 09, 2008 4:02 am    Post subject: Reply with quote

Spike wrote:
'uknown command: toggle'.


Oversight. That's right, the FitzQuake fullscreen vs. windowed mode menu uses the toggle command and I didn't change it or add it in.

Must fix tutorial. Thanks for the heads up.

I tested from the console and then did a quick and dirty menu test but didn't think to try to fullscreen ON/OFF in the menu.

Quote:
other than that, an ATI driver will 90% bug on you. Not instantly, but perhaps after a few map changes.
Run it windowed and just change the framebuffer size, and the next textures that are loaded (next map?) will be corrupted.

This is the method that carmack reported that *all* cards bugged out on in one way or another.

A more reliable way is to compleatly shut down the opengl renderer, and create a fresh new context. You'll need to load new textures, but quake doesn't really use anything that matters.


I don't have a machine with an ATI card to test, but I'll research the above more and see if I can do it "right" next the time I get a chance.

metlslime wrote:
Baker, I think Spike is referring to the bug you yourself reported to me, where your (Intel?) card would report "wglMakeCurrent failed" when you tried to switch just resolution, but it worked if you also changed color depth. I sent you a patch that addressed it, but as you mentioned above, you can't really create a new context without a good way to reload textures, which isn't available in stock glquake.


Sometime I'll have more time to finish studying the FitzQuake texture manager and incorporate the "re-use context" patch.

I know the above isn't absolutely perfect yet (aside from the accidental incorporation of the toggle command, which I will fix).

/By the way, the machine with the "wglMakeCurrent failed" issue was a GeForce Go 6150, not an Intel.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Inside3d Forums Forum Index -> Programming Tutorials All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2004 phpBB Group