You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
866 lines
29 KiB
866 lines
29 KiB
/*==========================================================================;
|
|
*
|
|
* Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: d3di.h
|
|
* Content: Direct3D HAL include file
|
|
*@@BEGIN_MSINTERNAL
|
|
*
|
|
* History:
|
|
* Date By Reason
|
|
* ==== == ======
|
|
* 09/11/95 stevela Initial rev with this header.
|
|
* 07/12/95 stevela Merged Colin's changes.
|
|
* 10/12/95 stevela Removed AGGREGATE_D3D.
|
|
* Validate args.
|
|
* 17/04/96 colinmc Bug 17008: DirectDraw/Direct3D deadlock
|
|
* 29/04/96 colinmc Bug 19954: Must query for Direct3D before texture
|
|
* or device
|
|
* 27/08/96 stevela Ifdefed out definition of ghEvent as we're using
|
|
* DirectDraw's critical section.
|
|
*@@END_MSINTERNAL
|
|
*
|
|
***************************************************************************/
|
|
|
|
#include "pch.cpp"
|
|
#pragma hdrstop
|
|
|
|
/*
|
|
* Create an api for the Direct3D object
|
|
*/
|
|
|
|
// Remove DDraw's type unsafe definition and replace with our C++ friendly def
|
|
#ifdef VALIDEX_CODE_PTR
|
|
#undef VALIDEX_CODE_PTR
|
|
#endif
|
|
#define VALIDEX_CODE_PTR( ptr ) \
|
|
(!IsBadCodePtr( (FARPROC) ptr ) )
|
|
|
|
LPCRITICAL_SECTION lpD3DCSect;
|
|
|
|
#if DBG
|
|
int iD3DCSCnt;
|
|
#endif
|
|
|
|
#if COLLECTSTATS
|
|
void DIRECT3DI::ResetTexStats()
|
|
{
|
|
((LPDDRAWI_DIRECTDRAW_INT)lpDD7)->lpLcl->dwNumTexLocks = ((LPDDRAWI_DIRECTDRAW_INT)lpDD7)->lpLcl->dwNumTexGetDCs = 0;
|
|
m_setpris = m_setLODs = m_texCreates = m_texDestroys = 0;
|
|
}
|
|
|
|
void DIRECT3DI::GetTexStats(LPD3DDEVINFO_TEXTURING pStats)
|
|
{
|
|
pStats->dwNumSetPriorities = GetNumSetPris();
|
|
pStats->dwNumSetLODs = GetNumSetLODs();
|
|
pStats->dwNumCreates = GetNumTexCreates();
|
|
pStats->dwNumDestroys = GetNumTexDestroys();
|
|
pStats->dwNumLocks = GetNumTexLocks();
|
|
pStats->dwNumGetDCs = GetNumTexGetDCs();
|
|
}
|
|
#endif
|
|
|
|
//---------------------------------------------------------------------
|
|
// for use by fns that take a GUID param before device is created
|
|
BOOL IsValidD3DDeviceGuid(REFCLSID riid) {
|
|
|
|
if (IsBadReadPtr(&riid, sizeof(CLSID))) {
|
|
return FALSE;
|
|
}
|
|
if( IsEqualIID(riid, IID_IDirect3DRampDevice) ||
|
|
IsEqualIID(riid, IID_IDirect3DRGBDevice) ||
|
|
IsEqualIID(riid, IID_IDirect3DMMXDevice) ||
|
|
IsEqualIID(riid, IID_IDirect3DHALDevice) ||
|
|
IsEqualIID(riid, IID_IDirect3DRefDevice) ||
|
|
IsEqualIID(riid, IID_IDirect3DNullDevice) ||
|
|
IsEqualIID(riid, IID_IDirect3DTnLHalDevice)) {
|
|
return TRUE;
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "Direct3DCreate"
|
|
|
|
DIRECT3DI::DIRECT3DI()
|
|
{
|
|
lpDD = NULL;
|
|
lpDD7 = NULL;
|
|
numDevs = 0;
|
|
mD3DUnk.pD3DI = this;
|
|
mD3DUnk.refCnt = 1;
|
|
|
|
LIST_INITIALIZE(&devices);
|
|
LIST_INITIALIZE(&textures);
|
|
|
|
lpFreeList = NULL; /* nothing is allocated initially */
|
|
lpBufferList = NULL;
|
|
lpTextureManager = NULL;
|
|
|
|
#ifdef __DISABLE_VIDMEM_VBS__
|
|
bDisableVidMemVBs = FALSE;
|
|
#endif
|
|
}
|
|
|
|
HRESULT DIRECT3DI::Initialize(IUnknown* pUnkOuter, LPDDRAWI_DIRECTDRAW_INT pDDrawInt)
|
|
{
|
|
// HACK. D3D needs a DD1 DDRAWI interface because it uses CreateSurface1 internally
|
|
// for exebufs, among other things. Because pDDrawInt could be any DDRAWI type,
|
|
// we need to QI to find a DD1 interface. But the D3DI object cannot keep a reference
|
|
// to its parent DD object because it is aggegrated with the DD obj, so that would constitute
|
|
// a circular reference that would prevent deletion. So we QI for DD1 interface, copy it into D3DI
|
|
// and release it, then point lpDD at the copy. (disgusting)
|
|
|
|
// another HACK alert: dont know which DDRAWI type pDDrawInt is, but a cast to LPDIRECTDRAW should
|
|
// work because QI is in the same place in all the DDRAWI vtables and is the same fn for all
|
|
HRESULT ret;
|
|
ret = ((LPDIRECTDRAW)pDDrawInt)->QueryInterface(IID_IDirectDraw, (LPVOID*)&lpDD);
|
|
if(FAILED(ret))
|
|
{
|
|
D3D_ERR( "QueryInterface for IDDraw failed" );
|
|
return ret;
|
|
}
|
|
memcpy(&DDInt_DD1,lpDD,sizeof(DDInt_DD1));
|
|
lpDD->Release();
|
|
lpDD=(LPDIRECTDRAW)&DDInt_DD1;
|
|
|
|
// We know that the pointer that is handed in is a DD7 interface, hence just typecast and assign
|
|
lpDD7 = reinterpret_cast<LPDIRECTDRAW7>(pDDrawInt);
|
|
|
|
lpTextureManager = new TextureCacheManager(this);
|
|
if(lpTextureManager == 0)
|
|
{
|
|
D3D_ERR("Out of memory allocating texture manager");
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
ret = lpTextureManager->Initialize();
|
|
if(ret != D3D_OK)
|
|
{
|
|
D3D_ERR("Failed to initialize texture manager");
|
|
return ret;
|
|
}
|
|
|
|
#if COLLECTSTATS
|
|
DWORD value = 0;
|
|
GetD3DRegValue(REG_DWORD, "DisplayStats", &value, sizeof(DWORD));
|
|
if(value != 0)
|
|
{
|
|
LOGFONT font;
|
|
strcpy(font.lfFaceName, STATS_FONT_FACE);
|
|
font.lfCharSet = DEFAULT_CHARSET;
|
|
font.lfClipPrecision = CLIP_DEFAULT_PRECIS;
|
|
font.lfEscapement = 0;
|
|
font.lfHeight = STATS_FONT_SIZE;
|
|
font.lfItalic = FALSE;
|
|
font.lfOrientation = 0;
|
|
font.lfOutPrecision = OUT_DEFAULT_PRECIS;
|
|
font.lfPitchAndFamily = DEFAULT_PITCH;
|
|
font.lfQuality = DEFAULT_QUALITY;
|
|
font.lfStrikeOut = FALSE;
|
|
font.lfUnderline = FALSE;
|
|
font.lfWeight = FW_DONTCARE;
|
|
font.lfWidth = 0;
|
|
m_hFont = CreateFontIndirect(&font);
|
|
}
|
|
else
|
|
{
|
|
m_hFont = 0;
|
|
}
|
|
#endif
|
|
|
|
#ifdef __DISABLE_VIDMEM_VBS__
|
|
{
|
|
bDisableVidMemVBs = FALSE;
|
|
DWORD value = 0;
|
|
GetD3DRegValue(REG_DWORD, "DisableVidMemVBs", &value, sizeof(DWORD));
|
|
if(value != 0)
|
|
{
|
|
// Disable VidMemVBs
|
|
bDisableVidMemVBs = TRUE;
|
|
}
|
|
|
|
// We also disable vidmem VBs unless the driver explicitly asks us to turn them on...
|
|
if (((LPDDRAWI_DIRECTDRAW_INT)lpDD7)->lpLcl->lpGbl->lpD3DGlobalDriverData)
|
|
{
|
|
if (0 == (((LPDDRAWI_DIRECTDRAW_INT)lpDD7)->lpLcl->lpGbl->lpD3DGlobalDriverData->hwCaps.dwDevCaps & D3DDEVCAPS_HWVERTEXBUFFER) )
|
|
{
|
|
bDisableVidMemVBs = TRUE;
|
|
}
|
|
}
|
|
}
|
|
#endif //__DISABLE_VIDMEM_VBS__
|
|
|
|
/*
|
|
* Are we really being aggregated?
|
|
*/
|
|
if (pUnkOuter != NULL)
|
|
{
|
|
/*
|
|
* Yup - we are being aggregated. Store the supplied
|
|
* IUnknown so we can punt to that.
|
|
* NOTE: We explicitly DO NOT AddRef here.
|
|
*/
|
|
this->lpOwningIUnknown = pUnkOuter;
|
|
/*
|
|
* Store away the interface pointer
|
|
*/
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Nope - but we pretend we are anyway by storing our
|
|
* own IUnknown as the parent IUnknown. This makes the
|
|
* code much neater.
|
|
*/
|
|
this->lpOwningIUnknown = static_cast<LPUNKNOWN>(&this->mD3DUnk);
|
|
}
|
|
return D3D_OK;
|
|
}
|
|
|
|
|
|
extern "C" HRESULT WINAPI Direct3DCreate(LPCRITICAL_SECTION lpDDCSect,
|
|
LPUNKNOWN* lplpDirect3D,
|
|
IUnknown* pUnkOuter)
|
|
{
|
|
LPDIRECT3DI pd3d;
|
|
|
|
try
|
|
{
|
|
DPFINIT();
|
|
|
|
/*
|
|
* No need to validate params as DirectDraw is giving them to us.
|
|
*/
|
|
|
|
/*
|
|
* Is another thread coming in and is this the first time?
|
|
*/
|
|
|
|
/*
|
|
* We can let every invocation of this function assign
|
|
* the critical section as we know its always going to
|
|
* be the same value (for a D3D session).
|
|
*/
|
|
lpD3DCSect = lpDDCSect;
|
|
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
|
|
// Release in the destructor
|
|
|
|
*lplpDirect3D = NULL;
|
|
|
|
// We do not support non aggregated Direct3D object yet
|
|
if (!pUnkOuter)
|
|
return DDERR_INVALIDPARAMS;
|
|
|
|
if (!(pd3d = static_cast<LPDIRECT3DI>(new DIRECT3DI)))
|
|
{
|
|
D3D_ERR("Out of memory allocating DIRECT3DI");
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
HRESULT hr = pd3d->Initialize(pUnkOuter, (LPDDRAWI_DIRECTDRAW_INT)pUnkOuter);
|
|
if(hr != D3D_OK)
|
|
{
|
|
D3D_ERR("Failed to initialize Direct3D.");
|
|
delete pd3d;
|
|
return hr;
|
|
}
|
|
|
|
/*
|
|
* NOTE: The special IUnknown is returned and not the actual
|
|
* Direct3D interface so you can't use this to drive Direct3D.
|
|
* You must query off this interface for the Direct3D interface.
|
|
*/
|
|
*lplpDirect3D = static_cast<LPUNKNOWN>(&(pd3d->mD3DUnk));
|
|
|
|
return (D3D_OK);
|
|
}
|
|
catch (HRESULT ret)
|
|
{
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "Direct3D::EnumDevices"
|
|
|
|
extern BOOL isMMXprocessor(void);
|
|
|
|
typedef struct _D3DI_DeviceType {
|
|
CONST GUID *pGuid;
|
|
char name[256];
|
|
char description[512];
|
|
} D3DI_DeviceType;
|
|
|
|
// Static definitions for various enumerable devices
|
|
static D3DI_DeviceType RGBDevice =
|
|
{
|
|
&IID_IDirect3DRGBDevice, "RGB Emulation",
|
|
"Microsoft Direct3D RGB Software Emulation"
|
|
};
|
|
static D3DI_DeviceType HALDevice =
|
|
{
|
|
&IID_IDirect3DHALDevice, "Direct3D HAL",
|
|
"Microsoft Direct3D Hardware acceleration through Direct3D HAL"
|
|
};
|
|
static D3DI_DeviceType RefDevice =
|
|
{
|
|
&IID_IDirect3DRefDevice, "Reference Rasterizer",
|
|
"Microsoft Reference Rasterizer"
|
|
};
|
|
static D3DI_DeviceType NullDevice =
|
|
{
|
|
&IID_IDirect3DNullDevice, "Null device",
|
|
"Microsoft Null Device"
|
|
};
|
|
static D3DI_DeviceType TnLHALDevice =
|
|
{
|
|
&IID_IDirect3DTnLHalDevice, "Direct3D T&L HAL",
|
|
"Microsoft Direct3D Hardware Transform and Lighting acceleration capable device"
|
|
};
|
|
|
|
static D3DI_DeviceType *AllDevices[] =
|
|
{
|
|
&RGBDevice, &HALDevice, &RefDevice, &NullDevice,
|
|
&TnLHALDevice, NULL
|
|
};
|
|
|
|
HRESULT
|
|
DIRECT3DI::EnumDevices(LPD3DENUMDEVICESCALLBACK7 lpEnumCallback,
|
|
LPVOID lpContext, DWORD dwSize, DWORD dwVer)
|
|
{
|
|
HRESULT err, userRet;
|
|
HKEY hKey;
|
|
LONG result;
|
|
int i;
|
|
|
|
try
|
|
{
|
|
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
|
|
// Release in the destructor
|
|
|
|
if (!VALIDEX_CODE_PTR((FARPROC)lpEnumCallback))
|
|
{
|
|
D3D_ERR( "Invalid callback pointer" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
BOOL bSoftwareOnly = FALSE;
|
|
BOOL bEnumReference = FALSE;
|
|
BOOL bEnumNullDevice = FALSE;
|
|
BOOL bEnumSeparateMMX = FALSE;
|
|
|
|
result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, RESPATH, 0, KEY_READ, &hKey);
|
|
if (result == ERROR_SUCCESS)
|
|
{
|
|
DWORD dwData, dwType;
|
|
DWORD dwDataSize;
|
|
|
|
// Enumerate software rasterizers only ?
|
|
dwDataSize = sizeof(dwData);
|
|
result = RegQueryValueEx(hKey, "SoftwareOnly", NULL,
|
|
&dwType, (BYTE *) &dwData, &dwDataSize);
|
|
if ( result == ERROR_SUCCESS && dwType == REG_DWORD )
|
|
{
|
|
bSoftwareOnly = ( dwData != 0 );
|
|
}
|
|
|
|
// Enumerate Reference Rasterizer ?
|
|
dwDataSize = sizeof(dwData);
|
|
result = RegQueryValueEx(hKey, "EnumReference", NULL,
|
|
&dwType, (BYTE *)&dwData, &dwDataSize);
|
|
if (result == ERROR_SUCCESS &&
|
|
dwType == REG_DWORD &&
|
|
dwDataSize == sizeof(dwData))
|
|
{
|
|
bEnumReference = (BOOL)dwData;
|
|
}
|
|
|
|
// Enumerate Null Device ?
|
|
dwDataSize = sizeof(dwData);
|
|
result = RegQueryValueEx(hKey, "EnumNullDevice", NULL,
|
|
&dwType, (BYTE *)&dwData, &dwDataSize);
|
|
if (result == ERROR_SUCCESS &&
|
|
dwType == REG_DWORD &&
|
|
dwDataSize == sizeof(dwData))
|
|
{
|
|
bEnumNullDevice = (BOOL)dwData;
|
|
}
|
|
|
|
|
|
RegCloseKey( hKey );
|
|
}
|
|
|
|
D3DI_DeviceType **lpDevices = AllDevices;
|
|
|
|
userRet = D3DENUMRET_OK;
|
|
for (i = 0; lpDevices[i] && userRet == D3DENUMRET_OK; i++)
|
|
{
|
|
LPSTR drvName = lpDevices[i]->name;
|
|
LPSTR drvDesc = lpDevices[i]->description;
|
|
REFCLSID riid = *lpDevices[i]->pGuid;
|
|
D3DDEVICEDESC7 HWDesc;
|
|
D3DDEVICEDESC7 HELDesc;
|
|
LPDDRAWI_DIRECTDRAW_GBL lpDDGbl;
|
|
IHalProvider *pHalProv;
|
|
HINSTANCE hDll;
|
|
|
|
if ( !bEnumReference &&
|
|
IsEqualIID(riid, IID_IDirect3DRefDevice))
|
|
{
|
|
// Not enumerating the reference.
|
|
continue;
|
|
}
|
|
|
|
if (!bEnumNullDevice &&
|
|
IsEqualIID(riid, IID_IDirect3DNullDevice))
|
|
{
|
|
// Not enumerating the Null device.
|
|
continue;
|
|
}
|
|
|
|
// By COM definition, our owning IUnknown is a pointer to the
|
|
// DirectDraw object that was used to create us.
|
|
// Check this for the existence of a Direct3D HAL.
|
|
lpDDGbl = ((LPDDRAWI_DIRECTDRAW_INT)this->lpDD)->lpLcl->lpGbl;
|
|
|
|
|
|
if (IsEqualIID(riid, IID_IDirect3DTnLHalDevice) && (lpDDGbl->lpD3DGlobalDriverData))
|
|
{
|
|
if (!(lpDDGbl->lpD3DGlobalDriverData->hwCaps.dwDevCaps &
|
|
D3DDEVCAPS_HWTRANSFORMANDLIGHT))
|
|
{
|
|
// Not enumerating the T&L device if the hardware doesnt support
|
|
// T&L
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// See if this is a software driver.
|
|
err = GetSwHalProvider(riid, &pHalProv, &hDll);
|
|
if (err == S_OK)
|
|
{
|
|
// Successfully got a software driver.
|
|
}
|
|
else if (err == E_NOINTERFACE &&
|
|
! bSoftwareOnly &&
|
|
GetHwHalProvider(riid, &pHalProv, &hDll, lpDDGbl) == S_OK)
|
|
{
|
|
// Successfully got a hardware driver.
|
|
}
|
|
else
|
|
{
|
|
// Unrecognized driver.
|
|
continue;
|
|
}
|
|
|
|
err = pHalProv->GetCaps(lpDDGbl, &HWDesc, &HELDesc, dwVer);
|
|
|
|
pHalProv->Release();
|
|
if (hDll != NULL)
|
|
{
|
|
FreeLibrary(hDll);
|
|
}
|
|
|
|
if (err != S_OK)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if( HWDesc.wMaxVertexBlendMatrices == 1 )
|
|
HWDesc.wMaxVertexBlendMatrices = 0;
|
|
|
|
if( HELDesc.wMaxVertexBlendMatrices == 1 )
|
|
HELDesc.wMaxVertexBlendMatrices = 0;
|
|
|
|
// If Hal device is being enumerated, strip out the
|
|
// HWTRANSFORM... flag
|
|
if (IsEqualIID(riid, IID_IDirect3DHALDevice))
|
|
{
|
|
HWDesc.dwMaxActiveLights = 0xffffffff;
|
|
HWDesc.wMaxVertexBlendMatrices = 4;
|
|
HWDesc.wMaxUserClipPlanes = __MAXUSERCLIPPLANES;
|
|
HWDesc.dwVertexProcessingCaps = D3DVTXPCAPS_ALL;
|
|
HWDesc.dwDevCaps &= ~(D3DDEVCAPS_HWTRANSFORMANDLIGHT);
|
|
}
|
|
|
|
if (IsEqualIID(riid, IID_IDirect3DRGBDevice))
|
|
{
|
|
HELDesc.dwMaxActiveLights = 0xffffffff;
|
|
HELDesc.wMaxVertexBlendMatrices = 4;
|
|
HELDesc.wMaxUserClipPlanes = __MAXUSERCLIPPLANES;
|
|
HELDesc.dwVertexProcessingCaps = D3DVTXPCAPS_ALL;
|
|
}
|
|
|
|
if (IsEqualIID(riid, IID_IDirect3DHALDevice) || IsEqualIID(riid, IID_IDirect3DTnLHalDevice))
|
|
{
|
|
memcpy(&HWDesc.deviceGUID, lpDevices[i]->pGuid, sizeof(GUID));
|
|
userRet = (*lpEnumCallback)(drvDesc, drvName,
|
|
&HWDesc, lpContext);
|
|
}
|
|
else
|
|
{
|
|
memcpy(&HELDesc.deviceGUID, lpDevices[i]->pGuid, sizeof(GUID));
|
|
userRet = (*lpEnumCallback)(drvDesc, drvName,
|
|
&HELDesc, lpContext);
|
|
}
|
|
}
|
|
|
|
return D3D_OK;
|
|
}
|
|
catch (HRESULT ret)
|
|
{
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
HRESULT D3DAPI DIRECT3DI::EnumDevices(LPD3DENUMDEVICESCALLBACK7 lpEnumCallback,
|
|
LPVOID lpContext)
|
|
{
|
|
return EnumDevices(lpEnumCallback, lpContext, D3DDEVICEDESC7SIZE, 4);
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "Direct3DI::EnumZBufferFormats"
|
|
|
|
HRESULT D3DAPI DIRECT3DI::EnumZBufferFormats(REFCLSID riid,
|
|
LPD3DENUMPIXELFORMATSCALLBACK lpEnumCallback,
|
|
LPVOID lpContext)
|
|
{
|
|
HRESULT ret, userRet;
|
|
LPDDPIXELFORMAT lpTmpPixFmts;
|
|
DWORD i,cPixFmts;
|
|
|
|
try
|
|
{
|
|
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
|
|
|
|
ret = D3D_OK;
|
|
|
|
if (!VALID_DIRECT3D_PTR(this))
|
|
{
|
|
D3D_ERR( "Invalid Direct3D3 pointer" );
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
if (!VALIDEX_CODE_PTR(lpEnumCallback))
|
|
{
|
|
D3D_ERR( "Invalid callback pointer" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if(!IsValidD3DDeviceGuid(riid))
|
|
{
|
|
D3D_ERR( "Invalid D3D Device GUID" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
if( IsEqualIID(riid, IID_IDirect3DHALDevice) ||
|
|
IsEqualIID(riid, IID_IDirect3DTnLHalDevice) )
|
|
{
|
|
LPDDRAWI_DIRECTDRAW_GBL pDdGbl=((LPDDRAWI_DIRECTDRAW_INT)this->lpDD)->lpLcl->lpGbl;
|
|
LPD3DHAL_GLOBALDRIVERDATA lpD3DHALGlobalDriverData=pDdGbl->lpD3DGlobalDriverData;
|
|
DWORD dwHW_ZBitDepthFlags;
|
|
if (NULL == lpD3DHALGlobalDriverData)
|
|
{
|
|
D3D_ERR("No HAL Support ZBufferBitDepths!");
|
|
return (DDERR_NOZBUFFERHW);
|
|
}
|
|
cPixFmts=pDdGbl->dwNumZPixelFormats;
|
|
if (cPixFmts==0) {
|
|
// driver is pre-dx6, so it doesn't support stencil buffer pix fmts or this callback.
|
|
// we can fake support using DD_BD bits in dwZBufferBitDepth in D3DDEVICEDESC
|
|
D3D_WARN(6,"EnumZBufferFormats not supported directly by driver, faking it using dwDeviceZBufferBitDepth DD_BD bits");
|
|
|
|
dwHW_ZBitDepthFlags=lpD3DHALGlobalDriverData->hwCaps.dwDeviceZBufferBitDepth;
|
|
|
|
if(!(dwHW_ZBitDepthFlags & (DDBD_8|DDBD_16|DDBD_24|DDBD_32))) {
|
|
D3D_ERR("No Supported ZBufferBitDepths!");
|
|
return (DDERR_NOZBUFFERHW);
|
|
}
|
|
|
|
// malloc space for 4 DDPIXELFORMATs, since that the most there could be (DDBD_8,16,24,32)
|
|
if (D3DMalloc((void**)&lpTmpPixFmts, 4*sizeof(DDPIXELFORMAT)) != D3D_OK) {
|
|
D3D_ERR("failed to alloc space for return descriptions");
|
|
return (DDERR_OUTOFMEMORY);
|
|
}
|
|
|
|
DWORD zdepthflags[4]= {DDBD_8,DDBD_16,DDBD_24,DDBD_32};
|
|
DWORD zbitdepths[4]= {8,16,24,32};
|
|
DWORD zbitmasks[4]= {0xff,0xffff,0xffffff,0xffffffff};
|
|
|
|
memset(lpTmpPixFmts,0,sizeof(4*sizeof(DDPIXELFORMAT)));
|
|
|
|
// create some DDPIXELFORMATs the app can look at
|
|
for(i=0;i<4;i++) {
|
|
if(dwHW_ZBitDepthFlags & zdepthflags[i]) {
|
|
lpTmpPixFmts[cPixFmts].dwSize=sizeof(DDPIXELFORMAT);
|
|
lpTmpPixFmts[cPixFmts].dwFlags=DDPF_ZBUFFER;
|
|
lpTmpPixFmts[cPixFmts].dwZBufferBitDepth=zbitdepths[i];
|
|
lpTmpPixFmts[cPixFmts].dwZBitMask= zbitmasks[i];
|
|
cPixFmts++;
|
|
}
|
|
}
|
|
} else {
|
|
// only show the app a temp copy of DDraw's real records
|
|
|
|
if (D3DMalloc((void**)&lpTmpPixFmts, cPixFmts*sizeof(DDPIXELFORMAT)) != D3D_OK) {
|
|
D3D_ERR("Out of memory allocating space for return descriptions");
|
|
return (DDERR_OUTOFMEMORY);
|
|
}
|
|
memcpy(lpTmpPixFmts, pDdGbl->lpZPixelFormats, cPixFmts*sizeof(DDPIXELFORMAT));
|
|
}
|
|
} else {
|
|
// Handle SW rasterizers
|
|
DDPIXELFORMAT *pDDPF;
|
|
|
|
// malloc space for 10 DDPIXELFORMAT's, which is currently more than enough for the SW rasterizers
|
|
if (D3DMalloc((void**)&lpTmpPixFmts, 10*sizeof(DDPIXELFORMAT)) != D3D_OK) {
|
|
D3D_ERR("Out of memory allocating space for return descriptions");
|
|
return (DDERR_OUTOFMEMORY);
|
|
}
|
|
|
|
cPixFmts=GetSwZBufferFormats(riid,&pDDPF);
|
|
memcpy(lpTmpPixFmts, pDDPF, cPixFmts*sizeof(DDPIXELFORMAT));
|
|
}
|
|
|
|
userRet = D3DENUMRET_OK;
|
|
for (i = 0; (i < cPixFmts) && (userRet == D3DENUMRET_OK); i++) {
|
|
userRet = (*lpEnumCallback)(&lpTmpPixFmts[i], lpContext);
|
|
}
|
|
|
|
D3DFree(lpTmpPixFmts);
|
|
|
|
return (D3D_OK);
|
|
}
|
|
catch (HRESULT ret)
|
|
{
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DIRECT3D::EvictManagedTextures"
|
|
HRESULT D3DAPI
|
|
DIRECT3DI::EvictManagedTextures()
|
|
{
|
|
try
|
|
{
|
|
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
|
|
if (!VALID_DIRECT3D_PTR(this))
|
|
{
|
|
D3D_ERR( "Invalid Direct3D3 pointer" );
|
|
return DDERR_INVALIDOBJECT;
|
|
}
|
|
LPDIRECT3DDEVICEI lpDevI = LIST_FIRST(&this->devices);
|
|
while (lpDevI)
|
|
{
|
|
if (lpDevI->dwFEFlags & D3DFE_REALHAL)
|
|
{
|
|
if (DDCAPS2_CANMANAGETEXTURE &
|
|
((LPDDRAWI_DIRECTDRAW_INT)this->lpDD)->lpLcl->lpGbl->ddCaps.dwCaps2)
|
|
{
|
|
lpDevI->SetRenderStateI((D3DRENDERSTATETYPE)D3DRENDERSTATE_EVICTMANAGEDTEXTURES,1);
|
|
lpDevI->FlushStates();
|
|
}
|
|
lpTextureManager->EvictTextures();
|
|
break;
|
|
}
|
|
lpDevI = LIST_NEXT(lpDevI,list);
|
|
}
|
|
return D3D_OK;
|
|
}
|
|
catch (HRESULT ret)
|
|
{
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DIRECT3D::FlushDevicesExcept"
|
|
|
|
HRESULT DIRECT3DI::FlushDevicesExcept(LPDIRECT3DDEVICEI pDev)
|
|
{
|
|
LPDIRECT3DDEVICEI lpDevI = LIST_FIRST(&this->devices);
|
|
while (lpDevI)
|
|
{
|
|
if(lpDevI != pDev)
|
|
{
|
|
HRESULT hr = lpDevI->FlushStates();
|
|
if(hr != D3D_OK)
|
|
{
|
|
DPF_ERR("Error flushing device in FlushDevicesExcept");
|
|
return hr;
|
|
}
|
|
}
|
|
lpDevI = LIST_NEXT(lpDevI,list);
|
|
}
|
|
return D3D_OK;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "FlushD3DDevices"
|
|
|
|
extern "C" HRESULT WINAPI FlushD3DDevices(LPDDRAWI_DDRAWSURFACE_LCL surf_lcl)
|
|
{
|
|
try
|
|
{
|
|
ULONGLONG qwBatch = (surf_lcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_CUBEMAP)
|
|
&& (surf_lcl->lpAttachListFrom != NULL) ?
|
|
surf_lcl->lpAttachListFrom->lpAttached->lpSurfMore->qwBatch.QuadPart :
|
|
surf_lcl->lpSurfMore->qwBatch.QuadPart;
|
|
LPDIRECT3DI lpD3D = static_cast<CDirect3DUnk*>(surf_lcl->lpSurfMore->lpDD_lcl->pD3DIUnknown)->pD3DI;
|
|
DDASSERT(lpD3D);
|
|
LPDIRECT3DDEVICEI lpDevI = LIST_FIRST(&lpD3D->devices);
|
|
while (lpDevI)
|
|
{
|
|
if(lpDevI->m_qwBatch <= qwBatch)
|
|
{
|
|
HRESULT hr = lpDevI->FlushStates();
|
|
if(hr != D3D_OK)
|
|
{
|
|
DPF_ERR("Error flushing device in FlushD3DDevices");
|
|
return hr;
|
|
}
|
|
}
|
|
lpDevI = LIST_NEXT(lpDevI,list);
|
|
}
|
|
return DD_OK;
|
|
}
|
|
catch (HRESULT ret)
|
|
{
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
extern "C" void WINAPI PaletteUpdateNotify(
|
|
LPVOID pD3DIUnknown,
|
|
DWORD dwPaletteHandle,
|
|
DWORD dwStartIndex,
|
|
DWORD dwNumberOfIndices,
|
|
LPPALETTEENTRY pFirstIndex)
|
|
{
|
|
try
|
|
{
|
|
LPDIRECT3DI lpD3D = static_cast<CDirect3DUnk*>(pD3DIUnknown)->pD3DI;
|
|
DDASSERT(lpD3D);
|
|
LPDIRECT3DDEVICEI lpDevI = LIST_FIRST(&lpD3D->devices);
|
|
while (lpDevI)
|
|
{
|
|
D3D_INFO(4,"PaletteUpdateNotify lpDevI(%x) %08lx %08lx %08lx %08lx",
|
|
lpDevI,dwPaletteHandle,dwStartIndex,dwNumberOfIndices,*(DWORD*)&pFirstIndex[10]);
|
|
if (IS_DX7HAL_DEVICE(lpDevI) &&
|
|
(lpDevI->dwFEFlags & D3DFE_REALHAL)
|
|
)
|
|
{
|
|
if(lpD3D->numDevs > 1)
|
|
lpD3D->FlushDevicesExcept(lpDevI);
|
|
static_cast<CDirect3DDevice7*>(lpDevI)->UpdatePalette(dwPaletteHandle,dwStartIndex,dwNumberOfIndices,pFirstIndex);
|
|
if(lpD3D->numDevs > 1)
|
|
lpDevI->FlushStates();
|
|
break;
|
|
}
|
|
lpDevI = LIST_NEXT(lpDevI,list);
|
|
}
|
|
}
|
|
catch (HRESULT ret)
|
|
{
|
|
D3D_ERR("PaletteUpdateNotify: FlushStates failed");
|
|
}
|
|
}
|
|
|
|
extern "C" void WINAPI PaletteAssociateNotify(
|
|
LPVOID pD3DIUnknown,
|
|
DWORD dwPaletteHandle,
|
|
DWORD dwPaletteFlags,
|
|
LPDDRAWI_DDRAWSURFACE_LCL surf_lcl )
|
|
{
|
|
try
|
|
{
|
|
LPDIRECT3DI lpD3D = static_cast<CDirect3DUnk*>(pD3DIUnknown)->pD3DI;
|
|
DDASSERT(lpD3D);
|
|
LPDIRECT3DDEVICEI lpDevI = LIST_FIRST(&lpD3D->devices);
|
|
while (lpDevI)
|
|
{
|
|
D3D_INFO(4,"PaletteAssociateNotify lpDevI(%x) %08lx %08lx",
|
|
lpDevI,dwPaletteHandle,surf_lcl->lpSurfMore->dwSurfaceHandle);
|
|
if (IS_DX7HAL_DEVICE(lpDevI) &&
|
|
(lpDevI->dwFEFlags & D3DFE_REALHAL)
|
|
)
|
|
{
|
|
if(lpD3D->numDevs > 1)
|
|
lpD3D->FlushDevicesExcept(lpDevI);
|
|
static_cast<CDirect3DDevice7*>(lpDevI)->SetPalette(dwPaletteHandle,dwPaletteFlags,surf_lcl->lpSurfMore->dwSurfaceHandle);
|
|
lpDevI->BatchTexture(surf_lcl);
|
|
if(lpD3D->numDevs > 1)
|
|
lpDevI->FlushStates();
|
|
break;
|
|
}
|
|
lpDevI = LIST_NEXT(lpDevI,list);
|
|
}
|
|
}
|
|
catch (HRESULT ret)
|
|
{
|
|
D3D_ERR("PaletteAssociateNotify: FlushStates failed");
|
|
}
|
|
}
|
|
|
|
extern "C" void WINAPI SurfaceFlipNotify(LPVOID pD3DIUnknown)
|
|
{
|
|
LPDIRECT3DI lpD3D = static_cast<CDirect3DUnk*>(pD3DIUnknown)->pD3DI;
|
|
DDASSERT(lpD3D);
|
|
LPDIRECT3DDEVICEI lpDevI = LIST_FIRST(&lpD3D->devices);
|
|
D3D_INFO(4,"SurfaceFlipNotify");
|
|
while (lpDevI)
|
|
{
|
|
if (IS_DX7HAL_DEVICE(lpDevI))
|
|
{
|
|
try
|
|
{
|
|
CDirect3DDevice7* lpDevI7 = static_cast<CDirect3DDevice7*>(lpDevI);
|
|
#ifndef WIN95
|
|
if(lpDevI->hSurfaceTarget != ((LPDDRAWI_DDRAWSURFACE_INT)lpDevI->lpDDSTarget)->lpLcl->hDDSurface)
|
|
{
|
|
lpDevI7->SetRenderTargetINoFlush(lpDevI->lpDDSTarget,lpDevI->lpDDSZBuffer);
|
|
lpDevI->hSurfaceTarget=((LPDDRAWI_DDRAWSURFACE_INT)lpDevI->lpDDSTarget)->lpLcl->hDDSurface;
|
|
}
|
|
#else
|
|
if(lpDevI->hSurfaceTarget != ((LPDDRAWI_DDRAWSURFACE_INT)lpDevI->lpDDSTarget)->lpLcl->lpSurfMore->dwSurfaceHandle)
|
|
{
|
|
lpDevI7->SetRenderTargetINoFlush(lpDevI->lpDDSTarget,lpDevI->lpDDSZBuffer);
|
|
lpDevI->hSurfaceTarget=((LPDDRAWI_DDRAWSURFACE_INT)lpDevI->lpDDSTarget)->lpLcl->lpSurfMore->dwSurfaceHandle;
|
|
}
|
|
#endif
|
|
}
|
|
catch (HRESULT ret)
|
|
{
|
|
D3D_ERR("SetRenderTarget Failed on SurfaceFlipNotify!");
|
|
}
|
|
}
|
|
lpDevI = LIST_NEXT(lpDevI,list);
|
|
}
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "D3DTextureUpdate"
|
|
|
|
extern "C" void WINAPI D3DTextureUpdate(IUnknown FAR * pD3DIUnknown)
|
|
{
|
|
LPDIRECT3DI lpD3D = static_cast<CDirect3DUnk*>(pD3DIUnknown)->pD3DI;
|
|
DDASSERT(lpD3D);
|
|
LPDIRECT3DDEVICEI lpDevI = LIST_FIRST(&lpD3D->devices);
|
|
while (lpDevI)
|
|
{
|
|
lpDevI->dwFEFlags |= D3DFE_NEED_TEXTURE_UPDATE;
|
|
lpDevI = LIST_NEXT(lpDevI,list);
|
|
}
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "D3DTextureUpdate"
|
|
|
|
extern "C" void WINAPI D3DBreakVBLock(LPVOID lpVB)
|
|
{
|
|
DDASSERT(lpVB);
|
|
CDirect3DVertexBuffer* lpVBI = static_cast<CDirect3DVertexBuffer*>(lpVB);
|
|
lpVBI->BreakLock();
|
|
}
|