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