~ubuntu-branches/ubuntu/quantal/mesa/quantal

« back to all changes in this revision

Viewing changes to src/mesa/drivers/d3d/D3DInit.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2007-02-21 12:44:07 UTC
  • mfrom: (1.2.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 22.
  • Revision ID: james.westby@ubuntu.com-20070221124407-rgcacs32mycrtadl
ImportĀ upstreamĀ versionĀ 6.5.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*===========================================================================*/
2
 
/*                                                                           */
3
 
/* Mesa-3.0 DirectX 6 Driver                                       Build 5   */
4
 
/*                                                                           */
5
 
/* By Leigh McRae                                                            */
6
 
/*                                                                           */
7
 
/* http://www.altsoftware.com/                                               */
8
 
/*                                                                           */
9
 
/* Copyright (c) 1999-1998  alt.software inc.  All Rights Reserved           */
10
 
/*===========================================================================*/
11
 
#include "D3DHAL.h"
12
 
/*===========================================================================*/
13
 
/* Local function prototypes.                                                */
14
 
/*===========================================================================*/
15
 
static void     DestroyAllSurfaces( PMESAD3DHAL pHAL );
16
 
static void     DestroyDevice( PMESAD3DHAL pHAL );
17
 
static void     DestroyInterfaces( PMESAD3DHAL pHAL );
18
 
 
19
 
HRESULT WINAPI   EnumSurfacesHook( LPDIRECTDRAWSURFACE4 lpDDS, LPDDSURFACEDESC2 lpDDSDesc, LPVOID pVoid );
20
 
HRESULT CALLBACK EnumZBufferHook( DDPIXELFORMAT* pddpf, VOID *pVoid );
21
 
HRESULT CALLBACK EnumDeviceHook( GUID FAR* lpGuid, LPSTR lpDesc, LPSTR lpName, LPD3DDEVICEDESC lpD3DHWDesc, LPD3DDEVICEDESC lpD3DHELDesc,  void *pVoid );
22
 
/*===========================================================================*/
23
 
/* Globals.                                                                  */
24
 
/*===========================================================================*/
25
 
//char          *errorMsg;
26
 
/*===========================================================================*/
27
 
/*  This function is responable for allocating the actual MESAD3DHAL struct. */
28
 
/* Each Mesa context will have its own MESAD3DHAL struct so its like a mini  */
29
 
/* context to some extent. All one time allocations/operations get done here.*/
30
 
/*===========================================================================*/
31
 
/* RETURN: TRUE, FALSE.                                                      */
32
 
/*===========================================================================*/
33
 
extern "C" PMESAD3DSHARED InitHAL( HWND hwnd )
34
 
{
35
 
  PMESAD3DHAL   pHAL;
36
 
  ULONG         rc;
37
 
 
38
 
  DPF(( DBG_FUNC, "InitHAL();" ));
39
 
  DPF(( DBG_CNTX_INFO, "hwnd: %d", hwnd ));
40
 
 
41
 
  /* Allocate the structure and zero it out. */   
42
 
  pHAL = (PMESAD3DHAL)ALLOC( sizeof(MESAD3DHAL) );
43
 
  if ( pHAL == NULL )
44
 
  {   
45
 
    RIP( pHAL, "InitHAL->", "Memory Allocation" );
46
 
    return (PMESAD3DSHARED)NULL;
47
 
  }
48
 
  memset( pHAL, 0, sizeof(MESAD3DHAL) );
49
 
 
50
 
  /* Get the texture manager going. */
51
 
  rc = InitTMgrHAL( pHAL );
52
 
  if ( rc == FALSE )
53
 
  {   
54
 
    RIP( pHAL, "InitTMgrHAL->", "Failed" );
55
 
    return (PMESAD3DSHARED)NULL;
56
 
  }
57
 
 
58
 
  /* Fill in the window parameters if we can. */
59
 
  pHAL->shared.hwnd = hwnd;
60
 
 
61
 
  /* Parse the user's enviroment variables to generate a debug mask. */
62
 
  ReadDBGEnv();
63
 
  
64
 
  return (PMESAD3DSHARED)pHAL;
65
 
}
66
 
/*===========================================================================*/
67
 
/*  This function will unload all the resources that the MESAD3DHAL struct   */
68
 
/* has bound to it.  The actual structure itself will be freed.              */
69
 
/*===========================================================================*/
70
 
/* RETURN:                                                                   */
71
 
/*===========================================================================*/
72
 
extern "C" void TermHAL( PMESAD3DSHARED pShared )
73
 
{
74
 
  PMESAD3DHAL   pHAL = (PMESAD3DHAL)pShared;
75
 
 
76
 
  DPF(( DBG_FUNC, "TermHAL();" ));
77
 
 
78
 
  /* Check for an empty wrapper structure. */
79
 
  if ( pHAL == NULL )
80
 
    return;
81
 
 
82
 
  /* Kill this texture manager. */
83
 
  TermTMgrHAL( pHAL );
84
 
 
85
 
  /* Kill any DDraw stuff if exists. */
86
 
  DestroyDevice( pHAL );
87
 
  DestroyAllSurfaces( pHAL );
88
 
  DestroyInterfaces( pHAL );
89
 
 
90
 
  FREE( pHAL );
91
 
}
92
 
/*===========================================================================*/
93
 
/*  This function is used to init and resize the rendering surface as the two*/
94
 
/* are almost the same.  First the device and all the surfaces are destoryed */
95
 
/* if they already exist.  Next we create a OffScreen rendering surface and  */
96
 
/* save some pixelformat info to do color convertions. Next we start to take */
97
 
/* care of getting the most out of the hardware. I use bHardware to determine*/
98
 
/* the state of the device we found in the device enumeration.  The enum proc*/
99
 
/* will try for hardware first.  I next use a bForceSW to make the enum proc */
100
 
/* choose a software device.  So I will try some combinations with HW first  */
101
 
/* until I feel I have to set the bForceSW and call this function again.  If */
102
 
/* this function is called with no width or height then use the internals.   */
103
 
/*   NOTE:  The worst case is that all will be in SW (RGBDevice) and really  */
104
 
/*         I should forget the whole thing and fall back to a DDraw span type*/
105
 
/*         rendering but what is the point.  This way I always know I have a */
106
 
/*         D3DDevice and that makes things easier.  I do impliment the span  */
107
 
/*         rendering function for stuff that I haven't done support for such */
108
 
/*         as points and lines.                                              */
109
 
/*===========================================================================*/
110
 
/* RETURN: TRUE, FALSE                                                       */
111
 
/*===========================================================================*/
112
 
extern "C" BOOL CreateHAL( PMESAD3DSHARED pShared )
113
 
{
114
 
  PMESAD3DHAL           pHAL = (PMESAD3DHAL)pShared;
115
 
  DDSURFACEDESC2        ddsd2;
116
 
  D3DDEVICEDESC         D3DSWDevDesc;
117
 
  DDSCAPS2              ddscaps;
118
 
  DWORD                 dwCoopFlags,
119
 
                    dwWidth,
120
 
                    dwHeight;
121
 
  ULONG                 rc;
122
 
 
123
 
  DPF(( DBG_FUNC, "CreateHAL();" ));
124
 
 
125
 
#define InitDDSD2(f)      memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) ); \
126
 
                          ddsd2.dwSize  = sizeof( DDSURFACEDESC2 ); \
127
 
                          ddsd2.dwFlags = f;
128
 
 
129
 
  if ( pHAL == NULL )
130
 
    return FALSE;
131
 
 
132
 
  /* Use the internal rectangle struct. */
133
 
  dwWidth  = pShared->rectW.right - pShared->rectW.left;
134
 
  dwHeight = pShared->rectW.bottom - pShared->rectW.top;
135
 
 
136
 
  DPF(( DBG_CNTX_INFO, "Width: %d Height: %d", dwWidth, dwHeight ));
137
 
 
138
 
  /* The dimensions might still be the same so just leave. */
139
 
  if ( (dwWidth == pShared->dwWidth) && (dwHeight == pShared->dwHeight) )
140
 
  {
141
 
    DPF(( DBG_CNTX_WARN, "Context size hasn't changed" ));
142
 
    return TRUE;
143
 
  }
144
 
 
145
 
  /* If one of the dimensions are zero then leave. WM_SIZE should get us back here. */
146
 
  if ( (dwWidth == 0) || (dwHeight == 0) )
147
 
    return TRUE;
148
 
 
149
 
  /* Save the renders dimensions. */
150
 
  pShared->dwWidth  = dwWidth;
151
 
  pShared->dwHeight = dwHeight;
152
 
 
153
 
  DPF(( DBG_CNTX_INFO, "Creating Context:\n cx:%d cy:%d", pShared->dwWidth, pShared->dwHeight ));
154
 
 
155
 
  /*=================================*/
156
 
  /* Create all required interfaces. */
157
 
  /*=================================*/
158
 
 
159
 
  /* Kill any DDraw stuff if exists. */
160
 
  DestroyDevice( pHAL );
161
 
  DestroyAllSurfaces( pHAL );
162
 
  DestroyInterfaces( pHAL );
163
 
 
164
 
  /* Create a instance of DDraw using the Primary display driver. */
165
 
  rc = DirectDrawCreate( NULL, &pHAL->lpDD, NULL );
166
 
  if( FAILED(rc) )
167
 
  {
168
 
    RIP( pHAL, "DirectDrawCreate->", ErrorStringD3D(rc) );
169
 
    return FALSE;
170
 
  }
171
 
 
172
 
  /* Get the DDraw4 interface. */
173
 
  rc = pHAL->lpDD->QueryInterface( IID_IDirectDraw4, (void **)&pHAL->lpDD4 );
174
 
  if( FAILED(rc) )
175
 
  {
176
 
    RIP( pHAL, "QueryInterface (IID_IDirectDraw4) ->", ErrorStringD3D(rc) );
177
 
    return FALSE;
178
 
  }
179
 
 
180
 
  /* Get the Direct3D3 interface. */
181
 
  rc = pHAL->lpDD4->QueryInterface( IID_IDirect3D3, (void **)&pHAL->lpD3D3 );
182
 
  if( FAILED(rc) )
183
 
  {
184
 
    RIP( pHAL, "QueryInterface (IID_IDirect3D3) ->", ErrorStringD3D(rc) );
185
 
    return FALSE;
186
 
  }
187
 
 
188
 
  /* Set the Cooperative level. NOTE: we need to know if we are FS at this point.*/
189
 
  dwCoopFlags = (pShared->bWindow == TRUE) ? DDSCL_NORMAL : (DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
190
 
  rc = pHAL->lpDD4->SetCooperativeLevel( pShared->hwnd, dwCoopFlags );
191
 
  if ( FAILED(rc) )
192
 
  {
193
 
    RIP( pHAL, "SetCooperativeLevel->", ErrorStringD3D(rc) );
194
 
    return FALSE;
195
 
  }
196
 
 
197
 
  /*==================================================================*/
198
 
  /* Get the best device we can and note whether its hardware or not. */
199
 
  /*==================================================================*/
200
 
  pShared->bForceSW = FALSE;
201
 
  pHAL->lpD3D3->EnumDevices( EnumDeviceHook, (void *)pHAL );
202
 
  pShared->bHardware = IsEqualIID( pHAL->guid, IID_IDirect3DHALDevice );
203
 
  DPF(( DBG_CNTX_INFO, "bHardware: %s", (pShared->bHardware) ? "TRUE" : "FALSE" ));
204
 
  DPF(( DBG_CNTX_INFO, "bWindowed: %s", (pShared->bWindow) ? "TRUE" : "FALSE" ));
205
 
 
206
 
  /*========================================================================*/
207
 
  /* HARDWARE was found.                                                    */
208
 
  /*========================================================================*/
209
 
  if ( pShared->bHardware == TRUE )
210
 
  {
211
 
    /*===================================*/
212
 
    /* HARDWARE -> Z-BUFFER.             */
213
 
    /*===================================*/
214
 
 
215
 
    /* Get a Z-Buffer pixelformat. */
216
 
    memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) );
217
 
    ddsd2.dwSize = sizeof( DDSURFACEDESC2 );
218
 
    rc = pHAL->lpD3D3->EnumZBufferFormats( pHAL->guid, EnumZBufferHook, (VOID*)&ddsd2.ddpfPixelFormat );
219
 
    if ( FAILED(rc) )
220
 
    {
221
 
         RIP( pHAL, "EnumZBufferFormatsl->", ErrorStringD3D(rc) );
222
 
         return FALSE;
223
 
    }
224
 
        
225
 
    /* Setup our request structure for the Z-buffer surface. */
226
 
    ddsd2.dwFlags        = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
227
 
    ddsd2.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
228
 
    ddsd2.dwWidth        = dwWidth;
229
 
    ddsd2.dwHeight       = dwHeight;
230
 
    rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pHAL->lpDDSZbuffer, NULL );
231
 
    if ( !FAILED(rc) )
232
 
    {
233
 
         DPF(( DBG_CNTX_INFO, "HW ZBuffer" ));
234
 
 
235
 
         /*===================================*/
236
 
         /* HARDWARE -> Z-BUFFER -> FLIPABLE  */
237
 
         /*===================================*/
238
 
         if ( pShared->bWindow == FALSE )
239
 
         {
240
 
           InitDDSD2( DDSD_CAPS | DDSD_BACKBUFFERCOUNT );
241
 
           ddsd2.dwBackBufferCount = 1;
242
 
           ddsd2.ddsCaps.dwCaps    = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
243
 
           rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pHAL->lpDDSPrimary, NULL );
244
 
           if ( FAILED(rc) )
245
 
           {    
246
 
                /* Make sure we try the next fall back. */
247
 
                DPF(( DBG_CNTX_WARN, "HW Flip/Complex not available" ));
248
 
                pHAL->lpDDSPrimary = NULL;
249
 
           }
250
 
           else
251
 
           {
252
 
                /* Get the back buffer that was created. */
253
 
                ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
254
 
                rc = pHAL->lpDDSPrimary->GetAttachedSurface( &ddscaps, &pHAL->lpDDSRender );
255
 
                if ( FAILED(rc) )
256
 
                {       
257
 
                  DPF(( DBG_CNTX_WARN, "GetAttachedSurface failed -> HW Flip/Complex" ));
258
 
                  
259
 
                  /* Make sure we try the next fall back. */
260
 
                  pHAL->lpDDSPrimary->Release();
261
 
                  pHAL->lpDDSPrimary = NULL;
262
 
                }       
263
 
                else
264
 
                {
265
 
                  /*  I have had problems when a complex surface comes back  */
266
 
                  /* with the back buffer being created in SW.  Not sure why */
267
 
                  /* or how this is possable but I'm checking for it here.   */
268
 
                  memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) ); 
269
 
                  ddsd2.dwSize = sizeof( DDSURFACEDESC2 );
270
 
                  DX_RESTORE( pHAL->lpDDSRender );
271
 
                  rc = pHAL->lpDDSRender->GetSurfaceDesc( &ddsd2 );
272
 
                  if ( FAILED(rc) )
273
 
                  {
274
 
                    RIP( pHAL, "GetSurfaceDesc (RENDER) ->", ErrorStringD3D(rc) );
275
 
                    return FALSE;
276
 
                  }
277
 
 
278
 
                  /* If the surface is in VID then we are happy with are Flipable. */
279
 
                  if ( ddsd2.ddsCaps.dwCaps & DDSCAPS_LOCALVIDMEM )
280
 
                  {
281
 
                    pShared->bFlipable = TRUE;
282
 
                    DPF(( DBG_CNTX_INFO, "HW Flip/Complex!" ));
283
 
                  }
284
 
                  else
285
 
                  {
286
 
                    /* Kill this setup. */
287
 
                    pHAL->lpDDSPrimary->Release();
288
 
                    pHAL->lpDDSPrimary = NULL;
289
 
                  }
290
 
                }
291
 
           }
