diff -urNp quake2~/Makefile quake2/Makefile
--- quake2~/Makefile	Mon Dec  5 21:29:10 2005
+++ quake2/Makefile	Mon Dec  5 21:53:34 2005
@@ -1777,6 +1777,7 @@ REF_GL_OBJS = \
 
 REF_GLX_OBJS = \
 	$(BUILDDIR)/ref_gl/gl_glx.o \
+	$(BUILDDIR)/ref_gl/fx_gamma.o \
 	$(BUILDDIR)/ref_gl/rw_linux.o \
 	$(BUILDDIR)/ref_gl/joystick.o
 #	$(BUILDDIR)/ref_gl/rw_x11.o
@@ -1851,6 +1852,9 @@ $(BUILDDIR)/ref_gl/glob.o :           $(
 $(BUILDDIR)/ref_gl/gl_glx.o :         $(LINUX_DIR)/gl_glx.c
 	$(DO_GL_SHLIB_CC) $(GLXCFLAGS)
 
+$(BUILDDIR)/ref_gl/fx_gamma.o :       $(LINUX_DIR)/fx_gamma.c
+	$(DO_GL_SHLIB_CC) $(GLXCFLAGS)
+
 $(BUILDDIR)/ref_gl/rw_linux.o :     $(LINUX_DIR)/rw_linux.c
 	$(DO_GL_SHLIB_CC) $(XCFLAGS)
 
diff -urNp quake2~/src/linux/fx_gamma.c quake2/src/linux/fx_gamma.c
--- quake2~/src/linux/fx_gamma.c	Thu Jan  1 02:00:00 1970
+++ quake2/src/linux/fx_gamma.c	Mon Dec  5 22:36:35 2005
@@ -0,0 +1,193 @@
+/*
+ * Small library providing gamma control functions for 3Dfx Voodoo1/2
+ * cards by abusing the exposed glide symbols when using fxMesa.
+ * Author: O. Sezer <sezero@users.sourceforge.net>	License: GPL
+ *
+ * This version is for compiling into an application
+ *
+ * How to use:
+ * If you are linking to the opengl library at compile time (-lGL),
+ * not much is necessary. If you dlopen() the opengl library, then
+ * RTLD_GLOBAL flag is necessary so that the library's symbols would be
+ * available to you: SDL_GL_LoadLibrary() is just fine in this regard.
+ * In either case, if the gllib is an fxMesa library, then you will have
+ * the necessary glide symbols exposed on you. Decide whether you have
+ * a Voodoo1/2 and then use the functions here.
+ *
+ * Issues:
+ * glSetDeviceGammaRamp3DFX works nicely with Voodoo2, but it crashes
+ * Voodoo1. The ramp functions are added for completeness sake anyway.
+ * do3dfxGammaCtrl works just fine for both Voodoo1 and Voodoo2.
+ *
+ * Revision history:
+ * v0.0.1, 2005-06-04:	Initial version, do3dfxGammaCtrl works fine,
+ *			glGetDeviceGammaRamp3DFX & co need more care
+ * v0.0.2, 2005-06-13:	tried following the exact win32 versions for
+ *			glGetDeviceGammaRamp3DFX/glSetDeviceGammaRamp3DFX
+ * v0.0.3, 2005-12-05:	Updated documentation about the RTLD_GLOBAL flag.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+
+/**********************************************************************/
+
+// 3dfx glide2 func for gamma correction
+static void (*FX_GammaControl2)(float) = NULL;
+// 3dfx glide3 func for gamma correction
+static void (*FX_GammaControl3)(float,float,float) = NULL;
+
+#define USE_GAMMA_RAMPS		0
+
+#if USE_GAMMA_RAMPS
+// 3dfx glide3 funcs to make a replacement wglSetDeviceGammaRamp3DFX
+#define GR_GAMMA_TABLE_ENTRIES	0x05
+static unsigned int (*FX_Get)(unsigned int, unsigned int, unsigned int *) = NULL;
+static void (*FX_LoadGammaTable)(unsigned int, unsigned int*, unsigned int*, unsigned int*) = NULL;
+#endif
+
+/**********************************************************************/
+
+/*
+ * Init_3dfxGammaCtrl
+ * Sends 0 for failure, 2 for glide2 or 3 for glide3 api.
+ */
+int Init_3dfxGammaCtrl (void)
+{
+	void *prjobj;
+	int ret = 0;
+
+	if (FX_GammaControl2 != NULL)
+		return 2;
+	if (FX_GammaControl3 != NULL)
+		return 3;
+
+	prjobj = dlopen(NULL, RTLD_LAZY);
+	if (prjobj != NULL)
+	{
+		if ((FX_GammaControl2 = dlsym(prjobj, "grGammaCorrectionValue")) != NULL)
+			ret = 2;
+		else if ((FX_GammaControl3 = dlsym(prjobj, "guGammaCorrectionRGB")) != NULL)
+			ret = 3;
+
+		dlclose(prjobj);
+	}
+	else
+	{	// shouldn't happen.
+		ret = -1;
+	}
+
+	return ret;
+}
+
+void Shutdown_3dfxGamma (void)
+{
+	FX_GammaControl2 = NULL;
+	FX_GammaControl3 = NULL;
+#if USE_GAMMA_RAMPS
+	FX_Get = NULL;
+	FX_LoadGammaTable = NULL;
+#endif
+}
+
+/*
+ * do3dfxGammaCtrl
+ */
+int do3dfxGammaCtrl(float value)
+{
+	if (FX_GammaControl2)
+		FX_GammaControl2 (value);
+	else if (FX_GammaControl3)
+		FX_GammaControl3 (value,value,value);
+
+	return 0;
+}
+
+/**********************************************************************/
+#if USE_GAMMA_RAMPS
+static int Check_3DfxGammaRamp (void)
+{
+	void *prjobj;
+
+	if (FX_LoadGammaTable != NULL)
+		return 1;
+
+	prjobj = dlopen(NULL, RTLD_LAZY);
+	if (prjobj != NULL)
+	{
+		FX_Get = dlsym(prjobj, "grGet");
+		FX_LoadGammaTable = dlsym(prjobj, "grLoadGammaTable");
+		if ((FX_LoadGammaTable != NULL) && (FX_Get != NULL))
+			return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * glSetDeviceGammaRamp3DFX is adapted from Mesa-6.x
+ *
+ * glSetDeviceGammaRamp3DFX crashes Voodoo1, at least
+ * currently, so it is not recommended yet.
+ */
+int glSetDeviceGammaRamp3DFX (void *arrays)
+{
+	int tableSize = 0;
+	int i, inc, idx;
+	unsigned short *red, *green, *blue;
+	unsigned int gammaTableR[256], gammaTableG[256], gammaTableB[256];
+
+	if ((FX_LoadGammaTable == NULL) || (FX_Get == NULL))
+		return 0;
+
+	FX_Get (GR_GAMMA_TABLE_ENTRIES, 4, &tableSize);
+	if (!tableSize)
+		return 0;
+
+	inc = 256 / tableSize;
+
+	red = (unsigned short *)arrays;
+	green = (unsigned short *)arrays + 256;
+	blue = (unsigned short *)arrays + 512;
+
+	for (i = 0, idx = 0; i < tableSize; i++, idx += inc)
+	{
+		gammaTableR[i] = red[idx] >> 8;
+		gammaTableG[i] = green[idx] >> 8;
+		gammaTableB[i] = blue[idx] >> 8;
+	}
+
+	FX_LoadGammaTable(tableSize, gammaTableR, gammaTableG, gammaTableB);
+
+	return 1;
+}
+
+/*
+ * glGetDeviceGammaRamp3DFX
+ * Sends a 1.0 gamma table. Also to be used for querying the lib.
+ */
+int glGetDeviceGammaRamp3DFX (void *arrays)
+{
+	int	i;
+	unsigned short	gammaTable[3][256];
+
+	if ((FX_LoadGammaTable == NULL) || (FX_Get == NULL))
+	{
+		if (Check_3DfxGammaRamp() == 0)
+			return 0;
+	}
+
+	for (i=0 ; i<256 ; i++)
+	{
+		 gammaTable[0][i] = i << 8;
+		 gammaTable[1][i] = i << 8;
+		 gammaTable[2][i] = i << 8;
+	}
+
+	memcpy(arrays, gammaTable, 3*256*sizeof(unsigned short));
+
+	return 1;
+}
+#endif
+
diff -urNp quake2~/src/linux/gl_glx.c quake2/src/linux/gl_glx.c
--- quake2~/src/linux/gl_glx.c	Mon Dec  5 21:29:15 2005
+++ quake2/src/linux/gl_glx.c	Mon Dec  5 21:58:59 2005
@@ -111,6 +111,11 @@ static XF86VidModeModeInfo **vidmodes;
 static int num_vidmodes;
 static qboolean vidmode_active = false;
 static XF86VidModeGamma oldgamma;
+// evil glide gamma hack
+extern int  Init_3dfxGammaCtrl(void);
+extern void Shutdown_3dfxGamma(void);
+extern int  do3dfxGammaCtrl(float g);
+static qboolean Check3dfxGamma(void);
 
 static qboolean mouse_active = false;
 static qboolean dgamouse = false;
@@ -606,6 +611,25 @@ static void InitSig(void)
 	signal(SIGTERM, signal_handler);
 }
 
+static qboolean Check3dfxGamma(void)
+{
+	int	ret;
+
+//	if ( ! COM_CheckParm("-3dfxgamma") )
+//		return false;
+
+	ret = Init_3dfxGammaCtrl();
+	switch (ret)
+	{
+		case 2:	// Glide2x
+		case 3:	// Glide3x
+			return true;
+	}
+
+	Com_Printf ("3DfxGammaCtrl returned %i\n3dfxGamma not available\n", ret);
+	return false;
+}
+
 /*
 ** GLimp_SetMode
 */
@@ -698,6 +722,7 @@ int GLimp_SetMode( int *pwidth, int *phe
 		}
 	}
 
+	gl_state.fxgamma = false;
 	gl_state.hwgamma = false;
 
 	/* do some pantsness */
@@ -765,15 +790,6 @@ int GLimp_SetMode( int *pwidth, int *phe
 				XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[best_fit]);
 				vidmode_active = true;
 
-				if (XF86VidModeGetGamma(dpy, scrnum, &oldgamma)) {
-					gl_state.hwgamma = true;
-					/* We can not reliably detect hardware gamma
-					   changes across software gamma calls, which
-					   can reset the flag, so change it anyway */
-					vid_gamma->modified = true;
-					ri.Con_Printf( PRINT_ALL, "Using hardware gamma\n");
-				}
-
 				// Move the viewport to top left
 				XF86VidModeSetViewPort(dpy, scrnum, 0, 0);
 			} else
