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++)
269 data[i][3] = (unsigned char) ((int) (in[i] - '0') * 255 / 7);
272 return R_LoadTexture2D(drawtexturepool, va("crosshair%i", num), 16, 16, &data[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
275 static rtexture_t *draw_generateditherpattern(void)
279 unsigned char data[8*8*4];
280 for (y = 0;y < 8;y++)
282 for (x = 0;x < 8;x++)
284 data[(y*8+x)*4+0] = data[(y*8+x)*4+1] = data[(y*8+x)*4+2] = ((x^y) & 4) ? 255 : 0;
285 data[(y*8+x)*4+3] = 255;
288 return R_LoadTexture2D(drawtexturepool, "ditherpattern", 8, 8, data, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_PRECACHE, NULL);
290 unsigned char data[16];
291 memset(data, 255, sizeof(data));
292 data[0] = data[1] = data[2] = data[12] = data[13] = data[14] = 0;
293 return R_LoadTexture2D(drawtexturepool, "ditherpattern", 2, 2, data, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_PRECACHE, NULL);
302 // FIXME: move this to client somehow
303 cachepic_t *Draw_CachePic (const char *path, qboolean persistent)
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 the pic from disk
344 pic->tex = loadtextureimage(drawtexturepool, path, 0, 0, false, flags);
345 if (pic->tex == NULL && !strncmp(path, "gfx/", 4))
347 // compatibility with older versions
348 pic->tex = loadtextureimage(drawtexturepool, path + 4, 0, 0, false, flags);
349 // failed to find gfx/whatever.tga or similar, try the wad
350 if (pic->tex == NULL && (p = (qpic_t *)W_GetLumpName (path + 4)))
352 if (!strcmp(path, "gfx/conchars"))
354 // conchars is a raw image and with color 0 as transparent instead of 255
355 pic->tex = R_LoadTexture2D(drawtexturepool, path, 128, 128, (unsigned char *)p, TEXTYPE_PALETTE, flags, palette_font);
358 pic->tex = R_LoadTexture2D(drawtexturepool, path, p->width, p->height, p->data, TEXTYPE_PALETTE, flags, palette_transparent);
362 if (pic->tex == NULL && !strcmp(path, "gfx/conchars"))
363 pic->tex = draw_generateconchars();
364 if (pic->tex == NULL && !strcmp(path, "ui/mousepointer"))
365 pic->tex = draw_generatemousepointer();
366 if (pic->tex == NULL && !strcmp(path, "gfx/prydoncursor001"))
367 pic->tex = draw_generatemousepointer();
368 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair1"))
369 pic->tex = draw_generatecrosshair(0);
370 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair2"))
371 pic->tex = draw_generatecrosshair(1);
372 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair3"))
373 pic->tex = draw_generatecrosshair(2);
374 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair4"))
375 pic->tex = draw_generatecrosshair(3);
376 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair5"))
377 pic->tex = draw_generatecrosshair(4);
378 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair6"))
379 pic->tex = draw_generatecrosshair(5);
380 if (pic->tex == NULL && !strcmp(path, "gfx/colorcontrol/ditherpattern"))
381 pic->tex = draw_generateditherpattern();
382 if (pic->tex == NULL)
384 Con_Printf("Draw_CachePic: failed to load %s\n", path);
385 pic->tex = r_texture_notexture;
388 pic->width = R_TextureWidth(pic->tex);
389 pic->height = R_TextureHeight(pic->tex);
393 cachepic_t *Draw_NewPic(const char *picname, int width, int height, int alpha, unsigned char *pixels)
398 crc = CRC_Block((unsigned char *)picname, strlen(picname));
399 hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
400 for (pic = cachepichash[hashkey];pic;pic = pic->chain)
401 if (!strcmp (picname, pic->name))
406 if (pic->tex && pic->width == width && pic->height == height)
408 R_UpdateTexture(pic->tex, pixels, 0, 0, width, height);
416 if (numcachepics == MAX_CACHED_PICS)
418 Con_Printf ("Draw_NewPic: numcachepics == MAX_CACHED_PICS\n");
419 // FIXME: support NULL in callers?
420 return cachepics; // return the first one
422 pic = cachepics + (numcachepics++);
423 strcpy (pic->name, picname);
425 pic->chain = cachepichash[hashkey];
426 cachepichash[hashkey] = pic;
431 pic->height = height;
433 R_FreeTexture(pic->tex);
434 pic->tex = R_LoadTexture2D(drawtexturepool, picname, width, height, pixels, TEXTYPE_RGBA, alpha ? TEXF_ALPHA : 0, NULL);
438 void Draw_FreePic(const char *picname)
443 // this doesn't really free the pic, but does free it's texture
444 crc = CRC_Block((unsigned char *)picname, strlen(picname));
445 hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
446 for (pic = cachepichash[hashkey];pic;pic = pic->chain)
448 if (!strcmp (picname, pic->name) && pic->tex)
450 R_FreeTexture(pic->tex);
463 static void gl_draw_start(void)
466 drawtexturepool = R_AllocTexturePool();
469 memset(cachepichash, 0, sizeof(cachepichash));
471 char_texture = Draw_CachePic("gfx/conchars", true)->tex;
472 for (i = 1;i <= NUMCROSSHAIRS;i++)
473 r_crosshairs[i] = Draw_CachePic(va("gfx/crosshair%i", i), true);
476 static void gl_draw_shutdown(void)
478 R_FreeTexturePool(&drawtexturepool);
481 memset(cachepichash, 0, sizeof(cachepichash));
484 static void gl_draw_newmap(void)
488 void GL_Draw_Init (void)
490 Cvar_RegisterVariable(&r_textshadow);
491 R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown, gl_draw_newmap);
494 void DrawQ_Begin(void)
496 r_view_width = bound(0, r_refdef.width, vid.width);
497 r_view_height = bound(0, r_refdef.height, vid.height);
499 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
500 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
502 r_view_matrix = r_refdef.viewentitymatrix;
503 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
506 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);CHECKGLERROR
507 GL_SetupView_Mode_Ortho(0, 0, vid_conwidth.integer, vid_conheight.integer, -10, 100);
508 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
509 R_Mesh_Matrix(&identitymatrix);
515 r_refdef.draw2dstage = true;
518 void DrawQ_Pic(float x, float y, cachepic_t *pic, float width, float height, float red, float green, float blue, float alpha, int flags)
520 if (!r_refdef.draw2dstage)
522 Con_Printf("DrawQ_Pic: not in 2d rendering stage!\n");
525 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);
528 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)
533 float vertex3f[QUADELEMENTS_MAXQUADS*4*3];
534 float texcoord2f[QUADELEMENTS_MAXQUADS*4*2];
536 if (!r_refdef.draw2dstage)
538 Con_Printf("DrawQ_String: not in 2d rendering stage!\n");
542 if (!r_render.integer)
545 if (alpha < (1.0f / 255.0f))
548 if(flags == DRAWFLAG_ADDITIVE)
549 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
550 else if(flags == DRAWFLAG_MODULATE)
551 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
552 else if(flags == DRAWFLAG_2XMODULATE)
553 GL_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR);
555 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
557 GL_Color(red, green, blue, alpha);
559 R_Mesh_VertexPointer(vertex3f);
560 R_Mesh_ColorPointer(NULL);
561 R_Mesh_ResetTextureState();
562 R_Mesh_TexBind(0, R_GetTexture(char_texture));
563 R_Mesh_TexCoordPointer(0, 2, texcoord2f);
571 for (i = 0;i < maxlen && x < vid_conwidth.integer && (num = string[i]);i++, x += w)
576 s = (num & 15)*0.0625f + (0.5f / 256.0f);
577 t = (num >> 4)*0.0625f + (0.5f / 256.0f);
578 u = 0.0625f - (1.0f / 256.0f);
579 v = 0.0625f - (1.0f / 256.0f);
580 at[ 0] = s ;at[ 1] = t ;
581 at[ 2] = s+u;at[ 3] = t ;
582 at[ 4] = s+u;at[ 5] = t+v;
583 at[ 6] = s ;at[ 7] = t+v;
584 av[ 0] = x ;av[ 1] = y ;av[ 2] = 10;
585 av[ 3] = x+w;av[ 4] = y ;av[ 5] = 10;
586 av[ 6] = x+w;av[ 7] = y+h;av[ 8] = 10;
587 av[ 9] = x ;av[10] = y+h;av[11] = 10;
591 if (batchcount >= QUADELEMENTS_MAXQUADS)
593 GL_LockArrays(0, batchcount * 4);
594 R_Mesh_Draw(0, batchcount * 4, batchcount * 2, quadelements);
603 GL_LockArrays(0, batchcount * 4);
604 R_Mesh_Draw(0, batchcount * 4, batchcount * 2, quadelements);
609 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)
611 if (!r_refdef.draw2dstage)
613 Con_Printf("DrawQ_String: not in 2d rendering stage!\n");
617 if (r_textshadow.integer)
618 DrawQ_String_Real(x+scalex*0.25,y+scaley*0.25,string,maxlen,scalex,scaley,0,0,0,alpha*0.8,flags);
620 DrawQ_String_Real(x,y,string,maxlen,scalex,scaley,red,green,blue,alpha,flags);
623 // color tag printing
624 static vec4_t string_colors[] =
627 // LordHavoc: why on earth is cyan before magenta in Quake3?
628 // LordHavoc: note: Doom3 uses white for [0] and [7]
629 {0.0, 0.0, 0.0, 1.0}, // black
630 {1.0, 0.0, 0.0, 1.0}, // red
631 {0.0, 1.0, 0.0, 1.0}, // green
632 {1.0, 1.0, 0.0, 1.0}, // yellow
633 {0.0, 0.0, 1.0, 1.0}, // blue
634 {0.0, 1.0, 1.0, 1.0}, // cyan
635 {1.0, 0.0, 1.0, 1.0}, // magenta
636 {1.0, 1.0, 1.0, 1.0}, // white
637 // [515]'s BX_COLOREDTEXT extension
638 {1.0, 1.0, 1.0, 0.5}, // half transparent
639 {0.5, 0.5, 0.5, 1.0} // half brightness
640 // Black's color table
641 //{1.0, 1.0, 1.0, 1.0},
642 //{1.0, 0.0, 0.0, 1.0},
643 //{0.0, 1.0, 0.0, 1.0},
644 //{0.0, 0.0, 1.0, 1.0},
645 //{1.0, 1.0, 0.0, 1.0},
646 //{0.0, 1.0, 1.0, 1.0},
647 //{1.0, 0.0, 1.0, 1.0},
648 //{0.1, 0.1, 0.1, 1.0}
651 #define STRING_COLORS_COUNT (sizeof(string_colors) / sizeof(vec4_t))
653 // color is read and changed in the end
654 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 )
659 const char *start, *current;
661 if (!r_refdef.draw2dstage)
663 Con_Printf("DrawQ_ColoredString: not in 2d rendering stage!\n");
666 if( !outcolor || *outcolor == -1 ) {
667 colorindex = STRING_COLOR_DEFAULT;
669 colorindex = *outcolor;
671 color = string_colors[colorindex];
674 len = (int)strlen( text );
676 len = min( maxlen, (int) strlen( text ) );
678 start = current = text;
680 // check for color control char
681 if( *current == STRING_COLOR_TAG ) {
688 // display the tag char?
689 if( *current == STRING_COLOR_TAG ) {
690 // only display one of the two
695 } else if( '0' <= *current && *current <= '9' ) {
698 colorindex = colorindex * 10 + (*current - '0');
699 // only read as long as it makes a valid index
700 if( colorindex >= (int)STRING_COLORS_COUNT ) {
701 // undo the last operation
707 } while( len > 0 && '0' <= *current && *current <= '9' );
709 color = string_colors[colorindex];
710 // we jump over the color tag
714 // go on and read normal text in until the next control char
715 while( len > 0 && *current != STRING_COLOR_TAG ) {
720 if( start != current ) {
722 DrawQ_String( x, y, start, current - start, scalex, scaley, basered * color[0], basegreen * color[1], baseblue * color[2], basealpha * color[3], flags );
723 // update x to be at the new start position
724 x += (current - start) * scalex;
725 // set start accordingly
730 // return the last colorindex
732 *outcolor = colorindex;
736 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)
740 if (!r_refdef.draw2dstage)
742 Con_Printf("DrawQ_SuperPic: not in 2d rendering stage!\n");
746 if (!r_render.integer)
749 if(flags == DRAWFLAG_ADDITIVE)
750 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
751 else if(flags == DRAWFLAG_MODULATE)
752 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
753 else if(flags == DRAWFLAG_2XMODULATE)
754 GL_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR);
756 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
758 R_Mesh_VertexPointer(floats);
759 R_Mesh_ColorPointer(floats + 20);
760 R_Mesh_ResetTextureState();
766 height = pic->height;
767 R_Mesh_TexBind(0, R_GetTexture(pic->tex));
768 R_Mesh_TexCoordPointer(0, 2, floats + 12);
769 floats[12] = s1;floats[13] = t1;
770 floats[14] = s2;floats[15] = t2;
771 floats[16] = s4;floats[17] = t4;
772 floats[18] = s3;floats[19] = t3;
775 floats[2] = floats[5] = floats[8] = floats[11] = 0;
776 floats[0] = floats[9] = x;
777 floats[1] = floats[4] = y;
778 floats[3] = floats[6] = x + width;
779 floats[7] = floats[10] = y + height;
780 floats[20] = r1;floats[21] = g1;floats[22] = b1;floats[23] = a1;
781 floats[24] = r2;floats[25] = g2;floats[26] = b2;floats[27] = a2;
782 floats[28] = r4;floats[29] = g4;floats[30] = b4;floats[31] = a4;
783 floats[32] = r3;floats[33] = g3;floats[34] = b3;floats[35] = a3;
785 R_Mesh_Draw(0, 4, 2, polygonelements);
788 void DrawQ_Mesh (drawqueuemesh_t *mesh, int flags)
790 if (!r_refdef.draw2dstage)
792 Con_Printf("DrawQ_Mesh: not in 2d rendering stage!\n");
796 if (!r_render.integer)
799 if(flags == DRAWFLAG_ADDITIVE)
800 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
801 else if(flags == DRAWFLAG_MODULATE)
802 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
803 else if(flags == DRAWFLAG_2XMODULATE)
804 GL_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR);
806 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
808 R_Mesh_VertexPointer(mesh->data_vertex3f);
809 R_Mesh_ColorPointer(mesh->data_color4f);
810 R_Mesh_ResetTextureState();
811 R_Mesh_TexBind(0, R_GetTexture(mesh->texture));
812 R_Mesh_TexCoordPointer(0, 2, mesh->data_texcoord2f);
814 GL_LockArrays(0, mesh->num_vertices);
815 R_Mesh_Draw(0, mesh->num_vertices, mesh->num_triangles, mesh->data_element3i);
819 void DrawQ_LineLoop (drawqueuemesh_t *mesh, int flags)
823 if (!r_refdef.draw2dstage)
825 Con_Printf("DrawQ_LineLoop: not in 2d rendering stage!\n");
829 if (!r_render.integer)
833 if(flags == DRAWFLAG_ADDITIVE)
834 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
835 else if(flags == DRAWFLAG_MODULATE)
836 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
837 else if(flags == DRAWFLAG_2XMODULATE)
838 GL_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR);
840 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
844 qglBegin(GL_LINE_LOOP);
845 for (num = 0;num < mesh->num_vertices;num++)
847 if (mesh->data_color4f)
848 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]);
849 qglVertex2f(mesh->data_vertex3f[num*3+0], mesh->data_vertex3f[num*3+1]);
855 //LordHavoc: FIXME: this is nasty!
856 void DrawQ_LineWidth (float width)
858 if (!r_refdef.draw2dstage)
860 Con_Printf("DrawQ_LineWidth: not in 2d rendering stage!\n");
864 qglLineWidth(width);CHECKGLERROR
867 //[515]: this is old, delete
868 void DrawQ_Line (float width, float x1, float y1, float x2, float y2, float r, float g, float b, float alpha, int flags)
870 if (!r_refdef.draw2dstage)
872 Con_Printf("DrawQ_Line: not in 2d rendering stage!\n");
876 if (!r_render.integer)
881 DrawQ_LineWidth(width);
883 if(flags == DRAWFLAG_ADDITIVE)
884 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
885 else if(flags == DRAWFLAG_MODULATE)
886 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
887 else if(flags == DRAWFLAG_2XMODULATE)
888 GL_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR);
890 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
892 GL_Color(r,g,b,alpha);
901 void DrawQ_SetClipArea(float x, float y, float width, float height)
903 if (!r_refdef.draw2dstage)
905 Con_Printf("DrawQ_SetClipArea: not in 2d rendering stage!\n");
909 // We have to convert the con coords into real coords
910 // OGL uses top to bottom
911 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)));
913 GL_ScissorTest(true);
916 void DrawQ_ResetClipArea(void)
918 if (!r_refdef.draw2dstage)
920 Con_Printf("DrawQ_ResetClipArea: not in 2d rendering stage!\n");
923 GL_ScissorTest(false);
926 void DrawQ_Finish(void)
928 if (!r_refdef.draw2dstage)
930 Con_Printf("R_DrawQueue: not in 2d rendering stage!\n");
934 r_refdef.draw2dstage = false;
937 static float blendvertex3f[9] = {-5000, -5000, 10, 10000, -5000, 10, -5000, 10000, 10};
938 void R_DrawGamma(void)
941 if (!vid_usinghwgamma)
943 // all the blends ignore depth
944 R_Mesh_VertexPointer(blendvertex3f);
945 R_Mesh_ColorPointer(NULL);
946 R_Mesh_ResetTextureState();
949 if (v_color_enable.integer)
951 c[0] = v_color_white_r.value;
952 c[1] = v_color_white_g.value;
953 c[2] = v_color_white_b.value;
956 c[0] = c[1] = c[2] = v_contrast.value;
957 if (c[0] >= 1.01f || c[1] >= 1.01f || c[2] >= 1.01f)
959 GL_BlendFunc(GL_DST_COLOR, GL_ONE);
960 while (c[0] >= 1.01f || c[1] >= 1.01f || c[2] >= 1.01f)
962 GL_Color(bound(0, c[0] - 1, 1), bound(0, c[1] - 1, 1), bound(0, c[2] - 1, 1), 1);
963 R_Mesh_Draw(0, 3, 1, polygonelements);
964 VectorScale(c, 0.5, c);
967 if (v_color_enable.integer)
969 c[0] = v_color_black_r.value;
970 c[1] = v_color_black_g.value;
971 c[2] = v_color_black_b.value;
974 c[0] = c[1] = c[2] = v_brightness.value;
975 if (c[0] >= 0.01f || c[1] >= 0.01f || c[2] >= 0.01f)
977 GL_BlendFunc(GL_ONE, GL_ONE);
978 GL_Color(c[0], c[1], c[2], 1);
979 R_Mesh_Draw(0, 3, 1, polygonelements);