292
 
         }
293
 
 
294
 
         /*===================================*/
295
 
         /* HARDWARE -> Z-BUFFER -> BLT       */
296
 
         /*===================================*/
297
 
         if ( pHAL->lpDDSPrimary == NULL )
298
 
         {
299
 
           pShared->bFlipable = FALSE;
300
 
 
301
 
           /* Create the Primary (front buffer). */
302
 
           InitDDSD2( DDSD_CAPS );
303
 
           ddsd2.ddsCaps.dwCaps  = DDSCAPS_PRIMARYSURFACE;
304
 
           rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pHAL->lpDDSPrimary, NULL );
305
 
           if ( FAILED(rc) )
306
 
           {
307
 
                /* This is an error as we should be able to do this at minimum. */
308
 
                RIP( pHAL, "CreateSurface (PRIMARY) ->", ErrorStringD3D(rc) );
309
 
                return FALSE;
310
 
           }
311
 
 
312
 
           /* Create the Render (back buffer). */
313
 
           InitDDSD2( DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT );
314
 
           ddsd2.dwWidth            = dwWidth;
315
 
           ddsd2.dwHeight           = dwHeight;
316
 
           ddsd2.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
317
 
           rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pHAL->lpDDSRender, NULL );
318
 
           if ( FAILED(rc) )
