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