1 /****************************************************************************
3 * Mesa 3-D graphics library
4 * Direct3D Driver Interface
6 * ========================================================================
8 * Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
25 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 * ========================================================================
31 * Environment: Windows 9x (Win32)
33 * Description: Pixel Formats.
35 ****************************************************************************/
40 #include "gld_driver.h"
43 // ***********************************************************************
45 char szColorDepthWarning[] =
46 "GLDirect does not support the current desktop\n\
48 You may need to change the display resolution to\n\
49 16 bits per pixel or higher color depth using\n\
50 the Windows Display Settings control panel\n\
51 before running this OpenGL application.\n";
53 // ***********************************************************************
54 // This pixel format will be used as a template when compiling the list
55 // of pixel formats supported by the hardware. Many fields will be
56 // filled in at runtime.
57 // PFD flag defaults are upgraded to match ChoosePixelFormat() -- DaveM
58 DGL_pixelFormat pfTemplateHW =
61 sizeof(PIXELFORMATDESCRIPTOR), // Size of the data structure
62 1, // Structure version - should be 1
64 PFD_DRAW_TO_WINDOW | // The buffer can draw to a window or device surface.
65 PFD_DRAW_TO_BITMAP | // The buffer can draw to a bitmap. (DaveM)
66 PFD_SUPPORT_GDI | // The buffer supports GDI drawing. (DaveM)
67 PFD_SUPPORT_OPENGL | // The buffer supports OpenGL drawing.
68 PFD_DOUBLEBUFFER | // The buffer is double-buffered.
69 0, // Placeholder for easy commenting of above flags
70 PFD_TYPE_RGBA, // Pixel type RGBA.
71 16, // Total colour bitplanes (excluding alpha bitplanes)
72 5, 0, // Red bits, shift
73 5, 5, // Green bits, shift
74 5, 10, // Blue bits, shift
75 0, 0, // Alpha bits, shift (destination alpha)
76 0, // Accumulator bits (total)
77 0, 0, 0, 0, // Accumulator bits: Red, Green, Blue, Alpha
80 0, // Number of auxiliary buffers
82 0, // Specifies the number of overlay and underlay planes.
84 0, // Specifies the transparent color or index of an underlay plane.
87 -1, // No depth/stencil buffer
90 // ***********************************************************************
91 // Return the count of the number of bits in a Bit Mask.
98 return 0; // account for non-RGB mode
100 for (i=0; dw; dw=dw>>1)
105 // ***********************************************************************
110 DWORD dwShift, dwMask;
113 return 0; // account for non-RGB mode
115 for (dwShift=0, dwMask=dwMaskIn; !(dwMask&1); dwShift++, dwMask>>=1);
120 // ***********************************************************************
122 BOOL IsValidPFD(int iPFD)
124 DGL_pixelFormat *lpPF;
130 if ((glb.lpPF == NULL) ||
131 (glb.nPixelFormatCount == 0))
135 if ( (iPFD < 1) || (iPFD > glb.nPixelFormatCount) ) {
136 ddlogMessage(DDLOG_ERROR, "PFD out of range\n");
137 return FALSE; // PFD is invalid
140 // Make a pointer to the pixel format
141 lpPF = &glb.lpPF[iPFD-1];
144 if (lpPF->pfd.nSize != sizeof(PIXELFORMATDESCRIPTOR)) {
145 ddlogMessage(DDLOG_ERROR, "Bad PFD size\n");
146 return FALSE; // PFD is invalid
150 if (lpPF->pfd.nVersion != 1) {
151 ddlogMessage(DDLOG_ERROR, "PFD is not Version 1\n");
152 return FALSE; // PFD is invalid
155 return TRUE; // PFD is valid
158 // ***********************************************************************
160 #ifndef _USE_GLD3_WGL
162 int iEnumCount; // Enumeration count
163 DWORD dwDisplayBitDepth; // Bit depth of current display mode
165 // ***********************************************************************
167 HRESULT WINAPI EnumDisplayModesCallback(
168 DDSURFACEDESC2* pddsd,
172 DDSURFACEDESC2 *lpDisplayMode;
177 return DDENUMRET_CANCEL;
179 dwModeDepth = pddsd->ddpfPixelFormat.dwRGBBitCount;
180 lpDisplayMode = (DDSURFACEDESC2 *)pvContext;
182 // Check mode for compatability with device.
183 if (dwModeDepth != dwDisplayBitDepth)
186 if (lpDisplayMode != NULL) {
187 memcpy(&lpDisplayMode[iEnumCount], pddsd, sizeof(DDSURFACEDESC2));
188 sprintf(buf, TEXT("Mode: %ld x %ld x %ld\n"),
189 pddsd->dwWidth, pddsd->dwHeight, dwModeDepth);
190 ddlogMessage(DDLOG_INFO, buf);
198 // ***********************************************************************
200 HRESULT CALLBACK d3dEnumZBufferFormatsCallback(
201 DDPIXELFORMAT* pddpf,
207 return D3DENUMRET_CANCEL;
209 if (pddpf->dwFlags & DDPF_ZBUFFER) {
210 if (lpZBufferPF == NULL) {
211 // Pass 1. Merely counting the PF
212 glb.nZBufferPFCount++;
214 // Pass 2. Save the PF
215 if (pddpf->dwFlags & DDPF_STENCILBUFFER) {
216 sprintf(buf, " %d: Z=%d S=%d\n",
218 pddpf->dwZBufferBitDepth,
219 pddpf->dwStencilBitDepth);
221 sprintf(buf, " %d: Z=%d S=0\n",
223 pddpf->dwZBufferBitDepth);
225 ddlogMessage(DDLOG_INFO, buf);
227 memcpy(&glb.lpZBufferPF[iEnumCount++],
229 sizeof(DDPIXELFORMAT));
233 return D3DENUMRET_OK;
235 #endif // _USE_GLD3_WGL
237 // ***********************************************************************
239 BOOL IsStencilSupportBroken(LPDIRECTDRAW4 lpDD4)
241 DDDEVICEIDENTIFIER dddi; // DX6 device identifier
242 BOOL bBroken = FALSE;
244 // Microsoft really fucked up with the GetDeviceIdentifier function
245 // on Windows 2000, since it locks up on stock driers on the CD. Updated
246 // drivers from vendors appear to work, but we can't identify the drivers
247 // without this function!!! For now we skip these tests on Windows 2000.
248 if ((GetVersion() & 0x80000000UL) == 0)
251 // Obtain device info
252 if (FAILED(IDirectDraw4_GetDeviceIdentifier(lpDD4, &dddi, 0)))
255 // Matrox G400 stencil buffer support does not draw anything in AutoCAD,
256 // but ordinary Z buffers draw shaded models fine. (DaveM)
257 if (dddi.dwVendorId == 0x102B) { // Matrox
258 if (dddi.dwDeviceId == 0x0525) { // G400
266 // ***********************************************************************
268 void dglBuildPixelFormatList()
273 DGL_pixelFormat *lpPF;
276 _gldDriver.BuildPixelformatList();
279 IDirectDraw *lpDD1 = NULL;
280 IDirectDraw4 *lpDD4 = NULL;
281 IDirect3D3 *lpD3D3 = NULL;
282 DDSURFACEDESC2 ddsdDisplayMode;
284 DWORD dwRb, dwGb, dwBb, dwAb; // Bit counts
285 DWORD dwRs, dwGs, dwBs, dwAs; // Bit shifts
286 DWORD dwPixelType; // RGB or color index
289 glb.nPixelFormatCount = 0;
291 glb.nZBufferPFCount = 0;
292 glb.lpZBufferPF = NULL;
293 glb.nDisplayModeCount = 0;
294 glb.lpDisplayModes = NULL;
297 // Examine the hardware for depth and stencil
301 hRes = DirectDrawCreate(NULL, &lpDD1, NULL);
303 hRes = DirectDrawCreate(&glb.ddGuid, &lpDD1, NULL);
306 ddlogError(DDLOG_ERROR, "dglBPFL: DirectDrawCreate failed", hRes);
310 // Query for DX6 IDirectDraw4.
311 hRes = IDirectDraw_QueryInterface(
316 ddlogError(DDLOG_ERROR, "dglBPFL: QueryInterface (DD4) failed", hRes);
321 // Retrieve caps of current display mode
322 ZeroMemory(&ddsdDisplayMode, sizeof(ddsdDisplayMode));
323 ddsdDisplayMode.dwSize = sizeof(ddsdDisplayMode);
324 hRes = IDirectDraw4_GetDisplayMode(lpDD4, &ddsdDisplayMode);
328 dwDisplayBitDepth = ddsdDisplayMode.ddpfPixelFormat.dwRGBBitCount;
329 dwPixelType = (dwDisplayBitDepth <= 8) ? PFD_TYPE_COLORINDEX : PFD_TYPE_RGBA;
330 dwRb = BitCount(ddsdDisplayMode.ddpfPixelFormat.dwRBitMask);
331 dwGb = BitCount(ddsdDisplayMode.ddpfPixelFormat.dwGBitMask);
332 dwBb = BitCount(ddsdDisplayMode.ddpfPixelFormat.dwBBitMask);
333 dwRs = BitShift(ddsdDisplayMode.ddpfPixelFormat.dwRBitMask);
334 dwGs = BitShift(ddsdDisplayMode.ddpfPixelFormat.dwGBitMask);
335 dwBs = BitShift(ddsdDisplayMode.ddpfPixelFormat.dwBBitMask);
337 if (BitCount(ddsdDisplayMode.ddpfPixelFormat.dwRGBAlphaBitMask)) {
338 dwAb = BitCount(ddsdDisplayMode.ddpfPixelFormat.dwRGBAlphaBitMask);
339 dwAs = BitShift(ddsdDisplayMode.ddpfPixelFormat.dwRGBAlphaBitMask);
345 // Query for available display modes
346 ddlogMessage(DDLOG_INFO, "\n");
347 ddlogMessage(DDLOG_INFO, "Display Modes:\n");
349 // Pass 1: Determine count
351 hRes = IDirectDraw4_EnumDisplayModes(
356 EnumDisplayModesCallback);
358 ddlogError(DDLOG_ERROR, "dglBPFL: EnumDisplayModes failed", hRes);
361 if (iEnumCount == 0) {
362 ddlogMessage(DDLOG_ERROR, "dglBPFL: No display modes found");
365 glb.lpDisplayModes = (DDSURFACEDESC2 *)calloc(iEnumCount,
366 sizeof(DDSURFACEDESC2));
367 if (glb.lpDisplayModes == NULL) {
368 ddlogMessage(DDLOG_ERROR, "dglBPFL: DDSURFACEDESC2 calloc failed");
371 glb.nDisplayModeCount = iEnumCount;
372 // Pass 2: Save modes
374 hRes = IDirectDraw4_EnumDisplayModes(
378 (void *)glb.lpDisplayModes,
379 EnumDisplayModesCallback);
381 ddlogError(DDLOG_ERROR, "dglBPFL: EnumDisplayModes failed", hRes);
384 // Query for IDirect3D3 interface
385 hRes = IDirectDraw4_QueryInterface(
390 ddlogError(DDLOG_ERROR, "dglBPFL: QueryInterface (D3D3) failed", hRes);
394 ddlogMessage(DDLOG_INFO, "\n");
395 ddlogMessage(DDLOG_INFO, "ZBuffer formats:\n");
397 // Pass 1. Count the ZBuffer pixel formats
398 hRes = IDirect3D3_EnumZBufferFormats(
401 d3dEnumZBufferFormatsCallback,
407 if (glb.nZBufferPFCount) {
408 glb.lpZBufferPF = (DDPIXELFORMAT *)calloc(glb.nZBufferPFCount,
409 sizeof(DDPIXELFORMAT));
410 if(glb.lpZBufferPF == NULL)
413 // Pass 2. Cache the ZBuffer pixel formats
414 iEnumCount = 0; // (Used by the enum function)
415 hRes = IDirect3D3_EnumZBufferFormats(
418 d3dEnumZBufferFormatsCallback,
425 // Remove stencil support for boards which don't work for AutoCAD;
426 // Matrox G400 does not work, but NVidia TNT2 and ATI Rage128 do... (DaveM)
427 if (IsStencilSupportBroken(lpDD4)) {
428 for (i=0; i<iEnumCount; i++)
429 if (glb.lpZBufferPF[i].dwFlags & DDPF_STENCILBUFFER)
430 glb.nZBufferPFCount--;
433 // One each for every ZBuffer pixel format (including no depth buffer)
434 // Times-two because duplicated for single buffering (as opposed to double)
435 glb.nPixelFormatCount = 2 * (glb.nZBufferPFCount + 1);
436 glb.lpPF = (DGL_pixelFormat *)calloc(glb.nPixelFormatCount,
437 sizeof(DGL_pixelFormat));
438 if (glb.lpPF == NULL)
441 // Fill in the pixel formats
442 // Note: Depth buffer bits are really (dwZBufferBitDepth-dwStencilBitDepth)
443 // but this will pass wierd numbers to the OpenGL app. (?)
446 pfTemplateHW.pfd.iPixelType = dwPixelType;
447 pfTemplateHW.pfd.cColorBits = dwDisplayBitDepth;
448 pfTemplateHW.pfd.cRedBits = dwRb;
449 pfTemplateHW.pfd.cGreenBits = dwGb;
450 pfTemplateHW.pfd.cBlueBits = dwBb;
451 pfTemplateHW.pfd.cAlphaBits = dwAb;
452 pfTemplateHW.pfd.cRedShift = dwRs;
453 pfTemplateHW.pfd.cGreenShift = dwGs;
454 pfTemplateHW.pfd.cBlueShift = dwBs;
455 pfTemplateHW.pfd.cAlphaShift = dwAs;
459 // Fill in the double-buffered pixel formats
460 for (i=0; i<(glb.nZBufferPFCount + 1); i++, lpPF++) {
461 memcpy(lpPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
463 lpPF->iZBufferPF = i-1;
464 lpPF->pfd.cDepthBits = glb.lpZBufferPF[i-1].dwZBufferBitDepth;
465 lpPF->pfd.cStencilBits = glb.lpZBufferPF[i-1].dwStencilBitDepth;
468 // Fill in the single-buffered pixel formats
469 for (i=0; i<(glb.nZBufferPFCount + 1); i++, lpPF++) {
470 memcpy(lpPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
472 lpPF->iZBufferPF = i-1;
473 lpPF->pfd.cDepthBits = glb.lpZBufferPF[i-1].dwZBufferBitDepth;
474 lpPF->pfd.cStencilBits = glb.lpZBufferPF[i-1].dwStencilBitDepth;
476 // Remove double-buffer flag. Could use XOR instead...
477 lpPF->pfd.dwFlags &= (~(PFD_DOUBLEBUFFER));
478 // Insert GDI flag for single buffered format only.
479 lpPF->pfd.dwFlags |= PFD_SUPPORT_GDI;
481 #endif // _USE_GLD3_WGL
483 // Lets dump the list to the log
484 // ** Based on "wglinfo" by Nate Robins **
485 ddlogMessage(DDLOG_INFO, "\n");
486 ddlogMessage(DDLOG_INFO, "Pixel Formats:\n");
487 ddlogMessage(DDLOG_INFO,
488 " visual x bf lv rg d st r g b a ax dp st accum buffs ms\n");
489 ddlogMessage(DDLOG_INFO,
490 " id dep cl sp sz l ci b ro sz sz sz sz bf th cl r g b a ns b\n");
491 ddlogMessage(DDLOG_INFO,
492 "-----------------------------------------------------------------\n");
493 for (i=0, lpPF = glb.lpPF; i<glb.nPixelFormatCount; i++, lpPF++) {
494 sprintf(buf, "0x%02x ", i+1);
496 sprintf(cat, "%2d ", lpPF->pfd.cColorBits);
498 if(lpPF->pfd.dwFlags & PFD_DRAW_TO_WINDOW) sprintf(cat, "wn ");
499 else if(lpPF->pfd.dwFlags & PFD_DRAW_TO_BITMAP) sprintf(cat, "bm ");
500 else sprintf(cat, ". ");
503 /* should find transparent pixel from LAYERPLANEDESCRIPTOR */
507 sprintf(cat, "%2d ", lpPF->pfd.cColorBits);
510 /* bReserved field indicates number of over/underlays */
511 if(lpPF->pfd.bReserved) sprintf(cat, " %d ", lpPF->pfd.bReserved);
512 else sprintf(cat, " . ");
515 sprintf(cat, " %c ", lpPF->pfd.iPixelType == PFD_TYPE_RGBA ? 'r' : 'c');
518 sprintf(cat, "%c ", lpPF->pfd.dwFlags & PFD_DOUBLEBUFFER ? 'y' : '.');
521 sprintf(cat, " %c ", lpPF->pfd.dwFlags & PFD_STEREO ? 'y' : '.');
524 if(lpPF->pfd.cRedBits && lpPF->pfd.iPixelType == PFD_TYPE_RGBA)
525 sprintf(cat, "%2d ", lpPF->pfd.cRedBits);
526 else sprintf(cat, " . ");
529 if(lpPF->pfd.cGreenBits && lpPF->pfd.iPixelType == PFD_TYPE_RGBA)
530 sprintf(cat, "%2d ", lpPF->pfd.cGreenBits);
531 else sprintf(cat, " . ");
534 if(lpPF->pfd.cBlueBits && lpPF->pfd.iPixelType == PFD_TYPE_RGBA)
535 sprintf(cat, "%2d ", lpPF->pfd.cBlueBits);
536 else sprintf(cat, " . ");
539 if(lpPF->pfd.cAlphaBits && lpPF->pfd.iPixelType == PFD_TYPE_RGBA)
540 sprintf(cat, "%2d ", lpPF->pfd.cAlphaBits);
541 else sprintf(cat, " . ");
544 if(lpPF->pfd.cAuxBuffers) sprintf(cat, "%2d ", lpPF->pfd.cAuxBuffers);
545 else sprintf(cat, " . ");
548 if(lpPF->pfd.cDepthBits) sprintf(cat, "%2d ", lpPF->pfd.cDepthBits);
549 else sprintf(cat, " . ");
552 if(lpPF->pfd.cStencilBits) sprintf(cat, "%2d ", lpPF->pfd.cStencilBits);
553 else sprintf(cat, " . ");
556 if(lpPF->pfd.cAccumRedBits) sprintf(cat, "%2d ", lpPF->pfd.cAccumRedBits);
557 else sprintf(cat, " . ");
560 if(lpPF->pfd.cAccumGreenBits) sprintf(cat, "%2d ", lpPF->pfd.cAccumGreenBits);
561 else sprintf(cat, " . ");
564 if(lpPF->pfd.cAccumBlueBits) sprintf(cat, "%2d ", lpPF->pfd.cAccumBlueBits);
565 else sprintf(cat, " . ");
568 if(lpPF->pfd.cAccumAlphaBits) sprintf(cat, "%2d ", lpPF->pfd.cAccumAlphaBits);
569 else sprintf(cat, " . ");
572 /* no multisample in Win32 */
573 sprintf(cat, " . .\n");
576 ddlogMessage(DDLOG_INFO, buf);
578 ddlogMessage(DDLOG_INFO,
579 "-----------------------------------------------------------------\n");
580 ddlogMessage(DDLOG_INFO, "\n");
582 #ifndef _USE_GLD3_WGL
584 // Release COM objects
589 // Popup warning message if non RGB color mode
590 if (dwDisplayBitDepth <= 8) {
591 ddlogPrintf(DDLOG_WARN, "Current Color Depth %d bpp is not supported", dwDisplayBitDepth);
592 MessageBox(NULL, szColorDepthWarning, "GLDirect", MB_OK | MB_ICONWARNING);
594 #endif // _USE_GLD3_WGL
597 // ***********************************************************************
599 void dglReleasePixelFormatList()
601 glb.nPixelFormatCount = 0;
606 #ifndef _USE_GLD3_WGL
607 glb.nZBufferPFCount = 0;
608 if (glb.lpZBufferPF) {
609 free(glb.lpZBufferPF);
610 glb.lpZBufferPF = NULL;
612 glb.nDisplayModeCount = 0;
613 if (glb.lpDisplayModes) {
614 free(glb.lpDisplayModes);
615 glb.lpDisplayModes = NULL;
617 #endif // _USE_GLD3_WGL
620 // ***********************************************************************