attempt at working around a NVIDIA 23.11 TNT driver bug which causes the menu text...
[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 //#define GL_COLOR_INDEX8_EXT     0x80E5
24
25 cvar_t scr_conalpha = {CVAR_SAVE, "scr_conalpha", "1"};
26
27 static rtexture_t *char_texture;
28
29 //=============================================================================
30 /* Support Routines */
31
32 #define MAX_CACHED_PICS 256
33 #define CACHEPICHASHSIZE 256
34 static cachepic_t *cachepichash[CACHEPICHASHSIZE];
35 static cachepic_t cachepics[MAX_CACHED_PICS];
36 static int numcachepics;
37
38 static rtexturepool_t *drawtexturepool;
39
40 static qbyte pointerimage[256] =
41 {
42         "333333332......."
43         "26777761........"
44         "2655541........."
45         "265541.........."
46         "2654561........."
47         "26414561........"
48         "251.14561......."
49         "21...14561......"
50         "1.....141......."
51         ".......1........"
52         "................"
53         "................"
54         "................"
55         "................"
56         "................"
57         "................"
58 };
59
60 static rtexture_t *draw_generatemousepointer(void)
61 {
62         int i;
63         qbyte buffer[256][4];
64         for (i = 0;i < 256;i++)
65         {
66                 if (pointerimage[i] == '.')
67                 {
68                         buffer[i][0] = 0;
69                         buffer[i][1] = 0;
70                         buffer[i][2] = 0;
71                         buffer[i][3] = 0;
72                 }
73                 else
74                 {
75                         buffer[i][0] = (pointerimage[i] - '0') * 16;
76                         buffer[i][1] = (pointerimage[i] - '0') * 16;
77                         buffer[i][2] = (pointerimage[i] - '0') * 16;
78                         buffer[i][3] = 255;
79                 }
80         }
81         return R_LoadTexture(drawtexturepool, "mousepointer", 16, 16, &buffer[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE);
82 }
83
84 // must match NUMCROSSHAIRS in r_crosshairs.c
85 #define NUMCROSSHAIRS 5
86
87 static qbyte *crosshairtexdata[NUMCROSSHAIRS] =
88 {
89         "................"
90         "................"
91         "................"
92         "...33......33..."
93         "...355....553..."
94         "....577..775...."
95         ".....77..77....."
96         "................"
97         "................"
98         ".....77..77....."
99         "....577..775...."
100         "...355....553..."
101         "...33......33..."
102         "................"
103         "................"
104         "................"
105         ,
106         "................"
107         "................"
108         "................"
109         "...3........3..."
110         "....5......5...."
111         ".....7....7....."
112         "......7..7......"
113         "................"
114         "................"
115         "......7..7......"
116         ".....7....7....."
117         "....5......5...."
118         "...3........3..."
119         "................"
120         "................"
121         "................"
122         ,
123         "................"
124         ".......77......."
125         ".......77......."
126         "................"
127         "................"
128         ".......44......."
129         ".......44......."
130         ".77..44..44..77."
131         ".77..44..44..77."
132         ".......44......."
133         ".......44......."
134         "................"
135         ".......77......."
136         ".......77......."
137         "................"
138         "................"
139         ,
140         "................"
141         "................"
142         "................"
143         "................"
144         "................"
145         "................"
146         "................"
147         "................"
148         "........7777777."
149         "........752....."
150         "........72......"
151         "........7......."
152         "........7......."
153         "........7......."
154         "................"
155         "................"
156         ,
157         "................"
158         "................"
159         "................"
160         "................"
161         "................"
162         "........7......."
163         "................"
164         "........4......."
165         ".....7.4.4.7...."
166         "........4......."
167         "................"
168         "........7......."
169         "................"
170         "................"
171         "................"
172         "................"
173 };
174
175 static rtexture_t *draw_generatecrosshair(int num)
176 {
177         int i;
178         char *in;
179         qbyte data[16*16][4];
180         in = crosshairtexdata[num];
181         for (i = 0;i < 16*16;i++)
182         {
183                 if (in[i] == '.')
184                 {
185                         data[i][0] = 255;
186                         data[i][1] = 255;
187                         data[i][2] = 255;
188                         data[i][3] = 0;
189                 }
190                 else
191                 {
192                         data[i][0] = 255;
193                         data[i][1] = 255;
194                         data[i][2] = 255;
195                         data[i][3] = (qbyte) ((int) (in[i] - '0') * 255 / 7);
196                 }
197         }
198         return R_LoadTexture(drawtexturepool, va("crosshair%i", num), 16, 16, &data[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE);
199 }
200
201 /*
202 ================
203 Draw_CachePic
204 ================
205 */
206 // FIXME: move this to client somehow
207 cachepic_t      *Draw_CachePic (char *path)
208 {
209         int i, crc, hashkey;
210         cachepic_t *pic;
211         qpic_t *p;
212
213         crc = CRC_Block(path, strlen(path));
214         hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
215         for (pic = cachepichash[hashkey];pic;pic = pic->chain)
216                 if (!strcmp (path, pic->name))
217                         return pic;
218         //for (pic = cachepics, i = 0;i < numcachepics;pic++, i++)
219         //      if (!strcmp (path, pic->name))
220         //              return pic;
221
222         if (numcachepics == MAX_CACHED_PICS)
223                 Sys_Error ("numcachepics == MAX_CACHED_PICS");
224         pic = cachepics + (numcachepics++);
225         strcpy (pic->name, path);
226         // link into list
227         pic->chain = cachepichash[hashkey];
228         cachepichash[hashkey] = pic;
229
230         // load the pic from disk
231         pic->tex = loadtextureimage(drawtexturepool, path, 0, 0, false, false, true);
232         if (pic->tex == NULL && (p = W_GetLumpName (path)))
233         {
234                 if (!strcmp(path, "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         if (pic->tex == NULL && !strcmp(path, "ui/mousepointer.tga"))
248                 pic->tex = draw_generatemousepointer();
249         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair1.tga"))
250                 pic->tex = draw_generatecrosshair(0);
251         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair2.tga"))
252                 pic->tex = draw_generatecrosshair(1);
253         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair3.tga"))
254                 pic->tex = draw_generatecrosshair(2);
255         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair4.tga"))
256                 pic->tex = draw_generatecrosshair(3);
257         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair5.tga"))
258                 pic->tex = draw_generatecrosshair(4);
259         if (pic->tex == NULL)
260                 Sys_Error ("Draw_CachePic: failed to load %s", path);
261
262         pic->width = R_TextureWidth(pic->tex);
263         pic->height = R_TextureHeight(pic->tex);
264         return pic;
265 }
266
267 /*
268 ===============
269 Draw_Init
270 ===============
271 */
272 static void gl_draw_start(void)
273 {
274         drawtexturepool = R_AllocTexturePool();
275
276         numcachepics = 0;
277         memset(cachepichash, 0, sizeof(cachepichash));
278
279         char_texture = Draw_CachePic("conchars")->tex;
280 }
281
282 static void gl_draw_shutdown(void)
283 {
284         R_FreeTexturePool(&drawtexturepool);
285
286         numcachepics = 0;
287         memset(cachepichash, 0, sizeof(cachepichash));
288 }
289
290 static void gl_draw_newmap(void)
291 {
292 }
293
294 void GL_Draw_Init (void)
295 {
296         Cvar_RegisterVariable (&scr_conalpha);
297
298         numcachepics = 0;
299         memset(cachepichash, 0, sizeof(cachepichash));
300
301         R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown, gl_draw_newmap);
302 }
303
304 void R_DrawQueue(void)
305 {
306         int pos, num, chartexnum, overbright;
307         float x, y, w, h, s, t, u, v;
308         cachepic_t *pic;
309         drawqueue_t *dq;
310         char *str, *currentpic;
311         int batch, batchcount, additive;
312         unsigned int color;
313
314         if (!r_render.integer)
315                 return;
316
317         qglViewport(vid.realx, vid.realy, vid.realwidth, vid.realheight);
318
319         qglMatrixMode(GL_PROJECTION);
320     qglLoadIdentity();
321         qglOrtho(0, vid.conwidth, vid.conheight, 0, -99999, 99999);
322
323         qglMatrixMode(GL_MODELVIEW);
324     qglLoadIdentity();
325
326         qglDisable(GL_DEPTH_TEST);
327         qglDisable(GL_CULL_FACE);
328         qglEnable(GL_BLEND);
329         qglEnable(GL_TEXTURE_2D);
330         qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
331
332         chartexnum = R_GetTexture(char_texture);
333
334         additive = false;
335         qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
336         currentpic = "";
337         pic = NULL;
338         qglBindTexture(GL_TEXTURE_2D, 0);
339         color = 0;
340         qglColor4ub(0,0,0,0);
341
342         // LordHavoc: NEAREST mode on text if not scaling up
343         /*
344         if (vid.realwidth <= (int) vid.conwidth)
345         {
346                 qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
347                 CHECKGLERROR
348                 qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
349                 CHECKGLERROR
350         }
351         else
352         {
353                 qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
354                 CHECKGLERROR
355                 qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
356                 CHECKGLERROR
357         }
358         */
359
360         overbright = v_overbrightbits.integer;
361         batch = false;
362         batchcount = 0;
363         for (pos = 0;pos < r_refdef.drawqueuesize;pos += ((drawqueue_t *)(r_refdef.drawqueue + pos))->size)
364         {
365                 dq = (drawqueue_t *)(r_refdef.drawqueue + pos);
366                 if (dq->flags & DRAWFLAG_ADDITIVE)
367                 {
368                         if (!additive)
369                         {
370                                 if (batch)
371                                 {
372                                         batch = false;
373                                         qglEnd();
374                                 }
375                                 additive = true;
376                                 qglBlendFunc(GL_SRC_ALPHA, GL_ONE);
377                         }
378                 }
379                 else
380                 {
381                         if (additive)
382                         {
383                                 if (batch)
384                                 {
385                                         batch = false;
386                                         qglEnd();
387                                 }
388                                 additive = false;
389                                 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
390                         }
391                 }
392                 if (color != dq->color)
393                 {
394                         color = dq->color;
395                         qglColor4ub((qbyte)(((color >> 24) & 0xFF) >> overbright), (qbyte)(((color >> 16) & 0xFF) >> overbright), (qbyte)(((color >> 8) & 0xFF) >> overbright), (qbyte)(color & 0xFF));
396                 }
397                 if (batch && batchcount > 128)
398                 {
399                         batch = false;
400                         qglEnd();
401                 }
402                 x = dq->x;
403                 y = dq->y;
404                 w = dq->scalex;
405                 h = dq->scaley;
406                 switch(dq->command)
407                 {
408                 case DRAWQUEUE_PIC:
409                         str = (char *)(dq + 1);
410                         if (*str)
411                         {
412                                 if (strcmp(str, currentpic))
413                                 {
414                                         if (batch)
415                                         {
416                                                 batch = false;
417                                                 qglEnd();
418                                         }
419                                         currentpic = str;
420                                         pic = Draw_CachePic(str);
421                                         qglBindTexture(GL_TEXTURE_2D, R_GetTexture(pic->tex));
422                                 }
423                                 if (w == 0)
424                                         w = pic->width;
425                                 if (h == 0)
426                                         h = pic->height;
427                                 if (!batch)
428                                 {
429                                         batch = true;
430                                         qglBegin(GL_TRIANGLES);
431                                         batchcount = 0;
432                                 }
433                                 //DrawQuad(dq->x, dq->y, w, h, 0, 0, 1, 1);
434                                 qglTexCoord2f (0, 0);qglVertex2f (x  , y  );
435                                 qglTexCoord2f (1, 0);qglVertex2f (x+w, y  );
436                                 qglTexCoord2f (1, 1);qglVertex2f (x+w, y+h);
437                                 qglTexCoord2f (0, 0);qglVertex2f (x  , y  );
438                                 qglTexCoord2f (1, 1);qglVertex2f (x+w, y+h);
439                                 qglTexCoord2f (0, 1);qglVertex2f (x  , y+h);
440                                 batchcount++;
441                         }
442                         else
443                         {
444                                 if (currentpic[0])
445                                 {
446                                         if (batch)
447                                         {
448                                                 batch = false;
449                                                 qglEnd();
450                                         }
451                                         currentpic = "";
452                                         qglBindTexture(GL_TEXTURE_2D, 0);
453                                 }
454                                 if (!batch)
455                                 {
456                                         batch = true;
457                                         qglBegin(GL_TRIANGLES);
458                                         batchcount = 0;
459                                 }
460                                 //DrawQuad(dq->x, dq->y, dq->scalex, dq->scaley, 0, 0, 1, 1);
461                                 qglTexCoord2f (0, 0);qglVertex2f (x  , y  );
462                                 qglTexCoord2f (1, 0);qglVertex2f (x+w, y  );
463                                 qglTexCoord2f (1, 1);qglVertex2f (x+w, y+h);
464                                 qglTexCoord2f (0, 0);qglVertex2f (x  , y  );
465                                 qglTexCoord2f (1, 1);qglVertex2f (x+w, y+h);
466                                 qglTexCoord2f (0, 1);qglVertex2f (x  , y+h);
467                                 batchcount++;
468                         }
469                         break;
470                 case DRAWQUEUE_STRING:
471                         str = (char *)(dq + 1);
472                         if (strcmp("conchars", currentpic))
473                         {
474                                 if (batch)
475                                 {
476                                         batch = false;
477                                         qglEnd();
478                                 }
479                                 currentpic = "conchars";
480                                 qglBindTexture(GL_TEXTURE_2D, chartexnum);
481                         }
482                         if (!batch)
483                         {
484                                 batch = true;
485                                 qglBegin(GL_TRIANGLES);
486                                 batchcount = 0;
487                         }
488                         while ((num = *str++) && x < vid.conwidth)
489                         {
490                                 if (num != ' ')
491                                 {
492                                         s = (num & 15)*0.0625f + (0.5f / 256.0f);
493                                         t = (num >> 4)*0.0625f + (0.5f / 256.0f);
494                                         u = 0.0625f - (1.0f / 256.0f);
495                                         v = 0.0625f - (1.0f / 256.0f);
496                                         //DrawQuad(x, y, w, h, (num & 15)*0.0625f + (0.5f / 256.0f), (num >> 4)*0.0625f + (0.5f / 256.0f), 0.0625f - (1.0f / 256.0f), 0.0625f - (1.0f / 256.0f));
497                                         qglTexCoord2f (s  , t  );qglVertex2f (x  , y  );
498                                         qglTexCoord2f (s+u, t  );qglVertex2f (x+w, y  );
499                                         qglTexCoord2f (s+u, t+v);qglVertex2f (x+w, y+h);
500                                         qglTexCoord2f (s  , t  );qglVertex2f (x  , y  );
501                                         qglTexCoord2f (s+u, t+v);qglVertex2f (x+w, y+h);
502                                         qglTexCoord2f (s  , t+v);qglVertex2f (x  , y+h);
503                                         batchcount++;
504                                 }
505                                 x += w;
506                         }
507                         break;
508                 }
509         }
510         if (batch)
511                 qglEnd();
512         CHECKGLERROR
513
514         if (!v_hwgamma.integer)
515         {
516                 qglDisable(GL_TEXTURE_2D);
517                 CHECKGLERROR
518                 t = v_contrast.value * (float) (1 << v_overbrightbits.integer);
519                 if (t >= 1.01f)
520                 {
521                         qglBlendFunc (GL_DST_COLOR, GL_ONE);
522                         CHECKGLERROR
523                         qglBegin (GL_TRIANGLES);
524                         while (t >= 1.01f)
525                         {
526                                 num = (int) ((t - 1.0f) * 255.0f);
527                                 if (num > 255)
528                                         num = 255;
529                                 qglColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
530                                 qglVertex2f (-5000, -5000);
531                                 qglVertex2f (10000, -5000);
532                                 qglVertex2f (-5000, 10000);
533                                 t *= 0.5;
534                         }
535                         qglEnd ();
536                         CHECKGLERROR
537                 }
538                 else if (t <= 0.99f)
539                 {
540                         qglBlendFunc(GL_ZERO, GL_SRC_COLOR);
541                         CHECKGLERROR
542                         qglBegin(GL_TRIANGLES);
543                         num = (int) (t * 255.0f);
544                         qglColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
545                         qglVertex2f (-5000, -5000);
546                         qglVertex2f (10000, -5000);
547                         qglVertex2f (-5000, 10000);
548                         qglEnd();
549                         CHECKGLERROR
550                 }
551                 if (v_brightness.value >= 0.01f)
552                 {
553                         qglBlendFunc (GL_ONE, GL_ONE);
554                         CHECKGLERROR
555                         num = (int) (v_brightness.value * 255.0f);
556                         qglColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
557                         CHECKGLERROR
558                         qglBegin (GL_TRIANGLES);
559                         qglVertex2f (-5000, -5000);
560                         qglVertex2f (10000, -5000);
561                         qglVertex2f (-5000, 10000);
562                         qglEnd ();
563                         CHECKGLERROR
564                 }
565                 qglEnable(GL_TEXTURE_2D);
566                 CHECKGLERROR
567         }
568
569         qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
570         CHECKGLERROR
571         qglEnable (GL_CULL_FACE);
572         CHECKGLERROR
573         qglEnable (GL_DEPTH_TEST);
574         CHECKGLERROR
575         qglDisable (GL_BLEND);
576         CHECKGLERROR
577         qglColor4ub (255, 255, 255, 255);
578         CHECKGLERROR
579 }