|
|
1.1 ! root 1: /* ! 2: Copyright (C) 1996-1997 Id Software, Inc. ! 3: ! 4: This program is free software; you can redistribute it and/or ! 5: modify it under the terms of the GNU General Public License ! 6: as published by the Free Software Foundation; either version 2 ! 7: of the License, or (at your option) any later version. ! 8: ! 9: This program is distributed in the hope that it will be useful, ! 10: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ! 12: ! 13: See the GNU General Public License for more details. ! 14: ! 15: You should have received a copy of the GNU General Public License ! 16: along with this program; if not, write to the Free Software ! 17: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ! 18: ! 19: */ ! 20: ! 21: // draw.c -- this is the only file outside the refresh that touches the ! 22: // vid buffer ! 23: ! 24: #include "quakedef.h" ! 25: ! 26: extern unsigned char d_15to8table[65536]; ! 27: extern cvar_t crosshair, cl_crossx, cl_crossy, crosshaircolor; ! 28: ! 29: cvar_t gl_nobind = {"gl_nobind", "0"}; ! 30: cvar_t gl_max_size = {"gl_max_size", "1024"}; ! 31: cvar_t gl_picmip = {"gl_picmip", "0"}; ! 32: ! 33: byte *draw_chars; // 8*8 graphic characters ! 34: qpic_t *draw_disc; ! 35: qpic_t *draw_backtile; ! 36: ! 37: int translate_texture; ! 38: int char_texture; ! 39: int cs_texture; // crosshair texture ! 40: ! 41: static byte cs_data[64] = { ! 42: 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, ! 43: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ! 44: 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, ! 45: 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, ! 46: 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, ! 47: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ! 48: 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, ! 49: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff ! 50: }; ! 51: ! 52: ! 53: typedef struct ! 54: { ! 55: int texnum; ! 56: float sl, tl, sh, th; ! 57: } glpic_t; ! 58: ! 59: byte conback_buffer[sizeof(qpic_t) + sizeof(glpic_t)]; ! 60: qpic_t *conback = (qpic_t *)&conback_buffer; ! 61: ! 62: int gl_lightmap_format = 4; ! 63: int gl_solid_format = 3; ! 64: int gl_alpha_format = 4; ! 65: ! 66: int gl_filter_min = GL_LINEAR_MIPMAP_NEAREST; ! 67: int gl_filter_max = GL_LINEAR; ! 68: ! 69: ! 70: int texels; ! 71: ! 72: typedef struct ! 73: { ! 74: int texnum; ! 75: char identifier[64]; ! 76: int width, height; ! 77: qboolean mipmap; ! 78: } gltexture_t; ! 79: ! 80: #define MAX_GLTEXTURES 1024 ! 81: gltexture_t gltextures[MAX_GLTEXTURES]; ! 82: int numgltextures; ! 83: ! 84: void GL_Bind (int texnum) ! 85: { ! 86: if (gl_nobind.value) ! 87: texnum = char_texture; ! 88: if (currenttexture == texnum) ! 89: return; ! 90: currenttexture = texnum; ! 91: #ifdef _WIN32 ! 92: bindTexFunc (GL_TEXTURE_2D, texnum); ! 93: #else ! 94: glBindTexture (GL_TEXTURE_2D, texnum); ! 95: #endif ! 96: } ! 97: ! 98: ! 99: /* ! 100: ============================================================================= ! 101: ! 102: scrap allocation ! 103: ! 104: Allocate all the little status bar obejcts into a single texture ! 105: to crutch up stupid hardware / drivers ! 106: ! 107: ============================================================================= ! 108: */ ! 109: ! 110: #define MAX_SCRAPS 1 ! 111: #define BLOCK_WIDTH 256 ! 112: #define BLOCK_HEIGHT 256 ! 113: ! 114: int scrap_allocated[MAX_SCRAPS][BLOCK_WIDTH]; ! 115: byte scrap_texels[MAX_SCRAPS][BLOCK_WIDTH*BLOCK_HEIGHT*4]; ! 116: qboolean scrap_dirty; ! 117: int scrap_texnum; ! 118: ! 119: // returns a texture number and the position inside it ! 120: int Scrap_AllocBlock (int w, int h, int *x, int *y) ! 121: { ! 122: int i, j; ! 123: int best, best2; ! 124: int texnum; ! 125: ! 126: for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++) ! 127: { ! 128: best = BLOCK_HEIGHT; ! 129: ! 130: for (i=0 ; i<BLOCK_WIDTH-w ; i++) ! 131: { ! 132: best2 = 0; ! 133: ! 134: for (j=0 ; j<w ; j++) ! 135: { ! 136: if (scrap_allocated[texnum][i+j] >= best) ! 137: break; ! 138: if (scrap_allocated[texnum][i+j] > best2) ! 139: best2 = scrap_allocated[texnum][i+j]; ! 140: } ! 141: if (j == w) ! 142: { // this is a valid spot ! 143: *x = i; ! 144: *y = best = best2; ! 145: } ! 146: } ! 147: ! 148: if (best + h > BLOCK_HEIGHT) ! 149: continue; ! 150: ! 151: for (i=0 ; i<w ; i++) ! 152: scrap_allocated[texnum][*x + i] = best + h; ! 153: ! 154: return texnum; ! 155: } ! 156: ! 157: Sys_Error ("Scrap_AllocBlock: full"); ! 158: return 0; ! 159: } ! 160: ! 161: int scrap_uploads; ! 162: ! 163: void Scrap_Upload (void) ! 164: { ! 165: scrap_uploads++; ! 166: GL_Bind(scrap_texnum); ! 167: GL_Upload8 (scrap_texels[0], BLOCK_WIDTH, BLOCK_HEIGHT, false, true); ! 168: scrap_dirty = false; ! 169: } ! 170: ! 171: //============================================================================= ! 172: /* Support Routines */ ! 173: ! 174: typedef struct cachepic_s ! 175: { ! 176: char name[MAX_QPATH]; ! 177: qpic_t pic; ! 178: byte padding[32]; // for appended glpic ! 179: } cachepic_t; ! 180: ! 181: #define MAX_CACHED_PICS 128 ! 182: cachepic_t menu_cachepics[MAX_CACHED_PICS]; ! 183: int menu_numcachepics; ! 184: ! 185: byte menuplyr_pixels[4096]; ! 186: ! 187: int pic_texels; ! 188: int pic_count; ! 189: ! 190: qpic_t *Draw_PicFromWad (char *name) ! 191: { ! 192: qpic_t *p; ! 193: glpic_t *gl; ! 194: ! 195: p = W_GetLumpName (name); ! 196: gl = (glpic_t *)p->data; ! 197: ! 198: // load little ones into the scrap ! 199: if (p->width < 64 && p->height < 64) ! 200: { ! 201: int x, y; ! 202: int i, j, k; ! 203: int texnum; ! 204: ! 205: texnum = Scrap_AllocBlock (p->width, p->height, &x, &y); ! 206: scrap_dirty = true; ! 207: k = 0; ! 208: for (i=0 ; i<p->height ; i++) ! 209: for (j=0 ; j<p->width ; j++, k++) ! 210: scrap_texels[texnum][(y+i)*BLOCK_WIDTH + x + j] = p->data[k]; ! 211: texnum += scrap_texnum; ! 212: gl->texnum = texnum; ! 213: gl->sl = (x+0.01)/(float)BLOCK_WIDTH; ! 214: gl->sh = (x+p->width-0.01)/(float)BLOCK_WIDTH; ! 215: gl->tl = (y+0.01)/(float)BLOCK_WIDTH; ! 216: gl->th = (y+p->height-0.01)/(float)BLOCK_WIDTH; ! 217: ! 218: pic_count++; ! 219: pic_texels += p->width*p->height; ! 220: } ! 221: else ! 222: { ! 223: gl->texnum = GL_LoadPicTexture (p); ! 224: gl->sl = 0; ! 225: gl->sh = 1; ! 226: gl->tl = 0; ! 227: gl->th = 1; ! 228: } ! 229: return p; ! 230: } ! 231: ! 232: ! 233: /* ! 234: ================ ! 235: Draw_CachePic ! 236: ================ ! 237: */ ! 238: qpic_t *Draw_CachePic (char *path) ! 239: { ! 240: cachepic_t *pic; ! 241: int i; ! 242: qpic_t *dat; ! 243: glpic_t *gl; ! 244: ! 245: for (pic=menu_cachepics, i=0 ; i<menu_numcachepics ; pic++, i++) ! 246: if (!strcmp (path, pic->name)) ! 247: return &pic->pic; ! 248: ! 249: if (menu_numcachepics == MAX_CACHED_PICS) ! 250: Sys_Error ("menu_numcachepics == MAX_CACHED_PICS"); ! 251: menu_numcachepics++; ! 252: strcpy (pic->name, path); ! 253: ! 254: // ! 255: // load the pic from disk ! 256: // ! 257: dat = (qpic_t *)COM_LoadTempFile (path); ! 258: if (!dat) ! 259: Sys_Error ("Draw_CachePic: failed to load %s", path); ! 260: SwapPic (dat); ! 261: ! 262: // HACK HACK HACK --- we need to keep the bytes for ! 263: // the translatable player picture just for the menu ! 264: // configuration dialog ! 265: if (!strcmp (path, "gfx/menuplyr.lmp")) ! 266: memcpy (menuplyr_pixels, dat->data, dat->width*dat->height); ! 267: ! 268: pic->pic.width = dat->width; ! 269: pic->pic.height = dat->height; ! 270: ! 271: gl = (glpic_t *)pic->pic.data; ! 272: gl->texnum = GL_LoadPicTexture (dat); ! 273: gl->sl = 0; ! 274: gl->sh = 1; ! 275: gl->tl = 0; ! 276: gl->th = 1; ! 277: ! 278: return &pic->pic; ! 279: } ! 280: ! 281: ! 282: void Draw_CharToConback (int num, byte *dest) ! 283: { ! 284: int row, col; ! 285: byte *source; ! 286: int drawline; ! 287: int x; ! 288: ! 289: row = num>>4; ! 290: col = num&15; ! 291: source = draw_chars + (row<<10) + (col<<3); ! 292: ! 293: drawline = 8; ! 294: ! 295: while (drawline--) ! 296: { ! 297: for (x=0 ; x<8 ; x++) ! 298: if (source[x] != 255) ! 299: dest[x] = 0x60 + source[x]; ! 300: source += 128; ! 301: dest += 320; ! 302: } ! 303: ! 304: } ! 305: ! 306: typedef struct ! 307: { ! 308: char *name; ! 309: int minimize, maximize; ! 310: } glmode_t; ! 311: ! 312: glmode_t modes[] = { ! 313: {"GL_NEAREST", GL_NEAREST, GL_NEAREST}, ! 314: {"GL_LINEAR", GL_LINEAR, GL_LINEAR}, ! 315: {"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST}, ! 316: {"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR}, ! 317: {"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST}, ! 318: {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR} ! 319: }; ! 320: ! 321: /* ! 322: =============== ! 323: Draw_TextureMode_f ! 324: =============== ! 325: */ ! 326: void Draw_TextureMode_f (void) ! 327: { ! 328: int i; ! 329: gltexture_t *glt; ! 330: ! 331: if (Cmd_Argc() == 1) ! 332: { ! 333: for (i=0 ; i< 6 ; i++) ! 334: if (gl_filter_min == modes[i].minimize) ! 335: { ! 336: Con_Printf ("%s\n", modes[i].name); ! 337: return; ! 338: } ! 339: Con_Printf ("current filter is unknown???\n"); ! 340: return; ! 341: } ! 342: ! 343: for (i=0 ; i< 6 ; i++) ! 344: { ! 345: if (!Q_strcasecmp (modes[i].name, Cmd_Argv(1) ) ) ! 346: break; ! 347: } ! 348: if (i == 6) ! 349: { ! 350: Con_Printf ("bad filter name\n"); ! 351: return; ! 352: } ! 353: ! 354: gl_filter_min = modes[i].minimize; ! 355: gl_filter_max = modes[i].maximize; ! 356: ! 357: // change all the existing mipmap texture objects ! 358: for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++) ! 359: { ! 360: if (glt->mipmap) ! 361: { ! 362: GL_Bind (glt->texnum); ! 363: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); ! 364: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); ! 365: } ! 366: } ! 367: } ! 368: ! 369: /* ! 370: =============== ! 371: Draw_Init ! 372: =============== ! 373: */ ! 374: void Draw_Init (void) ! 375: { ! 376: int i; ! 377: qpic_t *cb; ! 378: byte *dest; ! 379: int x; ! 380: char ver[40]; ! 381: glpic_t *gl; ! 382: int start; ! 383: byte *ncdata; ! 384: ! 385: Cvar_RegisterVariable (&gl_nobind); ! 386: Cvar_RegisterVariable (&gl_max_size); ! 387: Cvar_RegisterVariable (&gl_picmip); ! 388: ! 389: // 3dfx can only handle 256 wide textures ! 390: if (!Q_strncasecmp ((char *)gl_renderer, "3dfx",4) || ! 391: !Q_strncasecmp ((char *)gl_renderer, "Mesa",4)) ! 392: Cvar_Set ("gl_max_size", "256"); ! 393: ! 394: Cmd_AddCommand ("gl_texturemode", &Draw_TextureMode_f); ! 395: ! 396: // load the console background and the charset ! 397: // by hand, because we need to write the version ! 398: // string into the background before turning ! 399: // it into a texture ! 400: draw_chars = W_GetLumpName ("conchars"); ! 401: for (i=0 ; i<256*64 ; i++) ! 402: if (draw_chars[i] == 0) ! 403: draw_chars[i] = 255; // proper transparent color ! 404: ! 405: // now turn them into textures ! 406: char_texture = GL_LoadTexture ("charset", 128, 128, draw_chars, false, true); ! 407: // Draw_CrosshairAdjust(); ! 408: cs_texture = GL_LoadTexture ("crosshair", 8, 8, cs_data, false, true); ! 409: ! 410: start = Hunk_LowMark (); ! 411: ! 412: cb = (qpic_t *)COM_LoadHunkFile ("gfx/conback.lmp"); ! 413: if (!cb) ! 414: Sys_Error ("Couldn't load gfx/conback.lmp"); ! 415: SwapPic (cb); ! 416: ! 417: sprintf (ver, "%4.2f", VERSION); ! 418: dest = cb->data + 320 + 320*186 - 11 - 8*strlen(ver); ! 419: for (x=0 ; x<strlen(ver) ; x++) ! 420: Draw_CharToConback (ver[x], dest+(x<<3)); ! 421: ! 422: #if 0 ! 423: conback->width = vid.conwidth; ! 424: conback->height = vid.conheight; ! 425: ! 426: // scale console to vid size ! 427: dest = ncdata = Hunk_AllocName(vid.conwidth * vid.conheight, "conback"); ! 428: ! 429: for (y=0 ; y<vid.conheight ; y++, dest += vid.conwidth) ! 430: { ! 431: src = cb->data + cb->width * (y*cb->height/vid.conheight); ! 432: if (vid.conwidth == cb->width) ! 433: memcpy (dest, src, vid.conwidth); ! 434: else ! 435: { ! 436: f = 0; ! 437: fstep = cb->width*0x10000/vid.conwidth; ! 438: for (x=0 ; x<vid.conwidth ; x+=4) ! 439: { ! 440: dest[x] = src[f>>16]; ! 441: f += fstep; ! 442: dest[x+1] = src[f>>16]; ! 443: f += fstep; ! 444: dest[x+2] = src[f>>16]; ! 445: f += fstep; ! 446: dest[x+3] = src[f>>16]; ! 447: f += fstep; ! 448: } ! 449: } ! 450: } ! 451: #else ! 452: conback->width = cb->width; ! 453: conback->height = cb->height; ! 454: ncdata = cb->data; ! 455: #endif ! 456: ! 457: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); ! 458: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); ! 459: ! 460: gl = (glpic_t *)conback->data; ! 461: gl->texnum = GL_LoadTexture ("conback", conback->width, conback->height, ncdata, false, false); ! 462: gl->sl = 0; ! 463: gl->sh = 1; ! 464: gl->tl = 0; ! 465: gl->th = 1; ! 466: conback->width = vid.conwidth; ! 467: conback->height = vid.conheight; ! 468: ! 469: // free loaded console ! 470: Hunk_FreeToLowMark (start); ! 471: ! 472: // save a texture slot for translated picture ! 473: translate_texture = texture_extension_number++; ! 474: ! 475: // save slots for scraps ! 476: scrap_texnum = texture_extension_number; ! 477: texture_extension_number += MAX_SCRAPS; ! 478: ! 479: // ! 480: // get the other pics we need ! 481: // ! 482: draw_disc = Draw_PicFromWad ("disc"); ! 483: draw_backtile = Draw_PicFromWad ("backtile"); ! 484: } ! 485: ! 486: ! 487: ! 488: /* ! 489: ================ ! 490: Draw_Character ! 491: ! 492: Draws one 8*8 graphics character with 0 being transparent. ! 493: It can be clipped to the top of the screen to allow the console to be ! 494: smoothly scrolled off. ! 495: ================ ! 496: */ ! 497: void Draw_Character (int x, int y, int num) ! 498: { ! 499: int row, col; ! 500: float frow, fcol, size; ! 501: ! 502: if (num == 32) ! 503: return; // space ! 504: ! 505: num &= 255; ! 506: ! 507: if (y <= -8) ! 508: return; // totally off screen ! 509: ! 510: row = num>>4; ! 511: col = num&15; ! 512: ! 513: frow = row*0.0625; ! 514: fcol = col*0.0625; ! 515: size = 0.0625; ! 516: ! 517: GL_Bind (char_texture); ! 518: ! 519: glBegin (GL_QUADS); ! 520: glTexCoord2f (fcol, frow); ! 521: glVertex2f (x, y); ! 522: glTexCoord2f (fcol + size, frow); ! 523: glVertex2f (x+8, y); ! 524: glTexCoord2f (fcol + size, frow + size); ! 525: glVertex2f (x+8, y+8); ! 526: glTexCoord2f (fcol, frow + size); ! 527: glVertex2f (x, y+8); ! 528: glEnd (); ! 529: } ! 530: ! 531: /* ! 532: ================ ! 533: Draw_String ! 534: ================ ! 535: */ ! 536: void Draw_String (int x, int y, char *str) ! 537: { ! 538: while (*str) ! 539: { ! 540: Draw_Character (x, y, *str); ! 541: str++; ! 542: x += 8; ! 543: } ! 544: } ! 545: ! 546: /* ! 547: ================ ! 548: Draw_Alt_String ! 549: ================ ! 550: */ ! 551: void Draw_Alt_String (int x, int y, char *str) ! 552: { ! 553: while (*str) ! 554: { ! 555: Draw_Character (x, y, (*str) | 0x80); ! 556: str++; ! 557: x += 8; ! 558: } ! 559: } ! 560: ! 561: void Draw_Crosshair(void) ! 562: { ! 563: int x, y; ! 564: extern vrect_t scr_vrect; ! 565: unsigned char *pColor; ! 566: ! 567: if (crosshair.value == 2) { ! 568: x = scr_vrect.x + scr_vrect.width/2 - 3 + cl_crossx.value; ! 569: y = scr_vrect.y + scr_vrect.height/2 - 3 + cl_crossy.value; ! 570: ! 571: glTexEnvf ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); ! 572: pColor = (unsigned char *) &d_8to24table[(byte) crosshaircolor.value]; ! 573: glColor4ubv ( pColor ); ! 574: GL_Bind (cs_texture); ! 575: ! 576: glBegin (GL_QUADS); ! 577: glTexCoord2f (0, 0); ! 578: glVertex2f (x - 4, y - 4); ! 579: glTexCoord2f (1, 0); ! 580: glVertex2f (x+12, y-4); ! 581: glTexCoord2f (1, 1); ! 582: glVertex2f (x+12, y+12); ! 583: glTexCoord2f (0, 1); ! 584: glVertex2f (x - 4, y+12); ! 585: glEnd (); ! 586: ! 587: glTexEnvf ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); ! 588: } else if (crosshair.value) ! 589: Draw_Character (scr_vrect.x + scr_vrect.width/2-4 + cl_crossx.value, ! 590: scr_vrect.y + scr_vrect.height/2-4 + cl_crossy.value, ! 591: '+'); ! 592: } ! 593: ! 594: ! 595: /* ! 596: ================ ! 597: Draw_DebugChar ! 598: ! 599: Draws a single character directly to the upper right corner of the screen. ! 600: This is for debugging lockups by drawing different chars in different parts ! 601: of the code. ! 602: ================ ! 603: */ ! 604: void Draw_DebugChar (char num) ! 605: { ! 606: } ! 607: ! 608: /* ! 609: ============= ! 610: Draw_Pic ! 611: ============= ! 612: */ ! 613: void Draw_Pic (int x, int y, qpic_t *pic) ! 614: { ! 615: glpic_t *gl; ! 616: ! 617: if (scrap_dirty) ! 618: Scrap_Upload (); ! 619: gl = (glpic_t *)pic->data; ! 620: glColor4f (1,1,1,1); ! 621: GL_Bind (gl->texnum); ! 622: glBegin (GL_QUADS); ! 623: glTexCoord2f (gl->sl, gl->tl); ! 624: glVertex2f (x, y); ! 625: glTexCoord2f (gl->sh, gl->tl); ! 626: glVertex2f (x+pic->width, y); ! 627: glTexCoord2f (gl->sh, gl->th); ! 628: glVertex2f (x+pic->width, y+pic->height); ! 629: glTexCoord2f (gl->sl, gl->th); ! 630: glVertex2f (x, y+pic->height); ! 631: glEnd (); ! 632: } ! 633: ! 634: /* ! 635: ============= ! 636: Draw_AlphaPic ! 637: ============= ! 638: */ ! 639: void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha) ! 640: { ! 641: glpic_t *gl; ! 642: ! 643: if (scrap_dirty) ! 644: Scrap_Upload (); ! 645: gl = (glpic_t *)pic->data; ! 646: glDisable(GL_ALPHA_TEST); ! 647: glEnable (GL_BLEND); ! 648: // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); ! 649: glCullFace(GL_FRONT); ! 650: glColor4f (1,1,1,alpha); ! 651: GL_Bind (gl->texnum); ! 652: glBegin (GL_QUADS); ! 653: glTexCoord2f (gl->sl, gl->tl); ! 654: glVertex2f (x, y); ! 655: glTexCoord2f (gl->sh, gl->tl); ! 656: glVertex2f (x+pic->width, y); ! 657: glTexCoord2f (gl->sh, gl->th); ! 658: glVertex2f (x+pic->width, y+pic->height); ! 659: glTexCoord2f (gl->sl, gl->th); ! 660: glVertex2f (x, y+pic->height); ! 661: glEnd (); ! 662: glColor4f (1,1,1,1); ! 663: glEnable(GL_ALPHA_TEST); ! 664: glDisable (GL_BLEND); ! 665: } ! 666: ! 667: void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height) ! 668: { ! 669: glpic_t *gl; ! 670: float newsl, newtl, newsh, newth; ! 671: float oldglwidth, oldglheight; ! 672: ! 673: if (scrap_dirty) ! 674: Scrap_Upload (); ! 675: gl = (glpic_t *)pic->data; ! 676: ! 677: oldglwidth = gl->sh - gl->sl; ! 678: oldglheight = gl->th - gl->tl; ! 679: ! 680: newsl = gl->sl + (srcx*oldglwidth)/pic->width; ! 681: newsh = newsl + (width*oldglwidth)/pic->width; ! 682: ! 683: newtl = gl->tl + (srcy*oldglheight)/pic->height; ! 684: newth = newtl + (height*oldglheight)/pic->height; ! 685: ! 686: glColor4f (1,1,1,1); ! 687: GL_Bind (gl->texnum); ! 688: glBegin (GL_QUADS); ! 689: glTexCoord2f (newsl, newtl); ! 690: glVertex2f (x, y); ! 691: glTexCoord2f (newsh, newtl); ! 692: glVertex2f (x+width, y); ! 693: glTexCoord2f (newsh, newth); ! 694: glVertex2f (x+width, y+height); ! 695: glTexCoord2f (newsl, newth); ! 696: glVertex2f (x, y+height); ! 697: glEnd (); ! 698: } ! 699: ! 700: /* ! 701: ============= ! 702: Draw_TransPic ! 703: ============= ! 704: */ ! 705: void Draw_TransPic (int x, int y, qpic_t *pic) ! 706: { ! 707: ! 708: if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 || ! 709: (unsigned)(y + pic->height) > vid.height) ! 710: { ! 711: Sys_Error ("Draw_TransPic: bad coordinates"); ! 712: } ! 713: ! 714: Draw_Pic (x, y, pic); ! 715: } ! 716: ! 717: ! 718: /* ! 719: ============= ! 720: Draw_TransPicTranslate ! 721: ! 722: Only used for the player color selection menu ! 723: ============= ! 724: */ ! 725: void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation) ! 726: { ! 727: int v, u, c; ! 728: unsigned trans[64*64], *dest; ! 729: byte *src; ! 730: int p; ! 731: ! 732: GL_Bind (translate_texture); ! 733: ! 734: c = pic->width * pic->height; ! 735: ! 736: dest = trans; ! 737: for (v=0 ; v<64 ; v++, dest += 64) ! 738: { ! 739: src = &menuplyr_pixels[ ((v*pic->height)>>6) *pic->width]; ! 740: for (u=0 ; u<64 ; u++) ! 741: { ! 742: p = src[(u*pic->width)>>6]; ! 743: if (p == 255) ! 744: dest[u] = p; ! 745: else ! 746: dest[u] = d_8to24table[translation[p]]; ! 747: } ! 748: } ! 749: ! 750: glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans); ! 751: ! 752: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); ! 753: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); ! 754: ! 755: glColor3f (1,1,1); ! 756: glBegin (GL_QUADS); ! 757: glTexCoord2f (0, 0); ! 758: glVertex2f (x, y); ! 759: glTexCoord2f (1, 0); ! 760: glVertex2f (x+pic->width, y); ! 761: glTexCoord2f (1, 1); ! 762: glVertex2f (x+pic->width, y+pic->height); ! 763: glTexCoord2f (0, 1); ! 764: glVertex2f (x, y+pic->height); ! 765: glEnd (); ! 766: } ! 767: ! 768: ! 769: /* ! 770: ================ ! 771: Draw_ConsoleBackground ! 772: ! 773: ================ ! 774: */ ! 775: void Draw_ConsoleBackground (int lines) ! 776: { ! 777: char ver[80]; ! 778: int x, i; ! 779: int y; ! 780: ! 781: y = (vid.height * 3) >> 2; ! 782: if (lines > y) ! 783: Draw_Pic(0, lines-vid.height, conback); ! 784: else ! 785: Draw_AlphaPic (0, lines - vid.height, conback, (float)(1.2 * lines)/y); ! 786: ! 787: // hack the version number directly into the pic ! 788: // y = lines-186; ! 789: y = lines-14; ! 790: if (!cls.download) { ! 791: #ifdef __linux__ ! 792: sprintf (ver, "LinuxGL (%4.2f) QuakeWorld", LINUX_VERSION); ! 793: #else ! 794: sprintf (ver, "GL (%4.2f) QuakeWorld", GLQUAKE_VERSION); ! 795: #endif ! 796: x = vid.conwidth - (strlen(ver)*8 + 11) - (vid.conwidth*8/320)*7; ! 797: for (i=0 ; i<strlen(ver) ; i++) ! 798: Draw_Character (x + i * 8, y, ver[i] | 0x80); ! 799: } ! 800: } ! 801: ! 802: ! 803: /* ! 804: ============= ! 805: Draw_TileClear ! 806: ! 807: This repeats a 64*64 tile graphic to fill the screen around a sized down ! 808: refresh window. ! 809: ============= ! 810: */ ! 811: void Draw_TileClear (int x, int y, int w, int h) ! 812: { ! 813: glColor3f (1,1,1); ! 814: GL_Bind (*(int *)draw_backtile->data); ! 815: glBegin (GL_QUADS); ! 816: glTexCoord2f (x/64.0, y/64.0); ! 817: glVertex2f (x, y); ! 818: glTexCoord2f ( (x+w)/64.0, y/64.0); ! 819: glVertex2f (x+w, y); ! 820: glTexCoord2f ( (x+w)/64.0, (y+h)/64.0); ! 821: glVertex2f (x+w, y+h); ! 822: glTexCoord2f ( x/64.0, (y+h)/64.0 ); ! 823: glVertex2f (x, y+h); ! 824: glEnd (); ! 825: } ! 826: ! 827: ! 828: /* ! 829: ============= ! 830: Draw_Fill ! 831: ! 832: Fills a box of pixels with a single color ! 833: ============= ! 834: */ ! 835: void Draw_Fill (int x, int y, int w, int h, int c) ! 836: { ! 837: glDisable (GL_TEXTURE_2D); ! 838: glColor3f (host_basepal[c*3]/255.0, ! 839: host_basepal[c*3+1]/255.0, ! 840: host_basepal[c*3+2]/255.0); ! 841: ! 842: glBegin (GL_QUADS); ! 843: ! 844: glVertex2f (x,y); ! 845: glVertex2f (x+w, y); ! 846: glVertex2f (x+w, y+h); ! 847: glVertex2f (x, y+h); ! 848: ! 849: glEnd (); ! 850: glColor3f (1,1,1); ! 851: glEnable (GL_TEXTURE_2D); ! 852: } ! 853: //============================================================================= ! 854: ! 855: /* ! 856: ================ ! 857: Draw_FadeScreen ! 858: ! 859: ================ ! 860: */ ! 861: void Draw_FadeScreen (void) ! 862: { ! 863: glEnable (GL_BLEND); ! 864: glDisable (GL_TEXTURE_2D); ! 865: glColor4f (0, 0, 0, 0.8); ! 866: glBegin (GL_QUADS); ! 867: ! 868: glVertex2f (0,0); ! 869: glVertex2f (vid.width, 0); ! 870: glVertex2f (vid.width, vid.height); ! 871: glVertex2f (0, vid.height); ! 872: ! 873: glEnd (); ! 874: glColor4f (1,1,1,1); ! 875: glEnable (GL_TEXTURE_2D); ! 876: glDisable (GL_BLEND); ! 877: ! 878: Sbar_Changed(); ! 879: } ! 880: ! 881: //============================================================================= ! 882: ! 883: /* ! 884: ================ ! 885: Draw_BeginDisc ! 886: ! 887: Draws the little blue disc in the corner of the screen. ! 888: Call before beginning any disc IO. ! 889: ================ ! 890: */ ! 891: void Draw_BeginDisc (void) ! 892: { ! 893: if (!draw_disc) ! 894: return; ! 895: glDrawBuffer (GL_FRONT); ! 896: Draw_Pic (vid.width - 24, 0, draw_disc); ! 897: glDrawBuffer (GL_BACK); ! 898: } ! 899: ! 900: ! 901: /* ! 902: ================ ! 903: Draw_EndDisc ! 904: ! 905: Erases the disc icon. ! 906: Call after completing any disc IO ! 907: ================ ! 908: */ ! 909: void Draw_EndDisc (void) ! 910: { ! 911: } ! 912: ! 913: /* ! 914: ================ ! 915: GL_Set2D ! 916: ! 917: Setup as if the screen was 320*200 ! 918: ================ ! 919: */ ! 920: void GL_Set2D (void) ! 921: { ! 922: glViewport (glx, gly, glwidth, glheight); ! 923: ! 924: glMatrixMode(GL_PROJECTION); ! 925: glLoadIdentity (); ! 926: glOrtho (0, vid.width, vid.height, 0, -99999, 99999); ! 927: ! 928: glMatrixMode(GL_MODELVIEW); ! 929: glLoadIdentity (); ! 930: ! 931: glDisable (GL_DEPTH_TEST); ! 932: glDisable (GL_CULL_FACE); ! 933: glDisable (GL_BLEND); ! 934: glEnable (GL_ALPHA_TEST); ! 935: // glDisable (GL_ALPHA_TEST); ! 936: ! 937: glColor4f (1,1,1,1); ! 938: } ! 939: ! 940: //==================================================================== ! 941: ! 942: /* ! 943: ================ ! 944: GL_FindTexture ! 945: ================ ! 946: */ ! 947: int GL_FindTexture (char *identifier) ! 948: { ! 949: int i; ! 950: gltexture_t *glt; ! 951: ! 952: for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++) ! 953: { ! 954: if (!strcmp (identifier, glt->identifier)) ! 955: return gltextures[i].texnum; ! 956: } ! 957: ! 958: return -1; ! 959: } ! 960: ! 961: /* ! 962: ================ ! 963: GL_ResampleTexture ! 964: ================ ! 965: */ ! 966: void GL_ResampleTexture (unsigned *in, int inwidth, int inheight, unsigned *out, int outwidth, int outheight) ! 967: { ! 968: int i, j; ! 969: unsigned *inrow; ! 970: unsigned frac, fracstep; ! 971: ! 972: fracstep = inwidth*0x10000/outwidth; ! 973: for (i=0 ; i<outheight ; i++, out += outwidth) ! 974: { ! 975: inrow = in + inwidth*(i*inheight/outheight); ! 976: frac = fracstep >> 1; ! 977: for (j=0 ; j<outwidth ; j+=4) ! 978: { ! 979: out[j] = inrow[frac>>16]; ! 980: frac += fracstep; ! 981: out[j+1] = inrow[frac>>16]; ! 982: frac += fracstep; ! 983: out[j+2] = inrow[frac>>16]; ! 984: frac += fracstep; ! 985: out[j+3] = inrow[frac>>16]; ! 986: frac += fracstep; ! 987: } ! 988: } ! 989: } ! 990: ! 991: /* ! 992: ================ ! 993: GL_Resample8BitTexture -- JACK ! 994: ================ ! 995: */ ! 996: void GL_Resample8BitTexture (unsigned char *in, int inwidth, int inheight, unsigned char *out, int outwidth, int outheight) ! 997: { ! 998: int i, j; ! 999: unsigned char *inrow; ! 1000: unsigned frac, fracstep; ! 1001: ! 1002: fracstep = inwidth*0x10000/outwidth; ! 1003: for (i=0 ; i<outheight ; i++, out += outwidth) ! 1004: { ! 1005: inrow = in + inwidth*(i*inheight/outheight); ! 1006: frac = fracstep >> 1; ! 1007: for (j=0 ; j<outwidth ; j+=4) ! 1008: { ! 1009: out[j] = inrow[frac>>16]; ! 1010: frac += fracstep; ! 1011: out[j+1] = inrow[frac>>16]; ! 1012: frac += fracstep; ! 1013: out[j+2] = inrow[frac>>16]; ! 1014: frac += fracstep; ! 1015: out[j+3] = inrow[frac>>16]; ! 1016: frac += fracstep; ! 1017: } ! 1018: } ! 1019: } ! 1020: ! 1021: /* ! 1022: ================ ! 1023: GL_MipMap ! 1024: ! 1025: Operates in place, quartering the size of the texture ! 1026: ================ ! 1027: */ ! 1028: void GL_MipMap (byte *in, int width, int height) ! 1029: { ! 1030: int i, j; ! 1031: byte *out; ! 1032: ! 1033: width <<=2; ! 1034: height >>= 1; ! 1035: out = in; ! 1036: for (i=0 ; i<height ; i++, in+=width) ! 1037: { ! 1038: for (j=0 ; j<width ; j+=8, out+=4, in+=8) ! 1039: { ! 1040: out[0] = (in[0] + in[4] + in[width+0] + in[width+4])>>2; ! 1041: out[1] = (in[1] + in[5] + in[width+1] + in[width+5])>>2; ! 1042: out[2] = (in[2] + in[6] + in[width+2] + in[width+6])>>2; ! 1043: out[3] = (in[3] + in[7] + in[width+3] + in[width+7])>>2; ! 1044: } ! 1045: } ! 1046: } ! 1047: ! 1048: /* ! 1049: ================ ! 1050: GL_MipMap8Bit ! 1051: ! 1052: Mipping for 8 bit textures ! 1053: ================ ! 1054: */ ! 1055: void GL_MipMap8Bit (byte *in, int width, int height) ! 1056: { ! 1057: int i, j; ! 1058: byte *out; ! 1059: unsigned short r,g,b; ! 1060: byte *at1, *at2, *at3, *at4; ! 1061: ! 1062: height >>= 1; ! 1063: out = in; ! 1064: for (i=0 ; i<height ; i++, in+=width) ! 1065: for (j=0 ; j<width ; j+=2, out+=1, in+=2) ! 1066: { ! 1067: at1 = (byte *) &d_8to24table[in[0]]; ! 1068: at2 = (byte *) &d_8to24table[in[1]]; ! 1069: at3 = (byte *) &d_8to24table[in[width+0]]; ! 1070: at4 = (byte *) &d_8to24table[in[width+1]]; ! 1071: ! 1072: r = (at1[0]+at2[0]+at3[0]+at4[0]); r>>=5; ! 1073: g = (at1[1]+at2[1]+at3[1]+at4[1]); g>>=5; ! 1074: b = (at1[2]+at2[2]+at3[2]+at4[2]); b>>=5; ! 1075: ! 1076: out[0] = d_15to8table[(r<<0) + (g<<5) + (b<<10)]; ! 1077: } ! 1078: } ! 1079: ! 1080: /* ! 1081: =============== ! 1082: GL_Upload32 ! 1083: =============== ! 1084: */ ! 1085: void GL_Upload32 (unsigned *data, int width, int height, qboolean mipmap, qboolean alpha) ! 1086: { ! 1087: int samples; ! 1088: static unsigned scaled[1024*512]; // [512*256]; ! 1089: int scaled_width, scaled_height; ! 1090: ! 1091: for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1) ! 1092: ; ! 1093: for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1) ! 1094: ; ! 1095: ! 1096: scaled_width >>= (int)gl_picmip.value; ! 1097: scaled_height >>= (int)gl_picmip.value; ! 1098: ! 1099: if (scaled_width > gl_max_size.value) ! 1100: scaled_width = gl_max_size.value; ! 1101: if (scaled_height > gl_max_size.value) ! 1102: scaled_height = gl_max_size.value; ! 1103: ! 1104: if (scaled_width * scaled_height > sizeof(scaled)/4) ! 1105: Sys_Error ("GL_LoadTexture: too big"); ! 1106: ! 1107: samples = alpha ? gl_alpha_format : gl_solid_format; ! 1108: ! 1109: #if 0 ! 1110: if (mipmap) ! 1111: gluBuild2DMipmaps (GL_TEXTURE_2D, samples, width, height, GL_RGBA, GL_UNSIGNED_BYTE, trans); ! 1112: else if (scaled_width == width && scaled_height == height) ! 1113: glTexImage2D (GL_TEXTURE_2D, 0, samples, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans); ! 1114: else ! 1115: { ! 1116: gluScaleImage (GL_RGBA, width, height, GL_UNSIGNED_BYTE, trans, ! 1117: scaled_width, scaled_height, GL_UNSIGNED_BYTE, scaled); ! 1118: glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled); ! 1119: } ! 1120: #else ! 1121: texels += scaled_width * scaled_height; ! 1122: ! 1123: if (scaled_width == width && scaled_height == height) ! 1124: { ! 1125: if (!mipmap) ! 1126: { ! 1127: glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); ! 1128: goto done; ! 1129: } ! 1130: memcpy (scaled, data, width*height*4); ! 1131: } ! 1132: else ! 1133: GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height); ! 1134: ! 1135: glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled); ! 1136: if (mipmap) ! 1137: { ! 1138: int miplevel; ! 1139: ! 1140: miplevel = 0; ! 1141: while (scaled_width > 1 || scaled_height > 1) ! 1142: { ! 1143: GL_MipMap ((byte *)scaled, scaled_width, scaled_height); ! 1144: scaled_width >>= 1; ! 1145: scaled_height >>= 1; ! 1146: if (scaled_width < 1) ! 1147: scaled_width = 1; ! 1148: if (scaled_height < 1) ! 1149: scaled_height = 1; ! 1150: miplevel++; ! 1151: glTexImage2D (GL_TEXTURE_2D, miplevel, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled); ! 1152: } ! 1153: } ! 1154: done: ; ! 1155: #endif ! 1156: ! 1157: ! 1158: if (mipmap) ! 1159: { ! 1160: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); ! 1161: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); ! 1162: } ! 1163: else ! 1164: { ! 1165: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max); ! 1166: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); ! 1167: } ! 1168: } ! 1169: ! 1170: void GL_Upload8_EXT (byte *data, int width, int height, qboolean mipmap, qboolean alpha) ! 1171: { ! 1172: int i, s; ! 1173: qboolean noalpha; ! 1174: int samples; ! 1175: static unsigned char scaled[1024*512]; // [512*256]; ! 1176: int scaled_width, scaled_height; ! 1177: ! 1178: s = width*height; ! 1179: // if there are no transparent pixels, make it a 3 component ! 1180: // texture even if it was specified as otherwise ! 1181: if (alpha) ! 1182: { ! 1183: noalpha = true; ! 1184: for (i=0 ; i<s ; i++) ! 1185: { ! 1186: if (data[i] == 255) ! 1187: noalpha = false; ! 1188: } ! 1189: ! 1190: if (alpha && noalpha) ! 1191: alpha = false; ! 1192: } ! 1193: for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1) ! 1194: ; ! 1195: for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1) ! 1196: ; ! 1197: ! 1198: scaled_width >>= (int)gl_picmip.value; ! 1199: scaled_height >>= (int)gl_picmip.value; ! 1200: ! 1201: if (scaled_width > gl_max_size.value) ! 1202: scaled_width = gl_max_size.value; ! 1203: if (scaled_height > gl_max_size.value) ! 1204: scaled_height = gl_max_size.value; ! 1205: ! 1206: if (scaled_width * scaled_height > sizeof(scaled)) ! 1207: Sys_Error ("GL_LoadTexture: too big"); ! 1208: ! 1209: samples = 1; // alpha ? gl_alpha_format : gl_solid_format; ! 1210: ! 1211: texels += scaled_width * scaled_height; ! 1212: ! 1213: if (scaled_width == width && scaled_height == height) ! 1214: { ! 1215: if (!mipmap) ! 1216: { ! 1217: glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX , GL_UNSIGNED_BYTE, data); ! 1218: goto done; ! 1219: } ! 1220: memcpy (scaled, data, width*height); ! 1221: } ! 1222: else ! 1223: GL_Resample8BitTexture (data, width, height, scaled, scaled_width, scaled_height); ! 1224: ! 1225: glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled); ! 1226: if (mipmap) ! 1227: { ! 1228: int miplevel; ! 1229: ! 1230: miplevel = 0; ! 1231: while (scaled_width > 1 || scaled_height > 1) ! 1232: { ! 1233: GL_MipMap8Bit ((byte *)scaled, scaled_width, scaled_height); ! 1234: scaled_width >>= 1; ! 1235: scaled_height >>= 1; ! 1236: if (scaled_width < 1) ! 1237: scaled_width = 1; ! 1238: if (scaled_height < 1) ! 1239: scaled_height = 1; ! 1240: miplevel++; ! 1241: glTexImage2D (GL_TEXTURE_2D, miplevel, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled); ! 1242: } ! 1243: } ! 1244: done: ; ! 1245: ! 1246: if (mipmap) ! 1247: { ! 1248: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); ! 1249: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); ! 1250: } ! 1251: else ! 1252: { ! 1253: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max); ! 1254: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); ! 1255: } ! 1256: } ! 1257: ! 1258: extern qboolean VID_Is8bit(); ! 1259: ! 1260: /* ! 1261: =============== ! 1262: GL_Upload8 ! 1263: =============== ! 1264: */ ! 1265: void GL_Upload8 (byte *data, int width, int height, qboolean mipmap, qboolean alpha) ! 1266: { ! 1267: static unsigned trans[640*480]; // FIXME, temporary ! 1268: int i, s; ! 1269: qboolean noalpha; ! 1270: int p; ! 1271: ! 1272: s = width*height; ! 1273: // if there are no transparent pixels, make it a 3 component ! 1274: // texture even if it was specified as otherwise ! 1275: if (alpha) ! 1276: { ! 1277: noalpha = true; ! 1278: for (i=0 ; i<s ; i++) ! 1279: { ! 1280: p = data[i]; ! 1281: if (p == 255) ! 1282: noalpha = false; ! 1283: trans[i] = d_8to24table[p]; ! 1284: } ! 1285: ! 1286: if (alpha && noalpha) ! 1287: alpha = false; ! 1288: } ! 1289: else ! 1290: { ! 1291: if (s&3) ! 1292: Sys_Error ("GL_Upload8: s&3"); ! 1293: for (i=0 ; i<s ; i+=4) ! 1294: { ! 1295: trans[i] = d_8to24table[data[i]]; ! 1296: trans[i+1] = d_8to24table[data[i+1]]; ! 1297: trans[i+2] = d_8to24table[data[i+2]]; ! 1298: trans[i+3] = d_8to24table[data[i+3]]; ! 1299: } ! 1300: } ! 1301: ! 1302: if (VID_Is8bit() && !alpha && (data!=scrap_texels[0])) { ! 1303: GL_Upload8_EXT (data, width, height, mipmap, alpha); ! 1304: return; ! 1305: } ! 1306: ! 1307: GL_Upload32 (trans, width, height, mipmap, alpha); ! 1308: } ! 1309: ! 1310: /* ! 1311: ================ ! 1312: GL_LoadTexture ! 1313: ================ ! 1314: */ ! 1315: int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha) ! 1316: { ! 1317: int i; ! 1318: gltexture_t *glt; ! 1319: ! 1320: // see if the texture is allready present ! 1321: if (identifier[0]) ! 1322: { ! 1323: for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++) ! 1324: { ! 1325: if (!strcmp (identifier, glt->identifier)) ! 1326: { ! 1327: if (width != glt->width || height != glt->height) ! 1328: Sys_Error ("GL_LoadTexture: cache mismatch"); ! 1329: return gltextures[i].texnum; ! 1330: } ! 1331: } ! 1332: } ! 1333: else ! 1334: glt = &gltextures[numgltextures]; ! 1335: numgltextures++; ! 1336: ! 1337: strcpy (glt->identifier, identifier); ! 1338: glt->texnum = texture_extension_number; ! 1339: glt->width = width; ! 1340: glt->height = height; ! 1341: glt->mipmap = mipmap; ! 1342: ! 1343: GL_Bind(texture_extension_number ); ! 1344: ! 1345: GL_Upload8 (data, width, height, mipmap, alpha); ! 1346: ! 1347: texture_extension_number++; ! 1348: ! 1349: return texture_extension_number-1; ! 1350: } ! 1351: ! 1352: /* ! 1353: ================ ! 1354: GL_LoadPicTexture ! 1355: ================ ! 1356: */ ! 1357: int GL_LoadPicTexture (qpic_t *pic) ! 1358: { ! 1359: return GL_LoadTexture ("", pic->width, pic->height, pic->data, false, true); ! 1360: } ! 1361: ! 1362: /****************************************/ ! 1363: ! 1364: static GLenum oldtarget = TEXTURE0_SGIS; ! 1365: ! 1366: void GL_SelectTexture (GLenum target) ! 1367: { ! 1368: if (!gl_mtexable) ! 1369: return; ! 1370: #ifndef __linux__ // no multitexture under Linux yet ! 1371: qglSelectTextureSGIS(target); ! 1372: #endif ! 1373: if (target == oldtarget) ! 1374: return; ! 1375: cnttextures[oldtarget-TEXTURE0_SGIS] = currenttexture; ! 1376: currenttexture = cnttextures[target-TEXTURE0_SGIS]; ! 1377: oldtarget = target; ! 1378: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.