Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1049 lines
33 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
HRESULT D3DAPI DIRECT3DI::Initialize(REFCLSID riid)
{
return DDERR_ALREADYINITIALIZED;
}
//---------------------------------------------------------------------
// 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_IDirect3DNewRGBDevice)) {
return TRUE;
} else {
return FALSE;
}
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "Direct3DCreate"
DIRECT3DI::DIRECT3DI(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)) {
lpDD=NULL; //signal failure
D3D_ERR( "QueryInterface for IDDraw failed" );
return;
}
memcpy(&DDInt_DD1,lpDD,sizeof(DDInt_DD1));
lpDD->Release();
lpDD=(LPDIRECTDRAW)&DDInt_DD1;
ret = ((LPDIRECTDRAW)pDDrawInt)->QueryInterface(IID_IDirectDraw4, (LPVOID*)&lpDD4);
if(FAILED(ret))
{
lpDD4=NULL; //signal failure
D3D_WARN(1,"QueryInterface for IDDraw4 failed" );
}
else
{
memcpy(&DDInt_DD4,lpDD4,sizeof(DDInt_DD4));
lpDD4->Release();
lpDD4=(LPDIRECTDRAW4)&DDInt_DD4;
D3D_INFO(4,"QueryInterface for IDDraw4 succeeded" );
}
numDevs =
numViewports =
numLights =
numMaterials = 0;
mD3DUnk.pD3DI = this;
mD3DUnk.refCnt = 1;
LIST_INITIALIZE(&devices);
LIST_INITIALIZE(&viewports);
LIST_INITIALIZE(&lights);
LIST_INITIALIZE(&materials);
v_next = 1;
lpFreeList=NULL; /* nothing is allocated initially */
lpBufferList=NULL;
lpTextureManager=new TextureCacheManager(this);
/*
* 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);
}
}
extern "C" HRESULT WINAPI Direct3DCreate(LPCRITICAL_SECTION lpDDCSect,
LPUNKNOWN* lplpDirect3D,
IUnknown* pUnkOuter)
{
LPDIRECT3DI pd3d;
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(pUnkOuter, (LPDDRAWI_DIRECTDRAW_INT)pUnkOuter))))
{
return (DDERR_OUTOFMEMORY);
}
if(pd3d->lpDD==NULL) { //QI failed
delete pd3d;
return E_NOINTERFACE;
}
/*
* 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);
}
#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 RampDevice =
{
&IID_IDirect3DRampDevice, "Ramp Emulation",
"Microsoft Direct3D Mono(Ramp) Software Emulation"
};
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 MMXDevice =
{
&IID_IDirect3DMMXDevice, "MMX Emulation",
"Microsoft Direct3D MMX Software Emulation"
};
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 *AllDevices[] =
{
&RampDevice, &RGBDevice, &HALDevice, &MMXDevice, &RefDevice, &NullDevice, NULL
};
HRESULT
DIRECT3DI::EnumDevices(LPD3DENUMDEVICESCALLBACK lpEnumCallback,
LPVOID lpContext, DWORD dwSize, DWORD dwVer)
{
HRESULT err, userRet;
HKEY hKey;
LONG result;
int i;
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
// Release in the destructor
/*
* validate parms
*/
TRY
{
if (!VALIDEX_CODE_PTR((FARPROC)lpEnumCallback)) {
D3D_ERR( "Invalid callback pointer" );
return DDERR_INVALIDPARAMS;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
D3D_ERR( "Exception encountered validating parameters" );
return DDERR_INVALIDPARAMS;
}
BOOL bSoftwareOnly = FALSE;
DWORD dwEnumReference = 0;
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))
{
dwEnumReference = dwData;
}
if (dwVer >= 3)
{
// Enumerate MMX Rasterizer separately for DX6?
dwDataSize = sizeof(dwData);
result = RegQueryValueEx(hKey, "EnumSeparateMMX", NULL,
&dwType, (BYTE *)&dwData, &dwDataSize);
if (result == ERROR_SUCCESS &&
dwType == REG_DWORD &&
dwDataSize == sizeof(dwData))
{
bEnumSeparateMMX = (BOOL)dwData;
}
}
else
{
// Enumerate MMX Rasterizer separately for DX5
// MMX is not enumerated for DX3 and older later
bEnumSeparateMMX = TRUE;
}
// 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;
D3DDEVICEDESC HWDesc;
D3DDEVICEDESC HELDesc;
LPDDRAWI_DIRECTDRAW_GBL lpDDGbl;
IHalProvider *pHalProv;
HINSTANCE hDll;
if ( (dwVer < 2 || !isMMXprocessor()) &&
IsEqualIID(riid, IID_IDirect3DMMXDevice ) )
{
// Not Device2, not on MMX machine, or DisableMMX is set.
// Don't enumerate the MMX device.
continue;
}
if ( !bEnumSeparateMMX &&
IsEqualIID(riid, IID_IDirect3DMMXDevice ) )
{
// Not enumerating MMX separate from RGB.
continue;
}
if ( IsEqualIID(riid, IID_IDirect3DRefDevice) &&
!(dwEnumReference == 1) && // enumerate for all devices if value == 1
!( (dwVer >= 3) && (dwEnumReference == 2) ) ) // enumerate for Device3+ if value == 2
{
// Not enumerating the reference.
continue;
}
if (!bEnumNullDevice &&
IsEqualIID(riid, IID_IDirect3DNullDevice))
{
// Not enumerating the Null device.
continue;
}
#ifndef _X86_
if (IsEqualIID(riid, IID_IDirect3DRampDevice))
{
// Not enumerating ramp for non-x86 (alpha) platforms.
continue;
}
#endif
if((dwVer>=3) && IsEqualIID(riid, IID_IDirect3DRampDevice)) {
// Ramp not available in Device3. No more old-style texture handles.
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;
// 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;
}
HWDesc.dwSize = dwSize;
HELDesc.dwSize = dwSize;
userRet = (*lpEnumCallback)((GUID *) lpDevices[i]->pGuid, drvDesc, drvName,
&HWDesc, &HELDesc, lpContext);
}
return D3D_OK;
}
HRESULT D3DAPI CDirect3D::EnumDevices(LPD3DENUMDEVICESCALLBACK lpEnumCallback,
LPVOID lpContext)
{
return EnumDevices(lpEnumCallback, lpContext, D3DDEVICEDESCSIZE_V1, 1);
}
HRESULT D3DAPI CDirect3D2::EnumDevices(LPD3DENUMDEVICESCALLBACK lpEnumCallback,
LPVOID lpContext)
{
return EnumDevices(lpEnumCallback, lpContext, D3DDEVICEDESCSIZE_V2, 2);
}
HRESULT D3DAPI CDirect3D3::EnumDevices(LPD3DENUMDEVICESCALLBACK lpEnumCallback,
LPVOID lpContext)
{
return EnumDevices(lpEnumCallback, lpContext, D3DDEVICEDESCSIZE, 3);
}
#define MATCH(cap) ((matchCaps->cap & primCaps->cap) == matchCaps->cap)
static BOOL MatchCaps(DWORD dwFlags,
LPD3DPRIMCAPS matchCaps,
LPD3DPRIMCAPS primCaps)
{
if (dwFlags & D3DFDS_MISCCAPS) {
if (!MATCH(dwMiscCaps))
return FALSE;
}
if (dwFlags & D3DFDS_RASTERCAPS) {
if (!MATCH(dwRasterCaps))
return FALSE;
}
if (dwFlags & D3DFDS_ZCMPCAPS) {
if (!MATCH(dwZCmpCaps))
return FALSE;
}
if (dwFlags & D3DFDS_ALPHACMPCAPS) {
if (!MATCH(dwAlphaCmpCaps))
return FALSE;
}
if (dwFlags & D3DFDS_SRCBLENDCAPS) {
if (!MATCH(dwSrcBlendCaps))
return FALSE;
}
if (dwFlags & D3DFDS_DSTBLENDCAPS) {
if (!MATCH(dwDestBlendCaps))
return FALSE;
}
if (dwFlags & D3DFDS_SHADECAPS) {
if (!MATCH(dwShadeCaps))
return FALSE;
}
if (dwFlags & D3DFDS_TEXTURECAPS) {
if (!MATCH(dwTextureCaps))
return FALSE;
}
if (dwFlags & D3DFDS_TEXTUREFILTERCAPS) {
if (!MATCH(dwTextureFilterCaps))
return FALSE;
}
if (dwFlags & D3DFDS_TEXTUREBLENDCAPS) {
if (!MATCH(dwTextureBlendCaps))
return FALSE;
}
if (dwFlags & D3DFDS_TEXTUREADDRESSCAPS) {
if (!MATCH(dwTextureAddressCaps))
return FALSE;
}
return TRUE;
}
#undef MATCH
typedef struct _enumArgs {
D3DFINDDEVICESEARCH search;
int foundHardware;
int foundSoftware;
D3DFINDDEVICERESULT result;
} enumArgs;
HRESULT WINAPI enumFunc(LPGUID lpGuid,
LPSTR lpDeviceDescription,
LPSTR lpDeviceName,
LPD3DDEVICEDESC lpHWDesc,
LPD3DDEVICEDESC lpHELDesc,
LPVOID lpContext)
{
enumArgs* lpArgs = (enumArgs*)lpContext;
BOOL bHardware = (lpHWDesc->dcmColorModel != 0);
if (lpArgs->search.dwFlags & D3DFDS_GUID) {
if (!IsEqualGUID(lpArgs->search.guid, *lpGuid))
return D3DENUMRET_OK;
}
if (lpArgs->search.dwFlags & D3DFDS_HARDWARE) {
if (lpArgs->search.bHardware != bHardware)
return D3DENUMRET_OK;
}
if (lpArgs->search.dwFlags & D3DFDS_COLORMODEL) {
if ((lpHWDesc->dcmColorModel & lpArgs->search.dcmColorModel) == 0
&& (lpHELDesc->dcmColorModel & lpArgs->search.dcmColorModel) == 0) {
return D3DENUMRET_OK;
}
}
if (lpArgs->search.dwFlags & D3DFDS_TRIANGLES) {
if (!MatchCaps(lpArgs->search.dwFlags,
&lpArgs->search.dpcPrimCaps, &lpHWDesc->dpcTriCaps)
&& !MatchCaps(lpArgs->search.dwFlags,
&lpArgs->search.dpcPrimCaps, &lpHELDesc->dpcTriCaps))
return D3DENUMRET_OK;
}
if (lpArgs->search.dwFlags & D3DFDS_LINES) {
if (!MatchCaps(lpArgs->search.dwFlags,
&lpArgs->search.dpcPrimCaps, &lpHWDesc->dpcLineCaps)
&& !MatchCaps(lpArgs->search.dwFlags,
&lpArgs->search.dpcPrimCaps, &lpHELDesc->dpcLineCaps))
return D3DENUMRET_OK;
}
if (lpArgs->foundHardware && !bHardware)
return D3DENUMRET_OK;
if (bHardware)
lpArgs->foundHardware = TRUE;
else
lpArgs->foundSoftware = TRUE;
lpArgs->result.guid = *lpGuid;
lpArgs->result.ddHwDesc = *lpHWDesc;
lpArgs->result.ddSwDesc = *lpHELDesc;
return D3DENUMRET_OK;
}
#undef DPF_MODNAME
#define DPF_MODNAME "Direct3D::FindDevice"
HRESULT D3DAPI CDirect3D::FindDevice(LPD3DFINDDEVICESEARCH lpSearch, LPD3DFINDDEVICERESULT lpResult)
{
return FindDevice(lpSearch,lpResult,1);
}
HRESULT D3DAPI CDirect3D2::FindDevice(LPD3DFINDDEVICESEARCH lpSearch, LPD3DFINDDEVICERESULT lpResult)
{
return FindDevice(lpSearch,lpResult,2);
}
HRESULT D3DAPI CDirect3D3::FindDevice(LPD3DFINDDEVICESEARCH lpSearch, LPD3DFINDDEVICERESULT lpResult)
{
return FindDevice(lpSearch,lpResult,3);
}
HRESULT
DIRECT3DI::FindDevice(LPD3DFINDDEVICESEARCH lpSearch,
LPD3DFINDDEVICERESULT lpResult, DWORD dwVer)
{
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
// Release in the destructor
TRY
{
if (!VALID_D3DFINDDEVICESEARCH_PTR(lpSearch)) {
D3D_ERR( "Invalid search pointer" );
return DDERR_INVALIDPARAMS;
}
if (!VALID_D3DFINDDEVICERESULT_PTR(lpResult)) {
D3D_ERR( "Invalid result pointer" );
return DDERR_INVALIDPARAMS;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
D3D_ERR( "Exception encountered validating parameters" );
return DDERR_INVALIDPARAMS;
}
enumArgs args;
memset(&args, 0, sizeof args);
args.result.dwSize = sizeof(args.result);
args.search = *lpSearch;
switch(dwVer) {
case 1: CDirect3D::EnumDevices(enumFunc, &args); break;
case 2: CDirect3D2::EnumDevices(enumFunc, &args); break;
case 3: CDirect3D3::EnumDevices(enumFunc, &args); break;
}
if (args.foundHardware || args.foundSoftware) {
DWORD dwSize = lpResult->dwSize;
if (dwSize == sizeof( D3DFINDDEVICERESULT ) )
{
// The app is using DX6
D3D_INFO(4, "New D3DFINDDEVICERESULT size");
memcpy(lpResult, &args.result, lpResult->dwSize);
}
else
{
// The app is pre DX6
DWORD dwSize = lpResult->dwSize;
DWORD dDescSize = (dwSize - (sizeof(DWORD) + sizeof(GUID)))/2;
D3D_INFO(4, "Old D3DFINDDEVICERESULT size");
// Copy the header
memcpy(lpResult, &args.result, sizeof(DWORD)+sizeof(GUID));
//restore the size
lpResult->dwSize = dwSize;
// Copy and convert the embedded D3DDEVICEDESC's
// DDescSize = (lpResult->dwSize - (sizeof(DWORD) + sizeof(GUID)))/2
// This calculation assumes that the structure of
// LPD3DFINDDEVICERESULT is the same as in DX6, DX5, if it is changed
// This computation needs to be updated
memcpy((LPVOID) (&lpResult->ddHwDesc),
&args.result.ddHwDesc,
dDescSize);
memcpy((LPVOID) ((ULONG_PTR)&lpResult->ddHwDesc + dDescSize),
&args.result.ddSwDesc,
dDescSize);
}
return D3D_OK;
}
else
{
return DDERR_NOTFOUND;
}
}
#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;
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
ret = D3D_OK;
/*
* validate parms
*/
TRY
{
if (!VALID_DIRECT3D3_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;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
D3D_ERR( "Exception encountered validating parameters" );
return DDERR_INVALIDPARAMS;
}
if(IsEqualIID(riid, IID_IDirect3DHALDevice)) {
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);
}
#undef DPF_MODNAME
#define DPF_MODNAME "Direct3D::EnumOptTextureFormats"
HRESULT D3DAPI DIRECT3DI::EnumOptTextureFormats(REFCLSID riid, LPD3DENUMOPTTEXTUREFORMATSCALLBACK lpEnumCallback, LPVOID lpContext)
{
HRESULT ret, userRet;
LPDDSURFACEDESC lpDescs;
LPDDSURFACEDESC2 lpRetDescs;
LPDDOPTSURFACEDESC lpRetOptDescs;
LPD3DHAL_GLOBALDRIVERDATA lpD3DHALGlobalDriverData;
DWORD num_descs;
DWORD i;
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
ret = D3D_OK;
//
// Validation
//
TRY
{
if (!VALID_DIRECT3D3_PTR(this)) {
D3D_ERR( "Invalid Direct3D 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;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
D3D_ERR( "Exception encountered validating parameters" );
return DDERR_INVALIDPARAMS;
}
if(IsEqualIID(riid, IID_IDirect3DHALDevice)) {
lpD3DHALGlobalDriverData=((LPDDRAWI_DIRECTDRAW_INT)this->lpDD)->lpLcl->lpGbl->lpD3DGlobalDriverData;
num_descs = lpD3DHALGlobalDriverData->dwNumTextureFormats;
lpDescs = lpD3DHALGlobalDriverData->lpTextureFormats;
} else {
num_descs = GetSwTextureFormats(riid,&lpDescs,3/*enum for Device3*/);
}
if (!num_descs)
{
D3D_ERR("no texture formats supported");
return (D3DERR_TEXTURE_NO_SUPPORT);
}
//
// Make a local copy of these formats
//
if (D3DMalloc((void**)&lpRetDescs, sizeof(DDSURFACEDESC2) * num_descs)
!= D3D_OK)
{
D3D_ERR("Out of memory allocating space for return descriptions");
return (DDERR_OUTOFMEMORY);
}
for (i=0; i<num_descs; i++)
{
// We can copy only the subset of the data
memcpy(&lpRetDescs[i], &lpDescs[i], sizeof(DDSURFACEDESC));
}
userRet = D3DENUMRET_OK;
//
// First return the unoptimized formats......
//
for (i = 0; i < num_descs && userRet == D3DENUMRET_OK; i++)
{
userRet = (*lpEnumCallback)(&lpRetDescs[i], NULL, lpContext);
}
//
// ......Now return the formats capable of being optimized
//
for (i = 0; i < num_descs && userRet == D3DENUMRET_OK; i++)
{
userRet = (*lpEnumCallback)(&lpRetDescs[i], NULL, lpContext);
}
D3DFree(lpRetDescs);
return (D3D_OK);
}
#undef DPF_MODNAME
#define DPF_MODNAME "DIRECT3D::EvictManagedTextures"
HRESULT D3DAPI
DIRECT3DI::EvictManagedTextures()
{
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
if (!VALID_DIRECT3D_PTR(this))
{
D3D_ERR( "Invalid Direct3D3 pointer" );
return DDERR_INVALIDOBJECT;
}
lpTextureManager->EvictTextures();
return D3D_OK;
}
#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;
}
extern "C" void WINAPI PaletteUpdateNotify(
LPVOID pD3DIUnknown,
DWORD dwPaletteHandle,
DWORD dwStartIndex,
DWORD dwNumberOfIndices,
LPPALETTEENTRY pFirstIndex)
{
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))
{
if(lpD3D->numDevs > 1)
lpD3D->FlushDevicesExcept(lpDevI);
static_cast<CDirect3DDeviceIDP2*>(lpDevI)->UpdatePalette(dwPaletteHandle,dwStartIndex,dwNumberOfIndices,pFirstIndex);
if(lpD3D->numDevs > 1)
lpDevI->FlushStates();
break;
}
lpDevI = LIST_NEXT(lpDevI,list);
}
}
extern "C" void WINAPI PaletteAssociateNotify(
LPVOID pD3DIUnknown,
DWORD dwPaletteHandle,
DWORD dwPaletteFlags,
DWORD dwSurfaceHandle )
{
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, dwSurfaceHandle);
if (IS_DX7HAL_DEVICE(lpDevI))
{
if(lpD3D->numDevs > 1)
lpD3D->FlushDevicesExcept(lpDevI);
static_cast<CDirect3DDeviceIDP2*>(lpDevI)->SetPalette(dwPaletteHandle,dwPaletteFlags,dwSurfaceHandle);
if(lpD3D->numDevs > 1)
lpDevI->FlushStates();
break;
}
lpDevI = LIST_NEXT(lpDevI,list);
}
}
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))
{
#ifndef WIN95
if(lpDevI->hSurfaceTarget != ((LPDDRAWI_DDRAWSURFACE_INT)lpDevI->lpDDSTarget)->lpLcl->hDDSurface)
{
static_cast<CDirect3DDeviceIDP2*>(lpDevI)->SetRenderTargetI(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)
{
static_cast<CDirect3DDeviceIDP2*>(lpDevI)->SetRenderTargetI(lpDevI->lpDDSTarget,lpDevI->lpDDSZBuffer);
lpDevI->hSurfaceTarget=((LPDDRAWI_DDRAWSURFACE_INT)lpDevI->lpDDSTarget)->lpLcl->lpSurfMore->dwSurfaceHandle;
}
#endif
}
lpDevI = LIST_NEXT(lpDevI,list);
}
}
#undef DPF_MODNAME
#define DPF_MODNAME "FlushD3DDevices"
extern "C" HRESULT WINAPI FlushD3DDevices(LPDDRAWI_DDRAWSURFACE_LCL surf_lcl)
{
LPD3DBUCKET list = reinterpret_cast<LPD3DBUCKET>(surf_lcl->lpSurfMore->lpD3DDevIList);
while(list)
{
LPD3DBUCKET temp = list->next;
reinterpret_cast<LPDIRECT3DDEVICEI>(list->lpD3DDevI)->FlushStates();
list = temp;
}
return DD_OK;
}
#undef DPF_MODNAME
#define DPF_MODNAME "FlushD3DDevices2"
extern "C" HRESULT WINAPI FlushD3DDevices2(LPDDRAWI_DDRAWSURFACE_LCL surf_lcl)
{
LPD3DBUCKET list = reinterpret_cast<LPD3DBUCKET>(surf_lcl->lpSurfMore->lpD3DDevIList);
while(list)
{
LPD3DBUCKET temp = list->next;
if (list->lplpDDSZBuffer)
*list->lplpDDSZBuffer = 0; // detached
reinterpret_cast<LPDIRECT3DDEVICEI>(list->lpD3DDevI)->FlushStates();
list = temp;
}
return DD_OK;
}