Drop GLcontext typedef and use struct gl_context instead
[mesa.git] / src / mesa / drivers / windows / gldirect / dx9 / gld_wgl_dx9.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_dxerr9.h"
40 #include "gld_dx9.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 #define DDLOG_CRITICAL_OR_WARN DDLOG_CRITICAL
56
57 extern void _gld_mesa_warning(struct gl_context *, char *);
58 extern void _gld_mesa_fatal(struct gl_context *, char *);
59
60 //---------------------------------------------------------------------------
61
62 static char szColorDepthWarning[] =
63 "GLDirect does not support the current desktop\n\
64 color depth.\n\n\
65 You may need to change the display resolution to\n\
66 16 bits per pixel or higher color depth using\n\
67 the Windows Display Settings control panel\n\
68 before running this OpenGL application.\n";
69
70 // The only depth-stencil formats currently supported by Direct3D
71 // Surface Format Depth Stencil Total Bits
72 // D3DFMT_D32 32 - 32
73 // D3DFMT_D15S1 15 1 16
74 // D3DFMT_D24S8 24 8 32
75 // D3DFMT_D16 16 - 16
76 // D3DFMT_D24X8 24 - 32
77 // D3DFMT_D24X4S4 24 4 32
78
79 // This pixel format will be used as a template when compiling the list
80 // of pixel formats supported by the hardware. Many fields will be
81 // filled in at runtime.
82 // PFD flag defaults are upgraded to match ChoosePixelFormat() -- DaveM
83 static DGL_pixelFormat pfTemplateHW =
84 {
85 {
86 sizeof(PIXELFORMATDESCRIPTOR), // Size of the data structure
87 1, // Structure version - should be 1
88 // Flags:
89 PFD_DRAW_TO_WINDOW | // The buffer can draw to a window or device surface.
90 PFD_DRAW_TO_BITMAP | // The buffer can draw to a bitmap. (DaveM)
91 PFD_SUPPORT_GDI | // The buffer supports GDI drawing. (DaveM)
92 PFD_SUPPORT_OPENGL | // The buffer supports OpenGL drawing.
93 PFD_DOUBLEBUFFER | // The buffer is double-buffered.
94 0, // Placeholder for easy commenting of above flags
95 PFD_TYPE_RGBA, // Pixel type RGBA.
96 16, // Total colour bitplanes (excluding alpha bitplanes)
97 5, 0, // Red bits, shift
98 5, 0, // Green bits, shift
99 5, 0, // Blue bits, shift
100 0, 0, // Alpha bits, shift (destination alpha)
101 0, // Accumulator bits (total)
102 0, 0, 0, 0, // Accumulator bits: Red, Green, Blue, Alpha
103 0, // Depth bits
104 0, // Stencil bits
105 0, // Number of auxiliary buffers
106 0, // Layer type
107 0, // Specifies the number of overlay and underlay planes.
108 0, // Layer mask
109 0, // Specifies the transparent color or index of an underlay plane.
110 0 // Damage mask
111 },
112 D3DFMT_UNKNOWN, // No depth/stencil buffer
113 };
114
115 //---------------------------------------------------------------------------
116 // Vertex Shaders
117 //---------------------------------------------------------------------------
118 /*
119 // Vertex Shader Declaration
120 static DWORD dwTwoSidedLightingDecl[] =
121 {
122 D3DVSD_STREAM(0),
123 D3DVSD_REG(0, D3DVSDT_FLOAT3), // XYZ position
124 D3DVSD_REG(1, D3DVSDT_FLOAT3), // XYZ normal
125 D3DVSD_REG(2, D3DVSDT_D3DCOLOR), // Diffuse color
126 D3DVSD_REG(3, D3DVSDT_D3DCOLOR), // Specular color
127 D3DVSD_REG(4, D3DVSDT_FLOAT2), // 2D texture unit 0
128 D3DVSD_REG(5, D3DVSDT_FLOAT2), // 2D texture unit 1
129 D3DVSD_END()
130 };
131
132 // Vertex Shader for two-sided lighting
133 static char *szTwoSidedLightingVS =
134 // This is a test shader!
135 "vs.1.0\n"
136 "m4x4 oPos,v0,c0\n"
137 "mov oD0,v2\n"
138 "mov oD1,v3\n"
139 "mov oT0,v4\n"
140 "mov oT1,v5\n"
141 ;
142 */
143 //---------------------------------------------------------------------------
144 //---------------------------------------------------------------------------
145
146 typedef struct {
147 HINSTANCE hD3D9DLL; // Handle to d3d9.dll
148 FNDIRECT3DCREATE9 fnDirect3DCreate9; // Direct3DCreate9 function prototype
149 BOOL bDirect3D; // Persistant Direct3D9 exists
150 BOOL bDirect3DDevice; // Persistant Direct3DDevice9 exists
151 IDirect3D9 *pD3D; // Persistant Direct3D9
152 IDirect3DDevice9 *pDev; // Persistant Direct3DDevice9
153 } GLD_dx9_globals;
154
155 // These are "global" to all DX9 contexts. KeithH
156 static GLD_dx9_globals dx9Globals;
157
158 //---------------------------------------------------------------------------
159 //---------------------------------------------------------------------------
160
161 BOOL gldGetDXErrorString_DX(
162 HRESULT hr,
163 char *buf,
164 int nBufSize)
165 {
166 //
167 // Return a string describing the input HRESULT error code
168 //
169
170 const char *pStr = DXGetErrorString9(hr);
171
172 if (pStr == NULL)
173 return FALSE;
174
175 if (strlen(pStr) > nBufSize)
176 strncpy(buf, pStr, nBufSize);
177 else
178 strcpy(buf, pStr);
179
180 // D3DXGetErrorString(hr, buf, nBufSize);
181
182 return TRUE;
183 }
184
185 //---------------------------------------------------------------------------
186
187 static D3DMULTISAMPLE_TYPE _gldGetDeviceMultiSampleType(
188 IDirect3D9 *pD3D9,
189 D3DFORMAT SurfaceFormat,
190 D3DDEVTYPE d3dDevType,
191 BOOL Windowed)
192 {
193 int i;
194 HRESULT hr;
195
196 if (glb.dwMultisample == GLDS_MULTISAMPLE_NONE)
197 return D3DMULTISAMPLE_NONE;
198
199 if (glb.dwMultisample == GLDS_MULTISAMPLE_FASTEST) {
200 // Find fastest multisample
201 for (i=2; i<17; i++) {
202 hr = IDirect3D9_CheckDeviceMultiSampleType(
203 pD3D9,
204 glb.dwAdapter,
205 d3dDevType,
206 SurfaceFormat,
207 Windowed,
208 (D3DMULTISAMPLE_TYPE)i,
209 NULL);
210 if (SUCCEEDED(hr)) {
211 return (D3DMULTISAMPLE_TYPE)i;
212 }
213 }
214 } else {
215 // Find nicest multisample
216 for (i=16; i>1; i--) {
217 hr = IDirect3D9_CheckDeviceMultiSampleType(
218 pD3D9,
219 glb.dwAdapter,
220 d3dDevType,
221 SurfaceFormat,
222 Windowed,
223 (D3DMULTISAMPLE_TYPE)i,
224 NULL);
225 if (SUCCEEDED(hr)) {
226 return (D3DMULTISAMPLE_TYPE)i;
227 }
228 }
229 }
230
231 // Nothing found - return default
232 return D3DMULTISAMPLE_NONE;
233 }
234
235 //---------------------------------------------------------------------------
236
237 void _gldDestroyPrimitiveBuffer(
238 GLD_pb_dx9 *gldVB)
239 {
240 SAFE_RELEASE(gldVB->pVB);
241
242 // Sanity check...
243 gldVB->nLines = gldVB->nPoints = gldVB->nTriangles = 0;
244 }
245
246 //---------------------------------------------------------------------------
247
248 HRESULT _gldCreatePrimitiveBuffer(
249 struct gl_context *ctx,
250 GLD_driver_dx9 *lpCtx,
251 GLD_pb_dx9 *gldVB)
252 {
253 HRESULT hResult;
254 char *szCreateVertexBufferFailed = "CreateVertexBuffer failed";
255 DWORD dwMaxVertices; // Max number of vertices in vertex buffer
256 DWORD dwVBSize; // Total size of vertex buffer
257
258 // If CVA (Compiled Vertex Array) is used by an OpenGL app, then we
259 // will need enough vertices to cater for Mesa::Const.MaxArrayLockSize.
260 // We'll use IMM_SIZE if it's larger (which it should not be).
261 dwMaxVertices = MAX_ARRAY_LOCK_SIZE;
262
263 // Now calculate how many vertices to allow for in total
264 // 1 per point, 2 per line, 6 per quad = 9
265 dwVBSize = dwMaxVertices * 9 * gldVB->dwStride;
266
267 hResult = IDirect3DDevice9_CreateVertexBuffer(
268 lpCtx->pDev,
269 dwVBSize,
270 gldVB->dwUsage,
271 gldVB->dwFVF,
272 gldVB->dwPool,
273 &gldVB->pVB,
274 NULL);
275 if (FAILED(hResult)) {
276 ddlogMessage(DDLOG_CRITICAL_OR_WARN, szCreateVertexBufferFailed);
277 return hResult;
278 }
279
280 gldVB->nLines = gldVB->nPoints = gldVB->nTriangles = 0;
281 gldVB->pPoints = gldVB->pLines = gldVB->pTriangles = NULL;
282 gldVB->iFirstLine = dwMaxVertices; // Index of first line in VB
283 gldVB->iFirstTriangle = dwMaxVertices*3; // Index of first triangle in VB
284
285 return S_OK;
286 }
287
288 //---------------------------------------------------------------------------
289 // Function: _gldCreateVertexShaders
290 // Create DX9 Vertex Shaders.
291 //---------------------------------------------------------------------------
292 /*
293 void _gldCreateVertexShaders(
294 GLD_driver_dx9 *gld)
295 {
296 DWORD dwFlags;
297 LPD3DXBUFFER pVSOpcodeBuffer; // Vertex Shader opcode buffer
298 HRESULT hr;
299
300 #ifdef _DEBUG
301 dwFlags = D3DXASM_DEBUG;
302 #else
303 dwFlags = 0; // D3DXASM_SKIPVALIDATION;
304 #endif
305
306 ddlogMessage(DDLOG_INFO, "Creating shaders...\n");
307
308 // Init the shader handle
309 gld->VStwosidelight.hShader = 0;
310
311 if (gld->d3dCaps8.MaxStreams == 0) {
312 // Lame DX8 driver doesn't support streams
313 // Not fatal, as defaults will be used
314 ddlogMessage(DDLOG_WARN, "Driver doesn't support Vertex Shaders (MaxStreams==0)\n");
315 return;
316 }
317
318 // ** THIS DISABLES VERTEX SHADER SUPPORT **
319 // return;
320 // ** THIS DISABLES VERTEX SHADER SUPPORT **
321
322 //
323 // Two-sided lighting
324 //
325
326 #if 0
327 //
328 // DEBUGGING: Load shader from a text file
329 //
330 {
331 LPD3DXBUFFER pVSErrorBuffer; // Vertex Shader error buffer
332 hr = D3DXAssembleShaderFromFile(
333 "twoside.vsh",
334 dwFlags,
335 NULL, // No constants
336 &pVSOpcodeBuffer,
337 &pVSErrorBuffer);
338 if (pVSErrorBuffer && pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer))
339 ddlogMessage(DDLOG_INFO, pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer));
340 SAFE_RELEASE(pVSErrorBuffer);
341 }
342 #else
343 {
344 LPD3DXBUFFER pVSErrorBuffer; // Vertex Shader error buffer
345 // Assemble ascii shader text into shader opcodes
346 hr = D3DXAssembleShader(
347 szTwoSidedLightingVS,
348 strlen(szTwoSidedLightingVS),
349 dwFlags,
350 NULL, // No constants
351 &pVSOpcodeBuffer,
352 &pVSErrorBuffer);
353 if (pVSErrorBuffer && pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer))
354 ddlogMessage(DDLOG_INFO, pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer));
355 SAFE_RELEASE(pVSErrorBuffer);
356 }
357 #endif
358 if (FAILED(hr)) {
359 ddlogError(DDLOG_WARN, "AssembleShader failed", hr);
360 SAFE_RELEASE(pVSOpcodeBuffer);
361 return;
362 }
363
364 // This is for debugging. Remove to enable vertex shaders in HW
365 #define _GLD_FORCE_SW_VS 0
366
367 if (_GLD_FORCE_SW_VS) {
368 // _GLD_FORCE_SW_VS should be disabled for Final Release
369 ddlogMessage(DDLOG_SYSTEM, "[Forcing shaders in SW]\n");
370 }
371
372 // Try and create shader in hardware.
373 // NOTE: The D3D Ref device appears to succeed when trying to
374 // create the device in hardware, but later complains
375 // when trying to set it with SetVertexShader(). Go figure.
376 if (_GLD_FORCE_SW_VS || glb.dwDriver == GLDS_DRIVER_REF) {
377 // Don't try and create a hardware shader with the Ref device
378 hr = E_FAIL; // COM error/fail result
379 } else {
380 gld->VStwosidelight.bHardware = TRUE;
381 hr = IDirect3DDevice8_CreateVertexShader(
382 gld->pDev,
383 dwTwoSidedLightingDecl,
384 pVSOpcodeBuffer->lpVtbl->GetBufferPointer(pVSOpcodeBuffer),
385 &gld->VStwosidelight.hShader,
386 0);
387 }
388 if (FAILED(hr)) {
389 ddlogMessage(DDLOG_INFO, "... HW failed, trying SW...\n");
390 // Failed. Try and create shader for software processing
391 hr = IDirect3DDevice8_CreateVertexShader(
392 gld->pDev,
393 dwTwoSidedLightingDecl,
394 pVSOpcodeBuffer->lpVtbl->GetBufferPointer(pVSOpcodeBuffer),
395 &gld->VStwosidelight.hShader,
396 D3DUSAGE_SOFTWAREPROCESSING);
397 if (FAILED(hr)) {
398 gld->VStwosidelight.hShader = 0; // Sanity check
399 ddlogError(DDLOG_WARN, "CreateVertexShader failed", hr);
400 return;
401 }
402 // Succeeded, but for software processing
403 gld->VStwosidelight.bHardware = FALSE;
404 }
405
406 SAFE_RELEASE(pVSOpcodeBuffer);
407
408 ddlogMessage(DDLOG_INFO, "... OK\n");
409 }
410
411 //---------------------------------------------------------------------------
412
413 void _gldDestroyVertexShaders(
414 GLD_driver_dx9 *gld)
415 {
416 if (gld->VStwosidelight.hShader) {
417 IDirect3DDevice8_DeleteVertexShader(gld->pDev, gld->VStwosidelight.hShader);
418 gld->VStwosidelight.hShader = 0;
419 }
420 }
421 */
422 //---------------------------------------------------------------------------
423
424 BOOL gldCreateDrawable_DX(
425 DGL_ctx *ctx,
426 // BOOL bDefaultDriver,
427 BOOL bDirectDrawPersistant,
428 BOOL bPersistantBuffers)
429 {
430 //
431 // bDirectDrawPersistant: applies to IDirect3D9
432 // bPersistantBuffers: applies to IDirect3DDevice9
433 //
434
435 HRESULT hResult;
436 GLD_driver_dx9 *lpCtx = NULL;
437 D3DDEVTYPE d3dDevType;
438 D3DPRESENT_PARAMETERS d3dpp;
439 D3DDISPLAYMODE d3ddm;
440 DWORD dwBehaviourFlags;
441 D3DADAPTER_IDENTIFIER9 d3dIdent;
442
443 // Error if context is NULL.
444 if (ctx == NULL)
445 return FALSE;
446
447 if (ctx->glPriv) {
448 lpCtx = ctx->glPriv;
449 // Release any existing interfaces
450 SAFE_RELEASE(lpCtx->pDev);
451 SAFE_RELEASE(lpCtx->pD3D);
452 } else {
453 lpCtx = (GLD_driver_dx9*)malloc(sizeof(GLD_driver_dx9));
454 ZeroMemory(lpCtx, sizeof(lpCtx));
455 }
456
457 d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF;
458 // TODO: Check this
459 // if (bDefaultDriver)
460 // d3dDevType = D3DDEVTYPE_REF;
461
462 // Use persistant interface if needed
463 if (bDirectDrawPersistant && dx9Globals.bDirect3D) {
464 lpCtx->pD3D = dx9Globals.pD3D;
465 IDirect3D9_AddRef(lpCtx->pD3D);
466 goto SkipDirectDrawCreate;
467 }
468
469 // Create Direct3D9 object
470 lpCtx->pD3D = dx9Globals.fnDirect3DCreate9(D3D_SDK_VERSION);
471 if (lpCtx->pD3D == NULL) {
472 MessageBox(NULL, "Unable to initialize Direct3D9", "GLDirect", MB_OK);
473 ddlogMessage(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D9 interface");
474 nContextError = GLDERR_D3D;
475 goto return_with_error;
476 }
477
478 // Cache Direct3D interface for subsequent GLRCs
479 if (bDirectDrawPersistant && !dx9Globals.bDirect3D) {
480 dx9Globals.pD3D = lpCtx->pD3D;
481 IDirect3D9_AddRef(dx9Globals.pD3D);
482 dx9Globals.bDirect3D = TRUE;
483 }
484 SkipDirectDrawCreate:
485
486 // Get the display mode so we can make a compatible backbuffer
487 hResult = IDirect3D9_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm);
488 if (FAILED(hResult)) {
489 nContextError = GLDERR_D3D;
490 goto return_with_error;
491 }
492
493 // Get device caps
494 hResult = IDirect3D9_GetDeviceCaps(lpCtx->pD3D, glb.dwAdapter, d3dDevType, &lpCtx->d3dCaps9);
495 if (FAILED(hResult)) {
496 ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D9_GetDeviceCaps failed", hResult);
497 nContextError = GLDERR_D3D;
498 goto return_with_error;
499 }
500
501 // Check for hardware transform & lighting
502 lpCtx->bHasHWTnL = lpCtx->d3dCaps9.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ? TRUE : FALSE;
503
504 /*
505 //
506 // GONE FOR DX9?
507 //
508 // If this flag is present then we can't default to Mesa
509 // SW rendering between BeginScene() and EndScene().
510 if (lpCtx->d3dCaps9.Caps2 & D3DCAPS2_NO2DDURING3DSCENE) {
511 ddlogMessage(DDLOG_WARN,
512 "Warning : No 2D allowed during 3D scene.\n");
513 }
514 */
515
516 //
517 // Create the Direct3D context
518 //
519
520 // Re-use original IDirect3DDevice if persistant buffers exist.
521 // Note that we test for persistant IDirect3D9 as well
522 // bDirectDrawPersistant == persistant IDirect3D9 (DirectDraw9 does not exist)
523 if (bDirectDrawPersistant && bPersistantBuffers && dx9Globals.pD3D && dx9Globals.pDev) {
524 lpCtx->pDev = dx9Globals.pDev;
525 IDirect3DDevice9_AddRef(dx9Globals.pDev);
526 goto skip_direct3ddevice_create;
527 }
528
529 // Clear the presentation parameters (sets all members to zero)
530 ZeroMemory(&d3dpp, sizeof(d3dpp));
531
532 // Recommended by MS; needed for MultiSample.
533 // Be careful if altering this for FullScreenBlit
534 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
535
536 d3dpp.BackBufferFormat = d3ddm.Format;
537 d3dpp.BackBufferCount = 2; //1;
538 d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(lpCtx->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen);
539 d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData;
540 d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE;
541
542 if (ctx->bFullscreen) {
543 ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen
544 d3dpp.Windowed = FALSE;
545 d3dpp.BackBufferWidth = d3ddm.Width;
546 d3dpp.BackBufferHeight = d3ddm.Height;
547 d3dpp.hDeviceWindow = ctx->hWnd;
548 d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
549
550 // Support for vertical retrace synchronisation.
551 // Set default presentation interval in case caps bits are missing
552 d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
553 if (glb.bWaitForRetrace) {
554 if (lpCtx->d3dCaps9.PresentationIntervals & D3DPRESENT_INTERVAL_ONE)
555 d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
556 } else {
557 if (lpCtx->d3dCaps9.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE)
558 d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
559 }
560 } else {
561 ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages
562 d3dpp.Windowed = TRUE;
563 d3dpp.BackBufferWidth = ctx->dwWidth;
564 d3dpp.BackBufferHeight = ctx->dwHeight;
565 d3dpp.hDeviceWindow = ctx->hWnd;
566 d3dpp.FullScreen_RefreshRateInHz = 0;
567 // PresentationInterval Windowed mode is optional now in DX9 (DaveM)
568 d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
569 if (glb.bWaitForRetrace) {
570 d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
571 } else {
572 d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
573 }
574 }
575
576 // Decide if we can use hardware TnL
577 dwBehaviourFlags = (lpCtx->bHasHWTnL) ?
578 D3DCREATE_MIXED_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING;
579 // Add flag to tell D3D to be thread-safe
580 if (glb.bMultiThreaded)
581 dwBehaviourFlags |= D3DCREATE_MULTITHREADED;
582 // Add flag to tell D3D to be FPU-safe
583 if (!glb.bFastFPU)
584 dwBehaviourFlags |= D3DCREATE_FPU_PRESERVE;
585 hResult = IDirect3D9_CreateDevice(lpCtx->pD3D,
586 glb.dwAdapter,
587 d3dDevType,
588 ctx->hWnd,
589 dwBehaviourFlags,
590 &d3dpp,
591 &lpCtx->pDev);
592 if (FAILED(hResult)) {
593 ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D9_CreateDevice failed", hResult);
594 nContextError = GLDERR_D3D;
595 goto return_with_error;
596 }
597
598 if (bDirectDrawPersistant && bPersistantBuffers && dx9Globals.pD3D) {
599 dx9Globals.pDev = lpCtx->pDev;
600 dx9Globals.bDirect3DDevice = TRUE;
601 }
602
603 // Dump some useful stats
604 hResult = IDirect3D9_GetAdapterIdentifier(
605 lpCtx->pD3D,
606 glb.dwAdapter,
607 0, // No WHQL detection (avoid few seconds delay)
608 &d3dIdent);
609 if (SUCCEEDED(hResult)) {
610 ddlogPrintf(DDLOG_INFO, "[Driver Description: %s]", &d3dIdent.Description);
611 ddlogPrintf(DDLOG_INFO, "[Driver file: %s %d.%d.%02d.%d]",
612 d3dIdent.Driver,
613 HIWORD(d3dIdent.DriverVersion.HighPart),
614 LOWORD(d3dIdent.DriverVersion.HighPart),
615 HIWORD(d3dIdent.DriverVersion.LowPart),
616 LOWORD(d3dIdent.DriverVersion.LowPart));
617 ddlogPrintf(DDLOG_INFO, "[VendorId: 0x%X, DeviceId: 0x%X, SubSysId: 0x%X, Revision: 0x%X]",
618 d3dIdent.VendorId, d3dIdent.DeviceId, d3dIdent.SubSysId, d3dIdent.Revision);
619 }
620
621 // Test to see if IHV driver exposes Scissor Test (new for DX9)
622 lpCtx->bCanScissor = lpCtx->d3dCaps9.RasterCaps & D3DPRASTERCAPS_SCISSORTEST;
623 ddlogPrintf(DDLOG_INFO, "Can Scissor: %s", lpCtx->bCanScissor ? "Yes" : "No");
624
625 // Init projection matrix for D3D TnL
626 D3DXMatrixIdentity(&lpCtx->matProjection);
627 lpCtx->matModelView = lpCtx->matProjection;
628 // gld->bUseMesaProjection = TRUE;
629
630 skip_direct3ddevice_create:
631
632 // Create buffers to hold primitives
633 lpCtx->PB2d.dwFVF = GLD_FVF_2D_VERTEX;
634 lpCtx->PB2d.dwPool = D3DPOOL_SYSTEMMEM;
635 lpCtx->PB2d.dwStride = sizeof(GLD_2D_VERTEX);
636 lpCtx->PB2d.dwUsage = D3DUSAGE_DONOTCLIP |
637 D3DUSAGE_DYNAMIC |
638 D3DUSAGE_SOFTWAREPROCESSING |
639 D3DUSAGE_WRITEONLY;
640 hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB2d);
641 if (FAILED(hResult))
642 goto return_with_error;
643
644 lpCtx->PB3d.dwFVF = GLD_FVF_3D_VERTEX;
645 lpCtx->PB3d.dwPool = D3DPOOL_DEFAULT;
646 lpCtx->PB3d.dwStride = sizeof(GLD_3D_VERTEX);
647 lpCtx->PB3d.dwUsage = D3DUSAGE_DYNAMIC |
648 //DaveM D3DUSAGE_SOFTWAREPROCESSING |
649 D3DUSAGE_WRITEONLY;
650 hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB3d);
651 if (FAILED(hResult))
652 goto return_with_error;
653
654 /* // NOTE: A FVF code of zero indicates a non-FVF vertex buffer (for vertex shaders)
655 lpCtx->PBtwosidelight.dwFVF = 0; //GLD_FVF_TWOSIDED_VERTEX;
656 lpCtx->PBtwosidelight.dwPool = D3DPOOL_DEFAULT;
657 lpCtx->PBtwosidelight.dwStride = sizeof(GLD_TWOSIDED_VERTEX);
658 lpCtx->PBtwosidelight.dwUsage = D3DUSAGE_DONOTCLIP |
659 D3DUSAGE_DYNAMIC |
660 D3DUSAGE_SOFTWAREPROCESSING |
661 D3DUSAGE_WRITEONLY;
662 hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PBtwosidelight);
663 if (FAILED(hResult))
664 goto return_with_error;*/
665
666 // Now try and create the DX9 Vertex Shaders
667 // _gldCreateVertexShaders(lpCtx);
668
669 // Zero the pipeline usage counters
670 lpCtx->PipelineUsage.qwMesa.QuadPart =
671 // lpCtx->PipelineUsage.dwD3D2SVS.QuadPart =
672 lpCtx->PipelineUsage.qwD3DFVF.QuadPart = 0;
673
674 // Assign drawable to GL private
675 ctx->glPriv = lpCtx;
676 return TRUE;
677
678 return_with_error:
679 // Clean up and bail
680
681 // _gldDestroyVertexShaders(lpCtx);
682
683 // _gldDestroyPrimitiveBuffer(&lpCtx->PBtwosidelight);
684 _gldDestroyPrimitiveBuffer(&lpCtx->PB3d);
685 _gldDestroyPrimitiveBuffer(&lpCtx->PB2d);
686
687 SAFE_RELEASE(lpCtx->pDev);
688 SAFE_RELEASE(lpCtx->pD3D);
689 return FALSE;
690 }
691
692 //---------------------------------------------------------------------------
693
694 BOOL gldResizeDrawable_DX(
695 DGL_ctx *ctx,
696 BOOL bDefaultDriver,
697 BOOL bPersistantInterface,
698 BOOL bPersistantBuffers)
699 {
700 GLD_driver_dx9 *gld = NULL;
701 D3DDEVTYPE d3dDevType;
702 D3DPRESENT_PARAMETERS d3dpp;
703 D3DDISPLAYMODE d3ddm;
704 HRESULT hResult;
705
706 // Error if context is NULL.
707 if (ctx == NULL)
708 return FALSE;
709
710 gld = ctx->glPriv;
711 if (gld == NULL)
712 return FALSE;
713
714 if (ctx->bSceneStarted) {
715 IDirect3DDevice9_EndScene(gld->pDev);
716 ctx->bSceneStarted = FALSE;
717 }
718
719 d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF;
720 if (!bDefaultDriver)
721 d3dDevType = D3DDEVTYPE_REF; // Force Direct3D Reference Rasterise (software)
722
723 // Get the display mode so we can make a compatible backbuffer
724 hResult = IDirect3D9_GetAdapterDisplayMode(gld->pD3D, glb.dwAdapter, &d3ddm);
725 if (FAILED(hResult)) {
726 nContextError = GLDERR_D3D;
727 // goto return_with_error;
728 return FALSE;
729 }
730
731 // Destroy DX9 Vertex Shaders before Reset()
732 // _gldDestroyVertexShaders(gld);
733
734 // Release POOL_DEFAULT objects before Reset()
735 if (gld->PB2d.dwPool == D3DPOOL_DEFAULT)
736 _gldDestroyPrimitiveBuffer(&gld->PB2d);
737 if (gld->PB3d.dwPool == D3DPOOL_DEFAULT)
738 _gldDestroyPrimitiveBuffer(&gld->PB3d);
739 // if (gld->PBtwosidelight.dwPool == D3DPOOL_DEFAULT)
740 // _gldDestroyPrimitiveBuffer(&gld->PBtwosidelight);
741
742 // Clear the presentation parameters (sets all members to zero)
743 ZeroMemory(&d3dpp, sizeof(d3dpp));
744
745 // Recommended by MS; needed for MultiSample.
746 // Be careful if altering this for FullScreenBlit
747 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
748
749 d3dpp.BackBufferFormat = d3ddm.Format;
750 d3dpp.BackBufferCount = 1;
751 d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(gld->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen);
752 d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData;
753 d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE;
754
755 // TODO: Sync to refresh
756
757 if (ctx->bFullscreen) {
758 ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen
759 d3dpp.Windowed = FALSE;
760 d3dpp.BackBufferWidth = d3ddm.Width;
761 d3dpp.BackBufferHeight = d3ddm.Height;
762 d3dpp.hDeviceWindow = ctx->hWnd;
763 d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
764 d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
765 // Get better benchmark results? KeithH
766 // d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_UNLIMITED;
767 } else {
768 ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages
769 d3dpp.Windowed = TRUE;
770 d3dpp.BackBufferWidth = ctx->dwWidth;
771 d3dpp.BackBufferHeight = ctx->dwHeight;
772 d3dpp.hDeviceWindow = ctx->hWnd;
773 d3dpp.FullScreen_RefreshRateInHz = 0;
774 d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
775 }
776 hResult = IDirect3DDevice9_Reset(gld->pDev, &d3dpp);
777 if (FAILED(hResult)) {
778 ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Reset failed", hResult);
779 return FALSE;
780 //goto cleanup_and_return_with_error;
781 }
782
783 //
784 // Recreate POOL_DEFAULT objects
785 //
786 if (gld->PB2d.dwPool == D3DPOOL_DEFAULT) {
787 _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB2d);
788 }
789 if (gld->PB3d.dwPool == D3DPOOL_DEFAULT) {
790 _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB3d);
791 }
792 // if (gld->PBtwosidelight.dwPool == D3DPOOL_DEFAULT) {
793 // _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB2d);
794 // }
795
796 // Recreate DX9 Vertex Shaders
797 // _gldCreateVertexShaders(gld);
798
799 // Signal a complete state update
800 ctx->glCtx->Driver.UpdateState(ctx->glCtx, _NEW_ALL);
801
802 // Begin a new scene
803 IDirect3DDevice9_BeginScene(gld->pDev);
804 ctx->bSceneStarted = TRUE;
805
806 return TRUE;
807 }
808
809 //---------------------------------------------------------------------------
810
811 BOOL gldDestroyDrawable_DX(
812 DGL_ctx *ctx)
813 {
814 GLD_driver_dx9 *lpCtx = NULL;
815
816 // Error if context is NULL.
817 if (!ctx)
818 return FALSE;
819
820 // Error if the drawable does not exist.
821 if (!ctx->glPriv)
822 return FALSE;
823
824 lpCtx = ctx->glPriv;
825
826 #ifdef _DEBUG
827 // Dump out stats
828 ddlogPrintf(DDLOG_SYSTEM, "Usage: M:0x%X%X, D:0x%X%X",
829 lpCtx->PipelineUsage.qwMesa.HighPart,
830 lpCtx->PipelineUsage.qwMesa.LowPart,
831 lpCtx->PipelineUsage.qwD3DFVF.HighPart,
832 lpCtx->PipelineUsage.qwD3DFVF.LowPart);
833 #endif
834
835 // _gldDestroyVertexShaders(lpCtx);
836
837 // _gldDestroyPrimitiveBuffer(&lpCtx->PBtwosidelight);
838 _gldDestroyPrimitiveBuffer(&lpCtx->PB3d);
839 _gldDestroyPrimitiveBuffer(&lpCtx->PB2d);
840
841 SAFE_RELEASE(lpCtx->pDev);
842 SAFE_RELEASE(lpCtx->pD3D);
843
844 // Free the private drawable data
845 free(ctx->glPriv);
846 ctx->glPriv = NULL;
847
848 return TRUE;
849 }
850
851 //---------------------------------------------------------------------------
852
853 BOOL gldCreatePrivateGlobals_DX(void)
854 {
855 ZeroMemory(&dx9Globals, sizeof(dx9Globals));
856
857 // Load d3d9.dll
858 dx9Globals.hD3D9DLL = LoadLibrary("D3D9.DLL");
859 if (dx9Globals.hD3D9DLL == NULL)
860 return FALSE;
861
862 // Now try and obtain Direct3DCreate9
863 dx9Globals.fnDirect3DCreate9 = (FNDIRECT3DCREATE9)GetProcAddress(dx9Globals.hD3D9DLL, "Direct3DCreate9");
864 if (dx9Globals.fnDirect3DCreate9 == NULL) {
865 FreeLibrary(dx9Globals.hD3D9DLL);
866 return FALSE;
867 }
868
869 return TRUE;
870 }
871
872 //---------------------------------------------------------------------------
873
874 BOOL gldDestroyPrivateGlobals_DX(void)
875 {
876 if (dx9Globals.bDirect3DDevice) {
877 SAFE_RELEASE(dx9Globals.pDev);
878 dx9Globals.bDirect3DDevice = FALSE;
879 }
880 if (dx9Globals.bDirect3D) {
881 SAFE_RELEASE(dx9Globals.pD3D);
882 dx9Globals.bDirect3D = FALSE;
883 }
884
885 FreeLibrary(dx9Globals.hD3D9DLL);
886 dx9Globals.hD3D9DLL = NULL;
887 dx9Globals.fnDirect3DCreate9 = NULL;
888
889 return TRUE;
890 }
891
892 //---------------------------------------------------------------------------
893
894 static void _BitsFromDisplayFormat(
895 D3DFORMAT fmt,
896 BYTE *cColorBits,
897 BYTE *cRedBits,
898 BYTE *cGreenBits,
899 BYTE *cBlueBits,
900 BYTE *cAlphaBits)
901 {
902 switch (fmt) {
903 case D3DFMT_X1R5G5B5:
904 *cColorBits = 16;
905 *cRedBits = 5;
906 *cGreenBits = 5;
907 *cBlueBits = 5;
908 *cAlphaBits = 0;
909 return;
910 case D3DFMT_R5G6B5:
911 *cColorBits = 16;
912 *cRedBits = 5;
913 *cGreenBits = 6;
914 *cBlueBits = 5;
915 *cAlphaBits = 0;
916 return;
917 case D3DFMT_X8R8G8B8:
918 *cColorBits = 32;
919 *cRedBits = 8;
920 *cGreenBits = 8;
921 *cBlueBits = 8;
922 *cAlphaBits = 0;
923 return;
924 case D3DFMT_A8R8G8B8:
925 *cColorBits = 32;
926 *cRedBits = 8;
927 *cGreenBits = 8;
928 *cBlueBits = 8;
929 *cAlphaBits = 8;
930 return;
931 }
932
933 // Should not get here!
934 *cColorBits = 32;
935 *cRedBits = 8;
936 *cGreenBits = 8;
937 *cBlueBits = 8;
938 *cAlphaBits = 0;
939 }
940
941 //---------------------------------------------------------------------------
942
943 static void _BitsFromDepthStencilFormat(
944 D3DFORMAT fmt,
945 BYTE *cDepthBits,
946 BYTE *cStencilBits)
947 {
948 // NOTE: GL expects either 32 or 16 as depth bits.
949 switch (fmt) {
950 case D3DFMT_D32:
951 *cDepthBits = 32;
952 *cStencilBits = 0;
953 return;
954 case D3DFMT_D15S1:
955 *cDepthBits = 16;
956 *cStencilBits = 1;
957 return;
958 case D3DFMT_D24S8:
959 *cDepthBits = 32;
960 *cStencilBits = 8;
961 return;
962 case D3DFMT_D16:
963 *cDepthBits = 16;
964 *cStencilBits = 0;
965 return;
966 case D3DFMT_D24X8:
967 *cDepthBits = 32;
968 *cStencilBits = 0;
969 return;
970 case D3DFMT_D24X4S4:
971 *cDepthBits = 32;
972 *cStencilBits = 4;
973 return;
974 }
975 }
976
977 //---------------------------------------------------------------------------
978
979 BOOL gldBuildPixelformatList_DX(void)
980 {
981 D3DDISPLAYMODE d3ddm;
982 D3DFORMAT fmt[6];
983 IDirect3D9 *pD3D = NULL;
984 HRESULT hr;
985 int nSupportedFormats = 0;
986 int i;
987 DGL_pixelFormat *pPF;
988 BYTE cColorBits, cRedBits, cGreenBits, cBlueBits, cAlphaBits;
989 // char buf[128];
990 // char cat[8];
991
992 // Direct3D (SW or HW)
993 // These are arranged so that 'best' pixelformat
994 // is higher in the list (for ChoosePixelFormat).
995 const D3DFORMAT DepthStencil[6] = {
996 // New order: increaing Z, then increasing stencil
997 D3DFMT_D15S1,
998 D3DFMT_D16,
999 D3DFMT_D24X4S4,
1000 D3DFMT_D24X8,
1001 D3DFMT_D24S8,
1002 D3DFMT_D32,
1003 };
1004
1005 // Dump DX version
1006 ddlogMessage(GLDLOG_SYSTEM, "DirectX Version : 9.0\n");
1007
1008 // Release any existing pixelformat list
1009 if (glb.lpPF) {
1010 free(glb.lpPF);
1011 }
1012
1013 glb.nPixelFormatCount = 0;
1014 glb.lpPF = NULL;
1015
1016 //
1017 // Pixelformats for Direct3D (SW or HW) rendering
1018 //
1019
1020 // Get a Direct3D 9.0 interface
1021 pD3D = dx9Globals.fnDirect3DCreate9(D3D_SDK_VERSION);
1022 if (!pD3D) {
1023 return FALSE;
1024 }
1025
1026 // We will use the display mode format when finding compliant
1027 // rendertarget/depth-stencil surfaces.
1028 hr = IDirect3D9_GetAdapterDisplayMode(pD3D, glb.dwAdapter, &d3ddm);
1029 if (FAILED(hr)) {
1030 IDirect3D9_Release(pD3D);
1031 return FALSE;
1032 }
1033
1034 // Run through the possible formats and detect supported formats
1035 for (i=0; i<6; i++) {
1036 hr = IDirect3D9_CheckDeviceFormat(
1037 pD3D,
1038 glb.dwAdapter,
1039 glb.dwDriver==GLDS_DRIVER_HAL ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF,
1040 d3ddm.Format,
1041 D3DUSAGE_DEPTHSTENCIL,
1042 D3DRTYPE_SURFACE,
1043 DepthStencil[i]);
1044 if (FAILED(hr))
1045 // A failure here is not fatal.
1046 continue;
1047
1048 // Verify that the depth format is compatible.
1049 hr = IDirect3D9_CheckDepthStencilMatch(
1050 pD3D,
1051 glb.dwAdapter,
1052 glb.dwDriver==GLDS_DRIVER_HAL ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF,
1053 d3ddm.Format,
1054 d3ddm.Format,
1055 DepthStencil[i]);
1056 if (FAILED(hr))
1057 // A failure here is not fatal, just means depth-stencil
1058 // format is not compatible with this display mode.
1059 continue;
1060
1061 fmt[nSupportedFormats++] = DepthStencil[i];
1062 }
1063
1064 IDirect3D9_Release(pD3D);
1065
1066 if (nSupportedFormats == 0)
1067 return FALSE; // Bail: no compliant pixelformats
1068
1069 // Total count of pixelformats is:
1070 // (nSupportedFormats+1)*2
1071 // UPDATED: nSupportedFormats*2
1072 glb.lpPF = (DGL_pixelFormat *)calloc(nSupportedFormats*2, sizeof(DGL_pixelFormat));
1073 glb.nPixelFormatCount = nSupportedFormats*2;
1074 if (glb.lpPF == NULL) {
1075 glb.nPixelFormatCount = 0;
1076 return FALSE;
1077 }
1078
1079 // Get a copy of pointer that we can alter
1080 pPF = glb.lpPF;
1081
1082 // Cache colour bits from display format
1083 _BitsFromDisplayFormat(d3ddm.Format, &cColorBits, &cRedBits, &cGreenBits, &cBlueBits, &cAlphaBits);
1084
1085 //
1086 // Add single-buffer formats
1087 //
1088 /*
1089 // NOTE: No longer returning pixelformats that don't contain depth
1090 // Single-buffer, no depth-stencil buffer
1091 memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
1092 pPF->pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag
1093 pPF->pfd.cColorBits = cColorBits;
1094 pPF->pfd.cRedBits = cRedBits;
1095 pPF->pfd.cGreenBits = cGreenBits;
1096 pPF->pfd.cBlueBits = cBlueBits;
1097 pPF->pfd.cAlphaBits = cAlphaBits;
1098 pPF->pfd.cDepthBits = 0;
1099 pPF->pfd.cStencilBits = 0;
1100 pPF->dwDriverData = D3DFMT_UNKNOWN;
1101 pPF++;
1102 */
1103 for (i=0; i<nSupportedFormats; i++, pPF++) {
1104 memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
1105 pPF->pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag
1106 pPF->pfd.cColorBits = cColorBits;
1107 pPF->pfd.cRedBits = cRedBits;
1108 pPF->pfd.cGreenBits = cGreenBits;
1109 pPF->pfd.cBlueBits = cBlueBits;
1110 pPF->pfd.cAlphaBits = cAlphaBits;
1111 _BitsFromDepthStencilFormat(fmt[i], &pPF->pfd.cDepthBits, &pPF->pfd.cStencilBits);
1112 pPF->dwDriverData = fmt[i];
1113 }
1114
1115 //
1116 // Add double-buffer formats
1117 //
1118
1119 // NOTE: No longer returning pixelformats that don't contain depth
1120 /*
1121 memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
1122 pPF->pfd.cColorBits = cColorBits;
1123 pPF->pfd.cRedBits = cRedBits;
1124 pPF->pfd.cGreenBits = cGreenBits;
1125 pPF->pfd.cBlueBits = cBlueBits;
1126 pPF->pfd.cAlphaBits = cAlphaBits;
1127 pPF->pfd.cDepthBits = 0;
1128 pPF->pfd.cStencilBits = 0;
1129 pPF->dwDriverData = D3DFMT_UNKNOWN;
1130 pPF++;
1131 */
1132 for (i=0; i<nSupportedFormats; i++, pPF++) {
1133 memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
1134 pPF->pfd.cColorBits = cColorBits;
1135 pPF->pfd.cRedBits = cRedBits;
1136 pPF->pfd.cGreenBits = cGreenBits;
1137 pPF->pfd.cBlueBits = cBlueBits;
1138 pPF->pfd.cAlphaBits = cAlphaBits;
1139 _BitsFromDepthStencilFormat(fmt[i], &pPF->pfd.cDepthBits, &pPF->pfd.cStencilBits);
1140 pPF->dwDriverData = fmt[i];
1141 }
1142
1143 // Popup warning message if non RGB color mode
1144 {
1145 // This is a hack. KeithH
1146 HDC hdcDesktop = GetDC(NULL);
1147 DWORD dwDisplayBitDepth = GetDeviceCaps(hdcDesktop, BITSPIXEL);
1148 ReleaseDC(0, hdcDesktop);
1149 if (dwDisplayBitDepth <= 8) {
1150 ddlogPrintf(DDLOG_WARN, "Current Color Depth %d bpp is not supported", dwDisplayBitDepth);
1151 MessageBox(NULL, szColorDepthWarning, "GLDirect", MB_OK | MB_ICONWARNING);
1152 }
1153 }
1154
1155 // Mark list as 'current'
1156 glb.bPixelformatsDirty = FALSE;
1157
1158 return TRUE;
1159 }
1160
1161 //---------------------------------------------------------------------------
1162
1163 BOOL gldInitialiseMesa_DX(
1164 DGL_ctx *lpCtx)
1165 {
1166 GLD_driver_dx9 *gld = NULL;
1167 int MaxTextureSize, TextureLevels;
1168 BOOL bSoftwareTnL;
1169
1170 if (lpCtx == NULL)
1171 return FALSE;
1172
1173 gld = lpCtx->glPriv;
1174 if (gld == NULL)
1175 return FALSE;
1176
1177 if (glb.bMultitexture) {
1178 lpCtx->glCtx->Const.MaxTextureUnits = gld->d3dCaps9.MaxSimultaneousTextures;
1179 // Only support MAX_TEXTURE_UNITS texture units.
1180 // ** If this is altered then the FVF formats must be reviewed **.
1181 if (lpCtx->glCtx->Const.MaxTextureUnits > GLD_MAX_TEXTURE_UNITS_DX9)
1182 lpCtx->glCtx->Const.MaxTextureUnits = GLD_MAX_TEXTURE_UNITS_DX9;
1183 } else {
1184 // Multitexture override
1185 lpCtx->glCtx->Const.MaxTextureUnits = 1;
1186 }
1187
1188 // max texture size
1189 MaxTextureSize = min(gld->d3dCaps9.MaxTextureHeight, gld->d3dCaps9.MaxTextureWidth);
1190 if (MaxTextureSize == 0)
1191 MaxTextureSize = 256; // Sanity check
1192
1193 //
1194 // HACK!!
1195 if (MaxTextureSize > 1024)
1196 MaxTextureSize = 1024; // HACK - CLAMP TO 1024
1197 // HACK!!
1198 //
1199
1200 // Got to set MAX_TEXTURE_SIZE as max levels.
1201 // Who thought this stupid idea up? ;)
1202 TextureLevels = 0;
1203 // Calculate power-of-two.
1204 while (MaxTextureSize) {
1205 TextureLevels++;
1206 MaxTextureSize >>= 1;
1207 }
1208 lpCtx->glCtx->Const.MaxTextureLevels = (TextureLevels) ? TextureLevels : 8;
1209 lpCtx->glCtx->Const.MaxDrawBuffers = 1;
1210
1211 IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_LIGHTING, FALSE);
1212 IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_CULLMODE, D3DCULL_NONE);
1213 IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_DITHERENABLE, TRUE);
1214 IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
1215
1216 IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_ZENABLE,
1217 (lpCtx->lpPF->dwDriverData!=D3DFMT_UNKNOWN) ? D3DZB_TRUE : D3DZB_FALSE);
1218
1219 // Set the view matrix
1220 {
1221 D3DXMATRIX vm;
1222 #if 1
1223 D3DXMatrixIdentity(&vm);
1224 #else
1225 D3DXVECTOR3 Eye(0.0f, 0.0f, 0.0f);
1226 D3DXVECTOR3 At(0.0f, 0.0f, -1.0f);
1227 D3DXVECTOR3 Up(0.0f, 1.0f, 0.0f);
1228 D3DXMatrixLookAtRH(&vm, &Eye, &At, &Up);
1229 vm._31 = -vm._31;
1230 vm._32 = -vm._32;
1231 vm._33 = -vm._33;
1232 vm._34 = -vm._34;
1233 #endif
1234 IDirect3DDevice9_SetTransform(gld->pDev, D3DTS_VIEW, &vm);
1235 }
1236
1237 if (gld->bHasHWTnL) {
1238 if (glb.dwTnL == GLDS_TNL_DEFAULT)
1239 bSoftwareTnL = FALSE; // HW TnL
1240 else {
1241 bSoftwareTnL = ((glb.dwTnL == GLDS_TNL_MESA) || (glb.dwTnL == GLDS_TNL_D3DSW)) ? TRUE : FALSE;
1242 }
1243 } else {
1244 // No HW TnL, so no choice possible
1245 bSoftwareTnL = TRUE;
1246 }
1247 // IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, bSoftwareTnL);
1248 IDirect3DDevice9_SetSoftwareVertexProcessing(gld->pDev, bSoftwareTnL);
1249
1250 // Dump this in a Release build as well, now.
1251 //#ifdef _DEBUG
1252 ddlogPrintf(DDLOG_INFO, "HW TnL: %s",
1253 gld->bHasHWTnL ? (bSoftwareTnL ? "Disabled" : "Enabled") : "Unavailable");
1254 //#endif
1255
1256 gldEnableExtensions_DX9(lpCtx->glCtx);
1257 gldInstallPipeline_DX9(lpCtx->glCtx);
1258 gldSetupDriverPointers_DX9(lpCtx->glCtx);
1259
1260 // Signal a complete state update
1261 lpCtx->glCtx->Driver.UpdateState(lpCtx->glCtx, _NEW_ALL);
1262
1263 // Start a scene
1264 IDirect3DDevice9_BeginScene(gld->pDev);
1265 lpCtx->bSceneStarted = TRUE;
1266
1267 return TRUE;
1268 }
1269
1270 //---------------------------------------------------------------------------
1271
1272 BOOL gldSwapBuffers_DX(
1273 DGL_ctx *ctx,
1274 HDC hDC,
1275 HWND hWnd)
1276 {
1277 HRESULT hr;
1278 GLD_driver_dx9 *gld = NULL;
1279
1280 if (ctx == NULL)
1281 return FALSE;
1282
1283 gld = ctx->glPriv;
1284 if (gld == NULL)
1285 return FALSE;
1286
1287 if (ctx->bSceneStarted) {
1288 IDirect3DDevice9_EndScene(gld->pDev);
1289 ctx->bSceneStarted = FALSE;
1290 }
1291
1292 // Swap the buffers. hWnd may override the hWnd used for CreateDevice()
1293 hr = IDirect3DDevice9_Present(gld->pDev, NULL, NULL, hWnd, NULL);
1294
1295 exit_swap:
1296
1297 IDirect3DDevice9_BeginScene(gld->pDev);
1298 ctx->bSceneStarted = TRUE;
1299
1300 // Debugging code
1301 #ifdef _DEBUG
1302 // ddlogMessage(GLDLOG_WARN, "SwapBuffers\n");
1303 #endif
1304
1305 return (FAILED(hr)) ? FALSE : TRUE;
1306 }
1307
1308 //---------------------------------------------------------------------------
1309
1310 BOOL gldGetDisplayMode_DX(
1311 DGL_ctx *ctx,
1312 GLD_displayMode *glddm)
1313 {
1314 D3DDISPLAYMODE d3ddm;
1315 HRESULT hr;
1316 GLD_driver_dx9 *lpCtx = NULL;
1317 BYTE cColorBits, cRedBits, cGreenBits, cBlueBits, cAlphaBits;
1318
1319 if ((glddm == NULL) || (ctx == NULL))
1320 return FALSE;
1321
1322 lpCtx = ctx->glPriv;
1323 if (lpCtx == NULL)
1324 return FALSE;
1325
1326 if (lpCtx->pD3D == NULL)
1327 return FALSE;
1328
1329 hr = IDirect3D9_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm);
1330 if (FAILED(hr))
1331 return FALSE;
1332
1333 // Get info from the display format
1334 _BitsFromDisplayFormat(d3ddm.Format,
1335 &cColorBits, &cRedBits, &cGreenBits, &cBlueBits, &cAlphaBits);
1336
1337 glddm->Width = d3ddm.Width;
1338 glddm->Height = d3ddm.Height;
1339 glddm->BPP = cColorBits;
1340 glddm->Refresh = d3ddm.RefreshRate;
1341
1342 return TRUE;
1343 }
1344
1345 //---------------------------------------------------------------------------
1346