X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=gl_draw.c;h=ecd5154d6fd999a597d5e0499cd971a381ffba15;hp=2e6772f7fa75304cecafe434e7699ba3f24d36be;hb=3779acfc88fe7c276d68d21484116cee06cee9c8;hpb=468db062ea41a78210871ea5b2d53c01f9cab190 diff --git a/gl_draw.c b/gl_draw.c index 2e6772f7..ecd5154d 100644 --- a/gl_draw.c +++ b/gl_draw.c @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -18,1409 +18,700 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -// draw.c -- this is the only file outside the refresh that touches the -// vid buffer - #include "quakedef.h" +#include "image.h" +#include "wad.h" -#define GL_COLOR_INDEX8_EXT 0x80E5 - -extern unsigned char d_15to8table[65536]; - -cvar_t qsg_version = {"qsg_version", "1"}; -cvar_t gl_max_size = {"gl_max_size", "1024"}; -cvar_t gl_picmip = {"gl_picmip", "0"}; -cvar_t gl_conalpha = {"gl_conalpha", "1"}; -cvar_t gl_lerpimages = {"gl_lerpimages", "1"}; - -byte *draw_chars; // 8*8 graphic characters -qpic_t *draw_disc; - -int translate_texture; -int char_texture; - -typedef struct -{ - int texnum; - float sl, tl, sh, th; -} glpic_t; - -byte conback_buffer[sizeof(qpic_t) + sizeof(glpic_t)]; -qpic_t *conback = (qpic_t *)&conback_buffer; - -int gl_filter_min = GL_LINEAR_MIPMAP_LINEAR; //NEAREST; -int gl_filter_max = GL_LINEAR; - - -int texels; - -typedef struct -{ - int texnum; - char identifier[64]; - int width, height; - qboolean mipmap; -// LordHavoc: 32bit textures - int bytesperpixel; -// LordHavoc: CRC to identify cache mismatchs - int crc; - int lerped; // whether this texture was uploaded with or without interpolation -} gltexture_t; - -#define MAX_GLTEXTURES 4096 -gltexture_t gltextures[MAX_GLTEXTURES]; -int numgltextures; - -/* -============================================================================= - - scrap allocation +#include "cl_video.h" - Allocate all the little status bar obejcts into a single texture - to crutch up stupid hardware / drivers -============================================================================= -*/ - -#define MAX_SCRAPS 2 -#define BLOCK_WIDTH 256 -#define BLOCK_HEIGHT 256 - -int scrap_allocated[MAX_SCRAPS][BLOCK_WIDTH]; -byte scrap_texels[MAX_SCRAPS][BLOCK_WIDTH*BLOCK_HEIGHT*4]; -qboolean scrap_dirty; -int scrap_texnum; - -// returns a texture number and the position inside it -int Scrap_AllocBlock (int w, int h, int *x, int *y) -{ - int i, j; - int best, best2; - int texnum; - - for (texnum=0 ; texnum= best) - break; - if (scrap_allocated[texnum][i+j] > best2) - best2 = scrap_allocated[texnum][i+j]; - } - if (j == w) - { // this is a valid spot - *x = i; - *y = best = best2; - } - } - - if (best + h > BLOCK_HEIGHT) - continue; - - for (i=0 ; idata; - - // load little ones into the scrap - if (p->width < 64 && p->height < 64) - { - int x, y; - int i, j, k; - int texnum; - - texnum = Scrap_AllocBlock (p->width, p->height, &x, &y); - scrap_dirty = true; - k = 0; - for (i=0 ; iheight ; i++) - for (j=0 ; jwidth ; j++, k++) - scrap_texels[texnum][(y+i)*BLOCK_WIDTH + x + j] = p->data[k]; - texnum += scrap_texnum; - gl->texnum = texnum; - gl->sl = (x+0.01)/(float)BLOCK_WIDTH; - gl->sh = (x+p->width-0.01)/(float)BLOCK_WIDTH; - gl->tl = (y+0.01)/(float)BLOCK_WIDTH; - gl->th = (y+p->height-0.01)/(float)BLOCK_WIDTH; - - pic_count++; - pic_texels += p->width*p->height; - // LordHavoc: LINEAR interpolation - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - else - { - gl->texnum = GL_LoadPicTexture (p); - gl->sl = 0; - gl->sh = 1; - gl->tl = 0; - gl->th = 1; - // LordHavoc: LINEAR interpolation - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //NEAREST); - } - return p; -} - - -/* -================ -Draw_CachePic -================ -*/ -qpic_t *Draw_CachePic (char *path) -{ - cachepic_t *pic; - int i; - qpic_t *dat; - glpic_t *gl; - - for (pic=menu_cachepics, i=0 ; iname)) - return &pic->pic; - - if (menu_numcachepics == MAX_CACHED_PICS) - Sys_Error ("menu_numcachepics == MAX_CACHED_PICS"); - menu_numcachepics++; - strcpy (pic->name, path); - -// -// load the pic from disk -// - dat = (qpic_t *)COM_LoadTempFile (path, false); - if (!dat) - Sys_Error ("Draw_CachePic: failed to load %s", path); - SwapPic (dat); - - // HACK HACK HACK --- we need to keep the bytes for - // the translatable player picture just for the menu - // configuration dialog - if (!strcmp (path, "gfx/menuplyr.lmp")) - memcpy (menuplyr_pixels, dat->data, dat->width*dat->height); - - pic->pic.width = dat->width; - pic->pic.height = dat->height; - - gl = (glpic_t *)pic->pic.data; - gl->texnum = GL_LoadPicTexture (dat); - gl->sl = 0; - gl->sh = 1; - gl->tl = 0; - gl->th = 1; - - return &pic->pic; -} - - -void Draw_CharToConback (int num, byte *dest) -{ - int row, col; - byte *source; - int drawline; - int x; - - row = num>>4; - col = num&15; - source = draw_chars + (row<<10) + (col<<3); - - drawline = 8; - - while (drawline--) - { - for (x=0 ; x<8 ; x++) - if (source[x] != 255) - dest[x] = 0x60 + source[x]; - source += 128; - dest += 320; - } - -} - -typedef struct -{ - char *name; - int minimize, maximize; -} glmode_t; - -glmode_t modes[] = { - {"GL_NEAREST", GL_NEAREST, GL_NEAREST}, - {"GL_LINEAR", GL_LINEAR, GL_LINEAR}, - {"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST}, - {"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR}, - {"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST}, - {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR} +#include "lhfont.h" }; -/* -=============== -Draw_TextureMode_f -=============== -*/ -void Draw_TextureMode_f (void) +extern qbyte *LoadTGA (qbyte *f, int matchwidth, int matchheight); + +static rtexture_t *draw_generateconchars(void) { - int i; - gltexture_t *glt; + int i; + qbyte buffer[65536][4], *data = NULL; + double random; - if (Cmd_Argc() == 1) + fs_filesize = FONT_FILESIZE; + data = LoadTGA (concharimage, 256, 256); + fs_filesize = -1; +// Gold numbers + for (i = 0;i < 8192;i++) { - for (i=0 ; i< 6 ; i++) - if (gl_filter_min == modes[i].minimize) - { - Con_Printf ("%s\n", modes[i].name); - return; - } - Con_Printf ("current filter is unknown???\n"); - return; + random = lhrandom (0.0,1.0); + buffer[i][0] = 83 + (qbyte)(random * 64); + buffer[i][1] = 71 + (qbyte)(random * 32); + buffer[i][2] = 23 + (qbyte)(random * 16); + buffer[i][3] = data[i*4+0]; } - - for (i=0 ; i< 6 ; i++) +// White chars + for (i = 8192;i < 32768;i++) { - if (!Q_strcasecmp (modes[i].name, Cmd_Argv(1) ) ) - break; + random = lhrandom (0.0,1.0); + buffer[i][0] = 95 + (qbyte)(random * 64); + buffer[i][1] = 95 + (qbyte)(random * 64); + buffer[i][2] = 95 + (qbyte)(random * 64); + buffer[i][3] = data[i*4+0]; } - if (i == 6) +// Gold numbers + for (i = 32768;i < 40960;i++) { - Con_Printf ("bad filter name\n"); - return; + random = lhrandom (0.0,1.0); + buffer[i][0] = 83 + (qbyte)(random * 64); + buffer[i][1] = 71 + (qbyte)(random * 32); + buffer[i][2] = 23 + (qbyte)(random * 16); + buffer[i][3] = data[i*4+0]; } - - gl_filter_min = modes[i].minimize; - gl_filter_max = modes[i].maximize; - - // change all the existing mipmap texture objects - for (i=0, glt=gltextures ; imipmap) - { - glBindTexture(GL_TEXTURE_2D, glt->texnum); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); - } + random = lhrandom (0.0,1.0); + buffer[i][0] = 96 + (qbyte)(random * 64); + buffer[i][1] = 43 + (qbyte)(random * 32); + buffer[i][2] = 27 + (qbyte)(random * 32); + buffer[i][3] = data[i*4+0]; } -} - -extern void LoadSky_f(void); - -extern char *QSG_EXTENSIONS; -/* -=============== -Draw_Init -=============== -*/ -void rmain_registercvars(); -void Draw_Init (void) -{ - int i; - qpic_t *cb; - byte *dest; - int x, y; - char ver[40]; - glpic_t *gl; - int start; - - Cvar_RegisterVariable (&qsg_version); - Cvar_RegisterVariable (&gl_max_size); - Cvar_RegisterVariable (&gl_picmip); - Cvar_RegisterVariable (&gl_conalpha); - Cvar_RegisterVariable (&gl_lerpimages); - - // 3dfx can only handle 256 wide textures - if (!Q_strncasecmp ((char *)gl_renderer, "3dfx",4) || - strstr((char *)gl_renderer, "Glide")) - Cvar_Set ("gl_max_size", "256"); - - Cmd_AddCommand ("gl_texturemode", &Draw_TextureMode_f); - - Cmd_AddCommand ("loadsky", &LoadSky_f); - - // load the console background and the charset - // by hand, because we need to write the version - // string into the background before turning - // it into a texture - draw_chars = W_GetLumpName ("conchars"); - for (i=0 ; i<256*64 ; i++) - if (draw_chars[i] == 0) - draw_chars[i] = 255; // proper transparent color - - // now turn them into textures - char_texture = GL_LoadTexture ("charset", 128, 128, draw_chars, false, true, 1); - - start = Hunk_LowMark(); - - cb = (qpic_t *)COM_LoadMallocFile ("gfx/conback.lmp", false); - if (!cb) - Sys_Error ("Couldn't load gfx/conback.lmp"); - SwapPic (cb); - - // hack the version number directly into the pic -#ifdef NEHAHRA -#if defined(__linux__) - sprintf (ver, "DPNehahra Linux GL %.2f", (float) VERSION); -#else - sprintf (ver, "DPNehahra Windows GL %.2f", (float) VERSION); -#endif -#else -#if defined(__linux__) - sprintf (ver, "DarkPlaces Linux GL %.2f", (float)VERSION); -#else - sprintf (ver, "DarkPlaces Windows GL %.2f", (float)VERSION); -#endif +#if 0 + Image_WriteTGARGBA ("gfx/generated_conchars.tga", 256, 256, &buffer[0][0]); #endif - dest = cb->data + 320*186 + 320 - 11 - 8*strlen(ver); - y = strlen(ver); - for (x=0 ; xdata; - gl->texnum = GL_LoadTexture ("conback", cb->width, cb->height, cb->data, false, false, 1); - gl->sl = 0; - gl->sh = 1; - gl->tl = 0; - gl->th = 1; - conback->width = vid.width; - conback->height = vid.height; - - // free loaded console - free(cb); - - // save a texture slot for translated picture - translate_texture = texture_extension_number++; - - // save slots for scraps - scrap_texnum = texture_extension_number; - texture_extension_number += MAX_SCRAPS; - - // - // get the other pics we need - // - draw_disc = Draw_PicFromWad ("disc"); - - rmain_registercvars(); -} - - -/* -================ -Draw_Character - -Draws one 8*8 graphics character with 0 being transparent. -It can be clipped to the top of the screen to allow the console to be -smoothly scrolled off. -================ -*/ -void Draw_Character (int x, int y, int num) -{ - int row, col; - float frow, fcol, size; - - if (num == 32) - return; // space - - num &= 255; - - if (y <= -8) - return; // totally off screen - - row = num>>4; - col = num&15; - - frow = row*0.0625; - fcol = col*0.0625; - size = 0.0625; - - glBindTexture(GL_TEXTURE_2D, char_texture); - // LordHavoc: NEAREST mode on text if not scaling up - if ((int) vid.width < glwidth) - { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - } - glColor3f(1,1,1); - glBegin (GL_QUADS); - glTexCoord2f (fcol, frow); - glVertex2f (x, y); - glTexCoord2f (fcol + size, frow); - glVertex2f (x+8, y); - glTexCoord2f (fcol + size, frow + size); - glVertex2f (x+8, y+8); - glTexCoord2f (fcol, frow + size); - glVertex2f (x, y+8); - glEnd (); - - // LordHavoc: revert to LINEAR mode - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -} + Mem_Free(data); + return R_LoadTexture2D(drawtexturepool, "conchars", 256, 256, &buffer[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL); +} + +static qbyte pointerimage[256] = +{ + "333333332......." + "26777761........" + "2655541........." + "265541.........." + "2654561........." + "26414561........" + "251.14561......." + "21...14561......" + "1.....141......." + ".......1........" + "................" + "................" + "................" + "................" + "................" + "................" +}; -/* -================ -Draw_String -================ -*/ -// LordHavoc: sped this up a lot, and added maxlen -void Draw_String (int x, int y, char *str, int maxlen) +static rtexture_t *draw_generatemousepointer(void) { - int num; - float frow, fcol; - if (y <= -8 || y >= (int) vid.height || x >= (int) vid.width || *str == 0) // completely offscreen or no text to print - return; - if (maxlen < 1) - maxlen = strlen(str); - else if (maxlen > (int) strlen(str)) - maxlen = strlen(str); - glBindTexture(GL_TEXTURE_2D, char_texture); - - // LordHavoc: NEAREST mode on text if not scaling up - if ((int) vid.width < glwidth) - { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - } - - glColor3f(1,1,1); - glBegin (GL_QUADS); - while (maxlen-- && x < (int) vid.width) // stop rendering when out of characters or room + int i; + qbyte buffer[256][4]; + for (i = 0;i < 256;i++) { - if ((num = *str++) != 32) // skip spaces + if (pointerimage[i] == '.') { - frow = (float) ((int) num >> 4)*0.0625; - fcol = (float) ((int) num & 15)*0.0625; - glTexCoord2f (fcol, frow); - glVertex2f (x, y); - glTexCoord2f (fcol + 0.0625, frow); - glVertex2f (x+8, y); - glTexCoord2f (fcol + 0.0625, frow + 0.0625); - glVertex2f (x+8, y+8); - glTexCoord2f (fcol, frow + 0.0625); - glVertex2f (x, y+8); + buffer[i][0] = 0; + buffer[i][1] = 0; + buffer[i][2] = 0; + buffer[i][3] = 0; } - x += 8; - } - glEnd (); - - // LordHavoc: revert to LINEAR mode - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -} - -/* -============= -Draw_AlphaPic -============= -*/ -void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha) -{ - glpic_t *gl; - - if (scrap_dirty) - Scrap_Upload (); - gl = (glpic_t *)pic->data; -// glDisable(GL_ALPHA_TEST); -// glEnable (GL_BLEND); -// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -// glCullFace(GL_FRONT); - glColor4f(0.8,0.8,0.8,alpha); - glBindTexture(GL_TEXTURE_2D, gl->texnum); -// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glBegin (GL_QUADS); - glTexCoord2f (gl->sl, gl->tl); - glVertex2f (x, y); - glTexCoord2f (gl->sh, gl->tl); - glVertex2f (x+pic->width, y); - glTexCoord2f (gl->sh, gl->th); - glVertex2f (x+pic->width, y+pic->height); - glTexCoord2f (gl->sl, gl->th); - glVertex2f (x, y+pic->height); - glEnd (); - glColor3f(1,1,1); -// glEnable(GL_ALPHA_TEST); -// glDisable (GL_BLEND); -} - - -/* -============= -Draw_Pic -============= -*/ -void Draw_Pic (int x, int y, qpic_t *pic) -{ - glpic_t *gl; - - if (scrap_dirty) - Scrap_Upload (); - gl = (glpic_t *)pic->data; - glColor3f(0.8,0.8,0.8); - glBindTexture(GL_TEXTURE_2D, gl->texnum); - glBegin (GL_QUADS); - glTexCoord2f (gl->sl, gl->tl); - glVertex2f (x, y); - glTexCoord2f (gl->sh, gl->tl); - glVertex2f (x+pic->width, y); - glTexCoord2f (gl->sh, gl->th); - glVertex2f (x+pic->width, y+pic->height); - glTexCoord2f (gl->sl, gl->th); - glVertex2f (x, y+pic->height); - glEnd (); -} - - -/* -============= -Draw_TransPic -============= -*/ -void Draw_TransPic (int x, int y, qpic_t *pic) -{ - if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 || (unsigned)(y + pic->height) > vid.height) - Sys_Error ("Draw_TransPic: bad coordinates"); - -// glEnable(GL_BLEND); -// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -// glDisable(GL_ALPHA_TEST); - Draw_Pic (x, y, pic); -// glDisable(GL_BLEND); -} - - -/* -============= -Draw_TransPicTranslate - -Only used for the player color selection menu -============= -*/ -void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation) -{ - int v, u, c; - unsigned trans[64*64], *dest; - byte *src; - int p; - - glBindTexture(GL_TEXTURE_2D, translate_texture); - - c = pic->width * pic->height; - - dest = trans; - for (v=0 ; v<64 ; v++, dest += 64) - { - src = &menuplyr_pixels[ ((v*pic->height)>>6) *pic->width]; - for (u=0 ; u<64 ; u++) + else { - p = src[(u*pic->width)>>6]; - if (p == 255) - dest[u] = p; - else - dest[u] = d_8to24table[translation[p]]; + buffer[i][0] = (pointerimage[i] - '0') * 16; + buffer[i][1] = (pointerimage[i] - '0') * 16; + buffer[i][2] = (pointerimage[i] - '0') * 16; + buffer[i][3] = 255; } } + return R_LoadTexture2D(drawtexturepool, "mousepointer", 16, 16, &buffer[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL); +} + +// must match NUMCROSSHAIRS in r_crosshairs.c +#define NUMCROSSHAIRS 6 + +static qbyte *crosshairtexdata[NUMCROSSHAIRS] = +{ + "................" + "................" + "................" + "...33......33..." + "...355....553..." + "....577..775...." + ".....77..77....." + "................" + "................" + ".....77..77....." + "....577..775...." + "...355....553..." + "...33......33..." + "................" + "................" + "................" + , + "................" + "................" + "................" + "...3........3..." + "....5......5...." + ".....7....7....." + "......7..7......" + "................" + "................" + "......7..7......" + ".....7....7....." + "....5......5...." + "...3........3..." + "................" + "................" + "................" + , + "................" + ".......77......." + ".......77......." + "................" + "................" + ".......44......." + ".......44......." + ".77..44..44..77." + ".77..44..44..77." + ".......44......." + ".......44......." + "................" + "................" + ".......77......." + ".......77......." + "................" + , + "................" + "................" + "................" + "................" + "................" + "................" + "................" + "................" + "........7777777." + "........752....." + "........72......" + "........7......." + "........7......." + "........7......." + "........7......." + "................" + , + "................" + "................" + "................" + "................" + "................" + "........7......." + "................" + "........4......." + ".....7.4.4.7...." + "........4......." + "................" + "........7......." + "................" + "................" + "................" + "................" + , + "................" + "................" + "................" + "................" + "................" + "................" + "................" + ".......55......." + ".......55......." + "................" + "................" + "................" + "................" + "................" + "................" + "................" +}; - glTexImage2D (GL_TEXTURE_2D, 0, 4, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans); - - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - glColor3f(0.8,0.8,0.8); - glBegin (GL_QUADS); - glTexCoord2f (0, 0); - glVertex2f (x, y); - glTexCoord2f (1, 0); - glVertex2f (x+pic->width, y); - glTexCoord2f (1, 1); - glVertex2f (x+pic->width, y+pic->height); - glTexCoord2f (0, 1); - glVertex2f (x, y+pic->height); - glEnd (); -} - - -/* -================ -Draw_ConsoleBackground - -================ -*/ -void Draw_ConsoleBackground (int lines) -{ - // LordHavoc: changed alpha - //int y = (vid.height >> 1); - - if (lines >= (int) vid.height) - Draw_Pic(0, lines - vid.height, conback); - else - Draw_AlphaPic (0, lines - vid.height, conback, gl_conalpha.value*lines/vid.height); - // Draw_AlphaPic (0, lines - vid.height, conback, (float)(1.2 * lines)/y); -} - -/* -============= -Draw_Fill - -Fills a box of pixels with a single color -============= -*/ -void Draw_Fill (int x, int y, int w, int h, int c) -{ - glDisable (GL_TEXTURE_2D); - glColor3f (host_basepal[c*3]/255.0, host_basepal[c*3+1]/255.0, host_basepal[c*3+2]/255.0); - - glBegin (GL_QUADS); - - glVertex2f (x,y); - glVertex2f (x+w, y); - glVertex2f (x+w, y+h); - glVertex2f (x, y+h); - - glEnd (); - glColor3f(1,1,1); - glEnable (GL_TEXTURE_2D); -} -//============================================================================= - -//============================================================================= - -/* -================ -GL_Set2D - -Setup as if the screen was 320*200 -================ -*/ -void GL_Set2D (void) -{ - glViewport (glx, gly, glwidth, glheight); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity (); - glOrtho (0, vid.width, vid.height, 0, -99999, 99999); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity (); - - glDisable (GL_DEPTH_TEST); - glDisable (GL_CULL_FACE); - glEnable (GL_BLEND); // was Disable -// glEnable (GL_ALPHA_TEST); - glDisable (GL_ALPHA_TEST); - glEnable(GL_TEXTURE_2D); - - // LordHavoc: added this - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - - glColor3f(1,1,1); -} - -// LordHavoc: SHOWLMP stuff -#define SHOWLMP_MAXLABELS 256 -typedef struct showlmp_s -{ - qboolean isactive; - float x; - float y; - char label[32]; - char pic[128]; -} showlmp_t; - -showlmp_t showlmp[SHOWLMP_MAXLABELS]; - -void SHOWLMP_decodehide() +static rtexture_t *draw_generatecrosshair(int num) { int i; - byte *lmplabel; - lmplabel = MSG_ReadString(); - for (i = 0;i < SHOWLMP_MAXLABELS;i++) - if (showlmp[i].isactive && strcmp(showlmp[i].label, lmplabel) == 0) + char *in; + qbyte data[16*16][4]; + in = crosshairtexdata[num]; + for (i = 0;i < 16*16;i++) + { + if (in[i] == '.') { - showlmp[i].isactive = false; - return; + data[i][0] = 255; + data[i][1] = 255; + data[i][2] = 255; + data[i][3] = 0; } -} - -void SHOWLMP_decodeshow() -{ - int i, k; - byte lmplabel[256], picname[256]; - float x, y; - strcpy(lmplabel,MSG_ReadString()); - strcpy(picname, MSG_ReadString()); - x = MSG_ReadByte(); - y = MSG_ReadByte(); - k = -1; - for (i = 0;i < SHOWLMP_MAXLABELS;i++) - if (showlmp[i].isactive) + else { - if (strcmp(showlmp[i].label, lmplabel) == 0) - { - k = i; - break; // drop out to replace it - } + data[i][0] = 255; + data[i][1] = 255; + data[i][2] = 255; + data[i][3] = (qbyte) ((int) (in[i] - '0') * 255 / 7); } - else if (k < 0) // find first empty one to replace - k = i; - if (k < 0) - return; // none found to replace - // change existing one - showlmp[k].isactive = true; - strcpy(showlmp[k].label, lmplabel); - strcpy(showlmp[k].pic, picname); - showlmp[k].x = x; - showlmp[k].y = y; -} - -void SHOWLMP_drawall() -{ - int i; - for (i = 0;i < SHOWLMP_MAXLABELS;i++) - if (showlmp[i].isactive) - Draw_TransPic(showlmp[i].x, showlmp[i].y, Draw_CachePic(showlmp[i].pic)); -} - -void SHOWLMP_clear() -{ - int i; - for (i = 0;i < SHOWLMP_MAXLABELS;i++) - showlmp[i].isactive = false; -} - -//==================================================================== - -/* -================ -GL_FindTexture -================ -*/ -int GL_FindTexture (char *identifier) -{ - int i; - gltexture_t *glt; - - for (i=0, glt=gltextures ; iidentifier)) - return gltextures[i].texnum; } - - return -1; + return R_LoadTexture2D(drawtexturepool, va("crosshair%i", num), 16, 16, &data[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL); } -extern byte qgamma[]; - -// LordHavoc: gamma correction and improved resampling -void GL_ResampleTextureLerpLine (byte *in, byte *out, int inwidth, int outwidth) +static rtexture_t *draw_generateditherpattern(void) { - int j, xi, oldx = 0; - float f, fstep, l1, l2; - fstep = (float) inwidth/outwidth; - for (j = 0,f = 0;j < outwidth;j++, f += fstep) +#if 1 + int x, y; + qbyte data[8*8*4]; + for (y = 0;y < 8;y++) { - xi = (int) f; - if (xi != oldx) - { - in += (xi - oldx) * 4; - oldx = xi; - } - if (xi < (inwidth-1)) + for (x = 0;x < 8;x++) { - l2 = f - xi; - l1 = 1 - l2; - *out++ = qgamma[(byte) (in[0] * l1 + in[4] * l2)]; - *out++ = qgamma[(byte) (in[1] * l1 + in[5] * l2)]; - *out++ = qgamma[(byte) (in[2] * l1 + in[6] * l2)]; - *out++ = (byte) (in[3] * l1 + in[7] * l2) ; - } - else // last pixel of the line has no pixel to lerp to - { - *out++ = qgamma[in[0]]; - *out++ = qgamma[in[1]]; - *out++ = qgamma[in[2]]; - *out++ = in[3] ; + data[(y*8+x)*4+0] = data[(y*8+x)*4+1] = data[(y*8+x)*4+2] = ((x^y) & 4) ? 255 : 0; + data[(y*8+x)*4+3] = 255; } } + return R_LoadTexture2D(drawtexturepool, "ditherpattern", 8, 8, data, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_PRECACHE, NULL); +#else + qbyte data[16]; + memset(data, 255, sizeof(data)); + data[0] = data[1] = data[2] = data[12] = data[13] = data[14] = 0; + return R_LoadTexture2D(drawtexturepool, "ditherpattern", 2, 2, data, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_PRECACHE, NULL); +#endif } /* ================ -GL_ResampleTexture +Draw_CachePic ================ */ -void GL_ResampleTexture (void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight) +// FIXME: move this to client somehow +cachepic_t *Draw_CachePic (const char *path, qboolean persistent) { - // LordHavoc: gamma correction and greatly improved resampling - if (gl_lerpimages.value) + int i, crc, hashkey; + cachepic_t *pic; + qpic_t *p; + int flags; + + if (!strncmp(CLVIDEOPREFIX, path, sizeof(CLVIDEOPREFIX) - 1)) + { - int i, j, yi, oldy; - byte *inrow, *out, *row1, *row2; - float f, fstep, l1, l2; - out = outdata; - fstep = (float) inheight/outheight; - - row1 = malloc(outwidth*4); - row2 = malloc(outwidth*4); - inrow = indata; - oldy = 0; - GL_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth); - GL_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth); - for (i = 0, f = 0;i < outheight;i++,f += fstep) - { - yi = (int) f; - if (yi != oldy) - { - inrow = (byte *)((int)indata + inwidth*4*yi); - if (yi == oldy+1) - memcpy(row1, row2, outwidth*4); - else - GL_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth); - if (yi < (inheight-1)) - GL_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth); - else - memcpy(row2, row1, outwidth*4); - oldy = yi; - } - if (yi < (inheight-1)) - { - l2 = f - yi; - l1 = 1 - l2; - for (j = 0;j < outwidth;j++) - { - *out++ = (byte) (*row1++ * l1 + *row2++ * l2); - *out++ = (byte) (*row1++ * l1 + *row2++ * l2); - *out++ = (byte) (*row1++ * l1 + *row2++ * l2); - *out++ = (byte) (*row1++ * l1 + *row2++ * l2); - } - row1 -= outwidth*4; - row2 -= outwidth*4; - } - else // last line has no pixels to lerp to - { - for (j = 0;j < outwidth;j++) - { - *out++ = *row1++; - *out++ = *row1++; - *out++ = *row1++; - *out++ = *row1++; - } - row1 -= outwidth*4; - } - } - free(row1); - free(row2); + clvideo_t *video; + + video = CL_GetVideo(path); + if( video ) + return &video->cpif; } - else - { - int i, j; - unsigned frac, fracstep; - byte *inrow, *out, *inpix; - out = outdata; - fracstep = inwidth*0x10000/outwidth; - for (i=0 ; i> 8) ^ crc) % CACHEPICHASHSIZE; + for (pic = cachepichash[hashkey];pic;pic = pic->chain) + if (!strcmp (path, pic->name)) + return pic; + + if (numcachepics == MAX_CACHED_PICS) + { + Con_Printf ("Draw_CachePic: numcachepics == MAX_CACHED_PICS"); + // FIXME: support NULL in callers? + return cachepics; // return the first one + } + pic = cachepics + (numcachepics++); + strlcpy (pic->name, path, sizeof(pic->name)); + // link into list + pic->chain = cachepichash[hashkey]; + cachepichash[hashkey] = pic; + + flags = TEXF_ALPHA; + if (persistent) + flags |= TEXF_PRECACHE; + if (!strcmp(path, "gfx/colorcontrol/ditherpattern.tga")) + flags |= TEXF_CLAMP; + + // load the pic from disk + pic->tex = loadtextureimage(drawtexturepool, path, 0, 0, false, flags); + if (pic->tex == NULL && !strncmp(path, "gfx/", 4)) + { + // compatibility with older versions + pic->tex = loadtextureimage(drawtexturepool, path + 4, 0, 0, false, flags); + // failed to find gfx/whatever.tga or similar, try the wad + if (pic->tex == NULL && (p = W_GetLumpName (path + 4))) { - inrow = (byte *)indata + inwidth*(i*inheight/outheight)*4; - frac = fracstep >> 1; - for (j=0 ; j> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = *inpix++ ;frac += fracstep; - inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = *inpix++ ;frac += fracstep; - inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = *inpix++ ;frac += fracstep; - inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = *inpix++ ;frac += fracstep; + qbyte *pix; + // conchars is a raw image and with the wrong transparent color + pix = (qbyte *)p; + for (i = 0;i < 128 * 128;i++) + if (pix[i] == 0) + pix[i] = 255; + pic->tex = R_LoadTexture2D(drawtexturepool, path, 128, 128, pix, TEXTYPE_PALETTE, flags, palette_complete); } + else + pic->tex = R_LoadTexture2D(drawtexturepool, path, p->width, p->height, p->data, TEXTYPE_PALETTE, flags, palette_complete); } } -} -/* -================ -GL_Resample8BitTexture -- JACK -================ -*/ -void GL_Resample8BitTexture (unsigned char *in, int inwidth, int inheight, unsigned char *out, int outwidth, int outheight) -{ - int i, j; - unsigned char *inrow; - unsigned frac, fracstep; + if (pic->tex == NULL && !strcmp(path, "gfx/conchars")) + pic->tex = draw_generateconchars(); + if (pic->tex == NULL && !strcmp(path, "ui/mousepointer.tga")) + pic->tex = draw_generatemousepointer(); + if (pic->tex == NULL && !strcmp(path, "gfx/prydoncursor001.tga")) + pic->tex = draw_generatemousepointer(); + if (pic->tex == NULL && !strcmp(path, "gfx/crosshair1.tga")) + pic->tex = draw_generatecrosshair(0); + if (pic->tex == NULL && !strcmp(path, "gfx/crosshair2.tga")) + pic->tex = draw_generatecrosshair(1); + if (pic->tex == NULL && !strcmp(path, "gfx/crosshair3.tga")) + pic->tex = draw_generatecrosshair(2); + if (pic->tex == NULL && !strcmp(path, "gfx/crosshair4.tga")) + pic->tex = draw_generatecrosshair(3); + if (pic->tex == NULL && !strcmp(path, "gfx/crosshair5.tga")) + pic->tex = draw_generatecrosshair(4); + if (pic->tex == NULL && !strcmp(path, "gfx/crosshair6.tga")) + pic->tex = draw_generatecrosshair(5); + if (pic->tex == NULL && !strcmp(path, "gfx/colorcontrol/ditherpattern.tga")) + pic->tex = draw_generateditherpattern(); + if (pic->tex == NULL) + { + Con_Printf("Draw_CachePic: failed to load %s\n", path); + pic->tex = r_texture_notexture; + } + + pic->width = R_TextureWidth(pic->tex); + pic->height = R_TextureHeight(pic->tex); + return pic; +} + +cachepic_t *Draw_NewPic(const char *picname, int width, int height, int alpha, qbyte *pixels) +{ + int crc, hashkey; + cachepic_t *pic; + + crc = CRC_Block(picname, strlen(picname)); + hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE; + for (pic = cachepichash[hashkey];pic;pic = pic->chain) + if (!strcmp (picname, pic->name)) + break; - fracstep = inwidth*0x10000/outwidth; - for (i=0 ; i> 1; - for (j=0 ; jtex && pic->width == width && pic->height == height) { - out[j] = inrow[frac>>16]; - frac += fracstep; - out[j+1] = inrow[frac>>16]; - frac += fracstep; - out[j+2] = inrow[frac>>16]; - frac += fracstep; - out[j+3] = inrow[frac>>16]; - frac += fracstep; + R_UpdateTexture(pic->tex, pixels); + return pic; } } -} - - -/* -================ -GL_MipMap - -Operates in place, quartering the size of the texture -================ -*/ -void GL_MipMap (byte *in, int width, int height) -{ - int i, j; - byte *out; - - width <<=2; - height >>= 1; - out = in; - for (i=0 ; i>2; - out[1] = (in[1] + in[5] + in[width+1] + in[width+5])>>2; - out[2] = (in[2] + in[6] + in[width+2] + in[width+6])>>2; - out[3] = (in[3] + in[7] + in[width+3] + in[width+7])>>2; + if (numcachepics == MAX_CACHED_PICS) + { + Con_Printf ("Draw_NewPic: numcachepics == MAX_CACHED_PICS"); + // FIXME: support NULL in callers? + return cachepics; // return the first one + } + pic = cachepics + (numcachepics++); + strcpy (pic->name, picname); + // link into list + pic->chain = cachepichash[hashkey]; + cachepichash[hashkey] = pic; } } -} -/* -================ -GL_MipMap8Bit + pic->width = width; + pic->height = height; + if (pic->tex) + R_FreeTexture(pic->tex); + pic->tex = R_LoadTexture2D(drawtexturepool, picname, width, height, pixels, TEXTYPE_RGBA, alpha ? TEXF_ALPHA : 0, NULL); + return pic; +} -Mipping for 8 bit textures -================ -*/ -void GL_MipMap8Bit (byte *in, int width, int height) +void Draw_FreePic(const char *picname) { - int i, j; - unsigned short r,g,b; - byte *out, *at1, *at2, *at3, *at4; - - height >>= 1; - out = in; - for (i=0 ; i> 8) ^ crc) % CACHEPICHASHSIZE; + for (pic = cachepichash[hashkey];pic;pic = pic->chain) { - for (j=0 ; jname) && pic->tex) { - at1 = (byte *) (d_8to24table + in[0]); - at2 = (byte *) (d_8to24table + in[1]); - at3 = (byte *) (d_8to24table + in[width+0]); - at4 = (byte *) (d_8to24table + in[width+1]); - - r = (at1[0]+at2[0]+at3[0]+at4[0]); r>>=5; - g = (at1[1]+at2[1]+at3[1]+at4[1]); g>>=5; - b = (at1[2]+at2[2]+at3[2]+at4[2]); b>>=5; - - out[0] = d_15to8table[(r<<0) + (g<<5) + (b<<10)]; + R_FreeTexture(pic->tex); + pic->width = 0; + pic->height = 0; + return; } } } /* =============== -GL_Upload32 +Draw_Init =============== */ -void GL_Upload32 (void *data, int width, int height, qboolean mipmap, qboolean alpha) +static void gl_draw_start(void) { - int samples, scaled_width, scaled_height, i; - byte *in, *out, *scaled; - - for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1) - ; - for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1) - ; - - scaled_width >>= (int)gl_picmip.value; - scaled_height >>= (int)gl_picmip.value; - - if (scaled_width > gl_max_size.value) - scaled_width = gl_max_size.value; - if (scaled_height > gl_max_size.value) - scaled_height = gl_max_size.value; - - if (alpha) - { - alpha = false; - in = data; - for (i = 3;i < width*height*4;i += 4) - if (in[i] != 255) - { - alpha = true; - break; - } - } - - samples = alpha ? gl_alpha_format : gl_solid_format; + drawtexturepool = R_AllocTexturePool(); -#if 0 - if (mipmap) - gluBuild2DMipmaps (GL_TEXTURE_2D, samples, width, height, GL_RGBA, GL_UNSIGNED_BYTE, scaled); - else if (scaled_width == width && scaled_height == height) - glTexImage2D (GL_TEXTURE_2D, 0, samples, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled); - else - { - gluScaleImage (GL_RGBA, width, height, GL_UNSIGNED_BYTE, scaled, scaled_width, scaled_height, GL_UNSIGNED_BYTE, scaled); - glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled); - } -#else -texels += scaled_width * scaled_height; - - scaled = malloc(scaled_width*scaled_height*4); - if (scaled_width == width && scaled_height == height) - { - // LordHavoc: gamma correct while copying - in = (byte *)data; - out = (byte *)scaled; - for (i = 0;i < width*height;i++) - { - *out++ = qgamma[*in++]; - *out++ = qgamma[*in++]; - *out++ = qgamma[*in++]; - *out++ = *in++; - } - } - else - GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height); + numcachepics = 0; + memset(cachepichash, 0, sizeof(cachepichash)); - glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled); - if (mipmap) - { - int miplevel; - - miplevel = 0; - while (scaled_width > 1 || scaled_height > 1) - { - GL_MipMap ((byte *)scaled, scaled_width, scaled_height); - scaled_width >>= 1; - scaled_height >>= 1; - if (scaled_width < 1) - scaled_width = 1; - if (scaled_height < 1) - scaled_height = 1; - miplevel++; - glTexImage2D (GL_TEXTURE_2D, miplevel, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled); - } - } -#endif + char_texture = Draw_CachePic("gfx/conchars", true)->tex; +} +static void gl_draw_shutdown(void) +{ + R_FreeTexturePool(&drawtexturepool); - if (mipmap) - { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); - } - else - { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); - } - free(scaled); + numcachepics = 0; + memset(cachepichash, 0, sizeof(cachepichash)); } -void GL_Upload8_EXT (byte *data, int width, int height, qboolean mipmap) +static void gl_draw_newmap(void) { - int scaled_width, scaled_height; - byte *scaled = NULL; +} - for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1) - ; - for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1) - ; +void GL_Draw_Init (void) +{ + numcachepics = 0; + memset(cachepichash, 0, sizeof(cachepichash)); - scaled_width >>= (int)gl_picmip.value; - scaled_height >>= (int)gl_picmip.value; + R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown, gl_draw_newmap); +} - if (scaled_width > gl_max_size.value) - scaled_width = gl_max_size.value; - if (scaled_height > gl_max_size.value) - scaled_height = gl_max_size.value; +float blendvertex3f[9] = {-5000, -5000, 10, 10000, -5000, 10, -5000, 10000, 10}; - texels += scaled_width * scaled_height; +int quadelements[768]; +void R_DrawQueue(void) +{ + int pos, num, chartexnum, texnum, batch; + float x, y, w, h, s, t, u, v, *av, *at, c[4]; + cachepic_t *pic; + drawqueue_t *dq; + char *str; + int batchcount; + unsigned int color; + drawqueuemesh_t *mesh; + rmeshstate_t m; - if (scaled_width == width && scaled_height == height) - { - if (!mipmap) - { - glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX , GL_UNSIGNED_BYTE, data); - goto done; - } - scaled = malloc(scaled_width*scaled_height*4); - memcpy (scaled, data, width*height); - } - else - { - scaled = malloc(scaled_width*scaled_height*4); - GL_Resample8BitTexture (data, width, height, (void*) scaled, scaled_width, scaled_height); - } + if (!r_render.integer) + return; - glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled); - if (mipmap) + if (!quadelements[1]) { - int miplevel; - - miplevel = 0; - while (scaled_width > 1 || scaled_height > 1) + // elements for rendering a series of quads as triangles + for (batch = 0, pos = 0, num = 0;batch < 128;batch++, num += 4) { - GL_MipMap8Bit ((byte *)scaled, scaled_width, scaled_height); - scaled_width >>= 1; - scaled_height >>= 1; - if (scaled_width < 1) - scaled_width = 1; - if (scaled_height < 1) - scaled_height = 1; - miplevel++; - glTexImage2D (GL_TEXTURE_2D, miplevel, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled); + quadelements[pos++] = num; + quadelements[pos++] = num + 1; + quadelements[pos++] = num + 2; + quadelements[pos++] = num; + quadelements[pos++] = num + 2; + quadelements[pos++] = num + 3; } } -done: ; - - - if (mipmap) - { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); - } - else - { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); - } - free(scaled); -} -qboolean VID_Is8bit(); - -/* -=============== -GL_Upload8 -=============== -*/ -void GL_Upload8 (byte *data, int width, int height, qboolean mipmap, qboolean alpha) -{ - static unsigned *trans; - int i, s; - qboolean noalpha; - int p; - byte *indata; - int *outdata; - - s = width*height; - trans = malloc(s*4); - // if there are no transparent pixels, make it a 3 component - // texture even if it was specified as otherwise - if (alpha) - { - noalpha = true; - for (i=0 ; isize) + { + dq = (drawqueue_t *)(r_refdef.drawqueue + pos); + color = dq->color; + + if(dq->flags == DRAWFLAG_ADDITIVE) + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); + else if(dq->flags == DRAWFLAG_MODULATE) + GL_BlendFunc(GL_DST_COLOR, GL_ZERO); + else if(dq->flags == DRAWFLAG_2XMODULATE) + GL_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR); + else + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + GL_DepthMask(true); + GL_DepthTest(false); + + c[0] = (float) ((color >> 24) & 0xFF) * (1.0f / 255.0f); + c[1] = (float) ((color >> 16) & 0xFF) * (1.0f / 255.0f); + c[2] = (float) ((color >> 8) & 0xFF) * (1.0f / 255.0f); + c[3] = (float) ( color & 0xFF) * (1.0f / 255.0f); + x = dq->x; + y = dq->y; + w = dq->scalex; + h = dq->scaley; + + switch(dq->command) { - p = data[i]; - if (p != 255) - trans[i] = d_8to24table[p]; - else + case DRAWQUEUE_STRING: + GL_Color(c[0], c[1], c[2], c[3]); + str = (char *)(dq + 1); + batchcount = 0; + m.pointer_vertex = varray_vertex3f; + m.pointer_color = NULL; + m.pointer_texcoord[0] = varray_texcoord2f[0]; + m.tex[0] = chartexnum; + R_Mesh_State(&m); + at = varray_texcoord2f[0]; + av = varray_vertex3f; + while ((num = *str++) && x < vid_conwidth.integer) { - trans[i] = 0; // force to black - noalpha = false; + if (num != ' ') + { + s = (num & 15)*0.0625f + (0.5f / 256.0f); + t = (num >> 4)*0.0625f + (0.5f / 256.0f); + u = 0.0625f - (1.0f / 256.0f); + v = 0.0625f - (1.0f / 256.0f); + at[ 0] = s ;at[ 1] = t ; + at[ 2] = s+u;at[ 3] = t ; + at[ 4] = s+u;at[ 5] = t+v; + at[ 6] = s ;at[ 7] = t+v; + av[ 0] = x ;av[ 1] = y ;av[ 2] = 10; + av[ 3] = x+w;av[ 4] = y ;av[ 5] = 10; + av[ 6] = x+w;av[ 7] = y+h;av[ 8] = 10; + av[ 9] = x ;av[10] = y+h;av[11] = 10; + at += 8; + av += 12; + batchcount++; + if (batchcount >= 128) + { + GL_LockArrays(0, batchcount * 4); + R_Mesh_Draw(0, batchcount * 4, batchcount * 2, quadelements); + GL_LockArrays(0, 0); + batchcount = 0; + at = varray_texcoord2f[0]; + av = varray_vertex3f; + } + } + x += w; } - } - - if (noalpha) - { - if (VID_Is8bit() && (data!=scrap_texels[0])) + if (batchcount > 0) { - GL_Upload8_EXT (data, width, height, mipmap); - free(trans); - return; + GL_LockArrays(0, batchcount * 4); + R_Mesh_Draw(0, batchcount * 4, batchcount * 2, quadelements); + GL_LockArrays(0, 0); } - alpha = false; + break; + case DRAWQUEUE_MESH: + mesh = (void *)(dq + 1); + m.pointer_vertex = mesh->data_vertex3f; + m.pointer_color = mesh->data_color4f; + m.pointer_texcoord[0] = mesh->data_texcoord2f; + m.tex[0] = R_GetTexture(mesh->texture); + if (!m.tex[0]) + m.pointer_texcoord[0] = NULL; + R_Mesh_State(&m); + GL_LockArrays(0, mesh->num_vertices); + R_Mesh_Draw(0, mesh->num_vertices, mesh->num_triangles, mesh->data_element3i); + GL_LockArrays(0, 0); + break; + case DRAWQUEUE_SETCLIP: + { + // We have to convert the con coords into real coords + int x , y, width, height; + x = dq->x * ((float)vid.width / vid_conwidth.integer); + // OGL uses top to bottom + y = dq->y * ((float) vid.height / vid_conheight.integer); + width = dq->scalex * ((float)vid.width / vid_conwidth.integer); + height = dq->scaley * ((float)vid.height / vid_conheight.integer); + + GL_Scissor(x, y, width, height); + + GL_ScissorTest(true); + } + break; + case DRAWQUEUE_RESETCLIP: + GL_ScissorTest(false); + break; } } - else + + if (!vid_usinghwgamma) { - // LordHavoc: dodge the copy if it will be uploaded as 8bit - if (VID_Is8bit() && (data!=scrap_texels[0])) + // all the blends ignore depth + memset(&m, 0, sizeof(m)); + m.pointer_vertex = blendvertex3f; + R_Mesh_State(&m); + GL_DepthMask(true); + GL_DepthTest(false); + if (v_color_enable.integer) { - GL_Upload8_EXT (data, width, height, mipmap); - free(trans); - return; + c[0] = v_color_white_r.value; + c[1] = v_color_white_g.value; + c[2] = v_color_white_b.value; } - //if (s&3) - // Sys_Error ("GL_Upload8: s&3"); - indata = data; - outdata = trans; - if (s&1) - *outdata++ = d_8to24table[*indata++]; - if (s&2) + else + c[0] = c[1] = c[2] = v_contrast.value; + if (c[0] >= 1.01f || c[1] >= 1.01f || c[2] >= 1.01f) { - *outdata++ = d_8to24table[*indata++]; - *outdata++ = d_8to24table[*indata++]; + GL_BlendFunc(GL_DST_COLOR, GL_ONE); + while (c[0] >= 1.01f || c[1] >= 1.01f || c[2] >= 1.01f) + { + GL_Color(bound(0, c[0] - 1, 1), bound(0, c[1] - 1, 1), bound(0, c[2] - 1, 1), 1); + R_Mesh_Draw(0, 3, 1, polygonelements); + VectorScale(c, 0.5, c); + } } - for (i = 0;i < s;i+=4) + if (v_color_enable.integer) { - *outdata++ = d_8to24table[*indata++]; - *outdata++ = d_8to24table[*indata++]; - *outdata++ = d_8to24table[*indata++]; - *outdata++ = d_8to24table[*indata++]; + c[0] = v_color_black_r.value; + c[1] = v_color_black_g.value; + c[2] = v_color_black_b.value; } - } - - GL_Upload32 (trans, width, height, mipmap, alpha); - free(trans); -} - -/* -================ -GL_LoadTexture -================ -*/ -int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha, int bytesperpixel) -{ - unsigned short crc; - int i; - gltexture_t *glt; - - if (isDedicated) - return 1; - - // LordHavoc: do a CRC to confirm the data really is the same as previous occurances. - crc = CRC_Block(data, width*height*bytesperpixel); - // see if the texture is already present - if (identifier[0]) - { - for (i=0, glt=gltextures ; i= 0.01f || c[1] >= 0.01f || c[2] >= 0.01f) { - if (!strcmp (identifier, glt->identifier)) - { - // LordHavoc: everyone hates cache mismatchs, so I fixed it - if (crc != glt->crc || width != glt->width || height != glt->height) - { - Con_DPrintf("GL_LoadTexture: cache mismatch, replacing old texture\n"); - goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace - //Sys_Error ("GL_LoadTexture: cache mismatch"); - } - if ((gl_lerpimages.value != 0) != glt->lerped) - goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace - return glt->texnum; - } + GL_BlendFunc(GL_ONE, GL_ONE); + GL_Color(c[0], c[1], c[2], 1); + R_Mesh_Draw(0, 3, 1, polygonelements); } } - // LordHavoc: although this could be an else condition as it was in the original id code, - // it is more clear this way - // LordHavoc: check if there are still slots available - if (numgltextures >= MAX_GLTEXTURES) - Sys_Error ("GL_LoadTexture: ran out of texture slots (%d)\n", MAX_GLTEXTURES); - glt = &gltextures[numgltextures++]; - - strcpy (glt->identifier, identifier); - glt->texnum = texture_extension_number; - texture_extension_number++; -// LordHavoc: label to drop out of the loop into the setup code -GL_LoadTexture_setup: - glt->crc = crc; // LordHavoc: used to verify textures are identical - glt->width = width; - glt->height = height; - glt->mipmap = mipmap; - glt->bytesperpixel = bytesperpixel; - glt->lerped = gl_lerpimages.value != 0; - - glBindTexture(GL_TEXTURE_2D, glt->texnum); - - if (bytesperpixel == 1) // 8bit - GL_Upload8 (data, width, height, mipmap, alpha); - else // 32bit - GL_Upload32 (data, width, height, mipmap, true); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - - return glt->texnum; } -/* -================ -GL_LoadPicTexture -================ -*/ -int GL_LoadPicTexture (qpic_t *pic) -{ - return GL_LoadTexture ("", pic->width, pic->height, pic->data, false, true, 1); -} - -int GL_GetTextureSlots (int count) -{ - gltexture_t *glt, *first; - - first = glt = &gltextures[numgltextures]; - while (count--) - { - glt->identifier[0] = 0; - glt->texnum = texture_extension_number++; - glt->crc = 0; - glt->width = 0; - glt->height = 0; - glt->bytesperpixel = 0; - glt++; - numgltextures++; - } - return first->texnum; -}