1 //********************************************************************************************
2 //*
3 //*    This file is part of Egoboo.
4 //*
5 //*    Egoboo is free software: you can redistribute it and/or modify it
6 //*    under the terms of the GNU General Public License as published by
7 //*    the Free Software Foundation, either version 3 of the License, or
8 //*    (at your option) any later version.
9 //*
10 //*    Egoboo is distributed in the hope that it will be useful, but
11 //*    WITHOUT ANY WARRANTY; without even the implied warranty of
12 //*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 //*    General Public License for more details.
14 //*
15 //*    You should have received a copy of the GNU General Public License
16 //*    along with Egoboo.  If not, see <http://www.gnu.org/licenses/>.
17 //*
18 //********************************************************************************************
19 
20 /// @file texture.c
21 /// @brief Implementation of code for controlling object texturing
22 /// @details
23 
24 #include "texture.h"
25 
26 #include "egoboo_fileutil.h"
27 #include "egoboo_math.inl"
28 
29 //--------------------------------------------------------------------------------------------
30 //--------------------------------------------------------------------------------------------
31 
32 INSTANTIATE_LIST( ACCESS_TYPE_NONE, oglx_texture_t, TxTexture, TX_TEXTURE_COUNT );
33 
34 //--------------------------------------------------------------------------------------------
35 //--------------------------------------------------------------------------------------------
TxTexture_clear_data()36 void TxTexture_clear_data()
37 {
38     /// @details BB@> reset the free texture list. Start at TX_LAST so that the global textures/icons are
39     ///     can't be allocated by mistake
40 
41     int cnt, tnc;
42 
43     for ( cnt = TX_LAST, tnc = 0; cnt < TX_TEXTURE_COUNT; cnt++, tnc++ )
44     {
45         TxTexture.free_ref[tnc] = cnt;
46     }
47     TxTexture.free_count = tnc;
48 }
49 
50 //--------------------------------------------------------------------------------------------
TxTexture_init_all()51 void TxTexture_init_all()
52 {
53     /// @details ZZ@> This function clears out all of the textures
54 
55     TX_REF cnt;
56 
57     for ( cnt = 0; cnt < TX_TEXTURE_COUNT; cnt++ )
58     {
59         oglx_texture_ctor( TxTexture.lst + cnt );
60     }
61 
62     TxTexture_clear_data();
63 }
64 
65 //--------------------------------------------------------------------------------------------
TxTexture_release_all()66 void TxTexture_release_all()
67 {
68     /// @details ZZ@> This function releases all of the textures
69 
70     TX_REF cnt;
71 
72     for ( cnt = 0; cnt < TX_TEXTURE_COUNT; cnt++ )
73     {
74         oglx_texture_Release( TxTexture.lst + cnt );
75     }
76 
77     TxTexture_clear_data();
78 }
79 
80 //--------------------------------------------------------------------------------------------
TxTexture_delete_all()81 void TxTexture_delete_all()
82 {
83     /// @details ZZ@> This function clears out all of the textures
84 
85     TX_REF cnt;
86 
87     for ( cnt = 0; cnt < TX_TEXTURE_COUNT; cnt++ )
88     {
89         oglx_texture_dtor( TxTexture.lst + cnt );
90     }
91 
92     TxTexture_clear_data();
93 }
94 
95 //--------------------------------------------------------------------------------------------
TxTexture_reload_all()96 void TxTexture_reload_all()
97 {
98     /// @details ZZ@> This function re-loads all the current textures back into
99     ///               OpenGL texture memory using the cached SDL surfaces
100 
101     TX_REF cnt;
102 
103     for ( cnt = 0; cnt < TX_TEXTURE_COUNT; cnt++ )
104     {
105         oglx_texture_t * ptex = TxTexture.lst + cnt;
106 
107         if ( ptex->valid )
108         {
109             oglx_texture_Convert( ptex, ptex->surface, INVALID_KEY );
110         }
111     }
112 }
113 
114 //--------------------------------------------------------------------------------------------
TxTexture_get_free(const TX_REF itex)115 TX_REF TxTexture_get_free( const TX_REF itex )
116 {
117     TX_REF retval = ( TX_REF )INVALID_TX_TEXTURE;
118 
119     if ( itex >= 0 && itex < TX_LAST )
120     {
121         retval = itex;
122         oglx_texture_Release( TxTexture.lst + itex );
123     }
124     else if ( itex < 0 || itex >= TX_TEXTURE_COUNT )
125     {
126         if ( TxTexture.free_count > 0 )
127         {
128             TxTexture.free_count--;
129             TxTexture.update_guid++;
130 
131             retval = TxTexture.free_ref[TxTexture.free_count];
132         }
133         else
134         {
135             retval = ( TX_REF )INVALID_TX_TEXTURE;
136         }
137     }
138     else
139     {
140         int i;
141 
142         // grab the specified index
143         oglx_texture_Release( TxTexture.lst + ( TX_REF )itex );
144 
145         // if this index is on the free stack, remove it
146         for ( i = 0; i < TxTexture.free_count; i++ )
147         {
148             if ( TxTexture.free_ref[i] == itex )
149             {
150                 if ( TxTexture.free_count > 0 )
151                 {
152                     TxTexture.free_count--;
153                     TxTexture.update_guid++;
154 
155                     SWAP( size_t, TxTexture.free_ref[i], TxTexture.free_ref[TxTexture.free_count] );
156                 }
157                 break;
158             }
159         }
160     }
161 
162     return retval;
163 }
164 
165 //--------------------------------------------------------------------------------------------
TxTexture_free_one(const TX_REF itex)166 bool_t TxTexture_free_one( const TX_REF itex )
167 {
168     if ( itex < 0 || itex >= TX_TEXTURE_COUNT ) return bfalse;
169 
170     // release the texture
171     oglx_texture_Release( TxTexture.lst + itex );
172 
173 #if defined(_DEBUG)
174     {
175         int cnt;
176         // determine whether this texture is already in the list of free textures
177         // that is an error
178         for ( cnt = 0; cnt < TxTexture.free_count; cnt++ )
179         {
180             if ( itex == TxTexture.free_ref[cnt] ) return bfalse;
181         }
182     }
183 #endif
184 
185     if ( TxTexture.free_count >= TX_TEXTURE_COUNT )
186         return bfalse;
187 
188     // do not put anything below TX_LAST back onto the SDL_free stack
189     if ( itex >= TX_LAST )
190     {
191         TxTexture.free_ref[TxTexture.free_count] = REF_TO_INT( itex );
192 
193         TxTexture.free_count++;
194         TxTexture.update_guid++;
195     }
196 
197     return btrue;
198 }
199 
200 //--------------------------------------------------------------------------------------------
TxTexture_load_one_vfs(const char * filename,const TX_REF itex_src,Uint32 key)201 TX_REF TxTexture_load_one_vfs( const char *filename, const TX_REF itex_src, Uint32 key )
202 {
203     /// @details BB@> load a texture into TxTexture.
204     ///     If INVALID_TX_TEXTURE == itex, then we just get the next free index
205 
206     TX_REF retval;
207 
208     // get a texture index.
209     retval = TxTexture_get_free( itex_src );
210 
211     // handle an error
212     if ( retval >= 0 && retval < TX_TEXTURE_COUNT )
213     {
214         Uint32 txid = ego_texture_load_vfs( TxTexture.lst + retval, filename, key );
215         if ( INVALID_GL_ID == txid )
216         {
217             TxTexture_free_one( retval );
218             retval = INVALID_TX_TEXTURE;
219         }
220     }
221 
222     return retval;
223 }
224 
225 //--------------------------------------------------------------------------------------------
TxTexture_get_ptr(const TX_REF itex)226 oglx_texture_t * TxTexture_get_ptr( const TX_REF itex )
227 {
228     oglx_texture_t * ptex;
229 
230     if ( itex < 0 || itex >= TX_TEXTURE_COUNT ) return NULL;
231     ptex = TxTexture.lst + itex;
232 
233     if ( !oglx_texture_Valid( ptex ) )
234         return NULL;
235 
236     return ptex;
237 }
238