[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