7428 lines
274 KiB
C++
7428 lines
274 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// DX8SDDIFW
|
|
//
|
|
// Template library framework for creating a DX8 SDDI pluggable software
|
|
// rasterizer.
|
|
//
|
|
// Two #defines supported:
|
|
// DX8SDDIFW_NONAMESPACE: Don't use the DX8SDDIFW namespace. This can cause
|
|
// symbols to bloat up if not needed.
|
|
// DX8SDDIFW_NOCATCHALL: Don't use catch( ... ) in certain places to create
|
|
// a more stable driver. There are catch( ... ) clauses in certain areas
|
|
// like DP2 command processing, so that each command succeeds or fails.
|
|
// However, this can cause problems debugging, as Access Violations can
|
|
// be masked and caught without causing the app to freeze or even see an
|
|
// error.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
#if _MSC_VER > 1000
|
|
#pragma once
|
|
#endif // _MSC_VER > 1000
|
|
|
|
#if !defined( DX8SDDIFW_NONAMESPACE)
|
|
namespace DX8SDDIFW
|
|
{
|
|
#endif // !defined( DX8SDDIFW_NONAMESPACE)
|
|
|
|
// Since MSVC doesn't have a block type currently, include one. This
|
|
// dependency can be removed if a similar type is provided in CRT STL.
|
|
#include "block.h"
|
|
|
|
// Utility functions for clamping a value:
|
|
template< class T> inline
|
|
void clamp_max( T& Var, const T& ClampMax)
|
|
{
|
|
if( Var> ClampMax)
|
|
Var= ClampMax;
|
|
}
|
|
|
|
template< class T> inline
|
|
void clamp_min( T& Var, const T& ClampMin)
|
|
{
|
|
if( Var< ClampMin)
|
|
Var= ClampMin;
|
|
}
|
|
|
|
template< class T> inline
|
|
void clamp( T& Var, const T& ClampMin, const T& ClampMax)
|
|
{
|
|
assert( ClampMax>= ClampMin);
|
|
if( Var> ClampMax)
|
|
Var= ClampMax;
|
|
else if( Var< ClampMin)
|
|
Var= ClampMin;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CPushValue
|
|
//
|
|
// This class creates a safe run-time stack which pushes a value upon
|
|
// construction and pops the value upon destruction.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
template< class T>
|
|
struct CPushValue
|
|
{
|
|
protected: // Variables
|
|
T& m_Val;
|
|
T m_OldVal;
|
|
|
|
public: // Functions
|
|
CPushValue( T& Val, const T& NewVal) : m_Val( Val)
|
|
{
|
|
m_OldVal= Val;
|
|
Val= NewVal;
|
|
}
|
|
~CPushValue()
|
|
{
|
|
m_Val= m_OldVal;
|
|
}
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// COSDetector
|
|
//
|
|
// This class can detect whether the host OS is the Win9X code base or the WinNT
|
|
// code base. The difference is important, because driver structures differ
|
|
// depending on which OS the rasterizer runs on. We don't want to build 2 lib
|
|
// versions, thus requiring the app to link with both.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
class COSDetector
|
|
{
|
|
public: // Types
|
|
enum EOS
|
|
{
|
|
Unknown,
|
|
Win9X,
|
|
WinNT
|
|
};
|
|
|
|
protected: // Variables
|
|
const EOS m_eOS;
|
|
|
|
protected: // Functions
|
|
static EOS DetermineOS()
|
|
{
|
|
OSVERSIONINFO osvi;
|
|
ZeroMemory( &osvi, sizeof( osvi));
|
|
osvi.dwOSVersionInfoSize= sizeof( osvi);
|
|
if( !GetVersionEx( &osvi))
|
|
{
|
|
const bool Unsupported_OS_probably_Win31( false);
|
|
assert( Unsupported_OS_probably_Win31);
|
|
return EOS::Unknown;
|
|
}
|
|
else if( VER_PLATFORM_WIN32_WINDOWS== osvi.dwPlatformId)
|
|
return EOS::Win9X;
|
|
else if( VER_PLATFORM_WIN32_NT== osvi.dwPlatformId)
|
|
return EOS::WinNT;
|
|
else
|
|
{
|
|
const bool Unsupported_OS( false);
|
|
assert( Unsupported_OS);
|
|
return EOS::Unknown;
|
|
}
|
|
}
|
|
|
|
public: // Functions
|
|
COSDetector():
|
|
m_eOS( DetermineOS())
|
|
{ }
|
|
~COSDetector()
|
|
{ }
|
|
EOS GetOS() const
|
|
{ return m_eOS; }
|
|
};
|
|
extern COSDetector g_OSDetector;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// DDRAWI_XXX redefinitions
|
|
//
|
|
// Some DDRAWI_XXX structures differ depending on whether the binary is being
|
|
// compiled for Win9X or WinNT. We'll eliminate this difference, but to do so
|
|
// both OS structures need to be seperately defined. The structure which causes
|
|
// this is DDRAWI_DDRAWSURFACE_MORE. But for safety, more redefinition is done,
|
|
// to try to make developers aware of what's going on.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
class PORTABLE_DDRAWSURFACE_LCL;
|
|
struct PORTABLE_ATTACHLIST
|
|
{
|
|
DWORD dwFlags;
|
|
PORTABLE_ATTACHLIST* lpLink;
|
|
PORTABLE_DDRAWSURFACE_LCL* lpAttached; // attached surface local obj
|
|
DDRAWI_DDRAWSURFACE_INT* lpIAttached; // attached surface interface
|
|
};
|
|
|
|
class PORTABLE_DDRAWSURFACE_MORE;
|
|
class PORTABLE_DDRAWSURFACE_LCL
|
|
{
|
|
private:
|
|
PORTABLE_DDRAWSURFACE_MORE* m_lpSurfMore;
|
|
LPDDRAWI_DDRAWSURFACE_GBL m_lpGbl;
|
|
ULONG_PTR m_hDDSurface;
|
|
PORTABLE_ATTACHLIST* m_lpAttachList;
|
|
PORTABLE_ATTACHLIST* m_lpAttachListFrom;
|
|
DWORD m_dwLocalRefCnt;
|
|
DWORD m_dwProcessId;
|
|
DWORD m_dwFlags;
|
|
DDSCAPS m_ddsCaps;
|
|
union {
|
|
LPDDRAWI_DDRAWPALETTE_INT m_lpDDPalette;
|
|
LPDDRAWI_DDRAWPALETTE_INT m_lp16DDPalette;
|
|
};
|
|
union {
|
|
LPDDRAWI_DDRAWCLIPPER_LCL m_lpDDClipper;
|
|
LPDDRAWI_DDRAWCLIPPER_INT m_lp16DDClipper;
|
|
};
|
|
DWORD m_dwModeCreatedIn;
|
|
DWORD m_dwBackBufferCount;
|
|
DDCOLORKEY m_ddckCKDestBlt;
|
|
DDCOLORKEY m_ddckCKSrcBlt;
|
|
ULONG_PTR m_hDC;
|
|
ULONG_PTR m_dwReserved1;
|
|
DDCOLORKEY m_ddckCKSrcOverlay;
|
|
DDCOLORKEY m_ddckCKDestOverlay;
|
|
LPDDRAWI_DDRAWSURFACE_INT m_lpSurfaceOverlaying;
|
|
DBLNODE m_dbnOverlayNode;
|
|
RECT m_rcOverlaySrc;
|
|
RECT m_rcOverlayDest;
|
|
DWORD m_dwClrXparent;
|
|
DWORD m_dwAlpha;
|
|
LONG m_lOverlayX;
|
|
LONG m_lOverlayY;
|
|
|
|
public:
|
|
PORTABLE_DDRAWSURFACE_MORE*& lpSurfMore()
|
|
{ return m_lpSurfMore; }
|
|
LPDDRAWI_DDRAWSURFACE_GBL& lpGbl()
|
|
{ return m_lpGbl; }
|
|
ULONG_PTR& hDDSurface()
|
|
{ return m_hDDSurface; }
|
|
PORTABLE_ATTACHLIST*& lpAttachList()
|
|
{ return m_lpAttachList; }
|
|
PORTABLE_ATTACHLIST*& lpAttachListFrom()
|
|
{ return m_lpAttachListFrom; }
|
|
DWORD& dwLocalRefCnt()
|
|
{ return m_dwLocalRefCnt; }
|
|
DWORD& dwProcessId()
|
|
{ return m_dwProcessId; }
|
|
DWORD& dwFlags()
|
|
{ return m_dwFlags; }
|
|
DDSCAPS& ddsCaps()
|
|
{ return m_ddsCaps; }
|
|
LPDDRAWI_DDRAWPALETTE_INT& lpDDPalette()
|
|
{ return m_lpDDPalette; }
|
|
LPDDRAWI_DDRAWPALETTE_INT& lp16DDPalette()
|
|
{ return m_lp16DDPalette; }
|
|
LPDDRAWI_DDRAWCLIPPER_LCL& lpDDClipper()
|
|
{ return m_lpDDClipper; }
|
|
LPDDRAWI_DDRAWCLIPPER_INT& lp16DDClipper()
|
|
{ return m_lp16DDClipper; }
|
|
DWORD& dwModeCreatedIn()
|
|
{ return m_dwModeCreatedIn; }
|
|
DWORD& dwBackBufferCount()
|
|
{ return m_dwBackBufferCount; }
|
|
DDCOLORKEY& ddckCKDestBlt()
|
|
{ return m_ddckCKDestBlt; }
|
|
DDCOLORKEY& ddckCKSrcBlt()
|
|
{ return m_ddckCKSrcBlt; }
|
|
ULONG_PTR& hDC()
|
|
{ return m_hDC; }
|
|
ULONG_PTR& dwReserved1()
|
|
{ return m_dwReserved1; }
|
|
DDCOLORKEY& ddckCKSrcOverlay()
|
|
{ return m_ddckCKSrcOverlay; }
|
|
DDCOLORKEY& ddckCKDestOverlay()
|
|
{ return m_ddckCKDestOverlay; }
|
|
LPDDRAWI_DDRAWSURFACE_INT& lpSurfaceOverlaying()
|
|
{ return m_lpSurfaceOverlaying; }
|
|
DBLNODE& dbnOverlayNode()
|
|
{ return m_dbnOverlayNode; }
|
|
RECT& rcOverlaySrc()
|
|
{ return m_rcOverlaySrc; }
|
|
RECT& rcOverlayDest()
|
|
{ return m_rcOverlayDest; }
|
|
DWORD& dwClrXparent()
|
|
{ return m_dwClrXparent; }
|
|
DWORD& dwAlpha()
|
|
{ return m_dwAlpha; }
|
|
LONG& lOverlayX()
|
|
{ return m_lOverlayX; }
|
|
LONG& lOverlayY()
|
|
{ return m_lOverlayY; }
|
|
};
|
|
|
|
class PORTABLE_DDRAWSURFACE_MORE
|
|
{
|
|
public:
|
|
struct DDRAWI_DDRAWSURFACE_MORE_WIN9X
|
|
{
|
|
DWORD dwSize;
|
|
IUNKNOWN_LIST FAR * lpIUnknowns;
|
|
LPDDRAWI_DIRECTDRAW_LCL lpDD_lcl;
|
|
DWORD dwPageLockCount;
|
|
DWORD dwBytesAllocated;
|
|
LPDDRAWI_DIRECTDRAW_INT lpDD_int;
|
|
DWORD dwMipMapCount;
|
|
LPDDRAWI_DDRAWCLIPPER_INT lpDDIClipper;
|
|
LPHEAPALIASINFO lpHeapAliasInfo;
|
|
DWORD dwOverlayFlags;
|
|
LPVOID rgjunc;
|
|
LPDDRAWI_DDVIDEOPORT_LCL lpVideoPort;
|
|
LPDDOVERLAYFX lpddOverlayFX;
|
|
DDSCAPSEX ddsCapsEx;
|
|
DWORD dwTextureStage;
|
|
LPVOID lpDDRAWReserved;
|
|
LPVOID lpDDRAWReserved2;
|
|
LPVOID lpDDrawReserved3;
|
|
DWORD dwDDrawReserved4;
|
|
LPVOID lpDDrawReserved5;
|
|
LPDWORD lpGammaRamp;
|
|
LPDWORD lpOriginalGammaRamp;
|
|
LPVOID lpDDrawReserved6;
|
|
DWORD dwSurfaceHandle;
|
|
DWORD qwDDrawReserved8[2];
|
|
LPVOID lpDDrawReserved9;
|
|
DWORD cSurfaces;
|
|
LPDDSURFACEDESC2 pCreatedDDSurfaceDesc2;
|
|
PORTABLE_DDRAWSURFACE_LCL** slist;
|
|
DWORD dwFVF;
|
|
LPVOID lpVB;
|
|
};
|
|
struct DDRAWI_DDRAWSURFACE_MORE_WINNT
|
|
{
|
|
DWORD dwSize;
|
|
IUNKNOWN_LIST FAR * lpIUnknowns;
|
|
LPDDRAWI_DIRECTDRAW_LCL lpDD_lcl;
|
|
DWORD dwPageLockCount;
|
|
DWORD dwBytesAllocated;
|
|
LPDDRAWI_DIRECTDRAW_INT lpDD_int;
|
|
DWORD dwMipMapCount;
|
|
LPDDRAWI_DDRAWCLIPPER_INT lpDDIClipper;
|
|
LPHEAPALIASINFO lpHeapAliasInfo;
|
|
DWORD dwOverlayFlags;
|
|
LPVOID rgjunc;
|
|
LPDDRAWI_DDVIDEOPORT_LCL lpVideoPort;
|
|
LPDDOVERLAYFX lpddOverlayFX;
|
|
DDSCAPSEX ddsCapsEx;
|
|
DWORD dwTextureStage;
|
|
LPVOID lpDDRAWReserved;
|
|
LPVOID lpDDRAWReserved2;
|
|
LPVOID lpDDrawReserved3;
|
|
DWORD dwDDrawReserved4;
|
|
LPVOID lpDDrawReserved5;
|
|
LPDWORD lpGammaRamp;
|
|
LPDWORD lpOriginalGammaRamp;
|
|
LPVOID lpDDrawReserved6;
|
|
DISPLAYMODEINFO dmiDDrawReserved7;
|
|
DWORD dwSurfaceHandle;
|
|
DWORD qwDDrawReserved8[2];
|
|
LPVOID lpDDrawReserved9;
|
|
DWORD cSurfaces;
|
|
LPDDSURFACEDESC2 pCreatedDDSurfaceDesc2;
|
|
PORTABLE_DDRAWSURFACE_LCL** slist;
|
|
DWORD dwFVF;
|
|
LPVOID lpVB;
|
|
};
|
|
|
|
private:
|
|
union {
|
|
DDRAWI_DDRAWSURFACE_MORE_WIN9X m_Win9X;
|
|
DDRAWI_DDRAWSURFACE_MORE_WINNT m_WinNT;
|
|
};
|
|
|
|
public:
|
|
DWORD& dwSize()
|
|
{ return m_Win9X.dwSize; }
|
|
IUNKNOWN_LIST FAR *& lpIUnknowns()
|
|
{ return m_Win9X.lpIUnknowns; }
|
|
LPDDRAWI_DIRECTDRAW_LCL& lpDD_lcl()
|
|
{ return m_Win9X.lpDD_lcl; }
|
|
DWORD& dwPageLockCount()
|
|
{ return m_Win9X.dwPageLockCount; }
|
|
DWORD& dwBytesAllocated()
|
|
{ return m_Win9X.dwBytesAllocated; }
|
|
LPDDRAWI_DIRECTDRAW_INT& lpDD_int()
|
|
{ return m_Win9X.lpDD_int; }
|
|
DWORD& dwMipMapCount()
|
|
{ return m_Win9X.dwMipMapCount; }
|
|
LPDDRAWI_DDRAWCLIPPER_INT& lpDDIClipper()
|
|
{ return m_Win9X.lpDDIClipper; }
|
|
LPHEAPALIASINFO& lpHeapAliasInfo()
|
|
{ return m_Win9X.lpHeapAliasInfo; }
|
|
DWORD& dwOverlayFlags()
|
|
{ return m_Win9X.dwOverlayFlags; }
|
|
LPVOID& rgjunc()
|
|
{ return m_Win9X.rgjunc; }
|
|
LPDDRAWI_DDVIDEOPORT_LCL& lpVideoPort()
|
|
{ return m_Win9X.lpVideoPort; }
|
|
LPDDOVERLAYFX& lpddOverlayFX()
|
|
{ return m_Win9X.lpddOverlayFX; }
|
|
DDSCAPSEX& ddsCapsEx()
|
|
{ return m_Win9X.ddsCapsEx; }
|
|
DWORD& dwTextureStage()
|
|
{ return m_Win9X.dwTextureStage; }
|
|
LPVOID& lpDDRAWReserved()
|
|
{ return m_Win9X.lpDDRAWReserved; }
|
|
LPVOID& lpDDRAWReserved2()
|
|
{ return m_Win9X.lpDDRAWReserved2; }
|
|
LPVOID& lpDDrawReserved3()
|
|
{ return m_Win9X.lpDDrawReserved3; }
|
|
DWORD& dwDDrawReserved4()
|
|
{ return m_Win9X.dwDDrawReserved4; }
|
|
LPVOID& lpDDrawReserved5()
|
|
{ return m_Win9X.lpDDrawReserved5; }
|
|
LPDWORD& lpGammaRamp()
|
|
{ return m_Win9X.lpGammaRamp; }
|
|
LPDWORD& lpOriginalGammaRamp()
|
|
{ return m_Win9X.lpOriginalGammaRamp; }
|
|
LPVOID& lpDDrawReserved6()
|
|
{ return m_Win9X.lpDDrawReserved6; }
|
|
DWORD& dwSurfaceHandle()
|
|
{ switch( g_OSDetector.GetOS()) {
|
|
case( COSDetector::Win9X): return m_Win9X.dwSurfaceHandle;
|
|
case( COSDetector::WinNT): return m_WinNT.dwSurfaceHandle;
|
|
default: assert( 2!= 2); return m_WinNT.dwSurfaceHandle;
|
|
} }
|
|
DWORD& qwDDrawReserved8_0_()
|
|
{ switch( g_OSDetector.GetOS()) {
|
|
case( COSDetector::Win9X): return m_Win9X.qwDDrawReserved8[0];
|
|
case( COSDetector::WinNT): return m_WinNT.qwDDrawReserved8[0];
|
|
default: assert( 2!= 2); return m_WinNT.qwDDrawReserved8[0];
|
|
} }
|
|
DWORD& qwDDrawReserved8_1_()
|
|
{ switch( g_OSDetector.GetOS()) {
|
|
case( COSDetector::Win9X): return m_Win9X.qwDDrawReserved8[1];
|
|
case( COSDetector::WinNT): return m_WinNT.qwDDrawReserved8[1];
|
|
default: assert( 2!= 2); return m_WinNT.qwDDrawReserved8[1];
|
|
} }
|
|
LPVOID& lpDDrawReserved9()
|
|
{ switch( g_OSDetector.GetOS()) {
|
|
case( COSDetector::Win9X): return m_Win9X.lpDDrawReserved9;
|
|
case( COSDetector::WinNT): return m_WinNT.lpDDrawReserved9;
|
|
default: assert( 2!= 2); return m_WinNT.lpDDrawReserved9;
|
|
} }
|
|
DWORD& cSurfaces()
|
|
{ switch( g_OSDetector.GetOS()) {
|
|
case( COSDetector::Win9X): return m_Win9X.cSurfaces;
|
|
case( COSDetector::WinNT): return m_WinNT.cSurfaces;
|
|
default: assert( 2!= 2); return m_WinNT.cSurfaces;
|
|
} }
|
|
LPDDSURFACEDESC2& pCreatedDDSurfaceDesc2()
|
|
{ switch( g_OSDetector.GetOS()) {
|
|
case( COSDetector::Win9X): return m_Win9X.pCreatedDDSurfaceDesc2;
|
|
case( COSDetector::WinNT): return m_WinNT.pCreatedDDSurfaceDesc2;
|
|
default: assert( 2!= 2); return m_WinNT.pCreatedDDSurfaceDesc2;
|
|
} }
|
|
PORTABLE_DDRAWSURFACE_LCL**& slist()
|
|
{ switch( g_OSDetector.GetOS()) {
|
|
case( COSDetector::Win9X): return m_Win9X.slist;
|
|
case( COSDetector::WinNT): return m_WinNT.slist;
|
|
default: assert( 2!= 2); return m_WinNT.slist;
|
|
} }
|
|
DWORD& dwFVF()
|
|
{ switch( g_OSDetector.GetOS()) {
|
|
case( COSDetector::Win9X): return m_Win9X.dwFVF;
|
|
case( COSDetector::WinNT): return m_WinNT.dwFVF;
|
|
default: assert( 2!= 2); return m_WinNT.dwFVF;
|
|
} }
|
|
LPVOID& lpVB()
|
|
{ switch( g_OSDetector.GetOS()) {
|
|
case( COSDetector::Win9X): return m_Win9X.lpVB;
|
|
case( COSDetector::WinNT): return m_WinNT.lpVB;
|
|
default: assert( 2!= 2); return m_WinNT.lpVB;
|
|
} }
|
|
};
|
|
|
|
class PORTABLE_CONTEXTCREATEDATA
|
|
{
|
|
private:
|
|
union {
|
|
LPDDRAWI_DIRECTDRAW_GBL m_lpDDGbl;
|
|
LPDDRAWI_DIRECTDRAW_LCL m_lpDDLcl;
|
|
};
|
|
union {
|
|
LPDIRECTDRAWSURFACE m_lpDDS;
|
|
PORTABLE_DDRAWSURFACE_LCL* m_lpDDSLcl;
|
|
};
|
|
union {
|
|
LPDIRECTDRAWSURFACE m_lpDDSZ;
|
|
PORTABLE_DDRAWSURFACE_LCL* m_lpDDSZLcl;
|
|
};
|
|
union {
|
|
DWORD m_dwPID;
|
|
ULONG_PTR m_dwrstates;
|
|
};
|
|
ULONG_PTR m_dwhContext;
|
|
HRESULT m_ddrval;
|
|
|
|
public:
|
|
LPDDRAWI_DIRECTDRAW_GBL& lpDDGbl()
|
|
{ return m_lpDDGbl; }
|
|
LPDDRAWI_DIRECTDRAW_LCL& lpDDLcl()
|
|
{ return m_lpDDLcl; }
|
|
LPDIRECTDRAWSURFACE& lpDDS()
|
|
{ return m_lpDDS; }
|
|
PORTABLE_DDRAWSURFACE_LCL*& lpDDSLcl()
|
|
{ return m_lpDDSLcl; }
|
|
LPDIRECTDRAWSURFACE& lpDDSZ()
|
|
{ return m_lpDDSZ; }
|
|
PORTABLE_DDRAWSURFACE_LCL*& lpDDSZLcl()
|
|
{ return m_lpDDSZLcl; }
|
|
DWORD& dwPID()
|
|
{ return m_dwPID; }
|
|
ULONG_PTR& dwrstates()
|
|
{ return m_dwrstates; }
|
|
ULONG_PTR& dwhContext()
|
|
{ return m_dwhContext; }
|
|
HRESULT& ddrval()
|
|
{ return m_ddrval; }
|
|
};
|
|
|
|
class PORTABLE_SETRENDERTARGETDATA
|
|
{
|
|
private:
|
|
ULONG_PTR m_dwhContext;
|
|
union {
|
|
LPDIRECTDRAWSURFACE m_lpDDS;
|
|
PORTABLE_DDRAWSURFACE_LCL* m_lpDDSLcl;
|
|
};
|
|
union {
|
|
LPDIRECTDRAWSURFACE m_lpDDSZ;
|
|
PORTABLE_DDRAWSURFACE_LCL* m_lpDDSZLcl;
|
|
};
|
|
HRESULT m_ddrval;
|
|
|
|
public:
|
|
ULONG_PTR& dwhContext()
|
|
{ return m_dwhContext; }
|
|
LPDIRECTDRAWSURFACE& lpDDS()
|
|
{ return m_lpDDS; }
|
|
PORTABLE_DDRAWSURFACE_LCL*& lpDDSLcl()
|
|
{ return m_lpDDSLcl; }
|
|
LPDIRECTDRAWSURFACE& lpDDSZ()
|
|
{ return m_lpDDSZ; }
|
|
PORTABLE_DDRAWSURFACE_LCL*& lpDDSZLcl()
|
|
{ return m_lpDDSZLcl; }
|
|
HRESULT& ddrval()
|
|
{ return m_ddrval; }
|
|
};
|
|
|
|
class PORTABLE_DRAWPRIMITIVES2DATA
|
|
{
|
|
private:
|
|
ULONG_PTR m_dwhContext;
|
|
DWORD m_dwFlags;
|
|
DWORD m_dwVertexType;
|
|
PORTABLE_DDRAWSURFACE_LCL* m_lpDDCommands;
|
|
DWORD m_dwCommandOffset;
|
|
DWORD m_dwCommandLength;
|
|
union {
|
|
PORTABLE_DDRAWSURFACE_LCL* m_lpDDVertex;
|
|
LPVOID m_lpVertices;
|
|
};
|
|
DWORD m_dwVertexOffset;
|
|
DWORD m_dwVertexLength;
|
|
DWORD m_dwReqVertexBufSize;
|
|
DWORD m_dwReqCommandBufSize;
|
|
LPDWORD m_lpdwRStates;
|
|
union {
|
|
DWORD m_dwVertexSize;
|
|
HRESULT m_ddrval;
|
|
};
|
|
DWORD m_dwErrorOffset;
|
|
|
|
public:
|
|
ULONG_PTR& dwhContext()
|
|
{ return m_dwhContext; }
|
|
DWORD& dwFlags()
|
|
{ return m_dwFlags; }
|
|
DWORD& dwVertexType()
|
|
{ return m_dwVertexType; }
|
|
PORTABLE_DDRAWSURFACE_LCL*& lpDDCommands()
|
|
{ return m_lpDDCommands; }
|
|
DWORD& dwCommandOffset()
|
|
{ return m_dwCommandOffset; }
|
|
DWORD& dwCommandLength()
|
|
{ return m_dwCommandLength; }
|
|
PORTABLE_DDRAWSURFACE_LCL*& lpDDVertex()
|
|
{ return m_lpDDVertex; }
|
|
LPVOID& lpVertices()
|
|
{ return m_lpVertices; }
|
|
DWORD& dwVertexOffset()
|
|
{ return m_dwVertexOffset; }
|
|
DWORD& dwVertexLength()
|
|
{ return m_dwVertexLength; }
|
|
DWORD& dwReqVertexBufSize()
|
|
{ return m_dwReqVertexBufSize; }
|
|
DWORD& dwReqCommandBufSize()
|
|
{ return m_dwReqCommandBufSize; }
|
|
LPDWORD& lpdwRStates()
|
|
{ return m_lpdwRStates; }
|
|
DWORD& dwVertexSize()
|
|
{ return m_dwVertexSize; }
|
|
HRESULT& ddrval()
|
|
{ return m_ddrval; }
|
|
DWORD& dwErrorOffset()
|
|
{ return m_dwErrorOffset; }
|
|
};
|
|
|
|
class PORTABLE_CREATESURFACEEXDATA
|
|
{
|
|
private:
|
|
DWORD m_dwFlags;
|
|
LPDDRAWI_DIRECTDRAW_LCL m_lpDDLcl;
|
|
PORTABLE_DDRAWSURFACE_LCL* m_lpDDSLcl;
|
|
HRESULT m_ddRVal;
|
|
|
|
public:
|
|
DWORD& dwFlags()
|
|
{ return m_dwFlags; }
|
|
LPDDRAWI_DIRECTDRAW_LCL& lpDDLcl()
|
|
{ return m_lpDDLcl; }
|
|
PORTABLE_DDRAWSURFACE_LCL*& lpDDSLcl()
|
|
{ return m_lpDDSLcl; }
|
|
HRESULT& ddRVal()
|
|
{ return m_ddRVal; }
|
|
};
|
|
|
|
class PORTABLE_CREATESURFACEDATA
|
|
{
|
|
private:
|
|
LPDDRAWI_DIRECTDRAW_GBL m_lpDD;
|
|
LPDDSURFACEDESC m_lpDDSurfaceDesc;
|
|
PORTABLE_DDRAWSURFACE_LCL** m_lplpSList;
|
|
DWORD m_dwSCnt;
|
|
HRESULT m_ddRVal;
|
|
LPDDHAL_CREATESURFACE m_CreateSurface;
|
|
|
|
public:
|
|
LPDDRAWI_DIRECTDRAW_GBL& lpDD()
|
|
{ return m_lpDD; }
|
|
LPDDSURFACEDESC& lpDDSurfaceDesc()
|
|
{ return m_lpDDSurfaceDesc; }
|
|
PORTABLE_DDRAWSURFACE_LCL**& lplpSList()
|
|
{ return m_lplpSList; }
|
|
DWORD& dwSCnt()
|
|
{ return m_dwSCnt; }
|
|
HRESULT& ddRVal()
|
|
{ return m_ddRVal; }
|
|
LPDDHAL_CREATESURFACE& CreateSurface()
|
|
{ return m_CreateSurface; }
|
|
};
|
|
|
|
class PORTABLE_DESTROYSURFACEDATA
|
|
{
|
|
private:
|
|
LPDDRAWI_DIRECTDRAW_GBL m_lpDD;
|
|
PORTABLE_DDRAWSURFACE_LCL* m_lpDDSurface;
|
|
HRESULT m_ddRVal;
|
|
LPDDHALSURFCB_DESTROYSURFACE m_DestroySurface;
|
|
|
|
public:
|
|
LPDDRAWI_DIRECTDRAW_GBL& lpDD()
|
|
{ return m_lpDD; }
|
|
PORTABLE_DDRAWSURFACE_LCL*& lpDDSurface()
|
|
{ return m_lpDDSurface; }
|
|
HRESULT& ddRVal()
|
|
{ return m_ddRVal; }
|
|
LPDDHALSURFCB_DESTROYSURFACE& DestroySurface()
|
|
{ return m_DestroySurface; }
|
|
};
|
|
|
|
class PORTABLE_LOCKDATA
|
|
{
|
|
private:
|
|
LPDDRAWI_DIRECTDRAW_GBL m_lpDD;
|
|
PORTABLE_DDRAWSURFACE_LCL* m_lpDDSurface;
|
|
DWORD m_bHasRect;
|
|
RECTL m_rArea;
|
|
LPVOID m_lpSurfData;
|
|
HRESULT m_ddRVal;
|
|
LPDDHALSURFCB_LOCK m_Lock;
|
|
DWORD m_dwFlags;
|
|
|
|
public:
|
|
LPDDRAWI_DIRECTDRAW_GBL& lpDD()
|
|
{ return m_lpDD; }
|
|
PORTABLE_DDRAWSURFACE_LCL*& lpDDSurface()
|
|
{ return m_lpDDSurface; }
|
|
DWORD& bHasRect()
|
|
{ return m_bHasRect; }
|
|
RECTL& rArea()
|
|
{ return m_rArea; }
|
|
LPVOID& lpSurfData()
|
|
{ return m_lpSurfData; }
|
|
HRESULT& ddRVal()
|
|
{ return m_ddRVal; }
|
|
LPDDHALSURFCB_LOCK& Lock()
|
|
{ return m_Lock; }
|
|
DWORD& dwFlags()
|
|
{ return m_dwFlags; }
|
|
};
|
|
|
|
class PORTABLE_UNLOCKDATA
|
|
{
|
|
private:
|
|
LPDDRAWI_DIRECTDRAW_GBL m_lpDD;
|
|
PORTABLE_DDRAWSURFACE_LCL* m_lpDDSurface;
|
|
HRESULT m_ddRVal;
|
|
LPDDHALSURFCB_UNLOCK m_Unlock;
|
|
|
|
public:
|
|
LPDDRAWI_DIRECTDRAW_GBL& lpDD()
|
|
{ return m_lpDD; }
|
|
PORTABLE_DDRAWSURFACE_LCL*& lpDDSurface()
|
|
{ return m_lpDDSurface; }
|
|
HRESULT& ddRVal()
|
|
{ return m_ddRVal; }
|
|
LPDDHALSURFCB_UNLOCK& Unlock()
|
|
{ return m_Unlock; }
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CSurfaceLocker
|
|
//
|
|
// This class safely locks a surface upon construction and unlocks the surface
|
|
// upon destruction.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
template< class TSurfacePtr>
|
|
class CSurfaceLocker
|
|
{
|
|
protected: // Variables
|
|
TSurfacePtr m_pSurface;
|
|
void* m_pSData;
|
|
|
|
public: // Functions
|
|
explicit CSurfaceLocker( const TSurfacePtr& S, DWORD dwLockFlags,
|
|
const RECTL* pRect) : m_pSurface( S)
|
|
{ m_pSData= m_pSurface->Lock( dwLockFlags, pRect); }
|
|
~CSurfaceLocker()
|
|
{ m_pSurface->Unlock(); }
|
|
void* const& GetData() const
|
|
{ return m_pSData; }
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CEnsureFPUModeForC
|
|
//
|
|
// This class converts the FPU mode for x86 chips back into the mode compatable
|
|
// for C operations. The mode that D3D sets up for rasterizers is single
|
|
// precision, for more speed. But, sometimes, the rasterizer needs to do
|
|
// double operations and get double precision accuracy. This class sets up the
|
|
// mode for as long as the class is in scope.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
class CEnsureFPUModeForC
|
|
{
|
|
protected: // Variables
|
|
WORD m_wSaveFP;
|
|
|
|
public:
|
|
CEnsureFPUModeForC()
|
|
{
|
|
#if defined(_X86_)
|
|
// save floating point mode and set to double precision mode
|
|
// which is compatable with C/ C++
|
|
WORD wTemp, wSave;
|
|
__asm
|
|
{
|
|
fstcw wSave
|
|
mov ax, wSave
|
|
or ax, 0200h
|
|
mov wTemp, ax
|
|
fldcw wTemp
|
|
}
|
|
m_wSaveFP= wSave;
|
|
#endif
|
|
}
|
|
~CEnsureFPUModeForC()
|
|
{
|
|
#if defined(_X86_)
|
|
WORD wSave( m_wSaveFP);
|
|
__asm fldcw wSave
|
|
#endif
|
|
}
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// SDP2NextCmd
|
|
//
|
|
// A unary_function which can return the pointer to the next
|
|
// DrawPrimitive2 command in a contiguous buffer given a pointer to a valid
|
|
// DrawPrimitive2 command in the same buffer, as is a common situation for
|
|
// processing DrawPrimitive2 commands within the DrawPrimitive2 function call.
|
|
// This class is naturally useful for DrawPrimitive2 command iterators.
|
|
// It contains all the possible commands that could be encountered for a DX8SDDI
|
|
// driver.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
struct SDP2NextCmd:
|
|
public unary_function< const D3DHAL_DP2COMMAND*, D3DHAL_DP2COMMAND*>
|
|
{
|
|
// This function allows iteration from one D3DHAL_DP2COMMAND* to the next.
|
|
// This operation can be optimized quite a bit if many of the more advanced
|
|
// features aren't supported (as tough to process D3DDP2_OPs might not be
|
|
// encountered).
|
|
D3DHAL_DP2COMMAND* operator()( const D3DHAL_DP2COMMAND* pCur) const
|
|
{
|
|
const UINT8* pBRet= reinterpret_cast< const UINT8*>(pCur)+
|
|
sizeof( D3DHAL_DP2COMMAND);
|
|
switch( pCur->bCommand)
|
|
{
|
|
//case( D3DDP2OP_POINTS): // <DX8
|
|
//case( D3DDP2OP_INDEXEDLINELIST): // <DX8
|
|
//case( D3DDP2OP_INDEXEDTRIANGLELIST): // <DX8
|
|
//case( D3DDP2OP_RESERVED0):
|
|
case( D3DDP2OP_RENDERSTATE): // DX8 All
|
|
pBRet+= sizeof( D3DHAL_DP2RENDERSTATE)* pCur->wStateCount;
|
|
break;
|
|
//case( D3DDP2OP_LINELIST): // <DX8
|
|
//case( D3DDP2OP_LINESTRIP): // <DX8
|
|
//case( D3DDP2OP_INDEXEDLINESTRIP): // <DX8
|
|
//case( D3DDP2OP_TRIANGLELIST): // <DX8
|
|
//case( D3DDP2OP_TRIANGLESTRIP): // <DX8
|
|
//case( D3DDP2OP_INDEXEDTRIANGLESTRIP): // <DX8
|
|
//case( D3DDP2OP_TRIANGLEFAN): // <DX8
|
|
//case( D3DDP2OP_INDEXEDTRIANGLEFAN): // <DX8
|
|
//case( D3DDP2OP_TRIANGLEFAN_IMM): // <DX8
|
|
//case( D3DDP2OP_LINELIST_IMM): // <DX8
|
|
case( D3DDP2OP_TEXTURESTAGESTATE): // DX8 All
|
|
pBRet+= sizeof( D3DHAL_DP2TEXTURESTAGESTATE)* pCur->wStateCount;
|
|
break;
|
|
//case( D3DDP2OP_INDEXEDTRIANGLELIST2): // <DX8
|
|
//case( D3DDP2OP_INDEXEDLINELIST2): // <DX8
|
|
case( D3DDP2OP_VIEWPORTINFO): // DX8 All
|
|
pBRet+= sizeof( D3DHAL_DP2VIEWPORTINFO)* pCur->wStateCount;
|
|
break;
|
|
case( D3DDP2OP_WINFO): // DX8 All
|
|
pBRet+= sizeof( D3DHAL_DP2WINFO)* pCur->wStateCount;
|
|
break;
|
|
case( D3DDP2OP_SETPALETTE): // DX8 (if support palettized surf/tex)
|
|
pBRet+= sizeof( D3DHAL_DP2SETPALETTE)* pCur->wStateCount;
|
|
break;
|
|
case( D3DDP2OP_UPDATEPALETTE): // DX8 (if support palettized surf/tex)
|
|
assert( pCur->wStateCount== 1);
|
|
pBRet= pBRet+ sizeof( D3DHAL_DP2UPDATEPALETTE)+
|
|
reinterpret_cast< const D3DHAL_DP2UPDATEPALETTE*>(
|
|
pBRet)->wNumEntries* sizeof( DWORD);
|
|
break;
|
|
case( D3DDP2OP_ZRANGE): // DX8 (if support TnL)
|
|
pBRet+= sizeof( D3DHAL_DP2ZRANGE)* pCur->wStateCount;
|
|
break;
|
|
case( D3DDP2OP_SETMATERIAL): // DX8 (if support TnL)
|
|
pBRet+= sizeof( D3DHAL_DP2SETMATERIAL)* pCur->wStateCount;
|
|
break;
|
|
case( D3DDP2OP_SETLIGHT): // DX8 (if support TnL)
|
|
{ WORD wStateCount( pCur->wStateCount);
|
|
if( wStateCount!= 0) do
|
|
{
|
|
const D3DHAL_DP2SETLIGHT* pSL=
|
|
reinterpret_cast< const D3DHAL_DP2SETLIGHT*>( pBRet);
|
|
|
|
if( D3DHAL_SETLIGHT_DATA== pSL->dwDataType)
|
|
pBRet+= sizeof( D3DLIGHT8);
|
|
pBRet+= sizeof( D3DHAL_DP2SETLIGHT);
|
|
} while( --wStateCount); }
|
|
break;
|
|
case( D3DDP2OP_CREATELIGHT): // DX8 (if support TnL)
|
|
pBRet+= sizeof( D3DHAL_DP2CREATELIGHT)* pCur->wStateCount;
|
|
break;
|
|
case( D3DDP2OP_SETTRANSFORM): // DX8 (if support TnL)
|
|
pBRet+= sizeof( D3DHAL_DP2SETTRANSFORM)* pCur->wStateCount;
|
|
break;
|
|
case( D3DDP2OP_EXT): // DX8 (if work seemlessly with TnL extensions)
|
|
{ WORD wStateCount( pCur->wStateCount);
|
|
if( wStateCount!= 0) do
|
|
{
|
|
pBRet+= reinterpret_cast< const D3DHAL_DP2EXT*>(pBRet)->dwSize;
|
|
} while( --wStateCount); }
|
|
break;
|
|
case( D3DDP2OP_TEXBLT): // DX8 (if support vidmem texture)
|
|
pBRet+= sizeof( D3DHAL_DP2TEXBLT)* pCur->wStateCount;
|
|
break;
|
|
case( D3DDP2OP_STATESET): // DX8 All
|
|
pBRet+= sizeof( D3DHAL_DP2STATESET)* pCur->wStateCount;
|
|
break;
|
|
case( D3DDP2OP_SETPRIORITY): // DX8 (if manage textures)
|
|
pBRet+= sizeof( D3DHAL_DP2SETPRIORITY)* pCur->wStateCount;
|
|
break;
|
|
case( D3DDP2OP_SETRENDERTARGET): // DX8 All
|
|
pBRet+= sizeof( D3DHAL_DP2SETRENDERTARGET)* pCur->wStateCount;
|
|
break;
|
|
case( D3DDP2OP_CLEAR): // DX8 All
|
|
pBRet+= sizeof( D3DHAL_DP2CLEAR)- sizeof( RECT)+ sizeof( RECT)*
|
|
pCur->wStateCount;
|
|
break;
|
|
case( D3DDP2OP_SETTEXLOD): // DX8 (if manage textures)
|
|
pBRet+= sizeof( D3DHAL_DP2SETTEXLOD)* pCur->wStateCount;
|
|
break;
|
|
case( D3DDP2OP_SETCLIPPLANE): // DX8 (if support user clip planes)
|
|
pBRet+= sizeof( D3DHAL_DP2SETCLIPPLANE)* pCur->wStateCount;
|
|
break;
|
|
case( D3DDP2OP_CREATEVERTEXSHADER): // DX8 (if support vshaders)
|
|
{ WORD wStateCount( pCur->wStateCount);
|
|
if( wStateCount!= 0) do
|
|
{
|
|
const D3DHAL_DP2CREATEVERTEXSHADER* pCVS=
|
|
reinterpret_cast< const D3DHAL_DP2CREATEVERTEXSHADER*>(
|
|
pBRet);
|
|
pBRet+= sizeof( D3DHAL_DP2CREATEVERTEXSHADER)+
|
|
pCVS->dwDeclSize+ pCVS->dwCodeSize;
|
|
} while( --wStateCount); }
|
|
break;
|
|
case( D3DDP2OP_DELETEVERTEXSHADER): // DX8 (if support vshaders)
|
|
pBRet+= sizeof( D3DHAL_DP2VERTEXSHADER)* pCur->wStateCount;
|
|
break;
|
|
case( D3DDP2OP_SETVERTEXSHADER): // DX8 All
|
|
pBRet+= sizeof( D3DHAL_DP2VERTEXSHADER)* pCur->wStateCount;
|
|
break;
|
|
case( D3DDP2OP_SETVERTEXSHADERCONST): // DX8 (if support vshaders)
|
|
{ WORD wStateCount( pCur->wStateCount);
|
|
if( wStateCount!= 0) do
|
|
{
|
|
const D3DHAL_DP2SETVERTEXSHADERCONST* pSVSC=
|
|
reinterpret_cast< const D3DHAL_DP2SETVERTEXSHADERCONST*>(
|
|
pBRet);
|
|
pBRet+= sizeof( D3DHAL_DP2SETVERTEXSHADERCONST)+
|
|
4* sizeof( D3DVALUE)* pSVSC->dwCount;
|
|
} while( --wStateCount); }
|
|
break;
|
|
case( D3DDP2OP_SETSTREAMSOURCE): // DX8 All
|
|
pBRet+= sizeof( D3DHAL_DP2SETSTREAMSOURCE)* pCur->wStateCount;
|
|
break;
|
|
case( D3DDP2OP_SETSTREAMSOURCEUM): // DX8 All (unless no DrawPrimUP calls)
|
|
pBRet+= sizeof( D3DHAL_DP2SETSTREAMSOURCEUM)* pCur->wStateCount;
|
|
break;
|
|
case( D3DDP2OP_SETINDICES): // DX8 All
|
|
pBRet+= sizeof( D3DHAL_DP2SETINDICES)* pCur->wStateCount;
|
|
break;
|
|
case( D3DDP2OP_DRAWPRIMITIVE): // DX8 All
|
|
pBRet+= sizeof( D3DHAL_DP2DRAWPRIMITIVE)* pCur->wPrimitiveCount;
|
|
break;
|
|
case( D3DDP2OP_DRAWINDEXEDPRIMITIVE): // DX8 All
|
|
pBRet+= sizeof( D3DHAL_DP2DRAWINDEXEDPRIMITIVE)*
|
|
pCur->wPrimitiveCount;
|
|
break;
|
|
case( D3DDP2OP_CREATEPIXELSHADER): // DX8 (if support pshaders)
|
|
{ WORD wStateCount( pCur->wStateCount);
|
|
if( wStateCount!= 0) do
|
|
{
|
|
const D3DHAL_DP2CREATEPIXELSHADER* pCPS=
|
|
reinterpret_cast< const D3DHAL_DP2CREATEPIXELSHADER*>(
|
|
pBRet);
|
|
pBRet+= sizeof( D3DHAL_DP2CREATEPIXELSHADER)+
|
|
pCPS->dwCodeSize;
|
|
} while( --wStateCount); }
|
|
break;
|
|
case( D3DDP2OP_DELETEPIXELSHADER): // DX8 (if support pshaders)
|
|
pBRet+= sizeof( D3DHAL_DP2PIXELSHADER)* pCur->wStateCount;
|
|
break;
|
|
case( D3DDP2OP_SETPIXELSHADER): // DX8 (if support pshaders)
|
|
pBRet+= sizeof( D3DHAL_DP2PIXELSHADER)* pCur->wStateCount;
|
|
break;
|
|
case( D3DDP2OP_SETPIXELSHADERCONST): // DX8 (if support pshaders)
|
|
{ WORD wStateCount( pCur->wStateCount);
|
|
if( wStateCount!= 0) do
|
|
{
|
|
const D3DHAL_DP2SETPIXELSHADERCONST* pSPSC=
|
|
reinterpret_cast< const D3DHAL_DP2SETPIXELSHADERCONST*>(
|
|
pBRet);
|
|
pBRet+= sizeof( D3DHAL_DP2SETPIXELSHADERCONST)+
|
|
4* sizeof( D3DVALUE)* pSPSC->dwCount;
|
|
} while( --wStateCount); }
|
|
break;
|
|
case( D3DDP2OP_CLIPPEDTRIANGLEFAN): // DX8 All
|
|
pBRet+= sizeof( D3DHAL_CLIPPEDTRIANGLEFAN)* pCur->wPrimitiveCount;
|
|
break;
|
|
case( D3DDP2OP_DRAWPRIMITIVE2): // DX8 All
|
|
pBRet+= sizeof( D3DHAL_DP2DRAWPRIMITIVE2)* pCur->wPrimitiveCount;
|
|
break;
|
|
case( D3DDP2OP_DRAWINDEXEDPRIMITIVE2): // DX8 All
|
|
pBRet+= sizeof( D3DHAL_DP2DRAWINDEXEDPRIMITIVE2)*
|
|
pCur->wPrimitiveCount;
|
|
break;
|
|
case( D3DDP2OP_DRAWRECTPATCH): // DX8 (if support higher order prims)
|
|
{ WORD wPrimitiveCount( pCur->wPrimitiveCount);
|
|
if( wPrimitiveCount!= 0) do
|
|
{
|
|
const D3DHAL_DP2DRAWRECTPATCH* pDRP=
|
|
reinterpret_cast< const D3DHAL_DP2DRAWRECTPATCH*>(pBRet);
|
|
|
|
pBRet+= sizeof( D3DHAL_DP2DRAWRECTPATCH);
|
|
|
|
if((pDRP->Flags& RTPATCHFLAG_HASSEGS)!= 0)
|
|
pBRet+= 4* sizeof( D3DVALUE);
|
|
|
|
if((pDRP->Flags& RTPATCHFLAG_HASINFO)!= 0)
|
|
pBRet+= sizeof( D3DRECTPATCH_INFO);
|
|
} while( --wPrimitiveCount); }
|
|
break;
|
|
case( D3DDP2OP_DRAWTRIPATCH): // DX8 (if support higher order prims)
|
|
{ WORD wPrimitiveCount( pCur->wPrimitiveCount);
|
|
if( wPrimitiveCount!= 0) do
|
|
{
|
|
const D3DHAL_DP2DRAWTRIPATCH* pDTP=
|
|
reinterpret_cast< const D3DHAL_DP2DRAWTRIPATCH*>(pBRet);
|
|
|
|
pBRet+= sizeof( D3DHAL_DP2DRAWTRIPATCH);
|
|
|
|
if((pDTP->Flags& RTPATCHFLAG_HASSEGS)!= 0)
|
|
pBRet+= 3* sizeof( D3DVALUE);
|
|
|
|
if((pDTP->Flags& RTPATCHFLAG_HASINFO)!= 0)
|
|
pBRet+= sizeof( D3DTRIPATCH_INFO);
|
|
} while( --wPrimitiveCount); }
|
|
break;
|
|
case( D3DDP2OP_VOLUMEBLT): // DX8 (if support vidmem volume texture)
|
|
pBRet+= sizeof( D3DHAL_DP2VOLUMEBLT)* pCur->wStateCount;
|
|
break;
|
|
case( D3DDP2OP_BUFFERBLT): // DX8 (if support vidmem vrtx/indx buffer)
|
|
pBRet+= sizeof( D3DHAL_DP2BUFFERBLT)* pCur->wStateCount;
|
|
break;
|
|
case( D3DDP2OP_MULTIPLYTRANSFORM): // DX8 (if support TnL)
|
|
pBRet+= sizeof( D3DHAL_DP2MULTIPLYTRANSFORM)* pCur->wStateCount;
|
|
break;
|
|
default: {
|
|
const bool Unable_To_Parse_Unrecognized_D3DDP2OP( false);
|
|
assert( Unable_To_Parse_Unrecognized_D3DDP2OP);
|
|
} break;
|
|
}
|
|
return const_cast<D3DHAL_DP2COMMAND*>
|
|
(reinterpret_cast<const D3DHAL_DP2COMMAND*>(pBRet));
|
|
}
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CDP2CmdIterator & CDP2ConstCmdIterator
|
|
//
|
|
// These iterators are provided as a convenience to iterate DrawPrimitive2
|
|
// commands which are packed in a contiguous chunk of memory, as is typical
|
|
// of execute/ command buffers which need to be processed within the
|
|
// DrawPrimitive2 function call. The actual iteration logic is encapsulated in
|
|
// the template parameter, so that it can be easily extended, if certain
|
|
// commands aren't exepected and a better iteration scheme could be used.
|
|
//
|
|
// Be careful, these iterators are only useful for iterating. They do not
|
|
// directly know the size of the data they point to. For completeness, which
|
|
// would allow seperate storage of commands, another class would need to be
|
|
// created and assigned as the value_type. Dereferencing the iterator only
|
|
// returns a D3DHAL_DP2COMMAND without any extra data. Something like:
|
|
//
|
|
// CDP2Cmd DP2Cmd= *itDP2Cmd;
|
|
//
|
|
// is possible; but requires more work and definition of CDP2Cmd.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
template< class TNextCmd= SDP2NextCmd>
|
|
class CDP2CmdIterator
|
|
{
|
|
public: // Types
|
|
typedef forward_iterator_tag iterator_category;
|
|
typedef D3DHAL_DP2COMMAND value_type;
|
|
typedef ptrdiff_t difference_type;
|
|
typedef D3DHAL_DP2COMMAND* pointer;
|
|
typedef D3DHAL_DP2COMMAND& reference;
|
|
|
|
protected: // Variables
|
|
pointer m_pRawCmd;
|
|
TNextCmd m_NextCmd;
|
|
|
|
public: // Functions
|
|
CDP2CmdIterator( pointer pRaw= NULL)
|
|
:m_pRawCmd( pRaw) { }
|
|
CDP2CmdIterator( pointer pRaw, const TNextCmd& NextCmd)
|
|
:m_NextCmd( NextCmd), m_pRawCmd( pRaw) { }
|
|
CDP2CmdIterator( const CDP2CmdIterator< TNextCmd>& Other)
|
|
:m_NextCmd( Other.m_NextCmd), m_pRawCmd( Other.m_pRawCmd) { }
|
|
|
|
reference operator*() const
|
|
{ return *m_pRawCmd; }
|
|
pointer operator->() const
|
|
{ return m_pRawCmd; }
|
|
operator pointer() const
|
|
{ return m_pRawCmd; }
|
|
|
|
CDP2CmdIterator< TNextCmd>& operator++()
|
|
{ m_pRawCmd= m_NextCmd( m_pRawCmd); return *this; }
|
|
CDP2CmdIterator< TNextCmd> operator++(int)
|
|
{
|
|
CDP2CmdIterator< TNextCmd> tmp= *this;
|
|
m_pRawCmd= m_NextCmd( m_pRawCmd);
|
|
return tmp;
|
|
}
|
|
bool operator==( CDP2CmdIterator< TNextCmd>& x) const
|
|
{ return m_pRawCmd== x.m_pRawCmd; }
|
|
bool operator!=( CDP2CmdIterator< TNextCmd>& x) const
|
|
{ return m_pRawCmd!= x.m_pRawCmd; }
|
|
};
|
|
|
|
template< class TNextCmd= SDP2NextCmd>
|
|
class CConstDP2CmdIterator
|
|
{
|
|
public: // Types
|
|
typedef forward_iterator_tag iterator_category;
|
|
typedef const D3DHAL_DP2COMMAND value_type;
|
|
typedef ptrdiff_t difference_type;
|
|
typedef const D3DHAL_DP2COMMAND* pointer;
|
|
typedef const D3DHAL_DP2COMMAND& reference;
|
|
|
|
protected: // Variables
|
|
pointer m_pRawCmd;
|
|
TNextCmd m_NextCmd;
|
|
|
|
public: // Functions
|
|
CConstDP2CmdIterator( pointer pRaw= NULL)
|
|
:m_pRawCmd( pRaw) { }
|
|
CConstDP2CmdIterator( pointer pRaw, const TNextCmd& NextCmd)
|
|
:m_NextCmd( NextCmd), m_pRawCmd( pRaw) { }
|
|
CConstDP2CmdIterator( const CDP2CmdIterator< TNextCmd>& Other)
|
|
:m_NextCmd( Other.m_NextCmd), m_pRawCmd( Other.m_pRawCmd) { }
|
|
CConstDP2CmdIterator( const CConstDP2CmdIterator< TNextCmd>& Other)
|
|
:m_NextCmd( Other.m_NextCmd), m_pRawCmd( Other.m_pRawCmd) { }
|
|
|
|
reference operator*() const
|
|
{ return *m_pRawCmd; }
|
|
pointer operator->() const
|
|
{ return m_pRawCmd; }
|
|
operator pointer() const
|
|
{ return m_pRawCmd; }
|
|
|
|
CConstDP2CmdIterator< TNextCmd>& operator++()
|
|
{ m_pRawCmd= m_NextCmd( m_pRawCmd); return *this; }
|
|
CConstDP2CmdIterator< TNextCmd> operator++(int)
|
|
{
|
|
CConstDP2CmdIterator< TNextCmd> tmp= *this;
|
|
m_pRawCmd= m_NextCmd( m_pRawCmd);
|
|
return tmp;
|
|
}
|
|
bool operator==( CConstDP2CmdIterator< TNextCmd>& x) const
|
|
{ return m_pRawCmd== x.m_pRawCmd; }
|
|
bool operator!=( CConstDP2CmdIterator< TNextCmd>& x) const
|
|
{ return m_pRawCmd!= x.m_pRawCmd; }
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CDP2DataWrap
|
|
//
|
|
// This class is provided as a convenience to expose the
|
|
// PORTABLE_DRAWPRIMITIVES2DATA as a more friendly class. Mostly, it wraps the
|
|
// execute/ command buffer with an STL Sequence Container, so that the commands
|
|
// can be iterated over without copying and pre-parsing the command data.
|
|
//
|
|
// <Template Parameters>
|
|
// TNextCmd: a unary_function which takes a const D3DHAL_DP2COMMAND* in and
|
|
// returns a D3DHAL_DP2COMMAND* which points to the next command. In
|
|
// essence, a unary_function which enables a forward iterator on a
|
|
// contiguous command buffer.
|
|
//
|
|
// <Exposed Types>
|
|
// TCmds: The Sequence Container type which exposed the commands.
|
|
//
|
|
// <Exposed Functions>
|
|
// CDP2DataWrap( PORTABLE_DRAWPRIMITIVES2DATA& DP2Data): Constructor to wrap the
|
|
// PORTABLE_DRAWPRIMITIVES2DATA.
|
|
// const TCmds& GetCommands() const: Accessor function to get at the Sequence
|
|
// Container.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
template< class TNextCmd= SDP2NextCmd>
|
|
class CDP2DataWrap:
|
|
public PORTABLE_DRAWPRIMITIVES2DATA
|
|
{
|
|
public: // Types
|
|
class CDP2Cmds
|
|
{
|
|
public: // Types
|
|
typedef CConstDP2CmdIterator< TNextCmd> const_iterator;
|
|
typedef typename const_iterator::value_type value_type;
|
|
typedef typename const_iterator::reference const_reference;
|
|
typedef typename const_iterator::pointer const_pointer;
|
|
typedef typename const_iterator::difference_type difference_type;
|
|
typedef size_t size_type;
|
|
|
|
protected: // Variables
|
|
CDP2DataWrap< TNextCmd>* m_pDP2Data;
|
|
|
|
protected: // Functions
|
|
// Allow to call constructor and set member variable.
|
|
friend class CDP2DataWrap< TNextCmd>;
|
|
|
|
CDP2Cmds( )
|
|
:m_pDP2Data( NULL) { }
|
|
|
|
public: // Functions
|
|
const_iterator begin( void) const
|
|
{
|
|
return const_iterator( reinterpret_cast<D3DHAL_DP2COMMAND*>(
|
|
reinterpret_cast<UINT8*>(m_pDP2Data->lpDDCommands()->lpGbl()->fpVidMem)
|
|
+ m_pDP2Data->dwCommandOffset()));
|
|
}
|
|
const_iterator end( void) const
|
|
{
|
|
return const_iterator( reinterpret_cast<D3DHAL_DP2COMMAND*>(
|
|
reinterpret_cast<UINT8*>(m_pDP2Data->lpDDCommands()->lpGbl()->fpVidMem)
|
|
+ m_pDP2Data->dwCommandOffset()+ m_pDP2Data->dwCommandLength()));
|
|
}
|
|
size_type size( void) const
|
|
{
|
|
size_type N( 0);
|
|
const_iterator itS( begin());
|
|
const_iterator itE( end());
|
|
while( itS!= itE)
|
|
{ ++itS; ++N; }
|
|
return N;
|
|
}
|
|
size_type max_size( void) const
|
|
{ return size(); }
|
|
bool empty( void) const
|
|
{ return begin()== end(); }
|
|
};
|
|
typedef CDP2Cmds TCmds;
|
|
|
|
protected: // Variables
|
|
TCmds m_Cmds;
|
|
|
|
public: // Functions
|
|
explicit CDP2DataWrap( PORTABLE_DRAWPRIMITIVES2DATA& DP2Data)
|
|
: PORTABLE_DRAWPRIMITIVES2DATA( DP2Data)
|
|
{ m_Cmds.m_pDP2Data= this; }
|
|
const TCmds& GetCommands( void) const
|
|
{ return m_Cmds; }
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// SDP2MFnParser
|
|
//
|
|
// This class is a functional class, with many too many paramters to squeeze
|
|
// into the standard functional classes. It automates the parsing, member fn
|
|
// lookup, and dispatching for DrawPrimitive2 commands. This parser uses the
|
|
// command number to lookup a member function from a container to call.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
struct SDP2MFnParser
|
|
{
|
|
// <Parameters>
|
|
// MFnCaller: A binary_function type with TDP2CmdFnCtr::value_type,
|
|
// typically a member function pointer, as the first argument;
|
|
// TIter, typically a smart DP2 command iterator, as the second
|
|
// argument; and returns an HRESULT. This function type should call
|
|
// the member function to process the DP2 command, with the iterator
|
|
// used to determine the DP2 Cmd data.
|
|
// DP2CmdFnCtr: This can be any Unique, Pair Associative Container,
|
|
// typically a map, which associates a D3DHAL_DP2OPERATION with a
|
|
// member function.
|
|
// [itStart, itEnd): These iterators define a standard range of
|
|
// D3DHAL_DP2COMMAND. The iterators need only be forward iterators,
|
|
// and be convertable to raw D3DHAL_DP2COMMAND*. Note: itStart is
|
|
// a reference, so that the caller can determine the current iterator
|
|
// position upon return of function (when HRESULT!= DD_OK).
|
|
template< class TMFnCaller, class TDP2CmdFnCtr, class TIter>
|
|
HRESULT ParseDP2( TMFnCaller& MFnCaller, TDP2CmdFnCtr& DP2CmdFnCtr,
|
|
TIter& itStart, TIter itEnd) const
|
|
{
|
|
HRESULT hr( DD_OK);
|
|
while( itStart!= itEnd)
|
|
{
|
|
try
|
|
{
|
|
hr= MFnCaller( DP2CmdFnCtr[ itStart->bCommand], itStart);
|
|
} catch( HRESULT hrEx) {
|
|
hr= hrEx;
|
|
#if !defined( DX8SDDIFW_NOCATCHALL)
|
|
} catch ( ... ) {
|
|
const bool Unrecognized_Exception_In_A_DP2_Op_Function( false);
|
|
assert( Unrecognized_Exception_In_A_DP2_Op_Function);
|
|
hr= E_UNEXPECTED;
|
|
#endif // !defined( DX8SDDIFW_NOCATCHALL)
|
|
}
|
|
|
|
// Only move on to next command if DD_OK. Otherwise return out
|
|
// to caller. They can always call us back if caller determines
|
|
// error code is a SUCCESS.
|
|
if( DD_OK== hr)
|
|
++itStart;
|
|
else
|
|
break;
|
|
}
|
|
return hr;
|
|
}
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CSubStateSet & CMinimalStateSet
|
|
//
|
|
// This class contains a default implementation of a stateset. It copies/ packs
|
|
// a contiguous DP2 command buffer into a memory buffer. To capture, it asks
|
|
// the context to record the command buffer with the Context's current state.
|
|
// To execute, it fixes up a Fake DrawPrimitives2 point parameter
|
|
// and calls the context's DrawPrimitives2 entry point. The context
|
|
// needs to be able to handle recursive DrawPrimitives2 calls in order to use
|
|
// this default stateset. CStdDrawPrimitives2's DrawPrimitives2 handler
|
|
// does this by storing whether it is executing a stateset.
|
|
//
|
|
// <Template Parameters>
|
|
// TSuper: Standard parent type which is inheriting from this child class.
|
|
// In this case, it should typically be the CMyStateSet type.
|
|
// TC: The Context type, typically, CMyContext.
|
|
//
|
|
// <Exposed Types>
|
|
// TContext: The Context type passed in as a template parameter.
|
|
//
|
|
// <Exposed Functions>
|
|
// CSubStateSet( TContext&, const D3DHAL_DP2COMMAND*, const D3DHAL_DP2COMMAND*):
|
|
// The constructor which builds a stateset for a Context, from a range of
|
|
// a command buffer. The default implementation will just copy this range.
|
|
// CSubStateSet( const CSubStateSet& Other): Standard copy constructor.
|
|
// void Capture( TContext&): The state set is instructed to capture the
|
|
// necessary data from the Context, in order to perform an Execute later,
|
|
// which will restore the data fields or state that the state set was
|
|
// constructed with.
|
|
// void Execute( TContext&): Restore or rebuild the Context with the data/
|
|
// state that was saved during the Capture operation.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
template< class TSuper, class TC>
|
|
class CSubStateSet
|
|
{
|
|
public: // Types
|
|
typedef TC TContext;
|
|
|
|
protected: // Variables
|
|
TContext& m_Context;
|
|
D3DHAL_DP2COMMAND* m_pBeginSS;
|
|
size_t m_uiSSBufferSize;
|
|
|
|
protected: // Functions
|
|
CSubStateSet( const CSubStateSet< TSuper, TC>& Other)
|
|
:m_Context( Other.m_Context), m_pBeginSS( NULL),
|
|
m_uiSSBufferSize( Other.m_uiSSBufferSize)
|
|
{
|
|
try {
|
|
m_pBeginSS= reinterpret_cast< D3DHAL_DP2COMMAND*>(
|
|
operator new( m_uiSSBufferSize));
|
|
} catch( ... ) {
|
|
}
|
|
if( NULL== m_pBeginSS)
|
|
throw bad_alloc( "Not enough room to copy state set command "
|
|
"buffer.");
|
|
memcpy( m_pBeginSS, Other.m_pBeginSS, m_uiSSBufferSize);
|
|
}
|
|
CSubStateSet( TContext& C, const D3DHAL_DP2COMMAND* pBeginSS, const
|
|
D3DHAL_DP2COMMAND* pEndSS) : m_Context( C), m_pBeginSS( NULL),
|
|
m_uiSSBufferSize( 0)
|
|
{
|
|
// Convert the contiguous command pointers to byte pointers, to
|
|
// calculate the size of buffer needed to copy the data.
|
|
const UINT8* pSBytePtr= reinterpret_cast< const UINT8*>( pBeginSS);
|
|
const UINT8* pEBytePtr= reinterpret_cast< const UINT8*>( pEndSS);
|
|
m_uiSSBufferSize= static_cast< size_t>( pEBytePtr- pSBytePtr);
|
|
try {
|
|
m_pBeginSS= reinterpret_cast< D3DHAL_DP2COMMAND*>(
|
|
operator new( m_uiSSBufferSize));
|
|
} catch( ... ) {
|
|
}
|
|
if( NULL== m_pBeginSS)
|
|
throw bad_alloc( "Not enough room to allocate state set command "
|
|
"buffer.");
|
|
memcpy( m_pBeginSS, pBeginSS, m_uiSSBufferSize);
|
|
}
|
|
~CSubStateSet()
|
|
{
|
|
operator delete( static_cast< void*>( m_pBeginSS));
|
|
}
|
|
|
|
public: // Functions
|
|
CSubStateSet< TSuper, TC>& operator=( const CSubStateSet< TSuper, TC>& Oth)
|
|
{
|
|
assert( &m_Context== &Oth.m_Context);
|
|
if( m_uiSSBufferSize<= Oth.m_uiSSBufferSize)
|
|
{
|
|
m_uiSSBufferSize= Oth.m_uiSSBufferSize;
|
|
memcpy( m_pBeginSS, Oth.m_pBeginSS, m_uiSSBufferSize);
|
|
}
|
|
else
|
|
{
|
|
void* pNewBuffer= NULL;
|
|
try {
|
|
pNewBuffer= operator new( Oth.m_uiSSBufferSize);
|
|
} catch( ... ) {
|
|
}
|
|
if( NULL== pNewBuffer)
|
|
throw bad_alloc( "Not enough room to copy state set command "
|
|
"buffer.");
|
|
|
|
operator delete( static_cast< void*>( m_pBeginSS));
|
|
m_pBeginSS= reinterpret_cast< D3DHAL_DP2COMMAND*>( pNewBuffer);
|
|
m_uiSSBufferSize= Oth.m_uiSSBufferSize;
|
|
memcpy( m_pBeginSS, Other.m_pBeginSS, m_uiSSBufferSize);
|
|
}
|
|
return *this;
|
|
}
|
|
void Capture( TContext& Ctx)
|
|
{
|
|
assert( &m_Context== &Ctx);
|
|
|
|
UINT8* pBytePtr= reinterpret_cast< UINT8*>( m_pBeginSS);
|
|
D3DHAL_DP2COMMAND* pEndSS= reinterpret_cast< D3DHAL_DP2COMMAND*>(
|
|
pBytePtr+ m_uiSSBufferSize);
|
|
|
|
// Ask Context to record it's current state into the stored command
|
|
// buffer. CStdDrawPrimitives2 can provide an implementation of
|
|
// RecordCommandBuffer for the Context.
|
|
Ctx.RecordCommandBuffer( m_pBeginSS, pEndSS);
|
|
}
|
|
void Execute( TContext& Ctx)
|
|
{
|
|
assert( &m_Context== &Ctx);
|
|
|
|
// Build up a fake PORTABLE_DRAWPRIMITIVES2DATA environment.
|
|
PORTABLE_DDRAWSURFACE_LCL DDSLcl;
|
|
PORTABLE_DDRAWSURFACE_MORE DDSMore;
|
|
DDRAWI_DDRAWSURFACE_GBL DDSGbl;
|
|
memset( &DDSLcl, 0, sizeof( DDSLcl));
|
|
memset( &DDSMore, 0, sizeof( DDSMore));
|
|
memset( &DDSGbl, 0, sizeof( DDSGbl));
|
|
|
|
PORTABLE_DRAWPRIMITIVES2DATA FakeDPD;
|
|
|
|
FakeDPD.dwhContext()= reinterpret_cast< ULONG_PTR>( &Ctx);
|
|
FakeDPD.dwFlags()= D3DHALDP2_USERMEMVERTICES;
|
|
FakeDPD.dwVertexType()= 0;
|
|
FakeDPD.lpDDCommands()= &DDSLcl;
|
|
FakeDPD.dwCommandOffset()= 0;
|
|
FakeDPD.dwCommandLength()= m_uiSSBufferSize;
|
|
FakeDPD.lpVertices()= NULL;
|
|
FakeDPD.dwVertexOffset()= 0;
|
|
FakeDPD.dwVertexLength()= 0;
|
|
FakeDPD.dwReqVertexBufSize()= 0;
|
|
FakeDPD.dwReqCommandBufSize()= 0;
|
|
FakeDPD.lpdwRStates()= NULL;
|
|
FakeDPD.dwVertexSize()= 0;
|
|
|
|
// If the data is not 0, then a union can't be used, as we're
|
|
// writing over valid data.
|
|
DDSLcl.lpGbl()= &DDSGbl;
|
|
DDSLcl.ddsCaps().dwCaps= DDSCAPS2_COMMANDBUFFER| DDSCAPS_SYSTEMMEMORY;
|
|
DDSLcl.lpSurfMore()= &DDSMore;
|
|
DDSGbl.fpVidMem= reinterpret_cast<FLATPTR>( m_pBeginSS);
|
|
|
|
// Now call Context's DrawPrimitives2 entry point. CStdDrawPrimitives2
|
|
// can provide an implementation of DrawPrimitives2 for the Context.
|
|
HRESULT hr( Ctx.DrawPrimitives2( FakeDPD));
|
|
assert( SUCCEEDED( hr));
|
|
}
|
|
};
|
|
|
|
//
|
|
// <Template Parameters>
|
|
// TC: The Context type, typically, CMyContext.
|
|
//
|
|
template< class TC>
|
|
class CMinimalStateSet: public CSubStateSet< CMinimalStateSet, TC>
|
|
{
|
|
public: // Types
|
|
typedef TC TContext;
|
|
|
|
public: // Functions
|
|
CMinimalStateSet( const CMinimalStateSet< TC>& Other)
|
|
:CSubStateSet< CMinimalStateSet, TC>( Other)
|
|
{ }
|
|
CMinimalStateSet( TContext& C, const D3DHAL_DP2COMMAND* pBeginSS, const
|
|
D3DHAL_DP2COMMAND* pEndSS) :
|
|
CSubStateSet< CMinimalStateSet, TC>( C, pBeginSS, pEndSS) { }
|
|
~CMinimalStateSet() { }
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CStdDrawPrimitives2
|
|
//
|
|
// This class contains a default implementation of responding to the
|
|
// DrawPrimitives2 function call, as well as a function to record state back
|
|
// into a command buffer. Upon constuction, it will use the provided ranges
|
|
// to bind DP2 operations to both processing and recording member functions.
|
|
// In order to process the DrawPrimitives2 function call, it must wrap the
|
|
// PORTABLE_DRAWPRIMITIVES2DATA with a convience type which allows commands to
|
|
// be walked through with iterators. It will then use the DP2MFnParser to
|
|
// parse the DP2 commands and call the member functions.
|
|
//
|
|
// This class also provides a member function for processing the DP2 StateSet
|
|
// operation, and uses it to build up, manage, and execute state sets. In
|
|
// order to handle pure device state sets, it creates the appropriate command
|
|
// buffer for the Device (based off of caps), constructs a new state set
|
|
// on this command buffer, and asks the state set to Capture the current state.
|
|
//
|
|
// <Template Parameters>
|
|
// TSuper: Standard parent type which is inheriting from this child class.
|
|
// In this case, it should typically be the CMyContext type.
|
|
// TSS: The StateSet type, typically, CMyStateSet or CMinimalStateSet. The
|
|
// StateSet class should be able to be constructed from a command buffer,
|
|
// and then be able to Capture and Execute.
|
|
// TSSDB: This can be any Unique, Pair Associative Container, typically a map,
|
|
// which associates a DWORD state set handle to a StateSet type.
|
|
// TDP2D: This is some kind of wrapper class for PORTABLE_DRAWPRIMITIVES2DATA.
|
|
// The type is expected to inherit or emulate PORTABLE_DRAWPRIMITIVES2DATA's
|
|
// fields/ member variables, along with exposing an STL conforming
|
|
// container which provides iterators which ease iterating over the command
|
|
// buffer. This is typically CDP2DataWrap<>.
|
|
// TDP2MFC: A map container, which associates a D3DHAL_DP2OPERATION with a
|
|
// member function. A standard array is acceptable, as the number of
|
|
// entries is not variable at runtime. The member function is used to
|
|
// process the command.
|
|
// TDP2RMFC: A map container, which associates a D3DHAL_DP2OPERATION with a
|
|
// member function. A standard array is acceptable, as the number of
|
|
// entries is not variable at runtime. The member function is used to
|
|
// record or fill in the command with the current state.
|
|
//
|
|
// <Exposed Types>
|
|
// TDP2Data: The wrapper class type for PORTABLE_DRAWPRIMITIVES2DATA, which is
|
|
// the passed in TDP2D template parameter.
|
|
// TDP2DataCmds: The Sequence Container of DP2 commands provided by the
|
|
// TDP2Data wrapper class, which is relied upon to provide iteration over
|
|
// the command buffer. (TDP2Data::TCmds)
|
|
// TStateSet: The StateSet type, which was passed in as the TSS template
|
|
// parameter.
|
|
// TMFn: The member function type, which all DP2 command processing member
|
|
// functions should conform to. This is mostly exposed as a convience to
|
|
// Context implementors.
|
|
// TMFnCaller: An Adaptable Binary Function class which is used to call
|
|
// a TMFn, only being passed the TMFn and DP2 command pointer.
|
|
// TDP2CmdBind: A simple type, exposed as a convience to Context implementors,
|
|
// to provide a type that can be passed into the constructor, associating
|
|
// D3DHAL_DP2OPERATIONs with member functions/ TMFn.
|
|
// TRMFn: The member function type, which all DP2 command recording member
|
|
// functions should conform to. This is mostly exposed as a convience to
|
|
// Context implementors.
|
|
// TRMFnCaller: An Adaptable Binary Function class which is used to call
|
|
// a TRMFn, only being passed the TRMFn and DP2 command pointer.
|
|
// TRecDP2CmdBind: A simple type, exposed as a convience to Context implementors,
|
|
// to provide a type that can be passed into the constructor, associating
|
|
// D3DHAL_DP2OPERATIONs with member functions/ TRMFn.
|
|
//
|
|
// <Exposed Functions>
|
|
// CStdDrawPrimitives2(): Default constructor.
|
|
// template< class TIter1, class TIter2>
|
|
// CStdDrawPrimitives2( TIter1, const TIter1, TIter2, const TIter2): Standard
|
|
// constructor which receives two ranges of D3DHAL_DP2OPERATION bindings.
|
|
// The first range is a range of DP2 command processing bindings. The
|
|
// second range is a range of DP2 command recording bindings.
|
|
// void OnBeginDrawPrimitives2( TDP2Data&): A notification function called
|
|
// at the beginning of processing a DrawPrimitives2 entry point.
|
|
// void OnEndDrawPrimitives2( TDP2Data&): A notification function called at
|
|
// the end of processing a DrawPrimitives2 entry point.
|
|
// void CreateAndCaptureAllState( DWORD): The request to capture all state,
|
|
// which should only be received by pure devices.
|
|
// void CreateAndCapturePixelState( DWORD): The request to capture pixel state,
|
|
// which should only be received by pure devices.
|
|
// void CreateAndCaptureVertexState( DWORD): The request to capture vertex
|
|
// state, which should only be received by pure devices.
|
|
// HRESULT DP2StateSet( TDP2Data&, const D3DHAL_DP2COMMAND*, const void*): The
|
|
// default DP2 command processing member function for D3DDP2OP_STATESET.
|
|
// void RecordCommandBuffer( D3DHAL_DP2COMMAND*, D3DHAL_DP2COMMAND*): The
|
|
// request to save or fill in the blanks of the passed in range of command
|
|
// buffer, by using the DP2 command recording functions.
|
|
// HRESULT DrawPrimitives2( PORTABLE_DRAWPRIMITIVES2DATA&): The function,
|
|
// typically called by the Driver class to process the DrawPrimitives2
|
|
// entry point.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
template< class TSuper,
|
|
class TSS= CMinimalStateSet< TSuper>, class TSSDB= map< DWORD, TSS>,
|
|
class TDP2D= CDP2DataWrap<>,
|
|
class TDP2MFC= block<
|
|
HRESULT(TSuper::*)( TDP2D&, const D3DHAL_DP2COMMAND*, const void*), 66>,
|
|
class TDP2RMFC= block<
|
|
HRESULT(TSuper::*)( const D3DHAL_DP2COMMAND*, void*), 66> >
|
|
class CStdDrawPrimitives2
|
|
{
|
|
public: // Types
|
|
typedef TDP2D TDP2Data;
|
|
typedef typename TDP2Data::TCmds TDP2DataCmds;
|
|
typedef TSS TStateSet;
|
|
typedef HRESULT (TSuper::* TMFn)(TDP2Data&,const D3DHAL_DP2COMMAND*,
|
|
const void*);
|
|
struct TMFnCaller: // Used in conjunction
|
|
public binary_function< TMFn, const D3DHAL_DP2COMMAND*, HRESULT>
|
|
{
|
|
TSuper& m_Context;
|
|
TDP2Data& m_DP2Data;
|
|
|
|
TMFnCaller( TSuper& Context, TDP2Data& DP2Data)
|
|
: m_Context( Context), m_DP2Data( DP2Data)
|
|
{ }
|
|
|
|
result_type operator()( first_argument_type MFn,
|
|
second_argument_type pDP2Cmd) const
|
|
{
|
|
#if defined(DBG) || defined(_DEBUG)
|
|
const D3DHAL_DP2OPERATION Op(
|
|
static_cast< D3DHAL_DP2OPERATION>( pDP2Cmd->bCommand));
|
|
#endif
|
|
return (m_Context.*MFn)( m_DP2Data, pDP2Cmd, pDP2Cmd+ 1);
|
|
}
|
|
};
|
|
struct TDP2CmdBind
|
|
{
|
|
D3DHAL_DP2OPERATION m_DP2Op;
|
|
TMFn m_MFn;
|
|
|
|
operator D3DHAL_DP2OPERATION() const
|
|
{ return m_DP2Op; }
|
|
operator TMFn() const
|
|
{ return m_MFn; }
|
|
};
|
|
typedef HRESULT (TSuper::* TRMFn)( const D3DHAL_DP2COMMAND*, void*);
|
|
struct TRMFnCaller:
|
|
public binary_function< TRMFn, D3DHAL_DP2COMMAND*, HRESULT>
|
|
{
|
|
TSuper& m_Context;
|
|
|
|
TRMFnCaller( TSuper& Context)
|
|
: m_Context( Context)
|
|
{ }
|
|
|
|
result_type operator()( first_argument_type RMFn,
|
|
second_argument_type pDP2Cmd) const
|
|
{
|
|
#if defined(DBG) || defined(_DEBUG)
|
|
const D3DHAL_DP2OPERATION Op(
|
|
static_cast< D3DHAL_DP2OPERATION>( pDP2Cmd->bCommand));
|
|
#endif
|
|
return (m_Context.*RMFn)( pDP2Cmd, pDP2Cmd+ 1);
|
|
}
|
|
};
|
|
struct TRecDP2CmdBind
|
|
{
|
|
D3DHAL_DP2OPERATION m_DP2Op;
|
|
TRMFn m_RMFn;
|
|
|
|
operator D3DHAL_DP2OPERATION() const
|
|
{ return m_DP2Op; }
|
|
operator TRMFn() const
|
|
{ return m_RMFn; }
|
|
};
|
|
|
|
|
|
protected: // Types
|
|
typedef TSSDB TSSDB;
|
|
typedef TDP2MFC TDP2MFnCtr;
|
|
typedef TDP2RMFC TDP2RecMFnCtr;
|
|
|
|
protected: // Variables
|
|
static const HRESULT c_hrStateSetBegin;
|
|
static const HRESULT c_hrStateSetEnd;
|
|
TSSDB m_StateSetDB;
|
|
TDP2MFnCtr m_DefFnCtr;
|
|
TDP2RecMFnCtr m_RecFnCtr;
|
|
const D3DHAL_DP2COMMAND* m_pEndStateSet;
|
|
DWORD m_dwStateSetId;
|
|
bool m_bRecordingStateSet;
|
|
bool m_bExecutingStateSet;
|
|
|
|
protected: // Functions
|
|
// This function is used as a filler. If the assert is hit, step one
|
|
// level up/down in the call stack and check which DP2 Operation has
|
|
// no support, but the app indirectly needs it.
|
|
HRESULT DP2Empty( TDP2Data&, const D3DHAL_DP2COMMAND*, const void*)
|
|
{
|
|
const bool A_DP2_Op_Requires_A_Supporting_Function( false);
|
|
assert( A_DP2_Op_Requires_A_Supporting_Function);
|
|
return D3DERR_COMMAND_UNPARSED;
|
|
}
|
|
|
|
// This function is used as a fake, to prevent actual processing of
|
|
// DP2 Operations while recording a StateSet.
|
|
HRESULT DP2Fake( TDP2Data&, const D3DHAL_DP2COMMAND*, const void*)
|
|
{ return DD_OK; }
|
|
|
|
// Notification functions. Overriding is optional.
|
|
void OnBeginDrawPrimitives2( TDP2Data& DP2Data) const
|
|
{ }
|
|
void OnEndDrawPrimitives2( TDP2Data& DP2Data) const
|
|
{ }
|
|
|
|
CStdDrawPrimitives2()
|
|
:m_bRecordingStateSet( false), m_bExecutingStateSet( false),
|
|
m_pEndStateSet( NULL)
|
|
{
|
|
typename TDP2MFnCtr::iterator itCur( m_DefFnCtr.begin());
|
|
while( itCur!= m_DefFnCtr.end())
|
|
{
|
|
*itCur= DP2Empty;
|
|
++itCur;
|
|
}
|
|
itCur= m_RecFnCtr.begin();
|
|
while( itCur!= m_RecFnCtr.end())
|
|
{
|
|
*itCur= NULL;
|
|
++itCur;
|
|
}
|
|
m_DefFnCtr[ D3DDP2OP_STATESET]= DP2StateSet;
|
|
}
|
|
|
|
// [itSetStart, itSetEnd): A valid range of bindings, which associate
|
|
// a D3DHAL_DP2OPERATION with a processing member function.
|
|
// [itRecStart, itRecEnd): A valid range of bindings, which associate
|
|
// a D3DHAL_DP2OPERATION with a recording member function.
|
|
template< class TIter1, class TIter2> // TDP2CmdBind*, TRecDP2CmdBind*
|
|
CStdDrawPrimitives2( TIter1 itSetStart, const TIter1 itSetEnd,
|
|
TIter2 itRecStart, const TIter2 itRecEnd)
|
|
:m_bRecordingStateSet( false), m_bExecutingStateSet( false),
|
|
m_pEndStateSet( NULL)
|
|
{
|
|
typename TDP2MFnCtr::iterator itCur( m_DefFnCtr.begin());
|
|
while( itCur!= m_DefFnCtr.end())
|
|
{
|
|
*itCur= DP2Empty;
|
|
++itCur;
|
|
}
|
|
typename TDP2RecMFnCtr::iterator itRCur= m_RecFnCtr.begin();
|
|
while( itRCur!= m_RecFnCtr.end())
|
|
{
|
|
*itRCur= NULL;
|
|
++itRCur;
|
|
}
|
|
while( itSetStart!= itSetEnd)
|
|
{
|
|
const D3DHAL_DP2OPERATION DP2Op(
|
|
static_cast<D3DHAL_DP2OPERATION>(*itSetStart));
|
|
|
|
// This assert will fire if there are duplicate entries for the
|
|
// same DP2OPERATION.
|
|
assert( DP2Empty== m_DefFnCtr[ DP2Op]);
|
|
m_DefFnCtr[ DP2Op]= static_cast<TMFn>(*itSetStart);
|
|
++itSetStart;
|
|
}
|
|
while( itRecStart!= itRecEnd)
|
|
{
|
|
const D3DHAL_DP2OPERATION DP2Op(
|
|
static_cast<D3DHAL_DP2OPERATION>(*itRecStart));
|
|
|
|
// This assert will fire if there are duplicate entries for the
|
|
// same DP2OPERATION.
|
|
assert( NULL== m_RecFnCtr[ DP2Op]);
|
|
m_RecFnCtr[ DP2Op]= static_cast<TRMFn>(*itRecStart);
|
|
++itRecStart;
|
|
}
|
|
if( DP2Empty== m_DefFnCtr[ D3DDP2OP_STATESET])
|
|
m_DefFnCtr[ D3DDP2OP_STATESET]= DP2StateSet;
|
|
|
|
// Supporting these operations is considered the "safe minimal"
|
|
// support necessary to function. It is strongly recommended that
|
|
// these functions are supported, unless you know you can live without.
|
|
assert( m_DefFnCtr[ D3DDP2OP_VIEWPORTINFO]!= DP2Empty);
|
|
assert( m_DefFnCtr[ D3DDP2OP_WINFO]!= DP2Empty);
|
|
assert( m_DefFnCtr[ D3DDP2OP_RENDERSTATE]!= DP2Empty);
|
|
assert( m_DefFnCtr[ D3DDP2OP_TEXTURESTAGESTATE]!= DP2Empty);
|
|
assert( m_DefFnCtr[ D3DDP2OP_CLEAR]!= DP2Empty);
|
|
assert( m_DefFnCtr[ D3DDP2OP_SETRENDERTARGET]!= DP2Empty);
|
|
assert( m_DefFnCtr[ D3DDP2OP_SETVERTEXSHADER]!= DP2Empty);
|
|
assert( m_DefFnCtr[ D3DDP2OP_SETSTREAMSOURCE]!= DP2Empty);
|
|
assert( m_DefFnCtr[ D3DDP2OP_SETSTREAMSOURCEUM]!= DP2Empty);
|
|
assert( m_DefFnCtr[ D3DDP2OP_SETINDICES]!= DP2Empty);
|
|
assert( m_DefFnCtr[ D3DDP2OP_DRAWPRIMITIVE]!= DP2Empty);
|
|
assert( m_DefFnCtr[ D3DDP2OP_DRAWPRIMITIVE2]!= DP2Empty);
|
|
assert( m_DefFnCtr[ D3DDP2OP_DRAWINDEXEDPRIMITIVE]!= DP2Empty);
|
|
assert( m_DefFnCtr[ D3DDP2OP_DRAWINDEXEDPRIMITIVE2]!= DP2Empty);
|
|
assert( m_DefFnCtr[ D3DDP2OP_CLIPPEDTRIANGLEFAN]!= DP2Empty);
|
|
assert( m_RecFnCtr[ D3DDP2OP_VIEWPORTINFO]!= NULL);
|
|
assert( m_RecFnCtr[ D3DDP2OP_WINFO]!= NULL);
|
|
assert( m_RecFnCtr[ D3DDP2OP_RENDERSTATE]!= NULL);
|
|
assert( m_RecFnCtr[ D3DDP2OP_TEXTURESTAGESTATE]!= NULL);
|
|
assert( m_RecFnCtr[ D3DDP2OP_SETVERTEXSHADER]!= NULL);
|
|
assert( m_RecFnCtr[ D3DDP2OP_SETSTREAMSOURCE]!= NULL);
|
|
assert( m_RecFnCtr[ D3DDP2OP_SETINDICES]!= NULL);
|
|
// To remove this asserting, bind these functions to a different stub,
|
|
// most likely a member function of TSuper, which does nothing; so that
|
|
// they will not be equal to DP2Empty. Or use the default constructor.
|
|
}
|
|
~CStdDrawPrimitives2()
|
|
{ }
|
|
|
|
// To determine number of const registers available to pixel shader.
|
|
static DWORD GetNumPixelShaderConstReg( const DWORD dwPixelShaderVer)
|
|
{
|
|
switch(dwPixelShaderVer)
|
|
{
|
|
case( 0): return 0;
|
|
case( D3DPS_VERSION(1,0)): return 8;
|
|
case( D3DPS_VERSION(1,1)): return 8;
|
|
case( D3DPS_VERSION(254,254)): return 2;
|
|
case( D3DPS_VERSION(255,255)): return 16;
|
|
default: {
|
|
const bool Unrecognizable_Pixel_Shader_Version( false);
|
|
assert( Unrecognizable_Pixel_Shader_Version);
|
|
} break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
public: // Functions
|
|
// Default implementataions for Capturing amounts of state, DX8
|
|
// pure device style.
|
|
void CreateAndCaptureAllState( DWORD dwStateSetId)
|
|
{
|
|
#if defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
#if defined( D3D_ENABLE_SHADOW_JITTER)
|
|
typedef block< D3DRENDERSTATETYPE, 78> TAllRSToCapture;
|
|
#else // !defined( D3D_ENABLE_SHADOW_JITTER)
|
|
typedef block< D3DRENDERSTATETYPE, 75> TAllRSToCapture;
|
|
#endif // !defined( D3D_ENABLE_SHADOW_JITTER)
|
|
#else // !defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
typedef block< D3DRENDERSTATETYPE, 73> TAllRSToCapture;
|
|
#endif// !defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
const TAllRSToCapture AllRSToCapture=
|
|
{
|
|
D3DRENDERSTATE_SPECULARENABLE,
|
|
D3DRENDERSTATE_ZENABLE,
|
|
D3DRENDERSTATE_FILLMODE,
|
|
D3DRENDERSTATE_SHADEMODE,
|
|
D3DRENDERSTATE_LINEPATTERN,
|
|
D3DRENDERSTATE_ZWRITEENABLE,
|
|
D3DRENDERSTATE_ALPHATESTENABLE,
|
|
D3DRENDERSTATE_LASTPIXEL,
|
|
D3DRENDERSTATE_SRCBLEND,
|
|
D3DRENDERSTATE_DESTBLEND,
|
|
D3DRENDERSTATE_CULLMODE,
|
|
D3DRENDERSTATE_ZFUNC,
|
|
D3DRENDERSTATE_ALPHAREF,
|
|
D3DRENDERSTATE_ALPHAFUNC,
|
|
D3DRENDERSTATE_DITHERENABLE,
|
|
D3DRENDERSTATE_FOGENABLE,
|
|
D3DRENDERSTATE_STIPPLEDALPHA,
|
|
D3DRENDERSTATE_FOGCOLOR,
|
|
D3DRENDERSTATE_FOGTABLEMODE,
|
|
D3DRENDERSTATE_FOGSTART,
|
|
D3DRENDERSTATE_FOGEND,
|
|
D3DRENDERSTATE_FOGDENSITY,
|
|
D3DRENDERSTATE_EDGEANTIALIAS,
|
|
D3DRENDERSTATE_ALPHABLENDENABLE,
|
|
D3DRENDERSTATE_ZBIAS,
|
|
D3DRENDERSTATE_RANGEFOGENABLE,
|
|
D3DRENDERSTATE_STENCILENABLE,
|
|
D3DRENDERSTATE_STENCILFAIL,
|
|
D3DRENDERSTATE_STENCILZFAIL,
|
|
D3DRENDERSTATE_STENCILPASS,
|
|
D3DRENDERSTATE_STENCILFUNC,
|
|
D3DRENDERSTATE_STENCILREF,
|
|
D3DRENDERSTATE_STENCILMASK,
|
|
D3DRENDERSTATE_STENCILWRITEMASK,
|
|
D3DRENDERSTATE_TEXTUREFACTOR,
|
|
D3DRENDERSTATE_WRAP0,
|
|
D3DRENDERSTATE_WRAP1,
|
|
D3DRENDERSTATE_WRAP2,
|
|
D3DRENDERSTATE_WRAP3,
|
|
D3DRENDERSTATE_WRAP4,
|
|
D3DRENDERSTATE_WRAP5,
|
|
D3DRENDERSTATE_WRAP6,
|
|
D3DRENDERSTATE_WRAP7,
|
|
D3DRENDERSTATE_AMBIENT,
|
|
D3DRENDERSTATE_COLORVERTEX,
|
|
D3DRENDERSTATE_FOGVERTEXMODE,
|
|
D3DRENDERSTATE_CLIPPING,
|
|
D3DRENDERSTATE_LIGHTING,
|
|
D3DRENDERSTATE_NORMALIZENORMALS,
|
|
D3DRENDERSTATE_LOCALVIEWER,
|
|
D3DRENDERSTATE_EMISSIVEMATERIALSOURCE,
|
|
D3DRENDERSTATE_AMBIENTMATERIALSOURCE,
|
|
D3DRENDERSTATE_DIFFUSEMATERIALSOURCE,
|
|
D3DRENDERSTATE_SPECULARMATERIALSOURCE,
|
|
D3DRENDERSTATE_VERTEXBLEND,
|
|
D3DRENDERSTATE_CLIPPLANEENABLE,
|
|
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_POINTSIZE_MAX,
|
|
D3DRS_INDEXEDVERTEXBLENDENABLE,
|
|
D3DRS_COLORWRITEENABLE,
|
|
D3DRS_TWEENFACTOR,
|
|
D3DRS_BLENDOP,
|
|
#if defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
D3DRS_ZSLOPESCALE,
|
|
D3DRS_ZCLAMP,
|
|
#if defined( D3D_ENABLE_SHADOW_JITTER)
|
|
D3DRS_JITZBIASMIN,
|
|
D3DRS_JITZBIASMAX,
|
|
D3DRS_JITSHADOWSIZE,
|
|
#endif // defined( D3D_ENABLE_SHADOW_JITTER)
|
|
#endif // defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
};
|
|
#if defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
#if defined( D3D_ENABLE_SHADOW_JITTER)
|
|
assert( D3DRS_JITSHADOWSIZE== *AllRSToCapture.rbegin());
|
|
#else // !defined( D3D_ENABLE_SHADOW_JITTER)
|
|
assert( D3DRS_ZCLAMP== *AllRSToCapture.rbegin());
|
|
#endif // !defined( D3D_ENABLE_SHADOW_JITTER)
|
|
#else // !defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
assert( D3DRS_BLENDOP== *AllRSToCapture.rbegin());
|
|
#endif // !defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
|
|
#if defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
typedef block< D3DTEXTURESTAGESTATETYPE, 30> TAllTSSToCapture;
|
|
#else // !defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
typedef block< D3DTEXTURESTAGESTATETYPE, 27> TAllTSSToCapture;
|
|
#endif // !defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
const TAllTSSToCapture AllTSSToCapture=
|
|
{
|
|
D3DTSS_COLOROP,
|
|
D3DTSS_COLORARG1,
|
|
D3DTSS_COLORARG2,
|
|
D3DTSS_ALPHAOP,
|
|
D3DTSS_ALPHAARG1,
|
|
D3DTSS_ALPHAARG2,
|
|
D3DTSS_BUMPENVMAT00,
|
|
D3DTSS_BUMPENVMAT01,
|
|
D3DTSS_BUMPENVMAT10,
|
|
D3DTSS_BUMPENVMAT11,
|
|
D3DTSS_TEXCOORDINDEX,
|
|
D3DTSS_ADDRESSU,
|
|
D3DTSS_ADDRESSV,
|
|
D3DTSS_BORDERCOLOR,
|
|
D3DTSS_MAGFILTER,
|
|
D3DTSS_MINFILTER,
|
|
D3DTSS_MIPFILTER,
|
|
D3DTSS_MIPMAPLODBIAS,
|
|
D3DTSS_MAXMIPLEVEL,
|
|
D3DTSS_MAXANISOTROPY,
|
|
D3DTSS_BUMPENVLSCALE,
|
|
D3DTSS_BUMPENVLOFFSET,
|
|
D3DTSS_TEXTURETRANSFORMFLAGS,
|
|
D3DTSS_ADDRESSW,
|
|
D3DTSS_COLORARG0,
|
|
D3DTSS_ALPHAARG0,
|
|
D3DTSS_RESULTARG,
|
|
#if defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
D3DTSS_SHADOWNEARW,
|
|
D3DTSS_SHADOWFARW,
|
|
D3DTSS_SHADOWBUFFERENABLE,
|
|
#endif // defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
};
|
|
#if defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
assert( D3DTSS_SHADOWBUFFERENABLE== *AllTSSToCapture.rbegin());
|
|
#else // !defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
assert( D3DTSS_RESULTARG== *AllTSSToCapture.rbegin());
|
|
#endif // !defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
|
|
TSuper* pSThis= static_cast< TSuper*>( this);
|
|
typedef TSuper::TPerDDrawData TPerDDrawData;
|
|
typedef TPerDDrawData::TDriver TDriver;
|
|
const DWORD dwTextureStages( D3DHAL_TSS_MAXSTAGES);
|
|
const DWORD dwTextureMatrices( D3DHAL_TSS_MAXSTAGES);
|
|
const DWORD dwClipPlanes( TDriver::GetCaps().MaxUserClipPlanes);
|
|
const DWORD dwVertexShaderConsts( TDriver::GetCaps().MaxVertexShaderConst);
|
|
const DWORD dwPixelShaderConsts( GetNumPixelShaderConstReg(
|
|
TDriver::GetCaps().PixelShaderVersion));
|
|
|
|
// Algorithm to determine maximum SetTransform Index to support.
|
|
DWORD dwWorldMatrices( TDriver::GetCaps().MaxVertexBlendMatrixIndex+ 1);
|
|
if( TDriver::GetCaps().MaxVertexBlendMatrices> dwWorldMatrices)
|
|
dwWorldMatrices= TDriver::GetCaps().MaxVertexBlendMatrices;
|
|
|
|
DWORD dwActiveLights( 0);
|
|
size_t uiRecDP2BufferSize( 0);
|
|
|
|
// Pass 1: Calculate size of DP2 buffer required.
|
|
|
|
// Render States
|
|
if( m_RecFnCtr[ D3DDP2OP_RENDERSTATE]!= NULL)
|
|
{ assert( m_DefFnCtr[ D3DDP2OP_RENDERSTATE]!= DP2Empty);
|
|
|
|
uiRecDP2BufferSize+= sizeof( D3DHAL_DP2COMMAND)+
|
|
AllRSToCapture.size()* sizeof( D3DHAL_DP2RENDERSTATE);
|
|
}
|
|
else { assert( m_DefFnCtr[ D3DDP2OP_RENDERSTATE]== DP2Empty); }
|
|
|
|
// Texture States
|
|
if( m_RecFnCtr[ D3DDP2OP_TEXTURESTAGESTATE]!= NULL&&
|
|
dwTextureStages!= 0)
|
|
{ assert( m_DefFnCtr[ D3DDP2OP_TEXTURESTAGESTATE]!= DP2Empty);
|
|
|
|
uiRecDP2BufferSize+= sizeof( D3DHAL_DP2COMMAND)+ dwTextureStages*
|
|
AllTSSToCapture.size()* sizeof( D3DHAL_DP2TEXTURESTAGESTATE);
|
|
}
|
|
else { assert( m_DefFnCtr[ D3DDP2OP_TEXTURESTAGESTATE]== DP2Empty); }
|
|
|
|
// Viewport
|
|
if( m_RecFnCtr[ D3DDP2OP_VIEWPORTINFO]!= NULL)
|
|
{ assert( m_DefFnCtr[ D3DDP2OP_VIEWPORTINFO]!= DP2Empty);
|
|
|
|
uiRecDP2BufferSize+= sizeof( D3DHAL_DP2COMMAND)+
|
|
sizeof( D3DHAL_DP2VIEWPORTINFO);
|
|
}
|
|
else { assert( m_DefFnCtr[ D3DDP2OP_VIEWPORTINFO]== DP2Empty); }
|
|
|
|
// Transforms
|
|
if( m_RecFnCtr[ D3DDP2OP_SETTRANSFORM]!= NULL)
|
|
{ assert( m_DefFnCtr[ D3DDP2OP_SETTRANSFORM]!= DP2Empty);
|
|
|
|
// World, Texture, View, & Projection
|
|
uiRecDP2BufferSize+= sizeof( D3DHAL_DP2COMMAND)+
|
|
sizeof( D3DHAL_DP2SETTRANSFORM)* (dwWorldMatrices+
|
|
dwTextureMatrices+ 2);
|
|
}
|
|
else { assert( m_DefFnCtr[ D3DDP2OP_SETTRANSFORM]== DP2Empty); }
|
|
|
|
// Clipplanes
|
|
if( m_RecFnCtr[ D3DDP2OP_SETCLIPPLANE]!= NULL&& dwClipPlanes!= 0)
|
|
{ assert( m_DefFnCtr[ D3DDP2OP_SETCLIPPLANE]!= DP2Empty);
|
|
|
|
uiRecDP2BufferSize+= sizeof( D3DHAL_DP2COMMAND)+
|
|
sizeof( D3DHAL_DP2SETCLIPPLANE)* dwClipPlanes;
|
|
}
|
|
else { assert( m_DefFnCtr[ D3DDP2OP_SETCLIPPLANE]== DP2Empty); }
|
|
|
|
// Material
|
|
if( m_RecFnCtr[ D3DDP2OP_SETMATERIAL]!= NULL)
|
|
{ assert( m_DefFnCtr[ D3DDP2OP_SETMATERIAL]!= DP2Empty);
|
|
|
|
uiRecDP2BufferSize+= sizeof( D3DHAL_DP2COMMAND)+
|
|
sizeof( D3DHAL_DP2SETMATERIAL);
|
|
}
|
|
else { assert( m_DefFnCtr[ D3DDP2OP_SETMATERIAL]== DP2Empty); }
|
|
|
|
// Lights
|
|
if( m_RecFnCtr[ D3DDP2OP_CREATELIGHT]!= NULL)
|
|
{ assert( m_DefFnCtr[ D3DDP2OP_SETLIGHT]!= DP2Empty);
|
|
assert( m_DefFnCtr[ D3DDP2OP_CREATELIGHT]!= DP2Empty);
|
|
|
|
// Special exception here. First, ask how many active lights there
|
|
// are. We'll then prepare a buffer that the RecFnCtr function
|
|
// will have to know what to do with (as this is the only case
|
|
// that is not obvious how to handle). RecFnCtr will key off
|
|
// bCommand== 0.
|
|
|
|
const D3DHAL_DP2COMMAND DP2Cmd= {
|
|
static_cast< D3DHAL_DP2OPERATION>( 0), 0 };
|
|
|
|
// Ask for how many active lights in DP2ActiveLights.dwIndex;
|
|
D3DHAL_DP2CREATELIGHT DP2ActiveLights= { 0 };
|
|
(pSThis->*m_RecFnCtr[ D3DDP2OP_CREATELIGHT])(
|
|
&DP2Cmd, &DP2ActiveLights);
|
|
dwActiveLights= DP2ActiveLights.dwIndex;
|
|
|
|
if( dwActiveLights!= 0)
|
|
{
|
|
// Create structures.
|
|
uiRecDP2BufferSize+= sizeof( D3DHAL_DP2COMMAND)+ dwActiveLights*
|
|
sizeof( D3DHAL_DP2CREATELIGHT);
|
|
// Set structures.
|
|
uiRecDP2BufferSize+= sizeof( D3DHAL_DP2COMMAND)+ dwActiveLights*
|
|
(2* sizeof( D3DHAL_DP2SETLIGHT)+ sizeof( D3DLIGHT8));
|
|
}
|
|
}
|
|
else {
|
|
assert( m_DefFnCtr[ D3DDP2OP_SETLIGHT]== DP2Empty);
|
|
assert( m_DefFnCtr[ D3DDP2OP_CREATELIGHT]== DP2Empty);
|
|
}
|
|
|
|
// Vertex Shader
|
|
if( m_RecFnCtr[ D3DDP2OP_SETVERTEXSHADER]!= NULL)
|
|
{ assert( m_DefFnCtr[ D3DDP2OP_SETVERTEXSHADER]!= DP2Empty);
|
|
|
|
uiRecDP2BufferSize+= sizeof( D3DHAL_DP2COMMAND)+
|
|
sizeof( D3DHAL_DP2VERTEXSHADER);
|
|
}
|
|
else { assert( m_DefFnCtr[ D3DDP2OP_SETVERTEXSHADER]== DP2Empty); }
|
|
|
|
// Pixel Shader
|
|
if( m_RecFnCtr[ D3DDP2OP_SETPIXELSHADER]!= NULL)
|
|
{ assert( m_DefFnCtr[ D3DDP2OP_SETPIXELSHADER]!= DP2Empty);
|
|
|
|
uiRecDP2BufferSize+= sizeof( D3DHAL_DP2COMMAND)+
|
|
sizeof( D3DHAL_DP2PIXELSHADER);
|
|
}
|
|
else { assert( m_DefFnCtr[ D3DDP2OP_SETPIXELSHADER]== DP2Empty); }
|
|
|
|
// Vertex Shader Constants
|
|
if( m_RecFnCtr[ D3DDP2OP_SETVERTEXSHADERCONST]!= NULL&&
|
|
dwVertexShaderConsts!= 0)
|
|
{ assert( m_DefFnCtr[ D3DDP2OP_SETVERTEXSHADERCONST]!= DP2Empty);
|
|
|
|
uiRecDP2BufferSize+= sizeof( D3DHAL_DP2COMMAND)+
|
|
sizeof( D3DHAL_DP2SETVERTEXSHADERCONST)+
|
|
dwVertexShaderConsts* 4* sizeof(D3DVALUE);
|
|
}
|
|
else { assert( m_DefFnCtr[ D3DDP2OP_SETVERTEXSHADERCONST]== DP2Empty); }
|
|
|
|
// Pixel Shader Constants
|
|
if( m_RecFnCtr[ D3DDP2OP_SETPIXELSHADERCONST]!= NULL&&
|
|
dwPixelShaderConsts!= 0)
|
|
{ assert( m_DefFnCtr[ D3DDP2OP_SETPIXELSHADERCONST]!= DP2Empty);
|
|
|
|
uiRecDP2BufferSize+= sizeof( D3DHAL_DP2COMMAND)+
|
|
sizeof( D3DHAL_DP2SETPIXELSHADERCONST)+
|
|
dwPixelShaderConsts* 4* sizeof(D3DVALUE);
|
|
}
|
|
else { assert( m_DefFnCtr[ D3DDP2OP_SETPIXELSHADERCONST]== DP2Empty); }
|
|
|
|
// Pass 2: Build command buffer for states.
|
|
UINT8* pTempBuffer= NULL;
|
|
try {
|
|
pTempBuffer= reinterpret_cast< UINT8*>(
|
|
operator new ( uiRecDP2BufferSize));
|
|
} catch ( ... ) {
|
|
}
|
|
if( NULL== pTempBuffer)
|
|
throw bad_alloc( "Not enough room for StateSet");
|
|
|
|
D3DHAL_DP2COMMAND* pStartSSet= reinterpret_cast< D3DHAL_DP2COMMAND*>(
|
|
pTempBuffer);
|
|
D3DHAL_DP2COMMAND* pCur= pStartSSet;
|
|
D3DHAL_DP2COMMAND* pEndSSet= reinterpret_cast< D3DHAL_DP2COMMAND*>(
|
|
pTempBuffer+ uiRecDP2BufferSize);
|
|
|
|
// Render States
|
|
if( m_RecFnCtr[ D3DDP2OP_RENDERSTATE]!= NULL)
|
|
{
|
|
pCur->bCommand= D3DDP2OP_RENDERSTATE;
|
|
pCur->wStateCount= static_cast< WORD>( AllRSToCapture.size());
|
|
|
|
D3DHAL_DP2RENDERSTATE* pParam=
|
|
reinterpret_cast< D3DHAL_DP2RENDERSTATE*>( pCur+ 1);
|
|
|
|
TAllRSToCapture::const_iterator itRS( AllRSToCapture.begin());
|
|
while( itRS!= AllRSToCapture.end())
|
|
{
|
|
pParam->RenderState= *itRS;
|
|
++itRS;
|
|
++pParam;
|
|
}
|
|
|
|
pCur= reinterpret_cast< D3DHAL_DP2COMMAND*>( pParam);
|
|
}
|
|
|
|
// Texture States
|
|
if( m_RecFnCtr[ D3DDP2OP_TEXTURESTAGESTATE]!= NULL&&
|
|
dwTextureStages!= 0)
|
|
{
|
|
pCur->bCommand= D3DDP2OP_TEXTURESTAGESTATE;
|
|
pCur->wStateCount= static_cast< WORD>( dwTextureStages*
|
|
AllTSSToCapture.size());
|
|
|
|
D3DHAL_DP2TEXTURESTAGESTATE* pParam=
|
|
reinterpret_cast< D3DHAL_DP2TEXTURESTAGESTATE*>( pCur+ 1);
|
|
|
|
for( WORD wStage( 0); wStage< dwTextureStages; ++wStage)
|
|
{
|
|
TAllTSSToCapture::const_iterator itTSS( AllTSSToCapture.begin());
|
|
while( itTSS!= AllTSSToCapture.end())
|
|
{
|
|
pParam->wStage= wStage;
|
|
pParam->TSState= *itTSS;
|
|
++itTSS;
|
|
++pParam;
|
|
}
|
|
}
|
|
|
|
pCur= reinterpret_cast< D3DHAL_DP2COMMAND*>( pParam);
|
|
}
|
|
|
|
// Viewport
|
|
if( m_RecFnCtr[ D3DDP2OP_VIEWPORTINFO]!= NULL)
|
|
{
|
|
pCur->bCommand= D3DDP2OP_VIEWPORTINFO;
|
|
pCur->wStateCount= 1;
|
|
|
|
D3DHAL_DP2VIEWPORTINFO* pParam=
|
|
reinterpret_cast< D3DHAL_DP2VIEWPORTINFO*>( pCur+ 1);
|
|
|
|
pCur= reinterpret_cast< D3DHAL_DP2COMMAND*>( pParam+ 1);
|
|
}
|
|
|
|
// Transforms
|
|
if( m_RecFnCtr[ D3DDP2OP_SETTRANSFORM]!= NULL)
|
|
{
|
|
pCur->bCommand= D3DDP2OP_SETTRANSFORM;
|
|
pCur->wStateCount= static_cast< WORD>( dwWorldMatrices+
|
|
dwTextureMatrices+ 2);
|
|
|
|
D3DHAL_DP2SETTRANSFORM* pParam=
|
|
reinterpret_cast< D3DHAL_DP2SETTRANSFORM*>( pCur+ 1);
|
|
|
|
pParam->xfrmType= D3DTRANSFORMSTATE_PROJECTION;
|
|
++pParam;
|
|
|
|
pParam->xfrmType= D3DTRANSFORMSTATE_VIEW;
|
|
++pParam;
|
|
|
|
for( DWORD dwTM( 0); dwTM< dwTextureMatrices; ++dwTM)
|
|
{
|
|
pParam->xfrmType= static_cast< D3DTRANSFORMSTATETYPE>(
|
|
D3DTRANSFORMSTATE_TEXTURE0+ dwTM);
|
|
++pParam;
|
|
}
|
|
|
|
for( DWORD dwWM( 0); dwWM< dwWorldMatrices; ++dwWM)
|
|
{
|
|
pParam->xfrmType= D3DTS_WORLDMATRIX( dwWM);
|
|
++pParam;
|
|
}
|
|
|
|
pCur= reinterpret_cast< D3DHAL_DP2COMMAND*>( pParam);
|
|
}
|
|
|
|
// Clipplanes
|
|
if( m_RecFnCtr[ D3DDP2OP_SETCLIPPLANE]!= NULL&& dwClipPlanes!= 0)
|
|
{
|
|
pCur->bCommand= D3DDP2OP_SETCLIPPLANE;
|
|
pCur->wStateCount= static_cast< WORD>( dwClipPlanes);
|
|
|
|
D3DHAL_DP2SETCLIPPLANE* pParam=
|
|
reinterpret_cast< D3DHAL_DP2SETCLIPPLANE*>( pCur+ 1);
|
|
|
|
for( DWORD dwCP( 0); dwCP< dwClipPlanes; ++dwCP)
|
|
{
|
|
pParam->dwIndex= dwCP;
|
|
++pParam;
|
|
}
|
|
|
|
pCur= reinterpret_cast< D3DHAL_DP2COMMAND*>( pParam);
|
|
}
|
|
|
|
// Material
|
|
if( m_RecFnCtr[ D3DDP2OP_SETMATERIAL]!= NULL)
|
|
{
|
|
pCur->bCommand= D3DDP2OP_SETMATERIAL;
|
|
pCur->wStateCount= 1;
|
|
|
|
D3DHAL_DP2SETMATERIAL* pParam=
|
|
reinterpret_cast< D3DHAL_DP2SETMATERIAL*>( pCur+ 1);
|
|
|
|
pCur= reinterpret_cast< D3DHAL_DP2COMMAND*>( pParam+ 1);
|
|
}
|
|
|
|
// Lights
|
|
if( m_RecFnCtr[ D3DDP2OP_CREATELIGHT]!= NULL&& dwActiveLights!= 0)
|
|
{
|
|
// Special exception here. First, we asked how many active lights
|
|
// there were. The RecFnCtr function will have to know what to do
|
|
// with this buffer. We now give it a chance to fill in the
|
|
// light ids. RecFnCtr will key off bCommand== 0.
|
|
pCur->bCommand= static_cast< D3DHAL_DP2OPERATION>( 0);
|
|
pCur->wStateCount= static_cast< WORD>( dwActiveLights);
|
|
|
|
D3DHAL_DP2CREATELIGHT* pParam=
|
|
reinterpret_cast< D3DHAL_DP2CREATELIGHT*>( pCur+ 1);
|
|
(pSThis->*m_RecFnCtr[ D3DDP2OP_CREATELIGHT])(
|
|
pCur, pParam);
|
|
|
|
// Change back the bCommand for proper usage later.
|
|
pCur->bCommand= D3DDP2OP_CREATELIGHT;
|
|
pCur= reinterpret_cast< D3DHAL_DP2COMMAND*>( pParam+ dwActiveLights);
|
|
|
|
// Now, with the light ids in the CREATELIGHT structures, we can
|
|
// fill out SETLIGHT structures with ids correctly.
|
|
pCur->bCommand= D3DDP2OP_SETLIGHT;
|
|
pCur->wStateCount= static_cast< WORD>( 2* dwActiveLights);
|
|
|
|
D3DHAL_DP2SETLIGHT* pSParam=
|
|
reinterpret_cast< D3DHAL_DP2SETLIGHT*>( pCur+ 1);
|
|
|
|
for( DWORD dwL( 0); dwL< dwActiveLights; ++dwL)
|
|
{
|
|
pSParam->dwIndex= pParam->dwIndex;
|
|
pSParam->dwDataType= D3DHAL_SETLIGHT_DATA;
|
|
D3DLIGHT8* pLight= reinterpret_cast< D3DLIGHT8*>( pSParam+ 1);
|
|
|
|
pSParam= reinterpret_cast< D3DHAL_DP2SETLIGHT*>( pLight+ 1);
|
|
pSParam->dwIndex= pParam->dwIndex;
|
|
pSParam->dwDataType= D3DHAL_SETLIGHT_DISABLE;
|
|
++pParam;
|
|
++pSParam;
|
|
}
|
|
|
|
pCur= reinterpret_cast< D3DHAL_DP2COMMAND*>( pSParam);
|
|
}
|
|
|
|
// Vertex Shader
|
|
if( m_RecFnCtr[ D3DDP2OP_SETVERTEXSHADER]!= NULL)
|
|
{
|
|
pCur->bCommand= D3DDP2OP_SETVERTEXSHADER;
|
|
pCur->wStateCount= 1;
|
|
|
|
D3DHAL_DP2VERTEXSHADER* pParam=
|
|
reinterpret_cast< D3DHAL_DP2VERTEXSHADER*>( pCur+ 1);
|
|
|
|
pCur= reinterpret_cast< D3DHAL_DP2COMMAND*>( pParam+ 1);
|
|
}
|
|
|
|
// Pixel Shader
|
|
if( m_RecFnCtr[ D3DDP2OP_SETPIXELSHADER]!= NULL)
|
|
{
|
|
pCur->bCommand= D3DDP2OP_SETPIXELSHADER;
|
|
pCur->wStateCount= 1;
|
|
|
|
D3DHAL_DP2PIXELSHADER* pParam=
|
|
reinterpret_cast< D3DHAL_DP2PIXELSHADER*>( pCur+ 1);
|
|
|
|
pCur= reinterpret_cast< D3DHAL_DP2COMMAND*>( pParam+ 1);
|
|
}
|
|
|
|
// Vertex Shader Constants
|
|
if( m_RecFnCtr[ D3DDP2OP_SETVERTEXSHADERCONST]!= NULL&&
|
|
dwVertexShaderConsts!= 0)
|
|
{
|
|
pCur->bCommand= D3DDP2OP_SETVERTEXSHADERCONST;
|
|
pCur->wStateCount= 1;
|
|
|
|
D3DHAL_DP2SETVERTEXSHADERCONST* pParam=
|
|
reinterpret_cast< D3DHAL_DP2SETVERTEXSHADERCONST*>( pCur+ 1);
|
|
pParam->dwRegister= 0;
|
|
pParam->dwCount= dwVertexShaderConsts;
|
|
|
|
D3DVALUE* pFloat= reinterpret_cast< D3DVALUE*>( pParam+ 1);
|
|
pCur= reinterpret_cast< D3DHAL_DP2COMMAND*>(
|
|
pFloat+ 4* dwVertexShaderConsts);
|
|
}
|
|
|
|
// Pixel Shader Constants
|
|
if( m_RecFnCtr[ D3DDP2OP_SETPIXELSHADERCONST]!= NULL&&
|
|
dwPixelShaderConsts!= 0)
|
|
{
|
|
pCur->bCommand= D3DDP2OP_SETPIXELSHADERCONST;
|
|
pCur->wStateCount= 1;
|
|
|
|
D3DHAL_DP2SETPIXELSHADERCONST* pParam=
|
|
reinterpret_cast< D3DHAL_DP2SETPIXELSHADERCONST*>( pCur+ 1);
|
|
pParam->dwRegister= 0;
|
|
pParam->dwCount= dwPixelShaderConsts;
|
|
|
|
D3DVALUE* pFloat= reinterpret_cast< D3DVALUE*>( pParam+ 1);
|
|
pCur= reinterpret_cast< D3DHAL_DP2COMMAND*>(
|
|
pFloat+ 4* dwPixelShaderConsts);
|
|
}
|
|
|
|
assert( reinterpret_cast< D3DHAL_DP2COMMAND*>( pCur)== pEndSSet);
|
|
|
|
// Finally, build stateset.
|
|
pair< TSSDB::iterator, bool> Ret;
|
|
try {
|
|
Ret= m_StateSetDB.insert( TSSDB::value_type(
|
|
dwStateSetId, TStateSet( *pSThis, pStartSSet, pEndSSet)));
|
|
assert( Ret.second);
|
|
} catch ( ... ) {
|
|
operator delete ( static_cast< void*>( pTempBuffer));
|
|
throw;
|
|
}
|
|
|
|
// Now, capture it.
|
|
Ret.first->second.Capture( *pSThis);
|
|
}
|
|
|
|
void CreateAndCapturePixelState( DWORD dwStateSetId)
|
|
{
|
|
#if defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
#if defined( D3D_ENABLE_SHADOW_JITTER)
|
|
typedef block< D3DRENDERSTATETYPE, 44> TPixRSToCapture;
|
|
#else // !defined( D3D_ENABLE_SHADOW_JITTER)
|
|
typedef block< D3DRENDERSTATETYPE, 41> TPixRSToCapture;
|
|
#endif // !defined( D3D_ENABLE_SHADOW_JITTER)
|
|
#else // !defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
typedef block< D3DRENDERSTATETYPE, 39> TPixRSToCapture;
|
|
#endif // !defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
const TPixRSToCapture PixRSToCapture=
|
|
{
|
|
D3DRENDERSTATE_ZENABLE,
|
|
D3DRENDERSTATE_FILLMODE,
|
|
D3DRENDERSTATE_SHADEMODE,
|
|
D3DRENDERSTATE_LINEPATTERN,
|
|
D3DRENDERSTATE_ZWRITEENABLE,
|
|
D3DRENDERSTATE_ALPHATESTENABLE,
|
|
D3DRENDERSTATE_LASTPIXEL,
|
|
D3DRENDERSTATE_SRCBLEND,
|
|
D3DRENDERSTATE_DESTBLEND,
|
|
D3DRENDERSTATE_ZFUNC,
|
|
D3DRENDERSTATE_ALPHAREF,
|
|
D3DRENDERSTATE_ALPHAFUNC,
|
|
D3DRENDERSTATE_DITHERENABLE,
|
|
D3DRENDERSTATE_STIPPLEDALPHA,
|
|
D3DRENDERSTATE_FOGSTART,
|
|
D3DRENDERSTATE_FOGEND,
|
|
D3DRENDERSTATE_FOGDENSITY,
|
|
D3DRENDERSTATE_EDGEANTIALIAS,
|
|
D3DRENDERSTATE_ALPHABLENDENABLE,
|
|
D3DRENDERSTATE_ZBIAS,
|
|
D3DRENDERSTATE_STENCILENABLE,
|
|
D3DRENDERSTATE_STENCILFAIL,
|
|
D3DRENDERSTATE_STENCILZFAIL,
|
|
D3DRENDERSTATE_STENCILPASS,
|
|
D3DRENDERSTATE_STENCILFUNC,
|
|
D3DRENDERSTATE_STENCILREF,
|
|
D3DRENDERSTATE_STENCILMASK,
|
|
D3DRENDERSTATE_STENCILWRITEMASK,
|
|
D3DRENDERSTATE_TEXTUREFACTOR,
|
|
D3DRENDERSTATE_WRAP0,
|
|
D3DRENDERSTATE_WRAP1,
|
|
D3DRENDERSTATE_WRAP2,
|
|
D3DRENDERSTATE_WRAP3,
|
|
D3DRENDERSTATE_WRAP4,
|
|
D3DRENDERSTATE_WRAP5,
|
|
D3DRENDERSTATE_WRAP6,
|
|
D3DRENDERSTATE_WRAP7,
|
|
D3DRS_COLORWRITEENABLE,
|
|
D3DRS_BLENDOP,
|
|
#if defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
D3DRS_ZSLOPESCALE,
|
|
D3DRS_ZCLAMP,
|
|
#if defined( D3D_ENABLE_SHADOW_JITTER)
|
|
D3DRS_JITZBIASMIN,
|
|
D3DRS_JITZBIASMAX,
|
|
D3DRS_JITSHADOWSIZE,
|
|
#endif // defined( D3D_ENABLE_SHADOW_JITTER)
|
|
#endif // defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
};
|
|
#if defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
#if defined( D3D_ENABLE_SHADOW_JITTER)
|
|
assert( D3DRS_JITSHADOWSIZE== *PixRSToCapture.rbegin());
|
|
#else // !defined( D3D_ENABLE_SHADOW_JITTER)
|
|
assert( D3DRS_ZCLAMP== *PixRSToCapture.rbegin());
|
|
#endif // !defined( D3D_ENABLE_SHADOW_JITTER)
|
|
#else // !defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
assert( D3DRS_BLENDOP== *PixRSToCapture.rbegin());
|
|
#endif // !defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
|
|
#if defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
typedef block< D3DTEXTURESTAGESTATETYPE, 30> TPixTSSToCapture;
|
|
#else // !defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
typedef block< D3DTEXTURESTAGESTATETYPE, 27> TPixTSSToCapture;
|
|
#endif // !defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
const TPixTSSToCapture PixTSSToCapture=
|
|
{
|
|
D3DTSS_COLOROP,
|
|
D3DTSS_COLORARG1,
|
|
D3DTSS_COLORARG2,
|
|
D3DTSS_ALPHAOP,
|
|
D3DTSS_ALPHAARG1,
|
|
D3DTSS_ALPHAARG2,
|
|
D3DTSS_BUMPENVMAT00,
|
|
D3DTSS_BUMPENVMAT01,
|
|
D3DTSS_BUMPENVMAT10,
|
|
D3DTSS_BUMPENVMAT11,
|
|
D3DTSS_TEXCOORDINDEX,
|
|
D3DTSS_ADDRESSU,
|
|
D3DTSS_ADDRESSV,
|
|
D3DTSS_BORDERCOLOR,
|
|
D3DTSS_MAGFILTER,
|
|
D3DTSS_MINFILTER,
|
|
D3DTSS_MIPFILTER,
|
|
D3DTSS_MIPMAPLODBIAS,
|
|
D3DTSS_MAXMIPLEVEL,
|
|
D3DTSS_MAXANISOTROPY,
|
|
D3DTSS_BUMPENVLSCALE,
|
|
D3DTSS_BUMPENVLOFFSET,
|
|
D3DTSS_TEXTURETRANSFORMFLAGS,
|
|
D3DTSS_ADDRESSW,
|
|
D3DTSS_COLORARG0,
|
|
D3DTSS_ALPHAARG0,
|
|
D3DTSS_RESULTARG,
|
|
#if defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
D3DTSS_SHADOWNEARW,
|
|
D3DTSS_SHADOWFARW,
|
|
D3DTSS_SHADOWBUFFERENABLE,
|
|
#endif // defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
};
|
|
#if defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
assert( D3DTSS_SHADOWBUFFERENABLE== *PixTSSToCapture.rbegin());
|
|
#else // !defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
assert( D3DTSS_RESULTARG== *PixTSSToCapture.rbegin());
|
|
#endif // !defined( D3D_ENABLE_SHADOW_BUFFER)
|
|
|
|
TSuper* pSThis= static_cast< TSuper*>( this);
|
|
typedef TSuper::TPerDDrawData TPerDDrawData;
|
|
typedef TPerDDrawData::TDriver TDriver;
|
|
const DWORD dwTextureStages( D3DHAL_TSS_MAXSTAGES);
|
|
const DWORD dwPixelShaderConsts( GetNumPixelShaderConstReg(
|
|
TDriver::GetCaps().PixelShaderVersion));
|
|
|
|
size_t uiRecDP2BufferSize( 0);
|
|
|
|
// Pass 1: Calculate size of DP2 buffer required.
|
|
|
|
// Render States
|
|
if( m_RecFnCtr[ D3DDP2OP_RENDERSTATE]!= NULL)
|
|
{ assert( m_DefFnCtr[ D3DDP2OP_RENDERSTATE]!= DP2Empty);
|
|
|
|
uiRecDP2BufferSize+= sizeof( D3DHAL_DP2COMMAND)+
|
|
PixRSToCapture.size()* sizeof( D3DHAL_DP2RENDERSTATE);
|
|
}
|
|
else { assert( m_DefFnCtr[ D3DDP2OP_RENDERSTATE]== DP2Empty); }
|
|
|
|
// Texture States
|
|
if( m_RecFnCtr[ D3DDP2OP_TEXTURESTAGESTATE]!= NULL&&
|
|
dwTextureStages!= 0)
|
|
{ assert( m_DefFnCtr[ D3DDP2OP_TEXTURESTAGESTATE]!= DP2Empty);
|
|
|
|
uiRecDP2BufferSize+= sizeof( D3DHAL_DP2COMMAND)+ dwTextureStages*
|
|
PixTSSToCapture.size()* sizeof( D3DHAL_DP2TEXTURESTAGESTATE);
|
|
}
|
|
else { assert( m_DefFnCtr[ D3DDP2OP_TEXTURESTAGESTATE]== DP2Empty); }
|
|
|
|
// Pixel Shader
|
|
if( m_RecFnCtr[ D3DDP2OP_SETPIXELSHADER]!= NULL)
|
|
{ assert( m_DefFnCtr[ D3DDP2OP_SETPIXELSHADER]!= DP2Empty);
|
|
|
|
uiRecDP2BufferSize+= sizeof( D3DHAL_DP2COMMAND)+
|
|
sizeof( D3DHAL_DP2PIXELSHADER);
|
|
}
|
|
else { assert( m_DefFnCtr[ D3DDP2OP_SETPIXELSHADER]== DP2Empty); }
|
|
|
|
// Pixel Shader Constants
|
|
if( m_RecFnCtr[ D3DDP2OP_SETPIXELSHADERCONST]!= NULL&&
|
|
dwPixelShaderConsts!= 0)
|
|
{ assert( m_DefFnCtr[ D3DDP2OP_SETPIXELSHADERCONST]!= DP2Empty);
|
|
|
|
uiRecDP2BufferSize+= sizeof( D3DHAL_DP2COMMAND)+
|
|
sizeof( D3DHAL_DP2SETPIXELSHADERCONST)+
|
|
dwPixelShaderConsts* 4* sizeof(D3DVALUE);
|
|
}
|
|
else { assert( m_DefFnCtr[ D3DDP2OP_SETPIXELSHADERCONST]== DP2Empty); }
|
|
|
|
// Pass 2: Build command buffer for states.
|
|
UINT8* pTempBuffer= NULL;
|
|
try {
|
|
pTempBuffer= reinterpret_cast< UINT8*>(
|
|
operator new ( uiRecDP2BufferSize));
|
|
} catch ( ... ) {
|
|
}
|
|
if( NULL== pTempBuffer)
|
|
throw bad_alloc( "Not enough room for StateSet");
|
|
|
|
D3DHAL_DP2COMMAND* pStartSSet= reinterpret_cast< D3DHAL_DP2COMMAND*>(
|
|
pTempBuffer);
|
|
D3DHAL_DP2COMMAND* pCur= pStartSSet;
|
|
D3DHAL_DP2COMMAND* pEndSSet= reinterpret_cast< D3DHAL_DP2COMMAND*>(
|
|
pTempBuffer+ uiRecDP2BufferSize);
|
|
|
|
// Render States
|
|
if( m_RecFnCtr[ D3DDP2OP_RENDERSTATE]!= NULL)
|
|
{
|
|
pCur->bCommand= D3DDP2OP_RENDERSTATE;
|
|
pCur->wStateCount= static_cast< WORD>( PixRSToCapture.size());
|
|
|
|
D3DHAL_DP2RENDERSTATE* pParam=
|
|
reinterpret_cast< D3DHAL_DP2RENDERSTATE*>( pCur+ 1);
|
|
|
|
TPixRSToCapture::const_iterator itRS( PixRSToCapture.begin());
|
|
while( itRS!= PixRSToCapture.end())
|
|
{
|
|
pParam->RenderState= *itRS;
|
|
++itRS;
|
|
++pParam;
|
|
}
|
|
|
|
pCur= reinterpret_cast< D3DHAL_DP2COMMAND*>( pParam);
|
|
}
|
|
|
|
// Texture States
|
|
if( m_RecFnCtr[ D3DDP2OP_TEXTURESTAGESTATE]!= NULL&&
|
|
dwTextureStages!= 0)
|
|
{
|
|
pCur->bCommand= D3DDP2OP_TEXTURESTAGESTATE;
|
|
pCur->wStateCount= static_cast< WORD>( dwTextureStages*
|
|
PixTSSToCapture.size());
|
|
|
|
D3DHAL_DP2TEXTURESTAGESTATE* pParam=
|
|
reinterpret_cast< D3DHAL_DP2TEXTURESTAGESTATE*>( pCur+ 1);
|
|
|
|
for( WORD wStage( 0); wStage< dwTextureStages; ++wStage)
|
|
{
|
|
TPixTSSToCapture::const_iterator itTSS( PixTSSToCapture.begin());
|
|
while( itTSS!= PixTSSToCapture.end())
|
|
{
|
|
pParam->wStage= wStage;
|
|
pParam->TSState= *itTSS;
|
|
++itTSS;
|
|
++pParam;
|
|
}
|
|
}
|
|
|
|
pCur= reinterpret_cast< D3DHAL_DP2COMMAND*>( pParam);
|
|
}
|
|
|
|
// Pixel Shader
|
|
if( m_RecFnCtr[ D3DDP2OP_SETPIXELSHADER]!= NULL)
|
|
{
|
|
pCur->bCommand= D3DDP2OP_SETPIXELSHADER;
|
|
pCur->wStateCount= 1;
|
|
|
|
D3DHAL_DP2PIXELSHADER* pParam=
|
|
reinterpret_cast< D3DHAL_DP2PIXELSHADER*>( pCur+ 1);
|
|
|
|
pCur= reinterpret_cast< D3DHAL_DP2COMMAND*>( pParam+ 1);
|
|
}
|
|
|
|
// Pixel Shader Constants
|
|
if( m_RecFnCtr[ D3DDP2OP_SETPIXELSHADERCONST]!= NULL&&
|
|
dwPixelShaderConsts!= 0)
|
|
{
|
|
pCur->bCommand= D3DDP2OP_SETPIXELSHADERCONST;
|
|
pCur->wStateCount= 1;
|
|
|
|
D3DHAL_DP2SETPIXELSHADERCONST* pParam=
|
|
reinterpret_cast< D3DHAL_DP2SETPIXELSHADERCONST*>( pCur+ 1);
|
|
pParam->dwRegister= 0;
|
|
pParam->dwCount= dwPixelShaderConsts;
|
|
|
|
D3DVALUE* pFloat= reinterpret_cast< D3DVALUE*>( pParam+ 1);
|
|
pCur= reinterpret_cast< D3DHAL_DP2COMMAND*>(
|
|
pFloat+ 4* dwPixelShaderConsts);
|
|
}
|
|
|
|
assert( reinterpret_cast< D3DHAL_DP2COMMAND*>( pCur)== pEndSSet);
|
|
|
|
// Finally, build stateset.
|
|
pair< TSSDB::iterator, bool> Ret;
|
|
try {
|
|
Ret= m_StateSetDB.insert( TSSDB::value_type(
|
|
dwStateSetId, TStateSet( *pSThis, pStartSSet, pEndSSet)));
|
|
assert( Ret.second);
|
|
} catch ( ... ) {
|
|
operator delete ( static_cast< void*>( pTempBuffer));
|
|
throw;
|
|
}
|
|
|
|
// Now, capture it.
|
|
Ret.first->second.Capture( *pSThis);
|
|
}
|
|
|
|
void CreateAndCaptureVertexState( DWORD dwStateSetId)
|
|
{
|
|
typedef block< D3DRENDERSTATETYPE, 38> TVtxRSToCapture;
|
|
const TVtxRSToCapture VtxRSToCapture=
|
|
{
|
|
D3DRENDERSTATE_SPECULARENABLE,
|
|
D3DRENDERSTATE_SHADEMODE,
|
|
D3DRENDERSTATE_CULLMODE,
|
|
D3DRENDERSTATE_FOGENABLE,
|
|
D3DRENDERSTATE_FOGCOLOR,
|
|
D3DRENDERSTATE_FOGTABLEMODE,
|
|
D3DRENDERSTATE_FOGSTART,
|
|
D3DRENDERSTATE_FOGEND,
|
|
D3DRENDERSTATE_FOGDENSITY,
|
|
D3DRENDERSTATE_RANGEFOGENABLE,
|
|
D3DRENDERSTATE_AMBIENT,
|
|
D3DRENDERSTATE_COLORVERTEX,
|
|
D3DRENDERSTATE_FOGVERTEXMODE,
|
|
D3DRENDERSTATE_CLIPPING,
|
|
D3DRENDERSTATE_LIGHTING,
|
|
D3DRENDERSTATE_NORMALIZENORMALS,
|
|
D3DRENDERSTATE_LOCALVIEWER,
|
|
D3DRENDERSTATE_EMISSIVEMATERIALSOURCE,
|
|
D3DRENDERSTATE_AMBIENTMATERIALSOURCE,
|
|
D3DRENDERSTATE_DIFFUSEMATERIALSOURCE,
|
|
D3DRENDERSTATE_SPECULARMATERIALSOURCE,
|
|
D3DRENDERSTATE_VERTEXBLEND,
|
|
D3DRENDERSTATE_CLIPPLANEENABLE,
|
|
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_POINTSIZE_MAX,
|
|
D3DRS_INDEXEDVERTEXBLENDENABLE,
|
|
D3DRS_TWEENFACTOR
|
|
};
|
|
assert( D3DRS_TWEENFACTOR== *VtxRSToCapture.rbegin());
|
|
typedef block< D3DTEXTURESTAGESTATETYPE, 2> TVtxTSSToCapture;
|
|
const TVtxTSSToCapture VtxTSSToCapture=
|
|
{
|
|
D3DTSS_TEXCOORDINDEX,
|
|
D3DTSS_TEXTURETRANSFORMFLAGS
|
|
};
|
|
assert( D3DTSS_TEXTURETRANSFORMFLAGS== *VtxTSSToCapture.rbegin());
|
|
|
|
TSuper* pSThis= static_cast< TSuper*>( this);
|
|
typedef TSuper::TPerDDrawData TPerDDrawData;
|
|
typedef TPerDDrawData::TDriver TDriver;
|
|
const DWORD dwTextureStages( D3DHAL_TSS_MAXSTAGES);
|
|
const DWORD dwVertexShaderConsts( TDriver::GetCaps().MaxVertexShaderConst);
|
|
DWORD dwActiveLights( 0);
|
|
|
|
size_t uiRecDP2BufferSize( 0);
|
|
|
|
// Pass 1: Calculate size of DP2 buffer required.
|
|
|
|
// Render States
|
|
if( m_RecFnCtr[ D3DDP2OP_RENDERSTATE]!= NULL)
|
|
{ assert( m_DefFnCtr[ D3DDP2OP_RENDERSTATE]!= DP2Empty);
|
|
|
|
uiRecDP2BufferSize+= sizeof( D3DHAL_DP2COMMAND)+
|
|
VtxRSToCapture.size()* sizeof( D3DHAL_DP2RENDERSTATE);
|
|
}
|
|
else { assert( m_DefFnCtr[ D3DDP2OP_RENDERSTATE]== DP2Empty); }
|
|
|
|
// Texture States
|
|
if( m_RecFnCtr[ D3DDP2OP_TEXTURESTAGESTATE]!= NULL&&
|
|
dwTextureStages!= 0)
|
|
{ assert( m_DefFnCtr[ D3DDP2OP_TEXTURESTAGESTATE]!= DP2Empty);
|
|
|
|
uiRecDP2BufferSize+= sizeof( D3DHAL_DP2COMMAND)+ dwTextureStages*
|
|
VtxTSSToCapture.size()* sizeof( D3DHAL_DP2TEXTURESTAGESTATE);
|
|
}
|
|
else { assert( m_DefFnCtr[ D3DDP2OP_TEXTURESTAGESTATE]== DP2Empty); }
|
|
|
|
// Lights
|
|
if( m_RecFnCtr[ D3DDP2OP_CREATELIGHT]!= NULL)
|
|
{ assert( m_DefFnCtr[ D3DDP2OP_SETLIGHT]!= DP2Empty);
|
|
assert( m_DefFnCtr[ D3DDP2OP_CREATELIGHT]!= DP2Empty);
|
|
|
|
// Special exception here. First, ask how many active lights there
|
|
// are. We'll then prepare a buffer that the RecFnCtr function
|
|
// will have to know what to do with (as this is the only case
|
|
// that is not obvious how to handle). RecFnCtr will key off
|
|
// bCommand== 0.
|
|
|
|
const D3DHAL_DP2COMMAND DP2Cmd= {
|
|
static_cast< D3DHAL_DP2OPERATION>( 0), 0 };
|
|
|
|
// Ask for how many active lights in DP2ActiveLights.dwIndex;
|
|
D3DHAL_DP2CREATELIGHT DP2ActiveLights= { 0 };
|
|
(pSThis->*m_RecFnCtr[ D3DDP2OP_CREATELIGHT])(
|
|
&DP2Cmd, &DP2ActiveLights);
|
|
dwActiveLights= DP2ActiveLights.dwIndex;
|
|
|
|
if( dwActiveLights!= 0)
|
|
{
|
|
// Create structures.
|
|
uiRecDP2BufferSize+= sizeof( D3DHAL_DP2COMMAND)+ dwActiveLights*
|
|
sizeof( D3DHAL_DP2CREATELIGHT);
|
|
// Set structures.
|
|
uiRecDP2BufferSize+= sizeof( D3DHAL_DP2COMMAND)+ dwActiveLights*
|
|
(2* sizeof( D3DHAL_DP2SETLIGHT)+ sizeof( D3DLIGHT8));
|
|
}
|
|
}
|
|
else {
|
|
assert( m_DefFnCtr[ D3DDP2OP_SETLIGHT]== DP2Empty);
|
|
assert( m_DefFnCtr[ D3DDP2OP_CREATELIGHT]== DP2Empty);
|
|
}
|
|
|
|
// Vertex Shader
|
|
if( m_RecFnCtr[ D3DDP2OP_SETVERTEXSHADER]!= NULL)
|
|
{ assert( m_DefFnCtr[ D3DDP2OP_SETVERTEXSHADER]!= DP2Empty);
|
|
|
|
uiRecDP2BufferSize+= sizeof( D3DHAL_DP2COMMAND)+
|
|
sizeof( D3DHAL_DP2VERTEXSHADER);
|
|
}
|
|
else { assert( m_DefFnCtr[ D3DDP2OP_SETVERTEXSHADER]== DP2Empty); }
|
|
|
|
// Vertex Shader Constants
|
|
if( m_RecFnCtr[ D3DDP2OP_SETVERTEXSHADERCONST]!= NULL&&
|
|
dwVertexShaderConsts!= 0)
|
|
{ assert( m_DefFnCtr[ D3DDP2OP_SETVERTEXSHADERCONST]!= DP2Empty);
|
|
|
|
uiRecDP2BufferSize+= sizeof( D3DHAL_DP2COMMAND)+
|
|
sizeof( D3DHAL_DP2SETVERTEXSHADERCONST)+
|
|
dwVertexShaderConsts* 4* sizeof(D3DVALUE);
|
|
}
|
|
else { assert( m_DefFnCtr[ D3DDP2OP_SETVERTEXSHADERCONST]== DP2Empty); }
|
|
|
|
// Pass 2: Build command buffer for states.
|
|
UINT8* pTempBuffer= NULL;
|
|
try {
|
|
pTempBuffer= reinterpret_cast< UINT8*>(
|
|
operator new ( uiRecDP2BufferSize));
|
|
} catch ( ... ) {
|
|
}
|
|
if( NULL== pTempBuffer)
|
|
throw bad_alloc( "Not enough room for StateSet");
|
|
|
|
D3DHAL_DP2COMMAND* pStartSSet= reinterpret_cast< D3DHAL_DP2COMMAND*>(
|
|
pTempBuffer);
|
|
D3DHAL_DP2COMMAND* pCur= pStartSSet;
|
|
D3DHAL_DP2COMMAND* pEndSSet= reinterpret_cast< D3DHAL_DP2COMMAND*>(
|
|
pTempBuffer+ uiRecDP2BufferSize);
|
|
|
|
// Render States
|
|
if( m_RecFnCtr[ D3DDP2OP_RENDERSTATE]!= NULL)
|
|
{
|
|
pCur->bCommand= D3DDP2OP_RENDERSTATE;
|
|
pCur->wStateCount= static_cast< WORD>( VtxRSToCapture.size());
|
|
|
|
D3DHAL_DP2RENDERSTATE* pParam=
|
|
reinterpret_cast< D3DHAL_DP2RENDERSTATE*>( pCur+ 1);
|
|
|
|
TVtxRSToCapture::const_iterator itRS( VtxRSToCapture.begin());
|
|
while( itRS!= VtxRSToCapture.end())
|
|
{
|
|
pParam->RenderState= *itRS;
|
|
++itRS;
|
|
++pParam;
|
|
}
|
|
|
|
pCur= reinterpret_cast< D3DHAL_DP2COMMAND*>( pParam);
|
|
}
|
|
|
|
// Texture States
|
|
if( m_RecFnCtr[ D3DDP2OP_TEXTURESTAGESTATE]!= NULL&&
|
|
dwTextureStages!= 0)
|
|
{
|
|
pCur->bCommand= D3DDP2OP_TEXTURESTAGESTATE;
|
|
pCur->wStateCount= static_cast< WORD>( dwTextureStages*
|
|
VtxTSSToCapture.size());
|
|
|
|
D3DHAL_DP2TEXTURESTAGESTATE* pParam=
|
|
reinterpret_cast< D3DHAL_DP2TEXTURESTAGESTATE*>( pCur+ 1);
|
|
|
|
for( WORD wStage( 0); wStage< dwTextureStages; ++wStage)
|
|
{
|
|
TVtxTSSToCapture::const_iterator itTSS( VtxTSSToCapture.begin());
|
|
while( itTSS!= VtxTSSToCapture.end())
|
|
{
|
|
pParam->wStage= wStage;
|
|
pParam->TSState= *itTSS;
|
|
++itTSS;
|
|
++pParam;
|
|
}
|
|
}
|
|
|
|
pCur= reinterpret_cast< D3DHAL_DP2COMMAND*>( pParam);
|
|
}
|
|
|
|
// Lights
|
|
if( m_RecFnCtr[ D3DDP2OP_CREATELIGHT]!= NULL&& dwActiveLights!= 0)
|
|
{
|
|
// Special exception here. First, we asked how many active lights
|
|
// there were. The RecFnCtr function will have to know what to do
|
|
// with this buffer. We now give it a chance to fill in the
|
|
// light ids. RecFnCtr will key off bCommand== 0.
|
|
pCur->bCommand= static_cast< D3DHAL_DP2OPERATION>( 0);
|
|
pCur->wStateCount= static_cast< WORD>( dwActiveLights);
|
|
|
|
D3DHAL_DP2CREATELIGHT* pParam=
|
|
reinterpret_cast< D3DHAL_DP2CREATELIGHT*>( pCur+ 1);
|
|
(pSThis->*m_RecFnCtr[ D3DDP2OP_CREATELIGHT])(
|
|
pCur, pParam);
|
|
|
|
// Change back the bCommand for proper usage later.
|
|
pCur->bCommand= D3DDP2OP_CREATELIGHT;
|
|
pCur= reinterpret_cast< D3DHAL_DP2COMMAND*>( pParam+ dwActiveLights);
|
|
|
|
// Now, with the light ids in the CREATELIGHT structures, we can
|
|
// fill out SETLIGHT structures with ids correctly.
|
|
pCur->bCommand= D3DDP2OP_SETLIGHT;
|
|
pCur->wStateCount= static_cast< WORD>( 2* dwActiveLights);
|
|
|
|
D3DHAL_DP2SETLIGHT* pSParam=
|
|
reinterpret_cast< D3DHAL_DP2SETLIGHT*>( pCur+ 1);
|
|
|
|
for( DWORD dwL( 0); dwL< dwActiveLights; ++dwL)
|
|
{
|
|
pSParam->dwIndex= pParam->dwIndex;
|
|
pSParam->dwDataType= D3DHAL_SETLIGHT_DATA;
|
|
D3DLIGHT8* pLight= reinterpret_cast< D3DLIGHT8*>( pSParam+ 1);
|
|
|
|
pSParam= reinterpret_cast< D3DHAL_DP2SETLIGHT*>( pLight+ 1);
|
|
pSParam->dwIndex= pParam->dwIndex;
|
|
pSParam->dwDataType= D3DHAL_SETLIGHT_DISABLE;
|
|
++pParam;
|
|
++pSParam;
|
|
}
|
|
|
|
pCur= reinterpret_cast< D3DHAL_DP2COMMAND*>( pSParam);
|
|
}
|
|
|
|
// Vertex Shader
|
|
if( m_RecFnCtr[ D3DDP2OP_SETVERTEXSHADER]!= NULL)
|
|
{
|
|
pCur->bCommand= D3DDP2OP_SETVERTEXSHADER;
|
|
pCur->wStateCount= 1;
|
|
|
|
D3DHAL_DP2VERTEXSHADER* pParam=
|
|
reinterpret_cast< D3DHAL_DP2VERTEXSHADER*>( pCur+ 1);
|
|
|
|
pCur= reinterpret_cast< D3DHAL_DP2COMMAND*>( pParam+ 1);
|
|
}
|
|
|
|
// Vertex Shader Constants
|
|
if( m_RecFnCtr[ D3DDP2OP_SETVERTEXSHADERCONST]!= NULL&&
|
|
dwVertexShaderConsts!= 0)
|
|
{
|
|
pCur->bCommand= D3DDP2OP_SETVERTEXSHADERCONST;
|
|
pCur->wStateCount= 1;
|
|
|
|
D3DHAL_DP2SETVERTEXSHADERCONST* pParam=
|
|
reinterpret_cast< D3DHAL_DP2SETVERTEXSHADERCONST*>( pCur+ 1);
|
|
pParam->dwRegister= 0;
|
|
pParam->dwCount= dwVertexShaderConsts;
|
|
|
|
D3DVALUE* pFloat= reinterpret_cast< D3DVALUE*>( pParam+ 1);
|
|
pCur= reinterpret_cast< D3DHAL_DP2COMMAND*>(
|
|
pFloat+ 4* dwVertexShaderConsts);
|
|
}
|
|
|
|
assert( reinterpret_cast< D3DHAL_DP2COMMAND*>( pCur)== pEndSSet);
|
|
|
|
// Finally, build stateset.
|
|
pair< TSSDB::iterator, bool> Ret;
|
|
try {
|
|
Ret= m_StateSetDB.insert( TSSDB::value_type(
|
|
dwStateSetId, TStateSet( *pSThis, pStartSSet, pEndSSet)));
|
|
assert( Ret.second);
|
|
} catch ( ... ) {
|
|
operator delete ( static_cast< void*>( pTempBuffer));
|
|
throw;
|
|
}
|
|
|
|
// Now, capture it.
|
|
Ret.first->second.Capture( *pSThis);
|
|
}
|
|
|
|
// This member function handles the DP2OP_STATESET, which communicates back
|
|
// to the DrawPrimitives2 entry point handler to implement state sets.
|
|
HRESULT DP2StateSet( TDP2Data& DP2Data,
|
|
const D3DHAL_DP2COMMAND* pCmd, const void* pP)
|
|
{
|
|
const D3DHAL_DP2STATESET* pParam=
|
|
reinterpret_cast<const D3DHAL_DP2STATESET*>(pP);
|
|
HRESULT hr( DD_OK);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
TSuper* pSThis= static_cast<TSuper*>(this);
|
|
if( wStateCount!= 0) do
|
|
{
|
|
switch( pParam->dwOperation)
|
|
{
|
|
case( D3DHAL_STATESETCREATE):
|
|
assert( !m_bRecordingStateSet);
|
|
typedef TSuper::TPerDDrawData TPerDDrawData;
|
|
typedef TPerDDrawData::TDriver TDriver;
|
|
assert((TDriver::GetCaps().DevCaps& D3DDEVCAPS_PUREDEVICE)!= 0);
|
|
|
|
try {
|
|
switch( pParam->sbType)
|
|
{
|
|
case( D3DSBT_ALL):
|
|
pSThis->CreateAndCaptureAllState( pParam->dwParam);
|
|
break;
|
|
|
|
case( D3DSBT_PIXELSTATE):
|
|
pSThis->CreateAndCapturePixelState( pParam->dwParam);
|
|
break;
|
|
|
|
case( D3DSBT_VERTEXSTATE):
|
|
pSThis->CreateAndCaptureVertexState( pParam->dwParam);
|
|
break;
|
|
|
|
default: {
|
|
const bool Unrecognized_StateSetCreate_Operation( false);
|
|
assert( Unrecognized_StateSetCreate_Operation);
|
|
} break;
|
|
}
|
|
} catch( bad_alloc ba) {
|
|
return DDERR_OUTOFMEMORY;
|
|
}
|
|
break;
|
|
|
|
case( D3DHAL_STATESETBEGIN):
|
|
assert( 1== wStateCount);
|
|
assert( !m_bRecordingStateSet);
|
|
|
|
m_bRecordingStateSet= true;
|
|
hr= c_hrStateSetBegin;
|
|
// Returning this constant will break out of the parsing and
|
|
// notify DrawPrimitive2 entry point handler to create a state
|
|
// set.
|
|
break;
|
|
|
|
case( D3DHAL_STATESETCAPTURE):
|
|
if( !m_bRecordingStateSet)
|
|
{
|
|
// First, find the StateSet to capture.
|
|
typename TSSDB::iterator itSS(
|
|
m_StateSetDB.find( pParam->dwParam));
|
|
assert( itSS!= m_StateSetDB.end());
|
|
|
|
// Capture it.
|
|
itSS->second.Capture( *pSThis);
|
|
}
|
|
break;
|
|
|
|
case( D3DHAL_STATESETDELETE):
|
|
if( !m_bRecordingStateSet)
|
|
{
|
|
m_StateSetDB.erase( pParam->dwParam);
|
|
}
|
|
break;
|
|
|
|
case( D3DHAL_STATESETEND):
|
|
assert( 1== wStateCount);
|
|
assert( m_bRecordingStateSet);
|
|
m_bRecordingStateSet= false;
|
|
m_dwStateSetId= pParam->dwParam;
|
|
m_pEndStateSet= pCmd;
|
|
hr= c_hrStateSetEnd;
|
|
break;
|
|
|
|
case( D3DHAL_STATESETEXECUTE):
|
|
if( !m_bRecordingStateSet)
|
|
{
|
|
// First, find the StateSet to execute.
|
|
typename TSSDB::iterator itSS(
|
|
m_StateSetDB.find( pParam->dwParam));
|
|
assert( itSS!= m_StateSetDB.end());
|
|
|
|
// "Push" value of m_bExecutingStateSet, then set to true.
|
|
// "Pop" will occur at destruction.
|
|
CPushValue< bool> m_PushExecutingBit(
|
|
m_bExecutingStateSet, true);
|
|
|
|
// Execute it.
|
|
itSS->second.Execute( *pSThis);
|
|
}
|
|
break;
|
|
|
|
default: {
|
|
const bool Unrecognized_StateSet_Operation( false);
|
|
assert( Unrecognized_StateSet_Operation);
|
|
} break;
|
|
}
|
|
|
|
++pParam;
|
|
} while( SUCCEEDED( hr) && --wStateCount);
|
|
|
|
return hr;
|
|
}
|
|
|
|
// This function is used to record the current state of the context/ device
|
|
// into the command buffer.
|
|
void RecordCommandBuffer( D3DHAL_DP2COMMAND* pBeginSS,
|
|
D3DHAL_DP2COMMAND* pEndSS)
|
|
{
|
|
TSuper* pSThis= static_cast<TSuper*>(this);
|
|
|
|
CDP2CmdIterator<> itCur( pBeginSS);
|
|
const CDP2CmdIterator<> itEnd( pEndSS);
|
|
SDP2MFnParser DP2Parser;
|
|
TRMFnCaller RMFnCaller( *pSThis);
|
|
|
|
HRESULT hr( DD_OK);
|
|
while( itCur!= itEnd)
|
|
{
|
|
hr= DP2Parser.ParseDP2( RMFnCaller, m_RecFnCtr, itCur, itEnd);
|
|
assert( SUCCEEDED( hr));
|
|
|
|
// Ignore recording errors, except for debugging. Hopefully
|
|
// the processing of this DP2 command (when appling the state set)
|
|
// won't fault later.
|
|
if( FAILED( hr))
|
|
++itCur;
|
|
}
|
|
}
|
|
|
|
// Primary reason for class, handling of this function for the context.
|
|
HRESULT DrawPrimitives2( PORTABLE_DRAWPRIMITIVES2DATA& dpd)
|
|
{
|
|
TSuper* pSThis= static_cast<TSuper*>(this);
|
|
TDP2Data DP2Data( dpd);
|
|
|
|
// If not currently executing a stateset (which might recursively call
|
|
// this function) notify start of DP2 entry point.
|
|
if( !m_bExecutingStateSet)
|
|
pSThis->OnBeginDrawPrimitives2( DP2Data);
|
|
|
|
typename TDP2DataCmds::const_iterator itCur(
|
|
DP2Data.GetCommands().begin() );
|
|
const typename TDP2DataCmds::const_iterator itEnd(
|
|
DP2Data.GetCommands().end() );
|
|
SDP2MFnParser DP2Parser;
|
|
TMFnCaller MFnCaller( *pSThis, DP2Data);
|
|
|
|
HRESULT hr( DD_OK);
|
|
do
|
|
{
|
|
hr= DP2Parser.ParseDP2( MFnCaller, m_DefFnCtr,
|
|
itCur, itEnd);
|
|
|
|
if( c_hrStateSetBegin== hr)
|
|
{
|
|
typename TDP2DataCmds::const_iterator itStartSSet( ++itCur);
|
|
|
|
{
|
|
TDP2MFnCtr FakeFnCtr;
|
|
typename TDP2MFnCtr::iterator itCurFake( FakeFnCtr.begin());
|
|
while( itCurFake!= FakeFnCtr.end())
|
|
*itCurFake++ = DP2Fake;
|
|
FakeFnCtr[ D3DDP2OP_STATESET]= DP2StateSet;
|
|
|
|
hr= DP2Parser.ParseDP2( MFnCaller, FakeFnCtr,
|
|
itCur, itEnd);
|
|
|
|
assert( c_hrStateSetEnd== hr);
|
|
itCur++;
|
|
}
|
|
|
|
try
|
|
{
|
|
pair< TSSDB::iterator, bool> Ret;
|
|
Ret= m_StateSetDB.insert( TSSDB::value_type( m_dwStateSetId,
|
|
TStateSet( *pSThis, itStartSSet, m_pEndStateSet)));
|
|
|
|
// There shouldn't be two statesets with the same Id.
|
|
assert( Ret.second);
|
|
hr= S_OK;
|
|
} catch( bad_alloc e) {
|
|
hr= DDERR_OUTOFMEMORY;
|
|
}
|
|
}
|
|
assert( c_hrStateSetEnd!= hr);
|
|
} while( SUCCEEDED(hr)&& itCur!= itEnd);
|
|
|
|
if( FAILED( hr))
|
|
{
|
|
const D3DHAL_DP2COMMAND* pS= itCur;
|
|
const D3DHAL_DP2COMMAND* pE= itEnd;
|
|
dpd.dwErrorOffset()= reinterpret_cast<const UINT8*>(pE)-
|
|
reinterpret_cast<const UINT8*>(pS);
|
|
}
|
|
|
|
// If not currently executing a stateset (which might recursively call
|
|
// this function) notify end of DP2 entry point.
|
|
if( !m_bExecutingStateSet)
|
|
pSThis->OnEndDrawPrimitives2( DP2Data);
|
|
return hr;
|
|
}
|
|
};
|
|
|
|
template< class TSuper, class TSS, class TSSDB, class TDP2D, class TDP2MFC,
|
|
class TDP2RMFC>
|
|
const HRESULT CStdDrawPrimitives2< TSuper, TSS, TSSDB, TDP2D, TDP2MFC,
|
|
TDP2RMFC>::c_hrStateSetBegin= S_FALSE+ 556;
|
|
|
|
template< class TSuper, class TSS, class TSSDB, class TDP2D, class TDP2MFC,
|
|
class TDP2RMFC>
|
|
const HRESULT CStdDrawPrimitives2< TSuper, TSS, TSSDB, TDP2D, TDP2MFC,
|
|
TDP2RMFC>::c_hrStateSetEnd= S_FALSE+ 557;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CStdDP2ViewportInfoStore,
|
|
// CStdDP2WInfoStore,
|
|
// CStdDP2SetTransformStore,
|
|
// etc: CStdDP2xxxxxStore...
|
|
//
|
|
// These classes provide default DP2 operation support, typically just storing
|
|
// state. They have support for a notification mechanism, which delegates to
|
|
// the parent Context.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// MSVC doesn't support partial specialization or we could've had something
|
|
// elegant like:
|
|
//
|
|
// template< class TSuper, class TParam>
|
|
// class CStdDP2ParamStore {};
|
|
//
|
|
// for typical support like:
|
|
// CStdDP2ParamStore< ..., D3DHAL_DP2VIEWPORTINFO>
|
|
// CStdDP2ParamStore< ..., D3DHAL_DP2WINFO>
|
|
//
|
|
// with partial specializations for exceptions like:
|
|
//
|
|
// template< class TSuper>
|
|
// class CStdDP2ParamStore< TSuper, D3DHAL_DP2RENDERSTATE> {};
|
|
// template< class TSuper>
|
|
// class CStdDP2ParamStore< TSuper, D3DHAL_DP2TEXTURESTAGESTATE> {};
|
|
//
|
|
// So, without this support, it'll be easier for each class to have a unique
|
|
// name; as MSVC is currently buggy about inheriting from the same named class
|
|
// multiple times, even WITH a different template parameter.
|
|
|
|
//
|
|
// <Template Parameters>
|
|
// TSuper: Standard parent type which is inheriting from this child class.
|
|
// In this case, it should typically be the CMyContext type.
|
|
// TDP2Data: This is some kind of wrapper class for PORTABLE_DRAWPRIMITIVES2DATA
|
|
// The type is expected to inherit or emulate PORTABLE_DRAWPRIMITIVES2DATA's
|
|
// fields/ member variables, and should typically be consistent with
|
|
// CStdDrawPrimitives2< xxx >::TDP2Data.
|
|
//
|
|
template< class TSuper, class TDP2Data= CDP2DataWrap<> >
|
|
class CStdDP2ViewportInfoStore
|
|
{
|
|
protected: // Variables
|
|
D3DHAL_DP2VIEWPORTINFO m_Param;
|
|
|
|
protected: // Functions
|
|
CStdDP2ViewportInfoStore()
|
|
{ }
|
|
explicit CStdDP2ViewportInfoStore( const D3DHAL_DP2VIEWPORTINFO& P)
|
|
:m_Param( P)
|
|
{ }
|
|
~CStdDP2ViewportInfoStore()
|
|
{ }
|
|
|
|
D3DHAL_DP2VIEWPORTINFO NewDP2ViewportInfo( const D3DHAL_DP2VIEWPORTINFO&
|
|
CurParam, const D3DHAL_DP2VIEWPORTINFO& NewParam) const
|
|
{ // Tell notifier to store the new param.
|
|
return NewParam;
|
|
}
|
|
|
|
public: // Fuctions
|
|
void GetDP2ViewportInfo( D3DHAL_DP2VIEWPORTINFO& GetParam) const
|
|
{ GetParam= m_Param; }
|
|
operator D3DHAL_DP2VIEWPORTINFO() const
|
|
{ return m_Param; }
|
|
HRESULT DP2ViewportInfo( TDP2Data&, const D3DHAL_DP2COMMAND* pCmd,
|
|
const void* pP)
|
|
{
|
|
TSuper* pSThis= static_cast<TSuper*>(this);
|
|
const D3DHAL_DP2VIEWPORTINFO* pParam=
|
|
reinterpret_cast< const D3DHAL_DP2VIEWPORTINFO*>( pP);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
if( wStateCount!= 0) do
|
|
{
|
|
m_Param= pSThis->NewDP2ViewportInfo( m_Param, *pParam);
|
|
++pParam;
|
|
} while( --wStateCount!= 0);
|
|
return DD_OK;
|
|
}
|
|
HRESULT RecDP2ViewportInfo( const D3DHAL_DP2COMMAND* pCmd, void* pP)
|
|
{
|
|
D3DHAL_DP2VIEWPORTINFO* pParam=
|
|
reinterpret_cast< D3DHAL_DP2VIEWPORTINFO*>( pP);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
if( wStateCount!= 0) do
|
|
{
|
|
GetDP2ViewportInfo( *pParam);
|
|
++pParam;
|
|
} while( --wStateCount!= 0);
|
|
return DD_OK;
|
|
}
|
|
};
|
|
|
|
//
|
|
// <Template Parameters>
|
|
// TSuper: Standard parent type which is inheriting from this child class.
|
|
// In this case, it should typically be the CMyContext type.
|
|
// TDP2Data: This is some kind of wrapper class for PORTABLE_DRAWPRIMITIVES2DATA
|
|
// The type is expected to inherit or emulate PORTABLE_DRAWPRIMITIVES2DATA's
|
|
// fields/ member variables, and should typically be consistent with
|
|
// CStdDrawPrimitives2< xxx >::TDP2Data.
|
|
//
|
|
template< class TSuper, class TDP2Data= CDP2DataWrap<> >
|
|
class CStdDP2WInfoStore
|
|
{
|
|
protected: // Variables
|
|
D3DHAL_DP2WINFO m_Param;
|
|
|
|
protected: // Functions
|
|
CStdDP2WInfoStore()
|
|
{ }
|
|
explicit CStdDP2WInfoStore( const D3DHAL_DP2WINFO& P)
|
|
:m_Param( P)
|
|
{ }
|
|
~CStdDP2WInfoStore()
|
|
{ }
|
|
|
|
D3DHAL_DP2WINFO NewDP2WInfo( const D3DHAL_DP2WINFO& CurParam,
|
|
const D3DHAL_DP2WINFO& NewParam) const
|
|
{ // Tell notifier to store the new param.
|
|
return NewParam;
|
|
}
|
|
|
|
public: // Fuctions
|
|
void GetDP2WInfo( D3DHAL_DP2WINFO& GetParam) const
|
|
{ GetParam= m_Param; }
|
|
operator D3DHAL_DP2WINFO() const
|
|
{ return m_Param; }
|
|
HRESULT DP2WInfo( TDP2Data&, const D3DHAL_DP2COMMAND* pCmd,
|
|
const void* pP)
|
|
{
|
|
TSuper* pSThis= static_cast<TSuper*>(this);
|
|
const D3DHAL_DP2WINFO* pParam=
|
|
reinterpret_cast< const D3DHAL_DP2WINFO*>( pP);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
if( wStateCount!= 0) do
|
|
{
|
|
m_Param= pSThis->NewDP2WInfo( m_Param, *pParam);
|
|
++pParam;
|
|
} while( --wStateCount!= 0);
|
|
return DD_OK;
|
|
}
|
|
HRESULT RecDP2WInfo( const D3DHAL_DP2COMMAND* pCmd, void* pP)
|
|
{
|
|
D3DHAL_DP2WINFO* pParam=
|
|
reinterpret_cast< D3DHAL_DP2WINFO*>( pP);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
if( wStateCount!= 0) do
|
|
{
|
|
GetDP2WInfo( *pParam);
|
|
++pParam;
|
|
} while( --wStateCount!= 0);
|
|
return DD_OK;
|
|
}
|
|
};
|
|
|
|
//
|
|
// <Template Parameters>
|
|
// TSuper: Standard parent type which is inheriting from this child class.
|
|
// In this case, it should typically be the CMyContext type.
|
|
// TDP2Data: This is some kind of wrapper class for PORTABLE_DRAWPRIMITIVES2DATA
|
|
// The type is expected to inherit or emulate PORTABLE_DRAWPRIMITIVES2DATA's
|
|
// fields/ member variables, and should typically be consistent with
|
|
// CStdDrawPrimitives2< xxx >::TDP2Data.
|
|
//
|
|
template< class TSuper, class TDP2Data= CDP2DataWrap<> >
|
|
class CStdDP2ZRangeStore
|
|
{
|
|
protected: // Variables
|
|
D3DHAL_DP2ZRANGE m_Param;
|
|
|
|
protected: // Functions
|
|
CStdDP2ZRangeStore()
|
|
{ }
|
|
explicit CStdDP2ZRangeStore( const D3DHAL_DP2ZRANGE& P)
|
|
:m_Param( P)
|
|
{ }
|
|
~CStdDP2ZRangeStore()
|
|
{ }
|
|
|
|
D3DHAL_DP2ZRANGE NewDP2ZRange( const D3DHAL_DP2ZRANGE& CurParam,
|
|
const D3DHAL_DP2ZRANGE& NewParam) const
|
|
{ // Tell notifier to store the new param.
|
|
return NewParam;
|
|
}
|
|
|
|
public: // Fuctions
|
|
void GetDP2ZRange( D3DHAL_DP2ZRANGE& GetParam) const
|
|
{ GetParam= m_Param; }
|
|
operator D3DHAL_DP2ZRANGE() const
|
|
{ return m_Param; }
|
|
HRESULT DP2ZRange( TDP2Data&, const D3DHAL_DP2COMMAND* pCmd,
|
|
const void* pP)
|
|
{
|
|
TSuper* pSThis= static_cast<TSuper*>(this);
|
|
const D3DHAL_DP2ZRANGE* pParam=
|
|
reinterpret_cast< const D3DHAL_DP2ZRANGE*>( pP);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
if( wStateCount!= 0) do
|
|
{
|
|
m_Param= pSThis->NewDP2ZRange( m_Param, *pParam);
|
|
++pParam;
|
|
} while( --wStateCount!= 0);
|
|
return DD_OK;
|
|
}
|
|
HRESULT RecDP2ZRange( const D3DHAL_DP2COMMAND* pCmd, void* pP)
|
|
{
|
|
D3DHAL_DP2ZRANGE* pParam=
|
|
reinterpret_cast< D3DHAL_DP2ZRANGE*>( pP);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
if( wStateCount!= 0) do
|
|
{
|
|
GetDP2ZRange( *pParam);
|
|
++pParam;
|
|
} while( --wStateCount!= 0);
|
|
return DD_OK;
|
|
}
|
|
};
|
|
|
|
//
|
|
// <Template Parameters>
|
|
// TSuper: Standard parent type which is inheriting from this child class.
|
|
// In this case, it should typically be the CMyContext type.
|
|
// TDP2Data: This is some kind of wrapper class for PORTABLE_DRAWPRIMITIVES2DATA
|
|
// The type is expected to inherit or emulate PORTABLE_DRAWPRIMITIVES2DATA's
|
|
// fields/ member variables, and should typically be consistent with
|
|
// CStdDrawPrimitives2< xxx >::TDP2Data.
|
|
//
|
|
template< class TSuper, class TDP2Data= CDP2DataWrap<> >
|
|
class CStdDP2SetMaterialStore
|
|
{
|
|
protected: // Variables
|
|
D3DHAL_DP2SETMATERIAL m_Param;
|
|
|
|
protected: // Functions
|
|
CStdDP2SetMaterialStore()
|
|
{ }
|
|
explicit CStdDP2SetMaterialStore( const D3DHAL_DP2SETMATERIAL& P)
|
|
:m_Param( P)
|
|
{ }
|
|
~CStdDP2SetMaterialStore()
|
|
{ }
|
|
|
|
D3DHAL_DP2SETMATERIAL NewDP2SetMaterial( const D3DHAL_DP2SETMATERIAL& CurParam,
|
|
const D3DHAL_DP2SETMATERIAL& NewParam) const
|
|
{ // Tell notifier to store the new param.
|
|
return NewParam;
|
|
}
|
|
|
|
public: // Fuctions
|
|
void GetDP2SetMaterial( D3DHAL_DP2SETMATERIAL& GetParam) const
|
|
{ GetParam= m_Param; }
|
|
operator D3DHAL_DP2SETMATERIAL() const
|
|
{ return m_Param; }
|
|
HRESULT DP2SetMaterial( TDP2Data&, const D3DHAL_DP2COMMAND* pCmd,
|
|
const void* pP)
|
|
{
|
|
TSuper* pSThis= static_cast<TSuper*>(this);
|
|
const D3DHAL_DP2SETMATERIAL* pParam=
|
|
reinterpret_cast< const D3DHAL_DP2SETMATERIAL*>( pP);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
if( wStateCount!= 0) do
|
|
{
|
|
m_Param= pSThis->NewDP2SetMaterial( m_Param, *pParam);
|
|
++pParam;
|
|
} while( --wStateCount!= 0);
|
|
return DD_OK;
|
|
}
|
|
HRESULT RecDP2SetMaterial( const D3DHAL_DP2COMMAND* pCmd, void* pP)
|
|
{
|
|
D3DHAL_DP2SETMATERIAL* pParam=
|
|
reinterpret_cast< D3DHAL_DP2SETMATERIAL*>( pP);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
if( wStateCount!= 0) do
|
|
{
|
|
GetDP2SetMaterial( *pParam);
|
|
++pParam;
|
|
} while( --wStateCount);
|
|
return DD_OK;
|
|
}
|
|
};
|
|
|
|
//
|
|
// <Template Parameters>
|
|
// TSuper: Standard parent type which is inheriting from this child class.
|
|
// In this case, it should typically be the CMyContext type.
|
|
// TDP2Data: This is some kind of wrapper class for PORTABLE_DRAWPRIMITIVES2DATA
|
|
// The type is expected to inherit or emulate PORTABLE_DRAWPRIMITIVES2DATA's
|
|
// fields/ member variables, and should typically be consistent with
|
|
// CStdDrawPrimitives2< xxx >::TDP2Data.
|
|
//
|
|
template< class TSuper, class TDP2Data= CDP2DataWrap<> >
|
|
class CStdDP2SetVertexShaderStore
|
|
{
|
|
protected: // Variables
|
|
D3DHAL_DP2VERTEXSHADER m_Param;
|
|
|
|
protected: // Functions
|
|
CStdDP2SetVertexShaderStore()
|
|
{ }
|
|
explicit CStdDP2SetVertexShaderStore( const D3DHAL_DP2VERTEXSHADER& P)
|
|
: m_Param( P)
|
|
{ }
|
|
~CStdDP2SetVertexShaderStore()
|
|
{ }
|
|
|
|
D3DHAL_DP2VERTEXSHADER NewDP2SetVertexShader( const D3DHAL_DP2VERTEXSHADER&
|
|
CurParam, const D3DHAL_DP2VERTEXSHADER& NewParam) const
|
|
{ // Tell notifier to store the new param.
|
|
return NewParam;
|
|
}
|
|
|
|
public: // Fuctions
|
|
void GetDP2SetVertexShader( D3DHAL_DP2VERTEXSHADER& GetParam) const
|
|
{ GetParam= m_Param; }
|
|
operator D3DHAL_DP2VERTEXSHADER() const
|
|
{ return m_Param; }
|
|
HRESULT DP2SetVertexShader( TDP2Data&, const D3DHAL_DP2COMMAND* pCmd,
|
|
const void* pP)
|
|
{
|
|
TSuper* pSThis= static_cast<TSuper*>(this);
|
|
const D3DHAL_DP2VERTEXSHADER* pParam=
|
|
reinterpret_cast< const D3DHAL_DP2VERTEXSHADER*>( pP);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
if( wStateCount!= 0) do
|
|
{
|
|
m_Param= pSThis->NewDP2SetVertexShader( m_Param, *pParam);
|
|
|
|
// If the handle is 0, the Device/ Context needs to invalidate all
|
|
// streams.
|
|
if( 0== m_Param.dwHandle)
|
|
{
|
|
// The CStdDP2VStreamManager provides a default implementation
|
|
// for InvalidateAllVStreams()
|
|
pSThis->InvalidateAllVStreams();
|
|
// The CStdDP2IStreamManager provides a default implementation
|
|
// for InvalidateAllIStreams()
|
|
pSThis->InvalidateAllIStreams();
|
|
}
|
|
++pParam;
|
|
} while( --wStateCount!= 0);
|
|
return DD_OK;
|
|
}
|
|
HRESULT RecDP2SetVertexShader( const D3DHAL_DP2COMMAND* pCmd, void* pP)
|
|
{
|
|
D3DHAL_DP2VERTEXSHADER* pParam=
|
|
reinterpret_cast< D3DHAL_DP2VERTEXSHADER*>( pP);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
if( wStateCount!= 0) do
|
|
{
|
|
GetDP2SetVertexShader( *pParam);
|
|
++pParam;
|
|
} while( wStateCount!= 0);
|
|
return DD_OK;
|
|
}
|
|
};
|
|
|
|
//
|
|
// <Template Parameters>
|
|
// TSuper: Standard parent type which is inheriting from this child class.
|
|
// In this case, it should typically be the CMyContext type.
|
|
// TDP2Data: This is some kind of wrapper class for PORTABLE_DRAWPRIMITIVES2DATA
|
|
// The type is expected to inherit or emulate PORTABLE_DRAWPRIMITIVES2DATA's
|
|
// fields/ member variables, and should typically be consistent with
|
|
// CStdDrawPrimitives2< xxx >::TDP2Data.
|
|
//
|
|
template< class TSuper, class TDP2Data= CDP2DataWrap<> >
|
|
class CStdDP2SetPixelShaderStore
|
|
{
|
|
protected: // Variables
|
|
D3DHAL_DP2PIXELSHADER m_Param;
|
|
|
|
protected: // Functions
|
|
CStdDP2SetPixelShaderStore()
|
|
{ }
|
|
explicit CStdDP2SetPixelShaderStore( const D3DHAL_DP2PIXELSHADER& P)
|
|
: m_Param( P)
|
|
{ }
|
|
~CStdDP2SetPixelShaderStore()
|
|
{ }
|
|
|
|
D3DHAL_DP2PIXELSHADER NewDP2SetPixelShader( const D3DHAL_DP2PIXELSHADER&
|
|
CurParam, const D3DHAL_DP2PIXELSHADER& NewParam) const
|
|
{ // Tell notifier to store the new param.
|
|
return NewParam;
|
|
}
|
|
|
|
public: // Fuctions
|
|
void GetDP2SetPixelShader( D3DHAL_DP2PIXELSHADER& GetParam) const
|
|
{ GetParam= m_Param; }
|
|
operator D3DHAL_DP2PIXELSHADER() const
|
|
{ return m_Param; }
|
|
HRESULT DP2SetPixelShader( TDP2Data&, const D3DHAL_DP2COMMAND* pCmd,
|
|
const void* pP)
|
|
{
|
|
TSuper* pSThis= static_cast<TSuper*>(this);
|
|
const D3DHAL_DP2PIXELSHADER* pParam=
|
|
reinterpret_cast< const D3DHAL_DP2PIXELSHADER*>( pP);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
if( wStateCount!= 0) do
|
|
{
|
|
m_Param= pSThis->NewDP2SetPixelShader( m_Param, *pParam);
|
|
++pParam;
|
|
} while( --wStateCount!= 0);
|
|
return DD_OK;
|
|
}
|
|
HRESULT RecDP2SetPixelShader( const D3DHAL_DP2COMMAND* pCmd, void* pP)
|
|
{
|
|
D3DHAL_DP2PIXELSHADER* pParam=
|
|
reinterpret_cast< D3DHAL_DP2PIXELSHADER*>( pP);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
if( wStateCount!= 0) do
|
|
{
|
|
GetDP2SetPixelShader( *pParam);
|
|
++pParam;
|
|
} while( --wStateCount!= 0);
|
|
return DD_OK;
|
|
}
|
|
};
|
|
|
|
//
|
|
// <Template Parameters>
|
|
// TSuper: Standard parent type which is inheriting from this child class.
|
|
// In this case, it should typically be the CMyContext type.
|
|
// c_uiWorldMatrices: The number of world transform matrices that should be
|
|
// stored.
|
|
// c_uiTextureMatrices: The number of texture transform matrices that should
|
|
// be stored.
|
|
// TDP2Data: This is some kind of wrapper class for PORTABLE_DRAWPRIMITIVES2DATA
|
|
// The type is expected to inherit or emulate PORTABLE_DRAWPRIMITIVES2DATA's
|
|
// fields/ member variables, and should typically be consistent with
|
|
// CStdDrawPrimitives2< xxx >::TDP2Data.
|
|
//
|
|
template< class TSuper, const size_t c_uiWorldMatrices= 256,
|
|
const size_t c_uiTextureMatrices= D3DHAL_TSS_MAXSTAGES,
|
|
class TDP2Data= CDP2DataWrap<> >
|
|
class CStdDP2SetTransformStore
|
|
{
|
|
protected: // Types
|
|
typedef block< D3DMATRIX, 2+ c_uiTextureMatrices+ c_uiWorldMatrices>
|
|
TMatrices;
|
|
|
|
protected: // Variables
|
|
TMatrices m_Matrices;
|
|
|
|
private: // Functions
|
|
static bool IsValidTransformType( D3DTRANSFORMSTATETYPE Type)
|
|
{
|
|
// We might not be storing this transform matrix, so we shouldn't
|
|
// record it in a state set and ignore any SET requests.
|
|
if( (Type>= D3DTS_VIEW&& Type<= D3DTS_PROJECTION)||
|
|
(Type>= D3DTS_TEXTURE0&& Type< static_cast< D3DTRANSFORMSTATETYPE>(
|
|
D3DTS_TEXTURE0+ c_uiTextureMatrices))||
|
|
(Type>= D3DTS_WORLD&& Type< static_cast< D3DTRANSFORMSTATETYPE>(
|
|
D3DTS_WORLDMATRIX( c_uiWorldMatrices))))
|
|
return true;
|
|
return false;
|
|
}
|
|
static size_t TransformTypeToIndex( D3DTRANSFORMSTATETYPE Type)
|
|
{
|
|
assert( Type>= D3DTS_VIEW);
|
|
if( Type< D3DTS_TEXTURE0)
|
|
{
|
|
assert( Type<= D3DTS_PROJECTION);
|
|
return static_cast< size_t>( Type- D3DTS_VIEW);
|
|
}
|
|
else if( Type< D3DTS_WORLD)
|
|
{
|
|
assert( Type< static_cast< D3DTRANSFORMSTATETYPE>( \
|
|
D3DTS_TEXTURE0+ c_uiTextureMatrices));
|
|
return static_cast< size_t>( Type- D3DTS_TEXTURE0+ 2);
|
|
}
|
|
else
|
|
{
|
|
assert( Type< static_cast< D3DTRANSFORMSTATETYPE>( \
|
|
D3DTS_WORLDMATRIX( c_uiWorldMatrices)));
|
|
return static_cast< size_t>( Type- D3DTS_WORLD+
|
|
c_uiTextureMatrices+ 2);
|
|
}
|
|
}
|
|
|
|
protected: // Functions
|
|
CStdDP2SetTransformStore()
|
|
{ }
|
|
template< class TIter> // D3DHAL_DP2SETTRANSFORM*
|
|
CStdDP2SetTransformStore( TIter itStart, const TIter itEnd)
|
|
{
|
|
while( itStart!= itEnd)
|
|
{
|
|
m_Matrices[ TransformTypeToIndex( itStart->xfrmType)]=
|
|
itStart->matrix;
|
|
++itStart;
|
|
}
|
|
}
|
|
~CStdDP2SetTransformStore()
|
|
{ }
|
|
|
|
D3DHAL_DP2SETTRANSFORM NewDP2SetTransform( const D3DHAL_DP2SETTRANSFORM&
|
|
CurParam, const D3DHAL_DP2SETTRANSFORM& NewParam) const
|
|
{ // Tell notifier to store the new param.
|
|
return NewParam;
|
|
}
|
|
|
|
public: // Fuctions
|
|
D3DMATRIX GetTransform( D3DTRANSFORMSTATETYPE Type) const
|
|
{ return m_Matrices[ TransformTypeToIndex( Type)]; }
|
|
void GetDP2SetTransform( D3DHAL_DP2SETTRANSFORM& GetParam) const
|
|
{ GetParam.matrix= GetTransform( GetParam.xfrmType); }
|
|
HRESULT DP2SetTransform( TDP2Data&, const D3DHAL_DP2COMMAND* pCmd,
|
|
const void* pP)
|
|
{
|
|
TSuper* pSThis= static_cast<TSuper*>(this);
|
|
const D3DHAL_DP2SETTRANSFORM* pParam=
|
|
reinterpret_cast<const D3DHAL_DP2SETTRANSFORM*>( pP);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
if( wStateCount!= 0) do
|
|
{
|
|
if( IsValidTransformType( pParam->xfrmType))
|
|
{
|
|
D3DHAL_DP2SETTRANSFORM CurWrap;
|
|
CurWrap.xfrmType= pParam->xfrmType;
|
|
GetDP2SetTransform( CurWrap);
|
|
|
|
D3DHAL_DP2SETTRANSFORM NewState(
|
|
pSThis->NewDP2SetTransform( CurWrap, *pParam));
|
|
|
|
m_Matrices[ TransformTypeToIndex( NewState.xfrmType)]=
|
|
NewState.matrix;
|
|
}
|
|
++pParam;
|
|
} while( --wStateCount!= 0);
|
|
return DD_OK;
|
|
}
|
|
HRESULT RecDP2SetTransform( const D3DHAL_DP2COMMAND* pCmd, void* pP)
|
|
{
|
|
D3DHAL_DP2SETTRANSFORM* pParam=
|
|
reinterpret_cast< D3DHAL_DP2SETTRANSFORM*>( pP);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
if( wStateCount!= 0) do
|
|
{
|
|
if( IsValidTransformType( pParam->xfrmType))
|
|
GetDP2SetTransform( *pParam);
|
|
++pParam;
|
|
} while( --wStateCount!= 0);
|
|
return DD_OK;
|
|
}
|
|
};
|
|
|
|
//
|
|
// <Template Parameters>
|
|
// TSuper: Standard parent type which is inheriting from this child class.
|
|
// In this case, it should typically be the CMyContext type.
|
|
// c_uiClipPlanes: The number of user clip planes that should be stored. This
|
|
// should be consistent with the driver cap.
|
|
// TDP2Data: This is some kind of wrapper class for PORTABLE_DRAWPRIMITIVES2DATA
|
|
// The type is expected to inherit or emulate PORTABLE_DRAWPRIMITIVES2DATA's
|
|
// fields/ member variables, and should typically be consistent with
|
|
// CStdDrawPrimitives2< xxx >::TDP2Data.
|
|
//
|
|
template< class TSuper, const size_t c_uiClipPlanes,
|
|
class TDP2Data= CDP2DataWrap<> >
|
|
class CStdDP2SetClipPlaneStore
|
|
{
|
|
protected: // Types
|
|
typedef block< block< D3DVALUE, 4>, c_uiClipPlanes> TClipPlanes;
|
|
|
|
protected: // Variables
|
|
TClipPlanes m_ClipPlanes;
|
|
|
|
protected: // Functions
|
|
CStdDP2SetClipPlaneStore()
|
|
{ }
|
|
template< class TIter> // D3DHAL_DP2SETCLIPPLANE*
|
|
CStdDP2SetClipPlaneStore( TIter itStart, const TIter itEnd)
|
|
{
|
|
while( itStart!= itEnd)
|
|
{
|
|
m_ClipPlanes[ itStart->dwIndex]= itStart->plane;
|
|
++itStart;
|
|
}
|
|
}
|
|
~CStdDP2SetClipPlaneStore()
|
|
{ }
|
|
|
|
D3DHAL_DP2SETCLIPPLANE NewDP2SetClipPlane( const D3DHAL_DP2SETCLIPPLANE&
|
|
CurParam, const D3DHAL_DP2SETCLIPPLANE& NewParam) const
|
|
{ // Tell notifier to store the new param.
|
|
return NewParam;
|
|
}
|
|
|
|
public: // Functions
|
|
block< D3DVALUE, 4> GetClipPlane( DWORD dwIndex) const
|
|
{ return m_ClipPlanes[ dwIndex]; }
|
|
void GetDP2SetClipPlane( D3DHAL_DP2SETCLIPPLANE& GetParam) const
|
|
{
|
|
block< D3DVALUE, 4> CP( GetClipPlane( GetParam.dwIndex));
|
|
copy( CP.begin(), CP.end(), &GetParam.plane[ 0]);
|
|
}
|
|
HRESULT DP2SetClipPlane( TDP2Data& DP2Data,
|
|
const D3DHAL_DP2COMMAND* pCmd, const void* pP)
|
|
{
|
|
TSuper* pSThis= static_cast<TSuper*>(this);
|
|
const D3DHAL_DP2SETCLIPPLANE* pParam=
|
|
reinterpret_cast<const D3DHAL_DP2SETCLIPPLANE*>(pP);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
if( wStateCount!= 0) do
|
|
{
|
|
if( pParam->dwIndex< m_ClipPlanes.size())
|
|
{
|
|
D3DHAL_DP2SETCLIPPLANE CurWrap;
|
|
CurWrap.dwIndex= pParam->dwIndex;
|
|
GetDP2SetClipPlane( CurWrap);
|
|
|
|
D3DHAL_DP2SETCLIPPLANE NewState(
|
|
pSThis->NewDP2SetClipPlane( CurWrap, *pParam));
|
|
|
|
copy( &NewState.plane[ 0], &NewState.plane[ 4],
|
|
m_ClipPlanes[ NewState.dwIndex].begin());
|
|
}
|
|
++pParam;
|
|
} while( --wStateCount);
|
|
return DD_OK;
|
|
}
|
|
HRESULT RecDP2SetClipPlane( const D3DHAL_DP2COMMAND* pCmd, void* pP)
|
|
{
|
|
D3DHAL_DP2SETCLIPPLANE* pParam=
|
|
reinterpret_cast< D3DHAL_DP2SETCLIPPLANE*>(pP);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
if( wStateCount!= 0) do
|
|
{
|
|
if( pParam->dwIndex< m_ClipPlanes.size())
|
|
GetDP2SetClipPlane( *pParam);
|
|
++pParam;
|
|
} while( --wStateCount!= 0);
|
|
return DD_OK;
|
|
}
|
|
};
|
|
|
|
//
|
|
// <Template Parameters>
|
|
// TSuper: Standard parent type which is inheriting from this child class.
|
|
// In this case, it should typically be the CMyContext type.
|
|
// TDP2Data: This is some kind of wrapper class for PORTABLE_DRAWPRIMITIVES2DATA
|
|
// The type is expected to inherit or emulate PORTABLE_DRAWPRIMITIVES2DATA's
|
|
// fields/ member variables, and should typically be consistent with
|
|
// CStdDrawPrimitives2< xxx >::TDP2Data.
|
|
//
|
|
template< class TSuper, class TDP2Data= CDP2DataWrap<> >
|
|
class CStdDP2RenderStateStore
|
|
{
|
|
protected: // Variables
|
|
block< DWORD, D3DHAL_MAX_RSTATES> m_Param;
|
|
|
|
protected: // Functions
|
|
CStdDP2RenderStateStore()
|
|
{ m_Param[ D3DRENDERSTATE_SCENECAPTURE]= FALSE; }
|
|
template< class TIter> // D3DHAL_DP2RENDERSTATE*
|
|
CStdDP2RenderStateStore( TIter itStart, const TIter itEnd)
|
|
{
|
|
m_Param[ D3DRENDERSTATE_SCENECAPTURE]= FALSE;
|
|
while( itStart!= itEnd)
|
|
{
|
|
m_Param[ itStart->RenderState]= itStart->dwState;
|
|
itStart++;
|
|
}
|
|
}
|
|
~CStdDP2RenderStateStore()
|
|
{ }
|
|
|
|
D3DHAL_DP2RENDERSTATE NewDP2RenderState( const D3DHAL_DP2RENDERSTATE&
|
|
CurParam, const D3DHAL_DP2RENDERSTATE& NewParam) const
|
|
{ // Tell notifier to store the new param.
|
|
return NewParam;
|
|
}
|
|
|
|
void OnSceneCaptureStart( void)
|
|
{ }
|
|
void OnSceneCaptureEnd( void)
|
|
{ }
|
|
|
|
public: // Functions
|
|
DWORD GetRenderStateDW( D3DRENDERSTATETYPE RS) const
|
|
{ return m_Param[ RS]; }
|
|
D3DVALUE GetRenderStateDV( D3DRENDERSTATETYPE RS) const
|
|
{ return *(reinterpret_cast< const D3DVALUE*>( &m_Param[ RS])); }
|
|
void GetDP2RenderState( D3DHAL_DP2RENDERSTATE& GetParam) const
|
|
{ GetParam.dwState= GetRenderStateDW( GetParam.RenderState); }
|
|
HRESULT DP2RenderState( TDP2Data& DP2Data, const D3DHAL_DP2COMMAND* pCmd,
|
|
const void* pP)
|
|
{
|
|
TSuper* pSThis= static_cast<TSuper*>(this);
|
|
const D3DHAL_DP2RENDERSTATE* pParam=
|
|
reinterpret_cast<const D3DHAL_DP2RENDERSTATE*>(pP);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
D3DHAL_DP2RENDERSTATE SCap;
|
|
SCap.RenderState= static_cast< D3DRENDERSTATETYPE>(
|
|
D3DRENDERSTATE_SCENECAPTURE);
|
|
GetDP2RenderState( SCap);
|
|
const DWORD dwOldSC( SCap.dwState);
|
|
|
|
if((DP2Data.dwFlags()& D3DHALDP2_EXECUTEBUFFER)!= 0)
|
|
{
|
|
// DP2Data.lpdwRStates should be valid.
|
|
|
|
if( wStateCount!= 0) do
|
|
{
|
|
if( pParam->RenderState< D3DHAL_MAX_RSTATES)
|
|
{
|
|
D3DHAL_DP2RENDERSTATE CurWrap;
|
|
CurWrap.RenderState= pParam->RenderState;
|
|
GetDP2RenderState( CurWrap);
|
|
|
|
D3DHAL_DP2RENDERSTATE NewState(
|
|
pSThis->NewDP2RenderState( CurWrap, *pParam));
|
|
|
|
m_Param[ NewState.RenderState]= NewState.dwState;
|
|
DP2Data.lpdwRStates()[ NewState.RenderState]= NewState.dwState;
|
|
}
|
|
++pParam;
|
|
} while( --wStateCount!= 0);
|
|
|
|
}
|
|
else
|
|
{
|
|
if( wStateCount!= 0) do
|
|
{
|
|
if( pParam->RenderState< D3DHAL_MAX_RSTATES)
|
|
{
|
|
D3DHAL_DP2RENDERSTATE CurWrap;
|
|
CurWrap.RenderState= pParam->RenderState;
|
|
GetDP2RenderState( CurWrap);
|
|
|
|
D3DHAL_DP2RENDERSTATE NewState(
|
|
pSThis->NewDP2RenderState( CurWrap, *pParam));
|
|
|
|
m_Param[ NewState.RenderState]= NewState.dwState;
|
|
}
|
|
++pParam;
|
|
} while( --wStateCount!= 0);
|
|
}
|
|
|
|
GetDP2RenderState( SCap);
|
|
if( FALSE== dwOldSC && TRUE== SCap.dwState)
|
|
OnSceneCaptureStart();
|
|
else if( TRUE== dwOldSC && FALSE== SCap.dwState)
|
|
OnSceneCaptureEnd();
|
|
|
|
return DD_OK;
|
|
}
|
|
HRESULT RecDP2RenderState( const D3DHAL_DP2COMMAND* pCmd, void* pP)
|
|
{
|
|
D3DHAL_DP2RENDERSTATE* pParam=
|
|
reinterpret_cast< D3DHAL_DP2RENDERSTATE*>(pP);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
if( wStateCount) do
|
|
{
|
|
if( pParam->RenderState< D3DHAL_MAX_RSTATES)
|
|
GetDP2RenderState( *pParam);
|
|
++pParam;
|
|
} while( --wStateCount!= 0);
|
|
|
|
return DD_OK;
|
|
}
|
|
};
|
|
|
|
//
|
|
// <Template Parameters>
|
|
// TSuper: Standard parent type which is inheriting from this child class.
|
|
// In this case, it should typically be the CMyContext type.
|
|
// TDP2Data: This is some kind of wrapper class for PORTABLE_DRAWPRIMITIVES2DATA
|
|
// The type is expected to inherit or emulate PORTABLE_DRAWPRIMITIVES2DATA's
|
|
// fields/ member variables, and should typically be consistent with
|
|
// CStdDrawPrimitives2< xxx >::TDP2Data.
|
|
//
|
|
template< class TSuper, class TDP2Data= CDP2DataWrap<> >
|
|
class CStdDP2TextureStageStateStore
|
|
{
|
|
protected: // Variables
|
|
block< block< DWORD, D3DTSS_MAX>, D3DHAL_TSS_MAXSTAGES> m_Param;
|
|
|
|
protected: // Functions
|
|
CStdDP2TextureStageStateStore()
|
|
{ }
|
|
template< class TIter> // D3DHAL_DP2TEXTURESTAGESTATE*
|
|
CStdDP2TextureStageStateStore( TIter itStart, const TIter itEnd)
|
|
{
|
|
while( itStart!= itEnd)
|
|
{
|
|
m_Param[ itStart->wStage][ itStart->TSState]= itStart->dwValue();
|
|
++itStart;
|
|
}
|
|
}
|
|
~CStdDP2TextureStageStateStore()
|
|
{ }
|
|
|
|
D3DHAL_DP2TEXTURESTAGESTATE NewDP2TextureStageState( const
|
|
D3DHAL_DP2TEXTURESTAGESTATE& CurParam, const
|
|
D3DHAL_DP2TEXTURESTAGESTATE& NewParam) const
|
|
{ // Tell notifier to store the new param.
|
|
return NewParam;
|
|
}
|
|
|
|
public: // Functions
|
|
DWORD GetTextureStageStateDW( WORD wStage, WORD wTSState) const
|
|
{ return m_Param[ wStage][ wTSState]; }
|
|
D3DVALUE GetTextureStageStateDV( WORD wStage, WORD wTSState) const
|
|
{ return *(reinterpret_cast< const D3DVALUE*>( &m_Param[ wStage][ wTSState])); }
|
|
void GetDP2TextureStageState( D3DHAL_DP2TEXTURESTAGESTATE& GetParam) const
|
|
{ GetParam.dwValue= GetTextureStageStateDW( GetParam.wStage, GetParam.TSState); }
|
|
HRESULT DP2TextureStageState( TDP2Data& DP2Data,
|
|
const D3DHAL_DP2COMMAND* pCmd, const void* pP)
|
|
{
|
|
TSuper* pSThis= static_cast<TSuper*>(this);
|
|
const D3DHAL_DP2TEXTURESTAGESTATE* pParam=
|
|
reinterpret_cast<const D3DHAL_DP2TEXTURESTAGESTATE*>(pP);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
if( wStateCount!= 0) do
|
|
{
|
|
if( pParam->wStage< D3DHAL_TSS_MAXSTAGES&& pParam->TSState< D3DTSS_MAX)
|
|
{
|
|
D3DHAL_DP2TEXTURESTAGESTATE CurWrap;
|
|
CurWrap.wStage= pParam->wStage;
|
|
CurWrap.TSState= pParam->TSState;
|
|
GetDP2TextureStageState( CurWrap);
|
|
|
|
D3DHAL_DP2TEXTURESTAGESTATE NewState(
|
|
pSThis->NewDP2TextureStageState( CurWrap, *pParam));
|
|
|
|
m_Param[ NewState.wStage][ NewState.TSState]= NewState.dwValue;
|
|
}
|
|
++pParam;
|
|
} while( --wStateCount);
|
|
|
|
return DD_OK;
|
|
}
|
|
HRESULT RecDP2TextureStageState( const D3DHAL_DP2COMMAND* pCmd, void* pP)
|
|
{
|
|
D3DHAL_DP2TEXTURESTAGESTATE* pParam=
|
|
reinterpret_cast< D3DHAL_DP2TEXTURESTAGESTATE*>(pP);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
if( wStateCount!= 0) do
|
|
{
|
|
if( pParam->wStage< D3DHAL_TSS_MAXSTAGES&& pParam->TSState< D3DTSS_MAX)
|
|
GetDP2TextureStageState( *pParam);
|
|
++pParam;
|
|
} while( --wStateCount!= 0);
|
|
return DD_OK;
|
|
}
|
|
};
|
|
|
|
//
|
|
// The more complex manager classes:
|
|
//
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CVStream
|
|
//
|
|
// This class stores everything associated with a vertex stream. This
|
|
// implementation allows 4 representations (video, system, user, and none).
|
|
// This class is used by a VStream manager class.
|
|
//
|
|
// <Template Parameters>
|
|
// TS: Video memory surface object, typically either CMySurface or
|
|
// IVidMemSurface, etc. A valid pointer to this object is stored, when the
|
|
// stream source is from a video memory surface.
|
|
// TSDBE: The SurfDBEntry type, typically, CMySurfDBEntry or CSurfDBEntry. A
|
|
// valid pointer to this object is stored, when the stream source is from
|
|
// a video memory or system memory surface.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
template< class TS, class TSDBE>
|
|
class CVStream
|
|
{
|
|
public: // Types
|
|
typedef TS TSurface;
|
|
typedef TSDBE TSurfDBEntry;
|
|
enum EMemLocation
|
|
{
|
|
None,
|
|
User,
|
|
System,
|
|
Video
|
|
};
|
|
|
|
protected: // Variables
|
|
DWORD m_dwHandle;
|
|
TSurface m_Surface;
|
|
TSurfDBEntry m_SurfDBEntry;
|
|
void* m_pUserMemData;
|
|
DWORD m_dwStride;
|
|
DWORD m_dwFVF;
|
|
EMemLocation m_eMemLocation;
|
|
|
|
public: // Functions
|
|
CVStream()
|
|
: m_dwHandle( 0), m_pUserMemData( NULL), m_dwStride( 0), m_dwFVF( 0),
|
|
m_eMemLocation( None)
|
|
{ }
|
|
// Video Memory representation constructor.
|
|
CVStream( DWORD dwHandle, const TSurface& Surface,
|
|
const TSurfDBEntry& SurfDBEntry, DWORD dwStride): m_dwHandle( dwHandle),
|
|
m_Surface( Surface), m_SurfDBEntry( SurfDBEntry), m_pUserMemData( NULL),
|
|
m_dwStride( dwStride), m_dwFVF( 0), m_eMemLocation( Video)
|
|
{ }
|
|
// System Memory representation constructor.
|
|
CVStream( DWORD dwHandle, const TSurfDBEntry& SurfDBEntry, DWORD dwStride):
|
|
m_dwHandle( dwHandle), m_SurfDBEntry( SurfDBEntry),
|
|
m_pUserMemData( NULL), m_dwStride( dwStride), m_dwFVF( 0),
|
|
m_eMemLocation( System)
|
|
{ }
|
|
// User Memory representation constructor.
|
|
CVStream( void* pUserMem, DWORD dwStride):
|
|
m_dwHandle( 0), m_pUserMemData( pUserMem), m_dwStride( dwStride),
|
|
m_dwFVF( 0), m_eMemLocation( User)
|
|
{ }
|
|
|
|
EMemLocation GetMemLocation() const
|
|
{ return m_eMemLocation; }
|
|
void SetFVF( DWORD dwFVF)
|
|
{ m_dwFVF= dwFVF; }
|
|
DWORD GetFVF() const
|
|
{ return m_dwFVF; }
|
|
DWORD GetHandle() const
|
|
{
|
|
assert( GetMemLocation()== System|| GetMemLocation()== Video);
|
|
return m_dwHandle;
|
|
}
|
|
DWORD GetStride() const
|
|
{
|
|
assert( GetMemLocation()!= None);
|
|
return m_dwStride;
|
|
}
|
|
TSurface& GetVidMemRepresentation()
|
|
{
|
|
assert( GetMemLocation()== Video);
|
|
return m_Surface;
|
|
}
|
|
const TSurface& GetVidMemRepresentation() const
|
|
{
|
|
assert( GetMemLocation()== Video);
|
|
return m_Surface;
|
|
}
|
|
TSurfDBEntry& GetSurfDBRepresentation()
|
|
{
|
|
assert( GetMemLocation()== Video|| GetMemLocation()== System);
|
|
return m_SurfDBEntry;
|
|
}
|
|
const TSurfDBEntry& GetSurfDBRepresentation() const
|
|
{
|
|
assert( GetMemLocation()== Video|| GetMemLocation()== System);
|
|
return m_SurfDBEntry;
|
|
}
|
|
void* GetUserMemPtr() const
|
|
{
|
|
assert( GetMemLocation()== User);
|
|
return m_pUserMemData;
|
|
}
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CStdDP2VStreamManager
|
|
//
|
|
// This class contains DP2 member functions to correctly process
|
|
// D3DDP2OP_SETSTREAMSOURCE & D3DDP2OP_SETSTREAMSOURCEUM. It can also correctly
|
|
// record a command buffer operation for D3DDP2OP_SETSTREAMSOURCE. To do this,
|
|
// however, it must maintain information for vertex stream, or "manage"
|
|
// VStream objects.
|
|
//
|
|
// This class also contains a function, InvalidateAllStreams, which is needed
|
|
// to be called when a D3DDP2OP_SETVERTEXSHADER operation is processed with a
|
|
// zero value VERTEXSHADER.
|
|
//
|
|
// <Template Parameters>
|
|
// TSuper: Standard parent type which is inheriting from this child class.
|
|
// In this case, it should typically be the CMyContext type.
|
|
// TVS: The vertex stream type which represents data associated with a vertex
|
|
// stream. This is typically, CVStream<> or something derived from it.
|
|
// c_uiStreams: The number of vertex streams to support. Typically, non-TnL
|
|
// drivers only support 1. This should be consistent with the cap in the
|
|
// driver.
|
|
// TDP2Data: This is some kind of wrapper class for PORTABLE_DRAWPRIMITIVES2DATA
|
|
// The type is expected to inherit or emulate PORTABLE_DRAWPRIMITIVES2DATA's
|
|
// fields/ member variables, and should typically be consistent with
|
|
// CStdDrawPrimitives2< xxx >::TDP2Data.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
template< class TSuper,
|
|
class TVS= CVStream< TSuper::TPerDDrawData::TDriver::TSurface*, TSuper::TPerDDrawData::TSurfDBEntry*>,
|
|
const size_t c_uiStreams= 1, class TDP2Data= CDP2DataWrap<> >
|
|
class CStdDP2VStreamManager
|
|
{
|
|
public: // Types
|
|
typedef TVS TVStream;
|
|
typedef block< TVStream, c_uiStreams> TVStreamDB;
|
|
|
|
protected: // Variables
|
|
TVStreamDB m_VStreamDB;
|
|
|
|
protected: // Functions
|
|
CStdDP2VStreamManager()
|
|
{ }
|
|
~CStdDP2VStreamManager()
|
|
{ }
|
|
|
|
public: // Fuctions
|
|
TVStream& GetVStream( TVStreamDB::size_type uiStream)
|
|
{ return m_VStreamDB[ uiStream]; }
|
|
const TVStream& GetVStream( TVStreamDB::size_type uiStream) const
|
|
{ return m_VStreamDB[ uiStream]; }
|
|
HRESULT DP2SetStreamSource( TDP2Data&, const D3DHAL_DP2COMMAND* pCmd,
|
|
const void* pP)
|
|
{
|
|
const D3DHAL_DP2SETSTREAMSOURCE* pParam=
|
|
reinterpret_cast< const D3DHAL_DP2SETSTREAMSOURCE*>( pP);
|
|
TSuper* pSThis= static_cast<TSuper*>(this);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
if( wStateCount!= 0) do
|
|
{
|
|
if( pParam->dwStream< m_VStreamDB.size())
|
|
{
|
|
if( 0== pParam->dwVBHandle)
|
|
m_VStreamDB[ pParam->dwStream]= TVStream();
|
|
else
|
|
{
|
|
typename TSuper::TPerDDrawData::TSurfDBEntry* pDBEntry=
|
|
pSThis->GetPerDDrawData().GetSurfDBEntry(
|
|
pParam->dwVBHandle);
|
|
if( pDBEntry!= NULL)
|
|
{
|
|
if((pDBEntry->GetLCLddsCaps().dwCaps&
|
|
DDSCAPS_VIDEOMEMORY)!= 0)
|
|
{
|
|
// Assign in a video memory representation.
|
|
m_VStreamDB[ pParam->dwStream]=
|
|
TVStream( pParam->dwVBHandle, pSThis->
|
|
GetPerDDrawData().GetDriver().GetSurface(
|
|
*pDBEntry), pDBEntry, pParam->dwStride);
|
|
}
|
|
else
|
|
{
|
|
// Assign in a system memory representation.
|
|
m_VStreamDB[ pParam->dwStream]=
|
|
TVStream( pParam->dwVBHandle,
|
|
pDBEntry, pParam->dwStride);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Handle invalid, reset stream.
|
|
m_VStreamDB[ pParam->dwStream]= TVStream();
|
|
}
|
|
}
|
|
}
|
|
|
|
++pParam;
|
|
} while( --wStateCount!= 0);
|
|
return DD_OK;
|
|
}
|
|
HRESULT DP2SetStreamSourceUM( TDP2Data& DP2Data, const D3DHAL_DP2COMMAND* pCmd,
|
|
const void* pP)
|
|
{
|
|
const D3DHAL_DP2SETSTREAMSOURCEUM* pParam=
|
|
reinterpret_cast< const D3DHAL_DP2SETSTREAMSOURCEUM*>( pP);
|
|
TSuper* pSThis= static_cast<TSuper*>(this);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
if( wStateCount!= 0) do
|
|
{
|
|
if( pParam->dwStream< m_VStreamDB.size())
|
|
{
|
|
if( DP2Data.lpVertices()!= NULL)
|
|
{
|
|
// Assign in a user memory representation.
|
|
m_VStreamDB[ pParam->dwStream]=
|
|
TVStream( DP2Data.lpVertices(), pParam->dwStride);
|
|
}
|
|
else
|
|
{
|
|
// Reset stream.
|
|
m_VStreamDB[ pParam->dwStream]= TVStream();
|
|
}
|
|
}
|
|
|
|
++pParam;
|
|
} while( --wStateCount!= 0);
|
|
return DD_OK;
|
|
}
|
|
HRESULT RecDP2SetStreamSource( const D3DHAL_DP2COMMAND* pCmd, void* pP)
|
|
{
|
|
D3DHAL_DP2SETSTREAMSOURCE* pParam=
|
|
reinterpret_cast< D3DHAL_DP2SETSTREAMSOURCE*>( pP);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
if( wStateCount!= 0) do
|
|
{
|
|
const DWORD dwStream( pParam->dwStream);
|
|
if( dwStream< m_VStreamDB.size())
|
|
{
|
|
const TVStream& VStream( m_VStreamDB[ dwStream]);
|
|
switch( VStream.GetMemLocation())
|
|
{
|
|
case( TVStream::EMemLocation::None): ;
|
|
case( TVStream::EMemLocation::User): ;
|
|
pParam->dwVBHandle= 0;
|
|
pParam->dwStride= 0;
|
|
break;
|
|
|
|
case( TVStream::EMemLocation::System): ;
|
|
case( TVStream::EMemLocation::Video): ;
|
|
pParam->dwVBHandle= VStream.GetHandle();
|
|
pParam->dwStride= VStream.GetStride();
|
|
break;
|
|
|
|
default: {
|
|
const bool Unrecognized_VStream_enum( false);
|
|
assert( Unrecognized_VStream_enum);
|
|
}
|
|
}
|
|
}
|
|
|
|
++pParam;
|
|
} while( --wStateCount!= 0);
|
|
return DD_OK;
|
|
}
|
|
void InvalidateAllVStreams()
|
|
{
|
|
fill( m_VStreamDB.begin(), m_VStreamDB.end(), TVStream());
|
|
}
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CIStream
|
|
//
|
|
// This class stores everything associated with a index stream. This
|
|
// implementation allows 3 representations (video, system, and none).
|
|
// This class is used by a IStream manager class.
|
|
//
|
|
// <Template Parameters>
|
|
// TS: Video memory surface object, typically either CMySurface or
|
|
// IVidMemSurface, etc. A valid pointer to this object is stored, when the
|
|
// stream source is from a video memory surface.
|
|
// TSDBE: The SurfDBEntry type, typically, CMySurfDBEntry or CSurfDBEntry. A
|
|
// valid pointer to this object is stored, when the stream source is from
|
|
// a video memory or system memory surface.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
template< class TS, class TSDBE>
|
|
class CIStream
|
|
{
|
|
public: // Types
|
|
typedef TS TSurface;
|
|
typedef TSDBE TSurfDBEntry;
|
|
enum EMemLocation
|
|
{
|
|
None,
|
|
System,
|
|
Video
|
|
};
|
|
|
|
protected: // Variables
|
|
DWORD m_dwHandle;
|
|
TSurface m_Surface;
|
|
TSurfDBEntry m_SurfDBEntry;
|
|
DWORD m_dwStride;
|
|
EMemLocation m_eMemLocation;
|
|
|
|
public: // Functions
|
|
CIStream():
|
|
m_dwHandle( 0), m_dwStride( 0), m_eMemLocation( None)
|
|
{ }
|
|
// Video Memory representation constructor.
|
|
CIStream( DWORD dwHandle, const TSurface& Surface,
|
|
const TSurfDBEntry& SurfDBEntry, DWORD dwStride): m_dwHandle( dwHandle),
|
|
m_Surface( Surface), m_SurfDBEntry( SurfDBEntry), m_dwStride( dwStride),
|
|
m_eMemLocation( Video)
|
|
{ }
|
|
// System Memory representation constructor.
|
|
CIStream( DWORD dwHandle, const TSurfDBEntry& SurfDBEntry, DWORD dwStride):
|
|
m_dwHandle( dwHandle), m_SurfDBEntry( SurfDBEntry),
|
|
m_dwStride( dwStride), m_eMemLocation( System)
|
|
{ }
|
|
|
|
EMemLocation GetMemLocation() const
|
|
{ return m_eMemLocation; }
|
|
DWORD GetHandle() const
|
|
{
|
|
assert( GetMemLocation()== System|| GetMemLocation()== Video);
|
|
return m_dwHandle;
|
|
}
|
|
DWORD GetStride() const
|
|
{
|
|
assert( GetMemLocation()!= None);
|
|
return m_dwStride;
|
|
}
|
|
const TSurface& GetVidMemRepresentation() const
|
|
{
|
|
assert( GetMemLocation()== Video);
|
|
return m_Surface;
|
|
}
|
|
TSurface& GetVidMemRepresentation()
|
|
{
|
|
assert( GetMemLocation()== Video);
|
|
return m_Surface;
|
|
}
|
|
const TSurfDBEntry& GetSurfDBRepresentation() const
|
|
{
|
|
assert( GetMemLocation()== Video|| GetMemLocation()== System);
|
|
return m_SurfDBEntry;
|
|
}
|
|
TSurfDBEntry& GetSurfDBRepresentation()
|
|
{
|
|
assert( GetMemLocation()== Video|| GetMemLocation()== System);
|
|
return m_SurfDBEntry;
|
|
}
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CStdDP2IStreamManager
|
|
//
|
|
// This class contains DP2 member functions to correctly process
|
|
// D3DDP2OP_SETINDICES. It can also correctly record a command buffer operation
|
|
// for D3DDP2OP_SETINDICES. To do this, however, it must maintain information
|
|
// for index streams, or "manage" IStream objects.
|
|
//
|
|
// <Template Parameters>
|
|
// TSuper: Standard parent type which is inheriting from this child class.
|
|
// In this case, it should typically be the CMyContext type.
|
|
// TIS: The index stream type which represents data associated with a index
|
|
// stream. This is typically, CIStream<> or something derived from it.
|
|
// TDP2Data: This is some kind of wrapper class for PORTABLE_DRAWPRIMITIVES2DATA
|
|
// The type is expected to inherit or emulate PORTABLE_DRAWPRIMITIVES2DATA's
|
|
// fields/ member variables, and should typically be consistent with
|
|
// CStdDrawPrimitives2< xxx >::TDP2Data.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
template< class TSuper,
|
|
class TIS= CIStream< TSuper::TPerDDrawData::TDriver::TSurface*, TSuper::TPerDDrawData::TSurfDBEntry*>,
|
|
class TDP2Data= CDP2DataWrap<> >
|
|
class CStdDP2IStreamManager
|
|
{
|
|
public: // Types
|
|
typedef TIS TIStream;
|
|
typedef block< TIStream, 1> TIStreamDB;
|
|
|
|
protected: // Variables
|
|
TIStreamDB m_IStreamDB;
|
|
|
|
protected: // Functions
|
|
CStdDP2IStreamManager()
|
|
{ }
|
|
~CStdDP2IStreamManager()
|
|
{ }
|
|
|
|
public: // Fuctions
|
|
TIStream& GetIStream( TIStreamDB::size_type uiStream)
|
|
{ return m_IStreamDB[ uiStream]; }
|
|
const TIStream& GetIStream( TIStreamDB::size_type uiStream) const
|
|
{ return m_IStreamDB[ uiStream]; }
|
|
HRESULT DP2SetIndices( TDP2Data&, const D3DHAL_DP2COMMAND* pCmd,
|
|
const void* pP)
|
|
{
|
|
const D3DHAL_DP2SETINDICES* pParam=
|
|
reinterpret_cast< const D3DHAL_DP2SETINDICES*>( pP);
|
|
TSuper* pSThis= static_cast<TSuper*>(this);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
if( wStateCount!= 0) do
|
|
{
|
|
// For ease of extension in case multiple IStreams are supported
|
|
// later.
|
|
const DWORD dwStream( 0);
|
|
|
|
if( dwStream< m_IStreamDB.size())
|
|
{
|
|
if( 0== pParam->dwVBHandle)
|
|
m_IStreamDB[ dwStream]= TIStream();
|
|
else
|
|
{
|
|
typename TSuper::TPerDDrawData::TSurfDBEntry* pDBEntry=
|
|
pSThis->GetPerDDrawData().GetSurfDBEntry(
|
|
pParam->dwVBHandle);
|
|
if( pDBEntry!= NULL)
|
|
{
|
|
if((pDBEntry->GetLCLddsCaps().dwCaps&
|
|
DDSCAPS_VIDEOMEMORY)!= 0)
|
|
{
|
|
// Assign in a video memory representation.
|
|
m_IStreamDB[ dwStream]=
|
|
TIStream( pParam->dwVBHandle, pSThis->
|
|
GetPerDDrawData().GetDriver().GetSurface(
|
|
*pDBEntry), pDBEntry, pParam->dwStride);
|
|
}
|
|
else
|
|
{
|
|
// Assign in a system memory representation.
|
|
m_IStreamDB[ dwStream]=
|
|
TIStream( pParam->dwVBHandle,
|
|
pDBEntry, pParam->dwStride);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Handle invalid, reset stream.
|
|
m_IStreamDB[ dwStream]= TIStream();
|
|
}
|
|
}
|
|
}
|
|
|
|
++pParam;
|
|
} while( --wStateCount!= 0);
|
|
return DD_OK;
|
|
}
|
|
HRESULT RecDP2SetIndices( const D3DHAL_DP2COMMAND* pCmd, void* pP)
|
|
{
|
|
D3DHAL_DP2SETINDICES* pParam=
|
|
reinterpret_cast< D3DHAL_DP2SETINDICES*>( pP);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
if( wStateCount!= 0) do
|
|
{
|
|
const DWORD dwStream( 0);
|
|
if( dwStream< m_IStreamDB.size())
|
|
{
|
|
const TIStream& IStream( m_IStreamDB[ dwStream]);
|
|
switch( IStream.GetMemLocation())
|
|
{
|
|
case( TIStream::EMemLocation::None): ;
|
|
pParam->dwVBHandle= 0;
|
|
pParam->dwStride= 0;
|
|
break;
|
|
|
|
case( TIStream::EMemLocation::System): ;
|
|
case( TIStream::EMemLocation::Video): ;
|
|
pParam->dwVBHandle= IStream.GetHandle();
|
|
pParam->dwStride= IStream.GetStride();
|
|
break;
|
|
|
|
default: {
|
|
const bool Unrecognized_IStream_enum( false);
|
|
assert( Unrecognized_IStream_enum);
|
|
}
|
|
}
|
|
}
|
|
|
|
++pParam;
|
|
} while( --wStateCount!= 0);
|
|
return DD_OK;
|
|
}
|
|
void InvalidateAllIStreams()
|
|
{
|
|
fill( m_IStreamDB.begin(), m_IStreamDB.end(), TIStream());
|
|
}
|
|
};
|
|
|
|
class CPalDBEntry
|
|
{
|
|
protected: // Types
|
|
typedef block< DWORD, 256> TPalEntries;
|
|
|
|
protected: // Variables
|
|
DWORD m_dwFlags;
|
|
TPalEntries m_PalEntries;
|
|
|
|
public: // Functions
|
|
CPalDBEntry() : m_dwFlags( 0)
|
|
{ fill( m_PalEntries.begin(), m_PalEntries.end(), 0); }
|
|
~CPalDBEntry()
|
|
{ }
|
|
void SetFlags( DWORD dwFlags)
|
|
{ m_dwFlags= dwFlags; }
|
|
DWORD GetFlags()
|
|
{ return m_dwFlags; }
|
|
DWORD* GetEntries()
|
|
{ return m_PalEntries.begin(); }
|
|
template< class ForwardIterator>
|
|
void Update( TPalEntries::size_type uiStart, ForwardIterator f,
|
|
ForwardIterator l)
|
|
{ copy( f, l, m_PalEntries.begin()+ uiStart); }
|
|
};
|
|
|
|
//
|
|
// <Template Parameters>
|
|
// TSuper: Standard parent type which is inheriting from this child class.
|
|
// In this case, it should typically be the CMyContext type.
|
|
// TPDBE: This is the palette database entry type, or whatever is associated
|
|
// with a palette. This type is typically, CPalDBEntry or something
|
|
// derived from it.
|
|
// TPDB: This can be any Unique, Pair Associative Container, typically a map,
|
|
// which associates a DWORD palette handle to a palette type.
|
|
// TSPDB: This can be any Unique, Pair Associative Container, typically a map,
|
|
// which associates a DWORD surface handle to a DWORD palette handle.
|
|
// TDP2Data: This is some kind of wrapper class for PORTABLE_DRAWPRIMITIVES2DATA
|
|
// The type is expected to inherit or emulate PORTABLE_DRAWPRIMITIVES2DATA's
|
|
// fields/ member variables, and should typically be consistent with
|
|
// CStdDrawPrimitives2< xxx >::TDP2Data.
|
|
//
|
|
template< class TSuper, class TPDBE= CPalDBEntry, class TPDB= map< DWORD, TPDBE>,
|
|
class TDP2Data= CDP2DataWrap<> >
|
|
class CStdDP2PaletteManager
|
|
{
|
|
public: // Types
|
|
typedef TPDBE TPalDBEntry;
|
|
typedef TPDB TPalDB;
|
|
|
|
protected: // Variables
|
|
TPalDB m_PalDB;
|
|
|
|
protected: // Functions
|
|
CStdDP2PaletteManager()
|
|
{ }
|
|
~CStdDP2PaletteManager()
|
|
{ }
|
|
|
|
public: // Functions
|
|
void UpdatePalette( const D3DHAL_DP2UPDATEPALETTE* pParam)
|
|
{
|
|
typename TPalDB::iterator itPal(
|
|
m_PalDB.find( pParam->dwPaletteHandle));
|
|
|
|
if( m_PalDB.end()== itPal)
|
|
itPal= m_PalDB.insert( TPalDB::value_type( pParam->dwPaletteHandle,
|
|
TPalDBEntry())).first;
|
|
|
|
const DWORD* pEStart= reinterpret_cast< const DWORD*>( pParam+ 1);
|
|
itPal->second.Update( pParam->wStartIndex, pEStart,
|
|
pEStart+ pParam->wNumEntries);
|
|
}
|
|
void SetPalette( const D3DHAL_DP2SETPALETTE* pParam)
|
|
{
|
|
TSuper* pSThis= static_cast< TSuper*>( this);
|
|
typedef typename TSuper::TPerDDrawData TPerDDrawData;
|
|
typename TPerDDrawData::TSurfDBEntry* pSurfDBEntry=
|
|
pSThis->GetPerDDrawData().GetSurfDBEntry( pParam->dwSurfaceHandle);
|
|
assert( NULL!= pSurfDBEntry);
|
|
|
|
if( 0== pParam->dwPaletteHandle)
|
|
{
|
|
// Disassociate the surface with any palette.
|
|
pSurfDBEntry->SetPalette( NULL);
|
|
}
|
|
else
|
|
{
|
|
typename TPalDB::iterator itPal(
|
|
m_PalDB.find( pParam->dwPaletteHandle));
|
|
|
|
if( m_PalDB.end()== itPal)
|
|
itPal= m_PalDB.insert( TPalDB::value_type( pParam->dwPaletteHandle,
|
|
TPalDBEntry())).first;
|
|
|
|
itPal->second.SetFlags( pParam->dwPaletteFlags);
|
|
pSurfDBEntry->SetPalette( &itPal->second);
|
|
}
|
|
}
|
|
HRESULT DP2SetPalette( TDP2Data& DP2Data,
|
|
const D3DHAL_DP2COMMAND* pCmd, const void* pP)
|
|
{
|
|
TSuper* pSThis= static_cast<TSuper*>(this);
|
|
const D3DHAL_DP2SETPALETTE* pParam=
|
|
reinterpret_cast<const D3DHAL_DP2SETPALETTE*>(pP);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
try
|
|
{
|
|
if( wStateCount!= 0) do
|
|
{
|
|
pSThis->SetPalette( pParam);
|
|
++pParam;
|
|
} while( --wStateCount);
|
|
} catch ( bad_alloc ba)
|
|
{ return E_OUTOFMEMORY; }
|
|
|
|
return DD_OK;
|
|
}
|
|
HRESULT DP2UpdatePalette( TDP2Data& DP2Data,
|
|
const D3DHAL_DP2COMMAND* pCmd, const void* pP)
|
|
{
|
|
TSuper* pSThis= static_cast<TSuper*>(this);
|
|
const D3DHAL_DP2UPDATEPALETTE* pParam=
|
|
reinterpret_cast<const D3DHAL_DP2UPDATEPALETTE*>(pP);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
try
|
|
{
|
|
if( wStateCount!= 0)
|
|
pSThis->UpdatePalette( pParam);
|
|
} catch ( bad_alloc ba)
|
|
{ return E_OUTOFMEMORY; }
|
|
|
|
return DD_OK;
|
|
}
|
|
};
|
|
|
|
class CLightDBEntry:
|
|
public D3DLIGHT8
|
|
{
|
|
protected: // Variables
|
|
bool m_bEnabled;
|
|
|
|
public: // Functions
|
|
CLightDBEntry()
|
|
: m_bEnabled( false)
|
|
{
|
|
// Default light settings:
|
|
Type= D3DLIGHT_DIRECTIONAL;
|
|
Diffuse.r= 1.0f; Diffuse.g= 1.0f; Diffuse.b= 1.0f; Diffuse.a= 0.0f;
|
|
Specular.r= 0.0f; Specular.g= 0.0f; Specular.b= 0.0f; Specular.a= 0.0f;
|
|
Ambient.r= 0.0f; Ambient.g= 0.0f; Ambient.b= 0.0f; Ambient.a= 0.0f;
|
|
Position.x= 0.0f; Position.y= 0.0f; Position.z= 0.0f;
|
|
Direction.x= 0.0f; Direction.y= 0.0f; Direction.z= 1.0f;
|
|
Range= 0.0f;
|
|
Falloff= 0.0f;
|
|
Attenuation0= 0.0f;
|
|
Attenuation1= 0.0f;
|
|
Attenuation2= 0.0f;
|
|
Theta= 0.0f;
|
|
Phi= 0.0f;
|
|
}
|
|
operator const D3DLIGHT8&() const
|
|
{ return *static_cast< const D3DLIGHT8*>( this); }
|
|
CLightDBEntry& operator=( const D3DLIGHT8& Other)
|
|
{
|
|
*static_cast< D3DLIGHT8*>( this)= Other;
|
|
return *this;
|
|
}
|
|
void SetEnabled( bool bEn)
|
|
{ m_bEnabled= bEn; }
|
|
bool GetEnabled() const
|
|
{ return m_bEnabled; }
|
|
};
|
|
|
|
//
|
|
// <Template Parameters>
|
|
// TSuper: Standard parent type which is inheriting from this child class.
|
|
// In this case, it should typically be the CMyContext type.
|
|
// TLDBE: This is the light database entry type, or whatever is associated
|
|
// with a light. This type is typically, CLightDBEntry or something
|
|
// derived from it or convertable to D3DLIGHT8, at least.
|
|
// TLDB: This can be any Unique, Pair Associative Container, typically a map,
|
|
// which associates a DWORD light id to a light type.
|
|
// TDP2Data: This is some kind of wrapper class for PORTABLE_DRAWPRIMITIVES2DATA
|
|
// The type is expected to inherit or emulate PORTABLE_DRAWPRIMITIVES2DATA's
|
|
// fields/ member variables, and should typically be consistent with
|
|
// CStdDrawPrimitives2< xxx >::TDP2Data.
|
|
//
|
|
template< class TSuper, class TLDBE= CLightDBEntry,
|
|
class TLDB= map< DWORD, TLDBE>, class TDP2Data= CDP2DataWrap<> >
|
|
class CStdDP2LightManager
|
|
{
|
|
public: // Types
|
|
typedef TLDBE TLightDBEntry;
|
|
typedef TLDB TLightDB;
|
|
|
|
protected: // Variables
|
|
TLightDB m_LightDB;
|
|
|
|
protected: // Functions
|
|
CStdDP2LightManager()
|
|
{ }
|
|
~CStdDP2LightManager()
|
|
{ }
|
|
|
|
public: // Functions
|
|
void CreateLight( DWORD dwId)
|
|
{
|
|
pair< typename TLightDB::iterator, bool> Ret= m_LightDB.insert(
|
|
typename TLightDB::value_type( dwId, TLightDBEntry()));
|
|
}
|
|
void EnableLight( DWORD dwId, bool bEnable)
|
|
{
|
|
typename TLightDB::iterator itLight( m_LightDB.find( dwId));
|
|
assert( itLight!= m_LightDB.end());
|
|
|
|
itLight->second.SetEnabled( bEnable);
|
|
}
|
|
void UpdateLight( DWORD dwId, const D3DLIGHT8& LightValue)
|
|
{
|
|
typename TLightDB::iterator itLight( m_LightDB.find( dwId));
|
|
assert( itLight!= m_LightDB.end());
|
|
|
|
itLight->second= LightValue;
|
|
}
|
|
HRESULT DP2CreateLight( TDP2Data& DP2Data,
|
|
const D3DHAL_DP2COMMAND* pCmd, const void* pP)
|
|
{
|
|
TSuper* pSThis= static_cast< TSuper*>( this);
|
|
const D3DHAL_DP2CREATELIGHT* pParam=
|
|
reinterpret_cast< const D3DHAL_DP2CREATELIGHT*>( pP);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
try
|
|
{
|
|
if( wStateCount!= 0) do
|
|
{
|
|
pSThis->CreateLight( pParam->dwIndex);
|
|
++pParam;
|
|
} while( --wStateCount);
|
|
} catch ( bad_alloc ba)
|
|
{ return E_OUTOFMEMORY; }
|
|
|
|
return D3D_OK;
|
|
}
|
|
HRESULT DP2SetLight( TDP2Data& DP2Data,
|
|
const D3DHAL_DP2COMMAND* pCmd, const void* pP)
|
|
{
|
|
TSuper* pSThis= static_cast< TSuper*>( this);
|
|
const D3DHAL_DP2SETLIGHT* pParam=
|
|
reinterpret_cast< const D3DHAL_DP2SETLIGHT*>( pP);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
try
|
|
{
|
|
if( wStateCount!= 0) do
|
|
{
|
|
if( m_LightDB.end()== m_LightDB.find( pParam->dwIndex))
|
|
{
|
|
const bool SetLight_without_succeeded_CreateLight( false);
|
|
assert( SetLight_without_succeeded_CreateLight);
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
bool bEnable( false);
|
|
switch( pParam->dwDataType)
|
|
{
|
|
case( D3DHAL_SETLIGHT_DATA):
|
|
const D3DLIGHT8* pL= reinterpret_cast< const D3DLIGHT8*>(
|
|
pParam+ 1);
|
|
pSThis->UpdateLight( pParam->dwIndex, *pL);
|
|
pParam= reinterpret_cast< const D3DHAL_DP2SETLIGHT*>(
|
|
pL+ 1);
|
|
break;
|
|
|
|
case( D3DHAL_SETLIGHT_ENABLE):
|
|
bEnable= true; // Fall-through.
|
|
case( D3DHAL_SETLIGHT_DISABLE):
|
|
pSThis->EnableLight( pParam->dwIndex, bEnable);
|
|
++pParam;
|
|
break;
|
|
|
|
default: {
|
|
const bool Unrecognized_D3DHAL_SETLIGHT_data_type( false);
|
|
assert( Unrecognized_D3DHAL_SETLIGHT_data_type);
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
} while( --wStateCount);
|
|
} catch ( bad_alloc ba)
|
|
{ return E_OUTOFMEMORY; }
|
|
|
|
return D3D_OK;
|
|
}
|
|
HRESULT RecDP2CreateLight( const D3DHAL_DP2COMMAND* pCmd, void* pP)
|
|
{
|
|
D3DHAL_DP2CREATELIGHT* pParam=
|
|
reinterpret_cast< D3DHAL_DP2CREATELIGHT*>( pP);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
// Special case here, the default state set capturing, will ask how
|
|
// many active lights are needed to be recorded, and their id's. In
|
|
// order to support the default state set, we must process this
|
|
// specially.
|
|
if( 0== pCmd->bCommand)
|
|
{
|
|
// Now, we're either being asked how many lights or what their
|
|
// id's are.
|
|
if( 0== wStateCount)
|
|
pParam->dwIndex= m_LightDB.size();
|
|
else
|
|
{
|
|
assert( m_LightDB.size()== wStateCount);
|
|
typename TLightDB::const_iterator itCur( m_LightDB.begin());
|
|
do
|
|
{
|
|
pParam->dwIndex= itCur.first;
|
|
++pParam;
|
|
++itCur;
|
|
} while( --wStateCount!= 0);
|
|
}
|
|
return D3D_OK;
|
|
}
|
|
|
|
// Otherwise, recording creation is easy,
|
|
// leave the command buffer as is.
|
|
return D3D_OK;
|
|
}
|
|
HRESULT RecDP2SetLight( const D3DHAL_DP2COMMAND* pCmd, void* pP)
|
|
{
|
|
D3DHAL_DP2SETLIGHT* pParam=
|
|
reinterpret_cast< D3DHAL_DP2SETLIGHT*>( pP);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
const typename TLightDB::const_iterator itEnd( m_LightDB.end());
|
|
typename TLightDB::const_iterator itLight( itEnd);
|
|
if( wStateCount!= 0) do
|
|
{
|
|
if( itLight!= itEnd&& itLight->first!= pParam->dwIndex)
|
|
itLight= m_LightDB.find( pParam->dwIndex);
|
|
assert( itLight!= itEnd);
|
|
|
|
switch( pParam->dwDataType)
|
|
{
|
|
case( D3DHAL_SETLIGHT_DATA):
|
|
D3DLIGHT8* pL= reinterpret_cast< D3DLIGHT8*>( pParam+ 1);
|
|
*pL= itLight->second;
|
|
pParam= reinterpret_cast< D3DHAL_DP2SETLIGHT*>( pL+ 1);
|
|
break;
|
|
|
|
case( D3DHAL_SETLIGHT_ENABLE):
|
|
case( D3DHAL_SETLIGHT_DISABLE):
|
|
pParam->dwDataType= ( itLight->second.GetEnabled()?
|
|
D3DHAL_SETLIGHT_ENABLE: D3DHAL_SETLIGHT_DISABLE);
|
|
++pParam;
|
|
break;
|
|
|
|
default: {
|
|
const bool Unrecognized_D3DHAL_SETLIGHT_data_type( false);
|
|
assert( Unrecognized_D3DHAL_SETLIGHT_data_type);
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
} while( --wStateCount!= 0);
|
|
|
|
return D3D_OK;
|
|
}
|
|
};
|
|
|
|
template< class TS, class TSDBE>
|
|
class CRTarget
|
|
{
|
|
public: // Types
|
|
typedef TS TSurface;
|
|
typedef TSDBE TSurfDBEntry;
|
|
enum EMemLocation
|
|
{
|
|
None,
|
|
Video
|
|
};
|
|
|
|
protected: // Variables
|
|
DWORD m_dwHandle;
|
|
TSurface m_Surface;
|
|
TSurfDBEntry m_SurfDBEntry;
|
|
EMemLocation m_eMemLocation;
|
|
|
|
public: // Functions
|
|
CRTarget(): m_eMemLocation( None)
|
|
{ }
|
|
// Video Memory representation constructor.
|
|
CRTarget( DWORD dwHandle, const TSurface& Surface,
|
|
const TSurfDBEntry& SurfDBEntry): m_dwHandle( dwHandle),
|
|
m_Surface( Surface), m_SurfDBEntry( SurfDBEntry), m_eMemLocation( Video)
|
|
{ }
|
|
~CRTarget()
|
|
{ }
|
|
|
|
bool operator==( const CRTarget& Other) const
|
|
{
|
|
const EMemLocation MemLocation( GetMemLocation());
|
|
return MemLocation== Other.GetMemLocation()&&
|
|
(None== MemLocation|| GetHandle()== Other.GetHandle());
|
|
}
|
|
bool operator!=( const CRTarget& Other) const
|
|
{ return !(*this== Other); }
|
|
|
|
DWORD GetHandle() const
|
|
{
|
|
assert( GetMemLocation()!= None);
|
|
return m_dwHandle;
|
|
}
|
|
TSurface& GetVidMemRepresentation()
|
|
{
|
|
assert( GetMemLocation()== Video);
|
|
return m_Surface;
|
|
}
|
|
const TSurface& GetVidMemRepresentation() const
|
|
{
|
|
assert( GetMemLocation()== Video);
|
|
return m_Surface;
|
|
}
|
|
TSurfDBEntry& GetSurfDBRepresentation()
|
|
{
|
|
assert( GetMemLocation()== Video);
|
|
return m_SurfDBEntry;
|
|
}
|
|
const TSurfDBEntry& GetSurfDBRepresentation() const
|
|
{
|
|
assert( GetMemLocation()== Video);
|
|
return m_SurfDBEntry;
|
|
}
|
|
EMemLocation GetMemLocation() const
|
|
{ return m_eMemLocation; }
|
|
void Clear( const D3DHAL_DP2CLEAR& DP2Clear, const RECT& Rect)
|
|
{
|
|
if( GetMemLocation()!= None)
|
|
GetVidMemRepresentation()->Clear( DP2Clear, Rect);
|
|
}
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CSubContext
|
|
//
|
|
// This provides a base implementation for a context. It provides
|
|
// implementations for dealing with the SetRenderTarget and Clear
|
|
// DrawPrimitive2 commands; and also a minimal implementation for
|
|
// GetDriverState.
|
|
//
|
|
// <Template Parameters>
|
|
// TSuper: Standard parent type which is inheriting from this child class.
|
|
// In this case, it should typically be the CMyContext type.
|
|
// TPDDD: The PerDDrawData type, typically CMyPerDDrawData or
|
|
// CMinimalPerDDrawData<>.
|
|
// TDP2Data: This is some kind of wrapper class for PORTABLE_DRAWPRIMITIVES2DATA
|
|
// The type is expected to inherit or emulate PORTABLE_DRAWPRIMITIVES2DATA's
|
|
// fields/ member variables, and should typically be consistent with
|
|
// CStdDrawPrimitives2< xxx >::TDP2Data.
|
|
//
|
|
// <Exposed Types>
|
|
// TPerDDrawData: The PerDDrawData type, passed in as the template parameter,
|
|
// TPDDD.
|
|
// TDriver: This is equal to TPerDDrawData::TDriver. This type is exposed
|
|
// only as a convience to the implementation to get at TDriver::TSurface.
|
|
// TSurface: This is equal to TDriver::TSurface. This type is exposed only
|
|
// as a convience to the implementation.
|
|
//
|
|
// <Exposed Functions>
|
|
// CSubContext( TPerDDrawData&, TSurface*, TSurface*, DWORD): Constructor,
|
|
// a typical SDDI Context isnt' expected to be created without this data.
|
|
// ~CSubContext(): Standard destructor.
|
|
// TPerDDrawData& GetPerDDrawData() const: Trivial accessor function to get at
|
|
// the PerDDrawData.
|
|
// TSurface* GetRTarget() const: Trivial accessor function to get at the
|
|
// current render target.
|
|
// TSurface* GetZBuffer() const: Trivial accessor function to get at the
|
|
// current z/ stencil buffer.
|
|
// HRESULT DP2SetRenderTarget( TDP2Data&, const D3DHAL_DP2COMMAND*, const void*):
|
|
// The default DP2 command processing member function for
|
|
// D3DDP2OP_SETRENDERTARGET.
|
|
// void NewRenderTarget( TSurface*, TSurface*) const: Notification mechanism
|
|
// called just before new render targets are saved into the member
|
|
// variables. This notification mechanism is called by DP2SetRenderTarget.
|
|
// HRESULT DP2Clear( TDP2Data&, const D3DHAL_DP2COMMAND*, const void*):
|
|
// The default DP2 command processing member function for D3DDP2OP_CLEAR.
|
|
// This function relies on TSurface having a member function Clear.
|
|
// HRESULT GetDriverState( DDHAL_GETDRIVERSTATEDATA&): A minimal implementation
|
|
// of GetDriverState, which should return S_FALSE if the id isn't
|
|
// understood. This function should be overriden to add understanding for
|
|
// custom ids.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
template< class TSuper, class TPDDD,
|
|
class TRT= CRTarget< TPDDD::TDriver::TSurface*, TPDDD::TSurfDBEntry*>,
|
|
class TDP2Data= CDP2DataWrap<> >
|
|
class CSubContext
|
|
{
|
|
public: // Types
|
|
typedef TPDDD TPerDDrawData;
|
|
typedef TRT TRTarget;
|
|
|
|
protected: // Variables
|
|
TPerDDrawData& m_PerDDrawData;
|
|
TRTarget m_ColorBuffer;
|
|
TRTarget m_DepthBuffer;
|
|
|
|
protected: // Functions
|
|
void NewColorBuffer() const
|
|
{
|
|
// Override this notification mechanism to provide color buffer
|
|
// state managing.
|
|
}
|
|
void NewDepthBuffer() const
|
|
{
|
|
// Override this notification mechanism to provide depth buffer
|
|
// state managing.
|
|
}
|
|
|
|
CSubContext( TPerDDrawData& PerDDrawData, PORTABLE_CONTEXTCREATEDATA& ccd):
|
|
m_PerDDrawData( PerDDrawData)
|
|
{
|
|
// To set the render targets, we must convert the structures to our
|
|
// SurfDBEntry representation.
|
|
typename TPerDDrawData::TDriver& Driver= PerDDrawData.GetDriver();
|
|
|
|
if( ccd.lpDDSLcl()!= NULL)
|
|
{
|
|
typename TPerDDrawData::TDriver::TSurface* pSurface=
|
|
Driver.GetSurface( *ccd.lpDDSLcl());
|
|
if( pSurface!= NULL)
|
|
{
|
|
const DWORD dwHandle(
|
|
ccd.lpDDSLcl()->lpSurfMore()->dwSurfaceHandle());
|
|
|
|
m_ColorBuffer= TRTarget( dwHandle, pSurface,
|
|
PerDDrawData.GetSurfDBEntry( dwHandle));
|
|
}
|
|
}
|
|
if( ccd.lpDDSZLcl()!= NULL)
|
|
{
|
|
typename TPerDDrawData::TDriver::TSurface* pSurface=
|
|
Driver.GetSurface( *ccd.lpDDSZLcl());
|
|
if( pSurface!= NULL)
|
|
{
|
|
const DWORD dwHandle(
|
|
ccd.lpDDSZLcl()->lpSurfMore()->dwSurfaceHandle());
|
|
|
|
m_DepthBuffer= TRTarget( dwHandle, pSurface,
|
|
PerDDrawData.GetSurfDBEntry( dwHandle));
|
|
}
|
|
}
|
|
}
|
|
~CSubContext()
|
|
{ }
|
|
|
|
public: // Functions
|
|
TPerDDrawData& GetPerDDrawData() const { return m_PerDDrawData; }
|
|
const TRTarget& GetColorBuffer() const { return m_ColorBuffer; }
|
|
TRTarget& GetColorBuffer() { return m_ColorBuffer; }
|
|
const TRTarget& GetDepthBuffer() const { return m_DepthBuffer; }
|
|
TRTarget& GetDepthBuffer() { return m_DepthBuffer; }
|
|
|
|
HRESULT DP2SetRenderTarget( TDP2Data& DP2Data, const D3DHAL_DP2COMMAND*
|
|
pCmd, const void* pP)
|
|
{
|
|
const D3DHAL_DP2SETRENDERTARGET* pParam=
|
|
reinterpret_cast< const D3DHAL_DP2SETRENDERTARGET*>( pP);
|
|
TSuper* pSThis= static_cast< TSuper*>( this);
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
|
|
if( wStateCount!= 0)
|
|
{
|
|
TPerDDrawData& PerDDrawData= GetPerDDrawData();
|
|
typename TPerDDrawData::TDriver& Driver= PerDDrawData.GetDriver();
|
|
|
|
do
|
|
{
|
|
// To set the render targets, we must convert the handles to our
|
|
// SurfDBEntry representation.
|
|
typename TPerDDrawData::TSurfDBEntry* pSurfDBEntry=
|
|
PerDDrawData.GetSurfDBEntry( pParam->hRenderTarget);
|
|
if( pSurfDBEntry!= NULL)
|
|
{
|
|
// We can immediately convert the SurfDBEntry representation to our
|
|
// Video Memory object, because Render Targets MUST be VM.
|
|
typename TPerDDrawData::TDriver::TSurface* pSurface=
|
|
Driver.GetSurface( *pSurfDBEntry);
|
|
if( pSurface!= NULL)
|
|
{
|
|
m_ColorBuffer= TRTarget( pParam->hRenderTarget,
|
|
pSurface, pSurfDBEntry);
|
|
pSThis->NewColorBuffer();
|
|
}
|
|
}
|
|
|
|
pSurfDBEntry= PerDDrawData.GetSurfDBEntry( pParam->hZBuffer);
|
|
if( pSurfDBEntry!= NULL)
|
|
{
|
|
// We can immediately convert the SurfDBEntry representation to our
|
|
// Video Memory object, because Render Targets MUST be VM.
|
|
typename TPerDDrawData::TDriver::TSurface* pSurface=
|
|
Driver.GetSurface( *pSurfDBEntry);
|
|
if( pSurface!= NULL)
|
|
{
|
|
m_DepthBuffer= TRTarget( pParam->hZBuffer,
|
|
pSurface, pSurfDBEntry);
|
|
pSThis->NewDepthBuffer();
|
|
}
|
|
}
|
|
} while( --wStateCount!= 0);
|
|
}
|
|
return DD_OK;
|
|
}
|
|
HRESULT DP2Clear( TDP2Data& DP2Data, const D3DHAL_DP2COMMAND* pCmd,
|
|
const void* pP)
|
|
{
|
|
const D3DHAL_DP2CLEAR* pParam= reinterpret_cast< const D3DHAL_DP2CLEAR*>
|
|
( pP);
|
|
|
|
TSuper* pSThis= static_cast< TSuper*>( this);
|
|
const D3DHAL_DP2VIEWPORTINFO CurViewport( *pSThis);
|
|
RECT ViewportRect;
|
|
ViewportRect.left= CurViewport.dwX;
|
|
ViewportRect.top= CurViewport.dwY;
|
|
ViewportRect.right= CurViewport.dwX+ CurViewport.dwWidth;
|
|
ViewportRect.bottom= CurViewport.dwY+ CurViewport.dwHeight;
|
|
|
|
TRTarget& ColorBuffer= GetColorBuffer();
|
|
TRTarget& DepthBuffer= GetDepthBuffer();
|
|
const bool bClearBoth(!(ColorBuffer== DepthBuffer));
|
|
|
|
if( 0== pCmd->wStateCount)
|
|
{
|
|
if( TRTarget::EMemLocation::None!= ColorBuffer.GetMemLocation())
|
|
ColorBuffer.Clear( *pParam, ViewportRect);
|
|
if( TRTarget::EMemLocation::None!= DepthBuffer.GetMemLocation()&&
|
|
bClearBoth)
|
|
DepthBuffer.Clear( *pParam, ViewportRect);
|
|
}
|
|
else
|
|
{
|
|
WORD wStateCount( pCmd->wStateCount);
|
|
const RECT* pRect= pParam->Rects;
|
|
|
|
if((pParam->dwFlags& D3DCLEAR_COMPUTERECTS)!= 0)
|
|
{
|
|
// Clip rect to viewport.
|
|
RECT rcClipped( *pRect);
|
|
do
|
|
{
|
|
clamp_min( rcClipped.left, ViewportRect.left);
|
|
clamp_min( rcClipped.top, ViewportRect.top);
|
|
clamp( rcClipped.right, rcClipped.left, ViewportRect.right);
|
|
clamp( rcClipped.bottom, rcClipped.top, ViewportRect.bottom);
|
|
|
|
if( TRTarget::EMemLocation::None!=
|
|
ColorBuffer.GetMemLocation())
|
|
ColorBuffer.Clear( *pParam, rcClipped);
|
|
if( TRTarget::EMemLocation::None!=
|
|
DepthBuffer.GetMemLocation()&& bClearBoth)
|
|
DepthBuffer.Clear( *pParam, rcClipped);
|
|
pRect++;
|
|
} while( --wStateCount);
|
|
}
|
|
else
|
|
{
|
|
do
|
|
{
|
|
if( TRTarget::EMemLocation::None!=
|
|
ColorBuffer.GetMemLocation())
|
|
ColorBuffer.Clear( *pParam, *pRect);
|
|
if( TRTarget::EMemLocation::None!=
|
|
DepthBuffer.GetMemLocation()&& bClearBoth)
|
|
DepthBuffer.Clear( *pParam, *pRect);
|
|
pRect++;
|
|
} while( --wStateCount);
|
|
}
|
|
}
|
|
return DD_OK;
|
|
}
|
|
|
|
// A minimal implementation of GetDriverState, which should return S_FALSE
|
|
// if the id isn't understood. Override this function to add understanding.
|
|
HRESULT GetDriverState( DDHAL_GETDRIVERSTATEDATA& gdsd)
|
|
{ return S_FALSE; }
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CMinimalContext
|
|
//
|
|
// This class contains a minimal implementation of a Context for a driver,
|
|
// which supports only one stream, no TnL, and legacy pixel shading. This
|
|
// Context still needs an implementation of the primitive drawing functions,
|
|
// which it uses a Rasterizer class for. CMinimalContext takes care of most
|
|
// of the responsibilities of a SDDI driver, except rasterization.
|
|
//
|
|
// <Template Parameters>
|
|
// TPDDD: The PerDDrawData type, typically CMyPerDDrawData or
|
|
// CMinimalPerDDrawData<>.
|
|
// TR: The Rasterizer type, typically CMyRasterizer.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
template< class TPDDD, class TR>
|
|
class CMinimalContext:
|
|
public CSubContext< CMinimalContext< TPDDD, TR>, TPDDD>,
|
|
public CStdDrawPrimitives2< CMinimalContext< TPDDD, TR> >,
|
|
public CStdDP2ViewportInfoStore< CMinimalContext< TPDDD, TR> >,
|
|
public CStdDP2WInfoStore< CMinimalContext< TPDDD, TR> >,
|
|
public CStdDP2RenderStateStore< CMinimalContext< TPDDD, TR> >,
|
|
public CStdDP2TextureStageStateStore< CMinimalContext< TPDDD, TR> >,
|
|
public CStdDP2SetVertexShaderStore< CMinimalContext< TPDDD, TR> >,
|
|
public CStdDP2VStreamManager< CMinimalContext< TPDDD, TR> >,
|
|
public CStdDP2IStreamManager< CMinimalContext< TPDDD, TR> >
|
|
{
|
|
public: // Types
|
|
typedef TPDDD TPerDDrawData;
|
|
typedef TR TRasterizer;
|
|
typedef block< TDP2CmdBind, 15> TDP2Bindings;
|
|
typedef block< TRecDP2CmdBind, 7> TRecDP2Bindings;
|
|
|
|
protected: // Variables
|
|
TRasterizer m_Rasterizer;
|
|
static const TDP2Bindings c_DP2Bindings;
|
|
static const TRecDP2Bindings c_RecDP2Bindings;
|
|
|
|
public: // Functions
|
|
CMinimalContext( TPerDDrawData& PDDD, PORTABLE_CONTEXTCREATEDATA& ccd)
|
|
: CSubContext< CMinimalContext< TPDDD, TR>, TPDDD>( PDDD, ccd),
|
|
CStdDrawPrimitives2< CMinimalContext< TPDDD, TR>>(
|
|
c_DP2Bindings.begin(), c_DP2Bindings.end(),
|
|
c_RecDP2Bindings.begin(), c_RecDP2Bindings.end())
|
|
{
|
|
// These keep the arrays in sync with their typedef.
|
|
assert( D3DDP2OP_CLIPPEDTRIANGLEFAN== *c_DP2Bindings.rbegin());
|
|
assert( D3DDP2OP_SETINDICES== *c_RecDP2Bindings.rbegin());
|
|
}
|
|
~CMinimalContext() { }
|
|
|
|
// Provide this function to ease minimal implementations.
|
|
HRESULT ValidateTextureStageState( const D3DHAL_VALIDATETEXTURESTAGESTATEDATA&
|
|
vsssd) const
|
|
{ return DD_OK; }
|
|
|
|
HRESULT DP2DrawPrimitive( TDP2Data& DP2Data,
|
|
const D3DHAL_DP2COMMAND* pCmd, const void* pP)
|
|
{
|
|
const D3DHAL_DP2DRAWPRIMITIVE* pParam= reinterpret_cast<
|
|
const D3DHAL_DP2DRAWPRIMITIVE*>(pP);
|
|
return m_Rasterizer.DrawPrimitive( *this, *pCmd, pParam);
|
|
}
|
|
HRESULT DP2DrawPrimitive2( TDP2Data& DP2Data,
|
|
const D3DHAL_DP2COMMAND* pCmd, const void* pP)
|
|
{
|
|
const D3DHAL_DP2DRAWPRIMITIVE2* pParam= reinterpret_cast<
|
|
const D3DHAL_DP2DRAWPRIMITIVE2*>(pP);
|
|
return m_Rasterizer.DrawPrimitive2( *this, *pCmd, pParam);
|
|
}
|
|
HRESULT DP2DrawIndexedPrimitive( TDP2Data& DP2Data,
|
|
const D3DHAL_DP2COMMAND* pCmd, const void* pP)
|
|
{
|
|
const D3DHAL_DP2DRAWINDEXEDPRIMITIVE* pParam= reinterpret_cast<
|
|
const D3DHAL_DP2DRAWINDEXEDPRIMITIVE*>(pP);
|
|
return m_Rasterizer.DrawIndexedPrimitive( *this, *pCmd, pParam);
|
|
}
|
|
HRESULT DP2DrawIndexedPrimitive2( TDP2Data& DP2Data,
|
|
const D3DHAL_DP2COMMAND* pCmd, const void* pP)
|
|
{
|
|
const D3DHAL_DP2DRAWINDEXEDPRIMITIVE2* pParam= reinterpret_cast<
|
|
const D3DHAL_DP2DRAWINDEXEDPRIMITIVE2*>(pP);
|
|
return m_Rasterizer.DrawIndexedPrimitive2( *this, *pCmd, pParam);
|
|
}
|
|
HRESULT DP2ClippedTriangleFan( TDP2Data& DP2Data,
|
|
const D3DHAL_DP2COMMAND* pCmd, const void* pP)
|
|
{
|
|
const D3DHAL_CLIPPEDTRIANGLEFAN* pParam= reinterpret_cast<
|
|
const D3DHAL_CLIPPEDTRIANGLEFAN*>(pP);
|
|
return m_Rasterizer.ClippedTriangleFan( *this, *pCmd, pParam);
|
|
}
|
|
};
|
|
|
|
// These tables require TConstDP2Bindings to be changed also, with the number
|
|
// of bindings.
|
|
template< class TPDDD, class TR>
|
|
const CMinimalContext< TPDDD, TR>::TDP2Bindings
|
|
CMinimalContext< TPDDD, TR>::c_DP2Bindings=
|
|
{
|
|
D3DDP2OP_VIEWPORTINFO, DP2ViewportInfo,
|
|
D3DDP2OP_WINFO, DP2WInfo,
|
|
D3DDP2OP_RENDERSTATE, DP2RenderState,
|
|
D3DDP2OP_TEXTURESTAGESTATE, DP2TextureStageState,
|
|
D3DDP2OP_CLEAR, DP2Clear,
|
|
D3DDP2OP_SETRENDERTARGET, DP2SetRenderTarget,
|
|
D3DDP2OP_SETVERTEXSHADER, DP2SetVertexShader,
|
|
D3DDP2OP_SETSTREAMSOURCE, DP2SetStreamSource,
|
|
D3DDP2OP_SETSTREAMSOURCEUM, DP2SetStreamSourceUM,
|
|
D3DDP2OP_SETINDICES, DP2SetIndices,
|
|
D3DDP2OP_DRAWPRIMITIVE, DP2DrawPrimitive,
|
|
D3DDP2OP_DRAWPRIMITIVE2, DP2DrawPrimitive2,
|
|
D3DDP2OP_DRAWINDEXEDPRIMITIVE, DP2DrawIndexedPrimitive,
|
|
D3DDP2OP_DRAWINDEXEDPRIMITIVE2, DP2DrawIndexedPrimitive2,
|
|
D3DDP2OP_CLIPPEDTRIANGLEFAN, DP2ClippedTriangleFan
|
|
};
|
|
|
|
// These tables require TConstRecDP2Bindings to be changed also, with the number
|
|
// of bindings.
|
|
template< class TPDDD, class TR>
|
|
const CMinimalContext< TPDDD, TR>::TRecDP2Bindings
|
|
CMinimalContext< TPDDD, TR>::c_RecDP2Bindings=
|
|
{
|
|
D3DDP2OP_VIEWPORTINFO, RecDP2ViewportInfo,
|
|
D3DDP2OP_WINFO, RecDP2WInfo,
|
|
D3DDP2OP_RENDERSTATE, RecDP2RenderState,
|
|
D3DDP2OP_TEXTURESTAGESTATE, RecDP2TextureStageState,
|
|
D3DDP2OP_SETVERTEXSHADER, RecDP2SetVertexShader,
|
|
D3DDP2OP_SETSTREAMSOURCE, RecDP2SetStreamSource,
|
|
D3DDP2OP_SETINDICES, RecDP2SetIndices
|
|
};
|
|
|
|
class IVidMemSurface
|
|
{
|
|
protected: // Variables
|
|
DWORD m_dwHandle;
|
|
|
|
protected: // Functions
|
|
IVidMemSurface( DWORD dwHandle) : m_dwHandle( dwHandle) { }
|
|
|
|
public: // Functions
|
|
DWORD GetHandle() const
|
|
{ return m_dwHandle; }
|
|
virtual ~IVidMemSurface()
|
|
{ }
|
|
virtual void* Lock( DWORD dwFlags, const RECTL* pRect)= 0;
|
|
virtual void Unlock( void)= 0;
|
|
virtual void Clear( const D3DHAL_DP2CLEAR& DP2Clear, const RECT& RC)= 0;
|
|
};
|
|
|
|
struct SD3DDataConv
|
|
{
|
|
// A( 0), R( 1), G( 2), B( 3), Z( 4), S( 5)
|
|
typedef block< DWORD, 6> TMasks;
|
|
// A( 0), R( 1), G( 2), B( 3), Z( 4), ZBits( 5), S( 6), SBits( 7)
|
|
typedef block< signed char, 8> TD3DBitShftRgt;
|
|
TMasks m_ToSurfMasks;
|
|
TD3DBitShftRgt m_D3DBitShftRgt;
|
|
|
|
SD3DDataConv()
|
|
{
|
|
fill( m_ToSurfMasks.begin(), m_ToSurfMasks.end(),
|
|
static_cast< TMasks::value_type>( 0));
|
|
fill( m_D3DBitShftRgt.begin(), m_D3DBitShftRgt.end(),
|
|
static_cast< TD3DBitShftRgt::value_type>( 0));
|
|
}
|
|
SD3DDataConv( const DDPIXELFORMAT& PF)
|
|
{ (*this)= PF; }
|
|
SD3DDataConv& operator=( const DDPIXELFORMAT& PF)
|
|
{
|
|
const block< signed char, 4> D3DHighBitPos= {31,23,15,7};
|
|
|
|
fill( m_ToSurfMasks.begin(), m_ToSurfMasks.end(),
|
|
static_cast< TMasks::value_type>( 0));
|
|
fill( m_D3DBitShftRgt.begin(), m_D3DBitShftRgt.end(),
|
|
static_cast< TD3DBitShftRgt::value_type>( 0));
|
|
|
|
// Alpha
|
|
if((PF.dwFlags& DDPF_ALPHA)!= 0)
|
|
{
|
|
assert( PF.dwAlphaBitDepth< 32);
|
|
m_ToSurfMasks[ 0]= (0x1<< PF.dwAlphaBitDepth)- 1;
|
|
}
|
|
else if((PF.dwFlags& DDPF_ALPHAPIXELS)!= 0)
|
|
m_ToSurfMasks[ 0]= PF.dwRGBAlphaBitMask;
|
|
|
|
// RGB Color
|
|
if((PF.dwFlags& DDPF_RGB)!= 0)
|
|
{
|
|
m_ToSurfMasks[ 1]= PF.dwRBitMask;
|
|
m_ToSurfMasks[ 2]= PF.dwGBitMask;
|
|
m_ToSurfMasks[ 3]= PF.dwBBitMask;
|
|
}
|
|
|
|
// Z
|
|
if((PF.dwFlags& DDPF_ZBUFFER)!= 0)
|
|
{
|
|
m_D3DBitShftRgt[ 5]= PF.dwZBufferBitDepth;
|
|
if( 32== PF.dwZBufferBitDepth)
|
|
m_ToSurfMasks[ 4]= 0xFFFFFFFF;
|
|
else
|
|
m_ToSurfMasks[ 4]= (0x1<< PF.dwZBufferBitDepth)- 1;
|
|
}
|
|
else if((PF.dwFlags& DDPF_ZPIXELS)!= 0)
|
|
{
|
|
DWORD dwZBitMask( PF.dwRGBZBitMask);
|
|
m_ToSurfMasks[ 5]= PF.dwRGBZBitMask;
|
|
|
|
while((dwZBitMask& 1)== 0)
|
|
{
|
|
m_D3DBitShftRgt[ 4]--;
|
|
dwZBitMask>>= 1;
|
|
}
|
|
|
|
while((dwZBitMask& 1)!= 0)
|
|
{
|
|
dwZBitMask>>= 1;
|
|
m_D3DBitShftRgt[ 5]++;
|
|
}
|
|
}
|
|
|
|
// Stensil
|
|
if((PF.dwFlags& DDPF_STENCILBUFFER)!= 0)
|
|
{
|
|
DWORD dwSBitMask( PF.dwStencilBitMask);
|
|
m_ToSurfMasks[ 6]= PF.dwStencilBitMask;
|
|
|
|
while((dwSBitMask& 1)== 0)
|
|
{
|
|
m_D3DBitShftRgt[ 6]--;
|
|
dwSBitMask>>= 1;
|
|
}
|
|
|
|
while((dwSBitMask& 1)!= 0)
|
|
{
|
|
dwSBitMask>>= 1;
|
|
m_D3DBitShftRgt[ 7]++;
|
|
}
|
|
}
|
|
|
|
block< signed char, 4>::const_iterator itD3DBitPos( D3DHighBitPos.begin());
|
|
TD3DBitShftRgt::iterator itBitShftRgt( m_D3DBitShftRgt.begin());
|
|
TMasks::const_iterator itToSurfMask( m_ToSurfMasks.begin());
|
|
|
|
while( itD3DBitPos!= D3DHighBitPos.end())
|
|
{
|
|
signed char iBitPos( 31);
|
|
TMasks::value_type dwMask( 0x80000000);
|
|
|
|
while((dwMask& *itToSurfMask)== 0 && iBitPos>= 0)
|
|
{
|
|
dwMask>>= 1;
|
|
iBitPos--;
|
|
}
|
|
|
|
*itBitShftRgt= ( iBitPos>= 0? *itD3DBitPos- iBitPos: 0);
|
|
|
|
++itD3DBitPos;
|
|
++itToSurfMask;
|
|
++itBitShftRgt;
|
|
}
|
|
return *this;
|
|
}
|
|
// SurfData, ValidMask
|
|
pair< UINT32, UINT32> ConvColor( D3DCOLOR D3DColor) const
|
|
{
|
|
pair< UINT32, UINT32> RetVal( 0, 0);
|
|
|
|
const block< DWORD, 4> FromD3DMasks= {0xFF000000,0xFF0000,0xFF00,0xFF};
|
|
|
|
TD3DBitShftRgt::const_iterator itBitShftRgt( m_D3DBitShftRgt.begin());
|
|
block< DWORD, 4>::const_iterator itFromMask( FromD3DMasks.begin());
|
|
TMasks::const_iterator itToMask( m_ToSurfMasks.begin());
|
|
while( itFromMask!= FromD3DMasks.end())
|
|
{
|
|
const UINT32 uiTmp( D3DColor& *itFromMask);
|
|
|
|
RetVal.first|= *itToMask& (*itBitShftRgt>= 0?
|
|
uiTmp>> *itBitShftRgt: uiTmp<< *itBitShftRgt);
|
|
RetVal.second|= *itToMask;
|
|
|
|
++itBitShftRgt;
|
|
++itToMask;
|
|
++itFromMask;
|
|
}
|
|
return RetVal;
|
|
}
|
|
// SurfData, ValidMask
|
|
pair< UINT32, UINT32> ConvZ( D3DVALUE D3DZ) const
|
|
{
|
|
CEnsureFPUModeForC FPUMode;
|
|
|
|
if( D3DZ> 1.0f)
|
|
D3DZ= 1.0f;
|
|
else if( D3DZ< 0.0f)
|
|
D3DZ= 0.0f;
|
|
|
|
pair< UINT32, UINT32> RetVal( 0, 0);
|
|
|
|
const UINT32 uiMaxZ( m_D3DBitShftRgt[ 5]== 32? 0xFFFFFFFF:
|
|
(0x1<< m_D3DBitShftRgt[ 5])- 1);
|
|
|
|
const UINT32 uiZVal( static_cast<UINT32>(
|
|
static_cast< DOUBLE>(D3DZ)* static_cast< DOUBLE>(uiMaxZ)+ 0.5));
|
|
|
|
RetVal.first|= m_ToSurfMasks[ 4]& (m_D3DBitShftRgt[ 4]>= 0?
|
|
uiZVal>> m_D3DBitShftRgt[ 4]: uiZVal<< m_D3DBitShftRgt[ 4]);
|
|
RetVal.second|= m_ToSurfMasks[ 4];
|
|
return RetVal;
|
|
}
|
|
// SurfData, ValidMask
|
|
pair< UINT32, UINT32> ConvS( DWORD D3DStensil) const
|
|
{
|
|
pair< UINT32, UINT32> RetVal( 0, 0);
|
|
|
|
RetVal.first|= m_ToSurfMasks[ 5]& (m_D3DBitShftRgt[ 6]>= 0?
|
|
D3DStensil>> m_D3DBitShftRgt[ 6]: D3DStensil<< m_D3DBitShftRgt[ 6]);
|
|
RetVal.second|= m_ToSurfMasks[ 5];
|
|
return RetVal;
|
|
}
|
|
};
|
|
|
|
class CGenSurface:
|
|
public IVidMemSurface
|
|
{
|
|
public: // Types
|
|
typedef unsigned int TLocks;
|
|
|
|
protected: // Variables
|
|
SD3DDataConv m_D3DDataConv;
|
|
DWORD m_dwCaps;
|
|
TLocks m_uiLocks;
|
|
|
|
// Regular data
|
|
void* m_pData;
|
|
LONG m_lPitch;
|
|
size_t m_uiBytes;
|
|
WORD m_wWidth;
|
|
WORD m_wHeight;
|
|
|
|
unsigned char m_ucBPP;
|
|
|
|
public: // Functions
|
|
CGenSurface( const DDSURFACEDESC& SDesc, PORTABLE_DDRAWSURFACE_LCL& DDSurf)
|
|
:IVidMemSurface( DDSurf.lpSurfMore()->dwSurfaceHandle()),
|
|
m_dwCaps( SDesc.ddsCaps.dwCaps), m_uiLocks( 0), m_pData( NULL),
|
|
m_lPitch( 0), m_uiBytes( 0), m_wWidth( DDSurf.lpGbl()->wWidth),
|
|
m_wHeight( DDSurf.lpGbl()->wHeight), m_ucBPP( 0)
|
|
{
|
|
size_t uiBytesPerPixel( 0);
|
|
|
|
// Certain data needs to be written into the DDSurf description,
|
|
// so that the DXG runtime and the app will know characteristics
|
|
// about the surface. (fpVidMem, lPitch, etc.)
|
|
|
|
// DO NOT STORE &DDSurf! This is considered illegal. The typical
|
|
// implementation contains a surfaceDB which contains copies of the
|
|
// DDRAWI_ structures.
|
|
|
|
if((SDesc.dwFlags& DDSD_PIXELFORMAT)!= 0)
|
|
{
|
|
// CGenSurface can only be used for byte-aligned pixels.
|
|
assert( 8== SDesc.ddpfPixelFormat.dwRGBBitCount ||
|
|
16== SDesc.ddpfPixelFormat.dwRGBBitCount ||
|
|
24== SDesc.ddpfPixelFormat.dwRGBBitCount ||
|
|
32== SDesc.ddpfPixelFormat.dwRGBBitCount);
|
|
|
|
m_D3DDataConv= SDesc.ddpfPixelFormat;
|
|
m_ucBPP= static_cast<unsigned char>(
|
|
SDesc.ddpfPixelFormat.dwRGBBitCount>> 3);
|
|
|
|
// Align the Pitch/ Width.
|
|
DDSurf.lpGbl()->lPitch= m_lPitch= ((m_ucBPP* m_wWidth+ 7)& ~7);
|
|
m_uiBytes= m_lPitch* m_wHeight;
|
|
}
|
|
else if((m_dwCaps& DDSCAPS_EXECUTEBUFFER)!= 0)
|
|
{
|
|
// Execute buffers are considered linear and byte-sized.
|
|
m_lPitch= DDSurf.lpGbl()->lPitch;
|
|
m_uiBytes= m_lPitch* m_wHeight;
|
|
}
|
|
else
|
|
{
|
|
const bool Unsupported_Surface_In_Allocation_Routine2( false);
|
|
assert( Unsupported_Surface_In_Allocation_Routine2);
|
|
}
|
|
|
|
// It would've been nice to have the initial proctection NOACCESS, but
|
|
// it seems the HAL needs to read to the region, initially.
|
|
m_pData= VirtualAlloc( NULL, m_uiBytes, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
|
if( m_pData== NULL)
|
|
throw bad_alloc( "Not enough memory to allocate Surface data");
|
|
DDSurf.lpGbl()->fpVidMem= reinterpret_cast<FLATPTR>(m_pData);
|
|
}
|
|
virtual ~CGenSurface()
|
|
{
|
|
// Warning: m_uiLocks doesn't have to be 0. The run-time will destroy
|
|
// a surface without un-locking it.
|
|
assert( m_pData!= NULL);
|
|
VirtualFree( m_pData, 0, MEM_DECOMMIT| MEM_RELEASE);
|
|
}
|
|
virtual void* Lock( DWORD dwFlags, const RECTL* pRect)
|
|
{
|
|
// Typically, m_uiLocks!= 0 equals bad design or bug. But, it is valid.
|
|
// Second Dummy removes vc6 unrefd variable warning.
|
|
numeric_limits< TLocks> Dummy; Dummy;
|
|
assert( Dummy.max()!= m_uiLocks);
|
|
++m_uiLocks;
|
|
|
|
if( pRect!= NULL)
|
|
{
|
|
// If it is either a 1) VB, 2) IB or 3) CB then the rect has a
|
|
// special meaning. rect.top - rect.bottom gives the range of
|
|
// memory desired, because of being linear.
|
|
if((m_dwCaps& DDSCAPS_EXECUTEBUFFER)!= 0)
|
|
{
|
|
return static_cast<void*>( reinterpret_cast<UINT8*>(
|
|
m_pData)+ pRect->top);
|
|
}
|
|
else
|
|
{
|
|
return static_cast<void*>( reinterpret_cast<UINT8*>(
|
|
m_pData)+ pRect->top* m_lPitch+ pRect->left* m_ucBPP);
|
|
}
|
|
}
|
|
else
|
|
return m_pData;
|
|
}
|
|
virtual void Unlock( void)
|
|
{
|
|
assert( 0!= m_uiLocks);
|
|
--m_uiLocks;
|
|
}
|
|
virtual void Clear( const D3DHAL_DP2CLEAR& DP2Clear, const RECT& RC)
|
|
{
|
|
// A VB, IB, or CB should never be asked to 'Clear'. Only
|
|
// RenderTargets and ZBuffers, etc.
|
|
assert((m_dwCaps& DDSCAPS_EXECUTEBUFFER)== 0);
|
|
|
|
// Check for empty RECT.
|
|
if((RC.left>= RC.right) || (RC.top>= RC.bottom))
|
|
return;
|
|
|
|
assert( 1<= m_ucBPP && 4>= m_ucBPP);
|
|
UINT32 ui32BitFill( 0), ui32BitValidMask( 0);
|
|
UINT32 ui32BitSMask( 4== m_ucBPP? 0xFFFFFFFF: (1<< (m_ucBPP* 8))- 1);
|
|
|
|
pair< UINT32, UINT32> RetVal;
|
|
if((DP2Clear.dwFlags& D3DCLEAR_TARGET)!= 0)
|
|
{
|
|
RetVal= m_D3DDataConv.ConvColor( DP2Clear.dwFillColor);
|
|
ui32BitFill|= RetVal.first;
|
|
ui32BitValidMask|= RetVal.second;
|
|
}
|
|
if((DP2Clear.dwFlags& D3DCLEAR_ZBUFFER)!= 0)
|
|
{
|
|
RetVal= m_D3DDataConv.ConvZ( DP2Clear.dvFillDepth);
|
|
ui32BitFill|= RetVal.first;
|
|
ui32BitValidMask|= RetVal.second;
|
|
}
|
|
if((DP2Clear.dwFlags& D3DCLEAR_STENCIL)!= 0)
|
|
{
|
|
RetVal= m_D3DDataConv.ConvS( DP2Clear.dwFillStencil);
|
|
ui32BitFill|= RetVal.first;
|
|
ui32BitValidMask|= RetVal.second;
|
|
}
|
|
|
|
RECTL RectL;
|
|
RectL.top= RC.top;
|
|
RectL.left= RC.left;
|
|
RectL.bottom= RC.bottom;
|
|
RectL.right= RC.right;
|
|
unsigned int iRow( RC.bottom- RC.top);
|
|
const unsigned int iCols( RC.right- RC.left);
|
|
|
|
// New scope for SurfaceLocker.
|
|
{
|
|
CSurfaceLocker< CGenSurface*> MySLocker( this, 0, &RectL);
|
|
UINT8* pSData= reinterpret_cast<UINT8*>( MySLocker.GetData());
|
|
|
|
if( 3== m_ucBPP)
|
|
{
|
|
UINT32 ui32FillData[3];
|
|
ui32FillData[0]= ((ui32BitFill& 0xFFFFFF)<< 8)|
|
|
((ui32BitFill& 0xFF0000)>> 16);
|
|
ui32FillData[1]= ((ui32BitFill& 0x00FFFF)<< 16)|
|
|
((ui32BitFill& 0xFFFF00)>> 8);
|
|
ui32FillData[2]= ((ui32BitFill& 0x0000FF)<< 24)|
|
|
((ui32BitFill& 0xFFFFFF)>> 0);
|
|
|
|
// Little-endian implementation.
|
|
UINT8 ui8FillData[3];
|
|
ui8FillData[0]= (0xFF& ui32BitFill);
|
|
ui8FillData[1]= (0xFF00& ui32BitFill)>> 8;
|
|
ui8FillData[2]= (0xFF0000& ui32BitFill)>> 16;
|
|
|
|
if( ui32BitSMask== ui32BitValidMask)
|
|
{
|
|
// Only fill, no need to read, modify, write.
|
|
do
|
|
{
|
|
UINT32* p32Data= reinterpret_cast<UINT32*>(pSData);
|
|
|
|
// We've packed 4 pixels of data in 3 UINT32.
|
|
unsigned int iCol( iCols>> 2); // (>> 2) == (/ 4)
|
|
|
|
// Unroll.
|
|
if( iCol!= 0) do
|
|
{
|
|
p32Data[ 0]= ui32FillData[0];
|
|
p32Data[ 1]= ui32FillData[1];
|
|
p32Data[ 2]= ui32FillData[2];
|
|
p32Data[ 3]= ui32FillData[0];
|
|
p32Data[ 4]= ui32FillData[1];
|
|
p32Data[ 5]= ui32FillData[2];
|
|
p32Data[ 6]= ui32FillData[0];
|
|
p32Data[ 7]= ui32FillData[1];
|
|
p32Data[ 8]= ui32FillData[2];
|
|
p32Data[ 9]= ui32FillData[0];
|
|
p32Data[10]= ui32FillData[1];
|
|
p32Data[11]= ui32FillData[2];
|
|
p32Data+= 12;
|
|
} while( --iCol);
|
|
|
|
iCol= iCols& 0x3; // (% 4) == (& 0x3)
|
|
if( iCol!= 0) {
|
|
UINT8* p8Data= reinterpret_cast<UINT8*>(p32Data);
|
|
do
|
|
{
|
|
p8Data[0]= ui8FillData[0];
|
|
p8Data[1]= ui8FillData[1];
|
|
p8Data[2]= ui8FillData[2];
|
|
p8Data+= 3;
|
|
} while( --iCol);
|
|
}
|
|
|
|
pSData+= m_lPitch;
|
|
} while( --iRow);
|
|
}
|
|
else
|
|
{
|
|
const UINT32 ui32BitMask= ~ui32BitValidMask;
|
|
UINT32 ui32MaskData[3];
|
|
ui32MaskData[0]= ((ui32BitMask& 0xFFFFFF)<< 8)|
|
|
((ui32BitMask& 0xFF0000)>> 16);
|
|
ui32MaskData[1]= ((ui32BitMask& 0x00FFFF)<< 16)|
|
|
((ui32BitMask& 0xFFFF00)>> 8);
|
|
ui32MaskData[2]= ((ui32BitMask& 0x0000FF)<< 24)|
|
|
((ui32BitMask& 0xFFFFFF)>> 0);
|
|
|
|
UINT8 ui8MaskData[3];
|
|
ui8MaskData[0]= (0xFF& ui32BitMask);
|
|
ui8MaskData[1]= (0xFF00& ui32BitMask)>> 8;
|
|
ui8MaskData[2]= (0xFF0000& ui32BitMask)>> 16;
|
|
|
|
// Need to mask in the data.
|
|
do
|
|
{
|
|
UINT32* p32Data= reinterpret_cast<UINT32*>(pSData);
|
|
|
|
// We've packed 4 pixels of data in 3 UINT32.
|
|
int iCol( iCols>> 2); // (>> 2) == (/ 4)
|
|
|
|
// Unroll.
|
|
if( iCol!= 0) do
|
|
{
|
|
p32Data[ 0]= (p32Data[ 0]& ui32MaskData[0])| ui32FillData[0];
|
|
p32Data[ 1]= (p32Data[ 1]& ui32MaskData[1])| ui32FillData[1];
|
|
p32Data[ 2]= (p32Data[ 2]& ui32MaskData[2])| ui32FillData[2];
|
|
p32Data[ 3]= (p32Data[ 3]& ui32MaskData[0])| ui32FillData[0];
|
|
p32Data[ 4]= (p32Data[ 4]& ui32MaskData[1])| ui32FillData[1];
|
|
p32Data[ 5]= (p32Data[ 5]& ui32MaskData[2])| ui32FillData[2];
|
|
p32Data[ 6]= (p32Data[ 6]& ui32MaskData[0])| ui32FillData[0];
|
|
p32Data[ 7]= (p32Data[ 7]& ui32MaskData[1])| ui32FillData[1];
|
|
p32Data[ 8]= (p32Data[ 8]& ui32MaskData[2])| ui32FillData[2];
|
|
p32Data[ 9]= (p32Data[ 9]& ui32MaskData[0])| ui32FillData[0];
|
|
p32Data[10]= (p32Data[10]& ui32MaskData[1])| ui32FillData[1];
|
|
p32Data[11]= (p32Data[11]& ui32MaskData[2])| ui32FillData[2];
|
|
p32Data+= 12;
|
|
} while( --iCol);
|
|
|
|
iCol= iCols& 0x3; // (% 4) == (& 0x3)
|
|
if( iCol!= 0) {
|
|
UINT8* p8Data= reinterpret_cast<UINT8*>(p32Data);
|
|
do
|
|
{
|
|
p8Data[0]= (p8Data[0]& ui8MaskData[0])| ui8FillData[0];
|
|
p8Data[1]= (p8Data[1]& ui8MaskData[1])| ui8FillData[1];
|
|
p8Data[2]= (p8Data[2]& ui8MaskData[2])| ui8FillData[2];
|
|
p8Data+= 3;
|
|
} while( --iCol);
|
|
}
|
|
|
|
pSData+= m_lPitch;
|
|
} while( --iRow);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
unsigned int uiPakedPixels;
|
|
unsigned int uiPixelsLeft;
|
|
UINT32 ui32FillData;
|
|
UINT32 ui32MaskData;
|
|
if( 1== m_ucBPP)
|
|
{
|
|
uiPakedPixels= iCols>> 6;
|
|
uiPixelsLeft= iCols& 0x3F;
|
|
ui32FillData= (ui32BitFill& 0xFF)|
|
|
((ui32BitFill& 0xFF)<< 8)|
|
|
((ui32BitFill& 0xFF)<< 16)|
|
|
((ui32BitFill& 0xFF)<< 24);
|
|
ui32MaskData= (~ui32BitValidMask& 0xFF)|
|
|
((~ui32BitValidMask& 0xFF)<< 8)|
|
|
((~ui32BitValidMask& 0xFF)<< 16)|
|
|
((~ui32BitValidMask& 0xFF)<< 24);
|
|
}
|
|
else if( 2== m_ucBPP)
|
|
{
|
|
uiPakedPixels= iCols>> 5;
|
|
uiPixelsLeft= iCols& 0x1F;
|
|
ui32FillData= (ui32BitFill& 0xFFFF)|
|
|
((ui32BitFill& 0xFFFF)<< 16);
|
|
ui32MaskData= (~ui32BitValidMask& 0xFFFF)|
|
|
((~ui32BitValidMask& 0xFFFF)<< 16);
|
|
}
|
|
else if( 4== m_ucBPP)
|
|
{
|
|
uiPakedPixels= iCols>> 4;
|
|
uiPixelsLeft= iCols& 0xF;
|
|
ui32FillData= ui32BitFill;
|
|
ui32MaskData= ~ui32BitValidMask;
|
|
}
|
|
|
|
if( ui32BitSMask== ui32BitValidMask)
|
|
{
|
|
// Only fill, no need to read, modify, write.
|
|
do
|
|
{
|
|
UINT32* p32Data= reinterpret_cast<UINT32*>(pSData);
|
|
|
|
// We've packed pixels of data in a UINT32.
|
|
unsigned int iCol( uiPakedPixels);
|
|
|
|
// Unroll.
|
|
if( iCol!= 0) do
|
|
{
|
|
p32Data[ 0]= ui32FillData;
|
|
p32Data[ 1]= ui32FillData;
|
|
p32Data[ 2]= ui32FillData;
|
|
p32Data[ 3]= ui32FillData;
|
|
p32Data[ 4]= ui32FillData;
|
|
p32Data[ 5]= ui32FillData;
|
|
p32Data[ 6]= ui32FillData;
|
|
p32Data[ 7]= ui32FillData;
|
|
p32Data[ 8]= ui32FillData;
|
|
p32Data[ 9]= ui32FillData;
|
|
p32Data[10]= ui32FillData;
|
|
p32Data[11]= ui32FillData;
|
|
p32Data[12]= ui32FillData;
|
|
p32Data[13]= ui32FillData;
|
|
p32Data[14]= ui32FillData;
|
|
p32Data[15]= ui32FillData;
|
|
p32Data+= 16;
|
|
} while( --iCol);
|
|
|
|
iCol= uiPixelsLeft;
|
|
if( iCol!= 0) {
|
|
if( 1== m_ucBPP)
|
|
{
|
|
UINT8 ui8FillData= ui32FillData& 0xFF;
|
|
UINT8* p8Data= reinterpret_cast<UINT8*>(p32Data);
|
|
do
|
|
{
|
|
p8Data[0]= ui8FillData;
|
|
p8Data++;
|
|
} while( --iCol);
|
|
}
|
|
else if( 2== m_ucBPP)
|
|
{
|
|
UINT16 ui16FillData= ui32FillData& 0xFFFF;
|
|
UINT16* p16Data= reinterpret_cast<UINT16*>(p32Data);
|
|
do
|
|
{
|
|
p16Data[0]= ui16FillData;
|
|
p16Data++;
|
|
} while( --iCol);
|
|
}
|
|
else if( 4== m_ucBPP)
|
|
{
|
|
do
|
|
{
|
|
p32Data[0]= ui32FillData;
|
|
p32Data++;
|
|
} while( --iCol);
|
|
}
|
|
}
|
|
|
|
pSData+= m_lPitch;
|
|
} while( --iRow);
|
|
}
|
|
else
|
|
{
|
|
// Need to mask in the data.
|
|
do
|
|
{
|
|
UINT32* p32Data= reinterpret_cast<UINT32*>(pSData);
|
|
|
|
// We've packed pixels of data in a UINT32.
|
|
unsigned int iCol( uiPakedPixels);
|
|
|
|
// Unroll.
|
|
if( iCol!= 0) do
|
|
{
|
|
p32Data[ 0]= (p32Data[ 0]& ui32MaskData)| ui32FillData;
|
|
p32Data[ 1]= (p32Data[ 1]& ui32MaskData)| ui32FillData;
|
|
p32Data[ 2]= (p32Data[ 2]& ui32MaskData)| ui32FillData;
|
|
p32Data[ 3]= (p32Data[ 3]& ui32MaskData)| ui32FillData;
|
|
p32Data[ 4]= (p32Data[ 4]& ui32MaskData)| ui32FillData;
|
|
p32Data[ 5]= (p32Data[ 5]& ui32MaskData)| ui32FillData;
|
|
p32Data[ 6]= (p32Data[ 6]& ui32MaskData)| ui32FillData;
|
|
p32Data[ 7]= (p32Data[ 7]& ui32MaskData)| ui32FillData;
|
|
p32Data[ 8]= (p32Data[ 8]& ui32MaskData)| ui32FillData;
|
|
p32Data[ 9]= (p32Data[ 9]& ui32MaskData)| ui32FillData;
|
|
p32Data[10]= (p32Data[10]& ui32MaskData)| ui32FillData;
|
|
p32Data[11]= (p32Data[11]& ui32MaskData)| ui32FillData;
|
|
p32Data[12]= (p32Data[12]& ui32MaskData)| ui32FillData;
|
|
p32Data[13]= (p32Data[13]& ui32MaskData)| ui32FillData;
|
|
p32Data[14]= (p32Data[14]& ui32MaskData)| ui32FillData;
|
|
p32Data[15]= (p32Data[15]& ui32MaskData)| ui32FillData;
|
|
p32Data+= 16;
|
|
} while( --iCol);
|
|
|
|
iCol= uiPixelsLeft;
|
|
if( iCol!= 0) {
|
|
if( 1== m_ucBPP)
|
|
{
|
|
UINT8 ui8FillData= ui32FillData& 0xFF;
|
|
UINT8 ui8MaskData= ui32MaskData& 0xFF;
|
|
UINT8* p8Data= reinterpret_cast<UINT8*>(p32Data);
|
|
do
|
|
{
|
|
p8Data[0]= (p8Data[0]& ui8MaskData)| ui8FillData;
|
|
p8Data++;
|
|
} while( --iCol);
|
|
}
|
|
else if( 2== m_ucBPP)
|
|
{
|
|
UINT16 ui16FillData= ui32FillData& 0xFFFF;
|
|
UINT16 ui16MaskData= ui32MaskData& 0xFFFF;
|
|
UINT16* p16Data= reinterpret_cast<UINT16*>(p32Data);
|
|
do
|
|
{
|
|
p16Data[0]= (p16Data[0]& ui16MaskData)| ui16FillData;
|
|
p16Data++;
|
|
} while( --iCol);
|
|
}
|
|
else if( 4== m_ucBPP)
|
|
{
|
|
do
|
|
{
|
|
p32Data[0]= (p32Data[0]& ui32MaskData)| ui32FillData;
|
|
p32Data++;
|
|
} while( --iCol);
|
|
}
|
|
}
|
|
|
|
pSData+= m_lPitch;
|
|
} while( --iRow);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static IVidMemSurface* CreateSurf( const DDSURFACEDESC& SDesc,
|
|
PORTABLE_DDRAWSURFACE_LCL& DDSurf)
|
|
{
|
|
return new CGenSurface( SDesc, DDSurf);
|
|
}
|
|
};
|
|
|
|
struct SPixelFormat: public DDPIXELFORMAT
|
|
{
|
|
SPixelFormat( D3DFORMAT D3DFmt)
|
|
{
|
|
ZeroMemory( static_cast< DDPIXELFORMAT*>(this),
|
|
sizeof(DDPIXELFORMAT));
|
|
dwSize= sizeof(DDPIXELFORMAT);
|
|
|
|
// Convert away
|
|
if( HIWORD( static_cast< DWORD>(D3DFmt))!= 0)
|
|
{
|
|
dwFlags= DDPF_FOURCC;
|
|
dwFourCC= static_cast< DWORD>(D3DFmt);
|
|
}
|
|
else switch( D3DFmt)
|
|
{
|
|
case( D3DFMT_R8G8B8):
|
|
dwFlags = DDPF_RGB;
|
|
dwRBitMask = 0x00ff0000;
|
|
dwGBitMask = 0x0000ff00;
|
|
dwBBitMask = 0x000000ff;
|
|
dwRGBBitCount = 24;
|
|
break;
|
|
|
|
case( D3DFMT_A8R8G8B8):
|
|
dwFlags = DDPF_RGB| DDPF_ALPHAPIXELS;
|
|
dwRGBAlphaBitMask = 0xFF000000;
|
|
dwRBitMask = 0x00ff0000;
|
|
dwGBitMask = 0x0000ff00;
|
|
dwBBitMask = 0x000000ff;
|
|
dwRGBBitCount = 32;
|
|
break;
|
|
|
|
case( D3DFMT_X8R8G8B8):
|
|
dwFlags = DDPF_RGB;
|
|
dwRBitMask = 0x00ff0000;
|
|
dwGBitMask = 0x0000ff00;
|
|
dwBBitMask = 0x000000ff;
|
|
dwRGBBitCount = 32;
|
|
break;
|
|
|
|
case( D3DFMT_R5G6B5):
|
|
dwFlags = DDPF_RGB;
|
|
dwRBitMask = 0x0000f800;
|
|
dwGBitMask = 0x000007e0;
|
|
dwBBitMask = 0x0000001f;
|
|
dwRGBBitCount = 16;
|
|
break;
|
|
|
|
case( D3DFMT_X1R5G5B5):
|
|
dwFlags = DDPF_RGB;
|
|
dwRBitMask = 0x00007c00;
|
|
dwGBitMask = 0x000003e0;
|
|
dwBBitMask = 0x0000001f;
|
|
dwRGBBitCount = 16;
|
|
break;
|
|
|
|
case( D3DFMT_A1R5G5B5):
|
|
dwFlags = DDPF_RGB| DDPF_ALPHAPIXELS;
|
|
dwRGBAlphaBitMask = 0x00008000;
|
|
dwRBitMask = 0x00007c00;
|
|
dwGBitMask = 0x000003e0;
|
|
dwBBitMask = 0x0000001f;
|
|
dwRGBBitCount = 16;
|
|
break;
|
|
|
|
case( D3DFMT_A4R4G4B4):
|
|
dwFlags = DDPF_RGB| DDPF_ALPHAPIXELS;
|
|
dwRGBAlphaBitMask = 0x0000f000;
|
|
dwRBitMask = 0x00000f00;
|
|
dwGBitMask = 0x000000f0;
|
|
dwBBitMask = 0x0000000f;
|
|
dwRGBBitCount = 16;
|
|
break;
|
|
|
|
case( D3DFMT_X4R4G4B4):
|
|
dwFlags = DDPF_RGB;
|
|
dwRBitMask = 0x00000f00;
|
|
dwGBitMask = 0x000000f0;
|
|
dwBBitMask = 0x0000000f;
|
|
dwRGBBitCount = 16;
|
|
break;
|
|
|
|
case( D3DFMT_R3G3B2):
|
|
dwFlags = DDPF_RGB;
|
|
dwRBitMask = 0x000000e0;
|
|
dwGBitMask = 0x0000001c;
|
|
dwBBitMask = 0x00000003;
|
|
dwRGBBitCount = 8;
|
|
break;
|
|
|
|
case( D3DFMT_A8R3G3B2):
|
|
dwFlags = DDPF_RGB| DDPF_ALPHAPIXELS;
|
|
dwRGBAlphaBitMask = 0x0000FF00;
|
|
dwRBitMask = 0x000000e0;
|
|
dwGBitMask = 0x0000001c;
|
|
dwBBitMask = 0x00000003;
|
|
dwRGBBitCount = 16;
|
|
break;
|
|
|
|
case( D3DFMT_A8P8):
|
|
dwFlags = DDPF_RGB| DDPF_ALPHAPIXELS| DDPF_PALETTEINDEXED8;
|
|
dwRGBAlphaBitMask = 0x0000FF00;
|
|
dwRGBBitCount = 16;
|
|
break;
|
|
|
|
case( D3DFMT_P8):
|
|
dwFlags = DDPF_RGB| DDPF_PALETTEINDEXED8;
|
|
dwRGBBitCount = 8;
|
|
break;
|
|
|
|
case( D3DFMT_L8):
|
|
dwFlags = DDPF_LUMINANCE;
|
|
dwLuminanceBitMask = 0x000000FF;
|
|
dwLuminanceBitCount = 8;
|
|
break;
|
|
|
|
case( D3DFMT_A8L8):
|
|
dwFlags = DDPF_LUMINANCE| DDPF_ALPHAPIXELS;
|
|
dwLuminanceAlphaBitMask = 0x0000FF00;
|
|
dwLuminanceBitMask = 0x000000FF;
|
|
dwLuminanceBitCount = 16;
|
|
break;
|
|
|
|
case( D3DFMT_A4L4):
|
|
dwFlags = DDPF_LUMINANCE| DDPF_ALPHAPIXELS;
|
|
dwLuminanceAlphaBitMask = 0x000000F0;
|
|
dwLuminanceBitMask = 0x0000000F;
|
|
dwLuminanceBitCount = 8;
|
|
break;
|
|
|
|
case( D3DFMT_V8U8):
|
|
dwFlags = DDPF_BUMPDUDV;
|
|
dwBumpDvBitMask = 0x0000FF00;
|
|
dwBumpDuBitMask = 0x000000FF;
|
|
dwBumpBitCount = 16;
|
|
break;
|
|
|
|
case( D3DFMT_L6V5U5):
|
|
dwFlags = DDPF_BUMPDUDV| DDPF_BUMPLUMINANCE;
|
|
dwBumpLuminanceBitMask = 0x0000FC00;
|
|
dwBumpDvBitMask = 0x000003E0;
|
|
dwBumpDuBitMask = 0x0000001F;
|
|
dwBumpBitCount = 16;
|
|
break;
|
|
|
|
case( D3DFMT_X8L8V8U8):
|
|
dwFlags = DDPF_BUMPDUDV| DDPF_BUMPLUMINANCE;
|
|
dwBumpLuminanceBitMask = 0x00FF0000;
|
|
dwBumpDvBitMask = 0x0000FF00;
|
|
dwBumpDuBitMask = 0x000000FF;
|
|
dwBumpBitCount = 32;
|
|
break;
|
|
|
|
case( D3DFMT_A8):
|
|
dwFlags = DDPF_ALPHA;
|
|
dwAlphaBitDepth = 8;
|
|
break;
|
|
|
|
case( D3DFMT_D16):
|
|
case( D3DFMT_D16_LOCKABLE):
|
|
dwFlags = DDPF_ZBUFFER;
|
|
dwZBufferBitDepth = 16;
|
|
dwZBitMask = 0xFFFF;
|
|
break;
|
|
|
|
case( D3DFMT_D32):
|
|
dwFlags = DDPF_ZBUFFER;
|
|
dwZBufferBitDepth = 32;
|
|
dwZBitMask = 0xFFFFFFFF;
|
|
break;
|
|
|
|
case( D3DFMT_D15S1):
|
|
dwFlags = DDPF_ZBUFFER| DDPF_STENCILBUFFER;
|
|
dwZBufferBitDepth = 16;
|
|
dwZBitMask = 0xFFFE;
|
|
dwStencilBitDepth = 1;
|
|
dwStencilBitMask = 0x0001;
|
|
break;
|
|
|
|
case( D3DFMT_D24S8):
|
|
dwFlags = DDPF_ZBUFFER| DDPF_STENCILBUFFER;
|
|
dwZBufferBitDepth = 32;
|
|
dwZBitMask = 0xFFFFFF00;
|
|
dwStencilBitDepth = 8;
|
|
dwStencilBitMask = 0xFF;
|
|
break;
|
|
|
|
case( D3DFMT_S1D15):
|
|
dwFlags = DDPF_ZBUFFER| DDPF_STENCILBUFFER;
|
|
dwZBufferBitDepth = 16;
|
|
dwZBitMask = 0x7FFF;
|
|
dwStencilBitDepth = 1;
|
|
dwStencilBitMask = 0x8000;
|
|
break;
|
|
|
|
case( D3DFMT_S8D24):
|
|
dwFlags = DDPF_ZBUFFER| DDPF_STENCILBUFFER;
|
|
dwZBufferBitDepth = 32;
|
|
dwZBitMask = 0x00FFFFFF;
|
|
dwStencilBitDepth = 8;
|
|
dwStencilBitMask = 0xFF000000;
|
|
break;
|
|
|
|
case( D3DFMT_X8D24):
|
|
dwFlags = DDPF_ZBUFFER;
|
|
dwZBufferBitDepth = 32;
|
|
dwZBitMask = 0x00FFFFFF;
|
|
break;
|
|
|
|
case( D3DFMT_D24X8):
|
|
dwFlags = DDPF_ZBUFFER;
|
|
dwZBufferBitDepth = 32;
|
|
dwZBitMask = 0xFFFFFF00;
|
|
break;
|
|
|
|
case( D3DFMT_D24X4S4):
|
|
dwFlags = DDPF_ZBUFFER| DDPF_STENCILBUFFER;
|
|
dwZBufferBitDepth = 32;
|
|
dwZBitMask = 0xFFFFFF00;
|
|
dwStencilBitDepth = 4;
|
|
dwStencilBitMask = 0x0000000F;
|
|
break;
|
|
|
|
case( D3DFMT_X4S4D24):
|
|
dwFlags = DDPF_ZBUFFER| DDPF_STENCILBUFFER;
|
|
dwZBufferBitDepth = 32;
|
|
dwZBitMask = 0x00FFFFFF;
|
|
dwStencilBitDepth = 4;
|
|
dwStencilBitMask = 0x0F000000;
|
|
break;
|
|
|
|
default:
|
|
const bool Unrecognized_D3DFmt( false);
|
|
assert( Unrecognized_D3DFmt);
|
|
dwFlags= DDPF_FOURCC;
|
|
dwFourCC= static_cast< DWORD>(D3DFmt);
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
|
|
struct SMatchSDesc:
|
|
public unary_function< const DDSURFACEDESC&, bool>
|
|
{
|
|
const DDSURFACEDESC& m_SDesc;
|
|
|
|
SMatchSDesc( const DDSURFACEDESC& SDesc) : m_SDesc( SDesc) { }
|
|
|
|
result_type operator()( argument_type Arg) const
|
|
{
|
|
if((Arg.dwFlags& DDSD_CAPS)!= 0&& ((m_SDesc.dwFlags& DDSD_CAPS)== 0 ||
|
|
(m_SDesc.ddsCaps.dwCaps& Arg.ddsCaps.dwCaps)!= Arg.ddsCaps.dwCaps))
|
|
return false;
|
|
if((Arg.dwFlags& DDSD_PIXELFORMAT)!= 0&&
|
|
((m_SDesc.dwFlags& DDSD_PIXELFORMAT)== 0 ||
|
|
m_SDesc.ddpfPixelFormat.dwFlags!= Arg.ddpfPixelFormat.dwFlags ||
|
|
m_SDesc.ddpfPixelFormat.dwFourCC!= Arg.ddpfPixelFormat.dwFourCC ||
|
|
m_SDesc.ddpfPixelFormat.dwRGBBitCount!= Arg.ddpfPixelFormat.dwRGBBitCount ||
|
|
m_SDesc.ddpfPixelFormat.dwRBitMask!= Arg.ddpfPixelFormat.dwRBitMask ||
|
|
m_SDesc.ddpfPixelFormat.dwGBitMask!= Arg.ddpfPixelFormat.dwGBitMask ||
|
|
m_SDesc.ddpfPixelFormat.dwBBitMask!= Arg.ddpfPixelFormat.dwBBitMask ||
|
|
m_SDesc.ddpfPixelFormat.dwRGBZBitMask!= Arg.ddpfPixelFormat.dwRGBZBitMask))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CSurfaceAllocator
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
template< class TMatchFn= SMatchSDesc>
|
|
class CIVidMemAllocator
|
|
{
|
|
public: // Types
|
|
typedef IVidMemSurface TSurface;
|
|
typedef TSurface* (*TCreateSurfFn)( const DDSURFACEDESC&,
|
|
PORTABLE_DDRAWSURFACE_LCL&);
|
|
typedef vector< pair< DDSURFACEDESC, TCreateSurfFn> > TCreateSurfFns;
|
|
|
|
protected: // Types
|
|
TCreateSurfFns m_CreateSurfFns;
|
|
struct SAdaptedMatchFn: public TMatchFn
|
|
{
|
|
typedef typename TCreateSurfFns::value_type argument_type;
|
|
using typename TMatchFn::result_type;
|
|
|
|
SAdaptedMatchFn( const DDSURFACEDESC& SDesc) : TMatchFn( SDesc) {}
|
|
|
|
result_type operator()( argument_type Arg) const
|
|
{ return (*static_cast< const TMatchFn*>(this))( Arg.first); }
|
|
};
|
|
|
|
public: // Functions
|
|
CIVidMemAllocator() { }
|
|
template< class TIter>
|
|
CIVidMemAllocator( TIter itStart, const TIter itEnd)
|
|
{
|
|
while( itStart!= itEnd)
|
|
{
|
|
m_CreateSurfFns.push_back(
|
|
typename TCreateSurfFns::value_type( *itStart, *itStart));
|
|
itStart++;
|
|
}
|
|
}
|
|
~CIVidMemAllocator() { }
|
|
|
|
TSurface* CreateSurf( const DDSURFACEDESC& SDesc,
|
|
PORTABLE_DDRAWSURFACE_LCL& Surf) const
|
|
{
|
|
if( m_CreateSurfFns.empty())
|
|
return new CGenSurface( SDesc, Surf);
|
|
|
|
typename TCreateSurfFns::const_iterator itFound(
|
|
find_if( m_CreateSurfFns.begin(), m_CreateSurfFns.end(),
|
|
SAdaptedMatchFn( SDesc) ) );
|
|
|
|
if( itFound!= m_CreateSurfFns.end())
|
|
return (itFound->second)( SDesc, Surf);
|
|
|
|
// Warning, no specifications matched. If creation functions were
|
|
// provided, there should also be a "default" specification or
|
|
// DDSURFACEDESC with empty flags?, in order to "match rest".
|
|
const bool No_Default_CreateSurface_Function_Found( false);
|
|
assert( No_Default_CreateSurface_Function_Found);
|
|
return new CGenSurface( SDesc, Surf);
|
|
}
|
|
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CPerDDrawData
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
template< class THV= vector< DWORD> >
|
|
class CSurfDBEntry
|
|
{
|
|
public: // Types
|
|
typedef THV THandleVector;
|
|
|
|
protected: // Variables
|
|
DWORD m_LCLdwFlags;
|
|
DDSCAPS m_LCLddsCaps;
|
|
DWORD m_LCLdwBackBufferCount;
|
|
DWORD m_MOREdwMipMapCount;
|
|
DDSCAPSEX m_MOREddsCapsEx;
|
|
DWORD m_MOREdwSurfaceHandle;
|
|
DWORD m_MOREdwFVF;
|
|
DWORD m_GBLdwGlobalFlags;
|
|
ULONG_PTR m_GBLfpVidMem;
|
|
LONG m_GBLlPitch;
|
|
WORD m_GBLwHeight;
|
|
WORD m_GBLwWidth;
|
|
ULONG_PTR m_GBLdwReserved1;
|
|
DDPIXELFORMAT m_GBLddpfSurface;
|
|
THandleVector m_AttachedTo;
|
|
THandleVector m_AttachedFrom;
|
|
|
|
public: // Functions
|
|
CSurfDBEntry() { }
|
|
explicit CSurfDBEntry( PORTABLE_DDRAWSURFACE_LCL& DDSurf)
|
|
{
|
|
try{
|
|
(*this)= DDSurf;
|
|
} catch( ... ) {
|
|
m_AttachedTo.clear();
|
|
m_AttachedFrom.clear();
|
|
throw;
|
|
}
|
|
}
|
|
~CSurfDBEntry() { }
|
|
CSurfDBEntry< THV>& operator=( PORTABLE_DDRAWSURFACE_LCL& DDSurf)
|
|
{
|
|
// DO NOT STORE &DDSurf. This is considered illegal.
|
|
m_LCLdwFlags= DDSurf.dwFlags();
|
|
m_LCLddsCaps= DDSurf.ddsCaps();
|
|
m_LCLdwBackBufferCount= DDSurf.dwBackBufferCount();
|
|
m_MOREdwMipMapCount= DDSurf.lpSurfMore()->dwMipMapCount();
|
|
m_MOREddsCapsEx= DDSurf.lpSurfMore()->ddsCapsEx();
|
|
m_MOREdwSurfaceHandle= DDSurf.lpSurfMore()->dwSurfaceHandle();
|
|
m_MOREdwFVF= DDSurf.lpSurfMore()->dwFVF();
|
|
m_GBLdwGlobalFlags= DDSurf.lpGbl()->dwGlobalFlags;
|
|
m_GBLfpVidMem= DDSurf.lpGbl()->fpVidMem;
|
|
m_GBLlPitch= DDSurf.lpGbl()->lPitch;
|
|
m_GBLwHeight= DDSurf.lpGbl()->wHeight;
|
|
m_GBLwWidth= DDSurf.lpGbl()->wWidth;
|
|
m_GBLdwReserved1= DDSurf.lpGbl()->dwReserved1;
|
|
m_GBLddpfSurface= DDSurf.lpGbl()->ddpfSurface;
|
|
|
|
const DWORD dwMyHandle( DDSurf.lpSurfMore()->dwSurfaceHandle());
|
|
m_AttachedTo.clear();
|
|
m_AttachedFrom.clear();
|
|
|
|
PORTABLE_ATTACHLIST* pAl, *pNextAl;
|
|
if((pAl= DDSurf.lpAttachList())!= NULL)
|
|
{
|
|
pNextAl= pAl;
|
|
do
|
|
{
|
|
if( pNextAl->lpAttached!= NULL&& dwMyHandle!=
|
|
pNextAl->lpAttached->lpSurfMore()->dwSurfaceHandle())
|
|
{
|
|
m_AttachedTo.push_back(
|
|
pNextAl->lpAttached->lpSurfMore()->dwSurfaceHandle());
|
|
}
|
|
pNextAl= pNextAl->lpLink;
|
|
} while( pNextAl!= pAl && pNextAl!= NULL);
|
|
}
|
|
if((pAl= DDSurf.lpAttachListFrom())!= NULL)
|
|
{
|
|
pNextAl= pAl;
|
|
do
|
|
{
|
|
if( pNextAl->lpAttached!= NULL&& dwMyHandle!=
|
|
pNextAl->lpAttached->lpSurfMore()->dwSurfaceHandle())
|
|
{
|
|
m_AttachedFrom.push_back(
|
|
pNextAl->lpAttached->lpSurfMore()->dwSurfaceHandle());
|
|
}
|
|
pNextAl= pNextAl->lpLink;
|
|
} while( pNextAl!= pAl && pNextAl!= NULL);
|
|
}
|
|
return *this;
|
|
}
|
|
DWORD GetLCLdwFlags( void) const
|
|
{ return m_LCLdwFlags; }
|
|
const DDSCAPS& GetLCLddsCaps( void) const
|
|
{ return m_LCLddsCaps; }
|
|
DWORD GetLCLdwBackBufferCount( void) const
|
|
{ return m_LCLdwBackBufferCount; }
|
|
DWORD GetMOREdwMipMapCount( void) const
|
|
{ return m_MOREdwMipMapCount; }
|
|
const DDSCAPSEX& GetMOREddsCapsEx( void) const
|
|
{ return m_MOREddsCapsEx; }
|
|
DWORD GetMOREdwSurfaceHandle( void) const
|
|
{ return m_MOREdwSurfaceHandle; }
|
|
DWORD GetMOREdwFVF( void) const
|
|
{ return m_MOREdwFVF; }
|
|
DWORD GetGBLdwGlobalFlags( void) const
|
|
{ return m_GBLdwGlobalFlags; }
|
|
ULONG_PTR GetGBLfpVidMem( void) const
|
|
{ return m_GBLfpVidMem; }
|
|
LONG GetGBLlPitch( void) const
|
|
{ return m_GBLlPitch; }
|
|
WORD GetGBLwHeight( void) const
|
|
{ return m_GBLwHeight; }
|
|
WORD GetGBLwWidth( void) const
|
|
{ return m_GBLwWidth; }
|
|
ULONG_PTR GetGBLdwReserved1( void) const
|
|
{ return m_GBLdwReserved1; }
|
|
const DDPIXELFORMAT& GetGBLddpfSurface( void) const
|
|
{ return m_GBLddpfSurface; }
|
|
const THandleVector& GetAttachedTo( void) const
|
|
{ return m_AttachedTo; }
|
|
const THandleVector& GetAttachedFrom( void) const
|
|
{ return m_AttachedFrom; }
|
|
};
|
|
|
|
template< class TPDBE= CPalDBEntry, class THV= vector< DWORD> >
|
|
class CSurfDBEntryWPal:
|
|
public CSurfDBEntry< THV>
|
|
{
|
|
public: // Types
|
|
typedef TPDBE TPalDBEntry;
|
|
|
|
protected: // Variables
|
|
TPalDBEntry* m_pPalDBEntry;
|
|
|
|
public: // Functions
|
|
CSurfDBEntryWPal():
|
|
m_pPalDBEntry( NULL)
|
|
{ }
|
|
explicit CSurfDBEntryWPal( PORTABLE_DDRAWSURFACE_LCL& DDSurf):
|
|
CSurfDBEntry< THV>( DDSurf), m_pPalDBEntry( NULL)
|
|
{ }
|
|
~CSurfDBEntryWPal()
|
|
{ }
|
|
CSurfDBEntryWPal< TPDBE, THV>& operator=( PORTABLE_DDRAWSURFACE_LCL& DDSurf)
|
|
{
|
|
CSurfDBEntry< THV>* pSub= static_cast< CSurfDBEntry< THV>*>( this);
|
|
// DO NOT STORE &DDSurf. This is considered illegal.
|
|
*pSub= DDSurf;
|
|
return *this;
|
|
}
|
|
void SetPalette( TPalDBEntry* pPalDBEntry)
|
|
{ m_pPalDBEntry= pPalDBEntry; }
|
|
TPalDBEntry* GetPalette() const
|
|
{ return m_pPalDBEntry; }
|
|
};
|
|
|
|
template< class TSuper, class TD, class TSDBE= CSurfDBEntry<>,
|
|
class TSDB= map< DWORD, TSDBE>,
|
|
class TFS= set< PORTABLE_DDRAWSURFACE_LCL*> >
|
|
class CSubPerDDrawData
|
|
{
|
|
public: // Types
|
|
typedef TD TDriver;
|
|
typedef TSDBE TSurfDBEntry;
|
|
typedef TSDB TSurfDB;
|
|
|
|
protected: // Variables
|
|
TDriver& m_Driver;
|
|
TSurfDB m_SurfDB;
|
|
|
|
protected: // Functions
|
|
CSubPerDDrawData( TDriver& Driver, const DDRAWI_DIRECTDRAW_LCL& DDLcl)
|
|
:m_Driver( Driver)
|
|
{ }
|
|
~CSubPerDDrawData() { }
|
|
|
|
public: // Functions
|
|
TDriver& GetDriver( void) const { return m_Driver; }
|
|
TSurfDBEntry* GetSurfDBEntry( DWORD dwH)
|
|
{
|
|
typename TSurfDB::iterator itSurf( m_SurfDB.find( dwH));
|
|
if( itSurf!= m_SurfDB.end())
|
|
return &itSurf->second;
|
|
else
|
|
return NULL;
|
|
}
|
|
const TSurfDBEntry* GetSurfDBEntry( DWORD dwH) const
|
|
{
|
|
typename TSurfDB::const_iterator itSurf( m_SurfDB.find( dwH));
|
|
if( itSurf!= m_SurfDB.end())
|
|
return &itSurf->second;
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
bool PreProcessFullSurface( PORTABLE_DDRAWSURFACE_LCL& DDSLcl) const
|
|
{
|
|
// DO NOT STORE &DDSLcl. This is considered illegal.
|
|
// It is only valid for the duration of the call.
|
|
return false;
|
|
}
|
|
bool PreProcessIndividualSurface( PORTABLE_DDRAWSURFACE_LCL& DDSLcl) const
|
|
|
|
{
|
|
// DO NOT STORE &DDSLcl. This is considered illegal.
|
|
// It is only valid for the duration of the call.
|
|
return false;
|
|
}
|
|
void ProcessIndividualSurface( PORTABLE_DDRAWSURFACE_LCL& DDSLcl)
|
|
{
|
|
// DO NOT STORE &DDSLcl. This is considered illegal.
|
|
// It is only valid for the duration of the call.
|
|
pair< TSurfDB::iterator, bool> Ret= m_SurfDB.insert(
|
|
TSurfDB::value_type( DDSLcl.lpSurfMore()->dwSurfaceHandle(),
|
|
TSurfDBEntry( DDSLcl)));
|
|
|
|
// If not added, update data.
|
|
if( !Ret.second) Ret.first->second= DDSLcl;
|
|
}
|
|
void ProcessFullSurface( PORTABLE_DDRAWSURFACE_LCL& DDSLcl)
|
|
{
|
|
// DO NOT STORE &DDSLcl. This is considered illegal.
|
|
// It is only valid for the duration of the call.
|
|
TSuper* pSThis= static_cast<TSuper*>(this);
|
|
typedef TFS TFoundSet;
|
|
TFoundSet FoundSet;
|
|
typename TFoundSet::size_type OldSetSize( FoundSet.size());
|
|
|
|
// First traverse all over the attach lists looking for new surfaces.
|
|
PORTABLE_ATTACHLIST* pAl, *pNextAl;
|
|
FoundSet.insert( &DDSLcl);
|
|
typename TFoundSet::size_type NewSetSize( FoundSet.size());
|
|
while( OldSetSize!= NewSetSize)
|
|
{
|
|
OldSetSize= NewSetSize;
|
|
|
|
typename TFoundSet::iterator itSurf( FoundSet.begin());
|
|
while( itSurf!= FoundSet.end())
|
|
{
|
|
if((pAl= (*itSurf)->lpAttachList())!= NULL)
|
|
{
|
|
pNextAl= pAl;
|
|
do
|
|
{
|
|
if( pNextAl->lpAttached!= NULL)
|
|
FoundSet.insert( pNextAl->lpAttached);
|
|
|
|
pNextAl= pNextAl->lpLink;
|
|
} while( pNextAl!= pAl && pNextAl!= NULL);
|
|
}
|
|
if((pAl= (*itSurf)->lpAttachListFrom())!= NULL)
|
|
{
|
|
pNextAl= pAl;
|
|
do
|
|
{
|
|
if( pNextAl->lpAttached!= NULL)
|
|
FoundSet.insert( pNextAl->lpAttached);
|
|
|
|
pNextAl= pNextAl->lpLink;
|
|
} while( pNextAl!= pAl && pNextAl!= NULL);
|
|
}
|
|
itSurf++;
|
|
}
|
|
NewSetSize= FoundSet.size();
|
|
}
|
|
|
|
// After all surfaces have been found, add them to the DB.
|
|
typename TFoundSet::iterator itSurf( FoundSet.begin());
|
|
while( itSurf!= FoundSet.end())
|
|
{
|
|
if( !pSThis->PreProcessIndividualSurface( *(*itSurf)))
|
|
ProcessIndividualSurface( *(*itSurf));
|
|
|
|
itSurf++;
|
|
}
|
|
}
|
|
|
|
// Notification that a system or video memory surface was created. At the
|
|
// least, we have to keep track of the surface handles.
|
|
void SurfaceCreated( PORTABLE_DDRAWSURFACE_LCL& DDSLcl)
|
|
{
|
|
// DO NOT STORE &DDSLcl. This is considered illegal.
|
|
// It is only valid for the duration of the call.
|
|
TSuper* pSThis= static_cast<TSuper*>(this);
|
|
|
|
// If true is returned, then a super structure was recognized and
|
|
// processed. Otherwise, false indicates no recognition, and all
|
|
// surfaces will be scoured.
|
|
if( !pSThis->PreProcessFullSurface( DDSLcl))
|
|
pSThis->ProcessFullSurface( DDSLcl);
|
|
}
|
|
bool SurfaceDestroyed( PORTABLE_DDRAWSURFACE_LCL& DDSLcl)
|
|
{
|
|
// DO NOT STORE &DDSLcl. This is considered illegal.
|
|
// It is only valid for the duration of the call.
|
|
|
|
// No need to assert removal, as we might not be tracking this type
|
|
// of surface. Someone could override and filter out surfaces.
|
|
m_SurfDB.erase( DDSLcl.lpSurfMore()->dwSurfaceHandle());
|
|
|
|
// Return true to tell driver to delete this object. So,
|
|
// if DB is empty, odds are good to delete this.
|
|
return m_SurfDB.empty();
|
|
}
|
|
};
|
|
|
|
template< class TD>
|
|
class CMinimalPerDDrawData:
|
|
public CSubPerDDrawData< CMinimalPerDDrawData< TD>, TD>
|
|
{
|
|
public:
|
|
CMinimalPerDDrawData( TDriver& Driver, DDRAWI_DIRECTDRAW_LCL& DDLcl)
|
|
:CSubPerDDrawData< CMinimalPerDDrawData< TD>, TD>( Driver, DDLcl)
|
|
{ }
|
|
~CMinimalPerDDrawData() { }
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CSubDriver
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
template< class T>
|
|
struct SFakeEntryPointHook
|
|
{
|
|
SFakeEntryPointHook( T& t, const char* szEntryPoint) { }
|
|
~SFakeEntryPointHook() { }
|
|
};
|
|
|
|
template< class TD, class TC, class TSA= CIVidMemAllocator<>,
|
|
class TPDDD= CMinimalPerDDrawData< TD>,
|
|
class TCs= set< TC*>,
|
|
class TPDDDs= map< LPDDRAWI_DIRECTDRAW_LCL, TPDDD>,
|
|
class TSs= set< TSA::TSurface*>,
|
|
class TEntryPointHook= SFakeEntryPointHook< TD> >
|
|
class CSubDriver
|
|
{
|
|
public: // Types
|
|
typedef TD TDriver;
|
|
typedef TC TContext;
|
|
typedef TCs TContexts;
|
|
typedef TPDDD TPerDDrawData;
|
|
typedef TPDDDs TPerDDrawDatas;
|
|
typedef TSA TSurfAlloc;
|
|
typedef typename TSurfAlloc::TSurface TSurface;
|
|
typedef TSs TSurfaces;
|
|
|
|
class CSurfaceCapWrap
|
|
{
|
|
protected:
|
|
DDSURFACEDESC m_SDesc;
|
|
public:
|
|
CSurfaceCapWrap() { }
|
|
CSurfaceCapWrap( const D3DFORMAT D3DFmt, const DWORD dwSupportedOps,
|
|
const DWORD dwPrivateFmtBitCount= 0,
|
|
const WORD wFlipMSTypes= 0, const WORD wBltMSTypes= 0)
|
|
{
|
|
ZeroMemory( &m_SDesc, sizeof( m_SDesc));
|
|
m_SDesc.dwSize= sizeof( m_SDesc);
|
|
|
|
m_SDesc.ddpfPixelFormat.dwFlags= DDPF_D3DFORMAT;
|
|
m_SDesc.ddpfPixelFormat.dwFourCC= static_cast<DWORD>(D3DFmt);
|
|
m_SDesc.ddpfPixelFormat.dwOperations= dwSupportedOps;
|
|
m_SDesc.ddpfPixelFormat.dwPrivateFormatBitCount= dwPrivateFmtBitCount;
|
|
m_SDesc.ddpfPixelFormat.MultiSampleCaps.wFlipMSTypes= wFlipMSTypes;
|
|
m_SDesc.ddpfPixelFormat.MultiSampleCaps.wBltMSTypes= wBltMSTypes;
|
|
}
|
|
CSurfaceCapWrap( const D3DFORMAT D3DFmt, const bool bTexture,
|
|
const bool bVolTexture, const bool bCubeTexture,
|
|
const bool bOffScreenTarget, const bool bSameFmtTarget,
|
|
const bool bZStencil, const bool bZStencilWithColor,
|
|
const bool bSameFmtUpToAlpha, const bool b3DAccel,
|
|
const DWORD dwPrivateFmtBitCount= 0,
|
|
const WORD wFlipMSTypes= 0, const WORD wBltMSTypes= 0)
|
|
{
|
|
ZeroMemory( &m_SDesc, sizeof( m_SDesc));
|
|
m_SDesc.dwSize= sizeof( m_SDesc);
|
|
|
|
DWORD dwOps( 0);
|
|
if( bTexture) dwOps|= D3DFORMAT_OP_TEXTURE;
|
|
if( bVolTexture) dwOps|= D3DFORMAT_OP_VOLUMETEXTURE;
|
|
if( bCubeTexture) dwOps|= D3DFORMAT_OP_CUBETEXTURE;
|
|
if( bOffScreenTarget) dwOps|= D3DFORMAT_OP_OFFSCREEN_RENDERTARGET;
|
|
if( bSameFmtTarget) dwOps|= D3DFORMAT_OP_SAME_FORMAT_RENDERTARGET;
|
|
if( bZStencil) dwOps|= D3DFORMAT_OP_ZSTENCIL;
|
|
if( bZStencilWithColor) dwOps|= D3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH;
|
|
if( bSameFmtUpToAlpha) dwOps|= D3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET;
|
|
if( b3DAccel) dwOps|= D3DFORMAT_OP_3DACCELERATION;
|
|
|
|
m_SDesc.ddpfPixelFormat.dwFlags= DDPF_D3DFORMAT;
|
|
m_SDesc.ddpfPixelFormat.dwFourCC= static_cast<DWORD>(D3DFmt);
|
|
m_SDesc.ddpfPixelFormat.dwOperations= dwOps;
|
|
m_SDesc.ddpfPixelFormat.dwPrivateFormatBitCount= dwPrivateFmtBitCount;
|
|
m_SDesc.ddpfPixelFormat.MultiSampleCaps.wFlipMSTypes= wFlipMSTypes;
|
|
m_SDesc.ddpfPixelFormat.MultiSampleCaps.wBltMSTypes= wBltMSTypes;
|
|
}
|
|
~CSurfaceCapWrap() { }
|
|
operator DDSURFACEDESC() const
|
|
{ return m_SDesc; }
|
|
};
|
|
|
|
private:
|
|
// Stubs for secondary entry points.
|
|
DWORD static APIENTRY ContextCreateStub( LPD3DHAL_CONTEXTCREATEDATA pccd)
|
|
{
|
|
return sm_pGlobalDriver->ContextCreate(
|
|
*reinterpret_cast< PORTABLE_CONTEXTCREATEDATA*>( pccd));
|
|
}
|
|
DWORD static APIENTRY ContextDestroyStub( LPD3DHAL_CONTEXTDESTROYDATA pcdd)
|
|
{ return sm_pGlobalDriver->ContextDestroy( *pcdd); }
|
|
DWORD static APIENTRY ContextDestroyAllStub( LPD3DHAL_CONTEXTDESTROYALLDATA pcdad)
|
|
{ return sm_pGlobalDriver->ContextDestroyAll( *pcdad); }
|
|
DWORD static APIENTRY SceneCaptureStub( LPD3DHAL_SCENECAPTUREDATA pscd)
|
|
{ return sm_pGlobalDriver->SceneCapture( *pscd); }
|
|
DWORD static APIENTRY RenderStateStub( LPD3DHAL_RENDERSTATEDATA prsd)
|
|
{ return sm_pGlobalDriver->RenderState( *prsd); }
|
|
DWORD static APIENTRY RenderPrimitiveStub( LPD3DHAL_RENDERPRIMITIVEDATA prpd)
|
|
{ return sm_pGlobalDriver->RenderPrimitive( *prpd); }
|
|
DWORD static APIENTRY TextureCreateStub( LPD3DHAL_TEXTURECREATEDATA ptcd)
|
|
{ return sm_pGlobalDriver->TextureCreate( *ptcd); }
|
|
DWORD static APIENTRY TextureDestroyStub( LPD3DHAL_TEXTUREDESTROYDATA ptdd)
|
|
{ return sm_pGlobalDriver->TextureDestroy( *ptdd); }
|
|
DWORD static APIENTRY TextureSwapStub( LPD3DHAL_TEXTURESWAPDATA ptsd)
|
|
{ return sm_pGlobalDriver->TextureSwap( *ptsd); }
|
|
DWORD static APIENTRY TextureGetSurfStub( LPD3DHAL_TEXTUREGETSURFDATA ptgsd)
|
|
{ return sm_pGlobalDriver->TextureGetSurf( *ptgsd); }
|
|
DWORD static APIENTRY GetStateStub( LPD3DHAL_GETSTATEDATA pgsd)
|
|
{ return sm_pGlobalDriver->GetState( *pgsd); }
|
|
DWORD static APIENTRY SetRenderTargetStub( LPD3DHAL_SETRENDERTARGETDATA psrtd)
|
|
{
|
|
return sm_pGlobalDriver->SetRenderTarget(
|
|
*reinterpret_cast< PORTABLE_SETRENDERTARGETDATA*>( psrtd));
|
|
}
|
|
DWORD static APIENTRY ClearStub( LPD3DHAL_CLEARDATA pcd)
|
|
{ return sm_pGlobalDriver->Clear( *pcd); }
|
|
DWORD static APIENTRY DrawOnePrimitiveStub( LPD3DHAL_DRAWONEPRIMITIVEDATA pdopd)
|
|
{ return sm_pGlobalDriver->DrawOnePrimitive( *pdopd); }
|
|
DWORD static APIENTRY DrawOneIndexedPrimitiveStub( LPD3DHAL_DRAWONEINDEXEDPRIMITIVEDATA pdoipd)
|
|
{ return sm_pGlobalDriver->DrawOneIndexedPrimitive( *pdoipd); }
|
|
DWORD static APIENTRY DrawPrimitivesStub( LPD3DHAL_DRAWPRIMITIVESDATA pdpd)
|
|
{ return sm_pGlobalDriver->DrawPrimitives( *pdpd); }
|
|
DWORD static APIENTRY Clear2Stub( LPD3DHAL_CLEAR2DATA pc2d)
|
|
{ return sm_pGlobalDriver->Clear2( *pc2d); }
|
|
DWORD static APIENTRY ValidateTextureStageStateStub( LPD3DHAL_VALIDATETEXTURESTAGESTATEDATA pvtssd)
|
|
{ return sm_pGlobalDriver->ValidateTextureStageState( *pvtssd); }
|
|
DWORD static APIENTRY DrawPrimitives2Stub( LPD3DHAL_DRAWPRIMITIVES2DATA pdpd)
|
|
{
|
|
return sm_pGlobalDriver->DrawPrimitives2(
|
|
*reinterpret_cast< PORTABLE_DRAWPRIMITIVES2DATA*>( pdpd));
|
|
}
|
|
DWORD static APIENTRY GetDriverStateStub( LPDDHAL_GETDRIVERSTATEDATA pgdsd)
|
|
{ return sm_pGlobalDriver->GetDriverState( *pgdsd); }
|
|
DWORD static APIENTRY CreateSurfaceExStub( LPDDHAL_CREATESURFACEEXDATA pcsxd)
|
|
{
|
|
return sm_pGlobalDriver->CreateSurfaceEx(
|
|
*reinterpret_cast< PORTABLE_CREATESURFACEEXDATA*>( pcsxd));
|
|
}
|
|
DWORD static APIENTRY CreateSurfaceStub( LPDDHAL_CREATESURFACEDATA pcsd)
|
|
{
|
|
return sm_pGlobalDriver->CreateSurface(
|
|
*reinterpret_cast< PORTABLE_CREATESURFACEDATA*>( pcsd));
|
|
}
|
|
DWORD static APIENTRY DestroySurfaceStub( LPDDHAL_DESTROYSURFACEDATA pdsd)
|
|
{
|
|
return sm_pGlobalDriver->DestroySurface(
|
|
*reinterpret_cast< PORTABLE_DESTROYSURFACEDATA*>( pdsd));
|
|
}
|
|
DWORD static APIENTRY LockStub( LPDDHAL_LOCKDATA pld)
|
|
{
|
|
return sm_pGlobalDriver->Lock(
|
|
*reinterpret_cast< PORTABLE_LOCKDATA*>( pld));
|
|
}
|
|
DWORD static APIENTRY UnlockStub( LPDDHAL_UNLOCKDATA pud)
|
|
{
|
|
return sm_pGlobalDriver->Unlock(
|
|
*reinterpret_cast< PORTABLE_UNLOCKDATA*>( pud));
|
|
}
|
|
|
|
protected:
|
|
TSurfAlloc m_SurfAlloc;
|
|
TContexts m_Contexts;
|
|
TPerDDrawDatas m_PerDDrawDatas;
|
|
TSurfaces m_Surfaces;
|
|
typedef vector< DDSURFACEDESC> TSupportedSurfaces;
|
|
TSupportedSurfaces m_SupportedSurfaces;
|
|
|
|
template< class TIter> // DDSURFACEDESC*
|
|
CSubDriver( TIter itStart, const TIter itEnd, TSurfAlloc SA= TSurfAlloc()):
|
|
m_SurfAlloc( SA)
|
|
{
|
|
// Copy supported surfaces formats into a guarenteed contiguous storage
|
|
// for passing to D3D.
|
|
while( itStart!= itEnd)
|
|
m_SupportedSurfaces.push_back( *itStart++);
|
|
}
|
|
~CSubDriver() { }
|
|
// Binds a VidMem DDRAWI object together with an internal driver surface object.
|
|
void static AssociateSurface( PORTABLE_DDRAWSURFACE_LCL& DDSurf,
|
|
TSurface* pSurf)
|
|
{
|
|
assert((DDSurf.ddsCaps().dwCaps& DDSCAPS_VIDEOMEMORY)!= 0);
|
|
DDSurf.lpGbl()->dwReserved1= reinterpret_cast< ULONG_PTR>(pSurf);
|
|
}
|
|
|
|
public:
|
|
// The global driver static member pointer. Only one Driver object, and
|
|
// this points to it.
|
|
static TDriver* sm_pGlobalDriver;
|
|
|
|
TSurface* GetSurface( PORTABLE_DDRAWSURFACE_LCL& DDSurf,
|
|
bool bCheck= true) const
|
|
{
|
|
TSurface* pSurface= reinterpret_cast< TSurface*>(
|
|
DDSurf.lpGbl()->dwReserved1);
|
|
assert( bCheck&& m_Surfaces.find( pSurface)!= m_Surfaces.end());
|
|
return pSurface;
|
|
}
|
|
TSurface* GetSurface( const typename TPerDDrawData::TSurfDBEntry& DBEntry,
|
|
bool bCheck= true) const
|
|
{
|
|
TSurface* pSurface= reinterpret_cast< TSurface*>(
|
|
DBEntry.GetGBLdwReserved1());
|
|
assert( bCheck&& m_Surfaces.find( pSurface)!= m_Surfaces.end());
|
|
return pSurface;
|
|
}
|
|
|
|
// Secondary entry points with C++ friendly parameters.
|
|
DWORD ContextCreate( PORTABLE_CONTEXTCREATEDATA& ccd) throw()
|
|
{
|
|
try
|
|
{
|
|
TEntryPointHook EntryPointHook( *sm_pGlobalDriver, "ContextCreate");
|
|
|
|
ccd.ddrval()= DD_OK;
|
|
TDriver* pSThis= static_cast<TDriver*>(this);
|
|
|
|
// We should already have a PerDDrawData at this point, as the
|
|
// surfaces to initialize the context had to be created already,
|
|
// and the PerDDrawData should've been created there.
|
|
typename TPerDDrawDatas::iterator itPerDDrawData(
|
|
m_PerDDrawDatas.find( ccd.lpDDLcl()));
|
|
assert( itPerDDrawData!= m_PerDDrawDatas.end());
|
|
|
|
// Create the new context, passing in a ref to the PerDDrawData object.
|
|
auto_ptr< TContext> pNewContext( new TContext(
|
|
itPerDDrawData->second, ccd));
|
|
|
|
// Keep track of our new context.
|
|
pair< TContexts::iterator, bool> RetVal( m_Contexts.insert(
|
|
pNewContext.get()));
|
|
assert( RetVal.second); // Assure that there wasn't a duplicate.
|
|
|
|
// Ownership now has been transfered to m_Contexts & D3D.
|
|
ccd.dwhContext()= reinterpret_cast<ULONG_PTR>( pNewContext.release());
|
|
} catch( bad_alloc e) {
|
|
ccd.ddrval()= D3DHAL_OUTOFCONTEXTS;
|
|
} catch( HRESULT hr) {
|
|
ccd.ddrval()= hr;
|
|
#if !defined( DX8SDDIFW_NOCATCHALL)
|
|
} catch( ... ) {
|
|
const bool ContextCreate_Unrecognized_Exception( false);
|
|
assert( ContextCreate_Unrecognized_Exception);
|
|
ccd.ddrval()= E_UNEXPECTED;
|
|
#endif // !defined( DX8SDDIFW_NOCATCHALL)
|
|
}
|
|
return DDHAL_DRIVER_HANDLED;
|
|
}
|
|
DWORD ContextDestroy( D3DHAL_CONTEXTDESTROYDATA& cdd) throw()
|
|
{
|
|
try
|
|
{
|
|
TEntryPointHook EntryPointHook( *sm_pGlobalDriver, "ContextDestroy");
|
|
|
|
cdd.ddrval= DD_OK;
|
|
|
|
// Ownership now has been transfered to local auto_ptr.
|
|
auto_ptr< TContext> pContext(
|
|
reinterpret_cast<TContext*>(cdd.dwhContext));
|
|
|
|
// Remove tracking of this context.
|
|
typename TContexts::size_type Ret( m_Contexts.erase( pContext.get()));
|
|
assert( Ret!= 0);
|
|
} catch( HRESULT hr) {
|
|
cdd.ddrval= hr;
|
|
#if !defined( DX8SDDIFW_NOCATCHALL)
|
|
} catch( ... ) {
|
|
const bool ContextDestroy_Unrecognized_Exception( false);
|
|
assert( ContextDestroy_Unrecognized_Exception);
|
|
cdd.ddrval= E_UNEXPECTED;
|
|
#endif // !defined( DX8SDDIFW_NOCATCHALL)
|
|
}
|
|
return DDHAL_DRIVER_HANDLED;
|
|
}
|
|
DWORD ContextDestroyAll( D3DHAL_CONTEXTDESTROYALLDATA& cdad) const throw()
|
|
{
|
|
TEntryPointHook EntryPointHook( *sm_pGlobalDriver, "ContextDestroyAll");
|
|
const bool ContextDestroyAll_thought_to_be_depreciated_entry_point( false);
|
|
assert( ContextDestroyAll_thought_to_be_depreciated_entry_point);
|
|
return DDHAL_DRIVER_NOTHANDLED;
|
|
}
|
|
DWORD SceneCapture( D3DHAL_SCENECAPTUREDATA& scd) const throw()
|
|
{
|
|
TEntryPointHook EntryPointHook( *sm_pGlobalDriver, "SceneCapture");
|
|
const bool SceneCapture_thought_to_be_depreciated_entry_point( false);
|
|
assert( SceneCapture_thought_to_be_depreciated_entry_point);
|
|
return DDHAL_DRIVER_NOTHANDLED;
|
|
}
|
|
DWORD RenderState( D3DHAL_RENDERSTATEDATA& rsd) const throw()
|
|
{
|
|
TEntryPointHook EntryPointHook( *sm_pGlobalDriver, "RenderState");
|
|
const bool RenderState_thought_to_be_depreciated_entry_point( false);
|
|
assert( RenderState_thought_to_be_depreciated_entry_point);
|
|
return DDHAL_DRIVER_NOTHANDLED;
|
|
}
|
|
DWORD RenderPrimitive( D3DHAL_RENDERPRIMITIVEDATA& rpd) const throw()
|
|
{
|
|
TEntryPointHook EntryPointHook( *sm_pGlobalDriver, "RenderPrimitive");
|
|
const bool RenderPrimitive_thought_to_be_depreciated_entry_point( false);
|
|
assert( RenderPrimitive_thought_to_be_depreciated_entry_point);
|
|
return DDHAL_DRIVER_NOTHANDLED;
|
|
}
|
|
DWORD TextureCreate( D3DHAL_TEXTURECREATEDATA& tcd) const throw()
|
|
{
|
|
TEntryPointHook EntryPointHook( *sm_pGlobalDriver, "TextureCreate");
|
|
const bool TextureCreate_thought_to_be_depreciated_entry_point( false);
|
|
assert( TextureCreate_thought_to_be_depreciated_entry_point);
|
|
return DDHAL_DRIVER_NOTHANDLED;
|
|
}
|
|
DWORD TextureDestroy( D3DHAL_TEXTUREDESTROYDATA& tdd) const throw()
|
|
{
|
|
TEntryPointHook EntryPointHook( *sm_pGlobalDriver, "TextureDestroy");
|
|
const bool TextureDestroy_thought_to_be_depreciated_entry_point( false);
|
|
assert( TextureDestroy_thought_to_be_depreciated_entry_point);
|
|
return DDHAL_DRIVER_NOTHANDLED;
|
|
}
|
|
DWORD TextureSwap( D3DHAL_TEXTURESWAPDATA& tsd) const throw()
|
|
{
|
|
TEntryPointHook EntryPointHook( *sm_pGlobalDriver, "TextureSwap");
|
|
const bool TextureSwap_thought_to_be_depreciated_entry_point( false);
|
|
assert( TextureSwap_thought_to_be_depreciated_entry_point);
|
|
return DDHAL_DRIVER_NOTHANDLED;
|
|
}
|
|
DWORD TextureGetSurf( D3DHAL_TEXTUREGETSURFDATA& tgsd) const throw()
|
|
{
|
|
TEntryPointHook EntryPointHook( *sm_pGlobalDriver, "TextureGetSurf");
|
|
const bool TextureGetSurf_thought_to_be_depreciated_entry_point( false);
|
|
assert( TextureGetSurf_thought_to_be_depreciated_entry_point);
|
|
return DDHAL_DRIVER_NOTHANDLED;
|
|
}
|
|
DWORD GetState( D3DHAL_GETSTATEDATA& gsd) const throw()
|
|
{
|
|
TEntryPointHook EntryPointHook( *sm_pGlobalDriver, "GetState");
|
|
const bool GetState_thought_to_be_depreciated_entry_point( false);
|
|
assert( GetState_thought_to_be_depreciated_entry_point);
|
|
return DDHAL_DRIVER_NOTHANDLED;
|
|
}
|
|
DWORD SetRenderTarget( PORTABLE_SETRENDERTARGETDATA& srtd) const throw()
|
|
{
|
|
TEntryPointHook EntryPointHook( *sm_pGlobalDriver, "SetRenderTarget");
|
|
const bool SetRenderTarget_thought_to_be_depreciated_entry_point( false);
|
|
assert( SetRenderTarget_thought_to_be_depreciated_entry_point);
|
|
return DDHAL_DRIVER_NOTHANDLED;
|
|
}
|
|
DWORD Clear( D3DHAL_CLEARDATA& cd) const throw()
|
|
{
|
|
TEntryPointHook EntryPointHook( *sm_pGlobalDriver, "Clear");
|
|
const bool Clear_thought_to_be_depreciated_entry_point( false);
|
|
assert( Clear_thought_to_be_depreciated_entry_point);
|
|
return DDHAL_DRIVER_NOTHANDLED;
|
|
}
|
|
DWORD DrawOnePrimitive( D3DHAL_DRAWONEPRIMITIVEDATA& dopd) const throw()
|
|
{
|
|
TEntryPointHook EntryPointHook( *sm_pGlobalDriver, "DrawOnePrimitive");
|
|
const bool DrawOnePrimitive_thought_to_be_depreciated_entry_point( false);
|
|
assert( DrawOnePrimitive_thought_to_be_depreciated_entry_point);
|
|
return DDHAL_DRIVER_NOTHANDLED;
|
|
}
|
|
DWORD DrawOneIndexedPrimitive( D3DHAL_DRAWONEINDEXEDPRIMITIVEDATA& doipd) const throw()
|
|
{
|
|
TEntryPointHook EntryPointHook( *sm_pGlobalDriver, "DrawOneIndexedPrimitive");
|
|
const bool DrawOneIndexedPrimitive_thought_to_be_depreciated_entry_point( false);
|
|
assert( DrawOneIndexedPrimitive_thought_to_be_depreciated_entry_point);
|
|
return DDHAL_DRIVER_NOTHANDLED;
|
|
}
|
|
DWORD DrawPrimitives( D3DHAL_DRAWPRIMITIVESDATA& dpd) const throw()
|
|
{
|
|
TEntryPointHook EntryPointHook( *sm_pGlobalDriver, "DrawPrimitives");
|
|
const bool DrawPrimitives_thought_to_be_depreciated_entry_point( false);
|
|
assert( DrawPrimitives_thought_to_be_depreciated_entry_point);
|
|
return DDHAL_DRIVER_NOTHANDLED;
|
|
}
|
|
DWORD Clear2( D3DHAL_CLEAR2DATA& c2d) const throw()
|
|
{
|
|
TEntryPointHook EntryPointHook( *sm_pGlobalDriver, "Clear2");
|
|
const bool Clear2_thought_to_be_depreciated_entry_point( false);
|
|
assert( Clear2_thought_to_be_depreciated_entry_point);
|
|
return DDHAL_DRIVER_NOTHANDLED;
|
|
}
|
|
DWORD ValidateTextureStageState( D3DHAL_VALIDATETEXTURESTAGESTATEDATA& vtssd) const throw()
|
|
{
|
|
try
|
|
{
|
|
TEntryPointHook EntryPointHook( *sm_pGlobalDriver, "ValidateTextureStageState");
|
|
|
|
vtssd.ddrval= DD_OK;
|
|
TContext* pContext= reinterpret_cast<TContext*>(vtssd.dwhContext);
|
|
|
|
// Make sure we've created this context.
|
|
assert( m_Contexts.find( pContext)!= m_Contexts.end());
|
|
|
|
// Pass entry point to context.
|
|
vtssd.ddrval= pContext->ValidateTextureStageState( vtssd);
|
|
} catch( HRESULT hr) {
|
|
vtssd.ddrval= hr;
|
|
#if !defined( DX8SDDIFW_NOCATCHALL)
|
|
} catch( ... ) {
|
|
const bool ValidateTextureStageState_Unrecognized_Exception( false);
|
|
assert( ValidateTextureStageState_Unrecognized_Exception);
|
|
vtssd.ddrval= E_UNEXPECTED;
|
|
#endif // !defined( DX8SDDIFW_NOCATCHALL)
|
|
}
|
|
return DDHAL_DRIVER_HANDLED;
|
|
}
|
|
DWORD DrawPrimitives2( PORTABLE_DRAWPRIMITIVES2DATA& dpd) const throw()
|
|
{
|
|
try
|
|
{
|
|
TEntryPointHook EntryPointHook( *sm_pGlobalDriver, "DrawPrimitives2");
|
|
|
|
dpd.ddrval()= DD_OK;
|
|
TContext* pContext= reinterpret_cast<TContext*>(dpd.dwhContext());
|
|
|
|
// Make sure we've created this context.
|
|
assert( m_Contexts.find( pContext)!= m_Contexts.end());
|
|
|
|
// Pass entry point to context.
|
|
dpd.ddrval()= pContext->DrawPrimitives2( dpd);
|
|
} catch( HRESULT hr) {
|
|
dpd.ddrval()= hr;
|
|
#if !defined( DX8SDDIFW_NOCATCHALL)
|
|
} catch( ... ) {
|
|
const bool DrawPrimitives2_Unrecognized_Exception( false);
|
|
assert( DrawPrimitives2_Unrecognized_Exception);
|
|
dpd.ddrval()= E_UNEXPECTED;
|
|
#endif // !defined( DX8SDDIFW_NOCATCHALL)
|
|
}
|
|
return DDHAL_DRIVER_HANDLED;
|
|
}
|
|
DWORD GetDriverState( DDHAL_GETDRIVERSTATEDATA& gdsd) const throw()
|
|
{
|
|
// This entry point is hooked up to IDirect3DDevice8::GetInfo(
|
|
// DWORD DevInfoId, VOID* pDevInfoStruct, DWORD DevInfoStructSize).
|
|
// gdsd.dwFlags= DevInfoId
|
|
// gdsd.lpdwStates= pDevInfoStruct
|
|
// gdsd.dwLength= DevInfoStructSize
|
|
//
|
|
// This entry point can be used for driver defined/ extended state
|
|
// passing. Currently no DevInfoIds are pre-defined. S_FALSE should
|
|
// be returned if nothing is done or the Id is not understood.
|
|
try
|
|
{
|
|
TEntryPointHook EntryPointHook( *sm_pGlobalDriver, "GetDriverState");
|
|
|
|
gdsd.ddRVal= DD_OK;
|
|
TContext* pContext= reinterpret_cast< TContext*>( gdsd.dwhContext);
|
|
|
|
// Make sure we've created this context.
|
|
assert( m_Contexts.find( pContext)!= m_Contexts.end());
|
|
|
|
// Pass entry point to context.
|
|
gdsd.ddRVal= pContext->GetDriverState( gdsd);
|
|
} catch( HRESULT hr) {
|
|
gdsd.ddRVal= hr;
|
|
#if !defined( DX8SDDIFW_NOCATCHALL)
|
|
} catch( ... ) {
|
|
const bool GetDriverState_Unrecognized_Exception( false);
|
|
assert( GetDriverState_Unrecognized_Exception);
|
|
gdsd.ddRVal= E_UNEXPECTED;
|
|
#endif // !defined( DX8SDDIFW_NOCATCHALL)
|
|
}
|
|
return DDHAL_DRIVER_HANDLED;
|
|
}
|
|
DWORD CreateSurfaceEx( PORTABLE_CREATESURFACEEXDATA& csxd) throw()
|
|
{
|
|
try
|
|
{
|
|
TEntryPointHook EntryPointHook( *sm_pGlobalDriver, "CreateSurfaceEx");
|
|
|
|
TDriver* pSThis= static_cast<TDriver*>(this);
|
|
csxd.ddRVal()= DD_OK;
|
|
|
|
// Upon CreateSurfaceEx, we must detect whether this is a creation
|
|
// or destruction notification and pass it to the associated
|
|
// PerDDrawData.
|
|
|
|
// Get PerDDrawData for this DDraw object.
|
|
typename TPerDDrawDatas::iterator itPerDDrawData( m_PerDDrawDatas.find(
|
|
csxd.lpDDLcl()));
|
|
|
|
if( 0== csxd.lpDDSLcl()->lpGbl()->fpVidMem)
|
|
{ // System Memory Surface Destruction,
|
|
// Pass notification to PerDDrawData, if exists. PerDDraw data
|
|
// will return bool indicating whether to delete it or not.
|
|
if( itPerDDrawData!= m_PerDDrawDatas.end() &&
|
|
itPerDDrawData->second.SurfaceDestroyed( *csxd.lpDDSLcl()))
|
|
m_PerDDrawDatas.erase( itPerDDrawData);
|
|
}
|
|
else
|
|
{ // Video or System Memory Surface Creation
|
|
// If we don't have PerDDrawData for this DDraw object yet,
|
|
// we must create it.
|
|
if( itPerDDrawData== m_PerDDrawDatas.end())
|
|
{
|
|
// Typically, storing pointers to DDRAWI objects is illegal,
|
|
// but this case has been deemed okay. Otherwise, we
|
|
// couldn't have the concept of "per DDraw" data, as
|
|
// "per DDraw" would be hard to figure out; as nothing
|
|
// guarentees uniqueness between the DDRAWI objects, besides
|
|
// the pointers.
|
|
itPerDDrawData= m_PerDDrawDatas.insert(
|
|
TPerDDrawDatas::value_type( csxd.lpDDLcl(),
|
|
TPerDDrawData( *pSThis, *csxd.lpDDLcl())) ).first;
|
|
}
|
|
|
|
// Now pass notification to PerDDrawData.
|
|
// DO NOT STORE csxd.lpDDSLcl. This is considered illegal.
|
|
// It is only valid for the duration of the call.
|
|
itPerDDrawData->second.SurfaceCreated( *csxd.lpDDSLcl());
|
|
}
|
|
} catch( bad_alloc e) {
|
|
csxd.ddRVal()= DDERR_OUTOFMEMORY;
|
|
} catch( HRESULT hr) {
|
|
csxd.ddRVal()= hr;
|
|
#if !defined( DX8SDDIFW_NOCATCHALL)
|
|
} catch( ... ) {
|
|
const bool CreateSurfaceEx_Unrecognized_Exception( false);
|
|
assert( CreateSurfaceEx_Unrecognized_Exception);
|
|
csxd.ddRVal()= E_UNEXPECTED;
|
|
#endif // !defined( DX8SDDIFW_NOCATCHALL)
|
|
}
|
|
return DDHAL_DRIVER_HANDLED;
|
|
}
|
|
DWORD CreateSurface( PORTABLE_CREATESURFACEDATA& csd) throw()
|
|
{
|
|
try
|
|
{
|
|
TEntryPointHook EntryPointHook( *sm_pGlobalDriver, "CreateSurface");
|
|
|
|
TDriver* pSThis= static_cast<TDriver*>(this);
|
|
csd.ddRVal()= DD_OK;
|
|
|
|
// Upon CreateSurface, we must allocate memory for the "video"
|
|
// memory surface and also associate our internal representation
|
|
// with the surface.
|
|
|
|
DWORD dwS( 0);
|
|
try
|
|
{
|
|
// For each surface we're asked to create...
|
|
while( dwS< csd.dwSCnt())
|
|
{
|
|
// Get PerDDrawData for this DDraw object.
|
|
const LPDDRAWI_DIRECTDRAW_LCL pDDLcl(
|
|
csd.lplpSList()[ dwS]->lpSurfMore()->lpDD_lcl());
|
|
typename TPerDDrawDatas::iterator itPerDDrawData(
|
|
m_PerDDrawDatas.find( pDDLcl));
|
|
|
|
// If we don't have PerDDrawData for this DDraw object yet,
|
|
// we must create it.
|
|
if( itPerDDrawData== m_PerDDrawDatas.end())
|
|
{
|
|
// Typically, storing pointers to DDRAWI objects is
|
|
// illegal, but this case has been deemed okay.
|
|
// Otherwise, we couldn't have the concept of
|
|
// "per DDraw" data, as "per DDraw" would be hard to
|
|
// figure out; as nothing guarentees uniqueness
|
|
// between the DDRAWI objects, besides the pointers.
|
|
itPerDDrawData= m_PerDDrawDatas.insert(
|
|
TPerDDrawDatas::value_type( pDDLcl,
|
|
TPerDDrawData( *pSThis, *pDDLcl)) ).first;
|
|
}
|
|
|
|
// Create the new surface, by using the surface allocator.
|
|
// DO NOT STORE csd.lplpSList[ dwS]. This is considered
|
|
// illegal. It is only valid for the duration of the call.
|
|
auto_ptr< TSurface> pNewSurf(
|
|
m_SurfAlloc.CreateSurf( *csd.lpDDSurfaceDesc(),
|
|
*csd.lplpSList()[ dwS]));
|
|
|
|
// Add the pointer to our set of VM surfaces for tracking.
|
|
m_Surfaces.insert( pNewSurf.get());
|
|
|
|
// Bind the internal representation to the DDRAWI object.
|
|
AssociateSurface( *csd.lplpSList()[ dwS], pNewSurf.get());
|
|
|
|
pNewSurf.release();
|
|
dwS++;
|
|
}
|
|
} catch( ... ) {
|
|
// dwS will point to failed alloc, then deallocate the
|
|
// succeeded allocations.
|
|
|
|
// Bind NULL to the DDRAWI object and blank out fpVidMem, just
|
|
// in case.
|
|
AssociateSurface( *csd.lplpSList()[ dwS], NULL);
|
|
csd.lplpSList()[ dwS]->lpGbl()->fpVidMem= NULL;
|
|
if( dwS!= 0) do
|
|
{
|
|
--dwS;
|
|
|
|
TSurface* pSurface= GetSurface( *csd.lplpSList()[ dwS]);
|
|
m_Surfaces.erase( pSurface);
|
|
delete pSurface;
|
|
|
|
// Bind NULL to the DDRAWI object and blank out fpVidMem,
|
|
// to avoid DDraw in thinking the surface was allocated.
|
|
AssociateSurface( *csd.lplpSList()[ dwS], NULL);
|
|
csd.lplpSList()[ dwS]->lpGbl()->fpVidMem= NULL;
|
|
} while( dwS!= 0);
|
|
|
|
throw; // Re-throw the exception.
|
|
}
|
|
|
|
// We wait till CreateSurfaceEx to make the handle association.
|
|
} catch( bad_alloc e) {
|
|
csd.ddRVal()= DDERR_OUTOFMEMORY;
|
|
} catch( HRESULT hr) {
|
|
csd.ddRVal()= hr;
|
|
#if !defined( DX8SDDIFW_NOCATCHALL)
|
|
} catch( ... ) {
|
|
const bool CreateSurface_Unrecognized_Exception( false);
|
|
assert( CreateSurface_Unrecognized_Exception);
|
|
csd.ddRVal()= E_UNEXPECTED;
|
|
#endif // !defined( DX8SDDIFW_NOCATCHALL)
|
|
}
|
|
return DDHAL_DRIVER_HANDLED;
|
|
}
|
|
DWORD DestroySurface( PORTABLE_DESTROYSURFACEDATA& dsd) throw()
|
|
{
|
|
try
|
|
{
|
|
TEntryPointHook EntryPointHook( *sm_pGlobalDriver, "DestroySurface");
|
|
|
|
dsd.ddRVal()= DD_OK;
|
|
|
|
// Retrieve
|
|
TSurface* pSurface= GetSurface( *dsd.lpDDSurface());
|
|
|
|
// Surface object must be destroyed before the DB entry. This is
|
|
// a requirement so that a link (pointer) can safely be
|
|
// established between the DB entry and the object.
|
|
m_Surfaces.erase( pSurface);
|
|
delete pSurface;
|
|
|
|
// Pass destruction notice to PerDDrawData. If it returns true,
|
|
// then PerDDrawData indicates that it should be destroyed.
|
|
typename TPerDDrawDatas::iterator itPerDDrawData( m_PerDDrawDatas.find(
|
|
dsd.lpDDSurface()->lpSurfMore()->lpDD_lcl()));
|
|
if( itPerDDrawData!= m_PerDDrawDatas.end() &&
|
|
itPerDDrawData->second.SurfaceDestroyed( *dsd.lpDDSurface()))
|
|
m_PerDDrawDatas.erase( itPerDDrawData);
|
|
} catch( HRESULT hr) {
|
|
dsd.ddRVal()= hr;
|
|
#if !defined( DX8SDDIFW_NOCATCHALL)
|
|
} catch( ... ) {
|
|
const bool DestroySurface_Unrecognized_Exception( false);
|
|
assert( DestroySurface_Unrecognized_Exception);
|
|
dsd.ddRVal()= E_UNEXPECTED;
|
|
#endif // !defined( DX8SDDIFW_NOCATCHALL)
|
|
}
|
|
return DDHAL_DRIVER_HANDLED;
|
|
}
|
|
DWORD Lock( PORTABLE_LOCKDATA& ld) const throw()
|
|
{
|
|
// Typically, an application requesting a "Lock" of a multisampled
|
|
// surface is not allowed. It would require a MSLock or a new version
|
|
// of Lock to get access to the multisampled bits. However, these
|
|
// surfaces still need to be able to "Present" the bits or "Blt" the
|
|
// bits to the Primary, typically. This requires a workaround:
|
|
// The runtime WILL lock the surface (not for the app), expecting the
|
|
// rasterizer to subsample the multisampled bits into an equivalent
|
|
// non-multisampled area and return this smaller area out of Lock,
|
|
// so that the runtime can "Present" the bits, or whatever.
|
|
|
|
try
|
|
{
|
|
TEntryPointHook EntryPointHook( *sm_pGlobalDriver, "Lock");
|
|
|
|
ld.ddRVal()= DD_OK;
|
|
|
|
// First, retrieve surface object bound to this structure.
|
|
TSurface* pSurface= GetSurface( *ld.lpDDSurface());
|
|
|
|
// Pass control to object's Lock function.
|
|
ld.lpSurfData()= pSurface->Lock( ld.dwFlags(), (ld.bHasRect()?
|
|
&ld.rArea(): NULL));
|
|
} catch( HRESULT hr) {
|
|
ld.ddRVal()= hr;
|
|
#if !defined( DX8SDDIFW_NOCATCHALL)
|
|
} catch( ... ) {
|
|
const bool Lock_Unrecognized_Exception( false);
|
|
assert( Lock_Unrecognized_Exception);
|
|
ld.ddRVal()= E_UNEXPECTED;
|
|
#endif // !defined( DX8SDDIFW_NOCATCHALL)
|
|
}
|
|
return DDHAL_DRIVER_HANDLED;
|
|
}
|
|
DWORD Unlock( PORTABLE_UNLOCKDATA& ud) const throw()
|
|
{
|
|
try
|
|
{
|
|
TEntryPointHook EntryPointHook( *sm_pGlobalDriver, "Unlock");
|
|
|
|
ud.ddRVal()= DD_OK;
|
|
|
|
// First, retrieve surface object bound to this structure.
|
|
TSurface* pSurface= GetSurface( *ud.lpDDSurface());
|
|
|
|
// Pass control to object's Unlock function.
|
|
pSurface->Unlock();
|
|
} catch( HRESULT hr) {
|
|
ud.ddRVal()= hr;
|
|
#if !defined( DX8SDDIFW_NOCATCHALL)
|
|
} catch( ... ) {
|
|
const bool Unlock_Unrecognized_Exception( false);
|
|
assert( Unlock_Unrecognized_Exception);
|
|
ud.ddRVal()= E_UNEXPECTED;
|
|
#endif // !defined( DX8SDDIFW_NOCATCHALL)
|
|
}
|
|
return DDHAL_DRIVER_HANDLED;
|
|
}
|
|
|
|
// Main entry point of driver.
|
|
// Should be called by a bridge function, only.
|
|
HRESULT GetSWInfo( D3DCAPS8& Caps8, D3D8_SWCALLBACKS& Callbacks,
|
|
DWORD& dwNumTextures, DDSURFACEDESC*& pTexList) throw()
|
|
{
|
|
// This static member variable should be initialized to be NULL or
|
|
// point it to the global class.
|
|
assert( NULL== sm_pGlobalDriver|| \
|
|
static_cast< TDriver*>( this)== sm_pGlobalDriver);
|
|
sm_pGlobalDriver= static_cast< TDriver*>( this);
|
|
|
|
Callbacks.CreateContext = ContextCreateStub; // Needed.
|
|
Callbacks.ContextDestroy = ContextDestroyStub; // Needed.
|
|
Callbacks.ContextDestroyAll = ContextDestroyAllStub; // Unused in DX8DDI?
|
|
Callbacks.SceneCapture = SceneCaptureStub; // Unused in DX8DDI, now a render state.
|
|
Callbacks.RenderState = RenderStateStub; // Unused in DX8DDI?
|
|
Callbacks.RenderPrimitive = RenderPrimitiveStub; // Unused in DX8DDI?
|
|
Callbacks.TextureCreate = TextureCreateStub; // Unused in DX8DDI?
|
|
Callbacks.TextureDestroy = TextureDestroyStub; // Unused in DX8DDI?
|
|
Callbacks.TextureSwap = TextureSwapStub; // Unused in DX8DDI?
|
|
Callbacks.TextureGetSurf = TextureGetSurfStub; // Unused in DX8DDI?
|
|
Callbacks.GetState = GetStateStub; // Unused in DX8DDI?
|
|
Callbacks.SetRenderTarget = SetRenderTargetStub; // Unused in DX8DDI?
|
|
Callbacks.Clear = ClearStub; // Unused in DX8DDI?
|
|
Callbacks.DrawOnePrimitive = DrawOnePrimitiveStub; // Unused in DX8DDI?
|
|
Callbacks.DrawOneIndexedPrimitive = DrawOneIndexedPrimitiveStub; // Unused in DX8DDI?
|
|
Callbacks.DrawPrimitives = DrawPrimitivesStub; // Unused in DX8DDI?
|
|
Callbacks.Clear2 = Clear2Stub; // Unused in DX8DDI?
|
|
Callbacks.ValidateTextureStageState= ValidateTextureStageStateStub; // Optional?
|
|
Callbacks.DrawPrimitives2 = DrawPrimitives2Stub; // Needed.
|
|
Callbacks.GetDriverState = GetDriverStateStub; // Optional?
|
|
Callbacks.CreateSurfaceEx = CreateSurfaceExStub; // Needed.
|
|
Callbacks.CreateSurface = CreateSurfaceStub; // Needed.
|
|
Callbacks.DestroySurface = DestroySurfaceStub; // Needed.
|
|
Callbacks.Lock = LockStub; // Needed.
|
|
Callbacks.Unlock = UnlockStub; // Needed.
|
|
|
|
try {
|
|
Caps8= sm_pGlobalDriver->GetCaps();
|
|
|
|
// There needs to be support for some surfaces, at least.
|
|
assert( !m_SupportedSurfaces.empty());
|
|
|
|
dwNumTextures= m_SupportedSurfaces.size();
|
|
pTexList= &(*m_SupportedSurfaces.begin());
|
|
} catch( bad_alloc ba) {
|
|
return E_OUTOFMEMORY;
|
|
} catch( HRESULT hr) {
|
|
return hr;
|
|
#if !defined( DX8SDDIFW_NOCATCHALL)
|
|
} catch( ... ) {
|
|
return E_UNEXPECTED;
|
|
#endif // !defined( DX8SDDIFW_NOCATCHALL)
|
|
}
|
|
return S_OK;
|
|
}
|
|
};
|
|
|
|
template< class TD, class TR>
|
|
class CMinimalDriver:
|
|
public CSubDriver< TD, CMinimalContext< CMinimalPerDDrawData< TD>, TR> >
|
|
{
|
|
public: // Types
|
|
typedef TR TRasterizer;
|
|
|
|
protected:
|
|
template< class TIter> // DDSURFACEDESC*
|
|
CMinimalDriver( TIter itStart, const TIter itEnd) :
|
|
CSubDriver< TD, TContext>( itStart, itEnd)
|
|
{ /* TODO: Check caps? */ }
|
|
~CMinimalDriver()
|
|
{ }
|
|
};
|
|
|
|
#if !defined( DX8SDDIFW_NONAMESPACE)
|
|
}
|
|
#endif // !defined( DX8SDDIFW_NONAMESPACE)
|