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