]> icculus.org git repositories - taylor/freespace2.git/blob - src/graphics/grgl1texture.cpp
clean up Show_cpu and Show_mem routines; use generic Gr_textures_in
[taylor/freespace2.git] / src / graphics / grgl1texture.cpp
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
6  * the source.
7  */
8
9 #include "pstypes.h"
10 #include "2d.h"
11 #include "gropengl.h"
12 #include "grgl1.h"
13 #include "gropenglinternal.h"
14 #include "bmpman.h"
15 #include "grinternal.h"
16 #include "systemvars.h"
17 #include "osregistry.h"
18
19
20 int vram_full = 0;
21
22 typedef struct tcache_slot_opengl {
23         GLuint  texture_handle;
24         float   u_scale, v_scale;
25         int     bitmap_id;
26         int     size;
27         int     used_this_frame;
28         int     time_created;
29         ushort  w,h;
30
31         // sections
32         tcache_slot_opengl      *data_sections[MAX_BMAP_SECTIONS_X][MAX_BMAP_SECTIONS_Y];
33         tcache_slot_opengl      *parent;
34
35         gr_texture_source       texture_mode;
36 } tcache_slot_opengl;
37
38 static void *Texture_sections = NULL;
39 static tcache_slot_opengl *Textures = NULL;
40
41 static tcache_slot_opengl *GL_bound_texture;
42
43 static int GL_frame_count = 0;
44 static int GL_last_bitmap_id = -1;
45 static int GL_last_detail = -1;
46 static int GL_last_bitmap_type = -1;
47 static int GL_last_section_x = -1;
48 static int GL_last_section_y = -1;
49 static int GL_should_preload = 0;
50
51 extern int Gr_textures_in;
52
53 static gr_texture_source GL_current_texture_source = (gr_texture_source) -1;
54
55 static ubyte GL_xlat[256] = { 0 };
56
57 extern int bm_get_cache_slot( int bitmap_id, int separate_ani_frames );
58
59
60 void opengl1_set_texture_state(gr_texture_source ts)
61 {
62         if (ts == TEXTURE_SOURCE_NONE) {
63                 GL_bound_texture = NULL;
64
65                 glBindTexture(GL_TEXTURE_2D, 0);
66                 opengl1_tcache_set(-1, -1, NULL, NULL, 0, -1, -1, 0 );
67         } else if (GL_bound_texture &&
68                 GL_bound_texture->texture_mode != ts) {
69                 switch (ts) {
70                         case TEXTURE_SOURCE_DECAL:
71                                 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
72                                 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
73                                 break;
74                         case TEXTURE_SOURCE_NO_FILTERING:
75                                 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
76                                 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
77                                 break;
78                         default:
79                                 break;
80                 }
81
82                 GL_bound_texture->texture_mode = ts;
83         }
84
85         GL_current_texture_source = ts;
86 }
87
88
89 void opengl1_tcache_init()
90 {
91         int i, idx, s_idx;
92
93         uint tmp_pl = os_config_read_uint( NULL, NOX("PreloadTextures"), 1 );
94
95         if (tmp_pl == 1) {
96                 GL_should_preload = 1;
97         } else {
98                 GL_should_preload = 0;
99         }
100
101         Textures = (tcache_slot_opengl *)malloc(MAX_BITMAPS*sizeof(tcache_slot_opengl));
102         if ( !Textures )        {
103                 exit(1);
104         }
105
106         if (gr_screen.use_sections) {
107                 Texture_sections = (tcache_slot_opengl*)malloc(MAX_BITMAPS * MAX_BMAP_SECTIONS_X * MAX_BMAP_SECTIONS_Y * sizeof(tcache_slot_opengl));
108                 if(!Texture_sections){
109                         exit(1);
110                 }
111                 memset(Texture_sections, 0, MAX_BITMAPS * MAX_BMAP_SECTIONS_X * MAX_BMAP_SECTIONS_Y * sizeof(tcache_slot_opengl));
112         }
113
114         // Init the texture structures
115         int section_count = 0;
116         for( i=0; i<MAX_BITMAPS; i++ )  {
117                 Textures[i].texture_handle = 0;
118
119                 Textures[i].bitmap_id = -1;
120                 Textures[i].size = 0;
121                 Textures[i].used_this_frame = 0;
122
123                 Textures[i].parent = NULL;
124
125                 // allocate sections
126                 if (gr_screen.use_sections) {
127                         for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
128                                 for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
129                                         Textures[i].data_sections[idx][s_idx] = &((tcache_slot_opengl*)Texture_sections)[section_count++];
130                                         Textures[i].data_sections[idx][s_idx]->parent = &Textures[i];
131                                         Textures[i].data_sections[idx][s_idx]->texture_handle = 0;
132                                         Textures[i].data_sections[idx][s_idx]->bitmap_id = -1;
133                                         Textures[i].data_sections[idx][s_idx]->size = 0;
134                                         Textures[i].data_sections[idx][s_idx]->used_this_frame = 0;
135                                 }
136                         }
137                 } else {
138                         for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
139                                 for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
140                                         Textures[i].data_sections[idx][s_idx] = NULL;
141                                 }
142                         }
143                 }
144         }
145
146         GL_last_detail = Detail.hardware_textures;
147         GL_last_bitmap_id = -1;
148         GL_last_bitmap_type = -1;
149
150         GL_last_section_x = -1;
151         GL_last_section_y = -1;
152 }
153
154 static int opengl1_free_texture ( tcache_slot_opengl *t )
155 {
156         int idx, s_idx;
157
158
159         // Bitmap changed!!
160         if ( t->bitmap_id > -1 )        {
161                 // if I, or any of my children have been used this frame, bail
162                 if(t->used_this_frame == GL_frame_count){
163                         return 0;
164                 }
165
166                 if (gr_screen.use_sections) {
167                         for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
168                                 for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
169                                         if((t->data_sections[idx][s_idx] != NULL) && (t->data_sections[idx][s_idx]->used_this_frame == GL_frame_count)){
170                                                 return 0;
171                                         }
172                                 }
173                         }
174                 }
175
176                 // ok, now we know its legal to free everything safely
177                 t->texture_mode = (gr_texture_source) -1;
178                 glDeleteTextures (1, &t->texture_handle);
179                 t->texture_handle = 0;
180
181                 if ( GL_last_bitmap_id == t->bitmap_id )       {
182                         GL_last_bitmap_id = -1;
183                 }
184
185                 // if this guy has children, free them too, since the children
186                 // actually make up his size
187                 if (gr_screen.use_sections) {
188                         for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
189                                 for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
190                                         if(t->data_sections[idx][s_idx] != NULL){
191                                                 opengl1_free_texture(t->data_sections[idx][s_idx]);
192                                         }
193                                 }
194                         }
195                 }
196
197                 t->bitmap_id = -1;
198                 t->used_this_frame = 0;
199                 Gr_textures_in -= t->size;
200                 t->size = 0;
201         }
202
203         return 1;
204 }
205
206 void opengl1_free_texture_with_handle(int handle)
207 {
208         for(int i=0; i<MAX_BITMAPS; i++ )  {
209                 if (Textures[i].bitmap_id == handle) {
210                         Textures[i].used_this_frame = 0; // this bmp doesn't even exist any longer...
211                         opengl1_free_texture ( &Textures[i] );
212                 }
213         }
214 }
215
216 void opengl1_tcache_flush()
217 {
218         int i;
219
220         for( i=0; i<MAX_BITMAPS; i++ )  {
221                 opengl1_free_texture ( &Textures[i] );
222         }
223         if (Gr_textures_in != 0) {
224                 mprintf(( "WARNING: VRAM is at %d instead of zero after flushing!\n", Gr_textures_in ));
225                 Gr_textures_in = 0;
226         }
227
228         GL_last_bitmap_id = -1;
229         GL_last_section_x = -1;
230         GL_last_section_y = -1;
231 }
232
233 void opengl1_tcache_cleanup()
234 {
235         opengl1_tcache_flush ();
236
237         if ( Textures ) {
238                 free(Textures);
239                 Textures = NULL;
240         }
241
242         if( Texture_sections != NULL ){
243                 free(Texture_sections);
244                 Texture_sections = NULL;
245         }
246 }
247
248 void opengl1_tcache_frame()
249 {
250         GL_last_bitmap_id = -1;
251
252         GL_frame_count++;
253
254         /*
255         int idx, s_idx;
256         int i;
257         for( i=0; i<MAX_BITMAPS; i++ )  {
258                 Textures[i].used_this_frame = 0;
259
260                 // data sections
261                 if(Textures[i].data_sections[0][0] != NULL){
262                         SDL_assert(GL_texture_sections);
263                         if(GL_texture_sections){
264                                 for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
265                                         for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
266                                                 if(Textures[i].data_sections[idx][s_idx] != NULL){
267                                                         Textures[i].data_sections[idx][s_idx]->used_this_frame = 0;
268                                                 }
269                                         }
270                                 }
271                         }
272                 }
273         }
274         */
275
276         if ( vram_full )        {
277                 opengl1_tcache_flush();
278                 vram_full = 0;
279         }
280 }
281
282 static void opengl1_tcache_get_adjusted_texture_size(int w_in, int h_in, int *w_out, int *h_out)
283 {
284         int tex_w, tex_h;
285         int i;
286
287         // bogus
288         if((w_out == NULL) ||  (h_out == NULL)){
289                 return;
290         }
291
292         // starting size
293         tex_w = w_in;
294         tex_h = h_in;
295
296         // set height and width to a power of 2
297         for (i=0; i<16; i++ )   {
298                 if ( (tex_w > (1<<i)) && (tex_w <= (1<<(i+1))) )        {
299                         tex_w = 1 << (i+1);
300                         break;
301                 }
302         }
303
304         for (i=0; i<16; i++ )   {
305                 if ( (tex_h > (1<<i)) && (tex_h <= (1<<(i+1))) )        {
306                         tex_h = 1 << (i+1);
307                         break;
308                 }
309         }
310
311         // try to keep an 8:1 size ratio
312         if (tex_w/tex_h > 8)
313                 tex_h = tex_w/8;
314         if (tex_h/tex_w > 8)
315                 tex_w = tex_h/8;
316
317         if ( tex_w < GL_min_texture_width ) {
318                 tex_w = GL_min_texture_width;
319         } else if ( tex_w > GL_max_texture_width )     {
320                 tex_w = GL_max_texture_width;
321         }
322
323         if ( tex_h < GL_min_texture_height ) {
324                 tex_h = GL_min_texture_height;
325         } else if ( tex_h > GL_max_texture_height )    {
326                 tex_h = GL_max_texture_height;
327         }
328
329         // store the outgoing size
330         *w_out = tex_w;
331         *h_out = tex_h;
332 }
333
334 // data == start of bitmap data
335 // sx == x offset into bitmap
336 // sy == y offset into bitmap
337 // src_w == absolute width of section on source bitmap
338 // src_h == absolute height of section on source bitmap
339 // bmap_w == width of source bitmap
340 // bmap_h == height of source bitmap
341 // tex_w == width of final texture
342 // tex_h == height of final texture
343 static int opengl1_create_texture_sub(int bitmap_type, int texture_handle, ushort *data, int sx, int sy, int src_w, int src_h, int bmap_w, int bmap_h, int tex_w, int tex_h, tcache_slot_opengl *t, int reload, int resize, int fail_on_full)
344 {
345         int ret_val = 1;
346         int size;
347         int i, j;
348         ubyte *bmp_data = ((ubyte*)data);
349         ubyte *texmem = NULL, *texmemp;
350
351         // bogus
352         if((t == NULL) || (bmp_data == NULL)){
353                 return 0;
354         }
355
356         if ( t->used_this_frame == GL_frame_count )       {
357                 mprintf(( "ARGHH!!! Texture already used this frame!  Cannot free it!\n" ));
358                 return 0;
359         }
360         if ( !reload )  {
361                 // gah
362                 if(!opengl1_free_texture(t)){
363                         return 0;
364                 }
365         }
366
367         switch (bitmap_type) {
368                 case TCACHE_TYPE_AABITMAP:
369                         t->u_scale = (float)bmap_w / (float)tex_w;
370                         t->v_scale = (float)bmap_h / (float)tex_h;
371                         break;
372
373                 case TCACHE_TYPE_BITMAP_INTERFACE:
374                 case TCACHE_TYPE_BITMAP_SECTION:
375                         t->u_scale = (float)src_w / (float)tex_w;
376                         t->v_scale = (float)src_h / (float)tex_h;
377                         break;
378
379                 default:
380                         t->u_scale = 1.0f;
381                         t->v_scale = 1.0f;
382                         break;
383         }
384
385         if (!reload) {
386                 glGenTextures (1, &t->texture_handle);
387         }
388
389         if (t->texture_handle == 0) {
390                 nprintf(("Error", "!!DEBUG!! t->texture_handle == 0"));
391                 return 0;
392         }
393
394         GL_bound_texture = t;
395
396         GL_bound_texture->texture_mode = (gr_texture_source) -1;
397
398         glBindTexture (GL_TEXTURE_2D, t->texture_handle);
399
400         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
401         glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
402         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
403
404         /* this should be set next anyway */
405 //      if (GL_current_texture_source != TEXTURE_SOURCE_NONE) {
406 //              gr_opengl_set_texture_state(GL_current_texture_source);
407 //      }
408
409         size = 0;
410
411         switch (bitmap_type) {
412                 case TCACHE_TYPE_AABITMAP:
413                 {
414                         texmem = (ubyte *) malloc (tex_w*tex_h);
415                         texmemp = texmem;
416
417                         for (i=0;i<tex_h;i++)
418                         {
419                                 for (j=0;j<tex_w;j++)
420                                 {
421                                         if (i < bmap_h && j < bmap_w) {
422                                                 *texmemp++ = GL_xlat[bmp_data[i*bmap_w+j]];
423                                         } else {
424                                                 *texmemp++ = 0;
425                                         }
426                                 }
427                         }
428
429                         size = tex_w*tex_h;
430
431                         if (!reload) {
432                                 glTexImage2D (GL_TEXTURE_2D, 0, GL_ALPHA, tex_w, tex_h, 0, GL_ALPHA, GL_UNSIGNED_BYTE, texmem);
433                         } else {
434                                 glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, tex_w, tex_h, GL_ALPHA, GL_UNSIGNED_BYTE, texmem);
435                         }
436
437                         free (texmem);
438
439                         break;
440                 }
441
442                 case TCACHE_TYPE_BITMAP_INTERFACE:
443                 case TCACHE_TYPE_BITMAP_SECTION:
444                 {
445                         // if we aren't resizing in any way then we can just use bmp_data directly
446                         if ( resize ) {
447                                 texmem = (ubyte *) malloc (tex_w*tex_h*2);
448                                 texmemp = texmem;
449
450                                 for (i=0;i<tex_h;i++) {
451                                         for (j=0;j<tex_w;j++) {
452                                                 if (i < src_h && j < src_w) {
453                                                         *texmemp++ = bmp_data[((i+sy)*bmap_w+(j+sx))*2+0];
454                                                         *texmemp++ = bmp_data[((i+sy)*bmap_w+(j+sx))*2+1];
455                                                 } else {
456                                                         *texmemp++ = 0;
457                                                         *texmemp++ = 0;
458                                                 }
459                                         }
460                                 }
461                         }
462
463                         size = tex_w*tex_h*2;
464
465                         if (!reload) {
466                                 glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, tex_w, tex_h, 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, (resize) ? texmem : bmp_data);
467                         } else {
468                                 glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, tex_w, tex_h, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, (resize) ? texmem : bmp_data);
469                         }
470
471                         if (texmem != NULL)
472                                 free(texmem);
473
474                         break;
475                 }
476
477                 default:
478                 {
479                         // if we aren't resizing then we can just use bmp_data directly
480                         if ( resize ) {
481                                 texmem = (ubyte *) malloc (tex_w*tex_h*2);
482                                 texmemp = texmem;
483
484                                 SDL_assert( texmem != NULL );
485
486                                 fix u, utmp, v, du, dv;
487
488                                 u = v = 0;
489
490                                 du = ( (bmap_w-1)*F1_0 ) / tex_w;
491                                 dv = ( (bmap_h-1)*F1_0 ) / tex_h;
492
493                                 for (j=0;j<tex_h;j++) {
494                                         utmp = u;
495                                         for (i=0;i<tex_w;i++) {
496                                                 *texmemp++ = bmp_data[(f2i(v)*bmap_w+f2i(utmp))*2+0];
497                                                 *texmemp++ = bmp_data[(f2i(v)*bmap_w+f2i(utmp))*2+1];
498                                                 utmp += du;
499                                         }
500                                         v += dv;
501                                 }
502                         }
503
504                         size = tex_w*tex_h*2;
505
506                         if (!reload) {
507                                 glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, tex_w, tex_h, 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, (resize) ? texmem : bmp_data);
508                         } else {
509                                 glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, tex_w, tex_h, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, (resize) ? texmem : bmp_data);
510                         }
511
512                         if (texmem != NULL)
513                                 free(texmem);
514
515                         break;
516                 }
517         }
518
519         t->bitmap_id = texture_handle;
520         t->time_created = GL_frame_count;
521         t->used_this_frame = 0;
522         t->size = size;
523         t->w = (ushort)tex_w;
524         t->h = (ushort)tex_h;
525
526         if (!reload) {
527                 Gr_textures_in += t->size;
528         }
529
530         return ret_val;
531 }
532
533 static int opengl1_create_texture(int bitmap_handle, int bitmap_type, tcache_slot_opengl *tslot, int fail_on_full)
534 {
535         ubyte flags;
536         bitmap *bmp;
537         int final_w, final_h;
538         ubyte bpp = 16;
539         int reload = 0;
540         int resize = 0;
541         int cull_size = 0;
542
543         // setup texture/bitmap flags
544         flags = 0;
545         switch(bitmap_type){
546                 case TCACHE_TYPE_AABITMAP:
547                         flags |= BMP_AABITMAP;
548                         bpp = 8;
549                         break;
550                 case TCACHE_TYPE_NORMAL:
551                         flags |= BMP_TEX_OTHER;
552                         cull_size = 1;
553                         break;
554                 case TCACHE_TYPE_BITMAP_INTERFACE:
555                 case TCACHE_TYPE_XPARENT:
556                         flags |= BMP_TEX_XPARENT;
557                         break;
558                 default:
559                         Int3();
560                         return 0;
561         }
562
563         // lock the bitmap into the proper format
564         bmp = bm_lock(bitmap_handle, bpp, flags);
565         if ( bmp == NULL ) {
566                 mprintf(("Couldn't lock bitmap %d.\n", bitmap_handle ));
567                 return 0;
568         }
569
570         int max_w = bmp->w;
571         int max_h = bmp->h;
572
573         if (cull_size) {
574                 // if we are going to cull the size then we need to force a resize
575                 if (Detail.hardware_textures < 4) {
576                         resize = 1;
577
578                         // Detail.debris_culling goes from 0 to 4.
579                         max_w /= (16 >> Detail.hardware_textures);
580                         max_h /= (16 >> Detail.hardware_textures);
581                 }
582         }
583
584
585         // get final texture size as it will be allocated as a DD surface
586         opengl1_tcache_get_adjusted_texture_size(max_w, max_h, &final_w, &final_h);
587
588         if ( (final_w < 1) || (final_h < 1) ) {
589                 mprintf(("Bitmap is too small at %dx%d.\n", final_w, final_h));
590                 return 0;
591         }
592
593         // if we don't have to resize the image (to get power of 2, etc.) then skip that extra work
594         if ( (max_w != final_w) || (max_h != final_h) ) {
595                 resize = 1;
596         }
597
598         // if this tcache slot has no bitmap
599         if ( tslot->bitmap_id < 0) {
600                 reload = 0;
601         }
602         // different bitmap altogether - determine if the new one can use the old one's slot
603         else if (tslot->bitmap_id != bitmap_handle)     {
604                 if((final_w == tslot->w) && (final_h == tslot->h)){
605                         reload = 1;
606                         //ml_printf("Reloading texture %d\n", bitmap_handle);
607                 } else {
608                         reload = 0;
609                 }
610         }
611
612         // call the helper
613         int ret_val = opengl1_create_texture_sub(bitmap_type, bitmap_handle, (ushort*)bmp->data, 0, 0, bmp->w, bmp->h, bmp->w, bmp->h, final_w, final_h, tslot, reload, resize, fail_on_full);
614
615         // unlock the bitmap
616         bm_unlock(bitmap_handle);
617
618         return ret_val;
619 }
620
621 static int opengl1_create_texture_sectioned(int bitmap_handle, int bitmap_type, tcache_slot_opengl *tslot, int sx, int sy, int fail_on_full)
622 {
623         ubyte flags;
624         bitmap *bmp;
625         int final_w, final_h;
626         int section_x, section_y;
627         int reload = 0;
628         int resize = 1;
629
630         SDL_assert( gr_screen.use_sections );
631
632         // setup texture/bitmap flags
633         SDL_assert(bitmap_type == TCACHE_TYPE_BITMAP_SECTION);
634         if(bitmap_type != TCACHE_TYPE_BITMAP_SECTION){
635                 bitmap_type = TCACHE_TYPE_BITMAP_SECTION;
636         }
637         flags = BMP_TEX_XPARENT;
638
639         // lock the bitmap in the proper format
640         bmp = bm_lock(bitmap_handle, 16, flags);
641         if ( bmp == NULL ) {
642                 mprintf(("Couldn't lock bitmap %d.\n", bitmap_handle ));
643                 return 0;
644         }
645         // determine the width and height of this section
646         bm_get_section_size(bitmap_handle, sx, sy, &section_x, &section_y);
647
648         // get final texture size as it will be allocated as an opengl texture
649         opengl1_tcache_get_adjusted_texture_size(section_x, section_y, &final_w, &final_h);
650
651         if ( (final_w < 1) || (final_h < 1) ) {
652                 mprintf(("Bitmap is too small at %dx%d.\n", final_w, final_h));
653                 return 0;
654         }
655
656         // if we don't have to resize the image (to get power of 2, etc.) then skip that extra work
657         if ( (bmp->sections.num_x == 1) && (bmp->sections.num_y == 1) && (section_x == final_w) && (section_y == final_h) ) {
658                 resize = 0;
659         }
660
661         // if this tcache slot has no bitmap
662         if ( tslot->bitmap_id < 0) {
663                 reload = 0;
664         }
665         // different bitmap altogether - determine if the new one can use the old one's slot
666         else if (tslot->bitmap_id != bitmap_handle)     {
667                 if((final_w == tslot->w) && (final_h == tslot->h)){
668                         reload = 1;
669                 } else {
670                         reload = 0;
671                 }
672         }
673
674         // call the helper
675         int ret_val = opengl1_create_texture_sub(bitmap_type, bitmap_handle, (ushort*)bmp->data, bmp->sections.sx[sx], bmp->sections.sy[sy], section_x, section_y, bmp->w, bmp->h, final_w, final_h, tslot, reload, resize, fail_on_full);
676
677         // unlock the bitmap
678         bm_unlock(bitmap_handle);
679
680         return ret_val;
681 }
682
683 int opengl1_tcache_set(int bitmap_id, int bitmap_type, float *u_scale, float *v_scale, int fail_on_full, int sx, int sy, int force)
684 {
685         bitmap *bmp = NULL;
686
687         int idx, s_idx;
688         int ret_val = 1;
689
690         if (bitmap_id < 0)
691         {
692                 GL_last_bitmap_id = -1;
693                 return 0;
694         }
695
696         if ( GL_last_detail != Detail.hardware_textures )      {
697                 GL_last_detail = Detail.hardware_textures;
698                 opengl1_tcache_flush();
699         }
700
701         if (vram_full) {
702                 return 0;
703         }
704
705         int n = bm_get_cache_slot (bitmap_id, 1);
706         tcache_slot_opengl *t = &Textures[n];
707
708         if ( (GL_last_bitmap_id == bitmap_id) && (GL_last_bitmap_type==bitmap_type) && (t->bitmap_id == bitmap_id) && (GL_last_section_x == sx) && (GL_last_section_y == sy))       {
709                 t->used_this_frame = GL_frame_count;
710
711                 // mark all children as used
712                 if (gr_screen.use_sections) {
713                         for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
714                                 for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
715                                         if(t->data_sections[idx][s_idx] != NULL){
716                                                 t->data_sections[idx][s_idx]->used_this_frame = GL_frame_count;
717                                         }
718                                 }
719                         }
720                 }
721
722                 *u_scale = t->u_scale;
723                 *v_scale = t->v_scale;
724                 return 1;
725         }
726
727         if (bitmap_type == TCACHE_TYPE_BITMAP_SECTION){
728                 SDL_assert( gr_screen.use_sections );
729                 SDL_assert((sx >= 0) && (sy >= 0) && (sx < MAX_BMAP_SECTIONS_X) && (sy < MAX_BMAP_SECTIONS_Y));
730                 if(!((sx >= 0) && (sy >= 0) && (sx < MAX_BMAP_SECTIONS_X) && (sy < MAX_BMAP_SECTIONS_Y))){
731                         return 0;
732                 }
733
734                 ret_val = 1;
735
736                 // if the texture sections haven't been created yet
737                 if((t->bitmap_id < 0) || (t->bitmap_id != bitmap_id)){
738
739                         // lock the bitmap in the proper format
740                         bmp = bm_lock(bitmap_id, 16, BMP_TEX_XPARENT);
741                         bm_unlock(bitmap_id);
742
743                         // now lets do something for each texture
744
745                         for(idx=0; idx<bmp->sections.num_x; idx++){
746                                 for(s_idx=0; s_idx<bmp->sections.num_y; s_idx++){
747                                         // hmm. i'd rather we didn't have to do it this way...
748                                         if(!opengl1_create_texture_sectioned(bitmap_id, bitmap_type, t->data_sections[idx][s_idx], idx, s_idx, fail_on_full)){
749                                                 ret_val = 0;
750                                         }
751
752                                         // not used this frame
753                                         t->data_sections[idx][s_idx]->used_this_frame = 0;
754                                 }
755                         }
756
757                         // zero out pretty much everything in the parent struct since he's just the root
758                         t->bitmap_id = bitmap_id;
759                         t->texture_handle = 0;
760                         t->time_created = t->data_sections[sx][sy]->time_created;
761                         t->used_this_frame = 0;
762                 }
763
764                 // argh. we failed to upload. free anything we can
765                 if(!ret_val){
766                         opengl1_free_texture(t);
767                 }
768                 // swap in the texture we want
769                 else {
770                         t = t->data_sections[sx][sy];
771                 }
772         }
773         // all other "normal" textures
774         else if((bitmap_id < 0) || (bitmap_id != t->bitmap_id)){
775                 ret_val = opengl1_create_texture( bitmap_id, bitmap_type, t, fail_on_full );
776         }
777
778         // everything went ok
779         if(ret_val && (t->texture_handle) && !vram_full){
780                 *u_scale = t->u_scale;
781                 *v_scale = t->v_scale;
782
783                 GL_bound_texture = t;
784
785                 glBindTexture (GL_TEXTURE_2D, t->texture_handle );
786
787                 /* this should be set next anyway */
788 //              if (GL_current_texture_source != TEXTURE_SOURCE_NONE) {
789 //                      gr_opengl_set_texture_state(GL_current_texture_source);
790 //              }
791
792                 GL_last_bitmap_id = t->bitmap_id;
793                 GL_last_bitmap_type = bitmap_type;
794                 GL_last_section_x = sx;
795                 GL_last_section_y = sy;
796
797                 t->used_this_frame = GL_frame_count;
798         }
799         // gah
800         else {
801                 GL_last_bitmap_id = -1;
802                 GL_last_bitmap_type = -1;
803
804                 GL_last_section_x = -1;
805                 GL_last_section_y = -1;
806
807                 GL_bound_texture = NULL;
808
809                 glBindTexture (GL_TEXTURE_2D, 0);       // test - DDOI
810                 return 0;
811         }
812
813         return 1;
814 }
815
816 void gr_opengl1_preload_init()
817 {
818         if (gr_screen.mode != GR_OPENGL) {
819                 return;
820         }
821
822         opengl1_tcache_flush();
823 }
824
825 int gr_opengl1_preload(int bitmap_num, int is_aabitmap)
826 {
827         if ( gr_screen.mode != GR_OPENGL) {
828                 return 0;
829         }
830
831         if ( !GL_should_preload )      {
832                 return 0;
833         }
834
835         float u_scale, v_scale;
836         int retval;
837         int bitmap_type = TCACHE_TYPE_NORMAL;
838
839         if ( is_aabitmap )      {
840                 bitmap_type = TCACHE_TYPE_AABITMAP;
841         }
842
843         retval = opengl1_tcache_set(bitmap_num, bitmap_type, &u_scale, &v_scale, 1, -1, -1, 0 );
844
845         if ( !retval )  {
846                 mprintf(("Texture upload failed!\n" ));
847         }
848
849         return retval;
850 }
851
852 void gr_opengl1_set_gamma(float gamma)
853 {
854         Gr_gamma = gamma;
855         Gr_gamma_int = int (Gr_gamma*10);
856
857         // Create the Gamma lookup table
858         int i;
859         for (i=0;i<256; i++) {
860                 int v = fl2i(pow(i2fl(i)/255.0f, 1.0f/Gr_gamma)*255.0f);
861                 if ( v > 255 ) {
862                         v = 255;
863                 } else if ( v < 0 )     {
864                         v = 0;
865                 }
866                 Gr_gamma_lookup[i] = v;
867         }
868
869         // set the alpha gamma settings (for fonts)
870         for (i=0; i<16; i++) {
871                 GL_xlat[i] = (ubyte)Gr_gamma_lookup[(i*255)/15];
872         }
873
874         GL_xlat[15] = GL_xlat[1];
875
876         for (; i<256; i++) {
877                 GL_xlat[i] = GL_xlat[0];
878         }
879
880         // Flush any existing textures
881         opengl1_tcache_flush();
882 }