Gamma under OpenGL acceleration

Victor Shkamerda vvs at auto.bnm.org
Thu Apr 18 01:58:03 EDT 2002


>>>Chris Venter <chris at dsp.sun.ac.za> wrote:
>I compiled the r0.0.8 version on my Redhat 7.2 system (which has a 3dfx 
>voodoo banshee). Everything works as advertised, except the screen is 
>_very_ low contrast and dark. Does anybody have an idea of how to up the 
>gamma or some such thing?

Here's the patch that allows to change hardware gamma on the fly a la Quake 3. It's self documented, tested on Red Hat Linux 7.2. Sorry, I'm not sure if this list accepts attachments or not.

=============== 8< CUT HERE >8=============

 * this Linux Quake 2 patch allows to change OpenGL gamma on the fly without
   vid_restart. It uses hardware gamma where available (tested on
   XFree86 4.2.0 with DRI)
 * this is for GLX only, SDL should have its own implementation, based on
   its own gamma manipulation functions
 * this is implemented for fullscreen only. I'm not sure if it should be
   implemented for windowed mode
 * I've got the idea from MrG's BeefQuake for Windows, but the implementation
   is completely mine

diff -ur quake2.orig/src/linux/gl_glx.c quake2/src/linux/gl_glx.c
--- quake2.orig/src/linux/gl_glx.c	Wed Feb 13 11:58:08 2002
+++ quake2/src/linux/gl_glx.c	Sun Apr  7 17:32:54 2002
@@ -98,6 +98,7 @@
 static XF86VidModeModeInfo **vidmodes;
 static int num_vidmodes;
 static qboolean vidmode_active = false;
+static XF86VidModeGamma oldgamma;
 
 static qboolean	mlooking;
 
@@ -738,6 +739,8 @@
 		return rserr_invalid_mode;
 	}
 
+	gl_state.hwgamma = false;
+
 	if (vidmode_ext) {
 		int best_fit, best_dist, dist, x, y;
 		
@@ -770,6 +773,15 @@
 				XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[best_fit]);
 				vidmode_active = true;
 
+				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);
 			} else
@@ -887,6 +899,12 @@
 			qglXDestroyContext(dpy, ctx);
 		if (win)
 			XDestroyWindow(dpy, win);
+		if (gl_state.hwgamma) {
+			XF86VidModeSetGamma(dpy, scrnum, &oldgamma);
+			/* The gamma has changed, but SetMode will change it
+			   anyway, so why bother?
+			vid_gamma->modified = true; */
+		}
 		if (vidmode_active)
 			XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[0]);
 		XUngrabKeyboard(dpy, CurrentTime);
@@ -953,6 +971,28 @@
 }
 
 /*
+** UpdateHardwareGamma
+**
+** We are using gamma relative to the desktop, so that we can share it
+** with software renderer and don't require to change desktop gamma
+** to match hardware gamma image brightness. It seems that Quake 3 is
+** using the opposite approach, but it has no software renderer after
+** all.
+*/
+void UpdateHardwareGamma()
+{
+	XF86VidModeGamma gamma;
+	float g;
+
+	g = (1.3 - vid_gamma->value + 1);
+	g = (g>1 ? g : 1);
+	gamma.red = oldgamma.red * g;
+	gamma.green = oldgamma.green * g;
+	gamma.blue = oldgamma.blue * g;
+	XF86VidModeSetGamma(dpy, scrnum, &gamma);
+}
+
+/*
 ** GLimp_AppActivate
 */
 void GLimp_AppActivate( qboolean active )
diff -ur quake2.orig/src/linux/vid_menu.c quake2/src/linux/vid_menu.c
--- quake2.orig/src/linux/vid_menu.c	Mon Jan 14 15:20:18 2002
+++ quake2/src/linux/vid_menu.c	Sun Apr  7 17:35:23 2002
@@ -89,7 +89,8 @@
 
 	if ( stricmp( vid_ref->string, "soft" ) == 0 ||
 		 stricmp( vid_ref->string, "softx" ) == 0 ||
-		 stricmp( vid_ref->string, "softsdl" ) == 0 )
+		 stricmp( vid_ref->string, "softsdl" ) == 0 ||
+		 stricmp( vid_ref->string, "glx" ) == 0 )
 	{
 		float gamma = ( 0.8 - ( slider->curvalue/10.0 - 0.5 ) ) + 0.5;
 
diff -ur quake2.orig/src/ref_gl/gl_image.c quake2/src/ref_gl/gl_image.c
--- quake2.orig/src/ref_gl/gl_image.c	Fri Jan  4 14:46:15 2002
+++ quake2/src/ref_gl/gl_image.c	Sun Apr  7 16:16:43 2002
@@ -1542,7 +1542,7 @@
 
 	for ( i = 0; i < 256; i++ )
 	{
-		if ( g == 1 )
+		if ( g == 1 || gl_state.hwgamma )
 		{
 			gammatable[i] = i;
 		}
diff -ur quake2.orig/src/ref_gl/gl_local.h quake2/src/ref_gl/gl_local.h
--- quake2.orig/src/ref_gl/gl_local.h	Mon Apr  1 15:14:53 2002
+++ quake2/src/ref_gl/gl_local.h	Sun Apr  7 16:18:11 2002
@@ -426,6 +426,8 @@
 	float camera_separation;
 	qboolean stereo_enabled;
 
+	qboolean hwgamma;
+
 	unsigned char originalRedGammaTable[256];
 	unsigned char originalGreenGammaTable[256];
 	unsigned char originalBlueGammaTable[256];
diff -ur quake2.orig/src/ref_gl/gl_rmain.c quake2/src/ref_gl/gl_rmain.c
--- quake2.orig/src/ref_gl/gl_rmain.c	Fri Jan  4 14:46:17 2002
+++ quake2/src/ref_gl/gl_rmain.c	Sun Apr  7 16:17:48 2002
@@ -1439,6 +1439,8 @@
 R_BeginFrame
 @@@@@@@@@@@@@@@@@@@@@
 */
+extern void UpdateHardwareGamma();
+
 void R_BeginFrame( float camera_separation )
 {
 
@@ -1474,7 +1476,9 @@
 	{
 		vid_gamma->modified = false;
 
-		if ( gl_config.renderer & ( GL_RENDERER_VOODOO ) )
+		if ( gl_state.hwgamma ) {
+			UpdateHardwareGamma();
+		} else if ( gl_config.renderer & ( GL_RENDERER_VOODOO ) )
 		{
 			char envbuffer[1024];
 			float g;
=============== 8< CUT HERE >8=============




More information about the quake2 mailing list