2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
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
10 * $Logfile: /Freespace2/code/Graphics/GrGlideTexture.cpp $
15 * Code to manage Glide texture RAM
18 * Revision 1.2 2002/06/09 04:41:17 relnev
19 * added copyright header
21 * Revision 1.1.1.1 2002/05/03 03:28:09 root
25 * 14 10/13/99 9:22a Daveb
26 * Fixed Fred jumpnode placing bug. Fixed 1024 glide tiled texture problem
27 * related to movies. Fixed launcher spawning from PXO screen.
29 * 13 7/16/99 1:49p Dave
30 * 8 bit aabitmaps. yay.
32 * 12 7/13/99 1:15p Dave
33 * 32 bit support. Whee!
35 * 11 7/09/99 9:51a Dave
36 * Added thick polyline code.
38 * 10 7/08/99 8:10a Mikek
39 * Suppress compiler warning. Now I get an FS2 programming credit! :)
41 * 9 6/29/99 4:16p Dave
42 * Temporary speedup for tcache init.
44 * 8 6/29/99 10:35a Dave
45 * Interface polygon bitmaps! Whee!
47 * 7 6/16/99 4:06p Dave
48 * New pilot info popup. Added new draw-bitmap-as-poly function.
50 * 6 2/08/99 5:07p Dave
51 * FS2 chat server support. FS2 specific validated missions.
53 * 5 1/15/99 11:29a Neilk
54 * Fixed D3D screen/texture pixel formatting problem.
56 * 4 12/01/98 8:06a Dave
57 * Temporary checkin to fix some texture transparency problems in d3d.
59 * 3 11/30/98 1:07p Dave
60 * 16 bit conversion, first run.
62 * 2 10/07/98 10:53a Dave
65 * 1 10/07/98 10:49a Dave
67 * 18 5/14/98 5:39p John
68 * Added in code for multiple non-dimming lights.
70 * 17 4/27/98 9:33p John
73 * 16 4/27/98 9:25p John
74 * Made Glide skip any 2MB boundry, not just first one.
76 * 15 4/27/98 9:09p John
77 * Fixed bug where texture was crossing a 2MB line on Voodoo2. Added code
78 * to tell how full VRAM is and how much got paged in each frame.
80 * 14 4/27/98 10:44a John
81 * Put in a new texture caching algorithm that doesn't flush everything
84 * 13 4/26/98 12:02p John
85 * Made glide texturing do its own allocation rather than using the gu_
88 * 12 4/26/98 11:14a John
89 * Restructured/Cleaned up the caching code in preparation for the new
90 * improved caching system.
92 * 11 4/22/98 9:13p John
93 * Added code to replace frames of animations in vram if so desired.
95 * 10 4/21/98 9:16a John
96 * Fixed bug with directives display in Glide.
98 * 9 4/20/98 8:41p John
99 * Made debris culling actually reduce Glide texture resolution.
101 * 8 4/09/98 4:38p John
102 * Made non-darkening and transparent textures work under Glide. Fixed
103 * bug with Jim's computer not drawing any bitmaps.
105 * 7 4/09/98 2:21p John
106 * Fixed transparency bug with Glide
108 * 6 4/08/98 9:16p John
109 * Made transparency work for textures in Glide by using chromakey. Made
110 * nondarkening colors work.
112 * 5 4/08/98 8:47a John
113 * Moved all texture caching into a new module
115 * 4 4/06/98 4:45p John
116 * Removed some debug code that made textures 2x too small.
118 * 3 3/04/98 5:43p Hoffoss
121 * 2 3/04/98 3:50p John
122 * Made the Glide texture cache manager of Leighton's work with 256x256
125 * 1 3/03/98 4:42p John
126 * Added in Leighton's code to do texture caching on Glide.
131 //#define USE_8BPP_TEXTURES
134 #include <windowsx.h>
136 #include "glideutl.h"
141 #include "floating.h"
143 #include "grinternal.h"
149 #include "systemvars.h"
150 #include "grglideinternal.h"
152 #define TEXMEM_2MB_EDGE (2*1024*1024)
154 // Hardware specific values
155 typedef struct tcache_data {
157 GrAspectRatio_t aspect;
158 GrTextureFormat_t format;
163 typedef struct tcache_slot {
169 tcache_slot *data_sections[MAX_BMAP_SECTIONS_X][MAX_BMAP_SECTIONS_Y]; // NULL if no subsections are present.
173 #define MAX_AUX_TEXTURES 200
174 #define MAX_TEXTURES MAX_BITMAPS
176 // search for AUX to find all instancees of aux textures which can be put back in.
179 // static tcache_slot *Textures_aux = NULL; // auxiliary textures for storing sections of a texture
180 static void *Texture_sections = NULL;
181 static tcache_slot *Textures = NULL;
182 ubyte *Glide_tmp_ram = NULL;
184 int Glide_last_bitmap_id = -1;
185 int Glide_last_bitmap_type = -1;
186 int Glide_last_section_x = -1;
187 int Glide_last_section_y = -1;
188 float Glide_last_u_ratio, Glide_last_v_ratio;
190 static int Glide_last_detail = -1;
192 uint Glide_total_memory;
193 uint Glide_start_address;
194 uint Glide_end_address;
195 uint Glide_current_address;
197 int Glide_textures_in_frame = 0;
199 int Glide_explosion_vram = 0;
201 //=======================================================
202 // Code to manage texture memory.
203 // This basically allocates until out of VRAM, and then starts freeing
204 // blocks at the start of VRAM to make room for new textures.
205 // Based on code from Jason Scannell's webpage.
206 // http://members.home.net/jscannell.
212 tcache_slot *texture_ptr;
215 tblock *Tblocks = NULL; // Memory tracking blocks
216 int Tblock_num_blocks = 0; // How many blocks to use
218 int Tblock_freelist_start; // First block in free list
219 int Tblock_usedlist_start; // First block in allocation list
220 int Tblock_usedlist_head; // Last block in allocation list
222 uint Tblock_min_address; // Lowest address in texture memory
223 uint Tblock_max_address; // Highest address in texture memory
229 memset(Tblocks,0,sizeof(tblock)*Tblock_num_blocks);
231 for(i = 0; i < Tblock_num_blocks - 1; i++) {
232 Tblocks[i].next = i + 1;
235 Tblocks[Tblock_num_blocks - 1].next = -1;
237 Tblock_usedlist_start = -1;
238 Tblock_usedlist_head = -1;
239 Tblock_freelist_start = 0;
242 void InitBlocks(uint min, uint max, int num_blocks)
244 Tblock_num_blocks = num_blocks;
245 Tblock_min_address = min;
246 Tblock_max_address = max;
249 Tblocks = (tblock *)malloc(Tblock_num_blocks*sizeof(tblock));
250 SDL_assert(Tblocks!=NULL);
262 Tblock_num_blocks = 0;
265 void ReleaseSlotSub(tcache_slot *t)
274 for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
275 for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
277 if(t->data_sections[idx][s_idx] != NULL){
278 ReleaseSlotSub(t->data_sections[idx][s_idx]);
279 t->data_sections[idx][s_idx] = NULL;
285 void ReleaseSlot(int nBlock)
287 if ( Tblocks[nBlock].texture_ptr != NULL ) {
288 // if this guy has a parent (in the case of a sectioned bitmap), unset his bitmap
289 if(Tblocks[nBlock].texture_ptr->parent != NULL){
290 Tblocks[nBlock].texture_ptr->parent->bitmap_id = -1;
292 Tblocks[nBlock].texture_ptr->bitmap_id = -1;
295 // ReleaseSlotSub(Tblocks[nBlock].texture_ptr);
296 Tblocks[nBlock].texture_ptr = NULL;
299 Glide_textures_in -= Tblocks[nBlock].size;
303 void FreeBlock(int nBlock)
309 //---- Save next indices ----
310 nFreeNext = Tblock_freelist_start;
312 //---- Move alloc list block to start of free list ----
313 Tblock_freelist_start = nBlock;
314 Tblocks[nBlock].next = nFreeNext;
322 //---- Get block from free list ----
323 nNewBlock = Tblock_freelist_start;
325 //**** DOS NOT HANDLE EMPTY FREE LIST ****
326 Tblock_freelist_start = Tblocks[Tblock_freelist_start].next;
328 if(Tblock_usedlist_head < 0) {
329 //---- Alloc list is empty, add to start ----
330 Tblock_usedlist_start = nNewBlock;
331 Tblocks[nNewBlock].next = -1;
333 //---- Insert at head of alloc list ----
334 Tblocks[nNewBlock].next = Tblocks[Tblock_usedlist_head].next;
335 Tblocks[Tblock_usedlist_head].next = nNewBlock;
338 //---- Set new head index ----
339 Tblock_usedlist_head = nNewBlock;
344 // Macro to compute ending address of block
345 #define BLOCK_END(b) (Tblocks[b].start_address + Tblocks[b].size)
347 uint AllocateTexture(uint size, tcache_slot *texture_ptr)
352 if (Tblock_usedlist_start < 0) {
354 //---- Alloc list is empty ----
355 nNewBlock = AllocBlock();
356 Tblocks[nNewBlock].start_address = Tblock_min_address;
359 uint dwAddress = BLOCK_END(Tblock_usedlist_head);
360 if ( dwAddress + size < Tblock_max_address ) {
361 int a1 = dwAddress / TEXMEM_2MB_EDGE;
362 int a2 = (dwAddress+size) / TEXMEM_2MB_EDGE;
365 //mprintf(( "GrGlideTexture: Skipping a 2MB edge!\n" ));
366 dwAddress = a2*TEXMEM_2MB_EDGE;
370 if( (dwAddress + size > Tblock_max_address) || (Tblocks[Tblock_freelist_start].next<0) ) {
372 if ( Tblocks[Tblock_freelist_start].next < 0 ) {
373 mprintf(( "GrGlideTexture: AllocateTexture out of blocks! Get John.\n" ));
377 //---- No room left, go back to start ----
378 ReleaseSlot(Tblock_usedlist_start);
380 nNewBlock = Tblock_usedlist_head = Tblock_usedlist_start;
381 dwAddress = Tblock_min_address;
384 //---- Make new block ----
385 nNewBlock = AllocBlock();
388 next = Tblocks[Tblock_usedlist_head].next;
390 //---- Unlink blocks being overwritten ----
391 while((next >= 0) && (dwAddress + size > Tblocks[next].start_address)) {
393 int nTemp = Tblocks[next].next;
399 //---- Init new block ----
400 Tblocks[nNewBlock].next = next;
401 Tblocks[nNewBlock].start_address = dwAddress;
404 Tblocks[nNewBlock].size = size;
405 Tblocks[nNewBlock].texture_ptr = texture_ptr;
407 return Tblocks[nNewBlock].start_address;
410 void glide_tcache_set_initial_texture_mode()
412 grTexMipMapMode( GR_TMU0, GR_MIPMAP_DISABLE, FXFALSE);
413 grTexLodBiasValue( GR_TMU0, .5f);
414 grTexClampMode( GR_TMU0, GR_TEXTURECLAMP_WRAP, GR_TEXTURECLAMP_WRAP);
415 grTexFilterMode( GR_TMU0, GR_TEXTUREFILTER_BILINEAR, GR_TEXTUREFILTER_BILINEAR);
418 void glide_tcache_init()
420 // if we're already inited, allocate nothing new)
421 if(Textures == NULL){
422 Textures = (tcache_slot *)malloc((MAX_TEXTURES)*sizeof(tcache_slot));
430 Textures_aux = (tcache_slot*)malloc((MAX_TEXTURES) * MAX_BMAP_SECTIONS_X * MAX_BMAP_SECTIONS_Y sizeof(tcache_slot));
435 // if we're already inited, allocate nothing new)
436 if(Texture_sections == NULL){
437 Texture_sections = malloc(MAX_TEXTURES * MAX_BMAP_SECTIONS_X * MAX_BMAP_SECTIONS_Y * sizeof(tcache_slot));
438 if(!Texture_sections){
443 // if we're already inited, allocate nothing new)
444 if(Glide_tmp_ram == NULL){
445 Glide_tmp_ram = (ubyte *)malloc(256*256*2);
446 if ( !Glide_tmp_ram ) {
451 Glide_total_memory = guTexMemQueryAvail(GR_TMU0);
452 Glide_start_address = grTexMinAddress(GR_TMU0);
453 Glide_end_address = grTexMaxAddress(GR_TMU0);
454 Glide_current_address = Glide_start_address;
456 mprintf(( "Total texture memory on 3dfx card=%d bytes\n", Glide_total_memory ));
458 glide_tcache_set_initial_texture_mode();
460 InitBlocks(Glide_start_address,Glide_end_address, MAX_TEXTURES);
462 // Init the texture structures
463 int i, idx, s_idx, count;
465 for( i=0; i<MAX_TEXTURES; i++ ) {
466 Textures[i].bitmap_id = -1;
467 Textures[i].parent = NULL;
469 for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
470 for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
472 // Textures[i].data_sections[idx][s_idx] = NULL;
473 // Textures[i].data_sections[idx][s_idx] = (tcache_slot*)malloc(sizeof(tcache_slot));
474 Textures[i].data_sections[idx][s_idx] = &((tcache_slot*)Texture_sections)[count++];
475 Textures[i].data_sections[idx][s_idx]->parent = &Textures[i];
482 for( i=0; i<MAX_AUX_TEXTURES; i++){
483 Textures_aux[i].bitmap_id = -1;
485 for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
486 for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
487 Textures_aux[i].data_sections[idx][s_idx] = NULL;
493 Glide_textures_in = 0;
494 Glide_last_bitmap_id = -1;
495 Glide_last_section_x = -1;
496 Glide_last_section_y = -1;
498 Glide_last_detail = Detail.hardware_textures;
501 void glide_tcache_cleanup()
510 if ( Textures_aux ) {
515 if(Texture_sections){
516 free(Texture_sections);
517 Texture_sections = NULL;
520 if ( Glide_tmp_ram ) {
522 Glide_tmp_ram = NULL;
528 void glide_tcache_flush()
530 if ( grSstIsBusy() ) {
531 //mprintf(( "Pausing until 3DFX is idle before clearing texture RAM...\n" ));
532 grSstIdle(); // Wait for idle
535 Glide_current_address = Glide_start_address;
537 // Init the texture structures
538 int i; //, idx, s_idx;
539 for( i=0; i<MAX_TEXTURES; i++ ) {
540 Textures[i].bitmap_id = -1;
544 for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
545 for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
546 Textures[i].data_sections[idx][s_idx] = NULL;
554 for( i=0; i<MAX_AUX_TEXTURES; i++){
555 Textures_aux[i].bitmap_id = -1;
557 for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
558 for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
559 Textures_aux[i].data_sections[idx][s_idx] = NULL;
565 Glide_textures_in = 0;
566 Glide_last_bitmap_id = -1;
567 Glide_last_section_x = -1;
568 Glide_last_section_y = -1;
571 Glide_explosion_vram = 0;
576 // get a free aux texture
579 int ga_reentrant = 0;
580 tcache_slot *glide_get_aux_slot()
586 // never go in here more than twice
587 if(ga_reentrant > 1){
593 for(idx=0; idx<MAX_AUX_TEXTURES; idx++){
594 if(Textures_aux[idx].bitmap_id == -1){
600 // OH NO. This means we've run out of slots for bitmap sections. Let's just blast all of them free. whee!
602 mprintf(("AIEEEE! FLUSHIN SECTIONED BITMAPS!\n"));
603 for(idx=0; idx<MAX_TEXTURES; idx++){
604 if((Textures[idx].bitmap_id > -1) && (Textures[idx].data_sections[0][0] != NULL)){
605 ReleaseSlot(&Textures[idx] - Textures);
609 ret = glide_get_aux_slot();
617 Textures_aux[index].bitmap_id = -1;
618 Textures_aux[index].data.vram_offset = 0;
619 Textures_aux[index].data.vram_size = 0;
620 for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
621 for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
622 Textures_aux[index].data_sections[idx][s_idx] = NULL;
626 ret = &Textures_aux[index];
632 void glide_tcache_frame()
634 Glide_textures_in_frame = 0;
637 extern int palman_is_nondarkening(int r,int g, int b);
639 // data == start of bitmap data
640 // sx == x offset into bitmap
641 // sy == y offset into bitmap
642 // src_w == absolute width of section on source bitmap
643 // src_h == absolute height of section on source bitmap
644 // bmap_w == width of source bitmap
645 // bmap_h == height of source bitmap
646 // tex_w == width of final texture
647 // tex_h == height of final texture
648 int glide_create_texture_sub(int bitmap_type, int bitmap_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 *tslot)
652 // sanity - make sure we're not going to run off the end of the bitmap
654 SDL_assert(src_w <= (bmap_w - sx));
655 SDL_assert(src_h <= (bmap_h - sy));
658 if ( tex_w <= 16 ) tex_w = 16;
659 else if ( tex_w <= 32 ) tex_w = 32;
660 else if ( tex_w <= 64 ) tex_w = 64;
661 else if ( tex_w <= 128 ) tex_w = 128;
666 if ( tex_h <= 16 ) tex_h = 16;
667 else if ( tex_h <= 32 ) tex_h = 32;
668 else if ( tex_h <= 64 ) tex_h = 64;
669 else if ( tex_h <= 128 ) tex_h = 128;
674 // these can never be shrunk. meaning, the texture _must_ be big enough to hold every pixel
675 if ( (bitmap_type == TCACHE_TYPE_AABITMAP) || (bitmap_type == TCACHE_TYPE_BITMAP_SECTION) ) {
676 // W & H must be within 8x of each other.
677 if ( (tex_w==16) && (tex_h==256) ) {
679 } else if ( (tex_w==256) && (tex_h==16) ) {
683 // W & H must be within 8x of each other.
684 if ( (tex_w==16) && (tex_h==256) ) {
686 } else if ( (tex_w==256) && (tex_h==16) ) {
691 ushort *bmp_data = data;
692 ubyte *bmp_data_byte = (ubyte*)data;
694 GrTextureFormat_t tex_format;
696 if ( bitmap_type == TCACHE_TYPE_AABITMAP ) {
697 tex_format = GR_TEXFMT_ALPHA_8;
703 for (i=0; i<16; i++ ) {
704 xlat[i] = ubyte(Gr_gamma_lookup[(i*255)/15]);
708 for ( ; i<256; i++ ) {
712 // upload to temp ram
713 for (j = 0; j < tex_h; j++) {
714 // the proper line in the temp ram
715 lpSP = (ubyte*)(Glide_tmp_ram + tex_w * j);
717 // upload the line of texture from the source bitmap
718 for (i = 0; i < tex_w; i++) {
719 // if we're within the bounds of the section we're copying
720 if ( (j < src_h) && (i < src_w) ) {
721 *lpSP++ = xlat[(ubyte)bmp_data_byte[(j * bmap_w) + i + sx]];
723 // otherwise just copy black
729 } else if(bitmap_type == TCACHE_TYPE_BITMAP_SECTION){
730 tex_format = GR_TEXFMT_ARGB_1555;
733 for (j = 0; j < src_h; j++) {
734 // the proper line in the temp ram
735 lpSP = (unsigned short*)(Glide_tmp_ram + tex_w * 2 * j);
738 for (i = 0; i < src_w; i++) {
739 // stuff the texture into vram
740 *lpSP++ = bmp_data[((j+sy) * bmap_w) + sx + i];
744 tex_format = GR_TEXFMT_ARGB_1555;
745 fix u, utmp, v, du, dv;
750 // source line on the bitmap;
753 // scale through the texture
754 du = (src_w * F1_0) / tex_w;
755 dv = (src_h * F1_0) / tex_h;
757 for (j = 0; j < tex_h; j++) {
758 // the proper line in the temp ram
759 lpSP = (unsigned short*)(Glide_tmp_ram + tex_w * 2 * j);
761 // pixel offset on this individual line of the source bitmap
765 for (i = 0; i < tex_w; i++) {
766 // stuff the texture into vram
767 *lpSP++ = bmp_data[f2i(v) * bmap_w + f2i(utmp)];
773 // next line in the source bitmap
778 GrLOD_t lod=GR_LOD_16;
780 int longest = max(tex_w, tex_h);
782 float uscale, vscale;
783 if ( bitmap_type == TCACHE_TYPE_AABITMAP ) {
784 uscale = i2fl(bmap_w)*256.0f / i2fl(longest);
785 vscale = i2fl(bmap_h)*256.0f / i2fl(longest);
786 } else if(bitmap_type == TCACHE_TYPE_BITMAP_SECTION){
787 uscale = i2fl(src_w)*256.0f / i2fl(longest);
788 vscale = i2fl(src_h)*256.0f / i2fl(longest);
790 uscale = i2fl(tex_w)*256.0f / i2fl(longest);
791 vscale = i2fl(tex_h)*256.0f / i2fl(longest);
795 case 16: lod = GR_LOD_16; break;
796 case 32: lod = GR_LOD_32; break;
797 case 64: lod = GR_LOD_64; break;
798 case 128: lod = GR_LOD_128; break;
799 case 256: lod = GR_LOD_256; break;
804 GrAspectRatio_t aspect = GR_ASPECT_1x1; // aspect is widthxheight
806 if ( tex_w < tex_h ) {
807 int ratio = tex_h / tex_w;
809 case 1: aspect = GR_ASPECT_1x1; break;
810 case 2: aspect = GR_ASPECT_1x2; break;
811 case 4: aspect = GR_ASPECT_1x4; break;
812 case 8: aspect = GR_ASPECT_1x8; break;
816 int ratio = tex_w / tex_h;
818 case 1: aspect = GR_ASPECT_1x1; break;
819 case 2: aspect = GR_ASPECT_2x1; break;
820 case 4: aspect = GR_ASPECT_4x1; break;
821 case 8: aspect = GR_ASPECT_8x1; break;
829 info.smallLod = lod; //GR_LOD_256;
830 info.largeLod = lod; //GR_LOD_256;
831 info.aspectRatio = aspect; //GR_ASPECT_1x1;
832 info.format = tex_format; //GR_TEXFMT_ARGB_1555;
833 info.data = Glide_tmp_ram; //source data
835 int bytes_needed = grTexTextureMemRequired( GR_MIPMAPLEVELMASK_BOTH, &info );
837 // if ( (tslot->data.vram_offset == 0) || ((tslot->data.vram_offset>0)&&(bytes_needed>tslot->data.vram_size))) {
838 tslot->data.vram_offset = AllocateTexture( bytes_needed, tslot );
839 tslot->data.vram_size = bytes_needed;
840 Glide_textures_in += bytes_needed;
843 tslot->data.format = tex_format;
844 tslot->data.lod = lod;
845 tslot->data.aspect = aspect;
846 tslot->bitmap_id = bitmap_handle;
847 tslot->uscale = uscale;
848 tslot->vscale = vscale;
850 grTexDownloadMipMap(GR_TMU0, tslot->data.vram_offset, GR_MIPMAPLEVELMASK_BOTH, &info);
851 Glide_textures_in_frame += bytes_needed;
856 int glide_create_texture( int bitmap_handle, int bitmap_type, tcache_slot *tslot )
863 // setup texture/bitmap flags
866 case TCACHE_TYPE_AABITMAP:
867 flags |= BMP_AABITMAP;
870 case TCACHE_TYPE_XPARENT:
871 case TCACHE_TYPE_BITMAP_SECTION:
872 flags |= BMP_TEX_XPARENT;
874 case TCACHE_TYPE_NORMAL:
875 flags |= BMP_TEX_OTHER;
877 case TCACHE_TYPE_NONDARKENING:
878 flags |= BMP_TEX_NONDARK;
882 // lock the bitmap in the proper format
883 bmp = bm_lock(bitmap_handle, bpp, flags);
885 mprintf(("Couldn't lock bitmap %d.\n", bitmap_handle ));
892 if ( bitmap_type != TCACHE_TYPE_AABITMAP ) {
893 // Detail.debris_culling goes from 0 to 4.
894 max_w /= 16>>Detail.hardware_textures;
895 max_h /= 16>>Detail.hardware_textures;
899 ret = glide_create_texture_sub(bitmap_type, bitmap_handle, (ushort*)bmp->data, 0, 0, bmp->w, bmp->h, bmp->w, bmp->h, max_w, max_h, tslot);
902 bm_unlock(bitmap_handle);
908 // create a sectioned texture
909 int glide_create_texture_sectioned(int bitmap_handle, int bitmap_type, tcache_slot *tslot, int sx, int sy)
914 int section_x, section_y;
916 // setup texture/bitmap flags
917 SDL_assert(bitmap_type == TCACHE_TYPE_BITMAP_SECTION);
918 if(bitmap_type != TCACHE_TYPE_BITMAP_SECTION){
919 bitmap_type = TCACHE_TYPE_BITMAP_SECTION;
921 flags = BMP_TEX_XPARENT;
923 // lock the bitmap in the proper format
924 bmp = bm_lock(bitmap_handle, 16, flags);
926 mprintf(("Couldn't lock bitmap %d.\n", bitmap_handle ));
930 // determine the width and height of this section
931 bm_get_section_size(bitmap_handle, sx, sy, §ion_x, §ion_y);
934 ret = glide_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, section_x, section_y, tslot);
937 bm_unlock(bitmap_handle);
946 Glide_explosion_vram = 0;
949 extern int bm_get_cache_slot( int bitmap_id, int separate_ani_frames );
951 // Returns FALSE if error
952 int glide_tcache_set( int bitmap_id, int bitmap_type, float *u_ratio, float *v_ratio, int fail_on_full, int sx, int sy, int force )
957 if ( Glide_last_detail != Detail.hardware_textures ) {
958 Glide_last_detail = Detail.hardware_textures;
959 glide_tcache_flush();
962 // Check if this is the same as the last one... if so, we don't need to
964 if ( (Glide_last_bitmap_id == bitmap_id) && (Glide_last_bitmap_type==bitmap_type) && (Glide_last_section_x == sx) && (Glide_last_section_y == sy) && !force) {
965 *u_ratio = Glide_last_u_ratio;
966 *v_ratio = Glide_last_v_ratio;
971 n = bm_get_cache_slot( bitmap_id, 1 );
973 tcache_slot * t = &Textures[n];
975 // if this is a sectioned bitmap
976 if(bitmap_type == TCACHE_TYPE_BITMAP_SECTION){
977 // if the texture sections haven't been created yet
978 if((t->bitmap_id < 0) || (t->bitmap_id != bitmap_id) || force){
980 if(t->bitmap_id < 0){
981 t->data.vram_offset = 0;
984 // lock the bitmap in the proper format
985 bmp = bm_lock(bitmap_id, 16, BMP_TEX_XPARENT);
986 bm_unlock(bitmap_id);
988 // first we need to get enough free aux textures
991 for(idx=0; idx<bmp->sections.num_x; idx++){
992 for(s_idx=0; s_idx<bmp->sections.num_y; s_idx++){
993 // try and get a feww slot
994 t->data_sections[idx][s_idx] = glide_get_aux_slot();
995 if(t->data_sections[idx][s_idx] == NULL){
999 t->data_sections[idx][s_idx]->bitmap_id = bitmap_id;
1004 // now lets do something for each texture
1005 for(idx=0; idx<bmp->sections.num_x; idx++){
1006 for(s_idx=0; s_idx<bmp->sections.num_y; s_idx++){
1007 if(t->bitmap_id < 0){
1008 t->data_sections[idx][s_idx]->data.vram_offset = 0;
1011 t->data_sections[idx][s_idx]->bitmap_id = bitmap_id;
1012 glide_create_texture_sectioned( bitmap_id, bitmap_type, t->data_sections[idx][s_idx], idx, s_idx);
1016 t->bitmap_id = bitmap_id;
1019 // swap in the texture we want
1020 t = t->data_sections[sx][sy];
1022 // all other "normal" textures
1025 if ( t->bitmap_id < 0) {
1026 t->data.vram_offset = 0;
1027 glide_create_texture( bitmap_id, bitmap_type, t );
1029 // different bitmap altogether
1030 else if ( (t->bitmap_id != bitmap_id) || force) {
1031 glide_create_texture( bitmap_id, bitmap_type, t );
1035 *u_ratio = t->uscale;
1036 *v_ratio = t->vscale;
1040 info.smallLod = t->data.lod; //GR_LOD_256;
1041 info.largeLod = t->data.lod; //GR_LOD_256;
1042 info.aspectRatio = t->data.aspect; //GR_ASPECT_1x1;
1043 info.format = t->data.format; //GR_TEXFMT_ARGB_1555;
1044 info.data = 0; //source data
1046 grTexSource( GR_TMU0, t->data.vram_offset, GR_MIPMAPLEVELMASK_BOTH, &info );
1048 // Save current state so we don't have to do anything time consuming next time
1049 // we set this exact same texture
1050 Glide_last_bitmap_id = bitmap_id;
1051 Glide_last_bitmap_type = bitmap_type;
1052 Glide_last_section_x = sx;
1053 Glide_last_section_y = sy;
1054 Glide_last_u_ratio = t->uscale;
1055 Glide_last_v_ratio = t->vscale;