@@ -871,6 +887,31 @@ int GLimp_SetMode( int *pwidth, int *phe
 	return rserr_ok;
 }
 
+void GL_GammaInit (void)
+{
+	//if (strstr(gl_config.renderer_string, "Mesa Glide"))
+	if (!Q_strncasecmp (gl_config.renderer_string, "Mesa Glide", 10))
+	{ // attempt to use glide symbols for gamma
+		gl_state.fxgamma = Check3dfxGamma();
+		if (gl_state.fxgamma) {
+			Com_Printf("using 3dfx glide gamma controls\n");
+			vid_gamma->modified = true;
+		}
+	}
+	else if (vidmode_ext)
+	{
+		if (XF86VidModeGetGamma(dpy, scrnum, &oldgamma))
+		{
+			gl_state.hwgamma = true;
+			/* We can not reliably detect hardware gamma
+			   changes across software gamma calls, which
+			   can reset the flag, so change it anyway */
+			vid_gamma->modified = true;
+			ri.Con_Printf( PRINT_ALL, "Using hardware gamma\n");
+		}
+	}
+}
+
 /*
 ** GLimp_Shutdown
 **
@@ -886,6 +927,9 @@ void GLimp_Shutdown( void )
 	mouse_active = false;
 	dgamouse = false;
 
+	if (gl_state.fxgamma)
+		Shutdown_3dfxGamma();
+
 	if (dpy) {
 		if (ctx)
 			qglXDestroyContext(dpy, ctx);
@@ -985,6 +1029,24 @@ void UpdateHardwareGamma()
 	XF86VidModeSetGamma(dpy, scrnum, &gamma);
 }
 
+void Update3dfxGamma(void)
+{
+	float g;
+
+	if (!gl_state.fxgamma)
+		return;
+
+	g = (1.3 - vid_gamma->value + 1);
+	g = (g>1 ? g : 1);
+
+/*	if ((vid_gamma->value != 0)&&(vid_gamma->value > (1/GAMMA_MAX)))
+		g = 1.0/vid_gamma->value;
+	else
+		g = GAMMA_MAX;
+*/
+	do3dfxGammaCtrl (g);
+}
+
 /*
 ** GLimp_AppActivate
 */
