]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - vid_shared.c
fix flipped sprites
[xonotic/darkplaces.git] / vid_shared.c
index 1bfff4511b086854135841e8035bd85e20f3b6d5..8f33726427d5e70fb4d6dba5dab664b6614a11c0 100644 (file)
@@ -24,12 +24,28 @@ int gl_texture3d = false;
 int gl_texturecubemap = false;
 // GL_ARB_texture_env_dot3
 int gl_dot3arb = false;
+// GL_SGIS_texture_edge_clamp
+int gl_support_clamptoedge = false;
+// GL_NV_vertex_array_range
+int gl_support_var = false;
+// GL_NV_vertex_array_range2
+int gl_support_var2 = false;
 
 // LordHavoc: if window is hidden, don't update screen
 int vid_hidden = true;
 // LordHavoc: if window is not the active window, don't hog as much CPU time,
 // let go of the mouse, turn off sound, and restore system gamma ramps...
 int vid_activewindow = true;
+// LordHavoc: whether to allow use of hwgamma (disabled when window is inactive)
+int vid_allowhwgamma = false;
+
+// we don't know until we try it!
+int vid_hardwaregammasupported = true;
+// whether hardware gamma ramps are currently in effect
+int vid_usinghwgamma = false;
+
+unsigned short vid_gammaramps[768];
+unsigned short vid_systemgammaramps[768];
 
 cvar_t vid_fullscreen = {CVAR_SAVE, "vid_fullscreen", "1"};
 cvar_t vid_width = {CVAR_SAVE, "vid_width", "640"};
@@ -45,6 +61,22 @@ cvar_t in_pitch_max = {0, "in_pitch_max", "80"};
 
 cvar_t m_filter = {CVAR_SAVE, "m_filter","0"};
 
+cvar_t v_gamma = {CVAR_SAVE, "v_gamma", "1"};
+cvar_t v_contrast = {CVAR_SAVE, "v_contrast", "1"};
+cvar_t v_brightness = {CVAR_SAVE, "v_brightness", "0"};
+cvar_t v_color_enable = {CVAR_SAVE, "v_color_enable", "0"};
+cvar_t v_color_black_r = {CVAR_SAVE, "v_color_black_r", "0"};
+cvar_t v_color_black_g = {CVAR_SAVE, "v_color_black_g", "0"};
+cvar_t v_color_black_b = {CVAR_SAVE, "v_color_black_b", "0"};
+cvar_t v_color_grey_r = {CVAR_SAVE, "v_color_grey_r", "0.5"};
+cvar_t v_color_grey_g = {CVAR_SAVE, "v_color_grey_g", "0.5"};
+cvar_t v_color_grey_b = {CVAR_SAVE, "v_color_grey_b", "0.5"};
+cvar_t v_color_white_r = {CVAR_SAVE, "v_color_white_r", "1"};
+cvar_t v_color_white_g = {CVAR_SAVE, "v_color_white_g", "1"};
+cvar_t v_color_white_b = {CVAR_SAVE, "v_color_white_b", "1"};
+cvar_t v_overbrightbits = {CVAR_SAVE, "v_overbrightbits", "0"};
+cvar_t v_hwgamma = {0, "v_hwgamma", "1"};
+
 // brand of graphics chip
 const char *gl_vendor;
 // graphics chip model and other information
@@ -70,6 +102,11 @@ void (GLAPIENTRY *qglClientActiveTexture) (GLenum);
 void (GLAPIENTRY *qglLockArraysEXT) (GLint first, GLint count);
 void (GLAPIENTRY *qglUnlockArraysEXT) (void);
 
+//GL_NV_vertex_array_range
+GLvoid *(GLAPIENTRY *qglAllocateMemoryNV)(GLsizei size, GLfloat readFrequency, GLfloat writeFrequency, GLfloat priority);
+GLvoid (GLAPIENTRY *qglFreeMemoryNV)(GLvoid *pointer);
+GLvoid (GLAPIENTRY *qglVertexArrayRangeNV)(GLsizei length, GLvoid *pointer);
+GLvoid (GLAPIENTRY *qglFlushVertexArrayRangeNV)(GLvoid);
 
 // general GL functions
 
@@ -346,6 +383,25 @@ static dllfunction_t texture3dextfuncs[] =
        {NULL, NULL}
 };
 