319
 
           {
320
 
                DPF(( DBG_CNTX_WARN, "Failed HW Offscreen surface" ));
321
 
 
322
 
                /* Make sure we try the next fall back. */
323
 
                pHAL->lpDDSPrimary->Release();
324
 
                pHAL->lpDDSPrimary = NULL;
325
 
           }
326
 
           else
327
 
           {
328
 
                /*  Might as well check here too see if this surface is in */
329
 
                /* hardware.  If nothing else just to be consistant.       */
330
 
                memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) ); 
331
 
                ddsd2.dwSize = sizeof( DDSURFACEDESC2 );
332
 
                DX_RESTORE( pHAL->lpDDSRender );
333
 
                rc = pHAL->lpDDSRender->GetSurfaceDesc( &ddsd2 );
334
 
                if ( FAILED(rc) )
335
 
                {
336
 
                  RIP( pHAL, "GetSurfaceDesc (RENDER) ->", ErrorStringD3D(rc) );
337
 
                  return FALSE;
338
 
                }
339
 
 
340
 
                /* If the surface is in VID then we are happy. */
341
 
                if ( ddsd2.ddsCaps.dwCaps & DDSCAPS_LOCALVIDMEM )
342
 
                {
343
 
                  /*  Create a clipper object so that DDraw will be able to blt windows that */
344
 
                  /* have been clipped by the screen or other windows.                       */
345
 
                  pHAL->lpDD4->CreateClipper( 0, &pHAL->lpClipper, NULL );
346
 
                  pHAL->lpClipper->SetHWnd( 0, pShared->hwnd );
347
 
                  pHAL->lpDDSPrimary->SetClipper( pHAL->lpClipper );
348
 
                  pHAL->lpClipper->Release();
349
 
                  DPF(( DBG_CNTX_INFO, "HW RENDER surface" ));
350
 
                }