diff -urNp quake2~/src/ref_candygl/gl_image.c quake2/src/ref_candygl/gl_image.c
--- quake2~/src/ref_candygl/gl_image.c	Wed Jul 23 00:55:42 2003
+++ quake2/src/ref_candygl/gl_image.c	Mon Dec  5 21:30:11 2005
@@ -1893,7 +1893,8 @@ void	GL_InitImages (void)
 			ri.Sys_Error( ERR_FATAL, "Couldn't load pics/16to8.pcx");
 	}
 
-	if ( gl_config.renderer & ( GL_RENDERER_VOODOO | GL_RENDERER_VOODOO2 ) )
+	if (( gl_config.renderer & ( GL_RENDERER_VOODOO | GL_RENDERER_VOODOO2 ) )
+	    && !gl_state.fxgamma)
 	{
 		g = 1.0F;
 	}
diff -urNp quake2~/src/ref_candygl/gl_local.h quake2/src/ref_candygl/gl_local.h
--- quake2~/src/ref_candygl/gl_local.h	Sat Jul 12 04:59:52 2003
+++ quake2/src/ref_candygl/gl_local.h	Mon Dec  5 21:30:11 2005
@@ -530,6 +530,7 @@ typedef struct
 	unsigned char originalGreenGammaTable[256];
 	unsigned char originalBlueGammaTable[256];
   qboolean hwgamma;
