hopefully this fixes the problem in TNT drivers with the options menu (too much 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         glViewport(vid.realx, vid.realy, vid.realwidth, vid.realheight);
318
319         glMatrixMode(GL_PROJECTION);
320     glLoadIdentity();
321         glOrtho(0, vid.conwidth, vid.conheight, 0, -99999, 99999);
322
323         glMatrixMode(GL_MODELVIEW);
324     glLoadIdentity();
325
326         glDisable(GL_DEPTH_TEST);
327         glDisable(GL_CULL_FACE);
328         glEnable(GL_BLEND);
329         glEnable(GL_TEXTURE_2D);
330         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
331
332         chartexnum = R_GetTexture(char_texture);
333
334         additive = false;
335         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
336         currentpic = "";
337         pic = NULL;
338         glBindTexture(GL_TEXTURE_2D, 0);
339         color = 0;
340         glColor4ub(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                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
347                 CHECKGLERROR
348                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
349                 CHECKGLERROR
350         }
351         else
352         {
353                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
354                 CHECKGLERROR
355                 glTexParameteri(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                                         glEnd();
374                                 }
375                                 additive = true;
376                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
377                         }
378                 }
379                 else
380                 {
381                         if (additive)
382                         {
383                                 if (batch)
384                                 {
385                                         batch = false;
386                                         glEnd();
387                                 }
388                                 additive = false;
389                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
390                         }
391                 }
392                 if (color != dq->color)
393                 {
394                         color = dq->color;
395                         glColor4ub((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                         glEnd();
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                                                 glEnd();
418                                         }
419                                         currentpic = str;
420                                         pic = Draw_CachePic(str);
421                                         glBindTexture(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                                         glBegin(GL_QUADS);
431                                         batchcount = 0;
432                                 }
433                                 //DrawQuad(dq->x, dq->y, w, h, 0, 0, 1, 1);
434                                 glTexCoord2f (0, 0);glVertex2f (x  , y  );
435                                 glTexCoord2f (1, 0);glVertex2f (x+w, y  );
436                                 glTexCoord2f (1, 1);glVertex2f (x+w, y+h);
437                                 glTexCoord2f (0, 1);glVertex2f (x  , y+h);
438                                 batchcount++;
439                         }
440                         else
441                         {
442                                 if (currentpic[0])
443                                 {
444                                         if (batch)
445                                         {
446                                                 batch = false;
447                                                 glEnd();
448                                         }
449                                         currentpic = "";
450                                         glBindTexture(GL_TEXTURE_2D, 0);
451                                 }
452                                 if (!batch)
453                                 {
454                                         batch = true;
455                                         glBegin(GL_QUADS);
456                                         batchcount = 0;
457                                 }
458                                 //DrawQuad(dq->x, dq->y, dq->scalex, dq->scaley, 0, 0, 1, 1);
459                                 glTexCoord2f (0, 0);glVertex2f (x  , y  );
460                                 glTexCoord2f (1, 0);glVertex2f (x+w, y  );
461                                 glTexCoord2f (1, 1);glVertex2f (x+w, y+h);
462                                 glTexCoord2f (0, 1);glVertex2f (x  , y+h);
463                                 batchcount++;
464                         }
465                         break;
466                 case DRAWQUEUE_STRING:
467                         str = (char *)(dq + 1);
468                         if (strcmp("conchars", currentpic))
469                         {
470                                 if (batch)
471                                 {
472                                         batch = false;
473                                         glEnd();
474                                 }
475                                 currentpic = "conchars";
476                                 glBindTexture(GL_TEXTURE_2D, chartexnum);
477                         }
478                         if (!batch)
479                         {
480                                 batch = true;
481                                 glBegin(GL_QUADS);
482                                 batchcount = 0;
483                         }
484                         while ((num = *str++) && x < vid.conwidth)
485                         {
486                                 if (num != ' ')
487                                 {
488                                         s = (num & 15)*0.0625f + (0.5f / 256.0f);
489                                         t = (num >> 4)*0.0625f + (0.5f / 256.0f);
490                                         u = 0.0625f - (1.0f / 256.0f);
491                                         v = 0.0625f - (1.0f / 256.0f);
492                                         //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));
493                                         glTexCoord2f (s  , t  );glVertex2f (x  , y  );
494                                         glTexCoord2f (s+u, t  );glVertex2f (x+w, y  );
495                                         glTexCoord2f (s+u, t+v);glVertex2f (x+w, y+h);
496                                         glTexCoord2f (s  , t+v);glVertex2f (x  , y+h);
497                                         batchcount++;
498                                 }
499                                 x += w;
500                         }
501                         break;
502                 }
503         }
504         if (batch)
505                 glEnd();
506         CHECKGLERROR
507
508         if (!v_hwgamma.integer)
509         {
510                 glDisable(GL_TEXTURE_2D);
511                 CHECKGLERROR
512                 t = v_contrast.value * (float) (1 << v_overbrightbits.integer);
513                 if (t >= 1.01f)
514                 {
515                         glBlendFunc (GL_DST_COLOR, GL_ONE);
516                         CHECKGLERROR
517                         glBegin (GL_TRIANGLES);
518                         while (t >= 1.01f)
519                         {
520                                 num = (int) ((t - 1.0f) * 255.0f);
521                                 if (num > 255)
522                                         num = 255;
523                                 glColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
524                                 glVertex2f (-5000, -5000);
525                                 glVertex2f (10000, -5000);
526                                 glVertex2f (-5000, 10000);
527                                 t *= 0.5;
528                         }
529                         glEnd ();
530                         CHECKGLERROR
531                 }
532                 else if (t <= 0.99f)
533                 {
534                         glBlendFunc(GL_ZERO, GL_SRC_COLOR);
535                         CHECKGLERROR
536                         glBegin(GL_TRIANGLES);
537                         num = (int) (t * 255.0f);
538                         glColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
539                         glVertex2f (-5000, -5000);
540                         glVertex2f (10000, -5000);
541                         glVertex2f (-5000, 10000);
542                         glEnd();
543                         CHECKGLERROR
544                 }
545                 if (v_brightness.value >= 0.01f)
546                 {
547                         glBlendFunc (GL_ONE, GL_ONE);
548                         CHECKGLERROR
549                         num = (int) (v_brightness.value * 255.0f);
550                         glColor4ub ((qbyte) num, (qbyte) num, (qbyte) num, 255);
551                         CHECKGLERROR
552                         glBegin (GL_TRIANGLES);
553                         glVertex2f (-5000, -5000);
554                         glVertex2f (10000, -5000);
555                         glVertex2f (-5000, 10000);
556                         glEnd ();
557                         CHECKGLERROR
558                 }
559                 glEnable(GL_TEXTURE_2D);
560                 CHECKGLERROR
561         }
562
563         glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
564         CHECKGLERROR
565         glEnable (GL_CULL_FACE);
566         CHECKGLERROR
567         glEnable (GL_DEPTH_TEST);
568         CHECKGLERROR
569         glDisable (GL_BLEND);
570         CHECKGLERROR
571         glColor4ub (255, 255, 255, 255);
572         CHECKGLERROR
573 }