FS2_Open
Open source remastering of the Freespace 2 engine
gropengltexture.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) Volition, Inc. 1999. All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 #ifdef _WIN32
11 #include <windows.h>
12 #endif
13 
14 #include "bmpman/bmpman.h"
15 #include "cmdline/cmdline.h"
16 #include "ddsutils/ddsutils.h"
17 #include "globalincs/systemvars.h"
18 #include "graphics/grinternal.h"
19 #include "graphics/gropenglstate.h"
21 #include "math/vecmat.h"
22 #include "osapi/osregistry.h"
23 
24 
25 static tcache_slot_opengl *Textures = NULL;
26 static int *Tex_used_this_frame = NULL;
27 
35 int GL_last_detail = -1;
47 
48 extern int GLOWMAP;
49 extern int SPECMAP;
50 extern int CLOAKMAP;
51 extern int ENVMAP;
52 extern int Interp_multitex_cloakmap;
53 
54 
55 // forward declarations
57 void opengl_free_texture_with_handle(int handle);
58 void opengl_tcache_get_adjusted_texture_size(int w_in, int h_in, int *w_out, int *h_out);
59 int opengl_create_texture_sub(int bitmap_handle, int bitmap_type, int bmap_w, int bmap_h, int tex_w, int tex_h, ubyte *data = NULL, tcache_slot_opengl *t = NULL, int base_level = 0, int resize = 0, int reload = 0);
60 int opengl_create_texture (int bitmap_handle, int bitmap_type, tcache_slot_opengl *tslot = NULL);
61 
63 {
64  GL_CHECK_FOR_ERRORS("start of set_additive_tex_env()");
65 
69  } else {
71  }
72 
73  GL_CHECK_FOR_ERRORS("end of set_additive_tex_env()");
74 }
75 
77 {
78  GL_CHECK_FOR_ERRORS("start of set_modulate_tex_env()");
79 
83  } else {
85  }
86 
87  GL_CHECK_FOR_ERRORS("end of set_modulate_tex_env()");
88 }
89 
91 {
93  return 0.0f;
94  }
95 
96  if ( GL_max_anisotropy < 0.0f ) {
98  }
99 
100  // the spec says that it should be a minimum of 2.0
101  Assert( GL_max_anisotropy >= 2.0f );
102 
103  return GL_max_anisotropy;
104 }
105 
107 {
109 }
110 
112 {
113  int i;
114 
115  GL_should_preload = 1;
116 
119 
121 
123 
124  // if we are not using sections then make sure we have the min texture size available to us
125  // 1024 is what we need with the standard resolutions - taylor
126  if (GL_max_texture_width < 1024) {
127  Error(LOCATION, "A minimum texture size of \"1024x1024\" is required for FS2_Open but only \"%ix%i\" was found. Can not continue.", GL_max_texture_width, GL_max_texture_height);
128  }
129 
130  if (Textures == NULL) {
132  }
133 
134  if (Tex_used_this_frame == NULL) {
135  Tex_used_this_frame = (int *) vm_malloc_q(MAX_BITMAPS * sizeof(int));
136  }
137 
138  if ( !Textures || !Tex_used_this_frame )
139  Error(LOCATION, "Unable to allocate memory for OpenGL texture slots!");
140 
141 
142  memset( Tex_used_this_frame, 0, MAX_BITMAPS * sizeof(int) );
143 
144  // Init the texture structures
145  for (i = 0; i < MAX_BITMAPS; i++) {
146  Textures[i].reset();
147  }
148 
149  // check what mipmap filter we should be using
150  // 0 == Bilinear
151  // 1 == Trilinear
152  GL_mipmap_filter = os_config_read_uint(NULL, "TextureFilter", 1);
153 
154  if (GL_mipmap_filter > 1) {
155  GL_mipmap_filter = 1;
156  }
157 
158  // max size (width and/or height) that we can use for framebuffer/renderbuffer
161 
162  // if we can't do at least 128x128 then just disable FBOs
163  if (GL_max_renderbuffer_size < 128) {
164  mprintf(("WARNING: Max dimensions of FBO, %ix%i, is less the required minimum!! Extension will be disabled!\n", GL_max_renderbuffer_size, GL_max_renderbuffer_size));
166  }
167  }
168 
169  // anisotropy
171  // set max value first thing
173 
174  // now for the user setting
175  const char *plevel = os_config_read_string( NULL, NOX("OGL_AnisotropicFilter"), NOX("1.0") );
176  GL_anisotropy = (GLfloat) strtod(plevel, (char**)NULL);
177 
179  }
180 
182  if (GL_anisotropy > 1.0f) {
184  } else {
186  }
187  }
188 
189  // set the alpha gamma settings (for fonts)
190  memset( GL_xlat, 0, sizeof(GL_xlat) );
191 
192  for (i = 1; i < 15; i++) {
193  GL_xlat[i] = (ubyte)(GL_xlat[i-1] + 17);
194  }
195 
196  GL_xlat[15] = GL_xlat[1];
197 
200 
202 
203  GL_textures_in = 0;
205 }
206 
208 {
209  int n = bm_get_cache_slot(handle, 1);
210 
211  Tex_used_this_frame[n] = 0;
212  opengl_free_texture( &Textures[n] );
213 }
214 
216 {
217  int i;
218 
219  if ( Textures == NULL )
220  return;
221 
222  for (i = 0; i < MAX_BITMAPS; i++)
223  opengl_free_texture( &Textures[i] );
224 
225  if (GL_textures_in != 0) {
226  mprintf(( "WARNING: VRAM is at %d instead of zero after flushing!\n", GL_textures_in ));
227  GL_textures_in = 0;
228  }
229 }
230 
231 extern void opengl_kill_all_render_targets();
232 
234 {
236 
238 
239  GL_textures_in = 0;
241 
242  if (Textures != NULL) {
243  vm_free(Textures);
244  Textures = NULL;
245  }
246 
247  if (Tex_used_this_frame != NULL) {
248  vm_free(Tex_used_this_frame);
249  Tex_used_this_frame = NULL;
250  }
251 }
252 
254 {
256 
257  // make all textures as not used
258  memset( Tex_used_this_frame, 0, MAX_BITMAPS * sizeof(int) );
259 }
260 
261 extern bool GL_initted;
262 
264 {
265  if ( !GL_initted ) {
266  return;
267  }
268 
269  Tex_used_this_frame[n] = 0;
270  opengl_free_texture( &Textures[n] );
271 }
272 
277 bool opengl_texture_slot_valid(int n, int handle)
278 {
279  tcache_slot_opengl *t = &Textures[n];
280 
281  if (t->bitmap_handle < 0) {
282  return false;
283  }
284 
285  if (t->bitmap_handle != handle) {
286  return false;
287  }
288 
289  if ( !glIsTexture(t->texture_id) ) {
290  return false;
291  }
292 
293  return true;
294 }
295 
297 {
298  // Bitmap changed!!
299  if (t->texture_id) {
300  // if I, or any of my children have been used this frame, bail
301  // can't use bm_get_cache_slot() here since bitmap_id probably isn't valid
302  if ( (t->bitmap_handle >= 0) && Tex_used_this_frame[t->bitmap_handle % MAX_BITMAPS] ) {
303  return 0;
304  }
305 
306  // ok, now we know its legal to free everything safely
308  glDeleteTextures (1, &t->texture_id);
309 
310  GL_textures_in -= t->size;
311 
312  t->reset();
313  }
314 
315  return 1;
316 }
317 
318 void opengl_tcache_get_adjusted_texture_size(int w_in, int h_in, int *w_out, int *h_out)
319 {
320  int i, tex_w, tex_h;
321 
322  // bogus
323  if ( (w_out == NULL) || (h_out == NULL) ) {
324  return;
325  }
326 
327  // if we can support non-power-of-2 textures then just return current sizes - taylor
329  *w_out = w_in;
330  *h_out = h_in;
331 
332  return;
333  }
334 
335  // starting size
336  tex_w = w_in;
337  tex_h = h_in;
338 
339  for (i = 0; i < 16; i++) {
340  if ( (tex_w > (1<<i)) && (tex_w <= (1<<(i+1))) ) {
341  tex_w = 1 << (i+1);
342  break;
343  }
344  }
345 
346  for (i = 0; i < 16; i++) {
347  if ( (tex_h > (1<<i)) && (tex_h <= (1<<(i+1))) ) {
348  tex_h = 1 << (i+1);
349  break;
350  }
351  }
352 
355 
356  // store the outgoing size
357  *w_out = tex_w;
358  *h_out = tex_h;
359 }
360 
361 // data == start of bitmap data
362 // bmap_w == width of source bitmap
363 // bmap_h == height of source bitmap
364 // tex_w == width of final texture
365 // tex_h == height of final texture
366 int opengl_create_texture_sub(int bitmap_handle, int bitmap_type, int bmap_w, int bmap_h, int tex_w, int tex_h, ubyte *data, tcache_slot_opengl *t, int base_level, int resize, int reload)
367 {
368  int ret_val = 1;
369  int byte_mult = 0;
371  GLenum glFormat = GL_BGRA;
372  GLint intFormat = GL_RGBA;
373  ubyte saved_bpp = 0;
374  int mipmap_w = 0, mipmap_h = 0;
375  int dsize = 0, doffset = 0, block_size = 0;
376  int i,j,k;
377  ubyte *bmp_data = data;
378  ubyte *texmem = NULL, *texmemp = NULL;
379  int skip_size = 0, mipmap_levels = 0;
380 
381  GL_CHECK_FOR_ERRORS("start of create_texture_sub()");
382 
383  // bogus
384  if ( (t == NULL) || (bmp_data == NULL) ) {
385  return 0;
386  }
387 
388  int idx = bm_get_cache_slot( bitmap_handle, 1 );
389 
390  if ( Tex_used_this_frame[idx] ) {
391  mprintf(( "ARGHH!!! Texture already used this frame! Cannot free it!\n" ));
392  return 0;
393  }
394 
395  if ( !reload ) {
396  // save the bpp since it will get reset - fixes anis being 0 bpp
397  saved_bpp = t->bpp;
398 
399  // gah
400  if ( !opengl_free_texture(t) ) {
401  return 0;
402  }
403  }
404 
405  // for everything that might use mipmaps
406  mipmap_w = tex_w;
407  mipmap_h = tex_h;
408 
409  if ( (bitmap_type == TCACHE_TYPE_AABITMAP) || (bitmap_type == TCACHE_TYPE_INTERFACE) ) {
410  t->u_scale = (float)bmap_w / (float)tex_w;
411  t->v_scale = (float)bmap_h / (float)tex_h;
412  } else {
413  t->u_scale = 1.0f;
414  t->v_scale = 1.0f;
415  }
416 
417  if ( !reload ) {
418  glGenTextures (1, &t->texture_id);
419  }
420 
421  if (t->texture_id == 0) {
422  mprintf(("!!OpenGL DEBUG!! t->texture_id == 0\n"));
423  return 0;
424  }
425 
426  if (t->bpp == 0) {
427  // it got reset, revert to saved setting
428  t->bpp = saved_bpp;
429  }
430 
431  // set the byte per pixel multiplier
432  byte_mult = (t->bpp >> 3);
433 
434  // GL_BGRA_EXT is *much* faster with some hardware/drivers
435  if (byte_mult == 4) {
436  texFormat = GL_UNSIGNED_INT_8_8_8_8_REV;
437  intFormat = (gr_screen.bits_per_pixel == 32) ? GL_RGBA8 : GL_RGB5_A1;
438  glFormat = GL_BGRA;
439  } else if (byte_mult == 3) {
440  texFormat = GL_UNSIGNED_BYTE;
441  intFormat = (gr_screen.bits_per_pixel == 32) ? GL_RGB8 : GL_RGB5;
442  glFormat = GL_BGR;
443  } else if (byte_mult == 2) {
444  texFormat = GL_UNSIGNED_SHORT_1_5_5_5_REV;
445  intFormat = GL_RGB5_A1;
446  glFormat = GL_BGRA;
447  } else if (byte_mult == 1) {
448  Assertion( bitmap_type == TCACHE_TYPE_AABITMAP, "Invalid type for bitmap: %s BMPMAN handle: %d. Type expected was 0, we got %d instead.\nThis can be caused by using texture compression on a non-power-of-2 texture.\n", bm_get_filename(bitmap_handle), bitmap_handle, bitmap_type );
449  texFormat = GL_UNSIGNED_BYTE;
450  intFormat = GL_ALPHA;
451  glFormat = GL_ALPHA;
452  } else {
453  texFormat = GL_UNSIGNED_SHORT_1_5_5_5_REV;
454  intFormat = GL_RGBA;
455  glFormat = GL_BGRA;
456  }
457 
458  // check for compressed image types
459  switch ( bm_is_compressed(bitmap_handle) ) {
460  case DDS_DXT1:
461  case DDS_CUBEMAP_DXT1:
463  block_size = 8;
464  break;
465 
466  case DDS_DXT3:
467  case DDS_CUBEMAP_DXT3:
469  block_size = 16;
470  break;
471 
472  case DDS_DXT5:
473  case DDS_CUBEMAP_DXT5:
475  block_size = 16;
476  break;
477  }
478 
479 
480  if ( bitmap_type == TCACHE_TYPE_CUBEMAP ) {
482  }
483 
485 
486  GLenum min_filter = GL_LINEAR;
487 
488  if (t->mipmap_levels > 1) {
490 
493  }
494  }
495 
502 
504 
505  mipmap_levels = bm_get_num_mipmaps(bitmap_handle);
506 
507 
508  switch (bitmap_type) {
509  case TCACHE_TYPE_COMPRESSED: {
510  if (block_size > 0) {
511  // size of data block (4x4)
512  dsize = ((mipmap_h + 3) / 4) * ((mipmap_w + 3) / 4) * block_size;
513 
514  // if we are skipping mipmap levels in order to resize then we have to calc the new offset
515  for (i = 0; i < base_level; i++) {
516  doffset += dsize;
517 
518  mipmap_w >>= 1;
519  mipmap_h >>= 1;
520 
521  if (mipmap_w <= 0) {
522  mipmap_w = 1;
523  }
524 
525  if (mipmap_h <= 0) {
526  mipmap_h = 1;
527  }
528 
529  dsize = ((mipmap_h + 3) / 4) * ((mipmap_w + 3) / 4) * block_size;
530  }
531 
532  skip_size = doffset;
533 
534  if ( !reload ) {
535  vglCompressedTexImage2D(GL_TEXTURE_2D, 0, intFormat, mipmap_w, mipmap_h, 0, dsize, bmp_data + doffset);
536  } else {
537  vglCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mipmap_w, mipmap_h, intFormat, dsize, bmp_data + doffset);
538  }
539 
540  // now that the base image is done handle any mipmap levels
541  for (i = 1; i < (mipmap_levels - base_level); i++) {
542  // adjust the data offset for the next block
543  doffset += dsize;
544 
545  // reduce size by half for the next pass
546  mipmap_w >>= 1;
547  mipmap_h >>= 1;
548 
549  if (mipmap_w <= 0) {
550  mipmap_w = 1;
551  }
552 
553  if (mipmap_h <= 0) {
554  mipmap_h = 1;
555  }
556 
557  // size of data block (4x4)
558  dsize = ((mipmap_h + 3) / 4) * ((mipmap_w + 3) / 4) * block_size;
559 
560  if ( !reload ) {
561  vglCompressedTexImage2D(GL_TEXTURE_2D, i, intFormat, mipmap_w, mipmap_h, 0, dsize, bmp_data + doffset);
562  } else {
563  vglCompressedTexSubImage2D(GL_TEXTURE_2D, i, 0, 0, mipmap_w, mipmap_h, intFormat, dsize, bmp_data + doffset);
564  }
565  }
566  } else {
567  Int3();
568  return 0;
569  }
570 
571  break;
572  }
573 
574  case TCACHE_TYPE_AABITMAP: {
575  texmem = (ubyte *) vm_malloc (tex_w*tex_h*byte_mult);
576  texmemp = texmem;
577 
578  Assert( texmem != NULL );
579 
580  int luminance = 0;
581  for (i = 0; i < tex_h; i++) {
582  for (j = 0; j < tex_w; j++) {
583  if ( (i < bmap_h) && (j < bmap_w) ) {
584  if ( byte_mult > 1 ) {
585  luminance = 0;
586 
587  if ( byte_mult > 3 ) {
588  for (k = 0; k < 3; k++) {
589  luminance += bmp_data[(i*bmap_w+j)*byte_mult+k];
590  }
591 
592  *texmemp++ = (ubyte)((luminance / 3) * (bmp_data[(i*bmap_w+j)*byte_mult+3]/255.0f));
593  } else {
594  for (k = 0; k < byte_mult; k++) {
595  luminance += bmp_data[(i*bmap_w+j)*byte_mult+k];
596  }
597 
598  *texmemp++ = (ubyte)(luminance / byte_mult);
599  }
600  } else {
601  *texmemp++ = GL_xlat[bmp_data[i*bmap_w+j]];
602  }
603  } else {
604  *texmemp++ = 0;
605  }
606  }
607  }
608 
609  if ( !reload ) {
610  glTexImage2D (t->texture_target, 0, GL_ALPHA, tex_w, tex_h, 0, GL_ALPHA, GL_UNSIGNED_BYTE, texmem);
611  } else { // faster anis
612  glTexSubImage2D (t->texture_target, 0, 0, 0, tex_w, tex_h, GL_ALPHA, GL_UNSIGNED_BYTE, texmem);
613  }
614 
615  if (texmem != NULL) {
616  vm_free(texmem);
617  }
618 
619  break;
620  }
621 
622  case TCACHE_TYPE_INTERFACE: {
623  // if we aren't resizing then we can just use bmp_data directly
624  if (resize) {
625  texmem = (ubyte *) vm_malloc (tex_w*tex_h*byte_mult);
626  texmemp = texmem;
627 
628  Assert( texmem != NULL );
629 
630  for (i = 0; i < tex_h; i++) {
631  for (j = 0;j < tex_w; j++) {
632  if ( (i < bmap_h) && (j < bmap_w) ) {
633  for (k = 0; k < byte_mult; k++) {
634  *texmemp++ = bmp_data[(i*bmap_w+j)*byte_mult+k];
635  }
636  } else {
637  for (k = 0; k < byte_mult; k++) {
638  *texmemp++ = 0;
639  }
640  }
641  }
642  }
643  }
644 
645  if ( !reload ) {
646  glTexImage2D (t->texture_target, 0, intFormat, mipmap_w, mipmap_h, 0, glFormat, texFormat, (resize) ? texmem : bmp_data);
647  } else { // faster anis
648  glTexSubImage2D (t->texture_target, 0, 0, 0, mipmap_w, mipmap_h, glFormat, texFormat, (resize) ? texmem : bmp_data);
649  }
650 
651  if (texmem != NULL) {
652  vm_free(texmem);
653  }
654 
655  break;
656  }
657 
658  case TCACHE_TYPE_CUBEMAP: {
659  Assert( !resize );
660  Assert( texmem == NULL );
662 
663  // we have to load in all 6 faces...
664  for (i = 0; i < 6; i++) {
665  doffset += dsize;
666 
667  // check if it's a compressed cubemap first
668  if (block_size > 0) {
669  // size of data block (4x4)
670  dsize = ((mipmap_h + 3) / 4) * ((mipmap_w + 3) / 4) * block_size;
671 
672  if ( !reload ) {
673  vglCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+i, 0, intFormat, mipmap_w, mipmap_h, 0, dsize, bmp_data + doffset);
674  } else {
675  vglCompressedTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+i, 0, 0, 0, mipmap_w, mipmap_h, intFormat, dsize, bmp_data + doffset);
676  }
677 
678  // now that the base image is done handle any mipmap levels
679  for (j = 1; j < mipmap_levels; j++) {
680  // adjust the data offset for the next block
681  doffset += dsize;
682 
683  // reduce size by half for the next pass
684  mipmap_w >>= 1;
685  mipmap_h >>= 1;
686 
687  if (mipmap_w <= 0) {
688  mipmap_w = 1;
689  }
690 
691  if (mipmap_h <= 0) {
692  mipmap_h = 1;
693  }
694 
695  // size of data block (4x4)
696  dsize = ((mipmap_h + 3) / 4) * ((mipmap_w + 3) / 4) * block_size;
697 
698  if ( !reload ) {
699  vglCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+i, j, intFormat, mipmap_w, mipmap_h, 0, dsize, bmp_data + doffset);
700  } else {
701  vglCompressedTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+i, j, 0, 0, mipmap_w, mipmap_h, intFormat, dsize, bmp_data + doffset);
702  }
703  }
704  }
705  // nope, it's uncompressed...
706  else {
707  dsize = mipmap_h * mipmap_w * byte_mult;
708 
709  if ( !reload ) {
710  glTexImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_X+i, 0, intFormat, mipmap_w, mipmap_h, 0, glFormat, texFormat, bmp_data + doffset);
711  } else { // faster anis
712  glTexSubImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_X+i, 0, 0, 0, mipmap_w, mipmap_h, glFormat, texFormat, bmp_data + doffset);
713  }
714 
715  // base image is done so now take care of any mipmap levels
716  for (j = 1; j < mipmap_levels; j++) {
717  doffset += dsize;
718  mipmap_w >>= 1;
719  mipmap_h >>= 1;
720 
721  if (mipmap_w <= 0) {
722  mipmap_w = 1;
723  }
724 
725  if (mipmap_h <= 0) {
726  mipmap_h = 1;
727  }
728 
729  dsize = mipmap_h * mipmap_w * byte_mult;
730 
731  if ( !reload ) {
732  glTexImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_X+i, j, intFormat, mipmap_w, mipmap_h, 0, glFormat, texFormat, bmp_data + doffset);
733  } else {
734  glTexSubImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_X+i, j, 0, 0, mipmap_w, mipmap_h, glFormat, texFormat, bmp_data + doffset);
735  }
736  }
737  }
738 
739  // reset width and height for next face
740  mipmap_w = tex_w;
741  mipmap_h = tex_h;
742  }
743 
744  break;
745  }
746 
747  default: {
748  // if we aren't resizing then we can just use bmp_data directly
749  if (resize) {
750  texmem = (ubyte *) vm_malloc (tex_w*tex_h*byte_mult);
751  texmemp = texmem;
752 
753  Assert( texmem != NULL );
754 
755  fix u, utmp, v, du, dv;
756 
757  u = v = 0;
758 
759  du = ( (bmap_w-1)*F1_0 ) / tex_w;
760  dv = ( (bmap_h-1)*F1_0 ) / tex_h;
761 
762  for (j=0;j<tex_h;j++)
763  {
764  utmp = u;
765  for (i=0;i<tex_w;i++)
766  {
767  for (k = 0; k < byte_mult; k++) {
768  *texmemp++ = bmp_data[(f2i(v)*bmap_w+f2i(utmp))*byte_mult+k];
769  }
770  utmp += du;
771  }
772  v += dv;
773  }
774  }
775 
776  // should never have mipmap levels if we also have to manually resize
777  if ( (mipmap_levels > 1) && resize ) {
778  Assert( texmem == NULL );
779  }
780 
781  dsize = mipmap_h * mipmap_w * byte_mult;
782 
783  // if we are skipping mipmap levels in order to resize then we have to calc the new offset
784  for (i = 0; i < base_level; i++) {
785  doffset += dsize;
786 
787  mipmap_w >>= 1;
788  mipmap_h >>= 1;
789 
790  if (mipmap_w <= 0) {
791  mipmap_w = 1;
792  }
793 
794  if (mipmap_h <= 0) {
795  mipmap_h = 1;
796  }
797 
798  dsize = mipmap_h * mipmap_w * byte_mult;
799  }
800 
801  skip_size = doffset;
802 
803  if ( !reload ) {
804  glTexImage2D (GL_TEXTURE_2D, 0, intFormat, mipmap_w, mipmap_h, 0, glFormat, texFormat, (texmem != NULL) ? texmem : bmp_data + doffset);
805  } else { // faster anis
806  glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, mipmap_w, mipmap_h, glFormat, texFormat, (texmem != NULL) ? texmem : bmp_data + doffset);
807  }
808 
809 
810  // base image is done so now take care of any mipmap levels
811  for (i = 1; i < (mipmap_levels - base_level); i++) {
812  doffset += dsize;
813  mipmap_w >>= 1;
814  mipmap_h >>= 1;
815 
816  if (mipmap_w <= 0) {
817  mipmap_w = 1;
818  }
819 
820  if (mipmap_h <= 0) {
821  mipmap_h = 1;
822  }
823 
824  dsize = mipmap_h * mipmap_w * byte_mult;
825 
826  if ( !reload ) {
827  glTexImage2D (GL_TEXTURE_2D, i, intFormat, mipmap_w, mipmap_h, 0, glFormat, texFormat, bmp_data + doffset);
828  } else {
829  glTexSubImage2D (GL_TEXTURE_2D, i, 0, 0, mipmap_w, mipmap_h, glFormat, texFormat, bmp_data + doffset);
830  }
831  }
832 
833  if (texmem != NULL) {
834  vm_free(texmem);
835  }
836 
837  break;
838  }
839  }//end switch
840 
841 
842  t->bitmap_handle = bitmap_handle;
843  t->size = (dsize) ? ((doffset + dsize) - skip_size) : (tex_w * tex_h * byte_mult);
844  t->w = (ushort)tex_w;
845  t->h = (ushort)tex_h;
846 
848 
849  if ( !reload ) {
850  GL_textures_in += t->size;
851  }
852 
853  Tex_used_this_frame[idx] = 0;
854 
855  GL_CHECK_FOR_ERRORS("end of create_texture_sub()");
856 
857  return ret_val;
858 }
859 
860 int opengl_create_texture(int bitmap_handle, int bitmap_type, tcache_slot_opengl *tslot)
861 {
862  ubyte flags;
863  bitmap *bmp;
864  int final_w, final_h;
865  ubyte bpp = 16;
866  int reload = 0, resize = 0, base_level = 0;
867  int max_levels = 0;
868 
869  GL_CHECK_FOR_ERRORS("start of create_texture()");
870 
871  if (tslot == NULL) {
872  return 0;
873  }
874 
875  // setup texture/bitmap flags
876  flags = 0;
877  switch (bitmap_type) {
879  flags |= BMP_AABITMAP;
880  bpp = 8;
881  break;
882 
883  case TCACHE_TYPE_CUBEMAP:
884  case TCACHE_TYPE_NORMAL:
885  flags |= BMP_TEX_OTHER;
886  break;
887 
889  case TCACHE_TYPE_XPARENT:
890  flags |= BMP_TEX_XPARENT;
891  break;
892 
894  switch ( bm_is_compressed(bitmap_handle) ) {
895  case DDS_DXT1: //dxt1
896  bpp = 24;
897  flags |= BMP_TEX_DXT1;
898  break;
899 
900  case DDS_DXT3: //dxt3
901  bpp = 32;
902  flags |= BMP_TEX_DXT3;
903  break;
904 
905  case DDS_DXT5: //dxt5
906  bpp = 32;
907  flags |= BMP_TEX_DXT5;
908  break;
909 
910  case DDS_CUBEMAP_DXT1:
911  bpp = 24;
912  flags |= BMP_TEX_CUBEMAP;
913  break;
914 
915  case DDS_CUBEMAP_DXT3:
916  case DDS_CUBEMAP_DXT5:
917  bpp = 32;
918  flags |= BMP_TEX_CUBEMAP;
919  break;
920 
921  default:
922  Assert( 0 );
923  break;
924  }
925 
926  break;
927  }
928 
929  // lock the bitmap into the proper format
930  bmp = bm_lock(bitmap_handle, bpp, flags);
931 
932  if ( bmp == NULL ) {
933  mprintf(("Couldn't lock bitmap %d (%s).\n", bitmap_handle, bm_get_filename(bitmap_handle) ));
934  return 0;
935  }
936 
937  int max_w = bmp->w;
938  int max_h = bmp->h;
939 
940  max_levels = bm_get_num_mipmaps(bitmap_handle);
941 
942  // there should only ever be one mipmap level for interface graphics!!!
943  if ( (bitmap_type == TCACHE_TYPE_INTERFACE) && (max_levels > 1) ) {
944  max_levels = 1;
945  }
946 
947  // if we ended up locking a texture that wasn't originally compressed then this should catch it
948  if ( !(bitmap_type == TCACHE_TYPE_CUBEMAP) && bm_is_compressed(bitmap_handle) ) {
949  bitmap_type = TCACHE_TYPE_COMPRESSED;
950  }
951 
952  if ( (Detail.hardware_textures < 4) && (bitmap_type != TCACHE_TYPE_AABITMAP) && (bitmap_type != TCACHE_TYPE_INTERFACE)
953  && ((bitmap_type != TCACHE_TYPE_COMPRESSED) || ((bitmap_type == TCACHE_TYPE_COMPRESSED) && (max_levels > 1))) )
954  {
955  if (max_levels == 1) {
956  // if we are going to cull the size then we need to force a resize
957  // Detail.debris_culling goes from 0 to 4.
958  max_w /= (16 >> Detail.hardware_textures);
959  max_h /= (16 >> Detail.hardware_textures);
960 
963 
964  resize = 1;
965  } else {
966  // we have mipmap levels so use those as a resize point (image should already be power-of-2)
967  base_level = -(Detail.hardware_textures - 4);
968  Assert(base_level >= 0);
969 
970  if (base_level >= max_levels) {
971  base_level = max_levels - 1;
972  }
973 
974  Assert( (max_levels - base_level) >= 1 );
975  }
976  }
977 
978  // get final texture size
979  opengl_tcache_get_adjusted_texture_size(max_w, max_h, &final_w, &final_h);
980 
981  // only resize if we actually need a new size, better data use and speed out of opengl_create_texture_sub()
982  if ( (max_w != final_w) || (max_h != final_h) ) {
983  resize = 1;
984  // little safety check for later, we can't manually resize AND use mipmap resizing
985  Assert( !base_level );
986  }
987 
988  if ( (final_h < 1) || (final_w < 1) ) {
989  mprintf(("Bitmap %s is too small at %dx%d.\n", bm_get_filename(bitmap_handle), final_w, final_h ));
990  return 0;
991  }
992 
993  // if this tcache slot has no bitmap
994  if (tslot->bitmap_handle < 0) {
995  reload = 0;
996  }
997  // different bitmap altogether - determine if the new one can use the old one's slot
998  else if (tslot->bitmap_handle != bitmap_handle) {
999  if ( (final_w == tslot->w) && (final_h == tslot->h) ) {
1000  reload = 1;
1001  } else {
1002  reload = 0;
1003  }
1004  }
1005 
1006  // set the bits per pixel
1007  tslot->bpp = bmp->bpp;
1008 
1009  // max number of mipmap levels (NOTE: this is the max number used by the API, not how many true mipmap levels there are in the image!!)
1010  tslot->mipmap_levels = (ubyte)(max_levels - base_level);
1011 
1012  // call the helper
1013  int ret_val = opengl_create_texture_sub(bitmap_handle, bitmap_type, bmp->w, bmp->h, final_w, final_h, (ubyte*)bmp->data, tslot, base_level, resize, reload);
1014 
1015  // unlock the bitmap
1016  bm_unlock(bitmap_handle);
1017 
1018  // if we successfully sent the texture to API memory then go ahead and dump
1019  // the rest of the bitmap data in system memory.
1020  // NOTE: this doesn't do anything for user bitmaps (like screen grabs or streamed animations)
1021  if (ret_val) {
1022  bm_unload_fast(bitmap_handle);
1023  }
1024 
1025  GL_CHECK_FOR_ERRORS("end of create_texture()");
1026 
1027  return ret_val;
1028 }
1029 
1030 // WARNING: Needs to match what is in bm_internal.h!!!!!
1031 #define RENDER_TARGET_DYNAMIC 17
1032 
1033 int gr_opengl_tcache_set_internal(int bitmap_handle, int bitmap_type, float *u_scale, float *v_scale, int tex_unit = 0)
1034 {
1035  int ret_val = 1;
1036 
1037  GL_CHECK_FOR_ERRORS("start of tcache_set_internal()");
1038 
1042  }
1043 
1044  int n = bm_get_cache_slot (bitmap_handle, 1);
1045  tcache_slot_opengl *t = &Textures[n];
1046 
1047  GL_state.Texture.SetActiveUnit(tex_unit);
1048 
1049  if (!bm_is_render_target(bitmap_handle) &&
1050  ((t->bitmap_handle < 0) || (bitmap_handle != t->bitmap_handle)) )
1051  {
1052  ret_val = opengl_create_texture( bitmap_handle, bitmap_type, t );
1053  }
1054 
1055  // everything went ok
1056  if (ret_val && t->texture_id) {
1057  *u_scale = t->u_scale;
1058  *v_scale = t->v_scale;
1059 
1062 
1063  if ( (t->wrap_mode != GL_texture_addressing) && (bitmap_type != TCACHE_TYPE_AABITMAP)
1064  && (bitmap_type != TCACHE_TYPE_INTERFACE) && (bitmap_type != TCACHE_TYPE_CUBEMAP) )
1065  {
1069 
1071  }
1072 
1073  Tex_used_this_frame[n]++;
1074  }
1075  // gah
1076  else {
1077  mprintf(("Texturing disabled for bitmap %d (%s) due to internal error.\n", bitmap_handle, bm_get_filename(bitmap_handle)));
1079 
1080  return 0;
1081  }
1082 
1083  GL_CHECK_FOR_ERRORS("end of tcache_set_internal()");
1084 
1085  return 1;
1086 }
1087 
1088 int gr_opengl_tcache_set(int bitmap_handle, int bitmap_type, float *u_scale, float *v_scale, int stage)
1089 {
1090  int rc = 0;
1091 
1092  if (bitmap_handle <= 0) {
1093  return 0;
1094  }
1095 
1096  GL_CHECK_FOR_ERRORS("start of tcache_set()");
1097 
1098  // set special type if it's so, needed to be right later, but cubemaps are special
1099  if ( !(bitmap_type == TCACHE_TYPE_CUBEMAP) ) {
1100  int type = bm_get_tcache_type(bitmap_handle);
1101 
1102  if (type != TCACHE_TYPE_NORMAL) {
1103  bitmap_type = type;
1104  }
1105  }
1106 
1107  rc = gr_opengl_tcache_set_internal(bitmap_handle, bitmap_type, u_scale, v_scale, stage);
1108 
1109  GL_CHECK_FOR_ERRORS("end of tcache_set()");
1110 
1111  return rc;
1112 }
1113 
1115 {
1116  if (gr_screen.mode != GR_OPENGL)
1117  return;
1118 
1119 // opengl_tcache_flush ();
1120 }
1121 
1122 int gr_opengl_preload(int bitmap_num, int is_aabitmap)
1123 {
1124  float u_scale, v_scale;
1125  int retval;
1126 
1128 
1129  if ( !GL_should_preload ) {
1130  return 0;
1131  }
1132 
1133  retval = gr_opengl_tcache_set(bitmap_num, (is_aabitmap) ? TCACHE_TYPE_AABITMAP : TCACHE_TYPE_NORMAL, &u_scale, &v_scale);
1134 
1136 
1137  if ( !retval ) {
1138  mprintf(("Texture upload failed!\n"));
1139  }
1140 
1141  return retval;
1142 }
1143 
1144 static int GL_texture_panning_enabled = 0;
1145 void gr_opengl_set_texture_panning(float u, float v, bool enable)
1146 {
1147  if (Cmdline_nohtl)
1148  return;
1149 
1150  GLint current_matrix;
1151 
1152  if (enable) {
1153  glGetIntegerv(GL_MATRIX_MODE, &current_matrix);
1155  glPushMatrix();
1156  glTranslatef( u, v, 0.0f );
1157  glMatrixMode(current_matrix);
1158 
1159  GL_texture_panning_enabled = 1;
1160  } else if (GL_texture_panning_enabled) {
1161  glGetIntegerv(GL_MATRIX_MODE, &current_matrix);
1163  glPopMatrix();
1164  glMatrixMode(current_matrix);
1165 
1166  GL_texture_panning_enabled = 0;
1167  }
1168 }
1169 
1171 {
1172  GL_CHECK_FOR_ERRORS("start of set_texture_addressing()");
1173 
1174  switch (mode) {
1175  case TMAP_ADDRESS_CLAMP:
1177  break;
1178 
1179  case TMAP_ADDRESS_WRAP:
1181  break;
1182 
1183  case TMAP_ADDRESS_MIRROR: {
1186  } else {
1188  }
1189 
1190  break;
1191  }
1192 
1193  default:
1194  Int3();
1195  break;
1196  }
1197 
1198  GL_CHECK_FOR_ERRORS("end of set_texture_addressing()");
1199 }
1200 
1201 void gr_opengl_get_bitmap_from_texture(void* data_out, int bitmap_num)
1202 {
1203  float u,v;
1204 
1205  gr_opengl_tcache_set(bitmap_num, TCACHE_TYPE_NORMAL, &u, &v);
1206 
1207  int n = bm_get_cache_slot(bitmap_num, 1);
1208  tcache_slot_opengl *ts = &Textures[n];
1209 
1210  GLenum pixel_format = GL_RGB;
1211  GLenum data_format = GL_UNSIGNED_BYTE;
1212  int bytes_per_pixel = 3 * sizeof(ubyte);
1213 
1214  if ( bm_has_alpha_channel(bitmap_num) ) {
1215  pixel_format = GL_RGBA;
1216  bytes_per_pixel = 4 * sizeof(ubyte);
1217  }
1218 
1219  opengl_get_texture(ts->texture_target, pixel_format, data_format, 1, ts->w, ts->h, bytes_per_pixel, data_out, 0);
1220 }
1221 
1222 int opengl_get_texture( GLenum target, GLenum pixel_format, GLenum data_format, int num_mipmaps, int width, int height, int bytes_per_pixel, void* image_data, int offset )
1223 {
1224  int m_offset = offset;
1225  int m_width = width;
1226  int m_height = height;
1227 
1228  for ( int i = 0; i < num_mipmaps; i++ ) {
1229  glGetTexImage(target, i, pixel_format, data_format, (ubyte*)image_data + m_offset);
1230 
1231  m_offset += (m_width * m_height * bytes_per_pixel);
1232 
1233  // reduce by half for next mipmap level
1234  m_width >>= 1;
1235  m_height >>= 1;
1236 
1237  if (m_width < 1)
1238  m_width = 1;
1239 
1240  if (m_height < 1)
1241  m_height = 1;
1242  }
1243 
1244  return m_offset;
1245 }
1246 
1256 size_t opengl_export_render_target( int slot, int width, int height, int alpha, int num_mipmaps, ubyte *image_data )
1257 {
1258  tcache_slot_opengl *ts = &Textures[slot];
1259 
1260  GL_CHECK_FOR_ERRORS("start of export_image()");
1261 
1262  if (!image_data) {
1263  mprintf(("OpenGL ERROR: Tried to export a texture without a valid export location!\n"));
1264  return 0;
1265  }
1266 
1267  if (!ts->texture_target) {
1268  mprintf(("OpenGL ERROR: Tried to export a texture for which I don't know the texture target!\n"));
1269  return 0;
1270  }
1271 
1272  if (ts->mipmap_levels != num_mipmaps) {
1273  mprintf(("OpenGL ERROR: Number of mipmap levels requested is different from number available!\n"));
1274  return 0;
1275  }
1276 
1277  if ( (ts->texture_target != GL_TEXTURE_2D) && (ts->texture_target != GL_TEXTURE_CUBE_MAP) ) {
1278  mprintf(("OpenGL ERROR: Only 2D textures and cube maps can be exported!\n"));
1279  return 0;
1280  }
1281 
1282  if ( (ts->w != width) && (ts->h != height) ) {
1283  mprintf(("OpenGL ERROR: Passed width and height do not match values for texture!\n"));
1284  return 0;
1285  }
1286 
1287  int faces = 1;
1288  int m_width = width;
1289  int m_height = height;
1290  int m_bpp = (alpha) ? 4 : 3;
1291  int m_offset = 0;
1293 
1295  faces = 6;
1296 
1300 
1301  for (int i = 0; i < faces; i++) {
1302  m_offset = opengl_get_texture(
1303  target + i,
1304  (alpha) ? GL_BGRA : GL_BGR,
1306  ts->mipmap_levels,
1307  m_width,
1308  m_height,
1309  m_bpp,
1310  image_data,
1311  m_offset
1312  );
1313  }
1314 
1316 
1317  GL_CHECK_FOR_ERRORS("end of export_image()");
1318 
1319  return (size_t)m_offset;
1320 }
1321 
1322 void gr_opengl_update_texture(int bitmap_handle, int bpp, const ubyte* data, int width, int height)
1323 {
1324  GLenum texFormat, glFormat;
1325  int n = bm_get_cache_slot (bitmap_handle, 1);
1326  tcache_slot_opengl *t = &Textures[n];
1327  if(!t->texture_id)
1328  return;
1329  int byte_mult = (bpp >> 3);
1330  int true_byte_mult = (t->bpp >> 3);
1331  ubyte* texmem = NULL;
1332  // GL_BGRA_EXT is *much* faster with some hardware/drivers
1333  if (true_byte_mult == 4) {
1334  texFormat = GL_UNSIGNED_INT_8_8_8_8_REV;
1335  glFormat = GL_BGRA;
1336  } else if (true_byte_mult == 3) {
1337  texFormat = GL_UNSIGNED_BYTE;
1338  glFormat = GL_BGR;
1339  } else {
1340  texFormat = GL_UNSIGNED_SHORT_1_5_5_5_REV;
1341  glFormat = GL_BGRA;
1342  }
1343  if (byte_mult == 1) {
1344  texFormat = GL_UNSIGNED_BYTE;
1345  glFormat = GL_ALPHA;
1346  texmem = (ubyte *) vm_malloc (width*height*byte_mult);
1347  ubyte* texmemp = texmem;
1348 
1349  Assert( texmem != NULL );
1350 
1351  int luminance = 0;
1352  for (int i = 0; i < height; i++) {
1353  for (int j = 0; j < width; j++) {
1354  if ( (i < height) && (j < width) ) {
1355  if ( true_byte_mult > 1 ) {
1356  luminance = 0;
1357 
1358  if ( true_byte_mult > 3 ) {
1359  for (int k = 0; k < 3; k++) {
1360  luminance += data[(i*width+j)*true_byte_mult+k];
1361  }
1362 
1363  *texmemp++ = (ubyte)((luminance / 3) * (data[(i*width+j)*true_byte_mult+3]/255.0f));
1364  } else {
1365  for (int k = 0; k < true_byte_mult; k++) {
1366  luminance += data[(i*width+j)*true_byte_mult+k];
1367  }
1368 
1369  *texmemp++ = (ubyte)(luminance / true_byte_mult);
1370  }
1371  } else {
1372  *texmemp++ = GL_xlat[data[i*width+j]];
1373  }
1374  } else {
1375  *texmemp++ = 0;
1376  }
1377  }
1378  }
1379  }
1381  glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, glFormat, texFormat, (texmem)?texmem:data);
1382  if (texmem != NULL)
1383  vm_free(texmem);
1384 }
1385 
1386 // -----------------------------------------------------------------------------
1387 // GL_EXT_framebuffer_object stuff (ie, render-to-texture)
1388 //
1389 
1390 struct fbo_t {
1391  // these first vars should only be modified in opengl_make_render_target()
1394  int width;
1395  int height;
1397  // these next 2 should only be modifed in opengl_set_render_target()
1400 
1401  fbo_t() :
1402  renderbuffer_id(0), framebuffer_id(0), width(0), height(0),
1403  ref_count(0), working_slot(-1), is_static(0)
1404  {
1405  }
1406 };
1407 
1408 static SCP_vector<fbo_t> RenderTarget;
1409 static fbo_t *render_target = NULL;
1410 
1411 
1413 {
1414  GLenum status;
1415 
1417 
1418  if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
1419  char err_txt[100] = { 0 };
1420 
1421  switch (status) {
1423  strcpy_s(err_txt, "Incomplete attachments!");
1424  break;
1425 
1427  strcpy_s(err_txt, "Missing one or more image attachments!");
1428  break;
1429 
1431  strcpy_s(err_txt, "Attached images do not have the same width and height!");
1432  break;
1433 
1435  strcpy_s(err_txt, "Attached images do not have the same internal format!");
1436  break;
1437 
1439  strcpy_s(err_txt, "Draw buffer attachment point is NONE!");
1440  break;
1441 
1443  strcpy_s(err_txt, "Read buffer attachment point is NONE!");
1444  break;
1445 
1447  strcpy_s(err_txt, "Attached images violate current FBO restrictions!");
1448  break;
1449 
1450  default:
1451  strcpy_s(err_txt, "Unknown error!\n");
1452  break;
1453  }
1454 
1455  mprintf(("Framebuffer ERROR: %s\n", err_txt));
1456 
1457  return (int)status;
1458  }
1459 
1460  return 0;
1461 }
1462 
1463 static fbo_t *opengl_get_fbo(int width, int height)
1464 {
1465  size_t rt_size = RenderTarget.size();
1466 
1467  for (size_t i = 0; i < rt_size; i++) {
1468  if ( (RenderTarget[i].width == width) && (RenderTarget[i].height == height) ) {
1469  return &RenderTarget[i];
1470  }
1471  }
1472 
1473  return NULL;
1474 }
1475 
1477 {
1478  if ( (slot < 0) || (slot >= MAX_BITMAPS) ) {
1479  Int3();
1480  return;
1481  }
1482 
1483  // this will happen when opengl_kill_all_render_targets() gets called first on exit
1484  if ( RenderTarget.empty() ) {
1485  return;
1486  }
1487 
1488  tcache_slot_opengl *ts = &Textures[slot];
1489  size_t idx = 0;
1490 
1491  for (idx = 0; idx < RenderTarget.size(); idx++) {
1492  if ( (RenderTarget[idx].width == ts->w) && (RenderTarget[idx].height == ts->h) ) {
1493  break;
1494  }
1495  }
1496 
1497  // this may happen when textures are flushed, the w and h will get reset to 0
1498  if ( idx >= RenderTarget.size() ) {
1499  return;
1500  }
1501 
1502  RenderTarget[idx].ref_count--;
1503 
1504  if (RenderTarget[idx].ref_count <= 0) {
1505  mprintf(("OpenGL: Killing off unused %ix%i render target...\n", ts->w, ts->h));
1506 
1507  if (RenderTarget[idx].framebuffer_id) {
1508  vglDeleteFramebuffersEXT(1, &RenderTarget[idx].framebuffer_id);
1509  RenderTarget[idx].framebuffer_id = 0;
1510  }
1511 
1512  if (RenderTarget[idx].renderbuffer_id) {
1513  vglDeleteRenderbuffersEXT(1, &RenderTarget[idx].renderbuffer_id);
1514  RenderTarget[idx].renderbuffer_id = 0;
1515  }
1516 
1517  RenderTarget.erase( RenderTarget.begin() + idx );
1518  } else {
1519  mprintf(("OpenGL: Keeping %ix%i render target with ref_count of %i.\n", ts->w, ts->h, RenderTarget[idx].ref_count));
1520  }
1521 }
1522 
1524 {
1525  for (size_t i = 0; i < RenderTarget.size(); i++) {
1526  fbo_t *fbo = &RenderTarget[i];
1527 
1528  if (fbo->framebuffer_id) {
1530  fbo->framebuffer_id = 0;
1531  }
1532 
1533  if (fbo->renderbuffer_id) {
1535  fbo->renderbuffer_id = 0;
1536  }
1537  }
1538 
1539  RenderTarget.clear();
1540 }
1541 
1542 int opengl_set_render_target( int slot, int face, int is_static )
1543 {
1544  tcache_slot_opengl *ts = NULL;
1545  fbo_t *fbo = NULL;
1546 
1547  GL_CHECK_FOR_ERRORS("start of set_render_target()");
1548 
1549  if (slot < 0) {
1550  if ( (render_target != NULL) && (render_target->working_slot >= 0) ) {
1551  if (render_target->is_static) {
1552  extern void gr_opengl_bm_save_render_target(int slot);
1554  }
1555  }
1556 
1558 
1561 
1562  if (render_target != NULL) {
1563  render_target->working_slot = -1;
1564  render_target->is_static = 0;
1565  }
1566 
1567  // done with this render target so lets move on
1568  render_target = NULL;
1569 
1570  GL_rendering_to_texture = false;
1571 
1572  GL_CHECK_FOR_ERRORS("end of set_render_target(0)");
1573 
1574  return 1;
1575  }
1576 
1577  ts = &Textures[slot];
1578  Assert( ts != NULL );
1579 
1580  if (!ts->texture_id) {
1581  Int3();
1582  return 0;
1583  }
1584 
1585  fbo = opengl_get_fbo(ts->w, ts->h);
1586 
1587  if (fbo == NULL) {
1588  mprintf(("Tried to get an OpenGL FBO that didn't exist!\n"));
1589  return 0;
1590  }
1591 
1592  if ( !vglIsFramebufferEXT(fbo->framebuffer_id) /*|| !vglIsRenderbufferEXT(fbo->renderbuffer_id)*/ ) {
1593  Int3();
1594  return 0;
1595  }
1596 
1597 // vglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->renderbuffer_id);
1599 
1600  if (ts->texture_target == GL_TEXTURE_CUBE_MAP) {
1601  Assert( (face >= 0) && (face < 6) );
1603  } else {
1604  Assert( face <= 0 );
1606  }
1607 
1608 // vglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->renderbuffer_id);
1609 
1610  if ( opengl_check_framebuffer() ) {
1611  Int3();
1612  return 0;
1613  }
1614 
1615  fbo->working_slot = slot;
1616  fbo->is_static = is_static;
1617 
1618  // save current fbo for later use
1619  render_target = fbo;
1620 
1621  GL_rendering_to_texture = true;
1622 
1623  GL_CHECK_FOR_ERRORS("end of set_render_target()");
1624 
1625  return 1;
1626 }
1627 
1628 int opengl_make_render_target( int handle, int slot, int *w, int *h, ubyte *bpp, int *mm_lvl, int flags )
1629 {
1631 
1632  if (slot < 0) {
1633  Int3();
1634  return 0;
1635  }
1636 
1637  // got to have at least width and height!
1638  if (!w || !h) {
1639  Int3();
1640  return 0;
1641  }
1642 
1643  // size check
1644  if (*w > GL_max_renderbuffer_size) {
1646  }
1647 
1648  if (*h > GL_max_renderbuffer_size) {
1650  }
1651 
1652  tcache_slot_opengl *ts = &Textures[slot];
1653  fbo_t *fbo = opengl_get_fbo(*w, *h);
1654 
1655  GL_CHECK_FOR_ERRORS("start of make_render_target()");
1656 
1657  // since we only deal with one frame/render buffer, see if we need to modify what we have or use it as is
1658  if ( (fbo != NULL) && (fbo->width == *w) && (fbo->height == *h) ) {
1659  // both should be valid, but we check to catch the off-chance that something is fubar
1660  Assert( vglIsFramebufferEXT(fbo->framebuffer_id) /*&& vglIsRenderbufferEXT(fbo->renderbuffer_id)*/ );
1661 
1662  // we can use the existing FBO without modification so just setup the texture slot and move on
1663  if (flags & BMP_FLAG_CUBEMAP) {
1665  } else {
1667  }
1668 
1669  glGenTextures(1, &ts->texture_id);
1670 
1674 
1679 
1680  if (flags & BMP_FLAG_CUBEMAP) {
1681  // if a cubemap then we have to initalize each face
1682  for (int i = 0; i < 6; i++) {
1684  }
1685 
1687  } else {
1688  // non-cubemap so just do the normal thing
1691  }
1692 
1693  /* if (Cmdline_mipmap) {
1694  vglGenerateMipmapEXT(GL_state.Texture.GetTarget());
1695 
1696  extern int get_num_mipmap_levels(int w, int h);
1697  ts->mipmap_levels = get_num_mipmap_levels(*w, *h);
1698  } else */
1699  {
1700  ts->mipmap_levels = 1;
1701  }
1702 
1704 
1705  ts->w = (ushort)*w;
1706  ts->h = (ushort)*h;
1707  ts->bpp = 24;
1708  ts->bitmap_handle = -1;//handle;
1709  ts->u_scale = 1.0f;
1710  ts->v_scale = 1.0f;
1711 
1712  if (bpp) {
1713  *bpp = ts->bpp;
1714  }
1715 
1716  if (mm_lvl) {
1717  *mm_lvl = ts->mipmap_levels;
1718  }
1719 
1721 
1722  fbo->ref_count++;
1723 
1724  mprintf(("OpenGL: Reusing %ix%i FBO!\n", *w, *h));
1725 
1726  GL_CHECK_FOR_ERRORS("end of make_render_target(0)");
1727 
1728  return 1;
1729  }
1730 
1731  // now on to the good parts...
1732 
1733  fbo_t new_fbo;
1734 
1735  if (flags & BMP_FLAG_CUBEMAP) {
1737  } else {
1739  }
1740 
1741  // initialize color texture
1742  glGenTextures(1, &ts->texture_id);
1743 
1747 
1752 
1753  if (flags & BMP_FLAG_CUBEMAP) {
1754  // if a cubemap then we have to initalize each face
1755  for (int i = 0; i < 6; i++) {
1757  }
1758  } else {
1759  // non-cubemap so just do the normal thing
1761  }
1762 
1763 /* if (Cmdline_mipmap) {
1764  vglGenerateMipmapEXT(GL_state.Texture.GetTarget());
1765 
1766  extern int get_num_mipmap_levels(int w, int h);
1767  ts->mipmap_levels = get_num_mipmap_levels(*w, *h);
1768  } else */
1769  {
1770  ts->mipmap_levels = 1;
1771  }
1772 
1774 
1775  // render buffer
1776 // vglGenRenderbuffersEXT(1, &new_fbo.renderbuffer_id);
1777 // vglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, new_fbo.renderbuffer_id);
1778 // vglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, *w, *h);
1780 
1781  // frame buffer
1784 
1785  if (flags & BMP_FLAG_CUBEMAP) {
1787  } else {
1789  }
1790 
1791 // vglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, new_fbo.renderbuffer_id);
1792 
1793  if ( opengl_check_framebuffer() ) {
1794  // Oops!! reset everything and then bail
1795  mprintf(("OpenGL: Unable to create FBO!\n"));
1796 
1798 
1801  glDeleteTextures(1, &ts->texture_id);
1802  ts->texture_id = 0;
1803 
1805 
1806  // vglDeleteRenderbuffersEXT(1, &new_fbo.renderbuffer_id);
1807 
1809 
1810  return 0;
1811  }
1812 
1813  // save anything that needs saving, cleanup, and then exit
1814  ts->w = (ushort)*w;
1815  ts->h = (ushort)*h;
1816  ts->bpp = 24;
1818  ts->bitmap_handle = -1;//handle;
1819  ts->u_scale = 1.0f;
1820  ts->v_scale = 1.0f;
1821 
1822  new_fbo.width = ts->w;
1823  new_fbo.height = ts->h;
1824 
1825  if (bpp) {
1826  *bpp = ts->bpp;
1827  }
1828 
1829  if (mm_lvl) {
1830  *mm_lvl = ts->mipmap_levels;
1831  }
1832 
1833  // Clear the new Texture to black with alpha 1.0
1834  glClearColor(0.0f,0.0f,0.0f,1.0f);
1836 
1838 
1839  new_fbo.ref_count++;
1840 
1841  RenderTarget.push_back(new_fbo);
1842 
1844 
1845 
1846  mprintf(("OpenGL: Created %ix%i FBO!\n", ts->w, ts->h));
1847 
1848  GL_CHECK_FOR_ERRORS("end of make_render_target()");
1849 
1850  return 1;
1851 }
1852 
1870 {
1871  if (render_target == NULL || render_target->working_slot < 0)
1872  return 0;
1873  else
1874  return render_target->framebuffer_id;
1875 }
1876 
1877 //
1878 // End of GL_EXT_framebuffer_object stuff
1879 // -----------------------------------------------------------------------------
unsigned int GLuint
Definition: Gl.h:52
void bm_unlock(int handle)
Unlocks a bitmap.
Definition: bmpman.cpp:3005
GLuint framebuffer_id
#define vm_malloc_q(size)
Definition: pstypes.h:554
ubyte bpp
Requested bitdepth of each pixel. ( 7, 8, 15, 16, 24, 32)
Definition: bmpman.h:106
#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
Definition: Glext.h:3233
int i
Definition: multi_pxo.cpp:466
#define vm_free(ptr)
Definition: pstypes.h:548
WINGDIAPI void APIENTRY glGetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels)
uint os_config_read_uint(const char *section, const char *name, uint default_value)
Definition: osregistry.cpp:372
#define OGL_EXT_FRAMEBUFFER_OBJECT
#define TCACHE_TYPE_COMPRESSED
Definition: grinternal.h:54
#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT
Definition: Glext.h:4184
#define BMP_TEX_DXT3
dxt3 compressed 8r8g8b4a (32bit)
Definition: bmpman.h:56
GLfloat GLfloat GLfloat GLfloat h
Definition: Glext.h:7280
#define F1_0
Definition: fix.h:15
GLfloat GL_max_anisotropy
#define vglIsFramebufferEXT
#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT
Definition: Glext.h:4182
void gr_opengl_set_texture_panning(float u, float v, bool enable)
GLfloat opengl_get_max_anisotropy()
#define vglBindFramebufferEXT
int mode
Definition: 2d.h:371
#define GL_TEXTURE_CUBE_MAP_POSITIVE_X
Definition: Glext.h:226
WINGDIAPI void APIENTRY glMatrixMode(GLenum mode)
WINGDIAPI GLboolean APIENTRY glIsTexture(GLuint texture)
WINGDIAPI void APIENTRY glClear(GLbitfield mask)
#define vglCompressedTexSubImage2D
Assert(pm!=NULL)
void opengl_tcache_get_adjusted_texture_size(int w_in, int h_in, int *w_out, int *h_out)
WINGDIAPI void APIENTRY glTexEnvf(GLenum target, GLenum pname, GLfloat param)
#define mprintf(args)
Definition: pstypes.h:238
WINGDIAPI void APIENTRY glDeleteTextures(GLsizei n, const GLuint *textures)
#define GL_MODULATE
Definition: Gl.h:907
int opengl_create_texture_sub(int bitmap_handle, int bitmap_type, int bmap_w, int bmap_h, int tex_w, int tex_h, ubyte *data=NULL, tcache_slot_opengl *t=NULL, int base_level=0, int resize=0, int reload=0)
#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT
Definition: Glext.h:3230
GLuint opengl_get_rtt_framebuffer()
Gets the current RTT framebuffer.
#define DDS_CUBEMAP_DXT3
Definition: ddsutils.h:28
GLclampf f
Definition: Glext.h:7097
ubyte GL_xlat[256]
int GL_texture_ram
int bits_per_pixel
Definition: 2d.h:374
#define OGL_ARB_TEXTURE_MIRRORED_REPEAT
GLuint renderbuffer_id
#define Assertion(expr, msg,...)
Definition: clang.h:41
enum_h * u
Definition: lua.cpp:12649
bool opengl_texture_slot_valid(int n, int handle)
int bm_get_tcache_type(int num)
Gets the correct TCACHE_TYPE for compressed graphics (uncompressed are assumed TCACHE_TYPE_NORMAL) ...
Definition: bmpman.cpp:887
GLenum mode
Definition: Glext.h:5794
#define GL_TEXTURE_MAX_LEVEL
Definition: Glext.h:85
void opengl_free_texture_with_handle(int handle)
#define GL_UNSIGNED_SHORT_1_5_5_5_REV
Definition: Glext.h:74
const char * os_config_read_string(const char *section, const char *name, const char *default_value)
Definition: osregistry.cpp:322
opengl_texture_state Texture
GLenum GL_texture_addressing
#define GL_ALPHA
Definition: Gl.h:783
GLenum GL_texture_target
bool GL_initted
Definition: gropengl.cpp:60
#define BMP_TEX_DXT5
dxt5 compressed 8r8g8b8a (32bit)
Definition: bmpman.h:57
#define TMAP_ADDRESS_MIRROR
Definition: tmapper.h:95
void gr_opengl_update_texture(int bitmap_handle, int bpp, const ubyte *data, int width, int height)
#define Int3()
Definition: pstypes.h:292
bool bm_has_alpha_channel(int handle)
Checks to see if the indexed bitmap has an alpha channel.
Definition: bmpman.cpp:903
#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT
Definition: Glext.h:3108
#define GL_UNSIGNED_BYTE
Definition: Gl.h:192
int opengl_free_texture(tcache_slot_opengl *t)
#define GL_MAX_TEXTURE_SIZE
Definition: Gl.h:524
short h
Height, in number of pixels.
Definition: bmpman.h:104
#define GL_TEXTURE_WRAP_S
Definition: Gl.h:944
int bm_unload_fast(int handle, int clear_render_targets)
Quickly unloads a bitmap's data, ignoring the load_count.
Definition: bmpman.cpp:2968
#define GR_OPENGL
Definition: 2d.h:648
void opengl_tcache_shutdown()
WINGDIAPI void APIENTRY glPopMatrix(void)
GLenum type
Definition: Gl.h:1492
#define BMP_AABITMAP
antialiased bitmap
Definition: bmpman.h:52
#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT
Definition: Glext.h:4181
int opengl_set_render_target(int slot, int face, int is_static)
#define CLAMP(x, min, max)
Definition: pstypes.h:488
GLint GLsizei width
Definition: Gl.h:1505
#define GL_BGRA
Definition: Glext.h:78
void SetEnvMode(GLenum mode)
#define vglFramebufferTexture2DEXT
#define GL_RGB
Definition: Gl.h:784
GLenum GLuint GLint GLenum face
Definition: Glext.h:6586
#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT
Definition: Glext.h:4185
#define GL_ADD
Definition: Gl.h:69
GLint GL_max_texture_height
GLintptr offset
Definition: Glext.h:5497
int Cmdline_nohtl
Definition: cmdline.cpp:438
int GL_min_texture_height
int Interp_multitex_cloakmap
#define GL_RGB8
Definition: Gl.h:1000
#define GL_LINEAR
Definition: Gl.h:931
int CLOAKMAP
Definition: ship.cpp:14145
int GLOWMAP
References a map that is a fully lit version of its index -Bobboau.
Definition: bmpman.cpp:57
#define BMP_TEX_DXT1
dxt1 compressed 8r8g8b1a (24bit)
Definition: bmpman.h:55
int bm_is_compressed(int num)
Returns the compression type of the bitmap indexed by handle.
Definition: bmpman.cpp:952
#define GL_RGBA8
Definition: Gl.h:1007
#define vglBindRenderbufferEXT
#define vglDeleteRenderbuffersEXT
detail_levels Detail
Definition: systemvars.cpp:478
#define f2i(a)
Definition: fix.h:22
#define BMP_FLAG_CUBEMAP
Texture is a cubemap.
Definition: bmpman.h:68
int GL_min_texture_width
#define DDS_DXT5
Definition: ddsutils.h:25
void opengl_tcache_flush()
int GL_last_detail
#define GL_REPEAT
Definition: Gl.h:957
bool GL_rendering_to_texture
#define OGL_EXT_TEXTURE_LOD_BIAS
#define GL_COMBINE_RGB
Definition: Glext.h:259
WINGDIAPI void APIENTRY glTexParameterf(GLenum target, GLenum pname, GLfloat param)
#define GL_FRAMEBUFFER_EXT
Definition: Glext.h:4207
size_t opengl_export_render_target(int slot, int width, int height, int alpha, int num_mipmaps, ubyte *image_data)
#define TCACHE_TYPE_INTERFACE
Definition: grinternal.h:53
WINGDIAPI void APIENTRY glGenTextures(GLsizei n, GLuint *textures)
#define TCACHE_TYPE_CUBEMAP
Definition: grinternal.h:55
ogl_extension GL_Extensions[NUM_OGL_EXTENSIONS]
#define w(p)
Definition: modelsinc.h:68
GLint GL_supported_texture_units
const char * bm_get_filename(int handle)
Gets the filename of the bitmap indexed by handle, which must exist.
Definition: bmpman.cpp:727
#define GL_RGB5
Definition: Gl.h:999
#define GL_TEXTURE_MAX_ANISOTROPY_EXT
Definition: Glext.h:3107
short w
Width, in number of pixels.
Definition: bmpman.h:103
int hardware_textures
Definition: systemvars.h:169
int GL_mipmap_filter
Definition: bmpman.h:101
#define GL_FRAMEBUFFER_COMPLETE_EXT
Definition: Glext.h:4180
#define OGL_ARB_TEXTURE_CUBE_MAP
WINGDIAPI void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
int gr_opengl_tcache_set_internal(int bitmap_handle, int bitmap_type, float *u_scale, float *v_scale, int tex_unit=0)
bitmap * bm_lock(int handle, ubyte bpp, ubyte flags, bool nodebug)
Locks down the bitmap indexed by bitmapnum.
Definition: bmpman.cpp:1754
#define vglCheckFramebufferStatusEXT
void opengl_kill_render_target(int slot)
#define GL_TEXTURE_LOD_BIAS
Definition: Glext.h:295
#define GL_TEXTURE_WRAP_R
Definition: Glext.h:68
#define GL_CHECK_FOR_ERRORS(s)
Definition: gropengl.h:661
#define BMP_TEX_OTHER
so we can identify all "normal" textures
Definition: bmpman.h:54
int bm_is_render_target(int bitmap_id)
Checks to see if the given bitmap indexed by handle is a render target.
Definition: bmpman.cpp:993
int idx
Definition: multiui.cpp:761
#define GL_TEXTURE_MAG_FILTER
Definition: Gl.h:942
#define GL_LINEAR_MIPMAP_LINEAR
Definition: Gl.h:939
GLdouble GLdouble t
Definition: Glext.h:5329
#define Is_Extension_Enabled(x)
void opengl_set_modulate_tex_env()
void SetTarget(GLenum tex_target)
WINGDIAPI void APIENTRY glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
long fix
Definition: pstypes.h:54
GLclampd n
Definition: Glext.h:7286
unsigned char ubyte
Definition: pstypes.h:62
void Enable(GLuint tex_id=0)
int opengl_create_texture(int bitmap_handle, int bitmap_type, tcache_slot_opengl *tslot=NULL)
int GL_should_preload
#define GL_CLAMP_TO_EDGE
Definition: Glext.h:81
WINGDIAPI void APIENTRY glGetIntegerv(GLenum pname, GLint *params)
#define NOX(s)
Definition: pstypes.h:473
#define TCACHE_TYPE_XPARENT
Definition: grinternal.h:52
void _cdecl void void _cdecl Error(const char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
#define TMAP_ADDRESS_WRAP
Definition: tmapper.h:94
GLint GL_max_texture_width
#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT
Definition: Glext.h:4186
void opengl_tcache_init()
#define GL_UNSIGNED_INT_8_8_8_8_REV
Definition: Glext.h:75
GLbitfield flags
Definition: Glext.h:6722
#define vm_malloc(size)
Definition: pstypes.h:547
GLboolean enable
Definition: Glext.h:10591
void opengl_free_texture_slot(int n)
int bm_get_cache_slot(int bitmap_id, int separate_ani_frames)
Definition: bmpman.cpp:669
#define GL_TEXTURE_2D
Definition: Gl.h:570
#define BMP_TEX_CUBEMAP
a texture made for cubic environment map
Definition: bmpman.h:58
void opengl_set_additive_tex_env()
typedef float(SCP_EXT_CALLCONV *SCPTRACKIR_PFFLOATVOID)()
#define GL_TEXTURE_WRAP_T
Definition: Gl.h:945
WINGDIAPI void APIENTRY glGetFloatv(GLenum pname, GLfloat *params)
#define GL_RENDERBUFFER_EXT
Definition: Glext.h:4208
opengl_state GL_state
#define DDS_DXT3
Definition: ddsutils.h:24
GLint GLsizei GLsizei height
Definition: Gl.h:1505
GLubyte GLubyte GLubyte GLubyte w
Definition: Glext.h:5679
#define vglGenFramebuffersEXT
WINGDIAPI void APIENTRY glPushMatrix(void)
#define GL_TEXTURE_CUBE_MAP
Definition: Glext.h:224
int gr_opengl_preload(int bitmap_num, int is_aabitmap)
#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
Definition: Glext.h:3232
#define GL_MAX_TEXTURE_UNITS_ARB
Definition: Glext.h:1085
#define vglDeleteFramebuffersEXT
#define GL_TEXTURE_MIN_FILTER
Definition: Gl.h:943
void gr_opengl_get_bitmap_from_texture(void *data_out, int bitmap_num)
GLenum target
Definition: Glext.h:6872
screen gr_screen
Definition: 2d.cpp:46
#define TCACHE_TYPE_NORMAL
Definition: grinternal.h:51
void opengl_set_texture_target(GLenum target)
unsigned short ushort
Definition: pstypes.h:63
void gr_opengl_set_texture_addressing(int mode)
int GL_textures_in_frame
#define GL_FRAMEBUFFER_UNSUPPORTED_EXT
Definition: Glext.h:4187
int SPECMAP
References a map that is for specular mapping -Bobboau.
Definition: bmpman.cpp:58
#define OGL_ARB_TEXTURE_NON_POWER_OF_TWO
#define LOCATION
Definition: pstypes.h:245
#define OGL_EXT_TEXTURE_FILTER_ANISOTROPIC
GLenum GLsizei GLenum GLenum const GLvoid * data
Definition: Gl.h:1509
GLint GL_max_renderbuffer_size
ptr_u data
Pointer to data, or maybe offset into VRAM.
Definition: bmpman.h:109
WINGDIAPI void APIENTRY glBindTexture(GLenum target, GLuint texture)
void SetRGBScale(GLfloat scale)
Definition: gropenglstate.h:97
#define GL_TEXTURE
Definition: Gl.h:753
GLenum GL_texture_face
GLfloat GL_anisotropy
#define GL_MATRIX_MODE
Definition: Gl.h:429
void Delete(GLuint tex_id)
void opengl_preload_init()
#define MAX_BITMAPS
How many bitmaps the game can handle.
Definition: bmpman.h:48
int opengl_make_render_target(int handle, int slot, int *w, int *h, ubyte *bpp, int *mm_lvl, int flags)
unsigned int GLenum
Definition: Gl.h:43
int gr_opengl_tcache_set(int bitmap_handle, int bitmap_type, float *u_scale, float *v_scale, int stage)
WINGDIAPI void APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)
WINGDIAPI void APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param)
int GL_textures_in
void opengl_tcache_frame()
#define DDS_CUBEMAP_DXT1
Definition: ddsutils.h:27
int opengl_get_texture(GLenum target, GLenum pixel_format, GLenum data_format, int num_mipmaps, int width, int height, int bytes_per_pixel, void *image_data, int offset)
#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT
Definition: Glext.h:4183
#define DDS_CUBEMAP_DXT5
Definition: ddsutils.h:29
#define GL_BGR
Definition: Glext.h:77
#define TMAP_ADDRESS_CLAMP
Definition: tmapper.h:96
#define GL_RGB5_A1
Definition: Gl.h:1006
int opengl_check_framebuffer()
WINGDIAPI void APIENTRY glTranslatef(GLfloat x, GLfloat y, GLfloat z)
GLclampf GLclampf GLclampf alpha
Definition: Glext.h:5177
#define BMP_TEX_XPARENT
transparent texture
Definition: bmpman.h:53
void opengl_kill_all_render_targets()
#define GL_COLOR_BUFFER_BIT
Definition: Gl.h:96
#define GL_TEXTURE_FILTER_CONTROL
Definition: Glext.h:324
int bm_get_num_mipmaps(int num)
Gets the number of mipmaps of the indexed texture.
Definition: bmpman.cpp:838
#define DDS_DXT1
Definition: ddsutils.h:23
const GLdouble * v
Definition: Glext.h:5322
void gr_opengl_bm_save_render_target(int n)
#define GL_MAX_RENDERBUFFER_SIZE_EXT
Definition: Glext.h:4172
#define GL_MIRRORED_REPEAT_ARB
Definition: Glext.h:1242
#define vglCompressedTexImage2D
void SetActiveUnit(GLuint id=0)
#define GL_COLOR_ATTACHMENT0_EXT
Definition: Glext.h:4189
#define OGL_ARB_TEXTURE_ENV_COMBINE
#define GL_LINEAR_MIPMAP_NEAREST
Definition: Gl.h:937
int GLint
Definition: Gl.h:48
#define strcpy_s(...)
Definition: safe_strings.h:67
int ENVMAP
References a map that is for environment mapping -Bobboau.
Definition: bmpman.cpp:59
#define TCACHE_TYPE_AABITMAP
Definition: grinternal.h:50
#define GL_RGBA
Definition: Gl.h:785
float GLfloat
Definition: Gl.h:53
void SetEnvCombineMode(GLenum cmode, GLenum cfunc)