/////////////////////////////////////////////////////////////////////////////// // // ## ###### // ###### ### // ## ############### Shark 3D Engine (www.shark3d.com) // ########## # # # // ######## Copyright (c) 1996-2006 Spinor GmbH. // ######### # # # All rights reserved. // ## ########## // ## // /////////////////////////////////////////////////////////////////////////////// #include "drv_d3d9_eng.h" #include "drv_d3d9_mmx.h" #include "drv_d3d9_types.h" #include "drv_d3d9_util.h" #include "drv_d3d9_enum.h" #include "drv_d3d9_progutil.h" #include "drv_d3d9_paramblk.h" #include "drv_d3d9_inspect.h" #include "drv/util/drv_util_gfxutil.h" #include "sys/core/sys_util.h" #include "general/general_def.h" #include "util/base/util_strutil.h" #include "util/base/util_strbuf.h" #include "util/base/util_rawstrutil.h" #include "util/snk/util_snk_work.h" #include "util/snk/util_snk_extractutil.h" /////////////////////////////////////////////////////////////////////////////// S3D_UTIL_RECOG_DEFINEINFO(s3d_CDrvD3d9Batch); s3d_CDrvD3d9Batch::s3d_CDrvD3d9Batch( s3d_CUtilMsgHandler *ReportMsgHandler) { S3D_UTIL_RECOG_INITOBJ(s3d_CDrvD3d9Batch); m_ReportMsgHandler = ReportMsgHandler; // use_triangle_strips = false; } s3d_CDrvD3d9Batch::~s3d_CDrvD3d9Batch() { if(m_ReportMsgHandler) { s3d_CUtilMsg m; m.m_Code = "drv/imp/directx/d3d9/drv_d3d9_eng.report_batch_destroy"; m.m_StdTempl = "D3D: " "Destroying batch Addr=[1]."; m.AddInfo(""); m.AddInfo(s3d_CUtilStrUtil::StrOfPtr(this)); s3d_UtilMsgReportNote(m_ReportMsgHandler, m); } } /////////////////////////////////////////////////////////////////////////////// s3d_CDrvD3d9GfxEngCLOD::s3d_CDrvD3d9GfxEngCLOD( s3d_CUtilMsgHandler *MsgHandler, s3d_CUtilStr_cr Info, bool Bare, s3d_CCompSuppl *CompSuppl, s3d_CUtilAtomMgr *AtomMgr, s3d_CUtilMemPool *MemPool, s3d_CUtilStorageMgr *StorageMgr, s3d_CCompResMgr *ResMgr, s3d_CCompSuppl *UnivProgSuppl, s3d_CCompSuppl *UnivProgGivenSuppl, s3d_CUtilSnkChunk *DefaultOutParam) { m_MsgHandler = MsgHandler; m_Info = Info; m_AtomMgr = AtomMgr; m_MemPool = MemPool; m_ResMgr = ResMgr; m_StorageMgr = StorageMgr; m_UnivProgSuppl = UnivProgSuppl; m_UnivProgGivenSuppl = UnivProgGivenSuppl; m_DefaultOutParam = DefaultOutParam; m_CtxWin32 = 0; m_hWnd = 0; m_Prop = 0; m_BufWidth = 0; m_BufHeight = 0; m_BufColorAlphaBits = 0; m_BufDepthBits = 0; m_BufStencilBits = 0; m_BufDepthBiasScale = 0; m_SWVertProc = false; m_DevFlags = 0; m_DevType = D3DDEVTYPE_NULLREF; m_BackBufFmt = D3DFMT_UNKNOWN; m_DepthStencilFmt = D3DFMT_UNKNOWN; m_MainSurfCol = 0; m_MainSurfDepth = 0; m_FrmIdx = 0; m_CurSurfColUsedCnt = 0; m_MaxSimRTCnt = 0; m_CurSurfDepth = 0; m_DestProp = 0; m_DestCnt = -1; m_Adapter = 0; s3d_SysMemset(&m_DevCaps, 0, S3D_SYS_SIZEOFS(m_DevCaps)); s3d_SysMemset(&m_PresentParam, 0, S3D_SYS_SIZEOFS(m_PresentParam)); m_UseMSAA = false; s3d_SysMemset(&m_Viewport, 0, S3D_SYS_SIZEOFS(m_Viewport)); s3d_SysMemset(&m_ScissorRect, 0, S3D_SYS_SIZEOFS(m_ScissorRect)); m_CurScissorEnabled = false; m_CullMode = 0; m_DepthTestMode = 0; m_DepthBiasOverlay = 0; m_DepthBiasOffs = 0; m_BlendColSrcFac = 0; m_BlendColDestFac = 0; m_BlendColOp = 0; m_BlendAlphaSrcFac = 0; m_BlendAlphaDestFac = 0; m_BlendAlphaOp = 0; m_PaintMode = 0; m_StencilTestModeFront = 0; m_StencilTestModeBack = 0; m_StencilOpFailFront = 0; m_StencilOpDepthFailFront = 0; m_StencilOpDepthPassFront = 0; m_StencilOpFailBack = 0; m_StencilOpDepthFailBack = 0; m_StencilOpDepthPassBack = 0; m_AlphaTestMode = 0; m_AlphaTestRef = 0; m_PrevUsedFFP = false; m_MainProjOffsX = 0; m_MainProjOffsY = 0; m_CurProjOffsX = 0; m_CurProjOffsY = 0; m_MatProjDirty = false; s3d_SysMemset(&m_MatProj, 0, S3D_SYS_SIZEOFS(m_MatProj)); m_ParamBlk.Reset(); m_ParamStateProg.Done(); m_ParamStateFFP.Done(); m_MaxAttrCnt = 0; s3d_CSysIntps iAttr; for(iAttr = 0; iAttr < S3D_DRV_D3D9_MAX_ATTR_CNT; iAttr++) { m_CurTexTransfFlagsArray[iAttr] = D3DTTFF_DISABLE; m_CurTexOpArray[iAttr] = D3DTOP_DISABLE ; } m_MaxSampCnt = 0; s3d_CSysIntps iSamp; for(iSamp = 0; iSamp < S3D_DRV_D3D9_MAX_SAMPLER_CNT; iSamp++) { m_CurSampParamArray[iSamp].m_FilterMin = D3DTEXF_POINT; m_CurSampParamArray[iSamp].m_FilterMag = D3DTEXF_POINT; m_CurSampParamArray[iSamp].m_FilterMip = D3DTEXF_NONE; m_CurSampParamArray[iSamp].m_AddrX = D3DTADDRESS_WRAP; m_CurSampParamArray[iSamp].m_AddrY = D3DTADDRESS_WRAP; m_CurSampParamArray[iSamp].m_AddrZ = D3DTADDRESS_WRAP; m_CurSampParamArray[iSamp].m_SRGBTex = FALSE; m_SampModeArray[iSamp] = 0; } m_ParamBlk.m_SampMaxUsedCnt = 0; m_SampMaxWantCnt = 0; m_MinLbTexWidth = 0; m_MaxLbTexWidth = 0; m_MinLbTexHeight = 0; m_MaxLbTexHeight = 0; m_MinLbVolTexExt = 0; m_MaxLbVolTexExt = 0; m_MaxFilterMinStd = D3DTEXF_LINEAR; m_MaxFilterMagStd = D3DTEXF_LINEAR; m_MaxFilterMinCube = D3DTEXF_LINEAR; m_MaxFilterMagCube = D3DTEXF_LINEAR; m_MaxFilterMinVol = D3DTEXF_LINEAR; m_MaxFilterMagVol = D3DTEXF_LINEAR; m_MaxFilterMipStd = D3DTEXF_POINT; m_MaxFilterMipCube = D3DTEXF_POINT; m_MaxFilterMipVol = D3DTEXF_POINT; m_MatBoneDirty = false; m_MaxLightCnt = 0; m_LightingEnabled = false; m_WantLighting = false; m_WantLightCnt = 0; int iLight; for(iLight = 0; iLight < S3D_DRV_D3D9_MAX_LIGHT_CNT; iLight++) { m_LightEnabledArray[iLight] = false; m_LightDirtyArray[iLight] = false; } m_IdxFlushCnt = 0; } s3d_CDrvD3d9GfxEngCLOD::~s3d_CDrvD3d9GfxEngCLOD() { Done(); } void s3d_CDrvD3d9GfxEngCLOD::Done() { /* if(m_CtxWin32) m_CtxWin32->Win32NotifDestroyGfx(); m_CtxWin32 = 0; m_Ctx = 0; */ if(m_D3dDev) { S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->EvictManagedResources()); } m_D3dDev.Reset(); m_D3d.Reset(); } s3d_CUtilStr s3d_CDrvD3d9GfxEngCLOD::GetDesc() const { s3d_CUtilStrBuf Result; Result.Append("D3D v0x"); DWORD D3dVers = DIRECT3D_VERSION | D3D_SDK_VERSION; #ifdef D3D_DEBUG_INFO D3dVers &= ~0x80000000; #endif Result.AppendInt(D3dVers, 0, s3d_CUtilStrNum::Format_Hex); Result.Append(" \""); Result.Append(m_AdapterDesc); Result.Append("\" "); if(m_DevType == D3DDEVTYPE_REF) Result.Append("REF "); if(m_DevFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING) Result.Append("SWVB "); if(m_DevFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING) Result.Append("HWVB "); if(m_DevFlags & D3DCREATE_MIXED_VERTEXPROCESSING) Result.Append("MXVB "); if(m_DevFlags & D3DCREATE_PUREDEVICE) Result.Append("PURE "); Result.Append(s3d_CDrvD3d9Util::StrOfMutliSampleType( m_PresentParam.MultiSampleType)); Result = s3d_CUtilStrUtil::Trim(Result); return Result; } s3d_CDrvGfxOutPtr s3d_CDrvD3d9GfxEngCLOD::CreateOut( s3d_CUtilStr_cr Info, s3d_CDrvCtx *Ctx, s3d_CUtilStr_cr Device, int Prop, int Left, int Top, int Width, int Height, int Depth, int Frequency, s3d_CUtilSnkChunk *Param) { s3d_CDrvD3d9ParamPtr D3dParam = S3D_SYS_NEW s3d_CDrvD3d9Param; D3dParam->Init(m_MsgHandler, Param); return CreateOut( Info, Ctx, Device, Prop, Top, Left, Width, Height, Depth, Frequency, D3dParam); } s3d_CDrvGfxOutPtr s3d_CDrvD3d9GfxEngCLOD::CreateOut( s3d_CUtilStr_cr Info, s3d_CDrvCtx *Ctx, s3d_CUtilStr_cr Device, int Prop, int Left, int Top, int Width, int Height, int Depth, int Frequency, s3d_CUtilRecogBase *Param) { s3d_CDrvD3d9ParamPtr D3dParam = s3d_UtilRecogCastCheck( m_MsgHandler, Info, Param); return CreateOut( Info, Ctx, Device, Prop, Top, Left, Width, Height, Depth, Frequency, D3dParam); } s3d_CDrvGfxOutPtr s3d_CDrvD3d9GfxEngCLOD::CreateOut( s3d_CUtilStr_cr Info, s3d_CDrvCtx *Ctx, s3d_CUtilStr_cr Device, int Prop, int Left, int Top, int Width, int Height, int Depth, int Frequency, s3d_CDrvD3d9Param *D3dParam) { if(m_Ctx) return 0; // Already created. if(!D3dParam) return 0; m_Ctx = Ctx; m_Prop = Prop; m_D3dParam = D3dParam; m_StateMgr.m_MsgHandler = m_MsgHandler; m_StateMgr.m_Env = &m_Env; if(!D3DXCheckVersion(D3D_SDK_VERSION, D3DX_SDK_VERSION)) { s3d_CDrvD3d9Error e; e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_eng.wrong_d3dx_version"; e.m_StdTempl = "D3D: Wrong d3d version. " "Expecting D3D_SDK_VERSION=0x[1] " "and D3DX_SDK_VERSION=0x[2]. "; e.AddInfo(m_Info); e.AddInfo(s3d_CUtilStrUtil::StrOfInt( D3D_SDK_VERSION, 0, s3d_CUtilStrNum::Format_HexPadding)); e.AddInfo(s3d_CUtilStrUtil::StrOfInt( D3DX_SDK_VERSION, 0, s3d_CUtilStrNum::Format_HexPadding)); s3d_UtilMsgReportError(m_MsgHandler, e); return 0; } m_D3d.EmptyRef() = Direct3DCreate9(D3D_SDK_VERSION); if(!m_D3d) { s3d_CDrvD3d9Error e; e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_eng.dev_err"; e.m_StdTempl = "D3D: Error creating direct3d."; e.AddInfo(m_Info); s3d_UtilMsgReportError(m_MsgHandler, e); return 0; } #ifdef S3D_GENERAL_DEBUG D3DXDebugMute(FALSE); #else D3DXDebugMute(TRUE); #endif // Create window. m_CtxWin32 = s3d_UtilRttiCastCheck( m_MsgHandler, m_Info, Ctx); if(!m_CtxWin32) { s3d_CDrvD3d9Error e; e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_eng.no_context"; e.m_StdTempl = "D3D: No Win32 context."; e.AddInfo(m_Info); s3d_UtilMsgReportError(m_MsgHandler, e); return 0; } // Init d3d environment m_Env.Init(m_MsgHandler, D3dParam); bool IsFullscreen = false; bool IsFullscreenWindow = false; if(m_Prop & s3d_CDrvGfxMgr::Prop_Fullscreen) { if(D3dParam->m_FakedFullscreen) IsFullscreenWindow = true; else IsFullscreen = true; } bool NoStencil = false; if(m_Prop & s3d_CDrvGfxMgr::Prop_NoStencil) NoStencil = true; m_Adapter = D3DADAPTER_DEFAULT; if(!Device.IsEmpty()) { int DevId = 0; if(s3d_CUtilStrUtil::ParseInt(DevId, Device)) m_Adapter = DevId; if(m_Adapter >= m_D3d->GetAdapterCount()) { s3d_CDrvD3d9Error e; e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_eng.invalid_device"; e.m_StdTempl = "D3D: No such d3d device ([1])."; e.AddInfo(m_Info); e.AddInfo(Device); s3d_UtilMsgReportError(m_MsgHandler, e); m_Adapter = D3DADAPTER_DEFAULT; } } D3DADAPTER_IDENTIFIER9 AdapterIdentifier; DWORD Flags = 0; S3D_DRV_D3D9_CHECK( &m_Env, m_D3d->GetAdapterIdentifier( m_Adapter, Flags, &AdapterIdentifier)); m_AdapterDesc = s3d_CUtilStrUtil::Trim(AdapterIdentifier.Description); HMONITOR hMonitor = m_D3d->GetAdapterMonitor(m_Adapter); m_CtxWin32->Win32CreateWindow( m_MsgHandler, m_Info, 0, IsFullscreenWindow, hMonitor, Top, Left, Width, Height, Depth, Frequency); m_hWnd = m_CtxWin32->Win32GetWndHandle(); if(!m_hWnd) { s3d_CUtilMsg e; e.m_Code = "drv/imp/directx/d3d9/drv_d3d_eng.no_wnd_handle"; e.m_StdTempl = "No window created yet."; e.AddInfo(Info); s3d_UtilMsgReportError(m_MsgHandler, e); return 0; } // Create d3d device. m_BufWidth = -1; m_BufHeight = -1; m_BufColorAlphaBits = 0; m_BufDepthBits = 0; m_BufStencilBits = 0; m_BufDepthBiasScale = 0; m_DevType = D3DDEVTYPE_HAL; if(D3dParam->m_RefDriver) m_DevType = D3DDEVTYPE_REF; HRESULT Result; S3D_DRV_D3D9_CALLCHECK( &m_Env, Result, m_D3d->GetDeviceCaps( m_Adapter, m_DevType, &m_DevCaps)); if(FAILED(Result)) return 0; m_DevFlags = 0; if(!D3dParam->m_DisableFPUPreserve) m_DevFlags |= D3DCREATE_FPU_PRESERVE; if(D3dParam->m_PureDevice) m_DevFlags |= D3DCREATE_PUREDEVICE; int ReqVertShadVerMajor, ReqVertShadVerMinor; s3d_CDrvD3d9ProgUtil::ParseMajorMinor( ReqVertShadVerMajor, ReqVertShadVerMinor, D3dParam->m_ReqVertShadVer.GetLen(), D3dParam->m_ReqVertShadVer.GetChars()); if(s3d_CDrvD3d9ProgUtil::CompVer( ReqVertShadVerMajor, ReqVertShadVerMinor, D3DSHADER_VERSION_MAJOR(m_DevCaps.VertexShaderVersion), D3DSHADER_VERSION_MINOR(m_DevCaps.VertexShaderVersion)) > 0) { m_DevFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING; S3D_SYS_ASSERT(D3dParam->m_ForceHWVertexBuf == false); } else { if(D3dParam->m_ForceHWVertexBuf) m_DevFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING; else if(D3dParam->m_ForceSWVertexBuf) m_DevFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING; else m_DevFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING; } m_SWVertProc = (m_DevFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING) != 0; int AdapterDepth = Depth; BOOL Windowed = FALSE; if(!IsFullscreen || IsFullscreenWindow) { // Windowed device. RECT ClientRect; s3d_SysMemset(&ClientRect, 0, S3D_SYS_SIZEOFS(ClientRect)); GetClientRect(m_hWnd, &ClientRect); Windowed = TRUE; Width = ClientRect.right - ClientRect.left; Height = ClientRect.bottom - ClientRect.top; D3DDISPLAYMODE AdapterMode; S3D_DRV_D3D9_CHECK( &m_Env, m_D3d->GetAdapterDisplayMode( m_Adapter, &AdapterMode)); AdapterDepth = s3d_CDrvD3d9Util::ColBitsOfFmt(AdapterMode.Format); if(AdapterDepth > 16) AdapterDepth = 32; } else { // Fullscreen device. } s3d_CDrvD3d9Enum Enum; Enum.Enumerate( m_MsgHandler, Info, m_MemPool, D3dParam, m_D3d, IsFullscreen, NoStencil); s3d_CDrvD3d9EnumEntry EnumEntry; if(!Enum.SearchEntry( EnumEntry, m_Adapter, Prop, Width, Height, AdapterDepth, Frequency, IsFullscreen || IsFullscreenWindow)) { s3d_CDrvD3d9Error e; e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_eng.no_valid_adapter"; e.m_StdTempl = "D3D: No valid adapter found."; e.AddInfo(m_Info); s3d_UtilMsgReportError(m_MsgHandler, e); return 0; } Enum.GetBufferFmts(Depth, m_BackBufFmt, m_DepthStencilFmt, EnumEntry); if(m_BackBufFmt == D3DFMT_UNKNOWN) { s3d_CDrvD3d9Error e; e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_eng.backbuf_fmt_err"; e.m_StdTempl = "D3D: No valid backbuffer format found."; e.AddInfo(m_Info); s3d_UtilMsgReportError(m_MsgHandler, e); return 0; } if(m_DepthStencilFmt == D3DFMT_UNKNOWN) { s3d_CDrvD3d9Error e; e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_eng.depthstencil_fmt_err"; e.m_StdTempl = "D3D: No valid depthstencil format found."; e.AddInfo(m_Info); s3d_UtilMsgReportError(m_MsgHandler, e); return 0; } m_BufColorAlphaBits = s3d_CDrvD3d9Util::ColBitsOfFmt(m_BackBufFmt); m_BufDepthBits = s3d_CDrvD3d9Util::DepthBitsOfFmt(m_DepthStencilFmt); m_BufStencilBits = s3d_CDrvD3d9Util::StencilBitsOfFmt(m_DepthStencilFmt); int ScaleZInt = s3d_CSysInt32u(-1) >> (32 - m_BufDepthBits); m_BufDepthBiasScale = -1.f / s3d_SysFloatOfInt(ScaleZInt); const D3DMULTISAMPLE_TYPE s3d_MultiSampleType[] = { D3DMULTISAMPLE_NONE, D3DMULTISAMPLE_NONE, //D3DMULTISAMPLE_NONMASKABLE D3DMULTISAMPLE_2_SAMPLES, D3DMULTISAMPLE_3_SAMPLES, D3DMULTISAMPLE_4_SAMPLES, D3DMULTISAMPLE_5_SAMPLES, D3DMULTISAMPLE_6_SAMPLES, D3DMULTISAMPLE_7_SAMPLES, D3DMULTISAMPLE_8_SAMPLES, D3DMULTISAMPLE_9_SAMPLES, D3DMULTISAMPLE_10_SAMPLES, D3DMULTISAMPLE_11_SAMPLES, D3DMULTISAMPLE_12_SAMPLES, D3DMULTISAMPLE_13_SAMPLES, D3DMULTISAMPLE_14_SAMPLES, D3DMULTISAMPLE_15_SAMPLES, D3DMULTISAMPLE_16_SAMPLES, }; int MaxMultiSample = S3D_SYS_ARRAYCNTS(s3d_MultiSampleType) - 1; int WantMultiSample = D3dParam->m_MultiSample; if(WantMultiSample == 0) WantMultiSample = MaxMultiSample; else if(WantMultiSample > 0) s3d_SysSetToMin(WantMultiSample, MaxMultiSample); D3DMULTISAMPLE_TYPE MultiSampleType = D3DMULTISAMPLE_NONE; DWORD MultiSampleQuality = 0; int iMultiSample; for(iMultiSample = WantMultiSample; WantMultiSample >= 0; iMultiSample--) { D3DMULTISAMPLE_TYPE WantMultiSampleType = s3d_MultiSampleType[iMultiSample]; HRESULT Result; S3D_DRV_D3D9_HRESCALL( &m_Env, Result, m_D3d->CheckDeviceMultiSampleType( m_Adapter, m_DevType, m_BackBufFmt, Windowed, WantMultiSampleType, &MultiSampleQuality)); if(FAILED(Result)) continue; S3D_DRV_D3D9_HRESCALL( &m_Env, Result, m_D3d->CheckDeviceMultiSampleType( m_Adapter, m_DevType, m_DepthStencilFmt, Windowed, WantMultiSampleType, 0)); if(FAILED(Result)) continue; MultiSampleType = WantMultiSampleType; break; } // The valid range is between zero and one less than the level // returned by pQualityLevels used by CheckDeviceMultiSampleType(). if(MultiSampleQuality > 0) MultiSampleQuality = MultiSampleQuality - 1; m_UseMSAA = (MultiSampleType != D3DMULTISAMPLE_NONE); // Finally create device int RefreshRate = Frequency; if(Windowed || Frequency < 0) RefreshRate = 0; else if(RefreshRate > EnumEntry.m_GfxEnumEntry.m_Freq ) RefreshRate = EnumEntry.m_GfxEnumEntry.m_Freq; UINT PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; if(m_Prop & s3d_CDrvGfxMgr::Prop_Synch) PresentationInterval = D3DPRESENT_INTERVAL_ONE; s3d_SysMemset(&m_PresentParam, 0, S3D_SYS_SIZEOFS(m_PresentParam)); m_PresentParam.BackBufferWidth = Width; m_PresentParam.BackBufferHeight = Height; m_PresentParam.BackBufferFormat = m_BackBufFmt; m_PresentParam.BackBufferCount = 1; if(D3dParam->m_UseTrippleBuffering) m_PresentParam.BackBufferCount = 2; m_PresentParam.MultiSampleType = MultiSampleType; m_PresentParam.MultiSampleQuality = MultiSampleQuality; m_PresentParam.SwapEffect = D3DSWAPEFFECT_DISCARD; /* if((m_Caps.Caps3 & D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD) == 0) m_PresentParam.SwapEffect = D3DSWAPEFFECT_COPY; */ m_PresentParam.hDeviceWindow = m_hWnd; m_PresentParam.Windowed = Windowed; m_PresentParam.EnableAutoDepthStencil = true; m_PresentParam.AutoDepthStencilFormat = m_DepthStencilFmt; //StretchRects does not support discardable depth/stencil surfaces. m_PresentParam.Flags = 0;//D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL; m_PresentParam.FullScreen_RefreshRateInHz = RefreshRate; m_PresentParam.PresentationInterval = PresentationInterval; //Force NVIDIA PerfHUD #if 0 m_DevType = D3DDEVTYPE_REF; S3D_DRV_D3D9_HRESCALL( &m_Env, m_Adapter, m_D3d->GetAdapterCount() - 1); Flags = 0; S3D_DRV_D3D9_CHECK( &m_Env, m_D3d->GetAdapterIdentifier( m_Adapter, Flags, &AdapterIdentifier)); m_AdapterDesc = s3d_CUtilStrUtil::Trim(AdapterIdentifier.Description); m_DevFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING; #endif D3DPERF_SetOptions(D3dParam->m_PixEnabled ? 0 : 1); s3d_CDrvD3d9Device D3dDev; S3D_DRV_D3D9_CHECK( &m_Env, m_D3d->CreateDevice( m_Adapter, m_DevType, m_hWnd, m_DevFlags, &m_PresentParam, &D3dDev.EmptyRef())); if(!D3dDev) { s3d_CDrvD3d9Error e; e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_eng.cannot_create_device"; e.m_StdTempl = "D3D: Could not create Direct3D device."; e.AddInfo(m_Info); s3d_UtilMsgReportError(m_MsgHandler, e); return 0; } S3D_DRV_D3D9_CALLCHECK( &m_Env, Result, D3dDev->GetDeviceCaps(&m_DevCaps)); if(FAILED(Result)) return 0; S3D_DRV_D3D9_CHECK( &m_Env, D3dDev->GetSwapChain( 0, &m_SwapChain.EmptyRef())); if(!m_SwapChain) return 0; m_D3dDev = D3dDev; m_StateMgr.m_D3dDev = D3dDev; m_D3dCtx = S3D_SYS_NEW s3d_CDrvD3d9Ctx; m_D3dCtx->m_D3d = m_D3d; m_D3dCtx->m_D3dDev = m_D3dDev; m_D3dCtx->m_BackBufFmt = m_BackBufFmt; m_D3dCtx->m_MultiSampleType = m_PresentParam.MultiSampleType; m_D3dCtx->m_MultiSampleQuality = m_PresentParam.MultiSampleQuality; m_D3dCtx->m_Adapter = m_Adapter; m_D3dCtx->m_DevType = m_DevType; m_D3dCtx->m_Windowed = Windowed == TRUE; m_D3dCtx->m_MsgHandler = m_MsgHandler; m_D3dCtx->m_MemPool = m_MemPool; m_D3dCtx->m_Env = &m_Env; m_D3dCtx->m_D3dParam = D3dParam; // Texture stuff InitTexturing(); m_ParamBlk.Reset(); D3DXMatrixIdentity(&m_MatProj); m_MatProjDirty = false; m_Viewport.X = -1; m_Viewport.Y = -1; m_Viewport.Width = -1; m_Viewport.Height = -1; m_Viewport.MinZ = 0; m_Viewport.MaxZ = 1; m_ScissorRect.left = -1; m_ScissorRect.top = -1; m_ScissorRect.right = -1; m_ScissorRect.bottom = -1; m_CurScissorEnabled = false; CalcProjOffs( m_MainProjOffsX, m_MainProjOffsY, m_PresentParam.BackBufferWidth, m_PresentParam.BackBufferHeight); m_CurProjOffsX = m_MainProjOffsX; m_CurProjOffsY = m_MainProjOffsY; // Render to texture InitRenderToTex(); // Light InitLighting(); // Init all managers s3d_CDrvD3d9ProgCtxPtr ProgCtx = S3D_SYS_NEW s3d_CDrvD3d9ProgCtx; ProgCtx->m_MsgHandler = m_MsgHandler; ProgCtx->m_MemPool = m_MemPool; ProgCtx->m_ResMgr = m_ResMgr; ProgCtx->m_AtomMgr = m_AtomMgr; ProgCtx->m_UnivProgSuppl = m_UnivProgSuppl; ProgCtx->m_UnivProgGivenSuppl = m_UnivProgGivenSuppl; ProgCtx->m_Env = &m_Env; ProgCtx->m_D3dParam = m_D3dParam; ProgCtx->m_D3dDev = m_D3dDev; ProgCtx->m_MaxVS = m_DevCaps.VertexShaderVersion; ProgCtx->m_MaxPS = m_DevCaps.PixelShaderVersion; ProgCtx->m_MaxLightCnt = m_MaxLightCnt; ProgCtx->m_MaxAttrCnt = m_MaxAttrCnt; ProgCtx->m_MaxSampCnt = m_MaxSampCnt; m_ProgMgr = S3D_SYS_NEW s3d_CDrvD3d9ProgMgr(ProgCtx); s3d_CSysIntps VertIdxLimit = m_DevCaps.MaxVertexIndex + 1; m_BufMgr = S3D_SYS_NEW s3d_CDrvD3d9BufMgr( m_MsgHandler, m_ProgMgr, m_Env, D3dParam, VertIdxLimit, m_D3dDev); m_TexMgr = S3D_SYS_NEW s3d_CDrvD3d9TexMgr(m_D3dCtx); m_VisibMgr = S3D_SYS_NEW s3d_CDrvD3d9VisibMgr( m_MsgHandler, m_Env, D3dParam, m_D3dDev); m_ParamStateProg.Done(); m_ParamStateFFP.Done(); SetDefaultState(); InitDevCaps(); m_FrmIdx = 0; m_FlushEvent.Init(&m_Env, m_D3dDev); m_IdxFlushCnt = 0; return S3D_SYS_NEW s3d_CDrvD3d9GfxOut(this); } s3d_CUtilSnkChunkPtr s3d_CDrvD3d9GfxEngCLOD::GetDefaultOutParam() { return m_DefaultOutParam; } void s3d_CDrvD3d9GfxEngCLOD::RegisterNotifCtxChanged( s3d_CUtilNotifRecip *Recip) { m_NotifMgrCtx.Register(Recip); } void s3d_CDrvD3d9GfxEngCLOD::Alter( s3d_CUtilStr_cr Info, s3d_CUtilStr_cr Device, int Prop, int Left, int Top, int Width, int Height, int Depth, int Frequency, s3d_CUtilSnkChunk *Param) { s3d_CDrvD3d9ParamPtr D3dParam = S3D_SYS_NEW s3d_CDrvD3d9Param; D3dParam->Init(m_MsgHandler, Param); Alter(Info, Device, Prop, Top, Left, Width, Height, Depth, Frequency, D3dParam); } void s3d_CDrvD3d9GfxEngCLOD::Alter( s3d_CUtilStr_cr Info, s3d_CUtilStr_cr Device, int Prop, int Left, int Top, int Width, int Height, int Depth, int Frequency, s3d_CDrvD3d9Param *D3dParam) { HMONITOR hMonitor = 0; if(m_D3d) hMonitor = m_D3d->GetAdapterMonitor(m_Adapter); s3d_CUtilSnkChunkPtr WndParam; bool IsFullscreenWindow = false; if(m_CtxWin32) { m_CtxWin32->Win32AlterWindow( m_MsgHandler, Info, WndParam, IsFullscreenWindow, hMonitor, Top, Left, Width, Height, Depth, Frequency); } m_PresentParam.Windowed = ((Prop & s3d_CDrvGfxMgr::Prop_Fullscreen) == 0); UINT PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; if(Prop & s3d_CDrvGfxMgr::Prop_Synch) PresentationInterval = D3DPRESENT_INTERVAL_ONE; m_PresentParam.BackBufferWidth = Width; m_PresentParam.BackBufferHeight = Height; ResetDevice(); m_Prop = Prop; } void s3d_CDrvD3d9GfxEngCLOD::UserFunc(s3d_CUtilCoStr Func) { } bool s3d_CDrvD3d9GfxEngCLOD::HasCap( s3d_CSysIntps CapLen, const s3d_CSysChar *CapStart) const { if(s3d_CUtilRawStrUtil::IsEqual(CapLen, CapStart, S3D_DRV_D3D9_ENG_CAP_D3D)) return true; if(s3d_CUtilRawStrUtil::IsEqual(CapLen, CapStart, S3D_DRV_D3D9_ENG_CAP_D3D9)) return true; if(s3d_CUtilRawStrUtil::IsEqual(CapLen, CapStart, S3D_DRV_GFX_CAP_RENDER_TEX_COLORALPHA)) return true; if(s3d_CUtilRawStrUtil::IsEqual(CapLen, CapStart, S3D_DRV_GFX_CAP_RENDER_TEX_DEPTH)) return m_HasNvDepthTex || m_CanRenderDepth; if(s3d_CUtilRawStrUtil::IsEqual(CapLen, CapStart, S3D_DRV_GFX_CAP_STENCIL_TWOSIDED)) return ((m_DevCaps.StencilCaps & D3DSTENCILCAPS_TWOSIDED) != 0); if(s3d_CUtilRawStrUtil::IsEqual(CapLen, CapStart, S3D_DRV_GFX_CAP_STENCIL_WRAP)) return true; return false; } s3d_CDrvGfxStat *s3d_CDrvD3d9GfxEngCLOD::GetStat() { return &m_Stat; } int s3d_CDrvD3d9GfxEngCLOD::GetSampCnt() const { return m_MaxSampCnt; } void s3d_CDrvD3d9GfxEngCLOD::SnapTexSize( int &Width, int &Height, int &Depth, int TexProp, int SnapProp) { bool Snap = true; bool UseVol = false; bool UseCube = false; int MinWidth = (1 << m_MinLbTexWidth); int MaxWidth = (1 << m_MaxLbTexWidth); int MinHeight = (1 << m_MinLbTexHeight); int MaxHeight = (1 << m_MaxLbTexHeight); int MinDepth = (1 << m_MinLbVolTexExt); int MaxDepth = (1 << m_MaxLbVolTexExt); bool WantMipMap = false; if((TexProp & TexProp_Mipmap) != 0) WantMipMap = true; bool CanRect = false; bool CanNPOT2 = false; if((m_DevCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) != 0) CanRect = true; if(!CanRect && (m_DevCaps.TextureCaps & D3DPTEXTURECAPS_POW2) == 0) CanNPOT2 = true; if((TexProp & TexProp_RestrUsage) != 0) { if(CanRect || CanNPOT2) Snap = false; } else if((TexProp & TexProp_Volume) != 0) { UseVol = true; Snap = true; MinWidth = MinDepth; MaxWidth = MaxDepth; MinHeight = MinDepth; MaxHeight = MaxDepth; MinHeight = MinDepth; MaxHeight = MaxDepth; if((m_DevCaps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2) == 0) Snap = false; } else if((TexProp & TexProp_Cube) != 0) { UseCube = true; Snap = true; if((m_DevCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) == 0) Snap = false; } else { if(CanNPOT2) Snap = false; else if(CanRect && !WantMipMap) Snap = false; } /* if((TexProp & TexProp_Depth) != 0 || (TexProp & TexProp_RenderTarget) != 0) { Snap = false; Width = 512; Height = 512; } */ // NVIDIA depthtex if((TexProp & TexProp_Depth) != 0 && m_HasNvDepthTex) { // Width = 256; // Height = 256; Snap = false; } if(Snap) { int WidthLb, HeightLb, DepthLb; if(SnapProp & TexSnap_PreferDown) { WidthLb = s3d_CDrvUtilGfxUtil::BinLogDownInt(Width); HeightLb = s3d_CDrvUtilGfxUtil::BinLogDownInt(Height); DepthLb = s3d_CDrvUtilGfxUtil::BinLogDownInt(Depth); } else { WidthLb = s3d_CDrvUtilGfxUtil::BinLogUpInt(Width); HeightLb = s3d_CDrvUtilGfxUtil::BinLogUpInt(Height); DepthLb = s3d_CDrvUtilGfxUtil::BinLogUpInt(Depth); } Width = (1 << WidthLb); Height = (1 << HeightLb); Depth = (1 << DepthLb); } s3d_SysSetToMax(Width, MinWidth); s3d_SysSetToMax(Height, MinHeight); s3d_SysSetToMin(Width, MaxWidth); s3d_SysSetToMin(Height, MaxHeight); if(UseVol) { s3d_SysSetToMax(Depth, MinDepth); s3d_SysSetToMin(Depth, MaxDepth); } else Depth = 1; if(UseCube) { int Ext = s3d_SysMax(Width, Height); Width = Ext; Height = Ext; } s3d_SysSetToMax(Width, 1); s3d_SysSetToMax(Height, 1); s3d_SysSetToMax(Depth, 1); } s3d_CDrvGfxTexPtr s3d_CDrvD3d9GfxEngCLOD::CreateTexDirect( s3d_CUtilStr_cr Info, int TexProp, int Width, int Height, int Depth) { if(m_TexMgr) return m_TexMgr->CreateTexDirect(Info, TexProp, Width, Height, Depth); return 0; } s3d_CDrvGfxTexPtr s3d_CDrvD3d9GfxEngCLOD::CreateTexStream( s3d_CUtilStr_cr Info, int TexProp, s3d_CUtilStream *Stream) { if(m_TexMgr) return m_TexMgr->CreateTexStream(Info, TexProp, Stream); return 0; } s3d_CDrvGfxTexPtr s3d_CDrvD3d9GfxEngCLOD::CreateTexVideo( s3d_CUtilStr_cr Info, int TexProp, s3d_CDrvVideoPlayer *VideoPlayer) { if(m_TexMgr) return m_TexMgr->CreateTexVideo(Info, TexProp, VideoPlayer); return 0; } s3d_CDrvGfxTexPtr s3d_CDrvD3d9GfxEngCLOD::CreateTexIdent( s3d_CUtilStr_cr Info, int TexProp, s3d_CUtilStr_cr Ident) { return 0; } s3d_CDrvGfxTexPtr s3d_CDrvD3d9GfxEngCLOD::CreateTexUser( s3d_CUtilStr_cr Info, int TexProp, s3d_CCompObj *UserObj) { return 0; } void s3d_CDrvD3d9GfxEngCLOD::SetSampTex( int Samp, s3d_CDrvGfxTex *Tex) { if(Samp < 0) return; if(Samp >= m_MaxSampCnt) return; s3d_CDrvD3d9TexObjBase *TexImpl = s3d_UtilRecogCastSilent(Tex); if(m_WantSampTexArray[Samp] != TexImpl) { s3d_SysSetToMax(m_SampMaxWantCnt, Samp + 1); m_WantSampTexArray[Samp] = TexImpl; } } void s3d_CDrvD3d9GfxEngCLOD::SetSampTexElseNone( int SampStart) { if(SampStart < 0) return; if(SampStart >= m_MaxSampCnt) return; int iSamp = SampStart; int SampEnd = s3d_SysMax(m_ParamBlk.m_SampMaxUsedCnt, m_SampMaxWantCnt); while(iSamp < SampEnd) { if(m_WantSampTexArray[iSamp]) { m_WantSampTexArray[iSamp] = 0; s3d_SysSetToMax(m_SampMaxWantCnt, iSamp + 1); } iSamp++; } } void s3d_CDrvD3d9GfxEngCLOD::SetSampMode( int Samp, int SampMode) { if(Samp < 0) return; if(Samp >= m_MaxSampCnt) return; if(m_SampModeArray[Samp] == SampMode) return; m_SampModeArray[Samp] = SampMode; s3d_SysSetToMax(m_SampMaxWantCnt, Samp + 1); } s3d_CDrvGfxProgPtr s3d_CDrvD3d9GfxEngCLOD::CreateProg( s3d_CUtilNotifGather *NotifGather, s3d_CUtilSnkChunk *Desc) { if(!m_D3dDev) return 0; if(!Desc) return 0; if(!m_ProgMgr) return 0; return m_ProgMgr->CreateProg(NotifGather, Desc); } void s3d_CDrvD3d9GfxEngCLOD::GetMainSize(int &Width, int &Height) const { if(!m_D3dDev) { Width = 0; Height = 0; return; } Width = m_PresentParam.BackBufferWidth; Height = m_PresentParam.BackBufferHeight; } int s3d_CDrvD3d9GfxEngCLOD::GetMainColorAlphaBits() const { if(!m_D3dDev) return 0; return m_BufColorAlphaBits; } void s3d_CDrvD3d9GfxEngCLOD::SetGamma( s3d_CUtilVec3f_cr Gamma) { if(!m_D3dDev) return; float RFac = 1.0f / (255.0f * Gamma.m_x); float GFac = 1.0f / (255.0f * Gamma.m_y); float BFac = 1.0f / (255.0f * Gamma.m_z); D3DGAMMARAMP GammaRamp; if(m_D3dParam->m_EnableGamma2x2) { float Exp = 0.4545f; int i; for(i = 0; i < 256; i++) { float R = s3d_SysFloatOfInt(i) * RFac; float G = s3d_SysFloatOfInt(i) * GFac; float B = s3d_SysFloatOfInt(i) * BFac; float EffR = s3d_SysPow(R, Exp); float EffG = s3d_SysPow(G, Exp); float EffB = s3d_SysPow(B, Exp); GammaRamp.red[i] = s3d_SysIntOfFloatCoarse(EffR * 65535.0f); GammaRamp.green[i] = s3d_SysIntOfFloatCoarse(EffG * 65535.0f); GammaRamp.blue[i] = s3d_SysIntOfFloatCoarse(EffB * 65535.0f); } } else { int i; for(i = 0; i < 256; i++) { float R = s3d_SysFloatOfInt(i) * RFac; float G = s3d_SysFloatOfInt(i) * GFac; float B = s3d_SysFloatOfInt(i) * BFac; GammaRamp.red[i] = s3d_SysIntOfFloatCoarse(R * 65535.0f); GammaRamp.green[i] = s3d_SysIntOfFloatCoarse(G * 65535.0f); GammaRamp.blue[i] = s3d_SysIntOfFloatCoarse(B * 65535.0f); } } if((!m_PresentParam.Windowed && (m_DevCaps.Caps2 & D3DCAPS2_FULLSCREENGAMMA)) || (m_DevCaps.Caps3 & D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION)) { if(m_DevCaps.Caps2 & D3DCAPS2_FULLSCREENGAMMA) { DWORD Flags = D3DSGR_NO_CALIBRATION; if(m_DevCaps.Caps2 & D3DCAPS2_CANCALIBRATEGAMMA) Flags = D3DSGR_CALIBRATE; S3D_DRV_D3D9_CALL( &m_Env, m_D3dDev->SetGammaRamp( 0, Flags, &GammaRamp)); } } else { /* HDC hDC = ::GetDC(m_hWnd); BOOL Ok = ::SetDeviceGammaRamp( hDC, reinterpret_cast(&GammaRamp)); ::ReleaseDC(m_hWnd, hDC); */ } } void s3d_CDrvD3d9GfxEngCLOD::Present() { EndRender(); if(!m_SwapChain) return; DWORD Flags = 0; //Flags |= D3DPRESENT_DONOTWAIT; //if(m_Caps.Caps3 & D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION) // Flags |= D3DPRESENT_LINEAR_CONTENT; HRESULT Result = m_SwapChain->Present(0, 0, 0, 0, Flags); if(Result == D3DERR_DEVICELOST) { s3d_CUtilMsg m; m.m_Code = "drv/imp/directx/d3d9/drv_d3d9_eng.device_lost."; m.m_StdTempl = "D3D: Lost device \"[1]\"."; m.AddInfo(m_Info); m.AddInfo(m_AdapterDesc); //s3d_UtilMsgReportNote(m_MsgHandler, m); ResetDevice(); m_NotifMgrCtx.PerformNotif(); } else if(Result == E_FAIL) { // Ignore } else { S3D_DRV_D3D9_CHECKHRES(&m_Env, Result); } if(m_Ctx && m_CtxWin32) m_CtxWin32->Win32InformGfxSwapped(); m_FrmIdx++; } void s3d_CDrvD3d9GfxEngCLOD::GetCurTargetSize(int &Width, int &Height) const { if(!m_D3dDev) { Width = 0; Height = 0; return; } Width = m_BufWidth; Height = m_BufHeight; } void s3d_CDrvD3d9GfxEngCLOD::EndRender() { if(m_BufWidth >= 0 && m_BufHeight >= 0) { if(m_DestCnt >= 0) EndRenderTex(); else EndRenderMain(); } } void s3d_CDrvD3d9GfxEngCLOD::BeginRenderMain( int DestProp, s3d_CDrvGfxClearParam_cr ClearParam, s3d_CDrvGfxOut *GfxOut) { EndRender(); if(!m_D3dDev) return; m_BufWidth = m_PresentParam.BackBufferWidth; m_BufHeight = m_PresentParam.BackBufferHeight; if(m_PresentParam.Windowed) { RECT ClientRect; s3d_SysMemset(&ClientRect, 0, S3D_SYS_SIZEOFS(ClientRect)); GetClientRect(m_hWnd, &ClientRect); int Width = ClientRect.right - ClientRect.left; int Height = ClientRect.bottom - ClientRect.top; if(m_BufWidth != Width || m_BufHeight != Height) { if(Width > 0 && Height > 0) { s3d_CUtilMsg m; m.m_Code = "drv/imp/directx/d3d9/drv_d3d9_eng.new_client_size"; m.m_StdTempl = "D3D: " "New client size [2]x[3] for \"[1]\"."; m.AddInfo(m_Info); m.AddInfo(m_AdapterDesc); m.AddInfo(s3d_CUtilStrUtil::StrOfInt(Width)); m.AddInfo(s3d_CUtilStrUtil::StrOfInt(Height)); s3d_UtilMsgReportNote(m_MsgHandler, m); m_PresentParam.BackBufferWidth = Width; m_PresentParam.BackBufferHeight = Height; m_BufWidth = Width; m_BufHeight = Height; ResetDevice(); CalcProjOffs(m_MainProjOffsX, m_MainProjOffsY, Width, Height); m_NotifMgrCtx.PerformNotif(); } } } SetProjOffs(m_MainProjOffsX, m_MainProjOffsY); SetViewRect(1); RestoreRenderTargets(); S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->BeginScene()); Clear(ClearParam); } void s3d_CDrvD3d9GfxEngCLOD::EndRenderMain() { if(!m_D3dDev) return; m_BufWidth = -1; m_BufHeight = -1; S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->EndScene()); } void s3d_CDrvD3d9GfxEngCLOD::BeginRenderTex( int DestProp, s3d_CDrvGfxClearParam_cr ClearParam, int Width, int Height, s3d_CSysIntps DestCnt, const s3d_CDrvGfxDest *DestArray) { EndRender(); //S3D_DRV_D3D9_DBGPRINTF("************* BeginRenderTex\n"); if(!m_D3dDev) return; if(DestCnt < 0) return; if(!DestArray) return; m_BufWidth = Width; m_BufHeight = Height; float ProjOffsX, ProjOffsY; CalcProjOffs(ProjOffsX, ProjOffsY, Width, Height); SetProjOffs(ProjOffsX, ProjOffsY); SetViewRect(1); s3d_CSysIntps nDest = s3d_SysMin(m_MaxSimRTCnt, DestCnt); if(m_UseMSAA && (DestProp & DestProp_Antialias)) BeginRenderTexMSAA(Width, Height, nDest, DestArray); else BeginRenderTexStd(Width, Height, nDest, DestArray); m_DestProp = DestProp; if(DestCnt > S3D_SYS_ARRAYCNTS(m_DestArray)) DestCnt = S3D_SYS_ARRAYCNTS(m_DestArray); m_DestCnt = DestCnt; s3d_CSysIntps iDest; for(iDest = 0; iDest < DestCnt; iDest++) m_DestArray[iDest] = DestArray[iDest]; S3D_DRV_D3D9_CALL( &m_Env, m_D3dDev->BeginScene()); Clear(ClearParam); } void s3d_CDrvD3d9GfxEngCLOD::EndRenderTex() { //S3D_DRV_D3D9_DBGPRINTF("************* EndRenderTex\n"); if(!m_D3dDev) return; S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->EndScene()); if(m_UseMSAA && (m_DestProp & DestProp_Antialias)) EndRenderTexMSAA(); else EndRenderTexStd(); m_DestProp = 0; m_DestCnt = -1; m_BufWidth = -1; m_BufHeight = -1; } void s3d_CDrvD3d9GfxEngCLOD::CopyIntoTex( int Width, int Height, int SrcX, int SrcY, s3d_CSysIntps DestCnt, const s3d_CDrvGfxDest *DestArray) { if(!m_D3dDev) return; if(DestCnt < 1) return; s3d_CDrvD3d9TexObjBase *TexImpl = s3d_UtilRecogCastSilent( DestArray[0].m_Tex); if(!TexImpl) return; s3d_CDrvD3d9Surf DestSurf; S3D_DRV_D3D9_CHECK( &m_Env, TexImpl->GetRenderTarget(DestSurf, &DestArray[0])); if(!DestSurf) return; const RECT Rect = {SrcX, SrcY, Width, Height}; HRESULT Result; S3D_DRV_D3D9_CALLCHECK( &m_Env, Result, m_D3dDev->StretchRect( m_CurSurfColArray[0], &Rect, DestSurf, &Rect, D3DTEXF_LINEAR)); if(FAILED(Result)) { const PALETTEENTRY *PaletteEntry = 0; DWORD ColorKey = 0; S3D_DRV_D3D9_CHECK( &m_Env, D3DXLoadSurfaceFromSurface( DestSurf, PaletteEntry, &Rect, m_CurSurfColArray[0], PaletteEntry, &Rect, D3DX_FILTER_LINEAR, ColorKey)); } } void s3d_CDrvD3d9GfxEngCLOD::StoreScreenshot() { if(m_Ctx && m_CtxWin32) m_CtxWin32->Win32StoreScreenshot(); } void s3d_CDrvD3d9GfxEngCLOD::SetViewRect( s3d_CUtilTranslScale2f_cr ViewRect) { if(!m_D3dDev) return; // Use signed temporary vars for "< 0" comparsions since D3DVIEWPORT // uses unsigned member vars. int ViewPortX, ViewPortY, ViewPortWidth, ViewPortHeight; ViewPortX = s3d_SysIntOfFloatNearest( ViewRect.m_Transl.m_x * m_BufWidth); ViewPortY = s3d_SysIntOfFloatNearest( ViewRect.m_Transl.m_y * m_BufHeight); ViewPortWidth = s3d_SysIntOfFloatNearest( ViewRect.m_Scale.m_x * m_BufWidth); ViewPortHeight = s3d_SysIntOfFloatNearest( ViewRect.m_Scale.m_y * m_BufHeight); if(ViewPortWidth <= 0) ViewPortWidth = 1; // Below 1 can make troube for some drivers else if(ViewPortWidth > m_BufWidth) ViewPortWidth = m_BufWidth; if(ViewPortX < 0) ViewPortX = 0; else if((ViewPortX + ViewPortWidth) > m_BufWidth) ViewPortX = m_BufWidth - ViewPortWidth; if(ViewPortHeight <= 0) ViewPortHeight = 1; // Below 1 can make troube for some drivers else if(ViewPortHeight > m_BufHeight) ViewPortHeight = m_BufHeight; if(ViewPortY < 0) ViewPortY = 0; else if((ViewPortY + ViewPortHeight) > m_BufHeight) ViewPortY = m_BufHeight - ViewPortHeight; S3D_SYS_ASSERT(ViewPortX >= 0 && ViewPortY >= 0); if(m_Viewport.X != ViewPortX || m_Viewport.Y != ViewPortY || m_Viewport.Width != ViewPortWidth || m_Viewport.Height != ViewPortHeight) { m_Viewport.X = s3d_SysIntOfIntps(ViewPortX); m_Viewport.Y = s3d_SysIntOfIntps(ViewPortY); m_Viewport.Width = s3d_SysIntOfIntps(ViewPortWidth); m_Viewport.Height = s3d_SysIntOfIntps(ViewPortHeight); S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->SetViewport(&m_Viewport)); } } void s3d_CDrvD3d9GfxEngCLOD::SetViewDepthRange(float NegZ, float PosZ) { if(!m_D3dDev) return; if(m_Viewport.MinZ != NegZ || m_Viewport.MaxZ != PosZ) { m_Viewport.MinZ = NegZ; m_Viewport.MaxZ = PosZ; S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->SetViewport(&m_Viewport)); } } void s3d_CDrvD3d9GfxEngCLOD::SetScissorRect( int X, int Y, int Width, int Height) { if(X < 0) X = 0; if(Y < 0) Y = 0; int ViewWidth = m_Viewport.Width; int ViewHeight = m_Viewport.Height; if(Width <= 0 || Width > ViewWidth) Width = ViewWidth; if(Height <= 0 || Height > ViewHeight) Height = ViewHeight; if(X != m_ScissorRect.left || Y != m_ScissorRect.top || Width != m_ScissorRect.right || Height != m_ScissorRect.bottom) { m_ScissorRect.left = X; m_ScissorRect.top = Y; m_ScissorRect.right = Width; m_ScissorRect.bottom = Height; S3D_DRV_D3D9_CALL( &m_Env, m_D3dDev->SetScissorRect( &m_ScissorRect)); } EnabledScissor(true); } void s3d_CDrvD3d9GfxEngCLOD::SetScissorNone() { EnabledScissor(false); } /////////////////////////////////////////////////////////////////////////////// static const int s3d_DrvD3d9CullTable[3] = { D3DCULL_NONE, D3DCULL_CW, D3DCULL_CCW, }; void s3d_CDrvD3d9GfxEngCLOD::SetCullMode(int Mode) { S3D_DRV_D3D9_STATE_NE(m_CullMode, Mode) { if(s3d_SysIsValidArrayIdx( Mode, S3D_SYS_ARRAYCNTS(s3d_DrvD3d9CullTable))) { m_CullMode = Mode; m_State.m_CullMode = s3d_DrvD3d9CullTable[Mode]; S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetCullMode(m_State.m_CullMode)); } } } /////////////////////////////////////////////////////////////////////////////// static const int s3d_DrvD3d9DepthTestTable[8] = { D3DCMP_NEVER, D3DCMP_EQUAL, D3DCMP_LESS, D3DCMP_LESSEQUAL, D3DCMP_GREATER, D3DCMP_GREATEREQUAL, D3DCMP_NOTEQUAL, D3DCMP_ALWAYS, }; void s3d_CDrvD3d9GfxEngCLOD::SetDepthTest(int Mode) { S3D_DRV_D3D9_STATE_NE(m_DepthTestMode, Mode) { if(s3d_SysIsValidArrayIdx( Mode, S3D_SYS_ARRAYCNTS(s3d_DrvD3d9DepthTestTable))) { m_DepthTestMode = Mode; m_State.m_DepthTestMode = s3d_DrvD3d9DepthTestTable[Mode]; S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetDepthTestMode(m_State.m_DepthTestMode)); } } } void s3d_CDrvD3d9GfxEngCLOD::SetDepthWrite(bool Enabled) { S3D_DRV_D3D9_STATE_NE(m_State.m_DepthWrite, BOOL(Enabled)) { m_State.m_DepthWrite = Enabled; S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetDepthWrite(m_State.m_DepthWrite)); } } /////////////////////////////////////////////////////////////////////////////// int s3d_CDrvD3d9GfxEngCLOD::GetStencilBits() const { return m_BufStencilBits; } static const int s3d_DrvD3d9StencilTestTable[8] = { D3DCMP_NEVER, D3DCMP_EQUAL, D3DCMP_LESS, D3DCMP_LESSEQUAL, D3DCMP_GREATER, D3DCMP_GREATEREQUAL, D3DCMP_NOTEQUAL, D3DCMP_ALWAYS, }; static const int s3d_DrvD3d9StencilOpTable[8] = { D3DSTENCILOP_KEEP, D3DSTENCILOP_ZERO, D3DSTENCILOP_REPLACE, D3DSTENCILOP_INVERT, D3DSTENCILOP_INCRSAT, D3DSTENCILOP_DECRSAT, D3DSTENCILOP_INCR, D3DSTENCILOP_DECR, }; void s3d_CDrvD3d9GfxEngCLOD::SetStencilMode( int TestMask, int TestRef, int TestModeFront, int TestModeBack, int WriteMask, int OpFailFront, int OpDepthFailFront, int OpDepthPassFront, int OpFailBack, int OpDepthFailBack, int OpDepthPassBack) { S3D_DRV_D3D9_STATE_NE(TestModeFront, m_StencilTestModeFront) { m_StencilTestModeFront = TestModeFront; if(s3d_SysIsValidArrayIdx( TestModeFront, S3D_SYS_ARRAYCNTS(s3d_DrvD3d9StencilTestTable))) { m_State.m_StencilTestModeFront = s3d_DrvD3d9StencilTestTable[TestModeFront]; S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetStencilTestModeFront( m_State.m_StencilTestModeFront)); } } S3D_DRV_D3D9_STATE_NE(TestModeBack, m_StencilTestModeBack) { m_StencilTestModeBack = TestModeBack; if(s3d_SysIsValidArrayIdx( TestModeBack, S3D_SYS_ARRAYCNTS(s3d_DrvD3d9StencilTestTable))) { m_State.m_StencilTestModeBack = s3d_DrvD3d9StencilTestTable[TestModeBack]; S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetStencilTestModeBack( m_State.m_StencilTestModeBack)); } } m_State.m_StencilTestRef = TestRef; S3D_DRV_D3D9_SETSTATEDIRECT(m_StateMgr.SetStencilTestRef(TestRef)); m_State.m_StencilTestMask = TestMask; S3D_DRV_D3D9_SETSTATEDIRECT(m_StateMgr.SetStencilTestMask(TestMask)); m_State.m_StencilWriteMask = WriteMask; S3D_DRV_D3D9_SETSTATEDIRECT(m_StateMgr.SetStencilWriteMask(WriteMask)); S3D_DRV_D3D9_STATE_NE(OpFailFront, m_StencilOpFailFront) { m_StencilOpFailFront = OpFailFront; if(s3d_SysIsValidArrayIdx( OpFailFront, S3D_SYS_ARRAYCNTS(s3d_DrvD3d9StencilOpTable))) { m_State.m_StencilOpFailFront = s3d_DrvD3d9StencilOpTable[OpFailFront]; S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetStencilOpFailFront( m_State.m_StencilOpFailFront)); } } S3D_DRV_D3D9_STATE_NE(OpDepthFailFront, m_StencilOpDepthFailFront) { m_StencilOpDepthFailFront = OpDepthFailFront; if(s3d_SysIsValidArrayIdx( OpDepthFailFront, S3D_SYS_ARRAYCNTS(s3d_DrvD3d9StencilOpTable))) { m_State.m_StencilOpDepthFailFront = s3d_DrvD3d9StencilOpTable[OpDepthFailFront]; S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetStencilOpDepthFailFront( m_State.m_StencilOpDepthFailFront)); } } S3D_DRV_D3D9_STATE_NE(OpDepthPassFront, m_StencilOpDepthPassFront) { m_StencilOpDepthPassFront = OpDepthPassFront; if(s3d_SysIsValidArrayIdx( OpDepthPassFront, S3D_SYS_ARRAYCNTS(s3d_DrvD3d9StencilOpTable))) { m_State.m_StencilOpDepthPassFront = s3d_DrvD3d9StencilOpTable[OpDepthPassFront]; S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetStencilOpDepthPassFront( m_State.m_StencilOpDepthPassFront)); } } S3D_DRV_D3D9_STATE_NE(OpFailBack, m_StencilOpFailBack) { m_StencilOpFailBack = OpFailBack; if(s3d_SysIsValidArrayIdx( OpFailBack, S3D_SYS_ARRAYCNTS(s3d_DrvD3d9StencilOpTable))) { m_State.m_StencilOpFailBack = s3d_DrvD3d9StencilOpTable[OpFailBack]; S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetStencilOpFailBack( m_State.m_StencilOpFailBack)); } } S3D_DRV_D3D9_STATE_NE(OpDepthFailBack, m_StencilOpDepthFailBack) { m_StencilOpDepthFailBack = OpDepthFailBack; if(s3d_SysIsValidArrayIdx( OpDepthFailBack, S3D_SYS_ARRAYCNTS(s3d_DrvD3d9StencilOpTable))) { m_State.m_StencilOpDepthFailBack = s3d_DrvD3d9StencilOpTable[OpDepthFailBack]; S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetStencilOpDepthFailBack( m_State.m_StencilOpDepthFailBack)); } } S3D_DRV_D3D9_STATE_NE(OpDepthPassBack, m_StencilOpDepthPassBack) { m_StencilOpDepthPassBack = OpDepthPassBack; if(s3d_SysIsValidArrayIdx( OpDepthPassBack, S3D_SYS_ARRAYCNTS(s3d_DrvD3d9StencilOpTable))) { m_State.m_StencilOpDepthPassBack = s3d_DrvD3d9StencilOpTable[OpDepthPassBack]; S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetStencilOpDepthPassBack( m_State.m_StencilOpDepthPassBack)); } } if(TestModeFront == TestModeBack && OpFailFront == OpFailBack && OpDepthFailFront == OpDepthFailBack && OpDepthPassFront == OpDepthPassBack) { m_State.m_StencilTwoSidedEnabled = FALSE; S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetStencilTwoSidedEnabled(FALSE)); } else if(TestModeBack != TestModeFront || OpFailBack != OpFailFront || OpDepthFailBack != OpDepthFailFront || OpDepthPassBack != OpDepthPassFront) { m_State.m_StencilTwoSidedEnabled = TRUE; S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetStencilTwoSidedEnabled(TRUE)); } if(TestModeFront == TestMode_Always && OpFailFront == StencilOp_Keep && OpDepthFailFront == StencilOp_Keep && OpDepthPassFront == StencilOp_Keep) { m_State.m_StencilEnabled = FALSE; S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetStencilEnabled(FALSE)); } else { m_State.m_StencilEnabled = TRUE; S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetStencilEnabled(TRUE)); } } /////////////////////////////////////////////////////////////////////////////// static const int s3d_DrvD3d9AlphaTestTable[8] = { D3DCMP_NEVER, D3DCMP_EQUAL, D3DCMP_LESS, D3DCMP_LESSEQUAL, D3DCMP_GREATER, D3DCMP_GREATEREQUAL, D3DCMP_NOTEQUAL, D3DCMP_ALWAYS, }; void s3d_CDrvD3d9GfxEngCLOD::SetAlphaTest(int Mode, float Ref) { if(Mode == TestMode_Always) { m_State.m_AlphaTestEnabled = FALSE; S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetAlphaTestEnabled(FALSE)); } else { m_State.m_AlphaTestEnabled = TRUE; S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetAlphaTestEnabled(TRUE)); } S3D_DRV_D3D9_STATE_NE(m_AlphaTestMode, Mode) { if(s3d_SysIsValidArrayIdx( Mode, S3D_SYS_ARRAYCNTS(s3d_DrvD3d9AlphaTestTable))) { m_AlphaTestMode = Mode; m_State.m_AlphaTestMode = s3d_DrvD3d9AlphaTestTable[Mode]; S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetAlphaTestMode(m_State.m_AlphaTestMode)); } } S3D_DRV_D3D9_STATE_NE(m_AlphaTestRef, Ref) { if(Mode >= 2) { m_AlphaTestRef = Ref; m_State.m_AlphaTestRef = s3d_SysIntOfFloatCoarse(0xFF * Ref); S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetAlphaTestRef(m_State.m_AlphaTestRef)); } } } static const int s3d_DrvD3d9BlendFacTable[10] = { D3DBLEND_ZERO, D3DBLEND_ONE, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA, D3DBLEND_SRCCOLOR, D3DBLEND_INVSRCCOLOR, D3DBLEND_DESTALPHA, D3DBLEND_INVDESTALPHA, D3DBLEND_DESTCOLOR, D3DBLEND_INVDESTCOLOR, }; static const int s3d_DrvD3d9BlendOpTable[10] = { D3DBLENDOP_ADD, D3DBLENDOP_SUBTRACT, D3DBLENDOP_REVSUBTRACT, D3DBLENDOP_MIN, D3DBLENDOP_MAX, }; void s3d_CDrvD3d9GfxEngCLOD::SetBlendMode( int ColSrcFac, int ColDestFac, int ColOp, int AlphaSrcFac, int AlphaDestFac, int AlphaOp) { if(ColSrcFac == BlendFac_One && ColDestFac == BlendFac_Zero && ColOp == BlendOp_SrcPlusDest) { m_State.m_ColorWriteEnabled = D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_ALPHA; m_State.m_AlphaBlendEnabled = FALSE; } else if(ColSrcFac == BlendFac_Zero && ColDestFac == BlendFac_One && ColOp == BlendOp_SrcPlusDest) { m_State.m_ColorWriteEnabled = 0; m_State.m_AlphaBlendEnabled = FALSE; } else { m_State.m_ColorWriteEnabled = D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_ALPHA; m_State.m_AlphaBlendEnabled = TRUE; S3D_DRV_D3D9_STATE_NE(m_BlendColSrcFac, ColSrcFac) { if(s3d_SysIsValidArrayIdx( ColSrcFac, S3D_SYS_ARRAYCNTS(s3d_DrvD3d9BlendFacTable))) { m_BlendColSrcFac = ColSrcFac; m_State.m_SrcBlend = s3d_DrvD3d9BlendFacTable[ColSrcFac]; S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetSrcBlend(m_State.m_SrcBlend)); } } S3D_DRV_D3D9_STATE_NE(m_BlendColDestFac, ColDestFac) { if(s3d_SysIsValidArrayIdx( ColDestFac, S3D_SYS_ARRAYCNTS(s3d_DrvD3d9BlendFacTable))) { m_BlendColDestFac = ColDestFac; m_State.m_DestBlend = s3d_DrvD3d9BlendFacTable[ColDestFac]; S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetDestBlend(m_State.m_DestBlend)); } } S3D_DRV_D3D9_STATE_NE(m_BlendColOp, ColOp) { if(s3d_SysIsValidArrayIdx( ColOp, S3D_SYS_ARRAYCNTS(s3d_DrvD3d9BlendOpTable))) { m_BlendColOp = ColOp; m_State.m_BlendOp = s3d_DrvD3d9BlendOpTable[ColOp]; S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetBlendOp(m_State.m_BlendOp)); } } } m_State.m_SeparateAlphaBlendEnabled = FALSE; if(AlphaSrcFac != ColSrcFac || AlphaDestFac != ColDestFac || AlphaOp != ColOp) { if(AlphaSrcFac == BlendFac_Zero && AlphaDestFac == BlendFac_One || AlphaOp == BlendOp_SrcPlusDest) { m_State.m_ColorWriteEnabled &= ~D3DCOLORWRITEENABLE_ALPHA; } else { m_State.m_SeparateAlphaBlendEnabled = FALSE; S3D_DRV_D3D9_STATE_NE(m_BlendAlphaSrcFac, AlphaSrcFac) { if(s3d_SysIsValidArrayIdx( AlphaSrcFac, S3D_SYS_ARRAYCNTS(s3d_DrvD3d9BlendFacTable))) { m_BlendAlphaSrcFac = AlphaSrcFac; m_State.m_SrcBlendAlpha = s3d_DrvD3d9BlendFacTable[AlphaSrcFac]; S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetSrcBlendAlpha( m_State.m_SrcBlendAlpha)); } } S3D_DRV_D3D9_STATE_NE(m_BlendAlphaDestFac, AlphaDestFac) { if(s3d_SysIsValidArrayIdx( AlphaDestFac, S3D_SYS_ARRAYCNTS(s3d_DrvD3d9BlendFacTable))) { m_BlendAlphaDestFac = AlphaDestFac; m_State.m_DestBlendAlpha = s3d_DrvD3d9BlendFacTable[AlphaDestFac]; S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetDestBlendAlpha( m_State.m_DestBlendAlpha)); } } S3D_DRV_D3D9_STATE_NE(m_BlendAlphaOp, AlphaOp) { if(s3d_SysIsValidArrayIdx( AlphaOp, S3D_SYS_ARRAYCNTS(s3d_DrvD3d9BlendOpTable))) { m_BlendAlphaOp = AlphaOp; m_State.m_DestBlendAlpha = s3d_DrvD3d9BlendOpTable[AlphaOp]; S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetDestBlendAlpha( m_State.m_DestBlendAlpha)); } } } } S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetColorWriteEnabled( m_State.m_ColorWriteEnabled)); S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetAlphaBlendEnabled( m_State.m_AlphaBlendEnabled)); S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetSeparateAlphaBlendEnabled( m_State.m_SeparateAlphaBlendEnabled)); } /////////////////////////////////////////////////////////////////////////////// static const int s3d_DrvD3d9PaintTable[3] = { D3DFILL_SOLID, D3DFILL_WIREFRAME, D3DFILL_POINT, }; void s3d_CDrvD3d9GfxEngCLOD::SetPaintMode(int Mode) { S3D_DRV_D3D9_STATE_NE(m_PaintMode, Mode) { if(s3d_SysIsValidArrayIdx( Mode, S3D_SYS_ARRAYCNTS(s3d_DrvD3d9PaintTable))) { m_PaintMode = Mode; m_State.m_PaintMode = s3d_DrvD3d9PaintTable[Mode]; S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetPaintMode(m_State.m_PaintMode)); } } } void s3d_CDrvD3d9GfxEngCLOD::SetPaintExt(float Ext) { } void s3d_CDrvD3d9GfxEngCLOD::BeginVisib() { if(m_VisibMgr) m_VisibMgr->BeginVisib(); } s3d_CDrvGfxVisibPtr s3d_CDrvD3d9GfxEngCLOD::EndVisib() { if(m_VisibMgr) return m_VisibMgr->EndVisib(); return 0; } void s3d_CDrvD3d9GfxEngCLOD::SetFogNone() { S3D_DRV_D3D9_STATE_NE(m_State.m_FogDensity, 0.f) { m_ParamBlk.m_FogColDensity = D3DXVECTOR4(0.f, 0.f, 0.f, 0.f); m_ParamStateProg.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Fog; m_ParamStateFFP.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Fog; m_State.m_FogDensity = 0.f; m_State.m_FogColor = 0; S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetFogDensity(0.f)); S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetFogColor(0)); } } void s3d_CDrvD3d9GfxEngCLOD::SetFogExp( float Density, s3d_CUtilVec3f_cr Color) { D3DXVECTOR4 FogColDensity = D3DXVECTOR4(Color.m_x, Color.m_y, Color.m_z, Density); S3D_DRV_D3D9_STATE_NE(FogColDensity, m_ParamBlk.m_FogColDensity) { m_ParamStateProg.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Fog; m_ParamStateFFP.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Fog; m_ParamBlk.m_FogColDensity = FogColDensity; m_State.m_FogDensity = Density; S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetFogDensity(Density)); D3DCOLOR FogColor = S3D_DRV_D3D9_UTIL_COLORVALUE( Color.m_x, Color.m_y, Color.m_z, 1); m_State.m_FogColor = FogColor; S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetFogColor(FogColor)); } } /////////////////////////////////////////////////////////////////////////////// bool s3d_CDrvD3d9GfxEngCLOD::IsStereo() const { return false; } void s3d_CDrvD3d9GfxEngCLOD::SetStereoEyeOffset(s3d_CUtilVec3f_cr EyeOffset) { } void s3d_CDrvD3d9GfxEngCLOD::SetTransf(int Chan, int Slot, s3d_CUtilMat4x4f_cr Mat) { switch(Chan) { case TransfChan_Proj: { m_MatProj._11 = Mat.m_xx; m_MatProj._12 = Mat.m_xy; m_MatProj._13 = Mat.m_xz; m_MatProj._14 = Mat.m_xw; m_MatProj._21 = - Mat.m_yx; m_MatProj._22 = - Mat.m_yy; m_MatProj._23 = - Mat.m_yz; m_MatProj._24 = - Mat.m_yw; m_MatProj._31 = 0.5f * (Mat.m_zx + Mat.m_wx); m_MatProj._32 = 0.5f * (Mat.m_zy + Mat.m_wy); m_MatProj._33 = 0.5f * (Mat.m_zz + Mat.m_wz); m_MatProj._34 = 0.5f * (Mat.m_zw + Mat.m_ww); m_MatProj._41 = Mat.m_wx; m_MatProj._42 = Mat.m_wy; m_MatProj._43 = Mat.m_wz; m_MatProj._44 = Mat.m_ww; m_MatProjDirty = true; break; } case TransfChan_View: { LPD3DXMATRIXA16 MatView = &m_ParamBlk.m_MatView; MatView->_11 = Mat.m_xx; MatView->_12 = Mat.m_xy; MatView->_13 = Mat.m_xz; MatView->_14 = Mat.m_xw; MatView->_21 = Mat.m_yx; MatView->_22 = Mat.m_yy; MatView->_23 = Mat.m_yz; MatView->_24 = Mat.m_yw; MatView->_31 = Mat.m_zx; MatView->_32 = Mat.m_zy; MatView->_33 = Mat.m_zz; MatView->_34 = Mat.m_zw; MatView->_41 = Mat.m_wx; MatView->_42 = Mat.m_wy; MatView->_43 = Mat.m_wz; MatView->_44 = Mat.m_ww; m_ParamStateProg.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_MatView; m_ParamStateFFP.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_MatView; break; } case TransfChan_Gen: { if(s3d_SysIsValidArrayIdx(Slot, m_MaxAttrCnt)) { LPD3DXMATRIXA16 MatGen = &m_ParamBlk.m_MatGenArray[Slot]; MatGen->_11 = Mat.m_xx; MatGen->_12 = Mat.m_xy; MatGen->_13 = Mat.m_xz; MatGen->_14 = Mat.m_xw; MatGen->_21 = Mat.m_yx; MatGen->_22 = Mat.m_yy; MatGen->_23 = Mat.m_yz; MatGen->_24 = Mat.m_yw; MatGen->_31 = Mat.m_zx; MatGen->_32 = Mat.m_zy; MatGen->_33 = Mat.m_zz; MatGen->_34 = Mat.m_zw; MatGen->_41 = Mat.m_wx; MatGen->_42 = Mat.m_wy; MatGen->_43 = Mat.m_wz; MatGen->_44 = Mat.m_ww; m_ParamStateProg.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_MatGen; m_ParamStateFFP.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_MatGen; } break; } case TransfChan_Bone: { D3DXMATRIXA16 MatBone; MatBone._11 = Mat.m_xx; MatBone._12 = Mat.m_xy; MatBone._13 = Mat.m_xz; MatBone._14 = Mat.m_xw; MatBone._21 = Mat.m_yx; MatBone._22 = Mat.m_yy; MatBone._23 = Mat.m_yz; MatBone._24 = Mat.m_yw; MatBone._31 = Mat.m_zx; MatBone._32 = Mat.m_zy; MatBone._33 = Mat.m_zz; MatBone._34 = Mat.m_zw; MatBone._41 = Mat.m_wx; MatBone._42 = Mat.m_wy; MatBone._43 = Mat.m_wz; MatBone._44 = Mat.m_ww; m_MatBoneArray.SetAtGrow(Slot, MatBone); m_MatBoneDirty = true; break; } } } void s3d_CDrvD3d9GfxEngCLOD::SetTransfIdentity(int Chan, int Slot) { SetTransf(Chan, Slot, 1); } void s3d_CDrvD3d9GfxEngCLOD::SetClipPlane(s3d_CUtilVec4f_cr Plane) { } void s3d_CDrvD3d9GfxEngCLOD::SetDepthBias( float BiasOverlay, float BiasOffs) { if(m_DepthBiasOverlay != BiasOverlay || m_DepthBiasOffs != BiasOffs) { m_DepthBiasOverlay = BiasOverlay; m_DepthBiasOffs = BiasOffs; float D3dDepthBias = m_BufDepthBiasScale * BiasOverlay; float D3dSlopeScaleDepthBias = BiasOverlay + BiasOffs; S3D_DRV_D3D9_SETSTATEDIRECT( m_StateMgr.SetDepthBias(D3dDepthBias, D3dSlopeScaleDepthBias)); } } void s3d_CDrvD3d9GfxEngCLOD::DisableLighting() { m_WantLighting = false; m_WantLightCnt = 0; m_ParamStateProg.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Light; m_ParamStateFFP.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Light; } void s3d_CDrvD3d9GfxEngCLOD::SetLightArray( s3d_CSysIntps LightCnt, s3d_CDrvGfxLight **LightArray) { if(LightCnt < 0) return; if(LightCnt > m_MaxLightCnt) LightCnt = m_MaxLightCnt; D3DLIGHT9 *Light = m_ParamBlk.m_LightArray; s3d_CSysIntps iLight; for(iLight = 0; iLight < LightCnt; iLight++) { const s3d_CDrvGfxLight *GfxLight = LightArray[iLight]; D3DLIGHTTYPE LightType = D3DLIGHT_POINT; if(GfxLight->m_Parallel) { LightType = D3DLIGHT_DIRECTIONAL; S3D_SYS_ASSERT(GfxLight->m_ViewDir != 0); } if(Light->Type == LightType && Light->Position.x == GfxLight->m_ViewPos.m_x && Light->Position.y == GfxLight->m_ViewPos.m_y && Light->Position.z == GfxLight->m_ViewPos.m_z && Light->Direction.x == GfxLight->m_ViewDir.m_x && Light->Direction.y == GfxLight->m_ViewDir.m_y && Light->Direction.z == GfxLight->m_ViewDir.m_z && Light->Range == GfxLight->m_ViewRange && Light->Ambient.r == GfxLight->m_Ambient.m_x && Light->Ambient.g == GfxLight->m_Ambient.m_y && Light->Ambient.b == GfxLight->m_Ambient.m_z && Light->Diffuse.r == GfxLight->m_Diffuse.m_x && Light->Diffuse.g == GfxLight->m_Diffuse.m_y && Light->Diffuse.b == GfxLight->m_Diffuse.m_z && Light->Specular.r == GfxLight->m_Specular.m_x && Light->Specular.g == GfxLight->m_Specular.m_y && Light->Specular.b == GfxLight->m_Specular.m_z) { Light++; continue; } float Range = GfxLight->m_ViewRange; float AttenConst = 1.f; float AttenLinear = 0.f; float AttenQuadr = 4.f / (Range * Range); Light->Type = LightType; Light->Theta = 0.0f; Light->Phi = D3DX_PI; Light->Falloff = 1.0f; Light->Attenuation0 = AttenConst; Light->Attenuation1 = AttenLinear; Light->Attenuation2 = AttenQuadr; Light->Ambient.r = GfxLight->m_Ambient.m_x; Light->Ambient.g = GfxLight->m_Ambient.m_y; Light->Ambient.b = GfxLight->m_Ambient.m_z; Light->Ambient.a = 1.f; Light->Diffuse.r = GfxLight->m_Diffuse.m_x; Light->Diffuse.g = GfxLight->m_Diffuse.m_y; Light->Diffuse.b = GfxLight->m_Diffuse.m_z; Light->Diffuse.a = 1.f; Light->Specular.r = GfxLight->m_Specular.m_x; Light->Specular.g = GfxLight->m_Specular.m_y; Light->Specular.b = GfxLight->m_Specular.m_z; Light->Specular.a = 1.f; Light->Position.x = GfxLight->m_ViewPos.m_x; Light->Position.y = GfxLight->m_ViewPos.m_y; Light->Position.z = GfxLight->m_ViewPos.m_z; Light->Direction.x = GfxLight->m_ViewDir.m_x; Light->Direction.y = GfxLight->m_ViewDir.m_y; Light->Direction.z = GfxLight->m_ViewDir.m_z; Light->Range = GfxLight->m_ViewRange; m_LightDirtyArray[iLight] = true; Light++; } m_WantLighting = true; m_WantLightCnt = LightCnt; m_ParamStateProg.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Light; m_ParamStateFFP.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Light; } void s3d_CDrvD3d9GfxEngCLOD::SetMtl( s3d_CUtilVec3f_cr Ambient, s3d_CUtilVec3f_cr Diffuse, s3d_CUtilVec3f_cr Specular, s3d_CUtilVec3f_cr Emissive, float SpecExp, float Alpha) { D3DMATERIAL9 *Mtl = &m_ParamBlk.m_Mtl; if(Mtl->Ambient.r != Ambient.m_x ||Mtl->Ambient.g != Ambient.m_y || Mtl->Ambient.b != Ambient.m_z || Mtl->Ambient.a != Alpha) { Mtl->Ambient.r = Ambient.m_x; Mtl->Ambient.g = Ambient.m_y; Mtl->Ambient.b = Ambient.m_z; Mtl->Ambient.a = Alpha; m_ParamStateProg.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Mtl; m_ParamStateFFP.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Mtl; } if(Mtl->Diffuse.r != Diffuse.m_x || Mtl->Diffuse.g != Diffuse.m_y || Mtl->Diffuse.b != Diffuse.m_z || Mtl->Diffuse.a != Alpha) { Mtl->Diffuse.r = Diffuse.m_x; Mtl->Diffuse.g = Diffuse.m_y; Mtl->Diffuse.b = Diffuse.m_z; Mtl->Diffuse.a = Alpha; m_ParamStateProg.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Mtl; m_ParamStateFFP.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Mtl; } if(Mtl->Specular.r != Specular.m_x || Mtl->Specular.g != Specular.m_y || Mtl->Specular.b != Specular.m_z || Mtl->Specular.a != Alpha) { Mtl->Specular.r = Specular.m_x; Mtl->Specular.g = Specular.m_y; Mtl->Specular.b = Specular.m_z; Mtl->Specular.a = Alpha; m_ParamStateProg.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Mtl; m_ParamStateFFP.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Mtl; } if(Mtl->Emissive.r != Emissive.m_x || Mtl->Emissive.g != Emissive.m_y || Mtl->Emissive.b != Emissive.m_z || Mtl->Emissive.a != Alpha) { Mtl->Emissive.r = Emissive.m_x; Mtl->Emissive.g = Emissive.m_y; Mtl->Emissive.b = Emissive.m_z; Mtl->Emissive.a = Alpha; m_ParamStateProg.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Mtl; m_ParamStateFFP.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Mtl; } if(Mtl->Power != SpecExp) { Mtl->Power = SpecExp; m_ParamStateProg.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Mtl; m_ParamStateFFP.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Mtl; } } void s3d_CDrvD3d9GfxEngCLOD::SetColorAlpha( s3d_CUtilVec4f_cr ColorAlpha) { D3DCOLORVALUE *ColorAlphaVal = &m_ParamBlk.m_ColorAlphaVal; if(ColorAlphaVal->r != ColorAlpha.m_x || ColorAlphaVal->g != ColorAlpha.m_y || ColorAlphaVal->b != ColorAlpha.m_z || ColorAlphaVal->a != ColorAlpha.m_w) { ColorAlphaVal->r = ColorAlpha.m_x; ColorAlphaVal->g = ColorAlpha.m_y; ColorAlphaVal->b = ColorAlpha.m_z; ColorAlphaVal->a = ColorAlpha.m_w; } } void s3d_CDrvD3d9GfxEngCLOD::GetPacketLimits( int &MaxVertCnt, int &MaxPrimCnt, int Prim) { MaxPrimCnt = S3D_SYS_INTPS_MAX; MaxVertCnt = S3D_SYS_INTPS_MAX; if(m_DevCaps.MaxPrimitiveCount > 0) MaxPrimCnt = m_DevCaps.MaxPrimitiveCount; if(m_DevCaps.MaxVertexIndex > 0) MaxVertCnt = m_DevCaps.MaxVertexIndex - 1; } s3d_CDrvGfxBatchPtr s3d_CDrvD3d9GfxEngCLOD::CreateBatch( const s3d_CDrvGfxCharge *Charge) { if(!m_D3dDev) return 0; S3D_SYS_ASSERT(s3d_CDrvUtilGfxUtil::VerifyCharge(m_MsgHandler, Charge)); if(m_Prop & s3d_CDrvGfxMgr::Prop_NoBatch) return 0; if(!Charge) return 0; if(Charge->m_Topol.m_IdxCnt <= 0) return 0; if(Charge->m_VertSubCnt < m_D3dParam->m_MinBatchObjVertCnt) return 0; // Don't create batch if charge has a univprog! s3d_CDrvGfxProg *Prog = Charge->m_Prog; const s3d_CDrvD3d9Prog *ProgImpl = s3d_UtilRecogCastSilent(Charge->m_Prog); s3d_CDrvGfxUnivProg *UnivProg = 0; if(ProgImpl) UnivProg = ProgImpl->m_UnivProg; if(UnivProg) return 0; bool Complete = true; s3d_CSysIntps nAttrCnt = Charge->m_AttrCnt; int iAttr; for(iAttr = 0; iAttr < nAttrCnt; iAttr++) { s3d_CDrvGfxAttr *Attr = &Charge->m_AttrArray[iAttr]; if(Attr->m_BankDyn) Complete = false; } if(m_D3dParam->m_NoDynamicVertexBuf && !Complete) return 0; s3d_CSysIntps PacketCnt = Charge->m_Topol.m_PacketCnt; if(PacketCnt <= 0) return 0; if(!m_BufMgr) return 0; s3d_CDrvD3d9VertBufObjBatchPtr VertBufObj = m_BufMgr->CreateVertBufObjStatic( Charge, m_ProgMgr, m_SWVertProc); if(!VertBufObj) return 0; s3d_CDrvD3d9IdxBufObjBatchPtr IdxBufObj = m_BufMgr->CreateIdxBufObjStatic( Charge, VertBufObj->m_Usage, VertBufObj->m_Pool); if(!IdxBufObj) return 0; s3d_CSysIntps PrimCnt = s3d_CDrvUtilGfxUtil::PrimCntOfIdxCnt( Charge->m_Topol.m_Prim, Charge->m_IdxSubCnt); s3d_CUtilMsgHandler *ReportMsgHandler = 0; if(m_D3dParam->m_ReportBatch) ReportMsgHandler = m_MsgHandler; s3d_CDrvD3d9BatchPtr EngBatch = S3D_SYS_NEW s3d_CDrvD3d9Batch(ReportMsgHandler); EngBatch->m_MainInfo = Charge->m_MainInfo; EngBatch->m_ObjInfo = Charge->m_ObjInfo; EngBatch->m_ObjDesc = Charge->m_ObjDesc; EngBatch->m_Prog = Charge->m_Prog; EngBatch->m_Complete = Complete; EngBatch->m_VertBufObj = VertBufObj; EngBatch->m_IdxBufObj = IdxBufObj; EngBatch->m_PrimCnt = PrimCnt; EngBatch->m_VertSubCnt = Charge->m_VertSubCnt; EngBatch->m_VertSubBase = Charge->m_VertSubBase; EngBatch->m_IdxSubCnt = Charge->m_IdxSubCnt; EngBatch->m_IdxSubBase = Charge->m_IdxSubBase; EngBatch->m_BoneIdxSubCnt = Charge->m_BoneIdxSubCnt; EngBatch->m_BoneIdxSubBase = Charge->m_BoneIdxSubBase; EngBatch->m_PacketSubCnt = Charge->m_PacketSubCnt; EngBatch->m_PacketSubBase = Charge->m_PacketSubBase; if(m_D3dParam->m_ReportBatch) { s3d_CUtilMsg m; m.m_Code = "drv/imp/directx/d3d9/drv_d3d9_eng.report_batch_create"; m.m_StdTempl = "D3D: " "Creating batch Addr=[1]: '[2]' IdxSubCnt=[3] VertSubCnt=[4]"; m.AddInfo(""); m.AddInfo(s3d_CUtilStrUtil::StrOfPtr(EngBatch.Get())); m.AddInfo(Charge->m_MainInfo); m.AddInfo(s3d_CUtilStrUtil::StrOfIntps(Charge->m_IdxSubCnt)); m.AddInfo(s3d_CUtilStrUtil::StrOfIntps(Charge->m_VertSubCnt)); s3d_UtilMsgReportNote(m_MsgHandler, m); } return EngBatch.Get(); } S3D_SYS_INLINE void LoadMat4x4f( s3d_CUtilMat4x4f &DestMat, const D3DXMATRIXA16 &SrcMat) { DestMat.m_xx = SrcMat._11; DestMat.m_xy = SrcMat._12; DestMat.m_xz = SrcMat._13; DestMat.m_xw = SrcMat._14; DestMat.m_yx = SrcMat._21; DestMat.m_yy = SrcMat._22; DestMat.m_yz = SrcMat._23; DestMat.m_yw = SrcMat._24; DestMat.m_zx = SrcMat._31; DestMat.m_zy = SrcMat._32; DestMat.m_zz = SrcMat._33; DestMat.m_zw = SrcMat._34; DestMat.m_wx = SrcMat._41; DestMat.m_wy = SrcMat._42; DestMat.m_wz = SrcMat._43; DestMat.m_ww = SrcMat._44; } void s3d_CDrvD3d9GfxEngCLOD::ExecuteCharge( const s3d_CDrvGfxCharge *Charge, s3d_CDrvGfxBatch *Batch, s3d_CDrvGfxParam_cr GfxParam) { S3D_SYS_ASSERT(s3d_CDrvUtilGfxUtil::VerifyCharge(m_MsgHandler, Charge)); s3d_CDrvD3d9Batch *BatchImpl = 0; if(Batch) { BatchImpl = s3d_UtilRecogCastSilent(Batch); if(!BatchImpl) { S3D_SYS_ASSERT(0); return; } } if(BatchImpl && BatchImpl->m_Complete) { s3d_CDrvD3d9PixEvent PixEvent; if(m_D3dParam->m_PixEnabled) { s3d_CUtilMemPoolFrm MemPoolFrm(m_MemPool); s3d_CUtilMemPoolStrBuf PixInfo; s3d_CDrvD3d9PixEvent::InfoStrOfCharge( m_MemPool, "batch:", BatchImpl->m_ObjDesc.GetChars(), BatchImpl->m_MainInfo.GetChars(), BatchImpl->m_ObjInfo.GetChars(), PixInfo); PixEvent.Assign( PixInfo.GetChars(), S3D_DRV_D3D9_PIX_INSPBATCH_COLOR); } const s3d_CSysChar *Info = BatchImpl->m_MainInfo.GetChars(); s3d_CDrvD3d9VertBufObjBatch *VertBufObj = BatchImpl->m_VertBufObj; if(!VertBufObj) { S3D_SYS_ASSERT(0); return; } s3d_CDrvD3d9IdxBufObjBatch *IdxBufObj = BatchImpl->m_IdxBufObj; if(!IdxBufObj) { S3D_SYS_ASSERT(0); return; } int VertBufFmtDecl = VertBufObj->m_VertBufFmtDecl; bool UseFFP = (BatchImpl->m_Prog == 0); BeginDraw(Info, VertBufFmtDecl, UseFFP); SelectProg( Info, BatchImpl->m_Prog, BatchImpl->m_ObjInfo.GetChars(), BatchImpl->m_ObjDesc.GetChars(), VertBufObj->m_VertDecl, GfxParam); SelectBuffers(VertBufObj, IdxBufObj); s3d_CSysIntps VertSubBase = BatchImpl->m_VertSubBase; s3d_CSysIntps IdxSubBase = BatchImpl->m_IdxSubBase; s3d_CSysIntps PacketSubBase = BatchImpl->m_PacketSubBase; s3d_CSysIntps PacketSubCnt = BatchImpl->m_PacketSubCnt; s3d_CSysIntps BoneIdxSubBase = BatchImpl->m_BoneIdxSubBase; s3d_CDrvD3d9Packet *PacketSubArray = IdxBufObj->m_PacketArray + PacketSubBase; bool TrackDummyBlendTransf = false; if((VertBufFmtDecl & s3d_CDrvD3d9VertBufDesc::Decl_DummyBoneWgh)) TrackDummyBlendTransf = true; DrawIndexedBatchPacket( IdxBufObj->m_D3dPrim, PacketSubCnt, PacketSubArray, VertSubBase, IdxSubBase, BoneIdxSubBase, IdxBufObj->m_BoneIdxCnt, IdxBufObj->m_BoneIdxArray, TrackDummyBlendTransf); if(UseFFP) EndDrawFFP(Info); else EndDrawProg(Info); m_IdxFlushCnt += BatchImpl->m_IdxSubCnt; m_Stat.m_TotChargeCnt++; m_Stat.m_TotVertCnt += BatchImpl->m_VertSubCnt; m_Stat.m_TotPrimCnt += BatchImpl->m_PrimCnt; m_Stat.m_TotPacketCnt += BatchImpl->m_PacketSubCnt; } else if(Charge) { s3d_CDrvD3d9PixEvent PixEvent; if(m_D3dParam->m_PixEnabled) { s3d_CUtilMemPoolFrm MemPoolFrm(m_MemPool); s3d_CUtilMemPoolStrBuf PixInfo; s3d_CDrvD3d9PixEvent::InfoStrOfCharge( m_MemPool, "dyn:", Charge->m_ObjDesc, Charge->m_MainInfo, Charge->m_ObjInfo, PixInfo); PixEvent.Assign( PixInfo.GetChars(), S3D_DRV_D3D9_PIX_INSPCHARGE_COLOR); } s3d_CUtilMemPoolFrm MemPoolFrm(m_MemPool); s3d_CDrvGfxProg *Prog = Charge->m_Prog; const s3d_CDrvD3d9Prog *ProgImpl = s3d_UtilRecogCastSilent(Charge->m_Prog); s3d_CDrvGfxUnivProg *UnivProg = 0; if(ProgImpl) UnivProg = ProgImpl->m_UnivProg; if(UnivProg) { s3d_CUtilMat4x4f MatView; LoadMat4x4f(MatView, m_ParamBlk.m_MatView); s3d_CSysIntps MatBoneCnt = m_MatBoneArray.GetCnt(); s3d_CUtilMat4x4f *MatBoneArray = new(m_MemPool) s3d_CUtilMat4x4f[MatBoneCnt]; s3d_CSysIntps iMatBone; for(iMatBone = 0; iMatBone < MatBoneCnt; iMatBone++) LoadMat4x4f(MatBoneArray[iMatBone], m_MatBoneArray[iMatBone]); Charge = UnivProg->CreateCharge( m_MsgHandler, Charge->m_MainInfo, m_MemPool, Charge, GfxParam, MatView, MatBoneCnt, MatBoneArray); if(!Charge) return; } s3d_CSysIntps PacketSubCnt = Charge->m_PacketSubCnt; s3d_CDrvD3d9Packet *PacketSubArray = new(m_MemPool) s3d_CDrvD3d9Packet[PacketSubCnt]; if(!m_BufMgr) return; s3d_CSysIntps PacketSubBase = Charge->m_PacketSubBase; m_BufMgr->LoadBatchPacketData( Charge, PacketSubCnt, PacketSubArray, PacketSubBase); if(m_D3dParam->m_UseDIPUP) { s3d_CDrvD3d9IdxBufMem IdxBuf; s3d_CUtilMemPoolArray BoneIdxArray; m_BufMgr->FetchIdxBufMemDyn( m_MemPool, Charge, IdxBuf, BoneIdxArray); if(!IdxBuf.m_Data) return; s3d_CDrvD3d9VertBufMem VertBuf; m_BufMgr->FetchVertBufMemDyn( m_MemPool, Charge, m_ProgMgr, VertBuf); if(!VertBuf.m_Data) return; int VertBufFmtDecl = VertBuf.m_VertBufFmtDecl; s3d_CDrvGfxProg *Prog = Charge->m_Prog; bool UseFFP = (Prog == 0); BeginDraw(Charge->m_MainInfo, VertBufFmtDecl, UseFFP); SelectProg( Charge->m_MainInfo, Prog, Charge->m_ObjInfo, Charge->m_ObjDesc, VertBuf.m_VertDecl, GfxParam); if(m_CurVertDecl != VertBuf.m_VertDecl) { m_CurVertDecl = VertBuf.m_VertDecl; S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->SetVertexDeclaration(m_CurVertDecl)); } if(m_CurVertBufObj) { m_CurVertBufObj = 0; UINT StreamIdx = 0; UINT Offset = 0; UINT Stride = 0; LPDIRECT3DVERTEXBUFFER9 VertBuf = 0; S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->SetStreamSource( StreamIdx, VertBuf, Offset, Stride)); } if(m_CurIdxBufObj) { m_CurIdxBufObj = 0; LPDIRECT3DINDEXBUFFER9 IdxBuf = 0; S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->SetIndices(IdxBuf)); } bool TrackDummyBlendTransf = false; if((VertBufFmtDecl & s3d_CDrvD3d9VertBufDesc::Decl_DummyBoneWgh)) TrackDummyBlendTransf = true; s3d_CSysIntps VertSubBase = 0; s3d_CSysIntps IdxSubBase = 0; s3d_CSysIntps BoneIdxSubBase = 0; s3d_CSysIntps BoneIdxCnt = BoneIdxArray.GetCnt(); DrawIndexedBatchPacketUP( IdxBuf.m_Prim, PacketSubCnt, PacketSubArray, VertSubBase, VertBuf.m_Data, VertBuf.m_VertSize, IdxBuf.m_Fmt, IdxBuf.m_Data, BoneIdxSubBase, BoneIdxCnt, BoneIdxArray.GetPtrRaw(), TrackDummyBlendTransf); if(UseFFP) EndDrawFFP(Charge->m_MainInfo); else EndDrawProg(Charge->m_MainInfo); } else { s3d_CDrvD3d9VertBufObjPtr VertBufObj = m_BufMgr->FetchVertBufObjDyn( m_MemPool, Charge, m_ProgMgr, m_SWVertProc); if(!VertBufObj) { S3D_SYS_ASSERT(0); return; } s3d_CUtilMemPoolArray BoneIdxArray; s3d_CDrvD3d9IdxBufObj *IdxBufObj = m_BufMgr->FetchIdxBufObjDyn( m_MemPool, Charge, BoneIdxArray, VertBufObj->m_Usage, VertBufObj->m_Pool); if(!IdxBufObj) { S3D_SYS_ASSERT(0); return; } s3d_CDrvGfxProg* Prog = Charge->m_Prog; int VertBufFmtDecl = VertBufObj->m_VertBufFmtDecl; bool UseFFP = (Prog == 0); BeginDraw(Charge->m_MainInfo, VertBufFmtDecl, UseFFP); SelectProg( Charge->m_MainInfo, Prog, Charge->m_ObjInfo, Charge->m_ObjDesc, VertBufObj->m_VertDecl, GfxParam); m_CurVertBufObj = 0; m_CurIdxBufObj = 0; SelectBuffers(VertBufObj, IdxBufObj); s3d_CSysIntps VertSubBase = 0; s3d_CSysIntps IdxSubBase = 0; s3d_CSysIntps BoneIdxSubBase = 0; bool TrackDummyBlendTransf = false; if((VertBufFmtDecl & s3d_CDrvD3d9VertBufDesc::Decl_DummyBoneWgh)) TrackDummyBlendTransf = true; DrawIndexedBatchPacket( IdxBufObj->m_D3dPrim, PacketSubCnt, PacketSubArray, VertSubBase, IdxSubBase, BoneIdxSubBase, BoneIdxArray.GetCnt(), BoneIdxArray.GetPtrRaw(), TrackDummyBlendTransf); if(UseFFP) EndDrawFFP(Charge->m_MainInfo); else EndDrawProg(Charge->m_MainInfo); } m_IdxFlushCnt += Charge->m_IdxSubCnt; s3d_CSysIntps PrimCnt = s3d_CDrvUtilGfxUtil::PrimCntOfIdxCnt( Charge->m_Topol.m_Prim, Charge->m_IdxSubCnt); m_Stat.m_TotChargeCnt++; m_Stat.m_TotVertCnt += Charge->m_VertSubCnt; m_Stat.m_TotPrimCnt += PrimCnt; m_Stat.m_TotPacketCnt += PacketSubCnt; m_Stat.m_CostlyChargeCnt++; m_Stat.m_CostlyVertCnt += Charge->m_VertSubCnt; m_Stat.m_CostlyPrimCnt += PrimCnt; m_Stat.m_CostlyPacketCnt += PacketSubCnt; } if(m_D3dParam->m_IdxFlushCnt > 0 && m_IdxFlushCnt >= m_D3dParam->m_IdxFlushCnt) { m_IdxFlushCnt = 0; m_FlushEvent.End(); m_FlushEvent.Flush(); } } /////////////////////////////////////////////////////////////////////////////// void s3d_CDrvD3d9GfxEngCLOD::SetDefaultState() { if(!m_D3dDev) return; m_State.m_CullMode = D3DCULL_CW; m_State.m_DepthTestMode = D3DCMP_ALWAYS; m_State.m_DepthWrite = TRUE; m_State.m_DepthBias = 0; m_State.m_SlopeScaleDepthBias = 0; m_State.m_PaintMode = D3DFILL_SOLID; m_State.m_AlphaBlendEnabled = FALSE; m_State.m_SrcBlend = D3DBLEND_ONE; m_State.m_DestBlend = D3DBLEND_ZERO; m_State.m_SeparateAlphaBlendEnabled = FALSE; m_State.m_SrcBlendAlpha = D3DBLEND_ONE; m_State.m_DestBlendAlpha = D3DBLEND_ZERO; m_State.m_AlphaTestEnabled = FALSE; m_State.m_AlphaTestMode = D3DCMP_ALWAYS; m_State.m_AlphaTestRef = 0; m_State.m_ColorWriteEnabled = D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_ALPHA; m_State.m_StencilEnabled = FALSE; m_State.m_StencilTestModeFront = D3DCMP_ALWAYS; m_State.m_StencilTestRef = 0; m_State.m_StencilTestMask = 0; m_State.m_StencilWriteMask = 0; m_State.m_StencilOpFailFront = D3DSTENCILOP_KEEP; m_State.m_StencilOpDepthFailFront = D3DSTENCILOP_KEEP; m_State.m_StencilOpDepthPassFront = D3DSTENCILOP_KEEP; m_State.m_StencilTwoSidedEnabled = FALSE; m_State.m_StencilTestModeBack = D3DCMP_ALWAYS; m_State.m_StencilOpFailBack = D3DSTENCILOP_KEEP; m_State.m_StencilOpDepthFailBack = D3DSTENCILOP_KEEP; m_State.m_StencilOpDepthPassBack = D3DSTENCILOP_KEEP; m_State.m_FogDensity = 0.f; m_State.m_FogColor = 0; m_StateMgr.Invalidate(); m_StateMgr.Apply(m_State); m_CullMode = -1; m_DepthTestMode = -1; m_DepthBiasOverlay = 0.f; m_DepthBiasOffs = 0.f; m_BlendColSrcFac = -1; m_BlendColDestFac = -1; m_BlendColOp = -1; m_BlendAlphaSrcFac = -1; m_BlendAlphaDestFac = -1; m_BlendAlphaOp = -1; m_PaintMode = -1; m_StencilTestModeFront = -1; m_StencilTestModeBack = -1; m_StencilOpFailFront = -1; m_StencilOpDepthFailFront = -1; m_StencilOpDepthPassFront = -1; m_StencilOpFailBack = -1; m_StencilOpDepthFailBack = -1; m_StencilOpDepthPassBack = -1; m_AlphaTestMode = -1; m_AlphaTestRef = 0; float one = 1.0f; float zero = 0.0f; float sixtyfour = 64.0f; int iAttr; for(iAttr = 0; iAttr < m_MaxAttrCnt ; iAttr++) { S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateI( m_D3dDev, iAttr, D3DTSS_COLORARG1, D3DTA_TEXTURE)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateI( m_D3dDev, iAttr, D3DTSS_COLORARG2, D3DTA_CURRENT)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateI( m_D3dDev, iAttr, D3DTSS_ALPHAARG1, D3DTA_TEXTURE)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateI( m_D3dDev, iAttr, D3DTSS_ALPHAARG2, D3DTA_CURRENT)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateF( m_D3dDev, iAttr, D3DTSS_BUMPENVMAT00, zero)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateF( m_D3dDev, iAttr, D3DTSS_BUMPENVMAT01, zero)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateF( m_D3dDev, iAttr, D3DTSS_BUMPENVMAT10, zero)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateF( m_D3dDev, iAttr, D3DTSS_BUMPENVMAT11, zero)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateF( m_D3dDev, iAttr, D3DTSS_BUMPENVLSCALE, zero)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateF( m_D3dDev, iAttr, D3DTSS_BUMPENVLOFFSET, zero)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateI( m_D3dDev, iAttr, D3DTSS_BUMPENVLOFFSET, D3DTTFF_DISABLE)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateI( m_D3dDev, iAttr, D3DTSS_COLORARG0, D3DTA_CURRENT)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateI( m_D3dDev, iAttr, D3DTSS_ALPHAARG0, D3DTA_CURRENT)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateI( m_D3dDev, iAttr, D3DTSS_RESULTARG, D3DTA_CURRENT)); /* Default value? s3d_CDrvD3d9StateUtil::SetTextureStageStateI(m_D3dDev, iAttr, D3DTSS_CONSTANT, 0); */ } int iSamp; for(iSamp = 0; iSamp < m_MaxSampCnt; iSamp++) { S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, s3d_CDrvD3d9Util::D3dWrapOfSamp(iSamp), 0)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI( m_D3dDev, iSamp, D3DSAMP_BORDERCOLOR, 0)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateF( m_D3dDev, iSamp, D3DSAMP_MIPMAPLODBIAS, zero)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI( m_D3dDev, iSamp, D3DSAMP_MAXMIPLEVEL, 0)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI( m_D3dDev, iSamp, D3DSAMP_MAXANISOTROPY, 1)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI( m_D3dDev, iSamp, D3DSAMP_SRGBTEXTURE, FALSE)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI( m_D3dDev, iSamp, D3DSAMP_ELEMENTINDEX, 0)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI( m_D3dDev, iSamp, D3DSAMP_DMAPOFFSET, 0)); } S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_ZENABLE, D3DZB_TRUE)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_SHADEMODE, D3DSHADE_GOURAUD)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_DITHERENABLE, FALSE)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_LASTPIXEL, FALSE)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_FOGENABLE, FALSE)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_SPECULARENABLE, TRUE)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_FOGCOLOR, 0)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_FOGTABLEMODE, D3DFOG_NONE)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF( m_D3dDev, D3DRS_FOGSTART, zero)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF( m_D3dDev, D3DRS_FOGEND, one)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF( m_D3dDev, D3DRS_FOGDENSITY, one)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_RANGEFOGENABLE, FALSE)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_TEXTUREFACTOR, 0xFFFFFFFF)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_CLIPPING, TRUE)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_LIGHTING, FALSE)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_AMBIENT, 0)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_FOGVERTEXMODE, D3DFOG_NONE)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_COLORVERTEX, FALSE)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_LOCALVIEWER, TRUE)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_NORMALIZENORMALS, FALSE)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR2)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_COLOR2)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_VERTEXBLEND, D3DVBF_DISABLE)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_CLIPPLANEENABLE, 0)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF( m_D3dDev, D3DRS_POINTSIZE, sixtyfour)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF( m_D3dDev, D3DRS_POINTSIZE_MIN, one)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_POINTSPRITEENABLE, FALSE)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_POINTSCALEENABLE, FALSE)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF( m_D3dDev, D3DRS_POINTSCALE_A, zero)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF( m_D3dDev, D3DRS_POINTSCALE_B, zero)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF( m_D3dDev, D3DRS_POINTSCALE_C, zero)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_MULTISAMPLEANTIALIAS, BOOL(m_UseMSAA))); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_PATCHEDGESTYLE, D3DPATCHEDGE_DISCRETE)); #ifdef S3D_GENERAL_DEBUG S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_DEBUGMONITORTOKEN, D3DDMT_ENABLE)); #else S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_DEBUGMONITORTOKEN, D3DDMT_DISABLE)); #endif S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF( m_D3dDev, D3DRS_POINTSIZE_MAX, sixtyfour)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF( m_D3dDev, D3DRS_TWEENFACTOR, zero)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_BLENDOP, D3DBLENDOP_ADD)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_POSITIONDEGREE, D3DDEGREE_CUBIC)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_NORMALDEGREE, D3DDEGREE_LINEAR)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_SCISSORTESTENABLE, FALSE)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF( m_D3dDev, D3DRS_SLOPESCALEDEPTHBIAS, zero)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_ANTIALIASEDLINEENABLE, FALSE)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF( m_D3dDev, D3DRS_MINTESSELLATIONLEVEL, one)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF( m_D3dDev, D3DRS_MAXTESSELLATIONLEVEL, one)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF( m_D3dDev, D3DRS_ADAPTIVETESS_X, zero)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF( m_D3dDev, D3DRS_ADAPTIVETESS_Y, zero)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF( m_D3dDev, D3DRS_ADAPTIVETESS_Z, one)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF( m_D3dDev, D3DRS_ADAPTIVETESS_W, zero)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_ENABLEADAPTIVETESSELLATION, FALSE)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_COLORWRITEENABLE1, 0x0000000F)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_COLORWRITEENABLE2, 0x0000000F)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_COLORWRITEENABLE3, 0x0000000F)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_BLENDFACTOR, 0xFFFFFFFF)); BOOL EnabledSRGBWrite = BOOL(m_D3dParam->m_SRGBWriteEnabled); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_SRGBWRITEENABLE, EnabledSRGBWrite)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_SEPARATEALPHABLENDENABLE, FALSE)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_SRCBLENDALPHA, D3DBLEND_ONE)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_DESTBLENDALPHA, D3DBLEND_ZERO)); S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_BLENDOPALPHA, D3DBLENDOP_ADD)); } /////////////////////////////////////////////////////////////////////////////// void s3d_CDrvD3d9GfxEngCLOD::CalcProjOffs( float &ProjOffsX, float &ProjOffsY, int Width, int Height) { ProjOffsX = -1.0f / s3d_SysFloatOfInt(Width); ProjOffsY = 1.0f / s3d_SysFloatOfInt(Height); } void s3d_CDrvD3d9GfxEngCLOD::SetProjOffs( const float &ProjOffsX, const float &ProjOffsY) { if(m_CurProjOffsX != ProjOffsX || m_CurProjOffsY != ProjOffsY) { m_CurProjOffsX = ProjOffsX; m_CurProjOffsY = ProjOffsY; m_MatProjDirty = true; } } /////////////////////////////////////////////////////////////////////////////// void s3d_CDrvD3d9GfxEngCLOD::InitTexturing() { if(!m_D3dDev) return; m_MaxAttrCnt = m_DevCaps.MaxTextureBlendStages; if(m_MaxAttrCnt > S3D_DRV_D3D9_MAX_ATTR_CNT) { m_MaxAttrCnt = S3D_DRV_D3D9_MAX_ATTR_CNT; S3D_SYS_ASSERT(0); } int iAttr; for(iAttr = 0; iAttr < m_MaxAttrCnt; iAttr++) { LPD3DXMATRIXA16 MatGen = &m_ParamBlk.m_MatGenArray[iAttr]; D3DXMatrixIdentity(MatGen); m_CurTexTransfFlagsArray[iAttr] = D3DTTFF_DISABLE; m_CurTexOpArray[iAttr] = D3DTOP_DISABLE; S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateI( m_D3dDev, iAttr, D3DTSS_COLOROP, D3DTOP_DISABLE)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateI( m_D3dDev, iAttr, D3DTSS_ALPHAOP, D3DTOP_DISABLE)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateI( m_D3dDev, iAttr, D3DTSS_TEXCOORDINDEX, iAttr)); D3DTRANSFORMSTATETYPE TransfState = D3DTRANSFORMSTATETYPE(iAttr + D3DTS_TEXTURE0); S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->SetTransform(TransfState, MatGen)); } // The number of texture samplers available to the application is // determined by the pixel shader version // ps_1_1 to ps_1_3 4 texture samplers // ps_1_4 6 texture samplers // ps_2_0 16 texture samplers // fixed function pipeline: // MaxTextureBlendStages/MaxSimultaneousTextures texture samplers m_MaxSampCnt = m_DevCaps.MaxSimultaneousTextures; int PSVerMajor = D3DSHADER_VERSION_MAJOR(m_DevCaps.PixelShaderVersion); int PSVerMinor = D3DSHADER_VERSION_MINOR(m_DevCaps.PixelShaderVersion); if(PSVerMajor >= 2) m_MaxSampCnt = S3D_DRV_D3D9_MAX_SAMPLER_CNT; else if(PSVerMajor < 2) { if(PSVerMinor >= 4) m_MaxSampCnt = 6; else if(PSVerMinor >= 1 && PSVerMinor < 3) m_MaxSampCnt = 4; } if(m_MaxSampCnt > S3D_DRV_D3D9_MAX_SAMPLER_CNT) { m_MaxSampCnt = S3D_DRV_D3D9_MAX_SAMPLER_CNT; S3D_SYS_ASSERT(0); } if(m_D3dParam->m_MaxMipLevels < 0) m_D3dParam->m_MaxMipLevels = 0; if(m_D3dParam->m_MaxAnisoTropy < 0) m_D3dParam->m_MaxAnisoTropy = 1; if(DWORD(m_D3dParam->m_MaxAnisoTropy) > m_DevCaps.MaxAnisotropy) m_D3dParam->m_MaxAnisoTropy = m_DevCaps.MaxAnisotropy; int iSamp; for(iSamp = 0; iSamp < S3D_DRV_D3D9_MAX_SAMPLER_CNT; iSamp++) { m_ParamBlk.m_SampTexArray[iSamp] = 0; m_WantSampTexArray[iSamp] = 0; m_SampModeArray[iSamp] = 0; m_CurSampParamArray[iSamp].m_FilterMin = D3DTEXF_POINT; m_CurSampParamArray[iSamp].m_FilterMag = D3DTEXF_POINT; m_CurSampParamArray[iSamp].m_FilterMip = D3DTEXF_NONE; m_CurSampParamArray[iSamp].m_AddrX = D3DTADDRESS_WRAP; m_CurSampParamArray[iSamp].m_AddrY = D3DTADDRESS_WRAP; m_CurSampParamArray[iSamp].m_AddrZ = D3DTADDRESS_WRAP; m_CurSampParamArray[iSamp].m_SRGBTex = FALSE; if(iSamp < m_MaxSampCnt) { S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->SetTexture(iSamp, 0)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI( m_D3dDev, iSamp, D3DSAMP_MAGFILTER, D3DTEXF_POINT)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI( m_D3dDev, iSamp, D3DSAMP_MINFILTER, D3DTEXF_POINT)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI( m_D3dDev, iSamp, D3DSAMP_MIPFILTER, D3DTEXF_NONE)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI( m_D3dDev, iSamp, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI( m_D3dDev, iSamp, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI( m_D3dDev, iSamp, D3DSAMP_ADDRESSW, D3DTADDRESS_WRAP)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI( m_D3dDev, iSamp, D3DSAMP_MAXMIPLEVEL, m_D3dParam->m_MaxMipLevels)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI( m_D3dDev, iSamp, D3DSAMP_MAXANISOTROPY, m_D3dParam->m_MaxAnisoTropy)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI( m_D3dDev, iSamp, D3DSAMP_SRGBTEXTURE, FALSE)); } } m_ParamBlk.m_SampMaxUsedCnt = 0; m_SampMaxWantCnt = 0; m_MinLbTexWidth = m_D3dParam->m_MinLbTexWidth; m_MaxLbTexWidth = 8; int MaxTexWidth = m_DevCaps.MaxTextureWidth; if(MaxTexWidth > 0) m_MaxLbTexWidth = s3d_CDrvUtilGfxUtil::BinLogDownInt(MaxTexWidth); m_MinLbTexHeight = m_D3dParam->m_MinLbTexHeight; m_MaxLbTexHeight = 8; int MaxTexHeight = m_DevCaps.MaxTextureHeight; if(MaxTexHeight > 0) m_MaxLbTexHeight = s3d_CDrvUtilGfxUtil::BinLogDownInt(MaxTexHeight); m_MinLbVolTexExt = m_D3dParam->m_MinLbVolTexExt; m_MaxLbVolTexExt = 8; int MaxVolExt = m_DevCaps.MaxVolumeExtent; if(MaxVolExt > 0) m_MaxLbVolTexExt = s3d_CDrvUtilGfxUtil::BinLogDownInt(MaxVolExt); m_MaxFilterMinStd = D3DTEXF_LINEAR; m_MaxFilterMagStd = D3DTEXF_LINEAR; m_MaxFilterMinCube = D3DTEXF_LINEAR; m_MaxFilterMagCube = D3DTEXF_LINEAR; m_MaxFilterMinVol = D3DTEXF_LINEAR; m_MaxFilterMagVol = D3DTEXF_LINEAR; if(m_D3dParam->m_MaxAnisoTropy > 1) { if(m_DevCaps.TextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC) m_MaxFilterMinStd = D3DTEXF_ANISOTROPIC; if(m_DevCaps.TextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC) m_MaxFilterMagStd = D3DTEXF_ANISOTROPIC; if(m_DevCaps.CubeTextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC) m_MaxFilterMinCube = D3DTEXF_ANISOTROPIC; if(m_DevCaps.CubeTextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC) m_MaxFilterMagCube = D3DTEXF_ANISOTROPIC; if(m_DevCaps.VolumeTextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC) m_MaxFilterMinVol = D3DTEXF_ANISOTROPIC; if(m_DevCaps.VolumeTextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC) m_MaxFilterMagVol = D3DTEXF_ANISOTROPIC; } m_MaxFilterMipStd = D3DTEXF_POINT; m_MaxFilterMipCube = D3DTEXF_POINT; m_MaxFilterMipVol = D3DTEXF_POINT; if(m_DevCaps.TextureFilterCaps & D3DPTFILTERCAPS_MIPFLINEAR) m_MaxFilterMipStd = D3DTEXF_LINEAR; if(m_DevCaps.CubeTextureFilterCaps & D3DPTFILTERCAPS_MIPFLINEAR) m_MaxFilterMipCube = D3DTEXF_LINEAR; if(m_DevCaps.VolumeTextureFilterCaps & D3DPTFILTERCAPS_MIPFLINEAR) m_MaxFilterMipVol = D3DTEXF_LINEAR; } void s3d_CDrvD3d9GfxEngCLOD::SetTexOpTransf( int Attr, D3DTEXTUREOP Op, D3DTEXTURETRANSFORMFLAGS TransfFlag) { if(!m_D3dDev) return; if(s3d_SysIsValidArrayIdx(Attr, m_MaxAttrCnt)) { if(m_CurTexOpArray[Attr] != Op) { m_CurTexOpArray[Attr] = Op; S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateI( m_D3dDev, Attr, D3DTSS_COLOROP, Op)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateI( m_D3dDev, Attr, D3DTSS_ALPHAOP, Op)); } if(m_CurTexTransfFlagsArray[Attr] != TransfFlag) { m_CurTexTransfFlagsArray[Attr] = TransfFlag; S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateI( m_D3dDev, Attr, D3DTSS_TEXTURETRANSFORMFLAGS, TransfFlag)); } } } void s3d_CDrvD3d9GfxEngCLOD::UpdateSampParam( s3d_CSysIntps Samp, const s3d_CDrvD3d9TexObjBase *Tex) { if(Samp < 0 || Samp >= m_MaxSampCnt) return; if(!Tex) return; D3DRESOURCETYPE TexType = D3DRTYPE_TEXTURE; if(Tex->m_BaseTex) TexType = Tex->m_BaseTex->GetType(); s3d_CDrvD3d9SampParam *SampParam = &m_CurSampParamArray[Samp]; int SampMode = m_SampModeArray[Samp]; D3DTEXTUREADDRESS SampAddrX, SampAddrY, SampAddrZ; AddrOfSampMode( SampMode, SampAddrX, SampAddrY, SampAddrZ); if(SampParam->m_AddrX != SampAddrX) { SampParam->m_AddrX = SampAddrX; S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI( m_D3dDev, Samp, D3DSAMP_ADDRESSU, SampAddrX)); } if(SampParam->m_AddrY != SampAddrY) { SampParam->m_AddrY = SampAddrY; S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI( m_D3dDev, Samp, D3DSAMP_ADDRESSV, SampAddrY)); } if(TexType == D3DRTYPE_VOLUMETEXTURE && SampParam->m_AddrZ != SampAddrZ) { SampParam->m_AddrZ = SampAddrZ; S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI( m_D3dDev, Samp, D3DSAMP_ADDRESSW, SampAddrZ)); } D3DTEXTUREFILTERTYPE FilterMin, FilterMag, FilterMip; FilterOfSampMode( SampMode, Tex, FilterMin, FilterMag, FilterMip); // Set first Mag, otherwise not working correctly (why?)... if(SampParam->m_FilterMag != FilterMag) { SampParam->m_FilterMag = FilterMag; S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI( m_D3dDev, Samp, D3DSAMP_MAGFILTER, FilterMag)); } if(SampParam->m_FilterMin != FilterMin) { SampParam->m_FilterMin = FilterMin; S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI( m_D3dDev, Samp, D3DSAMP_MINFILTER, FilterMin)); } if(SampParam->m_FilterMip != FilterMip) { SampParam->m_FilterMip = FilterMip; S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI( m_D3dDev, Samp, D3DSAMP_MIPFILTER, FilterMip)); } BOOL SRGBTex = BOOL(Tex->m_TexFmt.m_SRGBRead); if(SampParam->m_SRGBTex != SRGBTex) { SampParam->m_SRGBTex = SRGBTex; S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI( m_D3dDev, Samp, D3DSAMP_SRGBTEXTURE, SRGBTex)); } } void s3d_CDrvD3d9GfxEngCLOD::AddrOfSampMode( int SampMode, D3DTEXTUREADDRESS &AddrX, D3DTEXTUREADDRESS &AddrY, D3DTEXTUREADDRESS &AddrZ) { AddrX = D3DTADDRESS_WRAP; if(SampMode & s3d_CDrvGfxEng::SampMode_ClampX) AddrX = D3DTADDRESS_CLAMP; else if(SampMode & s3d_CDrvGfxEng::SampMode_MirrorX) AddrX = D3DTADDRESS_MIRROR; AddrY = D3DTADDRESS_WRAP; if(SampMode & s3d_CDrvGfxEng::SampMode_ClampY) AddrY = D3DTADDRESS_CLAMP; else if(SampMode & s3d_CDrvGfxEng::SampMode_MirrorY) AddrY = D3DTADDRESS_MIRROR; AddrZ = D3DTADDRESS_WRAP; if(SampMode & s3d_CDrvGfxEng::SampMode_ClampZ) AddrZ = D3DTADDRESS_CLAMP; else if(SampMode & s3d_CDrvGfxEng::SampMode_MirrorZ) AddrZ = D3DTADDRESS_MIRROR; } void s3d_CDrvD3d9GfxEngCLOD::FilterOfSampMode( int SampMode, const s3d_CDrvD3d9TexObjBase *Tex, D3DTEXTUREFILTERTYPE &FilterMin, D3DTEXTUREFILTERTYPE &FilterMag, D3DTEXTUREFILTERTYPE &FilterMip) { FilterMin = D3DTEXF_POINT; FilterMag = D3DTEXF_POINT; FilterMip = D3DTEXF_NONE; bool CanFilter = Tex->m_TexFmt.m_CanFilter; int TexProp = Tex->m_Prop; if((SampMode & s3d_CDrvGfxEng::SampMode_Filter) != 0 && CanFilter) { if((TexProp & s3d_CDrvGfxEng::TexProp_Cube) != 0) { FilterMin = m_MaxFilterMinCube; FilterMag = m_MaxFilterMagCube; } else if((TexProp & s3d_CDrvGfxEng::TexProp_Volume) != 0) { FilterMin = m_MaxFilterMinVol; FilterMag = m_MaxFilterMagVol; } else { FilterMin = m_MaxFilterMinStd; FilterMag = m_MaxFilterMagStd; } } if((TexProp & s3d_CDrvGfxEng::TexProp_Mipmap) != 0) { FilterMip = D3DTEXF_POINT; if(CanFilter) { if((TexProp & s3d_CDrvGfxEng::TexProp_Cube) != 0) FilterMip = m_MaxFilterMipCube; else if((TexProp & s3d_CDrvGfxEng::TexProp_Volume) != 0) FilterMip = m_MaxFilterMipVol; else FilterMip = m_MaxFilterMipStd; } } } /////////////////////////////////////////////////////////////////////////////// void s3d_CDrvD3d9GfxEngCLOD::Clear( s3d_CDrvGfxClearParam_cr ClearParam) { if(!ClearParam.m_MustColorAlpha && !ClearParam.m_MustDepth && !ClearParam.m_MustStencil) return; if(!m_D3dDev) return; SetViewRect(1); SetViewDepthRange(0, 1); SetDepthWrite(true); SetBlendMode( BlendFac_One, BlendFac_Zero, BlendOp_SrcPlusDest, BlendFac_One, BlendFac_Zero, BlendOp_SrcPlusDest); SetStencilMode( 0, 0, TestMode_Always, TestMode_Always, -1, StencilOp_Keep, StencilOp_Keep, StencilOp_Keep, StencilOp_Keep, StencilOp_Keep, StencilOp_Keep); m_StateMgr.Apply(m_State); D3DCOLOR D3dColor = S3D_DRV_D3D9_UTIL_COLORVALUE( ClearParam.m_ColorAlpha.m_x, ClearParam.m_ColorAlpha.m_y, ClearParam.m_ColorAlpha.m_z, 1); /* if(m_DestCnt) D3dColor = rand() * WORD(-1); */ DWORD D3dFlags; D3dFlags = D3DCLEAR_TARGET; if(ClearParam.m_MustDepth || ClearParam.m_MustStencil) { D3dFlags |= D3DCLEAR_ZBUFFER; if(m_BufStencilBits > 0) D3dFlags |= D3DCLEAR_STENCIL; } int nRect = 1; if(m_BufWidth <= 0 || m_BufHeight <= 0) nRect = 0; D3DRECT Rect = {0, 0, m_BufWidth, m_BufHeight}; S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->Clear( nRect, &Rect, D3dFlags, D3dColor, ClearParam.m_Depth, ClearParam.m_Stencil)); } /////////////////////////////////////////////////////////////////////////////// void s3d_CDrvD3d9GfxEngCLOD::SelectBuffers( s3d_CDrvD3d9VertBufObj *VertBufObj, s3d_CDrvD3d9IdxBufObj *IdxBufObj) { if(!m_D3dDev) return; if(!VertBufObj) return; if(!IdxBufObj) return; if(!m_BufMgr) return; if(m_CurVertBufObj != VertBufObj) { m_CurVertBufObj = VertBufObj; UINT StreamIdx = 0; UINT Offset = 0; UINT Stride = UINT(VertBufObj->m_VertSize); S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->SetStreamSource( StreamIdx, VertBufObj->m_VertBuf, Offset, Stride)); } if(m_CurVertDecl != VertBufObj->m_VertDecl) { m_CurVertDecl = VertBufObj->m_VertDecl; S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->SetVertexDeclaration(m_CurVertDecl)); } if(!m_D3dParam->m_NoDummyBoneVertexBuf) { int VertBufFmtDecl = VertBufObj->m_VertBufFmtDecl; if((VertBufFmtDecl & s3d_CDrvD3d9VertBufDesc::Decl_DummyBoneWgh) || (VertBufFmtDecl & s3d_CDrvD3d9VertBufDesc::Decl_DummyBoneSubscr)) { if(m_D3dParam->m_PixEnabled) { s3d_CDrvD3d9PixEvent::SetMarker( "*** Using DummyBoneWghIdx ***", S3D_DRV_D3D9_PIX_STD_COLOR); } LPDIRECT3DVERTEXBUFFER9 VertBuf = m_BufMgr->GetVertBufDummyBlendWghIdx(); if(m_CurVertBufDummyBlendWghIdx != VertBuf) { m_CurVertBufDummyBlendWghIdx = VertBuf; UINT StreamIdx = S3D_DRV_D3D9_DUMMY_BLENDWGHIDX_STREAM; UINT Offset = 0; UINT Stride = 0; S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->SetStreamSource( StreamIdx, m_CurVertBufDummyBlendWghIdx, Offset, Stride)); } } else if(m_CurVertBufDummyBlendWghIdx) { m_CurVertBufDummyBlendWghIdx = 0; UINT StreamIdx = S3D_DRV_D3D9_DUMMY_BLENDWGHIDX_STREAM; UINT Offset = 0; UINT Stride = 0; S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->SetStreamSource( StreamIdx, 0, Offset, Stride)); } } if(m_CurIdxBufObj != IdxBufObj) { m_CurIdxBufObj = IdxBufObj; S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->SetIndices(IdxBufObj->m_IdxBuf)); } } void s3d_CDrvD3d9GfxEngCLOD::SelectProg( const s3d_CSysChar *Info, s3d_CDrvGfxProg *Prog, const s3d_CSysChar *BufInfo, const s3d_CSysChar *BufDesc, const s3d_CDrvD3d9VertDecl &VertDecl, s3d_CDrvGfxParam_cr GfxParam) { s3d_CDrvD3d9Prog *ProgImpl = s3d_UtilRecogCastSilent(Prog); m_ProgMgr->SelectProg( Info, ProgImpl, BufInfo, BufDesc, VertDecl, GfxParam, m_ParamBlk, m_ParamStateProg); } void s3d_CDrvD3d9GfxEngCLOD::BeginDraw( const s3d_CSysChar *Info, int VertBufFmtDecl, bool UseFFP) { m_StateMgr.Apply(m_State); if(m_MatProjDirty) { m_MatProjDirty = false; m_ParamStateProg.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_MatProj; m_ParamStateFFP.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_MatProj; // Adjust for texel->pixel mapping LPD3DXMATRIXA16 EffMatProj = &m_ParamBlk.m_MatProj; *EffMatProj = m_MatProj; EffMatProj->_11 += m_CurProjOffsX * EffMatProj->_41; EffMatProj->_12 += m_CurProjOffsX * EffMatProj->_42; EffMatProj->_13 += m_CurProjOffsX * EffMatProj->_43; EffMatProj->_14 += m_CurProjOffsX * EffMatProj->_44; EffMatProj->_21 += m_CurProjOffsY * EffMatProj->_41; EffMatProj->_22 += m_CurProjOffsY * EffMatProj->_42; EffMatProj->_23 += m_CurProjOffsY * EffMatProj->_43; EffMatProj->_24 += m_CurProjOffsY * EffMatProj->_44; } if(UseFFP) BeginDrawFFP(Info, VertBufFmtDecl); else BeginDrawProg(Info, VertBufFmtDecl); } void s3d_CDrvD3d9GfxEngCLOD::BeginDrawFFP( const s3d_CSysChar *Info, int VertBufFmtDecl) { if(!m_D3dDev) return; if(m_ParamStateFFP.m_DirtyMask & s3d_CDrvD3d9ParamBlkState::Dirty_MatProj) { D3DXMATRIXA16 Temp; D3DXMatrixTranspose(&Temp, &m_ParamBlk.m_MatProj); S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->SetTransform(D3DTS_PROJECTION, &Temp)); } if(m_ParamStateFFP.m_DirtyMask & s3d_CDrvD3d9ParamBlkState::Dirty_MatView) { D3DXMATRIXA16 Temp; D3DXMatrixTranspose(&Temp, &m_ParamBlk.m_MatView); S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->SetTransform(D3DTS_WORLD, &Temp)); } if((m_ParamStateFFP.m_DirtyMask & s3d_CDrvD3d9ParamBlkState::Dirty_Light) || !m_PrevUsedFFP) { const D3DLIGHT9 *Light = m_ParamBlk.m_LightArray; s3d_CSysIntps NewLightCnt = m_WantLightCnt; S3D_SYS_ASSERT(NewLightCnt >= 0); s3d_CSysIntps iLight; for(iLight = 0; iLight < NewLightCnt; iLight++) { // Light parameters have changed. if(m_LightDirtyArray[iLight]) { m_LightDirtyArray[iLight] = false; S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->SetLight(DWORD(iLight), Light)); } // Enabled light if its currently disabled. if(!m_LightEnabledArray[iLight]) { m_LightEnabledArray[iLight] = true; S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->LightEnable(DWORD(iLight), TRUE)); } Light++; } // Disable previous lights if necessary. for(iLight = NewLightCnt; iLight < m_ParamBlk.m_CurLightCnt; iLight++) { if(m_LightEnabledArray[iLight]) { m_LightEnabledArray[iLight] = false; S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->LightEnable(DWORD(iLight), FALSE)); } } EnabledLighting(m_WantLighting); m_ParamBlk.m_CurLightCnt = NewLightCnt; } // On pipeline switch set m_SampMaxWantCnt to m_SampMaxUsedCnt so we // can update tex transformflags. // If is m_SampMaxWantCnt > 0 set it to m_SampMaxUsedCnt as well, so we // can calcualte new m_SampMaxUsedCnt; if(m_SampMaxWantCnt > 0 || !m_PrevUsedFFP) s3d_SysSetToMax(m_SampMaxWantCnt, m_ParamBlk.m_SampMaxUsedCnt); s3d_CSysIntps SampUseCnt = 0; s3d_CSysIntps iSamp; for(iSamp = 0; iSamp < m_SampMaxWantCnt; iSamp++) { s3d_CDrvD3d9TexObjBase *Tex = m_WantSampTexArray[iSamp]; LPDIRECT3DBASETEXTURE9 BaseTex = 0; if(m_ParamBlk.m_SampTexArray[iSamp] != Tex) { m_ParamBlk.m_SampTexArray[iSamp] = Tex; if(Tex) BaseTex = Tex->m_BaseTex; S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->SetTexture(iSamp, BaseTex)); } if(Tex) { s3d_SysSetToMax(SampUseCnt, iSamp + 1); // In FFP, only support 2d texture coordinates: SetTexOpTransf(iSamp, D3DTOP_MODULATE, D3DTTFF_COUNT2); UpdateSampParam(iSamp, Tex); } else SetTexOpTransf(iSamp, D3DTOP_DISABLE, D3DTTFF_DISABLE); } if(m_SampMaxWantCnt > 0) { m_ParamBlk.m_SampMaxUsedCnt = SampUseCnt; m_SampMaxWantCnt = 0; } for(iSamp = 0; iSamp < m_ParamBlk.m_SampMaxUsedCnt; iSamp++) { s3d_CDrvD3d9TexObjBase *Tex = m_ParamBlk.m_SampTexArray[iSamp]; if(Tex) Tex->UpdateToFrm(m_FrmIdx); } if(m_ParamStateFFP.m_DirtyMask & s3d_CDrvD3d9ParamBlkState::Dirty_MatGen) { int nAttr = s3d_SysMin(m_ParamBlk.m_SampMaxUsedCnt, m_MaxAttrCnt); for(int iAttr = 0; iAttr < nAttr; iAttr++) { LPD3DXMATRIXA16 AttrMat = &m_ParamBlk.m_MatGenArray[iAttr]; D3DXMATRIXA16 Temp; if(!D3DXMatrixIsIdentity(AttrMat)) { D3DXMatrixTranspose(&Temp, AttrMat); AttrMat = &Temp; } S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->SetTransform( D3DTRANSFORMSTATETYPE( iAttr + D3DTS_TEXTURE0), AttrMat)); } } // Const color emulation if vertex has no color info if(!m_WantLighting && (VertBufFmtDecl & s3d_CDrvD3d9VertBufDesc::Decl_ColorAlpha) == 0) { m_ParamBlk.m_UseConstColorAlpha = true; D3DMATERIAL9 Mtl; Mtl.Ambient = m_ParamBlk.m_ColorAlphaVal; Mtl.Diffuse = m_ParamBlk.m_ColorAlphaVal; Mtl.Specular = m_ParamBlk.m_ColorAlphaVal; Mtl.Emissive = m_ParamBlk.m_ColorAlphaVal; Mtl.Power = 0.f; S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->SetMaterial(&Mtl)); EnabledLighting(true); } else if(m_ParamStateFFP.m_DirtyMask & s3d_CDrvD3d9ParamBlkState::Dirty_Mtl) { S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->SetMaterial(&m_ParamBlk.m_Mtl)); } m_ParamStateFFP.Done(); } void s3d_CDrvD3d9GfxEngCLOD::EndDrawFFP( const s3d_CSysChar *Info) { if(m_ParamBlk.m_UseConstColorAlpha) { EnabledLighting(false); m_ParamBlk.m_UseConstColorAlpha = false; m_ParamStateFFP.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Mtl; } m_PrevUsedFFP = true; } void s3d_CDrvD3d9GfxEngCLOD::BeginDrawProg( const s3d_CSysChar *Info, int VertBufFmtDecl) { if(!m_D3dDev) return; // On pipeline switch set m_SampMaxWantCnt to m_SampMaxUsedCnt so we // can update tex transformflags. // If is m_SampMaxWantCnt > 0 set it to m_SampMaxUsedCnt as well, so we // can calcualte new m_SampMaxUsedCnt; if(m_SampMaxWantCnt > 0 || m_PrevUsedFFP) s3d_SysSetToMax(m_SampMaxWantCnt, m_ParamBlk.m_SampMaxUsedCnt); s3d_CSysIntps SampUseCnt = 0; s3d_CSysIntps iSamp; for(iSamp = 0; iSamp < m_SampMaxWantCnt; iSamp++) { s3d_CDrvD3d9TexObjBase *Tex = m_WantSampTexArray[iSamp]; LPDIRECT3DBASETEXTURE9 BaseTex = 0; if(m_ParamBlk.m_SampTexArray[iSamp] != Tex) { m_ParamBlk.m_SampTexArray[iSamp] = Tex; if(Tex) BaseTex = Tex->m_BaseTex; S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->SetTexture(iSamp, BaseTex)); } if(Tex) { s3d_SysSetToMax(SampUseCnt, iSamp + 1); UpdateSampParam(iSamp, Tex); } SetTexOpTransf(iSamp, D3DTOP_DISABLE, D3DTTFF_DISABLE); } if(m_SampMaxWantCnt > 0) { m_ParamBlk.m_SampMaxUsedCnt = SampUseCnt; m_SampMaxWantCnt = 0; } for(iSamp = 0; iSamp < m_ParamBlk.m_SampMaxUsedCnt; iSamp++) { s3d_CDrvD3d9TexObjBase *Tex = m_ParamBlk.m_SampTexArray[iSamp]; if(Tex) Tex->UpdateToFrm(m_FrmIdx); } // Const color emulation if vertex has no color info if(!m_WantLighting && (VertBufFmtDecl & s3d_CDrvD3d9VertBufDesc::Decl_ColorAlpha) == 0) { m_ParamBlk.m_UseConstColorAlpha = true; } m_ParamBlk.m_CurLightCnt = m_WantLightCnt; if(m_LightingEnabled) { // Disable lighting for prog pipeline. EnabledLighting(false); m_ParamStateFFP.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Mtl; } } void s3d_CDrvD3d9GfxEngCLOD::EndDrawProg( const s3d_CSysChar *Info) { if(m_ParamBlk.m_UseConstColorAlpha) { m_ParamBlk.m_UseConstColorAlpha = false; m_ParamStateProg.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Mtl; } m_PrevUsedFFP = false; } void s3d_CDrvD3d9GfxEngCLOD::DrawIndexedBatchPacket( D3DPRIMITIVETYPE D3dPrim, s3d_CSysIntps PacketSubCnt, s3d_CDrvD3d9Packet *PacketSubArray, s3d_CSysIntps VertexSubBase, s3d_CSysIntps IndexSubBase, s3d_CSysIntps BoneIdxSubBase, s3d_CSysIntps BoneIdxCnt, const s3d_CSysInt32u *BoneIdxData, bool TrackDummyBlendTransf) { s3d_CDrvD3d9PixEvent PixEvent; if(m_D3dParam->m_PixEnabled) PixEvent.Assign("DrawIndexedBatchPacket", S3D_DRV_D3D9_PIX_STD_COLOR); if(!m_D3dDev) return; if(!BoneIdxData && TrackDummyBlendTransf) { s3d_CSysInt32u BoneIdxData[4]; BoneIdxData[0] = 0; BoneIdxData[1] = 0; BoneIdxData[2] = 0; BoneIdxData[3] = 0; m_ProgMgr->TrackTransfBone( S3D_SYS_ARRAYCNTS(BoneIdxData), BoneIdxData, 1, &m_ParamBlk.m_MatView); } s3d_CDrvD3d9Packet *CurPacket = PacketSubArray; const s3d_CSysInt32u *CurBoneIdxData = 0; if(BoneIdxData) CurBoneIdxData = BoneIdxData + BoneIdxSubBase; s3d_CSysIntps CurIndexSubBase = IndexSubBase; s3d_CSysIntps CurVertexSubBase = VertexSubBase; const s3d_CSysIntps MatBoneCnt = m_MatBoneArray.GetCnt(); const D3DXMATRIXA16 *MatBoneData = m_MatBoneArray.GetPtrRaw(); s3d_CSysIntps PacketRest = PacketSubCnt; while(PacketRest > 0) { PacketRest--; if(BoneIdxData) { m_ProgMgr->TrackTransfBone( CurPacket->m_BoneIdxCnt, CurBoneIdxData, MatBoneCnt, MatBoneData); CurBoneIdxData += CurPacket->m_BoneIdxCnt; } s3d_CSysIntps PacketPrimCnt = CurPacket->m_PrimCnt; if(PacketPrimCnt > 0) { INT BaseVertexIndex = 0; UINT MinVertexIndex = UINT(CurVertexSubBase); UINT NumVertices = UINT(CurPacket->m_VertCnt); UINT StartIndex = UINT(CurIndexSubBase); UINT nPrim = UINT(PacketPrimCnt); S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->DrawIndexedPrimitive( D3dPrim, BaseVertexIndex, MinVertexIndex, NumVertices, StartIndex, nPrim)); } CurIndexSubBase += CurPacket->m_IdxCnt; CurVertexSubBase += CurPacket->m_VertCnt; CurPacket++; } } void s3d_CDrvD3d9GfxEngCLOD::DrawIndexedBatchPacketUP( D3DPRIMITIVETYPE D3dPrim, s3d_CSysIntps PacketSubCnt, s3d_CDrvD3d9Packet *PacketSubArray, s3d_CSysIntps VertexSubBase, const s3d_CSysIntm *VertData, int VertSize, D3DFORMAT IdxFmt, const s3d_CSysIntm *IdxData, s3d_CSysIntps BoneIdxSubBase, s3d_CSysIntps BoneIdxCnt, const s3d_CSysInt32u *BoneIdxData, bool TrackDummyBlendTransf) { s3d_CDrvD3d9PixEvent PixEvent; if(m_D3dParam->m_PixEnabled) PixEvent.Assign( "DrawIndexedBatchPacketUP", S3D_DRV_D3D9_PIX_STD_COLOR); if(!m_D3dDev) return; if(!BoneIdxData && TrackDummyBlendTransf) { s3d_CSysInt32u BoneIdxData[4]; BoneIdxData[0] = 0; BoneIdxData[1] = 0; BoneIdxData[2] = 0; BoneIdxData[3] = 0; m_ProgMgr->TrackTransfBone( S3D_SYS_ARRAYCNTS(BoneIdxData), BoneIdxData, 1, &m_ParamBlk.m_MatView); } int OffsFactor = 2; if(IdxFmt == D3DFMT_INDEX32) OffsFactor = 4; s3d_CDrvD3d9Packet *CurPacket = PacketSubArray; const s3d_CSysInt32u *CurBoneIdxData = 0; if(BoneIdxData) CurBoneIdxData = BoneIdxData + BoneIdxSubBase; const s3d_CSysIntm *CurIdxData = IdxData; s3d_CSysIntps CurVertexSubBase = VertexSubBase; const s3d_CSysIntps MatBoneCnt = m_MatBoneArray.GetCnt(); const D3DXMATRIXA16 *MatBoneData = m_MatBoneArray.GetPtrRaw(); s3d_CSysIntps PacketRest = PacketSubCnt; while(PacketRest > 0) { PacketRest--; if(BoneIdxData) { m_ProgMgr->TrackTransfBone( CurPacket->m_BoneIdxCnt, CurBoneIdxData, MatBoneCnt, MatBoneData); CurBoneIdxData += CurPacket->m_BoneIdxCnt; } if(CurPacket->m_PrimCnt > 0) { INT BaseVertexIndex = 0; UINT MinVertexIndex = UINT(CurVertexSubBase); UINT NumVertices = UINT(CurPacket->m_VertCnt); UINT nPrim = UINT(CurPacket->m_PrimCnt); S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->DrawIndexedPrimitiveUP( D3dPrim, MinVertexIndex, NumVertices, nPrim, CurIdxData, IdxFmt, VertData, VertSize)); } CurIdxData += (CurPacket->m_IdxCnt * OffsFactor); CurVertexSubBase += CurPacket->m_VertCnt; CurPacket++; } } /////////////////////////////////////////////////////////////////////////////// void s3d_CDrvD3d9GfxEngCLOD::ResetDevice() { if(!m_D3dDev) return; HRESULT Result = m_D3dDev->TestCooperativeLevel(); if(Result == D3DERR_DEVICELOST) { return; } else if(SUCCEEDED(Result) || Result == D3DERR_DEVICENOTRESET) { Park(); S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->Reset(&m_PresentParam)); Unpark(); } else { S3D_DRV_D3D9_CHECKHRES(&m_Env, Result); } } /////////////////////////////////////////////////////////////////////////////// s3d_CDrvD3d9SurfRTPtr s3d_CDrvD3d9GfxEngCLOD::FindSurfRT( int Width, int Height, D3DFORMAT Fmt, D3DMULTISAMPLE_TYPE MultiSampleType) { s3d_CDrvD3d9SurfRTKey Key(Fmt, MultiSampleType); s3d_CDrvD3d9SurfRTPoolPtr SurfRTPool = m_SurfRTPoolMap.GetAtDefault(Key, 0); if(!SurfRTPool) { SurfRTPool = S3D_SYS_NEW s3d_CDrvD3d9SurfRTPool; m_SurfRTPoolMap.SetAt(Key, SurfRTPool); } s3d_CDrvD3d9SurfRTPtr SurfRT; if(!SurfRTPool->m_SurfRTArray.IsEmpty()) SurfRT = SurfRTPool->m_SurfRTArray.ExtractBack(); else SurfRT = S3D_SYS_NEW s3d_CDrvD3d9SurfRT; SurfRT->m_SurfRTPool = SurfRTPool; if(Width > SurfRT->m_Width || Height > SurfRT->m_Height) { s3d_CDrvD3d9Surf Surf; DWORD MultiSampleQuality = m_PresentParam.MultiSampleQuality; if(s3d_CDrvD3d9Util::IsDepthStencilFmt(Fmt)) { BOOL Discard = FALSE; S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->CreateDepthStencilSurface( Width, Height, Fmt, MultiSampleType, MultiSampleQuality, Discard, &Surf.EmptyRef(), 0)); } else { BOOL Lockable = FALSE; S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->CreateRenderTarget( Width, Height, Fmt, MultiSampleType, MultiSampleQuality, Lockable, &Surf.EmptyRef(), 0)); } if(!Surf) return 0; S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->EvictManagedResources()); SurfRT->m_Width = Width; SurfRT->m_Height = Height; SurfRT->m_Surf = Surf; } return SurfRT; } void s3d_CDrvD3d9GfxEngCLOD::BeginRenderTexStd( int Width, int Height, s3d_CSysIntps DestCnt, const s3d_CDrvGfxDest *DestArray) { s3d_CDrvD3d9Surf SurfDepth = m_MainSurfDepth; // Depthstencil surface must be as least as big as color surface // if main depthstencil surface is too small allocate a new surface if(m_PresentParam.MultiSampleType != D3DMULTISAMPLE_NONE || Width > s3d_CSysIntps(m_PresentParam.BackBufferWidth) || Height > s3d_CSysIntps(m_PresentParam.BackBufferHeight)) { s3d_CDrvD3d9SurfRTPtr SurfRTDepth = FindSurfRT( Width, Height, m_DepthStencilFmt, D3DMULTISAMPLE_NONE); if(SurfRTDepth) { m_CurSurfRTDepth = SurfRTDepth; SurfDepth = SurfRTDepth->m_Surf; } } int SurfColUsedCnt = 0; DWORD iDest; for(iDest = 0; iDest < DWORD(DestCnt); iDest++) { const s3d_CDrvGfxDest *GfxDest = &DestArray[iDest]; s3d_CDrvD3d9TexObjBase *TexImpl = s3d_UtilRecogCastSilent( GfxDest->m_Tex); if(!TexImpl) continue; UnbindTex(TexImpl); s3d_CDrvD3d9Surf DestSurf; S3D_DRV_D3D9_CHECK( &m_Env, TexImpl->GetRenderTarget(DestSurf, GfxDest)); if(!DestSurf) continue; if(TexImpl->m_TexFmt.m_FmtCol != D3DFMT_UNKNOWN) { //S3D_DRV_D3D9_DBGPRINTF( // "selecting RT(%d) w=%d, h=%d\n", iDest, Width, Height); if(m_CurSurfColArray[iDest] != DestSurf) { HRESULT Result; S3D_DRV_D3D9_CALLCHECK( &m_Env, Result, m_D3dDev->SetRenderTarget(iDest, DestSurf)); if(FAILED(Result)) continue; m_CurSurfColArray[iDest] = DestSurf; } SurfColUsedCnt++; } // NVIDIA depthtex else if(TexImpl->m_TexFmt.m_FmtDepth != D3DFMT_UNKNOWN) { //S3D_DRV_D3D9_DBGPRINTF( // "selecting RT(%d) w=%d, h=%dn", iDest, Width, Height); SurfDepth = DestSurf; // Only set a color buffer when we haven't set one already if(SurfColUsedCnt == 0 && DestCnt == 1) { s3d_CDrvD3d9Surf SurfCol = m_MainSurfCol; if(DWORD(Width) > m_PresentParam.BackBufferWidth || DWORD(Height) > m_PresentParam.BackBufferHeight) { s3d_CDrvD3d9SurfRTPtr SurfRTCol = FindSurfRT( Width, Height, m_BackBufFmt, D3DMULTISAMPLE_NONE); if(!SurfRTCol) continue; m_CurSurfRTColArray.SetAtRaw(iDest, SurfRTCol); SurfCol = SurfRTCol->m_Surf; } if(m_CurSurfColArray[iDest] != SurfCol) { HRESULT Result; S3D_DRV_D3D9_CALLCHECK( &m_Env, Result, m_D3dDev->SetRenderTarget(iDest, SurfCol)); if(FAILED(Result)) continue; m_CurSurfColArray[iDest] = SurfCol; SurfColUsedCnt++; } } } else { S3D_SYS_ASSERT(0); } } if(m_CurSurfDepth != SurfDepth) { S3D_DRV_D3D9_CALL( &m_Env, m_D3dDev->SetDepthStencilSurface(SurfDepth)); m_CurSurfDepth = SurfDepth; } SetRenderTargetElseNone(SurfColUsedCnt); } void s3d_CDrvD3d9GfxEngCLOD::EndRenderTexStd() { } void s3d_CDrvD3d9GfxEngCLOD::BeginRenderTexMSAA( int Width, int Height, s3d_CSysIntps DestCnt, const s3d_CDrvGfxDest *DestArray) { s3d_CDrvD3d9Surf SurfDepth = m_MainSurfDepth; if(DWORD(Width) > m_PresentParam.BackBufferWidth || DWORD(Height) > m_PresentParam.BackBufferHeight) { s3d_CDrvD3d9SurfRTPtr SurfRTDepth = FindSurfRT( Width, Height, m_DepthStencilFmt, m_PresentParam.MultiSampleType); m_CurSurfRTDepth = SurfRTDepth; SurfDepth = SurfRTDepth->m_Surf; } HRESULT Result = 0; int SurfColUsedCnt = 0; DWORD iDest; for(iDest = 0; iDest < DWORD(DestCnt); iDest++) { const s3d_CDrvGfxDest *GfxDest = &DestArray[iDest]; s3d_CDrvD3d9TexObjBase *TexImpl = s3d_UtilRecogCastSilent( GfxDest->m_Tex); if(!TexImpl) continue; // Shouldn't be needed as we're not using texture surface as // rendertarget. //UnbindTex(TexImpl); if(TexImpl->m_TexFmt.m_FmtDepth != D3DFMT_UNKNOWN) { s3d_CDrvD3d9Error e; e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_eng.error_depthtex_msaa"; e.m_StdTempl = "D3D: Can't use nvidia depth texture with MSAA."; e.AddInfo(m_Info); s3d_UtilMsgReportError(m_MsgHandler, e); continue; } if(!TexImpl->m_TexFmt.m_CanMultiSample) { s3d_CDrvD3d9Error e; e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_eng.error_depthtex_msaa"; e.m_StdTempl = "D3D: Can't use texture format '[1]' with MSAA."; e.AddInfo(m_Info); e.AddInfo(s3d_CDrvD3d9Util::StrOfFmt(TexImpl->m_TexFmt.m_FmtCol)); s3d_UtilMsgReportError(m_MsgHandler, e); continue; } D3DFORMAT FmtCol = TexImpl->m_TexFmt.m_FmtCol; if(FmtCol == D3DFMT_UNKNOWN) { S3D_SYS_ASSERT(0); continue; } s3d_CDrvD3d9Surf SurfCol; if(SurfColUsedCnt > 0 || FmtCol != m_BackBufFmt || DWORD(Width) > m_PresentParam.BackBufferWidth || DWORD(Height) > m_PresentParam.BackBufferHeight) { s3d_CDrvD3d9SurfRTPtr SurfRTCol = FindSurfRT( Width, Height, FmtCol, m_PresentParam.MultiSampleType); if(!SurfRTCol) continue; m_CurSurfRTColArray.SetAtRaw(iDest, SurfRTCol); SurfCol = SurfRTCol->m_Surf; } else { SurfCol = m_MainSurfCol; } if(m_CurSurfColArray[iDest] != SurfCol) { S3D_DRV_D3D9_CALLCHECK( &m_Env, Result, m_D3dDev->SetRenderTarget(iDest, SurfCol)); if(FAILED(Result)) continue; m_CurSurfColArray[iDest] = SurfCol; } SurfColUsedCnt++; } if(m_CurSurfDepth != SurfDepth) { S3D_DRV_D3D9_CALL( &m_Env, m_D3dDev->SetDepthStencilSurface(SurfDepth)); m_CurSurfDepth = SurfDepth; } SetRenderTargetElseNone(SurfColUsedCnt); } void s3d_CDrvD3d9GfxEngCLOD::EndRenderTexMSAA() { s3d_CSysIntps iDest; for(iDest = 0; iDest < m_DestCnt; iDest++) { DWORD Idx = DWORD(iDest); const s3d_CDrvGfxDest *GfxDest = &m_DestArray[iDest]; if(!GfxDest) continue; s3d_CDrvD3d9TexObjBase *TexImpl = s3d_UtilRecogCastSilent( GfxDest->m_Tex); if(!TexImpl) continue; if(!TexImpl->m_TexFmt.m_CanMultiSample) continue; s3d_CDrvD3d9Surf DestSurf; S3D_DRV_D3D9_CHECK( &m_Env, TexImpl->GetRenderTarget(DestSurf, GfxDest)); if(!DestSurf) return; const RECT Rect = {0, 0, m_BufWidth, m_BufHeight}; HRESULT Result; S3D_DRV_D3D9_CALLCHECK( &m_Env, Result, m_D3dDev->StretchRect( m_CurSurfColArray[iDest], &Rect, DestSurf, &Rect, D3DTEXF_LINEAR)); } } void s3d_CDrvD3d9GfxEngCLOD::UnbindTex( s3d_CDrvD3d9TexObjBase *TexImpl) { if(!TexImpl) return; int iSamp; for(iSamp = 0; iSamp < m_ParamBlk.m_SampMaxUsedCnt; iSamp++) { if(m_ParamBlk.m_SampTexArray[iSamp] == TexImpl) { m_ParamBlk.m_SampTexArray[iSamp] = 0; m_WantSampTexArray[iSamp] = 0; S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->SetTexture(iSamp, 0)); SetTexOpTransf(iSamp, D3DTOP_DISABLE, D3DTTFF_DISABLE); s3d_SysSetToMax(m_SampMaxWantCnt, iSamp + 1); } } } void s3d_CDrvD3d9GfxEngCLOD::SetRenderTargetElseNone( int Start) { s3d_CSysIntps nRT = s3d_SysMin(m_MaxSimRTCnt, m_CurSurfColUsedCnt); s3d_CSysIntps iRT; for(iRT = Start; iRT < nRT; iRT++) { if(m_CurSurfColArray[iRT]) { S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->SetRenderTarget(DWORD(iRT), 0)); m_CurSurfColArray[iRT] = 0; } } m_CurSurfColUsedCnt = Start; } void s3d_CDrvD3d9GfxEngCLOD::InitRenderToTex() { if(!m_D3dDev) return; m_MaxSimRTCnt = m_DevCaps.NumSimultaneousRTs; if(m_MaxSimRTCnt > S3D_DRV_D3D9_MAX_SIM_RT_CNT) { m_MaxSimRTCnt = S3D_DRV_D3D9_MAX_SIM_RT_CNT; S3D_SYS_ASSERT(0); } s3d_CSysIntps iRT; for(iRT = 0; iRT < m_MaxSimRTCnt; iRT++) m_CurSurfColArray[iRT] = 0; m_CurSurfRTColArray.SetCnt(m_MaxSimRTCnt); m_CurSurfColUsedCnt = 0; m_DestProp = 0; m_DestCnt = -1; S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->GetRenderTarget( 0, &m_MainSurfCol.EmptyRef())); S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->GetDepthStencilSurface( &m_MainSurfDepth.EmptyRef())); m_CurSurfColArray[0] = m_MainSurfCol; m_CurSurfDepth = m_MainSurfDepth; } void s3d_CDrvD3d9GfxEngCLOD::RestoreRenderTargets() { if(!m_D3dDev) return; S3D_SYS_ASSERT(m_DestCnt == -1); // Put temporary surfaces back to freelist m_CurSurfRTColArray.Clear(); m_CurSurfRTDepth = 0; if(m_CurSurfDepth != m_MainSurfDepth) { S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->SetDepthStencilSurface(m_MainSurfDepth)); m_CurSurfDepth = m_MainSurfDepth; } if(m_CurSurfColUsedCnt == 0) return; // First unbind render targets > 0, main color surface might be bound to // one of these slots. s3d_CSysIntps nRT = s3d_SysMin(m_MaxSimRTCnt, m_CurSurfColUsedCnt); s3d_CSysIntps iRT; for(iRT = 1; iRT < nRT; iRT++) { LPDIRECT3DSURFACE9 Surf = m_CurSurfColArray[iRT]; if(Surf) { S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->SetRenderTarget(DWORD(iRT), 0)); m_CurSurfColArray[iRT] = 0; } } if(m_CurSurfColArray[0] != m_MainSurfCol) { S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->SetRenderTarget(0, m_MainSurfCol)); m_CurSurfColArray[0] = m_MainSurfCol; } m_CurSurfColUsedCnt = 0; } /////////////////////////////////////////////////////////////////////////////// void s3d_CDrvD3d9GfxEngCLOD::EnabledScissor(bool Enabled) { if(m_CurScissorEnabled != Enabled) { m_CurScissorEnabled = Enabled; S3D_DRV_D3D9_CHECK( &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_SCISSORTESTENABLE, BOOL(Enabled))); } } /////////////////////////////////////////////////////////////////////////////// void s3d_CDrvD3d9GfxEngCLOD::InitLighting() { if(!m_D3dDev) return; m_LightingEnabled = false; m_WantLighting = false; m_MaxLightCnt = S3D_DRV_D3D9_MAX_LIGHT_CNT; if(DWORD(m_MaxLightCnt) > m_DevCaps.MaxActiveLights) { S3D_SYS_ASSERT(0); m_MaxLightCnt = m_DevCaps.MaxActiveLights; } m_WantLightCnt = 0; m_ParamBlk.m_CurLightCnt = 0; s3d_CSysIntps iLight; for(iLight = 0; iLight < m_MaxLightCnt; iLight++) { m_LightEnabledArray[iLight] = false; m_LightDirtyArray[iLight] = false; S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->LightEnable(DWORD(iLight), FALSE)); } S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_LIGHTING, FALSE)); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_NORMALIZENORMALS, FALSE)); } void s3d_CDrvD3d9GfxEngCLOD::EnabledLighting( bool Enabled) { if(!m_D3dDev) return; if(m_LightingEnabled != Enabled) { m_LightingEnabled = Enabled; S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_LIGHTING, BOOL(Enabled))); S3D_DRV_D3D9_CHECK( &m_Env, s3d_CDrvD3d9StateUtil::SetRenderStateI( m_D3dDev, D3DRS_NORMALIZENORMALS, BOOL(Enabled))); } } /////////////////////////////////////////////////////////////////////////////// void s3d_CDrvD3d9GfxEngCLOD::InitDevCaps() { m_HasNvDepthTex = false; m_CanRenderDepth = false; if(!m_D3d) return; HRESULT Result = 0; D3DDISPLAYMODE AdapterMode; S3D_DRV_D3D9_CALLCHECK( &m_Env, Result, m_D3d->GetAdapterDisplayMode( m_Adapter, &AdapterMode)); if(FAILED(Result)) return; D3DFORMAT AdapterFmt = AdapterMode.Format; // NVIDIA depthtex. if(m_D3dParam->m_NVDepthTexEnabled) { S3D_DRV_D3D9_HRESCALL( &m_Env, Result, m_D3d->CheckDeviceFormat( m_Adapter, m_DevType, AdapterFmt, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, D3DFMT_D24S8)); if(SUCCEEDED(Result)) m_HasNvDepthTex = true; } // Official "depthtex". if(m_DevCaps.PixelShaderVersion >= D3DPS_VERSION(1, 1)) { m_CanRenderDepth = false; S3D_DRV_D3D9_HRESCALL( &m_Env, Result, m_D3d->CheckDeviceFormat( m_Adapter, m_DevType, AdapterFmt, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_R32F)); if(SUCCEEDED(Result)) m_CanRenderDepth = true; else { S3D_DRV_D3D9_HRESCALL( &m_Env, Result, m_D3d->CheckDeviceFormat( m_Adapter, m_DevType, AdapterFmt, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_R16F)); if(SUCCEEDED(Result)) m_CanRenderDepth = true; } } } /////////////////////////////////////////////////////////////////////////////// void s3d_CDrvD3d9GfxEngCLOD::Park() { if(!m_D3dDev) return; S3D_DRV_D3D9_CHECK( &m_Env, m_D3dDev->EvictManagedResources()); if(m_BufMgr) m_BufMgr->Park(); if(m_TexMgr) m_TexMgr->Park(); RestoreRenderTargets(); m_CurSurfColArray[0].Reset(); m_CurSurfDepth.Reset(); m_MainSurfCol.Reset(); m_MainSurfDepth.Reset(); m_CurSurfRTDepth = 0; m_CurSurfRTColArray.Clear(); m_SurfRTPoolMap.Reset(); m_VisibMgr->Park(); m_FlushEvent.Reset(); } void s3d_CDrvD3d9GfxEngCLOD::Unpark() { if(!m_D3dDev) return; if(m_ProgMgr) m_ProgMgr->InvalidateProg(); if(m_TexMgr) m_TexMgr->Unpark(); if(m_BufMgr) m_BufMgr->Unpark(); // Invalidate buffers m_CurVertBufObj = 0; m_CurIdxBufObj = 0; m_CurVertDecl = 0; // Invalidate texturing InitTexturing(); // Invalidate lightstate InitLighting(); // Invalidate render targets InitRenderToTex(); SetDefaultState(); m_ParamStateFFP.Invalidate(); m_ParamStateProg.Invalidate(); m_MatProjDirty = true; m_MatBoneDirty = true; m_VisibMgr->Unpark(); m_FlushEvent.Init(&m_Env, m_D3dDev); } /////////////////////////////////////////////////////////////////////////////// s3d_CDrvD3d9GfxOut::s3d_CDrvD3d9GfxOut( s3d_CDrvD3d9GfxEngCLOD *GfxEng) { m_GfxEng = GfxEng; } s3d_CUtilStr s3d_CDrvD3d9GfxOut::GetDesc() { if(m_GfxEng) return m_GfxEng->GetDesc(); else return 0; } void s3d_CDrvD3d9GfxOut::Alter( s3d_CUtilStr_cr Info, s3d_CUtilStr_cr Device, int Prop, int Left, int Top, int Width, int Height, int Depth, int Frequency, s3d_CUtilSnkChunk *Param) { if(m_GfxEng) m_GfxEng->Alter(Info, Device, Prop, Top, Left, Width, Height, Depth, Frequency, Param); } void s3d_CDrvD3d9GfxOut::Alter( s3d_CUtilStr_cr Info, s3d_CUtilStr_cr Device, int Prop, int Left, int Top, int Width, int Height, int Depth, int Frequency, s3d_CDrvD3d9Param *D3dParam) { if(m_GfxEng) m_GfxEng->Alter(Info, Device, Prop, Top, Left, Width, Height, Depth, Frequency, D3dParam); } void s3d_CDrvD3d9GfxOut::Present() { if(m_GfxEng) m_GfxEng->Present(); } void s3d_CDrvD3d9GfxOut::GetSize(int &Width, int &Height) const { if(m_GfxEng) m_GfxEng->GetMainSize(Width, Height); else { Width = 0; Height = 0; } } int s3d_CDrvD3d9GfxOut::GetColorAlphaBits() const { if(m_GfxEng) return m_GfxEng->GetMainColorAlphaBits(); else return 0; } void s3d_CDrvD3d9GfxOut::SetGamma( s3d_CUtilVec3f_cr Gamma) { if(m_GfxEng) m_GfxEng->SetGamma(Gamma); } /////////////////////////////////////////////////////////////////////////////// // NEW for GAMETOOLS S3D_UTIL_RTTI_TABLE_DEFINE_DERIVED(s3d_CDrvD3d9GfxEngCLOD, s3d_CDrvGfxEng) S3D_UTIL_RTTI_TARGET_DEFINE(s3d_CDrvD3d9GfxEngCLOD) void s3d_CDrvD3d9GfxEngCLOD::ManipulateBatchForLODSTRIPS(s3d_CDrvGfxBatchPtr Batch, Geometry::LodStripsLibrary *lodstrips, float lod) { s3d_CDrvD3d9Batch *BatchImpl = s3d_UtilRecogCastSilent(Batch); if(!BatchImpl) { S3D_SYS_ASSERT(0); return; } //lodstrips->GoToLod(lod); /* BatchImpl->m_IdxBufObj->m_IdxCnt = 30; BatchImpl->m_IdxBufObj->m_PacketArray[0].m_IdxCnt = BatchImpl->m_IdxBufObj->m_IdxCnt; BatchImpl->m_IdxBufObj->m_PacketArray[0].m_PrimCnt = BatchImpl->m_IdxBufObj->m_PacketArray[0].m_IdxCnt - 2;*/ BatchImpl->m_IdxBufObj->m_D3dPrim = D3DPT_TRIANGLESTRIP; } void s3d_CDrvD3d9GfxEngCLOD::GetViewPos(float &x, float &y, float &z) { x = m_ParamBlk.m_MatView._41; y = m_ParamBlk.m_MatView._42; z = m_ParamBlk.m_MatView._43; }