|
|
/*==========================================================================;
* * 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; }
|