]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_draw.c
m.wantoverbright is gone
[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 batch, batchcount, additive;
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         additive = false;
388         qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
389         currentpic = "";
390         pic = NULL;
391         qglBindTexture(GL_TEXTURE_2D, 0);
392         color = 0;
393         qglColor4ub(0,0,0,0);
394
395         overbright = v_overbrightbits.integer;
396         batch = false;
397         batchcount = 0;
398         for (pos = 0;pos < r_refdef.drawqueuesize;pos += ((drawqueue_t *)(r_refdef.drawqueue + pos))->size)
399         {
400                 dq = (drawqueue_t *)(r_refdef.drawqueue + pos);
401                 additive = (dq->flags & DRAWFLAG_ADDITIVE) != 0;
402                 color = dq->color;
403                 m.blendfunc1 = GL_SRC_ALPHA;
404                 if (additive)
405                         m.blendfunc2 = GL_ONE;
406                 else
407                         m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
408                 m.depthdisable = true;
409                 R_Mesh_MainState(&m);
410                 cr = (float) ((color >> 24) & 0xFF) * (1.0f / 255.0f) * r_colorscale;
411                 cg = (float) ((color >> 16) & 0xFF) * (1.0f / 255.0f) * r_colorscale;
412                 cb = (float) ((color >>  8) & 0xFF) * (1.0f / 255.0f) * r_colorscale;
413                 ca = (float) ( color        & 0xFF) * (1.0f / 255.0f);
414                 x = dq->x;
415                 y = dq->y;
416                 w = dq->scalex;
417                 h = dq->scaley;
418                 switch(dq->command)
419                 {
420                 case DRAWQUEUE_PIC:
421                         str = (char *)(dq + 1);
422                         if (*str)
423                         {
424                                 if (strcmp(str, currentpic))
425                                 {
426                                         if (batch)
427                                         {
428                                                 batch = false;
429                                                 qglEnd();
430                                         }
431                                         currentpic = str;
432                                         pic = Draw_CachePic(str);
433                                         qglBindTexture(GL_TEXTURE_2D, R_GetTexture(pic->tex));
434                                 }
435                                 if (w == 0)
436                                         w = pic->width;
437                                 if (h == 0)
438                                         h = pic->height;
439                                 if (!batch)
440                                 {
441                                         batch = true;
442                                         qglBegin(GL_TRIANGLES);
443                                         batchcount = 0;
444                                 }
445                                 qglTexCoord2f (0, 0);qglVertex2f (x  , y  );
446                                 qglTexCoord2f (1, 0);qglVertex2f (x+w, y  );
447                                 qglTexCoord2f (1, 1);qglVertex2f (x+w, y+h);
448                                 qglTexCoord2f (0, 0);qglVertex2f (x  , y  );
449                                 qglTexCoord2f (1, 1);qglVertex2f (x+w, y+h);
450                                 qglTexCoord2f (0, 1);qglVertex2f (x  , y+h);
451                                 batchcount++;
452                         }
453                         else
454                         {
455                                 if (currentpic[0])
456                                 {
457                                         if (batch)
458                                         {
459                                                 batch = false;
460                                                 qglEnd();
461                                         }
462                                         currentpic = "";
463                                         qglBindTexture(GL_TEXTURE_2D, 0);
464                                 }
465                                 if (!batch)
466                                 {
467                                         batch = true;
468                                         qglBegin(GL_TRIANGLES);
469                                         batchcount = 0;
470                                 }
471                                 qglTexCoord2f (0, 0);qglVertex2f (x  , y  );
472                                 qglTexCoord2f (1, 0);qglVertex2f (x+w, y  );
473                                 qglTexCoord2f (1, 1);qglVertex2f (x+w, y+h);
474                                 qglTexCoord2f (0, 0);qglVertex2f (x  , y  );
475                                 qglTexCoord2f (1, 1);qglVertex2f (x+w, y+h);
476                                 qglTexCoord2f (0, 1);qglVertex2f (x  , y+h);
477                                 batchcount++;
478                         }
479                         break;
480                 case DRAWQUEUE_STRING:
481                         str = (char *)(dq + 1);
482                         if (strcmp("conchars", currentpic))
483                         {
484                                 if (batch)
485                                 {
486                                         batch = false;
487                                         qglEnd();
488                                 }
489                                 currentpic = "conchars";
490                                 qglBindTexture(GL_TEXTURE_2D, chartexnum);
491                         }
492                         if (!batch)
493                         {
494                                 batch = true;
495                                 qglBegin(GL_TRIANGLES);
496                                 batchcount = 0;
497                         }
498                         while ((num = *str++) && x < vid.conwidth)
499                         {
500                                 if (num != ' ')
501                                 {
502                                         s = (num & 15)*0.0625f + (0.5f / 256.0f);
503                                         t = (num >> 4)*0.0625f + (0.5f / 256.0f);
504                                         u = 0.0625f - (1.0f / 256.0f);
505                                         v = 0.0625f - (1.0f / 256.0f);
506                                         qglTexCoord2f (s  , t  );qglVertex2f (x  , y  );
507                                         qglTexCoord2f (s+u, t  );qglVertex2f (x+w, y  );
508                                         qglTexCoord2f (s+u, t+v);qglVertex2f (x+w, y+h);
509                                         qglTexCoord2f (s  , t  );qglVertex2f (x  , y  );
510                                         qglTexCoord2f (s+u, t+v);qglVertex2f (x+w, y+h);
511                                         qglTexCoord2f (s  , t+v);qglVertex2f (x  , y+h);
512                                         batchcount++;
513                                 }
514                                 x += w;
515                         }
516                         break;
517                 case DRAWQUEUE_MESH:
518                         if (batch)
519                         {
520                                 batch = false;
521                                 qglEnd();
522                         }
523                         
524                         mesh = (void *)(dq + 1);
525                         qglBindTexture(GL_TEXTURE_2D, R_GetTexture(mesh->texture));
526                         qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), mesh->vertices);CHECKGLERROR
527                         qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), mesh->texcoords);CHECKGLERROR
528                         qglColorPointer(4, GL_UNSIGNED_BYTE, sizeof(qbyte[4]), mesh->colors);CHECKGLERROR
529                         qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
530                         qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
531                         qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
532                         GL_DrawRangeElements(0, mesh->numvertices, mesh->numindices, mesh->indices);
533                         qglDisableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
534                         qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
535                         qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
536
537                         // restore color, since it got trashed by using color array
538                         qglColor4ub((qbyte)(((color >> 24) & 0xFF) >> overbright), (qbyte)(((color >> 16) & 0xFF) >> overbright), (qbyte)(((color >> 8) & 0xFF) >> overbright), (qbyte)(color & 0xFF));
539                         CHECKGLERROR
540                         currentpic = "\0";
541                         break;
542                 }
543         }
544         if (batch)
545                 qglEnd();
546         CHECKGLERROR
547
548         if (!v_hwgamma.integer)
549         {
550                 qglDisable(GL_TEXTURE_2D);
551                 CHECKGLERROR
552                 t = v_contrast.value * (float) (1 << v_overbrightbits.integer);
553                 if (t >= 1.01f)
554                 {
555                         qglBlendFunc (GL_DST_COLOR, GL_ONE);
556                         CHECKGLERROR
557                         qglBegin (GL_TRIANGLES);
558                         while (t >= 1.01f)
559                         {
560                                 num = (int) ((t - 1.0f) * 255.0f);
561                                 if (num > 255)
562                                         num = 255;
563                                 qglColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
564                                 qglVertex2f (-5000, -5000);
565                                 qglVertex2f (10000, -5000);
566                                 qglVertex2f (-5000, 10000);
567                                 t *= 0.5;
568                         }
569                         qglEnd ();
570                         CHECKGLERROR
571                 }
572                 else if (t <= 0.99f)
573                 {
574                         qglBlendFunc(GL_ZERO, GL_SRC_COLOR);
575                         CHECKGLERROR
576                         qglBegin(GL_TRIANGLES);
577                         num = (int) (t * 255.0f);
578                         qglColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
579                         qglVertex2f (-5000, -5000);
580                         qglVertex2f (10000, -5000);
581                         qglVertex2f (-5000, 10000);
582                         qglEnd();
583                         CHECKGLERROR
584                 }
585                 if (v_brightness.value >= 0.01f)
586                 {
587                         qglBlendFunc (GL_ONE, GL_ONE);
588                         CHECKGLERROR
589                         num = (int) (v_brightness.value * 255.0f);
590                         qglColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
591                         CHECKGLERROR
592                         qglBegin (GL_TRIANGLES);
593                         qglVertex2f (-5000, -5000);
594                         qglVertex2f (10000, -5000);
595                         qglVertex2f (-5000, 10000);
596                         qglEnd ();
597                         CHECKGLERROR
598                 }
599                 qglEnable(GL_TEXTURE_2D);
600                 CHECKGLERROR
601         }
602
603         qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
604         CHECKGLERROR
605         qglEnable (GL_CULL_FACE);
606         CHECKGLERROR
607         qglEnable (GL_DEPTH_TEST);
608         CHECKGLERROR
609         qglDisable (GL_BLEND);
610         CHECKGLERROR
611         qglColor4ub (255, 255, 255, 255);
612         CHECKGLERROR
613 }
614 #else
615 void R_DrawQueue(void)
616 {
617         int pos, num, chartexnum, overbright;
618         float x, y, w, h, s, t, u, v;
619         cachepic_t *pic;
620         drawqueue_t *dq;
621         char *str, *currentpic;
622         int batch, batchcount, additive;
623         unsigned int color;
624         drawqueuemesh_t *mesh;
625
626         if (!r_render.integer)
627                 return;
628
629         qglMatrixMode(GL_PROJECTION);
630         qglLoadIdentity();
631         qglOrtho(0, vid.conwidth, vid.conheight, 0, -99999, 99999);
632
633         qglMatrixMode(GL_MODELVIEW);
634     qglLoadIdentity();
635         
636         qglDisable(GL_DEPTH_TEST);
637         qglDisable(GL_CULL_FACE);
638         qglEnable(GL_BLEND);
639         qglEnable(GL_TEXTURE_2D);
640         qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
641
642         chartexnum = R_GetTexture(char_texture);
643
644         additive = false;
645         qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
646         currentpic = "";
647         pic = NULL;
648         qglBindTexture(GL_TEXTURE_2D, 0);
649         color = 0;
650         qglColor4ub(0,0,0,0);
651
652         overbright = v_overbrightbits.integer;
653         batch = false;
654         batchcount = 0;
655         for (pos = 0;pos < r_refdef.drawqueuesize;pos += ((drawqueue_t *)(r_refdef.drawqueue + pos))->size)
656         {
657                 dq = (drawqueue_t *)(r_refdef.drawqueue + pos);
658                 if (dq->flags & DRAWFLAG_ADDITIVE)
659                 {
660                         if (!additive)
661                         {
662                                 if (batch)
663                                 {
664                                         batch = false;
665                                         qglEnd();
666                                 }
667                                 additive = true;
668                                 qglBlendFunc(GL_SRC_ALPHA, GL_ONE);
669                         }
670                 }
671                 else
672                 {
673                         if (additive)
674                         {
675                                 if (batch)
676                                 {
677                                         batch = false;
678                                         qglEnd();
679                                 }
680                                 additive = false;
681                                 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
682                         }
683                 }
684                 if (color != dq->color)
685                 {
686                         color = dq->color;
687                         qglColor4ub((qbyte)(((color >> 24) & 0xFF) >> overbright), (qbyte)(((color >> 16) & 0xFF) >> overbright), (qbyte)(((color >> 8) & 0xFF) >> overbright), (qbyte)(color & 0xFF));
688                 }
689                 if (batch && batchcount > 128)
690                 {
691                         batch = false;
692                         qglEnd();
693                 }
694                 x = dq->x;
695                 y = dq->y;
696                 w = dq->scalex;
697                 h = dq->scaley;
698                 switch(dq->command)
699                 {
700                 case DRAWQUEUE_PIC:
701                         str = (char *)(dq + 1);
702                         if (*str)
703                         {
704                                 if (strcmp(str, currentpic))
705                                 {
706                                         if (batch)
707                                         {
708                                                 batch = false;
709                                                 qglEnd();
710                                         }
711                                         currentpic = str;
712                                         pic = Draw_CachePic(str);
713                                         qglBindTexture(GL_TEXTURE_2D, R_GetTexture(pic->tex));
714                                 }
715                                 if (w == 0)
716                                         w = pic->width;
717                                 if (h == 0)
718                                         h = pic->height;
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                         else
734                         {
735                                 if (currentpic[0])
736                                 {
737                                         if (batch)
738                                         {
739                                                 batch = false;
740                                                 qglEnd();
741                                         }
742                                         currentpic = "";
743                                         qglBindTexture(GL_TEXTURE_2D, 0);
744                                 }
745                                 if (!batch)
746                                 {
747                                         batch = true;
748                                         qglBegin(GL_TRIANGLES);
749                                         batchcount = 0;
750                                 }
751                                 qglTexCoord2f (0, 0);qglVertex2f (x  , y  );
752                                 qglTexCoord2f (1, 0);qglVertex2f (x+w, y  );
753                                 qglTexCoord2f (1, 1);qglVertex2f (x+w, y+h);
754                                 qglTexCoord2f (0, 0);qglVertex2f (x  , y  );
755                                 qglTexCoord2f (1, 1);qglVertex2f (x+w, y+h);
756                                 qglTexCoord2f (0, 1);qglVertex2f (x  , y+h);
757                                 batchcount++;
758                         }
759                         break;
760                 case DRAWQUEUE_STRING:
761                         str = (char *)(dq + 1);
762                         if (strcmp("conchars", currentpic))
763                         {
764                                 if (batch)
765                                 {
766                                         batch = false;
767                                         qglEnd();
768                                 }
769                                 currentpic = "conchars";
770                                 qglBindTexture(GL_TEXTURE_2D, chartexnum);
771                         }
772                         if (!batch)
773                         {
774                                 batch = true;
775                                 qglBegin(GL_TRIANGLES);
776                                 batchcount = 0;
777                         }
778                         while ((num = *str++) && x < vid.conwidth)
779                         {
780                                 if (num != ' ')
781                                 {
782                                         s = (num & 15)*0.0625f + (0.5f / 256.0f);
783                                         t = (num >> 4)*0.0625f + (0.5f / 256.0f);
784                                         u = 0.0625f - (1.0f / 256.0f);
785                                         v = 0.0625f - (1.0f / 256.0f);
786                                         qglTexCoord2f (s  , t  );qglVertex2f (x  , y  );
787                                         qglTexCoord2f (s+u, t  );qglVertex2f (x+w, y  );
788                                         qglTexCoord2f (s+u, t+v);qglVertex2f (x+w, y+h);
789                                         qglTexCoord2f (s  , t  );qglVertex2f (x  , y  );
790                                         qglTexCoord2f (s+u, t+v);qglVertex2f (x+w, y+h);
791                                         qglTexCoord2f (s  , t+v);qglVertex2f (x  , y+h);
792                                         batchcount++;
793                                 }
794                                 x += w;
795                         }
796                         break;
797                 case DRAWQUEUE_MESH:
798                         if (batch)
799                         {
800                                 batch = false;
801                                 qglEnd();
802                         }
803                         
804                         mesh = (void *)(dq + 1);
805                         qglBindTexture(GL_TEXTURE_2D, R_GetTexture(mesh->texture));
806                         qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), mesh->vertices);CHECKGLERROR
807                         qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), mesh->texcoords);CHECKGLERROR
808                         qglColorPointer(4, GL_UNSIGNED_BYTE, sizeof(qbyte[4]), mesh->colors);CHECKGLERROR
809                         qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
810                         qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
811                         qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
812                         GL_DrawRangeElements(0, mesh->numvertices, mesh->numindices, mesh->indices);
813                         qglDisableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
814                         qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
815                         qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
816
817                         // restore color, since it got trashed by using color array
818                         qglColor4ub((qbyte)(((color >> 24) & 0xFF) >> overbright), (qbyte)(((color >> 16) & 0xFF) >> overbright), (qbyte)(((color >> 8) & 0xFF) >> overbright), (qbyte)(color & 0xFF));
819                         CHECKGLERROR
820                         currentpic = "\0";
821                         break;
822                 }
823         }
824         if (batch)
825                 qglEnd();
826         CHECKGLERROR
827
828         if (!v_hwgamma.integer)
829         {
830                 qglDisable(GL_TEXTURE_2D);
831                 CHECKGLERROR
832                 t = v_contrast.value * (float) (1 << v_overbrightbits.integer);
833                 if (t >= 1.01f)
834                 {
835                         qglBlendFunc (GL_DST_COLOR, GL_ONE);
836                         CHECKGLERROR
837                         qglBegin (GL_TRIANGLES);
838                         while (t >= 1.01f)
839                         {
840                                 num = (int) ((t - 1.0f) * 255.0f);
841                                 if (num > 255)
842                                         num = 255;
843                                 qglColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
844                                 qglVertex2f (-5000, -5000);
845                                 qglVertex2f (10000, -5000);
846                                 qglVertex2f (-5000, 10000);
847                                 t *= 0.5;
848                         }
849                         qglEnd ();
850                         CHECKGLERROR
851                 }
852                 else if (t <= 0.99f)
853                 {
854                         qglBlendFunc(GL_ZERO, GL_SRC_COLOR);
855                         CHECKGLERROR
856                         qglBegin(GL_TRIANGLES);
857                         num = (int) (t * 255.0f);
858                         qglColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
859                         qglVertex2f (-5000, -5000);
860                         qglVertex2f (10000, -5000);
861                         qglVertex2f (-5000, 10000);
862                         qglEnd();
863                         CHECKGLERROR
864                 }
865                 if (v_brightness.value >= 0.01f)
866                 {
867                         qglBlendFunc (GL_ONE, GL_ONE);
868                         CHECKGLERROR
869                         num = (int) (v_brightness.value * 255.0f);
870                         qglColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
871                         CHECKGLERROR
872                         qglBegin (GL_TRIANGLES);
873                         qglVertex2f (-5000, -5000);
874                         qglVertex2f (10000, -5000);
875                         qglVertex2f (-5000, 10000);
876                         qglEnd ();
877                         CHECKGLERROR
878                 }
879                 qglEnable(GL_TEXTURE_2D);
880                 CHECKGLERROR
881         }
882
883         qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
884         CHECKGLERROR
885         qglEnable (GL_CULL_FACE);
886         CHECKGLERROR
887         qglEnable (GL_DEPTH_TEST);
888         CHECKGLERROR
889         qglDisable (GL_BLEND);
890         CHECKGLERROR
891         qglColor4ub (255, 255, 255, 255);
892         CHECKGLERROR
893 }
894 #endif
895