351
 
                else
352
 
                {
353
 
                  /* Kill this setup. */
354
 
                  pHAL->lpDDSRender->Release();
355
 
                  pHAL->lpDDSRender = NULL;
356
 
                  pHAL->lpDDSPrimary->Release();
357
 
                  pHAL->lpDDSPrimary = NULL;
358
 
                }
359
 
           }
360
 
         }      
361
 
 
362
 
         /*===================================*/
363
 
         /* Create D3DDEVICE -> HARDWARE.     */
364
 
         /*===================================*/
365
 
         if ( pHAL->lpDDSZbuffer && pHAL->lpDDSPrimary && pHAL->lpDDSRender )
366
 
         {
367
 
           DX_RESTORE( pHAL->lpDDSRender );
368
 
           DX_RESTORE( pHAL->lpDDSZbuffer );
369
 
 
370
 
           rc = pHAL->lpDDSRender->AddAttachedSurface( pHAL->lpDDSZbuffer );
371
 
           if ( FAILED(rc) )
372
 
           {
373
 
                RIP( pHAL, "AddAttachedSurface (ZBUFFER) ->", ErrorStringD3D(rc) );
374
 
                return FALSE;
375
 
           }
376
 
 
377
 
           rc = pHAL->lpD3D3->CreateDevice( IID_IDirect3DHALDevice, pHAL->lpDDSRender, &pHAL->lpD3DDevice, NULL );
378
 
           if ( rc != D3D_OK )
379
 
           {
380
 
                DPF(( DBG_CNTX_WARN, "Failed HW Device" ));
381
 
                pHAL->lpD3DDevice = NULL;
382
 
           }
383
 
           else
384
 
           {
385
 
                DPF(( DBG_CNTX_INFO, "HW Device" ));
386
 
           }
387
 
         }
388
 
    }   
389
 
  }
390
 
      
391
 
  /*========================================================================*/
392
 
  /* SOFTWARE fallback.                                                     */
393
 
  /*========================================================================*/
394
 
  if ( pHAL->lpD3DDevice == NULL )
395
 
  {
396
 
    DPF(( DBG_CNTX_INFO, "SW fallback :(" ));
397
 
 
398
 
    /* Make sure we have no surfaces allocated.  Just incase. */
399
 
    DestroyAllSurfaces( pHAL );
400
 
 
401
 
    /* Get a software device. */
402
 
    pShared->bFlipable = FALSE;
403
 
    pShared->bForceSW = TRUE;
404
 
    pHAL->lpD3D3->EnumDevices( EnumDeviceHook, (void *)pHAL );
405
 
    pShared->bHardware = IsEqualIID( pHAL->guid, IID_IDirect3DHALDevice );
406
 
 
407
 
     /*===================================*/
408
 
    /* SOFTWARE -> Z-BUFFER.             */
409
 
    /*===================================*/
410
 
 
411
 
    /*===================================*/
412
 
    /* SOFTWARE -> Z-BUFFER -> FLIPABLE  */
413
 
    /*===================================*/
414
 
    if ( pShared->bWindow == FALSE )
415
 
    {
416
 
         InitDDSD2( DDSD_CAPS | DDSD_BACKBUFFERCOUNT );
417
 
         ddsd2.dwBackBufferCount = 1;
418
 
         ddsd2.ddsCaps.dwCaps    = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
419
 
         ddsd2.ddpfPixelFormat.dwSize  = sizeof( DDPIXELFORMAT );
420
 
         ddsd2.ddpfPixelFormat.dwFlags = (DDPF_RGB | DDPF_ALPHAPIXELS);
421
 
         rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pHAL->lpDDSPrimary, NULL );
422
 
         if ( FAILED(rc) )
423
 
         {      
424
 
           DPF(( DBG_CNTX_WARN, "Failed SW Flip/Complex" ));
425
 
 
426
 
           /* Make sure we try the next fall back. */
427
 
           pHAL->lpDDSPrimary = NULL;
428
 
         }
429
 
         else
430
 
         {
431
 
           ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
432
 
           rc = pHAL->lpDDSPrimary->GetAttachedSurface( &ddscaps, &pHAL->lpDDSRender );
433
 
           if ( FAILED(rc) )
434
 
           {    
435
 
                /* Make sure we try the next fall back. */
436
 
                DPF(( DBG_CNTX_WARN, "GetAttachedSurface failed -> SW Flip/Complex" ));
437
 
                pHAL->lpDDSPrimary->Release();
438
 
                pHAL->lpDDSPrimary = NULL;
439
 
           }    
440
 
           else
441
 
           {
442
 
                DPF(( DBG_CNTX_INFO, "SW Flip/Complex" ));
443
 
                pShared->bFlipable = TRUE;
444
 
           }
445
 
         }
446
 
    }           
447
 
 
448
 
    /*===================================*/
449
 
    /* SOFTWARE -> Z-BUFFER -> BLT       */
