|
|
1.1 ! root 1: ! 2: // draw.c -- this is the only file outside the refresh that touches the ! 3: // vid buffer ! 4: ! 5: #include "quakedef.h" ! 6: ! 7: cvar_t gl_nobind = {"gl_nobind", "0"}; ! 8: cvar_t gl_max_size = {"gl_max_size", "1024"}; ! 9: cvar_t gl_round_down = {"gl_round_down", "1"}; ! 10: cvar_t gl_picmip = {"gl_picmip", "0"}; ! 11: ! 12: byte *draw_chars; // 8*8 graphic characters ! 13: qpic_t *draw_disc; ! 14: qpic_t *draw_backtile; ! 15: ! 16: int translate_texture; ! 17: int char_texture; ! 18: ! 19: typedef struct ! 20: { ! 21: int texnum; ! 22: float sl, tl, sh, th; ! 23: } glpic_t; ! 24: ! 25: byte conback_buffer[sizeof(qpic_t) + sizeof(glpic_t)]; ! 26: qpic_t *conback = (qpic_t *)&conback_buffer; ! 27: ! 28: int gl_lightmap_format = 4; ! 29: int gl_solid_format = 3; ! 30: int gl_alpha_format = 4; ! 31: ! 32: int gl_filter_min = GL_LINEAR_MIPMAP_NEAREST; ! 33: int gl_filter_max = GL_LINEAR; ! 34: ! 35: ! 36: int texels; ! 37: ! 38: typedef struct ! 39: { ! 40: int texnum; ! 41: char identifier[64]; ! 42: int width, height; ! 43: qboolean mipmap; ! 44: } gltexture_t; ! 45: ! 46: #define MAX_GLTEXTURES 1024 ! 47: gltexture_t gltextures[MAX_GLTEXTURES]; ! 48: int numgltextures; ! 49: ! 50: ! 51: void GL_Bind (int texnum) ! 52: { ! 53: if (gl_nobind.value) ! 54: texnum = char_texture; ! 55: if (currenttexture == texnum) ! 56: return; ! 57: currenttexture = texnum; ! 58: bindTexFunc (GL_TEXTURE_2D, texnum); ! 59: } ! 60: ! 61: void GL_Texels_f (void) ! 62: { ! 63: Con_Printf ("Current uploaded texels: %i\n", texels); ! 64: } ! 65: ! 66: /* ! 67: ============================================================================= ! 68: ! 69: scrap allocation ! 70: ! 71: Allocate all the little status bar obejcts into a single texture ! 72: to crutch up stupid hardware / drivers ! 73: ! 74: ============================================================================= ! 75: */ ! 76: ! 77: #define MAX_SCRAPS 1 ! 78: #define BLOCK_WIDTH 256 ! 79: #define BLOCK_HEIGHT 256 ! 80: ! 81: int scrap_allocated[MAX_SCRAPS][BLOCK_WIDTH]; ! 82: byte scrap_texels[MAX_SCRAPS][BLOCK_WIDTH*BLOCK_HEIGHT*4]; ! 83: qboolean scrap_dirty; ! 84: int scrap_texnum; ! 85: ! 86: // returns a texture number and the position inside it ! 87: int Scrap_AllocBlock (int w, int h, int *x, int *y) ! 88: { ! 89: int i, j; ! 90: int best, best2; ! 91: int bestx; ! 92: int texnum; ! 93: ! 94: for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++) ! 95: { ! 96: best = BLOCK_HEIGHT; ! 97: ! 98: for (i=0 ; i<BLOCK_WIDTH-w ; i++) ! 99: { ! 100: best2 = 0; ! 101: ! 102: for (j=0 ; j<w ; j++) ! 103: { ! 104: if (scrap_allocated[texnum][i+j] >= best) ! 105: break; ! 106: if (scrap_allocated[texnum][i+j] > best2) ! 107: best2 = scrap_allocated[texnum][i+j]; ! 108: } ! 109: if (j == w) ! 110: { // this is a valid spot ! 111: *x = i; ! 112: *y = best = best2; ! 113: } ! 114: } ! 115: ! 116: if (best + h > BLOCK_HEIGHT) ! 117: continue; ! 118: ! 119: for (i=0 ; i<w ; i++) ! 120: scrap_allocated[texnum][*x + i] = best + h; ! 121: ! 122: return texnum; ! 123: } ! 124: ! 125: return -1; ! 126: // Sys_Error ("Scrap_AllocBlock: full"); ! 127: } ! 128: ! 129: int scrap_uploads; ! 130: ! 131: void Scrap_Upload (void) ! 132: { ! 133: scrap_uploads++; ! 134: GL_Bind(scrap_texnum); ! 135: GL_Upload8 (scrap_texels[0], BLOCK_WIDTH, BLOCK_HEIGHT, false, true); ! 136: scrap_dirty = false; ! 137: } ! 138: ! 139: //============================================================================= ! 140: /* Support Routines */ ! 141: ! 142: typedef struct cachepic_s ! 143: { ! 144: char name[MAX_QPATH]; ! 145: qpic_t pic; ! 146: byte padding[32]; // for appended glpic ! 147: } cachepic_t; ! 148: ! 149: #define MAX_CACHED_PICS 128 ! 150: cachepic_t menu_cachepics[MAX_CACHED_PICS]; ! 151: int menu_numcachepics; ! 152: ! 153: byte menuplyr_pixels[4096]; ! 154: ! 155: int pic_texels; ! 156: int pic_count; ! 157: ! 158: qpic_t *Draw_PicFromWad (char *name) ! 159: { ! 160: qpic_t *p; ! 161: glpic_t *gl; ! 162: ! 163: p = W_GetLumpName (name); ! 164: gl = (glpic_t *)p->data; ! 165: ! 166: // load little ones into the scrap ! 167: if (p->width < 64 && p->height < 64) ! 168: { ! 169: int x, y; ! 170: int i, j, k; ! 171: int texnum; ! 172: ! 173: texnum = Scrap_AllocBlock (p->width, p->height, &x, &y); ! 174: if (texnum == -1) ! 175: goto nonscrap; ! 176: scrap_dirty = true; ! 177: k = 0; ! 178: for (i=0 ; i<p->height ; i++) ! 179: for (j=0 ; j<p->width ; j++, k++) ! 180: scrap_texels[texnum][(y+i)*BLOCK_WIDTH + x + j] = p->data[k]; ! 181: texnum += scrap_texnum; ! 182: gl->texnum = texnum; ! 183: gl->sl = (x+0.01)/(float)BLOCK_WIDTH; ! 184: gl->sh = (x+p->width-0.01)/(float)BLOCK_WIDTH; ! 185: gl->tl = (y+0.01)/(float)BLOCK_WIDTH; ! 186: gl->th = (y+p->height-0.01)/(float)BLOCK_WIDTH; ! 187: ! 188: pic_count++; ! 189: pic_texels += p->width*p->height; ! 190: } ! 191: else ! 192: { ! 193: nonscrap: ! 194: gl->texnum = GL_LoadPicTexture (p); ! 195: gl->sl = 0; ! 196: gl->sh = 1; ! 197: gl->tl = 0; ! 198: gl->th = 1; ! 199: } ! 200: return p; ! 201: } ! 202: ! 203: ! 204: /* ! 205: ================ ! 206: Draw_CachePic ! 207: ================ ! 208: */ ! 209: qpic_t *Draw_CachePic (char *path) ! 210: { ! 211: cachepic_t *pic; ! 212: int i; ! 213: qpic_t *dat; ! 214: glpic_t *gl; ! 215: ! 216: for (pic=menu_cachepics, i=0 ; i<menu_numcachepics ; pic++, i++) ! 217: if (!strcmp (path, pic->name)) ! 218: return &pic->pic; ! 219: ! 220: if (menu_numcachepics == MAX_CACHED_PICS) ! 221: Sys_Error ("menu_numcachepics == MAX_CACHED_PICS"); ! 222: menu_numcachepics++; ! 223: strcpy (pic->name, path); ! 224: ! 225: // ! 226: // load the pic from disk ! 227: // ! 228: dat = (qpic_t *)COM_LoadTempFile (path); ! 229: if (!dat) ! 230: Sys_Error ("Draw_CachePic: failed to load %s", path); ! 231: SwapPic (dat); ! 232: ! 233: // HACK HACK HACK --- we need to keep the bytes for ! 234: // the translatable player picture just for the menu ! 235: // configuration dialog ! 236: if (!strcmp (path, "gfx/menuplyr.lmp")) ! 237: memcpy (menuplyr_pixels, dat->data, dat->width*dat->height); ! 238: ! 239: pic->pic.width = dat->width; ! 240: pic->pic.height = dat->height; ! 241: ! 242: gl = (glpic_t *)pic->pic.data; ! 243: gl->texnum = GL_LoadPicTexture (dat); ! 244: gl->sl = 0; ! 245: gl->sh = 1; ! 246: gl->tl = 0; ! 247: gl->th = 1; ! 248: ! 249: return &pic->pic; ! 250: } ! 251: ! 252: ! 253: void Draw_CharToConback (int num, byte *dest) ! 254: { ! 255: int row, col; ! 256: byte *source; ! 257: int drawline; ! 258: int x; ! 259: ! 260: row = num>>4; ! 261: col = num&15; ! 262: source = draw_chars + (row<<10) + (col<<3); ! 263: ! 264: drawline = 8; ! 265: ! 266: while (drawline--) ! 267: { ! 268: for (x=0 ; x<8 ; x++) ! 269: if (source[x] != 255) ! 270: dest[x] = 0x60 + source[x]; ! 271: source += 128; ! 272: dest += 320; ! 273: } ! 274: ! 275: } ! 276: ! 277: typedef struct ! 278: { ! 279: char *name; ! 280: int minimize, maximize; ! 281: } mode_t; ! 282: ! 283: mode_t modes[] = { ! 284: {"GL_NEAREST", GL_NEAREST, GL_NEAREST}, ! 285: {"GL_LINEAR", GL_LINEAR, GL_LINEAR}, ! 286: {"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST}, ! 287: {"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR}, ! 288: {"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST}, ! 289: {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR} ! 290: }; ! 291: ! 292: /* ! 293: =============== ! 294: Draw_TextureMode_f ! 295: =============== ! 296: */ ! 297: void Draw_TextureMode_f (void) ! 298: { ! 299: int i; ! 300: gltexture_t *glt; ! 301: ! 302: if (Cmd_Argc() == 1) ! 303: { ! 304: for (i=0 ; i< 6 ; i++) ! 305: if (gl_filter_min == modes[i].minimize) ! 306: { ! 307: Con_Printf ("%s\n", modes[i].name); ! 308: return; ! 309: } ! 310: Con_Printf ("current filter is unknown???\n"); ! 311: return; ! 312: } ! 313: ! 314: for (i=0 ; i< 6 ; i++) ! 315: { ! 316: if (!Q_strcasecmp (modes[i].name, Cmd_Argv(1) ) ) ! 317: break; ! 318: } ! 319: if (i == 6) ! 320: { ! 321: Con_Printf ("bad filter name\n"); ! 322: return; ! 323: } ! 324: ! 325: gl_filter_min = modes[i].minimize; ! 326: gl_filter_max = modes[i].maximize; ! 327: ! 328: // change all the existing mipmap texture objects ! 329: for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++) ! 330: { ! 331: if (glt->mipmap) ! 332: { ! 333: GL_Bind (glt->texnum); ! 334: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); ! 335: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); ! 336: } ! 337: } ! 338: } ! 339: ! 340: /* ! 341: =============== ! 342: Draw_Init ! 343: =============== ! 344: */ ! 345: void Draw_Init (void) ! 346: { ! 347: int i; ! 348: qpic_t *cb; ! 349: byte *dest; ! 350: int x, y; ! 351: char ver[40]; ! 352: glpic_t *gl; ! 353: ! 354: Cvar_RegisterVariable (&gl_nobind); ! 355: Cvar_RegisterVariable (&gl_max_size); ! 356: Cvar_RegisterVariable (&gl_round_down); ! 357: Cvar_RegisterVariable (&gl_picmip); ! 358: ! 359: // 3dfx can only handle 256 wide textures ! 360: if (!Q_strncasecmp ((char *)gl_renderer, "3dfx",4)) ! 361: Cvar_Set ("gl_max_size", "256"); ! 362: ! 363: Cmd_AddCommand ("gl_texturemode", &Draw_TextureMode_f); ! 364: Cmd_AddCommand ("gl_texels", &GL_Texels_f); ! 365: ! 366: ! 367: // load the console background and the charset ! 368: // by hand, because we need to write the version ! 369: // string into the background before turning ! 370: // it into a texture ! 371: draw_chars = W_GetLumpName ("conchars"); ! 372: for (i=0 ; i<256*64 ; i++) ! 373: if (draw_chars[i] == 0) ! 374: draw_chars[i] = 255; // proper transparent color ! 375: ! 376: cb = (qpic_t *)COM_LoadTempFile ("gfx/conback.lmp"); ! 377: if (!cb) ! 378: Sys_Error ("Couldn't load gfx/conback.lmp"); ! 379: SwapPic (cb); ! 380: ! 381: // hack the version number directly into the pic ! 382: sprintf (ver, "(gl %4.2f) %4.2f", (float)GLQUAKE_VERSION, (float)VERSION); ! 383: dest = cb->data + 320*186 + 320 - 11 - 8*strlen(ver); ! 384: y = strlen(ver); ! 385: for (x=0 ; x<y ; x++) ! 386: Draw_CharToConback (ver[x], dest+(x<<3)); ! 387: ! 388: // now turn them into textures ! 389: char_texture = GL_LoadTexture ("charset", 128, 128, draw_chars, false, true); ! 390: conback->width = cb->width; ! 391: conback->height = cb->height; ! 392: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); ! 393: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); ! 394: ! 395: gl = (glpic_t *)conback->data; ! 396: gl->texnum = GL_LoadTexture ("conback", 320, 200, cb->data, false, false); ! 397: gl->sl = 0; ! 398: gl->sh = 1; ! 399: gl->tl = 0; ! 400: gl->th = 1; ! 401: ! 402: // save a texture slot for translated picture ! 403: translate_texture = texture_extension_number++; ! 404: ! 405: // save slots for scraps ! 406: scrap_texnum = texture_extension_number; ! 407: texture_extension_number += MAX_SCRAPS; ! 408: ! 409: // ! 410: // get the other pics we need ! 411: // ! 412: draw_disc = Draw_PicFromWad ("disc"); ! 413: draw_backtile = Draw_PicFromWad ("backtile"); ! 414: } ! 415: ! 416: ! 417: ! 418: /* ! 419: ================ ! 420: Draw_Character ! 421: ! 422: Draws one 8*8 graphics character with 0 being transparent. ! 423: It can be clipped to the top of the screen to allow the console to be ! 424: smoothly scrolled off. ! 425: ================ ! 426: */ ! 427: void Draw_Character (int x, int y, int num) ! 428: { ! 429: byte *dest; ! 430: byte *source; ! 431: unsigned short *pusdest; ! 432: int drawline; ! 433: int row, col; ! 434: float frow, fcol, size; ! 435: ! 436: if (num == 32) ! 437: return; // space ! 438: ! 439: num &= 255; ! 440: ! 441: if (y <= -8) ! 442: return; // totally off screen ! 443: ! 444: row = num>>4; ! 445: col = num&15; ! 446: ! 447: frow = row*0.0625; ! 448: fcol = col*0.0625; ! 449: size = 0.0625; ! 450: ! 451: GL_Bind (char_texture); ! 452: ! 453: glBegin (GL_QUADS); ! 454: glTexCoord2f (fcol, frow); ! 455: glVertex2f (x, y); ! 456: glTexCoord2f (fcol + size, frow); ! 457: glVertex2f (x+8, y); ! 458: glTexCoord2f (fcol + size, frow + size); ! 459: glVertex2f (x+8, y+8); ! 460: glTexCoord2f (fcol, frow + size); ! 461: glVertex2f (x, y+8); ! 462: glEnd (); ! 463: } ! 464: ! 465: /* ! 466: ================ ! 467: Draw_String ! 468: ================ ! 469: */ ! 470: void Draw_String (int x, int y, char *str) ! 471: { ! 472: while (*str) ! 473: { ! 474: Draw_Character (x, y, *str); ! 475: str++; ! 476: x += 8; ! 477: } ! 478: } ! 479: ! 480: /* ! 481: ================ ! 482: Draw_DebugChar ! 483: ! 484: Draws a single character directly to the upper right corner of the screen. ! 485: This is for debugging lockups by drawing different chars in different parts ! 486: of the code. ! 487: ================ ! 488: */ ! 489: void Draw_DebugChar (char num) ! 490: { ! 491: } ! 492: ! 493: /* ! 494: ============= ! 495: Draw_Pic ! 496: ============= ! 497: */ ! 498: void Draw_Pic (int x, int y, qpic_t *pic) ! 499: { ! 500: byte *dest, *source; ! 501: unsigned short *pusdest; ! 502: int v, u; ! 503: glpic_t *gl; ! 504: ! 505: if (scrap_dirty) ! 506: Scrap_Upload (); ! 507: gl = (glpic_t *)pic->data; ! 508: glColor4f (1,1,1,1); ! 509: GL_Bind (gl->texnum); ! 510: glBegin (GL_QUADS); ! 511: glTexCoord2f (gl->sl, gl->tl); ! 512: glVertex2f (x, y); ! 513: glTexCoord2f (gl->sh, gl->tl); ! 514: glVertex2f (x+pic->width, y); ! 515: glTexCoord2f (gl->sh, gl->th); ! 516: glVertex2f (x+pic->width, y+pic->height); ! 517: glTexCoord2f (gl->sl, gl->th); ! 518: glVertex2f (x, y+pic->height); ! 519: glEnd (); ! 520: } ! 521: ! 522: ! 523: /* ! 524: ============= ! 525: Draw_TransPic ! 526: ============= ! 527: */ ! 528: void Draw_TransPic (int x, int y, qpic_t *pic) ! 529: { ! 530: byte *dest, *source, tbyte; ! 531: unsigned short *pusdest; ! 532: int v, u; ! 533: ! 534: if (x < 0 || (unsigned)(x + pic->width) > vid.width || y < 0 || ! 535: (unsigned)(y + pic->height) > vid.height) ! 536: { ! 537: Sys_Error ("Draw_TransPic: bad coordinates"); ! 538: } ! 539: ! 540: Draw_Pic (x, y, pic); ! 541: } ! 542: ! 543: ! 544: /* ! 545: ============= ! 546: Draw_TransPicTranslate ! 547: ! 548: Only used for the player color selection menu ! 549: ============= ! 550: */ ! 551: void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation) ! 552: { ! 553: int v, u, c; ! 554: unsigned trans[64*64], *dest; ! 555: byte *src; ! 556: int p; ! 557: ! 558: GL_Bind (translate_texture); ! 559: ! 560: c = pic->width * pic->height; ! 561: ! 562: dest = trans; ! 563: for (v=0 ; v<64 ; v++, dest += 64) ! 564: { ! 565: src = &menuplyr_pixels[ ((v*pic->height)>>6) *pic->width]; ! 566: for (u=0 ; u<64 ; u++) ! 567: { ! 568: p = src[(u*pic->width)>>6]; ! 569: if (p == 255) ! 570: dest[u] = p; ! 571: else ! 572: dest[u] = d_8to24table[translation[p]]; ! 573: } ! 574: } ! 575: ! 576: glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans); ! 577: ! 578: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); ! 579: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); ! 580: ! 581: glColor3f (1,1,1); ! 582: glBegin (GL_QUADS); ! 583: glTexCoord2f (0, 0); ! 584: glVertex2f (x, y); ! 585: glTexCoord2f (1, 0); ! 586: glVertex2f (x+pic->width, y); ! 587: glTexCoord2f (1, 1); ! 588: glVertex2f (x+pic->width, y+pic->height); ! 589: glTexCoord2f (0, 1); ! 590: glVertex2f (x, y+pic->height); ! 591: glEnd (); ! 592: } ! 593: ! 594: ! 595: /* ! 596: ================ ! 597: Draw_ConsoleBackground ! 598: ! 599: ================ ! 600: */ ! 601: void Draw_ConsoleBackground (int lines) ! 602: { ! 603: Draw_Pic (0, lines-200, conback); ! 604: } ! 605: ! 606: ! 607: /* ! 608: ============= ! 609: Draw_TileClear ! 610: ! 611: This repeats a 64*64 tile graphic to fill the screen around a sized down ! 612: refresh window. ! 613: ============= ! 614: */ ! 615: void Draw_TileClear (int x, int y, int w, int h) ! 616: { ! 617: glColor3f (1,1,1); ! 618: GL_Bind (*(int *)draw_backtile->data); ! 619: glBegin (GL_QUADS); ! 620: glTexCoord2f (x/64.0, y/64.0); ! 621: glVertex2f (x, y); ! 622: glTexCoord2f ( (x+w)/64.0, y/64.0); ! 623: glVertex2f (x+w, y); ! 624: glTexCoord2f ( (x+w)/64.0, (y+h)/64.0); ! 625: glVertex2f (x+w, y+h); ! 626: glTexCoord2f ( x/64.0, (y+h)/64.0 ); ! 627: glVertex2f (x, y+h); ! 628: glEnd (); ! 629: } ! 630: ! 631: ! 632: /* ! 633: ============= ! 634: Draw_Fill ! 635: ! 636: Fills a box of pixels with a single color ! 637: ============= ! 638: */ ! 639: void Draw_Fill (int x, int y, int w, int h, int c) ! 640: { ! 641: glDisable (GL_TEXTURE_2D); ! 642: glColor3f (host_basepal[c*3]/255.0, ! 643: host_basepal[c*3+1]/255.0, ! 644: host_basepal[c*3+2]/255.0); ! 645: ! 646: glBegin (GL_QUADS); ! 647: ! 648: glVertex2f (x,y); ! 649: glVertex2f (x+w, y); ! 650: glVertex2f (x+w, y+h); ! 651: glVertex2f (x, y+h); ! 652: ! 653: glEnd (); ! 654: glColor3f (1,1,1); ! 655: glEnable (GL_TEXTURE_2D); ! 656: } ! 657: //============================================================================= ! 658: ! 659: /* ! 660: ================ ! 661: Draw_FadeScreen ! 662: ! 663: ================ ! 664: */ ! 665: void Draw_FadeScreen (void) ! 666: { ! 667: glEnable (GL_BLEND); ! 668: glDisable (GL_TEXTURE_2D); ! 669: glColor4f (0, 0, 0, 0.8); ! 670: glBegin (GL_QUADS); ! 671: ! 672: glVertex2f (0,0); ! 673: glVertex2f (320, 0); ! 674: glVertex2f (320, 200); ! 675: glVertex2f (0, 200); ! 676: ! 677: glEnd (); ! 678: glColor4f (1,1,1,1); ! 679: glEnable (GL_TEXTURE_2D); ! 680: glDisable (GL_BLEND); ! 681: ! 682: Sbar_Changed(); ! 683: } ! 684: ! 685: //============================================================================= ! 686: ! 687: /* ! 688: ================ ! 689: Draw_BeginDisc ! 690: ! 691: Draws the little blue disc in the corner of the screen. ! 692: Call before beginning any disc IO. ! 693: ================ ! 694: */ ! 695: void Draw_BeginDisc (void) ! 696: { ! 697: if (!draw_disc) ! 698: return; ! 699: glDrawBuffer (GL_FRONT); ! 700: Draw_Pic (320 - 24, 0, draw_disc); ! 701: glDrawBuffer (GL_BACK); ! 702: } ! 703: ! 704: ! 705: /* ! 706: ================ ! 707: Draw_EndDisc ! 708: ! 709: Erases the disc icon. ! 710: Call after completing any disc IO ! 711: ================ ! 712: */ ! 713: void Draw_EndDisc (void) ! 714: { ! 715: } ! 716: ! 717: /* ! 718: ================ ! 719: GL_Set2D ! 720: ! 721: Setup as if the screen was 320*200 ! 722: ================ ! 723: */ ! 724: void GL_Set2D (void) ! 725: { ! 726: glViewport (glx, gly, glwidth, glheight); ! 727: ! 728: glMatrixMode(GL_PROJECTION); ! 729: glLoadIdentity (); ! 730: glOrtho (0, 320, 200, 0, -99999, 99999); ! 731: ! 732: glMatrixMode(GL_MODELVIEW); ! 733: glLoadIdentity (); ! 734: ! 735: glDisable (GL_DEPTH_TEST); ! 736: glDisable (GL_CULL_FACE); ! 737: glDisable (GL_BLEND); ! 738: glEnable (GL_ALPHA_TEST); ! 739: // glDisable (GL_ALPHA_TEST); ! 740: ! 741: glColor4f (1,1,1,1); ! 742: } ! 743: ! 744: //==================================================================== ! 745: ! 746: /* ! 747: ================ ! 748: GL_FindTexture ! 749: ================ ! 750: */ ! 751: int GL_FindTexture (char *identifier) ! 752: { ! 753: int i; ! 754: gltexture_t *glt; ! 755: ! 756: for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++) ! 757: { ! 758: if (!strcmp (identifier, glt->identifier)) ! 759: return gltextures[i].texnum; ! 760: } ! 761: ! 762: return -1; ! 763: } ! 764: ! 765: /* ! 766: ================ ! 767: GL_ResampleTexture ! 768: ================ ! 769: */ ! 770: void GL_ResampleTexture (unsigned *in, int inwidth, int inheight, unsigned *out, int outwidth, int outheight) ! 771: { ! 772: int i, j; ! 773: unsigned *inrow, *inrow2; ! 774: unsigned frac, fracstep; ! 775: unsigned p1[1024], p2[1024]; ! 776: byte *pix1, *pix2, *pix3, *pix4; ! 777: ! 778: fracstep = inwidth*0x10000/outwidth; ! 779: ! 780: frac = fracstep>>2; ! 781: for (i=0 ; i<outwidth ; i++) ! 782: { ! 783: p1[i] = 4*(frac>>16); ! 784: frac += fracstep; ! 785: } ! 786: frac = 3*(fracstep>>2); ! 787: for (i=0 ; i<outwidth ; i++) ! 788: { ! 789: p2[i] = 4*(frac>>16); ! 790: frac += fracstep; ! 791: } ! 792: ! 793: for (i=0 ; i<outheight ; i++, out += outwidth) ! 794: { ! 795: inrow = in + inwidth*(int)((i+0.25)*inheight/outheight); ! 796: inrow2 = in + inwidth*(int)((i+0.75)*inheight/outheight); ! 797: frac = fracstep >> 1; ! 798: for (j=0 ; j<outwidth ; j++) ! 799: { ! 800: pix1 = (byte *)inrow + p1[j]; ! 801: pix2 = (byte *)inrow + p2[j]; ! 802: pix3 = (byte *)inrow2 + p1[j]; ! 803: pix4 = (byte *)inrow2 + p2[j]; ! 804: ((byte *)(out+j))[0] = (pix1[0] + pix2[0] + pix3[0] + pix4[0])>>2; ! 805: ((byte *)(out+j))[1] = (pix1[1] + pix2[1] + pix3[1] + pix4[1])>>2; ! 806: ((byte *)(out+j))[2] = (pix1[2] + pix2[2] + pix3[2] + pix4[2])>>2; ! 807: ((byte *)(out+j))[3] = (pix1[3] + pix2[3] + pix3[3] + pix4[3])>>2; ! 808: } ! 809: } ! 810: } ! 811: ! 812: /* ! 813: ================ ! 814: GL_MipMap ! 815: ! 816: Operates in place, quartering the size of the texture ! 817: ================ ! 818: */ ! 819: void GL_MipMap (byte *in, int width, int height) ! 820: { ! 821: int i, j; ! 822: byte *out; ! 823: ! 824: width <<=2; ! 825: height >>= 1; ! 826: out = in; ! 827: for (i=0 ; i<height ; i++, in+=width) ! 828: { ! 829: for (j=0 ; j<width ; j+=8, out+=4, in+=8) ! 830: { ! 831: out[0] = (in[0] + in[4] + in[width+0] + in[width+4])>>2; ! 832: out[1] = (in[1] + in[5] + in[width+1] + in[width+5])>>2; ! 833: out[2] = (in[2] + in[6] + in[width+2] + in[width+6])>>2; ! 834: out[3] = (in[3] + in[7] + in[width+3] + in[width+7])>>2; ! 835: } ! 836: } ! 837: } ! 838: ! 839: /* ! 840: =============== ! 841: GL_Upload32 ! 842: =============== ! 843: */ ! 844: void GL_Upload32 (unsigned *data, int width, int height, qboolean mipmap, qboolean alpha) ! 845: { ! 846: int samples; ! 847: static unsigned scaled[1024*512]; // [512*256]; ! 848: int scaled_width, scaled_height; ! 849: ! 850: for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1) ! 851: ; ! 852: if (gl_round_down.value && scaled_width > width) ! 853: scaled_width >>= 1; ! 854: for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1) ! 855: ; ! 856: if (gl_round_down.value && scaled_height > height) ! 857: scaled_height >>= 1; ! 858: ! 859: scaled_width >>= (int)gl_picmip.value; ! 860: scaled_height >>= (int)gl_picmip.value; ! 861: ! 862: if (scaled_width > gl_max_size.value) ! 863: scaled_width = gl_max_size.value; ! 864: if (scaled_height > gl_max_size.value) ! 865: scaled_height = gl_max_size.value; ! 866: ! 867: if (scaled_width * scaled_height > sizeof(scaled)/4) ! 868: Sys_Error ("GL_LoadTexture: too big"); ! 869: ! 870: samples = alpha ? gl_alpha_format : gl_solid_format; ! 871: ! 872: #if 0 ! 873: if (mipmap) ! 874: gluBuild2DMipmaps (GL_TEXTURE_2D, samples, width, height, GL_RGBA, GL_UNSIGNED_BYTE, trans); ! 875: else if (scaled_width == width && scaled_height == height) ! 876: glTexImage2D (GL_TEXTURE_2D, 0, samples, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans); ! 877: else ! 878: { ! 879: gluScaleImage (GL_RGBA, width, height, GL_UNSIGNED_BYTE, trans, ! 880: scaled_width, scaled_height, GL_UNSIGNED_BYTE, scaled); ! 881: glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled); ! 882: } ! 883: #else ! 884: ! 885: if (scaled_width == width && scaled_height == height) ! 886: { ! 887: if (!mipmap) ! 888: { ! 889: glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); ! 890: goto done; ! 891: } ! 892: memcpy (scaled, data, width*height*4); ! 893: } ! 894: else ! 895: GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height); ! 896: ! 897: texels += scaled_width * scaled_height; ! 898: glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled); ! 899: if (mipmap) ! 900: { ! 901: int miplevel; ! 902: ! 903: miplevel = 0; ! 904: while (scaled_width > 1 || scaled_height > 1) ! 905: { ! 906: GL_MipMap ((byte *)scaled, scaled_width, scaled_height); ! 907: scaled_width >>= 1; ! 908: scaled_height >>= 1; ! 909: if (scaled_width < 1) ! 910: scaled_width = 1; ! 911: if (scaled_height < 1) ! 912: scaled_height = 1; ! 913: miplevel++; ! 914: texels += scaled_width * scaled_height; ! 915: glTexImage2D (GL_TEXTURE_2D, miplevel, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled); ! 916: } ! 917: } ! 918: done: ; ! 919: #endif ! 920: ! 921: ! 922: if (mipmap) ! 923: { ! 924: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); ! 925: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); ! 926: } ! 927: else ! 928: { ! 929: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max); ! 930: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); ! 931: } ! 932: } ! 933: ! 934: /* ! 935: =============== ! 936: GL_Upload8 ! 937: =============== ! 938: */ ! 939: void GL_Upload8 (byte *data, int width, int height, qboolean mipmap, qboolean alpha) ! 940: { ! 941: static unsigned trans[640*480]; // FIXME, temporary ! 942: int i, s; ! 943: qboolean noalpha; ! 944: int p; ! 945: ! 946: s = width*height; ! 947: // if there are no transparent pixels, make it a 3 component ! 948: // texture even if it was specified as otherwise ! 949: if (alpha) ! 950: { ! 951: noalpha = true; ! 952: for (i=0 ; i<s ; i++) ! 953: { ! 954: p = data[i]; ! 955: if (p == 255) ! 956: noalpha = false; ! 957: trans[i] = d_8to24table[p]; ! 958: } ! 959: ! 960: if (alpha && noalpha) ! 961: alpha = false; ! 962: } ! 963: else ! 964: { ! 965: if (s&3) ! 966: Sys_Error ("GL_Upload8: s&3"); ! 967: for (i=0 ; i<s ; i+=4) ! 968: { ! 969: trans[i] = d_8to24table[data[i]]; ! 970: trans[i+1] = d_8to24table[data[i+1]]; ! 971: trans[i+2] = d_8to24table[data[i+2]]; ! 972: trans[i+3] = d_8to24table[data[i+3]]; ! 973: } ! 974: } ! 975: ! 976: GL_Upload32 (trans, width, height, mipmap, alpha); ! 977: } ! 978: ! 979: /* ! 980: ================ ! 981: GL_LoadTexture ! 982: ================ ! 983: */ ! 984: int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha) ! 985: { ! 986: qboolean noalpha; ! 987: int i, p, s; ! 988: gltexture_t *glt; ! 989: ! 990: // see if the texture is allready present ! 991: if (identifier[0]) ! 992: { ! 993: for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++) ! 994: { ! 995: if (!strcmp (identifier, glt->identifier)) ! 996: { ! 997: if (width != glt->width || height != glt->height) ! 998: Sys_Error ("GL_LoadTexture: cache mismatch"); ! 999: return gltextures[i].texnum; ! 1000: } ! 1001: } ! 1002: } ! 1003: else ! 1004: glt = &gltextures[numgltextures]; ! 1005: numgltextures++; ! 1006: ! 1007: strcpy (glt->identifier, identifier); ! 1008: glt->texnum = texture_extension_number; ! 1009: glt->width = width; ! 1010: glt->height = height; ! 1011: glt->mipmap = mipmap; ! 1012: ! 1013: GL_Bind(texture_extension_number ); ! 1014: ! 1015: GL_Upload8 (data, width, height, mipmap, alpha); ! 1016: ! 1017: texture_extension_number++; ! 1018: ! 1019: return texture_extension_number-1; ! 1020: } ! 1021: ! 1022: /* ! 1023: ================ ! 1024: GL_LoadPicTexture ! 1025: ================ ! 1026: */ ! 1027: int GL_LoadPicTexture (qpic_t *pic) ! 1028: { ! 1029: return GL_LoadTexture ("", pic->width, pic->height, pic->data, false, true); ! 1030: } ! 1031:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.