gl_image.c (33954B)
1 /* 2 Copyright (C) 1997-2001 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 #include "gl_local.h" 22 23 image_t gltextures[MAX_GLTEXTURES]; 24 int numgltextures; 25 int base_textureid; // gltextures[i] = base_textureid+i 26 27 static byte intensitytable[256]; 28 static unsigned char gammatable[256]; 29 30 cvar_t *intensity; 31 32 unsigned d_8to24table[256]; 33 34 qboolean GL_Upload8 (byte *data, int width, int height, qboolean mipmap, qboolean is_sky ); 35 qboolean GL_Upload32 (unsigned *data, int width, int height, qboolean mipmap); 36 37 38 int gl_solid_format = 3; 39 int gl_alpha_format = 4; 40 41 int gl_tex_solid_format = 3; 42 int gl_tex_alpha_format = 4; 43 44 int gl_filter_min = GL_LINEAR_MIPMAP_NEAREST; 45 int gl_filter_max = GL_LINEAR; 46 47 void GL_SetTexturePalette( unsigned palette[256] ) 48 { 49 int i; 50 unsigned char temptable[768]; 51 52 for ( i = 0; i < 256; i++ ) 53 { 54 temptable[i*3+0] = ( palette[i] >> 0 ) & 0xff; 55 temptable[i*3+1] = ( palette[i] >> 8 ) & 0xff; 56 temptable[i*3+2] = ( palette[i] >> 16 ) & 0xff; 57 } 58 59 if ( qglColorTableEXT && gl_ext_palettedtexture->value ) 60 { 61 qglColorTableEXT( GL_SHARED_TEXTURE_PALETTE_EXT, 62 GL_RGB, 63 256, 64 GL_RGB, 65 GL_UNSIGNED_BYTE, 66 temptable ); 67 } 68 } 69 70 void GL_EnableMultitexture( qboolean enable ) 71 { 72 if ( !qglSelectTextureSGIS ) 73 return; 74 75 if ( enable ) 76 { 77 GL_SelectTexture( GL_TEXTURE1_SGIS ); 78 qglEnable( GL_TEXTURE_2D ); 79 GL_TexEnv( GL_REPLACE ); 80 } 81 else 82 { 83 GL_SelectTexture( GL_TEXTURE1_SGIS ); 84 qglDisable( GL_TEXTURE_2D ); 85 GL_TexEnv( GL_REPLACE ); 86 } 87 GL_SelectTexture( GL_TEXTURE0_SGIS ); 88 GL_TexEnv( GL_REPLACE ); 89 } 90 91 void GL_SelectTexture( GLenum texture ) 92 { 93 int tmu; 94 95 if ( !qglSelectTextureSGIS ) 96 return; 97 98 if ( texture == GL_TEXTURE0_SGIS ) 99 tmu = 0; 100 else 101 tmu = 1; 102 103 if ( tmu == gl_state.currenttmu ) 104 return; 105 106 gl_state.currenttmu = tmu; 107 108 if ( tmu == 0 ) 109 qglSelectTextureSGIS( GL_TEXTURE0_SGIS ); 110 else 111 qglSelectTextureSGIS( GL_TEXTURE1_SGIS ); 112 } 113 114 void GL_TexEnv( GLenum mode ) 115 { 116 static int lastmodes[2] = { -1, -1 }; 117 118 if ( mode != lastmodes[gl_state.currenttmu] ) 119 { 120 qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode ); 121 lastmodes[gl_state.currenttmu] = mode; 122 } 123 } 124 125 void GL_Bind (int texnum) 126 { 127 extern image_t *draw_chars; 128 129 if (gl_nobind->value && draw_chars) // performance evaluation option 130 texnum = draw_chars->texnum; 131 if ( gl_state.currenttextures[gl_state.currenttmu] == texnum) 132 return; 133 gl_state.currenttextures[gl_state.currenttmu] = texnum; 134 qglBindTexture (GL_TEXTURE_2D, texnum); 135 } 136 137 void GL_MBind( GLenum target, int texnum ) 138 { 139 GL_SelectTexture( target ); 140 if ( target == GL_TEXTURE0_SGIS ) 141 { 142 if ( gl_state.currenttextures[0] == texnum ) 143 return; 144 } 145 else 146 { 147 if ( gl_state.currenttextures[1] == texnum ) 148 return; 149 } 150 GL_Bind( texnum ); 151 } 152 153 typedef struct 154 { 155 char *name; 156 int minimize, maximize; 157 } glmode_t; 158 159 glmode_t modes[] = { 160 {"GL_NEAREST", GL_NEAREST, GL_NEAREST}, 161 {"GL_LINEAR", GL_LINEAR, GL_LINEAR}, 162 {"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST}, 163 {"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR}, 164 {"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST}, 165 {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR} 166 }; 167 168 #define NUM_GL_MODES (sizeof(modes) / sizeof (glmode_t)) 169 170 typedef struct 171 { 172 char *name; 173 int mode; 174 } gltmode_t; 175 176 gltmode_t gl_alpha_modes[] = { 177 {"default", 4}, 178 {"GL_RGBA", GL_RGBA}, 179 {"GL_RGBA8", GL_RGBA8}, 180 {"GL_RGB5_A1", GL_RGB5_A1}, 181 {"GL_RGBA4", GL_RGBA4}, 182 {"GL_RGBA2", GL_RGBA2}, 183 }; 184 185 #define NUM_GL_ALPHA_MODES (sizeof(gl_alpha_modes) / sizeof (gltmode_t)) 186 187 gltmode_t gl_solid_modes[] = { 188 {"default", 3}, 189 {"GL_RGB", GL_RGB}, 190 {"GL_RGB8", GL_RGB8}, 191 {"GL_RGB5", GL_RGB5}, 192 {"GL_RGB4", GL_RGB4}, 193 {"GL_R3_G3_B2", GL_R3_G3_B2}, 194 #ifdef GL_RGB2_EXT 195 {"GL_RGB2", GL_RGB2_EXT}, 196 #endif 197 }; 198 199 #define NUM_GL_SOLID_MODES (sizeof(gl_solid_modes) / sizeof (gltmode_t)) 200 201 /* 202 =============== 203 GL_TextureMode 204 =============== 205 */ 206 void GL_TextureMode( char *string ) 207 { 208 int i; 209 image_t *glt; 210 211 for (i=0 ; i< NUM_GL_MODES ; i++) 212 { 213 if ( !Q_stricmp( modes[i].name, string ) ) 214 break; 215 } 216 217 if (i == NUM_GL_MODES) 218 { 219 ri.Con_Printf (PRINT_ALL, "bad filter name\n"); 220 return; 221 } 222 223 gl_filter_min = modes[i].minimize; 224 gl_filter_max = modes[i].maximize; 225 226 // change all the existing mipmap texture objects 227 for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++) 228 { 229 if (glt->type != it_pic && glt->type != it_sky ) 230 { 231 GL_Bind (glt->texnum); 232 qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); 233 qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); 234 } 235 } 236 } 237 238 /* 239 =============== 240 GL_TextureAlphaMode 241 =============== 242 */ 243 void GL_TextureAlphaMode( char *string ) 244 { 245 int i; 246 247 for (i=0 ; i< NUM_GL_ALPHA_MODES ; i++) 248 { 249 if ( !Q_stricmp( gl_alpha_modes[i].name, string ) ) 250 break; 251 } 252 253 if (i == NUM_GL_ALPHA_MODES) 254 { 255 ri.Con_Printf (PRINT_ALL, "bad alpha texture mode name\n"); 256 return; 257 } 258 259 gl_tex_alpha_format = gl_alpha_modes[i].mode; 260 } 261 262 /* 263 =============== 264 GL_TextureSolidMode 265 =============== 266 */ 267 void GL_TextureSolidMode( char *string ) 268 { 269 int i; 270 271 for (i=0 ; i< NUM_GL_SOLID_MODES ; i++) 272 { 273 if ( !Q_stricmp( gl_solid_modes[i].name, string ) ) 274 break; 275 } 276 277 if (i == NUM_GL_SOLID_MODES) 278 { 279 ri.Con_Printf (PRINT_ALL, "bad solid texture mode name\n"); 280 return; 281 } 282 283 gl_tex_solid_format = gl_solid_modes[i].mode; 284 } 285 286 /* 287 =============== 288 GL_ImageList_f 289 =============== 290 */ 291 void GL_ImageList_f (void) 292 { 293 int i; 294 image_t *image; 295 int texels; 296 const char *palstrings[2] = 297 { 298 "RGB", 299 "PAL" 300 }; 301 302 ri.Con_Printf (PRINT_ALL, "------------------\n"); 303 texels = 0; 304 305 for (i=0, image=gltextures ; i<numgltextures ; i++, image++) 306 { 307 if (image->texnum <= 0) 308 continue; 309 texels += image->upload_width*image->upload_height; 310 switch (image->type) 311 { 312 case it_skin: 313 ri.Con_Printf (PRINT_ALL, "M"); 314 break; 315 case it_sprite: 316 ri.Con_Printf (PRINT_ALL, "S"); 317 break; 318 case it_wall: 319 ri.Con_Printf (PRINT_ALL, "W"); 320 break; 321 case it_pic: 322 ri.Con_Printf (PRINT_ALL, "P"); 323 break; 324 default: 325 ri.Con_Printf (PRINT_ALL, " "); 326 break; 327 } 328 329 ri.Con_Printf (PRINT_ALL, " %3i %3i %s: %s\n", 330 image->upload_width, image->upload_height, palstrings[image->paletted], image->name); 331 } 332 ri.Con_Printf (PRINT_ALL, "Total texel count (not counting mipmaps): %i\n", texels); 333 } 334 335 336 /* 337 ============================================================================= 338 339 scrap allocation 340 341 Allocate all the little status bar obejcts into a single texture 342 to crutch up inefficient hardware / drivers 343 344 ============================================================================= 345 */ 346 347 #define MAX_SCRAPS 1 348 #define BLOCK_WIDTH 256 349 #define BLOCK_HEIGHT 256 350 351 int scrap_allocated[MAX_SCRAPS][BLOCK_WIDTH]; 352 byte scrap_texels[MAX_SCRAPS][BLOCK_WIDTH*BLOCK_HEIGHT]; 353 qboolean scrap_dirty; 354 355 // returns a texture number and the position inside it 356 int Scrap_AllocBlock (int w, int h, int *x, int *y) 357 { 358 int i, j; 359 int best, best2; 360 int texnum; 361 362 for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++) 363 { 364 best = BLOCK_HEIGHT; 365 366 for (i=0 ; i<BLOCK_WIDTH-w ; i++) 367 { 368 best2 = 0; 369 370 for (j=0 ; j<w ; j++) 371 { 372 if (scrap_allocated[texnum][i+j] >= best) 373 break; 374 if (scrap_allocated[texnum][i+j] > best2) 375 best2 = scrap_allocated[texnum][i+j]; 376 } 377 if (j == w) 378 { // this is a valid spot 379 *x = i; 380 *y = best = best2; 381 } 382 } 383 384 if (best + h > BLOCK_HEIGHT) 385 continue; 386 387 for (i=0 ; i<w ; i++) 388 scrap_allocated[texnum][*x + i] = best + h; 389 390 return texnum; 391 } 392 393 return -1; 394 // Sys_Error ("Scrap_AllocBlock: full"); 395 } 396 397 int scrap_uploads; 398 399 void Scrap_Upload (void) 400 { 401 scrap_uploads++; 402 GL_Bind(TEXNUM_SCRAPS); 403 GL_Upload8 (scrap_texels[0], BLOCK_WIDTH, BLOCK_HEIGHT, false, false ); 404 scrap_dirty = false; 405 } 406 407 /* 408 ================================================================= 409 410 PCX LOADING 411 412 ================================================================= 413 */ 414 415 416 /* 417 ============== 418 LoadPCX 419 ============== 420 */ 421 void LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height) 422 { 423 byte *raw; 424 pcx_t *pcx; 425 int x, y; 426 int len; 427 int dataByte, runLength; 428 byte *out, *pix; 429 430 *pic = NULL; 431 *palette = NULL; 432 433 // 434 // load the file 435 // 436 len = ri.FS_LoadFile (filename, (void **)&raw); 437 if (!raw) 438 { 439 ri.Con_Printf (PRINT_DEVELOPER, "Bad pcx file %s\n", filename); 440 return; 441 } 442 443 // 444 // parse the PCX file 445 // 446 pcx = (pcx_t *)raw; 447 448 pcx->xmin = LittleShort(pcx->xmin); 449 pcx->ymin = LittleShort(pcx->ymin); 450 pcx->xmax = LittleShort(pcx->xmax); 451 pcx->ymax = LittleShort(pcx->ymax); 452 pcx->hres = LittleShort(pcx->hres); 453 pcx->vres = LittleShort(pcx->vres); 454 pcx->bytes_per_line = LittleShort(pcx->bytes_per_line); 455 pcx->palette_type = LittleShort(pcx->palette_type); 456 457 raw = &pcx->data; 458 459 if (pcx->manufacturer != 0x0a 460 || pcx->version != 5 461 || pcx->encoding != 1 462 || pcx->bits_per_pixel != 8 463 || pcx->xmax >= 640 464 || pcx->ymax >= 480) 465 { 466 ri.Con_Printf (PRINT_ALL, "Bad pcx file %s\n", filename); 467 return; 468 } 469 470 out = malloc ( (pcx->ymax+1) * (pcx->xmax+1) ); 471 472 *pic = out; 473 474 pix = out; 475 476 if (palette) 477 { 478 *palette = malloc(768); 479 memcpy (*palette, (byte *)pcx + len - 768, 768); 480 } 481 482 if (width) 483 *width = pcx->xmax+1; 484 if (height) 485 *height = pcx->ymax+1; 486 487 for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1) 488 { 489 for (x=0 ; x<=pcx->xmax ; ) 490 { 491 dataByte = *raw++; 492 493 if((dataByte & 0xC0) == 0xC0) 494 { 495 runLength = dataByte & 0x3F; 496 dataByte = *raw++; 497 } 498 else 499 runLength = 1; 500 501 while(runLength-- > 0) 502 pix[x++] = dataByte; 503 } 504 505 } 506 507 if ( raw - (byte *)pcx > len) 508 { 509 ri.Con_Printf (PRINT_DEVELOPER, "PCX file %s was malformed", filename); 510 free (*pic); 511 *pic = NULL; 512 } 513 514 ri.FS_FreeFile (pcx); 515 } 516 517 /* 518 ========================================================= 519 520 TARGA LOADING 521 522 ========================================================= 523 */ 524 525 typedef struct _TargaHeader { 526 unsigned char id_length, colormap_type, image_type; 527 unsigned short colormap_index, colormap_length; 528 unsigned char colormap_size; 529 unsigned short x_origin, y_origin, width, height; 530 unsigned char pixel_size, attributes; 531 } TargaHeader; 532 533 534 /* 535 ============= 536 LoadTGA 537 ============= 538 */ 539 void LoadTGA (char *name, byte **pic, int *width, int *height) 540 { 541 int columns, rows, numPixels; 542 byte *pixbuf; 543 int row, column; 544 byte *buf_p; 545 byte *buffer; 546 int length; 547 TargaHeader targa_header; 548 byte *targa_rgba; 549 byte tmp[2]; 550 551 *pic = NULL; 552 553 // 554 // load the file 555 // 556 length = ri.FS_LoadFile (name, (void **)&buffer); 557 if (!buffer) 558 { 559 ri.Con_Printf (PRINT_DEVELOPER, "Bad tga file %s\n", name); 560 return; 561 } 562 563 buf_p = buffer; 564 565 targa_header.id_length = *buf_p++; 566 targa_header.colormap_type = *buf_p++; 567 targa_header.image_type = *buf_p++; 568 569 tmp[0] = buf_p[0]; 570 tmp[1] = buf_p[1]; 571 targa_header.colormap_index = LittleShort ( *((short *)tmp) ); 572 buf_p+=2; 573 tmp[0] = buf_p[0]; 574 tmp[1] = buf_p[1]; 575 targa_header.colormap_length = LittleShort ( *((short *)tmp) ); 576 buf_p+=2; 577 targa_header.colormap_size = *buf_p++; 578 targa_header.x_origin = LittleShort ( *((short *)buf_p) ); 579 buf_p+=2; 580 targa_header.y_origin = LittleShort ( *((short *)buf_p) ); 581 buf_p+=2; 582 targa_header.width = LittleShort ( *((short *)buf_p) ); 583 buf_p+=2; 584 targa_header.height = LittleShort ( *((short *)buf_p) ); 585 buf_p+=2; 586 targa_header.pixel_size = *buf_p++; 587 targa_header.attributes = *buf_p++; 588 589 if (targa_header.image_type!=2 590 && targa_header.image_type!=10) 591 ri.Sys_Error (ERR_DROP, "LoadTGA: Only type 2 and 10 targa RGB images supported\n"); 592 593 if (targa_header.colormap_type !=0 594 || (targa_header.pixel_size!=32 && targa_header.pixel_size!=24)) 595 ri.Sys_Error (ERR_DROP, "LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n"); 596 597 columns = targa_header.width; 598 rows = targa_header.height; 599 numPixels = columns * rows; 600 601 if (width) 602 *width = columns; 603 if (height) 604 *height = rows; 605 606 targa_rgba = malloc (numPixels*4); 607 *pic = targa_rgba; 608 609 if (targa_header.id_length != 0) 610 buf_p += targa_header.id_length; // skip TARGA image comment 611 612 if (targa_header.image_type==2) { // Uncompressed, RGB images 613 for(row=rows-1; row>=0; row--) { 614 pixbuf = targa_rgba + row*columns*4; 615 for(column=0; column<columns; column++) { 616 unsigned char red,green,blue,alphabyte; 617 switch (targa_header.pixel_size) { 618 case 24: 619 620 blue = *buf_p++; 621 green = *buf_p++; 622 red = *buf_p++; 623 *pixbuf++ = red; 624 *pixbuf++ = green; 625 *pixbuf++ = blue; 626 *pixbuf++ = 255; 627 break; 628 case 32: 629 blue = *buf_p++; 630 green = *buf_p++; 631 red = *buf_p++; 632 alphabyte = *buf_p++; 633 *pixbuf++ = red; 634 *pixbuf++ = green; 635 *pixbuf++ = blue; 636 *pixbuf++ = alphabyte; 637 break; 638 } 639 } 640 } 641 } 642 else if (targa_header.image_type==10) { // Runlength encoded RGB images 643 unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j; 644 for(row=rows-1; row>=0; row--) { 645 pixbuf = targa_rgba + row*columns*4; 646 for(column=0; column<columns; ) { 647 packetHeader= *buf_p++; 648 packetSize = 1 + (packetHeader & 0x7f); 649 if (packetHeader & 0x80) { // run-length packet 650 switch (targa_header.pixel_size) { 651 case 24: 652 blue = *buf_p++; 653 green = *buf_p++; 654 red = *buf_p++; 655 alphabyte = 255; 656 break; 657 case 32: 658 blue = *buf_p++; 659 green = *buf_p++; 660 red = *buf_p++; 661 alphabyte = *buf_p++; 662 break; 663 } 664 665 for(j=0;j<packetSize;j++) { 666 *pixbuf++=red; 667 *pixbuf++=green; 668 *pixbuf++=blue; 669 *pixbuf++=alphabyte; 670 column++; 671 if (column==columns) { // run spans across rows 672 column=0; 673 if (row>0) 674 row--; 675 else 676 goto breakOut; 677 pixbuf = targa_rgba + row*columns*4; 678 } 679 } 680 } 681 else { // non run-length packet 682 for(j=0;j<packetSize;j++) { 683 switch (targa_header.pixel_size) { 684 case 24: 685 blue = *buf_p++; 686 green = *buf_p++; 687 red = *buf_p++; 688 *pixbuf++ = red; 689 *pixbuf++ = green; 690 *pixbuf++ = blue; 691 *pixbuf++ = 255; 692 break; 693 case 32: 694 blue = *buf_p++; 695 green = *buf_p++; 696 red = *buf_p++; 697 alphabyte = *buf_p++; 698 *pixbuf++ = red; 699 *pixbuf++ = green; 700 *pixbuf++ = blue; 701 *pixbuf++ = alphabyte; 702 break; 703 } 704 column++; 705 if (column==columns) { // pixel packet run spans across rows 706 column=0; 707 if (row>0) 708 row--; 709 else 710 goto breakOut; 711 pixbuf = targa_rgba + row*columns*4; 712 } 713 } 714 } 715 } 716 breakOut:; 717 } 718 } 719 720 ri.FS_FreeFile (buffer); 721 } 722 723 724 /* 725 ==================================================================== 726 727 IMAGE FLOOD FILLING 728 729 ==================================================================== 730 */ 731 732 733 /* 734 ================= 735 Mod_FloodFillSkin 736 737 Fill background pixels so mipmapping doesn't have haloes 738 ================= 739 */ 740 741 typedef struct 742 { 743 short x, y; 744 } floodfill_t; 745 746 // must be a power of 2 747 #define FLOODFILL_FIFO_SIZE 0x1000 748 #define FLOODFILL_FIFO_MASK (FLOODFILL_FIFO_SIZE - 1) 749 750 #define FLOODFILL_STEP( off, dx, dy ) \ 751 { \ 752 if (pos[off] == fillcolor) \ 753 { \ 754 pos[off] = 255; \ 755 fifo[inpt].x = x + (dx), fifo[inpt].y = y + (dy); \ 756 inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; \ 757 } \ 758 else if (pos[off] != 255) fdc = pos[off]; \ 759 } 760 761 void R_FloodFillSkin( byte *skin, int skinwidth, int skinheight ) 762 { 763 byte fillcolor = *skin; // assume this is the pixel to fill 764 floodfill_t fifo[FLOODFILL_FIFO_SIZE]; 765 int inpt = 0, outpt = 0; 766 int filledcolor = -1; 767 int i; 768 769 if (filledcolor == -1) 770 { 771 filledcolor = 0; 772 // attempt to find opaque black 773 for (i = 0; i < 256; ++i) 774 if (d_8to24table[i] == (255 << 0)) // alpha 1.0 775 { 776 filledcolor = i; 777 break; 778 } 779 } 780 781 // can't fill to filled color or to transparent color (used as visited marker) 782 if ((fillcolor == filledcolor) || (fillcolor == 255)) 783 { 784 //printf( "not filling skin from %d to %d\n", fillcolor, filledcolor ); 785 return; 786 } 787 788 fifo[inpt].x = 0, fifo[inpt].y = 0; 789 inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; 790 791 while (outpt != inpt) 792 { 793 int x = fifo[outpt].x, y = fifo[outpt].y; 794 int fdc = filledcolor; 795 byte *pos = &skin[x + skinwidth * y]; 796 797 outpt = (outpt + 1) & FLOODFILL_FIFO_MASK; 798 799 if (x > 0) FLOODFILL_STEP( -1, -1, 0 ); 800 if (x < skinwidth - 1) FLOODFILL_STEP( 1, 1, 0 ); 801 if (y > 0) FLOODFILL_STEP( -skinwidth, 0, -1 ); 802 if (y < skinheight - 1) FLOODFILL_STEP( skinwidth, 0, 1 ); 803 skin[x + skinwidth * y] = fdc; 804 } 805 } 806 807 //======================================================= 808 809 810 /* 811 ================ 812 GL_ResampleTexture 813 ================ 814 */ 815 void GL_ResampleTexture (unsigned *in, int inwidth, int inheight, unsigned *out, int outwidth, int outheight) 816 { 817 int i, j; 818 unsigned *inrow, *inrow2; 819 unsigned frac, fracstep; 820 unsigned p1[1024], p2[1024]; 821 byte *pix1, *pix2, *pix3, *pix4; 822 823 fracstep = inwidth*0x10000/outwidth; 824 825 frac = fracstep>>2; 826 for (i=0 ; i<outwidth ; i++) 827 { 828 p1[i] = 4*(frac>>16); 829 frac += fracstep; 830 } 831 frac = 3*(fracstep>>2); 832 for (i=0 ; i<outwidth ; i++) 833 { 834 p2[i] = 4*(frac>>16); 835 frac += fracstep; 836 } 837 838 for (i=0 ; i<outheight ; i++, out += outwidth) 839 { 840 inrow = in + inwidth*(int)((i+0.25)*inheight/outheight); 841 inrow2 = in + inwidth*(int)((i+0.75)*inheight/outheight); 842 frac = fracstep >> 1; 843 for (j=0 ; j<outwidth ; j++) 844 { 845 pix1 = (byte *)inrow + p1[j]; 846 pix2 = (byte *)inrow + p2[j]; 847 pix3 = (byte *)inrow2 + p1[j]; 848 pix4 = (byte *)inrow2 + p2[j]; 849 ((byte *)(out+j))[0] = (pix1[0] + pix2[0] + pix3[0] + pix4[0])>>2; 850 ((byte *)(out+j))[1] = (pix1[1] + pix2[1] + pix3[1] + pix4[1])>>2; 851 ((byte *)(out+j))[2] = (pix1[2] + pix2[2] + pix3[2] + pix4[2])>>2; 852 ((byte *)(out+j))[3] = (pix1[3] + pix2[3] + pix3[3] + pix4[3])>>2; 853 } 854 } 855 } 856 857 /* 858 ================ 859 GL_LightScaleTexture 860 861 Scale up the pixel values in a texture to increase the 862 lighting range 863 ================ 864 */ 865 void GL_LightScaleTexture (unsigned *in, int inwidth, int inheight, qboolean only_gamma ) 866 { 867 if ( only_gamma ) 868 { 869 int i, c; 870 byte *p; 871 872 p = (byte *)in; 873 874 c = inwidth*inheight; 875 for (i=0 ; i<c ; i++, p+=4) 876 { 877 p[0] = gammatable[p[0]]; 878 p[1] = gammatable[p[1]]; 879 p[2] = gammatable[p[2]]; 880 } 881 } 882 else 883 { 884 int i, c; 885 byte *p; 886 887 p = (byte *)in; 888 889 c = inwidth*inheight; 890 for (i=0 ; i<c ; i++, p+=4) 891 { 892 p[0] = gammatable[intensitytable[p[0]]]; 893 p[1] = gammatable[intensitytable[p[1]]]; 894 p[2] = gammatable[intensitytable[p[2]]]; 895 } 896 } 897 } 898 899 /* 900 ================ 901 GL_MipMap 902 903 Operates in place, quartering the size of the texture 904 ================ 905 */ 906 void GL_MipMap (byte *in, int width, int height) 907 { 908 int i, j; 909 byte *out; 910 911 width <<=2; 912 height >>= 1; 913 out = in; 914 for (i=0 ; i<height ; i++, in+=width) 915 { 916 for (j=0 ; j<width ; j+=8, out+=4, in+=8) 917 { 918 out[0] = (in[0] + in[4] + in[width+0] + in[width+4])>>2; 919 out[1] = (in[1] + in[5] + in[width+1] + in[width+5])>>2; 920 out[2] = (in[2] + in[6] + in[width+2] + in[width+6])>>2; 921 out[3] = (in[3] + in[7] + in[width+3] + in[width+7])>>2; 922 } 923 } 924 } 925 926 /* 927 =============== 928 GL_Upload32 929 930 Returns has_alpha 931 =============== 932 */ 933 void GL_BuildPalettedTexture( unsigned char *paletted_texture, unsigned char *scaled, int scaled_width, int scaled_height ) 934 { 935 int i; 936 937 for ( i = 0; i < scaled_width * scaled_height; i++ ) 938 { 939 unsigned int r, g, b, c; 940 941 r = ( scaled[0] >> 3 ) & 31; 942 g = ( scaled[1] >> 2 ) & 63; 943 b = ( scaled[2] >> 3 ) & 31; 944 945 c = r | ( g << 5 ) | ( b << 11 ); 946 947 paletted_texture[i] = gl_state.d_16to8table[c]; 948 949 scaled += 4; 950 } 951 } 952 953 int upload_width, upload_height; 954 qboolean uploaded_paletted; 955 956 qboolean GL_Upload32 (unsigned *data, int width, int height, qboolean mipmap) 957 { 958 int samples; 959 unsigned scaled[256*256]; 960 unsigned char paletted_texture[256*256]; 961 int scaled_width, scaled_height; 962 int i, c; 963 byte *scan; 964 int comp; 965 966 uploaded_paletted = false; 967 968 for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1) 969 ; 970 if (gl_round_down->value && scaled_width > width && mipmap) 971 scaled_width >>= 1; 972 for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1) 973 ; 974 if (gl_round_down->value && scaled_height > height && mipmap) 975 scaled_height >>= 1; 976 977 // let people sample down the world textures for speed 978 if (mipmap) 979 { 980 scaled_width >>= (int)gl_picmip->value; 981 scaled_height >>= (int)gl_picmip->value; 982 } 983 984 // don't ever bother with >256 textures 985 if (scaled_width > 256) 986 scaled_width = 256; 987 if (scaled_height > 256) 988 scaled_height = 256; 989 990 if (scaled_width < 1) 991 scaled_width = 1; 992 if (scaled_height < 1) 993 scaled_height = 1; 994 995 upload_width = scaled_width; 996 upload_height = scaled_height; 997 998 if (scaled_width * scaled_height > sizeof(scaled)/4) 999 ri.Sys_Error (ERR_DROP, "GL_Upload32: too big"); 1000 1001 // scan the texture for any non-255 alpha 1002 c = width*height; 1003 scan = ((byte *)data) + 3; 1004 samples = gl_solid_format; 1005 for (i=0 ; i<c ; i++, scan += 4) 1006 { 1007 if ( *scan != 255 ) 1008 { 1009 samples = gl_alpha_format; 1010 break; 1011 } 1012 } 1013 1014 if (samples == gl_solid_format) 1015 comp = gl_tex_solid_format; 1016 else if (samples == gl_alpha_format) 1017 comp = gl_tex_alpha_format; 1018 else { 1019 ri.Con_Printf (PRINT_ALL, 1020 "Unknown number of texture components %i\n", 1021 samples); 1022 comp = samples; 1023 } 1024 1025 #if 0 1026 if (mipmap) 1027 gluBuild2DMipmaps (GL_TEXTURE_2D, samples, width, height, GL_RGBA, GL_UNSIGNED_BYTE, trans); 1028 else if (scaled_width == width && scaled_height == height) 1029 qglTexImage2D (GL_TEXTURE_2D, 0, comp, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans); 1030 else 1031 { 1032 gluScaleImage (GL_RGBA, width, height, GL_UNSIGNED_BYTE, trans, 1033 scaled_width, scaled_height, GL_UNSIGNED_BYTE, scaled); 1034 qglTexImage2D (GL_TEXTURE_2D, 0, comp, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled); 1035 } 1036 #else 1037 1038 if (scaled_width == width && scaled_height == height) 1039 { 1040 if (!mipmap) 1041 { 1042 if ( qglColorTableEXT && gl_ext_palettedtexture->value && samples == gl_solid_format ) 1043 { 1044 uploaded_paletted = true; 1045 GL_BuildPalettedTexture( paletted_texture, ( unsigned char * ) data, scaled_width, scaled_height ); 1046 qglTexImage2D( GL_TEXTURE_2D, 1047 0, 1048 GL_COLOR_INDEX8_EXT, 1049 scaled_width, 1050 scaled_height, 1051 0, 1052 GL_COLOR_INDEX, 1053 GL_UNSIGNED_BYTE, 1054 paletted_texture ); 1055 } 1056 else 1057 { 1058 qglTexImage2D (GL_TEXTURE_2D, 0, comp, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); 1059 } 1060 goto done; 1061 } 1062 memcpy (scaled, data, width*height*4); 1063 } 1064 else 1065 GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height); 1066 1067 GL_LightScaleTexture (scaled, scaled_width, scaled_height, !mipmap ); 1068 1069 if ( qglColorTableEXT && gl_ext_palettedtexture->value && ( samples == gl_solid_format ) ) 1070 { 1071 uploaded_paletted = true; 1072 GL_BuildPalettedTexture( paletted_texture, ( unsigned char * ) scaled, scaled_width, scaled_height ); 1073 qglTexImage2D( GL_TEXTURE_2D, 1074 0, 1075 GL_COLOR_INDEX8_EXT, 1076 scaled_width, 1077 scaled_height, 1078 0, 1079 GL_COLOR_INDEX, 1080 GL_UNSIGNED_BYTE, 1081 paletted_texture ); 1082 } 1083 else 1084 { 1085 qglTexImage2D( GL_TEXTURE_2D, 0, comp, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled ); 1086 } 1087 1088 if (mipmap) 1089 { 1090 int miplevel; 1091 1092 miplevel = 0; 1093 while (scaled_width > 1 || scaled_height > 1) 1094 { 1095 GL_MipMap ((byte *)scaled, scaled_width, scaled_height); 1096 scaled_width >>= 1; 1097 scaled_height >>= 1; 1098 if (scaled_width < 1) 1099 scaled_width = 1; 1100 if (scaled_height < 1) 1101 scaled_height = 1; 1102 miplevel++; 1103 if ( qglColorTableEXT && gl_ext_palettedtexture->value && samples == gl_solid_format ) 1104 { 1105 uploaded_paletted = true; 1106 GL_BuildPalettedTexture( paletted_texture, ( unsigned char * ) scaled, scaled_width, scaled_height ); 1107 qglTexImage2D( GL_TEXTURE_2D, 1108 miplevel, 1109 GL_COLOR_INDEX8_EXT, 1110 scaled_width, 1111 scaled_height, 1112 0, 1113 GL_COLOR_INDEX, 1114 GL_UNSIGNED_BYTE, 1115 paletted_texture ); 1116 } 1117 else 1118 { 1119 qglTexImage2D (GL_TEXTURE_2D, miplevel, comp, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled); 1120 } 1121 } 1122 } 1123 done: ; 1124 #endif 1125 1126 1127 if (mipmap) 1128 { 1129 qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); 1130 qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); 1131 } 1132 else 1133 { 1134 qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max); 1135 qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); 1136 } 1137 1138 return (samples == gl_alpha_format); 1139 } 1140 1141 /* 1142 =============== 1143 GL_Upload8 1144 1145 Returns has_alpha 1146 =============== 1147 */ 1148 /* 1149 static qboolean IsPowerOf2( int value ) 1150 { 1151 int i = 1; 1152 1153 1154 while ( 1 ) 1155 { 1156 if ( value == i ) 1157 return true; 1158 if ( i > value ) 1159 return false; 1160 i <<= 1; 1161 } 1162 } 1163 */ 1164 1165 qboolean GL_Upload8 (byte *data, int width, int height, qboolean mipmap, qboolean is_sky ) 1166 { 1167 unsigned trans[512*256]; 1168 int i, s; 1169 int p; 1170 1171 s = width*height; 1172 1173 if (s > sizeof(trans)/4) 1174 ri.Sys_Error (ERR_DROP, "GL_Upload8: too large"); 1175 1176 if ( qglColorTableEXT && 1177 gl_ext_palettedtexture->value && 1178 is_sky ) 1179 { 1180 qglTexImage2D( GL_TEXTURE_2D, 1181 0, 1182 GL_COLOR_INDEX8_EXT, 1183 width, 1184 height, 1185 0, 1186 GL_COLOR_INDEX, 1187 GL_UNSIGNED_BYTE, 1188 data ); 1189 1190 qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max); 1191 qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); 1192 } 1193 else 1194 { 1195 for (i=0 ; i<s ; i++) 1196 { 1197 p = data[i]; 1198 trans[i] = d_8to24table[p]; 1199 1200 if (p == 255) 1201 { // transparent, so scan around for another color 1202 // to avoid alpha fringes 1203 // FIXME: do a full flood fill so mips work... 1204 if (i > width && data[i-width] != 255) 1205 p = data[i-width]; 1206 else if (i < s-width && data[i+width] != 255) 1207 p = data[i+width]; 1208 else if (i > 0 && data[i-1] != 255) 1209 p = data[i-1]; 1210 else if (i < s-1 && data[i+1] != 255) 1211 p = data[i+1]; 1212 else 1213 p = 0; 1214 // copy rgb components 1215 ((byte *)&trans[i])[0] = ((byte *)&d_8to24table[p])[0]; 1216 ((byte *)&trans[i])[1] = ((byte *)&d_8to24table[p])[1]; 1217 ((byte *)&trans[i])[2] = ((byte *)&d_8to24table[p])[2]; 1218 } 1219 } 1220 1221 return GL_Upload32 (trans, width, height, mipmap); 1222 } 1223 } 1224 1225 1226 /* 1227 ================ 1228 GL_LoadPic 1229 1230 This is also used as an entry point for the generated r_notexture 1231 ================ 1232 */ 1233 image_t *GL_LoadPic (char *name, byte *pic, int width, int height, imagetype_t type, int bits) 1234 { 1235 image_t *image; 1236 int i; 1237 1238 // find a free image_t 1239 for (i=0, image=gltextures ; i<numgltextures ; i++,image++) 1240 { 1241 if (!image->texnum) 1242 break; 1243 } 1244 if (i == numgltextures) 1245 { 1246 if (numgltextures == MAX_GLTEXTURES) 1247 ri.Sys_Error (ERR_DROP, "MAX_GLTEXTURES"); 1248 numgltextures++; 1249 } 1250 image = &gltextures[i]; 1251 1252 if (strlen(name) >= sizeof(image->name)) 1253 ri.Sys_Error (ERR_DROP, "Draw_LoadPic: \"%s\" is too long", name); 1254 strcpy (image->name, name); 1255 image->registration_sequence = registration_sequence; 1256 1257 image->width = width; 1258 image->height = height; 1259 image->type = type; 1260 1261 if (type == it_skin && bits == 8) 1262 R_FloodFillSkin(pic, width, height); 1263 1264 // load little pics into the scrap 1265 if (image->type == it_pic && bits == 8 1266 && image->width < 64 && image->height < 64) 1267 { 1268 int x, y; 1269 int i, j, k; 1270 int texnum; 1271 1272 texnum = Scrap_AllocBlock (image->width, image->height, &x, &y); 1273 if (texnum == -1) 1274 goto nonscrap; 1275 scrap_dirty = true; 1276 1277 // copy the texels into the scrap block 1278 k = 0; 1279 for (i=0 ; i<image->height ; i++) 1280 for (j=0 ; j<image->width ; j++, k++) 1281 scrap_texels[texnum][(y+i)*BLOCK_WIDTH + x + j] = pic[k]; 1282 image->texnum = TEXNUM_SCRAPS + texnum; 1283 image->scrap = true; 1284 image->has_alpha = true; 1285 image->sl = (x+0.01)/(float)BLOCK_WIDTH; 1286 image->sh = (x+image->width-0.01)/(float)BLOCK_WIDTH; 1287 image->tl = (y+0.01)/(float)BLOCK_WIDTH; 1288 image->th = (y+image->height-0.01)/(float)BLOCK_WIDTH; 1289 } 1290 else 1291 { 1292 nonscrap: 1293 image->scrap = false; 1294 image->texnum = TEXNUM_IMAGES + (image - gltextures); 1295 GL_Bind(image->texnum); 1296 if (bits == 8) 1297 image->has_alpha = GL_Upload8 (pic, width, height, (image->type != it_pic && image->type != it_sky), image->type == it_sky ); 1298 else 1299 image->has_alpha = GL_Upload32 ((unsigned *)pic, width, height, (image->type != it_pic && image->type != it_sky) ); 1300 image->upload_width = upload_width; // after power of 2 and scales 1301 image->upload_height = upload_height; 1302 image->paletted = uploaded_paletted; 1303 image->sl = 0; 1304 image->sh = 1; 1305 image->tl = 0; 1306 image->th = 1; 1307 } 1308 1309 return image; 1310 } 1311 1312 1313 /* 1314 ================ 1315 GL_LoadWal 1316 ================ 1317 */ 1318 image_t *GL_LoadWal (char *name) 1319 { 1320 miptex_t *mt; 1321 int width, height, ofs; 1322 image_t *image; 1323 1324 ri.FS_LoadFile (name, (void **)&mt); 1325 if (!mt) 1326 { 1327 ri.Con_Printf (PRINT_ALL, "GL_FindImage: can't load %s\n", name); 1328 return r_notexture; 1329 } 1330 1331 width = LittleLong (mt->width); 1332 height = LittleLong (mt->height); 1333 ofs = LittleLong (mt->offsets[0]); 1334 1335 image = GL_LoadPic (name, (byte *)mt + ofs, width, height, it_wall, 8); 1336 1337 ri.FS_FreeFile ((void *)mt); 1338 1339 return image; 1340 } 1341 1342 /* 1343 =============== 1344 GL_FindImage 1345 1346 Finds or loads the given image 1347 =============== 1348 */ 1349 image_t *GL_FindImage (char *name, imagetype_t type) 1350 { 1351 image_t *image; 1352 int i, len; 1353 byte *pic, *palette; 1354 int width, height; 1355 1356 if (!name) 1357 return NULL; // ri.Sys_Error (ERR_DROP, "GL_FindImage: NULL name"); 1358 len = strlen(name); 1359 if (len<5) 1360 return NULL; // ri.Sys_Error (ERR_DROP, "GL_FindImage: bad name: %s", name); 1361 1362 // look for it 1363 for (i=0, image=gltextures ; i<numgltextures ; i++,image++) 1364 { 1365 if (!strcmp(name, image->name)) 1366 { 1367 image->registration_sequence = registration_sequence; 1368 return image; 1369 } 1370 } 1371 1372 // 1373 // load the pic from disk 1374 // 1375 pic = NULL; 1376 palette = NULL; 1377 if (!strcmp(name+len-4, ".pcx")) 1378 { 1379 LoadPCX (name, &pic, &palette, &width, &height); 1380 if (!pic) 1381 return NULL; // ri.Sys_Error (ERR_DROP, "GL_FindImage: can't load %s", name); 1382 image = GL_LoadPic (name, pic, width, height, type, 8); 1383 } 1384 else if (!strcmp(name+len-4, ".wal")) 1385 { 1386 image = GL_LoadWal (name); 1387 } 1388 else if (!strcmp(name+len-4, ".tga")) 1389 { 1390 LoadTGA (name, &pic, &width, &height); 1391 if (!pic) 1392 return NULL; // ri.Sys_Error (ERR_DROP, "GL_FindImage: can't load %s", name); 1393 image = GL_LoadPic (name, pic, width, height, type, 32); 1394 } 1395 else 1396 return NULL; // ri.Sys_Error (ERR_DROP, "GL_FindImage: bad extension on: %s", name); 1397 1398 1399 if (pic) 1400 free(pic); 1401 if (palette) 1402 free(palette); 1403 1404 return image; 1405 } 1406 1407 1408 1409 /* 1410 =============== 1411 R_RegisterSkin 1412 =============== 1413 */ 1414 struct image_s *R_RegisterSkin (char *name) 1415 { 1416 return GL_FindImage (name, it_skin); 1417 } 1418 1419 1420 /* 1421 ================ 1422 GL_FreeUnusedImages 1423 1424 Any image that was not touched on this registration sequence 1425 will be freed. 1426 ================ 1427 */ 1428 void GL_FreeUnusedImages (void) 1429 { 1430 int i; 1431 image_t *image; 1432 1433 // never free r_notexture or particle texture 1434 r_notexture->registration_sequence = registration_sequence; 1435 r_particletexture->registration_sequence = registration_sequence; 1436 1437 for (i=0, image=gltextures ; i<numgltextures ; i++, image++) 1438 { 1439 if (image->registration_sequence == registration_sequence) 1440 continue; // used this sequence 1441 if (!image->registration_sequence) 1442 continue; // free image_t slot 1443 if (image->type == it_pic) 1444 continue; // don't free pics 1445 // free it 1446 qglDeleteTextures (1, &image->texnum); 1447 memset (image, 0, sizeof(*image)); 1448 } 1449 } 1450 1451 1452 /* 1453 =============== 1454 Draw_GetPalette 1455 =============== 1456 */ 1457 int Draw_GetPalette (void) 1458 { 1459 int i; 1460 int r, g, b; 1461 unsigned v; 1462 byte *pic, *pal; 1463 int width, height; 1464 1465 // get the palette 1466 1467 LoadPCX ("pics/colormap.pcx", &pic, &pal, &width, &height); 1468 if (!pal) 1469 ri.Sys_Error (ERR_FATAL, "Couldn't load pics/colormap.pcx"); 1470 1471 for (i=0 ; i<256 ; i++) 1472 { 1473 r = pal[i*3+0]; 1474 g = pal[i*3+1]; 1475 b = pal[i*3+2]; 1476 1477 v = (255<<24) + (r<<0) + (g<<8) + (b<<16); 1478 d_8to24table[i] = LittleLong(v); 1479 } 1480 1481 d_8to24table[255] &= LittleLong(0xffffff); // 255 is transparent 1482 1483 free (pic); 1484 free (pal); 1485 1486 return 0; 1487 } 1488 1489 1490 /* 1491 =============== 1492 GL_InitImages 1493 =============== 1494 */ 1495 void GL_InitImages (void) 1496 { 1497 int i, j; 1498 float g = vid_gamma->value; 1499 1500 registration_sequence = 1; 1501 1502 // init intensity conversions 1503 intensity = ri.Cvar_Get ("intensity", "2", 0); 1504 1505 if ( intensity->value <= 1 ) 1506 ri.Cvar_Set( "intensity", "1" ); 1507 1508 gl_state.inverse_intensity = 1 / intensity->value; 1509 1510 Draw_GetPalette (); 1511 1512 if ( qglColorTableEXT ) 1513 { 1514 ri.FS_LoadFile( "pics/16to8.dat", &gl_state.d_16to8table ); 1515 if ( !gl_state.d_16to8table ) 1516 ri.Sys_Error( ERR_FATAL, "Couldn't load pics/16to8.pcx"); 1517 } 1518 1519 if ( gl_config.renderer & ( GL_RENDERER_VOODOO | GL_RENDERER_VOODOO2 ) ) 1520 { 1521 g = 1.0F; 1522 } 1523 1524 for ( i = 0; i < 256; i++ ) 1525 { 1526 if ( g == 1 ) 1527 { 1528 gammatable[i] = i; 1529 } 1530 else 1531 { 1532 float inf; 1533 1534 inf = 255 * pow ( (i+0.5)/255.5 , g ) + 0.5; 1535 if (inf < 0) 1536 inf = 0; 1537 if (inf > 255) 1538 inf = 255; 1539 gammatable[i] = inf; 1540 } 1541 } 1542 1543 for (i=0 ; i<256 ; i++) 1544 { 1545 j = i*intensity->value; 1546 if (j > 255) 1547 j = 255; 1548 intensitytable[i] = j; 1549 } 1550 } 1551 1552 /* 1553 =============== 1554 GL_ShutdownImages 1555 =============== 1556 */ 1557 void GL_ShutdownImages (void) 1558 { 1559 int i; 1560 image_t *image; 1561 1562 for (i=0, image=gltextures ; i<numgltextures ; i++, image++) 1563 { 1564 if (!image->registration_sequence) 1565 continue; // free image_t slot 1566 // free it 1567 qglDeleteTextures (1, &image->texnum); 1568 memset (image, 0, sizeof(*image)); 1569 } 1570 } 1571