/* * fx_gamma.c * $Id: fx_gamma.c,v 1.6 2007/07/06 12:45:42 sezero Exp $ * * 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 1 /* actual define is in gl_vidsdl.c */ #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 */