450
 
    /*===================================*/
451
 
    if ( pHAL->lpDDSPrimary == NULL )
452
 
    {
453
 
         /* Create the Primary (front buffer). */
454
 
         InitDDSD2( DDSD_CAPS );
455
 
         ddsd2.ddsCaps.dwCaps  = DDSCAPS_PRIMARYSURFACE;
456
 
         rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pHAL->lpDDSPrimary, NULL );
457
 
         if ( FAILED(rc) )
458
 
         {
459
 
           /* This is an error as we should be able to do this at minimum. */
460
 
           RIP( pHAL, "CreateSurface (PRIMARY) ->", ErrorStringD3D(rc) );
461
 
           return FALSE;
462
 
         }
463
 
 
464
 
         /* Create the Render (back buffer). */
465
 
         InitDDSD2( DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT );
466
 
         ddsd2.dwWidth                                  = dwWidth;
467
 
         ddsd2.dwHeight                         = dwHeight;
468
 
         ddsd2.ddsCaps.dwCaps                   = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
469
 
         ddsd2.ddpfPixelFormat.dwSize   = sizeof( DDPIXELFORMAT );
470
 
         ddsd2.ddpfPixelFormat.dwFlags  = (DDPF_RGB | DDPF_ALPHAPIXELS);
471
 
         rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pHAL->lpDDSRender, NULL );
472
 
         if ( FAILED(rc) )
473
 
         {
474
 
           /* That was our last hope. */
475
 
           RIP( pHAL, "CreateSurface (RENDER) ->", ErrorStringD3D(rc) );
476
 
           return FALSE;
477
 
         }
478
 
         else
479
 
         {
480
 
           DPF(( DBG_CNTX_INFO, "SW RENDER surface" ));
481
 
 
482
 
           /*  Create a clipper object so that DDraw will be able to blt windows that */
483
 
           /* have been clipped by the screen or other windows.                       */
484
 
           pHAL->lpDD4->CreateClipper( 0, &pHAL->lpClipper, NULL );
485
 
           pHAL->lpClipper->SetHWnd( 0, pShared->hwnd );
486
 
           pHAL->lpDDSPrimary->SetClipper( pHAL->lpClipper );
487
 
           pHAL->lpClipper->Release();
488
 
         }
489
 
    }           
490
 
        
491
 
    /*===================================*/
492
 
    /* Create D3DDEVICE -> SOFTWARE.     */
493
 
    /*===================================*/
494
 
    if ( pHAL->lpDDSPrimary && pHAL->lpDDSRender )
495
 
    {
496
 
         DX_RESTORE( pHAL->lpDDSRender );
497
 
         rc = pHAL->lpD3D3->CreateDevice( IID_IDirect3DRGBDevice, pHAL->lpDDSRender, &pHAL->lpD3DDevice, NULL );
498
 
         if ( rc != D3D_OK )
499
 
         {
500
 
           /* That was our last hope. */
501
 
           RIP( pHAL, "CreateDevice (IID_IDirect3DRGBDevice) ->", ErrorStringD3D(rc) );
502
 
           return FALSE;
503
 
         }
504
 
         
505
 
         DPF(( DBG_CNTX_INFO, "SW Device" ));
506
 
    }   
507
 
  }
508
 
 
509
 
  /*==============================================================================*/
510
 
  /* Get a copy of the render pixelformat so that wgl.c can call GetPixelInfoD3D. */
511
 
  /*==============================================================================*/
512
 
  memset( &pHAL->ddpf, 0, sizeof(DDPIXELFORMAT) );
513
 
  pHAL->ddpf.dwSize = sizeof( DDPIXELFORMAT );
514
 
  rc = pHAL->lpDDSRender->GetPixelFormat( &pHAL->ddpf );
515
 
  if ( FAILED(rc) )
516
 
  {
517
 
    RIP( pHAL, "GetPixelFormat ->", ErrorStringD3D(rc) );
518
 
    return FALSE;
519
 
  }
520
 
  DebugPixelFormat( "Using OFFSCREEN", &pHAL->ddpf );
521
 
  DebugPixelFormat( "Using ZBUFFER", &ddsd2.ddpfPixelFormat );
522
 
 
523
 
  /* Get a copy of what the D3DDevice supports for later use. */
524
 
  memset( &D3DSWDevDesc, 0, sizeof(D3DDEVICEDESC) );
525
 
  memset( &pHAL->D3DHWDevDesc, 0, sizeof(D3DDEVICEDESC) );
526
 
  D3DSWDevDesc.dwSize       = sizeof( D3DDEVICEDESC );
527
 
  pHAL->D3DHWDevDesc.dwSize = sizeof( D3DDEVICEDESC );
528
 
  rc = pHAL->lpD3DDevice->GetCaps( &pHAL->D3DHWDevDesc, &D3DSWDevDesc );
529
 
  if ( FAILED(rc) )
530
 
  {
531
 
    RIP( pHAL, "GetCaps ->", ErrorStringD3D(rc) );
532
 
    return FALSE;
533
 
  }
534
 
 
535
 
  /* Get a copy of the pixel convertion stuff for direct buffer access. */
536
 
  Solve8BitChannelPixelFormat( &pHAL->ddpf, &pShared->pixel );
537
 
  AlphaBlendTableHAL( pHAL );
538
 
 
539
 
  /* We must prime the Begin/End scene for SwapBuffers to work. */
540
 
  rc = pHAL->lpD3DDevice->BeginScene();   
541
 
  if ( FAILED(rc) )
542
 
  {
543
 
    RIP( pHAL, "BeginScene ->", ErrorStringD3D(rc) );
544
 
    return FALSE;
545
 
  }
546
 
 
547
 
#undef InitDDSD2
548
 
 
549
 
  return TRUE;
550
 
}
551
 
/*===========================================================================*/
552
 
/*  This function will make sure a viewport is created and set for the device*/
553
 
/* in the supplied structure.  If a rect is supplied then it will be used for*/
554
 
/* the viewport otherwise the current setting in the strucute will be used.  */
555
 