+static dllfunction_t glxvarfuncs[] =
+{
+       {"glXAllocateMemoryNV", (void **) &qglAllocateMemoryNV},
+       {"glXFreeMemoryNV", (void **) &qglFreeMemoryNV},
+       {"glVertexArrayRangeNV", (void **) &qglVertexArrayRangeNV},
+       {"glFlushVertexArrayRangeNV", (void **) &qglFlushVertexArrayRangeNV},
+       {NULL, NULL}
+};
+
+static dllfunction_t wglvarfuncs[] =
+{
+       {"wglAllocateMemoryNV", (void **) &qglAllocateMemoryNV},
+       {"wglFreeMemoryNV", (void **) &qglFreeMemoryNV},
+       {"glVertexArrayRangeNV", (void **) &qglVertexArrayRangeNV},
+       {"glFlushVertexArrayRangeNV", (void **) &qglFlushVertexArrayRangeNV},
+       {NULL, NULL}
+};
+
+
 void VID_CheckExtensions(void)
 {
        gl_stencil = vid_stencil.integer;
@@ -353,6 +409,9 @@ void VID_CheckExtensions(void)
        gl_dot3arb = false;
        gl_supportslockarrays = false;
        gl_textureunits = 1;
+       gl_support_clamptoedge = false;
+       gl_support_var = false;
+       gl_support_var2 = false;
 
        if (!GL_CheckExtension("OpenGL 1.1.0", opengl110funcs, NULL, false))
                Sys_Error("OpenGL 1.1.0 functions not found\n");
@@ -379,12 +438,52 @@ void VID_CheckExtensions(void)
        gl_texture3d = GL_CheckExtension("GL_EXT_texture3D", texture3dextfuncs, "-notexture3d", false);
        gl_texturecubemap = GL_CheckExtension("GL_ARB_texture_cube_map", NULL, "-nocubemap", false);
        gl_supportslockarrays = GL_CheckExtension("GL_EXT_compiled_vertex_array", compiledvertexarrayfuncs, "-nocva", false);
+       gl_support_clamptoedge = GL_CheckExtension("GL_EXT_texture_edge_clamp", NULL, "-noedgeclamp", false) || GL_CheckExtension("GL_SGIS_texture_edge_clamp", NULL, "-noedgeclamp", false);
+
+       if (!strcmp(gl_platform, "GLX"))
+               gl_support_var = GL_CheckExtension("GL_NV_vertex_array_range", glxvarfuncs, "-novar", false);
+       else if (!strcmp(gl_platform, "WGL"))
+               gl_support_var = GL_CheckExtension("GL_NV_vertex_array_range", wglvarfuncs, "-novar", false);
+       if (gl_support_var)
+               gl_support_var2 = GL_CheckExtension("GL_NV_vertex_array_range2", NULL, "-novar2", false);
 
        // we don't care if it's an extension or not, they are identical functions, so keep it simple in the rendering code
        if (qglDrawRangeElements == NULL)
                qglDrawRangeElements = qglDrawRangeElementsEXT;
 }
 
+int vid_vertexarrays_are_var = false;
+void *VID_AllocVertexArrays(mempool_t *pool, int size, int fast, float readfrequency, float writefrequency, float priority)
+{
+       void *m;
+       vid_vertexarrays_are_var = false;
+       if (fast && qglAllocateMemoryNV)
+       {
+               CHECKGLERROR
+               m = qglAllocateMemoryNV(size, readfrequency, writefrequency, priority);
+               CHECKGLERROR
+               if (m)
+               {
+                       vid_vertexarrays_are_var = true;
+                       return m;
+               }
+       }
+       return Mem_Alloc(pool, size);
+}
+
+void VID_FreeVertexArrays(void *pointer)
+{
+       if (vid_vertexarrays_are_var)
+       {
+               CHECKGLERROR
+               qglFreeMemoryNV(pointer);
+               CHECKGLERROR
+       }
+       else
+               Mem_Free(pointer);
+       vid_vertexarrays_are_var = false;
+}
+
 void Force_CenterView_f (void)
 {
        cl.viewangles[PITCH] = 0;
@@ -445,8 +544,114 @@ void IN_Mouse(usercmd_t *cmd, float mx, float my)
        }
 }
 
