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