/* Note that the rect is relative to the window.  So left/top must be 0,0 to */
556
 
/* use the whole window else there is scissoring going down.                 */
557
 
/*===========================================================================*/
558
 
/* RETURN: TRUE, FALSE.                                                      */
559
 
/*===========================================================================*/
560
 
extern "C" BOOL SetViewportHAL( PMESAD3DSHARED pShared, RECT *pRect, float minZ, float maxZ  )
561
 
{
562
 
  PMESAD3DHAL   pHAL = (PMESAD3DHAL)pShared;
563
 
  D3DVIEWPORT2 vdData;
564
 
  ULONG         rc;
565
 
  POINT         pt;
566
 
 
567
 
  DPF(( DBG_FUNC, "SetViewportHAL();" ));
568
 
 
569
 
  /* Make sure we have enough info. */
570
 
  if ( !pHAL || !pHAL->lpDDSPrimary || !pHAL->lpD3DDevice )
571
 
  {
572
 
    DPF(( DBG_CNTX_WARN, "SetViewport() -> NULL Pointer" ));
573
 
    return FALSE;
574
 
  }
575
 
 
576
 
  /* TODO: this is just a temp fix to stop redundant changes. */
577
 
  if ( pRect &&
578
 
          (pShared->rectV.left   == pRect->left)    &&
579
 
          (pShared->rectV.right  == pRect->right)   &&
580
 
          (pShared->rectV.top    == pRect->top)     &&
581
 
          (pShared->rectV.bottom == pRect->bottom) )
582
 
  {
583
 
    DPF(( DBG_CNTX_WARN, "Redundant viewport" ));
584
 
    return TRUE;
585
 
  }
586
 
 
587
 
  DPF(( DBG_CNTX_INFO, "Current Viewport:" ));
588
 
  DPF(( DBG_CNTX_INFO, "x: %d y: %d", pShared->rectV.left, pShared->rectV.top ));
589
 
  DPF(( DBG_CNTX_INFO, "cx: %d cy: %d", (pShared->rectV.right-pShared->rectV.left), (pShared->rectV.bottom-pShared->rectV.top) ));
590
 
  DPF(( DBG_CNTX_INFO, "New Viewport:" ));
591
 
  DPF(( DBG_CNTX_INFO, "x: %d y: %d", pRect->left, pRect->top ));
592
 
  DPF(( DBG_CNTX_INFO, "cx: %d cy: %d", (pRect->right-pRect->left), (pRect->bottom-pRect->top) ));
593
 
 
594
 
  /* Update the current viewport rect if one is supplied. */
595
 
  if ( pRect )      
596
 
    memcpy( &pShared->rectV, pRect, sizeof(RECT) );
597
 
         
598
 
  /* Build the request structure. */
599
 
  memset( &vdData, 0, sizeof(D3DVIEWPORT2) );
600
 
  vdData.dwSize   = sizeof(D3DVIEWPORT2);  
601
 
  vdData.dwX      = pShared->rectV.left;
602
 
  vdData.dwY      = pShared->rectV.top;
603
 
  vdData.dwWidth  = (pShared->rectV.right - pShared->rectV.left);
604
 
  vdData.dwHeight = (pShared->rectV.bottom - pShared->rectV.top);
605
 
 
606
 
  if ( !vdData.dwWidth || !vdData.dwHeight )
607
 
  {
608
 
    GetClientRect( pShared->hwnd, &pShared->rectW );
609
 
    pt.x = pt.y = 0;
610
 
    ClientToScreen( pShared->hwnd, &pt );
611
 
    OffsetRect( &pShared->rectW, pt.x, pt.y);
612
 
    vdData.dwX      = pShared->rectW.left;
613
 
    vdData.dwY      = pShared->rectW.top;
614
 
    vdData.dwWidth  = (pShared->rectW.right - pShared->rectW.left);
615
 
    vdData.dwHeight = (pShared->rectW.bottom - pShared->rectW.top);
616
 
    memcpy( &pShared->rectV, &pShared->rectW, sizeof(RECT) );
617
 
  }
618
 
 
619
 
  // The dvClipX, dvClipY, dvClipWidth, dvClipHeight, dvMinZ, 
620
 
  // and dvMaxZ members define the non-normalized post-perspective 
621
 
  // 3-D view volume which is visible to the viewer. In most cases, 
622
 
  // dvClipX is set to -1.0 and dvClipY is set to the inverse of 
623
 
  // the viewport's aspect ratio on the target surface, which can be 
624
 
  // calculated by dividing the dwHeight member by dwWidth. Similarly, 
625
 
  // the dvClipWidth member is typically 2.0 and dvClipHeight is set 
626
 
  // to twice the aspect ratio set in dwClipY. The dvMinZ and dvMaxZ 
627
 
  // are usually set to 0.0 and 1.0.
628
 
  vdData.dvClipX      = -1.0f;
629
 
  vdData.dvClipWidth  = 2.0f;
630
 
  vdData.dvClipY      = 1.0f;
631
 
  vdData.dvClipHeight = 2.0f;
632
 
  vdData.dvMaxZ       = maxZ;
633
 
  vdData.dvMinZ       = minZ;
634
 
 
635
 
  DPF(( DBG_CNTX_INFO, "zMin: %f zMax: %f", minZ, maxZ ));
636
 
 
637
 
  /*  I'm going to destroy the viewport everytime as when we size we will */
638
 
  /* have a new D3DDevice.  As this area doesn't need to be fast...       */
639
 
  if ( pHAL->lpViewport )
640
 
  {
641
 
    DPF(( DBG_CNTX_INFO, "DeleteViewport" ));
642
 
 
643
 
    pHAL->lpD3DDevice->DeleteViewport( pHAL->lpViewport );
644
 
    rc = pHAL->lpViewport->Release();
645
 
    pHAL->lpViewport = NULL;
646
 
  }
647
 
 
648
 
  rc = pHAL->lpD3D3->CreateViewport( &pHAL->lpViewport, NULL );
649
 
  if ( rc != D3D_OK )
650
 
  {
651
 
    DPF(( DBG_CNTX_ERROR, "CreateViewport Failed" ));
652
 
    return FALSE;
653
 
  }
654
 
 
655
 
  /* Update the device with the new viewport. */
656
 
  pHAL->lpD3DDevice->AddViewport( pHAL->lpViewport );
657
 
  pHAL->lpViewport->SetViewport2( &vdData );
658
 
  pHAL->lpD3DDevice->SetCurrentViewport( pHAL->lpViewport );
659
 
 
660
 
  return TRUE; 
661
 
}
662
 