+static float cachegamma, cachebrightness, cachecontrast, cacheblack[3], cachegrey[3], cachewhite[3];
+static int cacheoverbrightbits = -1, cachecolorenable, cachehwgamma;
+#define BOUNDCVAR(cvar, m1, m2) c = &(cvar);f = bound(m1, c->value, m2);if (c->value != f) Cvar_SetValueQuick(c, f);
+void VID_UpdateGamma(qboolean force)
+{
+       cvar_t *c;
+       float f;
+
+       // LordHavoc: don't mess with gamma tables if running dedicated
+       if (cls.state == ca_dedicated)
+               return;
+
+       if (!force
+        && vid_usinghwgamma == (vid_allowhwgamma && v_hwgamma.integer)
+        && v_overbrightbits.integer == cacheoverbrightbits
+        && v_gamma.value == cachegamma
+        && v_contrast.value == cachecontrast
+        && v_brightness.value == cachebrightness
+        && cachecolorenable == v_color_enable.integer
+        && cacheblack[0] == v_color_black_r.value
+        && cacheblack[1] == v_color_black_g.value
+        && cacheblack[2] == v_color_black_b.value
+        && cachegrey[0] == v_color_grey_r.value
+        && cachegrey[1] == v_color_grey_g.value
+        && cachegrey[2] == v_color_grey_b.value
+        && cachewhite[0] == v_color_white_r.value
+        && cachewhite[1] == v_color_white_g.value
+        && cachewhite[2] == v_color_white_b.value)
+               return;
+
+       if (vid_allowhwgamma && v_hwgamma.integer)
+       {
+               if (!vid_usinghwgamma)
+               {
+                       vid_usinghwgamma = true;
+                       vid_hardwaregammasupported = VID_GetGamma(vid_systemgammaramps);
+               }
+
+               BOUNDCVAR(v_gamma, 0.1, 5);cachegamma = v_gamma.value;
+               BOUNDCVAR(v_contrast, 1, 5);cachecontrast = v_contrast.value;
+               BOUNDCVAR(v_brightness, 0, 0.8);cachebrightness = v_brightness.value;
+               BOUNDCVAR(v_color_black_r, 0, 0.8);cacheblack[0] = v_color_black_r.value;
+               BOUNDCVAR(v_color_black_g, 0, 0.8);cacheblack[1] = v_color_black_g.value;
+               BOUNDCVAR(v_color_black_b, 0, 0.8);cacheblack[2] = v_color_black_b.value;
+               BOUNDCVAR(v_color_grey_r, 0, 0.95);cachegrey[0] = v_color_grey_r.value;
+               BOUNDCVAR(v_color_grey_g, 0, 0.95);cachegrey[1] = v_color_grey_g.value;
+               BOUNDCVAR(v_color_grey_b, 0, 0.95);cachegrey[2] = v_color_grey_b.value;
+               BOUNDCVAR(v_color_white_r, 1, 5);cachewhite[0] = v_color_white_r.value;
+               BOUNDCVAR(v_color_white_g, 1, 5);cachewhite[1] = v_color_white_g.value;
+               BOUNDCVAR(v_color_white_b, 1, 5);cachewhite[2] = v_color_white_b.value;
+               cachecolorenable = v_color_enable.integer;
+               cacheoverbrightbits = v_overbrightbits.integer;
+               cachehwgamma = v_hwgamma.integer;
+
+               if (cachecolorenable)
+               {
+                       BuildGammaTable16((float) (1 << cacheoverbrightbits), invpow(0.5, 1 - cachegrey[0]), cachewhite[0], cacheblack[0], vid_gammaramps);
+                       BuildGammaTable16((float) (1 << cacheoverbrightbits), invpow(0.5, 1 - cachegrey[1]), cachewhite[1], cacheblack[1], vid_gammaramps + 256);
+                       BuildGammaTable16((float) (1 << cacheoverbrightbits), invpow(0.5, 1 - cachegrey[2]), cachewhite[2], cacheblack[2], vid_gammaramps + 512);
+               }
+               else
+               {
+                       BuildGammaTable16((float) (1 << cacheoverbrightbits), cachegamma, cachecontrast, cachebrightness, vid_gammaramps);
+                       BuildGammaTable16((float) (1 << cacheoverbrightbits), cachegamma, cachecontrast, cachebrightness, vid_gammaramps + 256);
+                       BuildGammaTable16((float) (1 << cacheoverbrightbits), cachegamma, cachecontrast, cachebrightness, vid_gammaramps + 512);
+               }
+
+               vid_hardwaregammasupported = VID_SetGamma(vid_gammaramps);
+       }
+       else
+       {
+               if (vid_usinghwgamma)
+               {
+                       vid_usinghwgamma = false;
+                       vid_hardwaregammasupported = VID_SetGamma(vid_systemgammaramps);
+               }
+       }
+}
+
+void VID_RestoreSystemGamma(void)
+{
+       if (vid_usinghwgamma)
+       {
+               vid_usinghwgamma = false;
+               VID_SetGamma(vid_systemgammaramps);
+       }
+}
+
 void VID_Shared_Init(void)
 {
+       Cvar_RegisterVariable(&v_gamma);
+       Cvar_RegisterVariable(&v_brightness);
+       Cvar_RegisterVariable(&v_contrast);
+
+       Cvar_RegisterVariable(&v_color_enable);
+       Cvar_RegisterVariable(&v_color_black_r);
+       Cvar_RegisterVariable(&v_color_black_g);
+       Cvar_RegisterVariable(&v_color_black_b);
+       Cvar_RegisterVariable(&v_color_grey_r);
+       Cvar_RegisterVariable(&v_color_grey_g);
+       Cvar_RegisterVariable(&v_color_grey_b);
+       Cvar_RegisterVariable(&v_color_white_r);
+       Cvar_RegisterVariable(&v_color_white_g);
+       Cvar_RegisterVariable(&v_color_white_b);
+
+       Cvar_RegisterVariable(&v_hwgamma);
+       Cvar_RegisterVariable(&v_overbrightbits);
+
        Cvar_RegisterVariable(&vid_fullscreen);
        Cvar_RegisterVariable(&vid_width);
        Cvar_RegisterVariable(&vid_height);
@@ -581,3 +786,4 @@ void VID_Close(void)
        VID_CloseSystems();
        VID_Shutdown();
 }
+