// NeL - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #ifndef NL_DRIVER_DIRECT3D_H #define NL_DRIVER_DIRECT3D_H #include "nel/misc/types_nl.h" // NeL includes #include "nel/misc/matrix.h" #include "nel/misc/smart_ptr.h" #include "nel/misc/rgba.h" #include "nel/misc/event_emitter.h" #include "nel/misc/bit_set.h" #include "nel/misc/heap_memory.h" #include "nel/misc/event_emitter_multi.h" #include "nel/misc/time_nl.h" #include "nel/misc/hierarchical_timer.h" #include "nel/misc/win_event_emitter.h" #include "nel/3d/viewport.h" #include "nel/3d/scissor.h" #include "nel/3d/driver.h" #include "nel/3d/material.h" #include "nel/3d/vertex_buffer.h" #include "nel/3d/index_buffer.h" #include "nel/3d/ptr_set.h" #include "nel/3d/texture_cube.h" #include "nel/3d/occlusion_query.h" #include "nel/3d/vertex_program_parse.h" #include "nel/3d/light.h" // #include typedef HCURSOR nlCursor; #define EmptyCursor NULL // *** DEBUG MACRO // Define this to activate the debug mode (default is undefined) //#define NL_DEBUG_D3D // Define this to enable the render state caching (default is defined) #define NL_D3D_USE_RENDER_STATE_CACHE // allows to enable / disable cache test at runtime (for debug) //#define NL_D3D_RUNTIME_DEBUG_CACHE_TEST #ifdef NL_D3D_RUNTIME_DEBUG_CACHE_TEST #define NL_D3D_CACHE_TEST(label, cond) if (!_CacheTest[label] || (cond)) #else #define NL_D3D_CACHE_TEST(label, cond) if (cond) #endif // Define this to disable hardware vertex program (default is undefined) //#define NL_DISABLE_HARDWARE_VERTEX_PROGAM // Define this to disable hardware pixel shaders program (default is undefined) //#define NL_DISABLE_HARDWARE_PIXEL_SHADER // Define this to disable hardware vertex array AGP (default is undefined) //#define NL_DISABLE_HARDWARE_VERTEX_ARRAY_AGP // Define this to force the texture stage count (default is undefined) //#define NL_FORCE_TEXTURE_STAGE_COUNT 2 // Define this to force the use of pixel shader in the normal shaders (default is undefined) //#define NL_FORCE_PIXEL_SHADER_USE_FOR_NORMAL_SHADERS // Define this to enable profiling by the NV Perf HUD tool (default is undefined) //#define NL_D3D_USE_NV_PERF_HUD // Define this to enable profiling of driver functions (default is undefined). //#define NL_PROFILE_DRIVER_D3D #ifdef NL_PROFILE_DRIVER_D3D #define H_AUTO_D3D(label) H_AUTO(label) #else #define H_AUTO_D3D(label) #endif class CFpuRestorer { public: CFpuRestorer() { _FPControlWord = _controlfp(0, 0); } ~CFpuRestorer() { _controlfp(_FPControlWord, ~0); } private: unsigned int _FPControlWord; }; class CFpuChecker { public: CFpuChecker(const char *label) { _FPControlWord = _controlfp(0, 0); _Label = label; } ~CFpuChecker() { unsigned int newFP = _controlfp(0, 0); if ((newFP & (_MCW_DN | _MCW_IC | _MCW_RC | _MCW_PC)) != (_FPControlWord & (_MCW_DN | _MCW_IC | _MCW_RC | _MCW_PC))) { nlwarning(_Label); nlassert(0); } } private: const char *_Label; unsigned int _FPControlWord; }; inline bool operator==(const D3DCOLORVALUE &lhs, const D3DCOLORVALUE &rhs) { return lhs.r == rhs.r && lhs.g == rhs.g && lhs.b == rhs.b && lhs.a == rhs.a; } inline bool operator!=(const D3DCOLORVALUE &lhs, const D3DCOLORVALUE &rhs) { return !(lhs == rhs); } // *************************************************************************** namespace NL3D { const uint MAX_NUM_QUADS = 32767; // max number of quads in a single draw call using NLMISC::CMatrix; using NLMISC::CVector; class CDriverD3D; class CTextureDrvInfosD3D; class COcclusionQueryD3D; class CVolatileVertexBuffer; class CVolatileIndexBuffer; typedef std::list TOcclusionQueryList; // *************************************************************************** class COcclusionQueryD3D : public IOcclusionQuery { public: IDirect3DQuery9 *Query; NLMISC::CRefPtr Driver; // owner driver TOcclusionQueryList::iterator Iterator; // iterator in owner driver list of queries TOcclusionType OcclusionType; // current type of occlusion uint VisibleCount; // number of samples that passed the test bool QueryIssued; bool WasLost; // tells that query was lost, so calls to end() will have not effects (there's no matching begin) // From IOcclusionQuery virtual void begin(); virtual void end(); virtual TOcclusionType getOcclusionType(); virtual uint getVisibleCount(); }; using NLMISC::CRefCount; class IDriver; class CDriverD3D; // List typedef. class IShaderDrvInfos; typedef std::list TShaderDrvInfoPtrList; typedef TShaderDrvInfoPtrList::iterator ItShaderDrvInfoPtrList; /** * Interface for shader driver infos. */ class IShaderDrvInfos : public CRefCount { private: CDriverD3D *_Driver; ItShaderDrvInfoPtrList _DriverIterator; public: IShaderDrvInfos(CDriverD3D *drv, ItShaderDrvInfoPtrList it) {_Driver= drv; _DriverIterator= it;} // The virtual dtor is important. virtual ~IShaderDrvInfos(); }; /** * Shader resource for the driver. It is just a container for a ".fx" text file. */ /* *** IMPORTANT ******************** * *** IF YOU MODIFY THE STRUCTURE OF THIS CLASS, PLEASE INCREMENT IDriver::InterfaceVersion TO INVALIDATE OLD DRIVER DLL * ********************************** */ // -------------------------------------------------- class CD3DShaderFX { public: CD3DShaderFX(); ~CD3DShaderFX(); // Load a shader file bool loadShaderFile (const char *filename); // Set the shader text void setText (const char *text); // Get the shader text const char *getText () const { return _Text.c_str(); } // Set the shader name void setName (const char *name); // Get the shader name const char *getName () const { return _Name.c_str(); } public: // Private. For Driver only. bool _ShaderChanged; NLMISC::CRefPtr _DrvInfo; private: // The shader std::string _Text; // The shader name std::string _Name; }; // *************************************************************************** class CTextureDrvInfosD3D : public ITextureDrvInfos { public: /* ANY DATA ADDED HERE MUST BE SWAPPED IN swapTextureHandle() !! */ // The texture LPDIRECT3DBASETEXTURE9 Texture; IDirect3DTexture9 *Texture2d; IDirect3DCubeTexture9 *TextureCube; // The texture format and size D3DFORMAT DestFormat; uint Width; uint Height; // This is the owner driver. CDriverD3D *_Driver; // Is the internal format of the texture is a compressed one? bool SrcCompressed; bool IsCube; // Is a render target ? bool RenderTarget; // Mipmap levels uint8 Levels; uint8 FirstMipMap; // This is the computed size of what memory this texture take. uint32 TextureMemory; // The current wrap modes assigned to the texture. D3DTEXTUREADDRESS WrapS; D3DTEXTUREADDRESS WrapT; D3DTEXTUREFILTERTYPE MagFilter; D3DTEXTUREFILTERTYPE MinFilter; D3DTEXTUREFILTERTYPE MipFilter; CTextureDrvInfosD3D(IDriver *drv, ItTexDrvInfoPtrMap it, CDriverD3D *drvGl, bool renderTarget); ~CTextureDrvInfosD3D(); virtual uint getTextureMemoryUsed() const {return TextureMemory;} }; // *************************************************************************** class CVertexProgamDrvInfosD3D : public IProgramDrvInfos { public: // The shader IDirect3DVertexShader9 *Shader; CVertexProgamDrvInfosD3D(IDriver *drv, ItGPUPrgDrvInfoPtrList it); ~CVertexProgamDrvInfosD3D(); virtual uint getUniformIndex(const char *name) const { std::map::const_iterator it = ParamIndices.find(name); if (it != ParamIndices.end()) return it->second; return ~0; }; std::map ParamIndices; }; // *************************************************************************** class CPixelProgramDrvInfosD3D : public IProgramDrvInfos { public: // The shader IDirect3DPixelShader9 *Shader; CPixelProgramDrvInfosD3D(IDriver *drv, ItGPUPrgDrvInfoPtrList it); ~CPixelProgramDrvInfosD3D(); virtual uint getUniformIndex(const char *name) const { std::map::const_iterator it = ParamIndices.find(name); if (it != ParamIndices.end()) return it->second; return ~0; }; std::map ParamIndices; }; // *************************************************************************** class CVertexDeclaration { public: // The human readable values D3DVERTEXELEMENT9 VertexElements[CVertexBuffer::NumValue+1]; // The driver pointer IDirect3DVertexDeclaration9 *VertexDecl; }; // *************************************************************************** class CVBDrvInfosD3D : public IVBDrvInfos { public: IDirect3DVertexDeclaration9 *VertexDecl; IDirect3DVertexDeclaration9 *VertexDeclAliasDiffuseToSpecular; IDirect3DVertexDeclaration9 *VertexDeclNoDiffuse; uint ColorOffset; // Fix for Radeon 7xxx series -> see remarks in CDriverD3D::createVertexDeclaration IDirect3DVertexBuffer9 *VertexBuffer; uint Offset; // Vertex buffer offset bool UseVertexColor:1; bool Hardware:1; bool Volatile:1; // Volatile vertex buffer bool VolatileRAM:1; uint8 Stride:8; uint VolatileLockTime; // Volatile vertex buffer DWORD Usage; CVolatileVertexBuffer *VolatileVertexBuffer; CDriverD3D *Driver; #ifdef NL_DEBUG bool Locked; #endif CVBDrvInfosD3D(CDriverD3D *drv, ItVBDrvInfoPtrList it, CVertexBuffer *vb); virtual ~CVBDrvInfosD3D(); virtual uint8 *lock (uint first, uint last, bool readOnly); virtual void unlock (uint first, uint last); }; // *************************************************************************** class CIBDrvInfosD3D : public IIBDrvInfos { public: IDirect3DIndexBuffer9 *IndexBuffer; uint Offset; // Index buffer offset bool Volatile:1; // Volatile index buffer bool VolatileRAM:1; uint VolatileLockTime; // Volatile index buffer CVolatileIndexBuffer *VolatileIndexBuffer; CDriverD3D *Driver; std::vector RamVersion; // If device doesn't support 32 bit indexes, works in ram (unless it a 16 bit index buffer) CIBDrvInfosD3D(CDriverD3D *drv, ItIBDrvInfoPtrList it, CIndexBuffer *ib); virtual ~CIBDrvInfosD3D(); virtual void *lock (uint first, uint last, bool readOnly); virtual void unlock (uint first, uint last); }; // *************************************************************************** class CShaderDrvInfosD3D : public IShaderDrvInfos { public: enum { MaxShaderTexture=8, }; ID3DXEffect *Effect; bool Validated; // Texture handles D3DXHANDLE TextureHandle[MaxShaderTexture]; // Color handles D3DXHANDLE ColorHandle[MaxShaderTexture]; // Factor handles D3DXHANDLE FactorHandle[MaxShaderTexture]; // Scalar handles D3DXHANDLE ScalarFloatHandle[MaxShaderTexture]; CShaderDrvInfosD3D(CDriverD3D *drv, ItShaderDrvInfoPtrList it); virtual ~CShaderDrvInfosD3D(); }; // *************************************************************************** // Normal shader description class CNormalShaderDesc { public: CNormalShaderDesc () { H_AUTO_D3D(CNormalShaderDesc_CNormalShaderDesc); memset (this, 0, sizeof(CNormalShaderDesc)); } ~CNormalShaderDesc () { if (PixelShader) PixelShader->Release(); } bool StageUsed[IDRV_MAT_MAXTEXTURES]; uint32 TexEnvMode[IDRV_MAT_MAXTEXTURES]; bool operator==(const CNormalShaderDesc &other) const { uint i; for (i=0; i Allocator; }; // record of a single .fx pass class CFXPassRecord { public: void apply(class CDriverD3D &drv); ~CFXPassRecord(); std::vector States; }; template class CFXInputValue { public: T Value; bool Set; CFXInputValue() : Set(false) {} void reset(); bool operator==(const CFXInputValue &other) { if (!Set) return !(other.Set); return (Value == other.Value) != 0; } }; class CFXInputParams { public: enum { MaxNumParams = CShaderDrvInfosD3D::MaxShaderTexture }; CFXInputValue Textures[MaxNumParams]; CFXInputValue Colors[MaxNumParams]; CFXInputValue Vectors[MaxNumParams]; CFXInputValue Floats[MaxNumParams]; bool Touched; public: CFXInputParams() { Touched = true; } void setTexture(uint index, LPDIRECT3DBASETEXTURE9 value) { nlassert(index < MaxNumParams); if (!Textures[index].Set || value != Textures[index].Value) { Textures[index].Value = value; Textures[index].Set = true; Touched = true; } } void setColor(uint index, DWORD value) { nlassert(index < MaxNumParams); if (!Colors[index].Set || value != Colors[index].Value) { Colors[index].Value = value; Colors[index].Set = true; Touched = true; } } void setVector(uint index, const D3DXVECTOR4 &value) { nlassert(index < MaxNumParams); if (!Vectors[index].Set || value != Vectors[index].Value) { Vectors[index].Value = value; Vectors[index].Set = true; Touched = true; } } void setFloat(uint index, FLOAT value) { nlassert(index < MaxNumParams); if (!Floats[index].Set || value != Floats[index].Value) { Floats[index].Value = value; Floats[index].Set = true; Touched = true; } } // /* bool operator==(const CFXInputParams &other) { return std::equal(Textures, Textures + CShaderDrvInfosD3D::MaxShaderTexture, other.Textures) && std::equal(Vectors, Vectors + CShaderDrvInfosD3D::MaxShaderTexture, other.Vectors) && std::equal(Colors, Colors + CShaderDrvInfosD3D::MaxShaderTexture, other.Colors) && std::equal(Floats, Floats + CShaderDrvInfosD3D::MaxShaderTexture, other.Floats); } */ void reset() { for(uint k = 0; k < MaxNumParams; ++k) { Textures[k].Set = false; Colors[k].Set = false; Vectors[k].Set = false; Floats[k].Set = false; } Touched = true; } }; // .fx cache based on input parameters class CFXCache { public: // Input parameters CFXInputParams Params; // cache for .fx states std::vector Passes; uint Steadyness; uint NumPasses; public: CFXCache() : Steadyness(0) {} void begin(CShaderDrvInfosD3D *si, class CDriverD3D *driver); void applyPass(class CDriverD3D &drv, CShaderDrvInfosD3D *si, uint passIndex); void end(CShaderDrvInfosD3D *si); void reset(); void setConstants(CShaderDrvInfosD3D *si); }; // optimisation of an effect 2 class CFXPassRecorder : public ID3DXEffectStateManager { public: CFXPassRecord *Target; class CDriverD3D *Driver; public: CFXPassRecorder() : Target(NULL), Driver(NULL) {} HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID *ppvObj); ULONG STDMETHODCALLTYPE AddRef(VOID); ULONG STDMETHODCALLTYPE Release(VOID); HRESULT STDMETHODCALLTYPE LightEnable(DWORD Index, BOOL Enable); HRESULT STDMETHODCALLTYPE SetFVF(DWORD FVF); HRESULT STDMETHODCALLTYPE SetLight(DWORD Index, CONST D3DLIGHT9* pLight); HRESULT STDMETHODCALLTYPE SetMaterial(CONST D3DMATERIAL9* pMaterial); HRESULT STDMETHODCALLTYPE SetNPatchMode(FLOAT nSegments); HRESULT STDMETHODCALLTYPE SetPixelShader(LPDIRECT3DPIXELSHADER9 pShader); HRESULT STDMETHODCALLTYPE SetPixelShaderConstantB(UINT StartRegister, CONST BOOL* pConstantData, UINT RegisterCount); HRESULT STDMETHODCALLTYPE SetPixelShaderConstantF(UINT StartRegister, CONST FLOAT* pConstantData, UINT RegisterCount); HRESULT STDMETHODCALLTYPE SetPixelShaderConstantI(UINT StartRegister, CONST INT* pConstantData, UINT RegisterCount); HRESULT STDMETHODCALLTYPE SetRenderState(D3DRENDERSTATETYPE State, DWORD Value); HRESULT STDMETHODCALLTYPE SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value); HRESULT STDMETHODCALLTYPE SetTexture (DWORD Stage, LPDIRECT3DBASETEXTURE9 pTexture); HRESULT STDMETHODCALLTYPE SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value); HRESULT STDMETHODCALLTYPE SetTransform(D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix); HRESULT STDMETHODCALLTYPE SetVertexShader(LPDIRECT3DVERTEXSHADER9 pShader); HRESULT STDMETHODCALLTYPE SetVertexShaderConstantB(UINT StartRegister, CONST BOOL* pConstantData, UINT RegisterCount); HRESULT STDMETHODCALLTYPE SetVertexShaderConstantF(UINT StartRegister, CONST FLOAT* pConstantData, UINT RegisterCount); HRESULT STDMETHODCALLTYPE SetVertexShaderConstantI(UINT StartRegister, CONST INT* pConstantData, UINT RegisterCount); }; // *************************************************************************** struct CMaterialDrvInfosD3D : public IMaterialDrvInfos { public: D3DMATERIAL9 Material; D3DCOLOR UnlightedColor; BOOL SpecularEnabled; D3DBLEND SrcBlend; D3DBLEND DstBlend; D3DCMPFUNC ZComp; DWORD AlphaRef; D3DTEXTUREOP ColorOp[IDRV_MAT_MAXTEXTURES]; DWORD ColorArg0[IDRV_MAT_MAXTEXTURES]; DWORD ColorArg1[IDRV_MAT_MAXTEXTURES]; DWORD ColorArg2[IDRV_MAT_MAXTEXTURES]; uint NumColorArg[IDRV_MAT_MAXTEXTURES]; uint NumAlphaArg[IDRV_MAT_MAXTEXTURES]; D3DTEXTUREOP AlphaOp[IDRV_MAT_MAXTEXTURES]; DWORD AlphaArg0[IDRV_MAT_MAXTEXTURES]; DWORD AlphaArg1[IDRV_MAT_MAXTEXTURES]; DWORD AlphaArg2[IDRV_MAT_MAXTEXTURES]; D3DCOLOR ConstantColor[IDRV_MAT_MAXTEXTURES]; DWORD TexGen[IDRV_MAT_MAXTEXTURES]; IDirect3DPixelShader9 *PixelShader; IDirect3DPixelShader9 *PixelShaderUnlightedNoVertexColor; bool ActivateSpecularWorldTexMT[IDRV_MAT_MAXTEXTURES]; bool ActivateInvViewModelTexMT[IDRV_MAT_MAXTEXTURES]; bool VertexColorLighted; bool NeedsConstantForDiffuse; // Must use TFactor if not vertex color in the vertex buffer bool MultipleConstantNoPixelShader; // Multiple constant are possibly needed to setup the material. This flag is set only if the device has no pixel shaders // In this case diffuse color will be emulated by using an unlighted material with ambient bool MultiplePerStageConstant; // Are there more than one per-stage constant in the material ? uint8 ConstantIndex; // Index of the constant color to use (when only one constant color is needed and NeedsConstantForDiffuse == false); uint8 ConstantIndex2; // stage at which the 2nd constant is used (for emulation without pixel shaders) CRGBA Constant2; // value of the 2nd constant being used (for emulation without pixel shaders) uint NumUsedTexStages; // Last number of textures that were set in the material // Tex Env are only built for stages at which textures are set so if the number of used texture // change they must be rebuilt // Relevant parts of the pixel pipe for normal shader bool RGBPipe[IDRV_MAT_MAXTEXTURES]; bool AlphaPipe[IDRV_MAT_MAXTEXTURES]; CFXCache *FXCache; CMaterialDrvInfosD3D(IDriver *drv, ItMatDrvInfoPtrList it) : IMaterialDrvInfos(drv, it) { H_AUTO_D3D(CMaterialDrvInfosD3D_CMaterialDrvInfosD3D); PixelShader = NULL; PixelShaderUnlightedNoVertexColor = NULL; std::fill(RGBPipe, RGBPipe + IDRV_MAT_MAXTEXTURES, true); std::fill(AlphaPipe, AlphaPipe + IDRV_MAT_MAXTEXTURES, true); FXCache = NULL; NumUsedTexStages = 0; } ~CMaterialDrvInfosD3D() { delete FXCache; } void buildTexEnv (uint stage, const CMaterial::CTexEnv &env, bool textured); }; // // *************************************************************************** /* Volatile buffers. * * The volatile buffer system is a double buffer allocated during the render pass by objects that needs * a temporary buffer to render vertex or indexes. Each lock allocates a buffer region * and locks it with the NOOVERWRITE flag. Locks are not blocked. The buffer is reset at each frame begin. * There is a double buffer to take benefit of the "over swapbuffer" parallelisme. */ // *************************************************************************** class CVolatileVertexBuffer { public: CVolatileVertexBuffer(); ~CVolatileVertexBuffer(); CDriverD3D *Driver; IDirect3DVertexBuffer9 *VertexBuffer; uint Size; CVertexBuffer::TLocation Location; uint CurrentIndex; uint MaxSize; bool Locked; /* size is in bytes */ void init (CVertexBuffer::TLocation location, uint size, uint maxSize, CDriverD3D *driver); void release (); // Runtime buffer access, no-blocking lock. void *lock (uint size, uint stride, uint &offset); void unlock (); // Runtime reset (called at the beginning of the frame rendering), blocking lock here. void reset (); }; // *************************************************************************** class CVolatileIndexBuffer { public: CVolatileIndexBuffer(); ~CVolatileIndexBuffer(); CDriverD3D *Driver; IDirect3DIndexBuffer9 *IndexBuffer; uint Size; CIndexBuffer::TLocation Location; // current position in bytes! uint CurrentIndex; uint MaxSize; bool Locked; CIndexBuffer::TFormat Format; /* size is in bytes */ void init (CIndexBuffer::TLocation location, uint sizeInBytes, uint maxSize, CDriverD3D *driver, CIndexBuffer::TFormat format); void release (); // Runtime buffer access, no-blocking lock. Re void *lock (uint size, uint &offset); void unlock (); // Runtime reset (called at the beginning of the frame rendering), blocking lock here. void reset (); }; // *************************************************************************** class CDriverD3D : public IDriver, public ID3DXEffectStateManager { public: enum { CacheTest_CullMode = 0, CacheTest_RenderState = 1, CacheTest_TextureState = 2, CacheTest_TextureIndexMode = 3, CacheTest_TextureIndexUV = 4, CacheTest_Texture = 5, CacheTest_VertexProgram = 6, CacheTest_PixelShader = 7, CacheTest_VertexProgramConstant = 8, CacheTest_PixelShaderConstant = 9, CacheTest_SamplerState = 10, CacheTest_VertexBuffer = 11, CacheTest_IndexBuffer = 12, CacheTest_VertexDecl = 13, CacheTest_Matrix = 14, CacheTest_RenderTarget = 15, CacheTest_MaterialState = 16, CacheTest_DepthRange = 17, CacheTest_Count }; // Some constants enum { MaxLight=8, MaxRenderState=256, MaxTextureState=36, MaxTexture=8, MaxSamplerState=16, MaxSampler=8, MatrixStateRemap = 24, MaxMatrixState=32, MaxVertexProgramConstantState=96, MaxPixelShaderConstantState=96, }; // Prefered pixel formats enum { // Number of pixel format choice for each pixel format FinalPixelFormatChoice = 5, }; // Construction / destruction CDriverD3D(); virtual ~CDriverD3D(); virtual bool isLost() const { return _Lost; } // *************************************************************************** // Implementation // see nel\src\3d\driver.h // *************************************************************************** // Mode initialisation, requests virtual bool init (uintptr_t windowIcon = 0, emptyProc exitFunc = 0); virtual bool setDisplay(nlWindow wnd, const GfxMode& mode, bool show, bool resizeable) throw(EBadDisplay); virtual bool release(); virtual bool setMode(const GfxMode& mode); virtual bool getModes(std::vector &modes); virtual bool getCurrentScreenMode(GfxMode &mode); virtual void beginDialogMode(); virtual void endDialogMode(); virtual bool activate(); virtual bool isActive (); virtual bool initVertexBufferHard(uint agpMem, uint vramMem); // Windows interface virtual nlWindow getDisplay(); virtual emptyProc getWindowProc(); virtual NLMISC::IEventEmitter *getEventEmitter(); virtual void getWindowSize (uint32 &width, uint32 &height); virtual void getWindowPos (sint32 &x, sint32 &y); virtual uint8 getBitPerPixel (); /// Set the title of the NeL window virtual void setWindowTitle(const ucstring &title); /// Set icon(s) of the NeL window virtual void setWindowIcon(const std::vector &bitmaps); /// Set the position of the NeL window virtual void setWindowPos(sint32 x, sint32 y); /// Show or hide the NeL window virtual void showWindow(bool show); // Driver parameters virtual void disableHardwareVertexProgram(); virtual void disableHardwarePixelProgram(); virtual void disableHardwareIndexArrayAGP(); virtual void disableHardwareVertexArrayAGP(); virtual void disableHardwareTextureShader(); virtual void forceDXTCCompression(bool dxtcComp); virtual void setAnisotropicFilter(sint filter); virtual void forceTextureResize(uint divisor); // Driver information virtual uint getNumAdapter() const; virtual bool getAdapter(uint adapter, CAdapter &desc) const; virtual bool setAdapter(uint adapter); virtual uint32 getAvailableVertexAGPMemory (); virtual uint32 getAvailableVertexVRAMMemory (); virtual uint getNbTextureStages() const; virtual void getNumPerStageConstant(uint &lightedMaterial, uint &unlightedMaterial) const; virtual bool supportVertexBufferHard() const; virtual bool supportVolatileVertexBuffer() const; virtual bool supportIndexBufferHard() const; // todo hulud d3d vertex buffer hard virtual bool slowUnlockVertexBufferHard() const {return false;}; virtual uint getMaxVerticesByVertexBufferHard() const; virtual uint32 getImplementationVersion () const; virtual const char* getDriverInformation (); virtual const char* getVideocardInformation (); virtual CVertexBuffer::TVertexColorType getVertexColorFormat() const; // Textures virtual bool isTextureExist(const ITexture&tex); virtual bool setupTexture (ITexture& tex); virtual bool setupTextureEx (ITexture& tex, bool bUpload, bool &bAllUploaded, bool bMustRecreateSharedTexture= false); virtual bool uploadTexture (ITexture& tex, NLMISC::CRect& rect, uint8 nNumMipMap); // todo hulud d3d texture virtual bool uploadTextureCube (ITexture& /* tex */, NLMISC::CRect& /* rect */, uint8 /* nNumMipMap */, uint8 /* nNumFace */) {return false;}; // Material virtual bool setupMaterial(CMaterial& mat); virtual bool supportCloudRenderSinglePass () const; // Buffer virtual bool clear2D(CRGBA rgba); virtual bool clearZBuffer(float zval=1); virtual bool clearStencilBuffer(float stencilval=0); virtual void setColorMask (bool bRed, bool bGreen, bool bBlue, bool bAlpha); virtual bool swapBuffers(); virtual void getBuffer (CBitmap &bitmap); // Only 32 bits back buffer supported virtual void setDepthRange(float znear, float zfar); virtual void getDepthRange(float &znear, float &zfar) const; virtual void getZBuffer (std::vector &zbuffer); virtual void getBufferPart (CBitmap &bitmap, NLMISC::CRect &rect); // return true if driver support Bloom effect. virtual bool supportBloomEffect() const; // return true if driver support non-power of two textures virtual bool supportNonPowerOfTwoTextures() const; // copy the first texture in a second one of different dimensions virtual bool stretchRect (ITexture * srcText, NLMISC::CRect &srcRect, ITexture * destText, NLMISC::CRect &destRect); // Only 32 bits back buffer supported virtual bool isTextureRectangle(ITexture * /* tex */) const {return false;} IDirect3DSurface9* getSurfaceTexture(ITexture * text); void getDirect3DRect(NLMISC::CRect &rect, RECT & d3dRect); // todo hulud d3d buffers virtual void getZBufferPart (std::vector &zbuffer, NLMISC::CRect &rect); virtual bool setRenderTarget (ITexture *tex, uint32 x, uint32 y, uint32 width, uint32 height, uint32 mipmapLevel, uint32 cubeFace); virtual ITexture *getRenderTarget() const; virtual bool copyTargetToTexture (ITexture *tex, uint32 offsetx, uint32 offsety, uint32 x, uint32 y, uint32 width, uint32 height, uint32 mipmapLevel); virtual bool textureCoordinateAlternativeMode() const { return true; }; virtual bool getRenderTargetSize (uint32 &width, uint32 &height); virtual bool fillBuffer (CBitmap &bitmap); // Performances virtual void startSpecularBatch(); virtual void endSpecularBatch(); virtual void setSwapVBLInterval(uint interval); virtual uint getSwapVBLInterval(); virtual void swapTextureHandle(ITexture &tex0, ITexture &tex1); virtual uintptr_t getTextureHandle(const ITexture&tex); // Matrix, viewport and frustum virtual void setFrustum(float left, float right, float bottom, float top, float znear, float zfar, bool perspective = true); virtual void setFrustumMatrix(CMatrix &frust); virtual CMatrix getFrustumMatrix(); virtual float getClipSpaceZMin() const { return 0.f; } virtual void setupViewMatrix(const CMatrix& mtx); virtual void setupViewMatrixEx(const CMatrix& mtx, const CVector &cameraPos); virtual void setupModelMatrix(const CMatrix& mtx); virtual CMatrix getViewMatrix() const; virtual void forceNormalize(bool normalize); virtual bool isForceNormalize() const; virtual void setupScissor (const class CScissor& scissor); virtual void setupViewport (const class CViewport& viewport); virtual void getViewport(CViewport &viewport); // Vertex buffers virtual bool activeVertexBuffer(CVertexBuffer& VB); // Index buffers virtual bool activeIndexBuffer(CIndexBuffer& IB); // UV virtual void mapTextureStageToUV(uint stage, uint uv); // Indexed primitives virtual bool renderLines(CMaterial& mat, uint32 firstIndex, uint32 nlines); virtual bool renderTriangles(CMaterial& Mat, uint32 firstIndex, uint32 ntris); virtual bool renderSimpleTriangles(uint32 firstTri, uint32 ntris); // Indexed primitives with index offset virtual bool renderLinesWithIndexOffset(CMaterial& mat, uint32 firstIndex, uint32 nlines, uint indexOffset); virtual bool renderTrianglesWithIndexOffset(CMaterial& mat, uint32 firstIndex, uint32 ntris, uint indexOffset); virtual bool renderSimpleTrianglesWithIndexOffset(uint32 firstIndex, uint32 ntris, uint indexOffset); // Unindexed primitives with index offset virtual bool renderRawPoints(CMaterial& Mat, uint32 startIndex, uint32 numPoints); virtual bool renderRawLines(CMaterial& Mat, uint32 startIndex, uint32 numLines); virtual bool renderRawTriangles(CMaterial& Mat, uint32 startIndex, uint32 numTris); virtual bool renderRawQuads(CMaterial& Mat, uint32 startIndex, uint32 numQuads); // virtual void setPolygonMode (TPolygonMode mode); virtual void finish(); virtual void flush(); // Profile virtual void profileRenderedPrimitives(CPrimitiveProfile &pIn, CPrimitiveProfile &pOut); virtual uint32 profileAllocatedTextureMemory(); virtual uint32 profileSetupedMaterials() const; virtual uint32 profileSetupedModelMatrix() const; virtual void enableUsedTextureMemorySum (bool enable); virtual uint32 getUsedTextureMemory() const; virtual void startProfileVBHardLock(); virtual void endProfileVBHardLock(std::vector &result); virtual void profileVBHardAllocation(std::vector &result); virtual void startProfileIBLock(); virtual void endProfileIBLock(std::vector &result); virtual void profileIBAllocation(std::vector &result); //virtual void profileIBAllocation(std::vector &result); // Misc virtual TMessageBoxId systemMessageBox (const char* message, const char* title, TMessageBoxType type=okType, TMessageBoxIcon icon=noIcon); virtual uint64 getSwapBufferCounter() const { return _SwapBufferCounter; } // Inputs virtual void showCursor (bool b); virtual void setMousePos(float x, float y); virtual void setCapture (bool b); // see if system cursor is currently captured virtual bool isSystemCursorCaptured(); // Add a new cursor (name is case unsensitive) virtual void addCursor(const std::string &name, const NLMISC::CBitmap &bitmap); // Display a cursor from its name (case unsensitive) virtual void setCursor(const std::string &name, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY, bool forceRebuild = false); // Change default scale for all cursors virtual void setCursorScale(float scale); // Lights virtual uint getMaxLight () const; virtual void setLight (uint8 num, const CLight& light); virtual void enableLight (uint8 num, bool enable=true); virtual void setLightMapDynamicLight (bool enable, const CLight& light); // todo hulud d3d light virtual void setPerPixelLightingLight(CRGBA /* diffuse */, CRGBA /* specular */, float /* shininess */) {} virtual void setAmbientColor (CRGBA color); // Fog virtual bool fogEnabled(); virtual void enableFog(bool enable); virtual void setupFog(float start, float end, CRGBA color); virtual float getFogStart() const; virtual float getFogEnd() const; virtual CRGBA getFogColor() const; // Texture addressing modes // todo hulud d3d adressing mode virtual bool supportTextureShaders() const {return false;}; virtual bool supportMADOperator() const; // todo hulud d3d adressing mode virtual bool supportWaterShader() const; // todo hulud d3d adressing mode virtual bool supportTextureAddrMode(CMaterial::TTexAddressingMode /* mode */) const {return false;}; // todo hulud d3d adressing mode virtual void setMatrix2DForTextureOffsetAddrMode(const uint /* stage */, const float /* mat */[4]) {} // EMBM support virtual bool supportEMBM() const; virtual bool isEMBMSupportedAtStage(uint stage) const; virtual void setEMBMMatrix(const uint stage, const float mat[4]); virtual bool supportPerPixelLighting(bool /* specular */) const {return false;}; // index offset support virtual bool supportIndexOffset() const { return true; /* always supported with D3D driver */ } // Blend virtual bool supportBlendConstantColor() const; virtual void setBlendConstantColor(NLMISC::CRGBA col); virtual NLMISC::CRGBA getBlendConstantColor() const; // Monitor properties virtual bool setMonitorColorProperties (const CMonitorColorProperties &properties); // Polygon smoothing virtual void enablePolygonSmoothing(bool smooth); virtual bool isPolygonSmoothingEnabled() const; // Material multipass virtual sint beginMaterialMultiPass(); virtual void setupMaterialPass(uint pass); virtual void endMaterialMultiPass(); /// \name Vertex Program // @{ // Order of preference // - activeVertexProgram // - CMaterial pass[n] VP (uses activeVertexProgram, but does not override if one already set by code) // - default generic VP that mimics fixed pipeline / no VP with fixed pipeline /** * Does the driver supports vertex program, but emulated by CPU ? */ virtual bool isVertexProgramEmulated() const; /** Return true if the driver supports the specified vertex program profile. */ virtual bool supportVertexProgram(CVertexProgram::TProfile profile) const; /** Compile the given vertex program, return if successful. * If a vertex program was set active before compilation, * the state of the active vertex program is undefined behaviour afterwards. */ virtual bool compileVertexProgram(CVertexProgram *program); /** Set the active vertex program. This will override vertex programs specified in CMaterial render calls. * Also used internally by setupMaterial(CMaterial) when getVertexProgram returns NULL. * The vertex program is activated immediately. */ virtual bool activeVertexProgram(CVertexProgram *program); // @} /// \name Pixel Program // @{ // Order of preference // - activePixelProgram // - CMaterial pass[n] PP (uses activePixelProgram, but does not override if one already set by code) // - PP generated from CMaterial (uses activePixelProgram, but does not override if one already set by code) /** Return true if the driver supports the specified pixel program profile. */ virtual bool supportPixelProgram(CPixelProgram::TProfile profile) const; /** Compile the given pixel program, return if successful. * If a pixel program was set active before compilation, * the state of the active pixel program is undefined behaviour afterwards. */ virtual bool compilePixelProgram(CPixelProgram *program); /** Set the active pixel program. This will override pixel programs specified in CMaterial render calls. * Also used internally by setupMaterial(CMaterial) when getPixelProgram returns NULL. * The pixel program is activated immediately. */ virtual bool activePixelProgram(CPixelProgram *program); // @} /// \name Geometry Program // @{ // Order of preference // - activeGeometryProgram // - CMaterial pass[n] PP (uses activeGeometryProgram, but does not override if one already set by code) // - none /** Return true if the driver supports the specified pixel program profile. */ virtual bool supportGeometryProgram(CGeometryProgram::TProfile profile) const { return false; } /** Compile the given pixel program, return if successful. * If a pixel program was set active before compilation, * the state of the active pixel program is undefined behaviour afterwards. */ virtual bool compileGeometryProgram(CGeometryProgram *program) { return false; } /** Set the active pixel program. This will override pixel programs specified in CMaterial render calls. * Also used internally by setupMaterial(CMaterial) when getGeometryProgram returns NULL. * The pixel program is activated immediately. */ virtual bool activeGeometryProgram(CGeometryProgram *program) { return false; } // @} /// \name Program parameters // @{ // Set parameters virtual void setUniform1f(TProgram program, uint index, float f0); virtual void setUniform2f(TProgram program, uint index, float f0, float f1); virtual void setUniform3f(TProgram program, uint index, float f0, float f1, float f2); virtual void setUniform4f(TProgram program, uint index, float f0, float f1, float f2, float f3); virtual void setUniform1i(TProgram program, uint index, sint32 i0); virtual void setUniform2i(TProgram program, uint index, sint32 i0, sint32 i1); virtual void setUniform3i(TProgram program, uint index, sint32 i0, sint32 i1, sint32 i2); virtual void setUniform4i(TProgram program, uint index, sint32 i0, sint32 i1, sint32 i2, sint32 i3); virtual void setUniform1ui(TProgram program, uint index, uint32 ui0); virtual void setUniform2ui(TProgram program, uint index, uint32 ui0, uint32 ui1); virtual void setUniform3ui(TProgram program, uint index, uint32 ui0, uint32 ui1, uint32 ui2); virtual void setUniform4ui(TProgram program, uint index, uint32 ui0, uint32 ui1, uint32 ui2, uint32 ui3); virtual void setUniform3f(TProgram program, uint index, const NLMISC::CVector& v); virtual void setUniform4f(TProgram program, uint index, const NLMISC::CVector& v, float f3); virtual void setUniform4f(TProgram program, uint index, const NLMISC::CRGBAF& rgba); virtual void setUniform4x4f(TProgram program, uint index, const NLMISC::CMatrix& m); virtual void setUniform4fv(TProgram program, uint index, size_t num, const float *src); virtual void setUniform4iv(TProgram program, uint index, size_t num, const sint32 *src); virtual void setUniform4uiv(TProgram program, uint index, size_t num, const uint32 *src); // Set builtin parameters virtual void setUniformMatrix(TProgram program, uint index, TMatrix matrix, TTransform transform); virtual void setUniformFog(TProgram program, uint index); // Set feature parameters virtual bool setUniformDriver(TProgram program); // set all driver-specific features params (based on program->features->DriverFlags) virtual bool setUniformMaterial(TProgram program, CMaterial &material); // set all material-specific feature params (based on program->features->MaterialFlags) virtual void setUniformParams(TProgram program, CGPUProgramParams ¶ms); // set all user-provided params from the storage virtual bool isUniformProgramState() { return false; } // @} virtual void enableVertexProgramDoubleSidedColor(bool doubleSided); virtual bool supportVertexProgramDoubleSidedColor() const; // Occlusion query virtual bool supportOcclusionQuery() const; virtual IOcclusionQuery *createOcclusionQuery(); virtual void deleteOcclusionQuery(IOcclusionQuery *oq); /** Shader implementation * * Shader can assume this states are setuped: * TextureTransformFlags[n] = DISABLE; * TexCoordIndex[n] = n; * ColorOp[n] = DISABLE; * AlphaOp[n] = DISABLE; */ bool activeShader(CD3DShaderFX *shd); // Bench virtual void startBench (bool wantStandardDeviation = false, bool quick = false, bool reset = true); virtual void endBench (); virtual void displayBench (class NLMISC::CLog *log); virtual void setCullMode(TCullMode cullMode); virtual TCullMode getCullMode() const; virtual void enableStencilTest(bool enable); virtual bool isStencilTestEnabled() const; virtual void stencilFunc(TStencilFunc stencilFunc, int ref, uint mask); virtual void stencilOp(TStencilOp fail, TStencilOp zfail, TStencilOp zpass); virtual void stencilMask(uint mask); uint32 getMaxVertexIndex() const { return _MaxVertexIndex; } // *** Inline info uint inlGetNumTextStages() const { return _NbNeLTextureStages; } //private: public: // Hardware render variables, like matrices, render states struct CRenderVariable { CRenderVariable() { NextModified = NULL; Modified = false; } // Type of render state enum { RenderState = 0, TextureState, TextureIndexState, TexturePtrState, VertexProgramPtrState, PixelShaderPtrState, VertexProgramConstantState, PixelShaderConstantState, SamplerState, MatrixState, VBState, IBState, VertexDecl, LightState, RenderTargetState, } Type; CRenderVariable *NextModified; bool Modified; virtual void apply(CDriverD3D *driver) = 0; }; // Render state struct CRenderState : public CRenderVariable { CRenderState() { Type = RenderState; Value= 0; ValueSet = false; } D3DRENDERSTATETYPE StateID; DWORD Value; bool ValueSet; virtual void apply(CDriverD3D *driver); }; // Render texture state struct CTextureState : public CRenderVariable { CTextureState() { Type = TextureState; DeviceValue = 0xcccccccc; } DWORD StageID; D3DTEXTURESTAGESTATETYPE StateID; DWORD Value; DWORD DeviceValue; virtual void apply(CDriverD3D *driver); }; // Render texture index state struct CTextureIndexState : public CRenderVariable { CTextureIndexState() { Type = TextureIndexState; } DWORD StageID; DWORD TexGenMode; DWORD UVChannel; bool TexGen; virtual void apply(CDriverD3D *driver); }; // Render texture struct CTexturePtrState : public CRenderVariable { CTexturePtrState() { Type = TexturePtrState; Texture = NULL; } DWORD StageID; LPDIRECT3DBASETEXTURE9 Texture; virtual void apply(CDriverD3D *driver); }; // Render texture struct CVertexProgramPtrState : public CRenderVariable { CVertexProgramPtrState() { Type = VertexProgramPtrState; VertexProgram = NULL; } LPDIRECT3DVERTEXSHADER9 VertexProgram; // for debug const CVertexProgram *VP; virtual void apply(CDriverD3D *driver); }; // Render texture struct CPixelShaderPtrState : public CRenderVariable { CPixelShaderPtrState() { Type = PixelShaderPtrState; PixelShader = NULL; } LPDIRECT3DPIXELSHADER9 PixelShader; virtual void apply(CDriverD3D *driver); }; // Vertex buffer constants state struct CVertexProgramConstantState : public CRenderVariable { CVertexProgramConstantState() { Type = VertexProgramConstantState; } enum { Float= 0, Int, Undef, } ValueType; uint StateID; DWORD Values[4]; virtual void apply(CDriverD3D *driver); }; // Pixel shader constants state struct CPixelShaderConstantState : public CRenderVariable { CPixelShaderConstantState() { Type = PixelShaderConstantState; } enum { Float= 0, Int, Undef, } ValueType; uint StateID; DWORD Values[4]; virtual void apply(CDriverD3D *driver); }; // Render sampler state struct CSamplerState : public CRenderVariable { CSamplerState() { Type = SamplerState; } DWORD SamplerID; D3DSAMPLERSTATETYPE StateID; DWORD Value; virtual void apply(CDriverD3D *driver); }; // Render matrix struct CMatrixState : public CRenderVariable { CMatrixState() { Type = MatrixState; } D3DTRANSFORMSTATETYPE TransformType; D3DXMATRIX Matrix; virtual void apply(CDriverD3D *driver); }; // Render vertex buffer struct CVBState : public CRenderVariable { CVBState() { Type = VBState; VertexBuffer = NULL; ColorOffset = 0; } IDirect3DVertexBuffer9 *VertexBuffer; UINT Offset; UINT Stride; CVertexBuffer::TPreferredMemory PrefferedMemory; DWORD Usage; // d3d vb usage uint ColorOffset; // Fix for Radeon 7xxx series (see remark in CDriverD3D::createVertexDeclaration) virtual void apply(CDriverD3D *driver); }; // Render index buffer struct CIBState : public CRenderVariable { CIBState() { Type = IBState; IndexBuffer = NULL; } IDirect3DIndexBuffer9 *IndexBuffer; virtual void apply(CDriverD3D *driver); }; // Render vertex decl struct CVertexDeclState : public CRenderVariable { CVertexDeclState() { Type = VertexDecl; Decl = NULL; DeclAliasDiffuseToSpecular = NULL; DeclNoDiffuse = NULL; Stride= 0; AliasDiffuseToSpecular = false; EnableVertexColor = false; } IDirect3DVertexDeclaration9 *Decl; IDirect3DVertexDeclaration9 *DeclAliasDiffuseToSpecular; IDirect3DVertexDeclaration9 *DeclNoDiffuse; uint Stride; bool AliasDiffuseToSpecular; bool EnableVertexColor; virtual void apply(CDriverD3D *driver); }; // Render vertex buffer struct CLightState : public CRenderVariable { CLightState() { Type = LightState; Enabled = false; SettingsTouched = false; EnabledTouched = true; Light.Type = D3DLIGHT_POINT; Light.Range = 1; Light.Falloff = 1; Light.Position.x = 0; Light.Position.y = 0; Light.Position.z = 0; Light.Direction.x = 1; Light.Direction.y = 0; Light.Direction.z = 0; Light.Attenuation0 = 1; Light.Attenuation1 = 1; Light.Attenuation2 = 1; Light.Theta = 0; Light.Phi = 0; } uint8 LightIndex; bool SettingsTouched; bool EnabledTouched; bool Enabled; D3DLIGHT9 Light; virtual void apply(CDriverD3D *driver); }; // Render target struct CRenderTargetState : public CRenderVariable { CRenderTargetState() { Type = RenderTargetState; Target = NULL; Texture = NULL; Level = 0; CubeFace = 0; } IDirect3DSurface9 *Target; ITexture *Texture; uint8 Level; uint8 CubeFace; virtual void apply(CDriverD3D *driver); }; // material state struct CMaterialState : public CRenderVariable { CMaterialState() { //Current.Power = -1.f; Current.Diffuse.r = Current.Diffuse.g = Current.Diffuse.b = Current.Diffuse.a = 0.f; Current.Ambient.r = Current.Ambient.g = Current.Ambient.b = Current.Ambient.a = 0.f; Current.Specular.r = Current.Specular.g = Current.Specular.b = Current.Specular.a = 0.f; Current.Emissive.r = Current.Emissive.g = Current.Emissive.b = Current.Emissive.a = 0.f; Current.Power = 0.f; } D3DMATERIAL9 Current; virtual void apply(CDriverD3D *driver); }; // Friends friend void D3DWndProc(CDriverD3D *driver, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); friend class CTextureDrvInfosD3D; friend class CVBDrvInfosD3D; friend class CIBDrvInfosD3D; friend class CVolatileVertexBuffer; friend class CVolatileIndexBuffer; // Init render states void initRenderVariables(); // Reset render states void resetRenderVariables(); // Replace all arguments of color / alpha operators in the pixel pipe with the given value void replaceAllArgument(DWORD from, DWORD to, DWORD blendOpFrom); // Replace all arguments of color / alpha operators in the pixel pipe at the given stage with the given value void replaceAllArgumentAtStage(uint stage, DWORD from, DWORD to, DWORD blendOpFrom); void replaceAllRGBArgumentAtStage(uint stage, DWORD from, DWORD to, DWORD blendOpFrom); void replaceAllAlphaArgumentAtStage(uint stage, DWORD from, DWORD to, DWORD blendOpFrom); // Replace a the given color / alpha op void replaceArgumentAtStage(D3DTEXTURESTAGESTATETYPE state, DWORD stage, DWORD from, DWORD to); // Setup lighting & material so that it produces the given constant color (useful to simulate a per stage constant using diffuse) void setupConstantDiffuseColorFromLightedMaterial(D3DCOLOR color); // Update all modified render states, reset current material void updateRenderVariables(); // Update all modified render states, assume current material is still alive void updateRenderVariablesInternal(); // Reset the driver, release the lost resources bool reset (const GfxMode& mode); // Handle window size change bool handlePossibleSizeChange(); public: // Touch a render variable inline void touchRenderVariable (CRenderVariable *renderVariable) { // Modified ? if (!renderVariable->Modified) { // Link to modified states renderVariable->NextModified = _ModifiedRenderState; _ModifiedRenderState = renderVariable; renderVariable->Modified = true; } } // Access render states inline void setRenderState (D3DRENDERSTATETYPE renderState, DWORD value) { H_AUTO_D3D(CDriverD3D_setRenderState); #ifdef NL_DEBUG nlassert (_DeviceInterface); nlassert (renderStateTexture); setSamplerState (stage, D3DSAMP_ADDRESSU, d3dtext->WrapS); setSamplerState (stage, D3DSAMP_ADDRESSV, d3dtext->WrapT); setSamplerState (stage, D3DSAMP_MAGFILTER, d3dtext->MagFilter); setSamplerState (stage, D3DSAMP_MINFILTER, d3dtext->MinFilter); setSamplerState (stage, D3DSAMP_MIPFILTER, d3dtext->MipFilter); setSamplerState (stage, D3DSAMP_MAXANISOTROPY, _AnisotropicFilter); // Profile, log the use of this texture if (_SumTextureMemoryUsed) { // Insert the pointer of this texture _TextureUsed.insert (d3dtext); } } // Access vertex program inline void setVertexProgram (LPDIRECT3DVERTEXSHADER9 vertexProgram, const CVertexProgram *vp) { H_AUTO_D3D(CDriverD3D_setVertexProgram); nlassert (_DeviceInterface); // Ref on the state #ifdef NL_D3D_USE_RENDER_STATE_CACHE NL_D3D_CACHE_TEST(CacheTest_VertexProgram, _VertexProgramCache.VertexProgram != vertexProgram) #endif // NL_D3D_USE_RENDER_STATE_CACHE { _VertexProgramCache.VertexProgram = vertexProgram; _VertexProgramCache.VP = vp; touchRenderVariable (&_VertexProgramCache); } } // Access pixel shader inline void setPixelShader (LPDIRECT3DPIXELSHADER9 pixelShader) { H_AUTO_D3D(CDriverD3D_setPixelShader); nlassert (_DeviceInterface); // Ref on the state #ifdef NL_D3D_USE_RENDER_STATE_CACHE NL_D3D_CACHE_TEST(CacheTest_PixelShader, _PixelShaderCache.PixelShader != pixelShader) #endif // NL_D3D_USE_RENDER_STATE_CACHE { _PixelShaderCache.PixelShader = pixelShader; touchRenderVariable (&_PixelShaderCache); } } // Access vertex program constant inline void setVertexProgramConstant (uint index, const float *values) { H_AUTO_D3D(CDriverD3D_setVertexProgramConstant); nlassert (_DeviceInterface); nlassert (index=256) return (D3DTRANSFORMSTATETYPE)(MatrixStateRemap + type - 256); else return (uint)type; } inline void setMatrix (D3DTRANSFORMSTATETYPE type, const D3DXMATRIX &matrix) { H_AUTO_D3D(CDriverD3D_setMatrix); nlassert (_DeviceInterface); // Remap high matrices indexes type = (D3DTRANSFORMSTATETYPE)remapMatrixIndex (type); nlassert ((int)type<(int)MaxMatrixState); CMatrixState &theMatrix = _MatrixCache[type]; #ifdef NL_D3D_USE_RENDER_STATE_CACHE bool doUpdate = (matrix._11 != theMatrix.Matrix._11) || (matrix._12 != theMatrix.Matrix._12) || (matrix._13 != theMatrix.Matrix._13) || (matrix._14 != theMatrix.Matrix._14) || (matrix._21 != theMatrix.Matrix._21) || (matrix._22 != theMatrix.Matrix._22) || (matrix._23 != theMatrix.Matrix._23) || (matrix._24 != theMatrix.Matrix._24) || (matrix._31 != theMatrix.Matrix._31) || (matrix._32 != theMatrix.Matrix._32) || (matrix._33 != theMatrix.Matrix._33) || (matrix._34 != theMatrix.Matrix._34) || (matrix._41 != theMatrix.Matrix._41) || (matrix._42 != theMatrix.Matrix._42) || (matrix._43 != theMatrix.Matrix._43) || (matrix._44 != theMatrix.Matrix._44); NL_D3D_CACHE_TEST(CacheTest_Matrix, doUpdate) #endif // NL_D3D_USE_RENDER_STATE_CACHE { theMatrix.Matrix = matrix; touchRenderVariable (&theMatrix); } } // Access texture states inline void setRenderTarget (IDirect3DSurface9 *target, ITexture *texture, uint8 level, uint8 cubeFace) { H_AUTO_D3D(CDriverD3D_setRenderTarget); nlassert (_DeviceInterface); // Ref on the state #ifdef NL_D3D_USE_RENDER_STATE_CACHE NL_D3D_CACHE_TEST(CacheTest_RenderTarget, _RenderTarget.Target != target) #endif // NL_D3D_USE_RENDER_STATE_CACHE { _RenderTarget.Target = target; _RenderTarget.Texture = texture; _RenderTarget.Level = level; _RenderTarget.CubeFace = cubeFace; touchRenderVariable (&_RenderTarget); _ScissorTouched = true; } } public: void setMaterialState(const D3DMATERIAL9 &material) { H_AUTO_D3D(setMaterialState); #ifdef NL_D3D_USE_RENDER_STATE_CACHE bool update = material.Power != _MaterialState.Current.Power || material.Ambient != _MaterialState.Current.Ambient || material.Emissive != _MaterialState.Current.Emissive || material.Diffuse != _MaterialState.Current.Diffuse || material.Specular != _MaterialState.Current.Specular; NL_D3D_CACHE_TEST(CacheTest_MaterialState, update) #endif { _MaterialState.Current = material; touchRenderVariable(&_MaterialState); } } // Get the d3dtext mirror of an existing setuped texture. static inline CTextureDrvInfosD3D* getTextureD3D(ITexture& tex) { H_AUTO_D3D(CDriverD3D_getTextureD3D); CTextureDrvInfosD3D* d3dtex; d3dtex= (CTextureDrvInfosD3D*)(ITextureDrvInfos*)(tex.TextureDrvShare->DrvTexture); return d3dtex; } // Get the d3dtext mirror of an existing setuped pixel program. static inline CPixelProgramDrvInfosD3D* getPixelProgramD3D(CPixelProgram& pixelProgram) { H_AUTO_D3D(CDriverD3D_getPixelProgramD3D); CPixelProgramDrvInfosD3D* d3dPixelProgram; d3dPixelProgram = (CPixelProgramDrvInfosD3D*)(IProgramDrvInfos*)(pixelProgram.m_DrvInfo); return d3dPixelProgram; } // Get the d3dtext mirror of an existing setuped vertex program. static inline CVertexProgamDrvInfosD3D* getVertexProgramD3D(CVertexProgram& vertexProgram) { H_AUTO_D3D(CDriverD3D_getVertexProgramD3D); CVertexProgamDrvInfosD3D* d3dVertexProgram; d3dVertexProgram = (CVertexProgamDrvInfosD3D*)(IProgramDrvInfos*)(vertexProgram.m_DrvInfo); return d3dVertexProgram; } // *** Init helper bool isDepthFormatOk(UINT adapter, D3DDEVTYPE rasterizer, D3DFORMAT DepthFormat, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat); bool isTextureFormatOk(UINT adapter, D3DDEVTYPE rasterizer, D3DFORMAT TextureFormat, D3DFORMAT AdapterFormat); bool fillPresentParameter (D3DPRESENT_PARAMETERS ¶meters, D3DFORMAT &adapterFormat, const GfxMode& mode, const D3DDISPLAYMODE &adapterMode); // *** Texture helper D3DFORMAT getD3DDestTextureFormat (ITexture& tex); // Generates the texture, degades it, creates / resizes the d3d surface. Don't fill the surface. bool generateD3DTexture (ITexture& tex, bool textureDegradation, D3DFORMAT &destFormat, D3DFORMAT &srcFormat, bool &cube); // Return the memory used by the surface described iwith the parameters uint32 computeTextureMemoryUsage (uint width, uint height, uint levels, D3DFORMAT destFormat, bool cube); // Upload a texture part bool uploadTextureInternal (ITexture& tex, NLMISC::CRect& rect, uint8 destMipmap, uint8 srcMipmap, D3DFORMAT destFormat, D3DFORMAT srcFormat); // *** Matrix helper // Update _D3DModelView and _D3DModelViewProjection matrices. Call this if the model, the projection or the view matrix are modified void updateMatrices (); // Update the projection matrix. Call this if the driver resolution, the viewport or the frustum changes. void updateProjectionMatrix (); // *** Vertex buffer helper // Create a vertex declaration bool createVertexDeclaration (uint16 vertexFormat, const uint8 *typeArray, IDirect3DVertexDeclaration9 **vertexDecl, uint &colorOffset, bool aliasDiffuseToSpecular, bool bypassDiffuse, uint *stride = NULL ); // *** Index buffer helper // *** Multipass helpers void initInternalShaders(); void releaseInternalShaders(); bool setShaderTexture (uint textureHandle, ITexture *texture, CFXCache *cache); bool validateShader(CD3DShaderFX *shader); void activePass (uint pass) { H_AUTO_D3D(CDriverD3D_activePass); if (_CurrentShader) { CShaderDrvInfosD3D *drvInfo = static_cast((IShaderDrvInfos*)_CurrentShader->_DrvInfo); if (_CurrentMaterialInfo->FXCache) { nlassert(_CurrentMaterialInfo); _CurrentMaterialInfo->FXCache->applyPass(*this, drvInfo, pass); } else { #if (DIRECT3D_VERSION >= 0x0900) && (D3D_SDK_VERSION >= 32) drvInfo->Effect->BeginPass (pass); drvInfo->Effect->EndPass (); #else drvInfo->Effect->Pass (pass); #endif } } // Update render states updateRenderVariablesInternal(); } void beginMultiPass () { H_AUTO_D3D(CDriverD3D_beginMultiPass); if (_CurrentShader) { // Does the shader validated ? validateShader(_CurrentShader); // Init default state value uint i; for (i=0; i((IShaderDrvInfos*)_CurrentShader->_DrvInfo); if (_CurrentMaterialInfo->FXCache) { nlassert(_CurrentMaterialInfo); _CurrentMaterialInfo->FXCache->begin(drvInfo, this); } else { drvInfo->Effect->Begin (&_CurrentShaderPassCount, D3DXFX_DONOTSAVESTATE|D3DXFX_DONOTSAVESHADERSTATE); } } else // No shader setuped _CurrentShaderPassCount = 1; } void endMultiPass () { H_AUTO_D3D(CDriverD3D_endMultiPass); if (_CurrentShader) { CShaderDrvInfosD3D *drvInfo = static_cast((IShaderDrvInfos*)_CurrentShader->_DrvInfo); if (_CurrentMaterialInfo->FXCache) { _CurrentMaterialInfo->FXCache->end(drvInfo); } else { drvInfo->Effect->End (); } } } // render helpers bool renderPrimitives(D3DPRIMITIVETYPE primitiveType, uint numVertexPerPrim, CMaterial& mat, uint firstVertex, uint32 nPrims); bool renderIndexedPrimitives(D3DPRIMITIVETYPE primitiveType, uint numVertexPerPrim, CMaterial& mat, uint32 firstIndex, uint32 nPrims, uint indexOffset = 0); bool renderSimpleIndexedPrimitives(D3DPRIMITIVETYPE primitiveType, uint numVertexPerPrim, uint32 firstIndex, uint32 nPrims, uint indexOffset = 0); void convertToIndices16(uint firstIndex, uint numIndices); // Returns true if this material needs a constant color for the diffuse component static bool needsConstantForDiffuse (CMaterial &mat); /* Returns true if this normal needs constant. If true, numConstant is the number of needed constants, firstConstant is the first constants needed. */ static bool needsConstants (uint &numConstant, uint &firstConstant, uint &secondConstant, CMaterial &mat); // For normal shader, compute part of the pipeline that are worth setting // For example : if alpha output if not used (no alpha test or blend), then the alpha part won't be set at all static void computeRelevantTexEnv(CMaterial &mat, bool rgbPipe[IDRV_MAT_MAXTEXTURES], bool alphaPipe[IDRV_MAT_MAXTEXTURES]); // Build a pixel shader for normal shader IDirect3DPixelShader9 *buildPixelShader (const CNormalShaderDesc &normalShaderDesc, bool unlightedNoVertexColor); // Notify all the shaders drivers info that a device has been lost void notifyAllShaderDrvOfLostDevice(); // Notify all the shaders drivers info that a device has been reset void notifyAllShaderDrvOfResetDevice(); // *** Debug helpers void setDebugMaterial(); // ** From ID3DXEffectStateManager public: HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID *ppvObj); ULONG STDMETHODCALLTYPE AddRef(VOID); ULONG STDMETHODCALLTYPE Release(VOID); HRESULT STDMETHODCALLTYPE LightEnable(DWORD Index, BOOL Enable); HRESULT STDMETHODCALLTYPE SetFVF(DWORD FVF); HRESULT STDMETHODCALLTYPE SetLight(DWORD Index, CONST D3DLIGHT9* pLight); HRESULT STDMETHODCALLTYPE SetMaterial(CONST D3DMATERIAL9* pMaterial); HRESULT STDMETHODCALLTYPE SetNPatchMode(FLOAT nSegments); HRESULT STDMETHODCALLTYPE SetPixelShader(LPDIRECT3DPIXELSHADER9 pShader); HRESULT STDMETHODCALLTYPE SetPixelShaderConstantB(UINT StartRegister, CONST BOOL* pConstantData, UINT RegisterCount); HRESULT STDMETHODCALLTYPE SetPixelShaderConstantF(UINT StartRegister, CONST FLOAT* pConstantData, UINT RegisterCount); HRESULT STDMETHODCALLTYPE SetPixelShaderConstantI(UINT StartRegister, CONST INT* pConstantData, UINT RegisterCount); HRESULT STDMETHODCALLTYPE SetRenderState(D3DRENDERSTATETYPE State, DWORD Value); HRESULT STDMETHODCALLTYPE SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value); HRESULT STDMETHODCALLTYPE SetTexture (DWORD Stage, LPDIRECT3DBASETEXTURE9 pTexture); HRESULT STDMETHODCALLTYPE SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value); HRESULT STDMETHODCALLTYPE SetTransform(D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix); HRESULT STDMETHODCALLTYPE SetVertexShader(LPDIRECT3DVERTEXSHADER9 pShader); HRESULT STDMETHODCALLTYPE SetVertexShaderConstantB(UINT StartRegister, CONST BOOL* pConstantData, UINT RegisterCount); HRESULT STDMETHODCALLTYPE SetVertexShaderConstantF(UINT StartRegister, CONST FLOAT* pConstantData, UINT RegisterCount); HRESULT STDMETHODCALLTYPE SetVertexShaderConstantI(UINT StartRegister, CONST INT* pConstantData, UINT RegisterCount); private: void findNearestFullscreenVideoMode(); TShaderDrvInfoPtrList _ShaderDrvInfos; // Windows std::string _WindowClass; HWND _HWnd; sint32 _WindowX; sint32 _WindowY; bool _DestroyWindow; bool _Maximized; bool _HandlePossibleSizeChangeNextSize; GfxMode _CurrentMode; uint _Interval; bool _FullScreen; // cursors enum TColorDepth { ColorDepth16 = 0, ColorDepth32, ColorDepthCount }; TColorDepth _ColorDepth; std::string _CurrName; NLMISC::CRGBA _CurrCol; uint8 _CurrRot; uint _CurrHotSpotX; uint _CurrHotSpotY; float _CursorScale; nlCursor _DefaultCursor; bool _AlphaBlendedCursorSupported; bool _AlphaBlendedCursorSupportRetrieved; class CCursor { public: NLMISC::CBitmap Src; TColorDepth ColorDepth; uint OrigHeight; float HotspotScale; uint HotspotOffsetX; uint HotspotOffsetY; sint HotSpotX; sint HotSpotY; nlCursor Cursor; NLMISC::CRGBA Col; uint8 Rot; #if defined(NL_OS_UNIX) && !defined(NL_OS_MAC) Display *Dpy; #endif public: CCursor(); ~CCursor(); CCursor& operator= (const CCursor& from); void reset(); }; struct CStrCaseUnsensitiveCmp { bool operator()(const std::string &lhs, const std::string &rhs) const { return NLMISC::nlstricmp(lhs, rhs) < 0; } }; typedef std::map TCursorMap; TCursorMap _Cursors; // Directx uint32 _Adapter; D3DDEVTYPE _Rasterizer; LPDIRECT3D9 _D3D; public: IDirect3DDevice9 *_DeviceInterface; private: // Events NLMISC::CEventEmitterMulti _EventEmitter; // this can contains a win emitter and eventually a direct input emitter // Some matrices (Local -> Model -> World -> Screen) public: CVector _PZBCameraPos; private: CMatrix _UserModelMtx; CMatrix _UserViewMtx; public: CViewport _Viewport; private: D3DVIEWPORT9 _D3DViewport; public: CScissor _Scissor; private: float _OODeltaZ; // Backup znear and zfar D3DXMATRIX _D3DSpecularWorldTex; // World (as in NeL) to model matrix. D3DXMATRIX _D3DModelView; // Local to world (as in D3D) matrix. D3DXMATRIX _D3DModelViewProjection; // Local to screen (as in D3D) matrix. D3DXMATRIX _D3DInvModelView; // World (as in DX) to local matrix. bool _ForceNormalize; bool _FrustumPerspective; bool _InvertCullMode; bool _DoubleSided; float _FrustumLeft; float _FrustumRight; float _FrustumTop; float _FrustumBottom; float _FrustumZNear; float _FrustumZFar; float _FogStart; float _FogEnd; // Vertex memory available uint32 _AGPMemoryAllocated; uint32 _VRAMMemoryAllocated; // Textures caps D3DFORMAT _PreferedTextureFormat[ITexture::UploadFormatCount]; uint _ForceTextureResizePower; bool _ForceDXTCCompression:1; bool _TextureCubeSupported; bool _VertexProgram; bool _PixelProgram; uint16 _PixelProgramVersion; bool _DisableHardwareVertexProgram; bool _DisableHardwarePixelProgram; bool _DisableHardwareVertexArrayAGP; bool _DisableHardwareIndexArrayAGP; bool _DisableHardwarePixelShader; bool _MADOperatorSupported; bool _EMBMSupported; bool _CubbedMipMapSupported; bool _IsGeforce; bool _NonPowerOfTwoTexturesSupported; uint _MaxAnisotropy; bool _AnisotropicMinSupported; bool _AnisotropicMagSupported; bool _AnisotropicMinCubeSupported; bool _AnisotropicMagCubeSupported; uint _NbNeLTextureStages; // Number of texture stage for NeL (max IDRV_MAT_MAXTEXTURES) uint _MaxVerticesByVertexBufferHard; uint _MaxLight; uint32 _PixelShaderVersion; uint32 _MaxPrimitiveCount; uint32 _MaxVertexIndex; uint _MaxNumPerStageConstantLighted; uint _MaxNumPerStageConstantUnlighted; // Profiling CPrimitiveProfile _PrimitiveProfileIn; CPrimitiveProfile _PrimitiveProfileOut; uint32 _AllocatedTextureMemory; uint32 _NbSetupMaterialCall; uint32 _NbSetupModelMatrixCall; bool _SumTextureMemoryUsed; std::set _TextureUsed; // VBHard Lock Profiling struct CVBHardProfile { NLMISC::CRefPtr VBHard; NLMISC::TTicks AccumTime; // true if the VBHard was not always the same for the same chronogical place. bool Change; CVBHardProfile() { AccumTime= 0; Change= false; } }; // Index buffer lock profiling struct CIBProfile { NLMISC::CRefPtr IB; NLMISC::TTicks AccumTime; // true if the VBHard was not always the same for the same chronogical place. bool Change; CIBProfile() { AccumTime= 0; Change= false; } }; // The vb hard Profiles in chronogical order. bool _VBHardProfiling; std::vector _VBHardProfiles; uint _CurVBHardLockCount; uint _NumVBHardProfileFrame; void appendVBHardLockProfile(NLMISC::TTicks time, CVertexBuffer *vb); // The index buffer profile in chronogical order. bool _IBProfiling; std::vector _IBProfiles; uint _CurIBLockCount; uint _NumIBProfileFrame; public: NLMISC::TTicks _VolatileIBLockTime; NLMISC::TTicks _VolatileVBLockTime; private: void appendIBLockProfile(NLMISC::TTicks time, CIndexBuffer *ib); // VBHard profile std::set _VertexBufferHardSet; // The render variables public: CRenderState _RenderStateCache[MaxRenderState]; CTextureState _TextureStateCache[MaxTexture][MaxTextureState]; CTextureIndexState _TextureIndexStateCache[MaxTexture]; CTexturePtrState _TexturePtrStateCache[MaxTexture]; CSamplerState _SamplerStateCache[MaxSampler][MaxSamplerState]; CMatrixState _MatrixCache[MaxMatrixState]; CVertexProgramPtrState _VertexProgramCache; CPixelShaderPtrState _PixelShaderCache; CVertexProgramConstantState _VertexProgramConstantCache[MaxVertexProgramConstantState]; CPixelShaderConstantState _PixelShaderConstantCache[MaxPixelShaderConstantState]; CVertexDeclState _VertexDeclCache; CLightState _LightCache[MaxLight]; CRenderTargetState _RenderTarget; CMaterialState _MaterialState; private: // last activation of vertex buffer / index buffer NLMISC::CRefPtr _LastIndexBufferInfo; // Vertex buffer cache CVBState _VertexBufferCache; uint _VertexBufferSize; uint _VertexBufferOffset; public: bool _UseVertexColor; private: // Index buffer cache CIBState _IndexBufferCache; uint _IndexBufferOffset; // Current index buffer offset CIndexBuffer::TFormat _CurrIndexBufferFormat; // updated at call to activeIndexBuffer // The last vertex buffer needs vertex color bool _FogEnabled; NLMISC::CRefPtr _VertexProgramUser; NLMISC::CRefPtr _PixelProgramUser; // *** Internal resources // Current render pass uint _CurrentRenderPass; // Volatile double buffers CVolatileVertexBuffer *_VolatileVertexBufferRAM[2]; CVolatileVertexBuffer *_VolatileVertexBufferAGP[2]; CVolatileIndexBuffer *_VolatileIndexBuffer16RAM[2]; CVolatileIndexBuffer *_VolatileIndexBuffer16AGP[2]; CVolatileIndexBuffer *_VolatileIndexBuffer32RAM[2]; CVolatileIndexBuffer *_VolatileIndexBuffer32AGP[2]; // Special 16 bit index buffer for quads IDirect3DIndexBuffer9 *_QuadIB; // Vertex declaration list std::list _VertexDeclarationList; // Pixel shader list std::list _NormalPixelShaders[2]; // Quad indexes CIndexBuffer _QuadIndexes; CIndexBuffer _QuadIndexesAGP; // The last setuped shader CD3DShaderFX *_CurrentShader; UINT _CurrentShaderPassCount; public: struct CTextureRef { CRefPtr NeLTexture; LPDIRECT3DBASETEXTURE9 D3DTexture; }; const std::vector &getCurrentShaderTextures() const { return _CurrentShaderTextures; } private: std::vector _CurrentShaderTextures; // The last material setuped CMaterial *_CurrentMaterial; public: CMaterialDrvInfosD3D *_CurrentMaterialInfo; private: // Optim: To not test change in Materials states if just texture has changed. Very useful for landscape. uint32 _MaterialAllTextureTouchedFlag; // The modified render variables list CRenderVariable *_ModifiedRenderState; // Internal shaders CD3DShaderFX _ShaderLightmap0; CD3DShaderFX _ShaderLightmap1; CD3DShaderFX _ShaderLightmap2; CD3DShaderFX _ShaderLightmap3; CD3DShaderFX _ShaderLightmap4; CD3DShaderFX _ShaderLightmap0Blend; CD3DShaderFX _ShaderLightmap1Blend; CD3DShaderFX _ShaderLightmap2Blend; CD3DShaderFX _ShaderLightmap3Blend; CD3DShaderFX _ShaderLightmap4Blend; CD3DShaderFX _ShaderLightmap0X2; CD3DShaderFX _ShaderLightmap1X2; CD3DShaderFX _ShaderLightmap2X2; CD3DShaderFX _ShaderLightmap3X2; CD3DShaderFX _ShaderLightmap4X2; CD3DShaderFX _ShaderLightmap0BlendX2; CD3DShaderFX _ShaderLightmap1BlendX2; CD3DShaderFX _ShaderLightmap2BlendX2; CD3DShaderFX _ShaderLightmap3BlendX2; CD3DShaderFX _ShaderLightmap4BlendX2; CD3DShaderFX _ShaderCloud; CD3DShaderFX _ShaderWaterNoDiffuse; CD3DShaderFX _ShaderWaterDiffuse; // Backup frame buffer IDirect3DSurface9 *_BackBuffer; // Static bitmap buffer to convert rgba to bgra static std::vector _TempBuffer; // Version of the driver. Not the interface version!! Increment when implementation of the driver change. static const uint32 ReleaseVersion; uint64 _SwapBufferCounter; // occlusion query bool _OcclusionQuerySupported; TOcclusionQueryList _OcclusionQueryList; // depth range float _DepthRangeNear; float _DepthRangeFar; // bool _ScissorTouched; uint8 _CurrentUVRouting[MaxTexture]; bool _MustRestoreLight; D3DXMATRIX _D3DMatrixIdentity; DWORD _FogColor; uint _AnisotropicFilter; // stencil buffer bool _CurStencilTest; DWORD _CurStencilFunc; DWORD _CurStencilRef; DWORD _CurStencilMask; DWORD _CurStencilOpFail; DWORD _CurStencilOpZFail; DWORD _CurStencilOpZPass; DWORD _CurStencilWriteMask; public: // private, for access by COcclusionQueryD3D COcclusionQueryD3D *_CurrentOcclusionQuery; // *** Lightmap Dynamic Light // For Lightmap Dynamic Lighting CLight _LightMapDynamicLight; bool _LightMapDynamicLightEnabled; bool _LightMapDynamicLightDirty; CMaterial::TShader _CurrentMaterialSupportedShader; // this is the backup of standard lighting (cause GL states may be modified by Lightmap Dynamic Lighting) CLight _UserLight0; bool _UserLightEnable[MaxLight]; // methods to enable / disable DX light, without affecting _LightMapDynamicLight*, or _UserLight0* void setLightInternal(uint8 num, const CLight& light); void enableLightInternal(uint8 num, bool enable); // on/off Lights for LightMap mode: only the first light is enabled in lightmap mode void setupLightMapDynamicLighting(bool enable); TCullMode _CullMode; bool _Lost; bool _SceneBegun; WORD _DesktopGammaRamp[256 * 3]; bool _DesktopGammaRampValid; // for debug only static bool _CacheTest[CacheTest_Count]; static std::vector _QuadIndices; // tmp : quads indices -> to allow support of quads on devices that don't have 32 bit indices // reset an index buffer and force it to be reallocated void deleteIndexBuffer(CIBDrvInfosD3D *ib); // Build 16 bit index buffer for quad bool buildQuadIndexBuffer(); // Test if cursor is in the client area. always true when software cursor is used and window visible // (displayed in software when DirectInput is used) bool isSystemCursorInClientArea(); // Check if RGBA cursors are supported bool isAlphaBlendedCursorSupported(); // Update cursor appearance void updateCursor(bool forceRebuild = false); // Create default cursors void createCursors(); // Release all cursors void releaseCursors(); // Convert a NLMISC::CBitmap to nlCursor bool convertBitmapToCursor(const NLMISC::CBitmap &bitmap, nlCursor &cursor, uint iconWidth, uint iconHeight, uint iconDepth, const NLMISC::CRGBA &col, sint hotSpotX, sint hotSpotY); // build a cursor from src, src should have the same size that the hardware cursor // or a assertion is thrown nlCursor buildCursor(const NLMISC::CBitmap &src, NLMISC::CRGBA col, uint8 rot, sint hotSpotX, sint hotSpotY); // reset the cursor shape to the system arrow void setSystemArrow(); bool convertBitmapToIcon(const NLMISC::CBitmap &bitmap, HICON &icon, uint iconWidth, uint iconHeight, uint iconDepth, const NLMISC::CRGBA &col = NLMISC::CRGBA::White, sint hotSpotX = 0, sint hotSpotY = 0, bool cursor = false); virtual bool copyTextToClipboard(const ucstring &text); virtual bool pasteTextFromClipboard(ucstring &text); public: #ifdef NL_DEBUG std::set _LockedBuffers; #endif emptyProc ExitFunc; bool beginScene() { nlassert(!_SceneBegun); if (_DeviceInterface->BeginScene() != D3D_OK) return false; _SceneBegun = true; return true; } bool endScene() { nlassert(_SceneBegun); if (_DeviceInterface->EndScene() != D3D_OK) return false; _SceneBegun = false; return true; } bool hasSceneBegun() const { return _SceneBegun; } // Clip the wanted rectangle with window. return true if rect is not NULL. bool clipRect(NLMISC::CRect &rect); friend class IShaderDrvInfos; void removeShaderDrvInfoPtr(ItShaderDrvInfoPtrList shaderIt); }; #define NL_D3DCOLOR_RGBA(rgba) (D3DCOLOR_ARGB(rgba.A,rgba.R,rgba.G,rgba.B)) #define D3DCOLOR_NL_RGBA(rgba) (NLMISC::CRGBA((uint8)((rgba>>16)&0xff), (uint8)((rgba>>8)&0xff), (uint8)(rgba&0xff), (uint8)((rgba>>24)&0xff))) #define NL_D3DCOLORVALUE_RGBA(dest,rgba) \ dest.a=(float)rgba.A*(1.f/255.f);dest.r=(float)rgba.R*(1.f/255.f);dest.g=(float)rgba.G*(1.f/255.f);dest.b=(float)rgba.B*(1.f/255.f); #define NL_D3D_MATRIX(d3d_mt,nl_mt) \ { const float *nl_mt_ptr = nl_mt.get(); \ d3d_mt._11 = nl_mt_ptr[0]; \ d3d_mt._21 = nl_mt_ptr[4]; \ d3d_mt._31 = nl_mt_ptr[8]; \ d3d_mt._41 = nl_mt_ptr[12]; \ d3d_mt._12 = nl_mt_ptr[1]; \ d3d_mt._22 = nl_mt_ptr[5]; \ d3d_mt._32 = nl_mt_ptr[9]; \ d3d_mt._42 = nl_mt_ptr[13]; \ d3d_mt._13 = nl_mt_ptr[2]; \ d3d_mt._23 = nl_mt_ptr[6]; \ d3d_mt._33 = nl_mt_ptr[10]; \ d3d_mt._43 = nl_mt_ptr[14]; \ d3d_mt._14 = nl_mt_ptr[3]; \ d3d_mt._24 = nl_mt_ptr[7]; \ d3d_mt._34 = nl_mt_ptr[11]; \ d3d_mt._44 = nl_mt_ptr[15]; } // build matrix for texture 2D transform (special case in D3D) #define NL_D3D_TEX2D_MATRIX(d3d_mt,nl_mt) \ { const float *nl_mt_ptr = nl_mt.get(); \ d3d_mt._11 = nl_mt_ptr[0]; \ d3d_mt._12 = nl_mt_ptr[1]; \ d3d_mt._13 = nl_mt_ptr[3]; \ d3d_mt._14 = 0.f; \ d3d_mt._21 = nl_mt_ptr[4]; \ d3d_mt._22 = nl_mt_ptr[5]; \ d3d_mt._23 = nl_mt_ptr[7]; \ d3d_mt._24 = 0.f; \ d3d_mt._31 = nl_mt_ptr[12]; \ d3d_mt._32 = nl_mt_ptr[13]; \ d3d_mt._33 = nl_mt_ptr[15]; \ d3d_mt._34 = 0.f; \ d3d_mt._41 = 0.f; \ d3d_mt._42 = 0.f; \ d3d_mt._43 = 0.f; \ d3d_mt._44 = 1.f; } #define NL_D3DVECTOR_VECTOR(dest,vect) dest.x=(vect).x;dest.y=(vect).y;dest.z=(vect).z; #define FTODW(f) (*((DWORD*)&(f))) #define D3DCOLOR_FLOATS(floats,rgba) {floats[0]=(float)((rgba>>16)&0xff) * (1.f/255.f);floats[1]=(float)((rgba>>8)&0xff) * (1.f/255.f);\ floats[2]=(float)(rgba&0xff) * (1.f/255.f);floats[3]=(float)((rgba>>24)&0xff) * (1.f/255.f);} #define NL_FLOATS(floats,rgba) {floats[0] = (float)rgba.R * (1.f/255.f);floats[1] = (float)rgba.G * (1.f/255.f);\ floats[2] = (float)rgba.B * (1.f/255.f);floats[3] = (float)rgba.A * (1.f/255.f);} // *************************************************************************** // nbPixels is pixel count, not a byte count ! inline void copyRGBA2BGRA (uint32 *dest, const uint32 *src, uint nbPixels) { H_AUTO_D3D(CDriverD3D_copyRGBA2BGRA); while (nbPixels != 0) { register uint32 color = *src; *dest = (color & 0xff00ff00) | ((color&0xff)<<16) | ((color&0xff0000)>>16); dest++; src++; nbPixels--; } } // *************************************************************************** // set a D3DCOLORVALUE inline void setColor(D3DCOLORVALUE &dest, float r, float g, float b, float a) { dest.r = r; dest.g = g; dest.b = b; dest.a = a; } // *************************************************************************** // set a D3DCOLORVALUE from & D3DCOLOR inline void setColor(D3DCOLORVALUE &dest, const D3DCOLOR &src) { dest.r = (1.f / 255.f) * ((src >> 16) & 0xff); dest.g = (1.f / 255.f) * ((src >> 8) & 0xff); dest.b = (1.f / 255.f) * (src & 0xff); dest.a = (1.f / 255.f) * (src >> 24); } // *************************************************************************** // set a D3DCOLORVALUE from a CRGBA inline void setColor(D3DCOLORVALUE &dest, const NLMISC::CRGBA &src) { dest.r = (1.f / 255.f) * src.R; dest.g = (1.f / 255.f) * src.G; dest.b = (1.f / 255.f) * src.B; dest.a = (1.f / 255.f) * src.A; } // *************************************************************************** void fillQuadIndexes (uint16 *indexes, uint first, uint last); } // NL3D #ifndef NL_STATIC extern HINSTANCE HInstDLL; #endif #endif // NL_DRIVER_DIRECT3D_H