GL Gamma Correction
Moderator: InsideQC Admins
41 posts
• Page 3 of 3 • 1, 2, 3
Re: GL Gamma Correction
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 ideasHis 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.
- 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;
}
You might think the platform neutral video code is short because the platform-specific code is long. Except it's not true.
- 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);
}
The hardware gamma stuff annoyed me to death. Now I can sleep at night.
The night is young. How else can I annoy the world before sunsrise?
Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
-

Baker - Posts: 3666
- Joined: Tue Mar 14, 2006 5:15 am
Re: GL Gamma Correction
where's the code to enable anti aliasing?
also, no support for http://www.opengl.org/registry/specs/EX ... l_tear.txt
nor quad-buffered rendering, but I guess drivers fail at that too.
also, no support for http://www.opengl.org/registry/specs/EX ... l_tear.txt
nor quad-buffered rendering, but I guess drivers fail at that too.
- Spike
- Posts: 2892
- Joined: Fri Nov 05, 2004 3:12 am
- Location: UK
Re: GL Gamma Correction
The hardware gamma stuff annoyed me to death. Now I can sleep at night.
Hehe glad i could dig something up that could put your mind at rest
Very short platform code
Productivity is a state of mind.
-

revelator - Posts: 2567
- Joined: Thu Jan 24, 2008 12:04 pm
- Location: inside tha debugger
Re: GL Gamma Correction
Spike wrote:also, no support for http://www.opengl.org/registry/specs/EX ... l_tear.txt
Nice feature
read.. testing... work very nice
-

Barnes - Posts: 226
- Joined: Thu Dec 24, 2009 2:26 pm
- Location: Russia, Moscow
Re: GL Gamma Correction
Hmmm. I've setup multisample before and for some reason, it wasn't in my "frequently used code". Today, I thought I'd give it another shot and I gave it a shot at making it "elegant". But I can't.Spike wrote:where's the code to enable anti aliasing?
I'm not a fan of the flickering screen deal because you have to "create window/check extensions/use the oddball ARB extra pixel format patchwork bandage/destroy window/create window/set the arb bandage" every time. I like ALT-ENTER to switch between fullscreen and windowed mode, but when I do that, I have to have another flicker-fest to repeat that whole process.
At least to me, it's a bit annoying (I use ALT-ENTER a lot, but maybe that is because I'm constantly engine testing ... I don't really do that during "real" use). I think there is some "hide the window" trick out there, though ...
The night is young. How else can I annoy the world before sunsrise?
Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
-

Baker - Posts: 3666
- Joined: Tue Mar 14, 2006 5:15 am
Re: GL Gamma Correction
is the pixel format not the same whether its fullscreen or windowed?
either way, if you're changing the pixel format, you need to completely recreate the gl context.
thank god drivers don't have so many window/context-resized bugs nowadays...
either way, if you're changing the pixel format, you need to completely recreate the gl context.
thank god drivers don't have so many window/context-resized bugs nowadays...
- Spike
- Posts: 2892
- Joined: Fri Nov 05, 2004 3:12 am
- Location: UK
Re: GL Gamma Correction
If you use a 16-bit fullscreen mode and do ALT-ENTER to 32-bit desktop windowed mode. However, perhaps I need to re-evaluate whether or not 16-bit color is relevant in 2013, because it isn't. Perhaps I lose support for bpp switching and you get the desktop bpp no matter what.Spike wrote:is the pixel format not the same whether its fullscreen or windowed?
I'm still considering some sort of trickery for the double window start-up. You know the stupid "loading Quake" window?
I may resurrect it and give it a new purpose in this world, complete with gl context and secret agent instructions.
The night is young. How else can I annoy the world before sunsrise?
Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
-

