[quake2] Re: [evil patch] hwgamma hack for voodoo1/voodoo2

Brendan Burns brendanburns at comcast.net
Mon Dec 12 18:51:16 EST 2005


That was quick ;-)
Thanks for your changes.  I'll give them a more complete once over and
get them into CVS soon.

--brendan

On Mon, 2005-12-12 at 19:35 +0200, O.Sezer wrote:
> Brendan Burns wrote:
> > I agree with Vincent, that Voodoo cards are rarely used.  But its worth
> > supporting them if it doesn't break other stuff..  Here's my suggestion:
> > 
> > * Migrate all 3dfx related code out into its own file.
> > (this means removing Check3dfxGamma, Update3dfxGamma from gl_glx.c and
> > moving them to the newly added fx_gamma.c)
> > 
> > * Get rid of GL_GammaInit, add a GL_3dfxInit to fx_gamma.c
> > 
> > * put #ifdef V_3DFX ... #endif around all extern functions related to
> > 3dfx in gl_glx and 
> > 
> > * put an #ifdef'd call to GL_3dfxInit in R_init, likewise for the Update
> > and Shutdown functions.
> > 
> > Can you revise and send a new patch?
> > 
> > Thanks!
> > --brendan
> 
> I revised the patch, which is attached:
> The feature is bound to a Makefile option, defaulting to NO.
> Even if set to yes, it is only enabled on i386-Linux, not on
> anything else. GL_GammaInit() stuff removed, fxgamma decision
> is made while we are in  GLimp_SetMode(). 3dfxGamma is applied
> from within UpdateHardwareGamma().
> I think it's much less intrusive now. If it is to be applied,
> remember that it requires the RTLD_GLOBAL patch pre-applied.
> 
> Cheers,
> Ozkan
> 
> plain text document attachment (q2-3dfxgamma-3.patch)
> diff -urNp quake2~/Makefile quake2/Makefile
> --- quake2~/Makefile	2005-09-07 15:57:40.000000000 +0300
> +++ quake2/Makefile	2005-12-12 18:33:29.000000000 +0200
> @@ -30,6 +30,7 @@ BUILD_AA=NO		# build the ascii soft rend
>  BUILD_QMAX=NO		# build the fancier GL graphics
>  BUILD_RETEXTURE=YES	# build a version supporting retextured graphics
>  BUILD_REDBLUE=NO	# build a red-blue 3d glasses renderer...
> +USE_3DFXGAMMA=NO	# adds hardware gamma support for old Voodoo1/2 boards. linux only
>  STATICSDL=NO
>  SDLDIR=/usr/local/lib
>  
> @@ -254,6 +255,8 @@ ifeq ($(strip $(BUILD_ROGUE)),YES)
>   TARGETS += $(BUILDDIR)/rogue/game$(ARCH).$(SHLIBEXT)
>  endif
>  
> +OBJ_3DFXGAMMA:=
> +
>  ifeq ($(ARCH),axp)
>   ifeq ($(strip $(BUILD_SDLQUAKE2)),YES)
>    $(warning Warning: SDLQuake2 not supported for $(ARCH))
> @@ -402,6 +405,14 @@ ifeq ($(ARCH),i386)
>   ifeq ($(strip $(BUILD_SDLGL)),YES)
>    TARGETS += $(BUILDDIR)/ref_sdlgl.$(SHLIBEXT)
>   endif
> +
> + ifeq ($(OSTYPE),Linux)
> + ifeq ($(strip $(USE_3DFXGAMMA)),YES)
> +  OBJ_3DFXGAMMA:=$(BUILDDIR)/ref_gl/fx_gamma.o 
> +  GLXCFLAGS:=$(GLXCFLAGS) -DUSE_3DFXGAMMA
> + endif
> + endif
> +
>  endif # ARCH i386
>  
>  ifeq ($(strip $(BUILD_AA)),YES)
> @@ -1795,6 +1806,7 @@ REF_GL_OBJS = \
>  
>  REF_GLX_OBJS = \
>  	$(BUILDDIR)/ref_gl/gl_glx.o \
> +	$(OBJ_3DFXGAMMA)\
>  	$(BUILDDIR)/ref_gl/rw_linux.o \
>  	$(BUILDDIR)/ref_gl/joystick.o
>  #	$(BUILDDIR)/ref_gl/rw_x11.o
> @@ -1869,6 +1881,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	1970-01-01 02:00:00.000000000 +0200
> +++ quake2/src/linux/fx_gamma.c	2005-12-12 18:33:29.000000000 +0200
> @@ -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 at 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	2005-01-28 00:35:20.000000000 +0200
> +++ quake2/src/linux/gl_glx.c	2005-12-12 18:33:29.000000000 +0200
> @@ -112,6 +112,12 @@ static XF86VidModeModeInfo **vidmodes;
>  static int num_vidmodes;
>  static qboolean vidmode_active = false;
>  static XF86VidModeGamma oldgamma;
> +#ifdef USE_3DFXGAMMA
> +// evil glide gamma hack
> +extern int  Init_3dfxGammaCtrl(void);
> +extern void Shutdown_3dfxGamma(void);
> +extern int  do3dfxGammaCtrl(float g);
> +#endif
>  
>  static qboolean mouse_active = false;
>  static qboolean dgamouse = false;
> @@ -699,6 +705,7 @@ int GLimp_SetMode( int *pwidth, int *phe
>  		}
>  	}
>  
> +	gl_state.fxgamma = false;
>  	gl_state.hwgamma = false;
>  
>  	/* do some pantsness */
> @@ -766,14 +773,8 @@ int GLimp_SetMode( int *pwidth, int *phe
>  				XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[best_fit]);
>  				vidmode_active = true;
>  
> -				if (XF86VidModeGetGamma(dpy, scrnum, &oldgamma)) {
> +				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);
> @@ -869,6 +870,27 @@ int GLimp_SetMode( int *pwidth, int *phe
>  
>  	qglXMakeCurrent(dpy, win, ctx);
>  
> +#ifdef USE_3DFXGAMMA
> +	if (!Q_strncasecmp ((char *)qglGetString(GL_RENDERER), "Mesa Glide", 10))
> +	{ // attempt to use glide symbols for gamma
> +		gl_state.hwgamma = false;
> +		gl_state.fxgamma = Init_3dfxGammaCtrl();
> +		if (gl_state.fxgamma) {
> +			ri.Con_Printf(PRINT_ALL, "Using 3dfx glide gamma controls\n");
> +		}
> +	}
> +#endif
> +	if (gl_state.hwgamma)
> +		ri.Con_Printf(PRINT_ALL, "Using hardware gamma\n");
> +
> +	if (gl_state.hwgamma || gl_state.fxgamma)
> +	{
> +		/* 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;
> +	}
> +
>  	return rserr_ok;
>  }
>  
> @@ -887,6 +909,11 @@ void GLimp_Shutdown( void )
>  	mouse_active = false;
>  	dgamouse = false;
>  
> +#ifdef USE_3DFXGAMMA
> +	if (gl_state.fxgamma)
> +		Shutdown_3dfxGamma();
> +#endif
> +
>  	if (dpy) {
>  		if (ctx)
>  			qglXDestroyContext(dpy, ctx);
> @@ -980,6 +1007,14 @@ void UpdateHardwareGamma()
>  
>  	g = (1.3 - vid_gamma->value + 1);
>  	g = (g>1 ? g : 1);
> +
> +#ifdef USE_3DFXGAMMA
> +	if (gl_state.fxgamma)
> +	{
> +		do3dfxGammaCtrl (g);
> +		return;
> +	}
> +#endif
>  	gamma.red = oldgamma.red * g;
>  	gamma.green = oldgamma.green * g;
>  	gamma.blue = oldgamma.blue * g;
> diff -urNp quake2~/src/ref_candygl/gl_local.h quake2/src/ref_candygl/gl_local.h
> --- quake2~/src/ref_candygl/gl_local.h	2003-07-12 04:59:52.000000000 +0300
> +++ quake2/src/ref_candygl/gl_local.h	2005-12-12 18:33:29.000000000 +0200
> @@ -525,12 +525,13 @@ typedef struct
>  	qboolean	texture_compression; // Heffo - ARB Texture Compression
>  
> 
> -
>  	unsigned char originalRedGammaTable[256];
>  	unsigned char originalGreenGammaTable[256];
>  	unsigned char originalBlueGammaTable[256];
> -  qboolean hwgamma;
> -  
> +
> +	qboolean hwgamma;
> +	qboolean fxgamma;
> +
>  } glstate_t;
>  
>  extern glconfig_t  gl_config;
> diff -urNp quake2~/src/ref_gl/gl_image.c quake2/src/ref_gl/gl_image.c
> --- quake2~/src/ref_gl/gl_image.c	2004-09-25 01:06:52.000000000 +0300
> +++ quake2/src/ref_gl/gl_image.c	2005-12-12 18:33:29.000000000 +0200
> @@ -1568,14 +1568,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	2005-09-06 16:02:26.000000000 +0300
> +++ quake2/src/ref_gl/gl_local.h	2005-12-12 18:33:29.000000000 +0200
> @@ -432,6 +432,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	2005-09-07 01:46:08.000000000 +0300
> +++ quake2/src/ref_gl/gl_rmain.c	2005-12-12 18:33:29.000000000 +0200
> @@ -1484,7 +1484,7 @@ void R_BeginFrame( float camera_separati
>  	{
>  		vid_gamma->modified = false;
>  
> -		if ( gl_state.hwgamma ) {
> +		if ( gl_state.hwgamma || gl_state.fxgamma) {
>  			UpdateHardwareGamma();
>  		} else if ( gl_config.renderer & ( GL_RENDERER_VOODOO ) )
>  		{




More information about the quake2 mailing list