/*===========================================================================*/
663
 
/*                                                                           */
664
 
/*                                                                           */
665
 
/*===========================================================================*/
666
 
/* RETURN:                                                                   */
667
 
/*===========================================================================*/
668
 
HRESULT WINAPI EnumSurfacesHook( LPDIRECTDRAWSURFACE4 lpDDS, LPDDSURFACEDESC2 lpDDSDesc, LPVOID pVoid )
669
 
{
670
 
  DDSURFACEDESC2 *pddsd2 = (DDSURFACEDESC2 *)pVoid;
671
 
 
672
 
  DPF(( DBG_FUNC, "EnumSurfacesHook();" ));
673
 
 
674
 
  if ( (lpDDSDesc->ddpfPixelFormat.dwFlags == pddsd2->ddpfPixelFormat.dwFlags) && (lpDDSDesc->ddsCaps.dwCaps == pddsd2->ddsCaps.dwCaps) )
675
 
  {
676
 
    /* Save the pixelformat now so that we know we have one. */
677
 
    memcpy( pddsd2, lpDDSDesc, sizeof(DDSURFACEDESC2) );
678
 
 
679
 
    return D3DENUMRET_CANCEL;
680
 
  }
681
 
 
682
 
  return D3DENUMRET_OK;
683
 
}
684
 
/*===========================================================================*/
685
 
/*  This is the callback proc to get a Z-Buffer.  Thats it.                  */
686
 
/*===========================================================================*/
687
 
/* RETURN:                                                                   */
688
 
/*===========================================================================*/
689
 
HRESULT CALLBACK  EnumZBufferHook( DDPIXELFORMAT* pddpf, VOID *pVoid )
690
 
{
691
 
  DDPIXELFORMAT  *pddpfChoice = (DDPIXELFORMAT *)pVoid;
692
 
 
693
 
  DPF(( DBG_FUNC, "EnumZBufferHook();" ));
694
 
 
695
 
  /* If this is ANY type of depth-buffer, stop. */
696
 
  if( pddpf->dwFlags == DDPF_ZBUFFER )
697
 
  {
698
 
    /* Save the pixelformat now so that we know we have one. */
699
 
    memcpy( pddpfChoice, pddpf, sizeof(DDPIXELFORMAT) );
700
 
 
701
 
    /* I feel if the hardware supports this low then lets use it.  Could get ugly. */
702
 
    if( pddpf->dwZBufferBitDepth >= 8 )
703
 
    {
704
 
         return D3DENUMRET_CANCEL;
705
 
    }
706
 
  }
707
 
 
708
 
   return D3DENUMRET_OK;
709
 
}
710
 
/*===========================================================================*/
711
 
/*  This function handles the callback for the D3DDevice enumeration.  Good  */
712
 
/* god who's idea was this?  The D3D wrapper has two variable related to what*/
713
 
/* kind of device we want and have.  First we have a Bool that is set if we  */
714
 
/* have allocated a HW device.  We always look for the HW device first.  The */
715
 
/* other variable is used to force SW.  If we have run into a case that we   */
716
 
/* want to fallback to SW then we set this.  We will fallback if we cannot   */
717
 
/* texture in video memory (among others).                                   */
718
 
/*===========================================================================*/
719
 
/* RETURN:                                                                   */
720
 
/*===========================================================================*/
721
 
HRESULT CALLBACK  EnumDeviceHook( GUID FAR* lpGuid, LPSTR lpDesc, LPSTR lpName, LPD3DDEVICEDESC lpD3DHWDesc, LPD3DDEVICEDESC lpD3DHELDesc,  void *pVoid )
722
 
{
723
 
  PMESAD3DHAL           pHAL = (PMESAD3DHAL)pVoid;
724
 
  LPD3DDEVICEDESC   pChoice = lpD3DHWDesc;
725
 
 
726
 
  DPF(( DBG_FUNC, "EnumDeviceHook();" ));
727
 
 
728
 
  /* Determine if which device description is valid. */
729
 
  if ( pChoice->dcmColorModel == 0 )
730
 
    pChoice = lpD3DHELDesc;
731
 
 
732
 
  /* Make sure we always have a GUID. */
733
 
  memcpy( &pHAL->guid, lpGuid, sizeof(GUID) );
734
 
 
735
 
  /* This controls whether we will except HW or not. */
736
 
  if ( pHAL->shared.bForceSW == TRUE )
737
 
  {
738
 
    return (pChoice == lpD3DHELDesc) ? D3DENUMRET_CANCEL : D3DENUMRET_OK;
739
 
  }
740
 
 
741
 
  /* Always try for hardware. */
742
 
  if ( pChoice == lpD3DHWDesc )
743
 
  {
744
 
    return D3DENUMRET_CANCEL;
745
 
  }
746
 
 
747
 
  return D3DENUMRET_OK;
748
 
}
749
 
/*===========================================================================*/
750
 
/*  This function will destroy any and all surfaces that this context has    */
751
 
/* allocated.  If there is a clipper object then it will also be destoryed as*/
752
 
/* it is part of the Primary Surface.                                        */
753
 
/*===========================================================================*/
754
 
/* RETURN:                                                                   */
755
 
/*===========================================================================*/
756
 
static void DestroyAllSurfaces( PMESAD3DHAL pHAL )
757
 
