source: golgotha/src/render/glide/gr_vram.cc @ 80

Last change on this file since 80 was 80, checked in by Sam Hocevar, 11 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 13.6 KB
Line 
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 "video/glide/glide.h"
10#include "glide/gr_vram.hh"
11#include "time/profile.hh"
12#include "r1_res.hh"
13
14r1_glide_vram_class *r1_glide_vram_class_instance=0;
15
16i4_profile_class pf_glide_install_vram("glide install vram texture");
17i4_profile_class pf_glide_free_vram("glide free vram texture");
18
19r1_glide_vram_class::r1_glide_vram_class(const i4_pal *pal)
20
21  : r1_texture_manager_class(pal),finished_array(16,16)
22{   
23  tex_heap_man = 0;
24  tex_heap_man_2 = 0;
25
26  r1_glide_vram_class_instance = this;
27
28  r1_glide_vram_class::init();
29
30  min_texture_dimention = 1;
31
32  max_texture_dimention = r1_max_texture_size;
33
34  if (max_texture_dimention>256)
35    max_texture_dimention=256;     // glide can't go higher than 256
36   
37  regular_format.red_mask   = 31 << 11;
38  regular_format.green_mask = 63 << 5;
39  regular_format.blue_mask  = 31;
40  regular_format.alpha_mask = 0;
41  regular_format.lookup     = 0;
42  regular_format.calc_shift();
43  regular_format.pixel_depth = I4_16BIT;
44 
45  chroma_format.red_mask   = 31 << 10;
46  chroma_format.green_mask = 31 << 5;
47  chroma_format.blue_mask  = 31;
48  chroma_format.alpha_mask = 1 << 15;
49  chroma_format.lookup     = 0; 
50  chroma_format.calc_shift();
51  chroma_format.pixel_depth = I4_16BIT;
52 
53  alpha_format.red_mask   = 15 << 8;
54  alpha_format.green_mask = 15 << 4;
55  alpha_format.blue_mask  = 15;
56  alpha_format.alpha_mask = 15 << 12;
57  alpha_format.lookup     = 0; 
58  alpha_format.calc_shift();
59  alpha_format.pixel_depth = I4_16BIT;
60}
61
62void r1_glide_vram_class::init()
63{
64  r1_texture_manager_class::init();
65
66  int t_vram=grTexMaxAddress(GR_TMU0) - grTexMinAddress(GR_TMU0);
67 
68  int  heap1_size=t_vram > 2*1024*1024 ?  2*1024*1024 : t_vram;
69 
70  int heap2_size=t_vram - heap1_size;
71 
72  heap1_address=grTexMinAddress(GR_TMU0);
73  heap2_address=heap1_address + heap1_size;
74   
75  tex_heap_man = new r1_texture_heap_class(heap1_size,
76                                           heap1_address,
77                                           sizeof(free_node),
78                                           sizeof(used_node),
79                                           &frame_count);
80
81  /*  if (heap2_size>0)
82    tex_heap_man_2 = new r1_texture_heap_class(heap2_size,
83                                               heap2_address,
84                                               sizeof(free_node),
85                                               sizeof(used_node),
86                                               &frame_count);
87
88  */
89
90
91
92 
93  array_lock.lock();
94  array_lock.unlock();
95
96  bytes_loaded = 0;
97  textures_loaded = 0;
98}
99
100void r1_glide_vram_class::uninit()
101
102  if (tex_heap_man)
103  {
104    delete tex_heap_man;
105    tex_heap_man = 0;
106  }
107  if (tex_heap_man_2)
108  {
109    delete tex_heap_man_2;
110    tex_heap_man_2 = 0;
111  }
112
113 
114  r1_texture_manager_class::uninit();
115}
116
117i4_bool r1_glide_vram_class::immediate_mip_load(r1_mip_load_info *load_info)
118
119  if (textures_loaded > 0)
120  {
121    if (load_info->dest_mip->last_frame_used != -1)
122    {
123      load_info->error = R1_MIP_LOAD_BUSY;
124      return i4_F;
125    }
126  } 
127  pf_glide_install_vram.start();
128
129  r1_miplevel_t *mip = load_info->dest_mip;
130
131  sw32 actual_w,actual_h;
132
133  w32  w_lod=GR_LOD_1, h_lod=GR_LOD_1;
134
135  //determine the aspect ratio and level of detail
136  for (actual_w=min_texture_dimention; actual_w<mip->width; actual_w*=2)
137    w_lod--;
138
139  for (actual_h=min_texture_dimention; actual_h<mip->height; actual_h*=2)
140    h_lod--;
141
142  w32 need_size = ((actual_w * actual_h * 2) + 7) & (~7); // sizes must be 8 byte alligned 
143
144  used_node *new_used = (used_node *)tex_heap_man->alloc(need_size);
145  if (!new_used && tex_heap_man_2)
146    new_used = (used_node *)tex_heap_man_2->alloc(need_size);
147   
148  if (!new_used)
149  {
150    pf_glide_install_vram.stop();
151    load_info->error = R1_MIP_LOAD_NO_ROOM;
152    return i4_F;
153  }
154
155  free_node *f = (free_node *)new_used->node;
156
157  //f is the node we'll use
158 
159  if (load_info->src_file)
160  {
161    load_info->src_file->read(scratch_texture,mip->width*mip->height*2);
162  }
163  else
164  {
165
166    i4_str *fn = r1_texture_id_to_filename(mip->entry->id, r1_get_decompressed_dir());
167    i4_file_class *fp = i4_open(*fn);
168    delete fn;
169   
170    fp->seek(mip->entry->file_offsets[mip->level]+8);
171    fp->read(scratch_texture,mip->width*mip->height*2);
172
173    delete fp;
174  }     
175 
176  bytes_loaded += mip->width*mip->height*2;
177  textures_loaded++;
178 
179  //fill these data fields w/the appropriate data
180  f->mip = mip;
181  mip->vram_handle = new_used;
182 
183  if (mip->last_frame_used != -1)
184    mip->last_frame_used = frame_count;
185
186
187  // setup the correct lod (level of detail) and aspect variables
188  if (actual_w>=actual_h)
189  {
190    // uv correction for this texture because we made it pow2
191    f->smul   = (i4_float)(mip->width)  / (i4_float)actual_w * 256.0;
192    f->tmul   = (i4_float)(mip->height) / (i4_float)actual_w * 256.0;
193    f->lod    = w_lod;
194    f->aspect = GR_ASPECT_1x1 - (h_lod-w_lod);
195  }
196  else
197  {
198    f->smul   = (i4_float)(mip->width)  / (i4_float)actual_h * 256.0;
199    f->tmul   = (i4_float)(mip->height) / (i4_float)actual_h * 256.0;
200    f->lod    = h_lod;
201    f->aspect = w_lod-h_lod+GR_ASPECT_1x1;
202  }     
203
204  GrTexInfo tex_load_info;
205
206  tex_load_info.smallLod    = f->lod;
207  tex_load_info.largeLod    = f->lod;
208  tex_load_info.aspectRatio = f->aspect;
209  tex_load_info.format      = GR_TEXFMT_RGB_565;
210 
211  // download the texture to the card
212  grTexDownloadMipMapLevel(GR_TMU0,
213                           f->start,
214                           f->lod,
215                           f->lod,
216                           f->aspect,
217                           GR_TEXFMT_RGB_565,
218                           GR_MIPMAPLEVELMASK_BOTH,                           
219                           scratch_texture); 
220
221  pf_glide_install_vram.stop();
222 
223  return i4_T;
224}
225
226//typedef void (*async_callback)(w32 count, void *context);
227
228void glide_async_callback(w32 count, void *context)
229
230  r1_glide_vram_class::used_node *u = (r1_glide_vram_class::used_node *)context;
231  r1_glide_vram_class::free_node *f = (r1_glide_vram_class::free_node *)u->node;
232 
233  if (f->async_fp)
234    delete f->async_fp;
235
236  f->async_fp = 0;
237
238  r1_glide_vram_class_instance->async_load_finished(u); 
239}
240
241void r1_glide_vram_class::async_load_finished(used_node *u)
242{
243  array_lock.lock();
244 
245  finished_array.add(u); 
246 
247  array_lock.unlock();
248}
249
250i4_bool r1_glide_vram_class::async_mip_load(r1_mip_load_info *load_info)
251{
252  //return immediate_mip_load(load_info);
253
254  if (bytes_loaded > 32768 || textures_loaded > 16)
255  {
256    if (load_info->dest_mip->last_frame_used != -1)
257    {
258      load_info->error = R1_MIP_LOAD_BUSY;
259      return i4_F;
260    }
261  } 
262 
263  pf_glide_install_vram.start();
264
265  r1_miplevel_t *mip = load_info->dest_mip;
266
267  sw32 actual_w,actual_h;
268
269  w32  w_lod=GR_LOD_1, h_lod=GR_LOD_1;
270
271  //determine the aspect ratio and level of detail
272  for (actual_w=min_texture_dimention; actual_w<mip->width; actual_w*=2)
273    w_lod--;
274
275  for (actual_h=min_texture_dimention; actual_h<mip->height; actual_h*=2)
276    h_lod--;
277
278  w32 need_size = ((actual_w * actual_h * 2) + 7) & (~7); // sizes must be 8 byte alligned 
279
280  used_node *new_used = (used_node *)tex_heap_man->alloc(need_size,R1_TEX_HEAP_DONT_LIST);
281  if (!new_used && tex_heap_man_2)
282    new_used = (used_node *)tex_heap_man_2->alloc(need_size,R1_TEX_HEAP_DONT_LIST);
283 
284  if (!new_used)
285  {
286    pf_glide_install_vram.stop();
287    load_info->error = R1_MIP_LOAD_NO_ROOM;
288    return i4_F;
289  }
290
291  //f is the node we'll use
292  free_node *f = (free_node *)new_used->node; 
293 
294  //fill these data fields w/the appropriate data
295  f->mip      = mip;
296  f->data     = (w8 *)i4_malloc(need_size,"temp glide texture");
297  f->async_fp = 0;
298
299  mip->flags |= R1_MIPLEVEL_IS_LOADING;
300 
301  // setup the correct lod (level of detail) and aspect variables
302  if (actual_w>=actual_h)
303  {
304    // uv correction for this texture because we made it pow2
305    f->smul   = (i4_float)(mip->width)  / (i4_float)actual_w * 256.0;
306    f->tmul   = (i4_float)(mip->height) / (i4_float)actual_w * 256.0;
307    f->lod    = w_lod;
308    f->aspect = GR_ASPECT_1x1 - (h_lod-w_lod);
309  }
310  else
311  {
312    f->smul   = (i4_float)(mip->width)  / (i4_float)actual_h * 256.0;
313    f->tmul   = (i4_float)(mip->height) / (i4_float)actual_h * 256.0;
314    f->lod    = h_lod;
315    f->aspect = w_lod-h_lod+GR_ASPECT_1x1;
316  }
317
318  i4_bool async_worked;
319
320  if (load_info->src_file)
321  {
322    texture_resolution_changed=i4_T;
323    async_worked = load_info->src_file->async_read(f->data,mip->width*mip->height*2,glide_async_callback,new_used); 
324  }
325  else
326  {
327    i4_str *fn = r1_texture_id_to_filename(mip->entry->id, r1_get_decompressed_dir());
328   
329    i4_file_class *fp = i4_open(*fn,I4_READ | I4_NO_BUFFER | I4_SUPPORT_ASYNC);
330
331    delete fn;
332       
333    if (!fp)   
334      async_worked = i4_F;   
335    else
336    {
337      f->async_fp = fp;
338
339      fp->seek(mip->entry->file_offsets[mip->level]+8);
340
341      texture_resolution_changed=i4_T;
342      async_worked = fp->async_read(f->data,mip->width*mip->height*2,glide_async_callback,new_used);   
343    }
344  }   
345
346  if (!async_worked)
347  {
348    if (f->async_fp)
349      delete f->async_fp;
350
351    if (f->data)
352      i4_free(f->data);
353
354    mip->flags &= (~R1_MIPLEVEL_IS_LOADING);
355
356    if (new_used->node->start>=heap2_address)
357      tex_heap_man_2->free((r1_tex_heap_used_node *)new_used);
358    else
359      tex_heap_man->free((r1_tex_heap_used_node *)new_used);
360   
361    load_info->error = R1_MIP_LOAD_BUSY;   
362    pf_glide_install_vram.stop();
363    return i4_F;
364  }
365
366  bytes_loaded += mip->width*mip->height*2;
367  textures_loaded++;
368
369  pf_glide_install_vram.stop();
370  return i4_T; 
371}
372
373void r1_glide_vram_class::next_frame()
374{
375  r1_texture_manager_class::next_frame();
376
377  sw32 i;   
378
379  array_lock.lock();     
380
381  for (i=0; i<finished_array.size(); i++)
382  {
383    used_node *u = finished_array[i];
384    free_node *f = (free_node *)u->node;
385   
386    //this officially puts it in vram
387    f->mip->vram_handle      = u;
388    f->mip->flags           &= (~R1_MIPLEVEL_IS_LOADING);
389   
390    if (f->mip->last_frame_used != -1)
391      f->mip->last_frame_used  = frame_count;
392
393    if (u->node->start>=heap2_address)
394      tex_heap_man_2->update_usage((r1_tex_heap_used_node *)u);
395    else
396      //this adds it into the list of used nodes
397      tex_heap_man->update_usage((r1_tex_heap_used_node *)u);
398   
399    GrTexInfo tex_load_info;
400
401    tex_load_info.smallLod    = f->lod;
402    tex_load_info.largeLod    = f->lod;
403    tex_load_info.aspectRatio = f->aspect;
404    tex_load_info.format      = GR_TEXFMT_RGB_565;
405 
406    // download the texture to the card
407    grTexDownloadMipMapLevel(GR_TMU0,
408                             f->start,
409                             f->lod,
410                             f->lod,
411                             f->aspect,
412                             GR_TEXFMT_RGB_565,
413                             GR_MIPMAPLEVELMASK_BOTH,
414                             f->data);
415                           
416    i4_free(f->data);
417    f->data = 0;
418  }
419 
420  finished_array.clear();
421
422  array_lock.unlock();
423
424  if (tex_heap_man->needs_cleanup)
425    tex_heap_man->free_really_old();
426
427  if (tex_heap_man_2 && tex_heap_man_2->needs_cleanup)
428    tex_heap_man_2->free_really_old();
429
430 
431  bytes_loaded = 0;
432  textures_loaded = 0;
433}
434
435void r1_glide_vram_class::free_mip(r1_vram_handle_type vram_handle)
436{
437  pf_glide_free_vram.start();
438  r1_tex_heap_used_node *n=(r1_tex_heap_used_node *)vram_handle;
439 
440  if (n->node->start>=heap2_address)
441    tex_heap_man_2->free(n);
442  else
443    tex_heap_man->free(n);
444 
445  pf_glide_free_vram.stop();
446}
447
448void r1_glide_vram_class::select_texture(r1_vram_handle_type handle,
449                                         float &smul, float &tmul,
450                                         i4_bool holy, i4_bool alpha)
451
452  free_node *n = (free_node *)((used_node *)handle)->node;
453
454  GrTexInfo tex_source_info;
455 
456  tex_source_info.smallLod    = n->lod;
457  tex_source_info.largeLod    = n->lod;
458  tex_source_info.aspectRatio = n->aspect;
459 
460  if (alpha)
461    tex_source_info.format = GR_TEXFMT_ARGB_4444;
462  else
463  if (holy)
464    tex_source_info.format = GR_TEXFMT_ARGB_1555;
465  else
466    tex_source_info.format = GR_TEXFMT_RGB_565; 
467 
468  smul = n->smul;
469  tmul = n->tmul;
470
471  grTexSource(GR_TMU0,
472              n->start,
473              GR_MIPMAPLEVELMASK_BOTH,
474              &tex_source_info);
475}
476
477r1_miplevel_t *r1_glide_vram_class::get_texture(r1_texture_handle handle,
478                                                w32 frame_counter,
479                                                sw32 desired_width,
480                                                sw32 &w, sw32 &h)
481{
482  r1_miplevel_t *mip = r1_texture_manager_class::get_texture(handle,frame_counter,desired_width,w,h);
483
484  if (mip)
485  {
486    r1_tex_heap_used_node *u = (r1_tex_heap_used_node *)mip->vram_handle;
487
488    if (u)
489    {
490      if (u->node->start>=heap2_address)
491        tex_heap_man_2->update_usage(u);
492      else
493        tex_heap_man->update_usage(u);
494    }
495  }
496
497  return mip;   
498}
Note: See TracBrowser for help on using the repository browser.