source: golgotha/src/render/software/win32_specific.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: 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 <windows.h>
10#include <ddraw.h>
11#include <math.h>
12#include <memory.h>
13
14#include "r1_clip.hh"
15#include "r1_win.hh"
16
17#include "device/processor.hh"
18
19#include "software/r1_software.hh"
20#include "software/r1_software_texture.hh"
21#include "software/r1_software_globals.hh"
22#include "software/mappers.hh"
23#include "software/span_buffer.hh"
24#include "software/inline_fpu.hh"
25#include "software/win32_specific.hh"
26
27#include "video/win32/dx5.hh"
28#include "video/win32/dx5_util.hh"
29
30#include "time/profile.hh"
31
32static i4_profile_class pf_software_flush_spans("software::flush_spans");
33static i4_profile_class pf_software_draw("software::draw()");
34static i4_profile_class pf_software_blt("software::blt()");
35
36void r1_software_lock_render_buffer()
37
38  if (r1_software_render_buffer_is_locked) return;
39 
40  DDSURFACEDESC ddsd;
41  memset(&ddsd,0,sizeof(DDSURFACEDESC));
42  ddsd.dwSize = sizeof(DDSURFACEDESC);
43
44
45  r1_software_render_surface->Lock(NULL,&ddsd,DDLOCK_WAIT | DDLOCK_NOSYSLOCK,0);
46 
47  r1_software_render_buffer_ptr       = (w16 *)ddsd.lpSurface;
48  r1_software_render_buffer_bpl       = ddsd.lPitch;
49  r1_software_render_buffer_wpl       = ddsd.lPitch>>1;   
50 
51  if (r1_software_render_expand_type==R1_COPY_1x1_SCANLINE_SKIP)
52    r1_software_render_buffer_wpl *= 2;
53 
54  r1_software_render_buffer_height    = ddsd.dwHeight; 
55  r1_software_render_buffer_is_locked = i4_T;
56}
57
58void r1_software_unlock_render_buffer()
59{
60  if (!r1_software_render_buffer_is_locked) return;
61  r1_software_render_surface->Unlock(NULL);
62  r1_software_render_buffer_is_locked = i4_F; 
63}
64
65i4_bool r1_software_class::init(i4_display_class *display)
66{
67  if (display!=i4_dx5_display || i4_dx5_display->using_accelerated_driver())
68    return i4_F;
69 
70  fmt = display->get_palette()->source;
71 
72  init_span_buffer();
73
74  init_color_tints();
75
76  tmanager = new r1_software_texture_class(display->get_palette());
77 
78  texture_mode = 0;
79 
80  write_mask = R1_WRITE_W | R1_COMPARE_W | R1_WRITE_COLOR;
81  set_write_mode(write_mask);
82
83  shade_mode = R1_COLORED_SHADING;
84  set_shading_mode(shade_mode);
85
86  alpha_mode = R1_ALPHA_DISABLED;
87  set_alpha_mode(alpha_mode);
88
89  inverse_leftover_lookup_init(); //init the 1/<blah> table
90  initialize_function_pointers(i4_F); //init the function pointer tables, default to intel functions
91
92  return i4_T;
93}
94
95
96i4_bool r1_software_class::expand_type_supported(r1_expand_type type)
97{
98  if (type==R1_COPY_2x2)
99  {
100    DDCAPS card_caps, HELcaps;
101    memset(&card_caps, 0, sizeof(card_caps));
102    card_caps.dwSize=sizeof(DDCAPS); 
103    memset(&HELcaps, 0, sizeof(HELcaps));
104    HELcaps.dwSize=sizeof(DDCAPS); 
105    dx5_common.ddraw->GetCaps(&card_caps, &HELcaps);
106   
107    if (card_caps.dwCaps & DDCAPS_BLTSTRETCH)
108      return i4_T;
109    else
110      return i4_F;
111  }
112
113  if (type==R1_COPY_1x1 || type==R1_COPY_1x1_SCANLINE_SKIP)
114    return i4_T;
115
116  return i4_F;
117}
118
119
120
121
122
123r1_software_render_window_class::r1_software_render_window_class(
124                               w16 w, w16 h,r1_expand_type expand_type,
125                               r1_render_api_class *api)
126                               :r1_render_window_class(w,h,expand_type,api)
127{
128  sw32 wi,hi;
129  w32  flags;
130
131  if (expand_type==R1_COPY_2x2)      // if stretching determine if driver support bltstretch
132  {
133    DDCAPS card_caps, HELcaps;
134    memset(&card_caps, 0, sizeof(card_caps));
135    card_caps.dwSize=sizeof(DDCAPS); 
136    memset(&HELcaps, 0, sizeof(HELcaps));
137    HELcaps.dwSize=sizeof(DDCAPS); 
138    dx5_common.ddraw->GetCaps(&card_caps, &HELcaps);
139   
140    if (card_caps.dwCaps & DDCAPS_BLTSTRETCH)
141    {
142      flags = DX5_VRAM;
143      wi = w>>1;
144      hi = h>>1;
145    }
146    else
147    {     
148      flags = DX5_SYSTEM_RAM;
149      wi = w>>1;
150      hi = h>>1;
151    }       
152  }
153  else
154  {
155    wi = w;
156    hi = h;
157    flags = DX5_VRAM;
158  }
159 
160  surface = dx5_common.create_surface(DX5_SURFACE, wi,hi, flags); 
161 
162  if (surface==0)
163    i4_error("Unable to create surface for r1_software_render_window_class");
164
165  DDBLTFX fx;
166  memset(&fx,0,sizeof(DDBLTFX));
167  fx.dwSize = sizeof(DDBLTFX);
168   
169  fx.dwFillColor = 0x0000;
170  surface->Blt(NULL,NULL,NULL,DDBLT_WAIT | DDBLT_COLORFILL,&fx);   
171}
172
173r1_render_window_class *r1_software_class::create_render_window(int w, int h,
174                                             r1_expand_type expand_type)
175{
176  r1_software_render_window_class *new_window; 
177  if (w & 1) w++;
178  if (h & 1) h++;
179  new_window = new r1_software_render_window_class(w,h, expand_type, this); 
180  return new_window;
181}
182
183void r1_software_render_window_class::receive_event(i4_event *ev)
184{
185  if (expand_type==R1_COPY_2x2 && ev->type()==i4_event::MOUSE_MOVE)
186  {
187    CAST_PTR(mev, i4_mouse_move_event_class, ev);
188
189    int o_lx=mev->lx, o_ly=mev->ly, o_x=mev->x, o_y=mev->y;
190
191    mev->lx/=2;
192    mev->ly/=2;
193    mev->x/=2;
194    mev->y/=2;
195
196    i4_parent_window_class::receive_event(ev);
197
198    mev->lx=o_lx;
199    mev->ly=o_ly;
200    mev->x=o_x;
201    mev->y=o_y;
202  }
203  else i4_parent_window_class::receive_event(ev);
204}
205
206
207void r1_software_class::copy_part(i4_image_class *im,
208                                  int x, int y,             // position on screen
209                                  int x1, int y1,           // area of image to copy
210                                  int x2, int y2)
211{
212  //this better be true
213
214
215  RECT srcRect;
216  srcRect.top     = y1;
217  srcRect.bottom  = y2+1;
218  srcRect.left    = x1;
219  srcRect.right   = x2+1;
220
221  i4_bool lock_check = r1_software_render_buffer_is_locked;
222 
223  IDirectDrawSurface3 *temp_surf=0;
224  r1_software_render_surface->QueryInterface(IID_IDirectDrawSurface3,(void **)&temp_surf);
225
226  switch (r1_software_render_expand_type)
227  {   
228    case R1_COPY_1x1:     
229    case R1_COPY_2x2:     
230    case R1_COPY_1x1_SCANLINE_SKIP:
231    if (lock_check) r1_software_unlock_render_buffer();   
232   
233
234    temp_surf->BltFast(x,
235                       y,
236                       dx5_common.get_surface(im),
237                       &srcRect,
238                       DDBLTFAST_NOCOLORKEY);
239   
240    if (lock_check) r1_software_lock_render_buffer();
241    break;
242  }
243
244  temp_surf->Release();
245}
246
247
248void r1_software_render_window_class::draw(i4_draw_context_class &context)
249{
250  if (GetAsyncKeyState('L') & 1)
251  {
252    do_amd3d = !do_amd3d;
253   
254    i4_cpu_info_struct s;
255    i4_get_cpu_info(&s);
256
257    if ((s.cpu_flags & i4_cpu_info_struct::AMD3D)==0)
258      do_amd3d = i4_F;     
259   
260    r1_software_class_instance.initialize_function_pointers(do_amd3d); //amd3d functions
261
262    if (do_amd3d)
263      i4_warning("amd3d optimizations on");
264    else
265      i4_warning("amd3d optimizations off");
266  }
267
268  pf_software_draw.start();
269
270  r1_software_render_surface = surface;   
271  r1_software_render_expand_type = expand_type;     
272
273#ifdef DEBUG
274  r1_software_class_instance.lock_cheat = i4_F;
275#endif
276
277  r1_software_lock_render_buffer(); 
278
279  if (r1_software_class_instance.lock_cheat)
280    r1_software_unlock_render_buffer();
281
282  r1_software_class_instance.width_compare  = width();
283  r1_software_class_instance.height_compare = height();
284
285  r1_software_class_instance.modify_features(R1_PERSPECTIVE_CORRECT, 1);
286  r1_software_class_instance.modify_features(R1_SPANS, 1);
287
288  clear_spans();
289
290  r1_software_class_instance.context = &context; 
291  r1_render_window_class::draw(context); 
292  r1_software_class_instance.context = 0;
293
294  //set this to false so that set_color_tint() actuall does work
295 
296  i4_bool spans_still_on = r1_software_class_instance.is_feature_on(R1_SPANS);
297
298  r1_software_class_instance.modify_features(R1_SPANS, 0);
299
300  pf_software_flush_spans.start(); 
301  flush_spans(); 
302  pf_software_flush_spans.stop();
303 
304  //clear this so that no funny business happens with leftover
305  //color tint settings
306  r1_software_class_instance.set_color_tint(0);
307
308  //restore whatever state it was in
309  r1_software_class_instance.modify_features(R1_SPANS, spans_still_on);
310
311  //flush lines
312  if (num_buffered_lines)
313  {
314    sw32 i;
315    for (i=0;i<num_buffered_lines;i++)
316    { 
317      r1_software_class_instance.draw_line(software_lines[i].x0,
318                                           software_lines[i].y0,
319                                           software_lines[i].x1,
320                                           software_lines[i].y1,
321                                           software_lines[i].start_color);
322    }
323    num_buffered_lines=0;
324  }
325 
326  if (!r1_software_class_instance.lock_cheat)
327    r1_software_unlock_render_buffer();
328
329  RECT          srcRect;
330  RECT          destRect;
331
332  pf_software_blt.start();
333
334 
335  IDirectDrawSurface3 *surface3=0;
336  surface->QueryInterface(IID_IDirectDrawSurface3,(void **)&surface3);
337
338  i4_rect_list_class::area_iter cl;
339  i4_rect_list_class *clip=&context.clip;
340 
341  if (surface3)
342  switch (expand_type)
343  {
344    case R1_COPY_1x1_SCANLINE_SKIP:
345    case R1_COPY_1x1:     
346      for (cl = clip->list.begin(); cl !=  clip->list.end(); ++cl)
347      {
348        srcRect.left   = cl->x1;
349        srcRect.right  = cl->x2+1;
350        srcRect.top    = cl->y1;
351        srcRect.bottom = cl->y2+1;
352       
353        dx5_common.back_surface->BltFast(context.xoff+cl->x1,context.yoff+cl->y1,
354                                         surface3,&srcRect,
355                                         DDBLTFAST_NOCOLORKEY);
356      }
357      break;
358
359
360    case R1_COPY_2x2:     
361      for (cl = clip->list.begin(); cl !=  clip->list.end(); ++cl)
362      {
363        srcRect.left   = cl->x1/2;
364        srcRect.right  = (cl->x2+2)/2;
365        srcRect.top    = cl->y1/2;
366        srcRect.bottom = (cl->y2+2)/2;
367         
368        destRect.left   = context.xoff+cl->x1;
369        destRect.top    = context.yoff+cl->y1;
370        destRect.right  = (context.xoff+cl->x2+1)&(~1);
371        destRect.bottom = (context.yoff+cl->y2+1)&(~1);
372             
373        dx5_common.back_surface->Blt(&destRect, surface3, &srcRect, DDBLT_ASYNC | DDBLT_WAIT, NULL);     
374      }
375      break;
376  }
377  surface3->Release();
378 
379  pf_software_blt.stop();
380
381  r1_software_render_surface = 0;
382  pf_software_draw.stop();
383}
384
385r1_software_render_window_class::~r1_software_render_window_class()
386{
387  if (surface)
388    surface->Release();
389
390  surface=0;
391}
392
393void r1_software_class::clear_area(int x1, int y1, int x2, int y2, w32 color, float z)
394
395  if ((write_mask & R1_WRITE_COLOR) == 0) return;
396
397  if (write_mask & R1_COMPARE_W)   // need to use spans to do this
398  {
399    w32             old_const_color = get_constant_color(); 
400    r1_alpha_type   old_alpha_mode  = get_alpha_mode();
401    r1_shading_type old_shade_mode  = get_shade_mode();
402 
403    set_shading_mode(R1_CONSTANT_SHADING);
404    set_alpha_mode(R1_ALPHA_DISABLED); 
405 
406    set_constant_color(color);
407
408    disable_texture();
409
410    r1_vert v[4];
411
412    z -= 0.5;
413    if (z<r1_near_clip_z)
414      z = r1_near_clip_z;
415
416    v[3].px=x1;   v[3].py=y1;    v[3].v.z = z; v[3].w = 1/z;
417    v[2].px=x2+1; v[2].py=y1;    v[2].v.z = z; v[2].w = 1/z;
418    v[1].px=x2+1; v[1].py=y2+1;  v[1].v.z = z; v[1].w = 1/z;
419    v[0].px=x1;   v[0].py=y2+1;  v[0].v.z = z; v[0].w = 1/z;
420 
421    render_sprite(v);
422 
423    set_shading_mode(old_shade_mode);
424    set_constant_color(old_const_color);
425    set_alpha_mode(old_alpha_mode);
426  }
427  else
428  {
429    RECT dst;
430    dst.left=x1;// + context->xoff;
431    dst.right=x2/* + context->xoff*/+1;
432    dst.top=y1;// + context->xoff;
433    dst.bottom=y2/* + context->yoff*/+1;
434
435    DDBLTFX fx;
436    memset(&fx,0,sizeof(DDBLTFX));
437    fx.dwSize = sizeof(DDBLTFX);
438   
439    fx.dwFillColor = color;
440   
441    i4_bool lock_check = r1_software_render_buffer_is_locked;
442
443    if (lock_check) r1_software_unlock_render_buffer();
444   
445    r1_software_render_surface->Blt(&dst,NULL,NULL,DDBLT_WAIT | DDBLT_COLORFILL,&fx);
446   
447    if (lock_check) r1_software_lock_render_buffer();
448  }
449
450}
451
452i4_image_class *r1_software_class::create_compatible_image(w16 w, w16 h)
453
454  i4_image_class *a = dx5_common.create_image(w,h, DX5_VRAM);
455  if (!dx5_common.get_surface(a))
456  {
457    delete a;
458    a = dx5_common.create_image(w,h, DX5_SYSTEM_RAM);
459    if (!dx5_common.get_surface(a))
460    {
461      delete a;
462      return NULL;
463    }
464  }
465 
466  return a;
467}
468
469
Note: See TracBrowser for help on using the repository browser.