]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_draw.c
added bufferobject and bufferoffset parameters to all R_Mesh_*Pointer functions and...
[xonotic/darkplaces.git] / gl_draw.c
index 132674f920379a8857f9c03de3cde675f6eb904d..17883ca217202990b505f020c816b613ea54f4a0 100644 (file)
--- a/gl_draw.c
+++ b/gl_draw.c
@@ -19,15 +19,21 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
 
 #include "quakedef.h"
+#include "image.h"
+#include "wad.h"
 
-cvar_t scr_conalpha = {CVAR_SAVE, "scr_conalpha", "1"};
+#include "cl_video.h"
+
+cvar_t r_textshadow = {CVAR_SAVE, "r_textshadow", "0", "draws a shadow on all text to improve readability"};
 
 static rtexture_t *char_texture;
+cachepic_t *r_crosshairs[NUMCROSSHAIRS+1];
 
 //=============================================================================
 /* Support Routines */
 
-#define MAX_CACHED_PICS 256
+#define FONT_FILESIZE 13468
+#define MAX_CACHED_PICS 1024
 #define CACHEPICHASHSIZE 256
 static cachepic_t *cachepichash[CACHEPICHASHSIZE];
 static cachepic_t cachepics[MAX_CACHED_PICS];
@@ -35,8 +41,64 @@ static int numcachepics;
 
 static rtexturepool_t *drawtexturepool;
 
