//***************************************************************************
//**
//** Alias25 (C) 2000
//**
//** File: CDX8GRAPHICS.CPP
//**
//** Date: 25/11/2000
//**
//** Author: Pierre Renaux
//**
//** Desc: DirectX8 Graphics Wrapper Functions
//**
//***************************************************************************
//===========================================================================
// IMPLEMENTATION HEADERS
//===========================================================================
#include "CDX8Graphics.h"
//===========================================================================
// IMPLEMENTATION PRIVATE DEFINITIONS / ENUMERATIONS / SIMPLE TYPEDEFS
//===========================================================================
#ifndef __AGAMELIB_H__
#include <stdio.h>
#include <stdarg.h>
static void write_error(char *str, ...)
{
va_list ap;
char buf[1024];
va_start(ap, str);
vsprintf((char*)buf, (char*)str, ap);
va_end(ap);
OutputDebugString(buf);
}
#endif
//===========================================================================
// IMPLEMENTATION PRIVATE CLASS PROTOTYPES / EXTERNAL CLASS REFERENCES
//===========================================================================
//===========================================================================
// IMPLEMENTATION PRIVATE STRUCTURES / UTILITY CLASSES
//===========================================================================
// Structure used to represent an adpater
typedef struct DX8GRAPHIC_ADAPTER
{
// Gfx Modes
U32 num_mode;
D3DDISPLAYMODE *modes;
// Identifier structure
D3DADAPTER_IDENTIFIER8 id;
// Device Caps
D3DCAPS8 caps;
} DX8GRAPHIC_ADAPTER;
//===========================================================================
// IMPLEMENTATION REQUIRED EXTERNAL REFERENCES (AVOID)
//===========================================================================
/* Game Library reference */
#ifdef __AGAMELIB_H__
extern "C"
{
extern HWND agl_wnd;
extern int wnd_windowed;
extern BOOL wnd_paint_back;
}
#endif
//===========================================================================
// IMPLEMENTATION PRIVATE FUNCTION PROTOTYPES
//===========================================================================
//===========================================================================
// IMPLEMENTATION PRIVATE DATA
//===========================================================================
//===========================================================================
// IMPLEMENTATION PRIVATE FUNCTIONS
//===========================================================================
//===========================================================================
// INTERFACE DATA
//===========================================================================
//===========================================================================
// INTERFACE FUNCTIONS
//===========================================================================
//===========================================================================
// INTERFACE CLASS BODIES
//===========================================================================
//---------------------------------------------------------------------------
// Name: CDX8Graphics::CDX8Graphics()
// Desc: Constructor, load the D3D8.DLL file.
//---------------------------------------------------------------------------
CDX8Graphics::CDX8Graphics(HWND wnd)
{
Initialise(wnd);
}
//---------------------------------------------------------------------------
// Name: CDX8Graphics::CDX8Graphics()
// Desc: Constructor which allow you to specify directly a gfx mode to
// initialise and the window to use.
//---------------------------------------------------------------------------
CDX8Graphics::CDX8Graphics(HWND wnd, U32 adapter, int w, int h, D3DFORMAT pixformat, U32 behavior)
{
Initialise(wnd);
if(AllOk())
{
mp_all_ok = Gfx(adapter, w, h, pixformat, behavior);
}
}
//---------------------------------------------------------------------------
// Name: CDX8Graphics::CDX8Graphics()
// Desc: Constructor which allow you to specify directly a gfx mode to
// initialise.
//---------------------------------------------------------------------------
CDX8Graphics::CDX8Graphics(U32 adapter, int w, int h, D3DFORMAT pixformat, U32 behavior)
{
Initialise();
if(AllOk())
{
mp_all_ok = Gfx(adapter, w, h, pixformat, behavior);
}
}
//---------------------------------------------------------------------------
// Name: CDX8Graphics::~CDX8Graphics()
// Desc: Destructor, destroy all created objects, devices and unload the DLL.
//---------------------------------------------------------------------------
CDX8Graphics::~CDX8Graphics()
{
Uninitialise();
}
//---------------------------------------------------------------------------
// Name: CDX8Graphics::Initialise()
// Desc: Initialise the class.
//---------------------------------------------------------------------------
void CDX8Graphics::Initialise(HWND wnd)
{
// Set the default values of all members
mp_all_ok = FALSE;
mpUpdateInfo();
mp_d3d_obj = NULL;
mp_d3d_dev = NULL;
mp_num_adapter = 0;
mp_adapters = NULL;
// Load the D3D8 Dll
mp_d3d8_dll = LoadLibrary("D3D8.DLL");
if(!mp_d3d8_dll)
{
write_error("CDX8Graphics::Initialise() - Unable to load D3D8.DLL !");
return;
}
// Get the needed address functions
mpDirect3DCreate8 = (LPDIRECT3D8(WINAPI*)(UINT))GetProcAddress(mp_d3d8_dll, "Direct3DCreate8");
if(!mpDirect3DCreate8)
{
write_error("CDX8Graphics::Initialise() - Unable to get the Direct3DCreate8 procedure address !");
return;
}
// Create the Direct3D object
mp_d3d_obj = mpDirect3DCreate8(D3D_SDK_VERSION);
if(!mp_d3d_obj)
{
write_error("CDX8Graphics::Initialise() - Unable to create the IDirect3D8 object !");
return;
}
// Enumerate hardware
if(!mpEnumerateHardware())
{
write_error("CDX8Graphics::Initialise() - Unable to enumerate hardware !");
return;
}
// Set the current HWND to use
#ifdef __AGAMELIB_H__
mp_wnd = wnd ? wnd : agl_wnd;
#else
if(!wnd)
{
write_error("CDX8Graphics::Initialise() - No Window passed to the initialiser !");
return;
}
mp_wnd = wnd;
#endif
// All is ok so put the state variable at TRUE.
mp_all_ok = TRUE;
}
//---------------------------------------------------------------------------
// Name: CDX8Graphics::Uninitialise()
// Desc: Initialise the class.
//---------------------------------------------------------------------------
void CDX8Graphics::Uninitialise()
{
// Free the adpater list
if(mp_adapters)
{
for(U32 i = 0; i < mp_num_adapter; i++)
{
if(mp_adapters[i].modes)
{
delete mp_adapters[i].modes;
mp_adapters[i].modes = NULL;
}
}
delete mp_adapters;
}
// Free the D3D device
if(mp_d3d_dev)
{
mp_d3d_dev->Release();
mp_d3d_dev = NULL;
}
// Free the D3D object
if(mp_d3d_obj)
{
mp_d3d_obj->Release();
mp_d3d_obj = NULL;
}
// Free the DLL
if(mp_d3d8_dll)
{
FreeLibrary(mp_d3d8_dll);
mp_d3d8_dll = NULL;
mpDirect3DCreate8 = NULL;
}
// Set the window ptr to NULL
mp_wnd = NULL;
// All is not yet ok ;)
mp_all_ok = FALSE;
}
//---------------------------------------------------------------------------
// Name: CDX8Graphics::Gfx(U32 adapter, int w, int h, D3DFORMAT pixformat)
// Desc: Setup the gfx mode.
//---------------------------------------------------------------------------
BOOL CDX8Graphics::Gfx(U32 adapter, int w, int h, D3DFORMAT pixformat, U32 behavior)
{
if(!AdapterCapsWindowed(adapter))
pixformat = mpDesktopMode();
if(pixformat == D3DFMT_UNKNOWN)
{
return mpWindowedInit(adapter, w, h, behavior);
}
return mpFullScreenInit(adapter, w, h, pixformat, behavior);
}
//---------------------------------------------------------------------------
// Name: CDX8Graphics::Switch()
// Desc: Switch between fullscreen and windowed mode.s
//---------------------------------------------------------------------------
BOOL CDX8Graphics::Switch(BOOL fullscreen)
{
if(!AdapterCapsWindowed(mp_current_adapter))
return FALSE;
if(fullscreen == 2)
fullscreen = mp_fullscreen ? FALSE : TRUE;
if(fullscreen)
return Gfx(mp_current_adapter, mp_w, mp_h, mp_pixformat);
else
return Gfx(mp_current_adapter, mp_w, mp_h);
}
//---------------------------------------------------------------------------
// Name: CDX8Graphics::NumAdapter()
// Desc: Return the number of D3D adapter.
//---------------------------------------------------------------------------
U32 CDX8Graphics::NumAdapter()
{
return mp_num_adapter;
}
//---------------------------------------------------------------------------
// Name: CDX8Graphics::AdapterInfo()
// Desc: Return informations about an adapter.
//---------------------------------------------------------------------------
BOOL CDX8Graphics::AdapterInfo(U32 i, D3DCAPS8 *caps, char *name, char *desc)
{
if(i >= mp_num_adapter)
return FALSE;
if(name)
strncpy(name, mp_adapters[i].id.Driver, MAX_DEVICE_IDENTIFIER_STRING);
if(desc)
strncpy(desc, mp_adapters[i].id.Description, MAX_DEVICE_IDENTIFIER_STRING);
if(caps)
memcpy(caps, &mp_adapters[i].caps, sizeof(D3DCAPS8));
return TRUE;
}
//---------------------------------------------------------------------------
// Name: CDX8Graphics::AdapterNumMode()
// Desc: Return the number of gfx mode of an adpater.
//---------------------------------------------------------------------------
U32 CDX8Graphics::AdapterNumMode(U32 i)
{
if(i >= mp_num_adapter)
return 0;
return mp_adapters[i].num_mode;
}
//---------------------------------------------------------------------------
// Name: CDX8Graphics::AdapterMode()
// Desc: Enumerate a gfx mode of an adapter.
//---------------------------------------------------------------------------
BOOL CDX8Graphics::AdapterMode(U32 i, U32 imode, int *w, int *h, D3DFORMAT *format)
{
if(i >= mp_num_adapter)
goto error;
if(imode >= mp_adapters[i].num_mode)
goto error;
if(w) *w = mp_adapters[i].modes[imode].Width;
if(h) *h = mp_adapters[i].modes[imode].Height;
if(format) *format = mp_adapters[i].modes[imode].Format;
return TRUE;
error:;
if(w) *w = 0;
if(h) *h = 0;
if(format) *format = D3DFMT_UNKNOWN;
return FALSE;
}
//---------------------------------------------------------------------------
// Name: CDX8Graphics::AdapterCapsWindowed()
// Desc: Return TRUE if the specifed adapter can render in windowed
// mode.
//---------------------------------------------------------------------------
BOOL CDX8Graphics::AdapterCapsWindowed(U32 i)
{
D3DCAPS8 caps;
if(AdapterInfo(i, &caps))
{
if((caps.Caps2 & D3DCAPS2_CANRENDERWINDOWED) == D3DCAPS2_CANRENDERWINDOWED)
return TRUE;
}
return FALSE;
}
//---------------------------------------------------------------------------
// Name: CDX8Graphics::mpEnumerateHardware()
// Desc: Enumerate present harware.
//---------------------------------------------------------------------------
BOOL CDX8Graphics::mpEnumerateHardware()
{
U32 i, j, num_hal;
if(!mp_d3d_obj)
return FALSE;
// Get the number of adpaters
mp_num_adapter = mp_d3d_obj->GetAdapterCount();
if(mp_num_adapter < 1)
{
write_error("CDX8Graphics::mpEnumerateHardware() - No adapter detected !");
return FALSE;
}
// Alloc the adapters array
mp_adapters = new DX8GRAPHIC_ADAPTER[mp_num_adapter];
if(!mp_adapters)
{
write_error("CDX8Graphics::mpEnumerateHardware() - Unable to alloc mp_adapters !");
return FALSE;
}
// Gets Adapter identifier and gfx modes
for(i = 0, num_hal = 0; i < mp_num_adapter; i++)
{
if(FAILED(mp_d3d_obj->GetAdapterIdentifier(i, D3DENUM_NO_WHQL_LEVEL, &mp_adapters[num_hal].id)))
{
write_error("CDX8Graphics::mpEnumerateHardware() - Unable to adapter identifier [%d] !", i);
return FALSE;
}
if(FAILED(mp_d3d_obj->GetDeviceCaps(i, D3DDEVTYPE_HAL, &mp_adapters[num_hal].caps)))
{
write_error("CDX8Graphics::mpEnumerateHardware() - Unable to get HAL caps of an adapter [%d] !", i);
continue;
}
mp_adapters[num_hal].num_mode = mp_d3d_obj->GetAdapterModeCount(i);
mp_adapters[num_hal].modes = new D3DDISPLAYMODE[mp_adapters[num_hal].num_mode];
if(!mp_adapters[num_hal].modes)
{
write_error("CDX8Graphics::mpEnumerateHardware() - Unable to alloc mp_adapters[%d].modes !", i);
return FALSE;
}
for(j = 0; j < mp_adapters[num_hal].num_mode; j++)
{
mp_d3d_obj->EnumAdapterModes(i, j, &mp_adapters[num_hal].modes[j]);
}
num_hal++;
}
if(num_hal < 1)
{
write_error("CDX8Graphics::mpEnumerateHardware() - No HAL device detected !", i);
return FALSE;
}
return TRUE;
}
//---------------------------------------------------------------------------
// Name: CDX8Graphics::mpDesktopMode()
// Desc: Return the Dektop gfx mode.
//---------------------------------------------------------------------------
D3DFORMAT CDX8Graphics::mpDesktopMode(int *w, int *h)
{
D3DDISPLAYMODE dm; // Used to get the current gfx mode.
// First, get the desktop display mode
if(FAILED(mp_d3d_obj->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dm)))
{
write_error("CDX8Graphics::mpDesktopMode() - Unable to get the current display mode !");
return D3DFMT_UNKNOWN;
}
if(w) *w = dm.Width;
if(h) *h = dm.Height;
return dm.Format;
}
//---------------------------------------------------------------------------
// Name: CDX8Graphics::mpCheckUpBeforeGfxInitialisation()
// Desc: Reset all variables that need to be, before a gfx mode
// initialisation.
//---------------------------------------------------------------------------
void CDX8Graphics::mpCheckUpBeforeGfxInitialisation()
{
// Free the D3D device
if(mp_d3d_dev)
{
mp_d3d_dev->Release();
mp_d3d_dev = NULL;
}
// Reset the info vars.
mpUpdateInfo();
}
//---------------------------------------------------------------------------
// Name: CDX8Graphics::mpWindowedStyle()
// Desc: Change the style and the size of the window to use a windowed gfx
// mode.
//---------------------------------------------------------------------------
void CDX8Graphics::mpWindowedStyle(int w, int h)
{
RECT r;
int style;
#ifdef __AGAMELIB_H__
wnd_paint_back = 0;
wnd_windowed = 1;
#endif
style = GetWindowLong(mp_wnd, GWL_STYLE);
style &= ~(WS_BORDER | WS_SIZEBOX);
style |= WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU;
SetWindowLong(mp_wnd, GWL_STYLE, style);
SetRect(&r, 0, 0, w, h);
AdjustWindowRectEx(&r,
GetWindowLong(mp_wnd,GWL_STYLE),
GetMenu(mp_wnd) != NULL,
GetWindowLong(mp_wnd,GWL_EXSTYLE));
SetWindowPos(mp_wnd, HWND_NOTOPMOST,
(GetSystemMetrics(SM_CXSCREEN)-w)/2,
(GetSystemMetrics(SM_CYSCREEN)-h)/2,
r.right-r.left, r.bottom-r.top, 0);
}
//---------------------------------------------------------------------------
// Name: CDX8Graphics::mpFullScreenStyle()
// Desc: Change the style and the size of the window to use a fullscreen gfx
// mode.
//---------------------------------------------------------------------------
void CDX8Graphics::mpFullScreenStyle(int w, int h)
{
RECT r;
int style;
#ifdef __AGAMELIB_H__
wnd_paint_back = 0;
wnd_windowed = 0;
#endif
style = GetWindowLong(mp_wnd, GWL_STYLE);
style &= ~(WS_BORDER | WS_MINIMIZEBOX | WS_SYSMENU | WS_SIZEBOX | WS_CAPTION);
SetWindowLong(mp_wnd, GWL_STYLE, style);
SetRect(&r, 0, 0, w, h);
AdjustWindowRectEx(&r,
GetWindowLong(mp_wnd,GWL_STYLE),
GetMenu(mp_wnd) != NULL,
GetWindowLong(mp_wnd,GWL_EXSTYLE));
SetWindowPos(mp_wnd, HWND_NOTOPMOST,
(GetSystemMetrics(SM_CXSCREEN)-w)/2,
(GetSystemMetrics(SM_CYSCREEN)-h)/2,
r.right-r.left, r.bottom-r.top, 0);
}
//---------------------------------------------------------------------------
// Name: CDX8Graphics::mpWindowedInit()
// Desc: Initialise a windowed gfx mode. Return FALSE if failed,
// otherwise TRUE.
//---------------------------------------------------------------------------
BOOL CDX8Graphics::mpWindowedInit(U32 adapter, int w, int h, U32 behavior)
{
D3DFORMAT pixformat;
D3DPRESENT_PARAMETERS pp; // Used to create the D3D device.
mpCheckUpBeforeGfxInitialisation();
// Change the window size and style to match with the requested mode
mpWindowedStyle(w, h);
// Get the Desktop color format
pixformat = mpDesktopMode();
// Initialise the pp structure
ZeroMemory(&pp, sizeof(D3DPRESENT_PARAMETERS));
pp.Windowed = TRUE; // Use windowed mode
pp.SwapEffect = D3DSWAPEFFECT_DISCARD; // Use DISCARD swapping method
pp.BackBufferFormat = pixformat; // Use the same pixel format as the
// current display mode.
// Now create the D3D device with the same value as in the DX8Doc tutorial.
// Will be modified !
if(FAILED(mp_d3d_obj->CreateDevice(adapter, D3DDEVTYPE_HAL, mp_wnd,
behavior,
&pp, &mp_d3d_dev)))
{
write_error("CDX8Graphics::mpWindowedInit() - Unable to create the D3D device !");
return FALSE;
}
// Finally update the gfx mode informations
mpUpdateInfo(adapter, w, h, pixformat, FALSE);
return TRUE;
}
//---------------------------------------------------------------------------
// Name: CDX8Graphics::mpFullScreenInit()
// Desc: Initialise a fullscreen gfx mode. Return FALSE if failed,
// otherwise TRUE.
//---------------------------------------------------------------------------
BOOL CDX8Graphics::mpFullScreenInit(U32 adapter, int w, int h, D3DFORMAT pixformat, U32 behavior)
{
D3DPRESENT_PARAMETERS pp; // Used to create the D3D device.
mpCheckUpBeforeGfxInitialisation();
// Change the window size and style to match with the requested mode
mpFullScreenStyle(w, h);
// Initialise the pp structure
ZeroMemory(&pp, sizeof(D3DPRESENT_PARAMETERS));
pp.Windowed = FALSE; // Use fullscreen mode
pp.SwapEffect = D3DSWAPEFFECT_DISCARD; // Use DISCARD swapping method
pp.BackBufferWidth = w;
pp.BackBufferHeight = h;
pp.BackBufferFormat = pixformat; // Use the same pixel format as the
// current display mode.
// Now create the D3D device with the same value as in the DX8Doc tutorial.
// Will be modified !
if(FAILED(mp_d3d_obj->CreateDevice(adapter, D3DDEVTYPE_HAL, mp_wnd,
behavior,
&pp, &mp_d3d_dev)))
{
write_error("CDX8Graphics::mpWindowedInit() - Unable to create the D3D device !");
return FALSE;
}
// Finally update the gfx mode informations
mpUpdateInfo(adapter, w, h, pixformat, TRUE);
return TRUE;
}
//---------------------------------------------------------------------------
// Name: CDX8Graphics::mpUpdateInfo()
// Desc: Update the info variables.
//---------------------------------------------------------------------------
void CDX8Graphics::mpUpdateInfo(U32 adapter, int w, int h, D3DFORMAT pixformat, BOOL fullscreen)
{
mp_current_adapter = adapter;
mp_w = w;
mp_h = h;
mp_pixformat = pixformat;
mp_fullscreen = fullscreen;
}
//***************************************************************************
//**
//** END MODULE CDX8GRAPHICS.CPP
//**
//***************************************************************************
|