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 = {CVAR_SAVE, "r_textshadow", "0", "draws a shadow on all text to improve readability (note: value controls offset, 1 = 1 pixel, 1.5 = 1.5 pixels, etc)"};
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+1), 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"))
342 if (gl_texturecompression_2d.integer)
343 flags |= TEXF_COMPRESS;
345 // load a high quality image from disk if possible
346 pic->tex = loadtextureimage(drawtexturepool, path, 0, 0, false, flags);
347 if (pic->tex == NULL && !strncmp(path, "gfx/", 4))
349 // compatibility with older versions which did not require gfx/ prefix
350 pic->tex = loadtextureimage(drawtexturepool, path + 4, 0, 0, false, flags);
352 // if a high quality image was loaded, set the pic's size to match it, just
353 // in case there's no low quality version to get the size from
356 pic->width = R_TextureWidth(pic->tex);
357 pic->height = R_TextureHeight(pic->tex);
360 // now read the low quality version (wad or lmp file), and take the pic
361 // size from that even if we don't upload the texture, this way the pics
362 // show up the right size in the menu even if they were replaced with
363 // higher or lower resolution versions
364 dpsnprintf(lmpname, sizeof(lmpname), "%s.lmp", path);
365 if (!strncmp(path, "gfx/", 4) && (lmpdata = FS_LoadFile(lmpname, tempmempool, false, &lmpsize)))
369 pic->width = lmpdata[0] + lmpdata[1] * 256 + lmpdata[2] * 65536 + lmpdata[3] * 16777216;
370 pic->height = lmpdata[4] + lmpdata[5] * 256 + lmpdata[6] * 65536 + lmpdata[7] * 16777216;
371 // if no high quality replacement image was found, upload the original low quality texture
373 pic->tex = R_LoadTexture2D(drawtexturepool, path, pic->width, pic->height, lmpdata + 8, TEXTYPE_PALETTE, flags, palette_transparent);
377 else if ((lmpdata = W_GetLumpName (path + 4)))
379 if (!strcmp(path, "gfx/conchars"))
381 // conchars is a raw image and with color 0 as transparent instead of 255
384 // if no high quality replacement image was found, upload the original low quality texture
386 pic->tex = R_LoadTexture2D(drawtexturepool, path, 128, 128, lmpdata, TEXTYPE_PALETTE, flags, palette_font);
390 pic->width = lmpdata[0] + lmpdata[1] * 256 + lmpdata[2] * 65536 + lmpdata[3] * 16777216;
391 pic->height = lmpdata[4] + lmpdata[5] * 256 + lmpdata[6] * 65536 + lmpdata[7] * 16777216;
392 // if no high quality replacement image was found, upload the original low quality texture
394 pic->tex = R_LoadTexture2D(drawtexturepool, path, pic->width, pic->height, lmpdata + 8, TEXTYPE_PALETTE, flags, palette_transparent);
398 // if it's not found on disk, check if it's one of the builtin images
399 if (pic->tex == NULL)
401 if (pic->tex == NULL && !strcmp(path, "gfx/conchars"))
402 pic->tex = draw_generateconchars();
403 if (pic->tex == NULL && !strcmp(path, "ui/mousepointer"))
404 pic->tex = draw_generatemousepointer();
405 if (pic->tex == NULL && !strcmp(path, "gfx/prydoncursor001"))
406 pic->tex = draw_generatemousepointer();
407 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair1"))
408 pic->tex = draw_generatecrosshair(0);
409 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair2"))
410 pic->tex = draw_generatecrosshair(1);
411 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair3"))
412 pic->tex = draw_generatecrosshair(2);
413 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair4"))
414 pic->tex = draw_generatecrosshair(3);
415 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair5"))
416 pic->tex = draw_generatecrosshair(4);
417 if (pic->tex == NULL && !strcmp(path, "gfx/crosshair6"))
418 pic->tex = draw_generatecrosshair(5);
419 if (pic->tex == NULL && !strcmp(path, "gfx/colorcontrol/ditherpattern"))
420 pic->tex = draw_generateditherpattern();
421 if (pic->tex == NULL)
423 // don't complain about missing gfx/crosshair images
424 if (strncmp(path, "gfx/crosshair", 13))
425 Con_Printf("Draw_CachePic: failed to load %s\n", path);
426 pic->tex = r_texture_notexture;
428 pic->width = R_TextureWidth(pic->tex);
429 pic->height = R_TextureHeight(pic->tex);
435 cachepic_t *Draw_NewPic(const char *picname, int width, int height, int alpha, unsigned char *pixels)
440 crc = CRC_Block((unsigned char *)picname, strlen(picname));
441 hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
442 for (pic = cachepichash[hashkey];pic;pic = pic->chain)
443 if (!strcmp (picname, pic->name))
448 if (pic->tex && pic->width == width && pic->height == height)
450 R_UpdateTexture(pic->tex, pixels, 0, 0, width, height);
458 if (numcachepics == MAX_CACHED_PICS)
460 Con_Printf ("Draw_NewPic: numcachepics == MAX_CACHED_PICS\n");
461 // FIXME: support NULL in callers?
462 return cachepics; // return the first one
464 pic = cachepics + (numcachepics++);
465 strlcpy (pic->name, picname, sizeof(pic->name));
467 pic->chain = cachepichash[hashkey];
468 cachepichash[hashkey] = pic;
473 pic->height = height;
475 R_FreeTexture(pic->tex);
476 pic->tex = R_LoadTexture2D(drawtexturepool, picname, width, height, pixels, TEXTYPE_RGBA, alpha ? TEXF_ALPHA : 0, NULL);
480 void Draw_FreePic(const char *picname)
485 // this doesn't really free the pic, but does free it's texture
486 crc = CRC_Block((unsigned char *)picname, strlen(picname));
487 hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
488 for (pic = cachepichash[hashkey];pic;pic = pic->chain)
490 if (!strcmp (picname, pic->name) && pic->tex)
492 R_FreeTexture(pic->tex);
505 static void gl_draw_start(void)
508 drawtexturepool = R_AllocTexturePool();
511 memset(cachepichash, 0, sizeof(cachepichash));
513 char_texture = Draw_CachePic("gfx/conchars", true)->tex;
514 for (i = 1;i <= NUMCROSSHAIRS;i++)
515 r_crosshairs[i] = Draw_CachePic(va("gfx/crosshair%i", i), true);
517 // draw the loading screen so people have something to see in the newly opened window
518 SCR_UpdateLoadingScreen(true);
521 static void gl_draw_shutdown(void)
523 R_FreeTexturePool(&drawtexturepool);
526 memset(cachepichash, 0, sizeof(cachepichash));
529 static void gl_draw_newmap(void)
533 void GL_Draw_Init (void)
535 Cvar_RegisterVariable(&r_textshadow);
536 R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown, gl_draw_newmap);
539 static void _DrawQ_Setup(void)
541 if (r_refdef.draw2dstage)
543 r_refdef.draw2dstage = true;
545 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
546 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
547 GL_SetupView_Mode_Ortho(0, 0, vid_conwidth.integer, vid_conheight.integer, -10, 100);
548 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
549 qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
550 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
551 R_Mesh_Matrix(&identitymatrix);
555 GL_PolygonOffset(0, 0);
559 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
561 if (gl_support_fragment_shader)
563 qglUseProgramObjectARB(0);CHECKGLERROR
567 static void _DrawQ_ProcessDrawFlag(int flags)
571 if(flags == DRAWFLAG_ADDITIVE)
572 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
573 else if(flags == DRAWFLAG_MODULATE)
574 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
575 else if(flags == DRAWFLAG_2XMODULATE)
576 GL_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR);
578 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
581 void DrawQ_Pic(float x, float y, cachepic_t *pic, float width, float height, float red, float green, float blue, float alpha, int flags)
585 _DrawQ_ProcessDrawFlag(flags);
586 GL_Color(red, green, blue, alpha);
588 R_Mesh_VertexPointer(floats, 0, 0);
589 R_Mesh_ColorPointer(NULL, 0, 0);
590 R_Mesh_ResetTextureState();
596 height = pic->height;
597 R_Mesh_TexBind(0, R_GetTexture(pic->tex));
598 R_Mesh_TexCoordPointer(0, 2, floats + 12, 0, 0);
599 floats[12] = 0;floats[13] = 0;
600 floats[14] = 1;floats[15] = 0;
601 floats[16] = 1;floats[17] = 1;
602 floats[18] = 0;floats[19] = 1;
605 floats[2] = floats[5] = floats[8] = floats[11] = 0;
606 floats[0] = floats[9] = x;
607 floats[1] = floats[4] = y;
608 floats[3] = floats[6] = x + width;
609 floats[7] = floats[10] = y + height;
611 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
614 void DrawQ_Fill(float x, float y, float width, float height, float red, float green, float blue, float alpha, int flags)
618 _DrawQ_ProcessDrawFlag(flags);
619 GL_Color(red, green, blue, alpha);
621 R_Mesh_VertexPointer(floats, 0, 0);
622 R_Mesh_ColorPointer(NULL, 0, 0);
623 R_Mesh_ResetTextureState();
625 floats[2] = floats[5] = floats[8] = floats[11] = 0;
626 floats[0] = floats[9] = x;
627 floats[1] = floats[4] = y;
628 floats[3] = floats[6] = x + width;
629 floats[7] = floats[10] = y + height;
631 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
634 // color tag printing
635 static vec4_t string_colors[] =
638 // LordHavoc: why on earth is cyan before magenta in Quake3?
639 // LordHavoc: note: Doom3 uses white for [0] and [7]
640 {0.0, 0.0, 0.0, 1.0}, // black
641 {1.0, 0.0, 0.0, 1.0}, // red
642 {0.0, 1.0, 0.0, 1.0}, // green
643 {1.0, 1.0, 0.0, 1.0}, // yellow
644 {0.0, 0.0, 1.0, 1.0}, // blue
645 {0.0, 1.0, 1.0, 1.0}, // cyan
646 {1.0, 0.0, 1.0, 1.0}, // magenta
647 {1.0, 1.0, 1.0, 1.0}, // white
648 // [515]'s BX_COLOREDTEXT extension
649 {1.0, 1.0, 1.0, 0.5}, // half transparent
650 {0.5, 0.5, 0.5, 1.0} // half brightness
651 // Black's color table
652 //{1.0, 1.0, 1.0, 1.0},
653 //{1.0, 0.0, 0.0, 1.0},
654 //{0.0, 1.0, 0.0, 1.0},
655 //{0.0, 0.0, 1.0, 1.0},
656 //{1.0, 1.0, 0.0, 1.0},
657 //{0.0, 1.0, 1.0, 1.0},
658 //{1.0, 0.0, 1.0, 1.0},
659 //{0.1, 0.1, 0.1, 1.0}
662 #define STRING_COLORS_COUNT (sizeof(string_colors) / sizeof(vec4_t))
664 static void DrawQ_GetTextColor(float color[4], int colorindex, float r, float g, float b, float a, qboolean shadow)
666 Vector4Copy(string_colors[colorindex], color);
667 Vector4Set(color, color[0] * r, color[1] * g, color[2] * b, color[3] * a);
670 float shadowalpha = color[0]+color[1]+color[2] * 0.8;
671 Vector4Set(color, 0, 0, 0, color[3] * bound(0, shadowalpha, 1));
675 float DrawQ_String(float startx, float starty, const char *text, int maxlen, float w, float h, float basered, float basegreen, float baseblue, float basealpha, int flags, int *outcolor, qboolean ignorecolorcodes)
677 int i, num, shadow, colorindex = STRING_COLOR_DEFAULT;
678 float x = startx, y, s, t, u, v;
682 float vertex3f[QUADELEMENTS_MAXQUADS*4*3];
683 float texcoord2f[QUADELEMENTS_MAXQUADS*4*2];
684 float color4f[QUADELEMENTS_MAXQUADS*4*4];
689 _DrawQ_ProcessDrawFlag(flags);
691 R_Mesh_ColorPointer(color4f, 0, 0);
692 R_Mesh_ResetTextureState();
693 R_Mesh_TexBind(0, R_GetTexture(char_texture));
694 R_Mesh_TexCoordPointer(0, 2, texcoord2f, 0, 0);
695 R_Mesh_VertexPointer(vertex3f, 0, 0);
702 for (shadow = r_textshadow.value != 0;shadow >= 0;shadow--)
704 if (!outcolor || *outcolor == -1)
705 colorindex = STRING_COLOR_DEFAULT;
707 colorindex = *outcolor;
708 DrawQ_GetTextColor(color, colorindex, basered, basegreen, baseblue, basealpha, shadow);
714 x += r_textshadow.value;
715 y += r_textshadow.value;
717 for (i = 0;i < maxlen && text[i];i++, x += w)
721 if (text[i] == STRING_COLOR_TAG && !ignorecolorcodes && i + 1 < maxlen)
723 if (text[i+1] == STRING_COLOR_TAG)
729 else if (text[i+1] >= '0' && text[i+1] <= '9')
731 colorindex = text[i+1] - '0';
732 DrawQ_GetTextColor(color, colorindex, basered, basegreen, baseblue, basealpha, shadow);
739 s = (num & 15)*0.0625f + (0.5f / 256.0f);
740 t = (num >> 4)*0.0625f + (0.5f / 256.0f);
741 u = 0.0625f - (1.0f / 256.0f);
742 v = 0.0625f - (1.0f / 256.0f);
743 ac[ 0] = color[0];ac[ 1] = color[1];ac[ 2] = color[2];ac[ 3] = color[3];
744 ac[ 4] = color[0];ac[ 5] = color[1];ac[ 6] = color[2];ac[ 7] = color[3];
745 ac[ 8] = color[0];ac[ 9] = color[1];ac[10] = color[2];ac[11] = color[3];
746 ac[12] = color[0];ac[13] = color[1];ac[14] = color[2];ac[15] = color[3];
747 at[ 0] = s ;at[ 1] = t ;
748 at[ 2] = s+u;at[ 3] = t ;
749 at[ 4] = s+u;at[ 5] = t+v;
750 at[ 6] = s ;at[ 7] = t+v;
751 av[ 0] = x ;av[ 1] = y ;av[ 2] = 10;
752 av[ 3] = x+w;av[ 4] = y ;av[ 5] = 10;
753 av[ 6] = x+w;av[ 7] = y+h;av[ 8] = 10;
754 av[ 9] = x ;av[10] = y+h;av[11] = 10;
759 if (batchcount >= QUADELEMENTS_MAXQUADS)
761 if (basealpha >= (1.0f / 255.0f))
763 GL_LockArrays(0, batchcount * 4);
764 R_Mesh_Draw(0, batchcount * 4, batchcount * 2, quadelements, 0, 0);
776 if (basealpha >= (1.0f / 255.0f))
778 GL_LockArrays(0, batchcount * 4);
779 R_Mesh_Draw(0, batchcount * 4, batchcount * 2, quadelements, 0, 0);
785 *outcolor = colorindex;
787 // note: this relies on the proper text (not shadow) being drawn last
793 static int DrawQ_BuildColoredText(char *output2c, size_t maxoutchars, const char *text, int maxreadchars, qboolean ignorecolorcodes, int *outcolor)
795 int color, numchars = 0;
796 char *outputend2c = output2c + maxoutchars - 2;
797 if (!outcolor || *outcolor == -1)
798 color = STRING_COLOR_DEFAULT;
802 maxreadchars = 1<<30;
803 textend = text + maxreadchars;
804 while (text != textend && *text)
806 if (*text == STRING_COLOR_TAG && !ignorecolorcodes && text + 1 != textend)
808 if (text[1] == STRING_COLOR_TAG)
810 else if (text[1] >= '0' && text[1] <= '9')
812 color = text[1] - '0';
817 if (output2c >= outputend2c)
819 *output2c++ = *text++;
823 output2c[0] = output2c[1] = 0;
830 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)
834 _DrawQ_ProcessDrawFlag(flags);
836 R_Mesh_VertexPointer(floats, 0, 0);
837 R_Mesh_ColorPointer(floats + 20, 0, 0);
838 R_Mesh_ResetTextureState();
844 height = pic->height;
845 R_Mesh_TexBind(0, R_GetTexture(pic->tex));
846 R_Mesh_TexCoordPointer(0, 2, floats + 12, 0, 0);
847 floats[12] = s1;floats[13] = t1;
848 floats[14] = s2;floats[15] = t2;
849 floats[16] = s4;floats[17] = t4;
850 floats[18] = s3;floats[19] = t3;
853 floats[2] = floats[5] = floats[8] = floats[11] = 0;
854 floats[0] = floats[9] = x;
855 floats[1] = floats[4] = y;
856 floats[3] = floats[6] = x + width;
857 floats[7] = floats[10] = y + height;
858 floats[20] = r1;floats[21] = g1;floats[22] = b1;floats[23] = a1;
859 floats[24] = r2;floats[25] = g2;floats[26] = b2;floats[27] = a2;
860 floats[28] = r4;floats[29] = g4;floats[30] = b4;floats[31] = a4;
861 floats[32] = r3;floats[33] = g3;floats[34] = b3;floats[35] = a3;
863 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
866 void DrawQ_Mesh (drawqueuemesh_t *mesh, int flags)
868 _DrawQ_ProcessDrawFlag(flags);
870 R_Mesh_VertexPointer(mesh->data_vertex3f, 0, 0);
871 R_Mesh_ColorPointer(mesh->data_color4f, 0, 0);
872 R_Mesh_ResetTextureState();
873 R_Mesh_TexBind(0, R_GetTexture(mesh->texture));
874 R_Mesh_TexCoordPointer(0, 2, mesh->data_texcoord2f, 0, 0);
876 GL_LockArrays(0, mesh->num_vertices);
877 R_Mesh_Draw(0, mesh->num_vertices, mesh->num_triangles, mesh->data_element3i, 0, 0);
881 void DrawQ_LineLoop (drawqueuemesh_t *mesh, int flags)
885 _DrawQ_ProcessDrawFlag(flags);
889 qglBegin(GL_LINE_LOOP);
890 for (num = 0;num < mesh->num_vertices;num++)
892 if (mesh->data_color4f)
893 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]);
894 qglVertex2f(mesh->data_vertex3f[num*3+0], mesh->data_vertex3f[num*3+1]);
900 //[515]: this is old, delete
901 void DrawQ_Line (float width, float x1, float y1, float x2, float y2, float r, float g, float b, float alpha, int flags)
903 _DrawQ_ProcessDrawFlag(flags);
906 qglLineWidth(width);CHECKGLERROR
908 GL_Color(r,g,b,alpha);
917 void DrawQ_SetClipArea(float x, float y, float width, float height)
921 // We have to convert the con coords into real coords
922 // OGL uses top to bottom
923 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)));
925 GL_ScissorTest(true);
928 void DrawQ_ResetClipArea(void)
931 GL_ScissorTest(false);
934 void DrawQ_Finish(void)
936 r_refdef.draw2dstage = false;
939 static float blendvertex3f[9] = {-5000, -5000, 10, 10000, -5000, 10, -5000, 10000, 10};
940 void R_DrawGamma(void)
943 if (!vid_usinghwgamma)
945 // all the blends ignore depth
946 R_Mesh_VertexPointer(blendvertex3f, 0, 0);
947 R_Mesh_ColorPointer(NULL, 0, 0);
948 R_Mesh_ResetTextureState();
951 GL_PolygonOffset(0, 0);
953 if (v_color_enable.integer)
955 c[0] = v_color_white_r.value;
956 c[1] = v_color_white_g.value;
957 c[2] = v_color_white_b.value;
960 c[0] = c[1] = c[2] = v_contrast.value;
961 if (c[0] >= 1.01f || c[1] >= 1.01f || c[2] >= 1.01f)
963 GL_BlendFunc(GL_DST_COLOR, GL_ONE);
964 while (c[0] >= 1.01f || c[1] >= 1.01f || c[2] >= 1.01f)
966 GL_Color(bound(0, c[0] - 1, 1), bound(0, c[1] - 1, 1), bound(0, c[2] - 1, 1), 1);
967 R_Mesh_Draw(0, 3, 1, polygonelements, 0, 0);
968 VectorScale(c, 0.5, c);
971 if (v_color_enable.integer)
973 c[0] = v_color_black_r.value;
974 c[1] = v_color_black_g.value;
975 c[2] = v_color_black_b.value;
978 c[0] = c[1] = c[2] = v_brightness.value;
979 if (c[0] >= 0.01f || c[1] >= 0.01f || c[2] >= 0.01f)
981 GL_BlendFunc(GL_ONE, GL_ONE);
982 GL_Color(c[0], c[1], c[2], 1);
983 R_Mesh_Draw(0, 3, 1, polygonelements, 0, 0);