-static qbyte pointerimage[256] =
+static unsigned char concharimage[FONT_FILESIZE] =
+{
+#include "lhfont.h"
+};
+
+static rtexture_t *draw_generateconchars(void)
 {
+       int i;
+       unsigned char buffer[65536][4], *data = NULL;
+       double random;
+
+       data = LoadTGA (concharimage, FONT_FILESIZE, 256, 256);
+// Gold numbers
+       for (i = 0;i < 8192;i++)
+       {
+               random = lhrandom (0.0,1.0);
+               buffer[i][0] = 83 + (unsigned char)(random * 64);
+               buffer[i][1] = 71 + (unsigned char)(random * 32);
+               buffer[i][2] = 23 + (unsigned char)(random * 16);
+               buffer[i][3] = data[i*4+0];
+       }
+// White chars
+       for (i = 8192;i < 32768;i++)
+       {
+               random = lhrandom (0.0,1.0);
+               buffer[i][0] = 95 + (unsigned char)(random * 64);
+               buffer[i][1] = 95 + (unsigned char)(random * 64);
+               buffer[i][2] = 95 + (unsigned char)(random * 64);
+               buffer[i][3] = data[i*4+0];
+       }
+// Gold numbers
+       for (i = 32768;i < 40960;i++)
+       {
+               random = lhrandom (0.0,1.0);
+               buffer[i][0] = 83 + (unsigned char)(random * 64);
+               buffer[i][1] = 71 + (unsigned char)(random * 32);
+               buffer[i][2] = 23 + (unsigned char)(random * 16);
+               buffer[i][3] = data[i*4+0];
+       }
+// Red chars
+       for (i = 40960;i < 65536;i++)
+       {
+               random = lhrandom (0.0,1.0);
+               buffer[i][0] = 96 + (unsigned char)(random * 64);
+               buffer[i][1] = 43 + (unsigned char)(random * 32);
+               buffer[i][2] = 27 + (unsigned char)(random * 32);
+               buffer[i][3] = data[i*4+0];
+       }
+
+#if 0
+       Image_WriteTGARGBA ("gfx/generated_conchars.tga", 256, 256, &buffer[0][0]);
+#endif
+
+       Mem_Free(data);
+       return R_LoadTexture2D(drawtexturepool, "conchars", 256, 256, &buffer[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
+}
+
+static char *pointerimage =
        "333333332......."
        "26777761........"
        "2655541........."
@@ -53,12 +115,12 @@ static qbyte pointerimage[256] =
        "................"
        "................"
        "................"
-};
+;
 
 static rtexture_t *draw_generatemousepointer(void)
 {
        int i;
-       qbyte buffer[256][4];
+       unsigned char buffer[256][4];
        for (i = 0;i < 256;i++)
        {
                if (pointerimage[i] == '.')
@@ -76,13 +138,10 @@ static rtexture_t *draw_generatemousepointer(void)
                        buffer[i][3] = 255;
                }
        }
-       return R_LoadTexture(drawtexturepool, "mousepointer", 16, 16, &buffer[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE);
+       return R_LoadTexture2D(drawtexturepool, "mousepointer", 16, 16, &buffer[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
 }
 
-// must match NUMCROSSHAIRS in r_crosshairs.c
-#define NUMCROSSHAIRS 5
-
-static qbyte *crosshairtexdata[NUMCROSSHAIRS] =
+static char *crosshairtexdata[NUMCROSSHAIRS] =
 {
        "................"
        "................"
@@ -130,10 +189,10 @@ static qbyte *crosshairtexdata[NUMCROSSHAIRS] =
        ".......44......."
        ".......44......."
        "................"
+       "................"
        ".......77......."
        ".......77......."
        "................"
-       "................"
        ,
        "................"
        "................"
@@ -149,7 +208,7 @@ static qbyte *crosshairtexdata[NUMCROSSHAIRS] =
        "........7......."
        "........7......."
        "........7......."
-       "................"
+       "........7......."
        "................"
        ,
        "................"
@@ -168,13 +227,30 @@ static qbyte *crosshairtexdata[NUMCROSSHAIRS] =
        "................"
        "................"
        "................"
+       ,
+       "................"
+       "................"
+       "................"
+       "................"
+       "................"
+       "................"
+       "................"
+       ".......55......."
+       ".......55......."
+       "................"
+       "................"
+       "................"
+       "................"
+       "................"
+       "................"
+       "................"
 };
 
 static rtexture_t *draw_generatecrosshair(int num)
 {
        int i;
        char *in;
-       qbyte data[16*16][4];
+       unsigned char data[16*16][4];
        in = crosshairtexdata[num];
        for (i = 0;i < 16*16;i++)
        {
@@ -187,13 +263,33 @@ static rtexture_t *draw_generatecrosshair(int num)
                }
                else
                {
-                       data[i][0] = 255;
-                       data[i][1] = 255;
-                       data[i][2] = 255;
-                       data[i][3] = (qbyte) ((int) (in[i] - '0') * 255 / 7);
+                       data[i][0] = data[i][1] = data[i][2] = (unsigned char) ((int) (in[i] - '0') * 127 / 7 + 128);
+                       data[i][3] = 255;
                }
        }
-       return R_LoadTexture(drawtexturepool, va("crosshair%i", num), 16, 16, &data[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE);
+       return R_LoadTexture2D(drawtexturepool, va("crosshair%i", num+1), 16, 16, &data[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
+}
+
+static rtexture_t *draw_generateditherpattern(void)
+{
+#if 1
+       int x, y;
+       unsigned char data[8*8*4];
+       for (y = 0;y < 8;y++)
+       {
+               for (x = 0;x < 8;x++)
+               {
+                       data[(y*8+x)*4+0] = data[(y*8+x)*4+1] = data[(y*8+x)*4+2] = ((x^y) & 4) ? 255 : 0;
+                       data[(y*8+x)*4+3] = 255;
+               }
+       }
+       return R_LoadTexture2D(drawtexturepool, "ditherpattern", 8, 8, data, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_PRECACHE, NULL);
+#else
+       unsigned char data[16];
+       memset(data, 255, sizeof(data));
+       data[0] = data[1] = data[2] = data[12] = data[13] = data[14] = 0;
+       return R_LoadTexture2D(drawtexturepool, "ditherpattern", 2, 2, data, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_PRECACHE, NULL);
+#endif
 }
 
 /*
@@ -202,69 +298,144 @@ Draw_CachePic
 ================
 */
 // FIXME: move this to client somehow
-cachepic_t     *Draw_CachePic (char *path)
+cachepic_t     *Draw_CachePic (const char *path, qboolean persistent)
 {
-       int i, crc, hashkey;
+       int crc, hashkey;
        cachepic_t *pic;
-       qpic_t *p;
+       int flags;
+       fs_offset_t lmpsize;
+       unsigned char *lmpdata;
+       char lmpname[MAX_QPATH];
+
+       if (!strncmp(CLVIDEOPREFIX, path, sizeof(CLVIDEOPREFIX) - 1))
+       {
+               clvideo_t *video;
+
+               video = CL_GetVideoByName(path);
+               if( video )
+                       return &video->cpif;
+       }
 
-       crc = CRC_Block(path, strlen(path));
+       crc = CRC_Block((unsigned char *)path, strlen(path));
        hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
        for (pic = cachepichash[hashkey];pic;pic = pic->chain)
                if (!strcmp (path, pic->name))
                        return pic;
 
        if (numcachepics == MAX_CACHED_PICS)
-               Sys_Error ("numcachepics == MAX_CACHED_PICS");
+       {
+               Con_Printf ("Draw_CachePic: numcachepics == MAX_CACHED_PICS\n");
+               // FIXME: support NULL in callers?
+               return cachepics; // return the first one
+       }
        pic = cachepics + (numcachepics++);
-       strcpy (pic->name, path);
+       strlcpy (pic->name, path, sizeof(pic->name));
        // link into list
        pic->chain = cachepichash[hashkey];
        cachepichash[hashkey] = pic;
 
-       // load the pic from disk
-       pic->tex = loadtextureimage(drawtexturepool, path, 0, 0, false, false, true);
-       if (pic->tex == NULL && (p = W_GetLumpName (path)))
+       flags = TEXF_ALPHA;
+       if (persistent)
+               flags |= TEXF_PRECACHE;
+       if (!strcmp(path, "gfx/colorcontrol/ditherpattern"))
+               flags |= TEXF_CLAMP;
+
+       // load a high quality image from disk if possible
+       pic->tex = loadtextureimage(drawtexturepool, path, 0, 0, false, flags);
+       if (pic->tex == NULL && !strncmp(path, "gfx/", 4))
+       {
+               // compatibility with older versions which did not require gfx/ prefix
+               pic->tex = loadtextureimage(drawtexturepool, path + 4, 0, 0, false, flags);
+       }
+       // if a high quality image was loaded, set the pic's size to match it, just
+       // in case there's no low quality version to get the size from
+       if (pic->tex)
        {
-               if (!strcmp(path, "conchars"))
+               pic->width = R_TextureWidth(pic->tex);
+               pic->height = R_TextureHeight(pic->tex);
+       }
+
+       // now read the low quality version (wad or lmp file), and take the pic
+       // size from that even if we don't upload the texture, this way the pics
+       // show up the right size in the menu even if they were replaced with
+       // higher or lower resolution versions
+       dpsnprintf(lmpname, sizeof(lmpname), "%s.lmp", path);
+       if (!strncmp(path, "gfx/", 4) && (lmpdata = FS_LoadFile(lmpname, tempmempool, false, &lmpsize)))
+       {
+               if (lmpsize >= 9)
                {
-                       qbyte *pix;
-                       // conchars is a raw image and with the wrong transparent color
-                       pix = (qbyte *)p;
-                       for (i = 0;i < 128 * 128;i++)
-                               if (pix[i] == 0)
-                                       pix[i] = 255;
-                       pic->tex = R_LoadTexture (drawtexturepool, path, 128, 128, pix, TEXTYPE_QPALETTE, TEXF_ALPHA | TEXF_PRECACHE);
+                       pic->width = lmpdata[0] + lmpdata[1] * 256 + lmpdata[2] * 65536 + lmpdata[3] * 16777216;
+                       pic->height = lmpdata[4] + lmpdata[5] * 256 + lmpdata[6] * 65536 + lmpdata[7] * 16777216;
+                       // if no high quality replacement image was found, upload the original low quality texture
+                       if (!pic->tex)
+                               pic->tex = R_LoadTexture2D(drawtexturepool, path, pic->width, pic->height, lmpdata + 8, TEXTYPE_PALETTE, flags, palette_transparent);
+               }
+               Mem_Free(lmpdata);
+       }
+       else if ((lmpdata = W_GetLumpName (path + 4)))
+       {
+               if (!strcmp(path, "gfx/conchars"))
+               {
+                       // conchars is a raw image and with color 0 as transparent instead of 255
+                       pic->width = 128;
+                       pic->height = 128;
+                       // if no high quality replacement image was found, upload the original low quality texture
+                       if (!pic->tex)
+                               pic->tex = R_LoadTexture2D(drawtexturepool, path, 128, 128, lmpdata, TEXTYPE_PALETTE, flags, palette_font);
                }
                else
-                       pic->tex = R_LoadTexture (drawtexturepool, path, p->width, p->height, p->data, TEXTYPE_QPALETTE, TEXF_ALPHA | TEXF_PRECACHE);
+               {
+                       pic->width = lmpdata[0] + lmpdata[1] * 256 + lmpdata[2] * 65536 + lmpdata[3] * 16777216;
+                       pic->height = lmpdata[4] + lmpdata[5] * 256 + lmpdata[6] * 65536 + lmpdata[7] * 16777216;
+                       // if no high quality replacement image was found, upload the original low quality texture
+                       if (!pic->tex)
+                               pic->tex = R_LoadTexture2D(drawtexturepool, path, pic->width, pic->height, lmpdata + 8, TEXTYPE_PALETTE, flags, palette_transparent);
+               }
        }
-       if (pic->tex == NULL && !strcmp(path, "ui/mousepointer.tga"))
-               pic->tex = draw_generatemousepointer();
-       if (pic->tex == NULL && !strcmp(path, "gfx/crosshair1.tga"))
-               pic->tex = draw_generatecrosshair(0);
-       if (pic->tex == NULL && !strcmp(path, "gfx/crosshair2.tga"))
-               pic->tex = draw_generatecrosshair(1);
-       if (pic->tex == NULL && !strcmp(path, "gfx/crosshair3.tga"))
-               pic->tex = draw_generatecrosshair(2);
-       if (pic->tex == NULL && !strcmp(path, "gfx/crosshair4.tga"))
-               pic->tex = draw_generatecrosshair(3);
-       if (pic->tex == NULL && !strcmp(path, "gfx/crosshair5.tga"))
-               pic->tex = draw_generatecrosshair(4);
+
+       // if it's not found on disk, check if it's one of the builtin images
        if (pic->tex == NULL)
-               Sys_Error ("Draw_CachePic: failed to load %s", path);
+       {
+               if (pic->tex == NULL && !strcmp(path, "gfx/conchars"))
+                       pic->tex = draw_generateconchars();
+               if (pic->tex == NULL && !strcmp(path, "ui/mousepointer"))
+                       pic->tex = draw_generatemousepointer();
+               if (pic->tex == NULL && !strcmp(path, "gfx/prydoncursor001"))
+                       pic->tex = draw_generatemousepointer();
+               if (pic->tex == NULL && !strcmp(path, "gfx/crosshair1"))
+                       pic->tex = draw_generatecrosshair(0);
+               if (pic->tex == NULL && !strcmp(path, "gfx/crosshair2"))
+                       pic->tex = draw_generatecrosshair(1);
+               if (pic->tex == NULL && !strcmp(path, "gfx/crosshair3"))
+                       pic->tex = draw_generatecrosshair(2);
+               if (pic->tex == NULL && !strcmp(path, "gfx/crosshair4"))
+                       pic->tex = draw_generatecrosshair(3);
+               if (pic->tex == NULL && !strcmp(path, "gfx/crosshair5"))
+                       pic->tex = draw_generatecrosshair(4);
+               if (pic->tex == NULL && !strcmp(path, "gfx/crosshair6"))
+                       pic->tex = draw_generatecrosshair(5);
+               if (pic->tex == NULL && !strcmp(path, "gfx/colorcontrol/ditherpattern"))
+                       pic->tex = draw_generateditherpattern();
+               if (pic->tex == NULL)
+               {
+                       // don't complain about missing gfx/crosshair images
+                       if (strncmp(path, "gfx/crosshair", 13))
+                               Con_Printf("Draw_CachePic: failed to load %s\n", path);
+                       pic->tex = r_texture_notexture;
+               }
+               pic->width = R_TextureWidth(pic->tex);
+               pic->height = R_TextureHeight(pic->tex);
+       }
 
-       pic->width = R_TextureWidth(pic->tex);
-       pic->height = R_TextureHeight(pic->tex);
        return pic;
 }
 
-cachepic_t *Draw_NewPic(char *picname, int width, int height, int alpha, qbyte *pixels)
+cachepic_t *Draw_NewPic(const char *picname, int width, int height, int alpha, unsigned char *pixels)
 {
        int crc, hashkey;
        cachepic_t *pic;
 
-       crc = CRC_Block(picname, strlen(picname));
+       crc = CRC_Block((unsigned char *)picname, strlen(picname));
        hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
        for (pic = cachepichash[hashkey];pic;pic = pic->chain)
                if (!strcmp (picname, pic->name))
@@ -274,7 +445,7 @@ cachepic_t *Draw_NewPic(char *picname, int width, int height, int alpha, qbyte *
        {
                if (pic->tex && pic->width == width && pic->height == height)
                {
-                       R_UpdateTexture(pic->tex, pixels);
+                       R_UpdateTexture(pic->tex, pixels, 0, 0, width, height);
                        return pic;
                }
        }
@@ -283,9 +454,13 @@ cachepic_t *Draw_NewPic(char *picname, int width, int height, int alpha, qbyte *
                if (pic == NULL)
                {
                        if (numcachepics == MAX_CACHED_PICS)
-                               Sys_Error ("numcachepics == MAX_CACHED_PICS");
+                       {
+                               Con_Printf ("Draw_NewPic: numcachepics == MAX_CACHED_PICS\n");
+                               // FIXME: support NULL in callers?
+                               return cachepics; // return the first one
+                       }
                        pic = cachepics + (numcachepics++);
-                       strcpy (pic->name, picname);
+                       strlcpy (pic->name, picname, sizeof(pic->name));
                        // link into list
                        pic->chain = cachepichash[hashkey];
                        cachepichash[hashkey] = pic;
@@ -296,21 +471,21 @@ cachepic_t *Draw_NewPic(char *picname, int width, int height, int alpha, qbyte *
        pic->height = height;
        if (pic->tex)
                R_FreeTexture(pic->tex);
-       pic->tex = R_LoadTexture (drawtexturepool, picname, width, height, pixels, TEXTYPE_RGBA, alpha ? TEXF_ALPHA : 0);
+       pic->tex = R_LoadTexture2D(drawtexturepool, picname, width, height, pixels, TEXTYPE_RGBA, alpha ? TEXF_ALPHA : 0, NULL);
        return pic;
 }
 
-void Draw_FreePic(char *picname)
+void Draw_FreePic(const char *picname)
 {
        int crc;
        int hashkey;
        cachepic_t *pic;
        // this doesn't really free the pic, but does free it's texture
-       crc = CRC_Block(picname, strlen(picname));
+       crc = CRC_Block((unsigned char *)picname, strlen(picname));
        hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
        for (pic = cachepichash[hashkey];pic;pic = pic->chain)
        {
-               if (!strcmp (picname, pic->name))
+               if (!strcmp (picname, pic->name) && pic->tex)
                {
                        R_FreeTexture(pic->tex);
                        pic->width = 0;
@@ -327,12 +502,18 @@ Draw_Init
 */
 static void gl_draw_start(void)
 {
+       int i;
        drawtexturepool = R_AllocTexturePool();
 
        numcachepics = 0;
        memset(cachepichash, 0, sizeof(cachepichash));
 
-       char_texture = Draw_CachePic("conchars")->tex;
+       char_texture = Draw_CachePic("gfx/conchars", true)->tex;
+       for (i = 1;i <= NUMCROSSHAIRS;i++)
+               r_crosshairs[i] = Draw_CachePic(va("gfx/crosshair%i", i), true);
+
+       // draw the loading screen so people have something to see in the newly opened window
+       SCR_UpdateLoadingScreen(true);
 }
 
 static void gl_draw_shutdown(void)
@@ -349,547 +530,405 @@ static void gl_draw_newmap(void)
 
 void GL_Draw_Init (void)
 {
-       Cvar_RegisterVariable (&scr_conalpha);
+       Cvar_RegisterVariable(&r_textshadow);
+       R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown, gl_draw_newmap);
+}
 
-       numcachepics = 0;
-       memset(cachepichash, 0, sizeof(cachepichash));
+static void _DrawQ_Setup(void)
+{
+       if (r_refdef.draw2dstage)
+               return;
+       r_refdef.draw2dstage = true;
+       CHECKGLERROR
+       qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
+       GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
+       GL_SetupView_Mode_Ortho(0, 0, vid_conwidth.integer, vid_conheight.integer, -10, 100);
+       qglDepthFunc(GL_LEQUAL);CHECKGLERROR
+       qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
+       GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
+       R_Mesh_Matrix(&identitymatrix);
+
+       GL_DepthMask(true);
+       GL_DepthTest(false);
+       GL_Color(1,1,1,1);
+       GL_AlphaTest(false);
+       GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+       if (gl_support_fragment_shader)
+       {
+               qglUseProgramObjectARB(0);CHECKGLERROR
+       }
+}
 
-       R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown, gl_draw_newmap);
+static void _DrawQ_ProcessDrawFlag(int flags)
+{
+       _DrawQ_Setup();
+       CHECKGLERROR
+       if(flags == DRAWFLAG_ADDITIVE)
+               GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+       else if(flags == DRAWFLAG_MODULATE)
+               GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
+       else if(flags == DRAWFLAG_2XMODULATE)
+               GL_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR);
+       else
+               GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 }
 
-extern cvar_t gl_mesh_drawrangeelements;
-extern int gl_maxdrawrangeelementsvertices;
-extern int gl_maxdrawrangeelementsindices;
+void DrawQ_Pic(float x, float y, cachepic_t *pic, float width, float height, float red, float green, float blue, float alpha, int flags)
+{
+       DrawQ_SuperPic(x,y,pic,width,height,0,0,red,green,blue,alpha,1,0,red,green,blue,alpha,0,1,red,green,blue,alpha,1,1,red,green,blue,alpha,flags);
+}
 
-#if 0
-void R_DrawQueue(void)
+void DrawQ_String_Real(float x, float y, const char *string, int maxlen, float w, float h, float red, float green, float blue, float alpha, int flags)
 {
-       int pos, num, chartexnum, overbright;
-       float x, y, w, h, s, t, u, v;
-       cachepic_t *pic;
-       drawqueue_t *dq;
-       char *str, *currentpic;
-       int batch, batchcount, additive;
-       unsigned int color;
-       drawqueuemesh_t *mesh;
+       int i, num;
+       float *av, *at;
+       int batchcount;
+       float vertex3f[QUADELEMENTS_MAXQUADS*4*3];
+       float texcoord2f[QUADELEMENTS_MAXQUADS*4*2];
 
-       if (!r_render.integer)
+       if (alpha < (1.0f / 255.0f))
                return;
 
-       GL_SetupView_ViewPort(vid.realx, vid.realy, vid.realwidth, vid.realheight);
-       GL_SetupView_Mode_Ortho(0, 0, vid.conwidth, vid.conheight, -10, 100);
-       GL_SetupView_Orientation_Identity();
-       GL_DepthFunc(GL_LEQUAL);
-       R_Mesh_Start();
+       _DrawQ_ProcessDrawFlag(flags);
 
-       chartexnum = R_GetTexture(char_texture);
+       GL_Color(red, green, blue, alpha);
 
-       additive = false;
-       qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-       currentpic = "";
-       pic = NULL;
-       qglBindTexture(GL_TEXTURE_2D, 0);
-       color = 0;
-       qglColor4ub(0,0,0,0);
+       R_Mesh_VertexPointer(vertex3f, 0, 0);
+       R_Mesh_ColorPointer(NULL, 0, 0);
+       R_Mesh_ResetTextureState();
+       R_Mesh_TexBind(0, R_GetTexture(char_texture));
+       R_Mesh_TexCoordPointer(0, 2, texcoord2f, 0, 0);
 
-       overbright = v_overbrightbits.integer;
-       batch = false;
+       at = texcoord2f;
+       av = vertex3f;
        batchcount = 0;
-       for (pos = 0;pos < r_refdef.drawqueuesize;pos += ((drawqueue_t *)(r_refdef.drawqueue + pos))->size)
+
+       if (maxlen < 1)
+               maxlen = 9999;
+       for (i = 0;i < maxlen && x < vid_conwidth.integer && (num = string[i]);i++, x += w)
        {
-               dq = (drawqueue_t *)(r_refdef.drawqueue + pos);
-               additive = (dq->flags & DRAWFLAG_ADDITIVE) != 0;
-               color = dq->color;
-               m.blendfunc1 = GL_SRC_ALPHA;
-               if (additive)
-                       m.blendfunc2 = GL_ONE;
-               else
-                       m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
-               m.depthdisable = true;
-               R_Mesh_MainState(&m);
-               cr = (float) ((color >> 24) & 0xFF) * (1.0f / 255.0f) * r_colorscale;
-               cg = (float) ((color >> 16) & 0xFF) * (1.0f / 255.0f) * r_colorscale;
-               cb = (float) ((color >>  8) & 0xFF) * (1.0f / 255.0f) * r_colorscale;
-               ca = (float) ( color        & 0xFF) * (1.0f / 255.0f);
-               x = dq->x;
-               y = dq->y;
-               w = dq->scalex;
-               h = dq->scaley;
-               switch(dq->command)
+               float s, t, u, v;
+               if (num == ' ')
+                       continue;
+               s = (num & 15)*0.0625f + (0.5f / 256.0f);
+               t = (num >> 4)*0.0625f + (0.5f / 256.0f);
+               u = 0.0625f - (1.0f / 256.0f);
+               v = 0.0625f - (1.0f / 256.0f);
+               at[ 0] = s  ;at[ 1] = t  ;
+               at[ 2] = s+u;at[ 3] = t  ;
+               at[ 4] = s+u;at[ 5] = t+v;
+               at[ 6] = s  ;at[ 7] = t+v;
+               av[ 0] = x  ;av[ 1] = y  ;av[ 2] = 10;
+               av[ 3] = x+w;av[ 4] = y  ;av[ 5] = 10;
+               av[ 6] = x+w;av[ 7] = y+h;av[ 8] = 10;
+               av[ 9] = x  ;av[10] = y+h;av[11] = 10;
+               at += 8;
+               av += 12;
+               batchcount++;
+               if (batchcount >= QUADELEMENTS_MAXQUADS)
                {
-               case DRAWQUEUE_PIC:
-                       str = (char *)(dq + 1);
-                       if (*str)
-                       {
-                               if (strcmp(str, currentpic))
-                               {
-                                       if (batch)
-                                       {
-                                               batch = false;
-                                               qglEnd();
-                                       }
-                                       currentpic = str;
-                                       pic = Draw_CachePic(str);
-                                       qglBindTexture(GL_TEXTURE_2D, R_GetTexture(pic->tex));
-                               }
-                               if (w == 0)
-                                       w = pic->width;
-                               if (h == 0)
-                                       h = pic->height;
-                               if (!batch)
-                               {
-                                       batch = true;
-                                       qglBegin(GL_TRIANGLES);
-                                       batchcount = 0;
-                               }
-                               qglTexCoord2f (0, 0);qglVertex2f (x  , y  );
-                               qglTexCoord2f (1, 0);qglVertex2f (x+w, y  );
-                               qglTexCoord2f (1, 1);qglVertex2f (x+w, y+h);
-                               qglTexCoord2f (0, 0);qglVertex2f (x  , y  );
-                               qglTexCoord2f (1, 1);qglVertex2f (x+w, y+h);
-                               qglTexCoord2f (0, 1);qglVertex2f (x  , y+h);
-                               batchcount++;
-                       }
-                       else
-                       {
-                               if (currentpic[0])
-                               {
-                                       if (batch)
-                                       {
-                                               batch = false;
-                                               qglEnd();
-                                       }
-                                       currentpic = "";
-                                       qglBindTexture(GL_TEXTURE_2D, 0);
-                               }
-                               if (!batch)
-                               {
-                                       batch = true;
-                                       qglBegin(GL_TRIANGLES);
-                                       batchcount = 0;
-                               }
-                               qglTexCoord2f (0, 0);qglVertex2f (x  , y  );
-                               qglTexCoord2f (1, 0);qglVertex2f (x+w, y  );
-                               qglTexCoord2f (1, 1);qglVertex2f (x+w, y+h);
-                               qglTexCoord2f (0, 0);qglVertex2f (x  , y  );
-                               qglTexCoord2f (1, 1);qglVertex2f (x+w, y+h);
-                               qglTexCoord2f (0, 1);qglVertex2f (x  , y+h);
-                               batchcount++;
-                       }
-                       break;
-               case DRAWQUEUE_STRING:
-                       str = (char *)(dq + 1);
-                       if (strcmp("conchars", currentpic))
-                       {
-                               if (batch)
-                               {
-                                       batch = false;
-                                       qglEnd();
-                               }
-                               currentpic = "conchars";
-                               qglBindTexture(GL_TEXTURE_2D, chartexnum);
-                       }
-                       if (!batch)
-                       {
-                               batch = true;
-                               qglBegin(GL_TRIANGLES);
-                               batchcount = 0;
-                       }
-                       while ((num = *str++) && x < vid.conwidth)
-                       {
-                               if (num != ' ')
-                               {
-                                       s = (num & 15)*0.0625f + (0.5f / 256.0f);
-                                       t = (num >> 4)*0.0625f + (0.5f / 256.0f);
-                                       u = 0.0625f - (1.0f / 256.0f);
-                                       v = 0.0625f - (1.0f / 256.0f);
-                                       qglTexCoord2f (s  , t  );qglVertex2f (x  , y  );
-                                       qglTexCoord2f (s+u, t  );qglVertex2f (x+w, y  );
-                                       qglTexCoord2f (s+u, t+v);qglVertex2f (x+w, y+h);
-                                       qglTexCoord2f (s  , t  );qglVertex2f (x  , y  );
-                                       qglTexCoord2f (s+u, t+v);qglVertex2f (x+w, y+h);
-                                       qglTexCoord2f (s  , t+v);qglVertex2f (x  , y+h);
-                                       batchcount++;
-                               }
-                               x += w;
-                       }
-                       break;
-               case DRAWQUEUE_MESH:
-                       if (batch)
-                       {
-                               batch = false;
-                               qglEnd();
-                       }
-                       
-                       mesh = (void *)(dq + 1);
-                       qglBindTexture(GL_TEXTURE_2D, R_GetTexture(mesh->texture));
-                       qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), mesh->vertices);CHECKGLERROR
-                       qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), mesh->texcoords);CHECKGLERROR
-                       qglColorPointer(4, GL_UNSIGNED_BYTE, sizeof(qbyte[4]), mesh->colors);CHECKGLERROR
-                       qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
-                       qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
-                       qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
-                       GL_DrawRangeElements(0, mesh->numvertices, mesh->numindices, mesh->indices);
-                       qglDisableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
-                       qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
-                       qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
-
-                       // restore color, since it got trashed by using color array
-                       qglColor4ub((qbyte)(((color >> 24) & 0xFF) >> overbright), (qbyte)(((color >> 16) & 0xFF) >> overbright), (qbyte)(((color >> 8) & 0xFF) >> overbright), (qbyte)(color & 0xFF));
-                       CHECKGLERROR
-                       currentpic = "\0";
-                       break;
+                       GL_LockArrays(0, batchcount * 4);
+                       R_Mesh_Draw(0, batchcount * 4, batchcount * 2, quadelements, 0, 0);
+                       GL_LockArrays(0, 0);
+                       batchcount = 0;
+                       at = texcoord2f;
+                       av = vertex3f;
                }
        }
-       if (batch)
-               qglEnd();
-       CHECKGLERROR
-
-       if (!v_hwgamma.integer)
+       if (batchcount > 0)
        {
-               qglDisable(GL_TEXTURE_2D);
-               CHECKGLERROR
-               t = v_contrast.value * (float) (1 << v_overbrightbits.integer);
-               if (t >= 1.01f)
-               {
-                       qglBlendFunc (GL_DST_COLOR, GL_ONE);
-                       CHECKGLERROR
-                       qglBegin (GL_TRIANGLES);
-                       while (t >= 1.01f)
-                       {
-                               num = (int) ((t - 1.0f) * 255.0f);
-                               if (num > 255)
-                                       num = 255;
-                               qglColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
-                               qglVertex2f (-5000, -5000);
-                               qglVertex2f (10000, -5000);
-                               qglVertex2f (-5000, 10000);
-                               t *= 0.5;
+               GL_LockArrays(0, batchcount * 4);
+               R_Mesh_Draw(0, batchcount * 4, batchcount * 2, quadelements, 0, 0);
+               GL_LockArrays(0, 0);
+       }
+}
+
+void DrawQ_String(float x, float y, const char *string, int maxlen, float scalex, float scaley, float red, float green, float blue, float alpha, int flags)
+{
+       float shadow;
+       if (r_textshadow.integer) {
+               shadow = (1-((red+green+blue)));
+               shadow = bound(0, shadow, 1);
+               DrawQ_String_Real(x+scalex*0.25,y+scaley*0.25,string,maxlen,scalex,scaley,shadow,shadow,shadow,alpha*0.8,flags);
+       }
+
+       DrawQ_String_Real(x,y,string,maxlen,scalex,scaley,red,green,blue,alpha,flags);
+}
+
+// color tag printing
+static vec4_t string_colors[] =
+{
+       // Quake3 colors
+       // LordHavoc: why on earth is cyan before magenta in Quake3?
+       // LordHavoc: note: Doom3 uses white for [0] and [7]
+       {0.0, 0.0, 0.0, 1.0}, // black
+       {1.0, 0.0, 0.0, 1.0}, // red
+       {0.0, 1.0, 0.0, 1.0}, // green
+       {1.0, 1.0, 0.0, 1.0}, // yellow
+       {0.0, 0.0, 1.0, 1.0}, // blue
+       {0.0, 1.0, 1.0, 1.0}, // cyan
+       {1.0, 0.0, 1.0, 1.0}, // magenta
+       {1.0, 1.0, 1.0, 1.0}, // white
+       // [515]'s BX_COLOREDTEXT extension
+       {1.0, 1.0, 1.0, 0.5}, // half transparent
+       {0.5, 0.5, 0.5, 1.0}  // half brightness
+       // Black's color table
+       //{1.0, 1.0, 1.0, 1.0},
+       //{1.0, 0.0, 0.0, 1.0},
+       //{0.0, 1.0, 0.0, 1.0},
+       //{0.0, 0.0, 1.0, 1.0},
+       //{1.0, 1.0, 0.0, 1.0},
+       //{0.0, 1.0, 1.0, 1.0},
+       //{1.0, 0.0, 1.0, 1.0},
+       //{0.1, 0.1, 0.1, 1.0}
+};
+
+#define STRING_COLORS_COUNT    (sizeof(string_colors) / sizeof(vec4_t))
+
+// color is read and changed in the end
+float DrawQ_ColoredString( float x, float y, const char *text, int maxlen, float scalex, float scaley, float basered, float basegreen, float baseblue, float basealpha, int flags, int *outcolor )
+{
+       vec_t *color;
+       int len;
+       int colorindex;
+       const char *start, *current;
+
+       if( !outcolor || *outcolor == -1 ) {
+               colorindex = STRING_COLOR_DEFAULT;
+       } else {
+               colorindex = *outcolor;
+       }
+       color = string_colors[colorindex];
+
+       if( maxlen < 1)
+               len = (int)strlen( text );
+       else
+               len = min( maxlen, (int) strlen( text ) );
+
+       start = current = text;
+       while( len > 0 ) {
+               // check for color control char
+               if( *current == STRING_COLOR_TAG ) {
+                       // get next char
+                       current++;
+                       len--;
+                       if( len == 0 ) {
+                               break;
+                       }
+                       // display the tag char?
+                       if( *current == STRING_COLOR_TAG ) {
+                               // only display one of the two
+                               start = current;
+                               // get the next char
+                               current++;
+                               len--;
+                       } else if( '0' <= *current && *current <= '9' ) {
+                               colorindex = 0;
+                               do {
+                                       colorindex = colorindex * 10 + (*current - '0');
+                                       // only read as long as it makes a valid index
+                                       if( colorindex >= (int)STRING_COLORS_COUNT ) {
+                                               // undo the last operation
+                                               colorindex /= 10;
+                                               break;
+                                       }
+                                       current++;
+                                       len--;
+                               } while( len > 0 && '0' <= *current && *current <= '9' );
+                               // set the color
+                               color = string_colors[colorindex];
+                               // we jump over the color tag
+                               start = current;
                        }
-                       qglEnd ();
-                       CHECKGLERROR
                }
-               else if (t <= 0.99f)
-               {
-                       qglBlendFunc(GL_ZERO, GL_SRC_COLOR);
-                       CHECKGLERROR
-                       qglBegin(GL_TRIANGLES);
-                       num = (int) (t * 255.0f);
-                       qglColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
-                       qglVertex2f (-5000, -5000);
-                       qglVertex2f (10000, -5000);
-                       qglVertex2f (-5000, 10000);
-                       qglEnd();
-                       CHECKGLERROR
+               // go on and read normal text in until the next control char
+               while( len > 0 && *current != STRING_COLOR_TAG ) {
+                       current++;
+                       len--;
                }
-               if (v_brightness.value >= 0.01f)
-               {
-                       qglBlendFunc (GL_ONE, GL_ONE);
-                       CHECKGLERROR
-                       num = (int) (v_brightness.value * 255.0f);
-                       qglColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
-                       CHECKGLERROR
-                       qglBegin (GL_TRIANGLES);
-                       qglVertex2f (-5000, -5000);
-                       qglVertex2f (10000, -5000);
-                       qglVertex2f (-5000, 10000);
-                       qglEnd ();
-                       CHECKGLERROR
+               // display the text
+               if( start != current ) {
+                       // draw the string
+                       DrawQ_String( x, y, start, current - start, scalex, scaley, basered * color[0], basegreen * color[1], baseblue * color[2], basealpha * color[3], flags );
+                       // update x to be at the new start position
+                       x += (current - start) * scalex;
+                       // set start accordingly
+                       start = current;
                }
-               qglEnable(GL_TEXTURE_2D);
-               CHECKGLERROR
        }
 
-       qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+       if( start != current ) {
+               // draw the string
+               DrawQ_String( x, y, start, current - start, scalex, scaley, basered * color[0], basegreen * color[1], baseblue * color[2], basealpha * color[3], flags );
+               // update x to be at the new start position
+               x += (current - start) * scalex;
+               // set start accordingly
+               start = current;
+       }
+
+       // return the last colorindex
+       if( outcolor ) {
+               *outcolor = colorindex;
+       }
+
+       // return the new x position
+       return x;
+}
+
+void DrawQ_SuperPic(float x, float y, cachepic_t *pic, float width, float height, float s1, float t1, float r1, float g1, float b1, float a1, float s2, float t2, float r2, float g2, float b2, float a2, float s3, float t3, float r3, float g3, float b3, float a3, float s4, float t4, float r4, float g4, float b4, float a4, int flags)
+{
+       float floats[36];
+
+       _DrawQ_ProcessDrawFlag(flags);
+
+       R_Mesh_VertexPointer(floats, 0, 0);
+       R_Mesh_ColorPointer(floats + 20, 0, 0);
+       R_Mesh_ResetTextureState();
+       if (pic)
+       {
+               if (width == 0)
+                       width = pic->width;
+               if (height == 0)
+                       height = pic->height;
+               R_Mesh_TexBind(0, R_GetTexture(pic->tex));
+               R_Mesh_TexCoordPointer(0, 2, floats + 12, 0, 0);
+               floats[12] = s1;floats[13] = t1;
+               floats[14] = s2;floats[15] = t2;
+               floats[16] = s4;floats[17] = t4;
+               floats[18] = s3;floats[19] = t3;
+       }
+
+       floats[2] = floats[5] = floats[8] = floats[11] = 0;
+       floats[0] = floats[9] = x;
+       floats[1] = floats[4] = y;
+       floats[3] = floats[6] = x + width;
+       floats[7] = floats[10] = y + height;
+       floats[20] = r1;floats[21] = g1;floats[22] = b1;floats[23] = a1;
+       floats[24] = r2;floats[25] = g2;floats[26] = b2;floats[27] = a2;
+       floats[28] = r4;floats[29] = g4;floats[30] = b4;floats[31] = a4;
+       floats[32] = r3;floats[33] = g3;floats[34] = b3;floats[35] = a3;
+
+       R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
+}
+
+void DrawQ_Mesh (drawqueuemesh_t *mesh, int flags)
+{
+       _DrawQ_ProcessDrawFlag(flags);
+
+       R_Mesh_VertexPointer(mesh->data_vertex3f, 0, 0);
+       R_Mesh_ColorPointer(mesh->data_color4f, 0, 0);
+       R_Mesh_ResetTextureState();
+       R_Mesh_TexBind(0, R_GetTexture(mesh->texture));
+       R_Mesh_TexCoordPointer(0, 2, mesh->data_texcoord2f, 0, 0);
+
+       GL_LockArrays(0, mesh->num_vertices);
+       R_Mesh_Draw(0, mesh->num_vertices, mesh->num_triangles, mesh->data_element3i, 0, 0);
+       GL_LockArrays(0, 0);
+}
+
+void DrawQ_LineLoop (drawqueuemesh_t *mesh, int flags)
+{
+       int num;
+
+       _DrawQ_ProcessDrawFlag(flags);
+
+       GL_Color(1,1,1,1);
        CHECKGLERROR
-       qglEnable (GL_CULL_FACE);
+       qglBegin(GL_LINE_LOOP);
+       for (num = 0;num < mesh->num_vertices;num++)
+       {
+               if (mesh->data_color4f)
+                       GL_Color(mesh->data_color4f[num*4+0], mesh->data_color4f[num*4+1], mesh->data_color4f[num*4+2], mesh->data_color4f[num*4+3]);
+               qglVertex2f(mesh->data_vertex3f[num*3+0], mesh->data_vertex3f[num*3+1]);
+       }
+       qglEnd();
        CHECKGLERROR
-       qglEnable (GL_DEPTH_TEST);
+}
+
+//[515]: this is old, delete
+void DrawQ_Line (float width, float x1, float y1, float x2, float y2, float r, float g, float b, float alpha, int flags)
+{
+       _DrawQ_ProcessDrawFlag(flags);
+
        CHECKGLERROR
-       qglDisable (GL_BLEND);
+       qglLineWidth(width);CHECKGLERROR
+
+       GL_Color(r,g,b,alpha);
        CHECKGLERROR
-       qglColor4ub (255, 255, 255, 255);
+       qglBegin(GL_LINES);
+       qglVertex2f(x1, y1);
+       qglVertex2f(x2, y2);
+       qglEnd();
        CHECKGLERROR
 }
-#else
-void R_DrawQueue(void)
+
+void DrawQ_SetClipArea(float x, float y, float width, float height)
 {
-       int pos, num, chartexnum, overbright;
-       float x, y, w, h, s, t, u, v;
-       cachepic_t *pic;
-       drawqueue_t *dq;
-       char *str, *currentpic;
-       int batch, batchcount, additive;
-       unsigned int color;
-       drawqueuemesh_t *mesh;
+       _DrawQ_Setup();
 
-       if (!r_render.integer)
-               return;
+       // We have to convert the con coords into real coords
+       // OGL uses top to bottom
+       GL_Scissor((int)(x * ((float)vid.width / vid_conwidth.integer)), (int)(y * ((float) vid.height / vid_conheight.integer)), (int)(width * ((float)vid.width / vid_conwidth.integer)), (int)(height * ((float)vid.height / vid_conheight.integer)));
 
-       qglMatrixMode(GL_PROJECTION);
-       qglLoadIdentity();
-       qglOrtho(0, vid.conwidth, vid.conheight, 0, -99999, 99999);
-
-       qglMatrixMode(GL_MODELVIEW);
-    qglLoadIdentity();
-       
-       qglDisable(GL_DEPTH_TEST);
-       qglDisable(GL_CULL_FACE);
-       qglEnable(GL_BLEND);
-       qglEnable(GL_TEXTURE_2D);
-       qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-
-       chartexnum = R_GetTexture(char_texture);
-
-       additive = false;
-       qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-       currentpic = "";
-       pic = NULL;
-       qglBindTexture(GL_TEXTURE_2D, 0);
-       color = 0;
-       qglColor4ub(0,0,0,0);
-
-       overbright = v_overbrightbits.integer;
-       batch = false;
-       batchcount = 0;
-       for (pos = 0;pos < r_refdef.drawqueuesize;pos += ((drawqueue_t *)(r_refdef.drawqueue + pos))->size)
+       GL_ScissorTest(true);
+}
+
+void DrawQ_ResetClipArea(void)
+{
+       _DrawQ_Setup();
+       GL_ScissorTest(false);
+}
+
+void DrawQ_Finish(void)
+{
+       r_refdef.draw2dstage = false;
+}
+
+static float blendvertex3f[9] = {-5000, -5000, 10, 10000, -5000, 10, -5000, 10000, 10};
+void R_DrawGamma(void)
+{
+       float c[4];
+       if (!vid_usinghwgamma)
        {
-               dq = (drawqueue_t *)(r_refdef.drawqueue + pos);
-               if (dq->flags & DRAWFLAG_ADDITIVE)
+               // all the blends ignore depth
+               R_Mesh_VertexPointer(blendvertex3f, 0, 0);
+               R_Mesh_ColorPointer(NULL, 0, 0);
+               R_Mesh_ResetTextureState();
+               GL_DepthMask(true);
+               GL_DepthTest(false);
+               if (v_color_enable.integer)
                {
-                       if (!additive)
-                       {
-                               if (batch)
-                               {
-                                       batch = false;
-                                       qglEnd();
-                               }
-                               additive = true;
-                               qglBlendFunc(GL_SRC_ALPHA, GL_ONE);
-                       }
+                       c[0] = v_color_white_r.value;
+                       c[1] = v_color_white_g.value;
+                       c[2] = v_color_white_b.value;
                }
                else
+                       c[0] = c[1] = c[2] = v_contrast.value;
+               if (c[0] >= 1.01f || c[1] >= 1.01f || c[2] >= 1.01f)
                {
-                       if (additive)
+                       GL_BlendFunc(GL_DST_COLOR, GL_ONE);
+                       while (c[0] >= 1.01f || c[1] >= 1.01f || c[2] >= 1.01f)
                        {
-                               if (batch)
-                               {
-                                       batch = false;
-                                       qglEnd();
-                               }
-                               additive = false;
-                               qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+                               GL_Color(bound(0, c[0] - 1, 1), bound(0, c[1] - 1, 1), bound(0, c[2] - 1, 1), 1);
+                               R_Mesh_Draw(0, 3, 1, polygonelements, 0, 0);
+                               VectorScale(c, 0.5, c);
                        }
                }
-               if (color != dq->color)
+               if (v_color_enable.integer)
                {
-                       color = dq->color;
-                       qglColor4ub((qbyte)(((color >> 24) & 0xFF) >> overbright), (qbyte)(((color >> 16) & 0xFF) >> overbright), (qbyte)(((color >> 8) & 0xFF) >> overbright), (qbyte)(color & 0xFF));
+                       c[0] = v_color_black_r.value;
+                       c[1] = v_color_black_g.value;
+                       c[2] = v_color_black_b.value;
                }
-               if (batch && batchcount > 128)
-               {
-                       batch = false;
-                       qglEnd();
-               }
-               x = dq->x;
-               y = dq->y;
-               w = dq->scalex;
-               h = dq->scaley;
-               switch(dq->command)
-               {
-               case DRAWQUEUE_PIC:
-                       str = (char *)(dq + 1);
-                       if (*str)
-                       {
-                               if (strcmp(str, currentpic))
-                               {
-                                       if (batch)
-                                       {
-                                               batch = false;
-                                               qglEnd();
-                                       }
-                                       currentpic = str;
-                                       pic = Draw_CachePic(str);
-                                       qglBindTexture(GL_TEXTURE_2D, R_GetTexture(pic->tex));
-                               }
-                               if (w == 0)
-                                       w = pic->width;
-                               if (h == 0)
-                                       h = pic->height;
-                               if (!batch)
-                               {
-                                       batch = true;
-                                       qglBegin(GL_TRIANGLES);
-                                       batchcount = 0;
-                               }
-                               qglTexCoord2f (0, 0);qglVertex2f (x  , y  );
-                               qglTexCoord2f (1, 0);qglVertex2f (x+w, y  );
-                               qglTexCoord2f (1, 1);qglVertex2f (x+w, y+h);
-                               qglTexCoord2f (0, 0);qglVertex2f (x  , y  );
-                               qglTexCoord2f (1, 1);qglVertex2f (x+w, y+h);
-                               qglTexCoord2f (0, 1);qglVertex2f (x  , y+h);
-                               batchcount++;
-                       }
-                       else
-                       {
-                               if (currentpic[0])
-                               {
-                                       if (batch)
-                                       {
-                                               batch = false;
-                                               qglEnd();
-                                       }
-                                       currentpic = "";
-                                       qglBindTexture(GL_TEXTURE_2D, 0);
-                               }
-                               if (!batch)
-                               {
-                                       batch = true;
-                                       qglBegin(GL_TRIANGLES);
-                                       batchcount = 0;
-                               }
-                               qglTexCoord2f (0, 0);qglVertex2f (x  , y  );
-                               qglTexCoord2f (1, 0);qglVertex2f (x+w, y  );
-                               qglTexCoord2f (1, 1);qglVertex2f (x+w, y+h);
-                               qglTexCoord2f (0, 0);qglVertex2f (x  , y  );
-                               qglTexCoord2f (1, 1);qglVertex2f (x+w, y+h);
-                               qglTexCoord2f (0, 1);qglVertex2f (x  , y+h);
-                               batchcount++;
-                       }
-                       break;
-               case DRAWQUEUE_STRING:
-                       str = (char *)(dq + 1);
-                       if (strcmp("conchars", currentpic))
-                       {
-                               if (batch)
-                               {
-                                       batch = false;
-                                       qglEnd();
-                               }
-                               currentpic = "conchars";
-                               qglBindTexture(GL_TEXTURE_2D, chartexnum);
-                       }
-                       if (!batch)
-                       {
-                               batch = true;
-                               qglBegin(GL_TRIANGLES);
-                               batchcount = 0;
-                       }
-                       while ((num = *str++) && x < vid.conwidth)
-                       {
-                               if (num != ' ')
-                               {
-                                       s = (num & 15)*0.0625f + (0.5f / 256.0f);
-                                       t = (num >> 4)*0.0625f + (0.5f / 256.0f);
-                                       u = 0.0625f - (1.0f / 256.0f);
-                                       v = 0.0625f - (1.0f / 256.0f);
-                                       qglTexCoord2f (s  , t  );qglVertex2f (x  , y  );
-                                       qglTexCoord2f (s+u, t  );qglVertex2f (x+w, y  );
-                                       qglTexCoord2f (s+u, t+v);qglVertex2f (x+w, y+h);
-                                       qglTexCoord2f (s  , t  );qglVertex2f (x  , y  );
-                                       qglTexCoord2f (s+u, t+v);qglVertex2f (x+w, y+h);
-                                       qglTexCoord2f (s  , t+v);qglVertex2f (x  , y+h);
-                                       batchcount++;
-                               }
-                               x += w;
-                       }
-                       break;
-               case DRAWQUEUE_MESH:
-                       if (batch)
-                       {
-                               batch = false;
-                               qglEnd();
-                       }
-                       
-                       mesh = (void *)(dq + 1);
-                       qglBindTexture(GL_TEXTURE_2D, R_GetTexture(mesh->texture));
-                       qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), mesh->vertices);CHECKGLERROR
-                       qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), mesh->texcoords);CHECKGLERROR
-                       qglColorPointer(4, GL_UNSIGNED_BYTE, sizeof(qbyte[4]), mesh->colors);CHECKGLERROR
-                       qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
-                       qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
-                       qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
-                       GL_DrawRangeElements(0, mesh->numvertices, mesh->numindices, mesh->indices);
-                       qglDisableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
-                       qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
-                       qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
-
-                       // restore color, since it got trashed by using color array
-                       qglColor4ub((qbyte)(((color >> 24) & 0xFF) >> overbright), (qbyte)(((color >> 16) & 0xFF) >> overbright), (qbyte)(((color >> 8) & 0xFF) >> overbright), (qbyte)(color & 0xFF));
-                       CHECKGLERROR
-                       currentpic = "\0";
-                       break;
-               }
-       }
-       if (batch)
-               qglEnd();
-       CHECKGLERROR
-
-       if (!v_hwgamma.integer)
-       {
-               qglDisable(GL_TEXTURE_2D);
-               CHECKGLERROR
-               t = v_contrast.value * (float) (1 << v_overbrightbits.integer);
-               if (t >= 1.01f)
-               {
-                       qglBlendFunc (GL_DST_COLOR, GL_ONE);
-                       CHECKGLERROR
-                       qglBegin (GL_TRIANGLES);
-                       while (t >= 1.01f)
-                       {
-                               num = (int) ((t - 1.0f) * 255.0f);
-                               if (num > 255)
-                                       num = 255;
-                               qglColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
-                               qglVertex2f (-5000, -5000);
-                               qglVertex2f (10000, -5000);
-                               qglVertex2f (-5000, 10000);
-                               t *= 0.5;
-                       }
-                       qglEnd ();
-                       CHECKGLERROR
-               }
-               else if (t <= 0.99f)
-               {
-                       qglBlendFunc(GL_ZERO, GL_SRC_COLOR);
-                       CHECKGLERROR
-                       qglBegin(GL_TRIANGLES);
-                       num = (int) (t * 255.0f);
-                       qglColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
-                       qglVertex2f (-5000, -5000);
-                       qglVertex2f (10000, -5000);
-                       qglVertex2f (-5000, 10000);
-                       qglEnd();
-                       CHECKGLERROR
-               }
-               if (v_brightness.value >= 0.01f)
+               else
+                       c[0] = c[1] = c[2] = v_brightness.value;
+               if (c[0] >= 0.01f || c[1] >= 0.01f || c[2] >= 0.01f)
                {
-                       qglBlendFunc (GL_ONE, GL_ONE);
-                       CHECKGLERROR
-                       num = (int) (v_brightness.value * 255.0f);
-                       qglColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
-                       CHECKGLERROR
-                       qglBegin (GL_TRIANGLES);
-                       qglVertex2f (-5000, -5000);
-                       qglVertex2f (10000, -5000);
-                       qglVertex2f (-5000, 10000);
-                       qglEnd ();
-                       CHECKGLERROR
+                       GL_BlendFunc(GL_ONE, GL_ONE);
+                       GL_Color(c[0], c[1], c[2], 1);
+                       R_Mesh_Draw(0, 3, 1, polygonelements, 0, 0);
                }
-               qglEnable(GL_TEXTURE_2D);
-               CHECKGLERROR
        }
-
-       qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-       CHECKGLERROR
-       qglEnable (GL_CULL_FACE);
-       CHECKGLERROR
-       qglEnable (GL_DEPTH_TEST);
-       CHECKGLERROR
-       qglDisable (GL_BLEND);
-       CHECKGLERROR
-       qglColor4ub (255, 255, 255, 255);
-       CHECKGLERROR
 }
-#endif