Well, your code post was a major asset to my recent engine work. I entirely rewrote all the video code, all the input code, some of the menu code, reworked the lightmap code and with this added I have an engine that I can stand to look at the source code. The size of source files dropped 33% after rewriting the ghastly Quake video and input code to be light and tight. (* look how short my platform neutral vid.c is, below)reckless wrote:Definatly worth it sifting through mh's older OpenGL engine sources, lots of non standard but amazingly well working ideas His Q2 sources are also worth having a look at, many nice ideas in them.
Now I'm debating on whether to quickly port to OS X natively or via SDL. Or both so someone Linuxy has the opportunity to use the engine, I have worked with Linux before but it is so much work and hassles for so few users and so many diverse problems with such fragmentation of distros and versions.
But either way, I have say this was the icing on the cake. I still can't believe how fast it is for code that has to operate on the entire buffer. And this code has motivated me to push the boundaries on other things that irritate me.
Code: Select all
// vid.c -- common video
#include "quakedef.h"
viddef_t vid; // global video state
cvar_t vid_fullscreen = {"vid_fullscreen", "1", CVAR_ARCHIVE};
cvar_t vid_width = {"vid_width", "640", CVAR_ARCHIVE};
cvar_t vid_height = {"vid_height", "480", CVAR_ARCHIVE};
cvar_t vid_bpp = {"vid_bpp", "32", CVAR_ARCHIVE};
cvar_t vid_vsync = {"vid_vsync", "0", CVAR_ARCHIVE};
//
// set mode and restart
//
/*
================
VID_SetMode
================
*/
int VID_SetMode (int modenum)
{
// so Con_Printfs don't mess us up by forcing vid and snd updates
int temp = scr_disabled_for_loading;
qboolean re_setupgl;
scr_disabled_for_loading = true;
vid.canalttab = false;
// Stop Sounds
S_BlockSound ();
S_ClearBuffer ();
CDAudio_Pause ();
// Platform specific stuff
re_setupgl = (VID_Local_SetMode (modenum) == false);
// Assignment
{
vid.modenum_screen = modenum;
vid.screen = vid.modelist[vid.modenum_screen];
// keep cvars in line with actual mode
VID_Cvars_Sync_To_Mode (&vid.modelist[vid.modenum_screen]);
// Refresh console
SCR_Conwidth_f (NULL);
vid.recalc_refdef = 1;
vid.numpages = 2;
}
// GL break-in
GL_Evaluate_Renderer ();
GL_SetupState ();
// ensure swap settings right
VID_Local_Vsync_f (NULL);
if (re_setupgl)
{
Con_DPrintf ("Reuploading images\n");
TexMgr_ReloadImages (); // SAFE?
} else Con_DPrintf ("Reused context no reupload images\n");
TexMgr_RecalcWarpImageSize (); // SAFE?
// Restore sound
Input_Think ();
S_UnblockSound ();
CDAudio_Resume ();
vid.canalttab = true;
scr_disabled_for_loading = temp;
return true;
}
qboolean VID_Restart (int flags /* favorite vs. temp*/)
{
vmode_t newmode = VID_Cvars_To_Mode ();
vmode_t oldmode = vid.screen;
int newmodenum;
// No change scenario
if ( memcmp (&newmode, &oldmode, sizeof(vmode_t)) == 0)
{
Con_Printf ("Video mode request is same as current mode.\n");
return false;
}
// Fullscreen must check existing modes, window must set it instead.
switch (newmode.type)
{
case MODE_WINDOWED:
memcpy (&vid.modelist[MODE_WINDOWED], &newmode, sizeof (vmode_t) );
newmodenum = 0;
break;
case MODE_FULLSCREEN:
if (VID_Mode_Exists (&newmode, &newmodenum) == false)
{
Con_Printf ("%d x %d x %d (%i) is not a valid fullscreen mode\n",
(int)vid_width.value,
(int)vid_height.value,
(int)vid_bpp.value,
(int)vid_fullscreen.value);
return false;
}
break;
}
// Determine if the mode is invalid.
VID_SetMode (newmodenum);
if (flags == USER_SETTING_FAVORITE_MODE)
vid.modenum_user_selected = vid.modenum_screen;
return true;
}
/*
================
VID_Test -- johnfitz -- like vid_restart, but asks for confirmation after switching modes
================
*/
void VID_Test (void)
{
vmode_t newmode = VID_Cvars_To_Mode ();
vmode_t oldmode = vid.screen;
qboolean mode_changed = memcmp (&newmode, &vid.screen, sizeof(vmode_t) );
if (!mode_changed)
return;
//
// now try the switch
//
VID_Restart (USER_SETTING_FAVORITE_MODE);
//pop up confirmation dialog
if (!SCR_ModalMessage("Would you like to keep this\nvideo mode? (y/n)\n", 5.0f))
{
// User rejected new mode: revert cvars and mode
VID_Cvars_Sync_To_Mode (&oldmode);
VID_Restart (USER_SETTING_FAVORITE_MODE);
}
}
void VID_Alt_Enter_f (void)
{
if (vid.modenum_screen != vid.modenum_user_selected)
{
// Go to favorite mode
VID_Cvars_Sync_To_Mode ( &vid.modelist[vid.modenum_user_selected] );
VID_Restart (USER_SETTING_FAVORITE_MODE);
return;
}
// ALT-ENTER to a temp mode
if (vid.screen.type == MODE_WINDOWED)
VID_Cvars_Set_Autoselect_Temp_Fullscreen_Mode (vid.modenum_screen);
else VID_Cvars_Set_Autoselect_Temp_Windowed_Mode (vid.modenum_screen);
VID_Restart (ALT_ENTER_TEMPMODE);
}
void VID_Restart_f (void)
{
VID_Restart (USER_SETTING_FAVORITE_MODE);
}
//
// in-game
//
void VID_AppActivate(qboolean fActive, qboolean minimize)
{
vid.ActiveApp = fActive;
vid.Minimized = minimize;
// Con_Printf ("App activate occurred %i\n", vid.ActiveApp);
if (vid.ActiveApp)
{
if (!vid.sound_active)
{
S_UnblockSound ();
vid.sound_active = true;
}
if (vid.screen.type == MODE_FULLSCREEN && vid.canalttab && vid.wassuspended)
{
VID_Local_Suspend (false);
vid.wassuspended = false;
}
}
if (!vid.ActiveApp)
{
if (vid.screen.type == MODE_FULLSCREEN && vid.canalttab)
{
VID_Local_Suspend (true);
vid.wassuspended = true;
}
if (vid.sound_active)
{
S_BlockSound ();
vid.sound_active = false;
}
}
}
void VID_SwapBuffers (void)
{
VID_Local_SwapBuffers ();
}
//
// functions to match modes to cvars or reverse
//
void VID_Cvars_Sync_To_Mode (vmode_t* mymode)
{
// Don't allow anything exiting to call this. I think we are "ok"
Cvar_SetValue (vid_width.name, (float)mymode->width);
Cvar_SetValue (vid_height.name, (float)mymode->height);
Cvar_SetValue (vid_bpp.name, (float)mymode->bpp);
Cvar_SetValue (vid_fullscreen.name, mymode->type == MODE_FULLSCREEN ? 1 : 0);
}
vmode_t VID_Cvars_To_Mode (void)
{
vmode_t retmode;
retmode.type = vid_fullscreen.value ? MODE_FULLSCREEN : MODE_WINDOWED;
retmode.width = (int)vid_width.value;
retmode.height = (int)vid_height.value;
retmode.bpp = (int)vid_bpp.value;
if (retmode.type == MODE_WINDOWED)
{
retmode.width = CLAMP (MIN_WINDOWED_MODE_WIDTH, retmode.width, vid.desktop.width);
retmode.height = CLAMP (MIN_WINDOWED_MODE_HEIGHT, retmode.height, vid.desktop.height);
retmode.bpp = vid.desktop.bpp;
}
return retmode;
}
static qboolean VID_Read_Early_Cvars_For_File (const char* config_file_name)
{
qboolean found_any_vid_cvars = false;
cvar_t *video_cvars[] = {&vid_fullscreen, &vid_width, &vid_height, &vid_bpp, &scr_brightness, NULL};
char config_buffer[8192];
FILE *f;
int bytes_size = COM_FOpenFile (config_file_name, &f);
int i;
// Read the file into the buffer. Read the first 8000 bytes (if longer, tough cookies)
// Because it is pretty likely that size of file will get a "SZ_GetSpace: overflow without allowoverflow set"
// During command execution
if (bytes_size !=-1)
{
int bytes_in = q_min (bytes_size, 8000); // Cap at 8000
int bytes_read = fread (config_buffer, 1, bytes_in, f);
config_buffer [bytes_read + 1] = 0; // Null terminate just in case
fclose (f);
} else return false;
for (i = 0; video_cvars[i]; i++)
{
float value;
qboolean found = Parse_Float_From_String (&value, config_buffer, video_cvars[i]->name);
// MessageBox (NULL, va("Cvar %s was %s and is %g", video_cvars[i]->name, found ? "Found" : "Not found", found ? value : 0), "", MB_OK);
if (found == false)
continue;
Cvar_SetValue (video_cvars[i]->name, value);
found_any_vid_cvars = true;
}
return found_any_vid_cvars;
}
qboolean VID_Read_Early_Cvars (void)
{
// Any of these found and we bail
char *video_override_commandline_params[] = {"-window", "-width", "-height", "-current", "-bpp", NULL } ;
qboolean found_in_config, found_in_autoexec;
int i;
for (i = 0; video_override_commandline_params[i]; i++)
if (COM_CheckParm (video_override_commandline_params[i]))
return false;
found_in_config = VID_Read_Early_Cvars_For_File (CONFIG_CFG);
found_in_autoexec = VID_Read_Early_Cvars_For_File (AUTOEXEC_CFG);
return (found_in_config || found_in_autoexec);
}
qboolean VID_Mode_Exists (vmode_t* test, int *outmodenum)
{
int i;
for (i = 0; i < vid.nummodes; i++)
{
if (memcmp (&vid.modelist[i], test, sizeof(vmode_t)))
continue; // No match
// dup
if (outmodenum) *outmodenum = i;
return true; // Duplicate
}
return false;
}
void VID_MakeMode (modestate_t mode_type, vmode_t *new_mode)
{
new_mode->type = mode_type;
new_mode->width = 640;
new_mode->height= 480;
new_mode->bpp = vid.desktop.bpp;
// !!(int)vid_fullscreen.value --> turn into an int and "NOT" it twice
// so must have 0 or 1 value. In case vid_fullscreen is 2 or something weird
if ( (!!(int)vid_fullscreen.value) == mode_type)
{
new_mode->width = vid_width.value;
new_mode->height= vid_height.value;
new_mode->bpp = vid_bpp.value;
}
vid.nummodes ++;
}
void VID_Cvars_Set_Autoselect_Temp_Windowed_Mode (int favoritemode)
{
// Pencil in last windowed mode, but set the bpp to the desktop bpp
VID_Cvars_Sync_To_Mode (&vid.modelist[MODE_WINDOWED]);
Cvar_SetValue (vid_bpp.name, (float)vid.desktop.bpp);
}
void VID_Cvars_Set_Autoselect_Temp_Fullscreen_Mode (int favoritemode)
{
vmode_t *fave = &vid.modelist[favoritemode];
int best = -1;
int bestscore = -1;
int i;
// Look through the video modes.
// If an exact matching fullscreen mode of same resolution
// exists, pick that. Try to go for same bpp.
// Attempt 1: Match resolution
// Baker: Locate matching mode
for (i = 1; i < vid.nummodes; i ++)
{
vmode_t *mode = &vid.modelist[i];
int size_match = (mode->width == fave->width && mode->height == fave->height);
int bpp_match = mode->bpp == fave->bpp;
int bpp_deskmatch = mode->bpp == vid.desktop.bpp;
int score = size_match * 20 + bpp_match * 5 + bpp_deskmatch;
if (score <= bestscore)
continue; // Didn't beat best
// New best
best = i;
bestscore = score;
}
if (bestscore < 20)
{
// No size match ... try again
// If fails, pick something with width/height both divisble by 8
// so charset doesn't look stretched. Go for largest mode with
// desktop bpp and desktop refreshrate and desktop width/height
// Unless those are stupid.
best = -1;
bestscore = -1;
for (i = 1; i < vid.nummodes; i ++)
{
vmode_t *mode = &vid.modelist[i];
if (mode->width & 7)
continue; // Skip stupid resolutions
if (mode->height & 7)
continue; // Skip stupid resolutions
if (mode->bpp != vid.desktop.bpp && mode->bpp != fave->bpp)
continue;
if (mode->width >= vid.desktop.width - 7)
if (mode->height >= vid.desktop.height - 7)
{
// Take it
best = i;
break;
}
// Not an automatic winner. If largest ...
if (mode->width >= vid.modelist[best].width || mode->height >= vid.modelist[best].height)
{
best = i;
}
}
if (best == -1)
Sys_Error ("Couldn't find suitable video mode");
}
// Set cvars
VID_Cvars_Sync_To_Mode (&vid.modelist[best]);
// Ok ... cvars are ready !
}
//
// startup / shutdown
//
void VID_Init (void)
{
int i;
qboolean videos_cvars_read;
vid.desktop = VID_Local_GetDesktopProperties (); // Good time to get them.
Cvar_RegisterVariable (&vid_fullscreen);
Cvar_RegisterVariable (&vid_width);
Cvar_RegisterVariable (&vid_height);
Cvar_RegisterVariable (&vid_bpp);
Cvar_RegisterVariableWithCallback (&vid_vsync, VID_Local_Vsync_f);
Cvar_RegisterVariable (&scr_brightness);
Cmd_AddCommand ("vid_restart", VID_Restart_f);
Cmd_AddCommand ("vid_test", VID_Test);
Cmd_AddCommand ("gl_info", GL_Info_f);
// Now, if we have -window or anything we don't bother to read the cvars early
// But we will still read them later.
videos_cvars_read = VID_Read_Early_Cvars ();
if ((i = COM_CheckParm("-width")) && i + 1 < com_argc)
Cvar_SetValue (vid_width.name, (float)atoi(com_argv[i+1]) );
if ((i = COM_CheckParm("-height")) && i + 1 < com_argc)
Cvar_SetValue (vid_height.name, (float)atoi(com_argv[i+1]) );
if ((i = COM_CheckParm("-bpp")) && i + 1 < com_argc)
Cvar_SetValue (vid_bpp.name, (float)atoi(com_argv[i+1]) );
if (COM_CheckParm("-current"))
{
VID_Cvars_Sync_To_Mode (&vid.desktop); // Use desktop sizes.
}
if (COM_CheckParm("-window"))
Cvar_SetValue (vid_fullscreen.name, 0);
VID_Local_Window_PreSetup ();
// Add the default windowed and default fullscreen modes.
// This does allow a user to do an invalid mode in the a command line, but that's on them.
VID_MakeMode (MODE_WINDOWED, &vid.modelist[MODE_WINDOWED]);
VID_MakeMode (MODE_FULLSCREEN, &vid.modelist[MODE_FULLSCREEN]);
// Add the fullscreen modes
VID_Local_AddFullscreenModes ();
if (COM_CheckParm("-fullsbar"))
vid.fullsbardraw = true;
vid.initialized = true;
// Now we set the video mode
VID_SetMode (vid_fullscreen.value ? MODE_FULLSCREEN : MODE_WINDOWED);
vid.modenum_user_selected = vid.modenum_screen; // Default choice
VID_Menu_Init(); //johnfitz
}
void VID_Shutdown (void)
{
if (!vid.initialized)
return;
VID_Local_Window_Renderer_Teardown (TEARDOWN_FULL);
vid.canalttab = false;
}
Code: Select all
// vid_wgl.c -- Windows specific
#include "quakedef.h"
#include "winquake.h"
#include "resource.h" // IDI_ICON2
wplat_t wplat;
//
// miscelleanous init
//
void VID_Local_Window_PreSetup (void)
{
WNDCLASS wc;
wplat.hIcon = LoadIcon (wplat.hInstance, MAKEINTRESOURCE (IDI_ICON2));
// Register the frame class
wc.style = 0;
wc.lpfnWndProc = (WNDPROC)WIN_MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = wplat.hInstance;
wc.hIcon = wplat.hIcon;
wc.hCursor = LoadCursor (NULL,IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = 0;
wc.lpszClassName = ENGINE_NAME;
if (!RegisterClass (&wc) )
Sys_Error ("Couldn't register window class");
}
vmode_t VID_Local_GetDesktopProperties (void)
{
DEVMODE devmode;
vmode_t desktop = {0};
if (!EnumDisplaySettings (NULL, ENUM_CURRENT_SETTINGS, &devmode))
{
Sys_Error ("VID_UpdateDesktopProperties: EnumDisplaySettings failed\n");
return desktop;
}
desktop.type = MODE_FULLSCREEN;
desktop.width = devmode.dmPelsWidth;
desktop.height = devmode.dmPelsHeight;
desktop.bpp = devmode.dmBitsPerPel;
return desktop;
}
//
// vsync
//
qboolean VID_Local_Vsync_Init (const char* gl_extensions_str)
{
if (strstr(gl_extensions_str, "GL_EXT_swap_control") || strstr(gl_extensions_str, "GL_WIN_swap_hint"))
{
wplat.wglSwapIntervalEXT = (SETSWAPFUNC) wglGetProcAddress("wglSwapIntervalEXT");
wplat.wglGetSwapIntervalEXT = (GETSWAPFUNC) wglGetProcAddress("wglGetSwapIntervalEXT");
if (wplat.wglSwapIntervalEXT && wplat.wglGetSwapIntervalEXT && wplat.wglSwapIntervalEXT(0) &&
wplat.wglGetSwapIntervalEXT() != -1)
return true;
}
return false;
}
void VID_Local_Vsync_f (cvar_t *var)
{
if (renderer.gl_swap_control)
{
if (vid_vsync.value)
{
if (!wplat.wglSwapIntervalEXT(1))
Con_Printf ("VID_Vsync_f: failed on wglSwapIntervalEXT\n");
}
else
{
if (!wplat.wglSwapIntervalEXT(0))
Con_Printf ("VID_Vsync_f: failed on wglSwapIntervalEXT\n");
}
}
}
//
// vid modes
//
void VID_Local_AddFullscreenModes (void)
{
BOOL stat; // Used to test mode validity
DEVMODE devmode = {0};
int hmodenum = 0; // Hardware modes start at 0
// Baker: Run through every display mode and get information
while ( (stat = EnumDisplaySettings (NULL, hmodenum++, &devmode)) && vid.nummodes < MAX_MODE_LIST )
{
vmode_t test = { MODE_FULLSCREEN, devmode.dmPelsWidth, devmode.dmPelsHeight, devmode.dmBitsPerPel };
qboolean bpp_ok = (devmode.dmBitsPerPel >= 16);
qboolean width_ok = INBOUNDS (MIN_MODE_WIDTH, devmode.dmPelsWidth, MAX_MODE_WIDTH);
qboolean height_ok = INBOUNDS (MIN_MODE_HEIGHT, devmode.dmPelsHeight, MAX_MODE_HEIGHT);
qboolean qualified = (bpp_ok && width_ok && height_ok);
devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
if (qualified && !VID_Mode_Exists(&test, NULL) && ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL)
{
// Not a dup and test = ok ---> add it
memcpy (&vid.modelist[vid.nummodes++], &test, sizeof(vmode_t) );
}
}
}
void WIN_Construct_Or_Resize_Window (DWORD style, DWORD exstyle, RECT window_rect)
{
const char* nm = ENGINE_NAME;
int x = window_rect.left, y = window_rect.top;
int w = RECT_WIDTH(window_rect), h = RECT_HEIGHT(window_rect);
if (wplat.mainwindow)
{
SetWindowLong (wplat.mainwindow, GWL_EXSTYLE, exstyle);
SetWindowLong (wplat.mainwindow, GWL_STYLE, style);
SetWindowPos (wplat.mainwindow, NULL, x, y, w, h, SWP_DRAWFRAME);
return;
}
wplat.mainwindow = CreateWindowEx (exstyle, nm, nm, style, x, y, w, h, NULL, NULL, wplat.hInstance, NULL);
if (!wplat.mainwindow) Sys_Error ("Couldn't create DIB window");
}
void WIN_Change_DisplaySettings (int modenum)
{
// Change display settings
wplat.gdevmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
wplat.gdevmode.dmBitsPerPel = vid.modelist[modenum].bpp;
wplat.gdevmode.dmPelsWidth = vid.modelist[modenum].width;
wplat.gdevmode.dmPelsHeight = vid.modelist[modenum].height;
wplat.gdevmode.dmSize = sizeof (DEVMODE);
if (ChangeDisplaySettings (&wplat.gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
Sys_Error ("Couldn't set fullscreen mode %i x %i @ %i bpp", vid.modelist[modenum].width, vid.modelist[modenum].height, vid.modelist[modenum].bpp);
}
// Returns false if need to do GL setup again.
qboolean VID_Local_SetMode (int modenum)
{
qboolean reuseok = false;
RECT client_rect = {0,0,vid.modelist[modenum].width, vid.modelist[modenum].height};
RECT window_rect = client_rect;
qboolean bordered = vid.modelist[modenum].type == MODE_WINDOWED &&
(vid.modelist[modenum].width != vid.desktop.width ||
vid.modelist[modenum].height != vid.desktop.height);
DWORD ExWindowStyle = 0;
DWORD WindowStyle = bordered ? DW_BORDERED : DW_BORDERLESS;
qboolean restart = (wplat.mainwindow != NULL);
// Preserve these for hopeful reuse.
HDC wglHDC = restart ? wglGetCurrentDC() : 0;
HGLRC wglHRC = restart ? wglGetCurrentContext() : 0;
if (restart)
VID_Local_Window_Renderer_Teardown (TEARDOWN_NO_DELETE_GL_CONTEXT);
if (vid.modelist[modenum].type == MODE_FULLSCREEN)
WIN_Change_DisplaySettings (modenum);
AdjustWindowRectEx (&window_rect, WindowStyle, FALSE, ExWindowStyle);
WIN_AdjustRectToCenterScreen(&window_rect);
WIN_Construct_Or_Resize_Window (WindowStyle, ExWindowStyle, window_rect);
if (vid.modelist[modenum].type == MODE_WINDOWED)
ChangeDisplaySettings (NULL, 0);
// clear to black so it isn't empty
wplat.draw_context = GetDC(wplat.mainwindow);
PatBlt (wplat.draw_context, 0, 0, vid.modelist[modenum].width,vid.modelist[modenum].height, BLACKNESS);
// Get focus if we can, get foreground, finish setup, pump messages.
// then sleep a little.
ShowWindow (wplat.mainwindow, SW_SHOWDEFAULT);
UpdateWindow (wplat.mainwindow);
SetWindowPos (wplat.mainwindow, HWND_TOP, 0, 0, 0, 0, SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOCOPYBITS);
SetForegroundWindow (wplat.mainwindow);
{
MSG msg;
while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
Sleep (100);
}
WIN_SetupPixelFormat (wplat.draw_context);
if (wglHRC && (reuseok = wglMakeCurrent (wplat.draw_context, wglHRC)) == 0)
{
// Tried to reuse context and it failed
wglDeleteContext (wglHRC);
wglHRC = NULL;
Con_Printf ("Context reuse failed. Must reload textures.\n");
}
if (!wglHRC)
{
// Must create a context.
wglHRC = wglCreateContext( wplat.draw_context );
if (!wglHRC)
Sys_Error ("Could not initialize GL (wglCreateContext failed).\n\nMake sure you in are 65535 color mode, and try running -window.");
if (!wglMakeCurrent( wplat.draw_context, wglHRC ))
Sys_Error ("VID_Init: wglMakeCurrent failed");
}
return reuseok;
}
//
// in game
//
void VID_Local_SwapBuffers (void)
{
if (SwapBuffers (wplat.draw_context) == 0)
MessageBox (NULL, "Swapbuffers failed", "", MB_OK);
}
void VID_Local_Suspend (qboolean bSuspend)
{
if (bSuspend == false)
{
ChangeDisplaySettings (&wplat.gdevmode, CDS_FULLSCREEN);
ShowWindow(wplat.mainwindow, SW_SHOWNORMAL);
MoveWindow(wplat.mainwindow, 0, 0, wplat.gdevmode.dmPelsWidth, wplat.gdevmode.dmPelsHeight, false); //johnfitz -- alt-tab fix via Baker
} else ChangeDisplaySettings (NULL, 0);
}
//
// window setup
//
BOOL WIN_SetupPixelFormat(HDC hDC)
{
static PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
1, // version number
PFD_DRAW_TO_WINDOW | // support window
PFD_SUPPORT_OPENGL | // support OpenGL
PFD_DOUBLEBUFFER, // double buffered
PFD_TYPE_RGBA, // RGBA type
24, // 24-bit color depth
0, 0, 0, 0, 0, 0, // color bits ignored
0, // no alpha buffer
0, // shift bit ignored
0, // no accumulation buffer
0, 0, 0, 0, // accum bits ignored
32, // 32-bit z-buffer
0, // no stencil buffer
0, // no auxiliary buffer
PFD_MAIN_PLANE, // main layer
0, // reserved
0, 0, 0 // layer masks ignored
};
int pixelformat;
PIXELFORMATDESCRIPTOR test; //johnfitz
if ( (pixelformat = ChoosePixelFormat(hDC, &pfd)) == 0 )
{
MessageBox(NULL, "ChoosePixelFormat failed", "Error", MB_OK);
return FALSE;
}
DescribePixelFormat(hDC, pixelformat, sizeof(PIXELFORMATDESCRIPTOR), &test); //johnfitz
if (SetPixelFormat(hDC, pixelformat, &pfd) == FALSE)
{
MessageBox(NULL, "SetPixelFormat failed", "Error", MB_OK);
return FALSE;
}
return TRUE;
}
void WIN_AdjustRectToCenterScreen (RECT *in_windowrect)
{
vmode_t desktop = VID_Local_GetDesktopProperties ();
int nwidth = in_windowrect->right - in_windowrect->left;
int nheight = in_windowrect->bottom - in_windowrect->top;
in_windowrect->left = 0 + (desktop.width - nwidth) / 2;
in_windowrect->top = 0 + (desktop.height - nheight) / 2;
in_windowrect->right = in_windowrect->left + nwidth;
in_windowrect->bottom = in_windowrect->top + nheight;
}
//
// window teardown
//
void VID_Local_Window_Renderer_Teardown (int destroy)
{
// destroy = 1 = TEARDOWN_FULL else TEARDOWN_NO_DELETE_GL_CONTEXT (don't destroy the context or destroy window)
HGLRC hRC = wglGetCurrentContext();
HDC hDC = wglGetCurrentDC();
wglMakeCurrent(NULL, NULL);
if (hRC && destroy) wglDeleteContext(hRC);
if (hDC) ReleaseDC(wplat.mainwindow, hDC);
if (wplat.draw_context)
{
ReleaseDC (wplat.mainwindow, wplat.draw_context);
wplat.draw_context = NULL;
}
if (destroy)
{
DestroyWindow (wplat.mainwindow);
wplat.mainwindow = NULL;
}
ChangeDisplaySettings (NULL, 0);
}