2 * $Logfile: /Freespace2/code/Graphics/GrGlideTexture.cpp $
7 * Code to manage Glide texture RAM
10 * Revision 1.1 2002/05/03 03:28:09 root
14 * 14 10/13/99 9:22a Daveb
15 * Fixed Fred jumpnode placing bug. Fixed 1024 glide tiled texture problem
16 * related to movies. Fixed launcher spawning from PXO screen.
18 * 13 7/16/99 1:49p Dave
19 * 8 bit aabitmaps. yay.
21 * 12 7/13/99 1:15p Dave
22 * 32 bit support. Whee!
24 * 11 7/09/99 9:51a Dave
25 * Added thick polyline code.
27 * 10 7/08/99 8:10a Mikek
28 * Suppress compiler warning. Now I get an FS2 programming credit! :)
30 * 9 6/29/99 4:16p Dave
31 * Temporary speedup for tcache init.
33 * 8 6/29/99 10:35a Dave
34 * Interface polygon bitmaps! Whee!
36 * 7 6/16/99 4:06p Dave
37 * New pilot info popup. Added new draw-bitmap-as-poly function.
39 * 6 2/08/99 5:07p Dave
40 * FS2 chat server support. FS2 specific validated missions.
42 * 5 1/15/99 11:29a Neilk
43 * Fixed D3D screen/texture pixel formatting problem.
45 * 4 12/01/98 8:06a Dave
46 * Temporary checkin to fix some texture transparency problems in d3d.
48 * 3 11/30/98 1:07p Dave
49 * 16 bit conversion, first run.
51 * 2 10/07/98 10:53a Dave
54 * 1 10/07/98 10:49a Dave
56 * 18 5/14/98 5:39p John
57 * Added in code for multiple non-dimming lights.
59 * 17 4/27/98 9:33p John
62 * 16 4/27/98 9:25p John
63 * Made Glide skip any 2MB boundry, not just first one.
65 * 15 4/27/98 9:09p John
66 * Fixed bug where texture was crossing a 2MB line on Voodoo2. Added code
67 * to tell how full VRAM is and how much got paged in each frame.
69 * 14 4/27/98 10:44a John
70 * Put in a new texture caching algorithm that doesn't flush everything
73 * 13 4/26/98 12:02p John
74 * Made glide texturing do its own allocation rather than using the gu_
77 * 12 4/26/98 11:14a John
78 * Restructured/Cleaned up the caching code in preparation for the new
79 * improved caching system.
81 * 11 4/22/98 9:13p John
82 * Added code to replace frames of animations in vram if so desired.
84 * 10 4/21/98 9:16a John
85 * Fixed bug with directives display in Glide.
87 * 9 4/20/98 8:41p John
88 * Made debris culling actually reduce Glide texture resolution.
90 * 8 4/09/98 4:38p John
91 * Made non-darkening and transparent textures work under Glide. Fixed
92 * bug with Jim's computer not drawing any bitmaps.
94 * 7 4/09/98 2:21p John
95 * Fixed transparency bug with Glide
97 * 6 4/08/98 9:16p John
98 * Made transparency work for textures in Glide by using chromakey. Made
99 * nondarkening colors work.
101 * 5 4/08/98 8:47a John
102 * Moved all texture caching into a new module
104 * 4 4/06/98 4:45p John
105 * Removed some debug code that made textures 2x too small.
107 * 3 3/04/98 5:43p Hoffoss
110 * 2 3/04/98 3:50p John
111 * Made the Glide texture cache manager of Leighton's work with 256x256
114 * 1 3/03/98 4:42p John
115 * Added in Leighton's code to do texture caching on Glide.
120 //#define USE_8BPP_TEXTURES
123 #include <windowsx.h>
125 #include "glideutl.h"
130 #include "floating.h"
132 #include "grinternal.h"
138 #include "systemvars.h"
139 #include "grglideinternal.h"
141 #define TEXMEM_2MB_EDGE (2*1024*1024)
143 // Hardware specific values
144 typedef struct tcache_data {
146 GrAspectRatio_t aspect;
147 GrTextureFormat_t format;
152 typedef struct tcache_slot {
158 tcache_slot *data_sections[MAX_BMAP_SECTIONS_X][MAX_BMAP_SECTIONS_Y]; // NULL if no subsections are present.
162 #define MAX_AUX_TEXTURES 200
163 #define MAX_TEXTURES MAX_BITMAPS
165 // search for AUX to find all instancees of aux textures which can be put back in.
168 // static tcache_slot *Textures_aux = NULL; // auxiliary textures for storing sections of a texture
169 static void *Texture_sections = NULL;
170 static tcache_slot *Textures = NULL;
171 ubyte *Glide_tmp_ram = NULL;
173 int Glide_last_bitmap_id = -1;
174 int Glide_last_bitmap_type = -1;
175 int Glide_last_section_x = -1;
176 int Glide_last_section_y = -1;
177 float Glide_last_u_ratio, Glide_last_v_ratio;
179 static int Glide_last_detail = -1;
181 uint Glide_total_memory;
182 uint Glide_start_address;
183 uint Glide_end_address;
184 uint Glide_current_address;
186 int Glide_textures_in_frame = 0;
188 int Glide_explosion_vram = 0;
190 //=======================================================
191 // Code to manage texture memory.
192 // This basically allocates until out of VRAM, and then starts freeing
193 // blocks at the start of VRAM to make room for new textures.
194 // Based on code from Jason Scannell's webpage.
195 // http://members.home.net/jscannell.
201 tcache_slot *texture_ptr;
204 tblock *Tblocks = NULL; // Memory tracking blocks
205 int Tblock_num_blocks = 0; // How many blocks to use
207 int Tblock_freelist_start; // First block in free list
208 int Tblock_usedlist_start; // First block in allocation list
209 int Tblock_usedlist_head; // Last block in allocation list
211 uint Tblock_min_address; // Lowest address in texture memory
212 uint Tblock_max_address; // Highest address in texture memory
218 memset(Tblocks,0,sizeof(tblock)*Tblock_num_blocks);
220 for(i = 0; i < Tblock_num_blocks - 1; i++) {
221 Tblocks[i].next = i + 1;
224 Tblocks[Tblock_num_blocks - 1].next = -1;
226 Tblock_usedlist_start = -1;
227 Tblock_usedlist_head = -1;
228 Tblock_freelist_start = 0;
231 void InitBlocks(uint min, uint max, int num_blocks)
233 Tblock_num_blocks = num_blocks;
234 Tblock_min_address = min;
235 Tblock_max_address = max;
238 Tblocks = (tblock *)malloc(Tblock_num_blocks*sizeof(tblock));
239 Assert(Tblocks!=NULL);
251 Tblock_num_blocks = 0;
254 void ReleaseSlotSub(tcache_slot *t)
263 for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
264 for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
266 if(t->data_sections[idx][s_idx] != NULL){
267 ReleaseSlotSub(t->data_sections[idx][s_idx]);
268 t->data_sections[idx][s_idx] = NULL;
274 void ReleaseSlot(int nBlock)
276 if ( Tblocks[nBlock].texture_ptr != NULL ) {
277 // if this guy has a parent (in the case of a sectioned bitmap), unset his bitmap
278 if(Tblocks[nBlock].texture_ptr->parent != NULL){
279 Tblocks[nBlock].texture_ptr->parent->bitmap_id = -1;
281 Tblocks[nBlock].texture_ptr->bitmap_id = -1;
284 // ReleaseSlotSub(Tblocks[nBlock].texture_ptr);
285 Tblocks[nBlock].texture_ptr = NULL;
288 Glide_textures_in -= Tblocks[nBlock].size;
292 void FreeBlock(int nBlock)
298 //---- Save next indices ----
299 nFreeNext = Tblock_freelist_start;
301 //---- Move alloc list block to start of free list ----
302 Tblock_freelist_start = nBlock;
303 Tblocks[nBlock].next = nFreeNext;
311 //---- Get block from free list ----
312 nNewBlock = Tblock_freelist_start;
314 //**** DOS NOT HANDLE EMPTY FREE LIST ****
315 Tblock_freelist_start = Tblocks[Tblock_freelist_start].next;
317 if(Tblock_usedlist_head < 0) {
318 //---- Alloc list is empty, add to start ----
319 Tblock_usedlist_start = nNewBlock;
320 Tblocks[nNewBlock].next = -1;
322 //---- Insert at head of alloc list ----
323 Tblocks[nNewBlock].next = Tblocks[Tblock_usedlist_head].next;
324 Tblocks[Tblock_usedlist_head].next = nNewBlock;
327 //---- Set new head index ----
328 Tblock_usedlist_head = nNewBlock;
333 // Macro to compute ending address of block
334 #define BLOCK_END(b) (Tblocks[b].start_address + Tblocks[b].size)
336 uint AllocateTexture(uint size, tcache_slot *texture_ptr)
341 if (Tblock_usedlist_start < 0) {
343 //---- Alloc list is empty ----
344 nNewBlock = AllocBlock();
345 Tblocks[nNewBlock].start_address = Tblock_min_address;
348 uint dwAddress = BLOCK_END(Tblock_usedlist_head);
349 if ( dwAddress + size < Tblock_max_address ) {
350 int a1 = dwAddress / TEXMEM_2MB_EDGE;
351 int a2 = (dwAddress+size) / TEXMEM_2MB_EDGE;
354 //mprintf(( "GrGlideTexture: Skipping a 2MB edge!\n" ));
355 dwAddress = a2*TEXMEM_2MB_EDGE;
359 if( (dwAddress + size > Tblock_max_address) || (Tblocks[Tblock_freelist_start].next<0) ) {
361 if ( Tblocks[Tblock_freelist_start].next < 0 ) {
362 mprintf(( "GrGlideTexture: AllocateTexture out of blocks! Get John.\n" ));
366 //---- No room left, go back to start ----
367 ReleaseSlot(Tblock_usedlist_start);
369 nNewBlock = Tblock_usedlist_head = Tblock_usedlist_start;
370 dwAddress = Tblock_min_address;
373 //---- Make new block ----
374 nNewBlock = AllocBlock();
377 next = Tblocks[Tblock_usedlist_head].next;
379 //---- Unlink blocks being overwritten ----
380 while((next >= 0) && (dwAddress + size > Tblocks[next].start_address)) {
382 int nTemp = Tblocks[next].next;
388 //---- Init new block ----
389 Tblocks[nNewBlock].next = next;
390 Tblocks[nNewBlock].start_address = dwAddress;
393 Tblocks[nNewBlock].size = size;
394 Tblocks[nNewBlock].texture_ptr = texture_ptr;
396 return Tblocks[nNewBlock].start_address;
399 void glide_tcache_set_initial_texture_mode()
401 grTexMipMapMode( GR_TMU0, GR_MIPMAP_DISABLE, FXFALSE);
402 grTexLodBiasValue( GR_TMU0, .5f);
403 grTexClampMode( GR_TMU0, GR_TEXTURECLAMP_WRAP, GR_TEXTURECLAMP_WRAP);
404 grTexFilterMode( GR_TMU0, GR_TEXTUREFILTER_BILINEAR, GR_TEXTUREFILTER_BILINEAR);
407 void glide_tcache_init()
409 // if we're already inited, allocate nothing new)
410 if(Textures == NULL){
411 Textures = (tcache_slot *)malloc((MAX_TEXTURES)*sizeof(tcache_slot));
419 Textures_aux = (tcache_slot*)malloc((MAX_TEXTURES) * MAX_BMAP_SECTIONS_X * MAX_BMAP_SECTIONS_Y sizeof(tcache_slot));
424 // if we're already inited, allocate nothing new)
425 if(Texture_sections == NULL){
426 Texture_sections = malloc(MAX_TEXTURES * MAX_BMAP_SECTIONS_X * MAX_BMAP_SECTIONS_Y * sizeof(tcache_slot));
427 if(!Texture_sections){
432 // if we're already inited, allocate nothing new)
433 if(Glide_tmp_ram == NULL){
434 Glide_tmp_ram = (ubyte *)malloc(256*256*2);
435 if ( !Glide_tmp_ram ) {
440 Glide_total_memory = guTexMemQueryAvail(GR_TMU0);
441 Glide_start_address = grTexMinAddress(GR_TMU0);
442 Glide_end_address = grTexMaxAddress(GR_TMU0);
443 Glide_current_address = Glide_start_address;
445 mprintf(( "Total texture memory on 3dfx card=%d bytes\n", Glide_total_memory ));
447 glide_tcache_set_initial_texture_mode();
449 InitBlocks(Glide_start_address,Glide_end_address, MAX_TEXTURES);
451 // Init the texture structures
452 int i, idx, s_idx, count;
454 for( i=0; i<MAX_TEXTURES; i++ ) {
455 Textures[i].bitmap_id = -1;
456 Textures[i].parent = NULL;
458 for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
459 for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
461 // Textures[i].data_sections[idx][s_idx] = NULL;
462 // Textures[i].data_sections[idx][s_idx] = (tcache_slot*)malloc(sizeof(tcache_slot));
463 Textures[i].data_sections[idx][s_idx] = &((tcache_slot*)Texture_sections)[count++];
464 Textures[i].data_sections[idx][s_idx]->parent = &Textures[i];
471 for( i=0; i<MAX_AUX_TEXTURES; i++){
472 Textures_aux[i].bitmap_id = -1;
474 for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
475 for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
476 Textures_aux[i].data_sections[idx][s_idx] = NULL;
482 Glide_textures_in = 0;
483 Glide_last_bitmap_id = -1;
484 Glide_last_section_x = -1;
485 Glide_last_section_y = -1;
487 Glide_last_detail = Detail.hardware_textures;
490 void glide_tcache_cleanup()
499 if ( Textures_aux ) {
504 if(Texture_sections){
505 free(Texture_sections);
506 Texture_sections = NULL;
509 if ( Glide_tmp_ram ) {
511 Glide_tmp_ram = NULL;
517 void glide_tcache_flush()
519 if ( grSstIsBusy() ) {
520 //mprintf(( "Pausing until 3DFX is idle before clearing texture RAM...\n" ));
521 grSstIdle(); // Wait for idle
524 Glide_current_address = Glide_start_address;
526 // Init the texture structures
527 int i; //, idx, s_idx;
528 for( i=0; i<MAX_TEXTURES; i++ ) {
529 Textures[i].bitmap_id = -1;
533 for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
534 for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
535 Textures[i].data_sections[idx][s_idx] = NULL;
543 for( i=0; i<MAX_AUX_TEXTURES; i++){
544 Textures_aux[i].bitmap_id = -1;
546 for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
547 for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
548 Textures_aux[i].data_sections[idx][s_idx] = NULL;
554 Glide_textures_in = 0;
555 Glide_last_bitmap_id = -1;
556 Glide_last_section_x = -1;
557 Glide_last_section_y = -1;
560 Glide_explosion_vram = 0;
565 // get a free aux texture
568 int ga_reentrant = 0;
569 tcache_slot *glide_get_aux_slot()
575 // never go in here more than twice
576 if(ga_reentrant > 1){
582 for(idx=0; idx<MAX_AUX_TEXTURES; idx++){
583 if(Textures_aux[idx].bitmap_id == -1){
589 // OH NO. This means we've run out of slots for bitmap sections. Let's just blast all of them free. whee!
591 mprintf(("AIEEEE! FLUSHIN SECTIONED BITMAPS!\n"));
592 for(idx=0; idx<MAX_TEXTURES; idx++){
593 if((Textures[idx].bitmap_id > -1) && (Textures[idx].data_sections[0][0] != NULL)){
594 ReleaseSlot(&Textures[idx] - Textures);
598 ret = glide_get_aux_slot();
606 Textures_aux[index].bitmap_id = -1;
607 Textures_aux[index].data.vram_offset = 0;
608 Textures_aux[index].data.vram_size = 0;
609 for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
610 for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
611 Textures_aux[index].data_sections[idx][s_idx] = NULL;
615 ret = &Textures_aux[index];
621 void glide_tcache_frame()
623 Glide_textures_in_frame = 0;
626 extern int palman_is_nondarkening(int r,int g, int b);
628 // data == start of bitmap data
629 // sx == x offset into bitmap
630 // sy == y offset into bitmap
631 // src_w == absolute width of section on source bitmap
632 // src_h == absolute height of section on source bitmap
633 // bmap_w == width of source bitmap
634 // bmap_h == height of source bitmap
635 // tex_w == width of final texture
636 // tex_h == height of final texture
637 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)
641 // sanity - make sure we're not going to run off the end of the bitmap
643 Assert(src_w <= (bmap_w - sx));
644 Assert(src_h <= (bmap_h - sy));
647 if ( tex_w <= 16 ) tex_w = 16;
648 else if ( tex_w <= 32 ) tex_w = 32;
649 else if ( tex_w <= 64 ) tex_w = 64;
650 else if ( tex_w <= 128 ) tex_w = 128;
655 if ( tex_h <= 16 ) tex_h = 16;
656 else if ( tex_h <= 32 ) tex_h = 32;
657 else if ( tex_h <= 64 ) tex_h = 64;
658 else if ( tex_h <= 128 ) tex_h = 128;
663 // these can never be shrunk. meaning, the texture _must_ be big enough to hold every pixel
664 if ( (bitmap_type == TCACHE_TYPE_AABITMAP) || (bitmap_type == TCACHE_TYPE_BITMAP_SECTION) ) {
665 // W & H must be within 8x of each other.
666 if ( (tex_w==16) && (tex_h==256) ) {
668 } else if ( (tex_w==256) && (tex_h==16) ) {
672 // W & H must be within 8x of each other.
673 if ( (tex_w==16) && (tex_h==256) ) {
675 } else if ( (tex_w==256) && (tex_h==16) ) {
680 ushort *bmp_data = data;
681 ubyte *bmp_data_byte = (ubyte*)data;
683 GrTextureFormat_t tex_format;
685 if ( bitmap_type == TCACHE_TYPE_AABITMAP ) {
686 tex_format = GR_TEXFMT_ALPHA_8;
692 for (i=0; i<16; i++ ) {
693 xlat[i] = ubyte(Gr_gamma_lookup[(i*255)/15]);
697 for ( ; i<256; i++ ) {
701 // upload to temp ram
702 for (j = 0; j < tex_h; j++) {
703 // the proper line in the temp ram
704 lpSP = (ubyte*)(Glide_tmp_ram + tex_w * j);
706 // upload the line of texture from the source bitmap
707 for (i = 0; i < tex_w; i++) {
708 // if we're within the bounds of the section we're copying
709 if ( (j < src_h) && (i < src_w) ) {
710 *lpSP++ = xlat[(ubyte)bmp_data_byte[(j * bmap_w) + i + sx]];
712 // otherwise just copy black
718 } else if(bitmap_type == TCACHE_TYPE_BITMAP_SECTION){
719 tex_format = GR_TEXFMT_ARGB_1555;
722 for (j = 0; j < src_h; j++) {
723 // the proper line in the temp ram
724 lpSP = (unsigned short*)(Glide_tmp_ram + tex_w * 2 * j);
727 for (i = 0; i < src_w; i++) {
728 // stuff the texture into vram
729 *lpSP++ = bmp_data[((j+sy) * bmap_w) + sx + i];
733 tex_format = GR_TEXFMT_ARGB_1555;
734 fix u, utmp, v, du, dv;
739 // source line on the bitmap;
742 // scale through the texture
743 du = (src_w * F1_0) / tex_w;
744 dv = (src_h * F1_0) / tex_h;
746 for (j = 0; j < tex_h; j++) {
747 // the proper line in the temp ram
748 lpSP = (unsigned short*)(Glide_tmp_ram + tex_w * 2 * j);
750 // pixel offset on this individual line of the source bitmap
754 for (i = 0; i < tex_w; i++) {
755 // stuff the texture into vram
756 *lpSP++ = bmp_data[f2i(v) * bmap_w + f2i(utmp)];
762 // next line in the source bitmap
767 GrLOD_t lod=GR_LOD_16;
769 int longest = max(tex_w, tex_h);
771 float uscale, vscale;
772 if ( bitmap_type == TCACHE_TYPE_AABITMAP ) {
773 uscale = i2fl(bmap_w)*256.0f / i2fl(longest);
774 vscale = i2fl(bmap_h)*256.0f / i2fl(longest);
775 } else if(bitmap_type == TCACHE_TYPE_BITMAP_SECTION){
776 uscale = i2fl(src_w)*256.0f / i2fl(longest);
777 vscale = i2fl(src_h)*256.0f / i2fl(longest);
779 uscale = i2fl(tex_w)*256.0f / i2fl(longest);
780 vscale = i2fl(tex_h)*256.0f / i2fl(longest);
784 case 16: lod = GR_LOD_16; break;
785 case 32: lod = GR_LOD_32; break;
786 case 64: lod = GR_LOD_64; break;
787 case 128: lod = GR_LOD_128; break;
788 case 256: lod = GR_LOD_256; break;
793 GrAspectRatio_t aspect = GR_ASPECT_1x1; // aspect is widthxheight
795 if ( tex_w < tex_h ) {
796 int ratio = tex_h / tex_w;
798 case 1: aspect = GR_ASPECT_1x1; break;
799 case 2: aspect = GR_ASPECT_1x2; break;
800 case 4: aspect = GR_ASPECT_1x4; break;
801 case 8: aspect = GR_ASPECT_1x8; break;
805 int ratio = tex_w / tex_h;
807 case 1: aspect = GR_ASPECT_1x1; break;
808 case 2: aspect = GR_ASPECT_2x1; break;
809 case 4: aspect = GR_ASPECT_4x1; break;
810 case 8: aspect = GR_ASPECT_8x1; break;
818 info.smallLod = lod; //GR_LOD_256;
819 info.largeLod = lod; //GR_LOD_256;
820 info.aspectRatio = aspect; //GR_ASPECT_1x1;
821 info.format = tex_format; //GR_TEXFMT_ARGB_1555;
822 info.data = Glide_tmp_ram; //source data
824 int bytes_needed = grTexTextureMemRequired( GR_MIPMAPLEVELMASK_BOTH, &info );
826 // if ( (tslot->data.vram_offset == 0) || ((tslot->data.vram_offset>0)&&(bytes_needed>tslot->data.vram_size))) {
827 tslot->data.vram_offset = AllocateTexture( bytes_needed, tslot );
828 tslot->data.vram_size = bytes_needed;
829 Glide_textures_in += bytes_needed;
832 tslot->data.format = tex_format;
833 tslot->data.lod = lod;
834 tslot->data.aspect = aspect;
835 tslot->bitmap_id = bitmap_handle;
836 tslot->uscale = uscale;
837 tslot->vscale = vscale;
839 grTexDownloadMipMap(GR_TMU0, tslot->data.vram_offset, GR_MIPMAPLEVELMASK_BOTH, &info);
840 Glide_textures_in_frame += bytes_needed;
845 int glide_create_texture( int bitmap_handle, int bitmap_type, tcache_slot *tslot )
852 // setup texture/bitmap flags
855 case TCACHE_TYPE_AABITMAP:
856 flags |= BMP_AABITMAP;
859 case TCACHE_TYPE_XPARENT:
860 case TCACHE_TYPE_BITMAP_SECTION:
861 flags |= BMP_TEX_XPARENT;
863 case TCACHE_TYPE_NORMAL:
864 flags |= BMP_TEX_OTHER;
866 case TCACHE_TYPE_NONDARKENING:
867 flags |= BMP_TEX_NONDARK;
871 // lock the bitmap in the proper format
872 bmp = bm_lock(bitmap_handle, bpp, flags);
874 mprintf(("Couldn't lock bitmap %d.\n", bitmap_handle ));
881 if ( bitmap_type != TCACHE_TYPE_AABITMAP ) {
882 // Detail.debris_culling goes from 0 to 4.
883 max_w /= 16>>Detail.hardware_textures;
884 max_h /= 16>>Detail.hardware_textures;
888 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);
891 bm_unlock(bitmap_handle);
897 // create a sectioned texture
898 int glide_create_texture_sectioned(int bitmap_handle, int bitmap_type, tcache_slot *tslot, int sx, int sy)
903 int section_x, section_y;
905 // setup texture/bitmap flags
906 Assert(bitmap_type == TCACHE_TYPE_BITMAP_SECTION);
907 if(bitmap_type != TCACHE_TYPE_BITMAP_SECTION){
908 bitmap_type = TCACHE_TYPE_BITMAP_SECTION;
910 flags = BMP_TEX_XPARENT;
912 // lock the bitmap in the proper format
913 bmp = bm_lock(bitmap_handle, 16, flags);
915 mprintf(("Couldn't lock bitmap %d.\n", bitmap_handle ));
919 // determine the width and height of this section
920 bm_get_section_size(bitmap_handle, sx, sy, §ion_x, §ion_y);
923 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);
926 bm_unlock(bitmap_handle);
935 Glide_explosion_vram = 0;
938 extern int bm_get_cache_slot( int bitmap_id, int separate_ani_frames );
940 // Returns FALSE if error
941 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 )
946 if ( Glide_last_detail != Detail.hardware_textures ) {
947 Glide_last_detail = Detail.hardware_textures;
948 glide_tcache_flush();
951 // Check if this is the same as the last one... if so, we don't need to
953 if ( (Glide_last_bitmap_id == bitmap_id) && (Glide_last_bitmap_type==bitmap_type) && (Glide_last_section_x == sx) && (Glide_last_section_y == sy) && !force) {
954 *u_ratio = Glide_last_u_ratio;
955 *v_ratio = Glide_last_v_ratio;
960 n = bm_get_cache_slot( bitmap_id, 1 );
962 tcache_slot * t = &Textures[n];
964 // if this is a sectioned bitmap
965 if(bitmap_type == TCACHE_TYPE_BITMAP_SECTION){
966 // if the texture sections haven't been created yet
967 if((t->bitmap_id < 0) || (t->bitmap_id != bitmap_id) || force){
969 if(t->bitmap_id < 0){
970 t->data.vram_offset = 0;
973 // lock the bitmap in the proper format
974 bmp = bm_lock(bitmap_id, 16, BMP_TEX_XPARENT);
975 bm_unlock(bitmap_id);
977 // first we need to get enough free aux textures
980 for(idx=0; idx<bmp->sections.num_x; idx++){
981 for(s_idx=0; s_idx<bmp->sections.num_y; s_idx++){
982 // try and get a feww slot
983 t->data_sections[idx][s_idx] = glide_get_aux_slot();
984 if(t->data_sections[idx][s_idx] == NULL){
988 t->data_sections[idx][s_idx]->bitmap_id = bitmap_id;
993 // now lets do something for each texture
994 for(idx=0; idx<bmp->sections.num_x; idx++){
995 for(s_idx=0; s_idx<bmp->sections.num_y; s_idx++){
996 if(t->bitmap_id < 0){
997 t->data_sections[idx][s_idx]->data.vram_offset = 0;
1000 t->data_sections[idx][s_idx]->bitmap_id = bitmap_id;
1001 glide_create_texture_sectioned( bitmap_id, bitmap_type, t->data_sections[idx][s_idx], idx, s_idx);
1005 t->bitmap_id = bitmap_id;
1008 // swap in the texture we want
1009 t = t->data_sections[sx][sy];
1011 // all other "normal" textures
1014 if ( t->bitmap_id < 0) {
1015 t->data.vram_offset = 0;
1016 glide_create_texture( bitmap_id, bitmap_type, t );
1018 // different bitmap altogether
1019 else if ( (t->bitmap_id != bitmap_id) || force) {
1020 glide_create_texture( bitmap_id, bitmap_type, t );
1024 *u_ratio = t->uscale;
1025 *v_ratio = t->vscale;
1029 info.smallLod = t->data.lod; //GR_LOD_256;
1030 info.largeLod = t->data.lod; //GR_LOD_256;
1031 info.aspectRatio = t->data.aspect; //GR_ASPECT_1x1;
1032 info.format = t->data.format; //GR_TEXFMT_ARGB_1555;
1033 info.data = 0; //source data
1035 grTexSource( GR_TMU0, t->data.vram_offset, GR_MIPMAPLEVELMASK_BOTH, &info );
1037 // Save current state so we don't have to do anything time consuming next time
1038 // we set this exact same texture
1039 Glide_last_bitmap_id = bitmap_id;
1040 Glide_last_bitmap_type = bitmap_type;
1041 Glide_last_section_x = sx;
1042 Glide_last_section_y = sy;
1043 Glide_last_u_ratio = t->uscale;
1044 Glide_last_v_ratio = t->vscale;