Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gl_texture.cpp
Go to the documentation of this file.
1 /*
2  * Vega Strike
3  * Copyright (C) 2001-2002 Daniel Horn
4  *
5  * http://vegastrike.sourceforge.net/
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */
21 #define GL_EXT_texture_env_combine 1
22 #include "gldrv/sdds.h"
23 #include "gl_globals.h"
24 #include "vs_globals.h"
25 #include "vegastrike.h"
26 #include "config_xml.h"
27 #include "gfxlib.h"
28 
29 #ifndef GL_TEXTURE_CUBE_MAP_EXT
30 #define GL_TEXTURE_CUBE_MAP_EXT 0x8513
31 #define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515
32 #define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516
33 #define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517
34 #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518
35 #define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519
36 #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A
37 #endif
38 
39 //#define MAX_TEXTURES 16384
40 static GLint MAX_TEXTURE_SIZE = 256;
41 
42 extern GLenum GetGLTextureTarget( enum TEXTURE_TARGET texture_target );
43 
45 {
46  switch (textureformat)
47  {
48  case RGB24:
49  return GL_RGB;
50 
51  case RGB32:
52  return GL_RGB;
53 
54  case DXT1RGBA:
55  case DXT3:
56  case DXT5:
57  case DXT1:
58  case RGBA32:
59  return GL_RGBA;
60 
61  case RGBA16:
62  return GL_RGBA16;
63 
64  case RGB16:
65  return GL_RGB16;
66 
67  default:
68  return GL_RGBA;
69  }
70 }
71 
72 struct GLTexture
73 {
74  //unsigned char *texture;
75  GLubyte *palette;
76  int width;
77  int height;
78  int iwidth; //Interface width
79  int iheight; //Interface height
81  GLuint name;
83  GLenum textureformat;
84  GLenum targets;
86 };
87 //static GLTexture *textures=NULL;
88 //static GLEnum * targets=NULL;
89 
90 static vector< GLTexture >textures;
91 static int activetexture[32] = {
92  -1, -1, -1, -1, -1, -1, -1, -1,
93  -1, -1, -1, -1, -1, -1, -1, -1,
94  -1, -1, -1, -1, -1, -1, -1, -1,
95  -1, -1, -1, -1, -1, -1, -1, -1
96 };
97 
98 static void ConvertPalette( unsigned char *dest, unsigned char *src )
99 {
100  for (int a = 0; a < 256; a++, dest += 4, src += 4) {
101  memcpy( dest, src, 3 );
102  dest[3] = 255;
103  }
104 }
105 
106 int tmp_abs( int num )
107 {
108  return num < 0 ? -num : num;
109 }
110 
111 bool isPowerOfTwo( int num, int &which )
112 {
113  which = 0;
114  while (tmp_abs( num ) > 1) {
115  if ( (num/2)*2 != num )
116  return false;
117  which++;
118  num /= 2;
119  }
120  return true;
121 }
122 
123 #ifdef __APPLE__
124 
125 static GLint round2( GLint n )
126 {
127  GLint m;
128  for (m = 1; m < n; m *= 2)
129  ;
130  /* m>=n */
131  if (m-n <= n-m/2)
132  return m;
133  else
134  return m/2;
135 }
136 
137 static GLint bytes_per_pixel( GLenum format, GLenum type )
138 {
139  GLint n, m;
140  switch (format)
141  {
142  case GL_COLOR_INDEX:
143  case GL_STENCIL_INDEX:
144  case GL_DEPTH_COMPONENT:
145  case GL_RED:
146  case GL_GREEN:
147  case GL_BLUE:
148  case GL_ALPHA:
149  case GL_LUMINANCE:
150  n = 1;
151  break;
152  case GL_LUMINANCE_ALPHA:
153  n = 2;
154  break;
155  case GL_RGB:
156  case GL_BGR:
157  n = 3;
158  break;
159  case GL_RGBA:
160  case GL_BGRA:
161 #ifdef GL_EXT_abgr
162  case GL_ABGR_EXT:
163 #endif
164  n = 4;
165  break;
166  default:
167  n = 0;
168  }
169  switch (type)
170  {
171  case GL_UNSIGNED_BYTE:
172  m = sizeof (GLubyte);
173  break;
174  case GL_BYTE:
175  m = sizeof (GLbyte);
176  break;
177  case GL_BITMAP:
178  m = 1;
179  break;
180  case GL_UNSIGNED_SHORT:
181  m = sizeof (GLushort);
182  break;
183  case GL_SHORT:
184  m = sizeof (GLshort);
185  break;
186  case GL_UNSIGNED_INT:
187  m = sizeof (GLuint);
188  break;
189  case GL_INT:
190  m = sizeof (GLint);
191  break;
192  case GL_FLOAT:
193  m = sizeof (GLfloat);
194  break;
195  default:
196  m = 0;
197  }
198  return n*m;
199 }
200 
201 static GLint appleBuild2DMipmaps( GLenum target,
202  GLint components,
203  GLsizei width,
204  GLsizei height,
205  GLenum format,
206  GLenum type,
207  const void *data )
208 {
209  GLint w, h, maxsize;
210  void *image, *newimage;
211  GLint neww, newh, level, bpp;
212  int error;
213  GLboolean done;
214  GLint retval = 0;
215  GLint unpackrowlength, unpackalignment, unpackskiprows, unpackskippixels;
216  GLint packrowlength, packalignment, packskiprows, packskippixels;
217  if (width < 1 || height < 1)
218  return GLU_INVALID_VALUE;
219  glGetIntegerv( GL_MAX_TEXTURE_SIZE, &maxsize );
220 
221  w = round2( width );
222  if (w > maxsize)
223  w = maxsize;
224  h = round2( height );
225  if (h > maxsize)
226  h = maxsize;
227  bpp = bytes_per_pixel( format, type );
228  if (bpp == 0)
229  /* probably a bad format or type enum */
230  return GLU_INVALID_ENUM;
231  /* Get current glPixelStore values */
232  glGetIntegerv( GL_UNPACK_ROW_LENGTH, &unpackrowlength );
233  glGetIntegerv( GL_UNPACK_ALIGNMENT, &unpackalignment );
234  glGetIntegerv( GL_UNPACK_SKIP_ROWS, &unpackskiprows );
235  glGetIntegerv( GL_UNPACK_SKIP_PIXELS, &unpackskippixels );
236  glGetIntegerv( GL_PACK_ROW_LENGTH, &packrowlength );
237  glGetIntegerv( GL_PACK_ALIGNMENT, &packalignment );
238  glGetIntegerv( GL_PACK_SKIP_ROWS, &packskiprows );
239  glGetIntegerv( GL_PACK_SKIP_PIXELS, &packskippixels );
240 
241  /* set pixel packing */
242  glPixelStorei( GL_PACK_ROW_LENGTH, 0 );
243  glPixelStorei( GL_PACK_ALIGNMENT, 1 );
244  glPixelStorei( GL_PACK_SKIP_ROWS, 0 );
245  glPixelStorei( GL_PACK_SKIP_PIXELS, 0 );
246 
247  done = GL_FALSE;
248  if (w != width || h != height) {
249  /* must rescale image to get "top" mipmap texture image */
250  image = malloc( (w+4)*h*bpp );
251  if (!image)
252  return GLU_OUT_OF_MEMORY;
253  error = gluScaleImage( format, width, height, type, data,
254  w, h, type, image );
255  if (error) {
256  retval = error;
257  done = GL_TRUE;
258  }
259  } else {
260  image = (void*) data;
261  }
262  level = 0;
263  while (!done) {
264  if (image != data) {
265  /* set pixel unpacking */
266  glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
267  glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
268  glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 );
269  glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 );
270  }
271  glTexImage2D( target, level, components, w, h, 0, format, type, image );
272  if (w == 1 && h == 1)
273  break;
274  neww = (w < 2) ? 1 : w/2;
275  newh = (h < 2) ? 1 : h/2;
276  newimage = malloc( (neww+4)*newh*bpp );
277  if (!newimage)
278  return GLU_OUT_OF_MEMORY;
279  error = gluScaleImage( format, w, h, type, image,
280  neww, newh, type, newimage );
281  if (error) {
282  retval = error;
283  done = GL_TRUE;
284  }
285  if (image != data)
286  free( image );
287  image = newimage;
288 
289  w = neww;
290  h = newh;
291  level++;
292  }
293  if (image != data)
294  free( image );
295  /* Restore original glPixelStore state */
296  glPixelStorei( GL_UNPACK_ROW_LENGTH, unpackrowlength );
297  glPixelStorei( GL_UNPACK_ALIGNMENT, unpackalignment );
298  glPixelStorei( GL_UNPACK_SKIP_ROWS, unpackskiprows );
299  glPixelStorei( GL_UNPACK_SKIP_PIXELS, unpackskippixels );
300  glPixelStorei( GL_PACK_ROW_LENGTH, packrowlength );
301  glPixelStorei( GL_PACK_ALIGNMENT, packalignment );
302  glPixelStorei( GL_PACK_SKIP_ROWS, packskiprows );
303  glPixelStorei( GL_PACK_SKIP_PIXELS, packskippixels );
304 
305  return retval;
306 }
307 
308 #define gluBuild2DMipmaps appleBuild2DMipmaps
309 
310 #endif
311 
312 GFXBOOL /*GFXDRVAPI*/ GFXCreateTexture( int width,
313  int height,
314  TEXTUREFORMAT textureformat,
315  int *handle,
316  char *palette,
317  int texturestage,
318  enum FILTER mipmap,
319  enum TEXTURE_TARGET texture_target,
320  enum ADDRESSMODE address_mode )
321 {
322  int dummy = 0;
323  if ( ( mipmap&(MIPMAP|TRILINEAR) ) && !isPowerOfTwo( width, dummy ) )
324  VSFileSystem::vs_dprintf( 1, "Width %d not a power of two", width );
325  if ( ( mipmap&(MIPMAP|TRILINEAR) ) && !isPowerOfTwo( height, dummy ) )
326  VSFileSystem::vs_dprintf( 1, "Height %d not a power of two", height );
327  GFXActiveTexture( texturestage );
328  *handle = 0;
329  while ( *handle < static_cast<int>(textures.size()) ) {
330  if (!textures[*handle].alive)
331  break;
332  else
333  (*handle)++;
334  }
335  if ( (*handle) == static_cast<int>(textures.size()) ) {
336  textures.push_back( GLTexture() );
337  textures.back().palette = NULL;
338  textures.back().alive = GFXTRUE;
339  textures.back().name = -1;
340  textures.back().width = textures.back().height = textures.back().iwidth = textures.back().iheight = 1;
341  }
342  switch (texture_target)
343  {
344  case TEXTURE1D:
345  textures[*handle].targets = GL_TEXTURE_1D;
346  break;
347  case TEXTURE2D:
348  textures[*handle].targets = GL_TEXTURE_2D;
349  break;
350 #ifdef GL_EXT_texture3D
351  case TEXTURE3D:
352  textures[*handle].targets = GL_TEXTURE_3D;
353  break;
354 #endif
355  case CUBEMAP:
356  textures[*handle].targets = GL_TEXTURE_CUBE_MAP_EXT;
357  break;
358  case TEXTURERECT:
359  textures[*handle].targets = GL_TEXTURE_RECTANGLE_ARB;
360  break;
361  }
362  //for those libs with stubbed out handle gen't
363  textures[*handle].name = *handle+1;
364  textures[*handle].alive = GFXTRUE;
365  textures[*handle].texturestage = texturestage;
366  textures[*handle].mipmapped = mipmap;
367  glGenTextures( 1, &textures[*handle].name );
368  glBindTexture( textures[*handle].targets, textures[*handle].name );
369  activetexture[texturestage] = *handle;
370  GFXTextureAddressMode( address_mode, texture_target );
371  if (textures[*handle].mipmapped&(TRILINEAR|MIPMAP) && gl_options.mipmap >= 2) {
372  glTexParameteri( textures[*handle].targets, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
373  if (textures[*handle].mipmapped&TRILINEAR && gl_options.mipmap >= 3)
374  glTexParameteri( textures[*handle].targets, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
375  else
376  glTexParameteri( textures[*handle].targets, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
377  } else {
378  if (textures[*handle].mipmapped == NEAREST || gl_options.mipmap == 0) {
379  glTexParameteri( textures[*handle].targets, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
380  glTexParameteri( textures[*handle].targets, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
381  } else {
382  glTexParameteri( textures[*handle].targets, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
383  glTexParameteri( textures[*handle].targets, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
384  }
385  }
386  glTexParameterf( textures[*handle].targets, GL_TEXTURE_PRIORITY, .5 );
387  textures[*handle].width = width;
388  textures[*handle].height = height;
389  textures[*handle].iwidth = width;
390  textures[*handle].iheight = height;
391  textures[*handle].palette = NULL;
392  if (palette && textureformat == PALETTE8) {
393  VSFileSystem::vs_dprintf( 3, " palette " );
394  textures[*handle].palette = (GLubyte*) malloc( sizeof (GLubyte)*1024 );
395  ConvertPalette( textures[*handle].palette, (unsigned char*) palette );
396  }
397  textures[*handle].textureformat = GetUncompressedTextureFormat( textureformat );
398  return GFXTRUE;
399 }
400 
401 void /*GFXDRVAPI*/ GFXPrioritizeTexture( unsigned int handle, float priority )
402 {
403  glPrioritizeTextures( 1,
404 #if defined (__APPLE__)
405  (GLuint*)
406 #endif
407  &handle, &priority );
408 }
409 
410 void /*GFXDRVAPI*/ GFXAttachPalette( unsigned char *palette, int handle )
411 {
412  ConvertPalette( textures[handle].palette, palette );
413  //memcpy (textures[handle].palette,palette,768);
414 }
415 
416 static void DownSampleTexture( unsigned char **newbuf,
417  const unsigned char *oldbuf,
418  int &height,
419  int &width,
420  int pixsize,
421  int handle,
422  int maxheight,
423  int maxwidth,
424  float newfade )
425 {
426  assert( pixsize <= 4 );
427 
428  int i, j, k, l, m, n, o;
429  if (MAX_TEXTURE_SIZE < maxwidth)
430  maxwidth = MAX_TEXTURE_SIZE;
431  if (MAX_TEXTURE_SIZE < maxheight)
432  maxheight = MAX_TEXTURE_SIZE;
433  int newwidth = width > maxwidth ? maxwidth : width;
434  int scalewidth = width/newwidth;
435  int newheight = height > maxheight ? maxheight : height;
436  int scaleheight = height/newheight;
437  int inewfade = (int) (newfade*0x100);
438  //Proposed downsampling code -- end
439  if ( (scalewidth != 2) || (scaleheight != 2) || (inewfade != 0x100) ) {
440  //Generic, area average downsampling (optimized)
441  //Principle: The main optimizations/features
442  //a) integer arithmetic, with propper scaling for propper saturation
443  //b) unrolled loops (more parallelism, if the optimizer supports it)
444  //c) improved locality due to 32-pixel chunking
445  int wmask = scalewidth-1;
446  int hmask = scaleheight-1;
447  int tshift = 0;
448  int ostride = newwidth*pixsize;
449  int istride = width*pixsize;
450  int rowstride = scaleheight*istride;
451  int chunkstride = 32*pixsize;
452  int ichunkstride = scalewidth*chunkstride;
453  int wshift = 0;
454  int hshift = 0;
455  int amask = wmask;
456  while (amask)
457  amask >>= 1, tshift++, wshift++;
458  amask = hmask;
459  while (amask)
460  amask >>= 1, tshift++, hshift++;
461  int tmask = (1<<tshift)-1;
462  *newbuf = (unsigned char*) malloc( newheight*newwidth*pixsize*sizeof (unsigned char) );
463  unsigned int temp[32*4];
464  unsigned char *orow = (*newbuf);
465  const unsigned char *irow = oldbuf;
466  for (i = 0; i < newheight; i++, orow += ostride, irow += rowstride) {
467  const unsigned char *crow = irow;
468  unsigned char *orow2 = orow;
469  for (j = 0; j < newwidth; j += 32, crow += ichunkstride, orow2 += chunkstride) {
470  const unsigned char *crow2 = crow;
471  for (k = 0; k < chunkstride; k++)
472  temp[k] = 0;
473  for (m = 0; m < scaleheight; m++, crow2 += istride)
474  for (k = n = l = 0; (k < chunkstride) && (j+l < newwidth); k += pixsize, l++)
475  for (o = 0; o < scalewidth; o++)
476  (temp[k+0] += crow2[n++]),
477  (pixsize > 1) && (temp[k+1] += crow2[n++]),
478  (pixsize > 2) && (temp[k+2] += crow2[n++]),
479  //Unrolled loop
480  (pixsize > 3) && (temp[k+3] += crow2[n++]);
481  for (k = l = 0; (k < chunkstride) && (j+l < newwidth); k += pixsize, l++)
482  ( orow2[k+0] = (unsigned char) ( ( ( (temp[k+0]+tmask)>>tshift )*inewfade+0x80*(0x100-inewfade) )>>8 ) ),
483  (pixsize > 1)
484  && ( orow2[k+1] = (unsigned char) ( ( ( (temp[k+1]+tmask)>>tshift )*inewfade+0x80*(0x100-inewfade) )>>8 ) ),
485  (pixsize > 2)
486  && ( orow2[k+2] = (unsigned char) ( ( ( (temp[k+2]+tmask)>>tshift )*inewfade+0x80*(0x100-inewfade) )>>8 ) ),
487  //Unrolled loop
488  (pixsize > 3)
489  && ( orow2[k+3] = (unsigned char) ( ( ( (temp[k+3]+tmask)>>tshift )*inewfade+0x80*(0x100-inewfade) )>>8 ) );
490  }
491  }
492  } else {
493  //Specific purpose downsampler: 2x2 averaging
494  //a) Very little overhead
495  //b) Very common case (mipmap generation)
496  *newbuf = (unsigned char*) malloc( newheight*newwidth*pixsize*sizeof (unsigned char) );
497  unsigned char *orow = (*newbuf);
498  int ostride = newwidth*pixsize;
499  int istride = width*pixsize;
500  const unsigned char *irow[2] = {oldbuf, oldbuf+istride};
501  unsigned int temp[4] = { 0,0,0,0 };
502  for (i = 0; i < newheight; i++, irow[0] += 2*istride, irow[1] += 2*istride, orow += ostride)
503  for (j = k = 0; j < newwidth; j++, k += pixsize) {
504  (temp[0] = irow[0][(k<<1)+0]),
505  (pixsize > 1) && (temp[1] = irow[0][(k<<1)+1]),
506  (pixsize > 2) && (temp[2] = irow[0][(k<<1)+2]),
507  //Unrolled loop
508  (pixsize > 3) && (temp[3] = irow[0][(k<<1)+3]);
509 
510  (temp[0] += irow[0][(k<<1)+pixsize+0]),
511  (pixsize > 1) && (temp[1] += irow[0][(k<<1)+pixsize+1]),
512  (pixsize > 2) && (temp[2] += irow[0][(k<<1)+pixsize+2]),
513  //Unrolled loop
514  (pixsize > 3) && (temp[3] += irow[0][(k<<1)+pixsize+3]);
515 
516  (temp[0] += irow[1][(k<<1)+0]),
517  (pixsize > 1) && (temp[1] += irow[1][(k<<1)+1]),
518  (pixsize > 2) && (temp[2] += irow[1][(k<<1)+2]),
519  //Unrolled loop
520  (pixsize > 3) && (temp[3] += irow[1][(k<<1)+3]);
521 
522  (temp[0] += irow[1][(k<<1)+pixsize+0]),
523  (pixsize > 1) && (temp[1] += irow[1][(k<<1)+pixsize+1]),
524  (pixsize > 2) && (temp[2] += irow[1][(k<<1)+pixsize+2]),
525  //Unrolled loop
526  (pixsize > 3) && (temp[3] += irow[1][(k<<1)+pixsize+3]);
527 
528  ( orow[k+0] = (unsigned char) ( (temp[0]+3)>>2 ) ),
529  (pixsize > 1) && ( orow[k+1] = (unsigned char) ( (temp[1]+3)>>2 ) ),
530  (pixsize > 2) && ( orow[k+2] = (unsigned char) ( (temp[2]+3)>>2 ) ),
531  //Unrolled loop
532  (pixsize > 3) && ( orow[k+3] = (unsigned char) ( (temp[3]+3)>>2 ) );
533  }
534  }
535  width = newwidth;
536  height = newheight;
537 }
538 
539 static GLenum RGBCompressed( GLenum internalformat )
540 {
541  if (gl_options.compression) {
542  internalformat = GL_COMPRESSED_RGB_ARB;
543  if (gl_options.s3tc)
544  internalformat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
545  }
546  return internalformat;
547 }
548 
549 static GLenum RGBACompressed( GLenum internalformat )
550 {
551  if (gl_options.compression) {
552  internalformat = GL_COMPRESSED_RGBA_ARB;
553  if (gl_options.s3tc) {
554  switch (gl_options.compression)
555  {
556  case 3:
557  internalformat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
558  break;
559  case 2:
560  internalformat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
561  break;
562  case 1:
563  internalformat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
564  break;
565  }
566  }
567  }
568  return internalformat;
569 }
570 
571 GLenum GetTextureFormat( TEXTUREFORMAT textureformat )
572 {
573  switch (textureformat)
574  {
575  case PNGRGB24:
576  case RGB32:
577  return RGBCompressed( GL_RGB );
578 
579  case PNGRGBA32:
580  case RGBA32:
581  return RGBACompressed( GL_RGBA );
582 
583  case RGBA16:
584  return RGBACompressed( GL_RGBA16 );
585 
586  case RGB16:
587  return RGBCompressed( GL_RGB16 );
588 
589  case DXT1:
591 
592  case DXT1RGBA:
594 
595  case DXT3:
597 
598  case DXT5:
600 
601  default:
602  case DUMMY:
603  case RGB24:
604  return RGBCompressed( GL_RGB );
605  }
606 }
607 
609 {
610  GLenum image2D = GL_TEXTURE_2D;
611  switch (imagetarget)
612  {
613  case TEXTURE_2D:
614  image2D = GL_TEXTURE_2D;
615  break;
616  case CUBEMAP_POSITIVE_X:
618  break;
619  case CUBEMAP_NEGATIVE_X:
621  break;
622  case CUBEMAP_POSITIVE_Y:
624  break;
625  case CUBEMAP_NEGATIVE_Y:
627  break;
628  case CUBEMAP_POSITIVE_Z:
630  break;
631  case CUBEMAP_NEGATIVE_Z:
633  break;
634  case TEXTURE_RECTANGLE:
635  image2D = GL_TEXTURE_RECTANGLE_ARB;
636  break;
637  default:
638  assert(0 ||! "Bad case in file gl_texture.cpp, line 668 as of this writing.");
639  break;
640  }
641  return image2D;
642 }
643 
644 const char * GetImageTargetName( TEXTURE_IMAGE_TARGET imagetarget )
645 {
646  switch (imagetarget)
647  {
648  case TEXTURE_1D:
649  return "TEXTURE_1D";
650 
651  case TEXTURE_2D:
652  return "TEXTURE_2D";
653 
654  case TEXTURE_3D:
655  return "TEXTURE_3D";
656 
657  case CUBEMAP_POSITIVE_X:
658  return "CUBEMAP_POSITIVE_X";
659 
660  case CUBEMAP_NEGATIVE_X:
661  return "CUBEMAP_NEGATIVE_X";
662 
663  case CUBEMAP_POSITIVE_Y:
664  return "CUBEMAP_POSITIVE_Y";
665 
666  case CUBEMAP_NEGATIVE_Y:
667  return "CUBEMAP_NEGATIVE_Y";
668 
669  case CUBEMAP_POSITIVE_Z:
670  return "CUBEMAP_POSITIVE_Z";
671 
672  case CUBEMAP_NEGATIVE_Z:
673  return "CUBEMAP_NEGATIVE_Z";
674 
675  case TEXTURE_RECTANGLE:
676  return "TEXTURE_RECTANGLE";
677 
678  default:
679  return "UNK";
680  }
681 }
682 
683 GFXBOOL /*GFXDRVAPI*/ GFXTransferSubTexture( unsigned char *buffer,
684  int handle,
685  int x,
686  int y,
687  unsigned int width,
688  unsigned int height,
689  enum TEXTURE_IMAGE_TARGET imagetarget )
690 {
691  GLenum image2D = GetImageTarget( imagetarget );
692  glBindTexture( textures[handle].targets, textures[handle].name );
693 
694 //internalformat = GetTextureFormat (handle);
695 
696  glTexSubImage2D( image2D, 0, x, y, width, height, textures[handle].textureformat, GL_UNSIGNED_BYTE, buffer );
697  return GFXTRUE;
698 }
699 
700 GFXBOOL /*GFXDRVAPI*/ GFXTransferTexture( unsigned char *buffer,
701  int handle,
702  int inWidth,
703  int inHeight,
704  TEXTUREFORMAT internformat,
705  enum TEXTURE_IMAGE_TARGET imagetarget,
706  int maxdimension,
707  GFXBOOL detail_texture,
708  unsigned int pageIndex )
709 {
710  if (handle < 0)
711  return GFXFALSE;
712  int error = 0;
713 
714  int logsize = 1;
715  int logwid = 1;
716  unsigned char *data = NULL;
717  unsigned char *tempbuf = NULL;
718  GLenum internalformat;
719  GLenum image2D = GetImageTarget( imagetarget );
720  glBindTexture( textures[handle].targets, textures[handle].name );
721  int blocksize = 16;
722  bool comptemp = gl_options.compression;
723 
724  //Read in the number of mipmaps from buffer
725  int offset1 = 2;
726  int offset2;
727  int mips = 0;
728  if (internformat >= DXT1 && internformat <= DXT5) {
729  mips = 0;
730  if (buffer[0]) mips = mips*10+(buffer[0]-'0');
731  if (buffer[1]) mips = mips*10+(buffer[1]-'0');
732  }
733  if (inWidth > 0)
734  textures[handle].iwidth = textures[handle].width = inWidth;
735  if (inHeight > 0)
736  textures[handle].iheight = textures[handle].height = inHeight;
737  //This code i believe is executed if our texture isn't power of two
738  if ( ( textures[handle].mipmapped&(TRILINEAR|MIPMAP) )
739  && ( !isPowerOfTwo( textures[handle].width, logwid ) || !isPowerOfTwo( textures[handle].height, logsize ) ) ) {
740  static unsigned char NONPOWEROFTWO[1024] = {
741  255, 127, 127, 255,
742  255, 255, 0, 255,
743  255, 255, 0, 255,
744  255, 127, 127, 255
745  };
746  buffer = NONPOWEROFTWO;
747  textures[handle].width = 2;
748  textures[handle].height = 2;
749  //assert (false);
750  }
751  logsize = logsize > logwid ? logsize : logwid;
752  //By default, if we have no limit set, aux_texture sends us a high number
753  //for the max dimension, so that we know to grep the GL max number.
754  //Otherwise maxdimension is set by some user argument based on quality settings.
755  if (maxdimension == 65536)
756  maxdimension = gl_options.max_texture_dimension;
758  "Transferring %dx%d texture, page %d (eff: %dx%d - limited at %d - %d mips), onto name %d (%s)\n",
759  textures[handle].iwidth,
760  textures[handle].iheight,
761  pageIndex,
762  textures[handle].width,
763  textures[handle].height,
764  maxdimension,
765  mips,
766  textures[handle].name,
767  GetImageTargetName( imagetarget )
768  );
769  if (maxdimension == 44) {
770  detail_texture = 0;
771  maxdimension = 256;
772  if (internformat == DXT1 || internformat == DXT1RGBA)
773  blocksize = 8;
774  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
775  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
776  if (internformat >= DXT1 && internformat <= DXT5) {
777  if (textures[handle].width > 8 && textures[handle].height > 8 && mips > 0) {
778  offset1 += ( (textures[handle].width+3)/4 )*( (textures[handle].height+3)/4 )*blocksize;
779  if (textures[handle].width > 1) textures[handle].width >>= 1;
780  if (textures[handle].height > 1) textures[handle].height >>= 1;
781  if (textures[handle].iwidth > 1) textures[handle].iwidth >>= 1;
782  if (textures[handle].iheight > 1) textures[handle].iheight >>= 1;
783  --mips;
784  }
785  }
786  }
787  //If we are DDS, we can scale to max dimension by choosing a pre-made mipmap.
788  if (internformat == DXT1 || internformat == DXT1RGBA)
789  blocksize = 8;
790  if (internformat >= DXT1 && internformat <= DXT5) {
791  while ( (textures[handle].width > maxdimension || textures[handle].height > maxdimension) && mips > 0 ) {
792  offset1 += ( (textures[handle].width+3)/4 )*( (textures[handle].height+3)/4 )*blocksize;
793  if (textures[handle].width > 1) textures[handle].width >>= 1;
794  if (textures[handle].height > 1) textures[handle].height >>= 1;
795  if (textures[handle].iwidth > 1) textures[handle].iwidth >>= 1;
796  if (textures[handle].iheight > 1) textures[handle].iheight >>= 1;
797  --mips;
798  }
799  offset2 = offset1;
800  int w = textures[handle].width;
801  int h = textures[handle].height;
802  for (int i = 0; i < mips; ++i) {
803  offset2 += ( (w+3)/4 )*( (h+3)/4 )*blocksize;
804  if (w > 1) w >>= 1;
805  if (h > 1) h >>= 1;
806  }
807  } else {
808  //If we're not DDS, we have to generate a scaled version of the image
809  if (textures[handle].iwidth > maxdimension || textures[handle].iheight > maxdimension || textures[handle].iwidth
810  > MAX_TEXTURE_SIZE || textures[handle].iheight > MAX_TEXTURE_SIZE) {
811 #if !defined (GL_COLOR_INDEX8_EXT)
812  if (internformat != PALETTE8) {
813 #else
814  if (internformat != PALETTE8 || gl_options.PaletteExt) {
815 #endif
816  textures[handle].height = textures[handle].iheight;
817  textures[handle].width = textures[handle].iwidth;
818  DownSampleTexture( &tempbuf,
819  buffer,
820  textures[handle].height,
821  textures[handle].width,
822  ( internformat == PALETTE8 ? 1 : (internformat == RGBA32 ? 4 : 3) )*sizeof (unsigned char),
823  handle,
824  maxdimension,
825  maxdimension,
826  1 );
827  buffer = tempbuf;
828  VSFileSystem::vs_dprintf( 2, "Downsampled %dx%d texture (target: %dx%d - limited at %d)\n",
829  textures[handle].iwidth,
830  textures[handle].iheight,
831  textures[handle].width,
832  textures[handle].height,
833  maxdimension
834  );
835  }
836  offset2 = 2;
837  } else {
838  offset2 = offset1;
839  int w = textures[handle].width;
840  int h = textures[handle].height;
841  switch (internformat)
842  {
843  case PALETTE8:
844  offset2 += (w*h);
845  break;
846  case RGB16:
847  case RGBA16:
848  offset2 += (w*h)*2;
849  break;
850  case RGB24:
851  offset2 += (w*h)*3;
852  break;
853  case RGBA32:
854  case RGB32:
855  offset2 += (w*h)*4;
856  break;
857  case DXT1:
858  case DXT1RGBA:
859  offset2 += ( ( (w+3)/4 )*( (h+3)/4 ) )*8;
860  break;
861  case DXT3:
862  case DXT5:
863  offset2 += ( ( (w+3)/4 )*( (h+3)/4 ) )*16;
864  break;
865  case PNGPALETTE8:
866  offset2 += (w*h);
867  break;
868  case PNGRGB24:
869  offset2 += (w*h)*3;
870  break;
871  case PNGRGBA32:
872  offset2 += (w*h)*4;
873  break;
874  default:
875  offset2 = 2;
876  }
877  }
878  }
879  //skip to desired page
880  offset1 += pageIndex*(offset2-2);
881 
882  int height = textures[handle].height;
883  int width = textures[handle].width;
884  //If s3tc compression is disabled, our DDS files must be software decompressed
885  if (internformat >= DXT1 && internformat <= DXT5 && !gl_options.s3tc) {
886  unsigned char *tmpbuffer = buffer+offset1;
887  ddsDecompress( tmpbuffer, data, internformat, textures[handle].height, textures[handle].width );
888  buffer = data;
889  internformat = RGBA32;
890  textures[handle].textureformat = GL_RGBA;
891  }
892  if (internformat != PALETTE8 && internformat != PNGPALETTE8) {
893  internalformat = GetTextureFormat( internformat );
894  if ( ( ( textures[handle].mipmapped&(TRILINEAR|MIPMAP) ) && gl_options.mipmap >= 2 ) || detail_texture ) {
895  if (detail_texture) {
896  static FILTER fil =
897  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "detail_texture_trilinear",
898  "true" ) ) ? TRILINEAR : MIPMAP;
899  textures[handle].mipmapped = fil;
900  glTexParameteri( textures[handle].targets, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
901  if (fil&TRILINEAR)
902  glTexParameteri( textures[handle].targets, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
903  else
904  glTexParameteri( textures[handle].targets, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
905  }
906  XMLSupport::parse_int( vs_config->getVariable( "graphics", "detail_texture_full_color", "1" ) );
907  //If we are DDS and we need to generate mipmaps (almost everything gets sent here, even non-3d visuals)
908  if (internformat >= DXT1 && internformat <= DXT5) {
909  int size = 0;
910  int i = 0;
911  unsigned int offset = 0;
912  //The following takes into account C/C++'s catenation of floats to int
913  //by adding 3, we ensure that when width or height is 1, we get a 1 rather than 0
914  //from the division by 4. Because of catenation, all other numbers will result with
915  //the expected number as if the +3 wasn't there. same as max(1,width/4)
916  size = ( (width+3)/4 )*( (height+3)/4 )*blocksize;
917  for (i = 0; i < mips; ++i) {
918  glCompressedTexImage2D_p( image2D, i, internalformat, width, height, 0, size, buffer+offset1+offset );
919  //We halve width and height until they reach 1, or i == mips
920  if (width != 1)
921  width >>= 1;
922  if (height != 1)
923  height >>= 1;
924  if (i < mips-1)
925  offset += size;
926  size = ( (width+3)/4 )*( (height+3)/4 )*blocksize;
927  }
928  /* HACK */
929  //This is a workaround for ani_texture which hates not having
930  //mipmaps.
931  if (mips == 0) {
932  size = ( (width+3)/4 )*( (height+3)/4 )*blocksize;
933  //We need to reverse some parameters that are set cuz
934  //we're supposed to have mipmaps here. But ani_texture hates us.
935  glTexParameteri( textures[handle].targets, GL_TEXTURE_BASE_LEVEL, 0 );
936  glTexParameteri( textures[handle].targets, GL_TEXTURE_MAX_LEVEL, 0 );
937  glCompressedTexImage2D_p( image2D, 0, internalformat, width, height, 0, size, buffer+offset1 );
938  }
939  /* END HACK */
940  } else {
941  //We want mipmaps but we have uncompressed data
942  gluBuild2DMipmaps( image2D,
943  internalformat,
944  textures[handle].width,
945  textures[handle].height,
946  textures[handle].textureformat,
947  GL_UNSIGNED_BYTE,
948  buffer );
949  }
950  if (tempbuf)
951  free( tempbuf );
952  tempbuf = NULL;
953  } else {
954  //WE HAVE NO MIPMAPS HERE
955  if (internformat >= DXT1 && internformat <= DXT5) {
956  int size = 0;
957  size = ( (width+3)/4 )*( (height+3)/4 )*blocksize;
958  //force GL to only display our one texture (just in case)
959  glTexParameteri( textures[handle].targets, GL_TEXTURE_BASE_LEVEL, 0 );
960  glTexParameteri( textures[handle].targets, GL_TEXTURE_MAX_LEVEL, 0 );
961  glCompressedTexImage2D_p( image2D, 0, internalformat, width, height, 0, size, buffer+offset1 );
962  } else {
963  glTexImage2D( image2D,
964  0,
965  internalformat,
966  textures[handle].width,
967  textures[handle].height,
968  0,
969  textures[handle].textureformat,
970  GL_UNSIGNED_BYTE,
971  buffer );
972  }
973  }
974  } else {
975  //THIS IS 8bpp LAND
976  internalformat = GetTextureFormat( internformat );
977  //IRIX has no GL_COLOR_INDEX8 extension
978 #if defined (GL_COLOR_INDEX8_EXT)
979  if (gl_options.PaletteExt) {
980  error = glGetError();
981  glColorTable_p( textures[handle].targets, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, textures[handle].palette );
982  error = glGetError();
983  if (error) {
984  if (tempbuf)
985  free( tempbuf );
986  gl_options.compression = comptemp;
987  if (data)
988  free( data );
989  return GFXFALSE;
990  }
991  if ( ( textures[handle].mipmapped&(MIPMAP|TRILINEAR) ) && gl_options.mipmap >= 2 )
992  gluBuild2DMipmaps( image2D,
993  GL_COLOR_INDEX8_EXT,
994  textures[handle].width,
995  textures[handle].height,
996  GL_COLOR_INDEX,
997  GL_UNSIGNED_BYTE,
998  buffer );
999  else
1000  glTexImage2D( image2D,
1001  0,
1002  GL_COLOR_INDEX8_EXT,
1003  textures[handle].width,
1004  textures[handle].height,
1005  0,
1006  GL_COLOR_INDEX,
1007  GL_UNSIGNED_BYTE,
1008  buffer );
1009  } else
1010 #endif
1011  {
1012  int nsize = 4*textures[handle].iheight*textures[handle].iwidth;
1013  unsigned char *tbuf = (unsigned char*) malloc( sizeof (unsigned char)*nsize );
1014  //textures[handle].texture = tbuf;
1015  int j = 0;
1016  for (int i = 0; i < nsize; i += 4) {
1017  tbuf[i] = textures[handle].palette[4*buffer[j]];
1018  tbuf[i+1] = textures[handle].palette[4*buffer[j]+1];
1019  tbuf[i+2] = textures[handle].palette[4*buffer[j]+2];
1020  //used to be 255
1021  tbuf[i+3] = textures[handle].palette[4*buffer[j]+3];
1022  j++;
1023  }
1025  tbuf, handle,
1026  textures[handle].iwidth, textures[handle].iheight,
1027  RGBA32, imagetarget, maxdimension, detail_texture );
1028  free( tbuf );
1029  }
1030  }
1031  if (tempbuf)
1032  free( tempbuf );
1033  gl_options.compression = comptemp;
1034  if (data)
1035  free( data );
1036  return GFXTRUE;
1037 }
1038 
1039 void /*GFXDRVAPI*/ GFXDeleteTexture( int handle )
1040 {
1041  if (textures[handle].alive) {
1042  glDeleteTextures( 1, &textures[handle].name );
1043  for (size_t i = 0; i < sizeof (activetexture)/sizeof (int); ++i)
1044  if (activetexture[i] == handle)
1045  activetexture[i] = -1;
1046  }
1047  if (textures[handle].palette) {
1048  free( textures[handle].palette );
1049  textures[handle].palette = 0;
1050  }
1051  textures[handle].alive = GFXFALSE;
1052 }
1053 
1055 {
1056  for (size_t handle = 0; handle < textures.size(); ++handle) {
1057  textures[handle].palette = NULL;
1058  textures[handle].width = textures[handle].height = textures[handle].iwidth = textures[handle].iheight = 0;
1059  textures[handle].texturestage = 0;
1060  textures[handle].name = 0;
1061  textures[handle].alive = 0;
1062  textures[handle].textureformat = DUMMY;
1063  textures[handle].targets = 0;
1064  textures[handle].mipmapped = NEAREST;
1065  }
1066  glGetIntegerv( GL_MAX_TEXTURE_SIZE, &MAX_TEXTURE_SIZE );
1067 }
1068 
1070 {
1071  for (size_t handle = 0; handle < textures.size(); handle++)
1072  GFXDeleteTexture( handle );
1073 }
1074 
1075 void GFXTextureCoordGenMode( int stage, GFXTEXTURECOORDMODE tex, const float params[4], const float paramt[4] )
1076 {
1077  if (stage && stage >= static_cast<int>(gl_options.Multitexture)) return;
1078  GFXActiveTexture( stage );
1079  switch (tex)
1080  {
1081  case NO_GEN:
1082  glDisable( GL_TEXTURE_GEN_S );
1083  glDisable( GL_TEXTURE_GEN_T );
1084  glDisable( GL_TEXTURE_GEN_R );
1085  break;
1086  case EYE_LINEAR_GEN:
1087  glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
1088  glTexGenfv( GL_S, GL_EYE_PLANE, params );
1089  glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
1090  glTexGenfv( GL_T, GL_EYE_PLANE, paramt );
1091  glEnable( GL_TEXTURE_GEN_S );
1092  glEnable( GL_TEXTURE_GEN_T );
1093  glDisable( GL_TEXTURE_GEN_R );
1094  break;
1095  case OBJECT_LINEAR_GEN:
1096  glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
1097  glTexGenfv( GL_S, GL_OBJECT_PLANE, params );
1098  glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
1099  glTexGenfv( GL_T, GL_OBJECT_PLANE, paramt );
1100  glEnable( GL_TEXTURE_GEN_S );
1101  glEnable( GL_TEXTURE_GEN_T );
1102  glDisable( GL_TEXTURE_GEN_R );
1103  break;
1104  case SPHERE_MAP_GEN:
1105  glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
1106  glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
1107  glEnable( GL_TEXTURE_GEN_S );
1108  glEnable( GL_TEXTURE_GEN_T );
1109  glDisable( GL_TEXTURE_GEN_R );
1110  break;
1111  case CUBE_MAP_GEN:
1112 #ifdef NV_CUBE_MAP
1113  glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV );
1114  glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV );
1115  glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV );
1116  glEnable( GL_TEXTURE_GEN_S );
1117  glEnable( GL_TEXTURE_GEN_T );
1118  glEnable( GL_TEXTURE_GEN_R );
1119 #else
1120  assert( 0 );
1121 #endif
1122  break;
1123  }
1124 }
1125 
1126 void /*GFXDRVAPI*/ GFXSelectTexture( int handle, int stage )
1127 {
1128  if (stage && stage >= static_cast<int>(gl_options.Multitexture)) return;
1129  if (activetexture[stage] != handle) {
1130  GFXActiveTexture( stage );
1131  activetexture[stage] = handle;
1132  if ( gl_options.Multitexture || (stage == 0) )
1133  glBindTexture( textures[handle].targets, textures[handle].name );
1134  }
1135 }
1136 
1137 void GFXTextureEnv( int stage, GFXTEXTUREENVMODES mode, float arg2 )
1138 {
1139  if (stage && stage >= static_cast<int>(gl_options.Multitexture)) return;
1140  GLenum type;
1141  GFXActiveTexture( stage );
1142  switch (mode)
1143  {
1144  case GFXREPLACETEXTURE:
1145  type = GL_REPLACE;
1146  goto ENVMODE;
1147  case GFXADDTEXTURE:
1148  type = GL_ADD;
1149  goto ENVMODE;
1150  case GFXMODULATETEXTURE:
1151  type = GL_MODULATE;
1152 ENVMODE:
1153  glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, type );
1154  break;
1155  case GFXINTERPOLATETEXTURE:
1156  glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
1157  glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB );
1158  glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR );
1159  glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB );
1160  glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA );
1161  glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE );
1162  glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR );
1163  glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_TEXTURE );
1164  glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA );
1165  glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_CONSTANT );
1166  glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA );
1167  glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, GL_CONSTANT );
1168  glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, GL_SRC_ALPHA );
1169  {
1170  GLfloat arg2v[4] = {
1171  0, 0, 0, 1.0-arg2
1172  };
1173  glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, arg2v );
1174  }
1175  glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB );
1176  glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_INTERPOLATE_ARB );
1177  glTexEnvi( GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1 );
1178  glTexEnvi( GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1 );
1179  break;
1180  case GFXCOMPOSITETEXTURE:
1181  glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
1182  glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB );
1183  glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR );
1184  glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_CONSTANT );
1185  glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA );
1186  glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE );
1187  glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR );
1188  glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE );
1189  glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_ONE_MINUS_SRC_ALPHA );
1190  {
1191  GLfloat arg2v[4] = {
1192  0, 0, 0, arg2
1193  };
1194  glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, arg2v );
1195  }
1196  glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB );
1197  glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE );
1198  glTexEnvi( GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1 );
1199  glTexEnvi( GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1 );
1200  break;
1201  case GFXADDSIGNEDTEXTURE:
1202  glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
1203  glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB );
1204  glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR );
1205  glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB );
1206  glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE );
1207  glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR );
1208  glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD_SIGNED_ARB );
1209  glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE );
1210  glTexEnvi( GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1 );
1211  glTexEnvi( GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1 );
1212  break;
1213  case GFXDETAILTEXTURE:
1214  glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
1215  glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB );
1216  glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB );
1217  glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR );
1218  glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA );
1219  glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE );
1220  glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_TEXTURE );
1221  glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR );
1222  glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA );
1223  glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE );
1224  glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE );
1225  glTexEnvi( GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 2 );
1226  glTexEnvi( GL_TEXTURE_ENV, GL_ALPHA_SCALE, 2 );
1227  break;
1228  }
1229 }
1230 
1231 #ifndef GL_CLAMP_TO_EDGE_EXT
1232 #define GL_CLAMP_TO_EDGE_EXT 0x812F
1233 #endif
1234 #ifndef GL_CLAMP_TO_BORDER_ARB
1235 #define GL_CLAMP_TO_BORDER_ARB 0x812D
1236 #endif
1237 
1238 void GFXTextureWrap( int stage, GFXTEXTUREWRAPMODES mode, enum TEXTURE_TARGET target )
1239 {
1240  if (stage && stage >= static_cast<int>(gl_options.Multitexture)) return;
1241  GFXActiveTexture( stage );
1242  GLenum tt = GetGLTextureTarget( target );
1243  GLenum e1 = GL_REPEAT;
1244  GLenum e2 = 0;
1245  switch (mode)
1246  {
1247  case GFXCLAMPTEXTURE:
1248  e1 = GL_CLAMP;
1249  e2 = GL_CLAMP_TO_EDGE_EXT;
1250  break;
1251  case GFXREPEATTEXTURE:
1252  e1 = GL_REPEAT;
1253  e2 = 0;
1254  break;
1255  case GFXBORDERTEXTURE:
1256  e1 = GL_CLAMP;
1258  break;
1259  }
1260  glTexParameteri( tt, GL_TEXTURE_WRAP_S, e1 );
1261  if (target != TEXTURE1D) glTexParameteri( tt, GL_TEXTURE_WRAP_T, e1 );
1262  if (target == TEXTURE3D) glTexParameteri( tt, GL_TEXTURE_WRAP_R, e1 );
1263  if (e2) {
1264  glTexParameteri( tt, GL_TEXTURE_WRAP_S, e2 );
1265  if (target != TEXTURE1D) glTexParameteri( tt, GL_TEXTURE_WRAP_T, e2 );
1266  if (target == TEXTURE3D) glTexParameteri( tt, GL_TEXTURE_WRAP_R, e2 );
1267  }
1268 }
1269