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