source: golgotha/src/i4/video/glide/glide_display.cc @ 80

Last change on this file since 80 was 80, checked in by Sam Hocevar, 14 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: 12.7 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_display.hh"
10#include "image/image.hh"
11#include "time/profile.hh"
12#include "image/context.hh"
13#include "image/image16.hh"
14
15#ifdef _WINDOWS
16#include "video/glide/glidefunc.cc"
17#endif
18
19i4_profile_class pf_glide_flush_lock_write("glide_flush :: lock(WRITE)");
20i4_profile_class pf_glide_flush_mouse("glide_flush :: mouse draw");
21i4_profile_class pf_glide_flush_mouse_save("glide_flush :: mouse save");
22i4_profile_class pf_glide_flush_copy("glide_flush :: copy_vram");
23i4_profile_class pf_glide_flush_flip("glide_flush :: page_flip");
24
25i4_glide_display_class *i4_glide_display=0;
26
27struct gr_buf_status_type
28{
29  sw8            state;  // -1 = not locked, else 
30                         //    I4_FRAME_BUFFER_READ,
31                         // or I4_FRAME_BUFFER_WRITE
32  i4_image_class *im;
33  int gr_lock_type;
34
35} gr_buf[2];    // I4_FRONT_FRAME_BUFFER=0, I4_BACK_FRAME_BUFFER=1
36
37
38i4_image_class *i4_glide_display_class::lock_frame_buffer(i4_frame_buffer_type type,
39                                                          i4_frame_access_type access)
40{
41  if (gr_buf[type].state!=access)
42  {
43    if (gr_buf[type].state!=-1)
44      unlock_frame_buffer(type);
45
46    int gr_access = access==I4_FRAME_BUFFER_READ ? GR_LFB_READ_ONLY : GR_LFB_WRITE_ONLY;
47    int gr_buf_t = type == I4_FRONT_FRAME_BUFFER ? GR_BUFFER_FRONTBUFFER : GR_BUFFER_BACKBUFFER;
48
49    GrLfbInfo_t info;
50    info.size = sizeof(GrLfbInfo_t);
51
52    if (!grLfbLock(gr_access,
53                   gr_buf_t,
54                   GR_LFBWRITEMODE_565,
55                   GR_ORIGIN_UPPER_LEFT,
56                   FXFALSE,
57                   &info))
58      return 0;
59
60
61    gr_buf[type].im->bpl=info.strideInBytes;
62    gr_buf[type].im->data=info.lfbPtr;
63    gr_buf[type].gr_lock_type=gr_access;
64    gr_buf[type].state=access;
65  }
66
67  return gr_buf[type].im;
68}
69
70void i4_glide_display_class::unlock_frame_buffer(i4_frame_buffer_type type)
71{
72  if (gr_buf[type].state==-1)  // already unlocked?
73    return;   
74
75  int gr_buf_t = type == I4_FRONT_FRAME_BUFFER ? GR_BUFFER_FRONTBUFFER : GR_BUFFER_BACKBUFFER;
76 
77  grLfbUnlock(gr_buf[type].gr_lock_type, gr_buf_t);
78  gr_buf[type].im->data=0;
79  gr_buf[type].state=-1;
80}
81
82
83i4_bool procs_loaded = i4_F;
84
85#ifdef _WINDOWS
86void FreeTheGlideDll();
87FxBool GetProcAddresses();
88#else
89void FreeTheGlideDll() { ; }
90FxBool GetProcAddresses() { return 1; }
91#endif
92
93void i4_glide_display_class::init()
94{
95  if (procs_loaded)
96  {
97    GrHwConfiguration config;   
98    grSstQueryBoards(&config);
99
100    if (config.num_sst>0)
101    {
102      me.add_to_list("3dfx Native", 0, this, i4_display_list);
103    }
104  }
105}
106
107
108i4_glide_display_class::i4_glide_display_class()
109{
110  i4_glide_display=this;
111  mcursor=0;
112  mouse_save1=0;
113  mouse_save2=0;
114  prev_mouse_save=0;
115  procs_loaded = GetProcAddresses();
116  last_mouse_x=last_mouse_y=40;
117}
118
119i4_bool i4_glide_display_class::close()
120{
121  next_frame_copy.delete_list();
122
123  if (context)
124    delete context;
125  context=0;
126
127  for (int i=0; i<2; i++)
128    if (gr_buf[i].im)
129    {
130      delete gr_buf[i].im;
131      gr_buf[i].im=0;
132    }
133
134  if (fake_screen)
135  {
136    delete fake_screen;
137    fake_screen=0;
138  }
139 
140  if (grSstControl)
141    grSstControl(GR_CONTROL_DEACTIVATE);
142
143  if (grSstWinClose)
144    grSstWinClose();
145
146  if (grGlideShutdown)
147    grGlideShutdown();
148 
149  destroy_window();
150
151  return i4_T;
152}
153
154
155static GrFog_t    fogtable[GR_FOG_TABLE_SIZE];
156
157i4_bool i4_glide_display_class::initialize_mode()
158{
159  if (!create_window())
160    return i4_F; 
161
162  grGlideInit();
163  GrHwConfiguration config;   
164  grSstQueryHardware(&config);
165  if (config.num_sst<=0)
166  {
167    i4_error("Couldnt find your 3dfx board");
168  }
169  grSstSelect( 0 );
170 
171  grSstWinOpen(window_handle(),
172               tmp.glide_mode,
173               GR_REFRESH_60Hz,
174               GR_COLORFORMAT_ARGB,
175               GR_ORIGIN_UPPER_LEFT,
176               2, 1 );
177
178  grDepthBufferMode( GR_DEPTHBUFFER_WBUFFER );
179  grDepthBufferFunction( GR_CMP_LEQUAL);
180  grDepthMask( FXTRUE );
181  grCullMode(GR_CULL_DISABLE);
182  //  grCullMode( GR_CULL_POSITIVE );
183  grTexMipMapMode(GR_TMU0, GR_MIPMAP_DISABLE, FXFALSE);
184  grHints(GR_HINT_STWHINT, GR_STWHINT_W_DIFF_TMU0 |
185          GR_STWHINT_ST_DIFF_TMU0);
186
187  guColorCombineFunction( GR_COLORCOMBINE_TEXTURE_TIMES_ITRGB );
188  grTexCombineFunction(GR_TMU0, GR_TEXTURECOMBINE_DECAL);
189  grAlphaCombine(GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_ONE,
190                 GR_COMBINE_LOCAL_NONE,GR_COMBINE_OTHER_CONSTANT,0);
191  grAlphaBlendFunction(GR_BLEND_ONE,GR_BLEND_ZERO,GR_BLEND_ZERO,GR_BLEND_ZERO);
192
193  //  grTexClampMode(GR_TMU0,GR_TEXTURECLAMP_WRAP,GR_TEXTURECLAMP_WRAP);
194
195
196  //grGlideShamelessPlug(1);
197 // setup fog
198  //grFogMode( GR_FOG_WITH_TABLE );
199        //grFogColorValue( 0x00666666 );
200        w32 i;
201  w32 fog_density=0;
202  for (i=0;i<64;i++)
203  {
204    fog_density += 4;
205    if (fog_density>255) fog_density=255;
206    fogtable[i] = (w8)fog_density;
207  }
208  //guFogGenerateExp(fogtable,0.001f);
209        //grFogTable( fogtable );       
210
211  i4_pixel_format fmt;
212  fmt.pixel_depth=I4_16BIT;
213  fmt.red_mask=tmp.red_mask;
214  fmt.green_mask=tmp.green_mask;
215  fmt.blue_mask=tmp.blue_mask;
216  fmt.alpha_mask=0;
217  fmt.calc_shift();
218
219  pal = i4_pal_man.register_pal(&fmt);
220
221  fake_screen=i4_create_image(tmp.xres, tmp.yres, pal);
222  gr_buf[0].im=i4_create_image(tmp.xres, tmp.yres, pal, 0, 0);
223  gr_buf[0].state=-1;
224
225  gr_buf[1].im=i4_create_image(tmp.xres, tmp.yres, pal, 0, 0);
226  gr_buf[1].state=-1;
227
228   
229  context=new i4_draw_context_class(0,0,tmp.xres-1,tmp.yres-1);
230  context->both_dirty=new i4_rect_list_class;
231
232  memcpy(&cur_mode, &tmp, sizeof(cur_mode)); 
233 
234  return i4_T;
235}
236
237void i4_glide_display_class::remove_cursor(sw32 x, sw32 y, i4_image_class *mouse_save)
238{
239  if (mouse_save && mcursor)
240  {
241    i4_draw_context_class no_clip_context(0,0, width()-1, height()-1);     
242
243    pf_glide_flush_lock_write.start();   
244    i4_image_class *draw_to=lock_frame_buffer(I4_BACK_FRAME_BUFFER, I4_FRAME_BUFFER_WRITE);
245    pf_glide_flush_lock_write.stop();
246
247    int w=mouse_save->w, h=mouse_save->h;
248    ((i4_image16 *)mouse_save)->put_part_one_pixel_at_a_time(draw_to,
249                                                             x,y,0,0,w-1,h-1, no_clip_context);
250    unlock_frame_buffer(I4_BACK_FRAME_BUFFER);
251  }
252}
253
254void i4_glide_display_class::save_and_draw_cursor(sw32 x, sw32 y, i4_image_class *&mouse_save)
255{
256  if (mcursor)
257  {
258    pf_glide_flush_mouse_save.start();
259
260    if (mouse_save && (mouse_save->width()!=mcursor->pict->width() ||
261                       mouse_save->height()!=mcursor->pict->height()))
262    {
263      delete mouse_save;
264      mouse_save=i4_create_image(mcursor->pict->width(), mcursor->pict->height(), pal);
265    }
266    else if (!mouse_save)
267      mouse_save=i4_create_image(mcursor->pict->width(), mcursor->pict->height(), pal);
268
269    i4_draw_context_class no_clip_context(0,0, width()-1, height()-1);
270    sw32 x1=x, y1=y;
271    sw32 x2=x1+mcursor->pict->width()-1, y2=y1+mcursor->pict->height()-1;
272
273
274    if (x2 > width()-1)
275      x2=width()-1;
276    if (y2 > height()-1)
277      y2=height()-1;
278    if (x<width()-1 && y<height()-1)
279    {
280      i4_image16 *im=(i4_image16 *)lock_frame_buffer(I4_BACK_FRAME_BUFFER, I4_FRAME_BUFFER_READ);
281      im->put_part_one_pixel_at_a_time(mouse_save, 0,0, x1,y1,x2,y2, no_clip_context);
282      unlock_frame_buffer(I4_BACK_FRAME_BUFFER);
283    }
284           
285    i4_image16 *dest=(i4_image16 *)lock_frame_buffer(I4_BACK_FRAME_BUFFER, I4_FRAME_BUFFER_WRITE);
286    mcursor->pict->put_image_trans(dest,  x1,y1, mcursor->trans, no_clip_context);
287    unlock_frame_buffer(I4_BACK_FRAME_BUFFER);
288
289    pf_glide_flush_mouse_save.stop();
290  }
291}
292
293void i4_glide_display_class::flush()
294{
295  i4_rect_list_class::area_iter a;
296
297  sw32 mouse_x, mouse_y;
298  get_mouse_pos(mouse_x, mouse_y);
299
300
301  context->both_dirty->intersect_area(0,0,width()-1,height()-1);
302  w16 *middle_buffer=(w16 *)fake_screen->data;
303
304  pf_glide_flush_lock_write.start();
305  i4_image_class *bbuf=lock_frame_buffer(I4_BACK_FRAME_BUFFER, I4_FRAME_BUFFER_WRITE);
306  int bpl=bbuf->bpl;
307  void *bptr = bbuf->data;
308  pf_glide_flush_lock_write.stop();
309
310  pf_glide_flush_copy.start();
311  a=context->both_dirty->list.begin();
312  for (;a!=context->both_dirty->list.end();++a)
313    next_frame_copy.add_area(a->x1, a->y1, a->x2, a->y2);
314
315
316  a=next_frame_copy.list.begin();
317  for (;a!=context->both_dirty->list.end();++a)
318  {
319    for (w32 y=a->y1; y<=a->y2; y++)
320    {
321      w32 sx=a->x1, ex=(a->x2);
322
323      w16 *src=(w16 *)(((w16 *)middle_buffer)+y*cur_mode.xres + sx);
324      w16 *dst=(w16 *)(((w8 *)bptr)+y*bpl + sx*2);
325
326      while (sx<=ex)
327      {
328        *(dst++)=*(src++);
329        sx++;
330      }
331    }   
332  } 
333
334  next_frame_copy.swap(context->both_dirty);
335  context->both_dirty->delete_list();
336
337  pf_glide_flush_copy.stop();
338
339
340  pf_glide_flush_mouse.start();
341
342  i4_image_class **cur_save;
343  // if this is the first time to save, or last save wave to mouse_save2 then use 1
344  if (!prev_mouse_save || prev_mouse_save==mouse_save2)
345    cur_save=&mouse_save1;
346  else
347    cur_save=&mouse_save2;
348
349  save_and_draw_cursor(mouse_x - (sw32)mcursor->hot_x,
350                       mouse_y - (sw32)mcursor->hot_y, *cur_save);
351
352
353  pf_glide_flush_mouse.stop();
354
355  unlock_frame_buffer(I4_BACK_FRAME_BUFFER);
356 
357  pf_glide_flush_flip.start();
358  //  while (grBufferNumPending());
359  grBufferSwap(0);
360  pf_glide_flush_flip.stop();
361
362  pf_glide_flush_mouse.start();
363  if (prev_mouse_save)
364    remove_cursor(last_mouse_x, last_mouse_y, prev_mouse_save);
365  pf_glide_flush_mouse.stop();
366
367  prev_mouse_save=*cur_save;
368  last_mouse_x=mouse_x - (sw32)mcursor->hot_x;
369  last_mouse_y=mouse_y - (sw32)mcursor->hot_y;
370}
371
372
373i4_image_class *i4_glide_display_class::get_screen()
374{     
375  return fake_screen;
376}
377
378i4_bool i4_glide_display_class::set_mouse_shape(i4_cursor_class *cursor)
379{
380  if (mcursor)
381    delete mcursor;
382 
383  mcursor=cursor->copy(get_palette());
384 
385  return i4_T;
386}
387
388void i4_glide_display_class::uninit()
389{
390  if (mcursor)
391    delete mcursor;
392  if (mouse_save1)
393    delete mouse_save1;
394  if (mouse_save2)
395    delete mouse_save2;
396
397  mouse_save1 = 0;
398  mouse_save2 = 0;
399  mcursor = 0;
400}
401
402i4_glide_display_class::~i4_glide_display_class()
403{
404  FreeTheGlideDll();
405  procs_loaded = i4_F;
406}
407
408i4_display_class::mode *i4_glide_display_class::get_first_mode(int driver_id)
409{
410  tmp.glide_mode=GR_RESOLUTION_320x200;
411  tmp.xres=320;
412  tmp.yres=200;
413  tmp.flags=mode::PAGE_FLIPPED;
414  tmp.red_mask=31<<11;
415  tmp.green_mask=63<<5;
416  tmp.blue_mask=31;
417  strcpy(tmp.name, "320 X 200 16bit");
418  return &tmp;
419}
420
421i4_display_class::mode *i4_glide_display_class::get_next_mode()
422{
423  switch (tmp.glide_mode)
424  {
425    case GR_RESOLUTION_320x200 :
426      tmp.glide_mode=GR_RESOLUTION_320x240;
427      tmp.yres=240;
428      break;
429     
430    case GR_RESOLUTION_320x240 :
431      tmp.glide_mode=GR_RESOLUTION_400x256;
432      tmp.xres=400; tmp.yres=256;
433      break;
434
435    case GR_RESOLUTION_400x256 :
436      tmp.glide_mode=GR_RESOLUTION_512x384;
437      tmp.xres=512; tmp.yres=384;
438      break;
439
440
441    case GR_RESOLUTION_512x384 :
442      tmp.glide_mode=GR_RESOLUTION_640x200;
443      tmp.xres=640; tmp.yres=200;
444      break;
445
446    case GR_RESOLUTION_640x200 :
447      tmp.glide_mode=GR_RESOLUTION_640x350;
448      tmp.xres=640; tmp.yres=350;
449      break;
450
451    case GR_RESOLUTION_640x350 :
452      tmp.glide_mode=GR_RESOLUTION_640x400;
453      tmp.xres=640; tmp.yres=400;
454      break;
455
456    case GR_RESOLUTION_640x400 :
457      tmp.glide_mode=GR_RESOLUTION_640x480;
458      tmp.xres=640; tmp.yres=480;
459      break;
460
461    case GR_RESOLUTION_640x480 :
462      tmp.glide_mode=GR_RESOLUTION_800x600;
463      tmp.xres=800; tmp.yres=600;
464      break;
465
466    case GR_RESOLUTION_800x600 :
467      tmp.glide_mode=GR_RESOLUTION_960x720;
468      tmp.xres=960; tmp.yres=720;
469      break;
470
471    case GR_RESOLUTION_960x720 :
472      tmp.glide_mode=GR_RESOLUTION_856x480;
473      tmp.xres=856; tmp.yres=480;
474      break;
475
476    case GR_RESOLUTION_856x480 :
477      tmp.glide_mode=GR_RESOLUTION_512x256;
478      tmp.xres=512; tmp.yres=256;
479      break;
480
481
482    case GR_RESOLUTION_512x256 :
483      return 0;
484
485  }
486
487  sprintf(tmp.name, "%d X %d 16bit", tmp.xres, tmp.yres);
488
489  return &tmp;
490}
491
Note: See TracBrowser for help on using the repository browser.