mirror of
https://github.com/kevinbentley/Descent3.git
synced 2025-01-22 19:55:23 +00:00
529 lines
13 KiB
C++
529 lines
13 KiB
C++
/*
|
|
* 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 $
|
|
*
|
|
*
|
|
*
|
|
* $Log: not supported by cvs2svn $
|
|
*
|
|
* 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
|
|
*
|
|
* 14 3/11/99 10:54a Nate
|
|
* Changed "3Dfx Glide - Voodoo3" to only show up for Voodoo3 builds that
|
|
* don't include all APIs
|
|
*
|
|
* 13 3/09/99 11:57a Nate
|
|
* Changed "Voodoo Graphics Family" to "Voodoo3" for OEM_VOODOO3 builds
|
|
*
|
|
* 12 10/19/98 11:04a Nate
|
|
* More fixes to eliminate detection of software-only OpenGL
|
|
*
|
|
* 11 10/18/98 2:43p Nate
|
|
* Undid some of the suggested Glide init "fixes", as they would sometimes
|
|
* cause Direct3D enumeration to crash
|
|
*
|
|
* 10 10/16/98 3:18p Nate
|
|
*
|
|
* 9 10/15/98 7:30p Nate
|
|
*
|
|
* 8 10/13/98 3:03p Nate
|
|
* More fixes and changes.
|
|
*
|
|
* 7 10/12/98 7:13p Nate
|
|
* Fixed several bugs.
|
|
*
|
|
* 6 10/08/98 6:23p Nate
|
|
* Fixed a few bugs.
|
|
*
|
|
* 5 9/18/98 5:18p Nate
|
|
* Added a card type to the 3dfx Glide board detection type.
|
|
*
|
|
* 4 9/02/98 9:48a Nate
|
|
* Fixed hardware accelerator display bug in the Speed Tab
|
|
*
|
|
* 3 9/01/98 7:15p Nate
|
|
* Major Revision #2
|
|
*
|
|
* 2 8/05/98 11:54a Nate
|
|
* Initial Version
|
|
*
|
|
* $NoKeywords: $
|
|
*/
|
|
|
|
#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 {
|
|
GUID guid_2d;
|
|
LPGUID pguid_2d;
|
|
|
|
GUID guid_3d;
|
|
LPGUID pguid_3d;
|
|
|
|
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
|
|
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;
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
HRESULT (__stdcall *pfn_DirectDrawEnumerate) (LPDDENUMCALLBACK, LPVOID) = NULL;
|
|
HRESULT (__stdcall *pfn_DirectDrawCreate) (GUID FAR *, LPDIRECTDRAW FAR *, IUnknown FAR *) = NULL;
|
|
|
|
// Check for any Direct 3D devices
|
|
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:
|
|
|
|
// If any devices haven't been freed, free them
|
|
if(lpD3D!=NULL) {
|
|
lpD3D->Release();
|
|
lpD3D = NULL;
|
|
}
|
|
|
|
if(lpDD1!=NULL) {
|
|
lpDD1->Release();
|
|
lpDD1 = NULL;
|
|
}
|
|
//mprintf( "Direct3D Polling failed.\n" );
|
|
|
|
return;
|
|
}
|
|
|
|
void check_glide()
|
|
{
|
|
static GrHwConfiguration hwconfig;
|
|
module *GlideDLLHandle;
|
|
|
|
if ( !(GlideDLLHandle=LoadGlideDLL()) ) {
|
|
//mprintf( "Glide DLL not found!\n" );
|
|
return;
|
|
}
|
|
|
|
if (!GlideInited) {
|
|
|
|
// Check if any 3dfx systems are present
|
|
grSstQueryBoards(&hwconfig);
|
|
if(hwconfig.num_sst<=0) {
|
|
mod_FreeModule(GlideDLLHandle);
|
|
return;
|
|
}
|
|
|
|
grGlideInit();
|
|
GlideInited=TRUE;
|
|
|
|
if (grSstQueryHardware(&hwconfig)==0 || hwconfig.num_sst<1)
|
|
{
|
|
// Glide is now only shutdown when the application exits
|
|
//grGlideShutdown();
|
|
mod_FreeModule(GlideDLLHandle);
|
|
return;
|
|
}
|
|
|
|
grGlideShutdown();
|
|
}
|
|
|
|
if(hwconfig.num_sst<=0) {
|
|
mod_FreeModule(GlideDLLHandle);
|
|
return;
|
|
}
|
|
|
|
Cards[Num_cards].renderer_type=RENDERER_GLIDE;
|
|
|
|
switch(hwconfig.SSTs[0].type) {
|
|
case GR_SSTTYPE_VOODOO:
|
|
#if (defined(OEM_VOODOO3) && !defined(USE_ALL_VIDEO_OPTIONS))
|
|
strcpy( Cards[Num_cards].name, "Voodoo3" );
|
|
#else
|
|
strcpy( Cards[Num_cards].name, "Voodoo Graphics Family" );
|
|
#endif
|
|
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)
|
|
void shutdown_glide(void)
|
|
{
|
|
if(GlideInited) {
|
|
module *GlideDLLHandle;
|
|
|
|
if ( (GlideDLLHandle=LoadGlideDLL()) ) {
|
|
grGlideShutdown();
|
|
mod_FreeModule(GlideDLLHandle);
|
|
}
|
|
}
|
|
}
|
|
|
|
// OpenGL function pointer type definitions
|
|
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
|
|
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
|
|
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;
|
|
}
|
|
|
|
// Creates a string suitable for the list box
|
|
// (combines the renderer_type and the device name)
|
|
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);
|
|
}
|