{
758
 
  LONG  refCount;
759
 
 
760
 
  DPF(( DBG_FUNC, "DestroyAllSurfaces();" ));
761
 
 
762
 
  DX_RESTORE( pHAL->lpDDSPrimary );
763
 
  DX_RESTORE( pHAL->lpDDSRender );
764
 
  DX_RESTORE( pHAL->lpDDSZbuffer);
765
 
 
766
 
  if ( pHAL->lpDDSRender )
767
 
  {
768
 
    pHAL->lpDDSRender->Unlock( NULL );
769
 
 
770
 
    /* If this isn't a Flipable surface then we must clean up the render. */
771
 
    if ( pHAL->shared.bFlipable == FALSE)
772
 
    {
773
 
         if ( pHAL->lpDDSZbuffer )
774
 
         {
775
 
           DPF(( DBG_CNTX_INFO, "Remove attached surfaces from RENDER" ));
776
 
           pHAL->lpDDSRender->DeleteAttachedSurface( 0, NULL );
777
 
         }
778
 
 
779
 
         DPF(( DBG_CNTX_INFO, "Release RENDER" ));
780
 
         refCount = pHAL->lpDDSRender->Release();
781
 
         pHAL->lpDDSRender = NULL;
782
 
    }
783
 
  }
784
 
 
785
 
  if ( pHAL->lpDDSZbuffer )
786
 
  {
787
 
    DPF(( DBG_CNTX_INFO, "Release ZBuffer" ));
788
 
    pHAL->lpDDSZbuffer->Unlock( NULL );
789
 
    refCount = pHAL->lpDDSZbuffer->Release();
790
 
    pHAL->lpDDSZbuffer = NULL;
791
 
  }
792
 
 
793
 
  if ( pHAL->lpClipper )
794
 
  {
795
 
    DPF(( DBG_CNTX_INFO, "Release Clipper" ));
796
 
    refCount = pHAL->lpClipper->Release();
797
 
    pHAL->lpClipper = NULL;
798
 
  }
799
 
 
800
 
  if ( pHAL->lpDDSPrimary )
801
 
  {
802
 
    pHAL->lpDDSPrimary->Unlock( NULL );
803
 
 
804
 
    DPF(( DBG_CNTX_INFO, "Release PRIMARY" ));
805
 
    refCount = pHAL->lpDDSPrimary->Release();
806
 
    pHAL->lpDDSPrimary = NULL;
807
 
  }
808
 
}
809
 
/*===========================================================================*/
810
 
/*  This function will destroy the current D3DDevice and any resources that  */
811
 
/* belong to it.                                                             */
812
 
/*===========================================================================*/
813
 
/* RETURN:                                                                   */
814
 
/*===========================================================================*/
815
 
static void DestroyDevice( PMESAD3DHAL pHAL )
816
 
{
817
 
  LONG  refCount;
818
 
 
819
 
  DPF(( DBG_FUNC, "DestroyDevice();" ));
820
 
 
821
 
  /* Kill the D3D stuff if exists. */
822
 
  if ( pHAL->lpViewport )
823
 
  {
824
 
    DPF(( DBG_CNTX_INFO, "Delete Viewport" ));
825
 
    pHAL->lpD3DDevice->DeleteViewport( pHAL->lpViewport );
826
 
 
827
 
    DPF(( DBG_CNTX_INFO, "Release Viewport" ));
828
 
    refCount = pHAL->lpViewport->Release();
829
 
    pHAL->lpViewport = NULL;
830
 
  }
831
 
 
832
 
  if ( pHAL->lpD3DDevice != NULL )
833
 
  {
834
 
    DPF(( DBG_CNTX_INFO, "Release D3DDevice" ));
835
 
    refCount = pHAL->lpD3DDevice->EndScene();  
836
 
    refCount = pHAL->lpD3DDevice->Release();
837
 
    pHAL->lpD3DDevice = NULL;
838
 
  }
839
 
}
840
 
/*===========================================================================*/
841
 
/*  This function will destroy the current D3DDevice and any resources that  */
842
 
/* belong to it.                                                             */
843
 
/*===========================================================================*/
844
 
/* RETURN:                                                                   */
845
 
/*===========================================================================*/
846
 
static void DestroyInterfaces( PMESAD3DHAL pHAL )
847
 
{
848
 
  LONG  refCount;
849
 
 
850
 
  DPF(( DBG_FUNC, "DestroyInterfaces();" ));
851
 
 
852
 
  if ( pHAL->lpD3D3 != NULL )
853
 
  {
854
 
    DPF(( DBG_CNTX_INFO, "Release Direct3D3" ));
855
 
    refCount = pHAL->lpD3D3->Release();
856
 
    pHAL->lpD3D3 = NULL;
857
 
  }
858
 
 
859
 
  if ( pHAL->lpDD4 != NULL )
860
 
  {
861
 
    DPF(( DBG_CNTX_INFO, "Release DDraw4" ));
862
 
    refCount = pHAL->lpDD4->Release();
863
 
    pHAL->lpDD4 = NULL;
864
 
  }
865
 
 
866
 
  if ( pHAL->lpDD != NULL )
867
 
  {
868
 
    DPF(( DBG_CNTX_INFO, "Release DDraw" ));
869
 
    refCount = pHAL->lpDD->Release();
870
 
    pHAL->lpDD = NULL;
871
 
  }
872
 
}
873
 
/*===========================================================================*/
874
 
/*  This function will first send (not post) a message to the client window  */
875
 
/* that this context is using.  The client will respond by unbinding itself  */
876
 
/* and binding the 'default' context.  This allows the API to be supported   */
877
 
/* until the window can be destroyed.  Finally we post the quit message to   */
878
 
/* the client in hopes to end the application.                               */
879
 
/*===========================================================================*/
880
 
/* RETURN:                                                                   */
881
 
/*===========================================================================*/
882
 
void  FatalShutDown( PMESAD3DHAL pHAL )
883
 
{
884
 
  /* Whip this baby in too try and support the API until we die... */
885
 
  if ( pHAL )
886
 
    SendMessage( pHAL->shared.hwnd, UM_FATALSHUTDOWN, 0L, 0L );
887
 
 
888
 
  /* Close the client application down. */
889
 
  PostQuitMessage( 0 );
890
 
}
891