]> icculus.org git repositories - btb/d2x.git/blob - main/texmerge.c
move PhysicsFS initialisation, search path setup and argument reading to physfsx.h
[btb/d2x.git] / main / texmerge.c
1 /* $Id: texmerge.c,v 1.5 2005-07-30 01:50:17 chris Exp $ */
2 /*
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
13 */
14
15 /*
16  *
17  * Routines to cache merged textures.
18  *
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include <conf.h>
23 #endif
24
25 #include <stdio.h>
26
27 #include "gr.h"
28 #include "error.h"
29 #include "game.h"
30 #include "textures.h"
31 #include "mono.h"
32 #include "rle.h"
33 #include "piggy.h"
34
35 #ifdef OGL
36 #include "ogl_init.h"
37 #define MAX_NUM_CACHE_BITMAPS 200
38 #else
39 #define MAX_NUM_CACHE_BITMAPS 50
40 #endif
41
42 //static grs_bitmap * cache_bitmaps[MAX_NUM_CACHE_BITMAPS];                     
43
44 typedef struct  {
45         grs_bitmap * bitmap;
46         grs_bitmap * bottom_bmp;
47         grs_bitmap * top_bmp;
48         int             orient;
49         int             last_frame_used;
50 } TEXTURE_CACHE;
51
52 static TEXTURE_CACHE Cache[MAX_NUM_CACHE_BITMAPS];
53
54 static int num_cache_entries = 0;
55
56 static int cache_hits = 0;
57 static int cache_misses = 0;
58
59 void texmerge_close();
60 void merge_textures_super_xparent(int type, grs_bitmap *bottom_bmp, grs_bitmap *top_bmp,
61                                                                                          ubyte *dest_data);
62 void merge_textures_new(int type, grs_bitmap *bottom_bmp, grs_bitmap *top_bmp,
63                                                                 ubyte *dest_data);
64
65 //----------------------------------------------------------------------
66
67 int texmerge_init(int num_cached_textures)
68 {
69         int i;
70
71         if ( num_cached_textures <= MAX_NUM_CACHE_BITMAPS )
72                 num_cache_entries = num_cached_textures;
73         else
74                 num_cache_entries = MAX_NUM_CACHE_BITMAPS;
75         
76         for (i=0; i<num_cache_entries; i++ )    {
77                         // Make temp tmap for use when combining
78                 Cache[i].bitmap = gr_create_bitmap( 64, 64 );
79
80                 //if (get_selector( Cache[i].bitmap->bm_data, 64*64,  &Cache[i].bitmap->bm_selector))
81                 //      Error( "ERROR ALLOCATING CACHE BITMAP'S SELECTORS!!!!" );
82
83                 Cache[i].last_frame_used = -1;
84                 Cache[i].top_bmp = NULL;
85                 Cache[i].bottom_bmp = NULL;
86                 Cache[i].orient = -1;
87         }
88         atexit( texmerge_close );
89
90         return 1;
91 }
92
93 void texmerge_flush()
94 {
95         int i;
96
97         for (i=0; i<num_cache_entries; i++ )    {
98                 Cache[i].last_frame_used = -1;
99                 Cache[i].top_bmp = NULL;
100                 Cache[i].bottom_bmp = NULL;
101                 Cache[i].orient = -1;
102         }
103 }
104
105
106 //-------------------------------------------------------------------------
107 void texmerge_close()
108 {
109         int i;
110
111         for (i=0; i<num_cache_entries; i++ )    {
112                 gr_free_bitmap( Cache[i].bitmap );
113                 Cache[i].bitmap = NULL;
114         }
115 }
116
117 //--unused-- int info_printed = 0;
118
119 grs_bitmap * texmerge_get_cached_bitmap( int tmap_bottom, int tmap_top )
120 {
121         grs_bitmap *bitmap_top, *bitmap_bottom;
122         int i, orient;
123         int lowest_frame_count;
124         int least_recently_used;
125
126 //      if ( ((FrameCount % 1000)==0) && ((cache_hits+cache_misses)>0) && (!info_printed) )     {
127 //              mprintf( 0, "Texmap caching:  %d hits, %d misses. (Missed=%d%%)\n", cache_hits, cache_misses, (cache_misses*100)/(cache_hits+cache_misses)  );
128 //              info_printed = 1;
129 //      } else {
130 //              info_printed = 0;
131 //      }
132
133         bitmap_top = &GameBitmaps[Textures[tmap_top&0x3FFF].index];
134         bitmap_bottom = &GameBitmaps[Textures[tmap_bottom].index];
135         
136         orient = ((tmap_top&0xC000)>>14) & 3;
137
138         least_recently_used = 0;
139         lowest_frame_count = Cache[0].last_frame_used;
140         
141         for (i=0; i<num_cache_entries; i++ )    {
142                 if ( (Cache[i].last_frame_used > -1) && (Cache[i].top_bmp==bitmap_top) && (Cache[i].bottom_bmp==bitmap_bottom) && (Cache[i].orient==orient ))   {
143                         cache_hits++;
144                         Cache[i].last_frame_used = FrameCount;
145                         return Cache[i].bitmap;
146                 }       
147                 if ( Cache[i].last_frame_used < lowest_frame_count )    {
148                         lowest_frame_count = Cache[i].last_frame_used;
149                         least_recently_used = i;
150                 }
151         }
152
153         //---- Page out the LRU bitmap;
154         cache_misses++;
155
156         // Make sure the bitmaps are paged in...
157 #ifdef PIGGY_USE_PAGING
158         piggy_page_flushed = 0;
159
160         PIGGY_PAGE_IN(Textures[tmap_top&0x3FFF]);
161         PIGGY_PAGE_IN(Textures[tmap_bottom]);
162         if (piggy_page_flushed) {
163                 // If cache got flushed, re-read 'em.
164                 piggy_page_flushed = 0;
165                 PIGGY_PAGE_IN(Textures[tmap_top&0x3FFF]);
166                 PIGGY_PAGE_IN(Textures[tmap_bottom]);
167         }
168         Assert( piggy_page_flushed == 0 );
169 #endif
170
171 #ifdef OGL
172         ogl_freebmtexture(Cache[least_recently_used].bitmap);
173 #endif
174
175
176         if (bitmap_top->bm_flags & BM_FLAG_SUPER_TRANSPARENT)   {
177                 merge_textures_super_xparent( orient, bitmap_bottom, bitmap_top, Cache[least_recently_used].bitmap->bm_data );
178                 Cache[least_recently_used].bitmap->bm_flags = BM_FLAG_TRANSPARENT;
179                 Cache[least_recently_used].bitmap->avg_color = bitmap_top->avg_color;
180         } else  {
181                 merge_textures_new( orient, bitmap_bottom, bitmap_top, Cache[least_recently_used].bitmap->bm_data );
182                 Cache[least_recently_used].bitmap->bm_flags = bitmap_bottom->bm_flags & (~BM_FLAG_RLE);
183                 Cache[least_recently_used].bitmap->avg_color = bitmap_bottom->avg_color;
184         }
185
186         Cache[least_recently_used].top_bmp = bitmap_top;
187         Cache[least_recently_used].bottom_bmp = bitmap_bottom;
188         Cache[least_recently_used].last_frame_used = FrameCount;
189         Cache[least_recently_used].orient = orient;
190
191         return Cache[least_recently_used].bitmap;
192 }
193
194 void merge_textures_new( int type, grs_bitmap * bottom_bmp, grs_bitmap * top_bmp, ubyte * dest_data )
195 {
196         ubyte * top_data, *bottom_data;
197
198         if ( top_bmp->bm_flags & BM_FLAG_RLE )
199                 top_bmp = rle_expand_texture(top_bmp);
200
201         if ( bottom_bmp->bm_flags & BM_FLAG_RLE )
202                 bottom_bmp = rle_expand_texture(bottom_bmp);
203
204 //      Assert( bottom_bmp != top_bmp );
205
206         top_data = top_bmp->bm_data;
207         bottom_data = bottom_bmp->bm_data;
208
209 //      Assert( bottom_data != top_data );
210
211         // mprintf( 0, "Type=%d\n", type );
212
213         switch( type )  {
214         case 0:
215                 // Normal
216
217                 gr_merge_textures( bottom_data, top_data, dest_data );
218                 break;
219         case 1:
220                 gr_merge_textures_1( bottom_data, top_data, dest_data );
221                 break;
222         case 2:
223                 gr_merge_textures_2( bottom_data, top_data, dest_data );
224                 break;
225         case 3:
226                 gr_merge_textures_3( bottom_data, top_data, dest_data );
227                 break;
228         }
229 }
230
231 void merge_textures_super_xparent( int type, grs_bitmap * bottom_bmp, grs_bitmap * top_bmp, ubyte * dest_data )
232 {
233         ubyte c;
234         int x,y;
235
236         ubyte * top_data, *bottom_data;
237
238         if ( top_bmp->bm_flags & BM_FLAG_RLE )
239                 top_bmp = rle_expand_texture(top_bmp);
240
241         if ( bottom_bmp->bm_flags & BM_FLAG_RLE )
242                 bottom_bmp = rle_expand_texture(bottom_bmp);
243
244 //      Assert( bottom_bmp != top_bmp );
245
246         top_data = top_bmp->bm_data;
247         bottom_data = bottom_bmp->bm_data;
248
249 //      Assert( bottom_data != top_data );
250
251         //mprintf( 0, "SuperX remapping type=%d\n", type );
252         //Int3();
253          
254         switch( type )  {
255                 case 0:
256                         // Normal
257                         for (y=0; y<64; y++ )
258                                 for (x=0; x<64; x++ )   {
259                                         c = top_data[ 64*y+x ];         
260                                         if (c==TRANSPARENCY_COLOR)
261                                                 c = bottom_data[ 64*y+x ];
262                                         else if (c==254)
263                                                 c = TRANSPARENCY_COLOR;
264                                         *dest_data++ = c;
265                                 }
266                         break;
267                 case 1:
268                         // 
269                         for (y=0; y<64; y++ )
270                                 for (x=0; x<64; x++ )   {
271                                         c = top_data[ 64*x+(63-y) ];            
272                                         if (c==TRANSPARENCY_COLOR)
273                                                 c = bottom_data[ 64*y+x ];
274                                         else if (c==254)
275                                                 c = TRANSPARENCY_COLOR;
276                                         *dest_data++ = c;
277                                 }
278                         break;
279                 case 2:
280                         // Normal
281                         for (y=0; y<64; y++ )
282                                 for (x=0; x<64; x++ )   {
283                                         c = top_data[ 64*(63-y)+(63-x) ];
284                                         if (c==TRANSPARENCY_COLOR)
285                                                 c = bottom_data[ 64*y+x ];
286                                         else if (c==254)
287                                                 c = TRANSPARENCY_COLOR;
288                                         *dest_data++ = c;
289                                 }
290                         break;
291                 case 3:
292                         // Normal
293                         for (y=0; y<64; y++ )
294                                 for (x=0; x<64; x++ )   {
295                                         c = top_data[ 64*(63-x)+y  ];
296                                         if (c==TRANSPARENCY_COLOR)
297                                                 c = bottom_data[ 64*y+x ];
298                                         else if (c==254)
299                                                 c = TRANSPARENCY_COLOR;
300                                         *dest_data++ = c;
301                                 }
302                         break;
303         }
304 }