1 /*===========================================================================*/
3 /* Mesa-3.0 DirectX 6 Driver Build 5 */
7 /* http://www.altsoftware.com/ */
9 /* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
10 /*===========================================================================*/
12 /*===========================================================================*/
13 /* Local function prototypes. */
14 /*===========================================================================*/
15 static void DestroyAllSurfaces( PMESAD3DHAL pHAL
);
16 static void DestroyDevice( PMESAD3DHAL pHAL
);
17 static void DestroyInterfaces( PMESAD3DHAL pHAL
);
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 /*===========================================================================*/
24 /*===========================================================================*/
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
)
38 DPF(( DBG_FUNC
, "InitHAL();" ));
39 DPF(( DBG_CNTX_INFO
, "hwnd: %d", hwnd
));
41 /* Allocate the structure and zero it out. */
42 pHAL
= (PMESAD3DHAL
)ALLOC( sizeof(MESAD3DHAL
) );
45 RIP( pHAL
, "InitHAL->", "Memory Allocation" );
46 return (PMESAD3DSHARED
)NULL
;
48 memset( pHAL
, 0, sizeof(MESAD3DHAL
) );
50 /* Get the texture manager going. */
51 rc
= InitTMgrHAL( pHAL
);
54 RIP( pHAL
, "InitTMgrHAL->", "Failed" );
55 return (PMESAD3DSHARED
)NULL
;
58 /* Fill in the window parameters if we can. */
59 pHAL
->shared
.hwnd
= hwnd
;
61 /* Parse the user's enviroment variables to generate a debug mask. */
64 return (PMESAD3DSHARED
)pHAL
;
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 /*===========================================================================*/
71 /*===========================================================================*/
72 extern "C" void TermHAL( PMESAD3DSHARED pShared
)
74 PMESAD3DHAL pHAL
= (PMESAD3DHAL
)pShared
;
76 DPF(( DBG_FUNC
, "TermHAL();" ));
78 /* Check for an empty wrapper structure. */
82 /* Kill this texture manager. */
85 /* Kill any DDraw stuff if exists. */
86 DestroyDevice( pHAL
);
87 DestroyAllSurfaces( pHAL
);
88 DestroyInterfaces( pHAL
);
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
)
114 PMESAD3DHAL pHAL
= (PMESAD3DHAL
)pShared
;
115 DDSURFACEDESC2 ddsd2
;
116 D3DDEVICEDESC D3DSWDevDesc
;
123 DPF(( DBG_FUNC
, "CreateHAL();" ));
125 #define InitDDSD2(f) memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) ); \
126 ddsd2.dwSize = sizeof( DDSURFACEDESC2 ); \
132 /* Use the internal rectangle struct. */
133 dwWidth
= pShared
->rectW
.right
- pShared
->rectW
.left
;
134 dwHeight
= pShared
->rectW
.bottom
- pShared
->rectW
.top
;
136 DPF(( DBG_CNTX_INFO
, "Width: %d Height: %d", dwWidth
, dwHeight
));
138 /* The dimensions might still be the same so just leave. */
139 if ( (dwWidth
== pShared
->dwWidth
) && (dwHeight
== pShared
->dwHeight
) )
141 DPF(( DBG_CNTX_WARN
, "Context size hasn't changed" ));
145 /* If one of the dimensions are zero then leave. WM_SIZE should get us back here. */
146 if ( (dwWidth
== 0) || (dwHeight
== 0) )
149 /* Save the renders dimensions. */
150 pShared
->dwWidth
= dwWidth
;
151 pShared
->dwHeight
= dwHeight
;
153 DPF(( DBG_CNTX_INFO
, "Creating Context:\n cx:%d cy:%d", pShared
->dwWidth
, pShared
->dwHeight
));
155 /*=================================*/
156 /* Create all required interfaces. */
157 /*=================================*/
159 /* Kill any DDraw stuff if exists. */
160 DestroyDevice( pHAL
);
161 DestroyAllSurfaces( pHAL
);
162 DestroyInterfaces( pHAL
);
164 /* Create a instance of DDraw using the Primary display driver. */
165 rc
= DirectDrawCreate( NULL
, &pHAL
->lpDD
, NULL
);
168 RIP( pHAL
, "DirectDrawCreate->", ErrorStringD3D(rc
) );
172 /* Get the DDraw4 interface. */
173 rc
= pHAL
->lpDD
->QueryInterface( IID_IDirectDraw4
, (void **)&pHAL
->lpDD4
);
176 RIP( pHAL
, "QueryInterface (IID_IDirectDraw4) ->", ErrorStringD3D(rc
) );
180 /* Get the Direct3D3 interface. */
181 rc
= pHAL
->lpDD4
->QueryInterface( IID_IDirect3D3
, (void **)&pHAL
->lpD3D3
);
184 RIP( pHAL
, "QueryInterface (IID_IDirect3D3) ->", ErrorStringD3D(rc
) );
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
);
193 RIP( pHAL
, "SetCooperativeLevel->", ErrorStringD3D(rc
) );
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" ));
206 /*========================================================================*/
207 /* HARDWARE was found. */
208 /*========================================================================*/
209 if ( pShared
->bHardware
== TRUE
)
211 /*===================================*/
212 /* HARDWARE -> Z-BUFFER. */
213 /*===================================*/
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
);
221 RIP( pHAL
, "EnumZBufferFormatsl->", ErrorStringD3D(rc
) );
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
);
233 DPF(( DBG_CNTX_INFO
, "HW ZBuffer" ));
235 /*===================================*/
236 /* HARDWARE -> Z-BUFFER -> FLIPABLE */
237 /*===================================*/
238 if ( pShared
->bWindow
== FALSE
)
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
);
246 /* Make sure we try the next fall back. */
247 DPF(( DBG_CNTX_WARN
, "HW Flip/Complex not available" ));
248 pHAL
->lpDDSPrimary
= NULL
;
252 /* Get the back buffer that was created. */
253 ddscaps
.dwCaps
= DDSCAPS_BACKBUFFER
;
254 rc
= pHAL
->lpDDSPrimary
->GetAttachedSurface( &ddscaps
, &pHAL
->lpDDSRender
);
257 DPF(( DBG_CNTX_WARN
, "GetAttachedSurface failed -> HW Flip/Complex" ));
259 /* Make sure we try the next fall back. */
260 pHAL
->lpDDSPrimary
->Release();
261 pHAL
->lpDDSPrimary
= NULL
;
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
);
274 RIP( pHAL
, "GetSurfaceDesc (RENDER) ->", ErrorStringD3D(rc
) );
278 /* If the surface is in VID then we are happy with are Flipable. */
279 if ( ddsd2
.ddsCaps
.dwCaps
& DDSCAPS_LOCALVIDMEM
)
281 pShared
->bFlipable
= TRUE
;
282 DPF(( DBG_CNTX_INFO
, "HW Flip/Complex!" ));
286 /* Kill this setup. */
287 pHAL
->lpDDSPrimary
->Release();
288 pHAL
->lpDDSPrimary
= NULL
;
294 /*===================================*/
295 /* HARDWARE -> Z-BUFFER -> BLT */
296 /*===================================*/
297 if ( pHAL
->lpDDSPrimary
== NULL
)
299 pShared
->bFlipable
= FALSE
;
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
);
307 /* This is an error as we should be able to do this at minimum. */
308 RIP( pHAL
, "CreateSurface (PRIMARY) ->", ErrorStringD3D(rc
) );
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
);
320 DPF(( DBG_CNTX_WARN
, "Failed HW Offscreen surface" ));
322 /* Make sure we try the next fall back. */
323 pHAL
->lpDDSPrimary
->Release();
324 pHAL
->lpDDSPrimary
= NULL
;
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
);
336 RIP( pHAL
, "GetSurfaceDesc (RENDER) ->", ErrorStringD3D(rc
) );
340 /* If the surface is in VID then we are happy. */
341 if ( ddsd2
.ddsCaps
.dwCaps
& DDSCAPS_LOCALVIDMEM
)
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" ));
353 /* Kill this setup. */
354 pHAL
->lpDDSRender
->Release();
355 pHAL
->lpDDSRender
= NULL
;
356 pHAL
->lpDDSPrimary
->Release();
357 pHAL
->lpDDSPrimary
= NULL
;
362 /*===================================*/
363 /* Create D3DDEVICE -> HARDWARE. */
364 /*===================================*/
365 if ( pHAL
->lpDDSZbuffer
&& pHAL
->lpDDSPrimary
&& pHAL
->lpDDSRender
)
367 DX_RESTORE( pHAL
->lpDDSRender
);
368 DX_RESTORE( pHAL
->lpDDSZbuffer
);
370 rc
= pHAL
->lpDDSRender
->AddAttachedSurface( pHAL
->lpDDSZbuffer
);
373 RIP( pHAL
, "AddAttachedSurface (ZBUFFER) ->", ErrorStringD3D(rc
) );
377 rc
= pHAL
->lpD3D3
->CreateDevice( IID_IDirect3DHALDevice
, pHAL
->lpDDSRender
, &pHAL
->lpD3DDevice
, NULL
);
380 DPF(( DBG_CNTX_WARN
, "Failed HW Device" ));
381 pHAL
->lpD3DDevice
= NULL
;
385 DPF(( DBG_CNTX_INFO
, "HW Device" ));
391 /*========================================================================*/
392 /* SOFTWARE fallback. */
393 /*========================================================================*/
394 if ( pHAL
->lpD3DDevice
== NULL
)
396 DPF(( DBG_CNTX_INFO
, "SW fallback :(" ));
398 /* Make sure we have no surfaces allocated. Just incase. */
399 DestroyAllSurfaces( pHAL
);
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
);
407 /*===================================*/
408 /* SOFTWARE -> Z-BUFFER. */
409 /*===================================*/
411 /*===================================*/
412 /* SOFTWARE -> Z-BUFFER -> FLIPABLE */
413 /*===================================*/
414 if ( pShared
->bWindow
== FALSE
)
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
);
424 DPF(( DBG_CNTX_WARN
, "Failed SW Flip/Complex" ));
426 /* Make sure we try the next fall back. */
427 pHAL
->lpDDSPrimary
= NULL
;
431 ddscaps
.dwCaps
= DDSCAPS_BACKBUFFER
;
432 rc
= pHAL
->lpDDSPrimary
->GetAttachedSurface( &ddscaps
, &pHAL
->lpDDSRender
);
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
;
442 DPF(( DBG_CNTX_INFO
, "SW Flip/Complex" ));
443 pShared
->bFlipable
= TRUE
;
448 /*===================================*/
449 /* SOFTWARE -> Z-BUFFER -> BLT */
450 /*===================================*/
451 if ( pHAL
->lpDDSPrimary
== NULL
)
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
);
459 /* This is an error as we should be able to do this at minimum. */
460 RIP( pHAL
, "CreateSurface (PRIMARY) ->", ErrorStringD3D(rc
) );
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
);
474 /* That was our last hope. */
475 RIP( pHAL
, "CreateSurface (RENDER) ->", ErrorStringD3D(rc
) );
480 DPF(( DBG_CNTX_INFO
, "SW RENDER surface" ));
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();
491 /*===================================*/
492 /* Create D3DDEVICE -> SOFTWARE. */
493 /*===================================*/
494 if ( pHAL
->lpDDSPrimary
&& pHAL
->lpDDSRender
)
496 DX_RESTORE( pHAL
->lpDDSRender
);
497 rc
= pHAL
->lpD3D3
->CreateDevice( IID_IDirect3DRGBDevice
, pHAL
->lpDDSRender
, &pHAL
->lpD3DDevice
, NULL
);
500 /* That was our last hope. */
501 RIP( pHAL
, "CreateDevice (IID_IDirect3DRGBDevice) ->", ErrorStringD3D(rc
) );
505 DPF(( DBG_CNTX_INFO
, "SW Device" ));
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
);
517 RIP( pHAL
, "GetPixelFormat ->", ErrorStringD3D(rc
) );
520 DebugPixelFormat( "Using OFFSCREEN", &pHAL
->ddpf
);
521 DebugPixelFormat( "Using ZBUFFER", &ddsd2
.ddpfPixelFormat
);
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
);
531 RIP( pHAL
, "GetCaps ->", ErrorStringD3D(rc
) );
535 /* Get a copy of the pixel convertion stuff for direct buffer access. */
536 Solve8BitChannelPixelFormat( &pHAL
->ddpf
, &pShared
->pixel
);
537 AlphaBlendTableHAL( pHAL
);
539 /* We must prime the Begin/End scene for SwapBuffers to work. */
540 rc
= pHAL
->lpD3DDevice
->BeginScene();
543 RIP( pHAL
, "BeginScene ->", ErrorStringD3D(rc
) );
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
)
562 PMESAD3DHAL pHAL
= (PMESAD3DHAL
)pShared
;
567 DPF(( DBG_FUNC
, "SetViewportHAL();" ));
569 /* Make sure we have enough info. */
570 if ( !pHAL
|| !pHAL
->lpDDSPrimary
|| !pHAL
->lpD3DDevice
)
572 DPF(( DBG_CNTX_WARN
, "SetViewport() -> NULL Pointer" ));
576 /* TODO: this is just a temp fix to stop redundant changes. */
578 (pShared
->rectV
.left
== pRect
->left
) &&
579 (pShared
->rectV
.right
== pRect
->right
) &&
580 (pShared
->rectV
.top
== pRect
->top
) &&
581 (pShared
->rectV
.bottom
== pRect
->bottom
) )
583 DPF(( DBG_CNTX_WARN
, "Redundant viewport" ));
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
) ));
594 /* Update the current viewport rect if one is supplied. */
596 memcpy( &pShared
->rectV
, pRect
, sizeof(RECT
) );
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
);
606 if ( !vdData
.dwWidth
|| !vdData
.dwHeight
)
608 GetClientRect( pShared
->hwnd
, &pShared
->rectW
);
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
) );
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
;
635 DPF(( DBG_CNTX_INFO
, "zMin: %f zMax: %f", minZ
, maxZ
));
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
)
641 DPF(( DBG_CNTX_INFO
, "DeleteViewport" ));
643 pHAL
->lpD3DDevice
->DeleteViewport( pHAL
->lpViewport
);
644 rc
= pHAL
->lpViewport
->Release();
645 pHAL
->lpViewport
= NULL
;
648 rc
= pHAL
->lpD3D3
->CreateViewport( &pHAL
->lpViewport
, NULL
);
651 DPF(( DBG_CNTX_ERROR
, "CreateViewport Failed" ));
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
);
662 /*===========================================================================*/
665 /*===========================================================================*/
667 /*===========================================================================*/
668 HRESULT WINAPI
EnumSurfacesHook( LPDIRECTDRAWSURFACE4 lpDDS
, LPDDSURFACEDESC2 lpDDSDesc
, LPVOID pVoid
)
670 DDSURFACEDESC2
*pddsd2
= (DDSURFACEDESC2
*)pVoid
;
672 DPF(( DBG_FUNC
, "EnumSurfacesHook();" ));
674 if ( (lpDDSDesc
->ddpfPixelFormat
.dwFlags
== pddsd2
->ddpfPixelFormat
.dwFlags
) && (lpDDSDesc
->ddsCaps
.dwCaps
== pddsd2
->ddsCaps
.dwCaps
) )
676 /* Save the pixelformat now so that we know we have one. */
677 memcpy( pddsd2
, lpDDSDesc
, sizeof(DDSURFACEDESC2
) );
679 return D3DENUMRET_CANCEL
;
682 return D3DENUMRET_OK
;
684 /*===========================================================================*/
685 /* This is the callback proc to get a Z-Buffer. Thats it. */
686 /*===========================================================================*/
688 /*===========================================================================*/
689 HRESULT CALLBACK
EnumZBufferHook( DDPIXELFORMAT
* pddpf
, VOID
*pVoid
)
691 DDPIXELFORMAT
*pddpfChoice
= (DDPIXELFORMAT
*)pVoid
;
693 DPF(( DBG_FUNC
, "EnumZBufferHook();" ));
695 /* If this is ANY type of depth-buffer, stop. */
696 if( pddpf
->dwFlags
== DDPF_ZBUFFER
)
698 /* Save the pixelformat now so that we know we have one. */
699 memcpy( pddpfChoice
, pddpf
, sizeof(DDPIXELFORMAT
) );
701 /* I feel if the hardware supports this low then lets use it. Could get ugly. */
702 if( pddpf
->dwZBufferBitDepth
>= 8 )
704 return D3DENUMRET_CANCEL
;
708 return D3DENUMRET_OK
;
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 /*===========================================================================*/
720 /*===========================================================================*/
721 HRESULT CALLBACK
EnumDeviceHook( GUID FAR
* lpGuid
, LPSTR lpDesc
, LPSTR lpName
, LPD3DDEVICEDESC lpD3DHWDesc
, LPD3DDEVICEDESC lpD3DHELDesc
, void *pVoid
)
723 PMESAD3DHAL pHAL
= (PMESAD3DHAL
)pVoid
;
724 LPD3DDEVICEDESC pChoice
= lpD3DHWDesc
;
726 DPF(( DBG_FUNC
, "EnumDeviceHook();" ));
728 /* Determine if which device description is valid. */
729 if ( pChoice
->dcmColorModel
== 0 )
730 pChoice
= lpD3DHELDesc
;
732 /* Make sure we always have a GUID. */
733 memcpy( &pHAL
->guid
, lpGuid
, sizeof(GUID
) );
735 /* This controls whether we will except HW or not. */
736 if ( pHAL
->shared
.bForceSW
== TRUE
)
738 return (pChoice
== lpD3DHELDesc
) ? D3DENUMRET_CANCEL
: D3DENUMRET_OK
;
741 /* Always try for hardware. */
742 if ( pChoice
== lpD3DHWDesc
)
744 return D3DENUMRET_CANCEL
;
747 return D3DENUMRET_OK
;
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 /*===========================================================================*/
755 /*===========================================================================*/
756 static void DestroyAllSurfaces( PMESAD3DHAL pHAL
)
760 DPF(( DBG_FUNC
, "DestroyAllSurfaces();" ));
762 DX_RESTORE( pHAL
->lpDDSPrimary
);
763 DX_RESTORE( pHAL
->lpDDSRender
);
764 DX_RESTORE( pHAL
->lpDDSZbuffer
);
766 if ( pHAL
->lpDDSRender
)
768 pHAL
->lpDDSRender
->Unlock( NULL
);
770 /* If this isn't a Flipable surface then we must clean up the render. */
771 if ( pHAL
->shared
.bFlipable
== FALSE
)
773 if ( pHAL
->lpDDSZbuffer
)
775 DPF(( DBG_CNTX_INFO
, "Remove attached surfaces from RENDER" ));
776 pHAL
->lpDDSRender
->DeleteAttachedSurface( 0, NULL
);
779 DPF(( DBG_CNTX_INFO
, "Release RENDER" ));
780 refCount
= pHAL
->lpDDSRender
->Release();
781 pHAL
->lpDDSRender
= NULL
;
785 if ( pHAL
->lpDDSZbuffer
)
787 DPF(( DBG_CNTX_INFO
, "Release ZBuffer" ));
788 pHAL
->lpDDSZbuffer
->Unlock( NULL
);
789 refCount
= pHAL
->lpDDSZbuffer
->Release();
790 pHAL
->lpDDSZbuffer
= NULL
;
793 if ( pHAL
->lpClipper
)
795 DPF(( DBG_CNTX_INFO
, "Release Clipper" ));
796 refCount
= pHAL
->lpClipper
->Release();
797 pHAL
->lpClipper
= NULL
;
800 if ( pHAL
->lpDDSPrimary
)
802 pHAL
->lpDDSPrimary
->Unlock( NULL
);
804 DPF(( DBG_CNTX_INFO
, "Release PRIMARY" ));
805 refCount
= pHAL
->lpDDSPrimary
->Release();
806 pHAL
->lpDDSPrimary
= NULL
;
809 /*===========================================================================*/
810 /* This function will destroy the current D3DDevice and any resources that */
812 /*===========================================================================*/
814 /*===========================================================================*/
815 static void DestroyDevice( PMESAD3DHAL pHAL
)
819 DPF(( DBG_FUNC
, "DestroyDevice();" ));
821 /* Kill the D3D stuff if exists. */
822 if ( pHAL
->lpViewport
)
824 DPF(( DBG_CNTX_INFO
, "Delete Viewport" ));
825 pHAL
->lpD3DDevice
->DeleteViewport( pHAL
->lpViewport
);
827 DPF(( DBG_CNTX_INFO
, "Release Viewport" ));
828 refCount
= pHAL
->lpViewport
->Release();
829 pHAL
->lpViewport
= NULL
;
832 if ( pHAL
->lpD3DDevice
!= NULL
)
834 DPF(( DBG_CNTX_INFO
, "Release D3DDevice" ));
835 refCount
= pHAL
->lpD3DDevice
->EndScene();
836 refCount
= pHAL
->lpD3DDevice
->Release();
837 pHAL
->lpD3DDevice
= NULL
;
840 /*===========================================================================*/
841 /* This function will destroy the current D3DDevice and any resources that */
843 /*===========================================================================*/
845 /*===========================================================================*/
846 static void DestroyInterfaces( PMESAD3DHAL pHAL
)
850 DPF(( DBG_FUNC
, "DestroyInterfaces();" ));
852 if ( pHAL
->lpD3D3
!= NULL
)
854 DPF(( DBG_CNTX_INFO
, "Release Direct3D3" ));
855 refCount
= pHAL
->lpD3D3
->Release();
859 if ( pHAL
->lpDD4
!= NULL
)
861 DPF(( DBG_CNTX_INFO
, "Release DDraw4" ));
862 refCount
= pHAL
->lpDD4
->Release();
866 if ( pHAL
->lpDD
!= NULL
)
868 DPF(( DBG_CNTX_INFO
, "Release DDraw" ));
869 refCount
= pHAL
->lpDD
->Release();
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 /*===========================================================================*/
881 /*===========================================================================*/
882 void FatalShutDown( PMESAD3DHAL pHAL
)
884 /* Whip this baby in too try and support the API until we die... */
886 SendMessage( pHAL
->shared
.hwnd
, UM_FATALSHUTDOWN
, 0L, 0L );
888 /* Close the client application down. */
889 PostQuitMessage( 0 );