]> icculus.org git repositories - taylor/freespace2.git/blob - src/graphics/grd3dtexture.cpp
Initial revision
[taylor/freespace2.git] / src / graphics / grd3dtexture.cpp
1 /*
2  * $Logfile: /Freespace2/code/Graphics/GrD3DTexture.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * Code to manage loading textures into VRAM for Direct3D
8  *
9  * $Log$
10  * Revision 1.1  2002/05/03 03:28:09  root
11  * Initial revision
12  *
13  * 
14  * 22    9/09/99 8:53p Dave
15  * Fixed multiplayer degenerate orientation case problem. Make sure warp
16  * effect never goes lower than LOD 1. 
17  * 
18  * 21    9/05/99 11:19p Dave
19  * Made d3d texture cache much more safe. Fixed training scoring bug where
20  * it would backout scores without ever having applied them in the first
21  * place.
22  * 
23  * 20    8/16/99 4:04p Dave
24  * Big honking checkin.
25  * 
26  * 19    7/29/99 10:47p Dave
27  * Standardized D3D fogging using vertex fog. Shook out Savage 4 bugs.
28  * 
29  * 18    7/16/99 1:49p Dave
30  * 8 bit aabitmaps. yay.
31  * 
32  * 17    7/13/99 1:15p Dave
33  * 32 bit support. Whee!
34  * 
35  * 16    7/09/99 9:51a Dave
36  * Added thick polyline code.
37  * 
38  * 15    6/29/99 10:35a Dave
39  * Interface polygon bitmaps! Whee!
40  * 
41  * 14    6/16/99 4:06p Dave
42  * New pilot info popup. Added new draw-bitmap-as-poly function.
43  * 
44  * 13    5/05/99 9:02p Dave
45  * Fixed D3D aabitmap rendering. Spiffed up nebula effect a bit (added
46  * rotations, tweaked values, made bitmap selection more random). Fixed
47  * D3D beam weapon clipping problem. Added D3d frame dumping.
48  * 
49  * 12    2/11/99 3:08p Dave
50  * PXO refresh button. Very preliminary squad war support.
51  * 
52  * 11    2/05/99 12:52p Dave
53  * Fixed Glide nondarkening textures.
54  * 
55  * 10    2/03/99 11:44a Dave
56  * Fixed d3d transparent textures.
57  * 
58  * 9     1/30/99 5:08p Dave
59  * More new hi-res stuff.Support for nice D3D textures.
60  * 
61  * 8     1/15/99 11:29a Neilk
62  * Fixed D3D screen/texture pixel formatting problem. 
63  * 
64  * 7     1/12/99 12:53a Dave
65  * More work on beam weapons - made collision detection very efficient -
66  * collide against all object types properly - made 3 movement types
67  * smooth. Put in test code to check for possible non-darkening pixels on
68  * object textures.
69  * 
70  * 6     12/01/98 6:12p Johnson
71  * Make sure to page in weapon impact animations as xparent textures.
72  * 
73  * 5     12/01/98 10:32a Johnson
74  * Fixed direct3d font problems. Fixed sun bitmap problem. Fixed direct3d
75  * starfield problem.
76  * 
77  * 4     11/30/98 1:07p Dave
78  * 16 bit conversion, first run.
79  * 
80  * 3     10/09/98 2:57p Dave
81  * Starting splitting up OS stuff.
82  * 
83  * 2     10/07/98 10:52a Dave
84  * Initial checkin.
85  * 
86  * 1     10/07/98 10:49a Dave
87  * 
88  * 37    6/13/98 3:18p Hoffoss
89  * NOX()ed out a bunch of strings that shouldn't be translated.
90  * 
91  * 36    5/23/98 6:12p John
92  * added code to use registry to force preloading of textures or not.
93  * 
94  * 35    5/23/98 5:17p John
95  * added reg key to set texture divider
96  * 
97  * 34    5/23/98 5:01p John
98  * made agp preloading happen if >= 6 MB of VRAM.
99  * 
100  * 33    5/23/98 4:14p John
101  * Added code to preload textures to video card for AGP.   Added in code
102  * to page in some bitmaps that weren't getting paged in at level start.
103  * 
104  * 32    5/22/98 10:29p John
105  * made direct3d textures scale as little as glide.
106  * 
107  * 31    5/22/98 12:54p John
108  * forced all cards to use a max of 256 pixel wide textures, but added a
109  * registry setting to disable it.
110  * 
111  * 30    5/21/98 9:56p John
112  * Made Direct3D work with classic alpha-blending only devices, like the
113  * Virge.  Added a texture type XPARENT that fills the alpha in in the
114  * bitmap for Virge.   Added support for Permedia by making making
115  * additive alphablending be one/one instead of alpha/one, which didn't
116  * work, and there is no way to tell this from caps.
117  * 
118  * 29    5/20/98 10:23a John
119  * put in code to fix an optimized build problem.
120  * 
121  * 28    5/18/98 8:26p John
122  * Made cards with only 1bpp alpha fonts work.
123  * 
124  * 27    5/12/98 7:53p John
125  * Fixed some 3dfx d3d bugs on allenders, jasen and johnson's computers
126  * caused by 8:3:3:2 format being used, but not liked by the card.
127  * 
128  * 26    5/12/98 8:18a John
129  * Put in code to use a different texture format for alpha textures and
130  * normal textures.   Turned off filtering for aabitmaps.  Took out
131  * destblend=invsrccolor alpha mode that doesn't work on riva128. 
132  * 
133  * 25    5/11/98 10:58a John
134  * Fixed pilot name cursor bug.  Started adding in code for alphachannel
135  * textures.
136  * 
137  * 24    5/09/98 12:37p John
138  * More texture caching
139  * 
140  * 23    5/09/98 12:16p John
141  * Even better texture caching.
142  * 
143  * 22    5/09/98 11:07a John
144  * Better Direct3D texture caching
145  * 
146  * 21    5/08/98 5:41p John
147  * 
148  * 20    5/08/98 5:36p John
149  * MAde texturing blink white but not crash
150  * 
151  * 19    5/07/98 3:02p John
152  * Mpre texture cleanup.   You can now reinit d3d without a crash.
153  * 
154  * 18    5/07/98 11:31a John
155  * Removed DEMO defines
156  * 
157  * 17    5/07/98 10:28a John
158  * Made texture format use 4444.   Made fonts use alpha to render.
159  * 
160  * 16    5/07/98 9:40a John
161  * Fixed some bitmap transparency issues with Direct3D.
162  * 
163  * 15    5/06/98 11:21p John
164  * Fixed a bitmap bug with Direct3D.  Started adding new caching code into
165  * D3D.
166  * 
167  * 14    5/06/98 8:41p John
168  * Fixed some font clipping bugs.   Moved texture handle set code for d3d
169  * into the texture module.
170  * 
171  * 13    5/03/98 10:52a John
172  * Made D3D sort of work on 3dfx.
173  * 
174  * 12    5/03/98 10:43a John
175  * Working on Direct3D.
176  * 
177  * 11    4/09/98 11:05a John
178  * Removed all traces of Direct3D out of the demo version of Freespace and
179  * the launcher.
180  * 
181  * 10    3/12/98 5:36p John
182  * Took out any unused shaders.  Made shader code take rgbc instead of
183  * matrix and vector since noone used it like a matrix and it would have
184  * been impossible to do in hardware.   Made Glide implement a basic
185  * shader for online help.  
186  * 
187  * 9     3/08/98 10:25a John
188  * Made textures in VRAM reload if they changed
189  * 
190  * 8     3/07/98 8:29p John
191  * Put in some Direct3D features.  Transparency on bitmaps.  Made fonts &
192  * aabitmaps render nice.
193  * 
194  * 7     3/06/98 5:39p John
195  * Started adding in aabitmaps
196  * 
197  * 6     3/02/98 6:00p John
198  * Moved MAX_BITMAPS into BmpMan.h so the stuff in the graphics code that
199  * is dependent on it won't break if it changes.   Made ModelCache slots
200  * be equal to MAX_OBJECTS which is what it is.
201  * 
202  * 5     2/17/98 7:46p John
203  * Took out debug code
204  * 
205  * 4     2/17/98 7:28p John
206  * Got fonts and texturing working in Direct3D
207  * 
208  * 3     2/06/98 4:56p John
209  * Turned off texturing
210  * 
211  * 2     2/05/98 9:21p John
212  * Some new Direct3D code.   Added code to monitor a ton of stuff in the
213  * game.
214  * 
215  * 1     2/03/98 9:24p John
216  *
217  * $NoKeywords: $
218  */
219
220 #include "grd3d.h"
221 #include "grd3dinternal.h"
222 #include "2d.h"
223 #include "pstypes.h"
224 #include "bmpman.h"
225 #include "key.h"
226 #include "systemvars.h"
227 #include "osregistry.h"
228
229 #include "multi_log.h"
230
231 typedef struct tcache_slot_d3d {
232         LPDIRECTDRAWSURFACE             vram_texture_surface;
233         LPDIRECT3DTEXTURE2              vram_texture;
234         D3DTEXTUREHANDLE                        texture_handle;
235         float                                                   u_scale, v_scale;
236         int                                                     bitmap_id;
237         int                                                     size;
238         char                                                    used_this_frame;
239         int                                                     time_created;
240         ushort                                          w, h;
241
242         // sections
243         tcache_slot_d3d                 *data_sections[MAX_BMAP_SECTIONS_X][MAX_BMAP_SECTIONS_Y];
244         tcache_slot_d3d                 *parent;
245 } tcache_slot_d3d;
246
247 static void *Texture_sections = NULL;
248 tcache_slot_d3d *Textures = NULL;
249
250
251 int D3D_texture_sections = 0;
252 int D3D_texture_ram = 0;
253 int D3D_frame_count = 0;
254 int D3D_min_texture_width = 0;
255 int D3D_max_texture_width = 0;
256 int D3D_min_texture_height = 0;
257 int D3D_max_texture_height = 0;
258 int D3D_square_textures = 0;
259 int D3D_pow2_textures = 0;
260 int D3D_textures_in = 0;
261 int D3D_textures_in_frame = 0;
262 int D3D_last_bitmap_id = -1;
263 int D3D_last_detail = -1;
264 int D3D_last_bitmap_type = -1;
265 int D3D_last_section_x = -1;
266 int D3D_last_section_y = -1;
267
268
269 int vram_full = 0;
270
271 int d3d_free_texture( tcache_slot_d3d *t )
272 {
273         int idx, s_idx;
274
275         // Bitmap changed!!     
276         if ( t->bitmap_id > -1 )        {                               
277                 // if I, or any of my children have been used this frame, bail          
278                 if(t->used_this_frame){                 
279                         return 0;
280                 }               
281                 for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
282                         for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
283                                 if((t->data_sections[idx][s_idx] != NULL) && (t->data_sections[idx][s_idx]->used_this_frame)){
284                                         return 0;
285                                 }
286                         }
287                 }
288
289                 // ok, now we know its legal to free everything safely
290                 if ( t->vram_texture )  {
291                         t->vram_texture->Release();
292                         t->vram_texture = NULL;
293                 }
294
295                 if ( t->vram_texture_surface )  {
296                         t->vram_texture_surface->Release();
297                         t->vram_texture_surface = NULL;
298                 }
299
300                 t->texture_handle = NULL;
301
302                 if ( D3D_last_bitmap_id == t->bitmap_id )       {
303                         D3D_last_bitmap_id = -1;
304                 }
305                         
306                 // if this guy has children, free them too, since the children
307                 // actually make up his size
308                 for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
309                         for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
310                                 if(t->data_sections[idx][s_idx] != NULL){
311                                         d3d_free_texture(t->data_sections[idx][s_idx]);                                         
312                                 }
313                         }
314                 }                       
315
316                 t->bitmap_id = -1;
317                 t->used_this_frame = 0;
318                 D3D_textures_in -= t->size;             
319         }
320
321         return 1;
322 }
323
324 // we must make sure we never free my parent or any of my siblings!!!!!
325 int d3d_older_test(tcache_slot_d3d *new_slot, tcache_slot_d3d *test, tcache_slot_d3d *oldest)
326 {
327         if ( (test != new_slot) && (test != new_slot->parent) && (test->bitmap_id > -1) && (!test->used_this_frame))    {
328                 if ( (oldest == NULL) || (test->time_created < oldest->time_created))   {
329                         return 1;
330                 }
331         }
332
333         // not older
334         return 0;
335 }
336
337 int d3d_free_some_texture_ram(tcache_slot_d3d *t, int size)
338 {       
339         tcache_slot_d3d *oldest = NULL;
340         
341         // Go through all the textures... find the oldest one 
342         // that was not used this frame yet.
343         int i;
344
345         int goal_size = D3D_textures_in - size*2;
346         if ( goal_size < 0 )    {
347                 goal_size = 0;
348         } else if ( goal_size > D3D_texture_ram*3/4 )   {
349                 goal_size = D3D_texture_ram*3/4;
350         }
351
352         while( D3D_textures_in > goal_size )    {
353                 oldest = NULL;
354                 for( i=0; i<MAX_BITMAPS; i++ )  {                       
355                         // maybe pick this one
356                         if(d3d_older_test(t, &Textures[i], oldest)){
357                                 oldest = &Textures[i];
358                         }                                                       
359                 }
360
361                 if ( oldest == NULL )   {
362                         mprintf(( "Couldn't free enough VRAM this frame... you might see some ugliness!\n" ));
363                         return 0;
364                 }
365
366                 d3d_free_texture(oldest);
367         }
368
369         mprintf(( "Freed 1/4 of the VRAM\n" ));
370         return 1;
371 }
372
373 #ifndef NDEBUG
374 int Show_uploads = 0;
375 DCF_BOOL( show_uploads, Show_uploads )
376 #endif
377
378 // is the given existing texture handle the same dimensions as the passed in bitmap?
379 int d3d_tcache_same_dimension(int bitmap_id, int bitmap_type, tcache_slot_d3d *t)
380 {
381         int idx, s_idx;
382         int w, h, nframes, fps;
383         ubyte flags;
384         bitmap_section_info *s = NULL;
385
386         // get bitmap info
387         bm_get_info(bitmap_id, &w, &h, &flags, &nframes, &fps, &s);
388
389         // bogus
390         if(s == NULL){
391                 return 0;
392         }
393
394         // sectioned bitmap
395         if(bitmap_type == TCACHE_TYPE_BITMAP_SECTION){
396                 for(idx=0; idx<s->num_x; idx++){
397                         for(s_idx=0; s_idx<s->num_y; s_idx++){                          
398                                 // bogus
399                                 if(t->data_sections[idx][s_idx] == NULL){
400                                         return 0;
401                                 }
402
403                                 // given a bitmap and a section, return the size (w, h)
404                                 bm_get_section_size(bitmap_id, idx, s_idx, &w, &h);
405
406                                 // same ?
407                                 if((t->data_sections[idx][s_idx]->w != w) || (t->data_sections[idx][s_idx]->h != h)){
408                                         return 0;
409                                 }
410                         }
411                 }
412         }
413         // non-sectioned bitmap
414         else {
415                 if((t->w != w) || (t->h != h)){
416                         return 0;
417                 }
418         }
419
420         // all good
421         return 1;
422 }
423
424 // get the final texture size (the one which will get allocated as a surface)
425 void d3d_tcache_get_adjusted_texture_size(int w_in, int h_in, int *w_out, int *h_out)
426 {
427         int tex_w, tex_h;
428
429         // bogus
430         if((w_out == NULL) ||  (h_out == NULL)){
431                 return;
432         }
433
434         // starting size
435         tex_w = w_in;
436         tex_h = h_in;
437
438         if ( D3D_pow2_textures )        {
439                 int i;
440                 for (i=0; i<16; i++ )   {
441                         if ( (tex_w > (1<<i)) && (tex_w <= (1<<(i+1))) )        {
442                                 tex_w = 1 << (i+1);
443                                 break;
444                         }
445                 }
446
447                 for (i=0; i<16; i++ )   {
448                         if ( (tex_h > (1<<i)) && (tex_h <= (1<<(i+1))) )        {
449                                 tex_h = 1 << (i+1);
450                                 break;
451                         }
452                 }
453         }
454
455         if ( tex_w < D3D_min_texture_width ) {
456                 tex_w = D3D_min_texture_width;
457         } else if ( tex_w > D3D_max_texture_width )     {
458                 tex_w = D3D_max_texture_width;
459         }
460
461         if ( tex_h < D3D_min_texture_height ) {
462                 tex_h = D3D_min_texture_height;
463         } else if ( tex_h > D3D_max_texture_height )    {
464                 tex_h = D3D_max_texture_height;
465         }
466
467         if ( D3D_square_textures )      {
468                 int new_size;
469                 // Make the both be equal to larger of the two
470                 new_size = max(tex_w, tex_h);
471                 tex_w = new_size;
472                 tex_h = new_size;
473         }       
474
475         // store the outgoing size
476         *w_out = tex_w;
477         *h_out = tex_h;
478 }
479
480 // data == start of bitmap data
481 // sx == x offset into bitmap
482 // sy == y offset into bitmap
483 // src_w == absolute width of section on source bitmap
484 // src_h == absolute height of section on source bitmap
485 // bmap_w == width of source bitmap
486 // bmap_h == height of source bitmap
487 // tex_w == width of final texture
488 // tex_h == height of final texture
489 int d3d_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_d3d *t, int reload, int fail_on_full)
490 {
491         LPDIRECTDRAWSURFACE             sys_texture_surface = NULL;
492         LPDIRECT3DTEXTURE2              sys_texture = NULL;
493         int ret_val = 1;
494
495         #ifndef NDEBUG
496                 if ( Show_uploads )     {
497                         if ( reload )   {
498                                 mprintf(( "Reloading '%s'\n", bm_get_filename(texture_handle) ));
499                         } else {
500                                 mprintf(( "Uploading '%s'\n", bm_get_filename(texture_handle) ));
501                         }
502                 }
503         #endif
504
505         // bogus
506         if(t == NULL){
507                 return 0;
508         }
509                 
510         if ( t->used_this_frame )       {
511                 mprintf(( "ARGHH!!! Texture already used this frame!  Cannot free it!\n" ));
512                 return 0;
513         }       
514         if ( !reload )  {
515                 // gah
516                 if(!d3d_free_texture(t)){
517                         return 0;
518                 }
519         }
520
521         DDSURFACEDESC ddsd;
522         HRESULT ddrval;
523         DWORD dwHeight, dwWidth;
524         int i,j;        
525         ushort *bmp_data;
526
527         DDPIXELFORMAT *surface_desc;
528
529         switch( bitmap_type )   {
530                 case TCACHE_TYPE_AABITMAP:              
531                         surface_desc = &AlphaTextureFormat;
532                         break;
533
534                 case TCACHE_TYPE_XPARENT:
535                         Int3();
536
537                 default:
538                         surface_desc = &NonAlphaTextureFormat;
539         }       
540
541         // get final texture size
542         d3d_tcache_get_adjusted_texture_size(tex_w, tex_h, &tex_w, &tex_h);
543
544         if ( (tex_w < 1) || (tex_h < 1) )       {
545                 mprintf(("Bitmap is to small at %dx%d.\n", tex_w, tex_h ));             
546                 return 0;
547         }
548
549         if ( bitmap_type == TCACHE_TYPE_AABITMAP )      {
550                 t->u_scale = (float)bmap_w / (float)tex_w;
551                 t->v_scale = (float)bmap_h / (float)tex_h;
552         } else if(bitmap_type == TCACHE_TYPE_BITMAP_SECTION){
553                 t->u_scale = (float)src_w / (float)tex_w;
554                 t->v_scale = (float)src_h / (float)tex_h;
555         } else {
556                 t->u_scale = 1.0f;
557                 t->v_scale = 1.0f;
558         }
559                 
560         dwHeight = tex_h;
561         dwWidth = tex_w;
562         bmp_data = (ushort *)data;
563         ubyte *bmp_data_byte = (ubyte*)data;
564
565         // Create a surface in system memory and load texture into it.
566
567         // Create a surface of the given format using the dimensions of the bitmap
568         memset(&ddsd, 0, sizeof(DDSURFACEDESC));
569
570         ddsd.dwSize = sizeof(DDSURFACEDESC);
571         ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
572         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
573         ddsd.dwHeight = dwHeight;
574         ddsd.dwWidth = dwWidth;
575         ddsd.ddpfPixelFormat = *surface_desc;
576
577         sys_texture_surface = NULL;
578         ddrval = lpDD->CreateSurface(&ddsd, &sys_texture_surface, NULL);
579         if ( (ddrval != DD_OK) || (sys_texture_surface == NULL) ) {
580                 mprintf(("CreateSurface for texture failed (loadtex), w=%d, h=%d, %s\n", tex_w, tex_h, d3d_error_string(ddrval) ));
581                 mprintf(( "Texture RAM = %d KB\n", D3D_textures_in / 1024 ));
582                 // bm_unlock(bitmap_handle);
583                 return 0;
584         }
585         
586         // Lock the surface so it can be filled with the bitmap data
587         memset(&ddsd, 0, sizeof(DDSURFACEDESC));
588         ddsd.dwSize = sizeof(DDSURFACEDESC);
589         ddrval = sys_texture_surface->Lock(NULL, &ddsd, 0, NULL);
590         if (ddrval != DD_OK) {
591                 sys_texture_surface->Release();
592                 mprintf(("Lock failed while loading surface (loadtex).\n" ));
593                 return 0;
594         }
595
596         Assert( surface_desc->dwRGBBitCount == 16 );
597
598         // Each RGB bit count requires different pointers
599         ushort *lpSP;   
600         ushort xlat[256];
601         int r, g, b, a;
602
603         switch( bitmap_type )   {               
604                 case TCACHE_TYPE_AABITMAP:                      
605                         // setup convenient translation table
606                         for (i=0; i<16; i++ )   {
607                                 r = 255;
608                                 g = 255;
609                                 b = 255;
610                                 a = Gr_gamma_lookup[(i*255)/15];
611                                 r /= Gr_ta_red.scale;
612                                 g /= Gr_ta_green.scale;
613                                 b /= Gr_ta_blue.scale;
614                                 a /= Gr_ta_alpha.scale;
615                                 xlat[i] = unsigned short(((a<<Gr_ta_alpha.shift) | (r << Gr_ta_red.shift) | (g << Gr_ta_green.shift) | (b << Gr_ta_blue.shift)));
616                         }                       
617                         
618                         xlat[15] = xlat[1];                     
619                         for ( ; i<256; i++ )    {
620                                 xlat[i] = xlat[0];                                              
621                         }                       
622                         
623                         for (j = 0; j < tex_h; j++) {                           
624                                 lpSP = (unsigned short*)(((char*)ddsd.lpSurface) +      ddsd.lPitch * j);
625
626                                 for (i = 0; i < tex_w; i++) {
627                                         if ( (i < bmap_w) && (j<bmap_h) )       {                                               
628                                                 *lpSP++ = xlat[(ubyte)bmp_data_byte[j*bmap_w+i]];
629                                         } else {
630                                                 *lpSP++ = 0;
631                                         }
632                                 }
633                         }
634                 break;
635         
636         case TCACHE_TYPE_BITMAP_SECTION:        
637                 for (j = 0; j < src_h; j++) {
638                         // the proper line in the temp ram
639                         lpSP = (unsigned short*)(((char*)ddsd.lpSurface) +      ddsd.lPitch * j);
640
641                         // nice and clean
642                         for (i = 0; i < src_w; i++) {                                                                                           
643                                 // stuff the texture into vram
644                                 *lpSP++ = bmp_data[((j+sy) * bmap_w) + sx + i];
645                         }                       
646                 }
647                 break;
648
649         default:                {       // normal:              
650                         fix u, utmp, v, du, dv;
651
652                         u = v = 0;
653
654                         du = ( (bmap_w-1)*F1_0 ) / tex_w;
655                         dv = ( (bmap_h-1)*F1_0 ) / tex_h;
656                                                                                         
657                         for (j = 0; j < tex_h; j++) {
658                                 lpSP = (unsigned short*)(((char*)ddsd.lpSurface) +      ddsd.lPitch * j);
659
660                                 utmp = u;                               
661                                 
662                                 for (i = 0; i < tex_w; i++) {
663                                         *lpSP++ = bmp_data[f2i(v)*bmap_w+f2i(utmp)];
664                                         utmp += du;
665                                 }
666                                 v += dv;
667                         }
668                 }
669                 break;
670         }
671
672         // bm_unlock(bitmap_handle);
673
674         // Unlock the texture 
675         sys_texture_surface->Unlock(NULL);
676
677         sys_texture = NULL;
678         ddrval = sys_texture_surface->QueryInterface(IID_IDirect3DTexture2, (LPVOID *)&sys_texture);
679         if ( (ddrval != DD_OK) || (sys_texture == NULL) ) {
680                 mprintf(( "Getting sys surface's texture failed!\n" ));
681
682                 // bad return value
683                 ret_val = 0;
684
685                 goto FreeSurfacesAndExit;
686         }
687
688 RetryLoad:
689
690         if ( !reload )  {       
691                 // Create a surface of the given format using the dimensions of the bitmap
692                 memset(&ddsd, 0, sizeof(DDSURFACEDESC));
693
694                 ddsd.dwSize = sizeof(DDSURFACEDESC);
695                 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
696                 ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_ALLOCONLOAD | DDSCAPS_VIDEOMEMORY;
697                 //| DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_ALLOCONLOAD;
698                 ddsd.dwHeight = dwHeight;
699                 ddsd.dwWidth = dwWidth;
700                 ddsd.ddpfPixelFormat = *surface_desc;
701
702                 t->vram_texture_surface = NULL;
703                 ddrval = lpDD->CreateSurface(&ddsd, &t->vram_texture_surface, NULL);
704                 if ( (ddrval != DD_OK) || (t->vram_texture_surface == NULL) ) {
705                         t->vram_texture = NULL;
706                         t->vram_texture_surface = NULL;
707                         t->texture_handle = NULL;
708
709                         if ( ddrval==DDERR_OUTOFVIDEOMEMORY )   {
710                                 mprintf(("Out of VRAM (w=%d, h=%d, used=%d KB)\n", tex_w, tex_h, D3D_textures_in / 1024 ));
711                                 if ( fail_on_full )     {
712                                         // bad return value
713                                         ret_val = 0;
714
715                                         goto FreeSurfacesAndExit;
716                                 }
717                                 if ( d3d_free_some_texture_ram(t,dwHeight*dwWidth*2))   {
718                                         goto RetryLoad;
719                                 }
720                         } else {
721                                 mprintf(("CreateSurface for VRAM texture failed, w=%d, h=%d\n%s\n", tex_w, tex_h, d3d_error_string(ddrval) ));
722                                 mprintf(( "Texture RAM = %d KB\n", D3D_textures_in / 1024 ));
723                         }
724                         vram_full = 1;
725
726                         // bad return value
727                         ret_val = 0;
728
729                         goto FreeSurfacesAndExit;
730                         //goto RetryLoad;
731                 }
732
733                 t->vram_texture = NULL;
734                 ddrval = t->vram_texture_surface->QueryInterface(IID_IDirect3DTexture2, (LPVOID *)&t->vram_texture);
735                 if ( (ddrval != DD_OK) || (t->vram_texture == NULL) )   {
736                         mprintf(( "GR_D3D_INIT: TextureSurface->QueryInterface failed.\n" ));
737                         vram_full = 1;
738
739                         // bad return value
740                         ret_val = 0;
741
742                         goto FreeSurfacesAndExit;
743                 }
744
745                 //      char *name = bm_get_filename(bitmap_handle);
746                 //      mprintf(( "Uploading '%s'\n", name ));
747                 t->texture_handle = NULL;
748                 ddrval = t->vram_texture->GetHandle(lpD3DDevice, &t->texture_handle );
749                 if ( (ddrval != DD_OK) || (t->texture_handle == NULL) ) {
750                         mprintf(( "GR_D3D_INIT: Texture->GetHandle failed.\n" ));
751                         t->texture_handle = NULL;
752                         vram_full = 1;
753
754                         // bad return value
755                         ret_val = 0;
756
757                         goto FreeSurfacesAndExit;
758                 }
759         }
760
761         // argh. this texture appears to be bogus. lets free it
762         if(t->vram_texture == NULL){
763                 d3d_free_texture(t);
764                         
765                 // bad
766                 ret_val = 0;
767                 
768                 goto FreeSurfacesAndExit;
769         }
770
771         ddrval = t->vram_texture->Load( sys_texture );
772         if ( ddrval != DD_OK ) {
773                 mprintf(("VRAM Load failed, w=%d, h=%d, %s\n", tex_w, tex_h, d3d_error_string(ddrval) ));
774                 mprintf(( "Texture RAM = %d KB\n", D3D_textures_in / 1024 ));
775                 vram_full = 1;
776
777                 // bad return value
778                 ret_val = 0;
779
780                 goto FreeSurfacesAndExit;
781         }
782
783         t->bitmap_id = texture_handle;
784         t->time_created = D3D_frame_count;
785         t->used_this_frame = 0; 
786         t->size = tex_w * tex_h * 2;    
787         t->w = (ushort)tex_w;
788         t->h = (ushort)tex_h;
789         D3D_textures_in_frame += t->size;
790         if ( !reload )  {       
791                 D3D_textures_in += t->size;
792         }
793
794 FreeSurfacesAndExit:
795         if ( sys_texture )      {
796                 sys_texture->Release();
797                 sys_texture = NULL;
798         }
799
800         if ( sys_texture_surface )      {
801                 sys_texture_surface->Release();
802                 sys_texture_surface = NULL;
803         }
804
805         // hopefully this is 1  :)
806         return ret_val;
807 }
808
809 int d3d_create_texture(int bitmap_handle, int bitmap_type, tcache_slot_d3d *tslot, int fail_on_full)
810 {
811         ubyte flags;
812         bitmap *bmp;
813         int final_w, final_h;
814         ubyte bpp = 16;
815         int reload = 0;
816
817         // setup texture/bitmap flags
818         flags = 0;
819         switch(bitmap_type){
820         case TCACHE_TYPE_AABITMAP:
821                 flags |= BMP_AABITMAP;
822                 bpp = 8;
823                 break;
824         case TCACHE_TYPE_NORMAL:
825                 flags |= BMP_TEX_OTHER;
826         case TCACHE_TYPE_XPARENT:
827                 flags |= BMP_TEX_XPARENT;                               
828                 break;
829         case TCACHE_TYPE_NONDARKENING:          
830                 Int3();
831                 flags |= BMP_TEX_NONDARK;
832                 break;
833         }
834         
835         // lock the bitmap into the proper format
836         bmp = bm_lock(bitmap_handle, bpp, flags);
837         if ( bmp == NULL ) {
838                 mprintf(("Couldn't lock bitmap %d.\n", bitmap_handle ));
839                 return 0;
840         }
841
842         int max_w = bmp->w;
843         int max_h = bmp->h; 
844                 
845         if ( bitmap_type != TCACHE_TYPE_AABITMAP )      {
846                 max_w /= D3D_texture_divider;
847                 max_h /= D3D_texture_divider;
848
849                 // Detail.debris_culling goes from 0 to 4.
850                 max_w /= 16 >> Detail.hardware_textures;
851                 max_h /= 16 >> Detail.hardware_textures;
852         }
853
854         // get final texture size as it will be allocated as a DD surface
855         d3d_tcache_get_adjusted_texture_size(max_w, max_h, &final_w, &final_h);
856
857         // if this tcache slot has no bitmap
858         if ( tslot->bitmap_id < 0) {                    
859                 reload = 0;
860         }
861         // different bitmap altogether - determine if the new one can use the old one's slot
862         else if (tslot->bitmap_id != bitmap_handle)     {
863                 if((final_w == tslot->w) && (final_h == tslot->h)){
864                         reload = 1;
865
866                         ml_printf("Reloading texture %d\n", bitmap_handle);
867                 } else {
868                         reload = 0;
869                 }
870         }
871
872         // call the helper
873         int ret_val = d3d_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, reload, fail_on_full);
874
875         // unlock the bitmap
876         bm_unlock(bitmap_handle);
877
878         return ret_val;
879 }
880
881 int d3d_create_texture_sectioned(int bitmap_handle, int bitmap_type, tcache_slot_d3d *tslot, int sx, int sy, int fail_on_full)
882 {
883         ubyte flags;
884         bitmap *bmp;
885         int final_w, final_h;
886         int section_x, section_y;
887         int reload = 0;
888
889         // setup texture/bitmap flags
890         Assert(bitmap_type == TCACHE_TYPE_BITMAP_SECTION);
891         if(bitmap_type != TCACHE_TYPE_BITMAP_SECTION){
892                 bitmap_type = TCACHE_TYPE_BITMAP_SECTION;
893         }
894         flags = BMP_TEX_XPARENT;        
895                 
896         // lock the bitmap in the proper format
897         bmp = bm_lock(bitmap_handle, 16, flags);        
898         if ( bmp == NULL ) {
899                 mprintf(("Couldn't lock bitmap %d.\n", bitmap_handle ));
900                 return 0;
901         }       
902
903         // determine the width and height of this section
904         bm_get_section_size(bitmap_handle, sx, sy, &section_x, &section_y);     
905
906         // get final texture size as it will be allocated as a DD surface
907         d3d_tcache_get_adjusted_texture_size(section_x, section_y, &final_w, &final_h);
908
909         // if this tcache slot has no bitmap
910         if ( tslot->bitmap_id < 0) {                                    
911                 reload = 0;
912         }
913         // different bitmap altogether - determine if the new one can use the old one's slot
914         else if (tslot->bitmap_id != bitmap_handle)     {               
915                 if((final_w == tslot->w) && (final_h == tslot->h)){                     
916                         reload = 1;                     
917                 } else {                        
918                         reload = 0;
919                 }
920         }
921
922         // call the helper
923         int ret_val = d3d_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, reload, fail_on_full);
924
925         // unlock the bitmap
926         bm_unlock(bitmap_handle);
927
928         return ret_val;
929 }
930
931 extern int bm_get_cache_slot( int bitmap_id, int separate_ani_frames );
932 int d3d_tcache_set(int bitmap_id, int bitmap_type, float *u_scale, float *v_scale, int fail_on_full, int sx, int sy, int force )
933 {
934         bitmap *bmp = NULL;
935         int idx, s_idx; 
936         int ret_val = 1;
937
938         if ( bitmap_id < 0 )    {
939                 D3D_last_bitmap_id  = -1;
940                 return 0;
941         }
942
943         if ( D3D_last_detail != Detail.hardware_textures )      {
944                 D3D_last_detail = Detail.hardware_textures;
945                 d3d_tcache_flush();
946         }
947
948         //mprintf(( "Setting texture %d\n", bitmap_handle ));
949         if ( vram_full ) {
950                 return 0;
951         }
952
953         int n = bm_get_cache_slot( bitmap_id, 1 );
954         tcache_slot_d3d * t = &Textures[n];             
955         
956         if ( (D3D_last_bitmap_id == bitmap_id) && (D3D_last_bitmap_type==bitmap_type) && (t->bitmap_id == bitmap_id) && (D3D_last_section_x == sx) && (D3D_last_section_y == sy))       {
957                 t->used_this_frame++;
958                 
959                 // mark all children as used
960                 if(D3D_texture_sections){
961                         for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
962                                 for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
963                                         if(t->data_sections[idx][s_idx] != NULL){
964                                                 t->data_sections[idx][s_idx]->used_this_frame++;
965                                         }
966                                 }
967                         }
968                 }
969
970                 *u_scale = t->u_scale;
971                 *v_scale = t->v_scale;
972                 return 1;
973         }       
974
975         // if this is a sectioned bitmap
976         if(bitmap_type == TCACHE_TYPE_BITMAP_SECTION){          
977                 Assert((sx >= 0) && (sy >= 0) && (sx < MAX_BMAP_SECTIONS_X) && (sy < MAX_BMAP_SECTIONS_Y));
978                 if(!((sx >= 0) && (sy >= 0) && (sx < MAX_BMAP_SECTIONS_X) && (sy < MAX_BMAP_SECTIONS_Y))){
979                         return 0;
980                 }               
981
982                 ret_val = 1;
983
984                 // if the texture sections haven't been created yet
985                 if((t->bitmap_id < 0) || (t->bitmap_id != bitmap_id)){                                          
986                         // lock the bitmap in the proper format
987                         bmp = bm_lock(bitmap_id, 16, BMP_TEX_XPARENT);  
988                         bm_unlock(bitmap_id);                   
989                         
990                         // now lets do something for each texture                       
991                         for(idx=0; idx<bmp->sections.num_x; idx++){
992                                 for(s_idx=0; s_idx<bmp->sections.num_y; s_idx++){                                                                                                                                                               
993                                         // hmm. i'd rather we didn't have to do it this way...
994                                         if(!d3d_create_texture_sectioned(bitmap_id, bitmap_type, t->data_sections[idx][s_idx], idx, s_idx, fail_on_full)){
995                                                 ret_val = 0;
996                                         }
997
998                                         // not used this frame
999                                         t->data_sections[idx][s_idx]->used_this_frame = 0;
1000                                 }
1001                         }
1002
1003                         // zero out pretty much everything in the parent struct since he's just the root
1004                         t->bitmap_id = bitmap_id;                       
1005                         t->texture_handle = NULL;
1006                         t->time_created = t->data_sections[sx][sy]->time_created;
1007                         t->used_this_frame = 0;
1008                         t->vram_texture = NULL;
1009                         t->vram_texture_surface = NULL;
1010                 }               
1011
1012                 // argh. we failed to upload. free anything we can
1013                 if(!ret_val){
1014                         d3d_free_texture(t);
1015                 }
1016                 // swap in the texture we want                          
1017                 else {                  
1018                         t = t->data_sections[sx][sy];
1019                 }
1020         }
1021         // all other "normal" textures
1022         else if((bitmap_id < 0) || (bitmap_id != t->bitmap_id)){                
1023                 ret_val = d3d_create_texture( bitmap_id, bitmap_type, t, fail_on_full );                
1024         }                       
1025
1026         // everything went ok
1027         if(ret_val && (t->texture_handle != NULL) && !vram_full){
1028                 *u_scale = t->u_scale;
1029                 *v_scale = t->v_scale;
1030
1031                 d3d_SetRenderState(D3DRENDERSTATE_TEXTUREHANDLE, t->texture_handle );
1032                 
1033                 D3D_last_bitmap_id = t->bitmap_id;
1034                 D3D_last_bitmap_type = bitmap_type;
1035                 D3D_last_section_x = sx;
1036                 D3D_last_section_y = sy;
1037
1038                 t->used_this_frame++;           
1039         }
1040         // gah
1041         else {                  
1042                 return 0;
1043         }       
1044         
1045         return 1;
1046 }
1047
1048 int D3D_should_preload = 0;
1049
1050 void d3d_tcache_init(int use_sections)
1051 {
1052         int i, idx, s_idx;
1053
1054         D3D_should_preload = 0;
1055
1056         {
1057                 DDSCAPS ddsCaps;
1058                 DWORD dwFree, dwTotal;
1059
1060                 memset(&ddsCaps,0,sizeof(ddsCaps) );
1061                 ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1062                 HRESULT ddrval = lpDD->GetAvailableVidMem(&ddsCaps, &dwTotal, &dwFree);
1063                 if ( ddrval != DD_OK )  {
1064                         mprintf(( "GR_D3D_INIT: GetAvailableVidMem failed.\n" ));
1065                         dwFree = 0;
1066 //                      goto D3DError;
1067                 }
1068
1069                 D3D_texture_ram = dwFree;
1070
1071                 uint tmp_pl = os_config_read_uint( NULL, NOX("D3DPreloadTextures"), 255 );
1072
1073                 if ( tmp_pl == 0 )      {
1074                         D3D_should_preload = 0;
1075                 } else if ( tmp_pl == 1 )       {
1076                         D3D_should_preload = 1;
1077                 } else {
1078                         if ( D3D_texture_ram >= 6*1024*1024  )  {
1079                                 D3D_should_preload = 1;
1080                         } else {
1081                                 D3D_should_preload = 0;
1082                         }
1083                 }
1084
1085                 /*
1086                 int megs = dwFree / (1024*1024);                
1087                 uint tmp_val = os_config_read_uint( NULL, NOX("D3DTextureDivider"), 255 );
1088
1089                 if ( tmp_val == 0 )     {
1090                         // auto set
1091                         if ( megs <= 4 )        {
1092                                 D3D_texture_divider = 4;
1093                         } else if ( megs <=8 )  {
1094                                 D3D_texture_divider = 3;
1095                         } else if ( megs <=16 ) {
1096                                 D3D_texture_divider = 2;
1097                         } else {
1098                                 D3D_texture_divider = 1;
1099                         }
1100                 } else if ( tmp_val < 5 )       {
1101                         D3D_texture_divider = tmp_val;
1102                 } else {
1103                         // force to 4
1104                         D3D_texture_divider = 4;
1105                 }
1106                 */
1107
1108                 // setup texture divider
1109                 uint tmp_val = os_config_read_uint( NULL, NOX("D3DFast"), 1 );
1110                 D3D_texture_divider = 1;
1111                 if(tmp_val){
1112                         D3D_texture_divider = 4;
1113                 }                       
1114
1115 #ifndef NDEBUG
1116                 int megs = dwFree / (1024*1024);                
1117                 mprintf(( "TEXTURE RAM: %d bytes (%d MB) available, size divisor = %d\n", dwFree, megs, D3D_texture_divider ));
1118 #endif
1119         }
1120
1121         
1122         D3D_min_texture_width = (int)lpDevDesc->dwMinTextureWidth;
1123         D3D_max_texture_width = (int)lpDevDesc->dwMaxTextureWidth;
1124         D3D_min_texture_height = (int)lpDevDesc->dwMinTextureHeight;
1125         D3D_max_texture_height = (int)lpDevDesc->dwMaxTextureHeight;
1126
1127         // The following checks are needed because the PowerVR reports
1128         // it's texture caps as 0,0 up to 0,0.
1129         if ( D3D_min_texture_width < 16 )       {
1130                 D3D_min_texture_width = 16;
1131         }
1132         if ( D3D_min_texture_height < 16 )      {
1133                 D3D_min_texture_height = 16;
1134         }
1135         if ( D3D_max_texture_width < 16 )       {
1136                 mprintf(( "Driver claims to have a max texture width of %d.  Bashing to 256.\n(Is this a PowerVR?)\n", D3D_max_texture_width ));
1137                 D3D_max_texture_width = 256;                                    // Can we assume 256?
1138         }
1139
1140         if ( D3D_max_texture_height < 16 )      {
1141                 mprintf(( "Driver claims to have a max texture height of %d.  Bashing to 256.\n(Is this a PowerVR?)\n", D3D_max_texture_height ));
1142                 D3D_max_texture_height = 256;                                   // Can we assume 256?
1143         }
1144
1145         if (lpDevDesc->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY)   {
1146                 mprintf(( "Darn. Driver needs square textures.\n" ));
1147                 D3D_square_textures = 1;
1148         } else {
1149                 mprintf(( "Woohoo! Driver doesn't need square textures!\n" ));
1150                 D3D_square_textures = 0;
1151         }
1152
1153         if ( lpDevDesc->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2 )       {
1154                 mprintf(( "Textures must be power of 2.\n" ));
1155                 D3D_pow2_textures = 1;
1156         } else {
1157                 mprintf(( "Textures can be any size.\n" ));
1158                 D3D_pow2_textures = 0;
1159         }
1160
1161
1162         if ( !(DD_driver_caps.dwCaps2 & DDCAPS2_WIDESURFACES) ) {
1163                 if ( D3D_max_texture_width > gr_screen.max_w )  {
1164                         D3D_max_texture_width = gr_screen.max_w;
1165
1166                         if ( D3D_pow2_textures )        {
1167                                 for (i=0; i<16; i++ )   {
1168                                         if ( (D3D_max_texture_width>= (1<<i)) && (D3D_max_texture_width < (1<<(i+1))) ) {
1169                                                 D3D_max_texture_width = 1 << i;
1170                                                 break;
1171                                         }
1172                                 }
1173                         }
1174
1175                         if ( D3D_max_texture_height > D3D_max_texture_width )   {
1176                                 D3D_max_texture_height = D3D_max_texture_width;
1177                         }
1178
1179                         mprintf(( "Doesn't support wide surfaces. Bashing max down to %d\n", D3D_max_texture_width ));
1180                 }
1181         }
1182
1183         if ( !os_config_read_uint( NULL, NOX("D3DUseLargeTextures"), 0 ))       {
1184                 mprintf(( "No large texture flag specified, so using max of 256\n" ));
1185                 if ( D3D_max_texture_width > 256 )      {
1186                         D3D_max_texture_width = 256;
1187                 }
1188
1189                 if ( D3D_max_texture_height > 256 )     {
1190                         D3D_max_texture_height = 256;
1191                 }
1192         } else {
1193                 mprintf(( "Large textures enabled!\n" ));
1194         }
1195         
1196         Textures = (tcache_slot_d3d *)malloc(MAX_BITMAPS*sizeof(tcache_slot_d3d));
1197         if ( !Textures )        {
1198                 exit(1);
1199         }
1200
1201         if(use_sections){
1202                 Texture_sections = (tcache_slot_d3d*)malloc(MAX_BITMAPS * MAX_BMAP_SECTIONS_X * MAX_BMAP_SECTIONS_Y * sizeof(tcache_slot_d3d));
1203                 if(!Texture_sections){
1204                         exit(1);
1205                 }
1206                 memset(Texture_sections, 0, MAX_BITMAPS * MAX_BMAP_SECTIONS_X * MAX_BMAP_SECTIONS_Y * sizeof(tcache_slot_d3d));
1207         }
1208
1209         // Init the texture structures
1210         int section_count = 0;
1211         for( i=0; i<MAX_BITMAPS; i++ )  {
1212                 Textures[i].vram_texture = NULL;
1213                 Textures[i].vram_texture_surface = NULL;
1214                 Textures[i].texture_handle = NULL;
1215
1216                 Textures[i].bitmap_id = -1;
1217                 Textures[i].size = 0;
1218                 Textures[i].used_this_frame = 0; 
1219
1220                 Textures[i].parent = NULL;
1221
1222                 // allocate sections
1223                 if(use_sections){
1224                         for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
1225                                 for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
1226                                         Textures[i].data_sections[idx][s_idx] = &((tcache_slot_d3d*)Texture_sections)[section_count++];
1227                                         Textures[i].data_sections[idx][s_idx]->parent = &Textures[i];
1228                                         
1229                                         Textures[i].data_sections[idx][s_idx]->vram_texture = NULL;
1230                                         Textures[i].data_sections[idx][s_idx]->vram_texture_surface = NULL;
1231                                         Textures[i].data_sections[idx][s_idx]->texture_handle = NULL;
1232
1233                                         Textures[i].data_sections[idx][s_idx]->bitmap_id = -1;
1234                                         Textures[i].data_sections[idx][s_idx]->size = 0;
1235                                         Textures[i].data_sections[idx][s_idx]->used_this_frame = 0;
1236                                 }
1237                         }
1238                 } else {
1239                         for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
1240                                 for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
1241                                         Textures[i].data_sections[idx][s_idx] = NULL;                                   
1242                                 }
1243                         }
1244                 }
1245         }
1246
1247         D3D_texture_sections = use_sections;
1248
1249         D3D_last_detail = Detail.hardware_textures;
1250         D3D_last_bitmap_id = -1;
1251         D3D_last_bitmap_type = -1;
1252
1253         D3D_last_section_x = -1;
1254         D3D_last_section_y = -1;
1255
1256         D3D_textures_in = 0;
1257         D3D_textures_in_frame = 0;
1258
1259 }
1260
1261 void d3d_tcache_flush()
1262 {
1263         int i; 
1264
1265
1266         for( i=0; i<MAX_BITMAPS; i++ )  {
1267                 d3d_free_texture( &Textures[i] );               
1268         }
1269         if ( D3D_textures_in != 0 )     {
1270                 mprintf(( "WARNING: VRAM is at %d instead of zero after flushing!\n", D3D_textures_in ));
1271                 D3D_textures_in = 0;
1272         }
1273
1274         D3D_last_bitmap_id = -1;
1275         D3D_last_section_x = -1;
1276         D3D_last_section_y = -1;
1277 }
1278
1279 void d3d_tcache_cleanup()
1280 {
1281         d3d_tcache_flush();
1282         
1283         D3D_textures_in = 0;
1284         D3D_textures_in_frame = 0;
1285
1286         if ( Textures ) {
1287                 free(Textures);
1288                 Textures = NULL;
1289         }
1290
1291         if(Texture_sections != NULL){
1292                 free(Texture_sections);
1293                 Texture_sections = NULL;
1294         }
1295 }
1296
1297 void d3d_tcache_frame()
1298 {
1299         int idx, s_idx;
1300
1301         D3D_last_bitmap_id = -1;
1302         D3D_textures_in_frame = 0;
1303
1304         D3D_frame_count++;
1305
1306         int i;
1307         for( i=0; i<MAX_BITMAPS; i++ )  {
1308                 Textures[i].used_this_frame = 0; 
1309
1310                 // data sections
1311                 if(Textures[i].data_sections[0][0] != NULL){
1312                         Assert(D3D_texture_sections);
1313                         if(D3D_texture_sections){                               
1314                                 for(idx=0; idx<MAX_BMAP_SECTIONS_X; idx++){
1315                                         for(s_idx=0; s_idx<MAX_BMAP_SECTIONS_Y; s_idx++){
1316                                                 if(Textures[i].data_sections[idx][s_idx] != NULL){
1317                                                         Textures[i].data_sections[idx][s_idx]->used_this_frame = 0;
1318                                                 }
1319                                         }
1320                                 }
1321                         }
1322                 }
1323         }
1324
1325         if ( vram_full )        {
1326                 d3d_tcache_flush();
1327                 vram_full = 0;
1328         }
1329 }
1330
1331
1332 void gr_d3d_preload_init()
1333 {
1334         if ( gr_screen.mode != GR_DIRECT3D )    {
1335                 return;
1336         }
1337         d3d_tcache_flush();
1338 }
1339
1340 int gr_d3d_preload(int bitmap_num, int is_aabitmap)
1341 {
1342         if ( gr_screen.mode != GR_DIRECT3D )    {
1343                 return 0;
1344         }
1345
1346         if ( !D3D_should_preload )      {
1347                 return 0;
1348         }
1349
1350         float u_scale, v_scale;
1351
1352         int retval;
1353         
1354         if ( is_aabitmap )      {
1355                 retval = gr_tcache_set(bitmap_num, TCACHE_TYPE_AABITMAP, &u_scale, &v_scale, 1 );
1356         } else {
1357                 retval = gr_tcache_set(bitmap_num, TCACHE_TYPE_NORMAL, &u_scale, &v_scale, 1 );
1358         }
1359
1360         if ( !retval )  {
1361                 mprintf(("Texture upload failed!\n" ));
1362         }
1363
1364         return retval;
1365 }
1366
1367 // call this to safely fill in the texture shift and scale values for the specified texture type (Gr_t_*)
1368 void gr_d3d_get_tex_format(int alpha)
1369 {
1370         /*
1371         DDPIXELFORMAT *surface_desc;
1372         int s;  
1373         // RGB decoder
1374         unsigned long m;                
1375
1376         // get the proper texture format
1377         if(alpha){      
1378                 surface_desc = &AlphaTextureFormat;
1379         } else {        
1380                 surface_desc = &NonAlphaTextureFormat;
1381         }
1382
1383         // Determine the red, green and blue masks' shift and scale.
1384         for (s = 0, m = surface_desc->dwRBitMask; !(m & 1); s++, m >>= 1);
1385         Gr_t_red_shift = s;
1386         Gr_t_red_scale = 255 / (surface_desc->dwRBitMask >> s);
1387         for (s = 0, m = surface_desc->dwGBitMask; !(m & 1); s++, m >>= 1);
1388         Gr_t_green_shift = s;
1389         Gr_t_green_scale = 255 / (surface_desc->dwGBitMask >> s);
1390         for (s = 0, m = surface_desc->dwBBitMask; !(m & 1); s++, m >>= 1);
1391         Gr_t_blue_shift = s;
1392         Gr_t_blue_scale = 255 / (surface_desc->dwBBitMask >> s);
1393
1394         if ( surface_desc->dwFlags & DDPF_ALPHAPIXELS ) {
1395                 for (s = 0, m = surface_desc->dwRGBAlphaBitMask; !(m & 1); s++, m >>= 1);
1396                 Gr_t_alpha_shift = s;
1397                 Gr_t_alpha_scale = 255 / (surface_desc->dwRGBAlphaBitMask >> s);
1398         } else {
1399                 Gr_t_alpha_shift = 0;
1400                 Gr_t_alpha_scale = 256;
1401         }
1402         */
1403 }