]> git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
UNMERGE! Remove v_hwgamma feature as it is not worth maintaining and has severe restr...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Tue, 3 Apr 2018 05:33:43 +0000 (05:33 +0000)
committerRudolf Polzer <divVerent@xonotic.org>
Tue, 3 Apr 2018 14:26:24 +0000 (07:26 -0700)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@12359 d7cf8633-e32d-0410-b094-e92efae38249
::stable-branch::unmerge=77af8a073b9006fbdf7aa2e7bc92dba2f22b25af

cl_screen.c
gl_draw.c
menu.c
vid.h
vid_agl.c
vid_glx.c
vid_null.c
vid_sdl.c
vid_shared.c
vid_wgl.c

index 771d27c927ece82b57722d31cfbaa212454ca4ae..68bf62da5493fc3c1a9adb12c4d094401a1f470c 100644 (file)
@@ -56,6 +56,7 @@ cvar_t scr_screenshot_jpeg = {CVAR_SAVE, "scr_screenshot_jpeg","1", "save jpeg i
 cvar_t scr_screenshot_jpeg_quality = {CVAR_SAVE, "scr_screenshot_jpeg_quality","0.9", "image quality of saved jpeg"};
 cvar_t scr_screenshot_png = {CVAR_SAVE, "scr_screenshot_png","0", "save png instead of targa"};
 cvar_t scr_screenshot_gammaboost = {CVAR_SAVE, "scr_screenshot_gammaboost","1", "gamma correction on saved screenshots and videos, 1.0 saves unmodified images"};
+cvar_t scr_screenshot_hwgamma = {CVAR_SAVE, "scr_screenshot_hwgamma","1", "apply the video gamma ramp to saved screenshots and videos"};
 cvar_t scr_screenshot_alpha = {0, "scr_screenshot_alpha","0", "try to write an alpha channel to screenshots (debugging feature)"};
 cvar_t scr_screenshot_timestamp = {CVAR_SAVE, "scr_screenshot_timestamp", "1", "use a timestamp based number of the type YYYYMMDDHHMMSSsss instead of sequential numbering"};
 // scr_screenshot_name is defined in fs.c
@@ -115,6 +116,7 @@ cvar_t r_speeds_graph_maxdefault = {CVAR_SAVE, "r_speeds_graph_maxdefault", "100
 extern cvar_t v_glslgamma;
 extern cvar_t sbar_info_pos;
 extern cvar_t r_fog_clear;
+#define WANT_SCREENSHOT_HWGAMMA (scr_screenshot_hwgamma.integer && vid_usinghwgamma)
 
 int jpeg_supported = false;
 
@@ -1362,6 +1364,7 @@ void CL_Screen_Init(void)
        Cvar_RegisterVariable (&scr_screenshot_jpeg_quality);
        Cvar_RegisterVariable (&scr_screenshot_png);
        Cvar_RegisterVariable (&scr_screenshot_gammaboost);
+       Cvar_RegisterVariable (&scr_screenshot_hwgamma);
        Cvar_RegisterVariable (&scr_screenshot_name_in_mapdir);
        Cvar_RegisterVariable (&scr_screenshot_alpha);
        Cvar_RegisterVariable (&scr_screenshot_timestamp);
@@ -1608,10 +1611,17 @@ Cb = R * -.169 + G * -.332 + B *  .500 + 128.;
 Cr = R *  .500 + G * -.419 + B * -.0813 + 128.;
 */
 
-       // identity gamma table
-       BuildGammaTable16(1.0f, 1.0f, 1.0f, 0.0f, 1.0f, cls.capturevideo.vidramp, 256);
-       BuildGammaTable16(1.0f, 1.0f, 1.0f, 0.0f, 1.0f, cls.capturevideo.vidramp + 256, 256);
-       BuildGammaTable16(1.0f, 1.0f, 1.0f, 0.0f, 1.0f, cls.capturevideo.vidramp + 256*2, 256);
+       if(WANT_SCREENSHOT_HWGAMMA)
+       {
+               VID_BuildGammaTables(&cls.capturevideo.vidramp[0], 256);
+       }
+       else
+       {
+               // identity gamma table
+               BuildGammaTable16(1.0f, 1.0f, 1.0f, 0.0f, 1.0f, cls.capturevideo.vidramp, 256);
+               BuildGammaTable16(1.0f, 1.0f, 1.0f, 0.0f, 1.0f, cls.capturevideo.vidramp + 256, 256);
+               BuildGammaTable16(1.0f, 1.0f, 1.0f, 0.0f, 1.0f, cls.capturevideo.vidramp + 256*2, 256);
+       }
        if(scr_screenshot_gammaboost.value != 1)
        {
                double igamma = 1 / scr_screenshot_gammaboost.value;
@@ -1997,15 +2007,22 @@ qboolean SCR_ScreenShot(char *filename, unsigned char *buffer1, unsigned char *b
 
        GL_ReadPixelsBGRA(x, y, width, height, buffer1);
 
-       if(gammacorrect && (scr_screenshot_gammaboost.value != 1))
+       if(gammacorrect && (scr_screenshot_gammaboost.value != 1 || WANT_SCREENSHOT_HWGAMMA))
        {
                int i;
                double igamma = 1.0 / scr_screenshot_gammaboost.value;
                unsigned short vidramp[256 * 3];
-               // identity gamma table
-               BuildGammaTable16(1.0f, 1.0f, 1.0f, 0.0f, 1.0f, vidramp, 256);
-               BuildGammaTable16(1.0f, 1.0f, 1.0f, 0.0f, 1.0f, vidramp + 256, 256);
-               BuildGammaTable16(1.0f, 1.0f, 1.0f, 0.0f, 1.0f, vidramp + 256*2, 256);
+               if(WANT_SCREENSHOT_HWGAMMA)
+               {
+                       VID_BuildGammaTables(&vidramp[0], 256);
+               }
+               else
+               {
+                       // identity gamma table
+                       BuildGammaTable16(1.0f, 1.0f, 1.0f, 0.0f, 1.0f, vidramp, 256);
+                       BuildGammaTable16(1.0f, 1.0f, 1.0f, 0.0f, 1.0f, vidramp + 256, 256);
+                       BuildGammaTable16(1.0f, 1.0f, 1.0f, 0.0f, 1.0f, vidramp + 256*2, 256);
+               }
                if(scr_screenshot_gammaboost.value != 1)
                {
                        for (i = 0;i < 256 * 3;i++)
index 66f6de4f915cea1cdac0538a51d408febcd9d0b4..eae39c7490bc1c03c7a29d5775a07eac5663ebc7 100644 (file)
--- a/gl_draw.c
+++ b/gl_draw.c
@@ -2167,11 +2167,13 @@ void R_DrawGamma(void)
        case RENDERPATH_D3D10:
        case RENDERPATH_D3D11:
        case RENDERPATH_GLES2:
-               if (v_glslgamma.integer)
+               if (vid_usinghwgamma || v_glslgamma.integer)
                        return;
                break;
        case RENDERPATH_GL11:
        case RENDERPATH_GL13:
+               if (vid_usinghwgamma)
+                       return;
                break;
        case RENDERPATH_GLES1:
        case RENDERPATH_SOFT:
diff --git a/menu.c b/menu.c
index 5ad0755ae45f138a1021e173c5a5a9afed462b57..44b5f568464a3ce87a021fedb7747df9a8185db4 100644 (file)
--- a/menu.c
+++ b/menu.c
@@ -2124,6 +2124,8 @@ static void M_Menu_Options_ColorControl_AdjustSliders (int dir)
 
        optnum = 1;
        if (options_colorcontrol_cursor == optnum++)
+               Cvar_SetValueQuick (&v_hwgamma, !v_hwgamma.integer);
+       else if (options_colorcontrol_cursor == optnum++)
        {
                Cvar_SetValueQuick (&v_color_enable, 0);
                Cvar_SetValueQuick (&v_gamma, bound(1, v_gamma.value + dir * 0.125, 5));
@@ -2234,6 +2236,7 @@ static void M_Options_ColorControl_Draw (void)
        m_opty = 32 - bound(0, m_optcursor - (visible >> 1), max(0, OPTIONS_COLORCONTROL_ITEMS - visible)) * 8;
 
        M_Options_PrintCommand( "     Reset to defaults", true);
+       M_Options_PrintCheckbox("Hardware Gamma Control", vid_hardwaregammasupported.integer, v_hwgamma.integer);
        M_Options_PrintSlider(  "                 Gamma", !v_color_enable.integer, v_gamma.value, 1, 5);
        M_Options_PrintSlider(  "              Contrast", !v_color_enable.integer, v_contrast.value, 1, 5);
        M_Options_PrintSlider(  "            Brightness", !v_color_enable.integer, v_brightness.value, 0, 0.8);
@@ -2267,7 +2270,8 @@ static void M_Options_ColorControl_Draw (void)
        c[0] = menu_options_colorcontrol_correctionvalue.value; // intensity value that should be matched up to a 50% dither to 'correct' quake
        c[1] = c[0];
        c[2] = c[1];
-       VID_ApplyGammaToColor(c, c);
+       if (!(vid_hardwaregammasupported.integer && v_hwgamma.integer))
+               VID_ApplyGammaToColor(c, c);
        s = (float) 48 / 2 * vid.width / vid_conwidth.integer;
        t = (float) 48 / 2 * vid.height / vid_conheight.integer;
        u = s * 0.5;
@@ -2305,6 +2309,7 @@ static void M_Options_ColorControl_Key (int k, int ascii)
                switch (options_colorcontrol_cursor)
                {
                case 0:
+                       Cvar_SetValueQuick(&v_hwgamma, 1);
                        Cvar_SetValueQuick(&v_gamma, 1);
                        Cvar_SetValueQuick(&v_contrast, 1);
                        Cvar_SetValueQuick(&v_brightness, 0);
diff --git a/vid.h b/vid.h
index 91c42f0a932558b968e7a2d63a0373327cfe0cfb..73999c4880a6557715e73b004d47b3698ad5d89c 100644 (file)
--- a/vid.h
+++ b/vid.h
@@ -111,8 +111,8 @@ typedef struct viddef_s
        qboolean stencil;
        qboolean sRGB2D; // whether 2D rendering is sRGB corrected (based on sRGBcapable2D)
        qboolean sRGB3D; // whether 3D rendering is sRGB corrected (based on sRGBcapable3D)
-       qboolean sRGBcapable2D; // whether 2D rendering can be sRGB corrected (renderpath)
-       qboolean sRGBcapable3D; // whether 3D rendering can be sRGB corrected (renderpath)
+       qboolean sRGBcapable2D; // whether 2D rendering can be sRGB corrected (renderpath, v_hwgamma)
+       qboolean sRGBcapable3D; // whether 3D rendering can be sRGB corrected (renderpath, v_hwgamma)
 
        renderpath_t renderpath;
        qboolean forcevbo; // some renderpaths can not operate without it
@@ -177,6 +177,8 @@ void VID_EnableJoystick(qboolean enable);
 
 extern qboolean vid_hidden;
 extern qboolean vid_activewindow;
+extern cvar_t vid_hardwaregammasupported;
+extern qboolean vid_usinghwgamma;
 extern qboolean vid_supportrefreshrate;
 
 extern cvar_t vid_soft;
@@ -222,6 +224,7 @@ extern cvar_t v_color_grey_b;
 extern cvar_t v_color_white_r;
 extern cvar_t v_color_white_g;
 extern cvar_t v_color_white_b;
+extern cvar_t v_hwgamma;
 
 // brand of graphics chip
 extern const char *gl_vendor;
@@ -263,9 +266,20 @@ qboolean VID_InitMode(viddef_mode_t *mode);
 // allocates and opens an appropriate OpenGL context (and its window)
 
 
-// updates cachegamma variables and bumps vid_gammatables_serial if anything changed
+// sets hardware gamma correction, returns false if the device does not
+// support gamma control
+// (ONLY called by VID_UpdateGamma and VID_RestoreSystemGamma)
+int VID_SetGamma(unsigned short *ramps, int rampsize);
+// gets hardware gamma correction, returns false if the device does not
+// support gamma control
+// (ONLY called by VID_UpdateGamma and VID_RestoreSystemGamma)
+int VID_GetGamma(unsigned short *ramps, int rampsize);
+// makes sure ramp arrays are big enough and calls VID_GetGamma/VID_SetGamma
 // (ONLY to be called from VID_Finish!)
-void VID_UpdateGamma(void);
+void VID_UpdateGamma(qboolean force, int rampsize);
+// turns off hardware gamma ramps immediately
+// (called from various shutdown/deactivation functions)
+void VID_RestoreSystemGamma(void);
 
 qboolean VID_HasScreenKeyboardSupport(void);
 void VID_ShowKeyboard(qboolean show);
index 4fd603ea4e3d308fdc8c4641ff39abf2eb76eaf9..bacbb5ffd4d23a47fa49765cc489711257aa097c 100644 (file)
--- a/vid_agl.c
+++ b/vid_agl.c
@@ -190,6 +190,7 @@ void VID_SetMouse(qboolean fullscreengrab, qboolean relative, qboolean hidecurso
        }
 }
 
+#define GAMMA_TABLE_SIZE 256
 void VID_Finish (void)
 {
        qboolean vid_usevsync;
@@ -215,7 +216,7 @@ void VID_Finish (void)
                        GL_Finish();
                qaglSwapBuffers(context);
        }
-       VID_UpdateGamma();
+       VID_UpdateGamma(false, GAMMA_TABLE_SIZE);
 
        if (apple_multithreadedgl.integer)
        {
@@ -254,9 +255,65 @@ void VID_Finish (void)
        }
 }
 
+int VID_SetGamma(unsigned short *ramps, int rampsize)
+{
+       CGGammaValue table_red [GAMMA_TABLE_SIZE];
+       CGGammaValue table_green [GAMMA_TABLE_SIZE];
+       CGGammaValue table_blue [GAMMA_TABLE_SIZE];
+       int i;
+
+       // Convert the unsigned short table into 3 float tables
+       for (i = 0; i < rampsize; i++)
+               table_red[i] = (float)ramps[i] / 65535.0f;
+       for (i = 0; i < rampsize; i++)
+               table_green[i] = (float)ramps[i + rampsize] / 65535.0f;
+       for (i = 0; i < rampsize; i++)
+               table_blue[i] = (float)ramps[i + 2 * rampsize] / 65535.0f;
+
+       if (CGSetDisplayTransferByTable(CGMainDisplayID(), rampsize, table_red, table_green, table_blue) != CGDisplayNoErr)
+       {
+               Con_Print("VID_SetGamma: ERROR: CGSetDisplayTransferByTable failed!\n");
+               return false;
+       }
+
+       return true;
+}
+
+int VID_GetGamma(unsigned short *ramps, int rampsize)
+{
+       CGGammaValue table_red [GAMMA_TABLE_SIZE];
+       CGGammaValue table_green [GAMMA_TABLE_SIZE];
+       CGGammaValue table_blue [GAMMA_TABLE_SIZE];
+       CGTableCount actualsize = 0;
+       int i;
+
+       // Get the gamma ramps from the system
+       if (CGGetDisplayTransferByTable(CGMainDisplayID(), rampsize, table_red, table_green, table_blue, &actualsize) != CGDisplayNoErr)
+       {
+               Con_Print("VID_GetGamma: ERROR: CGGetDisplayTransferByTable failed!\n");
+               return false;
+       }
+       if (actualsize != (unsigned int)rampsize)
+       {
+               Con_Printf("VID_GetGamma: ERROR: invalid gamma table size (%u != %u)\n", actualsize, rampsize);
+               return false;
+       }
+
+       // Convert the 3 float tables into 1 unsigned short table
+       for (i = 0; i < rampsize; i++)
+               ramps[i] = table_red[i] * 65535.0f;
+       for (i = 0; i < rampsize; i++)
+               ramps[i + rampsize] = table_green[i] * 65535.0f;
+       for (i = 0; i < rampsize; i++)
+               ramps[i + 2 * rampsize] = table_blue[i] * 65535.0f;
+
+       return true;
+}
+
 void signal_handler(int sig)
 {
        Sys_PrintfToTerminal("Received signal %d, exiting...\n", sig);
+       VID_RestoreSystemGamma();
        Sys_Quit(1);
 }
 
@@ -341,6 +398,7 @@ void VID_Shutdown(void)
 
        VID_EnableJoystick(false);
        VID_SetMouse(false, false, false);
+       VID_RestoreSystemGamma();
 
        if (context != NULL)
        {
@@ -398,7 +456,11 @@ static OSStatus MainWindowEventHandler (EventHandlerCallRef nextHandler, EventRe
 static void VID_AppFocusChanged(qboolean windowIsActive)
 {
        if (vid_activewindow != windowIsActive)
+       {
                vid_activewindow = windowIsActive;
+               if (!vid_activewindow)
+                       VID_RestoreSystemGamma();
+       }
 
        if (windowIsActive || !snd_mutewhenidle.integer)
        {
index fc8766d8a1fbd5da371d76c3e17aad43faf6ee04..8327b2608e9a8e301af2d7d27d0101c0e6a816fd 100644 (file)
--- a/vid_glx.c
+++ b/vid_glx.c
@@ -119,9 +119,11 @@ static qboolean vid_usingmouse = false;
 static qboolean vid_usinghidecursor = false;
 static qboolean vid_usingvsync = false;
 static qboolean vid_usevsync = false;
+static qboolean vid_x11_hardwaregammasupported = false;
 #ifdef USEDGA
 static qboolean vid_x11_dgasupported = false;
 #endif
+static int vid_x11_gammarampsize = 0;
 
 #ifdef USEDGA
 cvar_t vid_dgamouse = {CVAR_SAVE, "vid_dgamouse", "0", "make use of DGA mouse input"};
@@ -703,6 +705,7 @@ static void HandleEvents(void)
                                break;
                        // window restored
                        vid_hidden = false;
+                       VID_RestoreSystemGamma();
 
                        if(vid_isvidmodefullscreen)
                        {
@@ -739,6 +742,7 @@ static void HandleEvents(void)
                                break;
                        // window iconified/rolledup/whatever
                        vid_hidden = true;
+                       VID_RestoreSystemGamma();
 
                        if(vid_isvidmodefullscreen)
                                XF86VidModeSwitchToMode(vidx11_display, vidx11_screen, &init_vidmode);
@@ -775,6 +779,7 @@ static void HandleEvents(void)
 
                        // window is no longer the input focus
                        vid_activewindow = false;
+                       VID_RestoreSystemGamma();
 
                        break;
                case EnterNotify:
@@ -850,6 +855,7 @@ void VID_Shutdown(void)
 
        VID_EnableJoystick(false);
        VID_SetMouse(false, false, false);
+       VID_RestoreSystemGamma();
 
        // FIXME: glXDestroyContext here?
        if (vid_isvidmodefullscreen)
@@ -887,6 +893,7 @@ void VID_Shutdown(void)
 static void signal_handler(int sig)
 {
        Con_Printf("Received signal %d, exiting...\n", sig);
+       VID_RestoreSystemGamma();
        Sys_Quit(1);
 }
 
@@ -962,7 +969,17 @@ void VID_Finish (void)
        }
 
        if (vid_x11_hardwaregammasupported)
-               VID_UpdateGamma();
+               VID_UpdateGamma(false, vid_x11_gammarampsize);
+}
+
+int VID_SetGamma(unsigned short *ramps, int rampsize)
+{
+       return XF86VidModeSetGammaRamp(vidx11_display, vidx11_screen, rampsize, ramps, ramps + rampsize, ramps + rampsize*2);
+}
+
+int VID_GetGamma(unsigned short *ramps, int rampsize)
+{
+       return XF86VidModeGetGammaRamp(vidx11_display, vidx11_screen, rampsize, ramps, ramps + rampsize, ramps + rampsize*2);
 }
 
 void VID_Init(void)
@@ -1299,6 +1316,7 @@ static qboolean VID_InitModeSoft(viddef_mode_t *mode)
        vid_usingvsync = false;
        vid_hidden = false;
        vid_activewindow = true;
+       vid_x11_hardwaregammasupported = XF86VidModeGetGammaRampSize(vidx11_display, vidx11_screen, &vid_x11_gammarampsize) != 0;
 #ifdef USEDGA
        vid_x11_dgasupported = XF86DGAQueryVersion(vidx11_display, &MajorVersion, &MinorVersion);
        if (!vid_x11_dgasupported)
@@ -1645,6 +1663,7 @@ static qboolean VID_InitModeGL(viddef_mode_t *mode)
        vid_usingvsync = false;
        vid_hidden = false;
        vid_activewindow = true;
+       vid_x11_hardwaregammasupported = XF86VidModeGetGammaRampSize(vidx11_display, vidx11_screen, &vid_x11_gammarampsize) != 0;
 #ifdef USEDGA
        vid_x11_dgasupported = XF86DGAQueryVersion(vidx11_display, &MajorVersion, &MinorVersion);
        if (!vid_x11_dgasupported)
index 4a13335804be43af45a6cb4e38c3cbb305377b27..a53997796db5411147e9eefbad5dc3940048aa44 100644 (file)
@@ -59,6 +59,16 @@ void VID_Finish (void)
 {
 }
 
+int VID_SetGamma(unsigned short *ramps, int rampsize)
+{
+       return FALSE;
+}
+
+int VID_GetGamma(unsigned short *ramps, int rampsize)
+{
+       return FALSE;
+}
+
 void VID_Init(void)
 {
        InitSig(); // trap evil signals
index dc210ad44a9e94e9bb79f84500cfb3d22dd687dc..98d6567ee19bee9ac97f9dcc6ce119727dcbc11a 100644 (file)
--- a/vid_sdl.c
+++ b/vid_sdl.c
@@ -2848,6 +2848,7 @@ void VID_Shutdown (void)
 {
        VID_EnableJoystick(false);
        VID_SetMouse(false, false, false);
+       VID_RestoreSystemGamma();
 
 #if SDL_MAJOR_VERSION == 1
 #ifndef WIN32
@@ -2880,6 +2881,24 @@ void VID_Shutdown (void)
        gl_platformextensions = "";
 }
 
+int VID_SetGamma (unsigned short *ramps, int rampsize)
+{
+#if SDL_MAJOR_VERSION == 1
+       return !SDL_SetGammaRamp (ramps, ramps + rampsize, ramps + rampsize*2);
+#else
+       return !SDL_SetWindowGammaRamp (window, ramps, ramps + rampsize, ramps + rampsize*2);
+#endif
+}
+
+int VID_GetGamma (unsigned short *ramps, int rampsize)
+{
+#if SDL_MAJOR_VERSION == 1
+       return !SDL_GetGammaRamp (ramps, ramps + rampsize, ramps + rampsize*2);
+#else
+       return !SDL_GetWindowGammaRamp (window, ramps, ramps + rampsize, ramps + rampsize*2);
+#endif
+}
+
 void VID_Finish (void)
 {
 #if SDL_MAJOR_VERSION == 1
@@ -2893,7 +2912,7 @@ void VID_Finish (void)
 #endif
        vid_activewindow = !vid_hidden && vid_hasfocus;
 
-       VID_UpdateGamma();
+       VID_UpdateGamma(false, 256);
 
        if (!vid_hidden)
        {
index 129641cfcfe1dd42586d710eac6143498123d6d8..843707b48f7b9ba2f9ea03cd7ca4b62fdad2d620 100644 (file)
@@ -140,6 +140,9 @@ cvar_t vid_soft = {CVAR_SAVE, "vid_soft", "0", "enables use of the DarkPlaces So
 cvar_t vid_soft_threads = {CVAR_SAVE, "vid_soft_threads", "8", "the number of threads the DarkPlaces Software Rasterizer should use"}; 
 cvar_t vid_soft_interlace = {CVAR_SAVE, "vid_soft_interlace", "1", "whether the DarkPlaces Software Rasterizer should interlace the screen bands occupied by each thread"};
 
+// we don't know until we try it!
+cvar_t vid_hardwaregammasupported = {CVAR_READONLY,"vid_hardwaregammasupported","1", "indicates whether hardware gamma is supported (updated by attempts to set hardware gamma ramps)"};
+
 // VorteX: more info cvars, mostly set in VID_CheckExtensions
 cvar_t gl_info_vendor = {CVAR_READONLY, "gl_info_vendor", "", "indicates brand of graphics chip"};
 cvar_t gl_info_renderer = {CVAR_READONLY, "gl_info_renderer", "", "indicates graphics chip model and other information"};
@@ -148,6 +151,13 @@ cvar_t gl_info_extensions = {CVAR_READONLY, "gl_info_extensions", "", "indicates
 cvar_t gl_info_platform = {CVAR_READONLY, "gl_info_platform", "", "indicates GL platform: WGL, GLX, or AGL."};
 cvar_t gl_info_driver = {CVAR_READONLY, "gl_info_driver", "", "name of driver library (opengl32.dll, libGL.so.1, or whatever)."};
 
+// whether hardware gamma ramps are currently in effect
+qboolean vid_usinghwgamma = false;
+
+int vid_gammarampsize = 0;
+unsigned short *vid_gammaramps = NULL;
+unsigned short *vid_systemgammaramps = NULL;
+
 cvar_t vid_fullscreen = {CVAR_SAVE, "vid_fullscreen", "1", "use fullscreen (1) or windowed (0)"};
 cvar_t vid_width = {CVAR_SAVE, "vid_width", "640", "resolution"};
 cvar_t vid_height = {CVAR_SAVE, "vid_height", "480", "resolution"};
@@ -195,9 +205,10 @@ cvar_t v_color_grey_b = {CVAR_SAVE, "v_color_grey_b", "0.5", "desired color of g
 cvar_t v_color_white_r = {CVAR_SAVE, "v_color_white_r", "1", "desired color of white"};
 cvar_t v_color_white_g = {CVAR_SAVE, "v_color_white_g", "1", "desired color of white"};
 cvar_t v_color_white_b = {CVAR_SAVE, "v_color_white_b", "1", "desired color of white"};
-cvar_t v_glslgamma = {CVAR_SAVE, "v_glslgamma", "1", "enables use of GLSL to apply gamma correction ramps"};
+cvar_t v_hwgamma = {CVAR_SAVE, "v_hwgamma", "0", "enables use of hardware gamma correction ramps if available (note: does not work very well on Windows2000 and above), values are 0 = off, 1 = attempt to use hardware gamma, 2 = use hardware gamma whether it works or not"};
+cvar_t v_glslgamma = {CVAR_SAVE, "v_glslgamma", "1", "enables use of GLSL to apply gamma correction ramps if available (note: overrides v_hwgamma)"};
 cvar_t v_glslgamma_2d = {CVAR_SAVE, "v_glslgamma_2d", "0", "applies GLSL gamma to 2d pictures (HUD, fonts)"};
-cvar_t v_psycho = {0, "v_psycho", "0", "easter egg - R.I.P. zinx http://obits.al.com/obituaries/birmingham/obituary.aspx?n=christopher-robert-lais&pid=186080667"};
+cvar_t v_psycho = {0, "v_psycho", "0", "easter egg"};
 
 // brand of graphics chip
 const char *gl_vendor;
@@ -1463,7 +1474,7 @@ static void Force_CenterView_f (void)
 
 static int gamma_forcenextframe = false;
 static float cachegamma, cachebrightness, cachecontrast, cacheblack[3], cachegrey[3], cachewhite[3], cachecontrastboost;
-static int cachecolorenable;
+static int cachecolorenable, cachehwgamma;
 
 void VID_ApplyGammaToColor(const float *rgb, float *out)
 {
@@ -1507,8 +1518,6 @@ void VID_BuildGammaTables(unsigned short *ramps, int rampsize)
        // LordHavoc: this code came from Ben Winslow and Zinx Verituse, I have
        // immensely butchered it to work with variable framerates and fit in with
        // the rest of darkplaces.
-       //
-       // R.I.P. zinx http://obits.al.com/obituaries/birmingham/obituary.aspx?n=christopher-robert-lais&pid=186080667
        if (v_psycho.integer)
        {
                int x, y;
@@ -1546,12 +1555,36 @@ void VID_BuildGammaTables(unsigned short *ramps, int rampsize)
        }
 }
 
-void VID_UpdateGamma(void)
+void VID_UpdateGamma(qboolean force, int rampsize)
 {
        cvar_t *c;
        float f;
+       int wantgamma;
        qboolean gamma_changed = false;
 
+       // LordHavoc: don't mess with gamma tables if running dedicated
+       if (cls.state == ca_dedicated)
+               return;
+
+       wantgamma = v_hwgamma.integer;
+       switch(vid.renderpath)
+       {
+       case RENDERPATH_GL20:
+       case RENDERPATH_D3D9:
+       case RENDERPATH_D3D10:
+       case RENDERPATH_D3D11:
+       case RENDERPATH_SOFT:
+       case RENDERPATH_GLES2:
+               if (v_glslgamma.integer)
+                       wantgamma = 0;
+               break;
+       case RENDERPATH_GL11:
+       case RENDERPATH_GL13:
+       case RENDERPATH_GLES1:
+               break;
+       }
+       if(!vid_activewindow)
+               wantgamma = 0;
 #define BOUNDCVAR(cvar, m1, m2) c = &(cvar);f = bound(m1, c->value, m2);if (c->value != f) Cvar_SetValueQuick(c, f);
        BOUNDCVAR(v_gamma, 0.1, 5);
        BOUNDCVAR(v_contrast, 0.2, 5);
@@ -1597,7 +1630,6 @@ void VID_UpdateGamma(void)
                }
        }
 
-       // if any gamma settings were changed, bump vid_gammatables_serial so we regenerate the gamma ramp texture
 #define GAMMACHECK(cache, value) if (cache != (value)) gamma_changed = true;cache = (value)
        if(v_psycho.integer)
                gamma_changed = true;
@@ -1618,7 +1650,64 @@ void VID_UpdateGamma(void)
 
        if(gamma_changed)
                ++vid_gammatables_serial;
+
+       GAMMACHECK(cachehwgamma    , wantgamma);
 #undef GAMMACHECK
+
+       if (!force && !gamma_forcenextframe && !gamma_changed)
+               return;
+
+       gamma_forcenextframe = false;
+
+       if (cachehwgamma)
+       {
+               if (!vid_usinghwgamma)
+               {
+                       vid_usinghwgamma = true;
+                       if (vid_gammarampsize != rampsize || !vid_gammaramps)
+                       {
+                               vid_gammarampsize = rampsize;
+                               if (vid_gammaramps)
+                                       Z_Free(vid_gammaramps);
+                               vid_gammaramps = (unsigned short *)Z_Malloc(6 * vid_gammarampsize * sizeof(unsigned short));
+                               vid_systemgammaramps = vid_gammaramps + 3 * vid_gammarampsize;
+                       }
+                       VID_GetGamma(vid_systemgammaramps, vid_gammarampsize);
+               }
+
+               VID_BuildGammaTables(vid_gammaramps, vid_gammarampsize);
+
+               // set vid_hardwaregammasupported to true if VID_SetGamma succeeds, OR if vid_hwgamma is >= 2 (forced gamma - ignores driver return value)
+               Cvar_SetValueQuick(&vid_hardwaregammasupported, VID_SetGamma(vid_gammaramps, vid_gammarampsize) || cachehwgamma >= 2);
+               // if custom gamma ramps failed (Windows stupidity), restore to system gamma
+               if(!vid_hardwaregammasupported.integer)
+               {
+                       if (vid_usinghwgamma)
+                       {
+                               vid_usinghwgamma = false;
+                               VID_SetGamma(vid_systemgammaramps, vid_gammarampsize);
+                       }
+               }
+       }
+       else
+       {
+               if (vid_usinghwgamma)
+               {
+                       vid_usinghwgamma = false;
+                       VID_SetGamma(vid_systemgammaramps, vid_gammarampsize);
+               }
+       }
+}
+
+void VID_RestoreSystemGamma(void)
+{
+       if (vid_usinghwgamma)
+       {
+               vid_usinghwgamma = false;
+               Cvar_SetValueQuick(&vid_hardwaregammasupported, VID_SetGamma(vid_systemgammaramps, vid_gammarampsize));
+               // force gamma situation to be reexamined next frame
+               gamma_forcenextframe = true;
+       }
 }
 
 #ifdef WIN32
@@ -1654,6 +1743,7 @@ void VID_Shared_Init(void)
        Con_Printf("DPSOFTRAST not available (SSE2 not compiled in)\n");
 #endif
 
+       Cvar_RegisterVariable(&vid_hardwaregammasupported);
        Cvar_RegisterVariable(&gl_info_vendor);
        Cvar_RegisterVariable(&gl_info_renderer);
        Cvar_RegisterVariable(&gl_info_version);
@@ -1676,6 +1766,7 @@ void VID_Shared_Init(void)
        Cvar_RegisterVariable(&v_color_white_g);
        Cvar_RegisterVariable(&v_color_white_b);
 
+       Cvar_RegisterVariable(&v_hwgamma);
        Cvar_RegisterVariable(&v_glslgamma);
        Cvar_RegisterVariable(&v_glslgamma_2d);
 
index 329e57df415c15c76219e259713576a60b9369ad..fbb027c3bcbb31ba2bd4e51103a1d90964a0fa9f 100644 (file)
--- a/vid_wgl.c
+++ b/vid_wgl.c
@@ -321,7 +321,7 @@ void VID_Finish (void)
        // without this help
        Sleep(0);
 
-       VID_UpdateGamma();
+       VID_UpdateGamma(false, 256);
 }
 
 //==========================================================================
@@ -498,6 +498,7 @@ void AppActivate(BOOL fActive, BOOL minimize)
                                ChangeDisplaySettings (NULL, CDS_FULLSCREEN);
                        vid_wassuspended = true;
                }
+               VID_RestoreSystemGamma();
        }
 }
 
@@ -710,6 +711,32 @@ LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM  wParam, LPARAM lParam)
        return lRet;
 }
 
+int VID_SetGamma(unsigned short *ramps, int rampsize)
+{
+       if (qwglMakeCurrent)
+       {
+               HDC hdc = GetDC (NULL);
+               int i = SetDeviceGammaRamp(hdc, ramps);
+               ReleaseDC (NULL, hdc);
+               return i; // return success or failure
+       }
+       else
+               return 0;
+}
+
+int VID_GetGamma(unsigned short *ramps, int rampsize)
+{
+       if (qwglMakeCurrent)
+       {
+               HDC hdc = GetDC (NULL);
+               int i = GetDeviceGammaRamp(hdc, ramps);
+               ReleaseDC (NULL, hdc);
+               return i; // return success or failure
+       }
+       else
+               return 0;
+}
+
 static void GL_CloseLibrary(void)
 {
        if (gldll)
@@ -1843,6 +1870,7 @@ void VID_Shutdown (void)
 
        VID_EnableJoystick(false);
        VID_SetMouse(false, false, false);
+       VID_RestoreSystemGamma();
 
        vid_initialized = false;
        isgl = gldll != NULL;