1 | /********************************************************************** <BR>
|
---|
2 | This file is part of Crack dot Com's free source code release of
|
---|
3 | Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
|
---|
4 | information about compiling & licensing issues visit this URL</a>
|
---|
5 | <PRE> If that doesn't help, contact Jonathan Clark at
|
---|
6 | golgotha_source@usa.net (Subject should have "GOLG" in it)
|
---|
7 | ***********************************************************************/
|
---|
8 |
|
---|
9 | #include "tmanage.hh"
|
---|
10 | #include "memory/malloc.hh"
|
---|
11 | #include "error/error.hh"
|
---|
12 | #include "checksum/checksum.hh"
|
---|
13 | #include "image/color.hh"
|
---|
14 | #include "string/str_checksum.hh"
|
---|
15 | #include "error/alert.hh"
|
---|
16 | #include "time/profile.hh"
|
---|
17 | #include "string/string.hh"
|
---|
18 | #include "status/status.hh"
|
---|
19 | #include "file/ram_file.hh"
|
---|
20 | #include "tex_cache.hh"
|
---|
21 | #include "file/file.hh"
|
---|
22 | #include "search.hh"
|
---|
23 | #include "r1_res.hh"
|
---|
24 | #include "image/image.hh"
|
---|
25 | #include "image/context.hh"
|
---|
26 | #include "time/profile.hh"
|
---|
27 |
|
---|
28 | i4_profile_class pf_register_texture("register_texture");
|
---|
29 |
|
---|
30 | w32 R1_CHROMA_COLOR = (254<<16) | (2<<8) | (166);
|
---|
31 |
|
---|
32 | i4_profile_class pf_get_texture("tmanage get texture");
|
---|
33 |
|
---|
34 | r1_texture_manager_class *r1_texture_manager=0;
|
---|
35 |
|
---|
36 | r1_texture_manager_class::r1_texture_manager_class(const i4_pal *pal)
|
---|
37 | : pal(pal),
|
---|
38 | registered_tnames(0,128)
|
---|
39 | {
|
---|
40 | textures_loaded=i4_F;
|
---|
41 | square_textures = i4_F;
|
---|
42 | }
|
---|
43 |
|
---|
44 | void r1_texture_manager_class::init()
|
---|
45 | {
|
---|
46 | texture_load_toggle = i4_T;
|
---|
47 | texture_resolution_changed = i4_F;
|
---|
48 | textures_loaded=i4_F;
|
---|
49 |
|
---|
50 | frame_count = 0;
|
---|
51 | entries = 0;
|
---|
52 | tanims = 0;
|
---|
53 |
|
---|
54 | total_tanims = 0;
|
---|
55 | total_textures = 0;
|
---|
56 |
|
---|
57 | registered_tnames.clear();
|
---|
58 | }
|
---|
59 |
|
---|
60 | char *r1_texture_manager_class::get_texture_name(r1_texture_handle handle)
|
---|
61 | {
|
---|
62 | if (handle<registered_tnames.size())
|
---|
63 | return registered_tnames[handle].name;
|
---|
64 | else
|
---|
65 | return "invalid";
|
---|
66 | }
|
---|
67 |
|
---|
68 |
|
---|
69 | void r1_texture_manager_class::uninit()
|
---|
70 | {
|
---|
71 | sw32 i,j;
|
---|
72 |
|
---|
73 | for (i=1; i<total_textures; i++)
|
---|
74 | {
|
---|
75 | for (j=0; j<R1_MAX_MIP_LEVELS; j++)
|
---|
76 | {
|
---|
77 | r1_miplevel_t *m = (*entries)[i].mipmaps[j];
|
---|
78 | if (m)
|
---|
79 | {
|
---|
80 | if(m->vram_handle)
|
---|
81 | {
|
---|
82 | free_mip(m->vram_handle);
|
---|
83 | m->vram_handle = 0;
|
---|
84 | }
|
---|
85 | delete m;
|
---|
86 | m = 0;
|
---|
87 | }
|
---|
88 | }
|
---|
89 | // delete (*entries)[i];
|
---|
90 | }
|
---|
91 |
|
---|
92 | if (entries)
|
---|
93 | {
|
---|
94 | delete entries;
|
---|
95 | entries = 0;
|
---|
96 | }
|
---|
97 |
|
---|
98 | registered_tnames.uninit();
|
---|
99 |
|
---|
100 | texture_load_toggle = i4_T;
|
---|
101 | texture_resolution_changed=i4_F;
|
---|
102 |
|
---|
103 | frame_count = 0;
|
---|
104 | tanims = 0;
|
---|
105 |
|
---|
106 | total_tanims = 0;
|
---|
107 | total_textures = 0;
|
---|
108 | textures_loaded = i4_F;
|
---|
109 | }
|
---|
110 |
|
---|
111 | void r1_texture_manager_class::reset()
|
---|
112 | {
|
---|
113 | uninit();
|
---|
114 | init();
|
---|
115 | }
|
---|
116 |
|
---|
117 | int entry_compare(const r1_texture_entry_struct *a, const r1_texture_entry_struct *b)
|
---|
118 | {
|
---|
119 | if (a->id<b->id)
|
---|
120 | return -1;
|
---|
121 | else if (a->id>b->id)
|
---|
122 | return 1;
|
---|
123 | else return 0;
|
---|
124 | }
|
---|
125 |
|
---|
126 | r1_texture_handle r1_texture_manager_class::find_texture(w32 id)
|
---|
127 | {
|
---|
128 | sw32 lo=1,hi=total_textures-1,mid;
|
---|
129 |
|
---|
130 | if (!entries)
|
---|
131 | return 0;
|
---|
132 |
|
---|
133 | r1_texture_entry_struct search_entry;
|
---|
134 | search_entry.id = id;
|
---|
135 |
|
---|
136 | sw32 location = entries->binary_search(&search_entry,entry_compare);
|
---|
137 |
|
---|
138 | if (location==-1)
|
---|
139 | return 0;
|
---|
140 |
|
---|
141 | return location;
|
---|
142 | }
|
---|
143 |
|
---|
144 |
|
---|
145 | void r1_texture_manager_class::matchup_textures()
|
---|
146 | {
|
---|
147 | sw32 i;
|
---|
148 | for (i=0; i<registered_tnames.size(); i++)
|
---|
149 | {
|
---|
150 | r1_texture_handle h = find_texture(registered_tnames[i].id);
|
---|
151 |
|
---|
152 | if (h)
|
---|
153 | registered_tnames[i].handle = h;
|
---|
154 | else
|
---|
155 | {
|
---|
156 | registered_tnames[i].handle = 0;
|
---|
157 | i4_warning("Texture matchup failed: %s",registered_tnames[i].name);
|
---|
158 | }
|
---|
159 | }
|
---|
160 |
|
---|
161 |
|
---|
162 | }
|
---|
163 |
|
---|
164 | int name_compare(const r1_texture_matchup_struct *a, const r1_texture_matchup_struct *b)
|
---|
165 | {
|
---|
166 | return strcmp(a->name, b->name);
|
---|
167 | }
|
---|
168 |
|
---|
169 |
|
---|
170 | r1_texture_handle r1_texture_manager_class::register_texture(const i4_const_str &tname,
|
---|
171 | const i4_const_str &error_string,
|
---|
172 | i4_bool *has_been_loaded)
|
---|
173 | {
|
---|
174 | pf_register_texture.start();
|
---|
175 |
|
---|
176 | if (textures_loaded)
|
---|
177 | i4_error("textures already loaded");
|
---|
178 |
|
---|
179 | int found = -1;
|
---|
180 |
|
---|
181 |
|
---|
182 | r1_texture_matchup_struct t;
|
---|
183 | i4_os_string(tname, t.name, 128);
|
---|
184 | t.id = r1_get_texture_id(tname);
|
---|
185 | t.handle = 0;
|
---|
186 | t.left = -1;
|
---|
187 | t.right = -1;
|
---|
188 |
|
---|
189 | if (has_been_loaded)
|
---|
190 | *has_been_loaded=0;
|
---|
191 |
|
---|
192 | // search the tree for the name
|
---|
193 | if (registered_tnames.size())
|
---|
194 | {
|
---|
195 | int root=0, parent=-1;
|
---|
196 | while (found<0)
|
---|
197 | {
|
---|
198 | parent=root;
|
---|
199 |
|
---|
200 | int res=strcmp(registered_tnames[root].name, t.name);
|
---|
201 | if (res==0)
|
---|
202 | {
|
---|
203 | if (has_been_loaded)
|
---|
204 | *has_been_loaded=1;
|
---|
205 | found = root;
|
---|
206 | }
|
---|
207 | else if (res<0)
|
---|
208 | root=registered_tnames[root].left;
|
---|
209 | else
|
---|
210 | root=registered_tnames[root].right;
|
---|
211 |
|
---|
212 | if (root==-1)
|
---|
213 | {
|
---|
214 | if (res<0)
|
---|
215 | found = registered_tnames[parent].left=registered_tnames.add(t);
|
---|
216 | else
|
---|
217 | found = registered_tnames[parent].right=registered_tnames.add(t);
|
---|
218 | }
|
---|
219 | }
|
---|
220 | }
|
---|
221 | else
|
---|
222 | found=registered_tnames.add(t);
|
---|
223 |
|
---|
224 | pf_register_texture.stop();
|
---|
225 | return found;
|
---|
226 | }
|
---|
227 |
|
---|
228 | int w32_compare(const w32 *a, const w32 *b)
|
---|
229 | {
|
---|
230 | if (*a < *b)
|
---|
231 | return -1;
|
---|
232 | else
|
---|
233 | if (*a > *b)
|
---|
234 | return 1;
|
---|
235 | else
|
---|
236 | return 0;
|
---|
237 | }
|
---|
238 |
|
---|
239 | w32 r1_get_file_id(const i4_const_str &fname)
|
---|
240 | {
|
---|
241 | int x;
|
---|
242 | char st[30], *s;
|
---|
243 | s=st;
|
---|
244 |
|
---|
245 | i4_const_str::iterator l=fname.begin();
|
---|
246 | while (l!=fname.end() && l.get().ascii_value()!='.')
|
---|
247 | {
|
---|
248 | *(s++)=l.get().ascii_value();
|
---|
249 | ++l;
|
---|
250 | }
|
---|
251 |
|
---|
252 | *s=0;
|
---|
253 |
|
---|
254 | if (sscanf(st,"%x",&x))
|
---|
255 | return x;
|
---|
256 | else return 0;
|
---|
257 | }
|
---|
258 |
|
---|
259 | void r1_texture_manager_class::toggle_texture_loading()
|
---|
260 | {
|
---|
261 | texture_load_toggle = (i4_bool)(!texture_load_toggle);
|
---|
262 | }
|
---|
263 |
|
---|
264 | r1_miplevel_t *r1_texture_manager_class::get_texture(r1_texture_handle _handle,
|
---|
265 | w32 frame_counter,
|
---|
266 | sw32 desired_width,
|
---|
267 | sw32 &ret_w, sw32 &ret_h)
|
---|
268 | {
|
---|
269 | pf_get_texture.start();
|
---|
270 |
|
---|
271 | if (desired_width > max_texture_dimention)
|
---|
272 | desired_width = max_texture_dimention;
|
---|
273 |
|
---|
274 | r1_texture_entry_struct *e;
|
---|
275 |
|
---|
276 | r1_texture_handle handle = registered_tnames[_handle].handle;
|
---|
277 | if (handle==0)
|
---|
278 | i4_error("get_texture called with invalid handle");
|
---|
279 |
|
---|
280 | if (handle>=total_textures)
|
---|
281 | i4_error("asking for bad texture");
|
---|
282 |
|
---|
283 | if (handle<0) // this is an animation
|
---|
284 | {
|
---|
285 | r1_texture_animation_entry_struct *ta=tanims+(-handle-1);
|
---|
286 | handle=ta->frames[frame_counter%ta->total_frames];
|
---|
287 | if (!handle)
|
---|
288 | {
|
---|
289 | pf_get_texture.stop();
|
---|
290 | return 0;
|
---|
291 | }
|
---|
292 | }
|
---|
293 |
|
---|
294 | e = &(*entries)[handle];
|
---|
295 |
|
---|
296 | sw32 i = 0;
|
---|
297 | sw32 highest_resident = -1;
|
---|
298 | sw32 need_to_use = 0;
|
---|
299 |
|
---|
300 | r1_miplevel_t *t = 0;
|
---|
301 |
|
---|
302 | //find the highest resident mip. can be precalculated and updated ?
|
---|
303 | for (i=0; i<R1_MAX_MIP_LEVELS; i++)
|
---|
304 | {
|
---|
305 | t = e->mipmaps[i];
|
---|
306 |
|
---|
307 | if (t)
|
---|
308 | {
|
---|
309 | if (t->width >= desired_width)
|
---|
310 | need_to_use = i;
|
---|
311 |
|
---|
312 | if (t->vram_handle)
|
---|
313 | {
|
---|
314 | if (t->width < desired_width)
|
---|
315 | {
|
---|
316 | //if there were no more higher than this,
|
---|
317 | //this is the best we can do
|
---|
318 | if (highest_resident==-1)
|
---|
319 | highest_resident = i;
|
---|
320 | break;
|
---|
321 | }
|
---|
322 | else
|
---|
323 | highest_resident = i;
|
---|
324 | }
|
---|
325 | }
|
---|
326 | else
|
---|
327 | {
|
---|
328 | break;
|
---|
329 | }
|
---|
330 | }
|
---|
331 |
|
---|
332 | if (highest_resident==-1)
|
---|
333 | {
|
---|
334 | i4_warning("No textures resident for handle %d", handle);
|
---|
335 | return 0;
|
---|
336 | }
|
---|
337 |
|
---|
338 | r1_miplevel_t *return_mip = e->mipmaps[highest_resident];
|
---|
339 |
|
---|
340 | if (!return_mip)
|
---|
341 | i4_error("catastophic error - r1_texture_manager_class::return_mip is 0");
|
---|
342 |
|
---|
343 | if (!return_mip->vram_handle)
|
---|
344 | i4_warning("returned a mip w/no vram handle");
|
---|
345 |
|
---|
346 | //this is to prevent the load below from deleting this miplevel from vram
|
---|
347 | sw32 old_last_frame = return_mip->last_frame_used;
|
---|
348 | return_mip->last_frame_used = frame_count;
|
---|
349 |
|
---|
350 | //loading information
|
---|
351 | r1_mip_load_info load_info;
|
---|
352 |
|
---|
353 | //i4_warning("texture loading is OFF");
|
---|
354 | if (texture_load_toggle && (highest_resident != need_to_use) && e->mipmaps[need_to_use])
|
---|
355 | {
|
---|
356 | load_info.src_file = 0;
|
---|
357 | load_info.dest_mip = e->mipmaps[need_to_use];
|
---|
358 | //should be asynchronous
|
---|
359 |
|
---|
360 | //prevents from trying to load this same mip level twice at the same time
|
---|
361 | if (!(load_info.dest_mip->flags & R1_MIPLEVEL_IS_LOADING))
|
---|
362 | {
|
---|
363 | //if there is no room for this mip, load up as high a level as possible
|
---|
364 | while (!async_mip_load(&load_info))
|
---|
365 | {
|
---|
366 | if (load_info.error==R1_MIP_LOAD_NO_ROOM)
|
---|
367 | {
|
---|
368 | //try to load a lower res
|
---|
369 | need_to_use++;
|
---|
370 | if (need_to_use==highest_resident) break;
|
---|
371 | if (!e->mipmaps[need_to_use]) break;
|
---|
372 | if (e->mipmaps[need_to_use]->flags & R1_MIPLEVEL_IS_LOADING) break;
|
---|
373 | load_info.dest_mip = e->mipmaps[need_to_use];
|
---|
374 | }
|
---|
375 | else
|
---|
376 | break;
|
---|
377 | }
|
---|
378 | }
|
---|
379 | //else
|
---|
380 | //{
|
---|
381 | // i4_warning("texture still loading, wont queue");
|
---|
382 | //}
|
---|
383 | }
|
---|
384 |
|
---|
385 | pf_get_texture.stop();
|
---|
386 |
|
---|
387 | //store the old information back.
|
---|
388 | return_mip->last_frame_used = old_last_frame;
|
---|
389 |
|
---|
390 | return return_mip;
|
---|
391 | }
|
---|
392 |
|
---|
393 | w32 r1_texture_manager_class::average_texture_color(r1_texture_handle _handle, w32 frame_num)
|
---|
394 | {
|
---|
395 | r1_texture_handle handle = registered_tnames[_handle].handle;
|
---|
396 |
|
---|
397 | r1_texture_entry_struct *e;
|
---|
398 |
|
---|
399 | if (handle>=total_textures)
|
---|
400 | i4_error("asking for bad texture");
|
---|
401 |
|
---|
402 | if (handle<0) // this is an animation
|
---|
403 | {
|
---|
404 | r1_texture_animation_entry_struct *ta=tanims+(-handle-1);
|
---|
405 | handle=ta->frames[frame_num%ta->total_frames];
|
---|
406 | if (!handle)
|
---|
407 | {
|
---|
408 | pf_get_texture.stop();
|
---|
409 | return 0;
|
---|
410 | }
|
---|
411 | }
|
---|
412 |
|
---|
413 | e = &(*entries)[handle];
|
---|
414 |
|
---|
415 | return e->average_color;
|
---|
416 | }
|
---|
417 |
|
---|
418 |
|
---|
419 | void r1_texture_manager_class::next_frame()
|
---|
420 | {
|
---|
421 | frame_count++;
|
---|
422 | //eventually (after a long fucking time) this could
|
---|
423 | //wrap around. just make sure its always > 0
|
---|
424 | if (frame_count<0) frame_count=0;
|
---|
425 | }
|
---|
426 |
|
---|
427 | int tex_entry_compare(const tex_cache_entry_t *a, const tex_cache_entry_t *b)
|
---|
428 | {
|
---|
429 | if (a->id > b->id)
|
---|
430 | return 1;
|
---|
431 | else
|
---|
432 | if (a->id < b->id)
|
---|
433 | return -1;
|
---|
434 | else
|
---|
435 | return 0;
|
---|
436 | }
|
---|
437 |
|
---|
438 | tex_cache_entry_t *find_id_in_tex_cache(tex_cache_entry_t *entries, w32 num_entries, w32 search_id)
|
---|
439 | {
|
---|
440 | if (!entries || num_entries==0)
|
---|
441 | return 0;
|
---|
442 |
|
---|
443 | w32 res;
|
---|
444 |
|
---|
445 | tex_cache_entry_t search;
|
---|
446 | search.id = search_id;
|
---|
447 |
|
---|
448 | if (!i4_base_bsearch(&search,res,entries,
|
---|
449 | sizeof(tex_cache_entry_t),
|
---|
450 | num_entries,
|
---|
451 | (i4_bsearch_compare_function_type)tex_entry_compare))
|
---|
452 | return 0;
|
---|
453 |
|
---|
454 | return entries+res;
|
---|
455 | }
|
---|
456 |
|
---|
457 | i4_bool palettes_are_same(i4_pixel_format *a, i4_pixel_format *b)
|
---|
458 | {
|
---|
459 | sw32 i;
|
---|
460 |
|
---|
461 | w8 *compare_a = (w8 *)a;
|
---|
462 | w8 *compare_b = (w8 *)b;
|
---|
463 |
|
---|
464 | for (i=0;i<sizeof(i4_pixel_format); i++)
|
---|
465 | {
|
---|
466 | if (*compare_a != *compare_b)
|
---|
467 | return i4_F;
|
---|
468 |
|
---|
469 | compare_a++;
|
---|
470 | compare_b++;
|
---|
471 | }
|
---|
472 |
|
---|
473 | return i4_T;
|
---|
474 | }
|
---|
475 |
|
---|
476 | #include "tex_cache.cc"
|
---|
477 | #include "tex_heap.cc"
|
---|
478 |
|
---|
479 | void r1_texture_manager_class::keep_resident(const i4_const_str &tname, sw32 desired_width)
|
---|
480 | {
|
---|
481 | w32 id = r1_get_texture_id(tname);
|
---|
482 | sw16 handle = find_texture(id);
|
---|
483 | if (!handle) return;
|
---|
484 |
|
---|
485 | r1_texture_entry_struct *t = &(*entries)[handle];
|
---|
486 |
|
---|
487 | r1_mip_load_info load_info;
|
---|
488 |
|
---|
489 | //load all levels <= desired_width
|
---|
490 | load_info.src_file = 0;
|
---|
491 |
|
---|
492 | sw32 j;
|
---|
493 | for (j=0; j<R1_MAX_MIP_LEVELS; j++)
|
---|
494 | {
|
---|
495 | r1_miplevel_t *mip = t->mipmaps[j];
|
---|
496 |
|
---|
497 | if (mip && (mip->width <= desired_width))
|
---|
498 | {
|
---|
499 | mip->last_frame_used = -1;
|
---|
500 |
|
---|
501 | if ((mip->vram_handle==0) && (!(mip->flags & R1_MIPLEVEL_IS_LOADING)))
|
---|
502 | {
|
---|
503 | load_info.dest_mip = mip;
|
---|
504 | if (!immediate_mip_load(&load_info))
|
---|
505 | {
|
---|
506 | //these absolutely must work
|
---|
507 | i4_error("keep_resident::could not load texture, cannot continue");
|
---|
508 | }
|
---|
509 | }
|
---|
510 | }
|
---|
511 | }
|
---|
512 | }
|
---|
513 |
|
---|
514 | i4_bool r1_texture_manager_class::load_textures()
|
---|
515 | {
|
---|
516 | sw32 i,j;
|
---|
517 |
|
---|
518 | if (textures_loaded)
|
---|
519 | return i4_F;
|
---|
520 |
|
---|
521 | r1_texture_ref *p=r1_texture_ref::first;
|
---|
522 | for (; p; p=p->next)
|
---|
523 | p->texture_handle=register_texture(p->name, "code reference");
|
---|
524 |
|
---|
525 | //create an array of texture id's from names[] and sort it
|
---|
526 | i4_array<w32> texture_file_ids(128,128);
|
---|
527 |
|
---|
528 | for (i=0; i<registered_tnames.size(); i++)
|
---|
529 | texture_file_ids.add(registered_tnames[i].id);
|
---|
530 |
|
---|
531 |
|
---|
532 | //sort the list
|
---|
533 | texture_file_ids.sort(w32_compare);
|
---|
534 |
|
---|
535 | //update / build / rebuild the cache file
|
---|
536 | keep_cache_current(&texture_file_ids);
|
---|
537 |
|
---|
538 | i4_file_class *cache_file = i4_open(r1_get_cache_file(), I4_READ | I4_NO_BUFFER);
|
---|
539 |
|
---|
540 | tex_cache_header_t tex_cache_header;
|
---|
541 |
|
---|
542 | if (cache_file)
|
---|
543 | {
|
---|
544 | //read in the header for further processing
|
---|
545 | tex_cache_header.read(cache_file);
|
---|
546 | }
|
---|
547 | else
|
---|
548 | {
|
---|
549 | i4_warning("Couldnt locate texture cache file.");
|
---|
550 | tex_cache_header.num_entries = 0;
|
---|
551 | tex_cache_header.entries = 0;
|
---|
552 | }
|
---|
553 |
|
---|
554 |
|
---|
555 | //OK FINALLY. process this crap. load information for all
|
---|
556 | //requested textures (their ids are currently in texture_file_ids)
|
---|
557 |
|
---|
558 | //dynamic array of loaded texture entries
|
---|
559 | i4_array<r1_texture_entry_struct> new_texture_entries(128,128);
|
---|
560 |
|
---|
561 | i4_status_class *stat = i4_create_status(r1_gets("loading_textures"));
|
---|
562 |
|
---|
563 | for (i=0; i<texture_file_ids.size(); i++)
|
---|
564 | {
|
---|
565 | w32 id = texture_file_ids[i];
|
---|
566 |
|
---|
567 | tex_cache_entry_t *t = find_id_in_tex_cache(tex_cache_header.entries,
|
---|
568 | tex_cache_header.num_entries,id);
|
---|
569 |
|
---|
570 | if (!t || (t->lowmipoffset==0xFFFFFFFF))
|
---|
571 | {
|
---|
572 | for (int k=0; k<registered_tnames.size(); k++)
|
---|
573 | if (registered_tnames[k].id==id)
|
---|
574 | {
|
---|
575 | i4_warning("Texture: %s not found in texture cache, run maxtool 'Update textures'", registered_tnames[k].name);
|
---|
576 | }
|
---|
577 | }
|
---|
578 | else
|
---|
579 | {
|
---|
580 | //texture is in the cache. need to load up some info, load the lowest mip, etc
|
---|
581 | //add it to the list of valid textures
|
---|
582 | r1_texture_entry_struct *new_entry = new_texture_entries.add();
|
---|
583 |
|
---|
584 | //the last one should always be null, hence the R1_MAX_MIP_LEVELS+1
|
---|
585 | memset(new_entry->mipmaps,0,sizeof(r1_miplevel_t *) * (R1_MAX_MIP_LEVELS+1));
|
---|
586 |
|
---|
587 | new_entry->flags = t->flags;
|
---|
588 | new_entry->id = t->id;
|
---|
589 | new_entry->average_color = t->average_color;
|
---|
590 |
|
---|
591 | generate_mip_offsets(t->base_width,t->base_height,t->num_mip_levels,(sw32 *)new_entry->file_offsets,2);
|
---|
592 |
|
---|
593 | //fill in this structure. information on mip levels
|
---|
594 | for (j=0; j<t->num_mip_levels; j++)
|
---|
595 | {
|
---|
596 | new_entry->mipmaps[j] = new r1_miplevel_t;
|
---|
597 |
|
---|
598 | r1_miplevel_t *mip = new_entry->mipmaps[j];
|
---|
599 |
|
---|
600 | mip->level = j;
|
---|
601 | mip->width = t->base_width /(1<<j);
|
---|
602 | mip->height = t->base_height/(1<<j);
|
---|
603 | mip->entry = new_entry;
|
---|
604 |
|
---|
605 | mip->flags = 0;
|
---|
606 | }
|
---|
607 |
|
---|
608 | //seek to the low mip offset (stored IN the cache file)
|
---|
609 | cache_file->seek(t->lowmipoffset+8);
|
---|
610 |
|
---|
611 | r1_mip_load_info load_info;
|
---|
612 |
|
---|
613 | //the dst_mip is the very last one
|
---|
614 | load_info.src_file = cache_file;
|
---|
615 | load_info.dest_mip = new_entry->mipmaps[t->num_mip_levels-1];
|
---|
616 |
|
---|
617 | //dont want these to ever be thrown out of texture memory
|
---|
618 | load_info.dest_mip->last_frame_used = -1;
|
---|
619 |
|
---|
620 | //load that low mip level
|
---|
621 | if (!immediate_mip_load(&load_info))
|
---|
622 | {
|
---|
623 | //check the error field in load_info
|
---|
624 | i4_error("Could not load lowest miplevel of a texture, cannot continue");
|
---|
625 | }
|
---|
626 | }
|
---|
627 |
|
---|
628 | if (stat)
|
---|
629 | stat->update((float)(i+1) / (float)texture_file_ids.size());
|
---|
630 | }
|
---|
631 |
|
---|
632 | if (stat)
|
---|
633 | delete stat;
|
---|
634 |
|
---|
635 | if (cache_file)
|
---|
636 | delete cache_file;
|
---|
637 |
|
---|
638 | if (tex_cache_header.entries)
|
---|
639 | i4_free(tex_cache_header.entries);
|
---|
640 | else
|
---|
641 | {
|
---|
642 | //there were no texture cache entries? just get rid of the file.
|
---|
643 | i4_unlink(r1_get_cache_file());
|
---|
644 | }
|
---|
645 |
|
---|
646 |
|
---|
647 | //theres 1 additional texture, which will be entries[0], the default texture
|
---|
648 | total_textures = new_texture_entries.size() + 1;
|
---|
649 |
|
---|
650 | entries = new i4_array<r1_texture_entry_struct>(total_textures,8);
|
---|
651 |
|
---|
652 | r1_texture_entry_struct blank_entry;
|
---|
653 | memset(&blank_entry,0,sizeof(r1_texture_entry_struct));
|
---|
654 | blank_entry.average_color = 0x00FFFFFF;
|
---|
655 |
|
---|
656 | entries->add(blank_entry);
|
---|
657 |
|
---|
658 | //should be sorted already but go ahead, sort again just in case
|
---|
659 | if (new_texture_entries.size())
|
---|
660 | new_texture_entries.sort(entry_compare);
|
---|
661 |
|
---|
662 | for (i=0; i<total_textures-1; i++)
|
---|
663 | {
|
---|
664 | entries->add();
|
---|
665 | memset(&(*entries)[i+1],0,sizeof(r1_texture_entry_struct));
|
---|
666 |
|
---|
667 | (*entries)[i+1] = new_texture_entries[i];
|
---|
668 |
|
---|
669 | //crap. have to update the entry pointers since the mip's ->entry
|
---|
670 | //references are in new_texture_entries (instead of entries[])
|
---|
671 | for (j=0; j<R1_MAX_MIP_LEVELS; j++)
|
---|
672 | {
|
---|
673 | if ((*entries)[i+1].mipmaps[j])
|
---|
674 | {
|
---|
675 | (*entries)[i+1].mipmaps[j]->entry = &(*entries)[i+1];
|
---|
676 | }
|
---|
677 | }
|
---|
678 | }
|
---|
679 |
|
---|
680 | matchup_textures();
|
---|
681 |
|
---|
682 | /*
|
---|
683 | i4_array<r1_texture_animation_entry_struct> anim_a(128,128);
|
---|
684 | for (i=0; i<names.size(); i++)
|
---|
685 | {
|
---|
686 | w32 id=r1_get_texture_id(*names[i]);
|
---|
687 | i4_str *fn=r1_animation_id_to_filename(id);
|
---|
688 | i4_file_class *fp=opener(*fn);
|
---|
689 | if (fp)
|
---|
690 | {
|
---|
691 | r1_texture_animation_entry_struct *a=anim_a.add();
|
---|
692 | a->id=fp->read_32();
|
---|
693 | a->total_frames=fp->read_16();
|
---|
694 | a->frames=(r1_texture_handle *)i4_malloc(sizeof(r1_texture_handle)*a->total_frames,
|
---|
695 | "animation frames");
|
---|
696 | for (j=0; j<a->total_frames; j++)
|
---|
697 | {
|
---|
698 | w32 id=fp->read_32();
|
---|
699 | a->frames[j]=find_texture(id);
|
---|
700 | }
|
---|
701 | }
|
---|
702 |
|
---|
703 | delete fn;
|
---|
704 | }
|
---|
705 |
|
---|
706 | total_tanims=anim_a.size();
|
---|
707 | if (total_tanims)
|
---|
708 | {
|
---|
709 | tanims=(r1_texture_animation_entry_struct *)i4_malloc(sizeof(r1_texture_animation_entry_struct)
|
---|
710 | * total_tanims, "animations");
|
---|
711 | for (i=0; i<anim_a.size(); i++)
|
---|
712 | tanims[i]=anim_a[i];
|
---|
713 | }
|
---|
714 | else
|
---|
715 | tanims=0;
|
---|
716 |
|
---|
717 | */
|
---|
718 | return i4_T;
|
---|
719 | }
|
---|
720 |
|
---|
721 | r1_texture_handle r1_texture_manager_class::register_image(i4_image_class *image)
|
---|
722 | {
|
---|
723 | if (!entries || !entries->size())
|
---|
724 | load_textures();
|
---|
725 |
|
---|
726 | //check to make sure image is power of 2
|
---|
727 | sw32 i,j,new_width,new_height;
|
---|
728 |
|
---|
729 | for (i=1; i < image->width(); i = i<<1);
|
---|
730 | new_width = i;
|
---|
731 |
|
---|
732 | for (i=1; i < image->height(); i = i<<1);
|
---|
733 | new_height = i;
|
---|
734 |
|
---|
735 |
|
---|
736 | r1_texture_handle return_handle = 0;
|
---|
737 |
|
---|
738 | i4_draw_context_class context(0,0,image->width()-1,image->height()-1);
|
---|
739 |
|
---|
740 |
|
---|
741 | r1_texture_entry_struct new_entry;
|
---|
742 | memset(&new_entry,0,sizeof(r1_texture_entry_struct));
|
---|
743 |
|
---|
744 |
|
---|
745 | const i4_pal *put_pal=pal;
|
---|
746 | if (image->pal->source.alpha_bits)
|
---|
747 | {
|
---|
748 | put_pal=i4_pal_man.register_pal(&alpha_format);
|
---|
749 | new_entry.flags|=R1_MIP_IS_ALPHATEXTURE;
|
---|
750 | }
|
---|
751 |
|
---|
752 |
|
---|
753 | i4_image_class *temp_image = i4_create_image(image->width(),image->height(), put_pal);
|
---|
754 | i4_image_class *texture_image = temp_image;
|
---|
755 |
|
---|
756 | image->put_image(temp_image,0,0,context);
|
---|
757 |
|
---|
758 | if (new_width != temp_image->width() || new_height != temp_image->height())
|
---|
759 | {
|
---|
760 | texture_image = i4_create_image(new_width,new_height, pal);
|
---|
761 |
|
---|
762 | sw32 old_width = temp_image->width();
|
---|
763 | sw32 old_height = temp_image->height();
|
---|
764 |
|
---|
765 | w16 *old_tex = (w16 *)temp_image->data;
|
---|
766 | w16 *new_tex = (w16 *)texture_image->data;
|
---|
767 | w16 *dst = new_tex;
|
---|
768 |
|
---|
769 | float width_ratio = (float)old_width / (float)new_width;
|
---|
770 | float height_ratio = (float)old_height / (float)new_height;
|
---|
771 |
|
---|
772 | //now scale the old to fit the new
|
---|
773 |
|
---|
774 | for (j=0; j<new_height; j++)
|
---|
775 | for (i=0; i<new_width; i++, dst++)
|
---|
776 | {
|
---|
777 | *dst = old_tex[(sw32)((double)j * height_ratio)*old_width + (sw32)((double)i * width_ratio)];
|
---|
778 | }
|
---|
779 |
|
---|
780 | delete temp_image;
|
---|
781 | }
|
---|
782 |
|
---|
783 | i4_ram_file_class *fake_file = new i4_ram_file_class(texture_image->data,
|
---|
784 | texture_image->width() *
|
---|
785 | texture_image->height() * 2);
|
---|
786 |
|
---|
787 |
|
---|
788 | new_entry.id = (*entries)[entries->size()-1].id + 1; //maintains the sorted order of the array
|
---|
789 | new_entry.average_color = 0xFFFFFFFF;
|
---|
790 | new_entry.mipmaps[0] = new r1_miplevel_t;
|
---|
791 |
|
---|
792 | r1_miplevel_t *mip = new_entry.mipmaps[0];
|
---|
793 |
|
---|
794 | mip->level = 0;
|
---|
795 | mip->width = texture_image->width();
|
---|
796 | mip->height = texture_image->height();
|
---|
797 |
|
---|
798 | mip->last_frame_used = -1;
|
---|
799 | mip->vram_handle = 0;
|
---|
800 | mip->flags = R1_MIP_IS_ALPHATEXTURE;
|
---|
801 |
|
---|
802 | entries->add(new_entry);
|
---|
803 | total_textures++;
|
---|
804 |
|
---|
805 | //update entry pointers for all miplevels
|
---|
806 | for (i=0; i<total_textures-1; i++)
|
---|
807 | {
|
---|
808 | //references are in new_texture_entries (instead of entries[])
|
---|
809 | for (j=0; j<R1_MAX_MIP_LEVELS; j++)
|
---|
810 | {
|
---|
811 | if ((*entries)[i+1].mipmaps[j])
|
---|
812 | {
|
---|
813 | (*entries)[i+1].mipmaps[j]->entry = &(*entries)[i+1];
|
---|
814 | }
|
---|
815 | }
|
---|
816 | }
|
---|
817 |
|
---|
818 | r1_mip_load_info load_info;
|
---|
819 | load_info.dest_mip = mip;
|
---|
820 | load_info.src_file = fake_file;
|
---|
821 |
|
---|
822 | if (!immediate_mip_load(&load_info))
|
---|
823 | {
|
---|
824 | i4_warning("tmanager:: register_image failed.");
|
---|
825 | }
|
---|
826 | else
|
---|
827 | {
|
---|
828 | return_handle = total_textures-1;
|
---|
829 | }
|
---|
830 |
|
---|
831 | delete fake_file;
|
---|
832 | delete texture_image;
|
---|
833 |
|
---|
834 | char name[256];
|
---|
835 | sprintf(name, "memory_image_%d", return_handle);
|
---|
836 | r1_texture_handle han=register_texture(name, name);
|
---|
837 | registered_tnames[han].handle=return_handle;
|
---|
838 |
|
---|
839 | return han;
|
---|
840 | }
|
---|
841 |
|
---|
842 |
|
---|
843 |
|
---|
844 |
|
---|
845 |
|
---|