|
|
/*==========================================================================;
* * 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 $ * *@@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 "drawprim.hpp"
#include "fe.h"
#include "enum.hpp"
//#define APIPROF
#ifdef APIPROF
#include "apiprof.cpp"
#endif //APIPROF
#if defined(PROFILE4)
#include <icecap.h>
#elif defined(PROFILE)
#include <icapexp.h>
#endif
// 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 void setIdentity(D3DMATRIXI * m);
#ifndef PROFILE4
#ifdef _X86_
extern HRESULT D3DAPI katmai_FEContextCreate(DWORD dwFlags, LPD3DFE_PVFUNCS *lpLeafFuncs); extern HRESULT D3DAPI wlmt_FEContextCreate(DWORD dwFlags, LPD3DFE_PVFUNCS *lpLeafFuncs); extern HRESULT D3DAPI x3DContextCreate(DWORD dwFlags, LPD3DFE_PVFUNCS *lpLeafFuncs); #endif
#endif
#ifdef _X86_
extern BOOL IsWin95(); #endif
extern HINSTANCE hMsGeometryDLL;
// This is a list of all rstates that UpdateInternalState does some
// work other than updating this->rstates[] array. This is used to
// do a quick bitwise check to see if this rstate is trivial or not.
const D3DRENDERSTATETYPE rsList[] = {
// renderstates that either need runtime attention or that cannot be sent
// to legacy drivers
D3DRENDERSTATE_FOGENABLE, D3DRENDERSTATE_SPECULARENABLE, D3DRENDERSTATE_RANGEFOGENABLE, D3DRENDERSTATE_FOGDENSITY, D3DRENDERSTATE_FOGSTART, D3DRENDERSTATE_FOGEND, D3DRENDERSTATE_WRAP0, D3DRENDERSTATE_WRAP1, D3DRENDERSTATE_WRAP2, D3DRENDERSTATE_WRAP3, D3DRENDERSTATE_WRAP4, D3DRENDERSTATE_WRAP5, D3DRENDERSTATE_WRAP6, D3DRENDERSTATE_WRAP7, D3DRENDERSTATE_CLIPPING, D3DRENDERSTATE_LIGHTING, D3DRENDERSTATE_AMBIENT, D3DRENDERSTATE_FOGVERTEXMODE, D3DRENDERSTATE_COLORVERTEX, D3DRENDERSTATE_LOCALVIEWER, D3DRENDERSTATE_NORMALIZENORMALS, D3DRENDERSTATE_COLORKEYBLENDENABLE, D3DRENDERSTATE_DIFFUSEMATERIALSOURCE, D3DRENDERSTATE_SPECULARMATERIALSOURCE, D3DRENDERSTATE_AMBIENTMATERIALSOURCE, D3DRENDERSTATE_EMISSIVEMATERIALSOURCE, D3DRENDERSTATE_VERTEXBLEND, D3DRENDERSTATE_CLIPPLANEENABLE, D3DRENDERSTATE_SHADEMODE, D3DRS_SOFTWAREVERTEXPROCESSING, D3DRS_POINTSIZE, D3DRS_POINTSIZE_MIN, D3DRS_POINTSPRITEENABLE, D3DRS_POINTSCALEENABLE, D3DRS_POINTSCALE_A, D3DRS_POINTSCALE_B, D3DRS_POINTSCALE_C, D3DRS_MULTISAMPLEANTIALIAS, D3DRS_MULTISAMPLEMASK, D3DRS_PATCHEDGESTYLE, D3DRS_PATCHSEGMENTS, D3DRS_DEBUGMONITORTOKEN, D3DRS_POINTSIZE_MAX, D3DRS_INDEXEDVERTEXBLENDENABLE, D3DRS_COLORWRITEENABLE, D3DRS_TWEENFACTOR, D3DRS_DEBUGMONITORTOKEN, D3DRS_BLENDOP, D3DRS_PATCHSEGMENTS,
// Retired renderstates to be filtered with DPF error and INVALID return
// NOTE: everything listed here is also assumed to appear in rsListRetired
D3DRENDERSTATE_TEXTUREHANDLE, D3DRENDERSTATE_TEXTUREADDRESS, D3DRENDERSTATE_WRAPU, D3DRENDERSTATE_WRAPV, D3DRENDERSTATE_MONOENABLE, D3DRENDERSTATE_ROP2, D3DRENDERSTATE_PLANEMASK, D3DRENDERSTATE_TEXTUREMAG, D3DRENDERSTATE_TEXTUREMIN, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DRENDERSTATE_SUBPIXEL, D3DRENDERSTATE_SUBPIXELX, D3DRENDERSTATE_STIPPLEENABLE, D3DRENDERSTATE_BORDERCOLOR, D3DRENDERSTATE_TEXTUREADDRESSU, D3DRENDERSTATE_TEXTUREADDRESSV, D3DRENDERSTATE_MIPMAPLODBIAS, D3DRENDERSTATE_ANISOTROPY, D3DRENDERSTATE_TRANSLUCENTSORTINDEPENDENT, D3DRENDERSTATE_STIPPLEPATTERN00, D3DRENDERSTATE_STIPPLEPATTERN01, D3DRENDERSTATE_STIPPLEPATTERN02, D3DRENDERSTATE_STIPPLEPATTERN03, D3DRENDERSTATE_STIPPLEPATTERN04, D3DRENDERSTATE_STIPPLEPATTERN05, D3DRENDERSTATE_STIPPLEPATTERN06, D3DRENDERSTATE_STIPPLEPATTERN07, D3DRENDERSTATE_STIPPLEPATTERN08, D3DRENDERSTATE_STIPPLEPATTERN09, D3DRENDERSTATE_STIPPLEPATTERN10, D3DRENDERSTATE_STIPPLEPATTERN11, D3DRENDERSTATE_STIPPLEPATTERN12, D3DRENDERSTATE_STIPPLEPATTERN13, D3DRENDERSTATE_STIPPLEPATTERN14, D3DRENDERSTATE_STIPPLEPATTERN15, D3DRENDERSTATE_STIPPLEPATTERN16, D3DRENDERSTATE_STIPPLEPATTERN17, D3DRENDERSTATE_STIPPLEPATTERN18, D3DRENDERSTATE_STIPPLEPATTERN19, D3DRENDERSTATE_STIPPLEPATTERN20, D3DRENDERSTATE_STIPPLEPATTERN21, D3DRENDERSTATE_STIPPLEPATTERN22, D3DRENDERSTATE_STIPPLEPATTERN23, D3DRENDERSTATE_STIPPLEPATTERN24, D3DRENDERSTATE_STIPPLEPATTERN25, D3DRENDERSTATE_STIPPLEPATTERN26, D3DRENDERSTATE_STIPPLEPATTERN27, D3DRENDERSTATE_STIPPLEPATTERN28, D3DRENDERSTATE_STIPPLEPATTERN29, D3DRENDERSTATE_STIPPLEPATTERN30, D3DRENDERSTATE_STIPPLEPATTERN31, // newly retired for DX8
D3DRENDERSTATE_ANTIALIAS, D3DRENDERSTATE_TEXTUREPERSPECTIVE, D3DRENDERSTATE_COLORKEYENABLE, D3DRENDERSTATE_COLORKEYBLENDENABLE, D3DRENDERSTATE_STIPPLEDALPHA,
};
// list of retired renderstates - need to make sure these are
// filtered and never get from app directly to driver
const D3DRENDERSTATETYPE rsListRetired[] = { D3DRENDERSTATE_TEXTUREHANDLE, D3DRENDERSTATE_TEXTUREADDRESS, D3DRENDERSTATE_WRAPU, D3DRENDERSTATE_WRAPV, D3DRENDERSTATE_MONOENABLE, D3DRENDERSTATE_ROP2, D3DRENDERSTATE_PLANEMASK, D3DRENDERSTATE_TEXTUREMAG, D3DRENDERSTATE_TEXTUREMIN, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DRENDERSTATE_SUBPIXEL, D3DRENDERSTATE_SUBPIXELX, D3DRENDERSTATE_STIPPLEENABLE, D3DRENDERSTATE_BORDERCOLOR, D3DRENDERSTATE_TEXTUREADDRESSU, D3DRENDERSTATE_TEXTUREADDRESSV, D3DRENDERSTATE_MIPMAPLODBIAS, D3DRENDERSTATE_ANISOTROPY, D3DRENDERSTATE_TRANSLUCENTSORTINDEPENDENT, D3DRENDERSTATE_STIPPLEPATTERN00, D3DRENDERSTATE_STIPPLEPATTERN01, D3DRENDERSTATE_STIPPLEPATTERN02, D3DRENDERSTATE_STIPPLEPATTERN03, D3DRENDERSTATE_STIPPLEPATTERN04, D3DRENDERSTATE_STIPPLEPATTERN05, D3DRENDERSTATE_STIPPLEPATTERN06, D3DRENDERSTATE_STIPPLEPATTERN07, D3DRENDERSTATE_STIPPLEPATTERN08, D3DRENDERSTATE_STIPPLEPATTERN09, D3DRENDERSTATE_STIPPLEPATTERN10, D3DRENDERSTATE_STIPPLEPATTERN11, D3DRENDERSTATE_STIPPLEPATTERN12, D3DRENDERSTATE_STIPPLEPATTERN13, D3DRENDERSTATE_STIPPLEPATTERN14, D3DRENDERSTATE_STIPPLEPATTERN15, D3DRENDERSTATE_STIPPLEPATTERN16, D3DRENDERSTATE_STIPPLEPATTERN17, D3DRENDERSTATE_STIPPLEPATTERN18, D3DRENDERSTATE_STIPPLEPATTERN19, D3DRENDERSTATE_STIPPLEPATTERN20, D3DRENDERSTATE_STIPPLEPATTERN21, D3DRENDERSTATE_STIPPLEPATTERN22, D3DRENDERSTATE_STIPPLEPATTERN23, D3DRENDERSTATE_STIPPLEPATTERN24, D3DRENDERSTATE_STIPPLEPATTERN25, D3DRENDERSTATE_STIPPLEPATTERN26, D3DRENDERSTATE_STIPPLEPATTERN27, D3DRENDERSTATE_STIPPLEPATTERN28, D3DRENDERSTATE_STIPPLEPATTERN29, D3DRENDERSTATE_STIPPLEPATTERN30, D3DRENDERSTATE_STIPPLEPATTERN31, // newly retired for DX8
D3DRENDERSTATE_ANTIALIAS, D3DRENDERSTATE_TEXTUREPERSPECTIVE, D3DRENDERSTATE_COLORKEYENABLE, D3DRENDERSTATE_COLORKEYBLENDENABLE, D3DRENDERSTATE_STIPPLEDALPHA, };
/////////////////////////////////////////////////////////////////////////////
// //
// CD3DHal //
// //
/////////////////////////////////////////////////////////////////////////////
//---------------------------------------------------------------------
CD3DHal::CD3DHal() { //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// DO NOT PUT INITIALIZATION IN THE CONSTRUCTOR.
// Put it in Init() instead. This is because the device can be
// "Destroy()ed" and "Init()ed" anytime via Reset. In this
// situation, the constructor is never called. (snene 01/00)
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
} //---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CD3DHal::StateInitialize"
void CD3DHal::StateInitialize(BOOL bZEnable) { DWORD i,j;
// Initialize the bit array indicating the rstates needing non-trivial
// work.
for (i=0; i < sizeof(rsList) / sizeof(D3DRENDERSTATETYPE); ++i) rsVec.SetBit(rsList[i]); // Initialize the bit array indicating the retired rstates
for (i=0; i < sizeof(rsListRetired) / sizeof(D3DRENDERSTATETYPE); ++i) rsVecRetired.SetBit(rsListRetired[i]); // Initialize the bit array indicating the vertex processing only rstates
for (i=0; i < sizeof(rsVertexProcessingList) / sizeof(D3DRENDERSTATETYPE); ++i) rsVertexProcessingOnly.SetBit(rsVertexProcessingList[i]);
// Obviate Set(Render;TextureStage)State filtering 'redundant' device state settings
// since this is the init step.
// memset( this->rstates, 0xff, sizeof(DWORD)*D3D_MAXRENDERSTATES);
for (i=0; i<D3D_MAXRENDERSTATES; i++) this->rstates[i] = 0xbaadcafe; // memset( this->tsstates, 0xff, sizeof(DWORD)*D3DHAL_TSS_MAXSTAGES*D3DHAL_TSS_STATESPERSTAGE );
for (j=0; j<D3DHAL_TSS_MAXSTAGES; j++) for (i=0; i<D3DHAL_TSS_STATESPERSTAGE; i++) this->tsstates[j][i] = 0xbaadcafe;
CD3DBase::StateInitialize(bZEnable);
if (GetDDIType() < D3DDDITYPE_DX8) { SetRenderStateInternal(D3DRENDERSTATE_TEXTUREPERSPECTIVE, TRUE); SetRenderStateInternal(D3DRENDERSTATE_COLORKEYENABLE, FALSE); SetRenderStateInternal(D3DRENDERSTATE_COLORKEYBLENDENABLE, FALSE); SetRenderStateInternal(D3DRENDERSTATE_STIPPLEDALPHA, FALSE); }
if (GetDDIType() < D3DDDITYPE_DX7) { // send retired renderstate init's to pre-DX7 HALs only
SetRenderStateInternal( D3DRENDERSTATE_STIPPLEENABLE, FALSE); SetRenderStateInternal( D3DRENDERSTATE_MONOENABLE, FALSE); SetRenderStateInternal( D3DRENDERSTATE_ROP2, R2_COPYPEN); SetRenderStateInternal( D3DRENDERSTATE_PLANEMASK, (DWORD)~0); SetRenderStateInternal( D3DRENDERSTATE_WRAPU, FALSE); SetRenderStateInternal( D3DRENDERSTATE_WRAPV, FALSE); SetRenderStateInternal( D3DRENDERSTATE_ANTIALIAS, FALSE); SetRenderStateInternal( D3DRENDERSTATE_SUBPIXEL, FALSE); /* 30 */ SetRenderStateInternal( D3DRENDERSTATE_SUBPIXELX, FALSE); SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN00, 0); SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN01, 0); /* 40 */ SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN02, 0); SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN03, 0); SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN04, 0); SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN05, 0); SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN06, 0); SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN07, 0); SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN08, 0); SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN09, 0); SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN10, 0); SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN11, 0); /* 50 */ SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN12, 0); SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN13, 0); SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN14, 0); SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN15, 0); SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN16, 0); SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN17, 0); SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN18, 0); SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN19, 0); SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN20, 0); SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN21, 0); /* 60 */ SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN22, 0); SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN23, 0); SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN24, 0); SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN25, 0); SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN26, 0); SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN27, 0); SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN28, 0); SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN29, 0); SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN30, 0); SetRenderStateInternal( D3DRENDERSTATE_STIPPLEPATTERN31, 0); /* 70 */ }
if( BehaviorFlags() & D3DCREATE_SOFTWARE_VERTEXPROCESSING ) { SwitchVertexProcessingMode(TRUE); rstates[D3DRS_SOFTWAREVERTEXPROCESSING] = TRUE; } else if( BehaviorFlags() & D3DCREATE_HARDWARE_VERTEXPROCESSING ) { SwitchVertexProcessingMode(FALSE); rstates[D3DRS_SOFTWAREVERTEXPROCESSING] = FALSE; } else if( BehaviorFlags() & D3DCREATE_MIXED_VERTEXPROCESSING ) { SetRenderStateInternal( D3DRS_SOFTWAREVERTEXPROCESSING, 0); } else { D3D_INFO( 0, "No Vertex Processing behavior specified, assuming software" ); SwitchVertexProcessingMode(TRUE); rstates[D3DRS_SOFTWAREVERTEXPROCESSING] = TRUE; } }
/*
* Initialisation - class part and device part */
//---------------------------------------------------------------------
HRESULT CD3DHal::D3DFE_Create() { DDSURFACEDESC ddsd; HRESULT hr; const D3DCAPS8 *pCaps = GetD3DCaps();
if (m_pDDI->GetDDIType() < D3DDDITYPE_DX7) { m_dwRuntimeFlags |= D3DRT_ONLY2FLOATSPERTEXTURE; } else if (m_pDDI->GetDDIType() < D3DDDITYPE_DX8) { // Some drivers (G200, G400) cannot handle more than 2 floats in
// texture coordinates, even they are supposed to. We set the
// runtime bit to mark such drivers and compute output FVF for vertex
// shaders accordingly
if (!(pCaps->TextureCaps & D3DPTEXTURECAPS_PROJECTED || pCaps->TextureCaps & D3DPTEXTURECAPS_CUBEMAP)) { m_dwRuntimeFlags |= D3DRT_ONLY2FLOATSPERTEXTURE; } } if (!(pCaps->TextureCaps & D3DPTEXTURECAPS_PROJECTED)) m_dwRuntimeFlags |= D3DRT_EMULATEPROJECTEDTEXTURE;
if (pCaps && pCaps->FVFCaps) { this->m_pv->dwMaxTextureIndices = pCaps->FVFCaps & D3DFVFCAPS_TEXCOORDCOUNTMASK; if (pCaps->FVFCaps & D3DFVFCAPS_DONOTSTRIPELEMENTS) this->m_pv->dwDeviceFlags |= D3DDEV_DONOTSTRIPELEMENTS;
DWORD value; if ((GetD3DRegValue(REG_DWORD, "DisableStripFVF", &value, 4) && value != 0)) { this->m_pv->dwDeviceFlags |= D3DDEV_DONOTSTRIPELEMENTS; } } else { this->m_pv->dwMaxTextureIndices = 1; }
this->dwFEFlags |= D3DFE_FRONTEND_DIRTY;
#if DBG
this->dwCaller=0; memset(this->dwPrimitiveType,0,sizeof(this->dwPrimitiveType)); memset(this->dwVertexType1,0,sizeof(this->dwVertexType1)); memset(this->dwVertexType2,0,sizeof(this->dwVertexType2)); #endif
// True for software rendering
m_dwNumStreams = __NUMSTREAMS; m_dwMaxUserClipPlanes = __MAXUSERCLIPPLANES;
this->m_pv->dwClipMaskOffScreen = 0xFFFFFFFF; if (pCaps != NULL) { if (pCaps->GuardBandLeft != 0.0f || pCaps->GuardBandRight != 0.0f || pCaps->GuardBandTop != 0.0f || pCaps->GuardBandBottom != 0.0f) { this->m_pv->dwDeviceFlags |= D3DDEV_GUARDBAND; this->m_pv->dwClipMaskOffScreen = ~__D3DCS_INGUARDBAND; DWORD v; if (GetD3DRegValue(REG_DWORD, "DisableGB", &v, 4) && v != 0) { this->m_pv->dwDeviceFlags &= ~D3DDEV_GUARDBAND; this->m_pv->dwClipMaskOffScreen = 0xFFFFFFFF; } #if DBG
// Try to get test values for the guard band
char value[80]; if (GetD3DRegValue(REG_SZ, "GuardBandLeft", &value, 80) && value[0] != 0) sscanf(value, "%f", &pCaps->GuardBandLeft); if (GetD3DRegValue(REG_SZ, "GuardBandRight", &value, 80) && value[0] != 0) sscanf(value, "%f", &pCaps->GuardBandRight); if (GetD3DRegValue(REG_SZ, "GuardBandTop", &value, 80) && value[0] != 0) sscanf(value, "%f", &pCaps->GuardBandTop); if (GetD3DRegValue(REG_SZ, "GuardBandBottom", &value, 80) && value[0] != 0) sscanf(value, "%f", &pCaps->GuardBandBottom); #endif // DBG
} }
LIST_INITIALIZE(&this->specular_tables); this->specular_table = NULL;
this->lightVertexFuncTable = &lightVertexTable; m_pv->lighting.activeLights = NULL;
this->m_ClipStatus.ClipUnion = 0; this->m_ClipStatus.ClipIntersection = ~0;
m_pv->pDDI = m_pDDI;
return S_OK; }
void CD3DHal::D3DFE_Destroy() { // Destroy lighting data
SpecularTable *spec; SpecularTable *spec_next;
for (spec = LIST_FIRST(&this->specular_tables); spec; spec = spec_next) { spec_next = LIST_NEXT(spec,list); D3DFree(spec); } LIST_INITIALIZE(&specular_tables);
delete m_pLightArray; m_pLightArray = NULL;
delete m_pv; m_pv = NULL;
delete m_pConvObj; m_pConvObj = NULL;
if (m_clrRects) { D3DFree(m_clrRects); m_clrRects = NULL; } }
/*
* Generic device part destroy */ CD3DHal::~CD3DHal() { Destroy(); }
void CD3DHal::Destroy() { try // Since Destroy() can be called directly by fw
{ //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// MUST CLEANUP AND RELEASE CURRENTLY SET TEXTURES BEFORE
// DOING ANY OTHER WORK, else we will get into situations
// where we are calling FlushStates or batching DDI tokens.
CleanupTextures(); //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
/* Clear flags that could prohibit cleanup */ m_dwHintFlags &= ~(D3DDEVBOOL_HINTFLAGS_INSCENE);
// Destroy vertex shaders. We need to delete vertex shaders completely
// to preserve behavior for DX8.0 apps. For DX8.1 apps we delete only
// PSGP part of a vertex shader. The rest will be used to re-create
// the shader during Reset()
if (m_pVShaderArray != NULL) { UINT size = m_pVShaderArray->GetSize(); for (UINT i=0; i < size; i++) { UINT Handle = m_pVShaderArray->HandleFromIndex(i); CVShader* pShader = (CVShader*)m_pVShaderArray->GetObject(Handle); if (pShader) { if (Enum()->GetAppSdkVersion() == D3D_SDK_VERSION_DX8) { m_pVShaderArray->ReleaseHandle(Handle, TRUE); } else { // We need to delete PSGP shader object before deleting
// D3DFE_PROCESSVERTICES object, because AMD has keeps a
// pointer to it inside the code object
if (pShader->m_dwFlags & CVShader::SOFTWARE) { delete pShader->m_pCode; pShader->m_pCode = NULL; } } } } } // Destroy pixel shaders for DX8.0 apps to preserve trhe original behavior
if (m_pPShaderArray != NULL) { UINT size = m_pPShaderArray->GetSize(); for (UINT i=0; i < size; i++) { UINT Handle = m_pPShaderArray->HandleFromIndex(i); CPShader* pShader = (CPShader*)m_pPShaderArray->GetObject(Handle); if (pShader) { if (Enum()->GetAppSdkVersion() == D3D_SDK_VERSION_DX8) { m_pPShaderArray->ReleaseHandle(Handle, TRUE); } } } }
if (m_pv) { if ( 0 != m_pv->pGeometryFuncs && (LPVOID)m_pv->pGeometryFuncs != (LPVOID)GeometryFuncsGuaranteed) { delete m_pv->pGeometryFuncs; m_pv->pGeometryFuncs = 0; }
if ( 0 != GeometryFuncsGuaranteed) { delete GeometryFuncsGuaranteed; GeometryFuncsGuaranteed = 0; m_pv->pGeometryFuncs = 0; } }
this->D3DFE_Destroy();
if ( 0 != rstates) { delete[] rstates; rstates = 0; }
delete pMatrixDirtyForDDI; pMatrixDirtyForDDI = NULL;
CD3DBase::Destroy(); } catch(HRESULT ret) { DPF_ERR("There was some error when Reset()ing the device; as a result some resources may not be freed."); } }
/*
* Create a device. * * This method * implements the CreateDevice method of the CEnum object. (The CEnum * object exposes the IDirect3D8 interface which supports enumeration * etc.) * */
#undef DPF_MODNAME
#define DPF_MODNAME "CEnum::CreateDevice"
STDMETHODIMP CEnum::CreateDevice( UINT iAdapter, D3DDEVTYPE DeviceType, HWND hwndFocusWindow, DWORD dwFlags, D3DPRESENT_PARAMETERS *pPresentationParams, IDirect3DDevice8 **ppNewInterface) { API_ENTER(this);
PD3D8_DEVICEDATA pDD; LPD3DBASE pd3ddev; HRESULT ret = D3D_OK; VOID* pInit = NULL;
if (!VALID_PTR_PTR(ppNewInterface)) { DPF_ERR("Invalid IDirect3DDevice8* pointer, CreateDevice fails"); return D3DERR_INVALIDCALL; }
// Zero out out parameters
*ppNewInterface = NULL;
if (!VALID_PTR(pPresentationParams, sizeof(D3DPRESENT_PARAMETERS))) { DPF_ERR("Invalid D3DPRESENT_PARAMETERS pointer, CreateDevice fails"); return D3DERR_INVALIDCALL; }
// Check that fullscreen parameters are correct
if (pPresentationParams->Windowed) { if (pPresentationParams->FullScreen_RefreshRateInHz != 0) { DPF_ERR("FullScreen_RefreshRateInHz must be zero for windowed mode. CreateDevice fails."); return D3DERR_INVALIDCALL; } if (pPresentationParams->FullScreen_PresentationInterval != 0) { DPF_ERR("FullScreen_PresentationInterval must be zero for windowed mode. CreateDevice fails."); return D3DERR_INVALIDCALL; } } else { DWORD interval = pPresentationParams->FullScreen_PresentationInterval; switch (interval) { case D3DPRESENT_INTERVAL_DEFAULT: case D3DPRESENT_INTERVAL_ONE: case D3DPRESENT_INTERVAL_TWO: case D3DPRESENT_INTERVAL_THREE: case D3DPRESENT_INTERVAL_FOUR: case D3DPRESENT_INTERVAL_IMMEDIATE: break; default: DPF_ERR("Invalid value for FullScreen_PresentationInterval. CreateDevice Fails."); return D3DERR_INVALIDCALL; } } if (pPresentationParams->BackBufferFormat == D3DFMT_UNKNOWN) { DPF_ERR("Invalid backbuffer format specified. CreateDevice fails."); return D3DERR_INVALIDCALL; }
if (pPresentationParams->Flags & ~D3DPRESENTFLAG_LOCKABLE_BACKBUFFER) { DPF_ERR("Invalid flag for Flags. CreateDevice fails."); return D3DERR_INVALIDCALL; }
// Validate the HWNDs that we are given
if (hwndFocusWindow && !IsWindow(hwndFocusWindow)) { DPF_ERR("Invalid HWND specified for hwndFocusWindow, CreateDevice fails"); return D3DERR_INVALIDCALL; } if (pPresentationParams->hDeviceWindow && !IsWindow(pPresentationParams->hDeviceWindow)) { DPF_ERR("Invalid HWND specified for PresentationParams.hDeviceWindow. CreateDevice fails."); return D3DERR_INVALIDCALL; }
// Make sure that we are given a focus window or a device window
if (NULL == hwndFocusWindow) { if (!pPresentationParams->Windowed) { DPF_ERR("Fullscreen CreateDevice must specify Focus window"); return D3DERR_INVALIDCALL; } else if (NULL == pPresentationParams->hDeviceWindow) { DPF_ERR("Neither hDeviceWindow nor Focus window specified. CreateDevice Failed."); return D3DERR_INVALIDCALL; } }
if (iAdapter >= m_cAdapter) { DPF_ERR("Invalid iAdapter parameter passed to CreateDevice"); return D3DERR_INVALIDCALL; }
if (dwFlags & ~VALID_D3DCREATE_FLAGS) { DPF_ERR("Invalid BehaviorFlags passed to CreateDevice"); return D3DERR_INVALIDCALL; }
// Check that exactly one of the vertex processing flags is set
DWORD dwVertexProcessingFlags = dwFlags & (D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MIXED_VERTEXPROCESSING);
if (dwVertexProcessingFlags != D3DCREATE_HARDWARE_VERTEXPROCESSING && dwVertexProcessingFlags != D3DCREATE_SOFTWARE_VERTEXPROCESSING && dwVertexProcessingFlags != D3DCREATE_MIXED_VERTEXPROCESSING) { DPF_ERR("Invalid Flags parameter to CreateDevice: Exactly One of the" " following must be set: D3DCREATE_HARDWARE_VERTEXPROCESSING," " D3DCREATE_SOFTWARE_VERTEXPROCESSING or" " D3DCREATE_MIXED_VERTEXPROCESSING"); return D3DERR_INVALIDCALL; }
if (DeviceType == D3DDEVTYPE_SW) { pInit = m_pSwInitFunction; if (pInit == NULL) { D3D_ERR("App specified D3DDEVTYPE_SW without first registering a software device. CreateDevice Failed."); return D3DERR_INVALIDCALL; } GetSwCaps(iAdapter); } else if (DeviceType == D3DDEVTYPE_REF) { GetRefCaps(iAdapter); }
ret = InternalDirectDrawCreate(&pDD, &m_AdapterInfo[iAdapter], DeviceType, pInit, GetUnknown16(iAdapter), m_AdapterInfo[iAdapter].HALCaps.pGDD8SupportedFormatOps, m_AdapterInfo[iAdapter].HALCaps.GDD8NumSupportedFormatOps); if( FAILED(ret) ) { D3D_ERR("Failed to create DirectDraw. CreateDevice Failed."); return ret; }
if((dwFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING) != 0) { if((dwFlags & D3DCREATE_PUREDEVICE) != 0) { D3D_ERR("Pure device cannot perform software processing. CreateDevice Failed."); InternalDirectDrawRelease(pDD); return D3DERR_INVALIDCALL; } } else if((dwFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING) != 0) { if((pDD->DriverData.D3DCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0) { D3D_ERR("Device cannot perform hardware processing"); InternalDirectDrawRelease(pDD); return D3DERR_INVALIDCALL; } } else if((dwFlags & D3DCREATE_MIXED_VERTEXPROCESSING) != 0) { if((pDD->DriverData.D3DCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0 || (dwFlags & D3DCREATE_PUREDEVICE) != 0) { D3D_ERR("Device cannot perform mixed processing because driver cannot do hardware T&L. CreateDevice Failed."); InternalDirectDrawRelease(pDD); return D3DERR_INVALIDCALL; } } else { if((dwFlags & D3DCREATE_PUREDEVICE) != 0) { if((pDD->DriverData.D3DCaps.DevCaps & D3DDEVCAPS_PUREDEVICE) == 0) { D3D_ERR("Hardware should be capable of creating a pure device"); InternalDirectDrawRelease(pDD); return D3DERR_INVALIDCALL; } } else { D3D_ERR("Must specify software, hardware or mixed vertex processing"); InternalDirectDrawRelease(pDD); return D3DERR_INVALIDCALL; } }
switch (DeviceType) { case D3DDEVTYPE_SW: case D3DDEVTYPE_REF: case D3DDEVTYPE_HAL: if (dwFlags & D3DCREATE_PUREDEVICE) { pd3ddev = new CD3DBase(); } else { pd3ddev = static_cast<LPD3DBASE>(new CD3DHal()); } break; default: D3D_ERR("Unrecognized or unsupported DeviceType. CreateDevice Failed."); InternalDirectDrawRelease(pDD); return D3DERR_INVALIDCALL; }
if (!pd3ddev) { D3D_ERR("Failed to allocate space for the device object. CreateDevice Failed."); InternalDirectDrawRelease(pDD); return (E_OUTOFMEMORY); }
#if DBG
{ char DevTypeMsg[256]; _snprintf( DevTypeMsg, 256, "=======================" ); switch( DeviceType ) { case D3DDEVTYPE_HAL: _snprintf( DevTypeMsg, 256, "%s Hal", DevTypeMsg ); break; case D3DDEVTYPE_SW: _snprintf( DevTypeMsg, 256, "%s Pluggable SW", DevTypeMsg ); break; case D3DDEVTYPE_REF: _snprintf( DevTypeMsg, 256, "%s Reference", DevTypeMsg ); break; default: _snprintf( DevTypeMsg, 256, "%s Unknown", DevTypeMsg ); break; } if (dwFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING) { _snprintf( DevTypeMsg, 256, "%s HWVP", DevTypeMsg ); } else if (dwFlags & D3DCREATE_MIXED_VERTEXPROCESSING) { _snprintf( DevTypeMsg, 256, "%s MixedVP", DevTypeMsg ); } else if (dwFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING) { _snprintf( DevTypeMsg, 256, "%s SWVP", DevTypeMsg ); } if (dwFlags & D3DCREATE_PUREDEVICE) { _snprintf( DevTypeMsg, 256, "%s Pure", DevTypeMsg ); } _snprintf( DevTypeMsg, 256, "%s device selected", DevTypeMsg ); D3D_INFO( 0, DevTypeMsg ); } #endif
//
// FW's Init
//
ret = static_cast<CBaseDevice*>(pd3ddev)->Init( pDD, DeviceType, hwndFocusWindow, dwFlags, pPresentationParams, iAdapter, this); if (FAILED(ret)) { D3D_ERR("Failed to initialize Framework Device. CreateDevice Failed."); delete pd3ddev; return ret; }
// We try and create a dummy vidmem vertexbuffer. If this doesn't
// succeed, we just turn off vidmem VBs. This is to work around
// the Rage 128 driver that reports DDERR_OUTOFVIDEOMEMORY even
// though it simply doesn't support vidmem VBs
if(!IS_DX8HAL_DEVICE(pd3ddev)) { #ifdef WIN95
//ON 9x we probe to see if the driver can do vidmem VBs...
CVertexBuffer *pVertexBuffer; ret = CVertexBuffer::CreateDriverVertexBuffer(pd3ddev, 1024, D3DFVF_TLVERTEX, D3DUSAGE_WRITEONLY | D3DUSAGE_DONOTCLIP, D3DUSAGE_WRITEONLY | D3DUSAGE_DONOTCLIP | D3DUSAGE_LOCK, D3DPOOL_DEFAULT, D3DPOOL_DEFAULT, REF_INTERNAL, &pVertexBuffer); if(FAILED(ret)) { if(pd3ddev->VBFailOversDisabled()) { DPF_ERR("Cannot create Vidmem vertex buffer. Will ***NOT*** failover to Sysmem."); return ret; } DPF(1,"Driver doesnt support VidMemVBs which is fine"); } else { // Get rid of the vb
pVertexBuffer->DecrementUseCount(); pd3ddev->EnableVidmemVBs(); } #else //WIN95
//On NT we require the drivers to tell us (by setting D3DDEVCAPS_HWVERTEXBUFFER)
//Turn off DX7 driver VBs on NT if asked to do so...
DWORD value; if ((GetD3DRegValue(REG_DWORD, "DisableVidMemVBs", &value, 4) != 0) && (value != 0)) { pd3ddev->DisableVidmemVBs(); } #endif //!WIN95
}
ret = pd3ddev->Init(); if (ret != D3D_OK) { delete pd3ddev; D3D_ERR("Failed to initialize D3DDevice. CreateDevice Failed."); return ret; }
// Looks like everything is in order
*ppNewInterface = static_cast<IDirect3DDevice8*>(pd3ddev);
#ifdef APIPROF
CApiProfileDevice* profile = new CApiProfileDevice; if (profile) { if (profile->Init() == D3D_OK) { profile->SetDevice(*ppNewInterface); *ppNewInterface = static_cast<IDirect3DDevice8*>(profile); } else { delete profile; } } #endif // APIPROF
return S_OK; }
#ifdef _X86_
// --------------------------------------------------------------------------
// Detect 3D extensions
// --------------------------------------------------------------------------
BOOL _asm_isX3D() { DWORD retval = 0; _asm { pushad ; CPUID trashes lots - save everything mov eax,80000000h ; Check for extended CPUID support
;;; We need to upgrade our compiler ;;; CPUID == 0f,a2 _emit 0x0f _emit 0xa2
cmp eax,80000001h ; Jump if no extended CPUID jb short done ;
mov eax,80000001h ; Check for feature ;;; CPUID == 0f,a2 _emit 0x0f _emit 0xa2
xor eax,eax ; test edx,80000000h ; setnz al ; mov retval,eax ;
done: popad ; Restore everything }; return retval; }
static BOOL isX3Dprocessor(void) { __try { if( _asm_isX3D() ) { return TRUE; } } __except(GetExceptionCode() == STATUS_ILLEGAL_INSTRUCTION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { } return FALSE; } //---------------------------------------------------------------------
// Detects Intel SSE processor
//
#pragma optimize("", off)
#define CPUID _asm _emit 0x0f _asm _emit 0xa2
#define SSE_PRESENT 0x02000000 // bit number 25
#define WNI_PRESENT 0x04000000 // bit number 26
DWORD IsIntelSSEProcessor(void) { DWORD retval = 0; DWORD RegisterEAX; DWORD RegisterEDX; char VendorId[12]; const char IntelId[13]="GenuineIntel";
__try { _asm { xor eax,eax CPUID mov RegisterEAX, eax mov dword ptr VendorId, ebx mov dword ptr VendorId+4, edx mov dword ptr VendorId+8, ecx } } __except (1) { return retval; }
// make sure EAX is > 0 which means the chip
// supports a value >=1. 1 = chip info
if (RegisterEAX == 0) return retval;
// this CPUID can't fail if the above test passed
__asm { mov eax,1 CPUID mov RegisterEAX,eax mov RegisterEDX,edx }
if (RegisterEDX & SSE_PRESENT) { retval |= D3DCPU_SSE; }
if (RegisterEDX & WNI_PRESENT) { retval |= D3DCPU_WLMT; }
return retval; } #pragma optimize("", on)
// IsProcessorFeatureAvailable() is supported only by WINNT. For other OS
// we emulate it
#ifdef WINNT
static BOOL D3DIsProcessorFeaturePresent(UINT feature) { switch (feature) { // WINNT does not recognize Willamette processor when we use
// PF_XMMI64_INSTRUCTIONS_AVAILABLE, so use our detection instead
case PF_XMMI64_INSTRUCTIONS_AVAILABLE: { DWORD flags = IsIntelSSEProcessor(); return flags & D3DCPU_WLMT; } default: return IsProcessorFeaturePresent(feature); } }
#else
#define PF_XMMI_INSTRUCTIONS_AVAILABLE 6
#define PF_3DNOW_INSTRUCTIONS_AVAILABLE 7
#define PF_XMMI64_INSTRUCTIONS_AVAILABLE 10
static BOOL D3DIsProcessorFeaturePresent(UINT feature) { switch (feature) { case PF_XMMI_INSTRUCTIONS_AVAILABLE: { if (IsWin95()) return FALSE; DWORD flags = IsIntelSSEProcessor(); return flags & D3DCPU_SSE; } case PF_3DNOW_INSTRUCTIONS_AVAILABLE: return isX3Dprocessor(); case PF_XMMI64_INSTRUCTIONS_AVAILABLE: { if (IsWin95()) return FALSE; DWORD flags = IsIntelSSEProcessor(); return flags & D3DCPU_WLMT; } default: return FALSE; } } #endif // WINNT
#endif // _X86_
//------------------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CD3DHal::InitDevice"
HRESULT CD3DHal::InitDevice() { HRESULT ret;
// Initialize values so we don't crash at shutdown
this->GeometryFuncsGuaranteed = NULL; this->rstates = NULL; m_pLightArray = NULL; m_pv = NULL; m_pCurrentShader = NULL; m_pConvObj = NULL; pMatrixDirtyForDDI = NULL; m_clrRects = NULL; m_clrCount = 0; m_pv = new D3DFE_PROCESSVERTICES; if (m_pv == NULL) { D3D_ERR("Could not allocate the FE/PSGP data structure (D3DFE_PROCESSVERTICES)."); return E_OUTOFMEMORY; } m_pv->pGeometryFuncs = NULL;
ret = CD3DBase::InitDevice(); if (ret != D3D_OK) { D3D_ERR("Failed to initialize CD3DBase."); return(ret); }
pMatrixDirtyForDDI = new CPackedBitArray; if( pMatrixDirtyForDDI == NULL ) { D3D_ERR("Could not allocate memory for internal data structure pMatrixDirtyForDDI."); return E_OUTOFMEMORY; }
if (FAILED(rsVec.Init(D3D_MAXRENDERSTATES)) || FAILED(rsVecRetired.Init(D3D_MAXRENDERSTATES)) || FAILED(rsVertexProcessingOnly.Init(D3D_MAXRENDERSTATES)) || FAILED(pMatrixDirtyForDDI->Init(D3D_MAXTRANSFORMSTATES))) { D3D_ERR("Could not allocate memory for renderstate processing bit vectors"); return E_OUTOFMEMORY; }
m_pLightArray = new CHandleArray; if (m_pLightArray == NULL) { D3D_ERR("Could not allocate memory for internal data structure m_pLightArray"); return E_OUTOFMEMORY; }
dwFEFlags = 0;
// Initialize FEFlags content that depends on DDI type
if ( (GetDDIType() == D3DDDITYPE_DX7TL) || (GetDDIType() == D3DDDITYPE_DX8TL) ) dwFEFlags |= D3DFE_TLHAL;
// Since this is HAL, initialize it to use the software pipeline
// this will be turned off when the SW/HW renderstate is set.
m_pv->dwVIDIn = 0;
m_pv->pD3DMappedTexI = (LPVOID*)(m_lpD3DMappedTexI);
/*-------------------------------------------------------------------------
* 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. *-----------------------------------------------------------------------*/
this->GeometryFuncsGuaranteed = new D3DFE_PVFUNCSI; if (this->GeometryFuncsGuaranteed == NULL) { D3D_ERR("Could not allocate memory for internal data structure GeometryFuncsGuaranteed"); return E_OUTOFMEMORY; } // Software constant register buffer must handle all constants, provided by
// hardware, to make Set/Get constants possible
this->GeometryFuncsGuaranteed->m_VertexVM.Init(GetD3DCaps()->MaxVertexShaderConst);
m_pv->pGeometryFuncs = (LPD3DFE_PVFUNCS)GeometryFuncsGuaranteed;
if (this->GeometryFuncsGuaranteed == NULL) { D3D_ERR("Could not allocate memory for FE/PSGP function table."); return D3DERR_INVALIDCALL; } // set up flag to use MMX when requested RGB
BOOL bUseMMXAsRGBDevice = FALSE;
D3DSURFACE_DESC desc = this->RenderTarget()->InternalGetDesc();
/*
* Check if the 3D cap is set on the surface. */ if ((desc.Usage & D3DUSAGE_RENDERTARGET) == 0) { D3D_ERR("**** The D3DUSAGE_RENDERTARGET is not set on this surface."); D3D_ERR("**** You need to add D3DUSAGE_RENDERTARGET to the Usage parameter"); D3D_ERR("**** when creating the surface."); return (D3DERR_INVALIDCALL); }
// Create front-end support structures.
ret = this->D3DFE_Create(); if (ret != D3D_OK) { D3D_ERR("Failed to create front-end data-structures."); goto handle_err; }
// In all other cases we simply allocate memory for rstates
rstates = new DWORD[D3D_MAXRENDERSTATES];
m_pv->lpdwRStates = this->rstates;
#ifndef PROFILE4
#ifdef _X86_
if ((ULONG_PTR)&m_pv->view & 0xF) { char s[256]; sprintf(s, "0%xh \n", (ULONG_PTR)&m_pv->view); OutputDebugString("INTERNAL ERROR:View matrix in D3DFE_PROCESSVERTICES structure must be aligned to 16 bytes\n"); OutputDebugString(s); ret = D3DERR_INVALIDCALL; goto handle_err; } // 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; } // value =
// 0 - PSGP enabled
// 1 - PSGP disabled
// 2 - X3D PSGP disabled
if (value != 1) { // Ask the PV implementation to create a device specific "context"
LPD3DFE_PVFUNCS pOptGeoFuncs = m_pv->pGeometryFuncs;
// TODO (bug 40438): Remove DLL interface for final
// Try to use PSGP DLL first
if (pfnFEContextCreate) { ret = pfnFEContextCreate(m_pv->dwDeviceFlags, &pOptGeoFuncs); if ((ret == D3D_OK) && pOptGeoFuncs) { D3D_INFO(0, "Using PSGP DLL"); m_pv->pGeometryFuncs = pOptGeoFuncs; goto l_chosen; } }
if (D3DIsProcessorFeaturePresent(PF_3DNOW_INSTRUCTIONS_AVAILABLE) && value != 2) { ret = x3DContextCreate(m_pv->dwDeviceFlags, &pOptGeoFuncs); if (ret == S_OK && pOptGeoFuncs) { D3D_INFO(0, "Using X3D PSGP"); m_pv->pGeometryFuncs = pOptGeoFuncs; goto l_chosen; } } if (D3DIsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE)) { ret = wlmt_FEContextCreate(m_pv->dwDeviceFlags, &pOptGeoFuncs); if (ret == S_OK && pOptGeoFuncs) { D3D_INFO(0, "Using WLMT PSGP"); m_pv->pGeometryFuncs = pOptGeoFuncs; goto l_chosen; } } if (D3DIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE)) { ret = katmai_FEContextCreate(m_pv->dwDeviceFlags, &pOptGeoFuncs); if (ret == S_OK && pOptGeoFuncs) { D3D_INFO(0, "Using P3 PSGP"); m_pv->pGeometryFuncs = pOptGeoFuncs; goto l_chosen; } } l_chosen:; }
#endif // _X86_
#endif // PROFILE4
{ if (HVbuf.Grow((__INIT_VERTEX_NUMBER*2)*sizeof(D3DFE_CLIPCODE)) != DD_OK) { D3D_ERR( "Could not allocate memory for internal buffer HVBuf" ); ret = E_OUTOFMEMORY; goto handle_err; } }
// Setup lights
if( FAILED( m_pLightArray->Grow( 8 ) ) ) { D3D_ERR( "Could not allocate memory for the light array" ); ret = E_OUTOFMEMORY; goto handle_err; } LIST_INITIALIZE(&m_ActiveLights);
// Setup material
memset(&m_pv->lighting.material, 0, sizeof(m_pv->lighting.material));
// Set viewport to update front-end data
SetViewportI(&m_Viewport);
m_pv->PointSizeMax = GetD3DCaps()->MaxPointSize; { DWORD EmulatePointSprites = 1; GetD3DRegValue(REG_DWORD, "EmulatePointSprites", &EmulatePointSprites, sizeof(DWORD)); if ((m_pv->PointSizeMax == 0 || !(GetD3DCaps()->FVFCaps & D3DFVFCAPS_PSIZE)) && EmulatePointSprites) { m_dwRuntimeFlags |= D3DRT_DOPOINTSPRITEEMULATION; if (m_pv->PointSizeMax == 0) m_pv->PointSizeMax = __MAX_POINT_SIZE; else m_dwRuntimeFlags |= D3DRT_SUPPORTSPOINTSPRITES; } } m_pfnPrepareToDraw = NULL;
return (D3D_OK);
handle_err: return(ret); } //---------------------------------------------------------------------
DWORD ProcessRects(CD3DHal* pDevI, DWORD dwCount, CONST D3DRECT* rects) { RECT vwport; DWORD i,j;
/*
* Rip through the rects and validate that they * are within the viewport. */
if (dwCount == 0 && rects == NULL) { dwCount = 1; } #if DBG
else if (rects == NULL) { D3D_ERR("The rects parameter is NULL."); throw D3DERR_INVALIDCALL; } #endif
if (dwCount > pDevI->m_clrCount) { LPD3DRECT newRects; if (D3D_OK == D3DMalloc((void**)&newRects, dwCount * sizeof(D3DRECT))) { memcpy((void*)newRects,(void*)pDevI->m_clrRects, pDevI->m_clrCount* sizeof(D3DRECT)); D3DFree((LPVOID)pDevI->m_clrRects); pDevI->m_clrRects = newRects; } else { pDevI->m_clrCount = 0; D3DFree((LPVOID)pDevI->m_clrRects); pDevI->m_clrRects = NULL; D3D_ERR("failed to allocate space for rects"); throw E_OUTOFMEMORY; } } pDevI->m_clrCount = dwCount;
// If nothing is specified, assume the viewport needs to be cleared
if (!rects) { pDevI->m_clrRects[0].x1 = pDevI->m_Viewport.X; pDevI->m_clrRects[0].y1 = pDevI->m_Viewport.Y; pDevI->m_clrRects[0].x2 = pDevI->m_Viewport.X + pDevI->m_Viewport.Width; pDevI->m_clrRects[0].y2 = pDevI->m_Viewport.Y + pDevI->m_Viewport.Height; return 1; } else { vwport.left = pDevI->m_Viewport.X; vwport.top = pDevI->m_Viewport.Y; vwport.right = pDevI->m_Viewport.X + pDevI->m_Viewport.Width; vwport.bottom = pDevI->m_Viewport.Y + pDevI->m_Viewport.Height;
j=0; for (i = 0; i < dwCount; i++) { if (IntersectRect((LPRECT)(pDevI->m_clrRects + j), &vwport, (LPRECT)(rects + i))) j++; } return j; } } //---------------------------------------------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "CD3DHal::ClearI"
void CD3DHal::ClearI(DWORD dwCount, CONST D3DRECT* rects, DWORD dwFlags, D3DCOLOR dwColor, D3DVALUE dvZ, DWORD dwStencil) { dwCount = ProcessRects(this, dwCount, rects); // Device should never receive 0 count, because for Pure device this
// means "clear whole viewport"
if (dwCount != 0) { // Call DDI specific Clear routine
m_pDDI->Clear(dwFlags, dwCount, m_clrRects, dwColor, dvZ, dwStencil); } }
|