//////////////////////////////////////////////////////////////////////////////// // // 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): // wStateCount; break; //case( D3DDP2OP_LINELIST): // wStateCount; break; //case( D3DDP2OP_INDEXEDTRIANGLELIST2): // 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 (reinterpret_cast(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. // //