source: golgotha/src/i4/video/win32/dx5_util.cc @ 80

Last change on this file since 80 was 80, checked in by Sam Hocevar, 15 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: 11.5 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/win32/dx5_util.hh"
10#include "video/win32/dx5_error.hh"
11#include "threads/threads.hh"
12#include "error/error.hh"
13
14#define DEPTH 16
15
16
17dx5_common_class       dx5_common;
18IDirectDraw2          *dx5_common_class::ddraw;
19IDirectDrawSurface3   *dx5_common_class::primary_surface, *dx5_common_class::back_surface,
20                      *dx5_common_class::front_surface;
21DDPIXELFORMAT          dx5_common_class::dd_fmt_565, dx5_common_class::dd_fmt_1555;
22i4_pixel_format        dx5_common_class::i4_fmt_565, dx5_common_class::i4_fmt_1555;
23
24
25
26IDirectDrawSurface3 *dx5_common_class::create_surface(dx5_surface_type type,
27                                                      int width, int height,
28                                                      int flags,
29                                                      DDPIXELFORMAT *format)
30{       
31  HRESULT result;
32  DDSURFACEDESC ddsd;
33  IDirectDrawSurface *surface;
34  IDirectDrawSurface3 *surface3;
35
36  memset(&ddsd,0,sizeof(DDSURFACEDESC));
37  ddsd.dwSize = sizeof(DDSURFACEDESC);
38
39  if (type==DX5_PAGE_FLIPPED_PRIMARY_SURFACE)
40  {
41    ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
42    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
43                          DDSCAPS_FLIP |
44                          DDSCAPS_COMPLEX |
45                          DDSCAPS_3DDEVICE |
46                          DDSCAPS_VIDEOMEMORY;
47    ddsd.dwBackBufferCount = 1;   
48  }
49  else if (type==DX5_BACKBUFFERED_PRIMARY_SURFACE)
50  {
51    ddsd.dwFlags = DDSD_CAPS;
52    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY;
53  }
54  else
55  {       
56    ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
57    ddsd.ddsCaps.dwCaps = 0;
58
59    if (format)
60    {
61      ddsd.dwFlags |= DDSD_PIXELFORMAT;
62      ddsd.ddpfPixelFormat = *format;
63    }
64
65    ddsd.dwWidth = width;
66    ddsd.dwHeight = height;     
67
68    if (flags & DX5_SYSTEM_RAM)
69      ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
70
71    if (flags & DX5_VRAM)
72      ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
73
74    if (flags & DX5_RENDERING_SURFACE)
75      ddsd.ddsCaps.dwCaps |= DDSCAPS_3DDEVICE;
76
77    if (type==DX5_TEXTURE)
78      ddsd.ddsCaps.dwCaps |= DDSCAPS_TEXTURE;
79  }
80
81
82  result = ddraw->CreateSurface(&ddsd, &surface, NULL);
83  if (!i4_dx5_check(result))
84    surface=0;
85
86  if (surface)
87  {
88    surface->QueryInterface(IID_IDirectDrawSurface3,(void **)&surface3); 
89    surface->Release();
90
91    if (flags & DX5_CLEAR)
92    {
93      DDBLTFX fx;
94      memset(&fx,0,sizeof(DDBLTFX));
95      fx.dwSize = sizeof(DDBLTFX);
96     
97      RECT r;
98      r.left   = 0;
99      r.top    = 0;
100      r.right  = width;
101      r.bottom = height;
102     
103      surface3->Blt(&r, 0, 0, DDBLT_COLORFILL,&fx);
104    }
105
106    if (type==DX5_PAGE_FLIPPED_PRIMARY_SURFACE)
107    {
108      primary_surface = surface3;
109   
110      // get the back buffer surface
111      DDSCAPS caps;
112      caps.dwCaps = DDSCAPS_BACKBUFFER;
113      result = primary_surface->GetAttachedSurface(&caps, &back_surface);
114      if (!i4_dx5_check(result))
115      {
116        primary_surface->Release();   primary_surface=0;
117        surface3=0;
118      }
119
120      caps.dwCaps = DDSCAPS_FRONTBUFFER;
121      result = primary_surface->GetAttachedSurface(&caps, &front_surface);
122      if (!i4_dx5_check(result))
123      {
124        back_surface->Release();      back_surface=0;
125        primary_surface->Release();   primary_surface=0;
126        surface3=0;
127      }
128
129    }
130    else if (type==DX5_BACKBUFFERED_PRIMARY_SURFACE)
131    {   
132      DDSURFACEDESC desc;
133
134      get_desc(surface3, desc);
135
136      primary_surface = surface3;
137      back_surface = create_surface(DX5_SURFACE, width, height,
138                                    DX5_RENDERING_SURFACE | DX5_VRAM | DX5_CLEAR);
139
140      if (!back_surface)
141      {
142        primary_surface->Release();
143        surface3=0;
144      }
145    }
146
147  }
148  else if (flags & DX5_VRAM)  // try to create it in system ram
149  {
150    i4_warning("failed to create surface in video memory");
151    surface3=create_surface(DX5_SURFACE, width, height,
152                            (flags & (~DX5_VRAM)) | DX5_SYSTEM_RAM, format);
153  }
154
155  return surface3;   
156}
157   
158
159void dx5_common_class::cleanup()
160{
161  if (back_surface)
162  {
163    back_surface->Release();
164    back_surface=0;
165  }
166
167  if (front_surface)
168  {
169    front_surface->Release();
170    front_surface=0;
171  }
172
173  if (primary_surface)
174  {
175    primary_surface->Release();
176    primary_surface=0;
177  } 
178
179  if (ddraw)
180  {
181    ddraw->Release();
182    ddraw=0;
183  }
184}
185 
186
187dx5_common_class::dx5_common_class()
188{
189  ddraw=0;
190  primary_surface=back_surface=front_surface=0;   
191
192  i4_fmt_565.pixel_depth = I4_16BIT; 
193  i4_fmt_565.red_mask    = 31 << 11;
194  i4_fmt_565.green_mask  = 63 << 5;
195  i4_fmt_565.blue_mask   = 31;
196  i4_fmt_565.alpha_mask  = 0;
197  i4_fmt_565.lookup = 0;
198  i4_fmt_565.calc_shift();
199
200  i4_fmt_1555.pixel_depth = I4_16BIT; 
201  i4_fmt_1555.red_mask    = 31 << 10;
202  i4_fmt_1555.green_mask  = 31 << 5;
203  i4_fmt_1555.blue_mask   = 31;
204  i4_fmt_1555.alpha_mask  = 0;
205  i4_fmt_1555.lookup = 0;
206  i4_fmt_1555.calc_shift();
207
208
209  memset(&dd_fmt_565,0,sizeof(DDPIXELFORMAT));
210  dd_fmt_565.dwSize = sizeof(DDPIXELFORMAT);
211  dd_fmt_565.dwFlags = DDPF_RGB;
212  dd_fmt_565.dwRGBBitCount = 16;
213  dd_fmt_565.dwRBitMask = 31 << 11;
214  dd_fmt_565.dwGBitMask = 63 << 5;
215  dd_fmt_565.dwBBitMask = 31;
216
217  memset(&dd_fmt_1555,0,sizeof(DDPIXELFORMAT));
218  dd_fmt_1555.dwSize = sizeof(DDPIXELFORMAT);
219  dd_fmt_1555.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
220  dd_fmt_1555.dwRGBBitCount     = 16;   
221  dd_fmt_1555.dwRBitMask        = 31 << 10;
222  dd_fmt_1555.dwGBitMask        = 31 << 5;
223  dd_fmt_1555.dwBBitMask        = 31;
224  dd_fmt_1555.dwRGBAlphaBitMask = 1 << 15;
225
226}
227
228
229//******************************* VIDEO MODE ENUMERATION ***************************
230static dx5_mode *dx_mode_list;
231
232HRESULT WINAPI dx5_vidmode_callback(LPDDSURFACEDESC lpDDSurfaceDesc,LPVOID lpContext)
233{
234  dx5_mode *m=new dx5_mode(dx_mode_list);
235  dx_mode_list=m; 
236  m->desc=*lpDDSurfaceDesc;
237
238  return DDENUMRET_OK; 
239}
240
241dx5_mode *dx5_common_class::get_mode_list(IDirectDraw2 *dd)
242{
243  dx_mode_list=0;
244
245  DDSURFACEDESC ddsd;
246  DDPIXELFORMAT p_format;
247
248  memset(&ddsd,0,sizeof(DDSURFACEDESC));
249  ddsd.dwSize   = sizeof(DDSURFACEDESC); 
250  ddsd.dwFlags  = DDSD_PIXELFORMAT;
251
252  memset(&p_format,0,sizeof(DDPIXELFORMAT));
253  p_format.dwSize = sizeof(DDPIXELFORMAT);
254  p_format.dwFlags = DDPF_RGB;
255  p_format.dwRGBBitCount = DEPTH;
256  ddsd.ddpfPixelFormat = p_format;
257
258  if (!i4_dx5_check(dd->EnumDisplayModes(0,&ddsd,0,(LPDDENUMMODESCALLBACK)dx5_vidmode_callback)))
259  {
260    free_mode_list(dx_mode_list);
261    dx_mode_list=0;
262  }
263
264  return dx_mode_list;
265}
266
267void dx5_common_class::free_mode_list(dx5_mode *list)
268{
269  while (list)
270  {
271    dx5_mode *p=list;
272    list=list->next;
273    delete p;
274  }
275}
276
277
278
279//************************** DRIVER ENUMERATION AND CREATION ************************
280static dx5_driver *dx_driver_list;
281
282BOOL WINAPI dd_device_callback(LPGUID lpGuid, LPSTR lpDeviceDesc,
283                               LPSTR lpDriverName, LPVOID lpUserArg)
284{
285  dx5_driver *d=new dx5_driver(dx_driver_list);
286  dx_driver_list=d;
287  d->lpGuid = lpGuid;
288  strcpy(d->DriverName, lpDriverName);
289  strcpy(d->DeviceDesc, lpDeviceDesc);
290  return DDENUMRET_OK; 
291}
292
293dx5_driver *dx5_common_class::get_driver_list()
294{
295  dx_driver_list=0;
296  if (!i4_dx5_check(DirectDrawEnumerate(dd_device_callback,0)))
297  {
298    free_driver_list(dx_driver_list);
299    dx_driver_list=0;
300  }
301  return dx_driver_list;
302}
303
304void dx5_common_class::free_driver_list(dx5_driver *list)
305{
306  while (list)
307  {
308    dx5_driver *n=list;
309    list=list->next;
310    delete n;
311  }
312}
313
314static IDirectDraw         *dx5_ddraw;
315
316BOOL WINAPI dd_create_callback(LPGUID lpGuid,   LPSTR lpDeviceDescription,
317                               LPSTR lpDriverName, LPVOID lpUserArg)
318{
319  char *desired_driver = (char *)lpUserArg;
320  if (!stricmp(desired_driver,lpDriverName))
321  {
322    HRESULT res = DirectDrawCreate(lpGuid, &dx5_ddraw, 0);
323    return DDENUMRET_CANCEL;
324  }
325  return DDENUMRET_OK; 
326}
327
328IDirectDraw2 *dx5_common_class::initialize_driver(dx5_driver *driver)
329{
330  if (!driver) return 0;
331
332  dx5_ddraw=0;
333  if (!i4_dx5_check(DirectDrawEnumerate(dd_create_callback,(void *)driver->DriverName)))
334    return 0;
335
336  if (!dx5_ddraw)
337    return 0;
338
339  IDirectDraw2 *dd=0;
340  if (!i4_dx5_check(dx5_ddraw->QueryInterface(IID_IDirectDraw2,(void **)&dd)))
341  {
342    dx5_ddraw->Release();
343    return 0;
344  }
345
346  dx5_ddraw->Release();  // we are only using DirectDraw2 interface, free this one
347
348  return dd;
349}
350
351static LPGUID dx5_hardware_guid;
352static dx5_d3d_info dx5_d3d;
353
354HRESULT __stdcall d3d_device_callback(LPGUID lpGuid,    LPSTR lpDeviceDescription,
355                                      LPSTR lpDeviceName, LPD3DDEVICEDESC lpD3DHWDeviceDesc,
356                                      LPD3DDEVICEDESC lpD3DHELDeviceDesc, LPVOID lpUserArg)
357{
358  if (strcmp(lpDeviceName, "Direct3D HAL")==0 && lpD3DHWDeviceDesc->dwDeviceZBufferBitDepth!=0)
359  {
360    dx5_d3d.lpGuid = lpGuid;
361    dx5_d3d.lpDeviceName = lpDeviceName;
362    dx5_d3d.hw_desc = *lpD3DHWDeviceDesc;
363    dx5_d3d.sw_desc = *lpD3DHELDeviceDesc;
364  }
365
366  return D3DENUMRET_OK;
367}
368
369
370dx5_d3d_info *dx5_common_class::get_driver_hardware_info(IDirectDraw2 *dd)
371
372  dx5_d3d.lpGuid=0;
373
374  IDirect3D2 *d3d;
375  if (!i4_dx5_check(dd->QueryInterface(IID_IDirect3D2,(void **)&d3d)))
376    return 0; 
377 
378  d3d->EnumDevices(d3d_device_callback,0);
379  d3d->Release();
380
381  if (dx5_d3d.lpGuid)
382    return &dx5_d3d;
383
384  return 0;
385}
386
387
388i4_dx5_image_class::i4_dx5_image_class(w16 _w, w16 _h, w32 flags)
389{
390  w=_w;
391  h=_h;
392
393  DDSURFACEDESC ddsd;
394 
395  dx5_common.get_surface_description(dx5_common.primary_surface,ddsd);
396
397  i4_pixel_format fmt;
398  fmt.pixel_depth = I4_16BIT; 
399  fmt.red_mask    = ddsd.ddpfPixelFormat.dwRBitMask;
400  fmt.green_mask  = ddsd.ddpfPixelFormat.dwGBitMask;
401  fmt.blue_mask   = ddsd.ddpfPixelFormat.dwBBitMask;
402  fmt.alpha_mask  = 0;
403  fmt.calc_shift();
404   
405  pal = i4_pal_man.register_pal(&fmt);
406
407  //we want to create the surface w/the same pixel format as the primary surface
408  surface = dx5_common.create_surface(DX5_SURFACE, w,h, flags, &ddsd.ddpfPixelFormat);
409
410  if (!surface) 
411    i4_warning("i4_dx5_image_class::create_surface failed");
412  else
413  {
414    lock();
415    unlock();
416  }
417}
418
419
420
421void i4_dx5_image_class::lock()
422{
423  DDSURFACEDESC ddsd;
424  memset(&ddsd, 0, sizeof(ddsd));
425  ddsd.dwSize=sizeof(ddsd);
426
427  if (!i4_dx5_check(surface->Lock(0, &ddsd,DDLOCK_WRITEONLY | DDLOCK_WAIT | DDLOCK_NOSYSLOCK,0)))
428    i4_error("couldn't lock surface");
429
430  data = (w8 *)ddsd.lpSurface;
431  bpl  = ddsd.lPitch; 
432}
433
434void i4_dx5_image_class::unlock()
435{
436  surface->Unlock(0);
437}
438
439
440
441IDirectDrawSurface3 *dx5_common_class::get_surface(i4_image_class *im)
442{
443  return ((i4_dx5_image_class *)im)->surface;
444
445}
446
447
448
449i4_image_class *dx5_common_class::create_image(int w, int h, w32 surface_flags)
450{
451  return new i4_dx5_image_class(w,h,surface_flags);
452}
Note: See TracBrowser for help on using the repository browser.