added newline to end of Draw_CachePic error message
[divverent/darkplaces.git] / gl_draw.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20
21 #include "quakedef.h"
22
23 cvar_t scr_conalpha = {CVAR_SAVE, "scr_conalpha", "1"};
24
25 static rtexture_t *char_texture;
26
27 //=============================================================================
28 /* Support Routines */
29
30 #define MAX_CACHED_PICS 256
31 #define CACHEPICHASHSIZE 256
32 static cachepic_t *cachepichash[CACHEPICHASHSIZE];
33 static cachepic_t cachepics[MAX_CACHED_PICS];
34 static int numcachepics;
35
36 static rtexturepool_t *drawtexturepool;
37
38 static qbyte pointerimage[256] =
39 {
40         "333333332......."
41         "26777761........"
42         "2655541........."
43         "265541.........."
44         "2654561........."
45         "26414561........"
46         "251.14561......."
47         "21...14561......"
48         "1.....141......."
49         ".......1........"
50         "................"
51         "................"
52         "................"
53         "................"
54         "................"
55         "................"
56 };
57
58 static rtexture_t *draw_generatemousepointer(void)
59 {
60         int i;
61         qbyte buffer[256][4];
62         for (i = 0;i < 256;i++)
63         {
64                 if (pointerimage[i] == '.')
65                 {
66                         buffer[i][0] = 0;
67                         buffer[i][1] = 0;
68                         buffer[i][2] = 0;
69                         buffer[i][3] = 0;
70                 }
71                 else
72                 {
73                         buffer[i][0] = (pointerimage[i] - '0') * 16;
74                         buffer[i][1] = (pointerimage[i] - '0') * 16;
75                         buffer[i][2] = (pointerimage[i] - '0') * 16;
76                         buffer[i][3] = 255;
77                 }
78         }
79         return R_LoadTexture(drawtexturepool, "mousepointer", 16, 16, &buffer[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE);
80 }
81
82 // must match NUMCROSSHAIRS in r_crosshairs.c
83 #define NUMCROSSHAIRS 5
84
85 static qbyte *crosshairtexdata[NUMCROSSHAIRS] =
86 {
87         "................"
88         "................"
89         "................"
90         "...33......33..."
91         "...355....553..."
92         "....577..775...."
93         ".....77..77....."
94         "................"
95         "................"
96         ".....77..77....."
97         "....577..775...."
98         "...355....553..."
99         "...33......33..."
100         "................"
101         "................"
102         "................"
103         ,
104         "................"
105         "................"
106         "................"
107         "...3........3..."
108         "....5......5...."
109         ".....7....7....."
110         "......7..7......"
111         "................"
112         "................"
113         "......7..7......"
114         ".....7....7....."
115         "....5......5...."
116         "...3........3..."
117         "................"
118         "................"
119         "................"
120         ,
121         "................"
122         ".......77......."
123         ".......77......."
124         "................"
125         "................"
126         ".......44......."
127         ".......44......."
128         ".77..44..44..77."
129         ".77..44..44..77."
130         ".......44......."
131         ".......44......."
132         "................"
133         ".......77......."
134         ".......77......."
135         "................"
136         "................"
137         ,
138         "................"
139         "................"
140         "................"
141         "................"
142         "................"
143         "................"
144         "................"
145         "................"
146         "........7777777."
147         "........752....."
148         "........72......"
149         "........7......."
150         "........7......."
151         "........7......."
152         "................"
153         "................"
154         ,
155         "................"
156         "................"
157         "................"
158         "................"
159         "................"
160         "........7......."
161         "................"
162         "........4......."
163         ".....7.4.4.7...."
164         "........4......."
165         "................"
166         "........7......."
167         "................"
168         "................"
169         "................"
170         "................"
171 };
172
173 static rtexture_t *draw_generatecrosshair(int num)
174 {
175         int i;
176         char *in;
177         qbyte data[16*16][4];
178         in = crosshairtexdata[num];
179         for (i = 0;i < 16*16;i++)
180         {
181                 if (in[i] == '.')
182                 {
183                         data[i][0] = 255;
184                         data[i][1] = 255;
185                         data[i][2] = 255;
186                         data[i][3] = 0;
187                 }
188                 else
189                 {
190                         data[i][0] = 255;
191                         data[i][1] = 255;
192                         data[i][2] = 255;
193                         data[i][3] = (qbyte) ((int) (in[i] - '0') * 255 / 7);
194                 }
195         }
196         return R_LoadTexture(drawtexturepool, va("crosshair%i", num), 16, 16, &data[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE);
197 }
198
199 /*
200 ================
201 Draw_CachePic
202 ================
203 */
204 // FIXME: move this to client somehow
205 cachepic_t      *Draw_CachePic (char *path)
206 {
207         int i, crc, hashkey;
208         cachepic_t *pic;
209         qpic_t *p;
210
211         crc = CRC_Block(path, strlen(path));
212         hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
213         for (pic = cachepichash[hashkey];pic;pic = pic->chain)
214                 if (!strcmp (path, pic->name))
215                         return pic;
216
217         if (numcachepics == MAX_CACHED_PICS)
218                 Sys_Error ("numcachepics == MAX_CACHED_PICS");
219         pic = cachepics + (numcachepics++);
220         strcpy (pic->name, path);
221         // link into list
222         pic->chain = cachepichash[hashkey];
223         cachepichash[hashkey] = pic;
224
225         // load the pic from disk
226         pic->tex = loadtextureimage(drawtexturepool, path, 0, 0, false, false, true);
227         if (pic->tex == NULL && !strncmp(path, "gfx/", 4))
228         {
229                 // compatibility with older versions
230                 pic->tex = loadtextureimage(drawtexturepool, path + 4, 0, 0, false, false, true);
231                 // failed to find gfx/whatever.tga or similar, try the wad
232                 if (pic->tex == NULL && (p = W_GetLumpName (path + 4)))
233                 {
234                         if (!strcmp(path, "gfx/conchars"))
235                         {
236                                 qbyte *pix;
237                                 // conchars is a raw image and with the wrong transparent color
238                                 pix = (qbyte *)p;
239                                 for (i = 0;i < 128 * 128;i++)
240                                         if (pix[i] == 0)
241                                                 pix[i] = 255;
242                                 pic->tex = R_LoadTexture (drawtexturepool, path, 128, 128, pix, TEXTYPE_QPALETTE, TEXF_ALPHA | TEXF_PRECACHE);
243                         }
244                         else
245                                 pic->tex = R_LoadTexture (drawtexturepool, path, p->width, p->height, p->data, TEXTYPE_QPALETTE, TEXF_ALPHA | TEXF_PRECACHE);
246                 }
247         }
248         if (pic->tex == NULL && !strcmp(path, "ui/mousepointer.tga"))
249                 pic->tex = draw_generatemousepointer();
250         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair1.tga"))
251                 pic->tex = draw_generatecrosshair(0);
252         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair2.tga"))
253                 pic->tex = draw_generatecrosshair(1);
254         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair3.tga"))
255                 pic->tex = draw_generatecrosshair(2);
256         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair4.tga"))
257                 pic->tex = draw_generatecrosshair(3);
258         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair5.tga"))
259                 pic->tex = draw_generatecrosshair(4);
260         if (pic->tex == NULL)
261         {
262                 Con_Printf ("Draw_CachePic: failed to load %s\n", path);
263                 pic->tex = r_notexture;
264         }
265
266         pic->width = R_TextureWidth(pic->tex);
267         pic->height = R_TextureHeight(pic->tex);
268         return pic;
269 }
270
271 cachepic_t *Draw_NewPic(char *picname, int width, int height, int alpha, qbyte *pixels)
272 {
273         int crc, hashkey;
274         cachepic_t *pic;
275
276         crc = CRC_Block(picname, strlen(picname));
277         hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
278         for (pic = cachepichash[hashkey];pic;pic = pic->chain)
279                 if (!strcmp (picname, pic->name))
280                         break;
281
282         if (pic)
283         {
284                 if (pic->tex && pic->width == width && pic->height == height)
285                 {
286                         R_UpdateTexture(pic->tex, pixels);
287                         return pic;
288                 }
289         }
290         else
291         {
292                 if (pic == NULL)
293                 {
294                         if (numcachepics == MAX_CACHED_PICS)
295                                 Sys_Error ("numcachepics == MAX_CACHED_PICS");
296                         pic = cachepics + (numcachepics++);
297                         strcpy (pic->name, picname);
298                         // link into list
299                         pic->chain = cachepichash[hashkey];
300                         cachepichash[hashkey] = pic;
301                 }
302         }
303
304         pic->width = width;
305         pic->height = height;
306         if (pic->tex)
307                 R_FreeTexture(pic->tex);
308         pic->tex = R_LoadTexture (drawtexturepool, picname, width, height, pixels, TEXTYPE_RGBA, alpha ? TEXF_ALPHA : 0);
309         return pic;
310 }
311
312 void Draw_FreePic(char *picname)
313 {
314         int crc;
315         int hashkey;
316         cachepic_t *pic;
317         // this doesn't really free the pic, but does free it's texture
318         crc = CRC_Block(picname, strlen(picname));
319         hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
320         for (pic = cachepichash[hashkey];pic;pic = pic->chain)
321         {
322                 if (!strcmp (picname, pic->name))
323                 {
324                         R_FreeTexture(pic->tex);
325                         pic->width = 0;
326                         pic->height = 0;
327                         return;
328                 }
329         }
330 }
331
332 /*
333 ===============
334 Draw_Init
335 ===============
336 */
337 static void gl_draw_start(void)
338 {
339         drawtexturepool = R_AllocTexturePool();
340
341         numcachepics = 0;
342         memset(cachepichash, 0, sizeof(cachepichash));
343
344         char_texture = Draw_CachePic("gfx/conchars")->tex;
345 }
346
347 static void gl_draw_shutdown(void)
348 {
349         R_FreeTexturePool(&drawtexturepool);
350
351         numcachepics = 0;
352         memset(cachepichash, 0, sizeof(cachepichash));
353 }
354
355 static void gl_draw_newmap(void)
356 {
357 }
358
359 void GL_Draw_Init (void)
360 {
361         Cvar_RegisterVariable (&scr_conalpha);
362
363         numcachepics = 0;
364         memset(cachepichash, 0, sizeof(cachepichash));
365
366         R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown, gl_draw_newmap);
367 }
368
369 extern cvar_t gl_mesh_drawrangeelements;
370 extern int gl_maxdrawrangeelementsvertices;
371 extern int gl_maxdrawrangeelementsindices;
372
373 #if 0
374 void R_DrawQueue(void)
375 {
376         int pos, num, chartexnum, overbright;
377         float x, y, w, h, s, t, u, v;
378         cachepic_t *pic;
379         drawqueue_t *dq;
380         char *str, *currentpic;
381         int batchcount;
382         unsigned int color;
383         drawqueuemesh_t *mesh;
384
385         if (!r_render.integer)
386                 return;
387
388         GL_SetupView_ViewPort(vid.realx, vid.realy, vid.realwidth, vid.realheight);
389         GL_SetupView_Mode_Ortho(0, 0, vid.conwidth, vid.conheight, -10, 100);
390         GL_SetupView_Orientation_Identity();
391         GL_DepthFunc(GL_LEQUAL);
392         R_Mesh_Start();
393
394         chartexnum = R_GetTexture(char_texture);
395
396         currentpic = "";
397         pic = NULL;
398         texnum = 0;
399         color = 0;
400
401         overbright = v_overbrightbits.integer;
402         batch = false;
403         batchcount = 0;
404         for (pos = 0;pos < r_refdef.drawqueuesize;pos += ((drawqueue_t *)(r_refdef.drawqueue + pos))->size)
405         {
406                 dq = (drawqueue_t *)(r_refdef.drawqueue + pos);
407                 additive = (dq->flags & DRAWFLAG_ADDITIVE) != 0;
408                 color = dq->color;
409                 m.blendfunc1 = GL_SRC_ALPHA;
410                 if (additive)
411                         m.blendfunc2 = GL_ONE;
412                 else
413                         m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
414                 m.depthdisable = true;
415                 R_Mesh_MainState(&m);
416
417                 cr = (float) ((color >> 24) & 0xFF) * (1.0f / 255.0f) * r_colorscale;
418                 cg = (float) ((color >> 16) & 0xFF) * (1.0f / 255.0f) * r_colorscale;
419                 cb = (float) ((color >>  8) & 0xFF) * (1.0f / 255.0f) * r_colorscale;
420                 ca = (float) ( color        & 0xFF) * (1.0f / 255.0f);
421                 x = dq->x;
422                 y = dq->y;
423                 w = dq->scalex;
424                 h = dq->scaley;
425                 
426                 switch(dq->command)
427                 {
428                 case DRAWQUEUE_PIC:
429                         str = (char *)(dq + 1);
430                         if (strcmp(str, currentpic))
431                         {
432                                 if (batch)
433                                 {
434                                         batch = false;
435                                         qglEnd();
436                                 }
437                                 currentpic = str;
438                                 pic = Draw_CachePic(str);
439                                 qglBindTexture(GL_TEXTURE_2D, R_GetTexture(pic->tex));
440                         }
441                         if (*str)
442                         {
443                                 if (w == 0)
444                                         w = pic->width;
445                                 if (h == 0)
446                                         h = pic->height;
447                         }
448                         varray_color[0] = varray_color[4] = varray_color[ 8] = varray_color[12] = cr;
449                         varray_color[1] = varray_color[5] = varray_color[ 9] = varray_color[13] = cg;
450                         varray_color[2] = varray_color[6] = varray_color[10] = varray_color[14] = cb;
451                         varray_color[3] = varray_color[7] = varray_color[11] = varray_color[15] = ca;
452                         varray_texcoord[0] = 0;varray_texcoord[1] = 0;
453                         varray_texcoord[2] = 1;varray_texcoord[3] = 0;
454                         varray_texcoord[4] = 1;varray_texcoord[5] = 1;
455                         varray_texcoord[6] = 0;varray_texcoord[7] = 1;
456                         varray_vertex[ 0] = x  ;varray_vertex[ 1] = y  ;varray_vertex[ 2] = 0;
457                         varray_vertex[ 4] = x+w;varray_vertex[ 5] = y  ;varray_vertex[ 6] = 0;
458                         varray_vertex[ 8] = x+w;varray_vertex[ 9] = y+h;varray_vertex[10] = 0;
459                         varray_vertex[12] = x  ;varray_vertex[13] = y+h;varray_vertex[14] = 0;
460                         R_Mesh_Draw(4, 2, polygonelements);
461                         break;
462                 case DRAWQUEUE_STRING:
463                         str = (char *)(dq + 1);
464                         if (strcmp("gfx/conchars", currentpic))
465                         {
466                                 if (batch)
467                                 {
468                                         batch = false;
469                                         qglEnd();
470                                 }
471                                 currentpic = "gfx/conchars";
472                                 qglBindTexture(GL_TEXTURE_2D, chartexnum);
473                         }
474                         batchcount = 0;
475                         ac = varray_color;
476                         at = varray_texcoord;
477                         av = varray_vertex;
478                         while ((num = *str++) && x < vid.conwidth)
479                         {
480                                 if (num != ' ')
481                                 {
482                                         s = (num & 15)*0.0625f + (0.5f / 256.0f);
483                                         t = (num >> 4)*0.0625f + (0.5f / 256.0f);
484                                         u = 0.0625f - (1.0f / 256.0f);
485                                         v = 0.0625f - (1.0f / 256.0f);
486                                         ac[0] = ac[4] = ac[ 8] = ac[12] = cr;
487                                         ac[1] = ac[5] = ac[ 9] = ac[13] = cg;
488                                         ac[2] = ac[6] = ac[10] = ac[14] = cb;
489                                         ac[3] = ac[7] = ac[11] = ac[15] = ca;
490                                         at[0] = s  ;at[1] = t  ;
491                                         at[2] = s+u;at[3] = t  ;
492                                         at[4] = s+u;at[5] = t+v;
493                                         at[6] = s  ;at[7] = t+v;
494                                         av[0] = x  ;av[1] = y  ;av[2] = 0;
495                                         av[4] = x+w;av[1] = y  ;av[2] = 0;
496                                         av[8] = x+w;av[1] = y+h;av[2] = 0;
497                                         av[0] = x  ;av[1] = y+h;av[2] = 0;
498                                         ac += 16;
499                                         at += 8;
500                                         av += 16;
501                                         batchcount++;
502                                         if (batchcount >= 128)
503                                         {
504                                                 R_Mesh_Draw(batchcount * 4, batchcount * 2, polygonelements);
505                                                 batchcount = 0;
506                                                 ac = varray_color;
507                                                 at = varray_texcoord;
508                                                 av = varray_vertex;
509                                         }
510                                 }
511                                 x += w;
512                         }
513                         R_Mesh_Draw(batchcount * 4, batchcount * 2, polygonelements);
514                         break;
515                 case DRAWQUEUE_MESH:
516                         mesh = (void *)(dq + 1);
517                         m.tex[0] = R_GetTexture(mesh->texture);
518                         R_Mesh_ResizeCheck(mesh->numvertices);
519                         memcpy(varray_vertex, mesh->vertices, sizeof(float[4]) * mesh->numvertices);
520                         memcpy(varray_texcoord, mesh->texcoords, sizeof(float[2]) * mesh->numvertices);
521                         memcpy(varray_color, mesh->colors, sizeof(float[4]) * mesh->numvertices);
522                         R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->indices);
523                         currentpic = "\0";
524                         break;
525                 }
526         }
527
528         if (!v_hwgamma.integer)
529         {
530                 t = v_contrast.value * (float) (1 << v_overbrightbits.integer);
531                 if (t >= 1.01f)
532                 {
533                         m.blendfunc1 = GL_DST_COLOR;
534                         m.blendfunc2 = GL_ONE;
535                         m.depthdisable = true;
536                         R_Mesh_State(&m);
537                         while (t >= 1.01f)
538                         {
539                                 cr = t - 1.0f;
540                                 if (cr > 1.0f)
541                                         cr = 1.0f;
542                                 varray_color[0] = varray_color[4] = varray_color[ 8] = varray_color[12] = cr;
543                                 varray_color[1] = varray_color[5] = varray_color[ 9] = varray_color[13] = cr;
544                                 varray_color[2] = varray_color[6] = varray_color[10] = varray_color[14] = cr;
545                                 varray_texcoord[0] = 0;varray_texcoord[1] = 0;
546                                 varray_texcoord[2] = 0;varray_texcoord[3] = 0;
547                                 varray_texcoord[4] = 0;varray_texcoord[5] = 0;
548                                 varray_vertex[0] = -5000;varray_vertex[1] = -5000;varray_vertex[2] = 0;
549                                 varray_vertex[4] = 10000;varray_vertex[1] = -5000;varray_vertex[2] = 0;
550                                 varray_vertex[8] = -5000;varray_vertex[1] = 10000;varray_vertex[2] = 0;
551                                 R_Mesh_Draw(3, 1, polygonelements);
552                                 t *= 0.5;
553                         }
554                 }
555                 else if (t <= 0.99f)
556                 {
557                         qglBlendFunc(GL_ZERO, GL_SRC_COLOR);
558                         CHECKGLERROR
559                         qglBegin(GL_TRIANGLES);
560                         num = (int) (t * 255.0f);
561                         qglColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
562                         qglVertex2f (-5000, -5000);
563                         qglVertex2f (10000, -5000);
564                         qglVertex2f (-5000, 10000);
565                         qglEnd();
566                         CHECKGLERROR
567                 }
568                 if (v_brightness.value >= 0.01f)
569                 {
570                         qglBlendFunc (GL_ONE, GL_ONE);
571                         CHECKGLERROR
572                         num = (int) (v_brightness.value * 255.0f);
573                         qglColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
574                         CHECKGLERROR
575                         qglBegin (GL_TRIANGLES);
576                         qglVertex2f (-5000, -5000);
577                         qglVertex2f (10000, -5000);
578                         qglVertex2f (-5000, 10000);
579                         qglEnd ();
580                         CHECKGLERROR
581                 }
582                 qglEnable(GL_TEXTURE_2D);
583                 CHECKGLERROR
584         }
585
586         qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
587         CHECKGLERROR
588         qglEnable (GL_CULL_FACE);
589         CHECKGLERROR
590         qglEnable (GL_DEPTH_TEST);
591         CHECKGLERROR
592         qglDisable (GL_BLEND);
593         CHECKGLERROR
594         qglColor4ub (255, 255, 255, 255);
595         CHECKGLERROR
596 }
597 #else
598 void R_DrawQueue(void)
599 {
600         int pos, num, chartexnum, overbright;
601         float x, y, w, h, s, t, u, v;
602         cachepic_t *pic;
603         drawqueue_t *dq;
604         char *str, *currentpic;
605         int batch, batchcount, additive;
606         unsigned int color;
607         drawqueuemesh_t *mesh;
608
609         if (!r_render.integer)
610                 return;
611
612         qglMatrixMode(GL_PROJECTION);
613         qglLoadIdentity();
614         qglOrtho(0, vid.conwidth, vid.conheight, 0, -99999, 99999);
615
616         qglMatrixMode(GL_MODELVIEW);
617     qglLoadIdentity();
618         
619         qglDisable(GL_DEPTH_TEST);
620         qglDisable(GL_CULL_FACE);
621         qglEnable(GL_BLEND);
622         qglEnable(GL_TEXTURE_2D);
623         qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
624
625         chartexnum = R_GetTexture(char_texture);
626
627         additive = false;
628         qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
629         currentpic = "";
630         pic = NULL;
631         qglBindTexture(GL_TEXTURE_2D, 0);
632         color = 0;
633         qglColor4ub(0,0,0,0);
634
635         overbright = v_overbrightbits.integer;
636         batch = false;
637         batchcount = 0;
638         for (pos = 0;pos < r_refdef.drawqueuesize;pos += ((drawqueue_t *)(r_refdef.drawqueue + pos))->size)
639         {
640                 dq = (drawqueue_t *)(r_refdef.drawqueue + pos);
641                 if (dq->flags & DRAWFLAG_ADDITIVE)
642                 {
643                         if (!additive)
644                         {
645                                 if (batch)
646                                 {
647                                         batch = false;
648                                         qglEnd();
649                                 }
650                                 additive = true;
651                                 qglBlendFunc(GL_SRC_ALPHA, GL_ONE);
652                         }
653                 }
654                 else
655                 {
656                         if (additive)
657                         {
658                                 if (batch)
659                                 {
660                                         batch = false;
661                                         qglEnd();
662                                 }
663                                 additive = false;
664                                 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
665                         }
666                 }
667                 if (color != dq->color)
668                 {
669                         color = dq->color;
670                         qglColor4ub((qbyte)(((color >> 24) & 0xFF) >> overbright), (qbyte)(((color >> 16) & 0xFF) >> overbright), (qbyte)(((color >> 8) & 0xFF) >> overbright), (qbyte)(color & 0xFF));
671                 }
672                 if (batch && batchcount > 128)
673                 {
674                         batch = false;
675                         qglEnd();
676                 }
677                 x = dq->x;
678                 y = dq->y;
679                 w = dq->scalex;
680                 h = dq->scaley;
681                 switch(dq->command)
682                 {
683                 case DRAWQUEUE_PIC:
684                         str = (char *)(dq + 1);
685                         if (*str)
686                         {
687                                 if (strcmp(str, currentpic))
688                                 {
689                                         if (batch)
690                                         {
691                                                 batch = false;
692                                                 qglEnd();
693                                         }
694                                         currentpic = str;
695                                         pic = Draw_CachePic(str);
696                                         qglBindTexture(GL_TEXTURE_2D, R_GetTexture(pic->tex));
697                                 }
698                                 if (w == 0)
699                                         w = pic->width;
700                                 if (h == 0)
701                                         h = pic->height;
702                                 if (!batch)
703                                 {
704                                         batch = true;
705                                         qglBegin(GL_TRIANGLES);
706                                         batchcount = 0;
707                                 }
708                                 qglTexCoord2f (0, 0);qglVertex2f (x  , y  );
709                                 qglTexCoord2f (1, 0);qglVertex2f (x+w, y  );
710                                 qglTexCoord2f (1, 1);qglVertex2f (x+w, y+h);
711                                 qglTexCoord2f (0, 0);qglVertex2f (x  , y  );
712                                 qglTexCoord2f (1, 1);qglVertex2f (x+w, y+h);
713                                 qglTexCoord2f (0, 1);qglVertex2f (x  , y+h);
714                                 batchcount++;
715                         }
716                         else
717                         {
718                                 if (currentpic[0])
719                                 {
720                                         if (batch)
721                                         {
722                                                 batch = false;
723                                                 qglEnd();
724                                         }
725                                         currentpic = "";
726                                         qglBindTexture(GL_TEXTURE_2D, 0);
727                                 }
728                                 if (!batch)
729                                 {
730                                         batch = true;
731                                         qglBegin(GL_TRIANGLES);
732                                         batchcount = 0;
733                                 }
734                                 qglTexCoord2f (0, 0);qglVertex2f (x  , y  );
735                                 qglTexCoord2f (1, 0);qglVertex2f (x+w, y  );
736                                 qglTexCoord2f (1, 1);qglVertex2f (x+w, y+h);
737                                 qglTexCoord2f (0, 0);qglVertex2f (x  , y  );
738                                 qglTexCoord2f (1, 1);qglVertex2f (x+w, y+h);
739                                 qglTexCoord2f (0, 1);qglVertex2f (x  , y+h);
740                                 batchcount++;
741                         }
742                         break;
743                 case DRAWQUEUE_STRING:
744                         str = (char *)(dq + 1);
745                         if (strcmp("gfx/conchars", currentpic))
746                         {
747                                 if (batch)
748                                 {
749                                         batch = false;
750                                         qglEnd();
751                                 }
752                                 currentpic = "gfx/conchars";
753                                 qglBindTexture(GL_TEXTURE_2D, chartexnum);
754                         }
755                         if (!batch)
756                         {
757                                 batch = true;
758                                 qglBegin(GL_TRIANGLES);
759                                 batchcount = 0;
760                         }
761                         while ((num = *str++) && x < vid.conwidth)
762                         {
763                                 if (num != ' ')
764                                 {
765                                         s = (num & 15)*0.0625f + (0.5f / 256.0f);
766                                         t = (num >> 4)*0.0625f + (0.5f / 256.0f);
767                                         u = 0.0625f - (1.0f / 256.0f);
768                                         v = 0.0625f - (1.0f / 256.0f);
769                                         qglTexCoord2f (s  , t  );qglVertex2f (x  , y  );
770                                         qglTexCoord2f (s+u, t  );qglVertex2f (x+w, y  );
771                                         qglTexCoord2f (s+u, t+v);qglVertex2f (x+w, y+h);
772                                         qglTexCoord2f (s  , t  );qglVertex2f (x  , y  );
773                                         qglTexCoord2f (s+u, t+v);qglVertex2f (x+w, y+h);
774                                         qglTexCoord2f (s  , t+v);qglVertex2f (x  , y+h);
775                                         batchcount++;
776                                 }
777                                 x += w;
778                         }
779                         break;
780                 case DRAWQUEUE_MESH:
781                         if (batch)
782                         {
783                                 batch = false;
784                                 qglEnd();
785                         }
786                         
787                         mesh = (void *)(dq + 1);
788                         qglBindTexture(GL_TEXTURE_2D, R_GetTexture(mesh->texture));
789                         qglVertexPointer(3, GL_FLOAT, sizeof(float[4]), mesh->vertices);CHECKGLERROR
790                         qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), mesh->texcoords);CHECKGLERROR
791                         qglColorPointer(4, GL_FLOAT, sizeof(float[4]), mesh->colors);CHECKGLERROR
792                         qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
793                         qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
794                         qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
795                         GL_DrawRangeElements(0, mesh->numvertices, mesh->numindices, mesh->indices);
796                         qglDisableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
797                         qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
798                         qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
799
800                         // restore color, since it got trashed by using color array
801                         qglColor4ub((qbyte)(((color >> 24) & 0xFF) >> overbright), (qbyte)(((color >> 16) & 0xFF) >> overbright), (qbyte)(((color >> 8) & 0xFF) >> overbright), (qbyte)(color & 0xFF));
802                         CHECKGLERROR
803                         currentpic = "\0";
804                         break;
805                 }
806         }
807         if (batch)
808                 qglEnd();
809         CHECKGLERROR
810
811         if (!v_hwgamma.integer)
812         {
813                 qglDisable(GL_TEXTURE_2D);
814                 CHECKGLERROR
815                 t = v_contrast.value * (float) (1 << v_overbrightbits.integer);
816                 if (t >= 1.01f)
817                 {
818                         qglBlendFunc (GL_DST_COLOR, GL_ONE);
819                         CHECKGLERROR
820                         qglBegin (GL_TRIANGLES);
821                         while (t >= 1.01f)
822                         {
823                                 num = (int) ((t - 1.0f) * 255.0f);
824                                 if (num > 255)
825                                         num = 255;
826                                 qglColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
827                                 qglVertex2f (-5000, -5000);
828                                 qglVertex2f (10000, -5000);
829                                 qglVertex2f (-5000, 10000);
830                                 t *= 0.5;
831                         }
832                         qglEnd ();
833                         CHECKGLERROR
834                 }
835                 else if (t <= 0.99f)
836                 {
837                         qglBlendFunc(GL_ZERO, GL_SRC_COLOR);
838                         CHECKGLERROR
839                         qglBegin(GL_TRIANGLES);
840                         num = (int) (t * 255.0f);
841                         qglColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
842                         qglVertex2f (-5000, -5000);
843                         qglVertex2f (10000, -5000);
844                         qglVertex2f (-5000, 10000);
845                         qglEnd();
846                         CHECKGLERROR
847                 }
848                 if (v_brightness.value >= 0.01f)
849                 {
850                         qglBlendFunc (GL_ONE, GL_ONE);
851                         CHECKGLERROR
852                         num = (int) (v_brightness.value * 255.0f);
853                         qglColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
854                         CHECKGLERROR
855                         qglBegin (GL_TRIANGLES);
856                         qglVertex2f (-5000, -5000);
857                         qglVertex2f (10000, -5000);
858                         qglVertex2f (-5000, 10000);
859                         qglEnd ();
860                         CHECKGLERROR
861                 }
862                 qglEnable(GL_TEXTURE_2D);
863                 CHECKGLERROR
864         }
865
866         qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
867         CHECKGLERROR
868         qglEnable (GL_CULL_FACE);
869         CHECKGLERROR
870         qglEnable (GL_DEPTH_TEST);
871         CHECKGLERROR
872         qglDisable (GL_BLEND);
873         CHECKGLERROR
874         qglColor4ub (255, 255, 255, 255);
875         CHECKGLERROR
876 }
877 #endif
878