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 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 // for jpeglib
26 #define HAVE_PROTOTYPES
27
28 #include "r_local.h"
29
30 #if defined HAVE_JPEG_JPEGLIB_H
31 #include "jpeg/jpeglib.h"
32 #else
33 #include "jpeglib.h"
34 #endif
35
36 image_t gltextures[MAX_GLTEXTURES];
37 image_t *r_mirrortexture;
38 image_t *r_depthtexture;
39 image_t *r_depthtexture2;
40 int numgltextures;
41 int base_textureid; // gltextures[i] = base_textureid+i
42
43 extern cvar_t *cl_hudimage1; //custom huds
44 extern cvar_t *cl_hudimage2;
45
46 unsigned d_8to24table[256];
47
48 qboolean GL_Upload8 (byte *data, int width, int height, int picmip, qboolean filter);
49 qboolean GL_Upload32 (byte *data, int width, int height, int picmip, qboolean filter, qboolean force_standard_mipmap);
50
51 int gl_solid_format = 3;
52 int gl_alpha_format = 4;
53
54 int gl_tex_solid_format = 3;
55 int gl_tex_alpha_format = 4;
56
57 int gl_filter_min = GL_LINEAR_MIPMAP_LINEAR;
58 int gl_filter_max = GL_LINEAR;
59
R_InitImageSubsystem(void)60 void R_InitImageSubsystem(void)
61 {
62 int max_aniso;
63
64 if ( strstr( gl_config.extensions_string, "GL_ARB_multitexture" ) )
65 {
66 Com_Printf ("...using GL_ARB_multitexture\n" );
67 qglMTexCoord2fARB = ( void * ) qwglGetProcAddress( "glMultiTexCoord2fARB" );
68 qglMTexCoord3fARB = ( void * ) qwglGetProcAddress( "glMultiTexCoord3fARB" );
69 qglMultiTexCoord3fvARB = (void*)qwglGetProcAddress("glMultiTexCoord3fvARB");
70 qglActiveTextureARB = ( void * ) qwglGetProcAddress( "glActiveTextureARB" );
71 qglClientActiveTextureARB = ( void * ) qwglGetProcAddress( "glClientActiveTextureARB" );
72 GL_TEXTURE0 = GL_TEXTURE0_ARB;
73 GL_TEXTURE1 = GL_TEXTURE1_ARB;
74 GL_TEXTURE2 = GL_TEXTURE2_ARB;
75 GL_TEXTURE3 = GL_TEXTURE3_ARB;
76 GL_TEXTURE4 = GL_TEXTURE4_ARB;
77 GL_TEXTURE5 = GL_TEXTURE5_ARB;
78 GL_TEXTURE6 = GL_TEXTURE6_ARB;
79 GL_TEXTURE7 = GL_TEXTURE7_ARB;
80 }
81 else
82 {
83 Com_Error (ERR_FATAL, "...GL_ARB_multitexture not found\n" );
84 }
85
86 gl_config.mtexcombine = false;
87 if ( strstr( gl_config.extensions_string, "GL_ARB_texture_env_combine" ) )
88 {
89 Com_Printf( "...using GL_ARB_texture_env_combine\n" );
90 gl_config.mtexcombine = true;
91 }
92 else
93 {
94 Com_Printf( "...GL_ARB_texture_env_combine not found\n" );
95 }
96 if ( !gl_config.mtexcombine )
97 {
98 if ( strstr( gl_config.extensions_string, "GL_EXT_texture_env_combine" ) )
99 {
100 Com_Printf( "...using GL_EXT_texture_env_combine\n" );
101 gl_config.mtexcombine = true;
102 }
103 else
104 {
105 Com_Printf( "...GL_EXT_texture_env_combine not found\n" );
106 }
107 }
108
109 if (strstr(gl_config.extensions_string, "GL_EXT_texture_filter_anisotropic"))
110 {
111 qglGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_aniso);
112
113 r_ext_max_anisotropy = Cvar_Get("r_ext_max_anisotropy", "1", CVAR_ARCHIVE );
114 Cvar_SetValue("r_ext_max_anisotropy", max_aniso);
115
116 r_anisotropic = Cvar_Get("r_anisotropic", "1", CVAR_ARCHIVE);
117 if (r_anisotropic->integer >= r_ext_max_anisotropy->integer)
118 Cvar_SetValue("r_anisotropic", r_ext_max_anisotropy->integer);
119 if (r_anisotropic->integer <= 0)
120 Cvar_SetValue("r_anisotropic", 1);
121
122 r_alphamasked_anisotropic = Cvar_Get("r_alphamasked_anisotropic", "1", CVAR_ARCHIVE);
123 if (r_alphamasked_anisotropic->integer >= r_ext_max_anisotropy->integer)
124 Cvar_SetValue("r_alphamasked_anisotropic", r_ext_max_anisotropy->integer);
125 if (r_alphamasked_anisotropic->integer <= 0)
126 Cvar_SetValue("r_alphamasked_anisotropic", 1);
127
128 if (r_anisotropic->integer == 1 && r_alphamasked_anisotropic->integer == 1)
129 Com_Printf("...ignoring GL_EXT_texture_filter_anisotropic\n");
130 else
131 Com_Printf("...using GL_EXT_texture_filter_anisotropic\n");
132 }
133 else
134 {
135 Com_Printf("...GL_EXT_texture_filter_anisotropic not found\n");
136 r_anisotropic = Cvar_Get("r_anisotropic", "0", CVAR_ARCHIVE);
137 r_alphamasked_anisotropic = Cvar_Get("r_alphamasked_anisotropic", "0", CVAR_ARCHIVE);
138 r_ext_max_anisotropy = Cvar_Get("r_ext_max_anisotropy", "0", CVAR_ARCHIVE);
139 }
140 }
141
142 GLenum bFunc1 = -1;
143 GLenum bFunc2 = -1;
GL_BlendFunction(GLenum sfactor,GLenum dfactor)144 void GL_BlendFunction (GLenum sfactor, GLenum dfactor)
145 {
146 if (sfactor!=bFunc1 || dfactor!=bFunc2)
147 {
148 bFunc1 = sfactor;
149 bFunc2 = dfactor;
150
151 qglBlendFunc(bFunc1, bFunc2);
152 }
153 }
154
155 GLenum shadeModelMode = -1;
156
GL_ShadeModel(GLenum mode)157 void GL_ShadeModel (GLenum mode)
158 {
159 if (mode!=shadeModelMode)
160 {
161 shadeModelMode = mode;
162 qglShadeModel(mode);
163 }
164 }
165
166 // FIXME:
167 // This centralized texture bind batching system is a great idea if you use it
168 // *everywhere*. Otherwise you just end up binding a texture elsewhere and
169 // this system doesn't know you've done it, so when you count on this system
170 // to bindanother texture, it doesn't know it has to, and it'll happily let
171 // you use the wrong texture. Anywhere we use glActiveTexture and
172 // glBindTexture directly can potentially screw things up.
173
GL_EnableMultitexture(qboolean enable)174 void GL_EnableMultitexture( qboolean enable )
175 {
176 if ( !qglActiveTextureARB )
177 return;
178
179 if ( enable )
180 {
181 GL_SelectTexture( GL_TEXTURE1 );
182 qglEnable( GL_TEXTURE_2D );
183 GL_TexEnv( GL_REPLACE );
184
185 GL_SelectTexture( GL_TEXTURE2 );
186 qglEnable( GL_TEXTURE_2D );
187 GL_TexEnv( GL_REPLACE );
188
189 GL_SelectTexture( GL_TEXTURE3 );
190 qglEnable( GL_TEXTURE_2D );
191 GL_TexEnv( GL_REPLACE );
192 }
193 else
194 {
195 GL_SelectTexture( GL_TEXTURE1 );
196 qglDisable( GL_TEXTURE_2D );
197 GL_TexEnv( GL_REPLACE );
198
199 GL_SelectTexture( GL_TEXTURE2 );
200 qglDisable( GL_TEXTURE_2D );
201 GL_TexEnv( GL_REPLACE );
202
203 GL_SelectTexture( GL_TEXTURE3 );
204 qglDisable( GL_TEXTURE_2D );
205 GL_TexEnv( GL_REPLACE );
206 }
207 GL_SelectTexture( GL_TEXTURE0 );
208 GL_TexEnv( GL_REPLACE );
209 }
210
GL_SelectTexture(GLenum texture)211 void GL_SelectTexture( GLenum texture )
212 {
213 int tmu;
214
215 if ( !qglActiveTextureARB )
216 return;
217
218 if ( texture == GL_TEXTURE0 )
219 {
220 tmu = 0;
221 }
222 else
223 {
224 tmu = 1;
225 }
226
227 if ( tmu == gl_state.currenttmu )
228 {
229 return;
230 }
231
232 gl_state.currenttmu = tmu;
233
234 if ( qglActiveTextureARB )
235 {
236 qglActiveTextureARB( texture );
237 qglClientActiveTextureARB( texture );
238 }
239 }
240
GL_TexEnv(GLenum mode)241 void GL_TexEnv( GLenum mode )
242 {
243 static int lastmodes[2] = { -1, -1 };
244
245 if ( mode != lastmodes[gl_state.currenttmu] )
246 {
247 qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode );
248 lastmodes[gl_state.currenttmu] = mode;
249 }
250 }
251
GL_Bind(int texnum)252 void GL_Bind (int texnum)
253 {
254 extern image_t *draw_chars;
255
256 if (gl_nobind->integer && draw_chars) // performance evaluation option
257 texnum = draw_chars->texnum;
258 if ( gl_state.currenttextures[gl_state.currenttmu] == texnum)
259 return;
260 gl_state.currenttextures[gl_state.currenttmu] = texnum;
261 qglBindTexture (GL_TEXTURE_2D, texnum);
262 }
263
GL_MBind(GLenum target,int texnum)264 void GL_MBind( GLenum target, int texnum )
265 {
266 GL_SelectTexture( target );
267 if ( target == GL_TEXTURE0 )
268 {
269 if ( gl_state.currenttextures[0] == texnum )
270 return;
271 }
272 else
273 {
274 if ( gl_state.currenttextures[1] == texnum )
275 return;
276 }
277 GL_Bind( texnum );
278 }
279
280 typedef struct
281 {
282 char *name;
283 int minimize, maximize;
284 } glmode_t;
285
286 glmode_t modes[] = {
287 {"GL_NEAREST", GL_NEAREST, GL_NEAREST},
288 {"GL_LINEAR", GL_LINEAR, GL_LINEAR},
289 {"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST},
290 {"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR},
291 {"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST},
292 {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
293 };
294
295 #define NUM_GL_MODES (sizeof(modes) / sizeof (glmode_t))
296
297 typedef struct
298 {
299 char *name;
300 int mode;
301 } gltmode_t;
302
303 gltmode_t gl_alpha_modes[] = {
304 {"default", 4},
305 {"GL_RGBA", GL_RGBA},
306 {"GL_RGBA8", GL_RGBA8},
307 {"GL_RGB5_A1", GL_RGB5_A1},
308 {"GL_RGBA4", GL_RGBA4},
309 {"GL_RGBA2", GL_RGBA2},
310 };
311
312 #define NUM_GL_ALPHA_MODES (sizeof(gl_alpha_modes) / sizeof (gltmode_t))
313
314 gltmode_t gl_solid_modes[] = {
315 {"default", 3},
316 {"GL_RGB", GL_RGB},
317 {"GL_RGB8", GL_RGB8},
318 {"GL_RGB5", GL_RGB5},
319 {"GL_RGB4", GL_RGB4},
320 {"GL_R3_G3_B2", GL_R3_G3_B2},
321 #ifdef GL_RGB2_EXT
322 {"GL_RGB2", GL_RGB2_EXT},
323 #endif
324 };
325
326 #define NUM_GL_SOLID_MODES (sizeof(gl_solid_modes) / sizeof (gltmode_t))
327
328 /*
329 ===============
330 GL_TextureMode
331 ===============
332 */
GL_TextureMode(char * string)333 void GL_TextureMode( char *string )
334 {
335 int i;
336 image_t *glt;
337
338 for (i=0 ; i< NUM_GL_MODES ; i++)
339 {
340 if ( !Q_strcasecmp( modes[i].name, string ) )
341 break;
342 }
343
344 if (i == NUM_GL_MODES)
345 {
346 Com_Printf ("bad filter name\n");
347 return;
348 }
349
350 gl_filter_min = modes[i].minimize;
351 gl_filter_max = modes[i].maximize;
352
353 // change all the existing mipmap texture objects
354 for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
355 {
356 if (glt->type != it_pic && glt->type != it_particle && glt->type != it_sky )
357 {
358 GL_Bind (glt->texnum);
359 qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
360 qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
361 }
362 }
363 }
364
365 /*
366 ===============
367 GL_TextureAlphaMode
368 ===============
369 */
GL_TextureAlphaMode(char * string)370 void GL_TextureAlphaMode( char *string )
371 {
372 int i;
373
374 for (i=0 ; i< NUM_GL_ALPHA_MODES ; i++)
375 {
376 if ( !Q_strcasecmp( gl_alpha_modes[i].name, string ) )
377 break;
378 }
379
380 if (i == NUM_GL_ALPHA_MODES)
381 {
382 Com_Printf ("bad alpha texture mode name\n");
383 return;
384 }
385
386 gl_tex_alpha_format = gl_alpha_modes[i].mode;
387 }
388
389 /*
390 ===============
391 GL_TextureSolidMode
392 ===============
393 */
GL_TextureSolidMode(char * string)394 void GL_TextureSolidMode( char *string )
395 {
396 int i;
397
398 for (i=0 ; i< NUM_GL_SOLID_MODES ; i++)
399 {
400 if ( !Q_strcasecmp( gl_solid_modes[i].name, string ) )
401 break;
402 }
403
404 if (i == NUM_GL_SOLID_MODES)
405 {
406 Com_Printf ("bad solid texture mode name\n");
407 return;
408 }
409
410 gl_tex_solid_format = gl_solid_modes[i].mode;
411 }
412
413 /*
414 ===============
415 GL_ImageList_f
416 ===============
417 */
GL_ImageList_f(void)418 void GL_ImageList_f (void)
419 {
420 int i;
421 image_t *image;
422 int texels;
423 const char *palstrings[2] =
424 {
425 "RGB",
426 "PAL"
427 };
428
429 Com_Printf ("------------------\n");
430 texels = 0;
431
432 for (i=0, image=gltextures ; i<numgltextures ; i++, image++)
433 {
434 if (image->texnum <= 0)
435 continue;
436 texels += image->upload_width*image->upload_height;
437 switch (image->type)
438 {
439 case it_skin:
440 Com_Printf ("M");
441 break;
442 case it_sprite:
443 Com_Printf ("S");
444 break;
445 case it_wall:
446 Com_Printf ("W");
447 break;
448 case it_pic:
449 Com_Printf ("P");
450 break;
451 case it_particle:
452 Com_Printf ("A");
453 break;
454 default:
455 Com_Printf (" ");
456 break;
457 }
458
459 Com_Printf (" %3i %3i %s: %s\n",
460 image->upload_width, image->upload_height, palstrings[image->paletted], image->name);
461 }
462 Com_Printf ("Total texel count (not counting mipmaps): %i\n", texels);
463 }
464
465
466 /*
467 =============================================================================
468
469 scrap allocation
470
471 Allocate all the little status bar obejcts into a single texture
472 to crutch up inefficient hardware / drivers
473
474 =============================================================================
475 */
476
477 #define MAX_SCRAPS 1
478 #define BLOCK_WIDTH 1024
479 #define BLOCK_HEIGHT 512
480
481 int scrap_allocated[MAX_SCRAPS][BLOCK_WIDTH];
482 byte scrap_texels[MAX_SCRAPS][BLOCK_WIDTH*BLOCK_HEIGHT*4];
483 qboolean scrap_dirty;
484
485 // returns a texture number and the position inside it
Scrap_AllocBlock(int w,int h,int * x,int * y)486 int Scrap_AllocBlock (int w, int h, int *x, int *y)
487 {
488 int i, j;
489 int best, best2;
490 int texnum;
491
492 for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++)
493 {
494 best = BLOCK_HEIGHT;
495
496 for (i=0 ; i<BLOCK_WIDTH-w ; i++)
497 {
498 best2 = 0;
499
500 for (j=0 ; j<w ; j++)
501 {
502 if (scrap_allocated[texnum][i+j] >= best)
503 break;
504 if (scrap_allocated[texnum][i+j] > best2)
505 best2 = scrap_allocated[texnum][i+j];
506 }
507 if (j == w)
508 { // this is a valid spot
509 *x = i;
510 *y = best = best2;
511 }
512 }
513
514 if (best + h > BLOCK_HEIGHT)
515 continue;
516
517 for (i=0 ; i<w ; i++)
518 scrap_allocated[texnum][*x + i] = best + h;
519
520 return texnum;
521 }
522
523 return -1;
524 /* Sys_Error ("Scrap_AllocBlock: full");*/
525 }
526
527 int scrap_uploads;
528
Scrap_Upload(void)529 void Scrap_Upload (void)
530 {
531 GL_Bind(TEXNUM_SCRAPS);
532 GL_Upload32 (scrap_texels[scrap_uploads++], BLOCK_WIDTH, BLOCK_HEIGHT, 0, false, true);
533 scrap_dirty = false;
534 }
535
536 //just a guessed size-- this isn't necessarily raw RGBA data, it's the
537 //encoded image data.
538 #define STATIC_RAWDATA_SIZE (1024*1024*4+256)
539 byte static_rawdata[STATIC_RAWDATA_SIZE];
540
541 /*
542 =================================================================
543
544 PCX LOADING
545
546 =================================================================
547 */
548
549
550 /*
551 ==============
552 LoadPCX
553 ==============
554 */
LoadPCX(char * filename,byte ** pic,byte ** palette,int * width,int * height)555 void LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height)
556 {
557 byte *raw;
558 pcx_t *pcx;
559 int x, y;
560 int len;
561 int dataByte, runLength;
562 byte *out, *pix;
563
564 *pic = NULL;
565 *palette = NULL;
566
567 //
568 // load the file
569 //
570 len = FS_LoadFile_TryStatic ( filename, (void **)&raw, static_rawdata,
571 STATIC_RAWDATA_SIZE);
572 if (!raw)
573 {
574 return;
575 }
576
577 //
578 // parse the PCX file
579 //
580 pcx = (pcx_t *)raw;
581
582 pcx->xmin = LittleShort(pcx->xmin);
583 pcx->ymin = LittleShort(pcx->ymin);
584 pcx->xmax = LittleShort(pcx->xmax);
585 pcx->ymax = LittleShort(pcx->ymax);
586 pcx->hres = LittleShort(pcx->hres);
587 pcx->vres = LittleShort(pcx->vres);
588 pcx->bytes_per_line = LittleShort(pcx->bytes_per_line);
589 pcx->palette_type = LittleShort(pcx->palette_type);
590
591 raw = &pcx->data;
592
593 if (pcx->manufacturer != 0x0a
594 || pcx->version != 5
595 || pcx->encoding != 1
596 || pcx->bits_per_pixel != 8
597 || pcx->xmax >= 1024
598 || pcx->ymax >= 512)
599 {
600 Com_Printf ("Bad pcx file %s\n", filename);
601 if ((byte *)pcx != static_rawdata)
602 FS_FreeFile (pcx);
603 return;
604 }
605
606 out = malloc ( (pcx->ymax+1) * (pcx->xmax+1) );
607
608 *pic = out;
609
610 pix = out;
611
612 if (palette)
613 {
614 *palette = malloc(768);
615 memcpy (*palette, (byte *)pcx + len - 768, 768);
616 }
617
618 if (width)
619 *width = pcx->xmax+1;
620 if (height)
621 *height = pcx->ymax+1;
622
623 for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1)
624 {
625 for (x=0 ; x<=pcx->xmax ; )
626 {
627 dataByte = *raw++;
628
629 if ((dataByte & 0xC0) == 0xC0)
630 {
631 runLength = dataByte & 0x3F;
632 dataByte = *raw++;
633 }
634 else
635 runLength = 1;
636
637 while (runLength-- > 0)
638 pix[x++] = dataByte;
639 }
640
641 }
642
643 if ( raw - (byte *)pcx > len)
644 {
645 Com_DPrintf ("PCX file %s was malformed", filename);
646 free (*pic);
647 *pic = NULL;
648 }
649
650 if ((byte *)pcx != static_rawdata)
651 FS_FreeFile (pcx);
652 }
653 /*
654 =================================================================
655
656 JPEG LOADING
657
658 By Robert 'Heffo' Heffernan
659
660 =================================================================
661 */
662
663 static JOCTET eoi_buffer[2] = {(JOCTET)0xFF, (JOCTET)JPEG_EOI};
664 static qboolean crjpg_corrupted;
665
crjpg_null(j_decompress_ptr cinfo)666 void crjpg_null(j_decompress_ptr cinfo)
667 {
668 }
669
crjpg_fill_input_buffer(j_decompress_ptr cinfo)670 int crjpg_fill_input_buffer(j_decompress_ptr cinfo)
671 {
672 Com_Printf("Premature end of JPEG data\n");
673 cinfo->src->next_input_byte = eoi_buffer;
674 cinfo->src->bytes_in_buffer = 2;
675 crjpg_corrupted = true;
676 return 1;
677 }
678
crjpg_skip_input_data(j_decompress_ptr cinfo,long num_bytes)679 void crjpg_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
680 {
681
682 cinfo->src->next_input_byte += (size_t) num_bytes;
683 cinfo->src->bytes_in_buffer -= (size_t) num_bytes;
684
685 if (cinfo->src->bytes_in_buffer < 0)
686 {
687 Com_Printf("Premature end of JPEG data\n");
688 cinfo->src->next_input_byte = eoi_buffer;
689 cinfo->src->bytes_in_buffer = 2;
690 crjpg_corrupted = true;
691 }
692 }
693
crjpg_mem_src(j_decompress_ptr cinfo,byte * mem,int len)694 void crjpg_mem_src(j_decompress_ptr cinfo, byte *mem, int len)
695 {
696 cinfo->src = (struct jpeg_source_mgr *)(*cinfo->mem->alloc_small)((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(struct jpeg_source_mgr));
697 cinfo->src->init_source = crjpg_null;
698 cinfo->src->fill_input_buffer = crjpg_fill_input_buffer;
699 cinfo->src->skip_input_data = crjpg_skip_input_data;
700 cinfo->src->resync_to_restart = jpeg_resync_to_restart;
701 cinfo->src->term_source = crjpg_null;
702 cinfo->src->bytes_in_buffer = len;
703 cinfo->src->next_input_byte = mem;
704 }
705
706 #define DSTATE_START 200 /* after create_decompress */
707 #define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */
708
709 /*
710 ==============
711 LoadJPG
712 ==============
713 */
714 #define STATIC_SCANLINE_SIZE (1024*3)
715 byte static_scanline[STATIC_SCANLINE_SIZE];
LoadJPG(char * filename,byte ** pic,int * width,int * height)716 void LoadJPG (char *filename, byte **pic, int *width, int *height)
717 {
718 struct jpeg_decompress_struct cinfo;
719 struct jpeg_error_mgr jerr;
720 byte *rawdata, *rgbadata, *scanline, *p, *q;
721 int rawsize, i;
722
723 crjpg_corrupted = false;
724 // Load JPEG file into memory
725 rawsize = FS_LoadFile_TryStatic ( filename, (void **)&rawdata,
726 static_rawdata, STATIC_RAWDATA_SIZE);
727 if (!rawdata)
728 {
729 return;
730 }
731
732 // Knightmare- check for bad data
733 if ( rawdata[6] != 'J'
734 || rawdata[7] != 'F'
735 || rawdata[8] != 'I'
736 || rawdata[9] != 'F') {
737 if (rawdata != static_rawdata)
738 FS_FreeFile(rawdata);
739 return;
740 }
741
742 // Initialise libJpeg Object
743 cinfo.err = jpeg_std_error(&jerr);
744 jpeg_create_decompress(&cinfo);
745
746 // Feed JPEG memory into the libJpeg Object
747 crjpg_mem_src(&cinfo, rawdata, rawsize);
748
749 // Process JPEG header
750 jpeg_read_header(&cinfo, true); // bombs out here
751
752 // Start Decompression
753 jpeg_start_decompress(&cinfo);
754
755 // Check Color Components
756 if(cinfo.output_components != 3)
757 {
758 jpeg_destroy_decompress(&cinfo);
759 if (rawdata != static_rawdata)
760 FS_FreeFile(rawdata);
761 return;
762 }
763
764 // Allocate Memory for decompressed image
765 rgbadata = malloc(cinfo.output_width * cinfo.output_height * 4);
766 if(!rgbadata)
767 {
768 jpeg_destroy_decompress(&cinfo);
769 if (rawdata != static_rawdata)
770 FS_FreeFile(rawdata);
771 return;
772 }
773
774 // Pass sizes to output
775 *width = cinfo.output_width; *height = cinfo.output_height;
776
777 // Allocate Scanline buffer
778 if (cinfo.output_width * 3 < STATIC_SCANLINE_SIZE)
779 {
780 scanline = &static_scanline[0];
781 }
782 else
783 {
784 scanline = malloc(cinfo.output_width * 3);
785 if(!scanline)
786 {
787 free(rgbadata);
788 jpeg_destroy_decompress(&cinfo);
789 if (rawdata != static_rawdata)
790 FS_FreeFile(rawdata);
791 return;
792 }
793 }
794
795 // Read Scanlines, and expand from RGB to RGBA
796 q = rgbadata;
797 while(cinfo.output_scanline < cinfo.output_height)
798 {
799 p = scanline;
800 jpeg_read_scanlines(&cinfo, &scanline, 1);
801
802 for(i=0; i<cinfo.output_width; i++)
803 {
804 q[0] = p[0];
805 q[1] = p[1];
806 q[2] = p[2];
807 q[3] = 255;
808
809 p+=3; q+=4;
810 }
811 }
812
813 // Free the scanline buffer
814 if (scanline != &static_scanline[0])
815 free(scanline);
816
817 // Finish Decompression
818 jpeg_finish_decompress(&cinfo);
819
820 // Destroy JPEG object
821 jpeg_destroy_decompress(&cinfo);
822
823 // Free the raw data now that it's done being processed
824 if (rawdata != static_rawdata)
825 FS_FreeFile(rawdata);
826
827 if (crjpg_corrupted)
828 Com_Printf ("JPEG file %s is likely corrupted, please obtain a fresh copy.\n", filename);
829
830 // Return the 'rgbadata'
831 *pic = rgbadata;
832 }
833
834
835 /*
836 =========================================================
837
838 TARGA LOADING
839
840 =========================================================
841 */
842
843 typedef struct _TargaHeader {
844 unsigned char id_length, colormap_type, image_type;
845 unsigned short colormap_index, colormap_length;
846 unsigned char colormap_size;
847 unsigned short x_origin, y_origin, width, height;
848 unsigned char pixel_size, attributes;
849 } TargaHeader;
850
851
852 /*
853 =============
854 LoadTGA
855 =============
856 */
LoadTGA(char * name,byte ** pic,int * width,int * height)857 void LoadTGA (char *name, byte **pic, int *width, int *height)
858 {
859 int columns, rows, numPixels;
860 byte *pixbuf;
861 int row, column;
862 byte *buf_p;
863 byte *buffer;
864 size_t buf_end;
865 int length;
866 TargaHeader targa_header;
867 byte *targa_rgba;
868 byte tmp[2];
869
870 *pic = NULL;
871
872 //
873 // load the file
874 //
875 length = FS_LoadFile_TryStatic ( name, (void **)&buffer,
876 static_rawdata, STATIC_RAWDATA_SIZE);
877 if (!buffer)
878 {
879 return;
880 }
881
882 buf_p = buffer;
883 buf_end = (size_t)(buffer+length);
884
885 #define GET_TGA_BYTE(dest) \
886 {\
887 if ((size_t)buf_p<buf_end)\
888 {\
889 (dest) = *buf_p++;\
890 }\
891 else\
892 {\
893 /* We don't set *pic to NULL, so if the image is mostly intact,
894 * whatever pixels were already there will still show up.
895 */\
896 Com_Printf ("LoadTGA: %s is either truncated or corrupt, please obtain a fresh copy!\n", name);\
897 return;\
898 }\
899 }
900
901 GET_TGA_BYTE (targa_header.id_length);
902 GET_TGA_BYTE (targa_header.colormap_type);
903 GET_TGA_BYTE (targa_header.image_type);
904
905 GET_TGA_BYTE (tmp[0]);
906 GET_TGA_BYTE (tmp[1]);
907 targa_header.colormap_index = LittleShort ( *((short *)tmp) );
908 GET_TGA_BYTE (tmp[0]);
909 GET_TGA_BYTE (tmp[1]);
910 targa_header.colormap_length = LittleShort ( *((short *)tmp) );
911 GET_TGA_BYTE (targa_header.colormap_size);
912 GET_TGA_BYTE (tmp[0]);
913 GET_TGA_BYTE (tmp[1]);
914 targa_header.x_origin = LittleShort ( *((short *)tmp) );
915 GET_TGA_BYTE (tmp[0]);
916 GET_TGA_BYTE (tmp[1]);
917 targa_header.y_origin = LittleShort ( *((short *)tmp) );
918 GET_TGA_BYTE (tmp[0]);
919 GET_TGA_BYTE (tmp[1]);
920 targa_header.width = LittleShort ( *((short *)tmp) );
921 GET_TGA_BYTE (tmp[0]);
922 GET_TGA_BYTE (tmp[1]);
923 targa_header.height = LittleShort ( *((short *)tmp) );
924 GET_TGA_BYTE (targa_header.pixel_size);
925 GET_TGA_BYTE (targa_header.attributes);
926
927 if (targa_header.image_type!=2
928 && targa_header.image_type!=10) {
929 //Com_Error (ERR_DROP, "LoadTGA: Only type 2 and 10 targa RGB images supported\n");
930 if (buffer != static_rawdata)
931 FS_FreeFile (buffer);
932 return;
933 }
934
935 if (targa_header.colormap_type !=0
936 || (targa_header.pixel_size!=32 && targa_header.pixel_size!=24)) {
937 //Com_Error (ERR_DROP, "LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
938 if (buffer != static_rawdata)
939 FS_FreeFile (buffer);
940 return;
941 }
942
943 columns = targa_header.width;
944 rows = targa_header.height;
945 numPixels = columns * rows;
946
947 if (width)
948 *width = columns;
949 if (height)
950 *height = rows;
951
952 targa_rgba = malloc (numPixels*4);
953 memset (targa_rgba, 0, numPixels*4);
954 *pic = targa_rgba;
955
956 if (targa_header.id_length != 0)
957 buf_p += targa_header.id_length; // skip TARGA image comment
958
959 if (targa_header.image_type==2) { // Uncompressed, RGB images
960 for(row=rows-1; row>=0; row--) {
961 pixbuf = targa_rgba + row*columns*4;
962 for(column=0; column<columns; column++) {
963 unsigned char red,green,blue,alphabyte=255;
964 GET_TGA_BYTE (blue);
965 GET_TGA_BYTE (green);
966 GET_TGA_BYTE (red);
967 if (targa_header.pixel_size == 32)
968 {
969 GET_TGA_BYTE (alphabyte);
970 }
971 *pixbuf++ = red;
972 *pixbuf++ = green;
973 *pixbuf++ = blue;
974 *pixbuf++ = alphabyte;
975 }
976 }
977 }
978 else if (targa_header.image_type==10) { // Runlength encoded RGB images
979 unsigned char red=0,green=0,blue=0,alphabyte=255,packetHeader,packetSize,j;
980 for(row=rows-1; row>=0; row--) {
981 pixbuf = targa_rgba + row*columns*4;
982 for(column=0; column<columns; ) {
983 GET_TGA_BYTE (packetHeader);
984 packetSize = 1 + (packetHeader & 0x7f);
985 if (packetHeader & 0x80) { // run-length packet
986 GET_TGA_BYTE (blue);
987 GET_TGA_BYTE (green);
988 GET_TGA_BYTE (red);
989 if (targa_header.pixel_size == 32)
990 GET_TGA_BYTE (alphabyte);
991
992 for(j=0;j<packetSize;j++) {
993 *pixbuf++ = red;
994 *pixbuf++ = green;
995 *pixbuf++ = blue;
996 *pixbuf++ = alphabyte;
997 column++;
998 if (column==columns) { // run spans across rows
999 column=0;
1000 if (row>0)
1001 row--;
1002 else
1003 goto breakOut;
1004 pixbuf = targa_rgba + row*columns*4;
1005 }
1006 }
1007 }
1008 else { // non run-length packet
1009 for(j=0;j<packetSize;j++) {
1010 GET_TGA_BYTE (blue);
1011 GET_TGA_BYTE (green);
1012 GET_TGA_BYTE (red);
1013 if (targa_header.pixel_size == 32)
1014 GET_TGA_BYTE (alphabyte);
1015 *pixbuf++ = red;
1016 *pixbuf++ = green;
1017 *pixbuf++ = blue;
1018 *pixbuf++ = alphabyte;
1019 column++;
1020 if (column==columns) { // pixel packet run spans across rows
1021 column=0;
1022 if (row>0)
1023 row--;
1024 else
1025 goto breakOut;
1026 pixbuf = targa_rgba + row*columns*4;
1027 }
1028 }
1029 }
1030 }
1031 breakOut:;
1032 }
1033 }
1034
1035 if (buffer != static_rawdata)
1036 FS_FreeFile (buffer);
1037 }
1038
1039
1040 /*
1041 ====================================================================
1042
1043 IMAGE FLOOD FILLING
1044
1045 ====================================================================
1046 */
1047
1048
1049 /*
1050 =================
1051 Mod_FloodFillSkin
1052
1053 Fill background pixels so mipmapping doesn't have haloes
1054 =================
1055 */
1056
1057 typedef struct
1058 {
1059 short x, y;
1060 } floodfill_t;
1061
1062 // must be a power of 2
1063 #define FLOODFILL_FIFO_SIZE 0x1000
1064 #define FLOODFILL_FIFO_MASK (FLOODFILL_FIFO_SIZE - 1)
1065
1066 #define FLOODFILL_STEP( off, dx, dy ) \
1067 { \
1068 if (pos[off] == fillcolor) \
1069 { \
1070 pos[off] = 255; \
1071 fifo[inpt].x = x + (dx), fifo[inpt].y = y + (dy); \
1072 inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; \
1073 } \
1074 else if (pos[off] != 255) fdc = pos[off]; \
1075 }
1076
R_FloodFillSkin(byte * skin,int skinwidth,int skinheight)1077 void R_FloodFillSkin( byte *skin, int skinwidth, int skinheight )
1078 {
1079 byte fillcolor = *skin; // assume this is the pixel to fill
1080 floodfill_t fifo[FLOODFILL_FIFO_SIZE];
1081 int inpt = 0, outpt = 0;
1082 int filledcolor = -1;
1083 int i;
1084
1085 if (filledcolor == -1)
1086 {
1087 filledcolor = 0;
1088 // attempt to find opaque black
1089 for (i = 0; i < 256; ++i)
1090 if (d_8to24table[i] == (255 << 0)) // alpha 1.0
1091 {
1092 filledcolor = i;
1093 break;
1094 }
1095 }
1096
1097 // can't fill to filled color or to transparent color (used as visited marker)
1098 if ((fillcolor == filledcolor) || (fillcolor == 255))
1099 {
1100 //printf( "not filling skin from %d to %d\n", fillcolor, filledcolor );
1101 return;
1102 }
1103
1104 fifo[inpt].x = 0, fifo[inpt].y = 0;
1105 inpt = (inpt + 1) & FLOODFILL_FIFO_MASK;
1106
1107 while (outpt != inpt)
1108 {
1109 int x = fifo[outpt].x, y = fifo[outpt].y;
1110 int fdc = filledcolor;
1111 byte *pos = &skin[x + skinwidth * y];
1112
1113 outpt = (outpt + 1) & FLOODFILL_FIFO_MASK;
1114
1115 if (x > 0) FLOODFILL_STEP( -1, -1, 0 );
1116 if (x < skinwidth - 1) FLOODFILL_STEP( 1, 1, 0 );
1117 if (y > 0) FLOODFILL_STEP( -skinwidth, 0, -1 );
1118 if (y < skinheight - 1) FLOODFILL_STEP( skinwidth, 0, 1 );
1119 skin[x + skinwidth * y] = fdc;
1120 }
1121 }
1122
1123 //=======================================================
1124
1125
1126 /*
1127 ================
1128 GL_ResampleTexture
1129 ================
1130 */
GL_ResampleTexture(byte * in,int inwidth,int inheight,byte * out,int outwidth,int outheight)1131 void GL_ResampleTexture (byte *in, int inwidth, int inheight, byte *out, int outwidth, int outheight)
1132 {
1133 int i, j;
1134 byte *inrow, *inrow2;
1135 unsigned frac, fracstep;
1136 unsigned p1[1024], p2[1024];
1137 byte *pix1, *pix2, *pix3, *pix4;
1138
1139 fracstep = inwidth*0x10000/outwidth;
1140
1141 frac = fracstep>>2;
1142 for (i=0 ; i<outwidth ; i++)
1143 {
1144 p1[i] = 4*(frac>>16);
1145 frac += fracstep;
1146 }
1147 frac = 3*(fracstep>>2);
1148 for (i=0 ; i<outwidth ; i++)
1149 {
1150 p2[i] = 4*(frac>>16);
1151 frac += fracstep;
1152 }
1153
1154 for (i=0 ; i<outheight ; i++, out += outwidth*4)
1155 {
1156 inrow = in + 4*inwidth*(int)((i+0.25)*inheight/outheight);
1157 inrow2 = in + 4*inwidth*(int)((i+0.75)*inheight/outheight);
1158 frac = fracstep >> 1;
1159 for (j=0 ; j<outwidth ; j++)
1160 {
1161 pix1 = inrow + p1[j];
1162 pix2 = inrow + p2[j];
1163 pix3 = inrow2 + p1[j];
1164 pix4 = inrow2 + p2[j];
1165 *(out+4*j+0) = (pix1[0] + pix2[0] + pix3[0] + pix4[0])>>2;
1166 *(out+4*j+1) = (pix1[1] + pix2[1] + pix3[1] + pix4[1])>>2;
1167 *(out+4*j+2) = (pix1[2] + pix2[2] + pix3[2] + pix4[2])>>2;
1168 *(out+4*j+3) = (pix1[3] + pix2[3] + pix3[3] + pix4[3])>>2;
1169 }
1170 }
1171 }
1172
1173 /*
1174 R_FilterTexture
1175
1176 Applies brightness and contrast to the specified image while optionally computing
1177 the image's average color. Also handles image inversion and monochrome. This is
1178 all munged into one function to reduce loops on level load.
1179 */
R_FilterTexture(byte * in,int width,int height)1180 void R_FilterTexture(byte *in, int width, int height)
1181 {
1182 int count;
1183 float fcb;
1184 int ix;
1185 static byte lut[256];
1186 static int first_time = 1;
1187 static float lut_gamma = 0.0f;
1188 static float lut_contrast = 0.0f;
1189
1190 if ( lut_gamma != vid_gamma->value || lut_contrast != vid_contrast->value || first_time ) {
1191 first_time = 0;
1192 lut_gamma = vid_gamma->value;
1193 lut_contrast = vid_contrast->value;
1194 // build lookup table
1195 for ( ix = 0; ix < sizeof(lut); ix++ ) {
1196 fcb = (float)ix / 255.0f;
1197 fcb *= lut_gamma;
1198 if (fcb < 0.0f )
1199 fcb = 0.0f;
1200 fcb -= 0.5f;
1201 fcb *= lut_contrast;
1202 fcb += 0.5f;
1203 fcb *= 255.0f;
1204 if ( fcb >= 255.0f )
1205 lut[ix] = 255 ;
1206 else if (fcb <= 0.0f )
1207 lut[ix] = 0;
1208 else
1209 lut[ix] = (byte)fcb;
1210 }
1211 }
1212
1213 // apply to image
1214 count = width * height;
1215 while ( count-- ) {
1216 *in = lut[*in];
1217 ++in;
1218 *in = lut[*in];
1219 ++in;
1220 *in = lut[*in];
1221 ++in;
1222 ++in;
1223 }
1224
1225 }
1226
1227
1228 #define ALPHATEST_THRESHOLD 169
1229 // Uses the canonical mipmap generation algorithm, but unlike OpenGL's built-
1230 // in mipmapping, it this function knows when to quit-- that is, when the
1231 // mipmaps have gotten too "mushy." Mushy mipmaps usually aren't a problem,
1232 // but they're a huge one when dealing with alphatest surfaces.
GL_RecursiveGenerateAlphaMipmaps(byte * data,int width,int height,int depth)1233 int GL_RecursiveGenerateAlphaMipmaps (byte *data, int width, int height, int depth)
1234 {
1235 int ret;
1236 int x, y;
1237 int newwidth, newheight;
1238 int upper_left_alpha;
1239 qboolean uniform = true;
1240 byte *mipmap, *scan, *scan2, *out;
1241
1242 if (width == 1 && height == 1)
1243 return depth;
1244
1245 newwidth = width;
1246 if (newwidth > 1)
1247 newwidth /= 2;
1248 newheight = height;
1249 if (newheight > 1)
1250 newheight /= 2;
1251
1252 mipmap = malloc (newwidth*newheight*4);
1253
1254 for (y = 0; (y+1) < height; y += 2)
1255 {
1256 for (x = 0; (x+1) < width; x += 2)
1257 {
1258 scan = data + (y*width+x)*4;
1259 scan2 = data + ((y+1)*width+x)*4;
1260 out = mipmap + ((y/2)*(width/2)+(x/2))*4;
1261 out[0] = (scan[0]+scan[4]+scan2[0]+scan2[4])/4;
1262 out[1] = (scan[1]+scan[5]+scan2[1]+scan2[5])/4;
1263 out[2] = (scan[2]+scan[6]+scan2[2]+scan2[6])/4;
1264 out[3] = (scan[3]+scan[7]+scan2[3]+scan2[7])/4;
1265 if (x == 0 && y == 0)
1266 upper_left_alpha = out[3];
1267 else if ((upper_left_alpha > ALPHATEST_THRESHOLD) != (out[3] > ALPHATEST_THRESHOLD))
1268 uniform = false;
1269 }
1270 }
1271
1272 if (uniform)
1273 {
1274 free (mipmap);
1275 return depth;
1276 }
1277
1278 ret = GL_RecursiveGenerateAlphaMipmaps (mipmap, newwidth, newheight, depth+1);
1279
1280 qglTexImage2D (GL_TEXTURE_2D, depth+1, gl_tex_alpha_format, newwidth, newheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, mipmap);
1281
1282 free (mipmap);
1283 return ret;
1284 }
1285
GL_GenerateAlphaMipmaps(byte * data,int width,int height)1286 int GL_GenerateAlphaMipmaps (byte *data, int width, int height)
1287 {
1288 return GL_RecursiveGenerateAlphaMipmaps (data, width, height, 0);
1289 }
1290
1291
1292 static int powers_of_two[] = {16,32,64,128,256,512,1024,2048,4096};
1293 int upload_width, upload_height;
1294 int crop_left, crop_right, crop_top, crop_bottom;
1295 qboolean uploaded_paletted;
1296
1297
GL_Upload32(byte * data,int width,int height,int picmip,qboolean filter,qboolean force_standard_mipmap)1298 qboolean GL_Upload32 (byte *data, int width, int height, int picmip, qboolean filter, qboolean force_standard_mipmap)
1299 {
1300 int samples;
1301 byte *scaled;
1302 int scaled_width, scaled_height;
1303 int i, c;
1304 byte *scan;
1305 int comp;
1306
1307 if(filter)
1308 R_FilterTexture(data, width, height);
1309
1310 uploaded_paletted = false; // scan the texture for any non-255 alpha
1311 c = width*height;
1312 scan = data + 3;
1313 samples = gl_solid_format;
1314 for (i=0 ; i<c ; i++, scan += 4)
1315 {
1316 if ( *scan != 255 )
1317 {
1318 samples = gl_alpha_format;
1319 break;
1320 }
1321 }
1322 comp = (samples == gl_solid_format) ? gl_tex_solid_format : gl_tex_alpha_format;
1323
1324 {
1325 int max_size;
1326 int i;
1327 qglGetIntegerv(GL_MAX_TEXTURE_SIZE,&max_size);
1328 scaled_width = scaled_height = 0;
1329
1330 for (i=0; i<8; i++)
1331 {
1332 if (width >= powers_of_two[i] && width < powers_of_two[i+1]) {
1333 if (width > ((powers_of_two[i] + powers_of_two[i+1])/2))
1334 scaled_width = powers_of_two[i+1];
1335 else
1336 scaled_width = powers_of_two[i];
1337 } else if (width == powers_of_two[i+1]) {
1338 scaled_width = powers_of_two[i+1];
1339 }
1340
1341 if (scaled_width && scaled_height)
1342 break;
1343 if (height >= powers_of_two[i] && height < powers_of_two[i+1]) {
1344 if (height > ((powers_of_two[i] + powers_of_two[i+1])/2))
1345 scaled_height = powers_of_two[i+1];
1346 else
1347 scaled_height = powers_of_two[i];
1348 } else if (height == powers_of_two[i+1]) {
1349 scaled_height = powers_of_two[i+1];
1350 }
1351 if (scaled_width && scaled_height)
1352 break;
1353 }
1354 // let people sample down the world textures for speed
1355 for (i = 0; i < picmip; i++)
1356 {
1357 if (scaled_width <= 1 || scaled_height <= 1)
1358 break;
1359 scaled_width >>= 1;
1360 scaled_height >>= 1;
1361 }
1362 if (scaled_width > max_size)
1363 scaled_width = max_size;
1364 if (scaled_height > max_size)
1365 scaled_height = max_size;
1366 }
1367
1368 if (scaled_width != width || scaled_height != height) {
1369 scaled=malloc((scaled_width * scaled_height) * 4);
1370 GL_ResampleTexture(data,width,height,scaled,scaled_width,scaled_height);
1371 } else {
1372 scaled=data;
1373 }
1374
1375 if (samples != gl_alpha_format || force_standard_mipmap)
1376 qglTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE );
1377 qglTexImage2D (GL_TEXTURE_2D, 0, comp, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
1378
1379 crop_left = crop_right = crop_top = crop_bottom = 0;
1380 if (samples == gl_alpha_format)
1381 {
1382 int x, y;
1383 qboolean found;
1384
1385 scan = (byte*)scaled+3;
1386
1387 for (y = 0; y < scaled_height; y++, crop_top++)
1388 {
1389 found = false;
1390 for (x = 0; x < scaled_width; x++)
1391 {
1392 scan = ((byte*)scaled + (y*scaled_width+x)*4+3);
1393 if (*scan != 0)
1394 found = true;
1395 }
1396 if (found)
1397 break;
1398 }
1399
1400 crop_left = scaled_width;
1401 crop_right = scaled_width;
1402
1403 for (; y < scaled_height; y++)
1404 {
1405 for (x = 0; x < scaled_width; x++)
1406 {
1407 scan = ((byte*)scaled + (y*scaled_width+x)*4+3);
1408 if (*scan != 0)
1409 {
1410 if (x < crop_left)
1411 crop_left = x;
1412 if (scaled_width-x-1 < crop_right)
1413 crop_right = scaled_width-x-1;
1414 crop_bottom = scaled_height-y-1;
1415 }
1416 }
1417 }
1418 }
1419
1420 if (samples == gl_alpha_format && !force_standard_mipmap)
1421 {
1422 int generated_mipmaps =
1423 GL_GenerateAlphaMipmaps (scaled, scaled_width, scaled_height);
1424 qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, generated_mipmaps);
1425 qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, r_alphamasked_anisotropic->integer);
1426 }
1427 else
1428 qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, r_anisotropic->integer);
1429
1430 if (scaled_width != width || scaled_height != height)
1431 free(scaled);
1432
1433 upload_width = scaled_width;
1434 upload_height = scaled_height;
1435 qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
1436 qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
1437
1438 return (samples == gl_alpha_format);
1439 }
1440
1441 /*
1442 ===============
1443 GL_Upload8
1444
1445 Returns has_alpha
1446 ===============
1447 */
GL_Upload8(byte * data,int width,int height,int picmip,qboolean filter)1448 qboolean GL_Upload8 (byte *data, int width, int height, int picmip, qboolean filter)
1449 {
1450 unsigned trans[512*256]; // contains 32 bit RGBA color
1451 int i, s;
1452 int p;
1453
1454 s = width*height;
1455
1456 if (s > sizeof(trans)/4)
1457 Com_Error (ERR_DROP, "GL_Upload8: too large");
1458
1459 for (i=0 ; i<s ; i++)
1460 {
1461 p = data[i];
1462 trans[i] = d_8to24table[p];
1463
1464 if (p == 255)
1465 { // transparent, so scan around for another color
1466 // to avoid alpha fringes
1467 // FIXME: do a full flood fill so mips work...
1468 if (i > width && data[i-width] != 255)
1469 p = data[i-width];
1470 else if (i < s-width && data[i+width] != 255)
1471 p = data[i+width];
1472 else if (i > 0 && data[i-1] != 255)
1473 p = data[i-1];
1474 else if (i < s-1 && data[i+1] != 255)
1475 p = data[i+1];
1476 else
1477 p = 0;
1478 // copy rgb components
1479 ((byte *)&trans[i])[0] = ((byte *)&d_8to24table[p])[0];
1480 ((byte *)&trans[i])[1] = ((byte *)&d_8to24table[p])[1];
1481 ((byte *)&trans[i])[2] = ((byte *)&d_8to24table[p])[2];
1482 }
1483 }
1484 return GL_Upload32 ((byte*)trans, width, height, picmip, filter, false);
1485 }
1486
1487 /*
1488 ================
1489 GL_ReservePic
1490
1491 Find a free image_t
1492 ================
1493 */
GL_FindFreeImage(char * name,int width,int height,imagetype_t type)1494 image_t *GL_FindFreeImage (char *name, int width, int height, imagetype_t type)
1495 {
1496 image_t *image;
1497 int i;
1498
1499 // find a free image_t
1500 for (i=0, image=gltextures ; i<numgltextures ; i++,image++)
1501 {
1502 if (!image->texnum)
1503 break;
1504 }
1505 if (i == numgltextures)
1506 {
1507 if (numgltextures == MAX_GLTEXTURES)
1508 Com_Error (ERR_DROP, "MAX_GLTEXTURES");
1509 numgltextures++;
1510 }
1511 image = &gltextures[i];
1512
1513 if (strlen(name) >= sizeof(image->name))
1514 Com_Error (ERR_DROP, "Draw_LoadPic: \"%s\" is too long", name);
1515
1516 strcpy (image->name, name);
1517
1518 if ( name[0] != '*' )
1519 { // not a special name, remove the path part
1520 strcpy( image->bare_name, COM_SkipPath( name ) );
1521 }
1522
1523 image->registration_sequence = registration_sequence;
1524
1525 image->width = width;
1526 image->height = height;
1527 image->type = type;
1528
1529 image->texnum = TEXNUM_IMAGES + (image - gltextures);
1530
1531 return image;
1532 }
1533
1534 /*
1535 ================
1536 GL_LoadPic
1537
1538 This is also used as an entry point for the generated r_notexture
1539 ================
1540 */
GL_LoadPic(char * name,byte * pic,int width,int height,imagetype_t type,int bits)1541 image_t *GL_LoadPic (char *name, byte *pic, int width, int height, imagetype_t type, int bits)
1542 {
1543 image_t *image;
1544 int i;
1545 int picmip;
1546
1547 image = GL_FindFreeImage (name, width, height, type);
1548
1549 if (type == it_skin && bits == 8)
1550 R_FloodFillSkin(pic, width, height);
1551
1552 if (type == it_particle || type == it_pic)
1553 picmip = 0;
1554 else
1555 picmip = gl_picmip->integer;
1556
1557 // load little particles into the scrap
1558 if (type == it_particle && bits != 8
1559 && image->width <= 128 && image->height <= 128)
1560 {
1561 int x, y;
1562 int i, j, k, l;
1563 int texnum;
1564
1565 texnum = Scrap_AllocBlock (image->width, image->height, &x, &y);
1566 if (texnum == -1)
1567 goto nonscrap;
1568 scrap_dirty = true;
1569
1570 // copy the texels into the scrap block
1571 k = 0;
1572 for (i=0 ; i<image->height ; i++)
1573 for (j=0 ; j<image->width ; j++)
1574 for (l = 0; l < 4; l++, k++)
1575 scrap_texels[texnum][((y+i)*BLOCK_WIDTH + x + j)*4+l] = pic[k];
1576 image->texnum = TEXNUM_SCRAPS + texnum; // overwrite old texnum
1577 image->scrap = true;
1578 image->has_alpha = true;
1579 image->sl = (double)(x+0.5)/(double)BLOCK_WIDTH;
1580 image->sh = (double)(x+image->width-0.5)/(double)BLOCK_WIDTH;
1581 image->tl = (double)(y+0.5)/(double)BLOCK_HEIGHT;
1582 image->th = (double)(y+image->height-0.5)/(double)BLOCK_HEIGHT;
1583 }
1584 else
1585 {
1586 nonscrap:
1587 image->scrap = false;
1588 GL_Bind(image->texnum);
1589 if (bits == 8) {
1590 image->has_alpha = GL_Upload8 (pic, width, height, picmip, type <= it_wall);
1591 } else {
1592 image->has_alpha = GL_Upload32 (pic, width, height, picmip, type <= it_wall, type >= it_bump);
1593 }
1594
1595 if (type == it_pic)
1596 qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
1597
1598 image->paletted = uploaded_paletted;
1599
1600 // size in pixels after power of 2 and scales
1601 image->upload_width = upload_width;
1602 image->upload_height = upload_height;
1603
1604 // vertex offset to apply when cropping
1605 image->crop_left = crop_left;
1606 image->crop_top = crop_top;
1607
1608 // size in pixels after cropping
1609 image->crop_width = upload_width-crop_left-crop_right;
1610 image->crop_height = upload_height-crop_top-crop_bottom;
1611
1612 // texcoords to use when not cropping
1613 image->sl = 0;
1614 image->sh = 1;
1615 image->tl = 0;
1616 image->th = 1;
1617
1618 // texcoords to use when cropping
1619 image->crop_sl = 0 + (float)crop_left/(float)upload_width;
1620 image->crop_sh = 1 - (float)crop_right/(float)upload_width;
1621 image->crop_tl = 0 + (float)crop_top/(float)upload_height;
1622 image->crop_th = 1 - (float)crop_bottom/(float)upload_height;
1623 }
1624
1625 COMPUTE_HASH_KEY( image->hash_key, name, i );
1626 return image;
1627 }
1628
1629
1630 /*
1631 ================
1632 GL_LoadWal
1633 ================
1634 */
GL_LoadWal(char * name)1635 image_t *GL_LoadWal (char *name)
1636 {
1637 miptex_t *mt;
1638 int width, height, ofs;
1639 image_t *image;
1640
1641 FS_LoadFile (name, (void **)&mt);
1642 if (!mt)
1643 {
1644 return r_notexture;
1645 }
1646
1647 width = LittleLong (mt->width);
1648 height = LittleLong (mt->height);
1649 ofs = LittleLong (mt->offsets[0]);
1650
1651 image = GL_LoadPic (name, (byte *)mt + ofs, width, height, it_wall, 8);
1652
1653 FS_FreeFile ((void *)mt);
1654
1655 return image;
1656 }
1657
1658
1659 /*
1660 ===============
1661 GL_GetImage
1662
1663 Finds an image, do not attempt to load it
1664 ===============
1665 */
GL_GetImage(const char * name)1666 image_t *GL_GetImage( const char * name )
1667 {
1668 image_t * image = NULL;
1669 unsigned int hash_key;
1670 int i;
1671
1672 COMPUTE_HASH_KEY( hash_key, name, i );
1673 for ( i = 0, image=gltextures ; i<numgltextures ; i++,image++)
1674 {
1675 if (hash_key == image->hash_key && !strcmp(name, image->name))
1676 {
1677 image->registration_sequence = registration_sequence;
1678 return image;
1679 }
1680 }
1681
1682 return NULL;
1683 }
1684
1685
1686 /*
1687 ===============
1688 GL_FreeImage
1689
1690 Frees an image slot and deletes the texture
1691 ===============
1692 */
GL_FreeImage(image_t * image)1693 void GL_FreeImage( image_t * image )
1694 {
1695 if ( ! image->texnum )
1696 return;
1697 qglDeleteTextures (1, (unsigned *)&image->texnum );
1698 if ( gl_state.currenttextures[gl_state.currenttmu] == image->texnum ) {
1699 gl_state.currenttextures[ gl_state.currenttmu ] = 0;
1700 }
1701 memset (image, 0, sizeof(*image));
1702 }
1703
1704
1705 /*
1706 ===============
1707 GL_FindImage
1708
1709 Finds or loads the given image
1710 ===============
1711 */
GL_FindImage(char * name,imagetype_t type)1712 image_t *GL_FindImage (char *name, imagetype_t type)
1713 {
1714 image_t *image = NULL;
1715 int len;
1716 byte *pic, *palette;
1717 int width, height;
1718 char shortname[MAX_QPATH];
1719
1720 if (!name)
1721 goto ret_image; // Com_Error (ERR_DROP, "GL_FindImage: NULL name");
1722 len = strlen(name);
1723 if (len < 5)
1724 goto ret_image; // Com_Error (ERR_DROP, "GL_FindImage: bad name: %s", name);
1725
1726 //if HUD, then we want to load the one according to what it is set to.
1727 if(!strcmp(name, "pics/i_health.pcx"))
1728 strcpy(name, cl_hudimage1->string);
1729 if(!strcmp(name, "pics/i_score.pcx"))
1730 strcpy(name, cl_hudimage2->string);
1731
1732 // look for it
1733 image = GL_GetImage( name );
1734 if ( image != NULL )
1735 return image;
1736
1737 // strip off .pcx, .tga, etc...
1738 COM_StripExtension ( name, shortname );
1739
1740 //
1741 // load the pic from disk
1742 //
1743 pic = NULL;
1744 palette = NULL;
1745
1746 // Try to load the image with different file extensions, in the following
1747 // order of decreasing preference: TGA, JPEG, PCX, and WAL.
1748
1749 LoadTGA (va("%s.tga", shortname), &pic, &width, &height);
1750 if (pic)
1751 {
1752 image = GL_LoadPic (name, pic, width, height, type, 32);
1753 goto done;
1754 }
1755
1756 LoadJPG (va("%s.jpg", shortname), &pic, &width, &height);
1757 if (pic)
1758 {
1759 image = GL_LoadPic (name, pic, width, height, type, 32);
1760 goto done;
1761 }
1762
1763 // TGA and JPEG are the only file types used for heightmaps and
1764 // normalmaps, so if we haven't found it yet, it isn't there, and we can
1765 // save ourselves a file lookup.
1766 if (type == it_bump)
1767 goto done;
1768
1769 LoadPCX (va("%s.pcx", shortname), &pic, &palette, &width, &height);
1770 if (pic)
1771 {
1772 image = GL_LoadPic (name, pic, width, height, type, 8);
1773 goto done;
1774 }
1775
1776 if (type == it_wall)
1777 image = GL_LoadWal (va("%s.wal", shortname));
1778
1779 done:
1780 if (pic)
1781 free(pic);
1782 if (palette)
1783 free(palette);
1784
1785 if (image != NULL)
1786 image->script = RS_FindScript (shortname);
1787
1788 ret_image:
1789 return image;
1790 }
1791
1792
1793
1794 /*
1795 ===============
1796 R_RegisterSkin
1797 ===============
1798 */
R_RegisterSkin(char * name)1799 struct image_s *R_RegisterSkin (char *name)
1800 {
1801 return GL_FindImage (name, it_skin);
1802 }
1803
1804
1805 /*
1806 ================
1807 GL_FreeUnusedImages
1808
1809 Any image that was not touched on this registration sequence
1810 will be freed.
1811 ================
1812 */
GL_FreeUnusedImages(void)1813 void GL_FreeUnusedImages (void)
1814 {
1815 int i;
1816 image_t *image;
1817
1818 // never free r_notexture
1819 r_notexture->registration_sequence = registration_sequence;
1820
1821 for (i=0, image=gltextures ; i<numgltextures ; i++, image++)
1822 {
1823 if (image->registration_sequence == registration_sequence)
1824 continue; // used this sequence
1825 if (!image->registration_sequence)
1826 continue; // free image_t slot
1827 if (image->type == it_pic || image->type == it_sprite || image->type == it_particle)
1828 continue; // don't free pics or particles
1829 // free it
1830 qglDeleteTextures (1, (unsigned *)&image->texnum );
1831 memset (image, 0, sizeof(*image));
1832 }
1833 }
1834
1835 /*
1836 ===============
1837 Draw_GetPalette
1838 ===============
1839 */
Draw_GetPalette(void)1840 int Draw_GetPalette (void)
1841 {
1842 int i;
1843 int r, g, b;
1844 unsigned v;
1845 byte *pic, *pal;
1846 int width, height;
1847
1848 // get the palette
1849
1850 LoadPCX ("pics/colormap.pcx", &pic, &pal, &width, &height);
1851 if (!pal)
1852 {
1853 Com_Error (ERR_FATAL,
1854 "Couldn't load pics/colormap.pcx\n"
1855 "The game executable cannot find its data files. This means\n"
1856 "the game is likely not installed correctly."
1857 // TODO: automatically generate a list of paths where the data
1858 // files should be
1859 #if defined UNIX_VARIANT
1860 " If you\ninstalled the game from the repository of a Linux\n"
1861 "distribution, please report this to ther package\n"
1862 "maintainers and have them check the README for packaging\n"
1863 "instructions."
1864 #endif //UNIX_VARIANT
1865 );
1866 }
1867
1868 for (i=0 ; i<256 ; i++)
1869 {
1870 r = pal[i*3+0];
1871 g = pal[i*3+1];
1872 b = pal[i*3+2];
1873
1874 v = (255<<24) + (r<<0) + (g<<8) + (b<<16);
1875 d_8to24table[i] = LittleLong(v);
1876 }
1877
1878 d_8to24table[255] &= LittleLong(0xffffff); // 255 is transparent
1879
1880 free (pic);
1881 free (pal);
1882
1883 return 0;
1884 }
1885
1886 // TODO: have r_newrefdef available before calling these, put r_mirroretxture
1887 // in that struct, base it on the viewport specified in that struct. (Needed
1888 // for splitscreen.)
R_InitMirrorTextures(void)1889 void R_InitMirrorTextures( void )
1890 {
1891 byte *data;
1892 int size;
1893 int size_oneside;
1894
1895 //init the partial screen texture
1896 size_oneside = ceil((512.0f/1080.0f)*(float)viddef.height);
1897 size = size_oneside * size_oneside * 4;
1898 data = malloc( size );
1899 memset( data, 255, size );
1900 r_mirrortexture = GL_LoadPic( "***r_mirrortexture***", (byte *)data, size_oneside, size_oneside, it_pic, 32 );
1901 free ( data );
1902 }
1903
R_InitDepthTextures(void)1904 void R_InitDepthTextures( void )
1905 {
1906 byte *data;
1907 int size, texture_height, texture_width;
1908
1909 //find closer power of 2 to screen size
1910 for (texture_width = 1;texture_width < viddef.width;texture_width *= 2);
1911 for (texture_height = 1;texture_height < viddef.height;texture_height *= 2);
1912
1913 //limit to 2048x2048 - anything larger is generally going to cause problems, and AA doesn't support res higher
1914 if(texture_width > 2048)
1915 texture_width = 2048;
1916 if(texture_height > 2048)
1917 texture_height = 2048;
1918
1919 //init the framebuffer textures
1920 size = texture_width * texture_height * 4;
1921
1922 data = malloc( size );
1923 memset( data, 255, size );
1924 r_depthtexture = GL_LoadPic( "***r_depthtexture***", (byte *)data, texture_width, texture_height, it_pic, 3 );
1925 r_depthtexture2 = GL_LoadPic( "***r_depthtexture2***", (byte *)data, texture_width, texture_height, it_pic, 3 );
1926 free ( data );
1927 }
1928
1929
1930 /*
1931 ===============
1932 GL_InitImages
1933 ===============
1934 */
GL_InitImages(void)1935 void GL_InitImages (void)
1936 {
1937
1938 registration_sequence = 1;
1939
1940 gl_state.inverse_intensity = 1;
1941
1942 Draw_GetPalette ();
1943
1944 R_InitMirrorTextures();//MIRRORS
1945 R_InitDepthTextures();//DEPTH(SHADOWMAPS)
1946 R_FB_InitTextures();//FULLSCREEN EFFECTS
1947 R_SI_InitTextures();//SIMPLE ITEMS
1948 R_InitBloomTextures();//BLOOMS
1949 }
1950
1951 /*
1952 ===============
1953 GL_ShutdownImages
1954 ===============
1955 */
GL_ShutdownImages(void)1956 void GL_ShutdownImages (void)
1957 {
1958 int i;
1959 image_t *image;
1960
1961 for (i=0, image=gltextures ; i<numgltextures ; i++, image++)
1962 {
1963 if (!image->registration_sequence)
1964 continue; // free image_t slot
1965 // free it
1966 qglDeleteTextures (1, (unsigned *)&image->texnum);
1967 memset (image, 0, sizeof(*image));
1968 }
1969
1970 memset (scrap_allocated, 0, sizeof(scrap_allocated));
1971 memset (scrap_texels, 0, sizeof(scrap_texels));
1972 scrap_dirty = false;
1973 scrap_uploads = 0;
1974 }
1975
1976