Baker - Posts: 3666
- Joined: Tue Mar 14, 2006 5:15 am
Re: GL Gamma Correction
loading screens suck. everyone knows that. thus you should get rid of that extra window. 
I can load up a timedemo, play through the entire thing, and get back to the console in the time it takes for my lcd monitor to change video mode.
with computers that fast, please tell me what the point of a splashscreen is.
indeed, much of the time spent loading is spent reading the exe and dlls and stuff (especially if running in msvc's debugger), all of that happens before your (win)main function is even called.
3-second rule. if it takes 3+ seconds for your window/menu/chimpanze to appear, you need a splashscreen that can appear earlier. otherwise you're just wasting cpu cycles making a window appear then disappear. not to mention really messing with input focus.
I can load up a timedemo, play through the entire thing, and get back to the console in the time it takes for my lcd monitor to change video mode.
with computers that fast, please tell me what the point of a splashscreen is.
indeed, much of the time spent loading is spent reading the exe and dlls and stuff (especially if running in msvc's debugger), all of that happens before your (win)main function is even called.
3-second rule. if it takes 3+ seconds for your window/menu/chimpanze to appear, you need a splashscreen that can appear earlier. otherwise you're just wasting cpu cycles making a window appear then disappear. not to mention really messing with input focus.
- Spike
- Posts: 2892
- Joined: Fri Nov 05, 2004 3:12 am
- Location: UK
Re: GL Gamma Correction
re: Starting Quake dialog .... Mine's gone real quick --- although I had removed it.Spike wrote:not to mention really messing with input focus.
Even now, as I resurrected it to give it "secret agent mission" before it goes away to look at multisample availability and get ARB pdf. Achieved very elegant and fast startup with no awkwardness. Works like charm. Looks polished. No flickering during startup because that little "Starting Quake" window goes away during vid init.
- Code: Select all
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");
if (wplat.hwnd_dialog)
{
if (!COM_CheckParm ("-noms")) // temp for testing, no I would not name a command line parameter that stupidly vague ;-) Will become read early cvar.
{
// Poke into it for the PFD
HDC hdc = GetDC(wplat.hwnd_dialog);
int unused = WIN_SetupPixelFormat (hdc);
HGLRC wglHRC = wglCreateContext( hdc );
HDC wglHDC = wglGetCurrentDC();
int unused2 = wglMakeCurrent( hdc, wglHRC);
// Do it. We already have desktop properties
wplat.multisamples = InitMultisample (wplat.hInstance, wplat.hwnd_dialog, wplat.pfd, &wplat.forcePixelFormat);
// Your mission is complete. You may leave now ...
wglMakeCurrent(NULL, NULL);
wglDeleteContext(wglHRC);
ReleaseDC(wplat.hwnd_dialog, wglHDC);
ReleaseDC(wplat.hwnd_dialog, hdc);
if (wplat.multisamples)
Con_Printf ("Enabled: Multisample x %i!\n", wplat.multisamples);
else Con_Printf ("Could not enable multisample\n");
} else Con_Warning ("Multisamples disabled by command line\n");
// Post teardown
DestroyWindow (wplat.hwnd_dialog);
wplat.hwnd_dialog = NULL;
}
}
"Multisampling antialiasing can be costly with marginal benefit at high resolution". Ah. Well, I had read an article talking about how great and with minimal implementation for the benefit, but said article didn't really mention the performance cost.
Still --- this was a great coding exercise and should I ever really get into 2D, multisample is virtually required (who wants jaggy lines with lines, etc.)
Good learning experience, will probably keep engine feature as "read early" cvar that requires engine restart on change to take effect to satisfy whoever wants feature --- as it is nice --- and that way I keep the code I spent a couple of hours on.
I already do that with "sndspeed" cvar now (plus my video cvars, plus scr_brightness so startup doesn't look dumb with brightness changing after config.cfg is read).
I'm rather satisfied with the implementation and I'm glad you pushed me a little to do this.
The night is young. How else can I annoy the world before sunsrise?
Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
-

Baker - Posts: 3666
- Joined: Tue Mar 14, 2006 5:15 am
Re: GL Gamma Correction
as option - use fxaa or if you have nvidia card - csaa
-

Barnes - Posts: 226
- Joined: Thu Dec 24, 2009 2:26 pm
- Location: Russia, Moscow
Re: GL Gamma Correction
Did homework on these learning what they are. Sounds like 4-5 different ever-improved methodologies emerged. When I start working with shaders, will revisit these.Barnes wrote:as option - use fxaa or if you have nvidia card - csaa
My lack of knowledge on the anti-aliasing techniques doesn't mean I'm not interested in them, more than I have been dealing with numerous "run-of-the-mill" issues "getting Quake right". But that is coming to a close, other than some of the networking stuff Spike likes to talk about and that I like to listen to.
The night is young. How else can I annoy the world before sunsrise?
Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
-

Baker - Posts: 3666
- Joined: Tue Mar 14, 2006 5:15 am
41 posts
• Page 3 of 3 • 1, 2, 3
Who is online
Users browsing this forum: No registered users and 1 guest