Thanks for your changes. I'll give them a more complete once over and
get them into CVS soon.
Post by O.SezerPost by Brendan BurnsI agree with Vincent, that Voodoo cards are rarely used. But its worth
* 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
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
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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 ) )
{