draw: corrections to allow for different cliptest cases
[mesa.git] / src / mesa / drivers / windows / gldirect / dx7 / gld_wgl_dx7.c
1 /****************************************************************************
2 *
3 * Mesa 3-D graphics library
4 * Direct3D Driver Interface
5 *
6 * ========================================================================
7 *
8 * Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
9 *
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:
16 *
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
19 *
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
26 * SOFTWARE.
27 *
28 * ======================================================================
29 *
30 * Language: ANSI C
31 * Environment: Windows 9x/2000/XP/XBox (Win32)
32 *
33 * Description: GLDirect Direct3D 8.x WGL (WindowsGL)
34 *
35 ****************************************************************************/
36
37 #include "dglcontext.h"
38 #include "gld_driver.h"
39 //#include "gld_dxerr8.h"
40 #include "gld_dx7.h"
41
42 #include "tnl/tnl.h"
43 #include "tnl/t_context.h"
44
45 // Copied from dglcontect.c
46 #define GLDERR_NONE 0
47 #define GLDERR_MEM 1
48 #define GLDERR_DDRAW 2
49 #define GLDERR_D3D 3
50 #define GLDERR_BPP 4
51 #define GLDERR_DDS 5
52 // This external var keeps track of any error
53 extern int nContextError;
54
55 // Uncomment this for persistant resources
56 //#define _GLD_PERSISTANT
57
58 #define DDLOG_CRITICAL_OR_WARN DDLOG_CRITICAL
59
60 extern void _gld_mesa_warning(GLcontext *, char *);
61 extern void _gld_mesa_fatal(GLcontext *, char *);
62
63 //---------------------------------------------------------------------------
64
65 static char szColorDepthWarning[] =
66 "GLDirect does not support the current desktop\n\
67 color depth.\n\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";
72
73 // The only depth-stencil formats currently supported by Direct3D
74 // Surface Format Depth Stencil Total Bits
75 // D3DFMT_D32 32 - 32
76 // D3DFMT_D15S1 15 1 16
77 // D3DFMT_D24S8 24 8 32
78 // D3DFMT_D16 16 - 16
79 // D3DFMT_D24X8 24 - 32
80 // D3DFMT_D24X4S4 24 4 32
81
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 =
87 {
88 {
89 sizeof(PIXELFORMATDESCRIPTOR), // Size of the data structure
90 1, // Structure version - should be 1
91 // Flags:
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
106 0, // Depth bits
107 0, // Stencil bits
108 0, // Number of auxiliary buffers
109 0, // Layer type
110 0, // Specifies the number of overlay and underlay planes.
111 0, // Layer mask
112 0, // Specifies the transparent color or index of an underlay plane.
113 0 // Damage mask
114 },
115 D3DX_SF_UNKNOWN, // No depth/stencil buffer
116 };
117
118 //---------------------------------------------------------------------------
119 // Vertex Shaders
120 //---------------------------------------------------------------------------
121 /*
122 // Vertex Shader Declaration
123 static DWORD dwTwoSidedLightingDecl[] =
124 {
125 D3DVSD_STREAM(0),
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
132 D3DVSD_END()
133 };
134
135 // Vertex Shader for two-sided lighting
136 static char *szTwoSidedLightingVS =
137 // This is a test shader!
138 "vs.1.0\n"
139 "m4x4 oPos,v0,c0\n"
140 "mov oD0,v2\n"
141 "mov oD1,v3\n"
142 "mov oT0,v4\n"
143 "mov oT1,v5\n"
144 ;
145 */
146 //---------------------------------------------------------------------------
147 //---------------------------------------------------------------------------
148
149 typedef struct {
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
156 BOOL bD3DXStarted;
157 } GLD_dx7_globals;
158
159 // These are "global" to all DX7 contexts. KeithH
160 static GLD_dx7_globals dx7Globals;
161
162 // Added for correct clipping of multiple open windows. (DaveM)
163 LPDIRECTDRAWSURFACE7 lpDDSPrimary = NULL;
164 LPDIRECTDRAWCLIPPER lpDDClipper = NULL;
165
166 //---------------------------------------------------------------------------
167 //---------------------------------------------------------------------------
168
169 BOOL gldGetDXErrorString_DX(
170 HRESULT hr,
171 char *buf,
172 int nBufSize)
173 {
174 //
175 // Return a string describing the input HRESULT error code
176 //
177
178 D3DXGetErrorString(hr, nBufSize, buf);
179 return TRUE;
180 }
181
182 //---------------------------------------------------------------------------
183 //
184 // DX7 does not support multisample
185 /*
186 static D3DMULTISAMPLE_TYPE _gldGetDeviceMultiSampleType(
187 IDirect3D8 *pD3D8,
188 D3DFORMAT SurfaceFormat,
189 D3DDEVTYPE d3dDevType,
190 BOOL Windowed)
191 {
192 int i;
193 HRESULT hr;
194
195 if (glb.dwMultisample == GLDS_MULTISAMPLE_NONE)
196 return D3DMULTISAMPLE_NONE;
197
198 if (glb.dwMultisample == GLDS_MULTISAMPLE_FASTEST) {
199 // Find fastest multisample
200 for (i=2; i<17; i++) {
201 hr = IDirect3D8_CheckDeviceMultiSampleType(
202 pD3D8,
203 glb.dwAdapter,
204 d3dDevType,
205 SurfaceFormat,
206 Windowed,
207 (D3DMULTISAMPLE_TYPE)i);
208 if (SUCCEEDED(hr)) {
209 return (D3DMULTISAMPLE_TYPE)i;
210 }
211 }
212 } else {
213 // Find nicest multisample
214 for (i=16; i>1; i--) {
215 hr = IDirect3D8_CheckDeviceMultiSampleType(
216 pD3D8,
217 glb.dwAdapter,
218 d3dDevType,
219 SurfaceFormat,
220 Windowed,
221 (D3DMULTISAMPLE_TYPE)i);
222 if (SUCCEEDED(hr)) {
223 return (D3DMULTISAMPLE_TYPE)i;
224 }
225 }
226 }
227
228 // Nothing found - return default
229 return D3DMULTISAMPLE_NONE;
230 }
231 */
232 //---------------------------------------------------------------------------
233
234 void _gldDestroyPrimitiveBuffer(
235 GLD_pb_dx7 *gldVB)
236 {
237 SAFE_RELEASE(gldVB->pVB);
238
239 // Sanity check...
240 gldVB->nLines = gldVB->nPoints = gldVB->nTriangles = 0;
241 }
242
243 //---------------------------------------------------------------------------
244
245 HRESULT _gldCreatePrimitiveBuffer(
246 GLcontext *ctx,
247 GLD_driver_dx7 *lpCtx,
248 GLD_pb_dx7 *gldVB)
249 {
250 HRESULT hResult;
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;
255
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;
260
261 // Max vertex buffer size limited in DX7. (DaveM)
262 if (dwMaxVertices*9 > D3DMAXNUMVERTICES)
263 dwMaxVertices = D3DMAXNUMVERTICES/9;
264
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;
268
269 vbdesc.dwSize = sizeof(vbdesc);
270 vbdesc.dwCaps = gldVB->dwCreateFlags;
271 vbdesc.dwFVF = gldVB->dwFVF;
272 vbdesc.dwNumVertices = dwMaxVertices * 9;
273
274 /* hResult = IDirect3DDevice8_CreateVertexBuffer(
275 lpCtx->pDev,
276 dwVBSize,
277 RAgldVB->dwUsage,
278 gldVB->dwFVF,
279 gldVB->dwPool,
280 &gldVB->pVB);*/
281 hResult = IDirect3D7_CreateVertexBuffer(
282 lpCtx->pD3D,
283 &vbdesc,
284 &gldVB->pVB,
285 0);
286 if (FAILED(hResult)) {
287 ddlogMessage(DDLOG_CRITICAL_OR_WARN, szCreateVertexBufferFailed);
288 return hResult;
289 }
290
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
295
296 return S_OK;
297 }
298
299 //---------------------------------------------------------------------------
300 // Function: _gldCreateVertexShaders
301 // Create DX8 Vertex Shaders.
302 //---------------------------------------------------------------------------
303 /*
304 void _gldCreateVertexShaders(
305 GLD_driver_dx8 *gld)
306 {
307 DWORD dwFlags;
308 LPD3DXBUFFER pVSOpcodeBuffer; // Vertex Shader opcode buffer
309 HRESULT hr;
310
311 #ifdef _DEBUG
312 dwFlags = D3DXASM_DEBUG;
313 #else
314 dwFlags = 0; // D3DXASM_SKIPVALIDATION;
315 #endif
316
317 ddlogMessage(DDLOG_INFO, "Creating shaders...\n");
318
319 // Init the shader handle
320 gld->VStwosidelight.hShader = 0;
321
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");
326 return;
327 }
328
329 // ** THIS DISABLES VERTEX SHADER SUPPORT **
330 // return;
331 // ** THIS DISABLES VERTEX SHADER SUPPORT **
332
333 //
334 // Two-sided lighting
335 //
336
337 #if 0
338 //
339 // DEBUGGING: Load shader from a text file
340 //
341 {
342 LPD3DXBUFFER pVSErrorBuffer; // Vertex Shader error buffer
343 hr = D3DXAssembleShaderFromFile(
344 "twoside.vsh",
345 dwFlags,
346 NULL, // No constants
347 &pVSOpcodeBuffer,
348 &pVSErrorBuffer);
349 if (pVSErrorBuffer && pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer))
350 ddlogMessage(DDLOG_INFO, pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer));
351 SAFE_RELEASE(pVSErrorBuffer);
352 }
353 #else
354 {
355 LPD3DXBUFFER pVSErrorBuffer; // Vertex Shader error buffer
356 // Assemble ascii shader text into shader opcodes
357 hr = D3DXAssembleShader(
358 szTwoSidedLightingVS,
359 strlen(szTwoSidedLightingVS),
360 dwFlags,
361 NULL, // No constants
362 &pVSOpcodeBuffer,
363 &pVSErrorBuffer);
364 if (pVSErrorBuffer && pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer))
365 ddlogMessage(DDLOG_INFO, pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer));
366 SAFE_RELEASE(pVSErrorBuffer);
367 }
368 #endif
369 if (FAILED(hr)) {
370 ddlogError(DDLOG_WARN, "AssembleShader failed", hr);
371 SAFE_RELEASE(pVSOpcodeBuffer);
372 return;
373 }
374
375 // This is for debugging. Remove to enable vertex shaders in HW
376 #define _GLD_FORCE_SW_VS 0
377
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");
381 }
382
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
390 } else {
391 gld->VStwosidelight.bHardware = TRUE;
392 hr = IDirect3DDevice8_CreateVertexShader(
393 gld->pDev,
394 dwTwoSidedLightingDecl,
395 pVSOpcodeBuffer->lpVtbl->GetBufferPointer(pVSOpcodeBuffer),
396 &gld->VStwosidelight.hShader,
397 0);
398 }
399 if (FAILED(hr)) {
400 ddlogMessage(DDLOG_INFO, "... HW failed, trying SW...\n");
401 // Failed. Try and create shader for software processing
402 hr = IDirect3DDevice8_CreateVertexShader(
403 gld->pDev,
404 dwTwoSidedLightingDecl,
405 pVSOpcodeBuffer->lpVtbl->GetBufferPointer(pVSOpcodeBuffer),
406 &gld->VStwosidelight.hShader,
407 D3DUSAGE_SOFTWAREPROCESSING);
408 if (FAILED(hr)) {
409 gld->VStwosidelight.hShader = 0; // Sanity check
410 ddlogError(DDLOG_WARN, "CreateVertexShader failed", hr);
411 return;
412 }
413 // Succeeded, but for software processing
414 gld->VStwosidelight.bHardware = FALSE;
415 }
416
417 SAFE_RELEASE(pVSOpcodeBuffer);
418
419 ddlogMessage(DDLOG_INFO, "... OK\n");
420 }
421
422 //---------------------------------------------------------------------------
423
424 void _gldDestroyVertexShaders(
425 GLD_driver_dx8 *gld)
426 {
427 if (gld->VStwosidelight.hShader) {
428 IDirect3DDevice8_DeleteVertexShader(gld->pDev, gld->VStwosidelight.hShader);
429 gld->VStwosidelight.hShader = 0;
430 }
431 }
432 */
433 //---------------------------------------------------------------------------
434
435 BOOL gldCreateDrawable_DX(
436 DGL_ctx *ctx,
437 // BOOL bDefaultDriver,
438 BOOL bDirectDrawPersistant,
439 BOOL bPersistantBuffers)
440 {
441 //
442 // bDirectDrawPersistant: applies to IDirect3D8
443 // bPersistantBuffers: applies to IDirect3DDevice8
444 //
445
446 // D3DDEVTYPE d3dDevType;
447 // D3DPRESENT_PARAMETERS d3dpp;
448 // D3DDISPLAYMODE d3ddm;
449 // DWORD dwBehaviourFlags;
450 // D3DADAPTER_IDENTIFIER8 d3dIdent;
451
452 HRESULT hr;
453 GLD_driver_dx7 *lpCtx = NULL;
454 D3DX_VIDMODEDESC d3ddm;
455
456 // Parameters for D3DXCreateContextEx
457 // These will be different for fullscreen and windowed
458 DWORD dwDeviceIndex;
459 DWORD dwFlags;
460 HWND hwnd;
461 HWND hwndFocus;
462 DWORD numColorBits;
463 DWORD numAlphaBits;
464 DWORD numDepthBits;
465 DWORD numStencilBits;
466 DWORD numBackBuffers;
467 DWORD dwWidth;
468 DWORD dwHeight;
469 DWORD refreshRate;
470
471 // Error if context is NULL.
472 if (ctx == NULL)
473 return FALSE;
474
475 if (ctx->glPriv) {
476 lpCtx = ctx->glPriv;
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;
482 } else {
483 lpCtx = (GLD_driver_dx7*)malloc(sizeof(GLD_driver_dx7));
484 ZeroMemory(lpCtx, sizeof(lpCtx));
485 }
486
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;
491
492 // TODO: Check this
493 // if (bDefaultDriver)
494 // d3dDevType = D3DDEVTYPE_REF;
495
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;
502 }
503 #endif
504 /*
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;
512 }
513 */
514
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;
521 }
522 SkipDirectDrawCreate:
523 #endif
524 /*
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;
530 }
531 */
532
533 #if 0
534 // Get device caps
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;
540 }
541
542 // Check for hardware transform & lighting
543 lpCtx->bHasHWTnL = lpCtx->d3dCaps8.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ? TRUE : FALSE;
544
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");
550 }
551 #endif
552
553 //
554 // Create the Direct3D context
555 //
556
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;
565 }
566 #endif
567 /*
568 // Clear the presentation parameters (sets all members to zero)
569 ZeroMemory(&d3dpp, sizeof(d3dpp));
570
571 // Recommended by MS; needed for MultiSample.
572 // Be careful if altering this for FullScreenBlit
573 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
574
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;
580
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;
588
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;
595 } else {
596 if (lpCtx->d3dCaps8.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE)
597 d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
598 }
599 } else {
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;
608 }
609
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,
617 glb.dwAdapter,
618 d3dDevType,
619 ctx->hWnd,
620 dwBehaviourFlags,
621 &d3dpp,
622 &lpCtx->pDev);
623 if (FAILED(hResult)) {
624 ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D8_CreateDevice failed", hResult);
625 nContextError = GLDERR_D3D;
626 goto return_with_error;
627 }
628 */
629
630 // Create D3DX context
631 if (ctx->bFullscreen) {
632 //
633 // FULLSCREEN
634 //
635
636 // Get display mode
637 D3DXGetCurrentVideoMode(D3DX_DEFAULT, &d3ddm);
638
639 // Fullscreen Parameters
640 dwFlags = D3DX_CONTEXT_FULLSCREEN;
641 hwnd = ctx->hWnd;
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;
651 } else {
652 //
653 // WINDOWED
654 //
655
656 // Windowed Parameters
657 dwFlags = 0; // No flags means "windowed"
658 hwnd = ctx->hWnd;
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;
668 }
669 hr = D3DXCreateContextEx(dwDeviceIndex, dwFlags, hwnd, hwndFocus,
670 numColorBits, numAlphaBits, numDepthBits, numStencilBits,
671 numBackBuffers,
672 dwWidth, dwHeight, refreshRate,
673 &lpCtx->pD3DXContext);
674 if (FAILED(hr)) {
675 ddlogError(DDLOG_CRITICAL_OR_WARN, "D3DXCreateContextEx failed", hr);
676 nContextError = GLDERR_D3D;
677 goto return_with_error;
678 }
679
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;
691
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;
700 }
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;
705 }
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;
710 }
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;
715 }
716 }
717
718 // Get device caps
719 IDirect3DDevice7_GetCaps(lpCtx->pDev, &lpCtx->d3dCaps);
720
721 // Determine HW TnL
722 lpCtx->bHasHWTnL = lpCtx->d3dCaps.dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ? TRUE : FALSE;
723
724 #ifdef _GLD_PERSISTANT
725 if (bDirectDrawPersistant && bPersistantBuffers && dx7Globals.pD3D) {
726 dx7Globals.pDev = lpCtx->pDev;
727 dx7Globals.bDirect3DDevice = TRUE;
728 }
729 #endif
730
731 #if 0
732 // Dump some useful stats
733 hResult = IDirect3D8_GetAdapterIdentifier(
734 lpCtx->pD3D,
735 glb.dwAdapter,
736 D3DENUM_NO_WHQL_LEVEL, // Avoids 1 to 2 second delay
737 &d3dIdent);
738 if (SUCCEEDED(hResult)) {
739 ddlogPrintf(DDLOG_INFO, "[Driver Description: %s]", &d3dIdent.Description);
740 ddlogPrintf(DDLOG_INFO, "[Driver file: %s %d.%d.%02d.%d]",
741 d3dIdent.Driver,
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);
748 }
749 #endif
750
751 // Init projection matrix for D3D TnL
752 D3DXMatrixIdentity((D3DXMATRIX*)&lpCtx->matProjection);
753 lpCtx->matModelView = lpCtx->matProjection;
754 // gld->bUseMesaProjection = TRUE;
755
756 skip_direct3ddevice_create:
757
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 |
764 D3DVBCAPS_WRITEONLY;
765 hr = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB2d);
766 if (FAILED(hr))
767 goto return_with_error;
768
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;
773
774 hr = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB3d);
775 if (FAILED(hr))
776 goto return_with_error;
777
778 // Zero the pipeline usage counters
779 lpCtx->PipelineUsage.qwMesa.QuadPart =
780 // lpCtx->PipelineUsage.dwD3D2SVS.QuadPart =
781 lpCtx->PipelineUsage.qwD3DFVF.QuadPart = 0;
782
783 // Assign drawable to GL private
784 ctx->glPriv = lpCtx;
785 return TRUE;
786
787 return_with_error:
788 // Clean up and bail
789 _gldDestroyPrimitiveBuffer(&lpCtx->PB3d);
790 _gldDestroyPrimitiveBuffer(&lpCtx->PB2d);
791
792 SAFE_RELEASE(lpCtx->pDev);
793 SAFE_RELEASE(lpCtx->pD3D);
794 //SAFE_RELEASE(lpCtx->pD3DXContext);
795 lpCtx->pD3DXContext->lpVtbl->Release(lpCtx->pD3DXContext);
796 return FALSE;
797 }
798
799 //---------------------------------------------------------------------------
800
801 BOOL gldResizeDrawable_DX(
802 DGL_ctx *ctx,
803 BOOL bDefaultDriver,
804 BOOL bPersistantInterface,
805 BOOL bPersistantBuffers)
806 {
807 GLD_driver_dx7 *gld = NULL;
808 // D3DDEVTYPE d3dDevType;
809 // D3DPRESENT_PARAMETERS d3dpp;
810 // D3DDISPLAYMODE d3ddm;
811 D3DX_VIDMODEDESC d3ddm;
812 HRESULT hr;
813 DWORD dwWidth, dwHeight;
814
815 // Error if context is NULL.
816 if (ctx == NULL)
817 return FALSE;
818
819 gld = ctx->glPriv;
820 if (gld == NULL)
821 return FALSE;
822
823 if (ctx->bSceneStarted) {
824 IDirect3DDevice7_EndScene(gld->pDev);
825 ctx->bSceneStarted = FALSE;
826 }
827 /*
828 d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF;
829 if (!bDefaultDriver)
830 d3dDevType = D3DDEVTYPE_REF; // Force Direct3D Reference Rasterise (software)
831
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;
837 return FALSE;
838 }
839 */
840 // Release objects before Reset()
841 _gldDestroyPrimitiveBuffer(&gld->PB3d);
842 _gldDestroyPrimitiveBuffer(&gld->PB2d);
843
844 /*
845 // Clear the presentation parameters (sets all members to zero)
846 ZeroMemory(&d3dpp, sizeof(d3dpp));
847
848 // Recommended by MS; needed for MultiSample.
849 // Be careful if altering this for FullScreenBlit
850 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
851
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;
857
858 // TODO: Sync to refresh
859
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;
870 } else {
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;
878 }
879 hResult = IDirect3DDevice8_Reset(gld->pDev, &d3dpp);
880 if (FAILED(hResult)) {
881 ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Reset failed", hResult);
882 return FALSE;
883 //goto cleanup_and_return_with_error;
884 }
885 */
886 // Obtain dimensions of 'window'
887 if (ctx->bFullscreen) {
888 D3DXGetCurrentVideoMode(D3DX_DEFAULT, &d3ddm);
889 dwWidth = d3ddm.width;
890 dwHeight = d3ddm.height;
891 } else {
892 dwWidth = ctx->dwWidth;
893 dwHeight = ctx->dwHeight;
894 }
895
896 // Resize context
897 hr = gld->pD3DXContext->lpVtbl->Resize(gld->pD3DXContext, dwWidth, dwHeight);
898 if (FAILED(hr)) {
899 ddlogError(DDLOG_CRITICAL_OR_WARN, "gldResizeDrawable_DX: Resize failed", hr);
900 return FALSE;
901 }
902
903 // Clear the resized surface (DaveM)
904 {
905 D3DVIEWPORT7 vp1, vp2;
906 IDirect3DDevice7_GetViewport(gld->pDev, &vp1);
907 IDirect3DDevice7_GetViewport(gld->pDev, &vp2);
908 vp2.dwX = 0;
909 vp2.dwY = 0;
910 vp2.dwWidth = dwWidth;
911 vp2.dwHeight = dwHeight;
912 IDirect3DDevice7_SetViewport(gld->pDev, &vp2);
913 hr = gld->pD3DXContext->lpVtbl->Clear(gld->pD3DXContext, D3DCLEAR_TARGET);
914 if (FAILED(hr))
915 ddlogError(DDLOG_WARN, "gldResizeDrawable_DX: Clear failed", hr);
916 IDirect3DDevice7_SetViewport(gld->pDev, &vp1);
917 }
918
919 //
920 // Recreate objects
921 //
922 _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB2d);
923 _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB3d);
924
925 // Signal a complete state update
926 ctx->glCtx->Driver.UpdateState(ctx->glCtx, _NEW_ALL);
927
928 // Begin a new scene
929 IDirect3DDevice7_BeginScene(gld->pDev);
930 ctx->bSceneStarted = TRUE;
931
932 return TRUE;
933 }
934
935 //---------------------------------------------------------------------------
936
937 BOOL gldDestroyDrawable_DX(
938 DGL_ctx *ctx)
939 {
940 GLD_driver_dx7 *lpCtx = NULL;
941
942 // Error if context is NULL.
943 if (!ctx)
944 return FALSE;
945
946 // Error if the drawable does not exist.
947 if (!ctx->glPriv)
948 return FALSE;
949
950 lpCtx = ctx->glPriv;
951
952 #ifdef _DEBUG
953 // Dump out stats
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);
959 #endif
960
961 // Destroy Primtive Buffers
962 _gldDestroyPrimitiveBuffer(&lpCtx->PB3d);
963 _gldDestroyPrimitiveBuffer(&lpCtx->PB2d);
964
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);
970
971 // Free the private drawable data
972 free(ctx->glPriv);
973 ctx->glPriv = NULL;
974
975 return TRUE;
976 }
977
978 //---------------------------------------------------------------------------
979
980 BOOL gldCreatePrivateGlobals_DX(void)
981 {
982 /*
983 ZeroMemory(&dx7Globals, sizeof(dx7Globals));
984
985 // Load d3d8.dll
986 dx8Globals.hD3D8DLL = LoadLibrary("D3D8.DLL");
987 if (dx8Globals.hD3D8DLL == NULL)
988 return FALSE;
989
990 // Now try and obtain Direct3DCreate8
991 dx8Globals.fnDirect3DCreate8 = (FNDIRECT3DCREATE8)GetProcAddress(dx8Globals.hD3D8DLL, "Direct3DCreate8");
992 if (dx8Globals.fnDirect3DCreate8 == NULL) {
993 FreeLibrary(dx8Globals.hD3D8DLL);
994 return FALSE;
995 }
996 */
997
998 // Initialise D3DX
999 return FAILED(D3DXInitialize()) ? FALSE : TRUE;
1000 }
1001
1002 //---------------------------------------------------------------------------
1003
1004 BOOL gldDestroyPrivateGlobals_DX(void)
1005 {
1006 /*
1007 if (dx7Globals.bDirect3DDevice) {
1008 SAFE_RELEASE(dx7Globals.pDev);
1009 dx7Globals.bDirect3DDevice = FALSE;
1010 }
1011 if (dx7Globals.bDirect3D) {
1012 SAFE_RELEASE(dx7Globals.pD3D);
1013 dx7Globals.bDirect3D = FALSE;
1014 }
1015
1016 FreeLibrary(dx8Globals.hD3D8DLL);
1017 dx8Globals.hD3D8DLL = NULL;
1018 dx8Globals.fnDirect3DCreate8 = NULL;
1019 */
1020 return FAILED(D3DXUninitialize()) ? FALSE : TRUE;
1021 }
1022
1023 //---------------------------------------------------------------------------
1024
1025 static void _BitsFromDisplayFormat(
1026 D3DX_SURFACEFORMAT fmt,
1027 BYTE *cColorBits,
1028 BYTE *cRedBits,
1029 BYTE *cGreenBits,
1030 BYTE *cBlueBits,
1031 BYTE *cAlphaBits)
1032 {
1033 switch (fmt) {
1034 /* case D3DX_SF_X1R5G5B5:
1035 *cColorBits = 16;
1036 *cRedBits = 5;
1037 *cGreenBits = 5;
1038 *cBlueBits = 5;
1039 *cAlphaBits = 0;
1040 return;*/
1041 case D3DX_SF_R5G5B5:
1042 *cColorBits = 16;
1043 *cRedBits = 5;
1044 *cGreenBits = 5;
1045 *cBlueBits = 5;
1046 *cAlphaBits = 0;
1047 return;
1048 case D3DX_SF_R5G6B5:
1049 *cColorBits = 16;
1050 *cRedBits = 5;
1051 *cGreenBits = 6;
1052 *cBlueBits = 5;
1053 *cAlphaBits = 0;
1054 return;
1055 case D3DX_SF_X8R8G8B8:
1056 *cColorBits = 32;
1057 *cRedBits = 8;
1058 *cGreenBits = 8;
1059 *cBlueBits = 8;
1060 *cAlphaBits = 0;
1061 return;
1062 case D3DX_SF_A8R8G8B8:
1063 *cColorBits = 32;
1064 *cRedBits = 8;
1065 *cGreenBits = 8;
1066 *cBlueBits = 8;
1067 *cAlphaBits = 8;
1068 return;
1069 }
1070
1071 // Should not get here!
1072 *cColorBits = 32;
1073 *cRedBits = 8;
1074 *cGreenBits = 8;
1075 *cBlueBits = 8;
1076 *cAlphaBits = 0;
1077 }
1078
1079 //---------------------------------------------------------------------------
1080
1081 static void _BitsFromDepthStencilFormat(
1082 D3DX_SURFACEFORMAT fmt,
1083 BYTE *cDepthBits,
1084 BYTE *cStencilBits)
1085 {
1086 // NOTE: GL expects either 32 or 16 as depth bits.
1087 switch (fmt) {
1088 case D3DX_SF_Z16S0:
1089 *cDepthBits = 16;
1090 *cStencilBits = 0;
1091 return;
1092 case D3DX_SF_Z32S0:
1093 *cDepthBits = 32;
1094 *cStencilBits = 0;
1095 return;
1096 case D3DX_SF_Z15S1:
1097 *cDepthBits = 15;
1098 *cStencilBits = 1;
1099 return;
1100 case D3DX_SF_Z24S8:
1101 *cDepthBits = 24;
1102 *cStencilBits = 8;
1103 return;
1104 case D3DX_SF_S1Z15:
1105 *cDepthBits = 15;
1106 *cStencilBits = 1;
1107 return;
1108 case D3DX_SF_S8Z24:
1109 *cDepthBits = 24;
1110 *cStencilBits = 8;
1111 return;
1112 }
1113 }
1114
1115 //---------------------------------------------------------------------------
1116 /*
1117 BOOL GLD_CheckDepthStencilMatch(
1118 DWORD dwDeviceIndex,
1119 D3DX_SURFACEFORMAT sfWant)
1120 {
1121 // Emulate function built in to DX9
1122 D3DX_SURFACEFORMAT sfFound;
1123 int i;
1124 int nFormats = D3DXGetMaxSurfaceFormats(dwDeviceIndex, NULL, D3DX_SC_DEPTHBUFFER);
1125 if (nFormats) {
1126 for (i=0; i<nFormats; i++) {
1127 D3DXGetSurfaceFormat(dwDeviceIndex, NULL, D3DX_SC_DEPTHBUFFER, i, &sfFound); }
1128 if (sfFound == sfWant)
1129 return TRUE;
1130 }
1131
1132 return FALSE;
1133 }
1134 */
1135 //---------------------------------------------------------------------------
1136
1137 D3DX_SURFACEFORMAT _gldFindCompatibleDepthStencilFormat(
1138 DWORD dwDeviceIndex)
1139 {
1140 // Jump through some hoops...
1141
1142 ID3DXContext *pD3DXContext = NULL;
1143 IDirectDrawSurface7 *pZBuffer = NULL;
1144 DDPIXELFORMAT ddpf;
1145 HWND hWnd;
1146
1147 // Get an HWND - use Desktop's
1148 hWnd = GetDesktopWindow();
1149
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,
1154 &pD3DXContext);
1155
1156 // Obtain depth buffer that was created in context
1157 pZBuffer = pD3DXContext->lpVtbl->GetZBuffer(pD3DXContext);
1158
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);
1164
1165 // Done with D3DX context
1166 pD3DXContext->lpVtbl->Release(pD3DXContext);
1167
1168 // Convert and return
1169 return D3DXMakeSurfaceFormat(&ddpf);
1170 }
1171
1172 //---------------------------------------------------------------------------
1173
1174 BOOL gldBuildPixelformatList_DX(void)
1175 {
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;
1182 HRESULT hr;
1183 int nSupportedFormats = 0; // Total formats
1184 int nDepthOnlyFormats = 0;
1185 int nDepthStencilFormats = 0;
1186 int i;
1187 DGL_pixelFormat *pPF;
1188 BYTE cColorBits, cRedBits, cGreenBits, cBlueBits, cAlphaBits;
1189 // char buf[128];
1190 // char cat[8];
1191
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,
1200 //D3DX_SF_D24X8,
1201 //D3DX_SF_D24X4S4,
1202 };*/
1203
1204 // Dump DX version
1205 ddlogMessage(GLDLOG_SYSTEM, "DirectX Version : 7.0\n");
1206
1207 // Release any existing pixelformat list
1208 if (glb.lpPF) {
1209 free(glb.lpPF);
1210 }
1211
1212 glb.nPixelFormatCount = 0;
1213 glb.lpPF = NULL;
1214
1215 //
1216 // Pixelformats for Direct3D (SW or HW) rendering
1217 //
1218
1219 dwDeviceIndex = (glb.dwDriver == GLDS_DRIVER_REF) ? D3DX_HWLEVEL_REFERENCE : D3DX_DEFAULT;
1220
1221 // Dump description
1222 D3DXGetDeviceDescription(dwDeviceIndex, &d3dxdd);
1223 ddlogPrintf(GLDLOG_SYSTEM, "Device: %s", d3dxdd.driverDesc);
1224
1225 // Get display mode
1226 D3DXGetCurrentVideoMode(D3DX_DEFAULT, &d3ddm);
1227
1228 #if 0
1229 // Phooey - this don't work...
1230 /*
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;
1244 }
1245 } else {
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;
1256 }
1257 }
1258 */
1259 // Go the Whole Hog...
1260 fmt[nSupportedFormats++] = _gldFindCompatibleDepthStencilFormat(dwDeviceIndex);
1261 #else
1262 //
1263 // Depth buffer formats WITHOUT stencil
1264 //
1265 surfClassFlags = D3DX_SC_DEPTHBUFFER;
1266 nDepthOnlyFormats = D3DXGetMaxSurfaceFormats(dwDeviceIndex, NULL, surfClassFlags);
1267 //
1268 // Depth buffer formats WITH stencil
1269 //
1270 surfClassFlags = D3DX_SC_DEPTHBUFFER | D3DX_SC_STENCILBUFFER;
1271 nDepthStencilFormats = D3DXGetMaxSurfaceFormats(dwDeviceIndex, NULL, surfClassFlags);
1272
1273 // Work out how many formats we have in total
1274 if ((nDepthOnlyFormats + nDepthStencilFormats) == 0)
1275 return FALSE; // Bail: no compliant pixelformats
1276
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++]);
1281 }
1282 // NOTE: For some reason we already get stencil formats when only specifying D3DX_SC_DEPTHBUFFER
1283 /*
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++]);
1288 }
1289 */
1290 #endif
1291
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;
1298 return FALSE;
1299 }
1300
1301 // Get a copy of pointer that we can alter
1302 pPF = glb.lpPF;
1303
1304 // Cache colour bits from display format
1305 // _BitsFromDisplayFormat(d3ddm.Format, &cColorBits, &cRedBits, &cGreenBits, &cBlueBits, &cAlphaBits);
1306 // Get display mode
1307 D3DXGetCurrentVideoMode(D3DX_DEFAULT, &d3ddm);
1308 cColorBits = d3ddm.bpp;
1309 cAlphaBits = 0;
1310 switch (d3ddm.bpp) {
1311 case 15:
1312 cRedBits = 5; cGreenBits = 5; cBlueBits = 5;
1313 break;
1314 case 16:
1315 cRedBits = 5; cGreenBits = 6; cBlueBits = 5;
1316 break;
1317 case 24:
1318 case 32:
1319 cRedBits = 8; cGreenBits = 8; cBlueBits = 8;
1320 break;
1321 default:
1322 cRedBits = 5; cGreenBits = 5; cBlueBits = 5;
1323 }
1324
1325 //
1326 // Add single-buffer formats
1327 //
1328
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;
1340 pPF++;*/
1341
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];
1352 }
1353
1354 //
1355 // Add double-buffer formats
1356 //
1357
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;
1367 pPF++;*/
1368
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];
1378 }
1379
1380 // Popup warning message if non RGB color mode
1381 {
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);
1389 }
1390 }
1391
1392 // Mark list as 'current'
1393 glb.bPixelformatsDirty = FALSE;
1394
1395 return TRUE;
1396 }
1397
1398 //---------------------------------------------------------------------------
1399
1400 BOOL gldInitialiseMesa_DX(
1401 DGL_ctx *lpCtx)
1402 {
1403 GLD_driver_dx7 *gld = NULL;
1404 int MaxTextureSize, TextureLevels;
1405 BOOL bSoftwareTnL;
1406
1407 if (lpCtx == NULL)
1408 return FALSE;
1409
1410 gld = lpCtx->glPriv;
1411 if (gld == NULL)
1412 return FALSE;
1413
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;
1420 } else {
1421 // Multitexture override
1422 lpCtx->glCtx->Const.MaxTextureUnits = 1;
1423 }
1424
1425 lpCtx->glCtx->Const.MaxDrawBuffers = 1;
1426
1427 // max texture size
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
1432
1433 //
1434 // HACK!!
1435 if (MaxTextureSize > 1024)
1436 MaxTextureSize = 1024; // HACK - CLAMP TO 1024
1437 // HACK!!
1438 //
1439
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? ;)
1443 TextureLevels = 0;
1444 // Calculate power-of-two.
1445 while (MaxTextureSize) {
1446 TextureLevels++;
1447 MaxTextureSize >>= 1;
1448 }
1449 lpCtx->glCtx->Const.MaxTextureLevels = (TextureLevels) ? TextureLevels : 8;
1450
1451 // Defaults
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);
1456
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);
1460
1461 // Set up Depth buffer
1462 IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_ZENABLE,
1463 (lpCtx->lpPF->dwDriverData!=D3DX_SF_UNKNOWN) ? D3DZB_TRUE : D3DZB_FALSE);
1464
1465 // Set the view matrix
1466 {
1467 D3DXMATRIX vm;
1468 #if 1
1469 D3DXMatrixIdentity(&vm);
1470 #else
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);
1475 vm._31 = -vm._31;
1476 vm._32 = -vm._32;
1477 vm._33 = -vm._33;
1478 vm._34 = -vm._34;
1479 #endif
1480 IDirect3DDevice7_SetTransform(gld->pDev, D3DTRANSFORMSTATE_VIEW, &vm);
1481 }
1482
1483 // DX7 does not support D3DRS_SOFTWAREVERTEXPROCESSING
1484 /*
1485 if (gld->bHasHWTnL) {
1486 if (glb.dwTnL == GLDS_TNL_DEFAULT)
1487 bSoftwareTnL = FALSE; // HW TnL
1488 else {
1489 bSoftwareTnL = ((glb.dwTnL == GLDS_TNL_MESA) || (glb.dwTnL == GLDS_TNL_D3DSW)) ? TRUE : FALSE;
1490 }
1491 } else {
1492 // No HW TnL, so no choice possible
1493 bSoftwareTnL = TRUE;
1494 }
1495 IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, bSoftwareTnL);
1496 */
1497
1498 // Dump this in a Release build as well, now.
1499 //#ifdef _DEBUG
1500 ddlogPrintf(DDLOG_INFO, "HW TnL: %s",
1501 // gld->bHasHWTnL ? (bSoftwareTnL ? "Disabled" : "Enabled") : "Unavailable");
1502 gld->bHasHWTnL ? "Enabled" : "Unavailable");
1503 //#endif
1504
1505 // Set up interfaces to Mesa
1506 gldEnableExtensions_DX7(lpCtx->glCtx);
1507 gldInstallPipeline_DX7(lpCtx->glCtx);
1508 gldSetupDriverPointers_DX7(lpCtx->glCtx);
1509
1510 // Signal a complete state update
1511 lpCtx->glCtx->Driver.UpdateState(lpCtx->glCtx, _NEW_ALL);
1512
1513 // Start a scene
1514 IDirect3DDevice7_BeginScene(gld->pDev);
1515 lpCtx->bSceneStarted = TRUE;
1516
1517 return TRUE;
1518 }
1519
1520 //---------------------------------------------------------------------------
1521
1522 BOOL gldSwapBuffers_DX(
1523 DGL_ctx *ctx,
1524 HDC hDC,
1525 HWND hWnd)
1526 {
1527 HRESULT hr;
1528 GLD_driver_dx7 *gld = NULL;
1529 DWORD dwFlags;
1530
1531 if (ctx == NULL)
1532 return FALSE;
1533
1534 gld = ctx->glPriv;
1535 if (gld == NULL)
1536 return FALSE;
1537
1538
1539 // End the scene if one is started
1540 if (ctx->bSceneStarted) {
1541 IDirect3DDevice7_EndScene(gld->pDev);
1542 ctx->bSceneStarted = FALSE;
1543 }
1544
1545 // Needed by D3DX for MDI multi-window apps (DaveM)
1546 if (lpDDClipper)
1547 IDirectDrawClipper_SetHWnd(lpDDClipper, 0, hWnd);
1548
1549 // Swap the buffers. hWnd may override the hWnd used for CreateDevice()
1550 // hr = IDirect3DDevice8_Present(gld->pDev, NULL, NULL, hWnd, NULL);
1551
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);
1556 if (FAILED(hr))
1557 ddlogError(DDLOG_WARN, "gldSwapBuffers_DX: UpdateFrame", hr);
1558
1559 if (hr == DDERR_SURFACELOST) {
1560 hr = gld->pD3DXContext->lpVtbl->RestoreSurfaces(gld->pD3DXContext);
1561 if (FAILED(hr))
1562 ddlogError(DDLOG_WARN, "gldSwapBuffers_DX: RestoreSurfaces", hr);
1563 }
1564
1565 exit_swap:
1566 // Begin a new scene
1567 IDirect3DDevice7_BeginScene(gld->pDev);
1568 ctx->bSceneStarted = TRUE;
1569
1570 return (FAILED(hr)) ? FALSE : TRUE;
1571 }
1572
1573 //---------------------------------------------------------------------------
1574
1575 BOOL gldGetDisplayMode_DX(
1576 DGL_ctx *ctx,
1577 GLD_displayMode *glddm)
1578 {
1579 // D3DDISPLAYMODE d3ddm;
1580 D3DX_VIDMODEDESC d3ddm;
1581 HRESULT hr;
1582 GLD_driver_dx7 *lpCtx = NULL;
1583 BYTE cColorBits, cRedBits, cGreenBits, cBlueBits, cAlphaBits;
1584
1585 if ((glddm == NULL) || (ctx == NULL))
1586 return FALSE;
1587
1588 lpCtx = ctx->glPriv;
1589 if (lpCtx == NULL)
1590 return FALSE;
1591
1592 if (lpCtx->pD3D == NULL)
1593 return FALSE;
1594
1595 // hr = IDirect3D8_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm);
1596 hr = D3DXGetCurrentVideoMode(D3DX_DEFAULT, &d3ddm);
1597 if (FAILED(hr))
1598 return FALSE;
1599
1600 // Get info from the display format
1601 // _BitsFromDisplayFormat(d3ddm.Format,
1602 // &cColorBits, &cRedBits, &cGreenBits, &cBlueBits, &cAlphaBits);
1603
1604 glddm->Width = d3ddm.width;
1605 glddm->Height = d3ddm.height;
1606 glddm->BPP = d3ddm.bpp;
1607 glddm->Refresh = d3ddm.refreshRate;
1608
1609 return TRUE;
1610 }
1611
1612 //---------------------------------------------------------------------------
1613