colors for DrawQ_Mesh are now float rather than byte, and vertices are padded to...
[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 && (p = W_GetLumpName (path)))
228         {
229                 if (!strcmp(path, "conchars"))
230                 {
231                         qbyte *pix;
232                         // conchars is a raw image and with the wrong transparent color
233                         pix = (qbyte *)p;
234                         for (i = 0;i < 128 * 128;i++)
235                                 if (pix[i] == 0)
236                                         pix[i] = 255;
237                         pic->tex = R_LoadTexture (drawtexturepool, path, 128, 128, pix, TEXTYPE_QPALETTE, TEXF_ALPHA | TEXF_PRECACHE);
238                 }
239                 else
240                         pic->tex = R_LoadTexture (drawtexturepool, path, p->width, p->height, p->data, TEXTYPE_QPALETTE, TEXF_ALPHA | TEXF_PRECACHE);
241         }
242         if (pic->tex == NULL && !strcmp(path, "ui/mousepointer.tga"))
243                 pic->tex = draw_generatemousepointer();
244         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair1.tga"))
245                 pic->tex = draw_generatecrosshair(0);
246         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair2.tga"))
247                 pic->tex = draw_generatecrosshair(1);
248         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair3.tga"))
249                 pic->tex = draw_generatecrosshair(2);
250         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair4.tga"))
251                 pic->tex = draw_generatecrosshair(3);
252         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair5.tga"))
253                 pic->tex = draw_generatecrosshair(4);
254         if (pic->tex == NULL)
255                 Sys_Error ("Draw_CachePic: failed to load %s", path);
256
257         pic->width = R_TextureWidth(pic->tex);
258         pic->height = R_TextureHeight(pic->tex);
259         return pic;
260 }
261
262 cachepic_t *Draw_NewPic(char *picname, int width, int height, int alpha, qbyte *pixels)
263 {
264         int crc, hashkey;
265         cachepic_t *pic;
266
267         crc = CRC_Block(picname, strlen(picname));
268         hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
269         for (pic = cachepichash[hashkey];pic;pic = pic->chain)
270                 if (!strcmp (picname, pic->name))
271                         break;
272
273         if (pic)
274         {
275                 if (pic->tex && pic->width == width && pic->height == height)
276                 {
277                         R_UpdateTexture(pic->tex, pixels);
278                         return pic;
279                 }
280         }
281         else
282         {
283                 if (pic == NULL)
284                 {
285                         if (numcachepics == MAX_CACHED_PICS)
286                                 Sys_Error ("numcachepics == MAX_CACHED_PICS");
287                         pic = cachepics + (numcachepics++);
288                         strcpy (pic->name, picname);
289                         // link into list
290                         pic->chain = cachepichash[hashkey];
291                         cachepichash[hashkey] = pic;
292                 }
293         }
294
295         pic->width = width;
296         pic->height = height;
297         if (pic->tex)
298                 R_FreeTexture(pic->tex);
299         pic->tex = R_LoadTexture (drawtexturepool, picname, width, height, pixels, TEXTYPE_RGBA, alpha ? TEXF_ALPHA : 0);
300         return pic;
301 }
302
303 void Draw_FreePic(char *picname)
304 {
305         int crc;
306         int hashkey;
307         cachepic_t *pic;
308         // this doesn't really free the pic, but does free it's texture
309         crc = CRC_Block(picname, strlen(picname));
310         hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
311         for (pic = cachepichash[hashkey];pic;pic = pic->chain)
312         {
313                 if (!strcmp (picname, pic->name))
314                 {
315                         R_FreeTexture(pic->tex);
316                         pic->width = 0;
317                         pic->height = 0;
318                         return;
319                 }
320         }
321 }
322
323 /*
324 ===============
325 Draw_Init
326 ===============
327 */
328 static void gl_draw_start(void)
329 {
330         drawtexturepool = R_AllocTexturePool();
331
332         numcachepics = 0;
333         memset(cachepichash, 0, sizeof(cachepichash));
334
335         char_texture = Draw_CachePic("conchars")->tex;
336 }
337
338 static void gl_draw_shutdown(void)
339 {
340         R_FreeTexturePool(&drawtexturepool);
341
342         numcachepics = 0;
343         memset(cachepichash, 0, sizeof(cachepichash));
344 }
345
346 static void gl_draw_newmap(void)
347 {
348 }
349
350 void GL_Draw_Init (void)
351 {
352         Cvar_RegisterVariable (&scr_conalpha);
353
354         numcachepics = 0;
355         memset(cachepichash, 0, sizeof(cachepichash));
356
357         R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown, gl_draw_newmap);
358 }
359
360 extern cvar_t gl_mesh_drawrangeelements;
361 extern int gl_maxdrawrangeelementsvertices;
362 extern int gl_maxdrawrangeelementsindices;
363
364 #if 0
365 void R_DrawQueue(void)
366 {
367         int pos, num, chartexnum, overbright;
368         float x, y, w, h, s, t, u, v;
369         cachepic_t *pic;
370         drawqueue_t *dq;
371         char *str, *currentpic;
372         int batchcount;
373         unsigned int color;
374         drawqueuemesh_t *mesh;
375
376         if (!r_render.integer)
377                 return;
378
379         GL_SetupView_ViewPort(vid.realx, vid.realy, vid.realwidth, vid.realheight);
380         GL_SetupView_Mode_Ortho(0, 0, vid.conwidth, vid.conheight, -10, 100);
381         GL_SetupView_Orientation_Identity();
382         GL_DepthFunc(GL_LEQUAL);
383         R_Mesh_Start();
384
385         chartexnum = R_GetTexture(char_texture);
386
387         currentpic = "";
388         pic = NULL;
389         texnum = 0;
390         color = 0;
391
392         overbright = v_overbrightbits.integer;
393         batch = false;
394         batchcount = 0;
395         for (pos = 0;pos < r_refdef.drawqueuesize;pos += ((drawqueue_t *)(r_refdef.drawqueue + pos))->size)
396         {
397                 dq = (drawqueue_t *)(r_refdef.drawqueue + pos);
398                 additive = (dq->flags & DRAWFLAG_ADDITIVE) != 0;
399                 color = dq->color;
400                 m.blendfunc1 = GL_SRC_ALPHA;
401                 if (additive)
402                         m.blendfunc2 = GL_ONE;
403                 else
404                         m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
405                 m.depthdisable = true;
406                 R_Mesh_MainState(&m);
407
408                 cr = (float) ((color >> 24) & 0xFF) * (1.0f / 255.0f) * r_colorscale;
409                 cg = (float) ((color >> 16) & 0xFF) * (1.0f / 255.0f) * r_colorscale;
410                 cb = (float) ((color >>  8) & 0xFF) * (1.0f / 255.0f) * r_colorscale;
411                 ca = (float) ( color        & 0xFF) * (1.0f / 255.0f);
412                 x = dq->x;
413                 y = dq->y;
414                 w = dq->scalex;
415                 h = dq->scaley;
416                 
417                 switch(dq->command)
418                 {
419                 case DRAWQUEUE_PIC:
420                         str = (char *)(dq + 1);
421                         if (strcmp(str, currentpic))
422                         {
423                                 if (batch)
424                                 {
425                                         batch = false;
426                                         qglEnd();
427                                 }
428                                 currentpic = str;
429                                 pic = Draw_CachePic(str);
430                                 qglBindTexture(GL_TEXTURE_2D, R_GetTexture(pic->tex));
431                         }
432                         if (*str)
433                         {
434                                 if (w == 0)
435                                         w = pic->width;
436                                 if (h == 0)
437                                         h = pic->height;
438                         }
439                         varray_color[0] = varray_color[4] = varray_color[ 8] = varray_color[12] = cr;
440                         varray_color[1] = varray_color[5] = varray_color[ 9] = varray_color[13] = cg;
441                         varray_color[2] = varray_color[6] = varray_color[10] = varray_color[14] = cb;
442                         varray_color[3] = varray_color[7] = varray_color[11] = varray_color[15] = ca;
443                         varray_texcoord[0] = 0;varray_texcoord[1] = 0;
444                         varray_texcoord[2] = 1;varray_texcoord[3] = 0;
445                         varray_texcoord[4] = 1;varray_texcoord[5] = 1;
446                         varray_texcoord[6] = 0;varray_texcoord[7] = 1;
447                         varray_vertex[ 0] = x  ;varray_vertex[ 1] = y  ;varray_vertex[ 2] = 0;
448                         varray_vertex[ 4] = x+w;varray_vertex[ 5] = y  ;varray_vertex[ 6] = 0;
449                         varray_vertex[ 8] = x+w;varray_vertex[ 9] = y+h;varray_vertex[10] = 0;
450                         varray_vertex[12] = x  ;varray_vertex[13] = y+h;varray_vertex[14] = 0;
451                         R_Mesh_Draw(4, 2, polygonelements);
452                         break;
453                 case DRAWQUEUE_STRING:
454                         str = (char *)(dq + 1);
455                         if (strcmp("conchars", currentpic))
456                         {
457                                 if (batch)
458                                 {
459                                         batch = false;
460                                         qglEnd();
461                                 }
462                                 currentpic = "conchars";
463                                 qglBindTexture(GL_TEXTURE_2D, chartexnum);
464                         }
465                         batchcount = 0;
466                         ac = varray_color;
467                         at = varray_texcoord;
468                         av = varray_vertex;
469                         while ((num = *str++) && x < vid.conwidth)
470                         {
471                                 if (num != ' ')
472                                 {
473                                         s = (num & 15)*0.0625f + (0.5f / 256.0f);
474                                         t = (num >> 4)*0.0625f + (0.5f / 256.0f);
475                                         u = 0.0625f - (1.0f / 256.0f);
476                                         v = 0.0625f - (1.0f / 256.0f);
477                                         ac[0] = ac[4] = ac[ 8] = ac[12] = cr;
478                                         ac[1] = ac[5] = ac[ 9] = ac[13] = cg;
479                                         ac[2] = ac[6] = ac[10] = ac[14] = cb;
480                                         ac[3] = ac[7] = ac[11] = ac[15] = ca;
481                                         at[0] = s  ;at[1] = t  ;
482                                         at[2] = s+u;at[3] = t  ;
483                                         at[4] = s+u;at[5] = t+v;
484                                         at[6] = s  ;at[7] = t+v;
485                                         av[0] = x  ;av[1] = y  ;av[2] = 0;
486                                         av[4] = x+w;av[1] = y  ;av[2] = 0;
487                                         av[8] = x+w;av[1] = y+h;av[2] = 0;
488                                         av[0] = x  ;av[1] = y+h;av[2] = 0;
489                                         ac += 16;
490                                         at += 8;
491                                         av += 16;
492                                         batchcount++;
493                                         if (batchcount >= 128)
494                                         {
495                                                 R_Mesh_Draw(batchcount * 4, batchcount * 2, polygonelements);
496                                                 batchcount = 0;
497                                                 ac = varray_color;
498                                                 at = varray_texcoord;
499                                                 av = varray_vertex;
500                                         }
501                                 }
502                                 x += w;
503                         }
504                         R_Mesh_Draw(batchcount * 4, batchcount * 2, polygonelements);
505                         break;
506                 case DRAWQUEUE_MESH:
507                         mesh = (void *)(dq + 1);
508                         m.tex[0] = R_GetTexture(mesh->texture);
509                         R_Mesh_ResizeCheck(mesh->numvertices);
510                         memcpy(varray_vertex, mesh->vertices, sizeof(float[4]) * mesh->numvertices);
511                         memcpy(varray_texcoord, mesh->texcoords, sizeof(float[2]) * mesh->numvertices);
512                         memcpy(varray_color, mesh->colors, sizeof(float[4]) * mesh->numvertices);
513                         R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->indices);
514                         currentpic = "\0";
515                         break;
516                 }
517         }
518
519         if (!v_hwgamma.integer)
520         {
521                 t = v_contrast.value * (float) (1 << v_overbrightbits.integer);
522                 if (t >= 1.01f)
523                 {
524                         m.blendfunc1 = GL_DST_COLOR;
525                         m.blendfunc2 = GL_ONE;
526                         m.depthdisable = true;
527                         R_Mesh_State(&m);
528                         while (t >= 1.01f)
529                         {
530                                 cr = t - 1.0f;
531                                 if (cr > 1.0f)
532                                         cr = 1.0f;
533                                 varray_color[0] = varray_color[4] = varray_color[ 8] = varray_color[12] = cr;
534                                 varray_color[1] = varray_color[5] = varray_color[ 9] = varray_color[13] = cr;
535                                 varray_color[2] = varray_color[6] = varray_color[10] = varray_color[14] = cr;
536                                 varray_texcoord[0] = 0;varray_texcoord[1] = 0;
537                                 varray_texcoord[2] = 0;varray_texcoord[3] = 0;
538                                 varray_texcoord[4] = 0;varray_texcoord[5] = 0;
539                                 varray_vertex[0] = -5000;varray_vertex[1] = -5000;varray_vertex[2] = 0;
540                                 varray_vertex[4] = 10000;varray_vertex[1] = -5000;varray_vertex[2] = 0;
541                                 varray_vertex[8] = -5000;varray_vertex[1] = 10000;varray_vertex[2] = 0;
542                                 R_Mesh_Draw(3, 1, polygonelements);
543                                 t *= 0.5;
544                         }
545                 }
546                 else if (t <= 0.99f)
547                 {
548                         qglBlendFunc(GL_ZERO, GL_SRC_COLOR);
549                         CHECKGLERROR
550                         qglBegin(GL_TRIANGLES);
551                         num = (int) (t * 255.0f);
552                         qglColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
553                         qglVertex2f (-5000, -5000);
554                         qglVertex2f (10000, -5000);
555                         qglVertex2f (-5000, 10000);
556                         qglEnd();
557                         CHECKGLERROR
558                 }
559                 if (v_brightness.value >= 0.01f)
560                 {
561                         qglBlendFunc (GL_ONE, GL_ONE);
562                         CHECKGLERROR
563                         num = (int) (v_brightness.value * 255.0f);
564                         qglColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
565                         CHECKGLERROR
566                         qglBegin (GL_TRIANGLES);
567                         qglVertex2f (-5000, -5000);
568                         qglVertex2f (10000, -5000);
569                         qglVertex2f (-5000, 10000);
570                         qglEnd ();
571                         CHECKGLERROR
572                 }
573                 qglEnable(GL_TEXTURE_2D);
574                 CHECKGLERROR
575         }
576
577         qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
578         CHECKGLERROR
579         qglEnable (GL_CULL_FACE);
580         CHECKGLERROR
581         qglEnable (GL_DEPTH_TEST);
582         CHECKGLERROR
583         qglDisable (GL_BLEND);
584         CHECKGLERROR
585         qglColor4ub (255, 255, 255, 255);
586         CHECKGLERROR
587 }
588 #else
589 void R_DrawQueue(void)
590 {
591         int pos, num, chartexnum, overbright;
592         float x, y, w, h, s, t, u, v;
593         cachepic_t *pic;
594         drawqueue_t *dq;
595         char *str, *currentpic;
596         int batch, batchcount, additive;
597         unsigned int color;
598         drawqueuemesh_t *mesh;
599
600         if (!r_render.integer)
601                 return;
602
603         qglMatrixMode(GL_PROJECTION);
604         qglLoadIdentity();
605         qglOrtho(0, vid.conwidth, vid.conheight, 0, -99999, 99999);
606
607         qglMatrixMode(GL_MODELVIEW);
608     qglLoadIdentity();
609         
610         qglDisable(GL_DEPTH_TEST);
611         qglDisable(GL_CULL_FACE);
612         qglEnable(GL_BLEND);
613         qglEnable(GL_TEXTURE_2D);
614         qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
615
616         chartexnum = R_GetTexture(char_texture);
617
618         additive = false;
619         qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
620         currentpic = "";
621         pic = NULL;
622         qglBindTexture(GL_TEXTURE_2D, 0);
623         color = 0;
624         qglColor4ub(0,0,0,0);
625
626         overbright = v_overbrightbits.integer;
627         batch = false;
628         batchcount = 0;
629         for (pos = 0;pos < r_refdef.drawqueuesize;pos += ((drawqueue_t *)(r_refdef.drawqueue + pos))->size)
630         {
631                 dq = (drawqueue_t *)(r_refdef.drawqueue + pos);
632                 if (dq->flags & DRAWFLAG_ADDITIVE)
633                 {
634                         if (!additive)
635                         {
636                                 if (batch)
637                                 {
638                                         batch = false;
639                                         qglEnd();
640                                 }
641                                 additive = true;
642                                 qglBlendFunc(GL_SRC_ALPHA, GL_ONE);
643                         }
644                 }
645                 else
646                 {
647                         if (additive)
648                         {
649                                 if (batch)
650                                 {
651                                         batch = false;
652                                         qglEnd();
653                                 }
654                                 additive = false;
655                                 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
656                         }
657                 }
658                 if (color != dq->color)
659                 {
660                         color = dq->color;
661                         qglColor4ub((qbyte)(((color >> 24) & 0xFF) >> overbright), (qbyte)(((color >> 16) & 0xFF) >> overbright), (qbyte)(((color >> 8) & 0xFF) >> overbright), (qbyte)(color & 0xFF));
662                 }
663                 if (batch && batchcount > 128)
664                 {
665                         batch = false;
666                         qglEnd();
667                 }
668                 x = dq->x;
669                 y = dq->y;
670                 w = dq->scalex;
671                 h = dq->scaley;
672                 switch(dq->command)
673                 {
674                 case DRAWQUEUE_PIC:
675                         str = (char *)(dq + 1);
676                         if (*str)
677                         {
678                                 if (strcmp(str, currentpic))
679                                 {
680                                         if (batch)
681                                         {
682                                                 batch = false;
683                                                 qglEnd();
684                                         }
685                                         currentpic = str;
686                                         pic = Draw_CachePic(str);
687                                         qglBindTexture(GL_TEXTURE_2D, R_GetTexture(pic->tex));
688                                 }
689                                 if (w == 0)
690                                         w = pic->width;
691                                 if (h == 0)
692                                         h = pic->height;
693                                 if (!batch)
694                                 {
695                                         batch = true;
696                                         qglBegin(GL_TRIANGLES);
697                                         batchcount = 0;
698                                 }
699                                 qglTexCoord2f (0, 0);qglVertex2f (x  , y  );
700                                 qglTexCoord2f (1, 0);qglVertex2f (x+w, y  );
701                                 qglTexCoord2f (1, 1);qglVertex2f (x+w, y+h);
702                                 qglTexCoord2f (0, 0);qglVertex2f (x  , y  );
703                                 qglTexCoord2f (1, 1);qglVertex2f (x+w, y+h);
704                                 qglTexCoord2f (0, 1);qglVertex2f (x  , y+h);
705                                 batchcount++;
706                         }
707                         else
708                         {
709                                 if (currentpic[0])
710                                 {
711                                         if (batch)
712                                         {
713                                                 batch = false;
714                                                 qglEnd();
715                                         }
716                                         currentpic = "";
717                                         qglBindTexture(GL_TEXTURE_2D, 0);
718                                 }
719                                 if (!batch)
720                                 {
721                                         batch = true;
722                                         qglBegin(GL_TRIANGLES);
723                                         batchcount = 0;
724                                 }
725                                 qglTexCoord2f (0, 0);qglVertex2f (x  , y  );
726                                 qglTexCoord2f (1, 0);qglVertex2f (x+w, y  );
727                                 qglTexCoord2f (1, 1);qglVertex2f (x+w, y+h);
728                                 qglTexCoord2f (0, 0);qglVertex2f (x  , y  );
729                                 qglTexCoord2f (1, 1);qglVertex2f (x+w, y+h);
730                                 qglTexCoord2f (0, 1);qglVertex2f (x  , y+h);
731                                 batchcount++;
732                         }
733                         break;
734                 case DRAWQUEUE_STRING:
735                         str = (char *)(dq + 1);
736                         if (strcmp("conchars", currentpic))
737                         {
738                                 if (batch)
739                                 {
740                                         batch = false;
741                                         qglEnd();
742                                 }
743                                 currentpic = "conchars";
744                                 qglBindTexture(GL_TEXTURE_2D, chartexnum);
745                         }
746                         if (!batch)
747                         {
748                                 batch = true;
749                                 qglBegin(GL_TRIANGLES);
750                                 batchcount = 0;
751                         }
752                         while ((num = *str++) && x < vid.conwidth)
753                         {
754                                 if (num != ' ')
755                                 {
756                                         s = (num & 15)*0.0625f + (0.5f / 256.0f);
757                                         t = (num >> 4)*0.0625f + (0.5f / 256.0f);
758                                         u = 0.0625f - (1.0f / 256.0f);
759                                         v = 0.0625f - (1.0f / 256.0f);
760                                         qglTexCoord2f (s  , t  );qglVertex2f (x  , y  );
761                                         qglTexCoord2f (s+u, t  );qglVertex2f (x+w, y  );
762                                         qglTexCoord2f (s+u, t+v);qglVertex2f (x+w, y+h);
763                                         qglTexCoord2f (s  , t  );qglVertex2f (x  , y  );
764                                         qglTexCoord2f (s+u, t+v);qglVertex2f (x+w, y+h);
765                                         qglTexCoord2f (s  , t+v);qglVertex2f (x  , y+h);
766                                         batchcount++;
767                                 }
768                                 x += w;
769                         }
770                         break;
771                 case DRAWQUEUE_MESH:
772                         if (batch)
773                         {
774                                 batch = false;
775                                 qglEnd();
776                         }
777                         
778                         mesh = (void *)(dq + 1);
779                         qglBindTexture(GL_TEXTURE_2D, R_GetTexture(mesh->texture));
780                         qglVertexPointer(3, GL_FLOAT, sizeof(float[4]), mesh->vertices);CHECKGLERROR
781                         qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), mesh->texcoords);CHECKGLERROR
782                         qglColorPointer(4, GL_FLOAT, sizeof(float[4]), mesh->colors);CHECKGLERROR
783                         qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
784                         qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
785                         qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
786                         GL_DrawRangeElements(0, mesh->numvertices, mesh->numindices, mesh->indices);
787                         qglDisableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
788                         qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
789                         qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
790
791                         // restore color, since it got trashed by using color array
792                         qglColor4ub((qbyte)(((color >> 24) & 0xFF) >> overbright), (qbyte)(((color >> 16) & 0xFF) >> overbright), (qbyte)(((color >> 8) & 0xFF) >> overbright), (qbyte)(color & 0xFF));
793                         CHECKGLERROR
794                         currentpic = "\0";
795                         break;
796                 }
797         }
798         if (batch)
799                 qglEnd();
800         CHECKGLERROR
801
802         if (!v_hwgamma.integer)
803         {
804                 qglDisable(GL_TEXTURE_2D);
805                 CHECKGLERROR
806                 t = v_contrast.value * (float) (1 << v_overbrightbits.integer);
807                 if (t >= 1.01f)
808                 {
809                         qglBlendFunc (GL_DST_COLOR, GL_ONE);
810                         CHECKGLERROR
811                         qglBegin (GL_TRIANGLES);
812                         while (t >= 1.01f)
813                         {
814                                 num = (int) ((t - 1.0f) * 255.0f);
815                                 if (num > 255)
816                                         num = 255;
817                                 qglColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
818                                 qglVertex2f (-5000, -5000);
819                                 qglVertex2f (10000, -5000);
820                                 qglVertex2f (-5000, 10000);
821                                 t *= 0.5;
822                         }
823                         qglEnd ();
824                         CHECKGLERROR
825                 }
826                 else if (t <= 0.99f)
827                 {
828                         qglBlendFunc(GL_ZERO, GL_SRC_COLOR);
829                         CHECKGLERROR
830                         qglBegin(GL_TRIANGLES);
831                         num = (int) (t * 255.0f);
832                         qglColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
833                         qglVertex2f (-5000, -5000);
834                         qglVertex2f (10000, -5000);
835                         qglVertex2f (-5000, 10000);
836                         qglEnd();
837                         CHECKGLERROR
838                 }
839                 if (v_brightness.value >= 0.01f)
840                 {
841                         qglBlendFunc (GL_ONE, GL_ONE);
842                         CHECKGLERROR
843                         num = (int) (v_brightness.value * 255.0f);
844                         qglColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
845                         CHECKGLERROR
846                         qglBegin (GL_TRIANGLES);
847                         qglVertex2f (-5000, -5000);
848                         qglVertex2f (10000, -5000);
849                         qglVertex2f (-5000, 10000);
850                         qglEnd ();
851                         CHECKGLERROR
852                 }
853                 qglEnable(GL_TEXTURE_2D);
854                 CHECKGLERROR
855         }
856
857         qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
858         CHECKGLERROR
859         qglEnable (GL_CULL_FACE);
860         CHECKGLERROR
861         qglEnable (GL_DEPTH_TEST);
862         CHECKGLERROR
863         qglDisable (GL_BLEND);
864         CHECKGLERROR
865         qglColor4ub (255, 255, 255, 255);
866         CHECKGLERROR
867 }
868 #endif
869