+  qboolean fxgamma;
   
 } glstate_t;
 
diff -urNp quake2~/src/ref_gl/gl_image.c quake2/src/ref_gl/gl_image.c
--- quake2~/src/ref_gl/gl_image.c	Mon Dec  5 21:29:15 2005
+++ quake2/src/ref_gl/gl_image.c	Mon Dec  5 21:30:11 2005
@@ -1558,14 +1558,15 @@ void	GL_InitImages (void)
 			ri.Sys_Error( ERR_FATAL, "Couldn't load pics/16to8.pcx");
 	}
 
-	if ( gl_config.renderer & ( GL_RENDERER_VOODOO | GL_RENDERER_VOODOO2 ) )
+	if ( ( gl_config.renderer & ( GL_RENDERER_VOODOO | GL_RENDERER_VOODOO2 ) )
+	    && !gl_state.fxgamma)
 	{
 		g = 1.0F;
 	}
 
 	for ( i = 0; i < 256; i++ )
 	{
-		if ( g == 1 || gl_state.hwgamma )
+		if ( g == 1 || gl_state.hwgamma || gl_state.fxgamma)
 		{
 			gammatable[i] = i;
 		}
diff -urNp quake2~/src/ref_gl/gl_local.h quake2/src/ref_gl/gl_local.h
--- quake2~/src/ref_gl/gl_local.h	Sun May  2 22:36:53 2004
+++ quake2/src/ref_gl/gl_local.h	Mon Dec  5 21:30:11 2005
@@ -430,6 +430,7 @@ typedef struct
 	qboolean stereo_enabled;
 
 	qboolean hwgamma;
+	qboolean fxgamma;	// hack to use glide symbols exposed upon us
 
 	unsigned char originalRedGammaTable[256];
 	unsigned char originalGreenGammaTable[256];
diff -urNp quake2~/src/ref_gl/gl_rmain.c quake2/src/ref_gl/gl_rmain.c
--- quake2~/src/ref_gl/gl_rmain.c	Wed Sep 22 00:32:01 2004
+++ quake2/src/ref_gl/gl_rmain.c	Mon Dec  5 21:30:11 2005
@@ -1112,6 +1112,7 @@ qboolean R_SetMode (void)
 	return true;
 }
 
+extern void GL_GammaInit(void);
 /*
 ===============
 R_Init
@@ -1176,6 +1177,8 @@ int R_Init( void *hinstance, void *hWnd 
 	gl_config.extensions_string = (char *)qglGetString (GL_EXTENSIONS);
 	ri.Con_Printf (PRINT_ALL, "GL_EXTENSIONS: %s\n", gl_config.extensions_string );
 
+	GL_GammaInit();
+
 	strncpy( renderer_buffer, gl_config.renderer_string, sizeof(renderer_buffer) );
 	renderer_buffer[sizeof(renderer_buffer)-1] = 0;
 	strlwr( renderer_buffer );
@@ -1448,6 +1451,7 @@ void R_Shutdown (void)
 R_BeginFrame
 @@@@@@@@@@@@@@@@@@@@@
 */
+extern void Update3dfxGamma();
 extern void UpdateHardwareGamma();
 
 void R_BeginFrame( float camera_separation )
@@ -1487,6 +1491,8 @@ void R_BeginFrame( float camera_separati
 
 		if ( gl_state.hwgamma ) {
 			UpdateHardwareGamma();
+		} else if ( gl_state.fxgamma ) {
+			Update3dfxGamma();
 		} else if ( gl_config.renderer & ( GL_RENDERER_VOODOO ) )
 		{
 			char envbuffer[1024];
