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.
1534 lines
58 KiB
1534 lines
58 KiB
/*==========================================================================;
|
|
*
|
|
* Copyright (C) 1995-1997 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: d3di.hpp
|
|
* Content: Direct3D internal include file
|
|
*
|
|
* $Id:
|
|
*
|
|
* History:
|
|
* Date By Reason
|
|
* ==== == ======
|
|
* 05/11/95 stevela Initial rev with this header.
|
|
*
|
|
***************************************************************************/
|
|
|
|
#ifndef _D3DI_HPP
|
|
#define _D3DI_HPP
|
|
|
|
#include "ddrawp.h"
|
|
#include "d3dp.h"
|
|
#include "d3dmem.h"
|
|
|
|
#if !defined(BUILD_DDDDK)
|
|
extern "C" {
|
|
#include "ddrawi.h"
|
|
};
|
|
#include "object.h"
|
|
#include "lists.hpp"
|
|
|
|
#include <d3ditype.h>
|
|
#include <d3dutil.h>
|
|
|
|
#include <d3dfe.hpp>
|
|
|
|
// Allow vtable hacking
|
|
#define VTABLE_HACK
|
|
|
|
// DEBUG_PIPELINE is defined to check performance and to allow to choose
|
|
// diifferent paths in the geometry pipeline
|
|
|
|
#if DBG
|
|
#define DEBUG_PIPELINE
|
|
#endif // DBG
|
|
|
|
#ifndef WIN95
|
|
// This is NT only
|
|
// Comment this out to disable registry based VidMemVB enables
|
|
#define __DISABLE_VIDMEM_VBS__
|
|
#endif
|
|
|
|
//--------------------------------------------------------------------
|
|
const DWORD __INIT_VERTEX_NUMBER = 1024;// Initial number of vertices in TL and
|
|
// clip flag buffers
|
|
const DWORD __MAX_VERTEX_SIZE = 180; // Max size of FVF vertex in bytes
|
|
//--------------------------------------------------------------------
|
|
/*
|
|
* Registry defines
|
|
*/
|
|
#define RESPATH "Software\\Microsoft\\Direct3D\\Drivers"
|
|
#define RESPATH_D3D "Software\\Microsoft\\Direct3D"
|
|
|
|
#define STATS_FONT_FACE "Terminal"
|
|
#define STATS_FONT_SIZE 9
|
|
|
|
#if COLLECTSTATS
|
|
DWORD BytesDownloaded(LPDDRAWI_DDRAWSURFACE_LCL lpLcl, LPRECT lpRect);
|
|
#endif
|
|
|
|
extern HINSTANCE hGeometryDLL;
|
|
|
|
/*
|
|
* CPU family and features flags
|
|
*/
|
|
extern DWORD dwCPUFamily, dwCPUFeatures;
|
|
extern char szCPUString[];
|
|
|
|
// MMX available
|
|
#define D3DCPU_MMX 0x00000001L
|
|
|
|
// FCOMI and CMOV are both supported
|
|
#define D3DCPU_FCOMICMOV 0x00000002L
|
|
|
|
// Reads block until satisfied
|
|
#define D3DCPU_BLOCKINGREAD 0x00000004L
|
|
|
|
// Extended 3D support available
|
|
#define D3DCPU_X3D 0x00000008L
|
|
|
|
// Pentium II CPU
|
|
#define D3DCPU_PII 0x000000010L
|
|
|
|
// Streaming SIMD Extensions (aka Katmai) CPU
|
|
#define D3DCPU_SSE 0x000000020L
|
|
|
|
// Intel Willamette CPU
|
|
#define D3DCPU_WLMT 0x000000040L
|
|
|
|
#define DEFAULT_GAMMA DTOVAL(1.4)
|
|
|
|
/*
|
|
INDEX_BATCH_SCALE is the constant which is used by DrawIndexedPrim
|
|
to deterimine if the number of primitives being drawn is small
|
|
relative to the number of vertices being passed. If it is then
|
|
the prims are dereferenced in batches and sent to DrawPrim.
|
|
*/
|
|
#define INDEX_BATCH_SCALE 2
|
|
|
|
#endif // BUILD_DDDDK
|
|
|
|
#if !defined(BUILD_DDDDK)
|
|
|
|
class DIRECT3DDEVICEI;
|
|
class CStateSets;
|
|
|
|
typedef class DIRECT3DI *LPDIRECT3DI;
|
|
typedef class DIRECT3DDEVICEI *LPDIRECT3DDEVICEI;
|
|
typedef class DIRECT3DLIGHTI *LPDIRECT3DLIGHTI;
|
|
typedef class DIRECT3DTEXTUREI *LPDIRECT3DTEXTUREI;
|
|
typedef class CDirect3DVertexBuffer *LPDIRECT3DVERTEXBUFFERI;
|
|
|
|
class CDirect3DUnk : public IUnknown
|
|
{
|
|
public:
|
|
unsigned refCnt; /* Reference count object */
|
|
public:
|
|
LPDIRECT3DI pD3DI;
|
|
public:
|
|
// IUnknown Methods
|
|
HRESULT D3DAPI QueryInterface(REFIID riid, LPVOID* ppvObj);
|
|
ULONG D3DAPI AddRef();
|
|
ULONG D3DAPI Release();
|
|
};
|
|
|
|
class DIRECT3DI : public IDirect3D7,
|
|
public CD3DAlloc
|
|
{
|
|
public: //Private Data
|
|
|
|
/*** Object Relations ***/
|
|
|
|
/* Devices */
|
|
int numDevs;/* Number of devices */
|
|
struct _devices { DIRECT3DDEVICEI* Root;} devices;
|
|
/* Associated IDirect3DDevices */
|
|
|
|
/* Vertex Buffers */
|
|
int numVBufs; /* Number of vertex buffers */
|
|
LIST_ROOT(_vbufs, CDirect3DVertexBuffer) vbufs;
|
|
/* Created IDirect3DVertexBuffers */
|
|
|
|
/* Textures */
|
|
LIST_ROOT(_textures, DIRECT3DTEXTUREI) textures;
|
|
|
|
/*** Object Data ***/
|
|
|
|
CDirect3DUnk mD3DUnk;
|
|
|
|
//RLDDIRegistry* lpReg; /* Registry */
|
|
struct _D3DBUCKET *lpFreeList; /* Free linked list */
|
|
struct _D3DBUCKET *lpBufferList;/* link list of headers of big chunks allocated*/
|
|
class TextureCacheManager *lpTextureManager;
|
|
/*
|
|
* DirectDraw Interface
|
|
*/
|
|
LPDIRECTDRAW lpDD;
|
|
LPDIRECTDRAW7 lpDD7; /* needed for CreateSurface to get LPDIRECTDRAWSURFACE7 */
|
|
|
|
// HACK. D3D needs a DD1 DDRAWI interface because it uses CreateSurface1 internally
|
|
// for exebufs, among other things. But the D3DI object cannot keep a reference
|
|
// to its parent DD object because it is aggegrated with the DD obj, so that would constitute
|
|
// a circular reference that would prevent deletion. So QI for DD1 interface, copy it into D3DI
|
|
// and release it, then point lpDD at the copy. (disgusting)
|
|
// More disgusting still: These need to be large enough to hold ddrawex interface structs
|
|
|
|
DDRAWI_DIRECTDRAW_INT DDInt_DD1;
|
|
|
|
/*
|
|
* The special IUnknown interface for the aggregate that does
|
|
* not punt to the parent object.
|
|
*/
|
|
LPUNKNOWN lpOwningIUnknown; /* The owning IUnknown */
|
|
|
|
#if COLLECTSTATS
|
|
// For displaying stats
|
|
HFONT m_hFont;
|
|
|
|
// Various counters for stats
|
|
DWORD m_setpris, m_setLODs, m_texCreates, m_texDestroys;
|
|
#endif
|
|
|
|
#ifdef __DISABLE_VIDMEM_VBS__
|
|
BOOL bDisableVidMemVBs;
|
|
#endif //__DISABLE_VIDMEM_VBS__
|
|
|
|
public: //Private methods
|
|
DIRECT3DI(); // Constructor called Direct3DCreate()
|
|
~DIRECT3DI(); // Destructor called by CDirect3DUnk::Release()
|
|
HRESULT Initialize(IUnknown* pUnkOuter, LPDDRAWI_DIRECTDRAW_INT pDDrawInt);
|
|
HRESULT EnumDevices(LPD3DENUMDEVICESCALLBACK7, LPVOID, DWORD, DWORD);
|
|
// Internal CreateVertexBuffer
|
|
HRESULT CreateVertexBufferI(LPD3DVERTEXBUFFERDESC, LPDIRECT3DVERTEXBUFFER7*, DWORD);
|
|
// Device flushing
|
|
HRESULT FlushDevicesExcept(LPDIRECT3DDEVICEI pDev);
|
|
public:
|
|
// IUnknown Methods
|
|
HRESULT D3DAPI QueryInterface(REFIID riid, LPVOID* ppvObj);
|
|
ULONG D3DAPI AddRef();
|
|
ULONG D3DAPI Release();
|
|
|
|
HRESULT D3DAPI EnumDevices(LPD3DENUMDEVICESCALLBACK7, LPVOID);
|
|
HRESULT D3DAPI CreateDevice(REFCLSID, LPDIRECTDRAWSURFACE7, LPDIRECT3DDEVICE7*);
|
|
HRESULT D3DAPI CreateVertexBuffer(LPD3DVERTEXBUFFERDESC, LPDIRECT3DVERTEXBUFFER7*, DWORD);
|
|
HRESULT D3DAPI EnumZBufferFormats(REFCLSID, LPD3DENUMPIXELFORMATSCALLBACK, LPVOID);
|
|
HRESULT D3DAPI EvictManagedTextures();
|
|
|
|
#if COLLECTSTATS
|
|
// Stats collection funcs
|
|
void ResetTexStats();
|
|
void GetTexStats(LPD3DDEVINFO_TEXTURING);
|
|
void IncNumSetPris()
|
|
{
|
|
++m_setpris;
|
|
}
|
|
void IncNumSetLODs()
|
|
{
|
|
++m_setLODs;
|
|
}
|
|
void IncNumTexCreates()
|
|
{
|
|
++m_texCreates;
|
|
}
|
|
void IncNumTexDestroys()
|
|
{
|
|
++m_texDestroys;
|
|
}
|
|
DWORD GetNumSetPris()
|
|
{
|
|
return m_setpris;
|
|
}
|
|
DWORD GetNumSetLODs()
|
|
{
|
|
return m_setLODs;
|
|
}
|
|
DWORD GetNumTexCreates()
|
|
{
|
|
return m_texCreates;
|
|
}
|
|
DWORD GetNumTexDestroys()
|
|
{
|
|
return m_texDestroys;
|
|
}
|
|
DWORD GetNumTexLocks()
|
|
{
|
|
return ((LPDDRAWI_DIRECTDRAW_INT)lpDD7)->lpLcl->dwNumTexLocks;
|
|
}
|
|
DWORD GetNumTexGetDCs()
|
|
{
|
|
return ((LPDDRAWI_DIRECTDRAW_INT)lpDD7)->lpLcl->dwNumTexGetDCs;
|
|
}
|
|
#endif
|
|
};
|
|
|
|
typedef DIRECT3DI* LPDIRECT3DI;
|
|
|
|
#include "d3dhal.h"
|
|
#include "halprov.h"
|
|
|
|
//---------------------------------------------------------------------
|
|
typedef HRESULT (*PFNDRVSETRENDERTARGET)(LPDIRECTDRAWSURFACE7, LPDIRECTDRAWSURFACE7,
|
|
LPDIRECTDRAWPALETTE, LPDIRECT3DDEVICEI);
|
|
|
|
typedef struct _D3DBUCKET
|
|
{
|
|
struct _D3DBUCKET *next;
|
|
union
|
|
{
|
|
LPVOID lpD3DDevI;
|
|
LPDDRAWI_DDRAWSURFACE_LCL lpLcl;
|
|
LPVOID lpBuffer;
|
|
LPDIRECT3DTEXTUREI lpD3DTexI;
|
|
};
|
|
union
|
|
{
|
|
HRESULT (__cdecl *pfnFlushStates)(LPVOID);
|
|
unsigned int ticks;
|
|
};
|
|
LPDIRECTDRAWSURFACE *lplpDDSZBuffer; //if not NULL, points to lpDDSZBuffer in Direct3DDeviceI
|
|
} D3DBUCKET,*LPD3DBUCKET;
|
|
|
|
typedef struct _D3DI_TEXTUREBLOCK
|
|
{
|
|
LIST_MEMBER(_D3DI_TEXTUREBLOCK) list;
|
|
/* Next block in IDirect3DTexture */
|
|
LIST_MEMBER(_D3DI_TEXTUREBLOCK) devList;
|
|
/* Next block in IDirect3DDevice */
|
|
|
|
LPDIRECT3DDEVICEI lpDevI;
|
|
|
|
/* this texture block refers to either an
|
|
* IDirect3DTexture/IDirect3DTexture2, so one of these pointers will
|
|
* always be NULL
|
|
*/
|
|
LPDIRECT3DTEXTUREI lpD3DTextureI;
|
|
/* pointer to internal struct for IDirect3DTexture/IDirect3DTexture2 */
|
|
|
|
D3DTEXTUREHANDLE hTex;
|
|
/* texture handle */
|
|
} D3DI_TEXTUREBLOCK;
|
|
typedef struct _D3DI_TEXTUREBLOCK *LPD3DI_TEXTUREBLOCK;
|
|
|
|
// Function to compute lighting
|
|
//
|
|
typedef struct _LIGHT_VERTEX_FUNC_TABLE
|
|
{
|
|
LIGHT_VERTEX_FUNC pfnDirectional;
|
|
LIGHT_VERTEX_FUNC pfnPointSpot;
|
|
// Used in multi-loop pipeline
|
|
PFN_LIGHTLOOP pfnDirectionalFirst;
|
|
PFN_LIGHTLOOP pfnDirectionalNext;
|
|
PFN_LIGHTLOOP pfnPointSpotFirst;
|
|
PFN_LIGHTLOOP pfnPointSpotNext;
|
|
} LIGHT_VERTEX_FUNC_TABLE;
|
|
//---------------------------------------------------------------------
|
|
class DIRECT3DLIGHTI : public CD3DAlloc
|
|
{
|
|
public:
|
|
DIRECT3DLIGHTI() {m_LightI.flags = 0;} // VALID bit is not set
|
|
HRESULT SetInternalData();
|
|
BOOL Enabled() {return (m_LightI.flags & D3DLIGHTI_ENABLED);}
|
|
BOOL Valid() {return (m_LightI.flags & D3DLIGHTI_VALID);}
|
|
|
|
LIST_MEMBER(DIRECT3DLIGHTI) m_List; // Active light list member
|
|
D3DLIGHT7 m_Light;
|
|
D3DI_LIGHT m_LightI;
|
|
};
|
|
//---------------------------------------------------------------------
|
|
//
|
|
// Bits for D3DFRONTEND flags (dwFEFlags in DIRECT3DDEVICEI)
|
|
//
|
|
const DWORD D3DFE_WORLDMATRIX_DIRTY = 1 << 0; // World matrix dirty bits
|
|
const DWORD D3DFE_WORLDMATRIX1_DIRTY = 1 << 1; // must be sequential !!!
|
|
const DWORD D3DFE_WORLDMATRIX2_DIRTY = 1 << 2;
|
|
const DWORD D3DFE_WORLDMATRIX3_DIRTY = 1 << 3;
|
|
const DWORD D3DFE_TLVERTEX = 1 << 5;
|
|
const DWORD D3DFE_REALHAL = 1 << 6;
|
|
const DWORD D3DFE_PROJMATRIX_DIRTY = 1 << 8;
|
|
const DWORD D3DFE_VIEWMATRIX_DIRTY = 1 << 9;
|
|
// Set when we need to check world-view matrix for orthogonality
|
|
const DWORD D3DFE_NEEDCHECKWORLDVIEWVMATRIX = 1 << 10;
|
|
// Set when some state has been changed and we have to go through the slow path
|
|
// Currently the bit is set when one of the following bits is set:
|
|
// D3DFE_PROJMATRIX_DIRTY
|
|
// D3DFE_VIEWMATRIX_DIRTY
|
|
// D3DFE_WORLDMATRIX_DIRTY
|
|
// D3DFE_WORLDMATRIX1_DIRTY
|
|
// D3DFE_WORLDMATRIX2_DIRTY
|
|
// D3DFE_WORLDMATRIX3_DIRTY
|
|
// D3DFE_VERTEXBLEND_DIRTY
|
|
// D3DFE_LIGHTS_DIRTY
|
|
// D3DFE_MATERIAL_DIRTY
|
|
// D3DFE_FVF_DIRTY
|
|
// D3DFE_CLIPPLANES_DIRTY
|
|
const DWORD D3DFE_FRONTEND_DIRTY = 1 << 11;
|
|
// We are in recording state set mode
|
|
const DWORD D3DFE_RECORDSTATEMODE = 1 << 12;
|
|
// We are in execution state set mode
|
|
// In this mode the front-and executes recorded states but does not pass
|
|
// them to the driver (the states will be passed using a set state handle)
|
|
const DWORD D3DFE_EXECUTESTATEMODE = 1 << 13;
|
|
const DWORD D3DFE_NEED_TRANSFORM_LIGHTS = 1 << 14;
|
|
const DWORD D3DFE_MATERIAL_DIRTY = 1 << 15;
|
|
const DWORD D3DFE_CLIPPLANES_DIRTY = 1 << 16;
|
|
const DWORD D3DFE_LIGHTS_DIRTY = 1 << 18;
|
|
// This bit is set when vertex blending state is dirty
|
|
const DWORD D3DFE_VERTEXBLEND_DIRTY = 1 << 19;
|
|
// Set if the Current Transformation Matrix has been changed
|
|
// Reset when frustum planes in the model space have been computed
|
|
const DWORD D3DFE_FRUSTUMPLANES_DIRTY = 1 << 20;
|
|
const DWORD D3DFE_WORLDVIEWMATRIX_DIRTY = 1 << 21;
|
|
const DWORD D3DFE_FVF_DIRTY = 1 << 22;
|
|
// This bit set if UpdateManagedTextures() needs to be called
|
|
const DWORD D3DFE_NEED_TEXTURE_UPDATE = 1 << 23;
|
|
// This bit set if mapping DX6 texture blend modes to renderstates is desired
|
|
const DWORD D3DFE_MAP_TSS_TO_RS = 1 << 24;
|
|
const DWORD D3DFE_INVWORLDVIEWMATRIX_DIRTY = 1 << 25;
|
|
|
|
//
|
|
const DWORD D3DFE_LOSTSURFACES = 1 << 27;
|
|
// This bit set if texturing is disabled
|
|
const DWORD D3DFE_DISABLE_TEXTURES = 1 << 28;
|
|
// Clip matrix is used to transform user clipping planes
|
|
// to the clipping space
|
|
const DWORD D3DFE_CLIPMATRIX_DIRTY = 1 << 29;
|
|
// HAL supports Transformation and Lighting
|
|
const DWORD D3DFE_TLHAL = 1 << 30;
|
|
// HAL supports state sets
|
|
const DWORD D3DFE_STATESETS = 1 << 31;
|
|
|
|
const DWORD D3DFE_TRANSFORM_DIRTY = D3DFE_PROJMATRIX_DIRTY |
|
|
D3DFE_VIEWMATRIX_DIRTY |
|
|
D3DFE_WORLDMATRIX_DIRTY |
|
|
D3DFE_WORLDMATRIX1_DIRTY |
|
|
D3DFE_WORLDMATRIX2_DIRTY |
|
|
D3DFE_WORLDMATRIX3_DIRTY |
|
|
D3DFE_VERTEXBLEND_DIRTY;
|
|
|
|
const DWORD D3DDEVBOOL_HINTFLAGS_INSCENE = 1 << 0; // Are we in a scene?
|
|
const DWORD D3DDEVBOOL_HINTFLAGS_MULTITHREADED = 1 << 1; // multithreaded device
|
|
const DWORD D3DDEVBOOL_HINTFLAGS_FPUSETUP = 1 << 3; // Means the FPU is already in preferred state.
|
|
|
|
//---------------------------------------------------------------------
|
|
//
|
|
// Bits for dwDebugFlags
|
|
//
|
|
// Set if DisableFVF key is not 0 in registry and driver supports FVF
|
|
const DWORD D3DDEBUG_DISABLEFVF = 1 << 0;
|
|
#ifdef WIN95
|
|
// Disable Draw Primitive DDI
|
|
const DWORD D3DDEBUG_DISABLEDP = 1 << 1;
|
|
// Disable Draw Primitive 2 DDI
|
|
const DWORD D3DDEBUG_DISABLEDP2 = 1 << 2;
|
|
#endif // WIN95
|
|
|
|
#ifdef WIN95
|
|
#define _D3D_FORCEDOUBLE 1
|
|
#else //WIN95
|
|
#define _D3D_FORCEDOUBLE 0
|
|
#endif //WIN95
|
|
#if _D3D_FORCEDOUBLE
|
|
// Set if ForceDouble key is not 0 in the registry and driver is pre-DX6 REALHAL
|
|
const DWORD D3DDEBUG_FORCEDOUBLE= 1 << 2;
|
|
#endif //_D3D_FORCEDOUBLE
|
|
|
|
//---------------------------------------------------------------------
|
|
// Bits for transform.dwFlags
|
|
//
|
|
|
|
// Frastum plane equations are valid
|
|
const DWORD D3DTRANS_VALIDFRUSTUM = 1 << 2;
|
|
//---------------------------------------------------------------------
|
|
typedef struct _D3DFE_TRANSFORM
|
|
{
|
|
D3DMATRIXI proj;
|
|
D3DMATRIXI view;
|
|
D3DMATRIXI world[4]; // Up to 4 world matrix
|
|
D3DMATRIXI mPC; // Mproj * Mclip
|
|
D3DMATRIXI mVPC; // Mview * PC
|
|
D3DMATRIXI mVPCI; // Inverse Mview * PC, used to transform clipping planes
|
|
D3DMATRIXI mCTMI; // Inverse current transformation matrix
|
|
D3DVECTORH frustum[6]; // Normalized plane equations for viewing frustum
|
|
// in the model space
|
|
D3DVECTORH userClipPlane[D3DMAXUSERCLIPPLANES];
|
|
|
|
DWORD dwMaxUserClipPlanes; // Number provided by the driver
|
|
DWORD dwFlags;
|
|
} D3DFE_TRANSFORM;
|
|
|
|
typedef void (*D3DFEDestroyProc)(LPDIRECT3DDEVICEI lpD3DDevI);
|
|
|
|
extern DWORD dwD3DTriBatchSize, dwTriBatchSize, dwLineBatchSize;
|
|
extern DWORD dwHWBufferSize, dwHWMaxTris;
|
|
extern DWORD dwHWFewVertices;
|
|
|
|
typedef enum {
|
|
D3DDEVTYPE_OLDHAL = 1,
|
|
D3DDEVTYPE_DPHAL,
|
|
D3DDEVTYPE_DP2HAL, // DX6 HAL
|
|
D3DDEVTYPE_DX7HAL, // DX7 HAL w/out T&L, with state sets
|
|
D3DDEVTYPE_DX7TLHAL
|
|
} D3DDEVICETYPE;
|
|
//---------------------------------------------------------------------
|
|
typedef HRESULT (DIRECT3DDEVICEI::*PFN_DRAWPRIM)();
|
|
|
|
//---------------------------------------------------------------------
|
|
// This type is used to define operation for ProcessPrimitive
|
|
//
|
|
typedef enum
|
|
{
|
|
__PROCPRIMOP_INDEXEDPRIM, // Process indexed primitive
|
|
__PROCPRIMOP_NONINDEXEDPRIM, // Process non-indexed primitive
|
|
} __PROCPRIMOP;
|
|
//---------------------------------------------------------------------
|
|
#ifdef _IA64_ // Removes IA64 compiler alignment warnings
|
|
#pragma pack(16)
|
|
#endif
|
|
|
|
#ifdef _AXP64_ // Removes AXP64 compiler alignment warnings
|
|
#pragma pack(16)
|
|
#endif
|
|
|
|
// We modify the compiler generated VTable for DIRECT3DDEVICEI object. To make
|
|
// life easy, all virtual functions are defined in DIRECT3DDEVICEI. Also since
|
|
// DEVICEI has multiple inheritance, there are more than 1 VTable.
|
|
// Currently we assume that it only inherits from IDirect3DDevice7 and
|
|
// D3DFE_PROCESSVERTICES and, in that order! Thus IDirect3DDevice7 and
|
|
// DIRECT3DDEVICEI share the same vtable. This is the VTable we copy and
|
|
// modify. The define below is the total entries in this vtable. It is the
|
|
// sum of the methods in IDirect3DDevice7 (incl. IUnknown) (49) and all the
|
|
// virtual methods in DIRECT3DDEVICEI ()
|
|
#define D3D_NUM_API_FUNCTIONS (49)
|
|
#define D3D_NUM_VIRTUAL_FUNCTIONS (D3D_NUM_API_FUNCTIONS+38)
|
|
|
|
// These constants are based on the assumption that rsVec array is an array
|
|
// of 32-bit intergers
|
|
const D3D_RSVEC_SHIFT = 5; // log2(sizeof(DWORD)*8);
|
|
const D3D_RSVEC_MASK = sizeof(DWORD) * 8 - 1;
|
|
|
|
class DIRECT3DDEVICEI : public IDirect3DDevice7,
|
|
public CD3DAlloc,
|
|
public D3DFE_PROCESSVERTICES
|
|
{
|
|
public: // Private Data
|
|
|
|
ULONGLONG m_qwBatch; // current batch number
|
|
|
|
DWORD dwHintFlags;
|
|
// Pointer to the PV funcs that we need to call
|
|
LPD3DFE_PVFUNCS pGeometryFuncs;
|
|
// buffer for H vertices
|
|
CAlignedBuffer32 HVbuf; // Used for clip flags
|
|
|
|
// Should be cache line aligned. Now it is not
|
|
D3DDEVICETYPE deviceType; // Device Type
|
|
|
|
/*** Object Relations ***/
|
|
LPDIRECT3DI lpDirect3DI; // parent
|
|
LIST_MEMBER(DIRECT3DDEVICEI)list; // Next device IDirect3D
|
|
|
|
/* Textures */
|
|
LIST_ROOT(_dmtextures, _D3DI_TEXTUREBLOCK) texBlocks;
|
|
/* Ref to created IDirect3DTextures */
|
|
|
|
/* Viewports */
|
|
D3DVIEWPORT7 m_Viewport;
|
|
DWORD clrCount; // Number of rects allocated
|
|
LPD3DRECT clrRects; // Rects used for clearing
|
|
|
|
/* Reference count object */
|
|
unsigned refCnt;
|
|
|
|
// for DX3-style devices aggregated onto ddraw, guid should be IID_IDirect3DRGBDevice,
|
|
// IID_IDirect3DHALDevice, etc. for DX5 and beyond, guid is IID_IDirect3DDevice,
|
|
// IID_IDirect3DDevice2, etc
|
|
GUID guid;
|
|
|
|
LPD3DHAL_CALLBACKS lpD3DHALCallbacks; /* HW specific */
|
|
LPD3DHAL_GLOBALDRIVERDATA lpD3DHALGlobalDriverData; /* HW specific */
|
|
LPD3DHAL_CALLBACKS2 lpD3DHALCallbacks2; /* HW specific */
|
|
LPD3DHAL_CALLBACKS3 lpD3DHALCallbacks3; /* DX6 DDI */
|
|
|
|
/* DirectDraw objects that we are holding references to */
|
|
|
|
LPDIRECTDRAW lpDD; // DirectDraw object
|
|
LPDDRAWI_DIRECTDRAW_GBL lpDDGbl; //
|
|
LPDIRECTDRAWSURFACE lpDDSTarget; // Render target
|
|
LPDIRECTDRAWSURFACE lpDDSZBuffer; // Z buffer
|
|
LPDIRECTDRAWPALETTE lpDDPalTarget; // Palette for render target (if any)
|
|
|
|
// these are saved for use by new GetRenderTarget and anything else that requires DDS4 functionality
|
|
LPDIRECTDRAWSURFACE7 lpDDSTarget_DDS7;
|
|
LPDIRECTDRAWSURFACE7 lpDDSZBuffer_DDS7;
|
|
|
|
// Front end data
|
|
D3DFE_TRANSFORM transform; // Transformation state
|
|
int iClipStatus; // Clipping status
|
|
DWORD dwhContext; // Driver context
|
|
|
|
// RenderTarget/ZBuf bit depth info used by Clear to Blt
|
|
DWORD red_mask;
|
|
DWORD red_scale;
|
|
DWORD red_shift;
|
|
DWORD green_mask;
|
|
DWORD green_scale;
|
|
DWORD green_shift;
|
|
DWORD blue_mask;
|
|
DWORD blue_scale;
|
|
DWORD blue_shift;
|
|
DWORD alpha_mask;
|
|
DWORD alpha_scale;
|
|
DWORD alpha_shift;
|
|
DWORD zmask_shift,stencilmask_shift;
|
|
BOOL bDDSTargetIsPalettized; // true if 4 or 8 bit rendertarget
|
|
|
|
// Pipeline state info
|
|
DWORD dwDebugFlags; // See debug bits above
|
|
|
|
#ifndef WIN95
|
|
DWORD_PTR hSurfaceTarget;
|
|
#else
|
|
DWORD hSurfaceTarget;
|
|
#endif
|
|
|
|
#ifdef TRACK_HAL_CALLS
|
|
DWORD hal_calls;
|
|
#endif
|
|
|
|
//--------------- Lights start -----------------------
|
|
DIRECT3DLIGHTI *m_pLights; // Growable light array
|
|
DWORD m_dwNumLights; // Size of m_Lights array
|
|
LIST_ROOT(_dlights, DIRECT3DLIGHTI) m_ActiveLights;
|
|
|
|
LIST_ROOT(name10,_SpecularTable) specular_tables;
|
|
SpecularTable* specular_table;
|
|
LIGHT_VERTEX_FUNC_TABLE *lightVertexFuncTable;
|
|
//--------------- Lights end -----------------------
|
|
|
|
/* Provider backing this driver */
|
|
IHalProvider* pHalProv;
|
|
HINSTANCE hDllProv;
|
|
|
|
/* Device description */
|
|
D3DDEVICEDESC7 d3dDevDesc;
|
|
|
|
/*
|
|
* Pointer to texture objects for currently installed textures. NULL indicates
|
|
* that the texture is either not set (rstate NULL) or that the handle to tex3 pointer
|
|
* mapping is not done. This mapping is expensive, so it is deferred until needed.
|
|
*
|
|
* This is needed for finding the WRAPU,V mode for texture index clipping (since
|
|
* the WRAPU,V state is part of the device).
|
|
*/
|
|
LPDIRECT3DTEXTUREI lpD3DMappedTexI[D3DHAL_TSS_MAXSTAGES];
|
|
LPD3DI_TEXTUREBLOCK lpD3DMappedBlock[D3DHAL_TSS_MAXSTAGES];
|
|
DWORD dwMaxTextureBlendStages; // Max number of blend stages supported by a driver
|
|
DWORD m_dwStageDirty;
|
|
LPDIRECTDRAWCLIPPER lpClipper;
|
|
|
|
/*
|
|
* DrawPrimitives batching
|
|
*/
|
|
|
|
|
|
// Buffer to put DrawPrimitives stuff into
|
|
// Used for both legacy and DrawPrimitive HALs
|
|
WORD *lpwDPBuffer;
|
|
WORD *lpwDPBufferAlloced;
|
|
#ifndef WIN95
|
|
DWORD dwDPBufferSize;
|
|
#endif
|
|
DWORD dwCurrentBatchVID; // Current FVF type in the batch buffer
|
|
|
|
LPD3DHAL_D3DEXTENDEDCAPS lpD3DExtendedCaps; /* HW specific */
|
|
LPDWORD rstates;
|
|
|
|
// Runtime copy of texture stage states
|
|
DWORD tsstates[D3DHAL_TSS_MAXSTAGES][D3DHAL_TSS_STATESPERSTAGE];
|
|
|
|
// Object to record state sets
|
|
CStateSets * m_pStateSets;
|
|
|
|
// This is a function provided by sw rasterizers.
|
|
// Currently, its only function is to provide an RGB8 clear color.
|
|
// It should be non-NULL for anything that supports an 8 bit RGB output
|
|
// type.
|
|
PFN_RASTSERVICE pfnRastService;
|
|
|
|
//
|
|
// This is function pointer is obtained through the
|
|
// HalProvider interface. For real_hals, it is found in all DX7+
|
|
// drivers in pDdGbl->lpDDCBtmp->HALDDMiscellaneous2.GetDriverState
|
|
// Of the software drivers, only Refrast supports it in its DX7+ mode.
|
|
LPDDHAL_GETDRIVERSTATE pfnGetDriverState;
|
|
|
|
// Max TSS that can be passed to the driver
|
|
D3DTEXTURESTAGESTATETYPE m_tssMax;
|
|
// Max RS that can be passed to the driver, used for CanHandleRenderState
|
|
D3DRENDERSTATETYPE m_rsMax;
|
|
// We use 32-bit ints for rsVec. The size if computed using ceil(D3D_MAXRENDERSTATES/32)
|
|
DWORD rsVec[(D3D_MAXRENDERSTATES + D3D_RSVEC_MASK) >> D3D_RSVEC_SHIFT];
|
|
DWORD rsVecRetired[(D3D_MAXRENDERSTATES + D3D_RSVEC_MASK) >> D3D_RSVEC_SHIFT];
|
|
#if COLLECTSTATS
|
|
D3DDEVINFO_TEXTURING m_texstats;
|
|
#endif
|
|
#ifdef VTABLE_HACK
|
|
// This points to the original (compiler generated) read-only vtable of DIRECT3DDEVICEI
|
|
PVOID* lpVtbl;
|
|
// The new vtable which is a read/write copy of the original to allow hacking
|
|
PVOID newVtbl[D3D_NUM_VIRTUAL_FUNCTIONS];
|
|
#endif // VTABLE_HACK
|
|
#ifdef PROFILE4
|
|
DWORD m_dwProfStart, m_dwProfStop;
|
|
#endif // PROFILE4
|
|
#ifdef PROFILE
|
|
DWORD m_dwProfStart, m_dwProfStop;
|
|
#endif // PROFILE
|
|
public: // virtual methods
|
|
DIRECT3DDEVICEI();
|
|
virtual ~DIRECT3DDEVICEI(); // 0
|
|
virtual HRESULT Init(REFCLSID riid, LPDIRECT3DI lpD3DI, LPDIRECTDRAWSURFACE lpDDS,
|
|
IUnknown* pUnkOuter, LPUNKNOWN* lplpD3DDevice); // 1
|
|
virtual HRESULT FlushStates(bool bWithinPrimitive = false)=0; // 2 // Use to flush current batch to the driver
|
|
virtual HRESULT FlushStatesReq(DWORD) { return FlushStates(); }; // 3
|
|
virtual HRESULT ProcessPrimitive(__PROCPRIMOP op = __PROCPRIMOP_NONINDEXEDPRIM)=0; // 4
|
|
virtual HRESULT CheckSurfaces(); // 5 // Check if the surfaces necessary for rendering are lost
|
|
virtual void WriteStateSetToDevice(D3DSTATEBLOCKTYPE) {} // 6
|
|
// Function to download viewport info to the driver
|
|
virtual void UpdateDrvViewInfo(LPD3DVIEWPORT7 lpVwpData) {}; // 7
|
|
virtual void UpdateDrvWInfo() {}; // 8
|
|
virtual HRESULT halCreateContext(); // 9
|
|
// This function is used when in SetRenderTarget the driver context is
|
|
// recreated
|
|
virtual HRESULT UpdateDriverStates(); // 10
|
|
virtual HRESULT ValidateFVF(DWORD dwFVF); // 11
|
|
virtual HRESULT SetupFVFData(DWORD *pdwInpVertexSize); // 12
|
|
|
|
virtual void LightChanged(DWORD dwLightIndex); // 13
|
|
virtual void MaterialChanged(); // 14
|
|
virtual void SetTransformI(D3DTRANSFORMSTATETYPE, LPD3DMATRIX); // 15
|
|
virtual void SetViewportI(LPD3DVIEWPORT7); // 16
|
|
virtual HRESULT D3DAPI SetTextureStageStateFast(DWORD dwStage,
|
|
D3DTEXTURESTAGESTATETYPE dwState,
|
|
DWORD dwValue); // 17
|
|
virtual HRESULT D3DAPI SetRenderStateFast(D3DRENDERSTATETYPE, DWORD); // 18
|
|
virtual void LightEnableI(DWORD dwLightIndex, BOOL); // 19
|
|
virtual HRESULT UpdateTextures(); // 20
|
|
virtual void SetRenderTargetI(LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE); // 21
|
|
virtual bool CanDoTexBlt(LPDDRAWI_DDRAWSURFACE_LCL lpDDSSrcSubFace_lcl,
|
|
LPDDRAWI_DDRAWSURFACE_LCL lpDDSDstSubFace_lcl); // 22
|
|
virtual void ClearI(DWORD dwFlags, DWORD clrCount, D3DCOLOR dwColor, D3DVALUE dvZ, DWORD dwStencil); // 23
|
|
#ifdef VTABLE_HACK
|
|
virtual HRESULT D3DAPI DrawPrimitiveTL(D3DPRIMITIVETYPE, DWORD, LPVOID, DWORD, DWORD) // 24
|
|
{ // Dummy function, should never be called
|
|
DDASSERT(1);
|
|
return DDERR_GENERIC;
|
|
};
|
|
virtual HRESULT D3DAPI DrawPrimitiveVBTL(D3DPRIMITIVETYPE, LPDIRECT3DVERTEXBUFFER7, DWORD, DWORD, DWORD) // 25
|
|
{ // Dummy function, should never be called
|
|
DDASSERT(1);
|
|
return DDERR_GENERIC;
|
|
};
|
|
virtual HRESULT D3DAPI DrawIndexedPrimitiveTL(D3DPRIMITIVETYPE, DWORD, LPVOID, DWORD, LPWORD, DWORD, DWORD) // 26
|
|
{ // Dummy function, should never be called
|
|
DDASSERT(1);
|
|
return DDERR_GENERIC;
|
|
};
|
|
virtual HRESULT D3DAPI DrawIndexedPrimitiveVBTL(D3DPRIMITIVETYPE, LPDIRECT3DVERTEXBUFFER7, DWORD, DWORD, LPWORD, DWORD, DWORD) // 27
|
|
{ // Dummy function, should never be called
|
|
DDASSERT(1);
|
|
return DDERR_GENERIC;
|
|
};
|
|
virtual HRESULT D3DAPI DrawPrimitiveFE(D3DPRIMITIVETYPE, DWORD, LPVOID, DWORD, DWORD) // 28
|
|
{ // Dummy function, should never be called
|
|
DDASSERT(1);
|
|
return DDERR_GENERIC;
|
|
};
|
|
virtual HRESULT D3DAPI DrawIndexedPrimitiveFE(D3DPRIMITIVETYPE, DWORD, LPVOID, DWORD, LPWORD, DWORD, DWORD) // 29
|
|
{ // Dummy function, should never be called
|
|
DDASSERT(1);
|
|
return DDERR_GENERIC;
|
|
};
|
|
virtual HRESULT D3DAPI DrawPrimitiveVBFE(D3DPRIMITIVETYPE, LPDIRECT3DVERTEXBUFFER7, DWORD, DWORD, DWORD) // 30
|
|
{ // Dummy function, should never be called
|
|
DDASSERT(1);
|
|
return DDERR_GENERIC;
|
|
};
|
|
virtual HRESULT D3DAPI DrawIndexedPrimitiveVBFE(D3DPRIMITIVETYPE, LPDIRECT3DVERTEXBUFFER7, DWORD, DWORD, LPWORD, DWORD, DWORD) // 31
|
|
{ // Dummy function, should never be called
|
|
DDASSERT(1);
|
|
return DDERR_GENERIC;
|
|
};
|
|
#endif
|
|
virtual void SetClipPlaneI(DWORD dwPlaneIndex, D3DVALUE* pPlaneEquation); // 32
|
|
virtual HRESULT D3DAPI SetTextureInternal(DWORD, LPDIRECTDRAWSURFACE7); // 33
|
|
virtual HRESULT D3DAPI ApplyStateBlockInternal(DWORD); // 34
|
|
virtual HRESULT SetTSSI(DWORD, D3DTEXTURESTAGESTATETYPE, DWORD) = 0; // 35
|
|
virtual HRESULT D3DAPI PreLoadFast(LPDIRECTDRAWSURFACE7); // 36
|
|
public: // non virtual methods
|
|
BOOL UpdateInternalTextureStageState(DWORD dwStage,
|
|
D3DTEXTURESTAGESTATETYPE dwState,
|
|
DWORD dwValue);
|
|
HRESULT stateInitialize(BOOL bZEnable);
|
|
HRESULT checkDeviceSurface(LPDIRECTDRAWSURFACE lpDDS, LPDIRECTDRAWSURFACE lpZbuffer, LPGUID pGuid);
|
|
HRESULT HookToD3D(LPDIRECT3DI lpD3DI);
|
|
HRESULT UnhookFromD3D();
|
|
HRESULT SetupFVFDataCommon(DWORD *pdwInpVertexSize);
|
|
void CleanupTextures();
|
|
BOOL NeedInternalTSSUpdate(DWORD dwState)
|
|
{
|
|
return dwState == D3DTSS_TEXCOORDINDEX || dwState >= D3DTSS_TEXTURETRANSFORMFLAGS ||
|
|
dwState == D3DTSS_COLOROP;
|
|
}
|
|
// Always use this function to update "rstates", because we have to
|
|
// set some internal flags when "rstats" is changed.
|
|
void UpdateInternalState(D3DRENDERSTATETYPE type, DWORD value);
|
|
// Checks for 'retired' render state - returns TRUE if not retired
|
|
BOOL CheckForRetiredRenderState(D3DRENDERSTATETYPE type)
|
|
{
|
|
if (!(rsVecRetired[type >> D3D_RSVEC_SHIFT] & (1ul << (type & D3D_RSVEC_MASK))))
|
|
{
|
|
// not retired
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
// Checks if we can pass the render state to the driver
|
|
BOOL CanHandleRenderState(D3DRENDERSTATETYPE type)
|
|
{
|
|
if (type >= m_rsMax)
|
|
{
|
|
// not an error condition because we don't send front-end stuff to
|
|
// non-TL Hal devices, for example, but don't send to HAL anyway
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
};
|
|
|
|
// Update internal state
|
|
void SetMaterialI(LPD3DMATERIAL7);
|
|
void SetLightI(DWORD dwLightIndex, LPD3DLIGHT7);
|
|
inline void SetFogFlags(void);
|
|
void ForceFVFRecompute(void) { dwVIDIn = 0; dwFEFlags |= D3DFE_FVF_DIRTY | D3DFE_FRONTEND_DIRTY; };
|
|
HRESULT CopySurface(LPDIRECTDRAWSURFACE7 lpDDSDst, LPRECT lpDestRect,
|
|
LPDIRECTDRAWSURFACE7 lpDDSSrc, LPRECT lpSrcRect,
|
|
DWORD dwFlags);
|
|
HRESULT GetTextureDDIHandle(LPDIRECT3DTEXTUREI lpTexI,
|
|
LPD3DI_TEXTUREBLOCK* lplpBlock);
|
|
LPD3DI_TEXTUREBLOCK HookTexture(LPDIRECT3DTEXTUREI lpD3DText);
|
|
LPD3DI_TEXTUREBLOCK D3DI_FindTextureBlock(LPDIRECT3DTEXTUREI lpTex);
|
|
void BatchTexture(LPDDRAWI_DDRAWSURFACE_LCL lpLcl)
|
|
{
|
|
if(m_qwBatch > lpLcl->lpSurfMore->qwBatch.QuadPart)
|
|
lpLcl->lpSurfMore->qwBatch.QuadPart = m_qwBatch;
|
|
}
|
|
HRESULT VerifyTextureCaps(LPDIRECT3DTEXTUREI lpTexI);
|
|
HRESULT CheckDrawPrimitiveVB(LPDIRECT3DVERTEXBUFFER7 lpVBuf, DWORD dwStartVertex, DWORD dwNumVertices, DWORD dwFlags);
|
|
void DisplayStats();
|
|
void CheckClipStatus(D3DVALUE * pPositions, DWORD dwStride, DWORD dwNumVertices,
|
|
DWORD *pdwClipUnion, DWORD *pdwClipIntersection);
|
|
HRESULT VerifyTexture(DWORD dwStage, LPDIRECTDRAWSURFACE7 lpTex);
|
|
HRESULT SetRenderStateInternal(D3DRENDERSTATETYPE, DWORD);
|
|
BOOL GetInfoInternal(DWORD dwDevInfoID, LPVOID pDevInfoStruct, DWORD dwSize);
|
|
#if COLLECTSTATS
|
|
void ResetTexStats();
|
|
void GetTexStats(LPD3DDEVINFO_TEXTURING);
|
|
void IncNumLoads()
|
|
{
|
|
++m_texstats.dwNumLoads;
|
|
}
|
|
void IncNumTexturesSet()
|
|
{
|
|
++m_texstats.dwNumSet;
|
|
}
|
|
void IncNumPreLoads()
|
|
{
|
|
++m_texstats.dwNumPreLoads;
|
|
}
|
|
void IncBytesDownloaded(LPDDRAWI_DDRAWSURFACE_LCL lpLcl, LPRECT lpRect)
|
|
{
|
|
m_texstats.dwApproxBytesLoaded += BytesDownloaded(lpLcl, lpRect);
|
|
}
|
|
#endif
|
|
#ifdef VTABLE_HACK
|
|
void VtblPreLoadFast()
|
|
{
|
|
// DIRECT3DDEVICEI::PreLoadFast
|
|
newVtbl[24] = lpVtbl[D3D_NUM_API_FUNCTIONS+36];
|
|
}
|
|
void VtblApplyStateBlockRecord()
|
|
{
|
|
// IDirect3DDevice7::ApplyStateBlock
|
|
newVtbl[39] = lpVtbl[39];
|
|
}
|
|
void VtblApplyStateBlockExecute()
|
|
{
|
|
// IDirect3DDevice7::ApplyStateBlockInternal
|
|
newVtbl[39] = lpVtbl[D3D_NUM_API_FUNCTIONS+34];
|
|
}
|
|
void VtblSetTextureRecord()
|
|
{
|
|
// IDirect3DDevice7::SetTexture
|
|
newVtbl[35] = lpVtbl[35];
|
|
}
|
|
void VtblSetTextureExecute()
|
|
{
|
|
// IDirect3DDevice7::SetTextureInternal
|
|
newVtbl[35] = lpVtbl[D3D_NUM_API_FUNCTIONS+33];
|
|
}
|
|
void VtblSetTextureStageStateRecord()
|
|
{
|
|
// IDirect3DDevice7::SetTextureStageState
|
|
newVtbl[37] = lpVtbl[37];
|
|
}
|
|
void VtblSetTextureStageStateExecute()
|
|
{
|
|
// IDirect3DDevice7::SetTextureStageStateI
|
|
newVtbl[37] = lpVtbl[D3D_NUM_API_FUNCTIONS+17];
|
|
}
|
|
void VtblSetRenderStateRecord()
|
|
{
|
|
// IDirect3DDevice7::SetRenderState
|
|
newVtbl[20] = lpVtbl[20];
|
|
}
|
|
void VtblSetRenderStateExecute()
|
|
{
|
|
// DIRECT3DDEVICEI::SetRenderStateFast
|
|
newVtbl[20] = lpVtbl[D3D_NUM_API_FUNCTIONS+18];
|
|
}
|
|
void VtblDrawPrimitiveDefault()
|
|
{
|
|
// IDirect3DDevice7::DrawPrimitive
|
|
newVtbl[25] = lpVtbl[25];
|
|
}
|
|
void VtblDrawPrimitiveTL()
|
|
{
|
|
// DIRECT3DDEVICEI::DrawPrimitiveTL
|
|
newVtbl[25] = lpVtbl[D3D_NUM_API_FUNCTIONS+24];
|
|
}
|
|
void VtblDrawPrimitiveVBDefault()
|
|
{
|
|
// IDirect3DDevice7::DrawPrimitiveVB
|
|
newVtbl[31] = lpVtbl[31];
|
|
}
|
|
void VtblDrawPrimitiveVBTL()
|
|
{
|
|
// DIRECT3DDEVICEI::DrawPrimitiveVBTL
|
|
newVtbl[31] = lpVtbl[D3D_NUM_API_FUNCTIONS+25];
|
|
}
|
|
void VtblDrawIndexedPrimitiveDefault()
|
|
{
|
|
// IDirect3DDevice7::DrawIndexedPrimitive
|
|
newVtbl[26] = lpVtbl[26];
|
|
}
|
|
void VtblDrawIndexedPrimitiveTL()
|
|
{
|
|
// DIRECT3DDEVICEI::DrawIndexedPrimitiveTL
|
|
newVtbl[26] = lpVtbl[D3D_NUM_API_FUNCTIONS+26];
|
|
}
|
|
void VtblDrawIndexedPrimitiveVBDefault()
|
|
{
|
|
// IDirect3DDevice7::DrawIndexedPrimitiveVB
|
|
newVtbl[32] = lpVtbl[32];
|
|
}
|
|
void VtblDrawIndexedPrimitiveVBTL()
|
|
{
|
|
// DIRECT3DDEVICEI::DrawIndexedPrimitiveVBTL
|
|
newVtbl[32] = lpVtbl[D3D_NUM_API_FUNCTIONS+27];
|
|
}
|
|
void VtblDrawPrimitiveFE()
|
|
{
|
|
// DIRECT3DDEVICEI::DrawPrimitiveFE
|
|
newVtbl[25] = lpVtbl[D3D_NUM_API_FUNCTIONS+28];
|
|
}
|
|
void VtblDrawIndexedPrimitiveFE()
|
|
{
|
|
// DIRECT3DDEVICEI::DrawIndexedPrimitiveFE
|
|
newVtbl[26] = lpVtbl[D3D_NUM_API_FUNCTIONS+29];
|
|
}
|
|
void VtblDrawPrimitiveVBFE()
|
|
{
|
|
// DIRECT3DDEVICEI::DrawPrimitiveFE
|
|
newVtbl[31] = lpVtbl[D3D_NUM_API_FUNCTIONS+30];
|
|
}
|
|
void VtblDrawIndexedPrimitiveVBFE()
|
|
{
|
|
// DIRECT3DDEVICEI::DrawIndexedPrimitiveFE
|
|
newVtbl[32] = lpVtbl[D3D_NUM_API_FUNCTIONS+31];
|
|
}
|
|
#endif
|
|
|
|
#if DBG
|
|
#define PROF_DRAWPRIMITIVEDEVICE2 0x0003
|
|
#define PROF_DRAWINDEXEDPRIMITIVEDEVICE2 0x0004
|
|
#define PROF_DRAWPRIMITIVESTRIDED 0x0005
|
|
#define PROF_DRAWINDEXEDPRIMITIVESTRIDED 0x0006
|
|
#define PROF_DRAWPRIMITIVEDEVICE3 0x0007
|
|
#define PROF_DRAWINDEXEDPRIMITIVEDEVICE3 0x0008
|
|
#define PROF_DRAWPRIMITIVEVB 0x0009
|
|
#define PROF_DRAWINDEXEDPRIMITIVEVB 0x000a
|
|
DWORD dwCaller;
|
|
DWORD dwPrimitiveType[PROF_DRAWINDEXEDPRIMITIVEVB+1];
|
|
DWORD dwVertexType1[PROF_DRAWINDEXEDPRIMITIVEVB+1];
|
|
DWORD dwVertexType2[PROF_DRAWINDEXEDPRIMITIVEVB+1];
|
|
void Profile(DWORD, D3DPRIMITIVETYPE, DWORD);
|
|
#else
|
|
#define Profile(a,b,c)
|
|
#endif
|
|
public:
|
|
// IUnknown Methods
|
|
HRESULT D3DAPI QueryInterface(REFIID riid, LPVOID* ppvObj);
|
|
ULONG D3DAPI AddRef();
|
|
ULONG D3DAPI Release();
|
|
|
|
// IDirect3DDevice7 Methods
|
|
HRESULT D3DAPI GetCaps(LPD3DDEVICEDESC7);
|
|
HRESULT D3DAPI EnumTextureFormats(LPD3DENUMPIXELFORMATSCALLBACK, LPVOID);
|
|
HRESULT D3DAPI BeginScene();
|
|
HRESULT D3DAPI EndScene();
|
|
HRESULT D3DAPI GetDirect3D(LPDIRECT3D7*);
|
|
HRESULT D3DAPI Clear(DWORD, LPD3DRECT, DWORD, D3DCOLOR, D3DVALUE, DWORD);
|
|
HRESULT D3DAPI SetRenderTarget(LPDIRECTDRAWSURFACE7, DWORD);
|
|
HRESULT D3DAPI GetRenderTarget(LPDIRECTDRAWSURFACE7 *);
|
|
HRESULT D3DAPI SetTransform(D3DTRANSFORMSTATETYPE, LPD3DMATRIX);
|
|
HRESULT D3DAPI GetTransform(D3DTRANSFORMSTATETYPE, LPD3DMATRIX);
|
|
HRESULT D3DAPI MultiplyTransform(D3DTRANSFORMSTATETYPE, LPD3DMATRIX);
|
|
HRESULT D3DAPI SetViewport(LPD3DVIEWPORT7);
|
|
HRESULT D3DAPI GetViewport(LPD3DVIEWPORT7);
|
|
HRESULT D3DAPI SetMaterial(LPD3DMATERIAL7);
|
|
HRESULT D3DAPI GetMaterial(LPD3DMATERIAL7);
|
|
HRESULT D3DAPI SetLight(DWORD, LPD3DLIGHT7);
|
|
HRESULT D3DAPI GetLight(DWORD, LPD3DLIGHT7);
|
|
HRESULT D3DAPI GetRenderState(D3DRENDERSTATETYPE, LPDWORD);
|
|
HRESULT D3DAPI SetRenderState(D3DRENDERSTATETYPE, DWORD);
|
|
HRESULT D3DAPI DrawPrimitive(D3DPRIMITIVETYPE, DWORD, LPVOID, DWORD, DWORD);
|
|
HRESULT D3DAPI DrawIndexedPrimitive(D3DPRIMITIVETYPE, DWORD, LPVOID, DWORD, LPWORD, DWORD, DWORD);
|
|
HRESULT D3DAPI SetClipStatus(LPD3DCLIPSTATUS);
|
|
HRESULT D3DAPI GetClipStatus(LPD3DCLIPSTATUS);
|
|
HRESULT D3DAPI DrawPrimitiveStrided(D3DPRIMITIVETYPE, DWORD, LPD3DDRAWPRIMITIVESTRIDEDDATA, DWORD, DWORD);
|
|
HRESULT D3DAPI DrawIndexedPrimitiveStrided(D3DPRIMITIVETYPE, DWORD, LPD3DDRAWPRIMITIVESTRIDEDDATA, DWORD, LPWORD, DWORD, DWORD);
|
|
HRESULT D3DAPI DrawPrimitiveVB(D3DPRIMITIVETYPE, LPDIRECT3DVERTEXBUFFER7, DWORD, DWORD, DWORD);
|
|
HRESULT D3DAPI DrawIndexedPrimitiveVB(D3DPRIMITIVETYPE, LPDIRECT3DVERTEXBUFFER7, DWORD, DWORD, LPWORD, DWORD, DWORD);
|
|
HRESULT D3DAPI ComputeSphereVisibility(LPD3DVECTOR, LPD3DVALUE, DWORD, DWORD, LPDWORD);
|
|
HRESULT D3DAPI GetTexture(DWORD, LPDIRECTDRAWSURFACE7 *);
|
|
HRESULT D3DAPI SetTexture(DWORD, LPDIRECTDRAWSURFACE7);
|
|
HRESULT D3DAPI GetTextureStageState(DWORD, D3DTEXTURESTAGESTATETYPE, LPDWORD);
|
|
HRESULT D3DAPI DuplicateStateBlock(DWORD InHandle, LPDWORD OutHandle);
|
|
HRESULT D3DAPI OverlayStateBlock(DWORD Handle);
|
|
HRESULT D3DAPI BeginStateBlock();
|
|
HRESULT D3DAPI EndStateBlock(LPDWORD);
|
|
HRESULT D3DAPI DeleteStateBlock(DWORD);
|
|
HRESULT D3DAPI ApplyStateBlock(DWORD);
|
|
HRESULT D3DAPI CaptureStateBlock(DWORD Handle);
|
|
HRESULT D3DAPI SetTextureStageState(DWORD dwStage,
|
|
D3DTEXTURESTAGESTATETYPE dwState,
|
|
DWORD dwValue);
|
|
HRESULT D3DAPI ValidateDevice(LPDWORD lpdwNumPasses) = 0;
|
|
HRESULT D3DAPI Load(LPDIRECTDRAWSURFACE7 lpDest, LPPOINT lpDestPoint,
|
|
LPDIRECTDRAWSURFACE7 lpSrc, LPRECT lpSrcRect,
|
|
DWORD dwFlags);
|
|
HRESULT D3DAPI LightEnable(DWORD dwLightIndex, BOOL);
|
|
HRESULT D3DAPI GetLightEnable(DWORD dwLightIndex, BOOL*);
|
|
HRESULT D3DAPI PreLoad(LPDIRECTDRAWSURFACE7 lpTex);
|
|
HRESULT D3DAPI GetInfo(DWORD dwDevInfoID, LPVOID pDevInfoStruct, DWORD dwSize);
|
|
HRESULT D3DAPI SetClipPlane(DWORD dwPlaneIndex, D3DVALUE* pPlaneEquation);
|
|
HRESULT D3DAPI GetClipPlane(DWORD dwPlaneIndex, D3DVALUE* pPlaneEquation);
|
|
HRESULT D3DAPI CreateStateBlock(D3DSTATEBLOCKTYPE sbt, LPDWORD pdwHandle);
|
|
};
|
|
|
|
// There is only DP2 HAL on NT
|
|
#ifdef WIN95
|
|
|
|
typedef struct _D3DHAL_DRAWPRIMCOUNTS *LPD3DHAL_DRAWPRIMCOUNTS;
|
|
|
|
// Legacy HAL batching is done with these structs.
|
|
typedef struct _D3DI_HWCOUNTS {
|
|
WORD wNumStateChanges; // Number of state changes batched
|
|
WORD wNumVertices; // Number of vertices in tri list
|
|
WORD wNumTriangles; // Number of triangles in tri list
|
|
} D3DI_HWCOUNTS, *LPD3DI_HWCOUNTS;
|
|
|
|
|
|
class CDirect3DDeviceIHW : public DIRECT3DDEVICEI
|
|
{
|
|
private: // Data
|
|
/* Legacy HALs */
|
|
|
|
// Buffer of counts structures that keep track of the
|
|
// number of render states and vertices buffered
|
|
LPD3DI_HWCOUNTS lpHWCounts;
|
|
|
|
// Buffer of triangle structures.
|
|
LPD3DTRIANGLE lpHWTris;
|
|
|
|
// Byte offset into lpHWVertices. This gets incremented
|
|
// by 8 when a render state is batched and by 32*dwNumVertices
|
|
// when a primitive is batched.
|
|
DWORD dwHWOffset;
|
|
|
|
// Max value of dwHWOffset. Used to decide whether to flush.
|
|
DWORD dwHWMaxOffset;
|
|
|
|
// Index into lpHWTris.
|
|
DWORD dwHWTriIndex;
|
|
|
|
// Number of counts structures used so far. This actually
|
|
// gives the number of primitives batched and the index of
|
|
// the counts structure to batch render states into.
|
|
DWORD dwHWNumCounts;
|
|
|
|
WORD *wTriIndex;
|
|
|
|
HRESULT DrawIndexedPrimitiveInBatchesHW(D3DPRIMITIVETYPE PrimitiveType,
|
|
D3DVERTEXTYPE VertexType,
|
|
LPD3DTLVERTEX lpVertices,
|
|
DWORD dwNumPrimitives,
|
|
LPWORD lpwIndices);
|
|
protected:
|
|
CBufferDDS TLVbuf;
|
|
public:
|
|
CDirect3DDeviceIHW() { deviceType = D3DDEVTYPE_OLDHAL; }
|
|
~CDirect3DDeviceIHW(); // Called by CDirect3DDeviceUnk::Release()
|
|
HRESULT SetRenderStateI(D3DRENDERSTATETYPE, DWORD);
|
|
HRESULT DrawPrim();
|
|
HRESULT DrawIndexPrim();
|
|
HRESULT DrawClippedPrim() {return DrawPrim();}
|
|
HRESULT FlushStates(bool bWithinPrimitive = false);
|
|
HRESULT D3DAPI ValidateDevice(LPDWORD lpdwNumPasses);
|
|
HRESULT SetTSSI(DWORD, D3DTEXTURESTAGESTATETYPE, DWORD);
|
|
HRESULT MapTSSToRS();
|
|
|
|
HRESULT Init(REFCLSID riid, LPDIRECT3DI lpD3DI, LPDIRECTDRAWSURFACE lpDDS,
|
|
IUnknown* pUnkOuter, LPUNKNOWN* lplpD3DDevice);
|
|
HRESULT ProcessPrimitive(__PROCPRIMOP op = __PROCPRIMOP_NONINDEXEDPRIM);
|
|
HRESULT MapFVFtoTLVertex(LPVOID lpAddress);
|
|
HRESULT MapFVFtoTLVertexIndexed();
|
|
};
|
|
|
|
class CDirect3DDeviceIDP : public CDirect3DDeviceIHW
|
|
{
|
|
private: // Data
|
|
/* data members of DIRECT3DDEVICEI that are specific to DX5 DrawPrimitive HAL drivers
|
|
should go here */
|
|
/* DrawPrimitive-aware HALs */
|
|
|
|
// pointer to current prim counts struct
|
|
LPD3DHAL_DRAWPRIMCOUNTS lpDPPrimCounts;
|
|
|
|
// Byte offset into buffer (we are currently
|
|
// using the device's wTriIndex)
|
|
DWORD dwDPOffset;
|
|
|
|
// Maximum offset. If dwDPOffset exceeds this, it is
|
|
// time to flush.
|
|
DWORD dwDPMaxOffset;
|
|
|
|
public:
|
|
CDirect3DDeviceIDP() { deviceType = D3DDEVTYPE_DPHAL; }
|
|
~CDirect3DDeviceIDP() { CleanupTextures(); }
|
|
HRESULT SetRenderStateI(D3DRENDERSTATETYPE, DWORD);
|
|
HRESULT DrawPrim();
|
|
HRESULT DrawIndexPrim();
|
|
HRESULT DrawClippedPrim() {return DrawPrim();}
|
|
HRESULT FlushStates(bool bWithinPrimitive = false);
|
|
|
|
HRESULT Init(REFCLSID riid, LPDIRECT3DI lpD3DI, LPDIRECTDRAWSURFACE lpDDS,
|
|
IUnknown* pUnkOuter, LPUNKNOWN* lplpD3DDevice);
|
|
HRESULT halCreateContext();
|
|
};
|
|
|
|
#define IS_DPHAL_DEVICE(lpDevI) ((lpDevI)->deviceType == D3DDEVTYPE_DPHAL)
|
|
|
|
#endif // WIN95
|
|
|
|
// Flags passed by the runtime to the DDI batching code via PV structure
|
|
// to enable new DDI batching to be done efficiently. These flags are
|
|
// marked as reserved in d3dfe.hpp
|
|
const DWORD D3DPV_WITHINPRIMITIVE = D3DPV_RESERVED1; // This flags that the flush has occured
|
|
// within an primitive. This indicates
|
|
// that we should not flush the vertex buffer
|
|
|
|
// If the vertices are in user memory
|
|
const DWORD D3DPV_USERMEMVERTICES = D3DPV_RESERVED3;
|
|
//---------------------------------------------------------------------
|
|
class CDirect3DDeviceIDP2 : public DIRECT3DDEVICEI
|
|
{
|
|
public: // data
|
|
static const DWORD dwD3DDefaultCommandBatchSize;
|
|
|
|
// This is the VB interface corresponding to the dp2data.lpDDVertex
|
|
// This is kept so that the VB can be released when done
|
|
// which cannot be done from just the LCL pointer which is lpDDVertex
|
|
CDirect3DVertexBuffer* lpDP2CurrBatchVBI;
|
|
DWORD TLVbuf_size;
|
|
DWORD TLVbuf_base;
|
|
#ifdef VTABLE_HACK
|
|
// Cached dwFlags for fast path
|
|
DWORD dwLastFlags;
|
|
// Last VB used in a call that involved D3D's FE.
|
|
CDirect3DVertexBuffer* lpDP2LastVBI;
|
|
#endif
|
|
DWORD dwDP2CommandBufSize;
|
|
DWORD dwDP2CommandLength;
|
|
|
|
// Cache line should start here
|
|
|
|
// Pointer to the actual data in CB1
|
|
LPVOID lpvDP2Commands;
|
|
|
|
|
|
//Pointer to the current position the CB1 buffer
|
|
LPD3DHAL_DP2COMMAND lpDP2CurrCommand;
|
|
// Perf issue: replace the below 3 fields by a 32 bit D3DHAL_DP2COMMAND struct
|
|
WORD wDP2CurrCmdCnt; // Mirror of Count field if the current command
|
|
BYTE bDP2CurrCmdOP; // Mirror of Opcode of the current command
|
|
BYTE bDummy; // Force DWORD alignment of next member
|
|
|
|
D3DHAL_DRAWPRIMITIVES2DATA dp2data;
|
|
|
|
// The buffer we currently batch into
|
|
LPDIRECTDRAWSURFACE7 lpDDSCB1;
|
|
LPDIRECT3DVERTEXBUFFER7 allocatedBuf;
|
|
LPVOID alignedBuf;
|
|
|
|
// Count read/write <-> write-only transistions
|
|
DWORD dwTLVbufChanges;
|
|
// Flags specific to DP2 device
|
|
DWORD dwDP2Flags;
|
|
// If a mode switch occurs just before a TLVbuf_Grow which requires to create a new
|
|
// VB, then the create will fail. This will leave the device in a state where
|
|
// allocatedBuf is NULL. This is bad since many places in the code we derefence this
|
|
// without checking for NULL. To have a contained fix, we create a small dummy system
|
|
// memory VB at device create and if we ever fail the grow due to mode switch, we assign
|
|
// this VB instead to allocated buf and set the TLVbuf_size to 0.
|
|
LPDIRECT3DVERTEXBUFFER7 pNullVB;
|
|
|
|
protected: // methods
|
|
inline void ClearBatch(bool);
|
|
HRESULT Init(REFCLSID riid, LPDIRECT3DI lpD3DI, LPDIRECTDRAWSURFACE lpDDS,
|
|
IUnknown* pUnkOuter, LPUNKNOWN* lplpD3DDevice);
|
|
HRESULT GrowCommandBuffer(LPDIRECT3DI lpD3DI, DWORD dwSize);
|
|
#if DBG
|
|
void ValidateVertex(LPDWORD lpdwVertex);
|
|
void ValidateCommand(LPD3DHAL_DP2COMMAND lpCmd);
|
|
#endif
|
|
public:
|
|
CDirect3DDeviceIDP2() { deviceType = D3DDEVTYPE_DP2HAL; }
|
|
|
|
~CDirect3DDeviceIDP2(); // Called by CDirect3DDeviceUnk::Release()
|
|
HRESULT FlushStates(bool bWithinPrimitive = false);
|
|
HRESULT FlushStatesReq(DWORD dwReqSize);
|
|
HRESULT SetRenderStateI(D3DRENDERSTATETYPE, DWORD);
|
|
HRESULT DrawPrim();
|
|
HRESULT DrawIndexPrim();
|
|
HRESULT DrawClippedPrim();
|
|
HRESULT D3DAPI ValidateDevice(LPDWORD lpdwNumPasses);
|
|
HRESULT SetTSSI(DWORD, D3DTEXTURESTAGESTATETYPE, DWORD);
|
|
// Called from DrawPrimitiveVB if a vertex buffer or TL buffer is used for rendering
|
|
HRESULT StartPrimVB(LPDIRECT3DVERTEXBUFFERI vb, DWORD dwStartVertex);
|
|
// Called if user memory buffer is used for rendering
|
|
HRESULT StartPrimUserMem(LPVOID memory);
|
|
// Called if TL buffer of used memory was used for rendering
|
|
HRESULT EndPrim();
|
|
|
|
HRESULT CheckSurfaces();
|
|
|
|
void UpdateDrvViewInfo(LPD3DVIEWPORT7 lpVwpData);
|
|
void UpdateDrvWInfo();
|
|
// This function is used when in SetRenderTarget the driver context is
|
|
// recreated
|
|
HRESULT UpdateDriverStates();
|
|
HRESULT SetupFVFData(DWORD *pdwInpVertexSize);
|
|
HRESULT ProcessPrimitive(__PROCPRIMOP op = __PROCPRIMOP_NONINDEXEDPRIM);
|
|
// Returns aligned buffer address
|
|
LPVOID TLVbuf_GetAddress()
|
|
{
|
|
return (LPBYTE)alignedBuf + TLVbuf_base;
|
|
}
|
|
// Returns aligned buffer size
|
|
DWORD TLVbuf_GetSize() { return TLVbuf_size - TLVbuf_base; }
|
|
DWORD& TLVbuf_Base() { return TLVbuf_base; }
|
|
// define these later on in this file after CDirect3DVertexBuffer is defined
|
|
inline CDirect3DVertexBuffer* TLVbuf_GetVBI();
|
|
inline LPDIRECTDRAWSURFACE TLVbuf_GetDDS();
|
|
HRESULT TLVbuf_Grow(DWORD dwSize, bool bWriteOnly);
|
|
// Initializes command header in the DP2 command buffer,
|
|
// reserves space for the comamnd data and returns pointer to the command
|
|
// data
|
|
// Throws an HRESULT exception in case of error
|
|
LPVOID GetHalBufferPointer(D3DHAL_DP2OPERATION op, DWORD dwDataSize);
|
|
HRESULT D3DAPI DrawPrimitiveTL(D3DPRIMITIVETYPE, DWORD, LPVOID, DWORD, DWORD);
|
|
HRESULT D3DAPI DrawPrimitiveVBTL(D3DPRIMITIVETYPE, LPDIRECT3DVERTEXBUFFER7, DWORD, DWORD, DWORD);
|
|
HRESULT D3DAPI DrawIndexedPrimitiveTL(D3DPRIMITIVETYPE, DWORD, LPVOID, DWORD, LPWORD, DWORD, DWORD);
|
|
HRESULT D3DAPI DrawIndexedPrimitiveVBTL(D3DPRIMITIVETYPE, LPDIRECT3DVERTEXBUFFER7, DWORD, DWORD, LPWORD, DWORD, DWORD);
|
|
HRESULT D3DAPI DrawPrimitiveFE(D3DPRIMITIVETYPE, DWORD, LPVOID, DWORD, DWORD);
|
|
HRESULT D3DAPI DrawIndexedPrimitiveFE(D3DPRIMITIVETYPE, DWORD, LPVOID, DWORD, LPWORD, DWORD, DWORD);
|
|
HRESULT D3DAPI DrawPrimitiveVBFE(D3DPRIMITIVETYPE, LPDIRECT3DVERTEXBUFFER7, DWORD, DWORD, DWORD);
|
|
HRESULT D3DAPI DrawIndexedPrimitiveVBFE(D3DPRIMITIVETYPE, LPDIRECT3DVERTEXBUFFER7, DWORD, DWORD, LPWORD, DWORD, DWORD);
|
|
};
|
|
// macros to characterize device
|
|
|
|
#define IS_DP2HAL_DEVICE(lpDevI) ((lpDevI)->deviceType >= D3DDEVTYPE_DP2HAL)
|
|
#define IS_DX7HAL_DEVICE(lpDevI) ((lpDevI)->deviceType >= D3DDEVTYPE_DX7HAL)
|
|
#define IS_TLHAL_DEVICE(lpDevI) ((lpDevI)->deviceType >= D3DDEVTYPE_DX7TLHAL)
|
|
#define IS_MT_DEVICE(lpDevI) ( (lpDevI)->dwHintFlags & D3DDEVBOOL_HINTFLAGS_MULTITHREADED )
|
|
#define IS_HW_DEVICE(lpDevI) ((lpDevI)->dwFEFlags & D3DFE_REALHAL)
|
|
#define IS_FPU_SETUP(lpDevI) ((lpDevI)->dwHintFlags & D3DDEVBOOL_HINTFLAGS_FPUSETUP )
|
|
|
|
/*
|
|
* Internal version of Direct3DTexture object; it has data after the vtable
|
|
*/
|
|
class DIRECT3DTEXTUREI : public CD3DAlloc
|
|
{
|
|
public:
|
|
|
|
/*** Object Relations ***/
|
|
LIST_ROOT(_blocks, _D3DI_TEXTUREBLOCK) blocks;
|
|
/* Devices we're associated with */
|
|
/* Next member in texture chain */
|
|
LIST_MEMBER(DIRECT3DTEXTUREI) m_List;
|
|
|
|
/*** Object Data ***/
|
|
LPDIRECT3DI lpDirect3DI;
|
|
DDRAWI_DDRAWSURFACE_INT DDS1Tex; //we need to keep the legacy
|
|
LPDIRECTDRAWSURFACE7 lpDDS;
|
|
LPDIRECTDRAWSURFACE7 lpDDSSys;
|
|
DDSURFACEDESC2 ddsd;
|
|
DWORD m_dwBytes;
|
|
DWORD m_dwVidBytes;
|
|
DWORD m_dwScene;
|
|
DWORD m_dwPriority;
|
|
DWORD m_dwTicks;
|
|
DWORD m_dwHeapIndex;
|
|
DWORD m_dwLOD;
|
|
D3DTEXTUREHANDLE m_hTex;
|
|
BOOL m_bInUse;
|
|
BOOL bDirty;
|
|
|
|
/*
|
|
* The special IUnknown interface for the aggregate that does
|
|
* not punt to the parent object.
|
|
*/
|
|
|
|
public:
|
|
DIRECT3DTEXTUREI();
|
|
virtual HRESULT Initialize(LPDIRECT3DI lpDirect3DI, LPDIRECTDRAWSURFACE7 pDDS);
|
|
virtual void Destroy();
|
|
ULONGLONG Cost() const
|
|
{
|
|
#ifdef _X86_
|
|
ULONGLONG retval;
|
|
_asm
|
|
{
|
|
mov ebx, this;
|
|
mov edx, [ebx]DIRECT3DTEXTUREI.m_bInUse;
|
|
shl edx, 31;
|
|
mov eax, [ebx]DIRECT3DTEXTUREI.m_dwPriority;
|
|
mov ecx, eax;
|
|
shr eax, 1;
|
|
or edx, eax;
|
|
mov DWORD PTR retval + 4, edx;
|
|
shl ecx, 31;
|
|
mov eax, [ebx]DIRECT3DTEXTUREI.m_dwTicks;
|
|
shr eax, 1;
|
|
or eax, ecx;
|
|
mov DWORD PTR retval, eax;
|
|
}
|
|
return retval;
|
|
#else
|
|
return ((ULONGLONG)m_bInUse << 63) + ((ULONGLONG)m_dwPriority << 31) + ((ULONGLONG)(m_dwTicks >> 1));
|
|
#endif
|
|
}
|
|
bool D3DManaged()
|
|
{
|
|
return this->lpDDSSys != NULL;
|
|
}
|
|
bool InVidmem()
|
|
{
|
|
return m_dwHeapIndex != 0;
|
|
}
|
|
|
|
void AddRef()
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT surf_int = (LPDDRAWI_DDRAWSURFACE_INT)(D3DManaged() ? this->lpDDSSys : this->lpDDS);
|
|
++(surf_int->dwIntRefCnt);
|
|
++(surf_int->lpLcl->dwLocalRefCnt);
|
|
++(surf_int->lpLcl->lpGbl->dwRefCnt);
|
|
}
|
|
void Release()
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_INT surf_int = (LPDDRAWI_DDRAWSURFACE_INT)(D3DManaged() ? this->lpDDSSys : this->lpDDS);
|
|
if(surf_int->dwIntRefCnt > 1) // only do this short way when it's not going away
|
|
{
|
|
--(surf_int->dwIntRefCnt);
|
|
--(surf_int->lpLcl->dwLocalRefCnt);
|
|
--(surf_int->lpLcl->lpGbl->dwRefCnt);
|
|
}
|
|
else
|
|
{
|
|
((LPDIRECTDRAWSURFACE7)surf_int)->Release();
|
|
}
|
|
}
|
|
|
|
virtual HRESULT SetPriority(DWORD dwPriority);
|
|
virtual HRESULT GetPriority(LPDWORD lpdwPriority);
|
|
virtual HRESULT SetLOD(DWORD dwLOD);
|
|
virtual HRESULT GetLOD(LPDWORD lpdwLOD);
|
|
};
|
|
|
|
// DIRECT3DTEXTUREM is used when the texture is desired
|
|
// to be driver managed
|
|
class DIRECT3DTEXTUREM : public DIRECT3DTEXTUREI
|
|
{
|
|
public:
|
|
HRESULT SetPriority(DWORD dwPriority);
|
|
HRESULT GetPriority(LPDWORD lpdwPriority);
|
|
HRESULT SetLOD(DWORD dwLOD);
|
|
HRESULT GetLOD(LPDWORD lpdwLOD);
|
|
};
|
|
|
|
// DIRECT3DTEXTUREM is used when the texture is desired
|
|
// to be managed by Direct3D
|
|
class DIRECT3DTEXTURED3DM : public DIRECT3DTEXTUREM
|
|
{
|
|
public:
|
|
void Destroy();
|
|
HRESULT Initialize(LPDIRECT3DI lpDirect3DI, LPDIRECTDRAWSURFACE7 pDDS);
|
|
void MarkDirtyPointers();
|
|
HRESULT SetPriority(DWORD dwPriority);
|
|
HRESULT SetLOD(DWORD dwLOD);
|
|
};
|
|
|
|
#define D3DVB_NUM_VIRTUAL_FUNCTIONS 10
|
|
// Internal VB create flag:
|
|
#define D3DVBFLAGS_CREATEMULTIBUFFER 0x80000000L
|
|
|
|
class CDirect3DVertexBuffer : public IDirect3DVertexBuffer7,
|
|
public CD3DAlloc
|
|
{
|
|
private:
|
|
HRESULT CreateMemoryBuffer(LPDIRECT3DI lpD3DI,
|
|
LPDIRECTDRAWSURFACE7 *lplpSurface7,
|
|
LPDIRECTDRAWSURFACE *lplpS,
|
|
LPVOID *lplpMemory,
|
|
DWORD dwBufferSize);
|
|
#ifdef VTABLE_HACK
|
|
// The new vtable which is a read/write copy of the original to allow hacking
|
|
PVOID newVtbl[D3DVB_NUM_VIRTUAL_FUNCTIONS];
|
|
#endif // VTABLE_HACK
|
|
// Internal data
|
|
DWORD dwPVFlags;
|
|
LPDIRECT3DDEVICEI lpDevIBatched; // Is this VB batched in a device ? If so we need to flush the device
|
|
// on Lock
|
|
DWORD dwLockCnt;
|
|
/* position.lpData = start of vertex buffer data
|
|
* position.dwStride = Number of bytes per vertex
|
|
*/
|
|
union {
|
|
D3DDP_PTRSTRIDE position;
|
|
D3DDP_PTRSTRIDE SOA;
|
|
};
|
|
DWORD dwNumVertices;
|
|
DWORD fvf; // Used in Input and Output
|
|
DWORD dwCaps;
|
|
DWORD dwMemType; // DDSCAPS_VIDEOMEMORY, DDSCAPS2_VERTEXBUFFER
|
|
DWORD srcVOP, dstVOP;
|
|
DWORD nTexCoord; // Number of texture coordinates
|
|
DWORD dwTexCoordSize[D3DDP_MAXTEXCOORD];// Size of every texture coordinate set
|
|
DWORD dwTexCoordSizeTotal; // Total size of all texture coordinates
|
|
int refCnt; /* Reference count */
|
|
D3DFE_CLIPCODE* clipCodes;
|
|
LPDIRECTDRAWSURFACE7 lpDDSVB; // DDraw Surface containing the actual VB memory
|
|
LPDIRECTDRAWSURFACE lpDDS1VB; // same dds, legacy interface for legacy hal.
|
|
BOOL bReallyOptimized; // VB could have OPTIMIZED caps set, but be
|
|
// not optimized
|
|
/*** Object Relations */
|
|
LPDIRECT3DI lpDirect3DI; /* Parent */
|
|
LIST_MEMBER(CDirect3DVertexBuffer)list; /* Next vertex buffer in IDirect3D */
|
|
|
|
// Friends
|
|
friend void hookVertexBufferToD3D(LPDIRECT3DI, LPDIRECT3DVERTEXBUFFERI);
|
|
friend class DIRECT3DDEVICEI;
|
|
friend class CDirect3DDeviceIDP2;
|
|
#ifdef VTABLE_HACK
|
|
// This points to the original (compiler generated) read-only vtable of DIRECT3DDEVICEI
|
|
PVOID* lpVtbl;
|
|
#endif // VTABLE_HACK
|
|
public:
|
|
CDirect3DVertexBuffer(LPDIRECT3DI);
|
|
~CDirect3DVertexBuffer();
|
|
HRESULT Init(LPDIRECT3DI, LPD3DVERTEXBUFFERDESC, DWORD);
|
|
LPDIRECTDRAWSURFACE GetDDS() { return lpDDS1VB; }
|
|
HRESULT Restore() { return lpDDSVB->Restore(); }
|
|
void UnlockI();
|
|
void BreakLock();
|
|
#ifndef WIN95
|
|
HRESULT LockWorkAround(CDirect3DDeviceIDP2 *pDev);
|
|
void UnlockWorkAround();
|
|
#endif // WIN95
|
|
|
|
// IUnknown Methods
|
|
HRESULT D3DAPI QueryInterface(REFIID riid, LPVOID* ppvObj); // 0
|
|
ULONG D3DAPI AddRef(); // 1
|
|
ULONG D3DAPI Release(); // 2
|
|
|
|
// IDirect3DVertexBuffer Methods
|
|
HRESULT D3DAPI Lock(DWORD, LPVOID*, LPDWORD); // 3
|
|
HRESULT D3DAPI Unlock(); // 4
|
|
HRESULT D3DAPI ProcessVertices(DWORD, DWORD, DWORD, LPDIRECT3DVERTEXBUFFER7, DWORD, LPDIRECT3DDEVICE7, DWORD); // 5
|
|
HRESULT D3DAPI GetVertexBufferDesc(LPD3DVERTEXBUFFERDESC); // 6
|
|
HRESULT D3DAPI Optimize(LPDIRECT3DDEVICE7 lpDevI, DWORD dwFlags); // 7
|
|
HRESULT D3DAPI ProcessVerticesStrided(DWORD, DWORD, DWORD, LPD3DDRAWPRIMITIVESTRIDEDDATA, DWORD, LPDIRECT3DDEVICE7, DWORD); // 8
|
|
protected:
|
|
// Internal Lock
|
|
virtual HRESULT D3DAPI LockI(DWORD, LPVOID*, LPDWORD); // 9
|
|
#ifdef VTABLE_HACK
|
|
void VtblLockDefault()
|
|
{
|
|
// 3: IDirect3DVertexBuffer7::Lock
|
|
newVtbl[3] = lpVtbl[3];
|
|
}
|
|
void VtblLockFast()
|
|
{
|
|
// 9: CDirect3DVertexBuffer::LockI
|
|
newVtbl[3] = lpVtbl[9];
|
|
}
|
|
#endif // VTABLE_HACK
|
|
HRESULT ValidateProcessVertices(DWORD vertexOP,
|
|
DWORD dwDstIndex,
|
|
DWORD dwCount,
|
|
LPVOID lpSrc,
|
|
LPDIRECT3DDEVICE7 lpDevice,
|
|
DWORD dwFlags);
|
|
HRESULT DoProcessVertices(LPDIRECT3DVERTEXBUFFERI lpSrcI,
|
|
LPDIRECT3DDEVICEI lpDevI,
|
|
DWORD vertexOP,
|
|
DWORD dwSrcIndex,
|
|
DWORD dwDstIndex,
|
|
DWORD dwFlags);
|
|
};
|
|
|
|
// Now that LPDIRECT3DVERTEXBUFFERI is defined...
|
|
inline CDirect3DVertexBuffer* CDirect3DDeviceIDP2::TLVbuf_GetVBI()
|
|
{
|
|
return static_cast<CDirect3DVertexBuffer*>(allocatedBuf);
|
|
}
|
|
|
|
inline LPDIRECTDRAWSURFACE CDirect3DDeviceIDP2::TLVbuf_GetDDS()
|
|
{
|
|
return TLVbuf_GetVBI()->GetDDS();
|
|
}
|
|
|
|
// The instance of the class providing a guaranteed implementation
|
|
// This is defined / instantiated in pipeln\helxfrm.cpp
|
|
extern D3DFE_PVFUNCS GeometryFuncsGuaranteed;
|
|
|
|
extern void
|
|
D3DDeviceDescConvert(LPD3DDEVICEDESC7 lpOut,
|
|
LPD3DDEVICEDESC_V1 lpV1,
|
|
LPD3DHAL_D3DEXTENDEDCAPS lpExt);
|
|
|
|
#endif
|
|
// @@END_MSINTERNAL
|
|
|
|
#endif /* _D3DI_H */
|