Descent3/legacy/D3Launch/3D_detect.cpp

513 lines
13 KiB
C++
Raw Normal View History

/*
2024-06-15 18:13:59 +00:00
* Descent 3
* Copyright (C) 2024 Parallax Software
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
--- HISTORICAL COMMENTS FOLLOW ---
* $Logfile: /DescentIII/Main/D3Launch/3D_detect.cpp $
* $Revision: 1.1.1.1 $
* $Date: 2003-08-26 03:56:51 $
* $Author: kevinb $
*
2024-06-15 18:13:59 +00:00
*
*
* $Log: not supported by cvs2svn $
2024-06-15 18:13:59 +00:00
*
* 15 5/19/99 12:29p Nate
* Fixed openGL crash, changed Network speed default, changed OpenGL
* detection to default to unchecked, and removed config file parsing from
* US version
2024-06-15 18:13:59 +00:00
*
* 14 3/11/99 10:54a Nate
* Changed "3Dfx Glide - Voodoo3" to only show up for Voodoo3 builds that
* don't include all APIs
2024-06-15 18:13:59 +00:00
*
* 13 3/09/99 11:57a Nate
* Changed "Voodoo Graphics Family" to "Voodoo3" for OEM_VOODOO3 builds
2024-06-15 18:13:59 +00:00
*
* 12 10/19/98 11:04a Nate
* More fixes to eliminate detection of software-only OpenGL
2024-06-15 18:13:59 +00:00
*
* 11 10/18/98 2:43p Nate
* Undid some of the suggested Glide init "fixes", as they would sometimes
2024-06-15 18:13:59 +00:00
* cause Direct3D enumeration to crash
*
* 10 10/16/98 3:18p Nate
2024-06-15 18:13:59 +00:00
*
* 9 10/15/98 7:30p Nate
2024-06-15 18:13:59 +00:00
*
* 8 10/13/98 3:03p Nate
* More fixes and changes.
2024-06-15 18:13:59 +00:00
*
* 7 10/12/98 7:13p Nate
* Fixed several bugs.
2024-06-15 18:13:59 +00:00
*
* 6 10/08/98 6:23p Nate
* Fixed a few bugs.
2024-06-15 18:13:59 +00:00
*
* 5 9/18/98 5:18p Nate
* Added a card type to the 3dfx Glide board detection type.
2024-06-15 18:13:59 +00:00
*
* 4 9/02/98 9:48a Nate
* Fixed hardware accelerator display bug in the Speed Tab
2024-06-15 18:13:59 +00:00
*
* 3 9/01/98 7:15p Nate
* Major Revision #2
2024-06-15 18:13:59 +00:00
*
* 2 8/05/98 11:54a Nate
* Initial Version
*
* $NoKeywords: $
*/
2024-06-15 18:13:59 +00:00
#define DYNAHEADER
#define DYNAHEADER_CREATE_STORAGE
#include "stdafx.h"
#include "dyna_glide.h"
#include "module.h"
#include "pserror.h"
#include "PsTypes.h"
#include "3d_detect.h"
#include "gl.h"
#include "D3Launch.h"
#include "VideoTab.h"
#undef D3D_OVERLOADS
#include "d3d.h"
#include "ddraw.h"
card3d Cards[MAX_CARDS];
int Num_cards = 0;
#define MAX_D2D_DEVICES 8
#define MAX_D3D_DEVICES 16
struct d3d_device {
2024-06-15 18:13:59 +00:00
GUID guid_2d;
LPGUID pguid_2d;
2024-06-15 18:13:59 +00:00
GUID guid_3d;
LPGUID pguid_3d;
2024-06-15 18:13:59 +00:00
char name[1024];
};
d3d_device D2D_devices[MAX_D2D_DEVICES];
d3d_device D3D_devices[MAX_D3D_DEVICES];
int Num_d2d_devices = 0;
int Num_d3d_devices = 0;
// The enumeration callback for D3D devices
2024-06-15 18:13:59 +00:00
HRESULT WINAPI gr_d3d_enum(LPGUID lpGUID, LPSTR lpDeviceDescription, LPSTR lpDeviceName, LPD3DDEVICEDESC lpHWDesc,
LPD3DDEVICEDESC lpHELDesc, LPVOID lpContext) {
int use_it = 0;
// mprintf( "Found 3d device %s: %s\n", lpDeviceName, lpDeviceDescription );
if (lpHWDesc && lpHWDesc->dwFlags != 0) {
use_it = 1;
} // else if ( lpHELDesc ) {
if (use_it) {
d3d_device *d2d = (d3d_device *)lpContext;
d3d_device *d3d = (d3d_device *)&D3D_devices[Num_d3d_devices++];
if (lpGUID) {
memmove(&d3d->guid_3d, lpGUID, sizeof(GUID));
d3d->pguid_3d = &d3d->guid_3d;
} else {
memset(&d3d->guid_3d, 0, sizeof(GUID));
d3d->pguid_3d = NULL;
}
memmove(&d3d->guid_2d, &d2d->guid_2d, sizeof(GUID));
if (d2d->pguid_2d) {
d3d->pguid_2d = &d3d->guid_2d;
} else {
d3d->pguid_2d = NULL;
}
// strcpy( d3d->name, "Direct 3D - " );
strcpy(d3d->name, d2d->name);
}
return D3DENUMRET_OK;
}
2024-06-15 18:13:59 +00:00
// The enumeration callback for 2D
BOOL WINAPI gr_d2d_enum(LPGUID lpGUID, LPSTR lpDeviceDescription, LPSTR lpDeviceName, LPVOID lpContext) {
d3d_device *d2d = (d3d_device *)&D2D_devices[Num_d2d_devices++];
// mprintf( "Found 2d device %s: %s\n", lpDeviceName, lpDeviceDescription );
if (lpGUID) {
memmove(&d2d->guid_2d, lpGUID, sizeof(GUID));
d2d->pguid_2d = &d2d->guid_2d;
} else {
memset(&d2d->guid_2d, 0, sizeof(GUID));
d2d->pguid_2d = NULL;
}
strcpy(d2d->name, lpDeviceDescription);
// strcat( d2d->name, lpDeviceName );
return D3DENUMRET_OK;
}
2024-06-15 18:13:59 +00:00
HRESULT(__stdcall *pfn_DirectDrawEnumerate)(LPDDENUMCALLBACK, LPVOID) = NULL;
HRESULT(__stdcall *pfn_DirectDrawCreate)(GUID FAR *, LPDIRECTDRAW FAR *, IUnknown FAR *) = NULL;
// Check for any Direct 3D devices
2024-06-15 18:13:59 +00:00
void check_direct3d() {
int i;
HRESULT ddrval;
LPDIRECTDRAW lpDD1 = NULL;
LPDIRECT3D2 lpD3D = NULL;
Num_d2d_devices = 0;
Num_d3d_devices = 0;
if (!Dd_dll_handle)
return;
if (!pfn_DirectDrawCreate)
pfn_DirectDrawCreate = (HRESULT(__stdcall *)(GUID FAR *, LPDIRECTDRAW FAR *, IUnknown FAR *))GetProcAddress(
Dd_dll_handle, "DirectDrawCreate");
if (!pfn_DirectDrawCreate)
goto D3DError;
if (!pfn_DirectDrawEnumerate)
pfn_DirectDrawEnumerate =
(HRESULT(__stdcall *)(LPDDENUMCALLBACK, LPVOID))GetProcAddress(Dd_dll_handle, "DirectDrawEnumerateA");
if (!pfn_DirectDrawEnumerate)
goto D3DError;
ddrval = pfn_DirectDrawEnumerate(gr_d2d_enum, NULL);
if (ddrval != DD_OK) {
OutputDebugString("GR_D3D_INIT: DirectDrawEnumerate failed.\n");
goto D3DError;
}
for (i = 0; i < Num_d2d_devices; i++) {
d3d_device *d2d = (d3d_device *)&D2D_devices[i];
ddrval = pfn_DirectDrawCreate(d2d->pguid_2d, &lpDD1, NULL);
if (ddrval != DD_OK) {
OutputDebugString("GR_D3D_INIT: DirectDrawCreate failed.\n");
goto D3DError;
}
ddrval = lpDD1->QueryInterface(IID_IDirect3D2, (LPVOID *)&lpD3D);
if (ddrval != DD_OK) {
OutputDebugString("GR_D3D_INIT: QueryInterface failed.\n");
goto D3DError;
}
ddrval = lpD3D->EnumDevices(gr_d3d_enum, d2d);
if (ddrval != DD_OK) {
OutputDebugString("WIN_DD32: D3D enum devices failed. (0x%x)\n"); //, ddrval );
}
lpD3D->Release();
lpD3D = NULL;
lpDD1->Release();
lpDD1 = NULL;
}
// Store Direct3D devices in number of cards
for (i = 0; i < Num_d3d_devices; i++) {
strcpy(Cards[Num_cards].name, D3D_devices[i].name);
Cards[Num_cards].renderer_type = RENDERER_DIRECT3D;
Num_cards++;
}
return;
D3DError:
2024-06-15 18:13:59 +00:00
// If any devices haven't been freed, free them
if (lpD3D != NULL) {
lpD3D->Release();
lpD3D = NULL;
}
2024-06-15 18:13:59 +00:00
if (lpDD1 != NULL) {
lpDD1->Release();
lpDD1 = NULL;
}
// mprintf( "Direct3D Polling failed.\n" );
2024-06-15 18:13:59 +00:00
return;
}
2024-06-15 18:13:59 +00:00
void check_glide() {
static GrHwConfiguration hwconfig;
module *GlideDLLHandle;
2024-06-15 18:13:59 +00:00
if (!(GlideDLLHandle = LoadGlideDLL())) {
// mprintf( "Glide DLL not found!\n" );
return;
}
2024-06-15 18:13:59 +00:00
if (!GlideInited) {
2024-06-15 18:13:59 +00:00
// Check if any 3dfx systems are present
grSstQueryBoards(&hwconfig);
if (hwconfig.num_sst <= 0) {
mod_FreeModule(GlideDLLHandle);
return;
}
2024-06-15 18:13:59 +00:00
grGlideInit();
GlideInited = TRUE;
2024-06-15 18:13:59 +00:00
if (grSstQueryHardware(&hwconfig) == 0 || hwconfig.num_sst < 1) {
// Glide is now only shutdown when the application exits
// grGlideShutdown();
mod_FreeModule(GlideDLLHandle);
return;
}
2024-06-15 18:13:59 +00:00
grGlideShutdown();
}
2024-06-15 18:13:59 +00:00
if (hwconfig.num_sst <= 0) {
mod_FreeModule(GlideDLLHandle);
return;
}
2024-06-15 18:13:59 +00:00
Cards[Num_cards].renderer_type = RENDERER_GLIDE;
2024-06-15 18:13:59 +00:00
switch (hwconfig.SSTs[0].type) {
case GR_SSTTYPE_VOODOO:
#if (defined(OEM_VOODOO3) && !defined(USE_ALL_VIDEO_OPTIONS))
2024-06-15 18:13:59 +00:00
strcpy(Cards[Num_cards].name, "Voodoo3");
#else
2024-06-15 18:13:59 +00:00
strcpy(Cards[Num_cards].name, "Voodoo Graphics Family");
#endif
2024-06-15 18:13:59 +00:00
break;
case GR_SSTTYPE_SST96:
strcpy(Cards[Num_cards].name, "SST96");
break;
case GR_SSTTYPE_AT3D:
strcpy(Cards[Num_cards].name, "AT3D");
break;
default:
strcpy(Cards[Num_cards].name, "");
break;
}
Num_cards++;
// Glide is now only shutdown when the application exits
// grGlideShutdown();
mod_FreeModule(GlideDLLHandle);
}
// Shuts down glide (if it has been initialized)
2024-06-15 18:13:59 +00:00
void shutdown_glide(void) {
if (GlideInited) {
module *GlideDLLHandle;
if ((GlideDLLHandle = LoadGlideDLL())) {
grGlideShutdown();
mod_FreeModule(GlideDLLHandle);
}
}
}
// OpenGL function pointer type definitions
2024-06-15 18:13:59 +00:00
typedef const GLubyte *(CALLBACK *LPFN_GLGETSTRING)(GLenum);
typedef BOOL(CALLBACK *LPFN_WGLMAKECURRENT)(HDC, HGLRC);
typedef HGLRC(CALLBACK *LPFN_WGLCREATECONTEXT)(HDC);
typedef BOOL(CALLBACK *LPFN_WGLDELETECONTEXT)(HGLRC);
// Check for OpenGL support, and add it to list
2024-06-15 18:13:59 +00:00
void check_openGL() {
LPFN_GLGETSTRING pfn_glGetString = NULL;
LPFN_WGLMAKECURRENT pfn_wglMakeCurrent = NULL;
LPFN_WGLCREATECONTEXT pfn_wglCreateContext = NULL;
LPFN_WGLDELETECONTEXT pfn_wglDeleteContext = NULL;
// Check for the OpenGL dll, and open it
if (opengl_dll_handle == NULL) {
opengl_dll_handle = LoadLibrary("opengl32.dll");
if (opengl_dll_handle == NULL) {
OutputDebugString("OpenGL DLL not found.\n");
return;
}
}
// Get the functions to check the OpenGL renderer
pfn_glGetString = (LPFN_GLGETSTRING)GetProcAddress(opengl_dll_handle, "glGetString");
pfn_wglCreateContext = (LPFN_WGLCREATECONTEXT)GetProcAddress(opengl_dll_handle, "wglCreateContext");
pfn_wglDeleteContext = (LPFN_WGLDELETECONTEXT)GetProcAddress(opengl_dll_handle, "wglDeleteContext");
pfn_wglMakeCurrent = (LPFN_WGLMAKECURRENT)GetProcAddress(opengl_dll_handle, "wglMakeCurrent");
if (!pfn_glGetString || !pfn_wglCreateContext || !pfn_wglDeleteContext || !pfn_wglMakeCurrent) {
OutputDebugString("Could not obtain pfn_glGetString().\n");
return;
}
// Make sure the video tab has been initialized first
if (CurrentVideoTab == NULL) {
OutputDebugString("The Video Tab was not set.\n");
return;
}
// Get the window device context
// NOTE:the window is now set to the scanning window that is
// displayed just before detect_3dcards() is called, and
// destroyed afterwords - this function will fail if
// it is called in any other context.
HDC hOpenGLDC = GetDC(CurrentVideoTab->m_MsgDlg.m_hWnd);
if (hOpenGLDC == NULL) {
OutputDebugString("GetDC() failed.\n");
return;
}
// Finds an acceptable pixel format to render to
PIXELFORMATDESCRIPTOR pfd, pfd_copy;
int pf;
memset(&pfd, 0, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_GENERIC_ACCELERATED;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 16;
pfd.cDepthBits = 16;
// Find the user's "best match" PFD
pf = ChoosePixelFormat(hOpenGLDC, &pfd);
if (pf == 0) {
OutputDebugString("ChoosePixelFormat() failed.\n");
return;
}
// Try and set the new PFD
if (SetPixelFormat(hOpenGLDC, pf, &pfd) == FALSE) {
DWORD ret = GetLastError();
OutputDebugString("SetPixelFormat() failed.\n");
return;
}
// Get a copy of the newly set PFD
if (DescribePixelFormat(hOpenGLDC, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd_copy) == 0) {
OutputDebugString("DescribePixelFormat() failed.\n");
return;
}
// Check the returned PFD to see if it is hardware accelerated
if ((pfd_copy.dwFlags & PFD_GENERIC_ACCELERATED) == 0 && (pfd_copy.dwFlags & PFD_GENERIC_FORMAT) != 0) {
OutputDebugString("Returned OpenGL device is not hardware accelerated.\n");
return;
}
// Create an OpenGL context, and make it the current context
HGLRC ResourceContext;
ResourceContext = pfn_wglCreateContext((HDC)hOpenGLDC);
if (ResourceContext == NULL) {
DWORD ret = GetLastError();
OutputDebugString("wglCreateContext() failed.\n");
return;
}
pfn_wglMakeCurrent((HDC)hOpenGLDC, ResourceContext);
// Add the OpenGL type to card list
Cards[Num_cards].renderer_type = RENDERER_OPENGL;
sprintf(Cards[Num_cards].name, "%s", pfn_glGetString(GL_RENDERER));
Num_cards++;
// Clean up
pfn_wglMakeCurrent(NULL, NULL);
pfn_wglDeleteContext(ResourceContext);
ReleaseDC(CurrentVideoTab->m_hWnd, hOpenGLDC);
}
// Fills in Cards and Num_cards
2024-06-15 18:13:59 +00:00
void detect_3dcards(int detect_direct3d, int detect_glide, int detect_opengl) {
if (VideoCardsDetected)
return;
Num_cards = 0;
// CString no_3d_msg;
// no_3d_msg.LoadString(IDS_3D_DETECT_NO3D);
// strcpy( Cards[Num_cards++].name, no_3d_msg );
// Put in the "none" option
Cards[Num_cards].renderer_type = RENDERER_NONE;
strcpy(Cards[Num_cards].name, "");
Num_cards++;
// Check for the other types
if (detect_opengl)
check_openGL();
if (detect_glide)
check_glide();
if (detect_direct3d)
check_direct3d();
// VideoCardsDetected=TRUE;
}
2024-06-15 18:13:59 +00:00
// Creates a string suitable for the list box
// (combines the renderer_type and the device name)
2024-06-15 18:13:59 +00:00
char *GetFullName(card3d *card) {
static char name[1024];
CString temp;
// empty out the name
strcpy(name, "");
// Copy the renderer type in
switch (card->renderer_type) {
case RENDERER_SOFTWARE_8BIT:
strcpy(name, "Software (8 bit)");
break;
case RENDERER_SOFTWARE_16BIT:
strcpy(name, "Software (16 bit)");
break;
case RENDERER_OPENGL:
strcpy(name, "OpenGL");
break;
case RENDERER_DIRECT3D:
strcpy(name, "Direct3D");
break;
case RENDERER_GLIDE:
strcpy(name, "3Dfx Glide");
break;
default:
temp.LoadString(IDS_3D_DETECT_NO3D);
strcpy(name, temp.GetBuffer(0));
break;
}
// tack on the Device name (if there is one)
if (strlen(card->name) > 0) {
strcat(name, " - ");
strcat(name, card->name);
}
return (name);
}