2 Copyright (C) 1996-1997 Id Software, Inc.
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.
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.
13 See the GNU General Public License for more details.
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.
27 cvar_t r_textshadow = {0, "r_textshadow", "0", "draws a shadow on all text to improve readability"};
29 static rtexture_t *char_texture;
30 cachepic_t *r_crosshairs[NUMCROSSHAIRS+1];
32 //=============================================================================
33 /* Support Routines */
35 #define FONT_FILESIZE 13468
36 #define MAX_CACHED_PICS 1024
37 #define CACHEPICHASHSIZE 256
38 static cachepic_t *cachepichash[CACHEPICHASHSIZE];
39 static cachepic_t cachepics[MAX_CACHED_PICS];
40 static int numcachepics;
42 static rtexturepool_t *drawtexturepool;
44 static unsigned char concharimage[FONT_FILESIZE] =
49 static rtexture_t *draw_generateconchars(void)
52 unsigned char buffer[65536][4], *data = NULL;
55 data = LoadTGA (concharimage, FONT_FILESIZE, 256, 256);
57 for (i = 0;i < 8192;i++)
59 random = lhrandom (0.0,1.0);
60 buffer[i][0] = 83 + (unsigned char)(random * 64);
61 buffer[i][1] = 71 + (unsigned char)(random * 32);
62 buffer[i][2] = 23 + (unsigned char)(random * 16);
63 buffer[i][3] = data[i*4+0];
66 for (i = 8192;i < 32768;i++)
68 random = lhrandom (0.0,1.0);
69 buffer[i][0] = 95 + (unsigned char)(random * 64);
70 buffer[i][1] = 95 + (unsigned char)(random * 64);
71 buffer[i][2] = 95 + (unsigned char)(random * 64);
72 buffer[i][3] = data[i*4+0];
75 for (i = 32768;i < 40960;i++)
77 random = lhrandom (0.0,1.0);
78 buffer[i][0] = 83 + (unsigned char)(random * 64);
79 buffer[i][1] = 71 + (unsigned char)(random * 32);
80 buffer[i][2] = 23 + (unsigned char)(random * 16);
81 buffer[i][3] = data[i*4+0];
84 for (i = 40960;i < 65536;i++)
86 random = lhrandom (0.0,1.0);
87 buffer[i][0] = 96 + (unsigned char)(random * 64);
88 buffer[i][1] = 43 + (unsigned char)(random * 32);
89 buffer[i][2] = 27 + (unsigned char)(random * 32);
90 buffer[i][3] = data[i*4+0];
94 Image_WriteTGARGBA ("gfx/generated_conchars.tga", 256, 256, &buffer[0][0]);
98 return R_LoadTexture2D(drawtexturepool, "conchars", 256, 256, &buffer[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
101 static char *pointerimage =
120 static rtexture_t *draw_generatemousepointer(void)
123 unsigned char buffer[256][4];
124 for (i = 0;i < 256;i++)
126 if (pointerimage[i] == '.')
135 buffer[i][0] = (pointerimage[i] - '0') * 16;
136 buffer[i][1] = (pointerimage[i] - '0') * 16;
137 buffer[i][2] = (pointerimage[i] - '0') * 16;
141 return R_LoadTexture2D(drawtexturepool, "mousepointer", 16, 16, &buffer[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
144 static char *crosshairtexdata[NUMCROSSHAIRS] =
249 static rtexture_t *draw_generatecrosshair(int num)
253 unsigned char data[16*16][4];
254 in = crosshairtexdata[num];
255 for (i = 0;i < 16*16;i++)
266 data[i][0] = data[i][1] = data[i][2] = (unsigned char) ((int) (in[i] - '0') * 127 / 7 + 128);
270 return R_LoadTexture2D(drawtexturepool, va("crosshair%i", num), 16, 16, &data[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
273 static rtexture_t *draw_generateditherpattern(void)
277 unsigned char data[8*8*4];
278 for (y = 0;y < 8;y++)
280 for (x = 0;x < 8;x++)
282 data[(y*8+x)*4+0] = data[(y*8+x)*4+1] = data[(y*8+x)*4+2] = ((x^y) & 4) ? 255 : 0;
283 data[(y*8+x)*4+3] = 255;
286 return R_LoadTexture2D(drawtexturepool, "ditherpattern", 8, 8, data, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_PRECACHE, NULL);
288 unsigned char data[16];
289 memset(data, 255, sizeof(data));
290 data[0] = data[1] = data[2] = data[12] = data[13] = data[14] = 0;
291 return R_LoadTexture2D(drawtexturepool, "ditherpattern", 2, 2, data, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_PRECACHE, NULL);
300 // FIXME: move this to client somehow
301 cachepic_t *Draw_CachePic (const char *path, qboolean persistent)
307 unsigned char *lmpdata;
308 char lmpname[MAX_QPATH];
310 if (!strncmp(CLVIDEOPREFIX, path, sizeof(CLVIDEOPREFIX) - 1))
314 video = CL_GetVideoByName(path);
319 crc = CRC_Block((unsigned char *)path, strlen(path));
320 hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
321 for (pic = cachepichash[hashkey];pic;pic = pic->chain)
322 if (!strcmp (path, pic->name))
325 if (numcachepics == MAX_CACHED_PICS)
327 Con_Printf ("Draw_CachePic: numcachepics == MAX_CACHED_PICS\n");
328 // FIXME: support NULL in callers?
329 return cachepics; // return the first one
331 pic = cachepics + (numcachepics++);
332 strlcpy (pic->name, path, sizeof(pic->name));
334 pic->chain = cachepichash[hashkey];
335 cachepichash[hashkey] = pic;
339 flags |= TEXF_PRECACHE;
340 if (!strcmp(path, "gfx/colorcontrol/ditherpattern"))
343 // load a high quality image from disk if possible
344 pic->tex = loadtextureimage(drawtexturepool, path, 0, 0, false, flags);
345 if (pic->tex == NULL && !strncmp(path, "gfx/", 4))
347 // compatibility with older versions which did not require gfx/ prefix
348 pic->tex = loadtextureimage(drawtexturepool, path + 4, 0, 0, false, flags);
350 // if a high quality image was loaded, set the pic's size to match it, just
351 // in case there's no low quality version to get the size from
354 pic->width = R_TextureWidth(pic->tex);
355 pic->height = R_TextureHeight(pic->tex);
358 // now read the low quality version (wad or lmp file), and take the pic
359 // size from that even if we don't upload the texture, this way the pics
360 // show up the right size in the menu even if they were replaced with
361 // higher or lower resolution versions
362 dpsnprintf(lmpname, sizeof(lmpname), "%s.lmp", path);
363 if (!strncmp(path, "gfx/", 4) && (lmpdata = FS_LoadFile(lmpname, tempmempool, false, &lmpsize)))
367 pic->width = lmpdata[0] + lmpdata[1] * 256 + lmpdata[2] * 65536 + lmpdata[3] * 16777216;
368 pic->height = lmpdata[4] + lmpdata[5] * 256 + lmpdata[6] * 65536 + lmpdata[7] * 16777216;
369 // if no high quality replacement image was found, upload the original low quality texture
371 pic->tex = R_LoadTexture2D(drawtexturepool, path, pic->width, pic->height, lmpdata + 8, TEXTYPE_PALETTE, flags, palette_transparent);
375 else if ((lmpdata = W_GetLumpName (path + 4)))
377 if (!strcmp(path, "gfx/conchars"))
379 // conchars is a raw image and with color 0 as transparent instead of 255
382 // if no high quality replacement image was found, upload the original low quality texture
384 pic->tex = R_LoadTexture2D(drawtexturepool, path, 128, 128, lmpdata, TEXTYPE_PALETTE, flags, palette_font);
388 pic->width = lmpdata[0] + lmpdata[1] * 256 + lmpdata[2] * 65536 + lmpdata[3] * 16777216;
389 pic->height = lmpdata[4] + lmpdata[5] * 256 + lmpdata[6] * 65536 + lmpdata[7] * 16777216;
390 // if no high quality replacement image was found, upload the original low quality texture
392 pic->tex = R_LoadTexture2D(drawtexturepool, path, pic->width, pic->height, lmpdata + 8, TEXTYPE_PALETTE, flags, palette_transparent);
396 // if it's not found on disk, check if it's one of the builtin images
397 if (pic->tex == NULL)
399 if (pic->tex == NULL && !strcmp(path, "gfx/conchars"))
400 pic->tex = draw_generateconchars();
401 if (pic->tex == NULL && !strcmp(path, "ui/mousepointer"))
402 pic->tex = draw_generatemousepointer();
403 if (pic->tex == NULL && !strcmp(path, "gfx/prydoncursor001"))
404 pic->tex = draw_generatemousepointer();
405 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair1"))
406 pic->tex = draw_generatecrosshair(0);
407 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair2"))
408 pic->tex = draw_generatecrosshair(1);
409 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair3"))
410 pic->tex = draw_generatecrosshair(2);
411 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair4"))
412 pic->tex = draw_generatecrosshair(3);
413 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair5"))
414 pic->tex = draw_generatecrosshair(4);
415 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair6"))
416 pic->tex = draw_generatecrosshair(5);
417 if (pic->tex == NULL && !strcmp(path, "gfx/colorcontrol/ditherpattern"))
418 pic->tex = draw_generateditherpattern();
419 if (pic->tex == NULL)
421 Con_Printf("Draw_CachePic: failed to load %s\n", path);
422 pic->tex = r_texture_notexture;
424 pic->width = R_TextureWidth(pic->tex);
425 pic->height = R_TextureHeight(pic->tex);
431 cachepic_t *Draw_NewPic(const char *picname, int width, int height, int alpha, unsigned char *pixels)
436 crc = CRC_Block((unsigned char *)picname, strlen(picname));
437 hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
438 for (pic = cachepichash[hashkey];pic;pic = pic->chain)
439 if (!strcmp (picname, pic->name))
444 if (pic->tex && pic->width == width && pic->height == height)
446 R_UpdateTexture(pic->tex, pixels, 0, 0, width, height);
454 if (numcachepics == MAX_CACHED_PICS)
456 Con_Printf ("Draw_NewPic: numcachepics == MAX_CACHED_PICS\n");
457 // FIXME: support NULL in callers?
458 return cachepics; // return the first one
460 pic = cachepics + (numcachepics++);
461 strcpy (pic->name, picname);
463 pic->chain = cachepichash[hashkey];
464 cachepichash[hashkey] = pic;
469 pic->height = height;
471 R_FreeTexture(pic->tex);
472 pic->tex = R_LoadTexture2D(drawtexturepool, picname, width, height, pixels, TEXTYPE_RGBA, alpha ? TEXF_ALPHA : 0, NULL);
476 void Draw_FreePic(const char *picname)
481 // this doesn't really free the pic, but does free it's texture
482 crc = CRC_Block((unsigned char *)picname, strlen(picname));
483 hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
484 for (pic = cachepichash[hashkey];pic;pic = pic->chain)
486 if (!strcmp (picname, pic->name) && pic->tex)
488 R_FreeTexture(pic->tex);
501 static void gl_draw_start(void)
504 drawtexturepool = R_AllocTexturePool();
507 memset(cachepichash, 0, sizeof(cachepichash));
509 char_texture = Draw_CachePic("gfx/conchars", true)->tex;
510 for (i = 1;i <= NUMCROSSHAIRS;i++)
511 r_crosshairs[i] = Draw_CachePic(va("gfx/crosshair%i", i), true);
514 static void gl_draw_shutdown(void)
516 R_FreeTexturePool(&drawtexturepool);
519 memset(cachepichash, 0, sizeof(cachepichash));
522 static void gl_draw_newmap(void)
526 void GL_Draw_Init (void)
528 Cvar_RegisterVariable(&r_textshadow);
529 R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown, gl_draw_newmap);
532 void DrawQ_Begin(void)
534 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
537 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
538 GL_SetupView_Mode_Ortho(0, 0, vid_conwidth.integer, vid_conheight.integer, -10, 100);
539 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
540 R_Mesh_Matrix(&identitymatrix);
546 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
548 r_refdef.draw2dstage = true;
551 static void _DrawQ_ProcessDrawFlag(int flags)
554 if(flags == DRAWFLAG_ADDITIVE)
555 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
556 else if(flags == DRAWFLAG_MODULATE)
557 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
558 else if(flags == DRAWFLAG_2XMODULATE)
559 GL_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR);
561 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
564 void DrawQ_Pic(float x, float y, cachepic_t *pic, float width, float height, float red, float green, float blue, float alpha, int flags)
566 if (!r_refdef.draw2dstage)
568 Con_Printf("DrawQ_Pic: not in 2d rendering stage!\n");
571 DrawQ_SuperPic(x,y,pic,width,height,0,0,red,green,blue,alpha,1,0,red,green,blue,alpha,0,1,red,green,blue,alpha,1,1,red,green,blue,alpha,flags);
574 void DrawQ_String_Real(float x, float y, const char *string, int maxlen, float w, float h, float red, float green, float blue, float alpha, int flags)
579 float vertex3f[QUADELEMENTS_MAXQUADS*4*3];
580 float texcoord2f[QUADELEMENTS_MAXQUADS*4*2];
582 if (!r_refdef.draw2dstage)
584 Con_Printf("DrawQ_String: not in 2d rendering stage!\n");
588 if (alpha < (1.0f / 255.0f))
591 _DrawQ_ProcessDrawFlag(flags);
593 GL_Color(red, green, blue, alpha);
595 R_Mesh_VertexPointer(vertex3f);
596 R_Mesh_ColorPointer(NULL);
597 R_Mesh_ResetTextureState();
598 R_Mesh_TexBind(0, R_GetTexture(char_texture));
599 R_Mesh_TexCoordPointer(0, 2, texcoord2f);
607 for (i = 0;i < maxlen && x < vid_conwidth.integer && (num = string[i]);i++, x += w)
612 s = (num & 15)*0.0625f + (0.5f / 256.0f);
613 t = (num >> 4)*0.0625f + (0.5f / 256.0f);
614 u = 0.0625f - (1.0f / 256.0f);
615 v = 0.0625f - (1.0f / 256.0f);
616 at[ 0] = s ;at[ 1] = t ;
617 at[ 2] = s+u;at[ 3] = t ;
618 at[ 4] = s+u;at[ 5] = t+v;
619 at[ 6] = s ;at[ 7] = t+v;
620 av[ 0] = x ;av[ 1] = y ;av[ 2] = 10;
621 av[ 3] = x+w;av[ 4] = y ;av[ 5] = 10;
622 av[ 6] = x+w;av[ 7] = y+h;av[ 8] = 10;
623 av[ 9] = x ;av[10] = y+h;av[11] = 10;
627 if (batchcount >= QUADELEMENTS_MAXQUADS)
629 GL_LockArrays(0, batchcount * 4);
630 R_Mesh_Draw(0, batchcount * 4, batchcount * 2, quadelements);
639 GL_LockArrays(0, batchcount * 4);
640 R_Mesh_Draw(0, batchcount * 4, batchcount * 2, quadelements);
645 void DrawQ_String(float x, float y, const char *string, int maxlen, float scalex, float scaley, float red, float green, float blue, float alpha, int flags)
647 if (!r_refdef.draw2dstage)
649 Con_Printf("DrawQ_String: not in 2d rendering stage!\n");
653 if (r_textshadow.integer)
654 DrawQ_String_Real(x+scalex*0.25,y+scaley*0.25,string,maxlen,scalex,scaley,0,0,0,alpha*0.8,flags);
656 DrawQ_String_Real(x,y,string,maxlen,scalex,scaley,red,green,blue,alpha,flags);
659 // color tag printing
660 static vec4_t string_colors[] =
663 // LordHavoc: why on earth is cyan before magenta in Quake3?
664 // LordHavoc: note: Doom3 uses white for [0] and [7]
665 {0.0, 0.0, 0.0, 1.0}, // black
666 {1.0, 0.0, 0.0, 1.0}, // red
667 {0.0, 1.0, 0.0, 1.0}, // green
668 {1.0, 1.0, 0.0, 1.0}, // yellow
669 {0.0, 0.0, 1.0, 1.0}, // blue
670 {0.0, 1.0, 1.0, 1.0}, // cyan
671 {1.0, 0.0, 1.0, 1.0}, // magenta
672 {1.0, 1.0, 1.0, 1.0}, // white
673 // [515]'s BX_COLOREDTEXT extension
674 {1.0, 1.0, 1.0, 0.5}, // half transparent
675 {0.5, 0.5, 0.5, 1.0} // half brightness
676 // Black's color table
677 //{1.0, 1.0, 1.0, 1.0},
678 //{1.0, 0.0, 0.0, 1.0},
679 //{0.0, 1.0, 0.0, 1.0},
680 //{0.0, 0.0, 1.0, 1.0},
681 //{1.0, 1.0, 0.0, 1.0},
682 //{0.0, 1.0, 1.0, 1.0},
683 //{1.0, 0.0, 1.0, 1.0},
684 //{0.1, 0.1, 0.1, 1.0}
687 #define STRING_COLORS_COUNT (sizeof(string_colors) / sizeof(vec4_t))
689 // color is read and changed in the end
690 void DrawQ_ColoredString( float x, float y, const char *text, int maxlen, float scalex, float scaley, float basered, float basegreen, float baseblue, float basealpha, int flags, int *outcolor )
695 const char *start, *current;
697 if (!r_refdef.draw2dstage)
699 Con_Printf("DrawQ_ColoredString: not in 2d rendering stage!\n");
702 if( !outcolor || *outcolor == -1 ) {
703 colorindex = STRING_COLOR_DEFAULT;
705 colorindex = *outcolor;
707 color = string_colors[colorindex];
710 len = (int)strlen( text );
712 len = min( maxlen, (int) strlen( text ) );
714 start = current = text;
716 // check for color control char
717 if( *current == STRING_COLOR_TAG ) {
724 // display the tag char?
725 if( *current == STRING_COLOR_TAG ) {
726 // only display one of the two
731 } else if( '0' <= *current && *current <= '9' ) {
734 colorindex = colorindex * 10 + (*current - '0');
735 // only read as long as it makes a valid index
736 if( colorindex >= (int)STRING_COLORS_COUNT ) {
737 // undo the last operation
743 } while( len > 0 && '0' <= *current && *current <= '9' );
745 color = string_colors[colorindex];
746 // we jump over the color tag
750 // go on and read normal text in until the next control char
751 while( len > 0 && *current != STRING_COLOR_TAG ) {
756 if( start != current ) {
758 DrawQ_String( x, y, start, current - start, scalex, scaley, basered * color[0], basegreen * color[1], baseblue * color[2], basealpha * color[3], flags );
759 // update x to be at the new start position
760 x += (current - start) * scalex;
761 // set start accordingly
766 // return the last colorindex
768 *outcolor = colorindex;
772 void DrawQ_SuperPic(float x, float y, cachepic_t *pic, float width, float height, float s1, float t1, float r1, float g1, float b1, float a1, float s2, float t2, float r2, float g2, float b2, float a2, float s3, float t3, float r3, float g3, float b3, float a3, float s4, float t4, float r4, float g4, float b4, float a4, int flags)
776 if (!r_refdef.draw2dstage)
778 Con_Printf("DrawQ_SuperPic: not in 2d rendering stage!\n");
782 _DrawQ_ProcessDrawFlag(flags);
784 R_Mesh_VertexPointer(floats);
785 R_Mesh_ColorPointer(floats + 20);
786 R_Mesh_ResetTextureState();
792 height = pic->height;
793 R_Mesh_TexBind(0, R_GetTexture(pic->tex));
794 R_Mesh_TexCoordPointer(0, 2, floats + 12);
795 floats[12] = s1;floats[13] = t1;
796 floats[14] = s2;floats[15] = t2;
797 floats[16] = s4;floats[17] = t4;
798 floats[18] = s3;floats[19] = t3;
801 floats[2] = floats[5] = floats[8] = floats[11] = 0;
802 floats[0] = floats[9] = x;
803 floats[1] = floats[4] = y;
804 floats[3] = floats[6] = x + width;
805 floats[7] = floats[10] = y + height;
806 floats[20] = r1;floats[21] = g1;floats[22] = b1;floats[23] = a1;
807 floats[24] = r2;floats[25] = g2;floats[26] = b2;floats[27] = a2;
808 floats[28] = r4;floats[29] = g4;floats[30] = b4;floats[31] = a4;
809 floats[32] = r3;floats[33] = g3;floats[34] = b3;floats[35] = a3;
811 R_Mesh_Draw(0, 4, 2, polygonelements);
814 void DrawQ_Mesh (drawqueuemesh_t *mesh, int flags)
816 if (!r_refdef.draw2dstage)
818 Con_Printf("DrawQ_Mesh: not in 2d rendering stage!\n");
822 _DrawQ_ProcessDrawFlag(flags);
824 R_Mesh_VertexPointer(mesh->data_vertex3f);
825 R_Mesh_ColorPointer(mesh->data_color4f);
826 R_Mesh_ResetTextureState();
827 R_Mesh_TexBind(0, R_GetTexture(mesh->texture));
828 R_Mesh_TexCoordPointer(0, 2, mesh->data_texcoord2f);
830 GL_LockArrays(0, mesh->num_vertices);
831 R_Mesh_Draw(0, mesh->num_vertices, mesh->num_triangles, mesh->data_element3i);
835 void DrawQ_LineLoop (drawqueuemesh_t *mesh, int flags)
839 if (!r_refdef.draw2dstage)
841 Con_Printf("DrawQ_LineLoop: not in 2d rendering stage!\n");
845 _DrawQ_ProcessDrawFlag(flags);
849 qglBegin(GL_LINE_LOOP);
850 for (num = 0;num < mesh->num_vertices;num++)
852 if (mesh->data_color4f)
853 GL_Color(mesh->data_color4f[num*4+0], mesh->data_color4f[num*4+1], mesh->data_color4f[num*4+2], mesh->data_color4f[num*4+3]);
854 qglVertex2f(mesh->data_vertex3f[num*3+0], mesh->data_vertex3f[num*3+1]);
860 //LordHavoc: FIXME: this is nasty!
861 void DrawQ_LineWidth (float width)
863 if (!r_refdef.draw2dstage)
865 Con_Printf("DrawQ_LineWidth: not in 2d rendering stage!\n");
869 qglLineWidth(width);CHECKGLERROR
872 //[515]: this is old, delete
873 void DrawQ_Line (float width, float x1, float y1, float x2, float y2, float r, float g, float b, float alpha, int flags)
875 if (!r_refdef.draw2dstage)
877 Con_Printf("DrawQ_Line: not in 2d rendering stage!\n");
883 DrawQ_LineWidth(width);
885 _DrawQ_ProcessDrawFlag(flags);
887 GL_Color(r,g,b,alpha);
896 void DrawQ_SetClipArea(float x, float y, float width, float height)
898 if (!r_refdef.draw2dstage)
900 Con_Printf("DrawQ_SetClipArea: not in 2d rendering stage!\n");
904 // We have to convert the con coords into real coords
905 // OGL uses top to bottom
906 GL_Scissor((int)(x * ((float)vid.width / vid_conwidth.integer)), (int)(y * ((float) vid.height / vid_conheight.integer)), (int)(width * ((float)vid.width / vid_conwidth.integer)), (int)(height * ((float)vid.height / vid_conheight.integer)));
908 GL_ScissorTest(true);
911 void DrawQ_ResetClipArea(void)
913 if (!r_refdef.draw2dstage)
915 Con_Printf("DrawQ_ResetClipArea: not in 2d rendering stage!\n");
918 GL_ScissorTest(false);
921 void DrawQ_Finish(void)
923 if (!r_refdef.draw2dstage)
925 Con_Printf("R_DrawQueue: not in 2d rendering stage!\n");
929 r_refdef.draw2dstage = false;
932 static float blendvertex3f[9] = {-5000, -5000, 10, 10000, -5000, 10, -5000, 10000, 10};
933 void R_DrawGamma(void)
936 if (!vid_usinghwgamma)
938 // all the blends ignore depth
939 R_Mesh_VertexPointer(blendvertex3f);
940 R_Mesh_ColorPointer(NULL);
941 R_Mesh_ResetTextureState();
944 if (v_color_enable.integer)
946 c[0] = v_color_white_r.value;
947 c[1] = v_color_white_g.value;
948 c[2] = v_color_white_b.value;
951 c[0] = c[1] = c[2] = v_contrast.value;
952 if (c[0] >= 1.01f || c[1] >= 1.01f || c[2] >= 1.01f)
954 GL_BlendFunc(GL_DST_COLOR, GL_ONE);
955 while (c[0] >= 1.01f || c[1] >= 1.01f || c[2] >= 1.01f)
957 GL_Color(bound(0, c[0] - 1, 1), bound(0, c[1] - 1, 1), bound(0, c[2] - 1, 1), 1);
958 R_Mesh_Draw(0, 3, 1, polygonelements);
959 VectorScale(c, 0.5, c);
962 if (v_color_enable.integer)
964 c[0] = v_color_black_r.value;
965 c[1] = v_color_black_g.value;
966 c[2] = v_color_black_b.value;
969 c[0] = c[1] = c[2] = v_brightness.value;
970 if (c[0] >= 0.01f || c[1] >= 0.01f || c[2] >= 0.01f)
972 GL_BlendFunc(GL_ONE, GL_ONE);
973 GL_Color(c[0], c[1], c[2], 1);
974 R_Mesh_Draw(0, 3, 1, polygonelements);