source: golgotha/src/render/software/r1_software_texture.cc

Last change on this file 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: 9.0 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 "software/r1_software_texture.hh"
10#include "video/win32/dx5.hh"
11#include "time/profile.hh"
12#include "r1_res.hh"
13
14i4_profile_class pf_software_install_vram("software install vram texture");
15i4_profile_class pf_software_free_vram("software free vram texture");
16
17r1_software_texture_class *r1_software_texture_class_instance=0;
18
19r1_software_texture_class::r1_software_texture_class(const i4_pal *pal)
20: r1_texture_manager_class(pal),finished_array(16,16)
21
22  r1_software_texture_class_instance = this;
23
24  tex_heap_man = 0;
25  texture_heap = 0;
26
27  init(); 
28 
29  min_texture_dimention = 1;
30  max_texture_dimention = r1_max_texture_size;
31
32  //setup the texture formats
33  regular_format = pal->source;
34  chroma_format  = regular_format;   
35 
36  alpha_format.red_mask   = 15 << 8;
37  alpha_format.green_mask = 15 << 4;
38  alpha_format.blue_mask  = 15;
39  alpha_format.alpha_mask = 15 << 12;
40  alpha_format.lookup     = 0; 
41  alpha_format.calc_shift();
42  alpha_format.pixel_depth = I4_16BIT;
43}
44
45
46void r1_software_texture_class::init()
47{
48  r1_texture_manager_class::init();
49 
50  int tex_mem_size = 1024*1024*8;
51  if (i4_available()/4 < tex_mem_size)
52    tex_mem_size=i4_available()/4;
53 
54  i4_warning("Software texture memory heap allocated: %d bytes", tex_mem_size);
55 
56  texture_heap = (w8 *)i4_malloc(tex_mem_size,"software texture memory heap");
57
58  tex_heap_man = new r1_texture_heap_class(tex_mem_size,
59                                           (w32)texture_heap,
60                                           sizeof(free_node),
61                                           sizeof(used_node),
62                                           &frame_count);
63 
64  array_lock.lock();
65  array_lock.unlock();
66 
67  bytes_loaded = 0;
68  textures_loaded = 0;
69}
70
71void r1_software_texture_class::uninit()
72
73  if (tex_heap_man)
74  {
75    delete tex_heap_man; 
76    tex_heap_man = 0;
77  }
78
79  if (texture_heap)
80  {
81    i4_warning("Software texture memory heap deallocated: 8 megs");
82
83    i4_free(texture_heap);
84    texture_heap = 0;
85  }
86 
87  r1_texture_manager_class::uninit();
88}
89
90i4_bool r1_software_texture_class::immediate_mip_load(r1_mip_load_info *load_info)
91
92  if (textures_loaded > 0)
93  {
94    if (load_info->dest_mip->last_frame_used != -1)
95    {
96      load_info->error = R1_MIP_LOAD_BUSY;
97      return i4_F;
98    }
99  } 
100  pf_software_install_vram.start(); 
101
102  r1_miplevel_t *mip = load_info->dest_mip; 
103
104  sw32 i,need_size; 
105 
106  need_size = mip->width * mip->height * 2;
107
108  used_node *new_used = (used_node *)tex_heap_man->alloc(need_size);
109 
110  if (!new_used)
111  {
112    pf_software_install_vram.stop();
113    load_info->error = R1_MIP_LOAD_NO_ROOM;
114    return i4_F;
115  }
116   
117  free_node *f = (free_node *)new_used->node;
118 
119  //f is the node we'll use 
120 
121  if (load_info->src_file)
122  {
123    load_info->src_file->read((w16 *)f->start,mip->width*mip->height*2);
124  }
125  else
126  {
127    i4_str *fn = r1_texture_id_to_filename(mip->entry->id, r1_get_decompressed_dir());   
128   
129    i4_file_class *fp = i4_open(*fn);
130
131    delete fn;
132   
133    fp->seek(mip->entry->file_offsets[mip->level]+8);   
134    fp->read((w16 *)f->start,mip->width*mip->height*2);       
135
136    delete fp;
137  }
138 
139  bytes_loaded += mip->width*mip->height*2;
140  textures_loaded++;
141
142  //load the texture
143  f->mip = mip;
144  mip->vram_handle = new_used;
145
146  if (mip->last_frame_used != -1)
147    mip->last_frame_used = frame_count;
148
149  pf_software_install_vram.stop();
150
151  return i4_T;
152}
153
154static i4_critical_section_class num_async_pending_lock;
155static int num_async_pending=0;
156
157r1_software_texture_class::~r1_software_texture_class()
158{
159  while (num_async_pending!=0)
160    i4_sleep(0);
161
162
163  uninit();
164}
165//typedef void (*async_callback)(w32 count, void *context);
166
167void software_async_callback(w32 count, void *context)
168
169  r1_software_texture_class::used_node *u = (r1_software_texture_class::used_node *)context;
170  r1_software_texture_class::free_node *f = (r1_software_texture_class::free_node *)u->node;
171 
172  if (f->async_fp)
173    delete f->async_fp;
174
175  f->async_fp = 0; 
176
177  if (count != f->mip->width*f->mip->height*2)
178    i4_warning("async texture read failure");
179
180  r1_software_texture_class_instance->async_load_finished(u); 
181
182  num_async_pending_lock.lock();
183  num_async_pending--;
184  num_async_pending_lock.unlock();
185}
186
187i4_bool r1_software_texture_class::async_mip_load(r1_mip_load_info *load_info)
188{
189  if (bytes_loaded > 32768 || textures_loaded > 16)
190  {
191    if (load_info->dest_mip->last_frame_used != -1)
192    {   
193      load_info->error = R1_MIP_LOAD_BUSY;
194      return i4_F;
195    }
196  }
197
198  pf_software_install_vram.start();
199
200  sw32 i;
201
202  r1_miplevel_t *mip = load_info->dest_mip; 
203 
204  w32 need_size = mip->width * mip->height * 2;
205
206  used_node *new_used = (used_node *)tex_heap_man->alloc(need_size,R1_TEX_HEAP_DONT_LIST);
207 
208  if (!new_used)
209  {
210    pf_software_install_vram.stop();
211    load_info->error = R1_MIP_LOAD_NO_ROOM;
212    return i4_F;
213  }
214 
215  //f is the node we'll use 
216  free_node *f = (free_node *)new_used->node;   
217 
218  f->mip         = mip;
219  f->async_fp    = 0;
220
221  mip->flags |= R1_MIPLEVEL_IS_LOADING;
222
223  i4_bool async_worked;
224
225  num_async_pending_lock.lock();
226  num_async_pending++;
227  num_async_pending_lock.unlock();
228
229  if (load_info->src_file)
230  {
231    async_worked = load_info->src_file->async_read((w16 *)f->start,mip->width*mip->height*2,software_async_callback,new_used);   
232  }
233  else
234  {
235    i4_str *fn = r1_texture_id_to_filename(mip->entry->id,r1_get_decompressed_dir());   
236   
237    i4_file_class *fp = i4_open(*fn,I4_READ | I4_NO_BUFFER | I4_SUPPORT_ASYNC);
238
239    delete fn;
240       
241    if (!fp)
242      async_worked = i4_F;
243    else
244    {
245      f->async_fp = fp;
246
247      fp->seek(mip->entry->file_offsets[mip->level]+8);
248
249      async_worked = fp->async_read((w16 *)f->start,mip->width*mip->height*2,software_async_callback,new_used);
250    }
251  }
252 
253  if (!async_worked)
254  { 
255    if (f->async_fp)
256      delete f->async_fp;
257   
258    mip->flags &= (~R1_MIPLEVEL_IS_LOADING);   
259    tex_heap_man->free((r1_tex_heap_used_node *)new_used);
260   
261    load_info->error = R1_MIP_LOAD_BUSY;   
262    pf_software_install_vram.stop();
263
264    num_async_pending_lock.lock();
265    num_async_pending--;
266    num_async_pending_lock.unlock();
267
268    return i4_F;
269  }
270
271  bytes_loaded += mip->width*mip->height*2;
272  textures_loaded++;
273
274  pf_software_install_vram.stop();
275
276  return i4_T;
277}
278
279void r1_software_texture_class::async_load_finished(used_node *u)
280{
281  array_lock.lock();
282 
283  finished_array.add(u); 
284 
285  array_lock.unlock();
286}
287
288void r1_software_texture_class::next_frame()
289{
290  r1_texture_manager_class::next_frame();
291
292  sw32 i;
293 
294  array_lock.lock();
295 
296  for (i=0; i<finished_array.size(); i++)
297  {
298    used_node *u = finished_array[i];
299    free_node *f = (free_node *)u->node;   
300   
301    //this officially puts it in vram
302    f->mip->vram_handle      = u;
303    f->mip->flags           &= (~R1_MIPLEVEL_IS_LOADING);
304   
305    if (f->mip->last_frame_used != -1)
306      f->mip->last_frame_used  = frame_count;   
307
308    //this adds it into the list of used nodes
309    tex_heap_man->update_usage((r1_tex_heap_used_node *)u);
310  } 
311
312  finished_array.clear();
313
314  array_lock.unlock();
315
316  if (tex_heap_man->needs_cleanup)
317  {
318    tex_heap_man->free_really_old();
319  }
320
321  bytes_loaded = 0;
322  textures_loaded = 0;
323}
324
325
326void r1_software_texture_class::free_mip(r1_vram_handle_type vram_handle)
327{
328  pf_software_free_vram.start();
329
330  tex_heap_man->free((r1_tex_heap_used_node *)vram_handle);
331 
332  pf_software_free_vram.stop();
333}
334
335void r1_software_texture_class::select_texture(r1_vram_handle_type handle,
336                                         float &smul, float &tmul)
337{
338  r1_tex_heap_used_node *u = (r1_tex_heap_used_node *)handle;
339
340  free_node *f = (free_node *)u->node;
341
342  smul = f->mip->width;
343  tmul = f->mip->height; 
344}
345
346r1_miplevel_t *r1_software_texture_class::get_texture(r1_texture_handle handle,
347                                                      w32 frame_counter,
348                                                      sw32 desired_width,
349                                                      sw32 &w, sw32 &h)
350{
351  r1_miplevel_t *mip = r1_texture_manager_class::get_texture(handle,frame_counter,desired_width,w,h);
352  if (!mip)
353    return 0;
354
355  r1_tex_heap_used_node *u = (r1_tex_heap_used_node *)mip->vram_handle; 
356 
357  if (u)
358    tex_heap_man->update_usage(u);
359
360  return mip;
361}
Note: See TracBrowser for help on using the repository browser.