adds native gamma support for 3dfx Voodoo1/2 to tyrquake-0.55 and 0.56 on linux through some glide hacks which are self-contained in the newly created fx_gamma.c. it is a compile time makefile option. also allows voodoo1/2 to be detected and in that case set VID_SetGammaRamp to NULL and made VID_IsFullscreen to return false. tyrquake homepage is at: http://disenchant.net/ diff -urN tyrquake-0.56/Makefile tyrquake-0.56x/Makefile --- tyrquake-0.56/Makefile 2007-02-14 11:26:01.000000000 +0200 +++ tyrquake-0.56x/Makefile 2007-07-06 12:00:44.000000000 +0300 @@ -21,6 +21,7 @@ DEBUG ?= N# Compile with debug info OPTIMIZED_CFLAGS ?= Y# Enable compiler optimisations (if DEBUG != Y) USE_X86_ASM ?= Y# Compile with x86 asm +USE_3DFXGAMMA ?= Y# Whether to allow glide gamma hacks for 3dfx Voodoo1/2 (Linux/BSD only) X11BASE ?= $(X11BASE_GUESS) QBASEDIR ?= .# Default basedir for quake data files (Linux/BSD only) @@ -96,6 +97,9 @@ NQ_UNIX_COMMON_LIBS = m X11 Xext Xxf86dga Xxf86vm NQ_UNIX_GL_LIBS = GL +ifeq ($(USE_3DFXGAMMA),Y) +NQ_UNIX_GL_LIBS+= dl +endif NQ_W32_SW_LFLAGS := $(patsubst %,-l%,$(NQ_W32_SW_LIBS) $(NQ_W32_COMMON_LIBS)) NQ_W32_GL_LFLAGS := $(patsubst %,-l%,$(NQ_W32_GL_LIBS) $(NQ_W32_COMMON_LIBS)) @@ -170,10 +174,17 @@ endif COMMON_CPPFLAGS += -I$(TOPDIR)/include +FLAGS_3DFXGAMMA:= +ifeq ($(TARGET_OS),UNIX) +ifeq ($(USE_3DFXGAMMA),Y) +FLAGS_3DFXGAMMA:=-DUSE_3DFXGAMMA +endif +endif + NQSW_CPPFLAGS := $(COMMON_CPPFLAGS) -DNQ_HACK -NQGL_CPPFLAGS := $(COMMON_CPPFLAGS) -DNQ_HACK -DGLQUAKE +NQGL_CPPFLAGS := $(COMMON_CPPFLAGS) -DNQ_HACK -DGLQUAKE $(FLAGS_3DFXGAMMA) QWSW_CPPFLAGS := $(COMMON_CPPFLAGS) -DQW_HACK -QWGL_CPPFLAGS := $(COMMON_CPPFLAGS) -DQW_HACK -DGLQUAKE +QWGL_CPPFLAGS := $(COMMON_CPPFLAGS) -DQW_HACK -DGLQUAKE $(FLAGS_3DFXGAMMA) QWSV_CPPFLAGS := $(COMMON_CPPFLAGS) -DQW_HACK -DSERVERONLY NQSW_CPPFLAGS += -I$(TOPDIR)/NQ @@ -496,6 +507,7 @@ # Objects only used in OpenGL rendering versions of NQ on the Unix Platform NQ_UNIX_GL_C_OBJS = \ + fx_gamma.o \ gl_vidlinuxglx.o NQ_UNIX_GL_ASM_OBJS = @@ -732,6 +744,7 @@ QW_W32_GL_ASM_OBJS = QW_UNIX_GL_C_OBJS = \ + fx_gamma.o \ gl_vidlinuxglx.o QW_UNIX_GL_ASM_OBJS = @@ -800,6 +813,9 @@ QW_UNIX_COMMON_LIBS = m X11 Xext Xxf86dga Xxf86vm QW_UNIX_GL_LIBS = GL +ifeq ($(USE_3DFXGAMMA),Y) +QW_LINUX_GL_LIBS+= dl +endif QW_W32_SW_LFLAGS := $(patsubst %,-l%,$(QW_W32_SW_LIBS) $(QW_W32_COMMON_LIBS)) QW_W32_GL_LFLAGS := $(patsubst %,-l%,$(QW_W32_GL_LIBS) $(QW_W32_COMMON_LIBS)) diff -urNp tyrquake-0.56/common/gl_vidlinuxglx.c tyrquake-0.56x/common/gl_vidlinuxglx.c --- tyrquake-0.56/common/gl_vidlinuxglx.c 2007-02-14 11:26:01.000000000 +0200 +++ tyrquake-0.56x/common/gl_vidlinuxglx.c 2007-07-06 12:06:14.000000000 +0300 @@ -101,6 +101,7 @@ const char *gl_renderer; const char *gl_version; const char *gl_extensions; +static qboolean is_old3dfx = false; static qboolean is8bit = false; qboolean gl_mtexable = false; static int gl_num_texture_units; @@ -438,6 +439,11 @@ HandleEvents(void) void (*VID_SetGammaRamp)(unsigned short ramp[3][256]); static unsigned short saved_gamma_ramp[3][256]; +#ifdef USE_3DFXGAMMA +/* 3dfx gamma hacks */ +#include "fx_gamma.h" +extern cvar_t v_gamma; +#endif /* USE_3DFXGAMMA */ void signal_handler(int sig) @@ -446,6 +452,10 @@ signal_handler(int sig) XAutoRepeatOn(x_disp); if (VID_SetGammaRamp) VID_SetGammaRamp(saved_gamma_ramp); +#ifdef USE_3DFXGAMMA + if (is_old3dfx) + Shutdown_3dfxGamma(); +#endif /* USE_3DFXGAMMA */ XCloseDisplay(x_disp); Sys_Quit(); exit(0); @@ -559,6 +569,23 @@ CheckMultiTextureExtensions(void) } } +#ifdef USE_3DFXGAMMA +static void +VID_Set3dfxGamma(unsigned short ramp[3][256]) +{ + float g; +# define GAMMA_MAX 3.0 + + /* not using gamma ramps on purpose: crashes with voodoo-1 */ + if (v_gamma.value > (1.0 / GAMMA_MAX)) + g = 1.0 / v_gamma.value; + else + g = GAMMA_MAX; + + do3dfxGammaCtrl (g); +} +#endif /* USE_3DFXGAMMA */ + static void VID_SetXF86GammaRamp(unsigned short ramp[3][256]) { @@ -606,6 +633,28 @@ GL_Init(void) CheckMultiTextureExtensions(); + if (!strncasecmp (gl_renderer, "3dfx", 4) || + !strncasecmp (gl_renderer, "SAGE Glide", 10) || + !strncasecmp (gl_renderer, "Mesa Glide", 10)) + { + int tmp; + /* X gamma is of no use for Mesa Glide which should be Voodoo1/2 */ + if (VID_SetGammaRamp) + VID_SetGammaRamp(saved_gamma_ramp); + VID_SetGammaRamp = NULL; + is_old3dfx = true; + +#ifdef USE_3DFXGAMMA + /* Here is an evil hack to abuse the Glide symbols exposed on us */ + tmp = Init_3dfxGammaCtrl(); + if (Init_3dfxGammaCtrl() > 0) + { + VID_SetGammaRamp = VID_Set3dfxGamma; + Con_Printf ("Using 3dfx glide%d gamma controls\n", tmp); + } +#endif /* USE_3DFXGAMMA */ + } + glClearColor(0.5, 0.5, 0.5, 0); glCullFace(GL_FRONT); glEnable(GL_TEXTURE_2D); @@ -968,6 +1017,10 @@ VID_Shutdown(void) { if (VID_SetGammaRamp) VID_SetGammaRamp(saved_gamma_ramp); +#ifdef USE_3DFXGAMMA + if (is_old3dfx) + Shutdown_3dfxGamma(); +#endif /* USE_3DFXGAMMA */ if (x_disp != NULL) { if (ctx != NULL) @@ -1070,5 +1123,7 @@ VID_LockBuffer() qboolean VID_IsFullScreen() { + if (is_old3dfx) + return true; return vidmode_active; } diff -urNp tyrquake-0.56/common/fx_gamma.c tyrquake-0.56x/common/fx_gamma.c --- tyrquake-0.56/common/fx_gamma.c 1970-01-01 02:00:00.000000000 +0200 +++ tyrquake-0.56x/common/fx_gamma.c 2007-07-06 12:10:38.000000000 +0300 @@ -0,0 +1,214 @@ +/* + * Small library providing gamma control functions for 3Dfx Voodoo1/2 + * cards by abusing the exposed glide symbols when using fxMesa. + * + * Author: O. Sezer License: GPL + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the accompanying COPYING file for more details. + * + * Compiling as a shared library: + * gcc lib3dfxgamma.c -O2 -fPIC -Wall -o lib3dfxgamma.so -shared + * + * 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. + * Besides, the GammaRamp3DFX functions are only available for Glide3: + * Glide2 users cannot benefit them, but the gamma control option is + * available for both Glide2 and Glide3. Therefore employing the gamma + * control option seems more beneficial. + * + * 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. + * v0.0.4, 2006-03-16: Fixed incorrect prototype for the grGet function + * (it takes a signed int param*, not unsigned). + * Also renamed FX_Get to FX_GetInteger to be more + * explicit. + */ + +#include +#include + +#if defined(USE_3DFXGAMMA) + +#include + +#define USE_GAMMA_RAMPS 0 + +#include "fx_gamma.h" + +/**********************************************************************/ + +/** PRIVATE STUFF **/ + +/* 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; + +#if USE_GAMMA_RAMPS +/* 3dfx glide3 funcs to make a replacement wglSetDeviceGammaRamp3DFX */ +#define GR_GAMMA_TABLE_ENTRIES 0x05 +static unsigned int (*FX_GetInteger)(unsigned int, unsigned int, signed 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 *symslist; + int ret = 0; + + if (FX_GammaControl2 != NULL) + return 2; + if (FX_GammaControl3 != NULL) + return 3; + + symslist = (void *) dlopen(NULL, RTLD_LAZY); + if (symslist != NULL) + { + if ((FX_GammaControl2 = (void (*) (float)) dlsym(symslist, "grGammaCorrectionValue")) != NULL) + ret = 2; + else if ((FX_GammaControl3 = (void (*) (float, float, float)) dlsym(symslist, "guGammaCorrectionRGB")) != NULL) + ret = 3; + + dlclose(symslist); + } + else + { /* shouldn't happen. */ + ret = -1; + } + + return ret; +} + +void Shutdown_3dfxGamma (void) +{ + FX_GammaControl2 = NULL; + FX_GammaControl3 = NULL; +#if USE_GAMMA_RAMPS + FX_GetInteger = NULL; + FX_LoadGammaTable = NULL; +#endif +} + +/* + * do3dfxGammaCtrl + */ +void do3dfxGammaCtrl (float value) +{ + if (FX_GammaControl2) + FX_GammaControl2 (value); + else if (FX_GammaControl3) + FX_GammaControl3 (value, value, value); +} + +/**********************************************************************/ +#if USE_GAMMA_RAMPS +static int Check_3DfxGammaRamp (void) +{ + void *symslist; + + if (FX_LoadGammaTable != NULL) + return 1; + + symslist = (void *) dlopen(NULL, RTLD_LAZY); + if (symslist != NULL) + { + FX_GetInteger = (unsigned int (*) (unsigned int, unsigned int, signed int *)) dlsym(symslist, "grGet"); + FX_LoadGammaTable = (void (*) (unsigned int, unsigned int *, unsigned int *, unsigned int *)) dlsym(symslist, "grLoadGammaTable"); + if ((FX_LoadGammaTable != NULL) && (FX_GetInteger != 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_GetInteger == NULL)) + return 0; + + FX_GetInteger (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_GetInteger == 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 /* USE_GAMMA_RAMPS */ + +#endif /* USE_3DFXGAMMA */ + diff -urNp tyrquake-0.56/common/fx_gamma.h tyrquake-0.56x/common/fx_gamma.h --- tyrquake-0.56/common/fx_gamma.h 1970-01-01 02:00:00.000000000 +0200 +++ tyrquake-0.56x/common/fx_gamma.h 2007-07-06 12:04:04.000000000 +0300 @@ -0,0 +1,43 @@ +/* + * Small library providing gamma control functions for 3Dfx Voodoo1/2 + * cards by abusing the exposed glide symbols when using fxMesa. + * Author: O. Sezer License: GPL + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the accompanying COPYING file for more details. + */ + +#ifndef __FXGAMMA_H +#define __FXGAMMA_H + +#ifdef __cplusplus +extern "C" { +#endif + +extern void Shutdown_3dfxGamma (void); + +extern int Init_3dfxGammaCtrl (void); + /* returns 0 for failure, 2 for glide2 or 3 for glide3 api. */ + +extern void do3dfxGammaCtrl (float value); + /* gamma correction procedure. takes the gamma value as its + arg (must be between 1 and 0.333) */ + +#if USE_GAMMA_RAMPS + +extern int glSetDeviceGammaRamp3DFX (void *arrays); + /* returns 1 for success, 0 for failure. */ + +extern int glGetDeviceGammaRamp3DFX (void *arrays); + /* sends a 1.0 gamma table. use for querying the lib. + returns 1 for success, 0 for failure. */ + +#endif /* USE_GAMMA_RAMPS */ + +#ifdef __cplusplus +} +#endif + +#endif /* __FXGAMMA_H */ +