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.
 
 
 
 
 
 

3241 lines
109 KiB

/*==========================================================================;
*
* Copyright (C) 1998 Microsoft Corporation. All Rights Reserved.
*
* File: d3ddev.cpp
* Content: Direct3D device implementation
*@@BEGIN_MSINTERNAL
*
* $Id: device.c,v 1.26 1995/12/04 11:29:47 sjl Exp $
*
* History:
* Date By Reason
* ==== == ======
* 05/11/95 stevela Initial rev with this header.
* 11/11/95 stevela Light code changed.
* 23/11/95 colinmc Modifications to support aggregatable interfaces
* 07/12/95 stevela Merged Colin's changes.
* 10/12/95 stevela Removed AGGREGATE_D3D.
* 18/12/95 stevela Added GetMatrix, GetState.
* 15/07/96 andyhird Initialise Render state on devices
* 13/08/96 andyhird Check surface and device are compatible
* 18/08/96 colinmc Fixed z-buffer leak
*@@END_MSINTERNAL
*
***************************************************************************/
#include "pch.cpp"
#pragma hdrstop
/*
* Create an api for the Direct3DDevice object
*/
extern "C" {
#define this _this
#include "ddrawpr.h"
#undef this
}
#include "commdrv.hpp"
#include "drawprim.hpp"
//#ifdef DEBUG_PIPELINE
#include "testprov.h"
//#endif //DEBUG_PIPELINE
// 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 ) )
#undef DPF_MODNAME
#define DPF_MODNAME "Direct3DDevice"
extern BOOL isMMXprocessor(void);
extern HRESULT GenGetPickRecords(LPDIRECT3DDEVICEI, D3DI_PICKDATA *);
extern BOOL IsValidD3DDeviceGuid(REFCLSID riid);
BOOL D3DI_isHALValid(LPD3DHAL_CALLBACKS halTable)
{
if(halTable==NULL) {
D3D_WARN(0, "HAL callbacks is NULL. HAL will not be enumerated.");
return FALSE;
}
if (halTable->dwSize != D3DHAL_SIZE_V1) {
D3D_WARN(0, "HAL callbacks invalid - size = %d, wanted %d. HAL will not be enumerated.",
halTable->dwSize, D3DHAL_SIZE_V1);
return FALSE;
}
if (halTable->dwReserved ||
halTable->dwReserved0 ||
halTable->dwReserved1 ||
halTable->dwReserved2 ||
halTable->dwReserved3 ||
halTable->dwReserved4 ||
halTable->dwReserved5 ||
halTable->dwReserved6 ||
halTable->dwReserved7 ||
halTable->dwReserved8 ||
halTable->dwReserved9 ||
halTable->lpReserved10 ||
halTable->lpReserved11 ||
halTable->lpReserved12 ||
halTable->lpReserved13 ||
halTable->lpReserved14 ||
halTable->lpReserved15 ||
halTable->lpReserved16 ||
halTable->lpReserved17 ||
halTable->lpReserved18 ||
halTable->lpReserved19 ||
halTable->lpReserved20 ||
halTable->lpReserved21) {
D3D_WARN(0, "HAL callbacks invalid - has non-zero reserved fields, HAL will not be enumerated.");
return FALSE;
}
return TRUE;
}
HRESULT DIRECT3DDEVICEI::stateInitialize(BOOL bZEnable)
{
D3DDEVICEDESC hwDesc, helDesc;
D3DLINEPATTERN defLPat;
HRESULT ret;
float tmpval;
BOOL ckeyenable = FALSE;
/* Get the device caps for MONOENABLE */
memset(&hwDesc, 0, sizeof(D3DDEVICEDESC));
hwDesc.dwSize = sizeof(D3DDEVICEDESC);
memset(&helDesc, 0, sizeof(D3DDEVICEDESC));
helDesc.dwSize = sizeof(D3DDEVICEDESC);
ret = GetCapsI(&hwDesc, &helDesc);
if (FAILED(ret)) {
D3D_ERR("stateInitialise: GetCaps failed");
return(ret);
}
/* If we run on (HAL OR RefRast) AND this is a DX3 app
then we need to initialize colorkey to TRUE so that the old HW driver (except s3 virge) behavior
is exhibited. */
if ( (this->dwVersion < 2) &&
( (IS_HW_DEVICE(this)) || (IsEqualIID(this->guid, IID_IDirect3DRefDevice)) ) )
{
ckeyenable = TRUE;
}
// Obviate SetRenderState filtering 'redundant' render state settings
// since this is the init step.
memset( this->rstates, 0xff, sizeof(DWORD)*D3DHAL_MAX_RSTATES );
this->rstates[D3DRENDERSTATE_PLANEMASK] = 0;
this->rstates[D3DRENDERSTATE_STENCILMASK] = 0;
this->rstates[D3DRENDERSTATE_STENCILWRITEMASK] = 0;
this->rstates[D3DRENDERSTATE_PLANEMASK] = 0;
SetRenderState( D3DRENDERSTATE_TEXTUREHANDLE, (DWORD)NULL);
SetRenderState( D3DRENDERSTATE_ANTIALIAS, FALSE);
SetRenderState( D3DRENDERSTATE_TEXTUREADDRESS, D3DTADDRESS_WRAP);
if (this->dwVersion <= 2)
{
SetRenderState( D3DRENDERSTATE_TEXTUREPERSPECTIVE, FALSE);
SetRenderState( D3DRENDERSTATE_SPECULARENABLE, TRUE);
}
else
{
// perspective enabled by default for Device3 and later
SetRenderState( D3DRENDERSTATE_TEXTUREPERSPECTIVE, TRUE);
// specular disabled by default for Device3 and later
SetRenderState( D3DRENDERSTATE_SPECULARENABLE, FALSE);
}
SetRenderState( D3DRENDERSTATE_WRAPU, FALSE);
SetRenderState( D3DRENDERSTATE_WRAPV, FALSE);
SetRenderState( D3DRENDERSTATE_ZENABLE, bZEnable);
SetRenderState( D3DRENDERSTATE_FILLMODE, D3DFILL_SOLID);
SetRenderState( D3DRENDERSTATE_SHADEMODE, D3DSHADE_GOURAUD);
defLPat.wRepeatFactor = 0;
defLPat.wLinePattern = 0;
SetRenderState( D3DRENDERSTATE_LINEPATTERN, *((LPDWORD)&defLPat)); /* 10 */
/*
((LPD3DSTATE)lpPointer)->drstRenderStateType =
(D3DRENDERSTATETYPE)D3DRENDERSTATE_LINEPATTERN;
memcpy(&(((LPD3DSTATE)lpPointer)->dwArg[0]), &defLPat, sizeof(DWORD));
lpPointer = (void *)(((LPD3DSTATE)lpPointer) + 1);*/
SetRenderState( D3DRENDERSTATE_ROP2, R2_COPYPEN);
SetRenderState( D3DRENDERSTATE_PLANEMASK, (DWORD)~0);
SetRenderState( D3DRENDERSTATE_ZWRITEENABLE, TRUE);
SetRenderState( D3DRENDERSTATE_ALPHATESTENABLE, FALSE);
SetRenderState( D3DRENDERSTATE_LASTPIXEL, TRUE);
SetRenderState( D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE);
SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_ZERO);
SetRenderState( D3DRENDERSTATE_CULLMODE, D3DCULL_CCW); /* 21 */
SetRenderState( D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
SetRenderState( D3DRENDERSTATE_ALPHAREF, 0);
SetRenderState( D3DRENDERSTATE_ALPHAFUNC, D3DCMP_ALWAYS);
SetRenderState( D3DRENDERSTATE_DITHERENABLE, FALSE);
SetRenderState( D3DRENDERSTATE_BLENDENABLE, FALSE);
SetRenderState( D3DRENDERSTATE_FOGENABLE, FALSE);
SetRenderState( D3DRENDERSTATE_ZVISIBLE, FALSE);
SetRenderState( D3DRENDERSTATE_SUBPIXEL, FALSE); /* 30 */
SetRenderState( D3DRENDERSTATE_SUBPIXELX, FALSE);
SetRenderState( D3DRENDERSTATE_STIPPLEDALPHA, FALSE);
SetRenderState( D3DRENDERSTATE_FOGCOLOR, 0);
SetRenderState( D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_NONE);
/* Initialise these - although they may not need doing */
tmpval = 0.0f;
SetRenderState( D3DRENDERSTATE_FOGTABLESTART, *((DWORD *)&tmpval));
tmpval = 1.0f;
SetRenderState( D3DRENDERSTATE_FOGTABLEEND, *((DWORD *)&tmpval));
tmpval = 1.0f;
SetRenderState( D3DRENDERSTATE_FOGTABLEDENSITY, *((DWORD *)&tmpval));
SetRenderState( D3DRENDERSTATE_STIPPLEENABLE, FALSE);
SetRenderState( D3DRENDERSTATE_EDGEANTIALIAS, FALSE);
SetRenderState( D3DRENDERSTATE_COLORKEYENABLE, ckeyenable);
SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
SetRenderState( D3DRENDERSTATE_BORDERCOLOR, 0);
SetRenderState( D3DRENDERSTATE_TEXTUREADDRESSU, D3DTADDRESS_WRAP);
SetRenderState( D3DRENDERSTATE_TEXTUREADDRESSV, D3DTADDRESS_WRAP);
SetRenderState( D3DRENDERSTATE_MIPMAPLODBIAS, 0);
SetRenderState( D3DRENDERSTATE_ZBIAS, 0);
SetRenderState( D3DRENDERSTATE_RANGEFOGENABLE, FALSE);
SetRenderState( D3DRENDERSTATE_ANISOTROPY, 1);
/* Again - all these probably don't need doing */
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN00, 0);
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN01, 0); /* 40 */
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN02, 0);
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN03, 0);
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN04, 0);
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN05, 0);
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN06, 0);
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN07, 0);
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN08, 0);
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN09, 0);
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN10, 0);
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN11, 0); /* 50 */
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN12, 0);
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN13, 0);
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN14, 0);
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN15, 0);
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN16, 0);
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN17, 0);
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN18, 0);
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN19, 0);
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN20, 0);
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN21, 0); /* 60 */
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN22, 0);
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN23, 0);
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN24, 0);
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN25, 0);
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN26, 0);
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN27, 0);
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN28, 0);
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN29, 0);
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN30, 0);
SetRenderState( D3DRENDERSTATE_STIPPLEPATTERN31, 0); /* 70 */
// init stencil states to something reasonable
// stencil enable is OFF by default since stenciling rasterizers will be
// faster with it disabled, even if stencil states are benign
SetRenderState( D3DRENDERSTATE_STENCILENABLE, FALSE);
SetRenderState( D3DRENDERSTATE_STENCILFAIL, D3DSTENCILOP_KEEP);
SetRenderState( D3DRENDERSTATE_STENCILZFAIL, D3DSTENCILOP_KEEP);
SetRenderState( D3DRENDERSTATE_STENCILPASS, D3DSTENCILOP_KEEP);
SetRenderState( D3DRENDERSTATE_STENCILFUNC, D3DCMP_ALWAYS);
SetRenderState( D3DRENDERSTATE_STENCILREF, 0);
SetRenderState( D3DRENDERSTATE_STENCILMASK, 0xFFFFFFFF);
SetRenderState( D3DRENDERSTATE_STENCILWRITEMASK,0xFFFFFFFF);
// don't forget about texturefactor (like we did in DX6.0...)
SetRenderState( D3DRENDERSTATE_TEXTUREFACTOR, 0xFFFFFFFF);
/* Check to see if the driver can do RGB - if not set MONOENABLE to
true otherwise false (ie. RGB) by default */
if (hwDesc.dwFlags & D3DDD_COLORMODEL) {
if ((hwDesc.dcmColorModel & D3DCOLOR_RGB)) {
D3D_INFO(3, "hw and RGB. MONOENABLE = FALSE");
SetRenderState( D3DRENDERSTATE_MONOENABLE, FALSE);
} else {
D3D_INFO(3, "hw and !RGB. MONOENABLE = TRUE");
SetRenderState( D3DRENDERSTATE_MONOENABLE, TRUE);
}
} else if (helDesc.dwFlags & D3DDD_COLORMODEL) {
if ((helDesc.dcmColorModel & D3DCOLOR_RGB)) {
D3D_INFO(3, "hel and RGB. MONOENABLE = FALSE");
SetRenderState( D3DRENDERSTATE_MONOENABLE, FALSE);
} else {
D3D_INFO(3, "hel and !RGB. MONOENABLE = TRUE");
SetRenderState( D3DRENDERSTATE_MONOENABLE, TRUE);
}
} else {
/* Hmm, something bad has happened if we get here! */
D3D_ERR("stateInitialise: neither hw or hel caps set");
return(DDERR_GENERIC);
}
for (unsigned i = 0; i < 8; i++)
{
SetRenderState( (D3DRENDERSTATETYPE)
(D3DRENDERSTATE_WRAPBIAS + i), FALSE );
}
for (i = 0; i < D3DHAL_TSS_MAXSTAGES; i++)
{
lpD3DMappedTexI[i] = NULL;
lpD3DMappedBlock[i] = NULL;
}
SetLightState( D3DLIGHTSTATE_COLORVERTEX, TRUE);
// Obviate SetTextureStageState/Settexture filtering 'redundant' render state
// settings since this is the init step.
memset( this->tsstates, 0xff, sizeof(DWORD)*D3DHAL_TSS_MAXSTAGES*D3DHAL_TSS_STATESPERSTAGE );
for (i = 0; i < D3DHAL_TSS_MAXSTAGES; i++)
{
SetTexture(i, NULL);
if(i == 0)
SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_MODULATE);
else
SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_DISABLE);
SetTextureStageState(i, D3DTSS_COLORARG1, D3DTA_TEXTURE);
SetTextureStageState(i, D3DTSS_COLORARG2, D3DTA_CURRENT);
if(i == 0)
SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
else
SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
SetTextureStageState(i, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
SetTextureStageState(i, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
SetTextureStageState(i, D3DTSS_BUMPENVMAT00, 0);
SetTextureStageState(i, D3DTSS_BUMPENVMAT01, 0);
SetTextureStageState(i, D3DTSS_BUMPENVMAT10, 0);
SetTextureStageState(i, D3DTSS_BUMPENVMAT11, 0);
SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, 0);
SetTextureStageState(i, D3DTSS_ADDRESS, D3DTADDRESS_WRAP);
SetTextureStageState(i, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
SetTextureStageState(i, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
SetTextureStageState(i, D3DTSS_BORDERCOLOR, 0x00000000);
SetTextureStageState(i, D3DTSS_MAGFILTER, D3DTFG_POINT);
SetTextureStageState(i, D3DTSS_MINFILTER, D3DTFN_POINT);
SetTextureStageState(i, D3DTSS_MIPFILTER, D3DTFP_NONE);
SetTextureStageState(i, D3DTSS_MIPMAPLODBIAS, 0);
SetTextureStageState(i, D3DTSS_MAXMIPLEVEL, 0);
SetTextureStageState(i, D3DTSS_MAXANISOTROPY, 1);
SetTextureStageState(i, D3DTSS_BUMPENVLSCALE, 0);
SetTextureStageState(i, D3DTSS_BUMPENVLOFFSET, 0);
}
// need to set legacy blend and filtering states after per-stage initialization
// to properly set defaults in device
SetRenderState( D3DRENDERSTATE_TEXTUREMAG, D3DFILTER_NEAREST);
SetRenderState( D3DRENDERSTATE_TEXTUREMIN, D3DFILTER_NEAREST);
SetRenderState( D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE);
// Reset request bit as legacy renderstates have been already initialized
// and no mapping is needed
this->dwFEFlags &= ~D3DFE_MAP_TSS_TO_RS;
return(D3D_OK);
}
DWORD BitDepthToDDBD(int bpp)
{
switch(bpp)
{
case 1:
return DDBD_1;
case 2:
return DDBD_2;
case 4:
return DDBD_4;
case 8:
return DDBD_8;
case 16:
return DDBD_16;
case 24:
return DDBD_24;
case 32:
return DDBD_32;
default:
D3D_ERR("Invalid bit depth");
return 0;
}
}
HRESULT DIRECT3DDEVICEI::checkDeviceSurface(LPDIRECTDRAWSURFACE lpDDS, LPDIRECTDRAWSURFACE lpZbuffer, LPGUID pGuid)
{
D3DDEVICEDESC hwDesc, helDesc;
DDPIXELFORMAT surfPF;
DDSCAPS surfCaps;
HRESULT ret;
DWORD bpp;
/* Get caps bits - check whether device and surface are:
- video/system memory and depth compatible */
if (FAILED(ret = lpDDS->GetCaps(&surfCaps))) {
D3D_ERR("Failed to get render-target surface caps");
return(ret);
}
memset(&surfPF, 0, sizeof(DDPIXELFORMAT));
surfPF.dwSize = sizeof(DDPIXELFORMAT);
if (FAILED(ret = lpDDS->GetPixelFormat(&surfPF))) {
D3D_ERR("Failed to get render-target surface pixel format");
return(ret);
}
memset(&hwDesc, 0, sizeof(D3DDEVICEDESC));
hwDesc.dwSize = sizeof(D3DDEVICEDESC);
memset(&helDesc, 0, sizeof(D3DDEVICEDESC));
helDesc.dwSize = sizeof(D3DDEVICEDESC);
// ATTENTION - Why doesn't this just look at the DEVICEI fields?
ret = GetCapsI(&hwDesc, &helDesc);
if (FAILED(ret)) {
D3D_ERR("GetCaps failed");
return(ret);
}
if (hwDesc.dwFlags) {
/* I'm taking this as evidence that its running on hardware - therefore
the surface should be in video memory */
D3D_INFO(3, "Hardware device being used");
if (!(surfCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) {
D3D_ERR("Render-target surface not in video memory for hw device");
return(D3DERR_SURFACENOTINVIDMEM);
}
}
/* A surface can only have one bit depth - whereas a device can support
multiple bit depths */
if (surfPF.dwFlags & DDPF_RGB) {
D3D_INFO(3, "Render-target surface is RGB");
bpp = BitDepthToDDBD(surfPF.dwRGBBitCount);
if (!bpp) {
D3D_ERR("Bogus render-target surface pixel depth");
return(DDERR_INVALIDPIXELFORMAT);
}
if((surfPF.dwRGBBitCount<16) && (IsEqualIID(*pGuid, IID_IDirect3DRefDevice) || IsEqualIID(*pGuid, IID_IDirect3DNullDevice))) {
// this is actually subsumed by the following test, but whatever
D3D_ERR("Reference rasterizer and null device dont support render targets with bitdepth < 16");
return(DDERR_INVALIDPIXELFORMAT);
}
if (!(bpp & helDesc.dwDeviceRenderBitDepth) &&
!(bpp & hwDesc.dwDeviceRenderBitDepth)) {
D3D_ERR("Render-target surface bitdepth is not supported by HEL or HW for this device");
return(DDERR_INVALIDPIXELFORMAT);
}
}
if(lpZbuffer==NULL)
return D3D_OK;
memset(&surfPF, 0, sizeof(DDPIXELFORMAT));
surfPF.dwSize = sizeof(DDPIXELFORMAT);
if (FAILED(ret = lpZbuffer->GetPixelFormat(&surfPF))) {
D3D_ERR("Failed to get zbuffer pixel format");
return(ret);
}
if (FAILED(ret = lpZbuffer->GetCaps(&surfCaps))) {
D3D_ERR("Failed to get Zbuffer caps");
return(ret);
}
if (hwDesc.dwFlags) {
if (!(surfCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) {
D3D_ERR("Zbuffer not in video memory for hw device");
return(D3DERR_ZBUFF_NEEDS_VIDEOMEMORY);
}
D3D_INFO(3, "Hw device, zbuffer in video memory");
} else if (helDesc.dwFlags) {
if (!(surfCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)) {
D3D_ERR("Zbuffer not in system memory for HEL device");
return(D3DERR_ZBUFF_NEEDS_SYSTEMMEMORY);
}
D3D_INFO(3, "Hel device, zbuffer in system memory");
// have to hack in a check to make sure ramp isn't used with stencil zbuffer
// cant do this validation until device creation time (instead of at zbuffer creation in
// ddhel.c) because rgb vs. ramp isn't known until now
if(IsEqualIID(*pGuid, IID_IDirect3DRampDevice)) {
if(surfPF.dwFlags & DDPF_STENCILBUFFER) {
D3D_ERR("Z-Buffer with stencil is invalid with RAMP software rasterizer");
return DDERR_INVALIDPARAMS;
}
}
}
if (surfPF.dwFlags & DDPF_ZBUFFER) {
bpp = BitDepthToDDBD(surfPF.dwZBufferBitDepth);
if (!bpp) {
D3D_ERR("Bogus Zbuffer surface pixel depth");
return(DDERR_INVALIDPIXELFORMAT);
}
}
return(D3D_OK);
}
/*
* Initialisation - class part and device part
*/
/*
* Generic class part initialisation
*/
HRESULT InitDeviceI(LPDIRECT3DDEVICEI lpDevI, LPDIRECT3DI lpD3DI)
{
LPDDRAWI_DIRECTDRAW_GBL lpDDI;
HRESULT error;
lpDDI = ((LPDDRAWI_DIRECTDRAW_INT)lpD3DI->lpDD)->lpLcl->lpGbl;
//
// Retrieve HAL information from provider.
//
error = lpDevI->pHalProv->GetCaps(lpDDI,
&lpDevI->d3dHWDevDesc,
&lpDevI->d3dHELDevDesc,
lpDevI->dwVersion);
if (error != S_OK)
{
return (error);
}
D3DHALPROVIDER_INTERFACEDATA HalProviderIData;
memset(&HalProviderIData,0,sizeof(HalProviderIData));
HalProviderIData.dwSize = sizeof(HalProviderIData);
if ((error = lpDevI->pHalProv->GetInterface(lpDDI,
&HalProviderIData,
lpDevI->dwVersion)) != S_OK)
{
return error;
}
// interface data for <=DX5 HAL
lpDevI->lpD3DHALGlobalDriverData = HalProviderIData.pGlobalData;
lpDevI->lpD3DExtendedCaps = HalProviderIData.pExtCaps;
lpDevI->lpD3DHALCallbacks = HalProviderIData.pCallbacks;
lpDevI->lpD3DHALCallbacks2 = HalProviderIData.pCallbacks2;
// interface data for DX6 HAL
lpDevI->lpD3DHALCallbacks3 = HalProviderIData.pCallbacks3;
lpDevI->pfnRampService = HalProviderIData.pfnRampService;
lpDevI->pfnRastService = HalProviderIData.pfnRastService;
lpDevI->dwHintFlags = 0;
// Zero out 8 bpp render target caps for real hardware.
if (lpDevI->d3dHWDevDesc.dwFlags != 0)
{
lpDevI->lpD3DHALGlobalDriverData->hwCaps.dwDeviceRenderBitDepth &=
(~DDBD_8);
}
if (!D3DI_isHALValid(lpDevI->lpD3DHALCallbacks))
{
return D3DERR_INITFAILED;
}
if (lpDevI->lpD3DExtendedCaps && lpDevI->lpD3DExtendedCaps->dwFVFCaps)
{
lpDevI->dwMaxTextureIndices =
lpDevI->lpD3DExtendedCaps->dwFVFCaps & D3DFVFCAPS_TEXCOORDCOUNTMASK;
lpDevI->dwMaxTextureBlendStages =
lpDevI->lpD3DExtendedCaps->wMaxTextureBlendStages;
lpDevI->dwDeviceFlags |= D3DDEV_FVF;
if (lpDevI->lpD3DExtendedCaps->dwFVFCaps & D3DFVFCAPS_DONOTSTRIPELEMENTS)
lpDevI->dwDeviceFlags |= D3DDEV_DONOTSTRIPELEMENTS;
DWORD value;
if ((lpDevI->dwDebugFlags & D3DDEBUG_DISABLEDP ||
lpDevI->dwDebugFlags & D3DDEBUG_DISABLEDP2 ||
(GetD3DRegValue(REG_DWORD, "DisableFVF", &value, 4) &&
value != 0)) &&
FVF_DRIVERSUPPORTED(lpDevI))
{
lpDevI->dwMaxTextureIndices = 1;
lpDevI->dwMaxTextureBlendStages = 1;
lpDevI->dwDeviceFlags &= ~D3DDEV_FVF;
lpDevI->dwDebugFlags |= D3DDEBUG_DISABLEFVF;
}
if ((GetD3DRegValue(REG_DWORD, "DisableStripFVF", &value, 4) &&
value != 0))
{
lpDevI->dwDeviceFlags |= D3DDEV_DONOTSTRIPELEMENTS;
}
}
else
{
lpDevI->dwMaxTextureIndices = 1;
lpDevI->dwMaxTextureBlendStages = 1;
}
lpDevI->pfnDrawPrim = &DIRECT3DDEVICEI::DrawPrim;
lpDevI->pfnDrawIndexedPrim = &DIRECT3DDEVICEI::DrawIndexPrim;
#if DBG
lpDevI->dwCaller=0;
memset(lpDevI->dwPrimitiveType,0,sizeof(lpDevI->dwPrimitiveType));
memset(lpDevI->dwVertexType1,0,sizeof(lpDevI->dwVertexType1));
memset(lpDevI->dwVertexType2,0,sizeof(lpDevI->dwVertexType2));
#endif
return D3D_OK;
}
HRESULT D3DMallocBucket(LPDIRECT3DI lpD3DI, LPD3DBUCKET *lplpBucket)
{
if (lpD3DI->lpFreeList == NULL ){
lpD3DI->lpTextureManager->cleanup(); //free unused nodes it may have
if (lpD3DI->lpFreeList == NULL )
{
LPD3DBUCKET lpBufferList;
LPVOID lpBuffer;
int i;
*lplpBucket=NULL;
if (D3DMalloc(&lpBuffer, D3DBUCKETBUFFERSIZE*sizeof(D3DBUCKET)) != D3D_OK)
return DDERR_OUTOFMEMORY;
D3D_INFO(9, "D3DMallocBucket %d Bytes allocated for %d free Buckets",
D3DBUCKETBUFFERSIZE*sizeof(D3DBUCKET),D3DBUCKETBUFFERSIZE-1);
lpBufferList=(LPD3DBUCKET)lpBuffer;
for (i=0;i<D3DBUCKETBUFFERSIZE-2;i++)
lpBufferList[i].next=&lpBufferList[i+1];
lpBufferList[D3DBUCKETBUFFERSIZE-2].next=NULL;
lpD3DI->lpFreeList=(LPD3DBUCKET)lpBuffer; //new free list
lpBufferList[D3DBUCKETBUFFERSIZE-1].next=lpD3DI->lpBufferList;//add to lpBufferList
lpBufferList[D3DBUCKETBUFFERSIZE-1].lpBuffer=lpBuffer;
lpD3DI->lpBufferList=&lpBufferList[D3DBUCKETBUFFERSIZE-1];
}
}
*lplpBucket=lpD3DI->lpFreeList;
lpD3DI->lpFreeList=lpD3DI->lpFreeList->next;
return D3D_OK;
}
void D3DFreeBucket(LPDIRECT3DI lpD3DI, LPD3DBUCKET lpBucket)
{
lpBucket->next=lpD3DI->lpFreeList;
lpD3DI->lpFreeList=lpBucket;
}
/*
* Generic device part destroy
*/
void DIRECT3DDEVICEI::DestroyDevice()
{
LPDIRECT3DVIEWPORTI lpViewI;
LPDIRECTDRAWSURFACE lpDDS=NULL, lpDDSZ=NULL;
LPDIRECTDRAWSURFACE4 lpDDS_DDS4=NULL;
LPDIRECTDRAWPALETTE lpDDPal=NULL;
BOOL bIsDX3Device;
/* Clear flags that could prohibit cleanup */
this->dwHintFlags &= ~(D3DDEVBOOL_HINTFLAGS_INBEGIN_ALL | D3DDEVBOOL_HINTFLAGS_INSCENE);
/*
* Remove all viewports attached to this device.
*/
while ((lpViewI = CIRCLE_QUEUE_FIRST(&this->viewports)) &&
(lpViewI != (LPDIRECT3DVIEWPORTI)&this->viewports)) {
DeleteViewport((LPDIRECT3DVIEWPORT3)lpViewI);
}
/*
* free up all textures created by this object - this also frees up Textures
* We need to do this backwards because we cannot have a texture bound to
* stage i + 1 when there is a texture bound to stage i.
*/
for (int i = D3DHAL_TSS_MAXSTAGES - 1; i >= 0; --i)
{
if (lpD3DMappedTexI[i])
{
lpD3DMappedTexI[i]->Release();
lpD3DMappedTexI[i] = NULL;
lpD3DMappedBlock[i] = NULL;
}
}
// The following code can result in D3DHAL_TextureDestroy() being called.
// This BATCHES NEW INSTRUCTIONS in the instruction stream. So we must
// make sure that at this point, the device is still able to accept
// instructions.
while (LIST_FIRST(&this->texBlocks)) {
LPD3DI_TEXTUREBLOCK tBlock = LIST_FIRST(&this->texBlocks);
D3DI_RemoveTextureHandle(tBlock);
// Remove from device
LIST_DELETE(tBlock, devList);
// Remove from texture
LIST_DELETE(tBlock, list);
D3DFree(tBlock);
}
/*
* free up all execute buffers created by this object
*/
while (LIST_FIRST(&this->buffers)) {
LPDIRECT3DEXECUTEBUFFERI lpBufI =
LIST_FIRST(&this->buffers);
lpBufI->Release();
}
/*
* All materials associated with this device must be disassocited
*/
while (LIST_FIRST(&this->matBlocks)) {
LPD3DI_MATERIALBLOCK mBlock =
LIST_FIRST(&this->matBlocks);
D3DI_RemoveMaterialBlock(mBlock);
}
// In DX3, d3d device is aggregated and doesnt keep references to
// rendertarget surfaces, so they shouldnt be "released"
bIsDX3Device=(this->lpDDSTarget == (LPDIRECTDRAWSURFACE)(this->lpOwningIUnknown));
if(!bIsDX3Device)
{
// Hold pointers into ddraw object for release after driver is destroyed
lpDDSZ = this->lpDDSZBuffer;
lpDDPal = this->lpDDPalTarget;
if (this->dwVersion == 2)
lpDDS = this->lpDDSTarget;
else
lpDDS_DDS4 = this->lpDDSTarget_DDS4;
}
//Unhook so that DDRAW surfaces won't try to flush the dead device
if (this->lpDDSTarget)
UnHookD3DDeviceFromSurface(this,((LPDDRAWI_DDRAWSURFACE_INT) this->lpDDSTarget)->lpLcl);
if (this->lpDDSZBuffer)
UnHookD3DDeviceFromSurface(this,((LPDDRAWI_DDRAWSURFACE_INT) this->lpDDSZBuffer)->lpLcl);
if (pGeometryFuncs != &GeometryFuncsGuaranteed)
delete pGeometryFuncs;
D3DFE_Destroy(this);
if (this->lpDirect3DI)
unhookDeviceFromD3D();
if (this->wTriIndex)
D3DFree(this->wTriIndex);
// Free the rstates that was allocated
if(!(IS_HW_DEVICE(this) && IS_DP2HAL_DEVICE(this)))
{
delete rstates;
}
if (this->lpwDPBufferAlloced)
D3DFree(this->lpwDPBufferAlloced);
if (this->lpvVertexBatch)
D3DFree(this->lpvVertexBatch);
if (this->lpIndexBatch)
D3DFree(this->lpIndexBatch);
if (this->lpHWCounts)
D3DFree(this->lpHWCounts);
if (this->lpHWTris)
D3DFree(this->lpHWTris);
DeleteCriticalSection(&this->BeginEndCSect);
if (this->pHalProv != NULL)
{
this->pHalProv->Release();
}
if (this->hDllProv != NULL)
{
FreeLibrary(this->hDllProv);
}
/* Now that the class has been destroyed, we should be able to release
any DDraw object that might need to be released */
if(!bIsDX3Device) {
if (lpDDS)
lpDDS->Release();
if (lpDDSZ)
lpDDSZ->Release();
if (lpDDPal)
lpDDPal->Release();
if (lpDDS_DDS4)
lpDDS_DDS4->Release();
}
}
HRESULT DIRECT3DDEVICEI::hookDeviceToD3D(LPDIRECT3DI lpD3DI)
{
LIST_INSERT_ROOT(&lpD3DI->devices, this, list);
this->lpDirect3DI = lpD3DI;
lpD3DI->numDevs++;
return (D3D_OK);
}
HRESULT DIRECT3DDEVICEI::unhookDeviceFromD3D()
{
LIST_DELETE(this, list);
this->lpDirect3DI->numDevs--;
this->lpDirect3DI = NULL;
return (D3D_OK);
}
HRESULT D3DAPI DIRECT3DDEVICEI::Initialize(LPDIRECT3D lpD3D, LPGUID lpGuid, LPD3DDEVICEDESC lpD3Ddd)
{
return DDERR_ALREADYINITIALIZED;
}
HRESULT HookD3DDeviceToSurface( LPDIRECT3DDEVICEI pd3ddev,
LPDDRAWI_DDRAWSURFACE_LCL lpLcl)
{
LPD3DBUCKET lpD3DDevIList;
LPDDRAWI_DDRAWSURFACE_MORE this_more;
// we only batch with DRAWPRIMITIVE aware HAL, so don't bother otherwise
if (!lpLcl) return DDERR_ALREADYINITIALIZED;
this_more = lpLcl->lpSurfMore;
for(lpD3DDevIList=(LPD3DBUCKET)this_more->lpD3DDevIList;
lpD3DDevIList;lpD3DDevIList=lpD3DDevIList->next) {
if ((LPDIRECT3DDEVICEI)lpD3DDevIList->lpD3DDevI==pd3ddev)
return DDERR_ALREADYINITIALIZED; // this device is already hooked to the surface
}
if (D3DMallocBucket(pd3ddev->lpDirect3DI,&lpD3DDevIList) != D3D_OK) {
D3D_ERR("HookD3DDeviceToSurface: Out of memory");
return DDERR_OUTOFMEMORY;
}
D3D_INFO(8,"adding lpd3ddev=%08lx to surface %08lx",pd3ddev,lpLcl);
//Link a node to the DDRAW surface
lpD3DDevIList->lpD3DDevI=(LPVOID)pd3ddev;
lpD3DDevIList->next=(LPD3DBUCKET)this_more->lpD3DDevIList;
this_more->lpD3DDevIList=lpD3DDevIList;
if (DDSCAPS_ZBUFFER & lpLcl->ddsCaps.dwCaps)
{
if (pd3ddev->dwVersion==1)
{
lpD3DDevIList->lplpDDSZBuffer=(LPDIRECTDRAWSURFACE*)&pd3ddev->lpDDSZBuffer_DDS4;
}
else
{
lpD3DDevIList->lplpDDSZBuffer=NULL;
}
}
return D3D_OK;
}
void UnHookD3DDeviceFromSurface( LPDIRECT3DDEVICEI pd3ddev,
LPDDRAWI_DDRAWSURFACE_LCL lpLcl)
{
LPD3DBUCKET last,current,temp;
LPDDRAWI_DDRAWSURFACE_MORE this_more;
// we only batch with DRAWPRIMITIVE aware HAL, so don't bother otherwise
if (!lpLcl) return;
this_more = lpLcl->lpSurfMore;
last=NULL;
current=(LPD3DBUCKET)this_more->lpD3DDevIList;
while(current){
if ((LPDIRECT3DDEVICEI)current->lpD3DDevI==pd3ddev){
temp=current;
current=current->next;
if (last)
last->next=current;
else
this_more->lpD3DDevIList=current;
D3DFreeBucket(pd3ddev->lpDirect3DI,temp);
D3D_INFO(8,"removed lpd3ddev=%08lx from surface %08lx",pd3ddev,lpLcl);
return; // end of search as this is only one pd3ddev in the list
}
else{
last=current;
current=current->next;
}
}
return;
}
HRESULT D3DFlushStates(LPDIRECT3DDEVICEI lpDevI)
{
return lpDevI->FlushStates();
}
/*
* Create a device.
*
* NOTE: Radical modifications to support the aggregatable device
* interface (so devices can be queried off DirectDraw surfaces):
*
* 1) This call is no longer a member of the Direct3D device interface.
* It is now an API function exported from the Direct3D DLL. Its
* a hidden API function - only DirectDraw will ever invoke it.
*
* 2) This call is, in effect, the class factory for Direct3DDevice
* objects. This function will be invoked to create the aggregated
* device object hanging off the DirectDraw surface.
*
* NOTE: So the Direct3DDevice knows which DirectDraw surface is
* its rendering target this function is passed an interface pointer
* for that DirectDraw surface. I suspect this blows a nice big
* hole in the COM model as the DirectDraw surface is also the
* owning interface of the device and I don't think aggregated
* objects should know about thier owning interfaces. However, to
* make this thing work this is what we have to do.
*
* EXTRA BIG NOTE: Because of the above don't take a reference to
* the DirectDraw surface passed in. If you do you will get a circular
* reference and the bloody thing will never die. When aggregated
* the device interface's lifetime is entirely defined by the
* lifetime of its owning interface (the DirectDraw surface) so the
* DirectDraw surface can never go away before the texture.
*
* EXTRA EXTRA BIG NOTE: No device description is passed in any more.
* The only things that can get passed in are things that DirectDraw
* knows about (which does not include stuff like dither and color
* model). Therefore, any input parameters must come in via a
* different IID for the device. The data returned by the device
* description must now be retrieved by another call.
*/
#undef DPF_MODNAME
#define DPF_MODNAME "Direct3DCreateDevice"
HRESULT WINAPI Direct3DCreateDevice(REFCLSID riid,
LPUNKNOWN lpDirect3D,
LPDIRECTDRAWSURFACE lpDDSTarget,
LPUNKNOWN* lplpD3DDevice,
IUnknown* pUnkOuter,
DWORD dwVersion)
{
LPDIRECT3DI lpD3DI;
LPDIRECT3DDEVICEI pd3ddev;
D3DCOLORMODEL cm = D3DCOLOR_MONO;
HRESULT ret = D3D_OK;
HKEY hKey = (HKEY) NULL;
bool bDisableDP = false;
bool bDisableST = false;
bool bDisableDP2 = false;
#if _D3D_FORCEDOUBLE
bool bForceDouble = true;
#endif //_D3D_FORCEDOUBLE
/* No need to validate params as they are passed to us by DirectDraw */
/* CreateDevice member of IDirect3D2 will cause this function to be called
* from within Direct3D. The parameters from the application level must be
* validated. Need a way to validate the surface pointer from outside DDraw.
*/
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
TRY
{
if( ! VALID_PTR_PTR( lplpD3DDevice) )
{
D3D_ERR( "Invalid ptr to device pointer in Direct3DCreateDevice" );
return DDERR_INVALIDPARAMS;
}
if(!IsValidD3DDeviceGuid(riid)) {
D3D_ERR( "Unrecognized Device GUID!");
return DDERR_INVALIDPARAMS;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
D3D_ERR( "Exception encountered validating parameters in Direct3DCreateDevice" );
return DDERR_INVALIDPARAMS;
}
*lplpD3DDevice = NULL;
// Might be safer to use dynamic_cast<> if RTTI is enabled
lpD3DI = reinterpret_cast<CDirect3DUnk*>(lpDirect3D)->pD3DI;
#ifndef _X86_
if(IsEqualIID(riid, IID_IDirect3DRampDevice)) {
// quietly fail if trying to create a RampDevice on a non-x86 platform
return DDERR_INVALIDPARAMS;
}
#endif
if((dwVersion>=3) && IsEqualIID(riid, IID_IDirect3DRampDevice)) {
// Ramp not available in Device3. No more old-style texture handles.
D3D_ERR( "RAMP Device is incompatible with IDirect3DDevice3 and so cannot be created from IDirect3D3");
return DDERR_INVALIDPARAMS;
}
if (IsEqualIID(riid, IID_IDirect3DMMXDevice) && !isMMXprocessor()) {
D3D_ERR("Can't create MMX Device on non-MMX machine");
return DDERR_INVALIDPARAMS;
}
if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, RESPATH_D3D, &hKey) )
{
DWORD dwType;
DWORD dwValue;
DWORD dwSize = 4;
#ifdef WIN95
if ( ERROR_SUCCESS == RegQueryValueEx( hKey, "DisableDP", NULL, &dwType, (LPBYTE) &dwValue, &dwSize) &&
dwType == REG_DWORD &&
dwValue != 0)
{
bDisableDP = true;
bDisableDP2 = true;
}
#endif //WIN95
if ( ERROR_SUCCESS == RegQueryValueEx( hKey, "DisableST", NULL, &dwType, (LPBYTE) &dwValue, &dwSize) &&
dwType == REG_DWORD &&
dwValue != 0)
{
bDisableST = true;
}
#ifdef WIN95
if ( ERROR_SUCCESS == RegQueryValueEx( hKey, "DisableDP2", NULL, &dwType, (LPBYTE) &dwValue, &dwSize) &&
dwType == REG_DWORD &&
dwValue != 0)
{
bDisableDP2 = true;
}
#endif //WIN95
D3D_INFO(2,"EnableDP2: %d",!bDisableDP2);
#if _D3D_FORCEDOUBLE
if ( ERROR_SUCCESS == RegQueryValueEx( hKey, "ForceDouble", NULL, &dwType, (LPBYTE) &dwValue, &dwSize) &&
dwType == REG_DWORD &&
dwValue == 0)
{
bForceDouble = false;
}
D3D_INFO(2,"ForceDouble: %d",bForceDouble);
#endif //_D3D_FORCEDOUBLE
RegCloseKey( hKey );
}
LPD3DHAL_GLOBALDRIVERDATA lpD3DHALGlobalDriverData=((LPDDRAWI_DIRECTDRAW_INT)lpD3DI->lpDD)->lpLcl->lpGbl->lpD3DGlobalDriverData;
#ifdef WIN95
/* Test for presence of CB HAL */
if (IsEqualIID(riid, IID_IDirect3DHALDevice) )
{
/* Test for presence of DP2 DDI */
if ((lpD3DHALGlobalDriverData)
&& (lpD3DHALGlobalDriverData->hwCaps.dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX)
)
{
pd3ddev = static_cast<LPDIRECT3DDEVICEI>(new CDirect3DDeviceIDP2());
if (pd3ddev) pd3ddev->deviceType = D3DDEVTYPE_DX7HAL;
}
else if ((!bDisableDP2) &&
((LPDDRAWI_DIRECTDRAW_INT)lpD3DI->lpDD)->lpLcl->lpGbl->lpD3DHALCallbacks3 &&
((LPD3DHAL_CALLBACKS3)((LPDDRAWI_DIRECTDRAW_INT)lpD3DI->lpDD)->lpLcl->lpGbl->lpD3DHALCallbacks3)->DrawPrimitives2)
{
pd3ddev = static_cast<LPDIRECT3DDEVICEI>(new CDirect3DDeviceIDP2());
}
/* Test for presence DP HAL */
else if ((!bDisableDP) &&
((LPDDRAWI_DIRECTDRAW_INT)lpD3DI->lpDD)->lpLcl->lpGbl->lpD3DHALCallbacks2 &&
((LPD3DHAL_CALLBACKS2)((LPDDRAWI_DIRECTDRAW_INT)lpD3DI->lpDD)->lpLcl->lpGbl->lpD3DHALCallbacks2)->DrawOnePrimitive)
{
pd3ddev = static_cast<LPDIRECT3DDEVICEI>(new CDirect3DDeviceIDP());
}
else
{
pd3ddev = static_cast<LPDIRECT3DDEVICEI>(new CDirect3DDeviceIHW());
}
}
else // all software rasterizers are DP-enabled
#endif // WIN95
if (!bDisableDP2)
{
if ((lpD3DHALGlobalDriverData)
&& (IsEqualIID(riid, IID_IDirect3DHALDevice) )
&& (lpD3DHALGlobalDriverData->hwCaps.dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX)
)
{
pd3ddev = static_cast<LPDIRECT3DDEVICEI>(new CDirect3DDeviceIDP2());
if (pd3ddev) pd3ddev->deviceType = D3DDEVTYPE_DX7HAL;
}
else
{
pd3ddev = static_cast<LPDIRECT3DDEVICEI>(new CDirect3DDeviceIDP2());
}
}
else if (!bDisableDP)
pd3ddev = static_cast<LPDIRECT3DDEVICEI>(new CDirect3DDeviceIDP());
else
pd3ddev = static_cast<LPDIRECT3DDEVICEI>(new CDirect3DDeviceIHW());
if (!pd3ddev) {
D3D_ERR("Failed to allocate space for D3DDevice. Quitting.");
return (DDERR_OUTOFMEMORY);
}
// If we have lost managed textures, we need to cleanup
// since CheckSurfaces() would fail which would cause
// FlushStates() to fail, which would result in the
// current batch being abandoned (along with any device initialization)
if(lpD3DI->lpTextureManager->CheckIfLost())
{
D3D_INFO(2, "Found lost managed textures. Evicting...");
lpD3DI->lpTextureManager->EvictTextures();
}
if (bDisableDP)
pd3ddev->dwDebugFlags |= D3DDEBUG_DISABLEDP;
if (bDisableDP2)
pd3ddev->dwDebugFlags |= D3DDEBUG_DISABLEDP2;
ret = pd3ddev->Init(riid, lpD3DI, lpDDSTarget, pUnkOuter, lplpD3DDevice, dwVersion);
if (ret!=D3D_OK)
{
delete pd3ddev;
D3D_ERR("Failed to intilialize D3DDevice");
return ret;
}
if (bDisableST)
pd3ddev->dwHintFlags |= D3DDEVBOOL_HINTFLAGS_MULTITHREADED;
#ifdef _X86_
if (((LPDDRAWI_DIRECTDRAW_INT)lpD3DI->lpDD)->lpLcl->dwLocalFlags & DDRAWILCL_FPUSETUP &&
IS_DP2HAL_DEVICE(pd3ddev))
{
WORD wSave, wTemp;
__asm {
fstcw wSave
mov ax, wSave
and ax, not 300h ;; single mode
or ax, 3fh ;; disable all exceptions
and ax, not 0C00h ;; round to nearest mode
mov wTemp, ax
fldcw wTemp
}
}
#if _D3D_FORCEDOUBLE
if (bForceDouble && (pd3ddev->deviceType <= D3DDEVTYPE_DPHAL))
{
pd3ddev->dwDebugFlags |= D3DDEBUG_FORCEDOUBLE;
}
else
{
pd3ddev->dwDebugFlags &= ~D3DDEBUG_FORCEDOUBLE;
}
#endif //_D3D_FORCEDOUBLE
#endif
return (ret);
}
HRESULT DIRECT3DDEVICEI::Init(REFCLSID riid, LPDIRECT3DI lpD3DI, LPDIRECTDRAWSURFACE lpDDS,
IUnknown* pUnkOuter, LPUNKNOWN* lplpD3DDevice, DWORD dwVersion)
{
DDSCAPS ddscaps;
DDSURFACEDESC ddsd;
HRESULT ret, ddrval;
LPDIRECTDRAWSURFACE lpDDSZ=NULL;
LPDIRECTDRAWPALETTE lpDDPal=NULL;
LPGUID pGuid;
BOOL bIsDX3Device;
DDSCAPS surfCaps;
this->dwFVFLastIn = this->dwFVFLastOut = 0;
this->mDevUnk.refCnt = 1;
this->dwVersion = dwVersion;
this->mDevUnk.pDevI = this;
pD3DMappedTexI = (LPVOID*)(this->lpD3DMappedTexI);
pfnFlushStates = D3DFlushStates;
this->dwFEFlags |= D3DFE_TSSINDEX_DIRTY;
/* Single threaded or Multi threaded app ? */
if (((LPDDRAWI_DIRECTDRAW_INT)lpD3DI->lpDD)->lpLcl->dwLocalFlags & DDRAWILCL_MULTITHREADED)
this->dwHintFlags |= D3DDEVBOOL_HINTFLAGS_MULTITHREADED;
/*
* Are we really being aggregated?
*/
bIsDX3Device=(pUnkOuter!=NULL);
if (bIsDX3Device)
{
/*
* 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;
DDASSERT(dwVersion==1);
}
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 = (LPUNKNOWN)&this->mDevUnk;
}
// create the begin/end critical section
InitializeCriticalSection(&this->BeginEndCSect);
/*
* Initialise textures
*/
LIST_INITIALIZE(&this->texBlocks);
/*
* Initialise buffers
*/
LIST_INITIALIZE(&this->buffers);
/*
* Initialise viewports
*/
CIRCLE_QUEUE_INITIALIZE(&this->viewports, DIRECT3DVIEWPORTI);
this->lpCurrentViewport = NULL;
this->v_id = 0;
/*
* Initialise materials
*/
LIST_INITIALIZE(&this->matBlocks);
this->lpvVertexBatch = this->lpIndexBatch = NULL;
this->dwHWNumCounts = 0;
this->dwHWOffset = 0;
this->dwHWTriIndex = 0;
this->lpTextureBatched = NULL;
this->dwVertexBase = 0;
pGeometryFuncs = &GeometryFuncsGuaranteed;
/*-----------------------------------------------------------------------------------------
* Up till now we have done the easy part of the initialization. This is the stuff that
* cannot fail. It initializes the object so that the destructor can be safely called if
* any of the further initialization does not succeed.
*---------------------------------------------------------------------------------------*/
/*
* Ensure the riid is one we understand.
*
* Query the registry.
*/
pGuid = (GUID *)&riid;
#if DBG
if (IsEqualIID(*pGuid, IID_IDirect3DRampDevice))
{
D3D_INFO(1, "======================= Ramp device selected");
}
if (IsEqualIID(*pGuid, IID_IDirect3DRGBDevice))
{
D3D_INFO(1, "======================= RGB device selected");
}
if (IsEqualIID(*pGuid, IID_IDirect3DMMXDevice))
{
D3D_INFO(1, "======================= RGB(MMX) device selected");
}
if (IsEqualIID(*pGuid, IID_IDirect3DHALDevice))
{
D3D_INFO(1, "======================= HAL device selected");
}
if (IsEqualIID(*pGuid, IID_IDirect3DRefDevice))
{
D3D_INFO(1, "======================= Reference Rasterizer device selected");
}
if (IsEqualIID(*pGuid, IID_IDirect3DNullDevice))
{
D3D_INFO(1, "======================= Null device selected");
}
if (IsEqualIID(*pGuid, IID_IDirect3DNewRGBDevice))
{
D3D_INFO(1, "======================= New RGB device selected");
}
D3D_INFO(1,"with HAL deviceType=%d",deviceType);
#endif
// set up flag to use MMX when requested RGB
BOOL bUseMMXAsRGBDevice = FALSE;
if (IsEqualIID(*pGuid, IID_IDirect3DRGBDevice) && isMMXprocessor())
{
bUseMMXAsRGBDevice = TRUE;
// read reg key to override use of MMX for RGB
HKEY hKey = (HKEY) NULL;
if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, RESPATH, &hKey) )
{
DWORD dwType;
DWORD dwValue;
DWORD dwSize = 4;
if ( ERROR_SUCCESS == RegQueryValueEx( hKey, "UseMMXForRGB", NULL, &dwType, (LPBYTE) &dwValue, &dwSize) &&
dwType == REG_DWORD &&
dwValue == 0)
{
bUseMMXAsRGBDevice = FALSE;
}
RegCloseKey( hKey );
}
if (bUseMMXAsRGBDevice)
{
D3D_INFO(1, " using MMX in RGB device");
}
}
BOOL bIsRamp = FALSE;
if (IsEqualIID(*pGuid, IID_IDirect3DRampDevice))
{
bIsRamp = TRUE;
}
if (IsEqualIID(*pGuid, IID_IDirect3DRGBDevice) &&
isMMXprocessor())
{
// Check for whether this app is one of the Intel ones
// that want the MMX rasterizer
LPDDRAWI_DIRECTDRAW_LCL lpDDLcl = ((LPDDRAWI_DIRECTDRAW_INT)lpD3DI->lpDD)->lpLcl;
// 0x4 corresponds to the "Intel app that wants MMX"
// flag defined in ddrawpr.h
if ( lpDDLcl->dwAppHackFlags & 0x4 )
{
pGuid = (GUID *)&IID_IDirect3DMMXDevice;
}
}
/*
* Check if the 3D cap is set on the surface.
*/
memset(&ddsd, 0, sizeof ddsd);
ddsd.dwSize = sizeof ddsd;
ddrval = lpDDS->GetSurfaceDesc(&ddsd);
if (ddrval != DD_OK) {
D3D_ERR("Failed to get surface description of device's surface.");
return (ddrval);
}
if (!(ddsd.ddsCaps.dwCaps & DDSCAPS_3DDEVICE)) {
D3D_ERR("**** The DDSCAPS_3DDEVICE is not set on this surface.");
D3D_ERR("**** You need to add DDSCAPS_3DDEVICE to ddsCaps.dwCaps");
D3D_ERR("**** when creating the surface.");
return (DDERR_INVALIDCAPS);
}
if (ddsd.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) {
D3D_ERR("**** DDSCAPS_ZBUFFER is set on this surface.");
D3D_ERR("**** Rendering into Z buffer surfaces is not");
D3D_ERR("**** currently supported by Direct3D.");
return (DDERR_INVALIDCAPS);
}
if (ddsd.dwWidth > 2048 || ddsd.dwHeight > 2048)
{
D3D_ERR("**** Surface too large - must be <= 2048 in width & height.");
return (DDERR_INVALIDOBJECT);
}
/* Check for palette... */
ret = lpDDS->GetPalette(&lpDDPal);
if ((ret != DD_OK) && (ret != DDERR_NOPALETTEATTACHED))
{
/*
* NOTE: Again, not an error (yet) if there is no palette attached.
* But if there is palette and we can't get at it for some reason
* - fail.
*/
D3D_ERR("Supplied DirectDraw Palette is invalid - can't create device");
return (DDERR_INVALIDPARAMS);
}
/*
* We're going to check now whether we should have got a palette.
*/
if (ret == DDERR_NOPALETTEATTACHED) {
if (ddsd.ddpfPixelFormat.dwRGBBitCount < 16) {
D3D_ERR("No palette supplied for palettized surface - can't create device");
return (DDERR_NOPALETTEATTACHED);
}
}
// For DX3, we must not keep references to Palette and ZBuffer to avoid
// circular references in the aggregation model. But for DX5+, we want
// to keep references to both to ensure they dont disappear.
if(bIsDX3Device && (lpDDPal != NULL))
lpDDPal->Release(); // release the reference GetPalette created
this->lpDDPalTarget = lpDDPal;
// Check for ZBuffer
memset(&surfCaps, 0, sizeof(DDSCAPS));
surfCaps.dwCaps = DDSCAPS_ZBUFFER;
if (FAILED(ret = lpDDS->GetAttachedSurface(&surfCaps, &lpDDSZ))) {
if (ret != DDERR_NOTFOUND) {
D3D_ERR("Failed GetAttachedSurface for ZBuffer");
goto handle_err;
}
D3D_INFO(2, "No zbuffer is attached to rendertarget surface (which is OK)");
}
if(bIsDX3Device && (lpDDSZ != NULL))
lpDDSZ->Release(); // release the reference GetAttachedSurface created
this->lpDDSZBuffer = lpDDSZ;
this->guid = *pGuid;
// Try to get a HAL provider for this driver (may need to use MMX guid if
// using MMX for RGB requested device)
ret = GetSwHalProvider(
bUseMMXAsRGBDevice ? IID_IDirect3DMMXAsRGBDevice : riid,
&this->pHalProv, &this->hDllProv);
if (ret == S_OK)
{
// Got a software provider.
}
else if (ret == E_NOINTERFACE &&
((ret = GetHwHalProvider(riid, &this->pHalProv,
&this->hDllProv,
((LPDDRAWI_DIRECTDRAW_INT)lpD3DI->lpDD)->lpLcl->lpGbl)) == S_OK))
{
// Got a hardware provider.
}
else
{
if(IsEqualIID(riid, IID_IDirect3DHALDevice)) {
D3D_ERR("Requested HAL Device non-existent or invalid");
} else {
D3D_ERR("Unable to get D3D Device provider for requested GUID");
}
goto handle_err;
}
{
// Initialize test HAL provider to drop HAL calls (sort of a Null device)
//
DWORD value = 0;
if (GetD3DRegValue(REG_DWORD, "DisableRendering", &value, sizeof(DWORD)) &&
value != 0)
{
ret = GetTestHalProvider(
riid, ((LPDDRAWI_DIRECTDRAW_INT)lpD3DI->lpDD)->lpLcl->lpGbl,
&this->pHalProv, this->pHalProv, 0);
if (ret != D3D_OK)
{
D3D_ERR("Unable to set up 'DisableRendering' mode");
goto handle_err;
}
}
}
// Initialise general DEVICEI information.
if ((ret = InitDeviceI(this, lpD3DI)) != D3D_OK)
{
D3D_ERR("Failed to initialise device");
goto handle_err;
}
// Check the surface and device to see if they're compatible
if (FAILED(ret = checkDeviceSurface(lpDDS,lpDDSZ,pGuid))) {
D3D_ERR("Device and surface aren't compatible");
goto handle_err;
}
// Create front-end support structures.
// ATTENTION - We probably want to avoid doing this if the driver
// does its own front end. Software fallbacks complicate the issue,
// though.
ret = D3DFE_Create(this, lpD3DI->lpDD, lpDDS, lpDDSZ, lpDDPal);
if (ret != D3D_OK)
{
D3D_ERR("Failed to create front-end data-structures.");
goto handle_err;
}
// Figure out place for rstates
if (IS_HW_DEVICE(this) && IS_DP2HAL_DEVICE(this))
{
// In case of HW DP2 HAL we reuse the kernel allocated
// memory for RStates since we need the driver to update
// it
rstates = (LPDWORD)lpwDPBuffer;
}
else
{
// In all other cases we simply allocate memory for rstates
rstates = new DWORD[D3DHAL_MAX_RSTATES];
}
D3DFE_PROCESSVERTICES::lpdwRStates = this->rstates;
// Check if we have a processor specific implementation available
// only use if DisablePSGP is not in registry or set to zero
DWORD value;
if (!GetD3DRegValue(REG_DWORD, "DisablePSGP", &value, sizeof(DWORD)))
{
value = 0;
}
#ifdef _X86_
extern HRESULT D3DAPI pii_FEContextCreate(DWORD dwFlags, LPD3DFE_PVFUNCS *lpLeafFuncs);
if (pfnFEContextCreate == pii_FEContextCreate)
{
// here if this is PentiumII PSGP
// regkey disable for PII PSGP - default is ENABLED
DWORD dwValue2; // disable if this is TRUE
if (!GetD3DRegValue(REG_DWORD, "DisablePIIPSGP", &dwValue2, sizeof(DWORD)))
{
dwValue2 = 0;
}
else
{
D3D_INFO(2, "DisablePIIPSGP %d",dwValue2);
}
// do disable
if ( dwValue2 )
{
pfnFEContextCreate = NULL;
}
}
#endif
if (pfnFEContextCreate && ( value == 0) && (!bIsRamp) )
{
D3D_INFO(2, "PSGP enabled for device");
// Ask the PV implementation to create a device specific "context"
LPD3DFE_PVFUNCS pOptGeoFuncs = pGeometryFuncs;
ret = pfnFEContextCreate(dwDeviceFlags, &pOptGeoFuncs);
if ((ret == D3D_OK) && pOptGeoFuncs)
{
D3D_INFO(2, "using PSGP");
pGeometryFuncs = pOptGeoFuncs;
}
}
/*
* put this device in the list of those owned by the Direct3D object
*/
ret = hookDeviceToD3D(lpD3DI);
if (ret != D3D_OK)
{
D3D_ERR("Failed to associate device with Direct3D");
goto handle_err;
}
{
if(lpD3DHALGlobalDriverData->hwCaps.dwMaxVertexCount == 0)
{
lpD3DHALGlobalDriverData->hwCaps.dwMaxVertexCount = __INIT_VERTEX_NUMBER;
}
if (TLVbuf.Grow(this, (__INIT_VERTEX_NUMBER*2)*sizeof(D3DTLVERTEX)) != DD_OK)
{
D3D_ERR( "Out of memory in DeviceCreate (TLVbuf)" );
ret = DDERR_OUTOFMEMORY;
goto handle_err;
}
if (HVbuf.Grow((__INIT_VERTEX_NUMBER*2)*sizeof(D3DFE_CLIPCODE)) != DD_OK)
{
D3D_ERR( "Out of memory in DeviceCreate (HVBuf)" );
ret = DDERR_OUTOFMEMORY;
goto handle_err;
}
ret = this->ClipperState.clipBuf.Grow
(this, MAX_CLIP_VERTICES*__MAX_VERTEX_SIZE);
if (ret != D3D_OK)
{
D3D_ERR( "Out of memory in DeviceCreate (ClipBuf)" );
ret = DDERR_OUTOFMEMORY;
goto handle_err;
}
ret = this->ClipperState.clipBufPrim.Grow
(this, MAX_CLIP_TRIANGLES*sizeof(D3DTRIANGLE));
if (ret != D3D_OK)
{
D3D_ERR( "Out of memory in DeviceCreate (ClipBufPrim)" );
ret = DDERR_OUTOFMEMORY;
goto handle_err;
}
}
/*
* IDirect3DDevice2 specific initialization
*/
if (D3DMalloc((void**)&this->wTriIndex, dwD3DTriBatchSize*4*sizeof(WORD)) != DD_OK) {
D3D_ERR( "Out of memory in DeviceCreate (wTriIndex)" );
ret = DDERR_OUTOFMEMORY;
goto handle_err;
}
if (D3DMalloc((void**)&this->lpHWCounts, dwHWBufferSize*sizeof(D3DI_HWCOUNTS)/32 ) != DD_OK)
{
D3D_ERR( "Out of memory in DeviceCreate (HWCounts)" );
ret = DDERR_OUTOFMEMORY;
goto handle_err;
}
memset(this->lpHWCounts, 0, sizeof(D3DI_HWCOUNTS) );
this->lpHWVertices = (LPD3DTLVERTEX) this->lpwDPBuffer;
if (D3DMalloc((void**)&this->lpHWTris, dwHWMaxTris*sizeof(D3DTRIANGLE) ) != DD_OK)
{
D3D_ERR( "Out of memory in DeviceCreate (HWVertices)" );
ret = DDERR_OUTOFMEMORY;
goto handle_err;
}
if (DDERR_OUTOFMEMORY == (ret=HookD3DDeviceToSurface(this, ((LPDDRAWI_DDRAWSURFACE_INT) lpDDS)->lpLcl)))
goto handle_err;
if (lpDDSZ && (DDERR_OUTOFMEMORY == (ret=HookD3DDeviceToSurface(this, ((LPDDRAWI_DDRAWSURFACE_INT) lpDDSZ)->lpLcl))))
{
UnHookD3DDeviceFromSurface(this, ((LPDDRAWI_DDRAWSURFACE_INT) lpDDS)->lpLcl);
goto handle_err;
}
/* Set the initial render state of the device */
if (FAILED(ret = stateInitialize(lpDDSZ!=NULL))) {
D3D_ERR("Failed to set initial state for device");
goto handle_err;
}
/*
* NOTE: We don't return the actual device interface. We
* return the device's special IUnknown interface which
* will be used in a QueryInterface to get the actual
* Direct3D device interface.
*/
*lplpD3DDevice = static_cast<LPUNKNOWN>(&(this->mDevUnk));
return (D3D_OK);
handle_err:
// might be able to simplify if this fn and not D3DFE_Create sets this->lpDDSZBuffer/this->lpDDPalette
if(lpDDSZ!=NULL) {
if(!bIsDX3Device) {
lpDDSZ->Release(); // release the reference GetAttachedSurface created
}
this->lpDDSZBuffer=NULL; // make sure the device destructor doesn't try to re-release this
// I'd let device destructor handle this, but errors can occur before D3DFE_Create is called
}
if(lpDDPal!=NULL) {
if(!bIsDX3Device) {
lpDDPal->Release(); // release the reference GetPalette created
}
this->lpDDPalTarget=NULL; // make sure the device destructor doesn't try to re-release this
}
D3D_ERR("Device creation failed!!");
return(ret);
}
#undef DPF_MODNAME
#define DPF_MODNAME "DIRECT3DDEVICEI::GetStats"
HRESULT D3DAPI DIRECT3DDEVICEI::GetStats(LPD3DSTATS lpStats)
{
// not implemented for Device3 (and newer) interfaces
if (this->dwVersion >= 3)
{
D3D_INFO(3, "GetStats not implemented for Device3 interface");
return E_NOTIMPL;
}
D3DSTATS stats;
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
/*
* validate parms
*/
TRY
{
if (!VALID_D3DSTATS_PTR(lpStats)) {
D3D_ERR( "Invalid D3DSTATS pointer" );
return DDERR_INVALIDPARAMS;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
D3D_ERR( "Exception encountered validating parameters in GetStats" );
return DDERR_INVALIDPARAMS;
}
stats = this->D3DStats;
*lpStats = stats;
lpStats->dwSize = sizeof(D3DSTATS);
return DD_OK;
}
/**
** Viewport Management
**/
HRESULT DIRECT3DDEVICEI::hookViewportToDevice(LPDIRECT3DVIEWPORTI lpD3DView)
{
CIRCLE_QUEUE_INSERT_END(&this->viewports, DIRECT3DVIEWPORTI,
lpD3DView, vw_list);
lpD3DView->lpDevI = this;
this->numViewports++;
return (D3D_OK);
}
#undef DPF_MODNAME
#define DPF_MODNAME "DIRECT3DDEVICEI::AddViewport"
HRESULT D3DAPI DIRECT3DDEVICEI::AddViewport(LPDIRECT3DVIEWPORT lpD3DView)
{
return AddViewport((LPDIRECT3DVIEWPORT3)lpD3DView);
}
HRESULT D3DAPI DIRECT3DDEVICEI::AddViewport(LPDIRECT3DVIEWPORT2 lpD3DView)
{
return AddViewport((LPDIRECT3DVIEWPORT3)lpD3DView);
}
HRESULT D3DAPI DIRECT3DDEVICEI::AddViewport(LPDIRECT3DVIEWPORT3 lpD3DView)
{
LPDIRECT3DVIEWPORTI lpViewI;
HRESULT err = D3D_OK;
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
lpViewI = (LPDIRECT3DVIEWPORTI)lpD3DView;
if (lpViewI->lpDevI) {
D3D_ERR("viewport already associated with a device");
return (DDERR_INVALIDPARAMS);
}
err = hookViewportToDevice(lpViewI);
/*
* AddRef the viewport.
*/
lpD3DView->AddRef();
return (err);
}
#undef DPF_MODNAME
#define DPF_MODNAME "Direct3DDevice::DeleteViewport"
HRESULT D3DAPI DIRECT3DDEVICEI::DeleteViewport(LPDIRECT3DVIEWPORT lpD3DView)
{
return DeleteViewport((LPDIRECT3DVIEWPORT3)lpD3DView);
}
HRESULT D3DAPI DIRECT3DDEVICEI::DeleteViewport(LPDIRECT3DVIEWPORT2 lpD3DView)
{
return DeleteViewport((LPDIRECT3DVIEWPORT3)lpD3DView);
}
HRESULT D3DAPI DIRECT3DDEVICEI::DeleteViewport(LPDIRECT3DVIEWPORT3 lpD3DView)
{
LPDIRECT3DVIEWPORTI lpViewI;
HRESULT err = D3D_OK;
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
/*
* validate parms
*/
TRY
{
if (!VALID_DIRECT3DVIEWPORT3_PTR(lpD3DView)) {
D3D_ERR( "Invalid Direct3DViewport pointer" );
return DDERR_INVALIDPARAMS;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
D3D_ERR( "Exception encountered validating parameters in DeleteViewport" );
return DDERR_INVALIDPARAMS;
}
if (this->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INBEGIN)
{
D3D_ERR( "DeleteViewport in Begin" );
return D3DERR_INBEGIN;
}
lpViewI = (LPDIRECT3DVIEWPORTI)lpD3DView;
if (lpViewI->lpDevI != this) {
D3D_ERR("This Viewport is not associated with this device");
return (DDERR_INVALIDPARAMS);
}
/*
* Remove this viewport from the device.
*/
CIRCLE_QUEUE_DELETE(&this->viewports, lpViewI, vw_list);
this->numViewports--;
lpViewI->lpDevI = NULL;
if (lpViewI == lpCurrentViewport)
{
// AnanKan (6/10/98):
// Apparently this release needs to be done for proper COM
// implementation, since we do lpCurrentViewport->AddRef() when
// we make a viewport the current viewport of the device. But this
// breaks some old apps (pplane.exe)
if(!(this->dwDeviceFlags & D3DDEV_PREDX6DEVICE))
lpCurrentViewport->Release();
lpCurrentViewport = NULL;
v_id = 0;
}
/*
* Release the viewport.
*/
lpD3DView->Release();
return (err);
}
#undef DPF_MODNAME
#define DPF_MODNAME "Direct3DDevice::NextViewport"
HRESULT D3DAPI DIRECT3DDEVICEI::NextViewport(LPDIRECT3DVIEWPORT lpD3DView,
LPDIRECT3DVIEWPORT* lplpView,
DWORD dwFlags)
{
return NextViewport((LPDIRECT3DVIEWPORT3)lpD3DView,
(LPDIRECT3DVIEWPORT3*)lplpView, dwFlags);
}
HRESULT D3DAPI DIRECT3DDEVICEI::NextViewport(LPDIRECT3DVIEWPORT2 lpD3DView,
LPDIRECT3DVIEWPORT2* lplpView,
DWORD dwFlags)
{
return NextViewport((LPDIRECT3DVIEWPORT3)lpD3DView,
(LPDIRECT3DVIEWPORT3*)lplpView, dwFlags);
}
HRESULT D3DAPI DIRECT3DDEVICEI::NextViewport(LPDIRECT3DVIEWPORT3 lpD3DView,
LPDIRECT3DVIEWPORT3* lplpView,
DWORD dwFlags)
{
LPDIRECT3DVIEWPORTI lpViewI;
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
/*
* validate parms
*/
TRY
{
if (!VALID_OUTPTR(lplpView)) {
D3D_ERR( "Invalid pointer to viewport object pointer" );
return DDERR_INVALIDPARAMS;
}
*lplpView = NULL;
if (!VALID_DIRECT3DDEVICE3_PTR(this)) {
D3D_ERR( "Invalid Direct3DDevice pointer" );
return DDERR_INVALIDOBJECT;
}
if (dwFlags == D3DNEXT_NEXT) {
if (!VALID_DIRECT3DVIEWPORT3_PTR(lpD3DView)) {
D3D_ERR( "Invalid Direct3DViewport pointer" );
return DDERR_INVALIDPARAMS;
}
lpViewI = (LPDIRECT3DVIEWPORTI)lpD3DView;
if (lpViewI->lpDevI != this) {
D3D_ERR("This Viewport is not associated with this device");
return (DDERR_INVALIDPARAMS);
}
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
D3D_ERR("Exception encountered validating parameters in NextViewport");
return DDERR_INVALIDPARAMS;
}
if (this->numViewports <= 0) {
D3D_ERR( "No viewport has been added to the device yet." );
return D3DERR_NOVIEWPORTS;
}
if (this->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INBEGIN)
{
D3D_ERR( "NextViewport called in Begin" );
return D3DERR_INBEGIN;
}
switch (dwFlags) {
case D3DNEXT_NEXT:
*lplpView = (LPDIRECT3DVIEWPORT3)
CIRCLE_QUEUE_NEXT(&this->viewports,lpViewI,vw_list);
break;
case D3DNEXT_HEAD:
*lplpView = (LPDIRECT3DVIEWPORT3)
CIRCLE_QUEUE_FIRST(&this->viewports);
break;
case D3DNEXT_TAIL:
*lplpView = (LPDIRECT3DVIEWPORT3)
CIRCLE_QUEUE_LAST(&this->viewports);
break;
default:
D3D_ERR("invalid dwFlags in NextViewport");
return (DDERR_INVALIDPARAMS);
}
if (*lplpView == (LPDIRECT3DVIEWPORT3)&this->viewports) {
*lplpView = NULL;
}
/*
* Must AddRef the returned object
*/
if (*lplpView) {
(*lplpView)->AddRef();
}
return (D3D_OK);
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DIRECT3DDEVICEI::Execute"
HRESULT D3DAPI DIRECT3DDEVICEI::Execute(LPDIRECT3DEXECUTEBUFFER lpBuffer,
LPDIRECT3DVIEWPORT lpD3DView,
DWORD dwInpFlags)
{
HRESULT ret;
LPDIRECT3DVIEWPORTI lpD3DViewI;
LPDIRECT3DVIEWPORTI lpD3DOldViewI;
BOOL viewportChanged;
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
/*
* validate parms
*/
TRY
{
if (!VALID_DIRECT3DDEVICE3_PTR(this))
{
D3D_ERR( "Invalid Direct3DDevice pointer" );
return DDERR_INVALIDOBJECT;
}
if (!VALID_DIRECT3DEXECUTEBUFFER_PTR(lpBuffer))
{
D3D_ERR( "Invalid Direct3DExecuteBuffer pointer" );
return DDERR_INVALIDOBJECT;
}
if (lpD3DView && (!VALID_DIRECT3DVIEWPORT_PTR(lpD3DView)) )
{
D3D_ERR( "Invalid Direct3DViewport pointer" );
return DDERR_INVALIDOBJECT;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
D3D_ERR( "Exception encountered validating parameters in Execute" );
return DDERR_INVALIDPARAMS;
}
lpD3DOldViewI = lpCurrentViewport;
if (lpD3DView)
lpD3DViewI = (LPDIRECT3DVIEWPORTI)lpD3DView;
else
lpD3DViewI = lpCurrentViewport;
// The viewport must be associated with lpDev device
//
if (lpD3DViewI->lpDevI != this)
{
return (DDERR_INVALIDPARAMS);
}
lpCurrentViewport = lpD3DViewI;
ret = CheckDeviceSettings(this);
if (ret != D3D_OK)
{
lpCurrentViewport = lpD3DOldViewI;
D3D_ERR("Bad Device settings");
return (ret);
}
/*
* Save existing fp state and then disable divide-by-zero exceptions.
* XXX need a better way for non-intel platforms.
*/
LPDIRECT3DEXECUTEBUFFERI lpBufferI;
D3DI_EXECUTEDATA exData;
lpBufferI = (LPDIRECT3DEXECUTEBUFFERI)lpBuffer;
/* Make sure this buffer is associated with the correct device */
if (lpBufferI->lpDevI != this)
{
D3D_ERR("Exe-buffer not associated with this device");
return (DDERR_INVALIDPARAMS);
}
if (lpBufferI->locked)
{
D3D_ERR("Exe-buffer is locked");
return (D3DERR_EXECUTE_LOCKED);
}
/* Apply any cached render states */
if ((ret=this->FlushStates()) != D3D_OK)
{
D3D_ERR("Error trying to flush batched commands");
return ret;
}
/*
* Create an execute data structure
*/
memset(&exData, 0, sizeof(exData));
exData.dwSize = sizeof(D3DI_EXECUTEDATA);
exData.dwHandle = lpBufferI->hBuf;
exData.dwVertexOffset = lpBufferI->exData.dwVertexOffset;
exData.dwVertexCount = lpBufferI->exData.dwVertexCount;
exData.dwInstructionOffset = lpBufferI->exData.dwInstructionOffset;
exData.dwInstructionLength = lpBufferI->exData.dwInstructionLength;
exData.dwHVertexOffset = lpBufferI->exData.dwHVertexOffset;
#if DBG
// Validation
if (exData.dwVertexOffset > exData.dwInstructionOffset ||
(exData.dwVertexCount * sizeof(D3DVERTEX) + exData.dwVertexOffset) >
exData.dwInstructionOffset)
{
D3D_WARN(1, "Execute: Instruction and vertex areas overlap");
}
#endif
this->dwFlags = D3DPV_INSIDEEXECUTE;
this->dwVIDOut = D3DFVF_TLVERTEX;
ret = this->ExecuteI(&exData, dwInpFlags);
if (ret != D3D_OK)
{
D3D_ERR("Error trying to Execute");
return ret;
}
this->dwFEFlags &= ~D3DFE_TLVERTEX; // This flag could be set inside
// Flush immediately since we cannot batch across EB calls (for DP2)
if ((ret=this->FlushStates()) != D3D_OK)
{
D3D_ERR("Error trying to flush batched commands");
return ret;
}
lpBufferI->exData.dsStatus = exData.dsStatus;
lpCurrentViewport = lpD3DOldViewI;
return (ret);
}
#undef DPF_MODNAME
#define DPF_MODNAME "Direct3DDevice::GetCaps"
HRESULT D3DAPI CDirect3DDevice::GetCaps(LPD3DDEVICEDESC lpD3DHWDevDesc,
LPD3DDEVICEDESC lpD3DHELDevDesc)
{
HRESULT ret;
ret = GetCapsI(lpD3DHWDevDesc, lpD3DHELDevDesc);
if ((ret == D3D_OK) && IS_PRE_DX5_DEVICE(this))
{
lpD3DHELDevDesc->dpcLineCaps.dwTextureFilterCaps &= ~(D3DPTFILTERCAPS_MIPNEAREST |
D3DPTFILTERCAPS_MIPLINEAR |
D3DPTFILTERCAPS_LINEARMIPNEAREST);
lpD3DHELDevDesc->dpcTriCaps.dwTextureFilterCaps &= ~(D3DPTFILTERCAPS_MIPNEAREST |
D3DPTFILTERCAPS_MIPLINEAR |
D3DPTFILTERCAPS_LINEARMIPNEAREST);
}
return ret;
}
HRESULT D3DAPI D3DAPI DIRECT3DDEVICEI::GetCaps(LPD3DDEVICEDESC lpD3DHWDevDesc,
LPD3DDEVICEDESC lpD3DHELDevDesc)
{
return GetCapsI(lpD3DHWDevDesc, lpD3DHELDevDesc);
}
HRESULT DIRECT3DDEVICEI::GetCapsI(LPD3DDEVICEDESC lpD3DHWDevDesc,
LPD3DDEVICEDESC lpD3DHELDevDesc)
{
HRESULT ret;
ret = D3D_OK;
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
/*
* validate parms
*/
TRY
{
if (!VALID_DIRECT3DDEVICE3_PTR(this)) {
D3D_ERR( "Invalid Direct3DDevice pointer" );
return DDERR_INVALIDOBJECT;
}
if (!VALID_D3DDEVICEDESC_PTR(lpD3DHWDevDesc)) {
D3D_ERR( "Invalid D3DDEVICEDESC pointer" );
return DDERR_INVALIDPARAMS;
}
if (!VALID_D3DDEVICEDESC_PTR(lpD3DHELDevDesc)) {
D3D_ERR( "Invalid D3DDEVICEDESC pointer" );
return DDERR_INVALIDPARAMS;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
D3D_ERR( "Exception encountered validating parameters in GetCaps" );
return DDERR_INVALIDPARAMS;
}
memcpy(lpD3DHWDevDesc, &this->d3dHWDevDesc, lpD3DHWDevDesc->dwSize);
memcpy(lpD3DHELDevDesc, &this->d3dHELDevDesc, lpD3DHELDevDesc->dwSize);
return (ret);
}
#undef DPF_MODNAME
#define DPF_MODNAME "Direct3DDevice::Pick"
HRESULT D3DAPI DIRECT3DDEVICEI::Pick(LPDIRECT3DEXECUTEBUFFER lpD3DExBuf,
LPDIRECT3DVIEWPORT lpD3DView,
DWORD dwFlags,
LPD3DRECT lpRect)
{
HRESULT ret;
LPDIRECT3DVIEWPORTI lpD3DViewI;
LPDIRECT3DVIEWPORTI lpD3DOldViewI;
LPDIRECT3DEXECUTEBUFFERI lpBufferI;
D3DI_PICKDATA pdata;
D3DI_EXECUTEDATA exData;
ret = D3D_OK;
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
/*
* validate parms
*/
TRY
{
if (!VALID_DIRECT3DDEVICE3_PTR(this)) {
D3D_ERR( "Invalid Direct3DDevice pointer" );
return DDERR_INVALIDOBJECT;
}
if (!VALID_DIRECT3DEXECUTEBUFFER_PTR(lpD3DExBuf)) {
D3D_ERR( "Invalid Direct3DExecuteBuffer pointer" );
return DDERR_INVALIDOBJECT;
}
if (!VALID_DIRECT3DVIEWPORT_PTR(lpD3DView)) {
D3D_ERR( "Invalid Direct3DViewport pointer" );
return DDERR_INVALIDOBJECT;
}
if (!VALID_D3DRECT_PTR(lpRect)) {
D3D_ERR( "Invalid D3DRECT pointer" );
return DDERR_INVALIDOBJECT;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
D3D_ERR( "Exception encountered validating parameters" );
return DDERR_INVALIDPARAMS;
}
lpD3DViewI = (LPDIRECT3DVIEWPORTI)lpD3DView;
/*
* The viewport must be associated with this device
*/
if (lpD3DViewI->lpDevI != this) {
D3D_ERR("viewport not associated with this device");
return (DDERR_INVALIDPARAMS);
}
lpBufferI = (LPDIRECT3DEXECUTEBUFFERI)lpD3DExBuf;
/* Make sure this buffer is associated with the correct device */
if (lpBufferI->lpDevI != this) {
D3D_ERR("Exe-buffer not associated with this device");
return (DDERR_INVALIDPARAMS);
}
if (lpBufferI->locked) {
D3D_ERR("Exe-buffer is locked");
return (D3DERR_EXECUTE_LOCKED);
}
lpD3DOldViewI = lpCurrentViewport;
lpCurrentViewport = lpD3DViewI;
ret = CheckDeviceSettings(this);
if (ret != D3D_OK)
{
D3D_ERR("Bad Device settings");
lpCurrentViewport = lpD3DOldViewI;
return (ret);
}
/*
* Create an execute data structure
*/
memset(&exData, 0, sizeof(exData));
exData.dwSize = sizeof(D3DI_EXECUTEDATA);
exData.dwHandle = lpBufferI->hBuf;
memcpy((LPBYTE)(&exData.dwVertexOffset),
(LPBYTE)(&lpBufferI->exData.dwVertexOffset),
sizeof(D3DEXECUTEDATA) - sizeof(DWORD));
pdata.exe = &exData;
pdata.pick.x1 = lpRect->x1;
pdata.pick.y1 = lpRect->y1;
pdata.pick.x2 = lpRect->x2;
pdata.pick.y2 = lpRect->y2;
this->dwFlags = D3DPV_INSIDEEXECUTE;
this->dwVIDOut = D3DFVF_TLVERTEX;
D3DHAL_ExecutePick(this, &pdata);
this->dwFEFlags &= ~D3DFE_TLVERTEX; // This flag could be set inside
lpCurrentViewport = lpD3DOldViewI;
return ret;
}
#undef DPF_MODNAME
#define DPF_MODNAME "Direct3DDevice::GetPickRecords"
HRESULT D3DAPI DIRECT3DDEVICEI::GetPickRecords(LPDWORD count,
LPD3DPICKRECORD records)
{
HRESULT ret;
D3DI_PICKDATA pdata;
D3DPICKRECORD* tmpBuff;
ret = D3D_OK;
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
/*
* validate parms
*/
TRY
{
if (!VALID_DIRECT3DDEVICE3_PTR(this)) {
D3D_ERR( "Invalid Direct3DDevice pointer" );
return DDERR_INVALIDOBJECT;
}
if (!VALID_DWORD_PTR(count)) {
D3D_ERR( "Invalid DWORD pointer" );
return DDERR_INVALIDPARAMS;
}
#if DBG
if (*count && records && IsBadWritePtr(records, *count * sizeof(D3DPICKRECORD))) {
D3D_ERR( "Invalid D3DPICKRECORD pointer" );
return DDERR_INVALIDPARAMS;
}
#endif
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
D3D_ERR( "Exception encountered validating parameters" );
return DDERR_INVALIDPARAMS;
}
pdata.records = NULL;
GenGetPickRecords(this, &pdata);
if (count && records && *count >= (unsigned long)pdata.pick_count)
{
int picked_size = pdata.pick_count * sizeof(D3DPICKRECORD);
if (D3DMalloc((void**)&tmpBuff, picked_size) != DD_OK)
{
return (DDERR_OUTOFMEMORY);
}
pdata.records = tmpBuff;
GenGetPickRecords(this, &pdata);
memcpy((char*)records, (char*)tmpBuff, picked_size);
D3DFree(tmpBuff);
}
*count = pdata.pick_count;
return (D3D_OK);
}
#undef DPF_MODNAME
#define DPF_MODNAME "Direct3DDevice::EnumTextureFormats"
#define DEFINEPF(flags, fourcc, bpp, rMask, gMask, bMask, aMask) \
{ sizeof(DDPIXELFORMAT), (flags), (fourcc), (bpp), (rMask), (gMask), (bMask), (aMask) }
static DDPIXELFORMAT g_DX5TexEnumIncListStatic[] = {
DEFINEPF(DDPF_RGB, 0UL, 16UL, 0x00007c00UL, 0x000003e0UL, 0x0000001fUL, 0x00000000), // 16bit 555
DEFINEPF(DDPF_RGB|DDPF_ALPHAPIXELS, 0UL, 16UL, 0x00007c00UL, 0x000003e0UL, 0x0000001fUL, 0x00008000), // 16bit 1555
DEFINEPF(DDPF_RGB, 0UL, 16UL, 0x0000f800UL, 0x000007e0UL, 0x0000001fUL, 0x00000000), // 16bit 565
DEFINEPF(DDPF_RGB|DDPF_ALPHAPIXELS, 0UL, 16UL, 0x00000f00UL, 0x000000f0UL, 0x0000000fUL, 0x0000f000), // 16bit 4444
DEFINEPF(DDPF_RGB|DDPF_ALPHAPIXELS, 0UL, 32UL, 0x00ff0000UL, 0x0000ff00UL, 0x000000ffUL, 0xff000000), // 32bit 8888
DEFINEPF(DDPF_RGB, 0UL, 32UL, 0x00ff0000UL, 0x0000ff00UL, 0x000000ffUL, 0x00000000), // 32bit 888
DEFINEPF(DDPF_RGB, 0UL, 8UL, 0x000000e0UL, 0x0000001cUL, 0x00000003UL, 0x00000000), // 8bit 332
DEFINEPF(DDPF_RGB|DDPF_PALETTEINDEXED4, 0UL, 4UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000), // 4bit pal
DEFINEPF(DDPF_RGB|DDPF_PALETTEINDEXED8, 0UL, 8UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000), // 8bit pal
};
DWORD g_cDX5TexEnumIncListStatic = sizeof(g_DX5TexEnumIncListStatic)/sizeof(DDPIXELFORMAT);
BOOL
MatchDDPIXELFORMAT( DDPIXELFORMAT* pddpfA, DDPIXELFORMAT* pddpfB )
{
if ( pddpfA->dwFlags != pddpfB->dwFlags ) return FALSE;
if ( pddpfA->dwRGBBitCount != pddpfB->dwRGBBitCount ) return FALSE;
if ( pddpfA->dwRBitMask != pddpfB->dwRBitMask ) return FALSE;
if ( pddpfA->dwGBitMask != pddpfB->dwGBitMask ) return FALSE;
if ( pddpfA->dwBBitMask != pddpfB->dwBBitMask ) return FALSE;
if ( pddpfA->dwRGBAlphaBitMask != pddpfB->dwRGBAlphaBitMask ) return FALSE;
if ( pddpfA->dwFourCC != pddpfB->dwFourCC ) return FALSE;
return TRUE;
}
void
LoadTexEnumInclList( char* pResPath, DDPIXELFORMAT*& pddpfInclList, DWORD& cInclList)
{
HKEY hKey = (HKEY)NULL;
if (ERROR_SUCCESS == RegOpenKey( HKEY_LOCAL_MACHINE,
pResPath, &hKey))
{
DWORD cSubKeys = 0;
if ( ERROR_SUCCESS == RegQueryInfoKey ( hKey,
NULL,NULL,NULL, &cSubKeys, NULL,
NULL,NULL,NULL,NULL,NULL,NULL ) )
{
D3D_INFO(3,"LoadTexEnumInclList: cSubKeys = %d",cSubKeys);
if (cSubKeys == 0) return;
// allocate space for ddpf inclusion list
cInclList = cSubKeys;
if (D3DMalloc((void**)&pddpfInclList, cInclList*sizeof(DDPIXELFORMAT)) != D3D_OK) {
D3D_ERR("malloc failed on texture enum inclusion list");
pddpfInclList = NULL;
cInclList = 0;
}
memset( pddpfInclList, 0, cInclList*sizeof(DDPIXELFORMAT) );
for (DWORD i=0; i<cSubKeys; i++)
{
char pName[128] = "";
DWORD cbName = 128;
if (ERROR_SUCCESS == RegEnumKeyEx( hKey, i, pName, &cbName,
NULL,NULL,NULL,NULL ) )
{
HKEY hTexKey = (HKEY)NULL;
if (ERROR_SUCCESS == RegOpenKey( hKey, pName, &hTexKey))
{
DWORD dwType; DWORD dwSize;
// get string of full ddpf
char pDDPFStr[128] = ""; DWORD cbDDPFStr = 128;
if (ERROR_SUCCESS == RegQueryValueEx(hTexKey, "ddpf",
NULL, &dwType, (LPBYTE)pDDPFStr, &cbDDPFStr) )
{
sscanf(pDDPFStr, "%x %x %d %x %x %x %x",
&pddpfInclList[i].dwFlags,&pddpfInclList[i].dwFourCC,&pddpfInclList[i].dwRGBBitCount,
&pddpfInclList[i].dwRBitMask,&pddpfInclList[i].dwGBitMask,&pddpfInclList[i].dwBBitMask,
&pddpfInclList[i].dwRGBAlphaBitMask);
}
D3D_INFO(3,"LoadTexEnumInclList: <%s> %08x %08x %2d %08x %08x %08x %08x",
pName,
pddpfInclList[i].dwFlags,
pddpfInclList[i].dwFourCC,
pddpfInclList[i].dwRGBBitCount,
pddpfInclList[i].dwRBitMask,
pddpfInclList[i].dwGBitMask,
pddpfInclList[i].dwBBitMask,
pddpfInclList[i].dwRGBAlphaBitMask);
}
else
{
D3D_INFO(3,"LoadTexEnumInclList: failed to open subkey %s",pName);
}
}
else
{
D3D_INFO(3,"LoadTexEnumInclList: failed to enumerate subkey %d",i);
}
}
}
}
}
HRESULT
DoEnumTextureFormats(
DIRECT3DDEVICEI* lpDevI,
LPD3DENUMTEXTUREFORMATSCALLBACK lpEnumCallbackDX5, // DX5 version
LPD3DENUMPIXELFORMATSCALLBACK lpEnumCallbackDX6, // DX6 version
LPVOID lpContext)
{
HRESULT ret, userRet;
LPDDSURFACEDESC lpDescs, lpRetDescs;
DWORD num_descs;
DWORD i;
ret = D3D_OK;
num_descs = lpDevI->lpD3DHALGlobalDriverData->dwNumTextureFormats;
lpDescs = lpDevI->lpD3DHALGlobalDriverData->lpTextureFormats;
if (!num_descs)
{
D3D_ERR("no texture formats supported");
return (D3DERR_TEXTURE_NO_SUPPORT);
}
if (D3DMalloc((void**)&lpRetDescs, sizeof(DDSURFACEDESC) * num_descs) != D3D_OK)
{
D3D_ERR("failed to alloc space for return descriptions");
return (DDERR_OUTOFMEMORY);
}
memcpy(lpRetDescs, lpDescs, sizeof(DDSURFACEDESC) * num_descs);
// get apphack flags
LPDDRAWI_DIRECTDRAW_LCL lpDDLcl = ((LPDDRAWI_DIRECTDRAW_INT)(lpDevI->lpDD))->lpLcl;
DWORD dwEnumInclAppHack =
((lpDDLcl->dwAppHackFlags & DDRAW_APPCOMPAT_TEXENUMINCL_0)?1:0) |
((lpDDLcl->dwAppHackFlags & DDRAW_APPCOMPAT_TEXENUMINCL_1)?2:0);
// two bit field:
// 0 - no apphack (default behavior)
// 1 - use no inclusion list
// 2 - use DX5 inclusion list
// 3 - use DX6 inclusion list
D3D_INFO(3, "APPCOMPAT_TEXENUMINCL: %d",dwEnumInclAppHack);
// enumeration limit defaults true for <DX6 interfaces, and can be disabled by apphack
BOOL bEnumLimit = (lpDevI->dwVersion < 3) ? TRUE : FALSE;
if (lpDDLcl->dwAppHackFlags & DDRAW_APPCOMPAT_TEXENUMLIMIT) { bEnumLimit = FALSE; }
D3D_INFO(3, "EnumTextureFormats: bEnumLimit %d",bEnumLimit);
#if DBG
// debug capability to eliminate enumeration of any subset of first 32 textures
DWORD dwEnumDisable = 0x0;
GetD3DRegValue(REG_DWORD, "TextureEnumDisable", &dwEnumDisable, sizeof(DWORD));
D3D_INFO(3, "TextureEnumDisable: %08x",dwEnumDisable);
#endif
DDPIXELFORMAT* pDX5TexEnumIncList = NULL;
DWORD cDX5TexEnumIncList = 0;
// load DX5 inclusion list from registry
LoadTexEnumInclList( RESPATH_D3D "\\DX5TextureEnumInclusionList",
pDX5TexEnumIncList, cDX5TexEnumIncList );
DDPIXELFORMAT* pDX6TexEnumIncList = NULL;
DWORD cDX6TexEnumIncList = 0;
// load DX6 list only for DX6 interface or apphack
if ((lpDevI->dwVersion == 3) || (dwEnumInclAppHack >= 3))
{
LoadTexEnumInclList( RESPATH_D3D "\\DX6TextureEnumInclusionList",
pDX6TexEnumIncList, cDX6TexEnumIncList );
}
userRet = D3DENUMRET_OK;
int cEnumLimit = 0;
for (i = 0; i < num_descs && userRet == D3DENUMRET_OK; i++)
{
D3D_INFO(3,"EnumTextureFormats: %2d %08x %08x %2d %08x %08x %08x %08x",i,
lpRetDescs[i].ddpfPixelFormat.dwFlags,
lpRetDescs[i].ddpfPixelFormat.dwFourCC,
lpRetDescs[i].ddpfPixelFormat.dwRGBBitCount,
lpRetDescs[i].ddpfPixelFormat.dwRBitMask,
lpRetDescs[i].ddpfPixelFormat.dwGBitMask,
lpRetDescs[i].ddpfPixelFormat.dwBBitMask,
lpRetDescs[i].ddpfPixelFormat.dwRGBAlphaBitMask);
#if DBG
if ( (i < 32) && (dwEnumDisable & (1<<i)) )
{
D3D_INFO(3, "EnumTextureFormats: filtering texture %d",i);
continue;
}
#endif
// Filtering out texture formats which are not on inclusion list -
if ( (dwEnumInclAppHack != 1) && // inclusion list not disabled by apphack
!(lpRetDescs[i].ddpfPixelFormat.dwFlags == DDPF_FOURCC) ) // not FourCC
{
BOOL bMatched = FALSE;
// match against DX5 base (static) inclusion list
for (DWORD j=0; j<g_cDX5TexEnumIncListStatic; j++)
{
if (MatchDDPIXELFORMAT( &(g_DX5TexEnumIncListStatic[j]), &(lpRetDescs[i].ddpfPixelFormat)))
{
bMatched = TRUE; break;
}
}
// match against DX5 extended (regkey) inclusion list
if (!bMatched && cDX5TexEnumIncList)
{
for (DWORD j=0; j<cDX5TexEnumIncList; j++)
{
if (MatchDDPIXELFORMAT( &(pDX5TexEnumIncList[j]), &(lpRetDescs[i].ddpfPixelFormat)))
{
bMatched = TRUE; break;
}
}
}
// match against DX6 regkey list for:
// (DX6 interface AND apphack not forcing DX5 inclusion list only) OR
// (apphack forcing DX6 inclusion list)
if ( ((lpDevI->dwVersion == 3) && (dwEnumInclAppHack != 2)) ||
(dwEnumInclAppHack == 3) )
{
for (DWORD j=0; j<cDX6TexEnumIncList; j++)
{
if (MatchDDPIXELFORMAT( &(pDX6TexEnumIncList[j]), &(lpRetDescs[i].ddpfPixelFormat)))
{
bMatched = TRUE; break;
}
}
}
if (!bMatched) {
D3D_INFO(3, "EnumTextureFormats: filtering non-included texture %d",i);
continue;
}
}
// exclude DXT1..5 for <DX6 interfaces
if ( (lpDevI->dwVersion < 3) && (lpRetDescs[i].ddpfPixelFormat.dwFlags == DDPF_FOURCC) )
{
if ( (lpRetDescs[i].ddpfPixelFormat.dwFourCC == MAKEFOURCC('D', 'X', 'T', '1')) ||
(lpRetDescs[i].ddpfPixelFormat.dwFourCC == MAKEFOURCC('D', 'X', 'T', '2')) ||
(lpRetDescs[i].ddpfPixelFormat.dwFourCC == MAKEFOURCC('D', 'X', 'T', '3')) ||
(lpRetDescs[i].ddpfPixelFormat.dwFourCC == MAKEFOURCC('D', 'X', 'T', '4')) ||
(lpRetDescs[i].ddpfPixelFormat.dwFourCC == MAKEFOURCC('D', 'X', 'T', '5')) )
{
D3D_INFO(3, "EnumTextureFormats: filtering DXT1..5 format for DX3/5 interfaces");
continue;
}
}
// exclude all FourCC code formats for <DX6 interfaces on DX7 drivers
if ( (lpDevI->dwVersion < 3) && IS_DX7HAL_DEVICE(lpDevI) &&
(lpRetDescs[i].ddpfPixelFormat.dwFlags == DDPF_FOURCC) )
{
D3D_INFO(3, "EnumTextureFormats: filtering all FOURCC formats for DX3/5 interfaces on DX7 HALs");
continue;
}
// do enumeration if not ('limit enabled' && 'limit exceeded')
if ( !(bEnumLimit && (++cEnumLimit > 10)) )
{
if (lpEnumCallbackDX5)
{
userRet = (*lpEnumCallbackDX5)(&lpRetDescs[i], lpContext);
}
if (lpEnumCallbackDX6)
{
userRet = (*lpEnumCallbackDX6)(&(lpRetDescs[i].ddpfPixelFormat), lpContext);
}
}
else
{
D3D_INFO(3, "EnumTextureFormats: enumeration limit exceeded");
}
}
D3DFree(lpRetDescs);
if (pDX5TexEnumIncList) D3DFree(pDX5TexEnumIncList);
if (pDX6TexEnumIncList) D3DFree(pDX6TexEnumIncList);
return (D3D_OK);
}
// Device/Device2 version
HRESULT D3DAPI DIRECT3DDEVICEI::EnumTextureFormats(
LPD3DENUMTEXTUREFORMATSCALLBACK lpEnumCallback,
LPVOID lpContext)
{
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
/*
* validate parms
*/
TRY
{
if (!VALID_DIRECT3DDEVICE3_PTR(this)) {
D3D_ERR( "Invalid Direct3DDevice pointer" );
return DDERR_INVALIDOBJECT;
}
if (!VALIDEX_CODE_PTR(lpEnumCallback)) {
D3D_ERR( "Invalid callback pointer" );
return DDERR_INVALIDPARAMS;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
D3D_ERR( "Exception encountered validating parameters" );
return DDERR_INVALIDPARAMS;
}
return DoEnumTextureFormats(this, lpEnumCallback, NULL, lpContext);
}
#undef DPF_MODNAME
#define DPF_MODNAME "Direct3DDevice::EnumTextureFormats"
// Device3 version
HRESULT D3DAPI DIRECT3DDEVICEI::EnumTextureFormats(
LPD3DENUMPIXELFORMATSCALLBACK lpEnumCallback,
LPVOID lpContext)
{
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
/*
* validate parms
*/
TRY
{
if (!VALID_DIRECT3DDEVICE3_PTR(this)) {
D3D_ERR( "Invalid Direct3DDevice pointer" );
return DDERR_INVALIDOBJECT;
}
if (!VALIDEX_CODE_PTR(lpEnumCallback)) {
D3D_ERR( "Invalid callback pointer" );
return DDERR_INVALIDPARAMS;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
D3D_ERR( "Exception encountered validating parameters" );
return DDERR_INVALIDPARAMS;
}
return DoEnumTextureFormats(this, NULL, lpEnumCallback, lpContext);
}
#undef DPF_MODNAME
#define DPF_MODNAME "Direct3DDevice::SwapTextureHandles"
HRESULT D3DAPI DIRECT3DDEVICEI::SwapTextureHandles(LPDIRECT3DTEXTURE lpTex1,
LPDIRECT3DTEXTURE lpTex2)
{
LPDIRECT3DTEXTUREI lpTex1I;
LPDIRECT3DTEXTUREI lpTex2I;
HRESULT ret;
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
/*
* validate parms
*/
TRY
{
if (!VALID_DIRECT3DDEVICE3_PTR(this)) {
D3D_ERR( "Invalid Direct3DDevice pointer" );
return DDERR_INVALIDOBJECT;
}
if (!VALID_DIRECT3DTEXTURE_PTR(lpTex1)) {
D3D_ERR( "Invalid Direct3DTexture pointer" );
return DDERR_INVALIDOBJECT;
}
if (!VALID_DIRECT3DTEXTURE_PTR(lpTex2)) {
D3D_ERR( "Invalid Direct3DTexture pointer" );
return DDERR_INVALIDOBJECT;
}
lpTex1I = static_cast<LPDIRECT3DTEXTUREI>(lpTex1);
lpTex2I = static_cast<LPDIRECT3DTEXTUREI>(lpTex2);
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
D3D_ERR( "Exception encountered validating parameters" );
return DDERR_INVALIDPARAMS;
}
ret = SwapTextureHandles((LPDIRECT3DTEXTURE2)lpTex1I,
(LPDIRECT3DTEXTURE2)lpTex2I);
return ret;
}
HRESULT D3DAPI DIRECT3DDEVICEI::SwapTextureHandles(LPDIRECT3DTEXTURE2 lpTex1,
LPDIRECT3DTEXTURE2 lpTex2)
{
LPDIRECT3DTEXTUREI lpTex1I;
LPDIRECT3DTEXTUREI lpTex2I;
HRESULT servRet;
D3DTEXTUREHANDLE hTex;
LPD3DI_TEXTUREBLOCK lptBlock1,lptBlock2;
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
/*
* validate parms
*/
TRY
{
if (!VALID_DIRECT3DDEVICE3_PTR(this)) {
D3D_ERR( "Invalid Direct3DDevice pointer" );
return DDERR_INVALIDOBJECT;
}
if (!VALID_DIRECT3DTEXTURE2_PTR(lpTex1)) {
D3D_ERR( "Invalid Direct3DTexture pointer" );
return DDERR_INVALIDOBJECT;
}
if (!VALID_DIRECT3DTEXTURE2_PTR(lpTex2)) {
D3D_ERR( "Invalid Direct3DTexture pointer" );
return DDERR_INVALIDOBJECT;
}
lpTex1I = static_cast<LPDIRECT3DTEXTUREI>(lpTex1);
lpTex2I = static_cast<LPDIRECT3DTEXTUREI>(lpTex2);
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
D3D_ERR( "Exception encountered validating parameters" );
return DDERR_INVALIDPARAMS;
}
if (lpTex1I->lpDDSSys || lpTex2I->lpDDSSys)
{
D3D_ERR("Can't Swap Managed textures. Returning DDERR_INVALIDPARAMS");
return DDERR_INVALIDPARAMS;
}
if (!(lptBlock1=D3DI_FindTextureBlock(lpTex1I,this)))
{
D3D_ERR("lpTex1 is an invalid texture handle.");
return DDERR_INVALIDPARAMS;
}
if (!(lptBlock2=D3DI_FindTextureBlock(lpTex2I,this)))
{
D3D_ERR("lpTex2 is an invalid texture handle.");
return DDERR_INVALIDPARAMS;
}
if (D3D_OK != (servRet=FlushStates()))
{
D3D_ERR("Error trying to flush batched commands during TextureSwap");
return servRet;
}
if (IS_DX7HAL_DEVICE(this))
{
LPDDRAWI_DDRAWSURFACE_LCL surf1 = ((LPDDRAWI_DDRAWSURFACE_INT)lpTex1I->lpDDS)->lpLcl;
LPDDRAWI_DDRAWSURFACE_LCL surf2 = ((LPDDRAWI_DDRAWSURFACE_INT)lpTex2I->lpDDS)->lpLcl;
LPDDRAWI_DIRECTDRAW_LCL pDDLcl = ((LPDDRAWI_DIRECTDRAW_INT)lpDirect3DI->lpDD)->lpLcl;
DDASSERT(pDDLcl != NULL);
// Update DDraw handle in driver GBL object.
pDDLcl->lpGbl->hDD = pDDLcl->hDD;
// Swap the handles stored in the surface locals
surf1->lpSurfMore->dwSurfaceHandle = lptBlock2->hTex;
surf2->lpSurfMore->dwSurfaceHandle = lptBlock1->hTex;
// Swap the surface pointers stored in the handle table stored in
// ddraw local
SURFACEHANDLELIST(pDDLcl).dwList[lptBlock1->hTex].lpSurface = surf2;
SURFACEHANDLELIST(pDDLcl).dwList[lptBlock2->hTex].lpSurface = surf1;
// call the driver to switch the textures mapped to the handles in
// the driver
DDASSERT(NULL != pDDLcl->lpGbl->lpDDCBtmp->HALDDMiscellaneous2.CreateSurfaceEx);
DDHAL_CREATESURFACEEXDATA csdex;
DWORD rc;
csdex.ddRVal = DDERR_GENERIC;
csdex.dwFlags = 0;
csdex.lpDDLcl = pDDLcl;
csdex.lpDDSLcl = surf1;
rc = pDDLcl->lpGbl->lpDDCBtmp->HALDDMiscellaneous2.CreateSurfaceEx(&csdex);
if( DDHAL_DRIVER_HANDLED == rc && DD_OK != csdex.ddRVal)
{
// Driver call failed
D3D_ERR("DdSwapTextureHandles failed!");
return D3DERR_TEXTURE_SWAP_FAILED;
}
csdex.lpDDSLcl = surf2;
rc = pDDLcl->lpGbl->lpDDCBtmp->HALDDMiscellaneous2.CreateSurfaceEx(&csdex);
if( DDHAL_DRIVER_HANDLED == rc && DD_OK != csdex.ddRVal)
{
// Driver call failed
D3D_ERR("DdSwapTextureHandles failed!");
return D3DERR_TEXTURE_SWAP_FAILED;
}
}
else
{
servRet=D3DHAL_TextureSwap(this,lptBlock1->hTex,lptBlock2->hTex);
if (D3D_OK != servRet)
{
D3D_ERR("SwapTextureHandles HAL call failed");
return D3DERR_TEXTURE_SWAP_FAILED;
}
}
hTex=lptBlock1->hTex;
lptBlock1->hTex=lptBlock2->hTex;
lptBlock2->hTex=hTex;
return (D3D_OK);
}
#undef DPF_MODNAME
#define DPF_MODNAME "Direct3DDevice::CreateMatrix"
HRESULT D3DAPI DIRECT3DDEVICEI::CreateMatrix(LPD3DMATRIXHANDLE lphMatrix)
{
HRESULT servRet;
D3DMATRIXHANDLE hMat;
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
/*
* validate parms
*/
TRY
{
if (!VALID_DIRECT3DDEVICE3_PTR(this)) {
D3D_ERR( "Invalid Direct3DDevice pointer" );
return DDERR_INVALIDOBJECT;
}
if (!VALID_D3DMATRIXHANDLE_PTR(lphMatrix)) {
D3D_ERR( "Invalid D3DMATRIXHANDLE pointer" );
return DDERR_INVALIDPARAMS;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
D3D_ERR( "Exception encountered validating parameters" );
return DDERR_INVALIDPARAMS;
}
*lphMatrix = 0;
servRet = D3DHAL_MatrixCreate(this, &hMat);
if (servRet != D3D_OK)
{
D3D_ERR("Could not create matrix.");
return (DDERR_OUTOFMEMORY);
}
D3D_INFO(4, "CreateMatrix, Matrix created. handle = %d", hMat);
*lphMatrix = hMat;
return (D3D_OK);
}
#undef DPF_MODNAME
#define DPF_MODNAME "Direct3DDevice::SetMatrix"
HRESULT D3DAPI DIRECT3DDEVICEI::SetMatrix(D3DMATRIXHANDLE hMatrix,
const LPD3DMATRIX lpdmMatrix)
{
HRESULT servRet;
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
/*
* validate parms
*/
TRY
{
if (!VALID_DIRECT3DDEVICE3_PTR(this)) {
D3D_ERR( "Invalid Direct3DDevice pointer" );
return DDERR_INVALIDOBJECT;
}
if (!VALID_D3DMATRIX_PTR(lpdmMatrix)) {
D3D_ERR( "Invalid D3DMATRIX pointer" );
return DDERR_INVALIDPARAMS;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
D3D_ERR( "Exception encountered validating parameters" );
return DDERR_INVALIDPARAMS;
}
if (!hMatrix) {
D3D_ERR("NULL hMatrix passed");
return (DDERR_INVALIDPARAMS);
}
servRet = D3DHAL_MatrixSetData(this, hMatrix, lpdmMatrix);
if (servRet != D3D_OK)
{
D3D_ERR("Could not set matrix");
return (DDERR_INVALIDPARAMS);
}
return (D3D_OK);
}
#undef DPF_MODNAME
#define DPF_MODNAME "Direct3DDevice::GetMatrix"
HRESULT D3DAPI DIRECT3DDEVICEI::GetMatrix(D3DMATRIXHANDLE hMatrix,
LPD3DMATRIX lpdmMatrix)
{
HRESULT servRet;
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
/*
* validate parms
*/
TRY
{
if (!VALID_DIRECT3DDEVICE3_PTR(this)) {
D3D_ERR( "Invalid Direct3DDevice pointer" );
return DDERR_INVALIDOBJECT;
}
if (!VALID_D3DMATRIX_PTR(lpdmMatrix)) {
D3D_ERR( "Invalid D3DMATRIX pointer" );
return DDERR_INVALIDPARAMS;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
D3D_ERR( "Exception encountered validating parameters" );
return DDERR_INVALIDPARAMS;
}
if (!hMatrix)
{
D3D_ERR("NULL hMatrix passed.");
return (DDERR_INVALIDPARAMS);
}
memset(lpdmMatrix, 0, sizeof(D3DMATRIX));
servRet = D3DHAL_MatrixGetData(this, hMatrix, lpdmMatrix);
if (servRet != D3D_OK)
{
D3D_ERR("Could not get matrix");
return (DDERR_INVALIDPARAMS);
}
return (D3D_OK);
}
#undef DPF_MODNAME
#define DPF_MODNAME "Direct3DDevice::DeleteMatrix"
HRESULT D3DAPI DIRECT3DDEVICEI::DeleteMatrix(D3DMATRIXHANDLE hMatrix)
{
HRESULT servRet;
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
/*
* validate parms
*/
TRY
{
if (!VALID_DIRECT3DDEVICE3_PTR(this)) {
D3D_ERR( "Invalid Direct3DDevice pointer" );
return DDERR_INVALIDOBJECT;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
D3D_ERR( "Exception encountered validating parameters" );
return DDERR_INVALIDPARAMS;
}
if (!hMatrix) {
D3D_ERR("invalid D3DMATRIXHANDLE");
return DDERR_INVALIDPARAMS;
}
servRet = D3DHAL_MatrixDestroy(this, hMatrix);
if (servRet != D3D_OK)
{
D3D_ERR("Could not delete matrix");
return (DDERR_INVALIDPARAMS);
}
return (D3D_OK);
}
#undef DPF_MODNAME
#define DPF_MODNAME "Direct3DDevice::BeginScene"
HRESULT D3DAPI DIRECT3DDEVICEI::BeginScene()
{
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
/*
* validate parms
*/
TRY
{
if (!VALID_DIRECT3DDEVICE_PTR(this)) {
D3D_ERR( "Invalid Direct3DDevice pointer" );
return DDERR_INVALIDOBJECT;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
D3D_ERR( "Exception encountered validating parameters" );
return DDERR_INVALIDPARAMS;
}
if (this->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INSCENE)
{
D3D_ERR("BeginScene, already in scene.");
return (D3DERR_SCENE_IN_SCENE);
}
// Check if we lost surfaces or rtarget / zbuffer was locked
HRESULT servRet = this->CheckSurfaces();
if (servRet != D3D_OK)
{
// If we lost surfaces
if (servRet == DDERR_SURFACELOST)
{
// Even if the app restores the rendertargets and z buffer, it
// doesn't know anything about vidmem execute buffers or
// managed texture surfaces in vidmem. So, we need to do
// this on our own. We first check if it is safe to restore
// surfaces. If not, we fail in the usual way. Else, we
// do the restore. Note that we will fail *only* if the
// app calls BeginScene at the wrong time.
servRet = this->lpDirect3DI->lpDD4->TestCooperativeLevel();
if (servRet == DD_OK)
{
// Everything must be evicted otherwise Restore might not work
// as there might be new surface allocated, in fact, we should
// post a flag in Device so that Texture manage stop calling
// CreateSurface() if this flag is indicating TestCooperativeLevel()
// failed, however, even we added those, the EvictTextures below
// is still needed but not this critical--kanqiu
this->lpDirect3DI->lpTextureManager->EvictTextures();
servRet = this->lpDirect3DI->lpDD4->RestoreAllSurfaces();
if (servRet != DD_OK)
return D3DERR_SCENE_BEGIN_FAILED;
}
else
return DDERR_SURFACELOST;
}
else
{
// Render target and / or the z buffer was locked
return servRet;
}
}
servRet = D3DHAL_SceneCapture(this, TRUE);
if (servRet != D3D_OK && servRet != DDERR_NOTFOUND)
{
D3D_ERR("Could not BeginScene.");
return D3DERR_SCENE_BEGIN_FAILED;
}
this->dwHintFlags |= D3DDEVBOOL_HINTFLAGS_INSCENE;
if (lpD3DHALGlobalDriverData->hwCaps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR)
{
lpDirect3DI->lpTextureManager->TimeStamp();
}
return (D3D_OK);
}
#undef DPF_MODNAME
#define DPF_MODNAME "Direct3DDevice::EndScene"
HRESULT D3DAPI DIRECT3DDEVICEI::EndScene()
{
HRESULT servRet;
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
/*
* validate parms
*/
TRY
{
if (!VALID_DIRECT3DDEVICE3_PTR(this)) {
D3D_ERR( "Invalid Direct3DDevice pointer" );
return DDERR_INVALIDOBJECT;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
D3D_ERR( "Exception encountered validating parameters" );
return DDERR_INVALIDPARAMS;
}
if (!(this->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INSCENE)) {
D3D_ERR("EndScene, not in scene.");
return (D3DERR_SCENE_NOT_IN_SCENE);
}
this->dwHintFlags &= ~D3DDEVBOOL_HINTFLAGS_INSCENE;
if (IS_DX7HAL_DEVICE(this))
{
// must set the token before FlushStates()
SetRenderStateI((D3DRENDERSTATETYPE)D3DRENDERSTATE_SCENECAPTURE, FALSE);
}
servRet = FlushStates(); //time to flush DrawPrimitives
if (servRet != D3D_OK)
{
D3D_ERR("Could not Flush commands in EndScene!");
return (D3DERR_SCENE_END_FAILED);
}
if (!IS_DX7HAL_DEVICE(this))
{
servRet = D3DHAL_SceneCapture(this, FALSE);
if (servRet != D3D_OK && servRet != DDERR_NOTFOUND)
{
DPF(0, "(ERROR) Direct3DDevice::EndScene: Could not EndScene. Returning %d", servRet);
return (D3DERR_SCENE_END_FAILED);
}
}
// Did we lose any surfaces during this scene ?
if (this->dwFEFlags & D3DFE_LOSTSURFACES)
{
D3D_INFO(3, "reporting DDERR_SURFACELOST in EndScene");
this->dwFEFlags &= ~D3DFE_LOSTSURFACES;
return DDERR_SURFACELOST;
}
return (D3D_OK);
}
#undef DPF_MODNAME
#define DPF_MODNAME "Direct3DDevice::GetDirect3D"
HRESULT D3DAPI DIRECT3DDEVICEI::GetDirect3D(LPDIRECT3D* lplpD3D)
{
LPDIRECT3D3 lpD3D3;
HRESULT ret;
ret = GetDirect3D(&lpD3D3);
if (ret == D3D_OK)
{
// *lplpD3D = dynamic_cast<LPDIRECT3D>(lpD3D3); // This is possible using RTTI
*lplpD3D = static_cast<LPDIRECT3D>(static_cast<LPDIRECT3DI>(lpD3D3)); // This is safe even using static_cast
}
return ret;
}
HRESULT D3DAPI DIRECT3DDEVICEI::GetDirect3D(LPDIRECT3D2* lplpD3D)
{
LPDIRECT3D3 lpD3D3;
HRESULT ret;
ret = GetDirect3D(&lpD3D3);
if (ret == D3D_OK)
{
// *lplpD3D = dynamic_cast<LPDIRECT3D>(lpD3D3); // This is possible using RTTI
*lplpD3D = static_cast<LPDIRECT3D2>(static_cast<LPDIRECT3DI>(lpD3D3)); // This is safe even using static_cast
}
return ret;
}
HRESULT D3DAPI DIRECT3DDEVICEI::GetDirect3D(LPDIRECT3D3* lplpD3D)
{
CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
/*
* validate parms
*/
TRY
{
if (!VALID_DIRECT3DDEVICE3_PTR(this)) {
D3D_ERR( "Invalid Direct3DDevice pointer" );
return DDERR_INVALIDOBJECT;
}
if (!VALID_OUTPTR(lplpD3D)) {
D3D_ERR( "Invalid Direct3D pointer pointer" );
return DDERR_INVALIDPARAMS;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
D3D_ERR( "Exception encountered validating parameters" );
return DDERR_INVALIDPARAMS;
}
*lplpD3D = (LPDIRECT3D3) this->lpDirect3DI;
(*lplpD3D)->AddRef();
return (D3D_OK);
}
void
D3DDeviceDescConvert(LPD3DDEVICEDESC lpOut,
LPD3DDEVICEDESC_V1 lpV1,
LPD3DHAL_D3DEXTENDEDCAPS lpExt)
{
if(lpV1!=NULL)
memcpy(lpOut, lpV1, D3DDEVICEDESCSIZE_V1);
if (lpExt)
{
// DX5
lpOut->dwSize = D3DDEVICEDESCSIZE;
lpOut->dwMinTextureWidth = lpExt->dwMinTextureWidth;
lpOut->dwMaxTextureWidth = lpExt->dwMaxTextureWidth;
lpOut->dwMinTextureHeight = lpExt->dwMinTextureHeight;
lpOut->dwMaxTextureHeight = lpExt->dwMaxTextureHeight;
lpOut->dwMinStippleWidth = lpExt->dwMinStippleWidth;
lpOut->dwMaxStippleWidth = lpExt->dwMaxStippleWidth;
lpOut->dwMinStippleHeight = lpExt->dwMinStippleHeight;
lpOut->dwMaxStippleHeight = lpExt->dwMaxStippleHeight;
// DX6
lpOut->dwMaxTextureRepeat = lpExt->dwMaxTextureRepeat;
lpOut->dwMaxTextureAspectRatio = lpExt->dwMaxTextureAspectRatio;
lpOut->dwMaxAnisotropy = lpExt->dwMaxAnisotropy;
lpOut->dvGuardBandLeft = lpExt->dvGuardBandLeft;
lpOut->dvGuardBandTop = lpExt->dvGuardBandTop;
lpOut->dvGuardBandRight = lpExt->dvGuardBandRight;
lpOut->dvGuardBandBottom = lpExt->dvGuardBandBottom;
lpOut->dvExtentsAdjust = lpExt->dvExtentsAdjust;
lpOut->dwStencilCaps = lpExt->dwStencilCaps;
lpOut->dwFVFCaps = lpExt->dwFVFCaps;
lpOut->dwTextureOpCaps = lpExt->dwTextureOpCaps;
lpOut->wMaxTextureBlendStages = lpExt->wMaxTextureBlendStages;
lpOut->wMaxSimultaneousTextures = lpExt->wMaxSimultaneousTextures;
}
}
//---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "DIRECT3DDEVICEI::CheckSurfaces"
HRESULT DIRECT3DDEVICEI::CheckSurfaces()
{
if(this->lpDirect3DI->lpTextureManager->CheckIfLost())
{
D3D_ERR("Managed Textures lost");
return DDERR_SURFACELOST;
}
if ( ((LPDDRAWI_DDRAWSURFACE_INT) this->lpDDSTarget)->lpLcl->lpGbl->dwUsageCount ||
(this->lpDDSZBuffer && ((LPDDRAWI_DDRAWSURFACE_INT) this->lpDDSZBuffer)->lpLcl->lpGbl->dwUsageCount) )
{
D3D_ERR("Render target or Z buffer locked");
return DDERR_SURFACEBUSY;
}
if ( ((LPDDRAWI_DDRAWSURFACE_INT) this->lpDDSTarget)->lpLcl->dwFlags & DDRAWISURF_INVALID )\
{
D3D_ERR("Render target buffer lost");
return DDERR_SURFACELOST;
}
if ( this->lpDDSZBuffer && ( ((LPDDRAWI_DDRAWSURFACE_INT) this->lpDDSZBuffer)->lpLcl->dwFlags & DDRAWISURF_INVALID ) )
{
D3D_ERR("Z buffer lost");
return DDERR_SURFACELOST;
}
return D3D_OK;
}