1 /****************************************************************************
3 * Mesa 3-D graphics library
4 * Direct3D Driver Interface
6 * ========================================================================
8 * Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
25 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 * ======================================================================
31 * Environment: Windows 9x/2000/XP/XBox (Win32)
33 * Description: GLDirect Direct3D 8.x WGL (WindowsGL)
35 ****************************************************************************/
37 #include "dglcontext.h"
38 #include "gld_driver.h"
39 //#include "gld_dxerr8.h"
43 #include "tnl/t_context.h"
45 // Copied from dglcontect.c
48 #define GLDERR_DDRAW 2
52 // This external var keeps track of any error
53 extern int nContextError
;
55 // Uncomment this for persistant resources
56 //#define _GLD_PERSISTANT
58 #define DDLOG_CRITICAL_OR_WARN DDLOG_CRITICAL
60 extern void _gld_mesa_warning(GLcontext
*, char *);
61 extern void _gld_mesa_fatal(GLcontext
*, char *);
63 //---------------------------------------------------------------------------
65 static char szColorDepthWarning
[] =
66 "GLDirect does not support the current desktop\n\
68 You may need to change the display resolution to\n\
69 16 bits per pixel or higher color depth using\n\
70 the Windows Display Settings control panel\n\
71 before running this OpenGL application.\n";
73 // The only depth-stencil formats currently supported by Direct3D
74 // Surface Format Depth Stencil Total Bits
76 // D3DFMT_D15S1 15 1 16
77 // D3DFMT_D24S8 24 8 32
79 // D3DFMT_D24X8 24 - 32
80 // D3DFMT_D24X4S4 24 4 32
82 // This pixel format will be used as a template when compiling the list
83 // of pixel formats supported by the hardware. Many fields will be
84 // filled in at runtime.
85 // PFD flag defaults are upgraded to match ChoosePixelFormat() -- DaveM
86 static DGL_pixelFormat pfTemplateHW
=
89 sizeof(PIXELFORMATDESCRIPTOR
), // Size of the data structure
90 1, // Structure version - should be 1
92 PFD_DRAW_TO_WINDOW
| // The buffer can draw to a window or device surface.
93 PFD_DRAW_TO_BITMAP
| // The buffer can draw to a bitmap. (DaveM)
94 PFD_SUPPORT_GDI
| // The buffer supports GDI drawing. (DaveM)
95 PFD_SUPPORT_OPENGL
| // The buffer supports OpenGL drawing.
96 PFD_DOUBLEBUFFER
| // The buffer is double-buffered.
97 0, // Placeholder for easy commenting of above flags
98 PFD_TYPE_RGBA
, // Pixel type RGBA.
99 16, // Total colour bitplanes (excluding alpha bitplanes)
100 5, 0, // Red bits, shift
101 5, 0, // Green bits, shift
102 5, 0, // Blue bits, shift
103 0, 0, // Alpha bits, shift (destination alpha)
104 0, // Accumulator bits (total)
105 0, 0, 0, 0, // Accumulator bits: Red, Green, Blue, Alpha
108 0, // Number of auxiliary buffers
110 0, // Specifies the number of overlay and underlay planes.
112 0, // Specifies the transparent color or index of an underlay plane.
115 D3DX_SF_UNKNOWN
, // No depth/stencil buffer
118 //---------------------------------------------------------------------------
120 //---------------------------------------------------------------------------
122 // Vertex Shader Declaration
123 static DWORD dwTwoSidedLightingDecl[] =
126 D3DVSD_REG(0, D3DVSDT_FLOAT3), // XYZ position
127 D3DVSD_REG(1, D3DVSDT_FLOAT3), // XYZ normal
128 D3DVSD_REG(2, D3DVSDT_D3DCOLOR), // Diffuse color
129 D3DVSD_REG(3, D3DVSDT_D3DCOLOR), // Specular color
130 D3DVSD_REG(4, D3DVSDT_FLOAT2), // 2D texture unit 0
131 D3DVSD_REG(5, D3DVSDT_FLOAT2), // 2D texture unit 1
135 // Vertex Shader for two-sided lighting
136 static char *szTwoSidedLightingVS =
137 // This is a test shader!
146 //---------------------------------------------------------------------------
147 //---------------------------------------------------------------------------
150 // HINSTANCE hD3D8DLL; // Handle to d3d8.dll
151 // FNDIRECT3DCREATE7 fnDirect3DCreate7; // Direct3DCreate8 function prototype
152 // BOOL bDirect3D; // Persistant Direct3D7 exists
153 // BOOL bDirect3DDevice; // Persistant Direct3DDevice7 exists
154 // IDirect3D7 *pD3D; // Persistant Direct3D7
155 // IDirect3DDevice7 *pDev; // Persistant Direct3DDevice7
159 // These are "global" to all DX7 contexts. KeithH
160 static GLD_dx7_globals dx7Globals
;
162 // Added for correct clipping of multiple open windows. (DaveM)
163 LPDIRECTDRAWSURFACE7 lpDDSPrimary
= NULL
;
164 LPDIRECTDRAWCLIPPER lpDDClipper
= NULL
;
166 //---------------------------------------------------------------------------
167 //---------------------------------------------------------------------------
169 BOOL
gldGetDXErrorString_DX(
175 // Return a string describing the input HRESULT error code
178 D3DXGetErrorString(hr
, nBufSize
, buf
);
182 //---------------------------------------------------------------------------
184 // DX7 does not support multisample
186 static D3DMULTISAMPLE_TYPE _gldGetDeviceMultiSampleType(
188 D3DFORMAT SurfaceFormat,
189 D3DDEVTYPE d3dDevType,
195 if (glb.dwMultisample == GLDS_MULTISAMPLE_NONE)
196 return D3DMULTISAMPLE_NONE;
198 if (glb.dwMultisample == GLDS_MULTISAMPLE_FASTEST) {
199 // Find fastest multisample
200 for (i=2; i<17; i++) {
201 hr = IDirect3D8_CheckDeviceMultiSampleType(
207 (D3DMULTISAMPLE_TYPE)i);
209 return (D3DMULTISAMPLE_TYPE)i;
213 // Find nicest multisample
214 for (i=16; i>1; i--) {
215 hr = IDirect3D8_CheckDeviceMultiSampleType(
221 (D3DMULTISAMPLE_TYPE)i);
223 return (D3DMULTISAMPLE_TYPE)i;
228 // Nothing found - return default
229 return D3DMULTISAMPLE_NONE;
232 //---------------------------------------------------------------------------
234 void _gldDestroyPrimitiveBuffer(
237 SAFE_RELEASE(gldVB
->pVB
);
240 gldVB
->nLines
= gldVB
->nPoints
= gldVB
->nTriangles
= 0;
243 //---------------------------------------------------------------------------
245 HRESULT
_gldCreatePrimitiveBuffer(
247 GLD_driver_dx7
*lpCtx
,
251 char *szCreateVertexBufferFailed
= "CreateVertexBuffer failed";
252 DWORD dwMaxVertices
; // Max number of vertices in vertex buffer
253 DWORD dwVBSize
; // Total size of vertex buffer
254 D3DVERTEXBUFFERDESC vbdesc
;
256 // If CVA (Compiled Vertex Array) is used by an OpenGL app, then we
257 // will need enough vertices to cater for Mesa::Const.MaxArrayLockSize.
258 // We'll use IMM_SIZE if it's larger (which it should not be).
259 dwMaxVertices
= MAX_ARRAY_LOCK_SIZE
;
261 // Max vertex buffer size limited in DX7. (DaveM)
262 if (dwMaxVertices
*9 > D3DMAXNUMVERTICES
)
263 dwMaxVertices
= D3DMAXNUMVERTICES
/9;
265 // Now calculate how many vertices to allow for in total
266 // 1 per point, 2 per line, 6 per quad = 9
267 dwVBSize
= dwMaxVertices
* 9 * gldVB
->dwStride
;
269 vbdesc
.dwSize
= sizeof(vbdesc
);
270 vbdesc
.dwCaps
= gldVB
->dwCreateFlags
;
271 vbdesc
.dwFVF
= gldVB
->dwFVF
;
272 vbdesc
.dwNumVertices
= dwMaxVertices
* 9;
274 /* hResult = IDirect3DDevice8_CreateVertexBuffer(
281 hResult
= IDirect3D7_CreateVertexBuffer(
286 if (FAILED(hResult
)) {
287 ddlogMessage(DDLOG_CRITICAL_OR_WARN
, szCreateVertexBufferFailed
);
291 gldVB
->nLines
= gldVB
->nPoints
= gldVB
->nTriangles
= 0;
292 gldVB
->pPoints
= gldVB
->pLines
= gldVB
->pTriangles
= NULL
;
293 gldVB
->iFirstLine
= dwMaxVertices
; // Index of first line in VB
294 gldVB
->iFirstTriangle
= dwMaxVertices
*3; // Index of first triangle in VB
299 //---------------------------------------------------------------------------
300 // Function: _gldCreateVertexShaders
301 // Create DX8 Vertex Shaders.
302 //---------------------------------------------------------------------------
304 void _gldCreateVertexShaders(
308 LPD3DXBUFFER pVSOpcodeBuffer; // Vertex Shader opcode buffer
312 dwFlags = D3DXASM_DEBUG;
314 dwFlags = 0; // D3DXASM_SKIPVALIDATION;
317 ddlogMessage(DDLOG_INFO, "Creating shaders...\n");
319 // Init the shader handle
320 gld->VStwosidelight.hShader = 0;
322 if (gld->d3dCaps8.MaxStreams == 0) {
323 // Lame DX8 driver doesn't support streams
324 // Not fatal, as defaults will be used
325 ddlogMessage(DDLOG_WARN, "Driver doesn't support Vertex Shaders (MaxStreams==0)\n");
329 // ** THIS DISABLES VERTEX SHADER SUPPORT **
331 // ** THIS DISABLES VERTEX SHADER SUPPORT **
334 // Two-sided lighting
339 // DEBUGGING: Load shader from a text file
342 LPD3DXBUFFER pVSErrorBuffer; // Vertex Shader error buffer
343 hr = D3DXAssembleShaderFromFile(
346 NULL, // No constants
349 if (pVSErrorBuffer && pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer))
350 ddlogMessage(DDLOG_INFO, pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer));
351 SAFE_RELEASE(pVSErrorBuffer);
355 LPD3DXBUFFER pVSErrorBuffer; // Vertex Shader error buffer
356 // Assemble ascii shader text into shader opcodes
357 hr = D3DXAssembleShader(
358 szTwoSidedLightingVS,
359 strlen(szTwoSidedLightingVS),
361 NULL, // No constants
364 if (pVSErrorBuffer && pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer))
365 ddlogMessage(DDLOG_INFO, pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer));
366 SAFE_RELEASE(pVSErrorBuffer);
370 ddlogError(DDLOG_WARN, "AssembleShader failed", hr);
371 SAFE_RELEASE(pVSOpcodeBuffer);
375 // This is for debugging. Remove to enable vertex shaders in HW
376 #define _GLD_FORCE_SW_VS 0
378 if (_GLD_FORCE_SW_VS) {
379 // _GLD_FORCE_SW_VS should be disabled for Final Release
380 ddlogMessage(DDLOG_SYSTEM, "[Forcing shaders in SW]\n");
383 // Try and create shader in hardware.
384 // NOTE: The D3D Ref device appears to succeed when trying to
385 // create the device in hardware, but later complains
386 // when trying to set it with SetVertexShader(). Go figure.
387 if (_GLD_FORCE_SW_VS || glb.dwDriver == GLDS_DRIVER_REF) {
388 // Don't try and create a hardware shader with the Ref device
389 hr = E_FAIL; // COM error/fail result
391 gld->VStwosidelight.bHardware = TRUE;
392 hr = IDirect3DDevice8_CreateVertexShader(
394 dwTwoSidedLightingDecl,
395 pVSOpcodeBuffer->lpVtbl->GetBufferPointer(pVSOpcodeBuffer),
396 &gld->VStwosidelight.hShader,
400 ddlogMessage(DDLOG_INFO, "... HW failed, trying SW...\n");
401 // Failed. Try and create shader for software processing
402 hr = IDirect3DDevice8_CreateVertexShader(
404 dwTwoSidedLightingDecl,
405 pVSOpcodeBuffer->lpVtbl->GetBufferPointer(pVSOpcodeBuffer),
406 &gld->VStwosidelight.hShader,
407 D3DUSAGE_SOFTWAREPROCESSING);
409 gld->VStwosidelight.hShader = 0; // Sanity check
410 ddlogError(DDLOG_WARN, "CreateVertexShader failed", hr);
413 // Succeeded, but for software processing
414 gld->VStwosidelight.bHardware = FALSE;
417 SAFE_RELEASE(pVSOpcodeBuffer);
419 ddlogMessage(DDLOG_INFO, "... OK\n");
422 //---------------------------------------------------------------------------
424 void _gldDestroyVertexShaders(
427 if (gld->VStwosidelight.hShader) {
428 IDirect3DDevice8_DeleteVertexShader(gld->pDev, gld->VStwosidelight.hShader);
429 gld->VStwosidelight.hShader = 0;
433 //---------------------------------------------------------------------------
435 BOOL
gldCreateDrawable_DX(
437 // BOOL bDefaultDriver,
438 BOOL bDirectDrawPersistant
,
439 BOOL bPersistantBuffers
)
442 // bDirectDrawPersistant: applies to IDirect3D8
443 // bPersistantBuffers: applies to IDirect3DDevice8
446 // D3DDEVTYPE d3dDevType;
447 // D3DPRESENT_PARAMETERS d3dpp;
448 // D3DDISPLAYMODE d3ddm;
449 // DWORD dwBehaviourFlags;
450 // D3DADAPTER_IDENTIFIER8 d3dIdent;
453 GLD_driver_dx7
*lpCtx
= NULL
;
454 D3DX_VIDMODEDESC d3ddm
;
456 // Parameters for D3DXCreateContextEx
457 // These will be different for fullscreen and windowed
465 DWORD numStencilBits
;
466 DWORD numBackBuffers
;
471 // Error if context is NULL.
477 // Release any existing interfaces (in reverse order)
478 SAFE_RELEASE(lpCtx
->pDev
);
479 SAFE_RELEASE(lpCtx
->pD3D
);
480 lpCtx
->pD3DXContext
->lpVtbl
->Release(lpCtx
->pD3DXContext
);
481 lpCtx
->pD3DXContext
= NULL
;
483 lpCtx
= (GLD_driver_dx7
*)malloc(sizeof(GLD_driver_dx7
));
484 ZeroMemory(lpCtx
, sizeof(lpCtx
));
487 // d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF;
488 // Use REF device if requested. Otherwise D3DX_DEFAULT will choose highest level
489 // of HW acceleration.
490 dwDeviceIndex
= (glb
.dwDriver
== GLDS_DRIVER_REF
) ? D3DX_HWLEVEL_REFERENCE
: D3DX_DEFAULT
;
493 // if (bDefaultDriver)
494 // d3dDevType = D3DDEVTYPE_REF;
496 #ifdef _GLD_PERSISTANT
497 // Use persistant interface if needed
498 if (bDirectDrawPersistant
&& dx7Globals
.bDirect3D
) {
499 lpCtx
->pD3D
= dx7Globals
.pD3D
;
500 IDirect3D7_AddRef(lpCtx
->pD3D
);
501 goto SkipDirectDrawCreate
;
505 // Create Direct3D7 object
506 lpCtx->pD3D = dx7Globals.fnDirect3DCreate8(D3D_SDK_VERSION_DX8_SUPPORT_WIN95);
507 if (lpCtx->pD3D == NULL) {
508 MessageBox(NULL, "Unable to initialize Direct3D8", "GLDirect", MB_OK);
509 ddlogMessage(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D8 interface");
510 nContextError = GLDERR_D3D;
511 goto return_with_error;
515 #ifdef _GLD_PERSISTANT
516 // Cache Direct3D interface for subsequent GLRCs
517 if (bDirectDrawPersistant
&& !dx8Globals
.bDirect3D
) {
518 dx7Globals
.pD3D
= lpCtx
->pD3D
;
519 IDirect3D7_AddRef(dx7Globals
.pD3D
);
520 dx7Globals
.bDirect3D
= TRUE
;
522 SkipDirectDrawCreate
:
525 // Get the display mode so we can make a compatible backbuffer
526 hResult = IDirect3D8_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm);
527 if (FAILED(hResult)) {
528 nContextError = GLDERR_D3D;
529 goto return_with_error;
535 hResult
= IDirect3D8_GetDeviceCaps(lpCtx
->pD3D
, glb
.dwAdapter
, d3dDevType
, &lpCtx
->d3dCaps8
);
536 if (FAILED(hResult
)) {
537 ddlogError(DDLOG_CRITICAL_OR_WARN
, "IDirect3D8_GetDeviceCaps failed", hResult
);
538 nContextError
= GLDERR_D3D
;
539 goto return_with_error
;
542 // Check for hardware transform & lighting
543 lpCtx
->bHasHWTnL
= lpCtx
->d3dCaps8
.DevCaps
& D3DDEVCAPS_HWTRANSFORMANDLIGHT
? TRUE
: FALSE
;
545 // If this flag is present then we can't default to Mesa
546 // SW rendering between BeginScene() and EndScene().
547 if (lpCtx
->d3dCaps8
.Caps2
& D3DCAPS2_NO2DDURING3DSCENE
) {
548 ddlogMessage(DDLOG_WARN
,
549 "Warning : No 2D allowed during 3D scene.\n");
554 // Create the Direct3D context
557 #ifdef _GLD_PERSISTANT
558 // Re-use original IDirect3DDevice if persistant buffers exist.
559 // Note that we test for persistant IDirect3D8 as well
560 // bDirectDrawPersistant == persistant IDirect3D8 (DirectDraw8 does not exist)
561 if (bDirectDrawPersistant
&& bPersistantBuffers
&& dx7Globals
.pD3D
&& dx7Globals
.pDev
) {
562 lpCtx
->pDev
= dx7Globals
.pDev
;
563 IDirect3DDevice7_AddRef(dx7Globals
.pDev
);
564 goto skip_direct3ddevice_create
;
568 // Clear the presentation parameters (sets all members to zero)
569 ZeroMemory(&d3dpp, sizeof(d3dpp));
571 // Recommended by MS; needed for MultiSample.
572 // Be careful if altering this for FullScreenBlit
573 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
575 d3dpp.BackBufferFormat = d3ddm.Format;
576 d3dpp.BackBufferCount = 1;
577 d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(lpCtx->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen);
578 d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData;
579 d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE;
581 if (ctx->bFullscreen) {
582 ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen
583 d3dpp.Windowed = FALSE;
584 d3dpp.BackBufferWidth = d3ddm.Width;
585 d3dpp.BackBufferHeight = d3ddm.Height;
586 d3dpp.hDeviceWindow = ctx->hWnd;
587 d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
589 // Support for vertical retrace synchronisation.
590 // Set default presentation interval in case caps bits are missing
591 d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
592 if (glb.bWaitForRetrace) {
593 if (lpCtx->d3dCaps8.PresentationIntervals & D3DPRESENT_INTERVAL_ONE)
594 d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE;
596 if (lpCtx->d3dCaps8.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE)
597 d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
600 ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages
601 d3dpp.Windowed = TRUE;
602 d3dpp.BackBufferWidth = ctx->dwWidth;
603 d3dpp.BackBufferHeight = ctx->dwHeight;
604 d3dpp.hDeviceWindow = ctx->hWnd;
605 d3dpp.FullScreen_RefreshRateInHz = 0;
606 // FullScreen_PresentationInterval must be default for Windowed mode
607 d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
610 // Decide if we can use hardware TnL
611 dwBehaviourFlags = (lpCtx->bHasHWTnL) ?
612 D3DCREATE_MIXED_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING;
613 // Add flag to tell D3D to be thread-safe
614 if (glb.bMultiThreaded)
615 dwBehaviourFlags |= D3DCREATE_MULTITHREADED;
616 hResult = IDirect3D8_CreateDevice(lpCtx->pD3D,
623 if (FAILED(hResult)) {
624 ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D8_CreateDevice failed", hResult);
625 nContextError = GLDERR_D3D;
626 goto return_with_error;
630 // Create D3DX context
631 if (ctx
->bFullscreen
) {
637 D3DXGetCurrentVideoMode(D3DX_DEFAULT
, &d3ddm
);
639 // Fullscreen Parameters
640 dwFlags
= D3DX_CONTEXT_FULLSCREEN
;
642 hwndFocus
= ctx
->hWnd
;
643 numColorBits
= ctx
->lpPF
->pfd
.cColorBits
;
644 numAlphaBits
= ctx
->lpPF
->pfd
.cAlphaBits
;
645 numDepthBits
= ctx
->lpPF
->pfd
.cDepthBits
+ ctx
->lpPF
->pfd
.cStencilBits
;
646 numStencilBits
= ctx
->lpPF
->pfd
.cStencilBits
;
647 numBackBuffers
= D3DX_DEFAULT
; // Default is 1 backbuffer
648 dwWidth
= d3ddm
.width
;
649 dwHeight
= d3ddm
.height
;
650 refreshRate
= d3ddm
.refreshRate
; // D3DX_DEFAULT;
656 // Windowed Parameters
657 dwFlags
= 0; // No flags means "windowed"
659 hwndFocus
= (HWND
)D3DX_DEFAULT
;
660 numColorBits
= D3DX_DEFAULT
; // Use Desktop depth
661 numAlphaBits
= ctx
->lpPF
->pfd
.cAlphaBits
;
662 numDepthBits
= ctx
->lpPF
->pfd
.cDepthBits
+ ctx
->lpPF
->pfd
.cStencilBits
;
663 numStencilBits
= ctx
->lpPF
->pfd
.cStencilBits
;
664 numBackBuffers
= D3DX_DEFAULT
; // Default is 1 backbuffer
665 dwWidth
= ctx
->dwWidth
;
666 dwHeight
= ctx
->dwHeight
;
667 refreshRate
= D3DX_DEFAULT
;
669 hr
= D3DXCreateContextEx(dwDeviceIndex
, dwFlags
, hwnd
, hwndFocus
,
670 numColorBits
, numAlphaBits
, numDepthBits
, numStencilBits
,
672 dwWidth
, dwHeight
, refreshRate
,
673 &lpCtx
->pD3DXContext
);
675 ddlogError(DDLOG_CRITICAL_OR_WARN
, "D3DXCreateContextEx failed", hr
);
676 nContextError
= GLDERR_D3D
;
677 goto return_with_error
;
680 // Obtain D3D7 interfaces from ID3DXContext
681 // lpCtx->pDD = ID3DXContext_GetDD(lpCtx->pD3DXContext);
682 lpCtx
->pDD
= lpCtx
->pD3DXContext
->lpVtbl
->GetDD(lpCtx
->pD3DXContext
);
683 if (lpCtx
->pDD
== NULL
)
684 goto return_with_error
;
685 lpCtx
->pD3D
= lpCtx
->pD3DXContext
->lpVtbl
->GetD3D(lpCtx
->pD3DXContext
);
686 if (lpCtx
->pD3D
== NULL
)
687 goto return_with_error
;
688 lpCtx
->pDev
= lpCtx
->pD3DXContext
->lpVtbl
->GetD3DDevice(lpCtx
->pD3DXContext
);
689 if (lpCtx
->pDev
== NULL
)
690 goto return_with_error
;
692 // Need to manage clipper manually for multiple windows
693 // since DX7 D3DX utility lib does not appear to do that. (DaveM)
694 if (!ctx
->bFullscreen
) {
695 // Get primary surface too
696 lpDDSPrimary
= lpCtx
->pD3DXContext
->lpVtbl
->GetPrimary(lpCtx
->pD3DXContext
);
697 if (lpDDSPrimary
== NULL
) {
698 ddlogPrintf(DDLOG_WARN
, "GetPrimary");
699 goto return_with_error
;
701 // Create clipper for correct window updates
702 if (IDirectDraw7_CreateClipper(lpCtx
->pDD
, 0, &lpDDClipper
, NULL
) != DD_OK
) {
703 ddlogPrintf(DDLOG_WARN
, "CreateClipper");
704 goto return_with_error
;
706 // Set the window that the clipper belongs to
707 if (IDirectDrawClipper_SetHWnd(lpDDClipper
, 0, hwnd
) != DD_OK
) {
708 ddlogPrintf(DDLOG_WARN
, "SetHWnd");
709 goto return_with_error
;
711 // Attach the clipper to the primary surface
712 if (IDirectDrawSurface7_SetClipper(lpDDSPrimary
, lpDDClipper
) != DD_OK
) {
713 ddlogPrintf(DDLOG_WARN
, "SetClipper");
714 goto return_with_error
;
719 IDirect3DDevice7_GetCaps(lpCtx
->pDev
, &lpCtx
->d3dCaps
);
722 lpCtx
->bHasHWTnL
= lpCtx
->d3dCaps
.dwDevCaps
& D3DDEVCAPS_HWTRANSFORMANDLIGHT
? TRUE
: FALSE
;
724 #ifdef _GLD_PERSISTANT
725 if (bDirectDrawPersistant
&& bPersistantBuffers
&& dx7Globals
.pD3D
) {
726 dx7Globals
.pDev
= lpCtx
->pDev
;
727 dx7Globals
.bDirect3DDevice
= TRUE
;
732 // Dump some useful stats
733 hResult
= IDirect3D8_GetAdapterIdentifier(
736 D3DENUM_NO_WHQL_LEVEL
, // Avoids 1 to 2 second delay
738 if (SUCCEEDED(hResult
)) {
739 ddlogPrintf(DDLOG_INFO
, "[Driver Description: %s]", &d3dIdent
.Description
);
740 ddlogPrintf(DDLOG_INFO
, "[Driver file: %s %d.%d.%02d.%d]",
742 HIWORD(d3dIdent
.DriverVersion
.HighPart
),
743 LOWORD(d3dIdent
.DriverVersion
.HighPart
),
744 HIWORD(d3dIdent
.DriverVersion
.LowPart
),
745 LOWORD(d3dIdent
.DriverVersion
.LowPart
));
746 ddlogPrintf(DDLOG_INFO
, "[VendorId: 0x%X, DeviceId: 0x%X, SubSysId: 0x%X, Revision: 0x%X]",
747 d3dIdent
.VendorId
, d3dIdent
.DeviceId
, d3dIdent
.SubSysId
, d3dIdent
.Revision
);
751 // Init projection matrix for D3D TnL
752 D3DXMatrixIdentity((D3DXMATRIX
*)&lpCtx
->matProjection
);
753 lpCtx
->matModelView
= lpCtx
->matProjection
;
754 // gld->bUseMesaProjection = TRUE;
756 skip_direct3ddevice_create
:
758 // Create buffers to hold primitives
759 lpCtx
->PB2d
.dwFVF
= GLD_FVF_2D_VERTEX
;
760 // lpCtx->PB2d.dwPool = D3DPOOL_SYSTEMMEM;
761 lpCtx
->PB2d
.dwStride
= sizeof(GLD_2D_VERTEX
);
762 lpCtx
->PB2d
.dwCreateFlags
= D3DVBCAPS_DONOTCLIP
|
763 D3DVBCAPS_SYSTEMMEMORY
|
765 hr
= _gldCreatePrimitiveBuffer(ctx
->glCtx
, lpCtx
, &lpCtx
->PB2d
);
767 goto return_with_error
;
769 lpCtx
->PB3d
.dwFVF
= GLD_FVF_3D_VERTEX
;
770 // lpCtx->PB3d.dwPool = D3DPOOL_DEFAULT;
771 lpCtx
->PB3d
.dwStride
= sizeof(GLD_3D_VERTEX
);
772 lpCtx
->PB3d
.dwCreateFlags
= D3DVBCAPS_WRITEONLY
;
774 hr
= _gldCreatePrimitiveBuffer(ctx
->glCtx
, lpCtx
, &lpCtx
->PB3d
);
776 goto return_with_error
;
778 // Zero the pipeline usage counters
779 lpCtx
->PipelineUsage
.qwMesa
.QuadPart
=
780 // lpCtx->PipelineUsage.dwD3D2SVS.QuadPart =
781 lpCtx
->PipelineUsage
.qwD3DFVF
.QuadPart
= 0;
783 // Assign drawable to GL private
789 _gldDestroyPrimitiveBuffer(&lpCtx
->PB3d
);
790 _gldDestroyPrimitiveBuffer(&lpCtx
->PB2d
);
792 SAFE_RELEASE(lpCtx
->pDev
);
793 SAFE_RELEASE(lpCtx
->pD3D
);
794 //SAFE_RELEASE(lpCtx->pD3DXContext);
795 lpCtx
->pD3DXContext
->lpVtbl
->Release(lpCtx
->pD3DXContext
);
799 //---------------------------------------------------------------------------
801 BOOL
gldResizeDrawable_DX(
804 BOOL bPersistantInterface
,
805 BOOL bPersistantBuffers
)
807 GLD_driver_dx7
*gld
= NULL
;
808 // D3DDEVTYPE d3dDevType;
809 // D3DPRESENT_PARAMETERS d3dpp;
810 // D3DDISPLAYMODE d3ddm;
811 D3DX_VIDMODEDESC d3ddm
;
813 DWORD dwWidth
, dwHeight
;
815 // Error if context is NULL.
823 if (ctx
->bSceneStarted
) {
824 IDirect3DDevice7_EndScene(gld
->pDev
);
825 ctx
->bSceneStarted
= FALSE
;
828 d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF;
830 d3dDevType = D3DDEVTYPE_REF; // Force Direct3D Reference Rasterise (software)
832 // Get the display mode so we can make a compatible backbuffer
833 hResult = IDirect3D8_GetAdapterDisplayMode(gld->pD3D, glb.dwAdapter, &d3ddm);
834 if (FAILED(hResult)) {
835 nContextError = GLDERR_D3D;
836 // goto return_with_error;
840 // Release objects before Reset()
841 _gldDestroyPrimitiveBuffer(&gld
->PB3d
);
842 _gldDestroyPrimitiveBuffer(&gld
->PB2d
);
845 // Clear the presentation parameters (sets all members to zero)
846 ZeroMemory(&d3dpp, sizeof(d3dpp));
848 // Recommended by MS; needed for MultiSample.
849 // Be careful if altering this for FullScreenBlit
850 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
852 d3dpp.BackBufferFormat = d3ddm.Format;
853 d3dpp.BackBufferCount = 1;
854 d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(gld->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen);
855 d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData;
856 d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE;
858 // TODO: Sync to refresh
860 if (ctx->bFullscreen) {
861 ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen
862 d3dpp.Windowed = FALSE;
863 d3dpp.BackBufferWidth = d3ddm.Width;
864 d3dpp.BackBufferHeight = d3ddm.Height;
865 d3dpp.hDeviceWindow = ctx->hWnd;
866 d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
867 d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
868 // Get better benchmark results? KeithH
869 // d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_UNLIMITED;
871 ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages
872 d3dpp.Windowed = TRUE;
873 d3dpp.BackBufferWidth = ctx->dwWidth;
874 d3dpp.BackBufferHeight = ctx->dwHeight;
875 d3dpp.hDeviceWindow = ctx->hWnd;
876 d3dpp.FullScreen_RefreshRateInHz = 0;
877 d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
879 hResult = IDirect3DDevice8_Reset(gld->pDev, &d3dpp);
880 if (FAILED(hResult)) {
881 ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Reset failed", hResult);
883 //goto cleanup_and_return_with_error;
886 // Obtain dimensions of 'window'
887 if (ctx
->bFullscreen
) {
888 D3DXGetCurrentVideoMode(D3DX_DEFAULT
, &d3ddm
);
889 dwWidth
= d3ddm
.width
;
890 dwHeight
= d3ddm
.height
;
892 dwWidth
= ctx
->dwWidth
;
893 dwHeight
= ctx
->dwHeight
;
897 hr
= gld
->pD3DXContext
->lpVtbl
->Resize(gld
->pD3DXContext
, dwWidth
, dwHeight
);
899 ddlogError(DDLOG_CRITICAL_OR_WARN
, "gldResizeDrawable_DX: Resize failed", hr
);
903 // Clear the resized surface (DaveM)
905 D3DVIEWPORT7 vp1
, vp2
;
906 IDirect3DDevice7_GetViewport(gld
->pDev
, &vp1
);
907 IDirect3DDevice7_GetViewport(gld
->pDev
, &vp2
);
910 vp2
.dwWidth
= dwWidth
;
911 vp2
.dwHeight
= dwHeight
;
912 IDirect3DDevice7_SetViewport(gld
->pDev
, &vp2
);
913 hr
= gld
->pD3DXContext
->lpVtbl
->Clear(gld
->pD3DXContext
, D3DCLEAR_TARGET
);
915 ddlogError(DDLOG_WARN
, "gldResizeDrawable_DX: Clear failed", hr
);
916 IDirect3DDevice7_SetViewport(gld
->pDev
, &vp1
);
922 _gldCreatePrimitiveBuffer(ctx
->glCtx
, gld
, &gld
->PB2d
);
923 _gldCreatePrimitiveBuffer(ctx
->glCtx
, gld
, &gld
->PB3d
);
925 // Signal a complete state update
926 ctx
->glCtx
->Driver
.UpdateState(ctx
->glCtx
, _NEW_ALL
);
929 IDirect3DDevice7_BeginScene(gld
->pDev
);
930 ctx
->bSceneStarted
= TRUE
;
935 //---------------------------------------------------------------------------
937 BOOL
gldDestroyDrawable_DX(
940 GLD_driver_dx7
*lpCtx
= NULL
;
942 // Error if context is NULL.
946 // Error if the drawable does not exist.
954 ddlogPrintf(DDLOG_SYSTEM
, "Usage: M:0x%X%X, D:0x%X%X",
955 lpCtx
->PipelineUsage
.qwMesa
.HighPart
,
956 lpCtx
->PipelineUsage
.qwMesa
.LowPart
,
957 lpCtx
->PipelineUsage
.qwD3DFVF
.HighPart
,
958 lpCtx
->PipelineUsage
.qwD3DFVF
.LowPart
);
961 // Destroy Primtive Buffers
962 _gldDestroyPrimitiveBuffer(&lpCtx
->PB3d
);
963 _gldDestroyPrimitiveBuffer(&lpCtx
->PB2d
);
965 // Release DX interfaces (in reverse order)
966 SAFE_RELEASE(lpCtx
->pDev
);
967 SAFE_RELEASE(lpCtx
->pD3D
);
968 //SAFE_RELEASE(lpCtx->pD3DXContext);
969 lpCtx
->pD3DXContext
->lpVtbl
->Release(lpCtx
->pD3DXContext
);
971 // Free the private drawable data
978 //---------------------------------------------------------------------------
980 BOOL
gldCreatePrivateGlobals_DX(void)
983 ZeroMemory(&dx7Globals, sizeof(dx7Globals));
986 dx8Globals.hD3D8DLL = LoadLibrary("D3D8.DLL");
987 if (dx8Globals.hD3D8DLL == NULL)
990 // Now try and obtain Direct3DCreate8
991 dx8Globals.fnDirect3DCreate8 = (FNDIRECT3DCREATE8)GetProcAddress(dx8Globals.hD3D8DLL, "Direct3DCreate8");
992 if (dx8Globals.fnDirect3DCreate8 == NULL) {
993 FreeLibrary(dx8Globals.hD3D8DLL);
999 return FAILED(D3DXInitialize()) ? FALSE
: TRUE
;
1002 //---------------------------------------------------------------------------
1004 BOOL
gldDestroyPrivateGlobals_DX(void)
1007 if (dx7Globals.bDirect3DDevice) {
1008 SAFE_RELEASE(dx7Globals.pDev);
1009 dx7Globals.bDirect3DDevice = FALSE;
1011 if (dx7Globals.bDirect3D) {
1012 SAFE_RELEASE(dx7Globals.pD3D);
1013 dx7Globals.bDirect3D = FALSE;
1016 FreeLibrary(dx8Globals.hD3D8DLL);
1017 dx8Globals.hD3D8DLL = NULL;
1018 dx8Globals.fnDirect3DCreate8 = NULL;
1020 return FAILED(D3DXUninitialize()) ? FALSE
: TRUE
;
1023 //---------------------------------------------------------------------------
1025 static void _BitsFromDisplayFormat(
1026 D3DX_SURFACEFORMAT fmt
,
1034 /* case D3DX_SF_X1R5G5B5:
1041 case D3DX_SF_R5G5B5
:
1048 case D3DX_SF_R5G6B5
:
1055 case D3DX_SF_X8R8G8B8
:
1062 case D3DX_SF_A8R8G8B8
:
1071 // Should not get here!
1079 //---------------------------------------------------------------------------
1081 static void _BitsFromDepthStencilFormat(
1082 D3DX_SURFACEFORMAT fmt
,
1086 // NOTE: GL expects either 32 or 16 as depth bits.
1115 //---------------------------------------------------------------------------
1117 BOOL GLD_CheckDepthStencilMatch(
1118 DWORD dwDeviceIndex,
1119 D3DX_SURFACEFORMAT sfWant)
1121 // Emulate function built in to DX9
1122 D3DX_SURFACEFORMAT sfFound;
1124 int nFormats = D3DXGetMaxSurfaceFormats(dwDeviceIndex, NULL, D3DX_SC_DEPTHBUFFER);
1126 for (i=0; i<nFormats; i++) {
1127 D3DXGetSurfaceFormat(dwDeviceIndex, NULL, D3DX_SC_DEPTHBUFFER, i, &sfFound); }
1128 if (sfFound == sfWant)
1135 //---------------------------------------------------------------------------
1137 D3DX_SURFACEFORMAT
_gldFindCompatibleDepthStencilFormat(
1138 DWORD dwDeviceIndex
)
1140 // Jump through some hoops...
1142 ID3DXContext
*pD3DXContext
= NULL
;
1143 IDirectDrawSurface7
*pZBuffer
= NULL
;
1147 // Get an HWND - use Desktop's
1148 hWnd
= GetDesktopWindow();
1150 // Create a fully specified default context.
1151 D3DXCreateContextEx(dwDeviceIndex
, 0, hWnd
, (HWND
)D3DX_DEFAULT
,
1152 D3DX_DEFAULT
, D3DX_DEFAULT
, D3DX_DEFAULT
, D3DX_DEFAULT
,
1153 D3DX_DEFAULT
, D3DX_DEFAULT
, D3DX_DEFAULT
, D3DX_DEFAULT
,
1156 // Obtain depth buffer that was created in context
1157 pZBuffer
= pD3DXContext
->lpVtbl
->GetZBuffer(pD3DXContext
);
1159 // Get pixel format of depth buffer
1160 ddpf
.dwSize
= sizeof(ddpf
);
1161 pZBuffer
->lpVtbl
->GetPixelFormat(pZBuffer
, &ddpf
);
1162 // Done with surface - release it
1163 pZBuffer
->lpVtbl
->Release(pZBuffer
);
1165 // Done with D3DX context
1166 pD3DXContext
->lpVtbl
->Release(pD3DXContext
);
1168 // Convert and return
1169 return D3DXMakeSurfaceFormat(&ddpf
);
1172 //---------------------------------------------------------------------------
1174 BOOL
gldBuildPixelformatList_DX(void)
1176 D3DX_DEVICEDESC d3dxdd
;
1177 D3DX_VIDMODEDESC d3ddm
;
1178 D3DX_SURFACEFORMAT fmt
[64]; // 64 should be enough...
1179 DWORD dwDeviceIndex
;
1180 DWORD surfClassFlags
;
1181 // IDirect3D7 *pD3D = NULL;
1183 int nSupportedFormats
= 0; // Total formats
1184 int nDepthOnlyFormats
= 0;
1185 int nDepthStencilFormats
= 0;
1187 DGL_pixelFormat
*pPF
;
1188 BYTE cColorBits
, cRedBits
, cGreenBits
, cBlueBits
, cAlphaBits
;
1192 // Direct3D (SW or HW)
1193 // These are arranged so that 'best' pixelformat
1194 // is higher in the list (for ChoosePixelFormat).
1195 /* const D3DFORMAT DepthStencil[4] = {
1196 D3DX_SF_Z16S0, //D3DX_SF_D16,
1197 D3DX_SF_Z15S1, //D3DX_SF_D15S1,
1198 D3DX_SF_Z32S0, //D3DX_SF_D32,
1199 D3DX_SF_Z24S8, //D3DX_SF_D24S8,
1205 ddlogMessage(GLDLOG_SYSTEM
, "DirectX Version : 7.0\n");
1207 // Release any existing pixelformat list
1212 glb
.nPixelFormatCount
= 0;
1216 // Pixelformats for Direct3D (SW or HW) rendering
1219 dwDeviceIndex
= (glb
.dwDriver
== GLDS_DRIVER_REF
) ? D3DX_HWLEVEL_REFERENCE
: D3DX_DEFAULT
;
1222 D3DXGetDeviceDescription(dwDeviceIndex
, &d3dxdd
);
1223 ddlogPrintf(GLDLOG_SYSTEM
, "Device: %s", d3dxdd
.driverDesc
);
1226 D3DXGetCurrentVideoMode(D3DX_DEFAULT
, &d3ddm
);
1229 // Phooey - this don't work...
1231 // Since D3DXGetMaxSurfaceFormats() can lie to us, we'll need a workaround.
1232 // Explicitly test for matching depth/stencil to display bpp.
1233 if (d3ddm.bpp <= 16) {
1234 if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z16S0))
1235 fmt[nSupportedFormats++] = D3DX_SF_Z16S0;
1236 if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z15S1))
1237 fmt[nSupportedFormats++] = D3DX_SF_Z15S1;
1238 if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_S1Z15))
1239 fmt[nSupportedFormats++] = D3DX_SF_S1Z15;
1240 // Didn't find anything? Try default
1241 if (nSupportedFormats == 0) {
1242 if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z32S0))
1243 fmt[nSupportedFormats++] = D3DX_SF_Z32S0;
1246 if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z32S0))
1247 fmt[nSupportedFormats++] = D3DX_SF_Z32S0;
1248 if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z24S8))
1249 fmt[nSupportedFormats++] = D3DX_SF_Z24S8;
1250 if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_S8Z24))
1251 fmt[nSupportedFormats++] = D3DX_SF_S8Z24;
1252 // Didn't find anything? Try default
1253 if (nSupportedFormats == 0) {
1254 if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z16S0))
1255 fmt[nSupportedFormats++] = D3DX_SF_Z16S0;
1259 // Go the Whole Hog...
1260 fmt
[nSupportedFormats
++] = _gldFindCompatibleDepthStencilFormat(dwDeviceIndex
);
1263 // Depth buffer formats WITHOUT stencil
1265 surfClassFlags
= D3DX_SC_DEPTHBUFFER
;
1266 nDepthOnlyFormats
= D3DXGetMaxSurfaceFormats(dwDeviceIndex
, NULL
, surfClassFlags
);
1268 // Depth buffer formats WITH stencil
1270 surfClassFlags
= D3DX_SC_DEPTHBUFFER
| D3DX_SC_STENCILBUFFER
;
1271 nDepthStencilFormats
= D3DXGetMaxSurfaceFormats(dwDeviceIndex
, NULL
, surfClassFlags
);
1273 // Work out how many formats we have in total
1274 if ((nDepthOnlyFormats
+ nDepthStencilFormats
) == 0)
1275 return FALSE
; // Bail: no compliant pixelformats
1277 // Get depth buffer formats WITHOUT stencil
1278 surfClassFlags
= D3DX_SC_DEPTHBUFFER
;
1279 for (i
=0; i
<nDepthOnlyFormats
; i
++) {
1280 D3DXGetSurfaceFormat(dwDeviceIndex
, NULL
, surfClassFlags
, i
, &fmt
[nSupportedFormats
++]);
1282 // NOTE: For some reason we already get stencil formats when only specifying D3DX_SC_DEPTHBUFFER
1284 // Get depth buffer formats WITH stencil
1285 surfClassFlags = D3DX_SC_DEPTHBUFFER | D3DX_SC_STENCILBUFFER;
1286 for (i=0; i<nDepthStencilFormats; i++) {
1287 D3DXGetSurfaceFormat(dwDeviceIndex, NULL, surfClassFlags, i, &fmt[nSupportedFormats++]);
1292 // Total count of pixelformats is:
1293 // (nSupportedFormats+1)*2
1294 glb
.lpPF
= (DGL_pixelFormat
*)calloc((nSupportedFormats
)*2, sizeof(DGL_pixelFormat
));
1295 glb
.nPixelFormatCount
= (nSupportedFormats
)*2;
1296 if (glb
.lpPF
== NULL
) {
1297 glb
.nPixelFormatCount
= 0;
1301 // Get a copy of pointer that we can alter
1304 // Cache colour bits from display format
1305 // _BitsFromDisplayFormat(d3ddm.Format, &cColorBits, &cRedBits, &cGreenBits, &cBlueBits, &cAlphaBits);
1307 D3DXGetCurrentVideoMode(D3DX_DEFAULT
, &d3ddm
);
1308 cColorBits
= d3ddm
.bpp
;
1310 switch (d3ddm
.bpp
) {
1312 cRedBits
= 5; cGreenBits
= 5; cBlueBits
= 5;
1315 cRedBits
= 5; cGreenBits
= 6; cBlueBits
= 5;
1319 cRedBits
= 8; cGreenBits
= 8; cBlueBits
= 8;
1322 cRedBits
= 5; cGreenBits
= 5; cBlueBits
= 5;
1326 // Add single-buffer formats
1329 /* // Single-buffer, no depth-stencil buffer
1330 memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
1331 pPF->pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag
1332 pPF->pfd.cColorBits = cColorBits;
1333 pPF->pfd.cRedBits = cRedBits;
1334 pPF->pfd.cGreenBits = cGreenBits;
1335 pPF->pfd.cBlueBits = cBlueBits;
1336 pPF->pfd.cAlphaBits = cAlphaBits;
1337 pPF->pfd.cDepthBits = 0;
1338 pPF->pfd.cStencilBits = 0;
1339 pPF->dwDriverData = D3DX_SF_UNKNOWN;
1342 for (i
=0; i
<nSupportedFormats
; i
++, pPF
++) {
1343 memcpy(pPF
, &pfTemplateHW
, sizeof(DGL_pixelFormat
));
1344 pPF
->pfd
.dwFlags
&= ~PFD_DOUBLEBUFFER
; // Remove doublebuffer flag
1345 pPF
->pfd
.cColorBits
= cColorBits
;
1346 pPF
->pfd
.cRedBits
= cRedBits
;
1347 pPF
->pfd
.cGreenBits
= cGreenBits
;
1348 pPF
->pfd
.cBlueBits
= cBlueBits
;
1349 pPF
->pfd
.cAlphaBits
= cAlphaBits
;
1350 _BitsFromDepthStencilFormat(fmt
[i
], &pPF
->pfd
.cDepthBits
, &pPF
->pfd
.cStencilBits
);
1351 pPF
->dwDriverData
= fmt
[i
];
1355 // Add double-buffer formats
1358 /* memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
1359 pPF->pfd.cColorBits = cColorBits;
1360 pPF->pfd.cRedBits = cRedBits;
1361 pPF->pfd.cGreenBits = cGreenBits;
1362 pPF->pfd.cBlueBits = cBlueBits;
1363 pPF->pfd.cAlphaBits = cAlphaBits;
1364 pPF->pfd.cDepthBits = 0;
1365 pPF->pfd.cStencilBits = 0;
1366 pPF->dwDriverData = D3DX_SF_UNKNOWN;
1369 for (i
=0; i
<nSupportedFormats
; i
++, pPF
++) {
1370 memcpy(pPF
, &pfTemplateHW
, sizeof(DGL_pixelFormat
));
1371 pPF
->pfd
.cColorBits
= cColorBits
;
1372 pPF
->pfd
.cRedBits
= cRedBits
;
1373 pPF
->pfd
.cGreenBits
= cGreenBits
;
1374 pPF
->pfd
.cBlueBits
= cBlueBits
;
1375 pPF
->pfd
.cAlphaBits
= cAlphaBits
;
1376 _BitsFromDepthStencilFormat(fmt
[i
], &pPF
->pfd
.cDepthBits
, &pPF
->pfd
.cStencilBits
);
1377 pPF
->dwDriverData
= fmt
[i
];
1380 // Popup warning message if non RGB color mode
1382 // This is a hack. KeithH
1383 HDC hdcDesktop
= GetDC(NULL
);
1384 DWORD dwDisplayBitDepth
= GetDeviceCaps(hdcDesktop
, BITSPIXEL
);
1385 ReleaseDC(0, hdcDesktop
);
1386 if (dwDisplayBitDepth
<= 8) {
1387 ddlogPrintf(DDLOG_WARN
, "Current Color Depth %d bpp is not supported", dwDisplayBitDepth
);
1388 MessageBox(NULL
, szColorDepthWarning
, "GLDirect", MB_OK
| MB_ICONWARNING
);
1392 // Mark list as 'current'
1393 glb
.bPixelformatsDirty
= FALSE
;
1398 //---------------------------------------------------------------------------
1400 BOOL
gldInitialiseMesa_DX(
1403 GLD_driver_dx7
*gld
= NULL
;
1404 int MaxTextureSize
, TextureLevels
;
1410 gld
= lpCtx
->glPriv
;
1414 if (glb
.bMultitexture
) {
1415 lpCtx
->glCtx
->Const
.MaxTextureUnits
= gld
->d3dCaps
.wMaxSimultaneousTextures
;
1416 // Only support MAX_TEXTURE_UNITS texture units.
1417 // ** If this is altered then the FVF formats must be reviewed **.
1418 if (lpCtx
->glCtx
->Const
.MaxTextureUnits
> GLD_MAX_TEXTURE_UNITS_DX7
)
1419 lpCtx
->glCtx
->Const
.MaxTextureUnits
= GLD_MAX_TEXTURE_UNITS_DX7
;
1421 // Multitexture override
1422 lpCtx
->glCtx
->Const
.MaxTextureUnits
= 1;
1425 lpCtx
->glCtx
->Const
.MaxDrawBuffers
= 1;
1428 // MaxTextureSize = min(gld->d3dCaps8.MaxTextureHeight, gld->d3dCaps8.MaxTextureWidth);
1429 MaxTextureSize
= min(gld
->d3dCaps
.dwMaxTextureHeight
, gld
->d3dCaps
.dwMaxTextureWidth
);
1430 if (MaxTextureSize
== 0)
1431 MaxTextureSize
= 256; // Sanity check
1435 if (MaxTextureSize
> 1024)
1436 MaxTextureSize
= 1024; // HACK - CLAMP TO 1024
1440 // TODO: Check this again for Mesa 5
1441 // Got to set MAX_TEXTURE_SIZE as max levels.
1442 // Who thought this stupid idea up? ;)
1444 // Calculate power-of-two.
1445 while (MaxTextureSize
) {
1447 MaxTextureSize
>>= 1;
1449 lpCtx
->glCtx
->Const
.MaxTextureLevels
= (TextureLevels
) ? TextureLevels
: 8;
1452 IDirect3DDevice7_SetRenderState(gld
->pDev
, D3DRENDERSTATE_LIGHTING
, FALSE
);
1453 IDirect3DDevice7_SetRenderState(gld
->pDev
, D3DRENDERSTATE_CULLMODE
, D3DCULL_NONE
);
1454 IDirect3DDevice7_SetRenderState(gld
->pDev
, D3DRENDERSTATE_DITHERENABLE
, TRUE
);
1455 IDirect3DDevice7_SetRenderState(gld
->pDev
, D3DRENDERSTATE_SHADEMODE
, D3DSHADE_GOURAUD
);
1457 // Set texture coord set to be used with each stage
1458 IDirect3DDevice7_SetTextureStageState(gld
->pDev
, 0, D3DTSS_TEXCOORDINDEX
, 0);
1459 IDirect3DDevice7_SetTextureStageState(gld
->pDev
, 1, D3DTSS_TEXCOORDINDEX
, 1);
1461 // Set up Depth buffer
1462 IDirect3DDevice7_SetRenderState(gld
->pDev
, D3DRENDERSTATE_ZENABLE
,
1463 (lpCtx
->lpPF
->dwDriverData
!=D3DX_SF_UNKNOWN
) ? D3DZB_TRUE
: D3DZB_FALSE
);
1465 // Set the view matrix
1469 D3DXMatrixIdentity(&vm
);
1471 D3DXVECTOR3
Eye(0.0f
, 0.0f
, 0.0f
);
1472 D3DXVECTOR3
At(0.0f
, 0.0f
, -1.0f
);
1473 D3DXVECTOR3
Up(0.0f
, 1.0f
, 0.0f
);
1474 D3DXMatrixLookAtRH(&vm
, &Eye
, &At
, &Up
);
1480 IDirect3DDevice7_SetTransform(gld
->pDev
, D3DTRANSFORMSTATE_VIEW
, &vm
);
1483 // DX7 does not support D3DRS_SOFTWAREVERTEXPROCESSING
1485 if (gld->bHasHWTnL) {
1486 if (glb.dwTnL == GLDS_TNL_DEFAULT)
1487 bSoftwareTnL = FALSE; // HW TnL
1489 bSoftwareTnL = ((glb.dwTnL == GLDS_TNL_MESA) || (glb.dwTnL == GLDS_TNL_D3DSW)) ? TRUE : FALSE;
1492 // No HW TnL, so no choice possible
1493 bSoftwareTnL = TRUE;
1495 IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, bSoftwareTnL);
1498 // Dump this in a Release build as well, now.
1500 ddlogPrintf(DDLOG_INFO
, "HW TnL: %s",
1501 // gld->bHasHWTnL ? (bSoftwareTnL ? "Disabled" : "Enabled") : "Unavailable");
1502 gld
->bHasHWTnL
? "Enabled" : "Unavailable");
1505 // Set up interfaces to Mesa
1506 gldEnableExtensions_DX7(lpCtx
->glCtx
);
1507 gldInstallPipeline_DX7(lpCtx
->glCtx
);
1508 gldSetupDriverPointers_DX7(lpCtx
->glCtx
);
1510 // Signal a complete state update
1511 lpCtx
->glCtx
->Driver
.UpdateState(lpCtx
->glCtx
, _NEW_ALL
);
1514 IDirect3DDevice7_BeginScene(gld
->pDev
);
1515 lpCtx
->bSceneStarted
= TRUE
;
1520 //---------------------------------------------------------------------------
1522 BOOL
gldSwapBuffers_DX(
1528 GLD_driver_dx7
*gld
= NULL
;
1539 // End the scene if one is started
1540 if (ctx
->bSceneStarted
) {
1541 IDirect3DDevice7_EndScene(gld
->pDev
);
1542 ctx
->bSceneStarted
= FALSE
;
1545 // Needed by D3DX for MDI multi-window apps (DaveM)
1547 IDirectDrawClipper_SetHWnd(lpDDClipper
, 0, hWnd
);
1549 // Swap the buffers. hWnd may override the hWnd used for CreateDevice()
1550 // hr = IDirect3DDevice8_Present(gld->pDev, NULL, NULL, hWnd, NULL);
1552 // Set refresh sync flag
1553 dwFlags
= glb
.bWaitForRetrace
? 0 : D3DX_UPDATE_NOVSYNC
;
1554 // Render and show frame
1555 hr
= gld
->pD3DXContext
->lpVtbl
->UpdateFrame(gld
->pD3DXContext
, dwFlags
);
1557 ddlogError(DDLOG_WARN
, "gldSwapBuffers_DX: UpdateFrame", hr
);
1559 if (hr
== DDERR_SURFACELOST
) {
1560 hr
= gld
->pD3DXContext
->lpVtbl
->RestoreSurfaces(gld
->pD3DXContext
);
1562 ddlogError(DDLOG_WARN
, "gldSwapBuffers_DX: RestoreSurfaces", hr
);
1566 // Begin a new scene
1567 IDirect3DDevice7_BeginScene(gld
->pDev
);
1568 ctx
->bSceneStarted
= TRUE
;
1570 return (FAILED(hr
)) ? FALSE
: TRUE
;
1573 //---------------------------------------------------------------------------
1575 BOOL
gldGetDisplayMode_DX(
1577 GLD_displayMode
*glddm
)
1579 // D3DDISPLAYMODE d3ddm;
1580 D3DX_VIDMODEDESC d3ddm
;
1582 GLD_driver_dx7
*lpCtx
= NULL
;
1583 BYTE cColorBits
, cRedBits
, cGreenBits
, cBlueBits
, cAlphaBits
;
1585 if ((glddm
== NULL
) || (ctx
== NULL
))
1588 lpCtx
= ctx
->glPriv
;
1592 if (lpCtx
->pD3D
== NULL
)
1595 // hr = IDirect3D8_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm);
1596 hr
= D3DXGetCurrentVideoMode(D3DX_DEFAULT
, &d3ddm
);
1600 // Get info from the display format
1601 // _BitsFromDisplayFormat(d3ddm.Format,
1602 // &cColorBits, &cRedBits, &cGreenBits, &cBlueBits, &cAlphaBits);
1604 glddm
->Width
= d3ddm
.width
;
1605 glddm
->Height
= d3ddm
.height
;
1606 glddm
->BPP
= d3ddm
.bpp
;
1607 glddm
->Refresh
= d3ddm
.refreshRate
;
1612 //---------------------------------------------------------------------------