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