source: GTP/trunk/App/Demos/Geom/Shark3D/src/drv_d3d9_eng.cpp @ 2236

Revision 2236, 158.1 KB checked in by gumbau, 17 years ago (diff)
Line 
1///////////////////////////////////////////////////////////////////////////////
2//
3//      ##  ######
4//       ######  ###
5//  ## ###############        Shark 3D Engine (www.shark3d.com)
6//   ########## # # #
7//    ########                Copyright (c) 1996-2006 Spinor GmbH.
8//   ######### # # #          All rights reserved.
9//  ##   ##########
10//      ##
11//
12///////////////////////////////////////////////////////////////////////////////
13
14#include "drv_d3d9_eng.h"
15#include "drv_d3d9_mmx.h"
16#include "drv_d3d9_types.h"
17#include "drv_d3d9_util.h"
18#include "drv_d3d9_enum.h"
19#include "drv_d3d9_progutil.h"
20#include "drv_d3d9_paramblk.h"
21#include "drv_d3d9_inspect.h"
22#include "drv/util/drv_util_gfxutil.h"
23#include "sys/core/sys_util.h"
24#include "general/general_def.h"
25#include "util/base/util_strutil.h"
26#include "util/base/util_strbuf.h"
27#include "util/base/util_rawstrutil.h"
28#include "util/snk/util_snk_work.h"
29#include "util/snk/util_snk_extractutil.h"
30
31///////////////////////////////////////////////////////////////////////////////
32
33S3D_UTIL_RECOG_DEFINEINFO(s3d_CDrvD3d9Batch);
34
35s3d_CDrvD3d9Batch::s3d_CDrvD3d9Batch(
36        s3d_CUtilMsgHandler *ReportMsgHandler)
37{
38    S3D_UTIL_RECOG_INITOBJ(s3d_CDrvD3d9Batch);
39
40    m_ReportMsgHandler = ReportMsgHandler;
41//      use_triangle_strips = false;
42}
43
44s3d_CDrvD3d9Batch::~s3d_CDrvD3d9Batch()
45{
46    if(m_ReportMsgHandler)
47    {
48        s3d_CUtilMsg m;
49        m.m_Code = "drv/imp/directx/d3d9/drv_d3d9_eng.report_batch_destroy";
50        m.m_StdTempl = "D3D: "
51                "Destroying batch Addr=[1].";
52        m.AddInfo("");
53        m.AddInfo(s3d_CUtilStrUtil::StrOfPtr(this));
54        s3d_UtilMsgReportNote(m_ReportMsgHandler, m);
55    }
56}
57
58///////////////////////////////////////////////////////////////////////////////
59
60s3d_CDrvD3d9GfxEngCLOD::s3d_CDrvD3d9GfxEngCLOD(
61        s3d_CUtilMsgHandler *MsgHandler, s3d_CUtilStr_cr Info,
62        bool Bare, s3d_CCompSuppl *CompSuppl,
63        s3d_CUtilAtomMgr *AtomMgr, s3d_CUtilMemPool *MemPool,
64        s3d_CUtilStorageMgr *StorageMgr, s3d_CCompResMgr *ResMgr,
65        s3d_CCompSuppl *UnivProgSuppl, s3d_CCompSuppl *UnivProgGivenSuppl,
66        s3d_CUtilSnkChunk *DefaultOutParam)
67{
68    m_MsgHandler = MsgHandler;
69    m_Info = Info;
70    m_AtomMgr = AtomMgr;
71    m_MemPool = MemPool;
72    m_ResMgr = ResMgr;
73    m_StorageMgr = StorageMgr;
74    m_UnivProgSuppl = UnivProgSuppl;
75    m_UnivProgGivenSuppl = UnivProgGivenSuppl;
76    m_DefaultOutParam = DefaultOutParam;
77
78    m_CtxWin32 = 0;
79    m_hWnd = 0;
80
81    m_Prop = 0;
82    m_BufWidth = 0;
83    m_BufHeight = 0;
84
85    m_BufColorAlphaBits = 0;
86    m_BufDepthBits = 0;
87    m_BufStencilBits = 0;
88    m_BufDepthBiasScale = 0;
89
90    m_SWVertProc = false;
91    m_DevFlags = 0;
92    m_DevType = D3DDEVTYPE_NULLREF;
93    m_BackBufFmt = D3DFMT_UNKNOWN;
94    m_DepthStencilFmt = D3DFMT_UNKNOWN;
95    m_MainSurfCol = 0;
96    m_MainSurfDepth = 0;
97
98    m_FrmIdx = 0;
99
100    m_CurSurfColUsedCnt = 0;
101    m_MaxSimRTCnt = 0;
102    m_CurSurfDepth = 0;
103    m_DestProp = 0;
104    m_DestCnt = -1;
105
106    m_Adapter = 0;
107    s3d_SysMemset(&m_DevCaps, 0, S3D_SYS_SIZEOFS(m_DevCaps));
108    s3d_SysMemset(&m_PresentParam, 0, S3D_SYS_SIZEOFS(m_PresentParam));
109    m_UseMSAA = false;
110    s3d_SysMemset(&m_Viewport, 0, S3D_SYS_SIZEOFS(m_Viewport));
111    s3d_SysMemset(&m_ScissorRect, 0, S3D_SYS_SIZEOFS(m_ScissorRect));
112    m_CurScissorEnabled = false;
113
114    m_CullMode = 0;
115    m_DepthTestMode = 0;
116    m_DepthBiasOverlay = 0;
117    m_DepthBiasOffs = 0;
118    m_BlendColSrcFac = 0;
119    m_BlendColDestFac = 0;
120    m_BlendColOp = 0;
121    m_BlendAlphaSrcFac = 0;
122    m_BlendAlphaDestFac = 0;
123    m_BlendAlphaOp = 0;
124    m_PaintMode = 0;
125    m_StencilTestModeFront = 0;
126    m_StencilTestModeBack = 0;
127    m_StencilOpFailFront = 0;
128    m_StencilOpDepthFailFront = 0;
129    m_StencilOpDepthPassFront = 0;
130    m_StencilOpFailBack = 0;
131    m_StencilOpDepthFailBack = 0;
132    m_StencilOpDepthPassBack = 0;
133    m_AlphaTestMode = 0;
134    m_AlphaTestRef = 0;
135    m_PrevUsedFFP = false;
136
137    m_MainProjOffsX = 0;
138    m_MainProjOffsY = 0;
139    m_CurProjOffsX = 0;
140    m_CurProjOffsY = 0;
141    m_MatProjDirty = false;
142    s3d_SysMemset(&m_MatProj, 0, S3D_SYS_SIZEOFS(m_MatProj));
143
144    m_ParamBlk.Reset();
145    m_ParamStateProg.Done();
146    m_ParamStateFFP.Done();
147
148    m_MaxAttrCnt = 0;
149    s3d_CSysIntps iAttr;
150    for(iAttr = 0; iAttr < S3D_DRV_D3D9_MAX_ATTR_CNT; iAttr++)
151    {
152        m_CurTexTransfFlagsArray[iAttr] = D3DTTFF_DISABLE;
153        m_CurTexOpArray[iAttr] = D3DTOP_DISABLE ;
154    }
155    m_MaxSampCnt = 0;
156    s3d_CSysIntps iSamp;
157    for(iSamp = 0; iSamp < S3D_DRV_D3D9_MAX_SAMPLER_CNT; iSamp++)
158    {
159        m_CurSampParamArray[iSamp].m_FilterMin = D3DTEXF_POINT;
160        m_CurSampParamArray[iSamp].m_FilterMag = D3DTEXF_POINT;
161        m_CurSampParamArray[iSamp].m_FilterMip = D3DTEXF_NONE;
162        m_CurSampParamArray[iSamp].m_AddrX = D3DTADDRESS_WRAP;
163        m_CurSampParamArray[iSamp].m_AddrY = D3DTADDRESS_WRAP;
164        m_CurSampParamArray[iSamp].m_AddrZ = D3DTADDRESS_WRAP;
165        m_CurSampParamArray[iSamp].m_SRGBTex = FALSE;
166        m_SampModeArray[iSamp] = 0;
167    }
168    m_ParamBlk.m_SampMaxUsedCnt = 0;
169    m_SampMaxWantCnt = 0;
170    m_MinLbTexWidth = 0;
171    m_MaxLbTexWidth = 0;
172    m_MinLbTexHeight = 0;
173    m_MaxLbTexHeight = 0;
174    m_MinLbVolTexExt = 0;
175    m_MaxLbVolTexExt = 0;
176    m_MaxFilterMinStd = D3DTEXF_LINEAR;
177    m_MaxFilterMagStd = D3DTEXF_LINEAR;
178    m_MaxFilterMinCube = D3DTEXF_LINEAR;
179    m_MaxFilterMagCube = D3DTEXF_LINEAR;
180    m_MaxFilterMinVol = D3DTEXF_LINEAR;
181    m_MaxFilterMagVol = D3DTEXF_LINEAR;
182    m_MaxFilterMipStd = D3DTEXF_POINT;
183    m_MaxFilterMipCube = D3DTEXF_POINT;
184    m_MaxFilterMipVol = D3DTEXF_POINT;
185
186    m_MatBoneDirty = false;
187
188    m_MaxLightCnt = 0;
189    m_LightingEnabled = false;
190    m_WantLighting = false;
191    m_WantLightCnt = 0;
192    int iLight;
193    for(iLight = 0; iLight < S3D_DRV_D3D9_MAX_LIGHT_CNT; iLight++)
194    {
195        m_LightEnabledArray[iLight] = false;
196        m_LightDirtyArray[iLight] = false;
197    }
198
199    m_IdxFlushCnt = 0;
200}
201
202s3d_CDrvD3d9GfxEngCLOD::~s3d_CDrvD3d9GfxEngCLOD()
203{
204    Done();
205}
206
207void s3d_CDrvD3d9GfxEngCLOD::Done()
208{
209/*
210    if(m_CtxWin32)
211        m_CtxWin32->Win32NotifDestroyGfx();
212    m_CtxWin32 = 0;
213    m_Ctx = 0;
214*/
215    if(m_D3dDev)
216    {
217        S3D_DRV_D3D9_CHECK(
218                &m_Env, m_D3dDev->EvictManagedResources());
219    }
220    m_D3dDev.Reset();
221    m_D3d.Reset();
222}
223
224s3d_CUtilStr s3d_CDrvD3d9GfxEngCLOD::GetDesc() const
225{
226    s3d_CUtilStrBuf Result;
227    Result.Append("D3D v0x");
228    DWORD D3dVers = DIRECT3D_VERSION | D3D_SDK_VERSION;
229#ifdef D3D_DEBUG_INFO
230    D3dVers &= ~0x80000000;
231#endif
232    Result.AppendInt(D3dVers, 0, s3d_CUtilStrNum::Format_Hex);
233    Result.Append(" \"");
234    Result.Append(m_AdapterDesc);
235    Result.Append("\" ");
236    if(m_DevType == D3DDEVTYPE_REF)
237        Result.Append("REF ");
238    if(m_DevFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING)
239        Result.Append("SWVB ");
240    if(m_DevFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING)
241        Result.Append("HWVB ");
242    if(m_DevFlags & D3DCREATE_MIXED_VERTEXPROCESSING)
243        Result.Append("MXVB ");
244    if(m_DevFlags & D3DCREATE_PUREDEVICE)
245        Result.Append("PURE ");
246    Result.Append(s3d_CDrvD3d9Util::StrOfMutliSampleType(
247            m_PresentParam.MultiSampleType));
248    Result = s3d_CUtilStrUtil::Trim(Result);
249    return Result;
250}
251
252s3d_CDrvGfxOutPtr s3d_CDrvD3d9GfxEngCLOD::CreateOut(
253        s3d_CUtilStr_cr Info, s3d_CDrvCtx *Ctx,
254        s3d_CUtilStr_cr Device, int Prop,
255        int Left, int Top, int Width, int Height,
256        int Depth, int Frequency,
257        s3d_CUtilSnkChunk *Param)
258{
259    s3d_CDrvD3d9ParamPtr D3dParam = S3D_SYS_NEW s3d_CDrvD3d9Param;
260    D3dParam->Init(m_MsgHandler, Param);
261    return CreateOut(
262            Info, Ctx, Device, Prop, Top, Left, Width, Height,
263            Depth, Frequency, D3dParam);
264}
265
266s3d_CDrvGfxOutPtr s3d_CDrvD3d9GfxEngCLOD::CreateOut(
267        s3d_CUtilStr_cr Info, s3d_CDrvCtx *Ctx,
268        s3d_CUtilStr_cr Device, int Prop,
269        int Left, int Top, int Width, int Height,
270        int Depth, int Frequency, s3d_CUtilRecogBase *Param)
271{
272    s3d_CDrvD3d9ParamPtr D3dParam
273            = s3d_UtilRecogCastCheck<s3d_CDrvD3d9Param>(
274                    m_MsgHandler, Info, Param);
275    return CreateOut(
276            Info, Ctx, Device, Prop, Top, Left, Width, Height,
277            Depth, Frequency, D3dParam);
278}
279
280s3d_CDrvGfxOutPtr s3d_CDrvD3d9GfxEngCLOD::CreateOut(
281        s3d_CUtilStr_cr Info, s3d_CDrvCtx *Ctx,
282        s3d_CUtilStr_cr Device, int Prop,
283        int Left, int Top, int Width, int Height,
284        int Depth, int Frequency, s3d_CDrvD3d9Param *D3dParam)
285{
286    if(m_Ctx)
287        return 0; // Already created.
288
289    if(!D3dParam)
290        return 0;
291
292    m_Ctx = Ctx;
293    m_Prop = Prop;
294    m_D3dParam = D3dParam;
295
296    m_StateMgr.m_MsgHandler = m_MsgHandler;
297    m_StateMgr.m_Env = &m_Env;
298
299    if(!D3DXCheckVersion(D3D_SDK_VERSION, D3DX_SDK_VERSION))
300    {
301        s3d_CDrvD3d9Error e;
302        e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_eng.wrong_d3dx_version";
303        e.m_StdTempl = "D3D: Wrong d3d version. "
304                "Expecting D3D_SDK_VERSION=0x[1] "
305                "and D3DX_SDK_VERSION=0x[2]. ";
306        e.AddInfo(m_Info);
307        e.AddInfo(s3d_CUtilStrUtil::StrOfInt(
308                D3D_SDK_VERSION, 0, s3d_CUtilStrNum::Format_HexPadding));
309        e.AddInfo(s3d_CUtilStrUtil::StrOfInt(
310                D3DX_SDK_VERSION, 0, s3d_CUtilStrNum::Format_HexPadding));
311        s3d_UtilMsgReportError(m_MsgHandler, e);
312        return 0;
313    }
314
315    m_D3d.EmptyRef() = Direct3DCreate9(D3D_SDK_VERSION);
316    if(!m_D3d)
317    {
318        s3d_CDrvD3d9Error e;
319        e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_eng.dev_err";
320        e.m_StdTempl = "D3D: Error creating direct3d.";
321        e.AddInfo(m_Info);
322        s3d_UtilMsgReportError(m_MsgHandler, e);
323        return 0;
324    }
325
326#ifdef S3D_GENERAL_DEBUG
327    D3DXDebugMute(FALSE);
328#else
329    D3DXDebugMute(TRUE);
330#endif
331
332    // Create window.
333    m_CtxWin32 = s3d_UtilRttiCastCheck<s3d_CDrvWin32CtxInterf>(
334            m_MsgHandler, m_Info, Ctx);
335    if(!m_CtxWin32)
336    {
337        s3d_CDrvD3d9Error e;
338        e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_eng.no_context";
339        e.m_StdTempl = "D3D: No Win32 context.";
340        e.AddInfo(m_Info);
341        s3d_UtilMsgReportError(m_MsgHandler, e);
342        return 0;
343    }
344
345    // Init d3d environment
346    m_Env.Init(m_MsgHandler, D3dParam);
347
348    bool IsFullscreen = false;
349    bool IsFullscreenWindow = false;
350    if(m_Prop & s3d_CDrvGfxMgr::Prop_Fullscreen)
351    {
352        if(D3dParam->m_FakedFullscreen)
353            IsFullscreenWindow = true;
354        else
355            IsFullscreen = true;
356    }
357
358    bool NoStencil = false;
359    if(m_Prop & s3d_CDrvGfxMgr::Prop_NoStencil)
360        NoStencil = true;
361
362    m_Adapter = D3DADAPTER_DEFAULT;
363    if(!Device.IsEmpty())
364    {
365        int DevId = 0;
366        if(s3d_CUtilStrUtil::ParseInt(DevId, Device))
367            m_Adapter = DevId;
368        if(m_Adapter >= m_D3d->GetAdapterCount())
369        {
370            s3d_CDrvD3d9Error e;
371            e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_eng.invalid_device";
372            e.m_StdTempl = "D3D: No such d3d device ([1]).";
373            e.AddInfo(m_Info);
374            e.AddInfo(Device);
375            s3d_UtilMsgReportError(m_MsgHandler, e);
376           
377            m_Adapter = D3DADAPTER_DEFAULT;
378        }
379    }
380    D3DADAPTER_IDENTIFIER9 AdapterIdentifier;
381    DWORD Flags = 0;
382    S3D_DRV_D3D9_CHECK(
383            &m_Env, m_D3d->GetAdapterIdentifier(
384                m_Adapter, Flags, &AdapterIdentifier));
385    m_AdapterDesc = s3d_CUtilStrUtil::Trim(AdapterIdentifier.Description);
386
387    HMONITOR hMonitor = m_D3d->GetAdapterMonitor(m_Adapter);
388    m_CtxWin32->Win32CreateWindow(
389            m_MsgHandler, m_Info, 0, IsFullscreenWindow, hMonitor,
390            Top, Left, Width, Height, Depth, Frequency);
391    m_hWnd  = m_CtxWin32->Win32GetWndHandle();
392    if(!m_hWnd)
393    {
394        s3d_CUtilMsg e;
395        e.m_Code = "drv/imp/directx/d3d9/drv_d3d_eng.no_wnd_handle";
396        e.m_StdTempl = "No window created yet.";
397        e.AddInfo(Info);
398        s3d_UtilMsgReportError(m_MsgHandler, e);
399        return 0;
400    }
401
402    // Create d3d device.
403
404    m_BufWidth = -1;
405    m_BufHeight = -1;
406    m_BufColorAlphaBits = 0;
407    m_BufDepthBits = 0;
408    m_BufStencilBits = 0;
409    m_BufDepthBiasScale = 0;
410
411    m_DevType = D3DDEVTYPE_HAL;
412    if(D3dParam->m_RefDriver)
413        m_DevType = D3DDEVTYPE_REF;
414
415    HRESULT Result;
416    S3D_DRV_D3D9_CALLCHECK(
417            &m_Env, Result, m_D3d->GetDeviceCaps(
418                m_Adapter, m_DevType, &m_DevCaps));
419    if(FAILED(Result))
420        return 0;
421
422    m_DevFlags = 0;
423    if(!D3dParam->m_DisableFPUPreserve)
424        m_DevFlags |= D3DCREATE_FPU_PRESERVE;
425    if(D3dParam->m_PureDevice)
426        m_DevFlags |= D3DCREATE_PUREDEVICE;
427
428    int ReqVertShadVerMajor, ReqVertShadVerMinor;
429    s3d_CDrvD3d9ProgUtil::ParseMajorMinor(
430            ReqVertShadVerMajor, ReqVertShadVerMinor,
431            D3dParam->m_ReqVertShadVer.GetLen(),
432            D3dParam->m_ReqVertShadVer.GetChars());
433
434    if(s3d_CDrvD3d9ProgUtil::CompVer(
435        ReqVertShadVerMajor, ReqVertShadVerMinor,
436        D3DSHADER_VERSION_MAJOR(m_DevCaps.VertexShaderVersion),
437        D3DSHADER_VERSION_MINOR(m_DevCaps.VertexShaderVersion))
438            > 0)
439    {
440        m_DevFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
441        S3D_SYS_ASSERT(D3dParam->m_ForceHWVertexBuf == false);
442    }
443    else
444    {
445        if(D3dParam->m_ForceHWVertexBuf)
446            m_DevFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
447        else if(D3dParam->m_ForceSWVertexBuf)
448            m_DevFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
449        else
450            m_DevFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
451    }
452    m_SWVertProc = (m_DevFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING) != 0;
453
454    int AdapterDepth = Depth;
455    BOOL Windowed = FALSE;
456    if(!IsFullscreen || IsFullscreenWindow)
457    {
458        // Windowed device.
459
460        RECT ClientRect;
461        s3d_SysMemset(&ClientRect, 0, S3D_SYS_SIZEOFS(ClientRect));
462        GetClientRect(m_hWnd, &ClientRect);
463
464        Windowed = TRUE;
465        Width  = ClientRect.right  - ClientRect.left;
466        Height = ClientRect.bottom - ClientRect.top;
467
468        D3DDISPLAYMODE AdapterMode;
469        S3D_DRV_D3D9_CHECK(
470                &m_Env, m_D3d->GetAdapterDisplayMode(
471                    m_Adapter, &AdapterMode));
472       
473        AdapterDepth = s3d_CDrvD3d9Util::ColBitsOfFmt(AdapterMode.Format);
474        if(AdapterDepth > 16)
475            AdapterDepth = 32;
476    }
477    else
478    {
479        // Fullscreen device.
480    }
481
482    s3d_CDrvD3d9Enum Enum;
483    Enum.Enumerate(
484            m_MsgHandler, Info, m_MemPool, D3dParam,
485            m_D3d, IsFullscreen, NoStencil);
486 
487    s3d_CDrvD3d9EnumEntry EnumEntry;
488    if(!Enum.SearchEntry(
489            EnumEntry, m_Adapter, Prop, Width, Height,
490            AdapterDepth, Frequency, IsFullscreen || IsFullscreenWindow))
491    {
492        s3d_CDrvD3d9Error e;
493        e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_eng.no_valid_adapter";
494        e.m_StdTempl = "D3D: No valid adapter found.";
495        e.AddInfo(m_Info);
496        s3d_UtilMsgReportError(m_MsgHandler, e);
497        return 0;
498    }
499
500    Enum.GetBufferFmts(Depth, m_BackBufFmt, m_DepthStencilFmt, EnumEntry);
501
502    if(m_BackBufFmt == D3DFMT_UNKNOWN)
503    {
504        s3d_CDrvD3d9Error e;
505        e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_eng.backbuf_fmt_err";
506        e.m_StdTempl = "D3D: No valid backbuffer format found.";
507        e.AddInfo(m_Info);
508        s3d_UtilMsgReportError(m_MsgHandler, e);
509        return 0;
510    }
511   
512    if(m_DepthStencilFmt == D3DFMT_UNKNOWN)
513    {
514        s3d_CDrvD3d9Error e;
515        e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_eng.depthstencil_fmt_err";
516        e.m_StdTempl = "D3D: No valid depthstencil format found.";
517        e.AddInfo(m_Info);
518        s3d_UtilMsgReportError(m_MsgHandler, e);
519        return 0;
520    }
521
522    m_BufColorAlphaBits = s3d_CDrvD3d9Util::ColBitsOfFmt(m_BackBufFmt);
523    m_BufDepthBits = s3d_CDrvD3d9Util::DepthBitsOfFmt(m_DepthStencilFmt);
524    m_BufStencilBits = s3d_CDrvD3d9Util::StencilBitsOfFmt(m_DepthStencilFmt);
525    int ScaleZInt = s3d_CSysInt32u(-1) >> (32 - m_BufDepthBits);
526    m_BufDepthBiasScale = -1.f / s3d_SysFloatOfInt<float>(ScaleZInt);
527
528    const D3DMULTISAMPLE_TYPE s3d_MultiSampleType[] =
529    {
530        D3DMULTISAMPLE_NONE,
531        D3DMULTISAMPLE_NONE, //D3DMULTISAMPLE_NONMASKABLE
532        D3DMULTISAMPLE_2_SAMPLES,
533        D3DMULTISAMPLE_3_SAMPLES,
534        D3DMULTISAMPLE_4_SAMPLES,
535        D3DMULTISAMPLE_5_SAMPLES,
536        D3DMULTISAMPLE_6_SAMPLES,
537        D3DMULTISAMPLE_7_SAMPLES,
538        D3DMULTISAMPLE_8_SAMPLES,
539        D3DMULTISAMPLE_9_SAMPLES,
540        D3DMULTISAMPLE_10_SAMPLES,
541        D3DMULTISAMPLE_11_SAMPLES,
542        D3DMULTISAMPLE_12_SAMPLES,
543        D3DMULTISAMPLE_13_SAMPLES,
544        D3DMULTISAMPLE_14_SAMPLES,
545        D3DMULTISAMPLE_15_SAMPLES,
546        D3DMULTISAMPLE_16_SAMPLES,
547    };
548    int MaxMultiSample = S3D_SYS_ARRAYCNTS(s3d_MultiSampleType) - 1;
549    int WantMultiSample = D3dParam->m_MultiSample;
550    if(WantMultiSample == 0)
551        WantMultiSample = MaxMultiSample;
552    else if(WantMultiSample > 0)
553        s3d_SysSetToMin(WantMultiSample, MaxMultiSample);
554   
555    D3DMULTISAMPLE_TYPE MultiSampleType = D3DMULTISAMPLE_NONE;
556    DWORD MultiSampleQuality = 0;
557    int iMultiSample;
558    for(iMultiSample = WantMultiSample; WantMultiSample >= 0; iMultiSample--)
559    {
560        D3DMULTISAMPLE_TYPE WantMultiSampleType
561                = s3d_MultiSampleType[iMultiSample];
562        HRESULT Result;
563        S3D_DRV_D3D9_HRESCALL(
564                &m_Env, Result, m_D3d->CheckDeviceMultiSampleType(
565                    m_Adapter, m_DevType, m_BackBufFmt, Windowed,
566                    WantMultiSampleType, &MultiSampleQuality));
567        if(FAILED(Result))
568            continue;
569
570        S3D_DRV_D3D9_HRESCALL(
571                &m_Env, Result, m_D3d->CheckDeviceMultiSampleType(
572                    m_Adapter, m_DevType, m_DepthStencilFmt, Windowed,
573                    WantMultiSampleType, 0));
574        if(FAILED(Result))
575            continue;
576
577        MultiSampleType = WantMultiSampleType;
578        break;
579    }
580    // The valid range is between zero and one less than the level
581    // returned by pQualityLevels used by CheckDeviceMultiSampleType().
582    if(MultiSampleQuality > 0)
583        MultiSampleQuality = MultiSampleQuality - 1;
584
585    m_UseMSAA = (MultiSampleType != D3DMULTISAMPLE_NONE);
586
587    // Finally create device
588    int RefreshRate = Frequency;
589    if(Windowed || Frequency < 0)
590        RefreshRate = 0;
591    else if(RefreshRate > EnumEntry.m_GfxEnumEntry.m_Freq )
592        RefreshRate = EnumEntry.m_GfxEnumEntry.m_Freq;
593
594    UINT PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
595    if(m_Prop & s3d_CDrvGfxMgr::Prop_Synch)
596        PresentationInterval = D3DPRESENT_INTERVAL_ONE;
597
598    s3d_SysMemset(&m_PresentParam, 0, S3D_SYS_SIZEOFS(m_PresentParam));
599    m_PresentParam.BackBufferWidth = Width;
600    m_PresentParam.BackBufferHeight = Height;
601    m_PresentParam.BackBufferFormat = m_BackBufFmt;
602    m_PresentParam.BackBufferCount = 1;
603    if(D3dParam->m_UseTrippleBuffering)
604        m_PresentParam.BackBufferCount = 2;
605    m_PresentParam.MultiSampleType = MultiSampleType;
606    m_PresentParam.MultiSampleQuality = MultiSampleQuality;
607    m_PresentParam.SwapEffect = D3DSWAPEFFECT_DISCARD;
608/*
609    if((m_Caps.Caps3 & D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD) == 0)
610        m_PresentParam.SwapEffect = D3DSWAPEFFECT_COPY;
611*/
612    m_PresentParam.hDeviceWindow = m_hWnd;
613    m_PresentParam.Windowed = Windowed;
614    m_PresentParam.EnableAutoDepthStencil = true;
615    m_PresentParam.AutoDepthStencilFormat = m_DepthStencilFmt;
616    //StretchRects does not support discardable depth/stencil surfaces.
617    m_PresentParam.Flags = 0;//D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
618    m_PresentParam.FullScreen_RefreshRateInHz = RefreshRate;
619    m_PresentParam.PresentationInterval = PresentationInterval;
620
621//Force NVIDIA PerfHUD
622#if 0
623    m_DevType = D3DDEVTYPE_REF;
624    S3D_DRV_D3D9_HRESCALL(
625            &m_Env, m_Adapter, m_D3d->GetAdapterCount() - 1);
626    Flags = 0;
627    S3D_DRV_D3D9_CHECK(
628            &m_Env, m_D3d->GetAdapterIdentifier(
629                m_Adapter, Flags, &AdapterIdentifier));
630    m_AdapterDesc = s3d_CUtilStrUtil::Trim(AdapterIdentifier.Description);
631    m_DevFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
632#endif
633
634    D3DPERF_SetOptions(D3dParam->m_PixEnabled ? 0 : 1);
635
636    s3d_CDrvD3d9Device D3dDev;
637    S3D_DRV_D3D9_CHECK(
638            &m_Env, m_D3d->CreateDevice(
639                m_Adapter, m_DevType, m_hWnd, m_DevFlags, &m_PresentParam,
640                &D3dDev.EmptyRef()));
641    if(!D3dDev)
642    {
643        s3d_CDrvD3d9Error e;
644        e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_eng.cannot_create_device";
645        e.m_StdTempl = "D3D: Could not create Direct3D device.";
646        e.AddInfo(m_Info);
647        s3d_UtilMsgReportError(m_MsgHandler, e);
648        return 0;
649    }
650   
651    S3D_DRV_D3D9_CALLCHECK(
652            &m_Env, Result, D3dDev->GetDeviceCaps(&m_DevCaps));
653    if(FAILED(Result))
654        return 0;
655
656    S3D_DRV_D3D9_CHECK(
657            &m_Env, D3dDev->GetSwapChain(
658                0, &m_SwapChain.EmptyRef()));
659    if(!m_SwapChain)
660        return 0;
661
662    m_D3dDev = D3dDev;
663    m_StateMgr.m_D3dDev = D3dDev;
664
665    m_D3dCtx = S3D_SYS_NEW s3d_CDrvD3d9Ctx;
666    m_D3dCtx->m_D3d = m_D3d;
667    m_D3dCtx->m_D3dDev = m_D3dDev;
668    m_D3dCtx->m_BackBufFmt = m_BackBufFmt;
669    m_D3dCtx->m_MultiSampleType = m_PresentParam.MultiSampleType;
670    m_D3dCtx->m_MultiSampleQuality = m_PresentParam.MultiSampleQuality;
671    m_D3dCtx->m_Adapter = m_Adapter;
672    m_D3dCtx->m_DevType = m_DevType;
673    m_D3dCtx->m_Windowed = Windowed == TRUE;
674
675    m_D3dCtx->m_MsgHandler = m_MsgHandler;
676    m_D3dCtx->m_MemPool = m_MemPool;
677    m_D3dCtx->m_Env = &m_Env;
678    m_D3dCtx->m_D3dParam = D3dParam;
679
680    // Texture stuff
681    InitTexturing();
682
683    m_ParamBlk.Reset();
684    D3DXMatrixIdentity(&m_MatProj);
685    m_MatProjDirty = false;
686    m_Viewport.X = -1;
687    m_Viewport.Y = -1;
688    m_Viewport.Width = -1;
689    m_Viewport.Height = -1;
690    m_Viewport.MinZ = 0;
691    m_Viewport.MaxZ = 1;
692    m_ScissorRect.left = -1;
693    m_ScissorRect.top = -1;
694    m_ScissorRect.right = -1;
695    m_ScissorRect.bottom = -1;
696    m_CurScissorEnabled = false;
697
698    CalcProjOffs(
699            m_MainProjOffsX, m_MainProjOffsY,
700            m_PresentParam.BackBufferWidth, m_PresentParam.BackBufferHeight);
701    m_CurProjOffsX = m_MainProjOffsX;
702    m_CurProjOffsY = m_MainProjOffsY;
703
704    // Render to texture
705    InitRenderToTex();
706
707    // Light
708    InitLighting();
709
710    // Init all managers
711
712    s3d_CDrvD3d9ProgCtxPtr ProgCtx = S3D_SYS_NEW s3d_CDrvD3d9ProgCtx;
713    ProgCtx->m_MsgHandler = m_MsgHandler;
714    ProgCtx->m_MemPool = m_MemPool;
715    ProgCtx->m_ResMgr = m_ResMgr;
716    ProgCtx->m_AtomMgr = m_AtomMgr;
717    ProgCtx->m_UnivProgSuppl = m_UnivProgSuppl;
718    ProgCtx->m_UnivProgGivenSuppl = m_UnivProgGivenSuppl;
719    ProgCtx->m_Env = &m_Env;
720    ProgCtx->m_D3dParam = m_D3dParam;
721    ProgCtx->m_D3dDev = m_D3dDev;
722    ProgCtx->m_MaxVS = m_DevCaps.VertexShaderVersion;
723    ProgCtx->m_MaxPS = m_DevCaps.PixelShaderVersion;
724    ProgCtx->m_MaxLightCnt = m_MaxLightCnt;
725    ProgCtx->m_MaxAttrCnt = m_MaxAttrCnt;
726    ProgCtx->m_MaxSampCnt = m_MaxSampCnt;
727
728    m_ProgMgr = S3D_SYS_NEW s3d_CDrvD3d9ProgMgr(ProgCtx);
729
730    s3d_CSysIntps VertIdxLimit = m_DevCaps.MaxVertexIndex + 1;
731    m_BufMgr = S3D_SYS_NEW s3d_CDrvD3d9BufMgr(
732            m_MsgHandler, m_ProgMgr, m_Env, D3dParam, VertIdxLimit, m_D3dDev);
733
734    m_TexMgr = S3D_SYS_NEW s3d_CDrvD3d9TexMgr(m_D3dCtx);
735
736    m_VisibMgr = S3D_SYS_NEW s3d_CDrvD3d9VisibMgr(
737            m_MsgHandler, m_Env, D3dParam, m_D3dDev);
738
739    m_ParamStateProg.Done();
740    m_ParamStateFFP.Done();
741
742    SetDefaultState();
743    InitDevCaps();
744
745    m_FrmIdx = 0;
746
747    m_FlushEvent.Init(&m_Env, m_D3dDev);
748    m_IdxFlushCnt = 0;
749
750    return S3D_SYS_NEW s3d_CDrvD3d9GfxOut(this);
751}
752
753s3d_CUtilSnkChunkPtr s3d_CDrvD3d9GfxEngCLOD::GetDefaultOutParam()
754{
755    return m_DefaultOutParam;
756}
757
758void s3d_CDrvD3d9GfxEngCLOD::RegisterNotifCtxChanged(
759        s3d_CUtilNotifRecip *Recip)
760{
761    m_NotifMgrCtx.Register(Recip);
762}
763
764void s3d_CDrvD3d9GfxEngCLOD::Alter(
765        s3d_CUtilStr_cr Info,
766        s3d_CUtilStr_cr Device, int Prop,
767        int Left, int Top, int Width, int Height,
768        int Depth, int Frequency, s3d_CUtilSnkChunk *Param)
769{
770    s3d_CDrvD3d9ParamPtr D3dParam = S3D_SYS_NEW s3d_CDrvD3d9Param;
771    D3dParam->Init(m_MsgHandler, Param);
772    Alter(Info, Device, Prop, Top, Left, Width, Height,
773            Depth, Frequency, D3dParam);
774}
775
776void s3d_CDrvD3d9GfxEngCLOD::Alter(
777        s3d_CUtilStr_cr Info,
778        s3d_CUtilStr_cr Device, int Prop,
779        int Left, int Top, int Width, int Height,
780        int Depth, int Frequency,
781        s3d_CDrvD3d9Param *D3dParam)
782{
783    HMONITOR hMonitor = 0;
784    if(m_D3d)
785        hMonitor = m_D3d->GetAdapterMonitor(m_Adapter);
786    s3d_CUtilSnkChunkPtr WndParam;
787    bool IsFullscreenWindow = false;
788    if(m_CtxWin32)
789    {
790        m_CtxWin32->Win32AlterWindow(
791                m_MsgHandler, Info, WndParam, IsFullscreenWindow, hMonitor,
792                    Top, Left, Width, Height, Depth, Frequency);
793    }
794
795    m_PresentParam.Windowed = ((Prop & s3d_CDrvGfxMgr::Prop_Fullscreen) == 0);
796
797    UINT PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
798    if(Prop & s3d_CDrvGfxMgr::Prop_Synch)
799        PresentationInterval = D3DPRESENT_INTERVAL_ONE;
800
801    m_PresentParam.BackBufferWidth = Width;
802    m_PresentParam.BackBufferHeight = Height;
803
804    ResetDevice();
805
806    m_Prop = Prop;
807}
808
809void s3d_CDrvD3d9GfxEngCLOD::UserFunc(s3d_CUtilCoStr Func)
810{
811}
812
813bool s3d_CDrvD3d9GfxEngCLOD::HasCap(
814        s3d_CSysIntps CapLen, const s3d_CSysChar *CapStart) const
815{
816    if(s3d_CUtilRawStrUtil::IsEqual(CapLen, CapStart,
817            S3D_DRV_D3D9_ENG_CAP_D3D))
818        return true;
819    if(s3d_CUtilRawStrUtil::IsEqual(CapLen, CapStart,
820            S3D_DRV_D3D9_ENG_CAP_D3D9))
821        return true;
822    if(s3d_CUtilRawStrUtil::IsEqual(CapLen, CapStart,
823            S3D_DRV_GFX_CAP_RENDER_TEX_COLORALPHA))
824        return true;
825    if(s3d_CUtilRawStrUtil::IsEqual(CapLen, CapStart,
826            S3D_DRV_GFX_CAP_RENDER_TEX_DEPTH))
827        return m_HasNvDepthTex || m_CanRenderDepth;
828    if(s3d_CUtilRawStrUtil::IsEqual(CapLen, CapStart,
829            S3D_DRV_GFX_CAP_STENCIL_TWOSIDED))
830        return ((m_DevCaps.StencilCaps & D3DSTENCILCAPS_TWOSIDED) != 0);
831    if(s3d_CUtilRawStrUtil::IsEqual(CapLen, CapStart,
832            S3D_DRV_GFX_CAP_STENCIL_WRAP))
833        return true;
834
835    return false;
836}
837
838s3d_CDrvGfxStat *s3d_CDrvD3d9GfxEngCLOD::GetStat()
839{
840    return &m_Stat;
841}
842
843int s3d_CDrvD3d9GfxEngCLOD::GetSampCnt() const
844{
845    return m_MaxSampCnt;
846}
847
848void s3d_CDrvD3d9GfxEngCLOD::SnapTexSize(
849        int &Width, int &Height, int &Depth, int TexProp, int SnapProp)
850{
851    bool Snap = true;
852    bool UseVol = false;
853    bool UseCube = false;
854
855    int MinWidth = (1 << m_MinLbTexWidth);
856    int MaxWidth = (1 << m_MaxLbTexWidth);
857    int MinHeight = (1 << m_MinLbTexHeight);
858    int MaxHeight = (1 << m_MaxLbTexHeight);
859    int MinDepth = (1 << m_MinLbVolTexExt);
860    int MaxDepth = (1 << m_MaxLbVolTexExt);
861
862    bool WantMipMap = false;
863    if((TexProp & TexProp_Mipmap) != 0)
864        WantMipMap = true;
865    bool CanRect = false;
866    bool CanNPOT2 = false;
867    if((m_DevCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) != 0)
868        CanRect = true;
869    if(!CanRect && (m_DevCaps.TextureCaps & D3DPTEXTURECAPS_POW2) == 0)
870        CanNPOT2 = true;
871
872    if((TexProp & TexProp_RestrUsage) != 0)
873    {
874        if(CanRect || CanNPOT2)
875            Snap = false;
876    }
877    else if((TexProp & TexProp_Volume) != 0)
878    {
879        UseVol = true;
880        Snap = true;
881        MinWidth = MinDepth;
882        MaxWidth = MaxDepth;
883        MinHeight = MinDepth;
884        MaxHeight = MaxDepth;
885        MinHeight = MinDepth;
886        MaxHeight = MaxDepth;
887        if((m_DevCaps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2) == 0)
888            Snap = false;
889    }
890    else if((TexProp & TexProp_Cube) != 0)
891    {
892        UseCube = true;
893        Snap = true;
894        if((m_DevCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) == 0)
895            Snap = false;
896    }
897    else
898    {
899        if(CanNPOT2)
900            Snap = false;
901        else if(CanRect && !WantMipMap)
902            Snap = false;
903    }
904
905/*
906    if((TexProp & TexProp_Depth) != 0 || (TexProp & TexProp_RenderTarget) != 0)
907    {
908        Snap = false;
909        Width = 512;
910        Height = 512;
911    }
912*/
913
914    // NVIDIA depthtex
915    if((TexProp & TexProp_Depth) != 0 && m_HasNvDepthTex)
916    {
917//        Width = 256;
918//        Height = 256;
919        Snap = false;
920    }
921
922    if(Snap)
923    {
924        int WidthLb, HeightLb, DepthLb;
925        if(SnapProp & TexSnap_PreferDown)
926        {
927            WidthLb = s3d_CDrvUtilGfxUtil::BinLogDownInt(Width);
928            HeightLb = s3d_CDrvUtilGfxUtil::BinLogDownInt(Height);
929            DepthLb = s3d_CDrvUtilGfxUtil::BinLogDownInt(Depth);
930        }
931        else
932        {
933            WidthLb = s3d_CDrvUtilGfxUtil::BinLogUpInt(Width);
934            HeightLb = s3d_CDrvUtilGfxUtil::BinLogUpInt(Height);
935            DepthLb = s3d_CDrvUtilGfxUtil::BinLogUpInt(Depth);
936        }
937        Width = (1 << WidthLb);
938        Height = (1 << HeightLb);
939        Depth = (1 << DepthLb);
940    }
941
942    s3d_SysSetToMax(Width, MinWidth);
943    s3d_SysSetToMax(Height, MinHeight);
944    s3d_SysSetToMin(Width, MaxWidth);
945    s3d_SysSetToMin(Height, MaxHeight);
946   
947    if(UseVol)
948    {
949        s3d_SysSetToMax(Depth, MinDepth);
950        s3d_SysSetToMin(Depth, MaxDepth);
951    }
952    else
953        Depth = 1;
954
955    if(UseCube)
956    {
957        int Ext = s3d_SysMax(Width, Height);
958        Width = Ext;
959        Height = Ext;
960    }
961
962    s3d_SysSetToMax(Width, 1);
963    s3d_SysSetToMax(Height, 1);
964    s3d_SysSetToMax(Depth, 1);
965}
966
967s3d_CDrvGfxTexPtr s3d_CDrvD3d9GfxEngCLOD::CreateTexDirect(
968        s3d_CUtilStr_cr Info, int TexProp,
969        int Width, int Height, int Depth)
970{
971    if(m_TexMgr)
972        return m_TexMgr->CreateTexDirect(Info, TexProp, Width, Height, Depth);
973    return 0;
974}
975
976s3d_CDrvGfxTexPtr s3d_CDrvD3d9GfxEngCLOD::CreateTexStream(
977        s3d_CUtilStr_cr Info, int TexProp,
978        s3d_CUtilStream *Stream)
979{
980    if(m_TexMgr)
981        return m_TexMgr->CreateTexStream(Info, TexProp, Stream);
982    return 0;
983}
984
985s3d_CDrvGfxTexPtr s3d_CDrvD3d9GfxEngCLOD::CreateTexVideo(
986        s3d_CUtilStr_cr Info, int TexProp,
987        s3d_CDrvVideoPlayer *VideoPlayer)
988{
989    if(m_TexMgr)
990        return m_TexMgr->CreateTexVideo(Info, TexProp, VideoPlayer);
991    return 0;
992}
993
994s3d_CDrvGfxTexPtr s3d_CDrvD3d9GfxEngCLOD::CreateTexIdent(
995        s3d_CUtilStr_cr Info, int TexProp,
996        s3d_CUtilStr_cr Ident)
997{
998    return 0;
999}
1000
1001s3d_CDrvGfxTexPtr s3d_CDrvD3d9GfxEngCLOD::CreateTexUser(
1002        s3d_CUtilStr_cr Info, int TexProp,
1003        s3d_CCompObj *UserObj)
1004{
1005    return 0;
1006}
1007
1008void s3d_CDrvD3d9GfxEngCLOD::SetSampTex(
1009        int Samp, s3d_CDrvGfxTex *Tex)
1010{
1011    if(Samp < 0)
1012        return;
1013    if(Samp >= m_MaxSampCnt)
1014        return;
1015
1016    s3d_CDrvD3d9TexObjBase *TexImpl
1017            = s3d_UtilRecogCastSilent<s3d_CDrvD3d9TexObjBase>(Tex);
1018   
1019    if(m_WantSampTexArray[Samp] != TexImpl)
1020    {
1021        s3d_SysSetToMax(m_SampMaxWantCnt, Samp + 1);
1022        m_WantSampTexArray[Samp] = TexImpl;
1023    }
1024}
1025
1026void s3d_CDrvD3d9GfxEngCLOD::SetSampTexElseNone(
1027        int SampStart)
1028{
1029    if(SampStart < 0)
1030        return;
1031    if(SampStart >= m_MaxSampCnt)
1032        return;
1033
1034    int iSamp = SampStart;
1035    int SampEnd = s3d_SysMax(m_ParamBlk.m_SampMaxUsedCnt, m_SampMaxWantCnt);
1036    while(iSamp < SampEnd)
1037    {
1038        if(m_WantSampTexArray[iSamp])
1039        {
1040            m_WantSampTexArray[iSamp] = 0;
1041            s3d_SysSetToMax(m_SampMaxWantCnt, iSamp + 1);
1042        }
1043        iSamp++;
1044    }
1045}
1046
1047void s3d_CDrvD3d9GfxEngCLOD::SetSampMode(
1048        int Samp, int SampMode)
1049{
1050    if(Samp < 0)
1051        return;
1052    if(Samp >= m_MaxSampCnt)
1053        return;
1054
1055    if(m_SampModeArray[Samp] == SampMode)
1056        return;
1057
1058    m_SampModeArray[Samp] = SampMode;
1059    s3d_SysSetToMax(m_SampMaxWantCnt, Samp + 1);
1060}
1061
1062s3d_CDrvGfxProgPtr s3d_CDrvD3d9GfxEngCLOD::CreateProg(
1063        s3d_CUtilNotifGather *NotifGather, s3d_CUtilSnkChunk *Desc)
1064{
1065    if(!m_D3dDev)
1066        return 0;
1067    if(!Desc)
1068        return 0;
1069    if(!m_ProgMgr)
1070        return 0;
1071    return m_ProgMgr->CreateProg(NotifGather, Desc);
1072}
1073
1074void s3d_CDrvD3d9GfxEngCLOD::GetMainSize(int &Width, int &Height) const
1075{
1076    if(!m_D3dDev)
1077    {
1078        Width = 0;
1079        Height = 0;
1080        return;
1081    }
1082
1083    Width = m_PresentParam.BackBufferWidth;
1084    Height = m_PresentParam.BackBufferHeight;
1085}
1086
1087int s3d_CDrvD3d9GfxEngCLOD::GetMainColorAlphaBits() const
1088{
1089    if(!m_D3dDev)
1090        return 0;
1091
1092    return m_BufColorAlphaBits;
1093}
1094
1095void s3d_CDrvD3d9GfxEngCLOD::SetGamma(
1096        s3d_CUtilVec3f_cr Gamma)
1097{
1098    if(!m_D3dDev)
1099        return;
1100
1101    float RFac = 1.0f / (255.0f * Gamma.m_x);
1102    float GFac = 1.0f / (255.0f * Gamma.m_y);
1103    float BFac = 1.0f / (255.0f * Gamma.m_z);
1104    D3DGAMMARAMP GammaRamp;
1105    if(m_D3dParam->m_EnableGamma2x2)
1106    {
1107        float Exp = 0.4545f;
1108        int i;
1109        for(i = 0; i < 256; i++)
1110        {
1111            float R = s3d_SysFloatOfInt<float>(i) * RFac;
1112            float G = s3d_SysFloatOfInt<float>(i) * GFac;
1113            float B = s3d_SysFloatOfInt<float>(i) * BFac;
1114            float EffR = s3d_SysPow(R, Exp);
1115            float EffG = s3d_SysPow(G, Exp);
1116            float EffB = s3d_SysPow(B, Exp);
1117            GammaRamp.red[i] = s3d_SysIntOfFloatCoarse(EffR * 65535.0f);
1118            GammaRamp.green[i] = s3d_SysIntOfFloatCoarse(EffG * 65535.0f);
1119            GammaRamp.blue[i] = s3d_SysIntOfFloatCoarse(EffB * 65535.0f);
1120        }
1121    }
1122    else
1123    {
1124        int i;
1125        for(i = 0; i < 256; i++)
1126        {
1127            float R = s3d_SysFloatOfInt<float>(i) * RFac;
1128            float G = s3d_SysFloatOfInt<float>(i) * GFac;
1129            float B = s3d_SysFloatOfInt<float>(i) * BFac;
1130            GammaRamp.red[i] = s3d_SysIntOfFloatCoarse(R * 65535.0f);
1131            GammaRamp.green[i] = s3d_SysIntOfFloatCoarse(G * 65535.0f);
1132            GammaRamp.blue[i] = s3d_SysIntOfFloatCoarse(B * 65535.0f);
1133        }
1134    }
1135
1136    if((!m_PresentParam.Windowed
1137            && (m_DevCaps.Caps2 & D3DCAPS2_FULLSCREENGAMMA))
1138        || (m_DevCaps.Caps3 & D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION))
1139    {
1140        if(m_DevCaps.Caps2 & D3DCAPS2_FULLSCREENGAMMA)
1141        {
1142            DWORD Flags = D3DSGR_NO_CALIBRATION;
1143            if(m_DevCaps.Caps2 & D3DCAPS2_CANCALIBRATEGAMMA)
1144                Flags = D3DSGR_CALIBRATE;
1145            S3D_DRV_D3D9_CALL(
1146                    &m_Env, m_D3dDev->SetGammaRamp(
1147                        0, Flags, &GammaRamp));
1148        }
1149    }
1150    else
1151    {
1152/*
1153        HDC hDC = ::GetDC(m_hWnd);
1154        BOOL Ok = ::SetDeviceGammaRamp(
1155                hDC, reinterpret_cast<LPVOID>(&GammaRamp));
1156        ::ReleaseDC(m_hWnd, hDC);
1157*/
1158    }
1159}
1160
1161void s3d_CDrvD3d9GfxEngCLOD::Present()
1162{
1163    EndRender();
1164
1165    if(!m_SwapChain)
1166        return;
1167
1168    DWORD Flags = 0;
1169    //Flags |= D3DPRESENT_DONOTWAIT;
1170    //if(m_Caps.Caps3 & D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION)
1171    //    Flags |= D3DPRESENT_LINEAR_CONTENT;
1172    HRESULT Result = m_SwapChain->Present(0, 0, 0, 0, Flags);
1173    if(Result == D3DERR_DEVICELOST)
1174    {
1175        s3d_CUtilMsg m;
1176        m.m_Code = "drv/imp/directx/d3d9/drv_d3d9_eng.device_lost.";
1177        m.m_StdTempl  = "D3D: Lost device \"[1]\".";
1178        m.AddInfo(m_Info);
1179        m.AddInfo(m_AdapterDesc);
1180        //s3d_UtilMsgReportNote(m_MsgHandler, m);
1181       
1182        ResetDevice();
1183
1184        m_NotifMgrCtx.PerformNotif();
1185    }
1186    else if(Result == E_FAIL)
1187    {
1188        // Ignore
1189    }
1190    else
1191    {
1192        S3D_DRV_D3D9_CHECKHRES(&m_Env, Result);
1193    }
1194 
1195    if(m_Ctx && m_CtxWin32)
1196        m_CtxWin32->Win32InformGfxSwapped();
1197
1198    m_FrmIdx++;
1199}
1200
1201void s3d_CDrvD3d9GfxEngCLOD::GetCurTargetSize(int &Width, int &Height) const
1202{
1203    if(!m_D3dDev)
1204    {
1205        Width = 0;
1206        Height = 0;
1207        return;
1208    }
1209
1210    Width = m_BufWidth;
1211    Height = m_BufHeight;
1212}
1213
1214void s3d_CDrvD3d9GfxEngCLOD::EndRender()
1215{
1216    if(m_BufWidth >= 0 && m_BufHeight >= 0)
1217    {
1218        if(m_DestCnt >= 0)
1219            EndRenderTex();
1220        else
1221            EndRenderMain();
1222    }
1223}
1224
1225void s3d_CDrvD3d9GfxEngCLOD::BeginRenderMain(
1226        int DestProp,
1227        s3d_CDrvGfxClearParam_cr ClearParam,
1228        s3d_CDrvGfxOut *GfxOut)
1229{
1230    EndRender();
1231
1232    if(!m_D3dDev)
1233        return;
1234
1235    m_BufWidth = m_PresentParam.BackBufferWidth;
1236    m_BufHeight = m_PresentParam.BackBufferHeight;
1237
1238    if(m_PresentParam.Windowed)
1239    {
1240        RECT ClientRect;
1241        s3d_SysMemset(&ClientRect, 0, S3D_SYS_SIZEOFS(ClientRect));
1242        GetClientRect(m_hWnd, &ClientRect);
1243
1244        int Width  = ClientRect.right  - ClientRect.left;
1245        int Height = ClientRect.bottom - ClientRect.top;
1246        if(m_BufWidth != Width || m_BufHeight != Height)
1247        {
1248            if(Width > 0 && Height > 0)
1249            {
1250                s3d_CUtilMsg m;
1251                m.m_Code  =
1252                        "drv/imp/directx/d3d9/drv_d3d9_eng.new_client_size";
1253                m.m_StdTempl  = "D3D: "
1254                    "New client size [2]x[3] for \"[1]\".";
1255                m.AddInfo(m_Info);
1256                m.AddInfo(m_AdapterDesc);
1257                m.AddInfo(s3d_CUtilStrUtil::StrOfInt(Width));
1258                m.AddInfo(s3d_CUtilStrUtil::StrOfInt(Height));
1259                s3d_UtilMsgReportNote(m_MsgHandler, m);
1260
1261                m_PresentParam.BackBufferWidth = Width;
1262                m_PresentParam.BackBufferHeight = Height;
1263                m_BufWidth = Width;
1264                m_BufHeight = Height;
1265             
1266                ResetDevice();
1267
1268                CalcProjOffs(m_MainProjOffsX, m_MainProjOffsY, Width, Height);
1269
1270                m_NotifMgrCtx.PerformNotif();
1271            }
1272        }
1273    }
1274
1275    SetProjOffs(m_MainProjOffsX, m_MainProjOffsY);
1276    SetViewRect(1);
1277    RestoreRenderTargets();
1278
1279    S3D_DRV_D3D9_CHECK(
1280            &m_Env, m_D3dDev->BeginScene());
1281
1282    Clear(ClearParam);
1283}
1284
1285void s3d_CDrvD3d9GfxEngCLOD::EndRenderMain()
1286{
1287    if(!m_D3dDev)
1288        return;
1289
1290    m_BufWidth = -1;
1291    m_BufHeight = -1;
1292
1293    S3D_DRV_D3D9_CHECK(
1294            &m_Env, m_D3dDev->EndScene());
1295}
1296
1297void s3d_CDrvD3d9GfxEngCLOD::BeginRenderTex(
1298        int DestProp,         
1299        s3d_CDrvGfxClearParam_cr ClearParam,
1300        int Width, int Height,
1301        s3d_CSysIntps DestCnt, const s3d_CDrvGfxDest *DestArray)
1302{
1303    EndRender();
1304
1305    //S3D_DRV_D3D9_DBGPRINTF("************* BeginRenderTex\n");
1306    if(!m_D3dDev)
1307        return;
1308    if(DestCnt < 0)
1309        return;
1310    if(!DestArray)
1311        return;
1312
1313    m_BufWidth = Width;
1314    m_BufHeight = Height;
1315   
1316    float ProjOffsX, ProjOffsY;
1317    CalcProjOffs(ProjOffsX, ProjOffsY, Width, Height);
1318    SetProjOffs(ProjOffsX, ProjOffsY);
1319    SetViewRect(1);
1320
1321    s3d_CSysIntps nDest = s3d_SysMin(m_MaxSimRTCnt, DestCnt);
1322    if(m_UseMSAA && (DestProp & DestProp_Antialias))
1323        BeginRenderTexMSAA(Width, Height, nDest, DestArray);
1324    else
1325        BeginRenderTexStd(Width, Height, nDest, DestArray);
1326   
1327    m_DestProp = DestProp;
1328
1329    if(DestCnt > S3D_SYS_ARRAYCNTS(m_DestArray))
1330        DestCnt = S3D_SYS_ARRAYCNTS(m_DestArray);
1331    m_DestCnt = DestCnt;
1332    s3d_CSysIntps iDest;
1333    for(iDest = 0; iDest < DestCnt; iDest++)
1334        m_DestArray[iDest] = DestArray[iDest];
1335
1336    S3D_DRV_D3D9_CALL(
1337            &m_Env, m_D3dDev->BeginScene());
1338
1339    Clear(ClearParam);
1340}
1341
1342void s3d_CDrvD3d9GfxEngCLOD::EndRenderTex()
1343{
1344    //S3D_DRV_D3D9_DBGPRINTF("************* EndRenderTex\n");
1345    if(!m_D3dDev)
1346        return;
1347
1348    S3D_DRV_D3D9_CHECK(
1349            &m_Env, m_D3dDev->EndScene());
1350
1351    if(m_UseMSAA && (m_DestProp & DestProp_Antialias))
1352        EndRenderTexMSAA();
1353    else
1354        EndRenderTexStd();
1355
1356    m_DestProp = 0;
1357    m_DestCnt = -1;
1358    m_BufWidth = -1;
1359    m_BufHeight = -1;
1360}
1361
1362void s3d_CDrvD3d9GfxEngCLOD::CopyIntoTex(
1363        int Width, int Height, int SrcX, int SrcY,
1364        s3d_CSysIntps DestCnt, const s3d_CDrvGfxDest *DestArray)
1365{
1366    if(!m_D3dDev)
1367        return;
1368    if(DestCnt < 1)
1369        return;
1370
1371    s3d_CDrvD3d9TexObjBase *TexImpl
1372            = s3d_UtilRecogCastSilent<s3d_CDrvD3d9TexObjBase>(
1373                    DestArray[0].m_Tex);
1374    if(!TexImpl)
1375        return;
1376   
1377    s3d_CDrvD3d9Surf DestSurf;
1378    S3D_DRV_D3D9_CHECK(
1379            &m_Env, TexImpl->GetRenderTarget(DestSurf, &DestArray[0]));
1380    if(!DestSurf)
1381        return;
1382
1383    const RECT Rect = {SrcX, SrcY, Width, Height};
1384    HRESULT Result;
1385    S3D_DRV_D3D9_CALLCHECK(
1386            &m_Env, Result, m_D3dDev->StretchRect(
1387                m_CurSurfColArray[0], &Rect, DestSurf, &Rect, D3DTEXF_LINEAR));
1388    if(FAILED(Result))
1389    {
1390        const PALETTEENTRY *PaletteEntry = 0;
1391        DWORD ColorKey = 0;
1392        S3D_DRV_D3D9_CHECK(
1393                &m_Env, D3DXLoadSurfaceFromSurface(
1394                    DestSurf, PaletteEntry, &Rect,
1395                    m_CurSurfColArray[0], PaletteEntry, &Rect,
1396                    D3DX_FILTER_LINEAR, ColorKey));
1397    }
1398}
1399
1400void s3d_CDrvD3d9GfxEngCLOD::StoreScreenshot()
1401{
1402    if(m_Ctx && m_CtxWin32)
1403        m_CtxWin32->Win32StoreScreenshot();
1404}
1405
1406void s3d_CDrvD3d9GfxEngCLOD::SetViewRect(
1407        s3d_CUtilTranslScale2f_cr ViewRect)
1408{
1409    if(!m_D3dDev)
1410        return;
1411
1412    // Use signed temporary vars for "< 0" comparsions since D3DVIEWPORT
1413    // uses unsigned member vars.
1414    int ViewPortX, ViewPortY, ViewPortWidth, ViewPortHeight;
1415    ViewPortX = s3d_SysIntOfFloatNearest(
1416            ViewRect.m_Transl.m_x * m_BufWidth);
1417    ViewPortY = s3d_SysIntOfFloatNearest(
1418            ViewRect.m_Transl.m_y * m_BufHeight);
1419    ViewPortWidth = s3d_SysIntOfFloatNearest(
1420            ViewRect.m_Scale.m_x * m_BufWidth);
1421    ViewPortHeight = s3d_SysIntOfFloatNearest(
1422            ViewRect.m_Scale.m_y * m_BufHeight);
1423
1424    if(ViewPortWidth <= 0)
1425        ViewPortWidth = 1; // Below 1 can make troube for some drivers
1426    else if(ViewPortWidth > m_BufWidth)
1427        ViewPortWidth = m_BufWidth;
1428    if(ViewPortX < 0)
1429        ViewPortX = 0;
1430    else if((ViewPortX + ViewPortWidth) > m_BufWidth)
1431        ViewPortX = m_BufWidth - ViewPortWidth;
1432
1433    if(ViewPortHeight <= 0)
1434        ViewPortHeight = 1; // Below 1 can make troube for some drivers
1435    else if(ViewPortHeight > m_BufHeight)
1436        ViewPortHeight = m_BufHeight;
1437    if(ViewPortY < 0)
1438        ViewPortY = 0;
1439    else if((ViewPortY + ViewPortHeight) > m_BufHeight)
1440        ViewPortY = m_BufHeight - ViewPortHeight;
1441
1442    S3D_SYS_ASSERT(ViewPortX >= 0 && ViewPortY >= 0);
1443
1444
1445    if(m_Viewport.X != ViewPortX || m_Viewport.Y != ViewPortY
1446        || m_Viewport.Width != ViewPortWidth
1447        || m_Viewport.Height != ViewPortHeight)
1448    {
1449        m_Viewport.X = s3d_SysIntOfIntps(ViewPortX);
1450        m_Viewport.Y = s3d_SysIntOfIntps(ViewPortY);
1451        m_Viewport.Width = s3d_SysIntOfIntps(ViewPortWidth);
1452        m_Viewport.Height = s3d_SysIntOfIntps(ViewPortHeight);
1453
1454        S3D_DRV_D3D9_CHECK(
1455                &m_Env, m_D3dDev->SetViewport(&m_Viewport));
1456    }
1457}
1458
1459void s3d_CDrvD3d9GfxEngCLOD::SetViewDepthRange(float NegZ, float PosZ)
1460{
1461    if(!m_D3dDev)
1462        return;
1463
1464    if(m_Viewport.MinZ != NegZ || m_Viewport.MaxZ != PosZ)
1465    {
1466        m_Viewport.MinZ = NegZ;
1467        m_Viewport.MaxZ = PosZ;
1468        S3D_DRV_D3D9_CHECK(
1469                &m_Env, m_D3dDev->SetViewport(&m_Viewport));
1470    }
1471}
1472
1473void s3d_CDrvD3d9GfxEngCLOD::SetScissorRect(
1474        int X, int Y, int Width, int Height)
1475{
1476    if(X < 0)
1477        X = 0;
1478    if(Y < 0)
1479        Y = 0;
1480    int ViewWidth = m_Viewport.Width;
1481    int ViewHeight = m_Viewport.Height;
1482    if(Width <= 0 || Width > ViewWidth)
1483        Width = ViewWidth;
1484    if(Height <= 0 || Height > ViewHeight)
1485        Height = ViewHeight;
1486   
1487    if(X != m_ScissorRect.left
1488        || Y != m_ScissorRect.top
1489        || Width != m_ScissorRect.right
1490        || Height != m_ScissorRect.bottom)
1491    {
1492        m_ScissorRect.left = X;
1493        m_ScissorRect.top = Y;
1494        m_ScissorRect.right = Width;
1495        m_ScissorRect.bottom = Height;
1496
1497        S3D_DRV_D3D9_CALL(
1498                &m_Env, m_D3dDev->SetScissorRect(
1499                    &m_ScissorRect));
1500    }
1501    EnabledScissor(true);
1502}
1503
1504void s3d_CDrvD3d9GfxEngCLOD::SetScissorNone()
1505{
1506    EnabledScissor(false);
1507}
1508
1509///////////////////////////////////////////////////////////////////////////////
1510
1511static const int s3d_DrvD3d9CullTable[3] =
1512{
1513    D3DCULL_NONE, D3DCULL_CW, D3DCULL_CCW,
1514};
1515
1516void s3d_CDrvD3d9GfxEngCLOD::SetCullMode(int Mode)
1517{
1518    S3D_DRV_D3D9_STATE_NE(m_CullMode, Mode)
1519    {
1520        if(s3d_SysIsValidArrayIdx(
1521                Mode, S3D_SYS_ARRAYCNTS(s3d_DrvD3d9CullTable)))
1522        {
1523            m_CullMode = Mode;
1524            m_State.m_CullMode = s3d_DrvD3d9CullTable[Mode];
1525            S3D_DRV_D3D9_SETSTATEDIRECT(
1526                    m_StateMgr.SetCullMode(m_State.m_CullMode));
1527        }
1528    }
1529}
1530
1531///////////////////////////////////////////////////////////////////////////////
1532
1533static const int s3d_DrvD3d9DepthTestTable[8] =
1534{
1535    D3DCMP_NEVER, D3DCMP_EQUAL,
1536    D3DCMP_LESS, D3DCMP_LESSEQUAL,
1537    D3DCMP_GREATER, D3DCMP_GREATEREQUAL,
1538    D3DCMP_NOTEQUAL, D3DCMP_ALWAYS,
1539};
1540
1541void s3d_CDrvD3d9GfxEngCLOD::SetDepthTest(int Mode)
1542{
1543    S3D_DRV_D3D9_STATE_NE(m_DepthTestMode, Mode)
1544    {
1545        if(s3d_SysIsValidArrayIdx(
1546                Mode, S3D_SYS_ARRAYCNTS(s3d_DrvD3d9DepthTestTable)))
1547        {
1548            m_DepthTestMode = Mode;
1549            m_State.m_DepthTestMode = s3d_DrvD3d9DepthTestTable[Mode];
1550            S3D_DRV_D3D9_SETSTATEDIRECT(
1551                    m_StateMgr.SetDepthTestMode(m_State.m_DepthTestMode));
1552        }
1553    }
1554}
1555
1556void s3d_CDrvD3d9GfxEngCLOD::SetDepthWrite(bool Enabled)
1557{
1558    S3D_DRV_D3D9_STATE_NE(m_State.m_DepthWrite, BOOL(Enabled))
1559    {
1560        m_State.m_DepthWrite = Enabled;
1561        S3D_DRV_D3D9_SETSTATEDIRECT(
1562                m_StateMgr.SetDepthWrite(m_State.m_DepthWrite));
1563    }
1564}
1565
1566///////////////////////////////////////////////////////////////////////////////
1567
1568int s3d_CDrvD3d9GfxEngCLOD::GetStencilBits() const
1569{
1570    return m_BufStencilBits;
1571}
1572
1573static const int s3d_DrvD3d9StencilTestTable[8] =
1574{
1575    D3DCMP_NEVER, D3DCMP_EQUAL,
1576    D3DCMP_LESS, D3DCMP_LESSEQUAL,
1577    D3DCMP_GREATER, D3DCMP_GREATEREQUAL,
1578    D3DCMP_NOTEQUAL, D3DCMP_ALWAYS,
1579};
1580
1581static const int s3d_DrvD3d9StencilOpTable[8] =
1582{
1583    D3DSTENCILOP_KEEP, D3DSTENCILOP_ZERO,
1584    D3DSTENCILOP_REPLACE, D3DSTENCILOP_INVERT,
1585    D3DSTENCILOP_INCRSAT, D3DSTENCILOP_DECRSAT,
1586    D3DSTENCILOP_INCR, D3DSTENCILOP_DECR,
1587};
1588
1589
1590void s3d_CDrvD3d9GfxEngCLOD::SetStencilMode(
1591        int TestMask, int TestRef, int TestModeFront, int TestModeBack,
1592        int WriteMask,
1593        int OpFailFront, int OpDepthFailFront, int OpDepthPassFront,
1594        int OpFailBack, int OpDepthFailBack, int OpDepthPassBack)
1595{
1596    S3D_DRV_D3D9_STATE_NE(TestModeFront, m_StencilTestModeFront)
1597    {
1598        m_StencilTestModeFront = TestModeFront;
1599        if(s3d_SysIsValidArrayIdx(
1600                TestModeFront,
1601                S3D_SYS_ARRAYCNTS(s3d_DrvD3d9StencilTestTable)))
1602        {
1603            m_State.m_StencilTestModeFront
1604                    = s3d_DrvD3d9StencilTestTable[TestModeFront];
1605            S3D_DRV_D3D9_SETSTATEDIRECT(
1606                    m_StateMgr.SetStencilTestModeFront(
1607                        m_State.m_StencilTestModeFront));
1608        }
1609    }
1610    S3D_DRV_D3D9_STATE_NE(TestModeBack, m_StencilTestModeBack)
1611    {
1612        m_StencilTestModeBack = TestModeBack;
1613        if(s3d_SysIsValidArrayIdx(
1614                TestModeBack,
1615                S3D_SYS_ARRAYCNTS(s3d_DrvD3d9StencilTestTable)))
1616        {
1617            m_State.m_StencilTestModeBack
1618                    = s3d_DrvD3d9StencilTestTable[TestModeBack];
1619            S3D_DRV_D3D9_SETSTATEDIRECT(
1620                    m_StateMgr.SetStencilTestModeBack(
1621                        m_State.m_StencilTestModeBack));
1622        }
1623    }
1624   
1625    m_State.m_StencilTestRef = TestRef;
1626    S3D_DRV_D3D9_SETSTATEDIRECT(m_StateMgr.SetStencilTestRef(TestRef));
1627    m_State.m_StencilTestMask = TestMask;
1628    S3D_DRV_D3D9_SETSTATEDIRECT(m_StateMgr.SetStencilTestMask(TestMask));
1629    m_State.m_StencilWriteMask = WriteMask;
1630    S3D_DRV_D3D9_SETSTATEDIRECT(m_StateMgr.SetStencilWriteMask(WriteMask));
1631
1632    S3D_DRV_D3D9_STATE_NE(OpFailFront, m_StencilOpFailFront)
1633    {
1634        m_StencilOpFailFront = OpFailFront;
1635        if(s3d_SysIsValidArrayIdx(
1636                OpFailFront,
1637                S3D_SYS_ARRAYCNTS(s3d_DrvD3d9StencilOpTable)))
1638        {
1639            m_State.m_StencilOpFailFront =
1640                    s3d_DrvD3d9StencilOpTable[OpFailFront];
1641            S3D_DRV_D3D9_SETSTATEDIRECT(
1642                    m_StateMgr.SetStencilOpFailFront(
1643                        m_State.m_StencilOpFailFront));
1644        }
1645    }
1646    S3D_DRV_D3D9_STATE_NE(OpDepthFailFront, m_StencilOpDepthFailFront)
1647    {
1648        m_StencilOpDepthFailFront = OpDepthFailFront;
1649        if(s3d_SysIsValidArrayIdx(
1650                OpDepthFailFront,
1651                S3D_SYS_ARRAYCNTS(s3d_DrvD3d9StencilOpTable)))
1652        {
1653            m_State.m_StencilOpDepthFailFront
1654                    = s3d_DrvD3d9StencilOpTable[OpDepthFailFront];
1655            S3D_DRV_D3D9_SETSTATEDIRECT(
1656                    m_StateMgr.SetStencilOpDepthFailFront(
1657                        m_State.m_StencilOpDepthFailFront));
1658        }
1659    }
1660    S3D_DRV_D3D9_STATE_NE(OpDepthPassFront, m_StencilOpDepthPassFront)
1661    {
1662        m_StencilOpDepthPassFront = OpDepthPassFront;
1663        if(s3d_SysIsValidArrayIdx(
1664                OpDepthPassFront,
1665                S3D_SYS_ARRAYCNTS(s3d_DrvD3d9StencilOpTable)))
1666        {
1667            m_State.m_StencilOpDepthPassFront
1668                    = s3d_DrvD3d9StencilOpTable[OpDepthPassFront];
1669            S3D_DRV_D3D9_SETSTATEDIRECT(
1670                    m_StateMgr.SetStencilOpDepthPassFront(
1671                        m_State.m_StencilOpDepthPassFront));
1672        }
1673    }
1674
1675    S3D_DRV_D3D9_STATE_NE(OpFailBack, m_StencilOpFailBack)
1676    {
1677        m_StencilOpFailBack = OpFailBack;
1678        if(s3d_SysIsValidArrayIdx(
1679                OpFailBack,
1680                S3D_SYS_ARRAYCNTS(s3d_DrvD3d9StencilOpTable)))
1681        {
1682            m_State.m_StencilOpFailBack
1683                    = s3d_DrvD3d9StencilOpTable[OpFailBack];
1684            S3D_DRV_D3D9_SETSTATEDIRECT(
1685                    m_StateMgr.SetStencilOpFailBack(
1686                        m_State.m_StencilOpFailBack));
1687        }
1688    }
1689    S3D_DRV_D3D9_STATE_NE(OpDepthFailBack, m_StencilOpDepthFailBack)
1690    {
1691        m_StencilOpDepthFailBack = OpDepthFailBack;
1692        if(s3d_SysIsValidArrayIdx(
1693                OpDepthFailBack,
1694                S3D_SYS_ARRAYCNTS(s3d_DrvD3d9StencilOpTable)))
1695        {
1696            m_State.m_StencilOpDepthFailBack
1697                    = s3d_DrvD3d9StencilOpTable[OpDepthFailBack];
1698            S3D_DRV_D3D9_SETSTATEDIRECT(
1699                    m_StateMgr.SetStencilOpDepthFailBack(
1700                        m_State.m_StencilOpDepthFailBack));
1701        }
1702    }
1703    S3D_DRV_D3D9_STATE_NE(OpDepthPassBack, m_StencilOpDepthPassBack)
1704    {
1705        m_StencilOpDepthPassBack = OpDepthPassBack;
1706        if(s3d_SysIsValidArrayIdx(
1707                OpDepthPassBack,
1708                S3D_SYS_ARRAYCNTS(s3d_DrvD3d9StencilOpTable)))
1709        {
1710            m_State.m_StencilOpDepthPassBack
1711                    = s3d_DrvD3d9StencilOpTable[OpDepthPassBack];
1712            S3D_DRV_D3D9_SETSTATEDIRECT(
1713                    m_StateMgr.SetStencilOpDepthPassBack(
1714                        m_State.m_StencilOpDepthPassBack));
1715        }
1716    }
1717
1718    if(TestModeFront == TestModeBack
1719            && OpFailFront == OpFailBack
1720            && OpDepthFailFront == OpDepthFailBack
1721            && OpDepthPassFront == OpDepthPassBack)
1722    {
1723        m_State.m_StencilTwoSidedEnabled = FALSE;
1724        S3D_DRV_D3D9_SETSTATEDIRECT(
1725                m_StateMgr.SetStencilTwoSidedEnabled(FALSE));
1726    }
1727    else if(TestModeBack != TestModeFront
1728            || OpFailBack != OpFailFront
1729            || OpDepthFailBack != OpDepthFailFront
1730            || OpDepthPassBack != OpDepthPassFront)
1731    {
1732        m_State.m_StencilTwoSidedEnabled = TRUE;
1733        S3D_DRV_D3D9_SETSTATEDIRECT(
1734                m_StateMgr.SetStencilTwoSidedEnabled(TRUE));
1735    }
1736
1737    if(TestModeFront == TestMode_Always
1738            && OpFailFront == StencilOp_Keep
1739            && OpDepthFailFront == StencilOp_Keep
1740            && OpDepthPassFront == StencilOp_Keep)
1741    {
1742        m_State.m_StencilEnabled = FALSE;
1743        S3D_DRV_D3D9_SETSTATEDIRECT(
1744                m_StateMgr.SetStencilEnabled(FALSE));
1745    }
1746    else
1747    {
1748        m_State.m_StencilEnabled = TRUE;
1749        S3D_DRV_D3D9_SETSTATEDIRECT(
1750                m_StateMgr.SetStencilEnabled(TRUE));
1751    }
1752}
1753
1754///////////////////////////////////////////////////////////////////////////////
1755
1756static const int s3d_DrvD3d9AlphaTestTable[8] =
1757{
1758    D3DCMP_NEVER, D3DCMP_EQUAL,
1759    D3DCMP_LESS, D3DCMP_LESSEQUAL,
1760    D3DCMP_GREATER, D3DCMP_GREATEREQUAL,
1761    D3DCMP_NOTEQUAL, D3DCMP_ALWAYS,
1762};
1763
1764void s3d_CDrvD3d9GfxEngCLOD::SetAlphaTest(int Mode, float Ref)
1765{
1766    if(Mode == TestMode_Always)
1767    {
1768        m_State.m_AlphaTestEnabled = FALSE;
1769        S3D_DRV_D3D9_SETSTATEDIRECT(
1770                m_StateMgr.SetAlphaTestEnabled(FALSE));
1771    }
1772    else
1773    {
1774        m_State.m_AlphaTestEnabled = TRUE;
1775        S3D_DRV_D3D9_SETSTATEDIRECT(
1776                m_StateMgr.SetAlphaTestEnabled(TRUE));
1777    }
1778
1779    S3D_DRV_D3D9_STATE_NE(m_AlphaTestMode, Mode)
1780    {
1781        if(s3d_SysIsValidArrayIdx(
1782                Mode,
1783                S3D_SYS_ARRAYCNTS(s3d_DrvD3d9AlphaTestTable)))
1784        {
1785            m_AlphaTestMode = Mode;
1786            m_State.m_AlphaTestMode = s3d_DrvD3d9AlphaTestTable[Mode];
1787            S3D_DRV_D3D9_SETSTATEDIRECT(
1788                    m_StateMgr.SetAlphaTestMode(m_State.m_AlphaTestMode));
1789        }
1790    }
1791   
1792    S3D_DRV_D3D9_STATE_NE(m_AlphaTestRef, Ref)
1793    {
1794        if(Mode >= 2)
1795        {
1796            m_AlphaTestRef = Ref;
1797            m_State.m_AlphaTestRef = s3d_SysIntOfFloatCoarse(0xFF * Ref);
1798            S3D_DRV_D3D9_SETSTATEDIRECT(
1799                    m_StateMgr.SetAlphaTestRef(m_State.m_AlphaTestRef));
1800        }
1801    }
1802}
1803
1804static const int s3d_DrvD3d9BlendFacTable[10] =
1805{
1806    D3DBLEND_ZERO, D3DBLEND_ONE,
1807    D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA,
1808    D3DBLEND_SRCCOLOR, D3DBLEND_INVSRCCOLOR,
1809    D3DBLEND_DESTALPHA, D3DBLEND_INVDESTALPHA,
1810    D3DBLEND_DESTCOLOR, D3DBLEND_INVDESTCOLOR,
1811};
1812
1813static const int s3d_DrvD3d9BlendOpTable[10] =
1814{
1815    D3DBLENDOP_ADD,
1816    D3DBLENDOP_SUBTRACT, D3DBLENDOP_REVSUBTRACT,
1817    D3DBLENDOP_MIN, D3DBLENDOP_MAX,
1818};
1819
1820void s3d_CDrvD3d9GfxEngCLOD::SetBlendMode(
1821        int ColSrcFac, int ColDestFac, int ColOp,
1822        int AlphaSrcFac, int AlphaDestFac, int AlphaOp)
1823{
1824    if(ColSrcFac == BlendFac_One && ColDestFac == BlendFac_Zero
1825            && ColOp == BlendOp_SrcPlusDest)
1826    {
1827        m_State.m_ColorWriteEnabled
1828            = D3DCOLORWRITEENABLE_RED
1829            | D3DCOLORWRITEENABLE_GREEN
1830            | D3DCOLORWRITEENABLE_BLUE
1831            | D3DCOLORWRITEENABLE_ALPHA;
1832        m_State.m_AlphaBlendEnabled = FALSE;
1833    }
1834    else if(ColSrcFac == BlendFac_Zero && ColDestFac == BlendFac_One
1835            && ColOp == BlendOp_SrcPlusDest)
1836    {
1837        m_State.m_ColorWriteEnabled = 0;
1838        m_State.m_AlphaBlendEnabled = FALSE;
1839    }
1840    else
1841    {
1842        m_State.m_ColorWriteEnabled
1843            = D3DCOLORWRITEENABLE_RED
1844            | D3DCOLORWRITEENABLE_GREEN
1845            | D3DCOLORWRITEENABLE_BLUE
1846            | D3DCOLORWRITEENABLE_ALPHA;
1847        m_State.m_AlphaBlendEnabled = TRUE;
1848        S3D_DRV_D3D9_STATE_NE(m_BlendColSrcFac, ColSrcFac)
1849        {
1850            if(s3d_SysIsValidArrayIdx(
1851                    ColSrcFac,
1852                    S3D_SYS_ARRAYCNTS(s3d_DrvD3d9BlendFacTable)))
1853            {   
1854                m_BlendColSrcFac = ColSrcFac;
1855                m_State.m_SrcBlend = s3d_DrvD3d9BlendFacTable[ColSrcFac];
1856                S3D_DRV_D3D9_SETSTATEDIRECT(
1857                        m_StateMgr.SetSrcBlend(m_State.m_SrcBlend));
1858            }
1859        }
1860        S3D_DRV_D3D9_STATE_NE(m_BlendColDestFac, ColDestFac)
1861        {
1862            if(s3d_SysIsValidArrayIdx(
1863                    ColDestFac,
1864                    S3D_SYS_ARRAYCNTS(s3d_DrvD3d9BlendFacTable)))
1865            {   
1866                m_BlendColDestFac = ColDestFac;
1867                m_State.m_DestBlend = s3d_DrvD3d9BlendFacTable[ColDestFac];
1868                S3D_DRV_D3D9_SETSTATEDIRECT(
1869                        m_StateMgr.SetDestBlend(m_State.m_DestBlend));
1870            }
1871        }
1872        S3D_DRV_D3D9_STATE_NE(m_BlendColOp, ColOp)
1873        {
1874            if(s3d_SysIsValidArrayIdx(
1875                    ColOp,
1876                    S3D_SYS_ARRAYCNTS(s3d_DrvD3d9BlendOpTable)))
1877            {   
1878                m_BlendColOp = ColOp;
1879                m_State.m_BlendOp = s3d_DrvD3d9BlendOpTable[ColOp];
1880                S3D_DRV_D3D9_SETSTATEDIRECT(
1881                        m_StateMgr.SetBlendOp(m_State.m_BlendOp));
1882            }
1883        }
1884    }
1885
1886    m_State.m_SeparateAlphaBlendEnabled = FALSE;
1887    if(AlphaSrcFac != ColSrcFac || AlphaDestFac != ColDestFac
1888                || AlphaOp != ColOp)
1889    {
1890        if(AlphaSrcFac == BlendFac_Zero && AlphaDestFac == BlendFac_One
1891                || AlphaOp == BlendOp_SrcPlusDest)
1892        {
1893            m_State.m_ColorWriteEnabled &= ~D3DCOLORWRITEENABLE_ALPHA;
1894        }
1895        else
1896        {
1897            m_State.m_SeparateAlphaBlendEnabled = FALSE;
1898            S3D_DRV_D3D9_STATE_NE(m_BlendAlphaSrcFac, AlphaSrcFac)
1899            {
1900                if(s3d_SysIsValidArrayIdx(
1901                        AlphaSrcFac,
1902                        S3D_SYS_ARRAYCNTS(s3d_DrvD3d9BlendFacTable)))
1903                {   
1904                    m_BlendAlphaSrcFac = AlphaSrcFac;
1905                    m_State.m_SrcBlendAlpha
1906                            = s3d_DrvD3d9BlendFacTable[AlphaSrcFac];
1907                    S3D_DRV_D3D9_SETSTATEDIRECT(
1908                            m_StateMgr.SetSrcBlendAlpha(
1909                                    m_State.m_SrcBlendAlpha));
1910                }
1911            }
1912            S3D_DRV_D3D9_STATE_NE(m_BlendAlphaDestFac, AlphaDestFac)
1913            {
1914                if(s3d_SysIsValidArrayIdx(
1915                        AlphaDestFac,
1916                        S3D_SYS_ARRAYCNTS(s3d_DrvD3d9BlendFacTable)))
1917                {   
1918                    m_BlendAlphaDestFac = AlphaDestFac;
1919                    m_State.m_DestBlendAlpha
1920                            = s3d_DrvD3d9BlendFacTable[AlphaDestFac];
1921                    S3D_DRV_D3D9_SETSTATEDIRECT(
1922                            m_StateMgr.SetDestBlendAlpha(
1923                                    m_State.m_DestBlendAlpha));
1924                }
1925            }
1926            S3D_DRV_D3D9_STATE_NE(m_BlendAlphaOp, AlphaOp)
1927            {
1928                if(s3d_SysIsValidArrayIdx(
1929                        AlphaOp,
1930                        S3D_SYS_ARRAYCNTS(s3d_DrvD3d9BlendOpTable)))
1931                {   
1932                    m_BlendAlphaOp = AlphaOp;
1933                    m_State.m_DestBlendAlpha
1934                            = s3d_DrvD3d9BlendOpTable[AlphaOp];
1935                    S3D_DRV_D3D9_SETSTATEDIRECT(
1936                            m_StateMgr.SetDestBlendAlpha(
1937                                    m_State.m_DestBlendAlpha));
1938                }
1939            }
1940        }
1941    }
1942
1943    S3D_DRV_D3D9_SETSTATEDIRECT(
1944            m_StateMgr.SetColorWriteEnabled(
1945                    m_State.m_ColorWriteEnabled));
1946    S3D_DRV_D3D9_SETSTATEDIRECT(
1947            m_StateMgr.SetAlphaBlendEnabled(
1948                    m_State.m_AlphaBlendEnabled));
1949    S3D_DRV_D3D9_SETSTATEDIRECT(
1950            m_StateMgr.SetSeparateAlphaBlendEnabled(
1951                    m_State.m_SeparateAlphaBlendEnabled));
1952}
1953
1954///////////////////////////////////////////////////////////////////////////////
1955
1956static const int s3d_DrvD3d9PaintTable[3] =
1957{
1958    D3DFILL_SOLID, D3DFILL_WIREFRAME, D3DFILL_POINT,
1959};
1960
1961void s3d_CDrvD3d9GfxEngCLOD::SetPaintMode(int Mode)
1962{
1963    S3D_DRV_D3D9_STATE_NE(m_PaintMode, Mode)
1964    {
1965        if(s3d_SysIsValidArrayIdx(
1966                Mode,
1967                S3D_SYS_ARRAYCNTS(s3d_DrvD3d9PaintTable)))
1968        {
1969            m_PaintMode = Mode;
1970            m_State.m_PaintMode = s3d_DrvD3d9PaintTable[Mode];
1971            S3D_DRV_D3D9_SETSTATEDIRECT(
1972                    m_StateMgr.SetPaintMode(m_State.m_PaintMode));
1973        }
1974    }
1975}
1976
1977void s3d_CDrvD3d9GfxEngCLOD::SetPaintExt(float Ext)
1978{
1979}
1980
1981void s3d_CDrvD3d9GfxEngCLOD::BeginVisib()
1982{
1983    if(m_VisibMgr)
1984        m_VisibMgr->BeginVisib();
1985}
1986
1987s3d_CDrvGfxVisibPtr s3d_CDrvD3d9GfxEngCLOD::EndVisib()
1988{
1989    if(m_VisibMgr)
1990        return m_VisibMgr->EndVisib();
1991    return 0;
1992}
1993
1994void s3d_CDrvD3d9GfxEngCLOD::SetFogNone()
1995{
1996    S3D_DRV_D3D9_STATE_NE(m_State.m_FogDensity, 0.f)
1997    {
1998        m_ParamBlk.m_FogColDensity = D3DXVECTOR4(0.f, 0.f, 0.f, 0.f);
1999       
2000        m_ParamStateProg.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Fog;
2001        m_ParamStateFFP.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Fog;
2002
2003        m_State.m_FogDensity = 0.f;
2004        m_State.m_FogColor = 0;
2005        S3D_DRV_D3D9_SETSTATEDIRECT(
2006                m_StateMgr.SetFogDensity(0.f));
2007        S3D_DRV_D3D9_SETSTATEDIRECT(
2008                m_StateMgr.SetFogColor(0));
2009    }
2010}
2011
2012void s3d_CDrvD3d9GfxEngCLOD::SetFogExp(
2013        float Density, s3d_CUtilVec3f_cr Color)
2014{
2015    D3DXVECTOR4 FogColDensity
2016            = D3DXVECTOR4(Color.m_x, Color.m_y, Color.m_z, Density);
2017   
2018    S3D_DRV_D3D9_STATE_NE(FogColDensity, m_ParamBlk.m_FogColDensity)
2019    {
2020        m_ParamStateProg.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Fog;
2021        m_ParamStateFFP.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Fog;
2022        m_ParamBlk.m_FogColDensity = FogColDensity;
2023
2024        m_State.m_FogDensity = Density;
2025        S3D_DRV_D3D9_SETSTATEDIRECT(
2026                m_StateMgr.SetFogDensity(Density));
2027       
2028        D3DCOLOR FogColor = S3D_DRV_D3D9_UTIL_COLORVALUE(
2029                    Color.m_x, Color.m_y, Color.m_z, 1);
2030       
2031        m_State.m_FogColor = FogColor;
2032        S3D_DRV_D3D9_SETSTATEDIRECT(
2033                m_StateMgr.SetFogColor(FogColor));
2034    }
2035}
2036
2037///////////////////////////////////////////////////////////////////////////////
2038
2039bool s3d_CDrvD3d9GfxEngCLOD::IsStereo() const
2040{
2041    return false;
2042}
2043
2044void s3d_CDrvD3d9GfxEngCLOD::SetStereoEyeOffset(s3d_CUtilVec3f_cr EyeOffset)
2045{
2046}
2047
2048void s3d_CDrvD3d9GfxEngCLOD::SetTransf(int Chan, int Slot, s3d_CUtilMat4x4f_cr Mat)
2049{
2050    switch(Chan)
2051    {
2052        case TransfChan_Proj:
2053        {
2054            m_MatProj._11 = Mat.m_xx;
2055            m_MatProj._12 = Mat.m_xy;
2056            m_MatProj._13 = Mat.m_xz;
2057            m_MatProj._14 = Mat.m_xw;
2058            m_MatProj._21 = - Mat.m_yx;
2059            m_MatProj._22 = - Mat.m_yy;
2060            m_MatProj._23 = - Mat.m_yz;
2061            m_MatProj._24 = - Mat.m_yw;
2062            m_MatProj._31 = 0.5f * (Mat.m_zx + Mat.m_wx);
2063            m_MatProj._32 = 0.5f * (Mat.m_zy + Mat.m_wy);
2064            m_MatProj._33 = 0.5f * (Mat.m_zz + Mat.m_wz);
2065            m_MatProj._34 = 0.5f * (Mat.m_zw + Mat.m_ww);
2066            m_MatProj._41 = Mat.m_wx;
2067            m_MatProj._42 = Mat.m_wy;
2068            m_MatProj._43 = Mat.m_wz;
2069            m_MatProj._44 = Mat.m_ww;
2070            m_MatProjDirty = true;
2071            break;
2072        }
2073        case TransfChan_View:
2074        {
2075            LPD3DXMATRIXA16 MatView = &m_ParamBlk.m_MatView;
2076            MatView->_11 = Mat.m_xx;
2077            MatView->_12 = Mat.m_xy;
2078            MatView->_13 = Mat.m_xz;
2079            MatView->_14 = Mat.m_xw;
2080            MatView->_21 = Mat.m_yx;
2081            MatView->_22 = Mat.m_yy;
2082            MatView->_23 = Mat.m_yz;
2083            MatView->_24 = Mat.m_yw;
2084            MatView->_31 = Mat.m_zx;
2085            MatView->_32 = Mat.m_zy;
2086            MatView->_33 = Mat.m_zz;
2087            MatView->_34 = Mat.m_zw;
2088            MatView->_41 = Mat.m_wx;
2089            MatView->_42 = Mat.m_wy;
2090            MatView->_43 = Mat.m_wz;
2091            MatView->_44 = Mat.m_ww;
2092            m_ParamStateProg.m_DirtyMask
2093                    |= s3d_CDrvD3d9ParamBlkState::Dirty_MatView;
2094            m_ParamStateFFP.m_DirtyMask
2095                    |= s3d_CDrvD3d9ParamBlkState::Dirty_MatView;
2096            break;
2097        }
2098        case TransfChan_Gen:
2099        {
2100            if(s3d_SysIsValidArrayIdx(Slot, m_MaxAttrCnt))
2101            {
2102                LPD3DXMATRIXA16 MatGen = &m_ParamBlk.m_MatGenArray[Slot];
2103                MatGen->_11 = Mat.m_xx;
2104                MatGen->_12 = Mat.m_xy;
2105                MatGen->_13 = Mat.m_xz;
2106                MatGen->_14 = Mat.m_xw;
2107                MatGen->_21 = Mat.m_yx;
2108                MatGen->_22 = Mat.m_yy;
2109                MatGen->_23 = Mat.m_yz;
2110                MatGen->_24 = Mat.m_yw;
2111                MatGen->_31 = Mat.m_zx;
2112                MatGen->_32 = Mat.m_zy;
2113                MatGen->_33 = Mat.m_zz;
2114                MatGen->_34 = Mat.m_zw;
2115                MatGen->_41 = Mat.m_wx;
2116                MatGen->_42 = Mat.m_wy;
2117                MatGen->_43 = Mat.m_wz;
2118                MatGen->_44 = Mat.m_ww;
2119                m_ParamStateProg.m_DirtyMask
2120                        |= s3d_CDrvD3d9ParamBlkState::Dirty_MatGen;
2121                m_ParamStateFFP.m_DirtyMask
2122                        |= s3d_CDrvD3d9ParamBlkState::Dirty_MatGen;
2123            }
2124            break;
2125        }
2126        case TransfChan_Bone:
2127        {
2128            D3DXMATRIXA16 MatBone;
2129            MatBone._11 = Mat.m_xx;
2130            MatBone._12 = Mat.m_xy;
2131            MatBone._13 = Mat.m_xz;
2132            MatBone._14 = Mat.m_xw;
2133            MatBone._21 = Mat.m_yx;
2134            MatBone._22 = Mat.m_yy;
2135            MatBone._23 = Mat.m_yz;
2136            MatBone._24 = Mat.m_yw;
2137            MatBone._31 = Mat.m_zx;
2138            MatBone._32 = Mat.m_zy;
2139            MatBone._33 = Mat.m_zz;
2140            MatBone._34 = Mat.m_zw;
2141            MatBone._41 = Mat.m_wx;
2142            MatBone._42 = Mat.m_wy;
2143            MatBone._43 = Mat.m_wz;
2144            MatBone._44 = Mat.m_ww;
2145            m_MatBoneArray.SetAtGrow(Slot, MatBone);
2146            m_MatBoneDirty = true;
2147            break;
2148        }
2149    }
2150}
2151
2152void s3d_CDrvD3d9GfxEngCLOD::SetTransfIdentity(int Chan, int Slot)
2153{
2154    SetTransf(Chan, Slot, 1);
2155}
2156
2157void s3d_CDrvD3d9GfxEngCLOD::SetClipPlane(s3d_CUtilVec4f_cr Plane)
2158{
2159}
2160
2161void s3d_CDrvD3d9GfxEngCLOD::SetDepthBias(
2162        float BiasOverlay, float BiasOffs)
2163{
2164    if(m_DepthBiasOverlay != BiasOverlay || m_DepthBiasOffs != BiasOffs)
2165    {
2166        m_DepthBiasOverlay = BiasOverlay;
2167        m_DepthBiasOffs = BiasOffs;
2168
2169        float D3dDepthBias = m_BufDepthBiasScale * BiasOverlay;
2170        float D3dSlopeScaleDepthBias = BiasOverlay + BiasOffs;
2171        S3D_DRV_D3D9_SETSTATEDIRECT(
2172                m_StateMgr.SetDepthBias(D3dDepthBias, D3dSlopeScaleDepthBias));
2173    }
2174}
2175
2176void s3d_CDrvD3d9GfxEngCLOD::DisableLighting()
2177{
2178    m_WantLighting = false;
2179    m_WantLightCnt = 0;
2180    m_ParamStateProg.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Light;
2181    m_ParamStateFFP.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Light;
2182}
2183
2184void s3d_CDrvD3d9GfxEngCLOD::SetLightArray(
2185        s3d_CSysIntps LightCnt, s3d_CDrvGfxLight **LightArray)
2186{
2187    if(LightCnt < 0)
2188        return;
2189
2190    if(LightCnt > m_MaxLightCnt)
2191        LightCnt = m_MaxLightCnt;
2192
2193    D3DLIGHT9 *Light = m_ParamBlk.m_LightArray;
2194    s3d_CSysIntps iLight;
2195    for(iLight = 0; iLight < LightCnt; iLight++)
2196    {
2197        const s3d_CDrvGfxLight *GfxLight = LightArray[iLight];
2198        D3DLIGHTTYPE LightType = D3DLIGHT_POINT;
2199        if(GfxLight->m_Parallel)
2200        {
2201            LightType = D3DLIGHT_DIRECTIONAL;
2202            S3D_SYS_ASSERT(GfxLight->m_ViewDir != 0);
2203        }
2204       
2205        if(Light->Type == LightType
2206                && Light->Position.x == GfxLight->m_ViewPos.m_x
2207                && Light->Position.y == GfxLight->m_ViewPos.m_y
2208                && Light->Position.z == GfxLight->m_ViewPos.m_z
2209                && Light->Direction.x == GfxLight->m_ViewDir.m_x
2210                && Light->Direction.y == GfxLight->m_ViewDir.m_y
2211                && Light->Direction.z == GfxLight->m_ViewDir.m_z
2212                && Light->Range == GfxLight->m_ViewRange
2213                && Light->Ambient.r == GfxLight->m_Ambient.m_x
2214                && Light->Ambient.g == GfxLight->m_Ambient.m_y
2215                && Light->Ambient.b == GfxLight->m_Ambient.m_z
2216                && Light->Diffuse.r == GfxLight->m_Diffuse.m_x
2217                && Light->Diffuse.g == GfxLight->m_Diffuse.m_y
2218                && Light->Diffuse.b == GfxLight->m_Diffuse.m_z
2219                && Light->Specular.r == GfxLight->m_Specular.m_x
2220                && Light->Specular.g == GfxLight->m_Specular.m_y
2221                && Light->Specular.b == GfxLight->m_Specular.m_z)
2222        {
2223            Light++;
2224            continue;
2225        }
2226
2227        float Range = GfxLight->m_ViewRange;
2228        float AttenConst = 1.f;
2229        float AttenLinear = 0.f;
2230        float AttenQuadr = 4.f / (Range * Range);
2231
2232        Light->Type     = LightType;
2233        Light->Theta    = 0.0f;
2234        Light->Phi      = D3DX_PI;
2235        Light->Falloff  = 1.0f;
2236   
2237        Light->Attenuation0 = AttenConst;
2238        Light->Attenuation1 = AttenLinear;
2239        Light->Attenuation2 = AttenQuadr;
2240
2241        Light->Ambient.r = GfxLight->m_Ambient.m_x;     
2242        Light->Ambient.g = GfxLight->m_Ambient.m_y;     
2243        Light->Ambient.b = GfxLight->m_Ambient.m_z;     
2244        Light->Ambient.a = 1.f;     
2245        Light->Diffuse.r = GfxLight->m_Diffuse.m_x;     
2246        Light->Diffuse.g = GfxLight->m_Diffuse.m_y;     
2247        Light->Diffuse.b = GfxLight->m_Diffuse.m_z;     
2248        Light->Diffuse.a = 1.f;     
2249        Light->Specular.r = GfxLight->m_Specular.m_x;     
2250        Light->Specular.g = GfxLight->m_Specular.m_y;     
2251        Light->Specular.b = GfxLight->m_Specular.m_z;     
2252        Light->Specular.a = 1.f;     
2253
2254        Light->Position.x = GfxLight->m_ViewPos.m_x;
2255        Light->Position.y = GfxLight->m_ViewPos.m_y;
2256        Light->Position.z = GfxLight->m_ViewPos.m_z;
2257   
2258        Light->Direction.x = GfxLight->m_ViewDir.m_x;
2259        Light->Direction.y = GfxLight->m_ViewDir.m_y;
2260        Light->Direction.z = GfxLight->m_ViewDir.m_z;
2261
2262        Light->Range = GfxLight->m_ViewRange;
2263
2264        m_LightDirtyArray[iLight] = true;
2265        Light++;
2266    }
2267
2268    m_WantLighting = true;
2269    m_WantLightCnt = LightCnt;
2270    m_ParamStateProg.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Light;
2271    m_ParamStateFFP.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Light;
2272}
2273
2274void s3d_CDrvD3d9GfxEngCLOD::SetMtl(
2275        s3d_CUtilVec3f_cr Ambient, s3d_CUtilVec3f_cr Diffuse,
2276        s3d_CUtilVec3f_cr Specular, s3d_CUtilVec3f_cr Emissive,
2277        float SpecExp, float Alpha)
2278{
2279    D3DMATERIAL9 *Mtl = &m_ParamBlk.m_Mtl;
2280    if(Mtl->Ambient.r != Ambient.m_x
2281        ||Mtl->Ambient.g != Ambient.m_y
2282        || Mtl->Ambient.b != Ambient.m_z
2283        || Mtl->Ambient.a != Alpha)
2284    {
2285        Mtl->Ambient.r = Ambient.m_x;
2286        Mtl->Ambient.g = Ambient.m_y;
2287        Mtl->Ambient.b = Ambient.m_z;
2288        Mtl->Ambient.a = Alpha;
2289        m_ParamStateProg.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Mtl;
2290        m_ParamStateFFP.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Mtl;
2291    }
2292    if(Mtl->Diffuse.r != Diffuse.m_x
2293        || Mtl->Diffuse.g != Diffuse.m_y
2294        || Mtl->Diffuse.b != Diffuse.m_z
2295        || Mtl->Diffuse.a != Alpha)
2296    {
2297        Mtl->Diffuse.r = Diffuse.m_x;
2298        Mtl->Diffuse.g = Diffuse.m_y;
2299        Mtl->Diffuse.b = Diffuse.m_z;
2300        Mtl->Diffuse.a = Alpha;
2301        m_ParamStateProg.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Mtl;
2302        m_ParamStateFFP.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Mtl;
2303    }
2304    if(Mtl->Specular.r != Specular.m_x
2305        || Mtl->Specular.g != Specular.m_y
2306        || Mtl->Specular.b != Specular.m_z
2307        || Mtl->Specular.a != Alpha)
2308    {
2309        Mtl->Specular.r = Specular.m_x;
2310        Mtl->Specular.g = Specular.m_y;
2311        Mtl->Specular.b = Specular.m_z;
2312        Mtl->Specular.a = Alpha;
2313        m_ParamStateProg.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Mtl;
2314        m_ParamStateFFP.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Mtl;
2315    }
2316    if(Mtl->Emissive.r != Emissive.m_x
2317        || Mtl->Emissive.g != Emissive.m_y
2318        || Mtl->Emissive.b != Emissive.m_z
2319        || Mtl->Emissive.a != Alpha)
2320    {
2321        Mtl->Emissive.r = Emissive.m_x;
2322        Mtl->Emissive.g = Emissive.m_y;
2323        Mtl->Emissive.b = Emissive.m_z;
2324        Mtl->Emissive.a = Alpha;
2325        m_ParamStateProg.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Mtl;
2326        m_ParamStateFFP.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Mtl;
2327    }
2328    if(Mtl->Power != SpecExp)
2329    {
2330        Mtl->Power = SpecExp;
2331        m_ParamStateProg.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Mtl;
2332        m_ParamStateFFP.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Mtl;
2333    }
2334}
2335
2336void s3d_CDrvD3d9GfxEngCLOD::SetColorAlpha(
2337        s3d_CUtilVec4f_cr ColorAlpha)
2338{
2339    D3DCOLORVALUE *ColorAlphaVal = &m_ParamBlk.m_ColorAlphaVal;
2340    if(ColorAlphaVal->r != ColorAlpha.m_x
2341        || ColorAlphaVal->g != ColorAlpha.m_y
2342        || ColorAlphaVal->b != ColorAlpha.m_z
2343        || ColorAlphaVal->a != ColorAlpha.m_w)
2344    {
2345        ColorAlphaVal->r = ColorAlpha.m_x;
2346        ColorAlphaVal->g = ColorAlpha.m_y;
2347        ColorAlphaVal->b = ColorAlpha.m_z;
2348        ColorAlphaVal->a = ColorAlpha.m_w;
2349    }
2350}
2351
2352void s3d_CDrvD3d9GfxEngCLOD::GetPacketLimits(
2353        int &MaxVertCnt, int &MaxPrimCnt, int Prim)
2354{
2355    MaxPrimCnt = S3D_SYS_INTPS_MAX;
2356    MaxVertCnt = S3D_SYS_INTPS_MAX;
2357
2358    if(m_DevCaps.MaxPrimitiveCount > 0)
2359        MaxPrimCnt = m_DevCaps.MaxPrimitiveCount;
2360    if(m_DevCaps.MaxVertexIndex > 0)
2361        MaxVertCnt = m_DevCaps.MaxVertexIndex - 1;
2362}
2363
2364s3d_CDrvGfxBatchPtr s3d_CDrvD3d9GfxEngCLOD::CreateBatch(
2365        const s3d_CDrvGfxCharge *Charge)
2366{
2367    if(!m_D3dDev)
2368        return 0;
2369
2370    S3D_SYS_ASSERT(s3d_CDrvUtilGfxUtil::VerifyCharge(m_MsgHandler, Charge));
2371
2372    if(m_Prop & s3d_CDrvGfxMgr::Prop_NoBatch)
2373        return 0;
2374    if(!Charge)
2375        return 0;
2376    if(Charge->m_Topol.m_IdxCnt <= 0)
2377        return 0;
2378    if(Charge->m_VertSubCnt < m_D3dParam->m_MinBatchObjVertCnt)
2379        return 0;
2380
2381    // Don't create batch if charge has a univprog!
2382    s3d_CDrvGfxProg *Prog = Charge->m_Prog;
2383    const s3d_CDrvD3d9Prog *ProgImpl
2384            = s3d_UtilRecogCastSilent<s3d_CDrvD3d9Prog>(Charge->m_Prog);
2385    s3d_CDrvGfxUnivProg *UnivProg = 0;
2386    if(ProgImpl)
2387        UnivProg = ProgImpl->m_UnivProg;
2388    if(UnivProg)
2389        return 0;
2390
2391    bool Complete = true;
2392    s3d_CSysIntps nAttrCnt = Charge->m_AttrCnt;
2393    int iAttr;
2394    for(iAttr = 0; iAttr < nAttrCnt; iAttr++)
2395    {
2396        s3d_CDrvGfxAttr *Attr = &Charge->m_AttrArray[iAttr];
2397        if(Attr->m_BankDyn)
2398            Complete = false;
2399    }
2400
2401    if(m_D3dParam->m_NoDynamicVertexBuf && !Complete)
2402        return 0;
2403
2404    s3d_CSysIntps PacketCnt = Charge->m_Topol.m_PacketCnt;
2405    if(PacketCnt <= 0)
2406        return 0;
2407
2408    if(!m_BufMgr)
2409        return 0;
2410
2411    s3d_CDrvD3d9VertBufObjBatchPtr VertBufObj
2412            = m_BufMgr->CreateVertBufObjStatic(
2413                    Charge, m_ProgMgr, m_SWVertProc);
2414    if(!VertBufObj)
2415        return 0;
2416
2417    s3d_CDrvD3d9IdxBufObjBatchPtr IdxBufObj
2418            = m_BufMgr->CreateIdxBufObjStatic(
2419                Charge, VertBufObj->m_Usage, VertBufObj->m_Pool);
2420
2421    if(!IdxBufObj)
2422        return 0;
2423
2424    s3d_CSysIntps PrimCnt = s3d_CDrvUtilGfxUtil::PrimCntOfIdxCnt(
2425            Charge->m_Topol.m_Prim, Charge->m_IdxSubCnt);
2426
2427    s3d_CUtilMsgHandler *ReportMsgHandler = 0;
2428    if(m_D3dParam->m_ReportBatch)
2429        ReportMsgHandler = m_MsgHandler;
2430
2431    s3d_CDrvD3d9BatchPtr EngBatch
2432            = S3D_SYS_NEW s3d_CDrvD3d9Batch(ReportMsgHandler);
2433    EngBatch->m_MainInfo = Charge->m_MainInfo;
2434    EngBatch->m_ObjInfo = Charge->m_ObjInfo;
2435    EngBatch->m_ObjDesc = Charge->m_ObjDesc;
2436    EngBatch->m_Prog = Charge->m_Prog;
2437    EngBatch->m_Complete = Complete;
2438    EngBatch->m_VertBufObj = VertBufObj;
2439    EngBatch->m_IdxBufObj = IdxBufObj;
2440    EngBatch->m_PrimCnt = PrimCnt;
2441    EngBatch->m_VertSubCnt = Charge->m_VertSubCnt;
2442    EngBatch->m_VertSubBase = Charge->m_VertSubBase;
2443    EngBatch->m_IdxSubCnt = Charge->m_IdxSubCnt;
2444    EngBatch->m_IdxSubBase = Charge->m_IdxSubBase;
2445    EngBatch->m_BoneIdxSubCnt = Charge->m_BoneIdxSubCnt;
2446    EngBatch->m_BoneIdxSubBase = Charge->m_BoneIdxSubBase;
2447    EngBatch->m_PacketSubCnt = Charge->m_PacketSubCnt;
2448    EngBatch->m_PacketSubBase = Charge->m_PacketSubBase;
2449
2450    if(m_D3dParam->m_ReportBatch)
2451    {
2452        s3d_CUtilMsg m;
2453        m.m_Code = "drv/imp/directx/d3d9/drv_d3d9_eng.report_batch_create";
2454        m.m_StdTempl = "D3D: "
2455                "Creating batch Addr=[1]: '[2]' IdxSubCnt=[3] VertSubCnt=[4]";
2456        m.AddInfo("");
2457        m.AddInfo(s3d_CUtilStrUtil::StrOfPtr(EngBatch.Get()));
2458        m.AddInfo(Charge->m_MainInfo);
2459        m.AddInfo(s3d_CUtilStrUtil::StrOfIntps(Charge->m_IdxSubCnt));
2460        m.AddInfo(s3d_CUtilStrUtil::StrOfIntps(Charge->m_VertSubCnt));
2461        s3d_UtilMsgReportNote(m_MsgHandler, m);
2462    }
2463
2464    return EngBatch.Get();
2465}
2466
2467S3D_SYS_INLINE
2468void LoadMat4x4f(
2469        s3d_CUtilMat4x4f &DestMat, const D3DXMATRIXA16 &SrcMat)
2470{
2471    DestMat.m_xx = SrcMat._11;
2472    DestMat.m_xy = SrcMat._12;
2473    DestMat.m_xz = SrcMat._13;
2474    DestMat.m_xw = SrcMat._14;
2475    DestMat.m_yx = SrcMat._21;
2476    DestMat.m_yy = SrcMat._22;
2477    DestMat.m_yz = SrcMat._23;
2478    DestMat.m_yw = SrcMat._24;
2479    DestMat.m_zx = SrcMat._31;
2480    DestMat.m_zy = SrcMat._32;
2481    DestMat.m_zz = SrcMat._33;
2482    DestMat.m_zw = SrcMat._34;
2483    DestMat.m_wx = SrcMat._41;
2484    DestMat.m_wy = SrcMat._42;
2485    DestMat.m_wz = SrcMat._43;
2486    DestMat.m_ww = SrcMat._44;
2487}
2488
2489void s3d_CDrvD3d9GfxEngCLOD::ExecuteCharge(
2490        const s3d_CDrvGfxCharge *Charge, s3d_CDrvGfxBatch *Batch,
2491        s3d_CDrvGfxParam_cr GfxParam)
2492{
2493    S3D_SYS_ASSERT(s3d_CDrvUtilGfxUtil::VerifyCharge(m_MsgHandler, Charge));
2494
2495    s3d_CDrvD3d9Batch *BatchImpl = 0;
2496    if(Batch)
2497    {
2498        BatchImpl = s3d_UtilRecogCastSilent<s3d_CDrvD3d9Batch>(Batch);
2499        if(!BatchImpl)
2500        {
2501            S3D_SYS_ASSERT(0);
2502            return;
2503        }
2504    }
2505
2506    if(BatchImpl && BatchImpl->m_Complete)
2507    {
2508        s3d_CDrvD3d9PixEvent PixEvent;
2509        if(m_D3dParam->m_PixEnabled)
2510        {
2511            s3d_CUtilMemPoolFrm MemPoolFrm(m_MemPool);
2512            s3d_CUtilMemPoolStrBuf PixInfo;
2513            s3d_CDrvD3d9PixEvent::InfoStrOfCharge(
2514                    m_MemPool, "batch:",
2515                    BatchImpl->m_ObjDesc.GetChars(),
2516                    BatchImpl->m_MainInfo.GetChars(),
2517                    BatchImpl->m_ObjInfo.GetChars(),
2518                    PixInfo);
2519            PixEvent.Assign(
2520                    PixInfo.GetChars(), S3D_DRV_D3D9_PIX_INSPBATCH_COLOR);
2521        }
2522
2523        const s3d_CSysChar *Info = BatchImpl->m_MainInfo.GetChars();
2524
2525        s3d_CDrvD3d9VertBufObjBatch *VertBufObj = BatchImpl->m_VertBufObj;
2526        if(!VertBufObj)
2527        {
2528            S3D_SYS_ASSERT(0);
2529            return;
2530        }
2531        s3d_CDrvD3d9IdxBufObjBatch *IdxBufObj = BatchImpl->m_IdxBufObj;
2532        if(!IdxBufObj)
2533        {
2534            S3D_SYS_ASSERT(0);
2535            return;
2536        }
2537
2538        int VertBufFmtDecl = VertBufObj->m_VertBufFmtDecl;
2539        bool UseFFP = (BatchImpl->m_Prog == 0);
2540        BeginDraw(Info, VertBufFmtDecl, UseFFP);
2541        SelectProg(
2542                Info, BatchImpl->m_Prog,
2543                BatchImpl->m_ObjInfo.GetChars(),
2544                BatchImpl->m_ObjDesc.GetChars(),
2545                VertBufObj->m_VertDecl, GfxParam);
2546        SelectBuffers(VertBufObj, IdxBufObj);
2547
2548        s3d_CSysIntps VertSubBase = BatchImpl->m_VertSubBase;
2549        s3d_CSysIntps IdxSubBase = BatchImpl->m_IdxSubBase;
2550        s3d_CSysIntps PacketSubBase = BatchImpl->m_PacketSubBase;
2551        s3d_CSysIntps PacketSubCnt = BatchImpl->m_PacketSubCnt;
2552        s3d_CSysIntps BoneIdxSubBase = BatchImpl->m_BoneIdxSubBase;
2553
2554        s3d_CDrvD3d9Packet *PacketSubArray
2555                = IdxBufObj->m_PacketArray + PacketSubBase;
2556
2557        bool TrackDummyBlendTransf = false;
2558        if((VertBufFmtDecl & s3d_CDrvD3d9VertBufDesc::Decl_DummyBoneWgh))
2559            TrackDummyBlendTransf = true;
2560           
2561        DrawIndexedBatchPacket(
2562                IdxBufObj->m_D3dPrim, PacketSubCnt, PacketSubArray,
2563                VertSubBase, IdxSubBase, BoneIdxSubBase,
2564                IdxBufObj->m_BoneIdxCnt, IdxBufObj->m_BoneIdxArray,
2565                TrackDummyBlendTransf);
2566
2567        if(UseFFP)
2568            EndDrawFFP(Info);
2569        else
2570            EndDrawProg(Info);
2571
2572        m_IdxFlushCnt += BatchImpl->m_IdxSubCnt;
2573
2574        m_Stat.m_TotChargeCnt++;
2575        m_Stat.m_TotVertCnt += BatchImpl->m_VertSubCnt;
2576        m_Stat.m_TotPrimCnt += BatchImpl->m_PrimCnt;
2577        m_Stat.m_TotPacketCnt += BatchImpl->m_PacketSubCnt;
2578    }
2579    else if(Charge)
2580    {
2581        s3d_CDrvD3d9PixEvent PixEvent;
2582        if(m_D3dParam->m_PixEnabled)
2583        {
2584            s3d_CUtilMemPoolFrm MemPoolFrm(m_MemPool);
2585            s3d_CUtilMemPoolStrBuf PixInfo;
2586            s3d_CDrvD3d9PixEvent::InfoStrOfCharge(
2587                    m_MemPool, "dyn:",
2588                    Charge->m_ObjDesc,
2589                    Charge->m_MainInfo,
2590                    Charge->m_ObjInfo,
2591                    PixInfo);
2592            PixEvent.Assign(
2593                    PixInfo.GetChars(), S3D_DRV_D3D9_PIX_INSPCHARGE_COLOR);
2594        }
2595
2596        s3d_CUtilMemPoolFrm MemPoolFrm(m_MemPool);
2597
2598        s3d_CDrvGfxProg *Prog = Charge->m_Prog;
2599        const s3d_CDrvD3d9Prog *ProgImpl
2600                = s3d_UtilRecogCastSilent<s3d_CDrvD3d9Prog>(Charge->m_Prog);
2601        s3d_CDrvGfxUnivProg *UnivProg = 0;
2602        if(ProgImpl)
2603            UnivProg = ProgImpl->m_UnivProg;
2604        if(UnivProg)
2605        {
2606            s3d_CUtilMat4x4f MatView;
2607            LoadMat4x4f(MatView, m_ParamBlk.m_MatView);
2608            s3d_CSysIntps MatBoneCnt = m_MatBoneArray.GetCnt();
2609            s3d_CUtilMat4x4f *MatBoneArray
2610                    = new(m_MemPool) s3d_CUtilMat4x4f[MatBoneCnt];
2611            s3d_CSysIntps iMatBone;
2612            for(iMatBone = 0; iMatBone < MatBoneCnt; iMatBone++)
2613                LoadMat4x4f(MatBoneArray[iMatBone], m_MatBoneArray[iMatBone]);
2614
2615            Charge = UnivProg->CreateCharge(
2616                    m_MsgHandler, Charge->m_MainInfo, m_MemPool, Charge,
2617                    GfxParam, MatView, MatBoneCnt, MatBoneArray);
2618            if(!Charge)
2619                return;
2620        }
2621
2622        s3d_CSysIntps PacketSubCnt = Charge->m_PacketSubCnt;
2623        s3d_CDrvD3d9Packet *PacketSubArray
2624                = new(m_MemPool) s3d_CDrvD3d9Packet[PacketSubCnt];
2625
2626        if(!m_BufMgr)
2627            return;
2628
2629        s3d_CSysIntps PacketSubBase = Charge->m_PacketSubBase;
2630        m_BufMgr->LoadBatchPacketData(
2631                Charge, PacketSubCnt, PacketSubArray, PacketSubBase);
2632
2633        if(m_D3dParam->m_UseDIPUP)
2634        {
2635            s3d_CDrvD3d9IdxBufMem IdxBuf;
2636            s3d_CUtilMemPoolArray<s3d_CSysInt32u> BoneIdxArray;
2637            m_BufMgr->FetchIdxBufMemDyn(
2638                    m_MemPool, Charge, IdxBuf, BoneIdxArray);
2639            if(!IdxBuf.m_Data)
2640                return;
2641
2642            s3d_CDrvD3d9VertBufMem VertBuf;
2643            m_BufMgr->FetchVertBufMemDyn(
2644                    m_MemPool, Charge, m_ProgMgr, VertBuf);
2645            if(!VertBuf.m_Data)
2646                return;
2647
2648            int VertBufFmtDecl = VertBuf.m_VertBufFmtDecl;
2649
2650            s3d_CDrvGfxProg *Prog = Charge->m_Prog;
2651            bool UseFFP = (Prog == 0);
2652            BeginDraw(Charge->m_MainInfo, VertBufFmtDecl, UseFFP);
2653            SelectProg(
2654                    Charge->m_MainInfo, Prog,
2655                    Charge->m_ObjInfo, Charge->m_ObjDesc,
2656                    VertBuf.m_VertDecl, GfxParam);
2657
2658            if(m_CurVertDecl != VertBuf.m_VertDecl)
2659            {
2660                m_CurVertDecl = VertBuf.m_VertDecl;
2661                S3D_DRV_D3D9_CHECK(
2662                        &m_Env, m_D3dDev->SetVertexDeclaration(m_CurVertDecl));
2663            }
2664            if(m_CurVertBufObj)
2665            {
2666                m_CurVertBufObj = 0;
2667                UINT StreamIdx = 0;
2668                UINT Offset = 0;
2669                UINT Stride = 0;
2670                LPDIRECT3DVERTEXBUFFER9 VertBuf = 0;
2671                S3D_DRV_D3D9_CHECK(
2672                        &m_Env, m_D3dDev->SetStreamSource(
2673                        StreamIdx, VertBuf, Offset, Stride));
2674            }
2675            if(m_CurIdxBufObj)
2676            {
2677                m_CurIdxBufObj = 0;
2678                LPDIRECT3DINDEXBUFFER9 IdxBuf = 0;
2679                S3D_DRV_D3D9_CHECK(
2680                        &m_Env, m_D3dDev->SetIndices(IdxBuf));
2681            }
2682
2683            bool TrackDummyBlendTransf = false;
2684            if((VertBufFmtDecl & s3d_CDrvD3d9VertBufDesc::Decl_DummyBoneWgh))
2685                TrackDummyBlendTransf = true;
2686
2687            s3d_CSysIntps VertSubBase = 0;
2688            s3d_CSysIntps IdxSubBase = 0;
2689            s3d_CSysIntps BoneIdxSubBase = 0;
2690            s3d_CSysIntps BoneIdxCnt = BoneIdxArray.GetCnt();
2691            DrawIndexedBatchPacketUP(
2692                    IdxBuf.m_Prim, PacketSubCnt, PacketSubArray,
2693                    VertSubBase, VertBuf.m_Data, VertBuf.m_VertSize,
2694                    IdxBuf.m_Fmt, IdxBuf.m_Data,
2695                    BoneIdxSubBase, BoneIdxCnt, BoneIdxArray.GetPtrRaw(),
2696                    TrackDummyBlendTransf);
2697
2698            if(UseFFP)
2699                EndDrawFFP(Charge->m_MainInfo);
2700            else
2701                EndDrawProg(Charge->m_MainInfo);
2702        }
2703        else
2704        {
2705            s3d_CDrvD3d9VertBufObjPtr VertBufObj
2706                    = m_BufMgr->FetchVertBufObjDyn(
2707                        m_MemPool, Charge, m_ProgMgr, m_SWVertProc);
2708            if(!VertBufObj)
2709            {
2710                S3D_SYS_ASSERT(0);
2711                return;
2712            }
2713           
2714            s3d_CUtilMemPoolArray<s3d_CSysInt32u> BoneIdxArray;
2715            s3d_CDrvD3d9IdxBufObj *IdxBufObj
2716                    = m_BufMgr->FetchIdxBufObjDyn(
2717                        m_MemPool, Charge, BoneIdxArray,
2718                        VertBufObj->m_Usage, VertBufObj->m_Pool);
2719            if(!IdxBufObj)
2720            {
2721                S3D_SYS_ASSERT(0);
2722                return;
2723            }
2724       
2725            s3d_CDrvGfxProg* Prog = Charge->m_Prog;
2726            int VertBufFmtDecl = VertBufObj->m_VertBufFmtDecl;
2727            bool UseFFP = (Prog == 0);
2728            BeginDraw(Charge->m_MainInfo, VertBufFmtDecl, UseFFP);
2729            SelectProg(
2730                    Charge->m_MainInfo, Prog,
2731                    Charge->m_ObjInfo, Charge->m_ObjDesc,
2732                    VertBufObj->m_VertDecl, GfxParam);
2733            m_CurVertBufObj = 0;
2734            m_CurIdxBufObj = 0;
2735            SelectBuffers(VertBufObj, IdxBufObj);
2736
2737            s3d_CSysIntps VertSubBase = 0;
2738            s3d_CSysIntps IdxSubBase = 0;
2739            s3d_CSysIntps BoneIdxSubBase = 0;
2740
2741            bool TrackDummyBlendTransf = false;
2742            if((VertBufFmtDecl & s3d_CDrvD3d9VertBufDesc::Decl_DummyBoneWgh))
2743                TrackDummyBlendTransf = true;
2744
2745            DrawIndexedBatchPacket(
2746                    IdxBufObj->m_D3dPrim, PacketSubCnt, PacketSubArray,
2747                    VertSubBase, IdxSubBase, BoneIdxSubBase,
2748                    BoneIdxArray.GetCnt(), BoneIdxArray.GetPtrRaw(),
2749                    TrackDummyBlendTransf);
2750
2751            if(UseFFP)
2752                EndDrawFFP(Charge->m_MainInfo);
2753            else
2754                EndDrawProg(Charge->m_MainInfo);
2755        }
2756
2757        m_IdxFlushCnt += Charge->m_IdxSubCnt;
2758
2759        s3d_CSysIntps PrimCnt = s3d_CDrvUtilGfxUtil::PrimCntOfIdxCnt(
2760                Charge->m_Topol.m_Prim, Charge->m_IdxSubCnt);
2761        m_Stat.m_TotChargeCnt++;
2762        m_Stat.m_TotVertCnt += Charge->m_VertSubCnt;
2763        m_Stat.m_TotPrimCnt += PrimCnt;
2764        m_Stat.m_TotPacketCnt += PacketSubCnt;
2765
2766        m_Stat.m_CostlyChargeCnt++;
2767        m_Stat.m_CostlyVertCnt += Charge->m_VertSubCnt;
2768        m_Stat.m_CostlyPrimCnt += PrimCnt;
2769        m_Stat.m_CostlyPacketCnt += PacketSubCnt;
2770    }
2771
2772    if(m_D3dParam->m_IdxFlushCnt > 0
2773            && m_IdxFlushCnt >= m_D3dParam->m_IdxFlushCnt)
2774    {
2775        m_IdxFlushCnt = 0;
2776        m_FlushEvent.End();
2777        m_FlushEvent.Flush();
2778    }
2779}
2780
2781///////////////////////////////////////////////////////////////////////////////
2782
2783void s3d_CDrvD3d9GfxEngCLOD::SetDefaultState()
2784{
2785    if(!m_D3dDev)
2786        return;
2787
2788    m_State.m_CullMode = D3DCULL_CW;
2789    m_State.m_DepthTestMode = D3DCMP_ALWAYS;
2790    m_State.m_DepthWrite = TRUE;
2791    m_State.m_DepthBias = 0;
2792    m_State.m_SlopeScaleDepthBias = 0;
2793
2794    m_State.m_PaintMode = D3DFILL_SOLID;
2795
2796    m_State.m_AlphaBlendEnabled = FALSE;
2797    m_State.m_SrcBlend = D3DBLEND_ONE;
2798    m_State.m_DestBlend = D3DBLEND_ZERO;
2799    m_State.m_SeparateAlphaBlendEnabled = FALSE;
2800    m_State.m_SrcBlendAlpha = D3DBLEND_ONE;
2801    m_State.m_DestBlendAlpha = D3DBLEND_ZERO;
2802
2803    m_State.m_AlphaTestEnabled = FALSE;
2804    m_State.m_AlphaTestMode = D3DCMP_ALWAYS;
2805    m_State.m_AlphaTestRef = 0;
2806
2807    m_State.m_ColorWriteEnabled
2808        = D3DCOLORWRITEENABLE_RED
2809        | D3DCOLORWRITEENABLE_GREEN
2810        | D3DCOLORWRITEENABLE_BLUE
2811        | D3DCOLORWRITEENABLE_ALPHA;
2812
2813    m_State.m_StencilEnabled = FALSE;
2814    m_State.m_StencilTestModeFront = D3DCMP_ALWAYS;
2815    m_State.m_StencilTestRef = 0;
2816    m_State.m_StencilTestMask = 0;
2817    m_State.m_StencilWriteMask = 0;
2818    m_State.m_StencilOpFailFront = D3DSTENCILOP_KEEP;
2819    m_State.m_StencilOpDepthFailFront = D3DSTENCILOP_KEEP;
2820    m_State.m_StencilOpDepthPassFront = D3DSTENCILOP_KEEP;
2821    m_State.m_StencilTwoSidedEnabled = FALSE;
2822    m_State.m_StencilTestModeBack = D3DCMP_ALWAYS;
2823    m_State.m_StencilOpFailBack = D3DSTENCILOP_KEEP;
2824    m_State.m_StencilOpDepthFailBack = D3DSTENCILOP_KEEP;
2825    m_State.m_StencilOpDepthPassBack = D3DSTENCILOP_KEEP;
2826    m_State.m_FogDensity = 0.f;
2827    m_State.m_FogColor = 0;
2828   
2829    m_StateMgr.Invalidate();
2830    m_StateMgr.Apply(m_State);
2831
2832    m_CullMode = -1;
2833    m_DepthTestMode = -1;
2834    m_DepthBiasOverlay = 0.f;
2835    m_DepthBiasOffs = 0.f;
2836    m_BlendColSrcFac = -1;
2837    m_BlendColDestFac = -1;
2838    m_BlendColOp = -1;
2839    m_BlendAlphaSrcFac = -1;
2840    m_BlendAlphaDestFac = -1;
2841    m_BlendAlphaOp = -1;
2842    m_PaintMode = -1;
2843    m_StencilTestModeFront = -1;
2844    m_StencilTestModeBack = -1;
2845    m_StencilOpFailFront = -1;
2846    m_StencilOpDepthFailFront = -1;
2847    m_StencilOpDepthPassFront = -1;
2848    m_StencilOpFailBack = -1;
2849    m_StencilOpDepthFailBack = -1;
2850    m_StencilOpDepthPassBack = -1;
2851    m_AlphaTestMode = -1;
2852    m_AlphaTestRef = 0;
2853
2854    float one = 1.0f;
2855    float zero = 0.0f;
2856    float sixtyfour = 64.0f;
2857
2858    int iAttr;
2859    for(iAttr = 0; iAttr < m_MaxAttrCnt ; iAttr++)
2860    {
2861        S3D_DRV_D3D9_CHECK(
2862                &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateI(
2863                    m_D3dDev, iAttr, D3DTSS_COLORARG1, D3DTA_TEXTURE));
2864        S3D_DRV_D3D9_CHECK(
2865                &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateI(
2866                    m_D3dDev, iAttr, D3DTSS_COLORARG2, D3DTA_CURRENT));
2867        S3D_DRV_D3D9_CHECK(
2868                &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateI(
2869                    m_D3dDev, iAttr, D3DTSS_ALPHAARG1, D3DTA_TEXTURE));
2870        S3D_DRV_D3D9_CHECK(
2871                &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateI(
2872                    m_D3dDev, iAttr, D3DTSS_ALPHAARG2, D3DTA_CURRENT));
2873        S3D_DRV_D3D9_CHECK(
2874                &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateF(
2875                    m_D3dDev, iAttr, D3DTSS_BUMPENVMAT00, zero));
2876        S3D_DRV_D3D9_CHECK(
2877                &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateF(
2878                    m_D3dDev, iAttr, D3DTSS_BUMPENVMAT01, zero));
2879        S3D_DRV_D3D9_CHECK(
2880                &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateF(
2881                    m_D3dDev, iAttr, D3DTSS_BUMPENVMAT10, zero));
2882        S3D_DRV_D3D9_CHECK(
2883                &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateF(
2884                    m_D3dDev, iAttr, D3DTSS_BUMPENVMAT11, zero));
2885        S3D_DRV_D3D9_CHECK(
2886                &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateF(
2887                    m_D3dDev, iAttr, D3DTSS_BUMPENVLSCALE, zero));
2888        S3D_DRV_D3D9_CHECK(
2889                &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateF(
2890                    m_D3dDev, iAttr, D3DTSS_BUMPENVLOFFSET, zero));
2891        S3D_DRV_D3D9_CHECK(
2892                &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateI(
2893                    m_D3dDev, iAttr, D3DTSS_BUMPENVLOFFSET, D3DTTFF_DISABLE));
2894        S3D_DRV_D3D9_CHECK(
2895                &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateI(
2896                    m_D3dDev, iAttr, D3DTSS_COLORARG0, D3DTA_CURRENT));
2897        S3D_DRV_D3D9_CHECK(
2898                &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateI(
2899                    m_D3dDev, iAttr, D3DTSS_ALPHAARG0, D3DTA_CURRENT));
2900        S3D_DRV_D3D9_CHECK(
2901                &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateI(
2902                    m_D3dDev, iAttr, D3DTSS_RESULTARG, D3DTA_CURRENT));
2903/*
2904        Default value?
2905        s3d_CDrvD3d9StateUtil::SetTextureStageStateI(m_D3dDev,
2906                iAttr, D3DTSS_CONSTANT, 0);
2907*/
2908    }
2909
2910    int iSamp;
2911    for(iSamp = 0; iSamp < m_MaxSampCnt; iSamp++)
2912    {
2913        S3D_DRV_D3D9_CHECK(
2914                &m_Env, s3d_CDrvD3d9StateUtil::SetRenderStateI(
2915                    m_D3dDev, s3d_CDrvD3d9Util::D3dWrapOfSamp(iSamp), 0));
2916        S3D_DRV_D3D9_CHECK(
2917                &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI(
2918                    m_D3dDev, iSamp, D3DSAMP_BORDERCOLOR, 0));
2919        S3D_DRV_D3D9_CHECK(
2920                &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateF(
2921                    m_D3dDev, iSamp, D3DSAMP_MIPMAPLODBIAS, zero));
2922        S3D_DRV_D3D9_CHECK(
2923                &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI(
2924                    m_D3dDev, iSamp, D3DSAMP_MAXMIPLEVEL, 0));
2925        S3D_DRV_D3D9_CHECK(
2926                &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI(
2927                    m_D3dDev, iSamp, D3DSAMP_MAXANISOTROPY, 1));
2928        S3D_DRV_D3D9_CHECK(
2929                &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI(
2930                    m_D3dDev, iSamp, D3DSAMP_SRGBTEXTURE, FALSE));
2931        S3D_DRV_D3D9_CHECK(
2932                &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI(
2933                    m_D3dDev, iSamp, D3DSAMP_ELEMENTINDEX, 0));
2934        S3D_DRV_D3D9_CHECK(
2935                &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI(
2936                    m_D3dDev, iSamp, D3DSAMP_DMAPOFFSET, 0));
2937    }
2938   
2939    S3D_DRV_D3D9_CHECK(
2940            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
2941                m_D3dDev, D3DRS_ZENABLE, D3DZB_TRUE));
2942    S3D_DRV_D3D9_CHECK(
2943            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
2944                m_D3dDev, D3DRS_SHADEMODE, D3DSHADE_GOURAUD));
2945    S3D_DRV_D3D9_CHECK(
2946            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
2947                m_D3dDev, D3DRS_DITHERENABLE, FALSE));
2948    S3D_DRV_D3D9_CHECK(
2949            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
2950                m_D3dDev, D3DRS_LASTPIXEL, FALSE));
2951    S3D_DRV_D3D9_CHECK(
2952            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
2953                m_D3dDev, D3DRS_FOGENABLE, FALSE));
2954    S3D_DRV_D3D9_CHECK(
2955            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
2956                m_D3dDev, D3DRS_SPECULARENABLE, TRUE));
2957    S3D_DRV_D3D9_CHECK(
2958            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
2959                m_D3dDev, D3DRS_FOGCOLOR, 0));
2960    S3D_DRV_D3D9_CHECK(
2961            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
2962                m_D3dDev, D3DRS_FOGTABLEMODE, D3DFOG_NONE));
2963    S3D_DRV_D3D9_CHECK(
2964            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF(
2965                m_D3dDev, D3DRS_FOGSTART, zero));
2966    S3D_DRV_D3D9_CHECK(
2967            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF(
2968                m_D3dDev, D3DRS_FOGEND, one));
2969    S3D_DRV_D3D9_CHECK(
2970            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF(
2971                m_D3dDev, D3DRS_FOGDENSITY, one));
2972    S3D_DRV_D3D9_CHECK(
2973            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
2974                m_D3dDev, D3DRS_RANGEFOGENABLE, FALSE));
2975    S3D_DRV_D3D9_CHECK(
2976            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
2977                m_D3dDev, D3DRS_TEXTUREFACTOR, 0xFFFFFFFF));
2978    S3D_DRV_D3D9_CHECK(
2979            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
2980                m_D3dDev, D3DRS_CLIPPING, TRUE));
2981    S3D_DRV_D3D9_CHECK(
2982            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
2983                m_D3dDev, D3DRS_LIGHTING, FALSE));
2984    S3D_DRV_D3D9_CHECK(
2985            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
2986                m_D3dDev, D3DRS_AMBIENT, 0));
2987    S3D_DRV_D3D9_CHECK(
2988            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
2989                m_D3dDev, D3DRS_FOGVERTEXMODE, D3DFOG_NONE));
2990    S3D_DRV_D3D9_CHECK(
2991            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
2992                m_D3dDev, D3DRS_COLORVERTEX, FALSE));
2993    S3D_DRV_D3D9_CHECK(
2994            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
2995                m_D3dDev, D3DRS_LOCALVIEWER, TRUE));
2996    S3D_DRV_D3D9_CHECK(
2997            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
2998                m_D3dDev, D3DRS_NORMALIZENORMALS, FALSE));
2999    S3D_DRV_D3D9_CHECK(
3000            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
3001                m_D3dDev, D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1));
3002    S3D_DRV_D3D9_CHECK(
3003            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
3004                m_D3dDev, D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR2));
3005    S3D_DRV_D3D9_CHECK(
3006            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
3007                m_D3dDev, D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_COLOR2));
3008    S3D_DRV_D3D9_CHECK(
3009            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
3010                m_D3dDev, D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL));
3011    S3D_DRV_D3D9_CHECK(
3012            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
3013                m_D3dDev, D3DRS_VERTEXBLEND, D3DVBF_DISABLE));
3014    S3D_DRV_D3D9_CHECK(
3015            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
3016                m_D3dDev, D3DRS_CLIPPLANEENABLE, 0));
3017    S3D_DRV_D3D9_CHECK(
3018            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF(
3019                m_D3dDev, D3DRS_POINTSIZE, sixtyfour));
3020    S3D_DRV_D3D9_CHECK(
3021            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF(
3022                m_D3dDev, D3DRS_POINTSIZE_MIN, one));
3023    S3D_DRV_D3D9_CHECK(
3024            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
3025                m_D3dDev, D3DRS_POINTSPRITEENABLE, FALSE));
3026    S3D_DRV_D3D9_CHECK(
3027            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
3028                m_D3dDev, D3DRS_POINTSCALEENABLE, FALSE));
3029    S3D_DRV_D3D9_CHECK(
3030            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF(
3031                m_D3dDev, D3DRS_POINTSCALE_A, zero));
3032    S3D_DRV_D3D9_CHECK(
3033            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF(
3034                m_D3dDev, D3DRS_POINTSCALE_B, zero));
3035    S3D_DRV_D3D9_CHECK(
3036            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF(
3037                m_D3dDev, D3DRS_POINTSCALE_C, zero));
3038    S3D_DRV_D3D9_CHECK(
3039            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
3040                m_D3dDev, D3DRS_MULTISAMPLEANTIALIAS, BOOL(m_UseMSAA)));
3041    S3D_DRV_D3D9_CHECK(
3042            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
3043                m_D3dDev, D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF));
3044    S3D_DRV_D3D9_CHECK(
3045            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
3046                m_D3dDev, D3DRS_PATCHEDGESTYLE, D3DPATCHEDGE_DISCRETE));
3047#ifdef S3D_GENERAL_DEBUG
3048    S3D_DRV_D3D9_CHECK(
3049            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
3050                m_D3dDev, D3DRS_DEBUGMONITORTOKEN, D3DDMT_ENABLE));
3051#else
3052    S3D_DRV_D3D9_CHECK(
3053            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
3054                m_D3dDev, D3DRS_DEBUGMONITORTOKEN, D3DDMT_DISABLE));
3055#endif
3056    S3D_DRV_D3D9_CHECK(
3057            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF(
3058                m_D3dDev, D3DRS_POINTSIZE_MAX, sixtyfour));
3059    S3D_DRV_D3D9_CHECK(
3060            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
3061                m_D3dDev, D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE));
3062
3063    S3D_DRV_D3D9_CHECK(
3064            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF(
3065                m_D3dDev, D3DRS_TWEENFACTOR, zero));
3066    S3D_DRV_D3D9_CHECK(
3067            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
3068                m_D3dDev, D3DRS_BLENDOP, D3DBLENDOP_ADD));
3069    S3D_DRV_D3D9_CHECK(
3070            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
3071                m_D3dDev, D3DRS_POSITIONDEGREE, D3DDEGREE_CUBIC));
3072    S3D_DRV_D3D9_CHECK(
3073            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
3074                m_D3dDev, D3DRS_NORMALDEGREE, D3DDEGREE_LINEAR));
3075    S3D_DRV_D3D9_CHECK(
3076            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
3077                m_D3dDev, D3DRS_SCISSORTESTENABLE, FALSE));
3078    S3D_DRV_D3D9_CHECK(
3079            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF(
3080                m_D3dDev, D3DRS_SLOPESCALEDEPTHBIAS, zero));
3081    S3D_DRV_D3D9_CHECK(
3082            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
3083                m_D3dDev, D3DRS_ANTIALIASEDLINEENABLE, FALSE));
3084    S3D_DRV_D3D9_CHECK(
3085            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF(
3086                m_D3dDev, D3DRS_MINTESSELLATIONLEVEL, one));
3087    S3D_DRV_D3D9_CHECK(
3088            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF(
3089                m_D3dDev, D3DRS_MAXTESSELLATIONLEVEL, one));
3090    S3D_DRV_D3D9_CHECK(
3091            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF(
3092                m_D3dDev, D3DRS_ADAPTIVETESS_X, zero));
3093    S3D_DRV_D3D9_CHECK(
3094            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF(
3095                m_D3dDev, D3DRS_ADAPTIVETESS_Y, zero));
3096    S3D_DRV_D3D9_CHECK(
3097            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF(
3098                m_D3dDev, D3DRS_ADAPTIVETESS_Z, one));
3099    S3D_DRV_D3D9_CHECK(
3100            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateF(
3101                m_D3dDev, D3DRS_ADAPTIVETESS_W, zero));
3102    S3D_DRV_D3D9_CHECK(
3103            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
3104                m_D3dDev, D3DRS_ENABLEADAPTIVETESSELLATION, FALSE));
3105
3106    S3D_DRV_D3D9_CHECK(
3107            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
3108                m_D3dDev, D3DRS_COLORWRITEENABLE1, 0x0000000F));
3109    S3D_DRV_D3D9_CHECK(
3110            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
3111                m_D3dDev, D3DRS_COLORWRITEENABLE2, 0x0000000F));
3112    S3D_DRV_D3D9_CHECK(
3113            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
3114                m_D3dDev, D3DRS_COLORWRITEENABLE3, 0x0000000F));
3115    S3D_DRV_D3D9_CHECK(
3116            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
3117                m_D3dDev, D3DRS_BLENDFACTOR, 0xFFFFFFFF));
3118    BOOL EnabledSRGBWrite = BOOL(m_D3dParam->m_SRGBWriteEnabled);
3119    S3D_DRV_D3D9_CHECK(
3120            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
3121                m_D3dDev, D3DRS_SRGBWRITEENABLE, EnabledSRGBWrite));
3122
3123    S3D_DRV_D3D9_CHECK(
3124            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
3125                m_D3dDev, D3DRS_SEPARATEALPHABLENDENABLE, FALSE));
3126    S3D_DRV_D3D9_CHECK(
3127            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
3128                m_D3dDev, D3DRS_SRCBLENDALPHA, D3DBLEND_ONE));
3129    S3D_DRV_D3D9_CHECK(
3130            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
3131                m_D3dDev, D3DRS_DESTBLENDALPHA, D3DBLEND_ZERO));
3132    S3D_DRV_D3D9_CHECK(
3133            &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
3134                m_D3dDev, D3DRS_BLENDOPALPHA, D3DBLENDOP_ADD));
3135}
3136
3137///////////////////////////////////////////////////////////////////////////////
3138
3139void s3d_CDrvD3d9GfxEngCLOD::CalcProjOffs(
3140        float &ProjOffsX, float &ProjOffsY, int Width, int Height)
3141{
3142    ProjOffsX = -1.0f / s3d_SysFloatOfInt<float>(Width);
3143    ProjOffsY = 1.0f / s3d_SysFloatOfInt<float>(Height);
3144}
3145
3146void s3d_CDrvD3d9GfxEngCLOD::SetProjOffs(
3147        const float &ProjOffsX, const float &ProjOffsY)
3148{
3149    if(m_CurProjOffsX != ProjOffsX || m_CurProjOffsY != ProjOffsY)
3150    {
3151        m_CurProjOffsX = ProjOffsX;
3152        m_CurProjOffsY = ProjOffsY;
3153        m_MatProjDirty = true;
3154    }
3155}
3156
3157///////////////////////////////////////////////////////////////////////////////
3158
3159void s3d_CDrvD3d9GfxEngCLOD::InitTexturing()
3160{
3161    if(!m_D3dDev)
3162        return;
3163
3164    m_MaxAttrCnt = m_DevCaps.MaxTextureBlendStages;
3165    if(m_MaxAttrCnt > S3D_DRV_D3D9_MAX_ATTR_CNT)
3166    {
3167        m_MaxAttrCnt = S3D_DRV_D3D9_MAX_ATTR_CNT;
3168        S3D_SYS_ASSERT(0);
3169    }
3170
3171    int iAttr;
3172    for(iAttr = 0; iAttr < m_MaxAttrCnt; iAttr++)
3173    {
3174        LPD3DXMATRIXA16 MatGen = &m_ParamBlk.m_MatGenArray[iAttr];
3175        D3DXMatrixIdentity(MatGen);
3176        m_CurTexTransfFlagsArray[iAttr] = D3DTTFF_DISABLE;
3177        m_CurTexOpArray[iAttr] = D3DTOP_DISABLE;
3178
3179        S3D_DRV_D3D9_CHECK(
3180                &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateI(
3181                    m_D3dDev, iAttr, D3DTSS_COLOROP, D3DTOP_DISABLE));
3182        S3D_DRV_D3D9_CHECK(
3183                &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateI(
3184                    m_D3dDev, iAttr, D3DTSS_ALPHAOP, D3DTOP_DISABLE));
3185        S3D_DRV_D3D9_CHECK(
3186                &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateI(
3187                    m_D3dDev, iAttr, D3DTSS_TEXCOORDINDEX, iAttr));
3188
3189        D3DTRANSFORMSTATETYPE TransfState
3190                = D3DTRANSFORMSTATETYPE(iAttr + D3DTS_TEXTURE0);
3191        S3D_DRV_D3D9_CHECK(
3192                &m_Env, m_D3dDev->SetTransform(TransfState, MatGen));
3193    }
3194
3195    // The number of texture samplers available to the application is
3196    // determined by the pixel shader version
3197    // ps_1_1 to ps_1_3 4 texture samplers
3198    // ps_1_4 6 texture samplers
3199    // ps_2_0 16 texture samplers
3200    // fixed function pipeline:
3201    // MaxTextureBlendStages/MaxSimultaneousTextures texture samplers
3202    m_MaxSampCnt = m_DevCaps.MaxSimultaneousTextures;
3203    int PSVerMajor = D3DSHADER_VERSION_MAJOR(m_DevCaps.PixelShaderVersion);
3204    int PSVerMinor = D3DSHADER_VERSION_MINOR(m_DevCaps.PixelShaderVersion);
3205    if(PSVerMajor >= 2)
3206        m_MaxSampCnt = S3D_DRV_D3D9_MAX_SAMPLER_CNT;
3207    else if(PSVerMajor < 2)
3208    {
3209        if(PSVerMinor >= 4)
3210            m_MaxSampCnt = 6;
3211        else if(PSVerMinor >= 1 && PSVerMinor < 3)
3212            m_MaxSampCnt = 4;
3213    }
3214    if(m_MaxSampCnt > S3D_DRV_D3D9_MAX_SAMPLER_CNT)
3215    {
3216        m_MaxSampCnt = S3D_DRV_D3D9_MAX_SAMPLER_CNT;
3217        S3D_SYS_ASSERT(0);
3218    }
3219   
3220    if(m_D3dParam->m_MaxMipLevels < 0)
3221        m_D3dParam->m_MaxMipLevels = 0;
3222
3223    if(m_D3dParam->m_MaxAnisoTropy < 0)
3224        m_D3dParam->m_MaxAnisoTropy = 1;
3225    if(DWORD(m_D3dParam->m_MaxAnisoTropy) > m_DevCaps.MaxAnisotropy)
3226        m_D3dParam->m_MaxAnisoTropy = m_DevCaps.MaxAnisotropy;       
3227
3228    int iSamp;
3229    for(iSamp = 0; iSamp < S3D_DRV_D3D9_MAX_SAMPLER_CNT; iSamp++)
3230    {
3231        m_ParamBlk.m_SampTexArray[iSamp] = 0;
3232        m_WantSampTexArray[iSamp] = 0;
3233        m_SampModeArray[iSamp] = 0;
3234        m_CurSampParamArray[iSamp].m_FilterMin = D3DTEXF_POINT;
3235        m_CurSampParamArray[iSamp].m_FilterMag = D3DTEXF_POINT;
3236        m_CurSampParamArray[iSamp].m_FilterMip = D3DTEXF_NONE;
3237        m_CurSampParamArray[iSamp].m_AddrX = D3DTADDRESS_WRAP;
3238        m_CurSampParamArray[iSamp].m_AddrY = D3DTADDRESS_WRAP;
3239        m_CurSampParamArray[iSamp].m_AddrZ = D3DTADDRESS_WRAP;
3240        m_CurSampParamArray[iSamp].m_SRGBTex = FALSE;
3241
3242        if(iSamp < m_MaxSampCnt)
3243        {
3244            S3D_DRV_D3D9_CHECK(
3245                    &m_Env, m_D3dDev->SetTexture(iSamp, 0));
3246            S3D_DRV_D3D9_CHECK(
3247                    &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI(
3248                        m_D3dDev, iSamp, D3DSAMP_MAGFILTER, D3DTEXF_POINT));
3249            S3D_DRV_D3D9_CHECK(
3250                    &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI(
3251                        m_D3dDev, iSamp, D3DSAMP_MINFILTER, D3DTEXF_POINT));
3252            S3D_DRV_D3D9_CHECK(
3253                    &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI(
3254                        m_D3dDev, iSamp, D3DSAMP_MIPFILTER, D3DTEXF_NONE));
3255            S3D_DRV_D3D9_CHECK(
3256                    &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI(
3257                        m_D3dDev, iSamp, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP));
3258            S3D_DRV_D3D9_CHECK(
3259                    &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI(
3260                        m_D3dDev, iSamp, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP));
3261            S3D_DRV_D3D9_CHECK(
3262                    &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI(
3263                        m_D3dDev, iSamp, D3DSAMP_ADDRESSW, D3DTADDRESS_WRAP));
3264            S3D_DRV_D3D9_CHECK(
3265                    &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI(
3266                        m_D3dDev, iSamp,
3267                        D3DSAMP_MAXMIPLEVEL, m_D3dParam->m_MaxMipLevels));
3268            S3D_DRV_D3D9_CHECK(
3269                    &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI(
3270                        m_D3dDev, iSamp,
3271                        D3DSAMP_MAXANISOTROPY, m_D3dParam->m_MaxAnisoTropy));
3272            S3D_DRV_D3D9_CHECK(
3273                    &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI(
3274                        m_D3dDev, iSamp, D3DSAMP_SRGBTEXTURE, FALSE));
3275        }
3276    }
3277
3278    m_ParamBlk.m_SampMaxUsedCnt = 0;
3279    m_SampMaxWantCnt = 0;
3280
3281    m_MinLbTexWidth =  m_D3dParam->m_MinLbTexWidth;
3282    m_MaxLbTexWidth = 8;
3283    int MaxTexWidth = m_DevCaps.MaxTextureWidth;
3284    if(MaxTexWidth > 0)
3285        m_MaxLbTexWidth = s3d_CDrvUtilGfxUtil::BinLogDownInt(MaxTexWidth);
3286
3287    m_MinLbTexHeight =  m_D3dParam->m_MinLbTexHeight;
3288    m_MaxLbTexHeight = 8;
3289    int MaxTexHeight = m_DevCaps.MaxTextureHeight;
3290    if(MaxTexHeight > 0)
3291        m_MaxLbTexHeight = s3d_CDrvUtilGfxUtil::BinLogDownInt(MaxTexHeight);
3292
3293    m_MinLbVolTexExt = m_D3dParam->m_MinLbVolTexExt;
3294    m_MaxLbVolTexExt = 8;
3295    int MaxVolExt = m_DevCaps.MaxVolumeExtent;
3296    if(MaxVolExt > 0)
3297        m_MaxLbVolTexExt = s3d_CDrvUtilGfxUtil::BinLogDownInt(MaxVolExt);
3298
3299    m_MaxFilterMinStd = D3DTEXF_LINEAR;
3300    m_MaxFilterMagStd = D3DTEXF_LINEAR;
3301    m_MaxFilterMinCube = D3DTEXF_LINEAR;
3302    m_MaxFilterMagCube = D3DTEXF_LINEAR;
3303    m_MaxFilterMinVol = D3DTEXF_LINEAR;
3304    m_MaxFilterMagVol = D3DTEXF_LINEAR;
3305
3306    if(m_D3dParam->m_MaxAnisoTropy > 1)
3307    {
3308        if(m_DevCaps.TextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC)
3309            m_MaxFilterMinStd = D3DTEXF_ANISOTROPIC;
3310        if(m_DevCaps.TextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC)
3311            m_MaxFilterMagStd = D3DTEXF_ANISOTROPIC;
3312
3313        if(m_DevCaps.CubeTextureFilterCaps &
3314                D3DPTFILTERCAPS_MINFANISOTROPIC)
3315            m_MaxFilterMinCube = D3DTEXF_ANISOTROPIC;
3316        if(m_DevCaps.CubeTextureFilterCaps &
3317                D3DPTFILTERCAPS_MAGFANISOTROPIC)
3318            m_MaxFilterMagCube = D3DTEXF_ANISOTROPIC;
3319
3320        if(m_DevCaps.VolumeTextureFilterCaps &
3321                D3DPTFILTERCAPS_MINFANISOTROPIC)
3322            m_MaxFilterMinVol = D3DTEXF_ANISOTROPIC;
3323        if(m_DevCaps.VolumeTextureFilterCaps &
3324                D3DPTFILTERCAPS_MAGFANISOTROPIC)
3325            m_MaxFilterMagVol = D3DTEXF_ANISOTROPIC;
3326    }
3327
3328    m_MaxFilterMipStd = D3DTEXF_POINT;
3329    m_MaxFilterMipCube = D3DTEXF_POINT;
3330    m_MaxFilterMipVol = D3DTEXF_POINT;
3331    if(m_DevCaps.TextureFilterCaps & D3DPTFILTERCAPS_MIPFLINEAR)
3332        m_MaxFilterMipStd = D3DTEXF_LINEAR;
3333    if(m_DevCaps.CubeTextureFilterCaps & D3DPTFILTERCAPS_MIPFLINEAR)
3334        m_MaxFilterMipCube = D3DTEXF_LINEAR;
3335    if(m_DevCaps.VolumeTextureFilterCaps & D3DPTFILTERCAPS_MIPFLINEAR)
3336        m_MaxFilterMipVol = D3DTEXF_LINEAR;
3337}
3338
3339void s3d_CDrvD3d9GfxEngCLOD::SetTexOpTransf(
3340        int Attr, D3DTEXTUREOP Op, D3DTEXTURETRANSFORMFLAGS TransfFlag)
3341{
3342    if(!m_D3dDev)
3343        return;
3344
3345    if(s3d_SysIsValidArrayIdx(Attr, m_MaxAttrCnt))
3346    {
3347        if(m_CurTexOpArray[Attr] != Op)
3348        {
3349            m_CurTexOpArray[Attr] = Op;
3350            S3D_DRV_D3D9_CHECK(
3351                    &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateI(
3352                        m_D3dDev, Attr, D3DTSS_COLOROP, Op));
3353            S3D_DRV_D3D9_CHECK(
3354                    &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateI(
3355                        m_D3dDev, Attr, D3DTSS_ALPHAOP, Op));
3356        }
3357        if(m_CurTexTransfFlagsArray[Attr] != TransfFlag)
3358        {
3359            m_CurTexTransfFlagsArray[Attr] = TransfFlag;
3360            S3D_DRV_D3D9_CHECK(
3361                    &m_Env, s3d_CDrvD3d9StateUtil::SetTextureStageStateI(
3362                        m_D3dDev, Attr,
3363                        D3DTSS_TEXTURETRANSFORMFLAGS, TransfFlag));
3364        }
3365    }
3366}
3367
3368void s3d_CDrvD3d9GfxEngCLOD::UpdateSampParam(
3369        s3d_CSysIntps Samp, const s3d_CDrvD3d9TexObjBase *Tex)
3370{
3371    if(Samp < 0 || Samp >= m_MaxSampCnt)
3372        return;
3373    if(!Tex)
3374        return;
3375
3376    D3DRESOURCETYPE TexType = D3DRTYPE_TEXTURE;
3377    if(Tex->m_BaseTex)
3378        TexType = Tex->m_BaseTex->GetType();
3379    s3d_CDrvD3d9SampParam *SampParam = &m_CurSampParamArray[Samp];
3380    int SampMode = m_SampModeArray[Samp];
3381   
3382    D3DTEXTUREADDRESS SampAddrX, SampAddrY, SampAddrZ;
3383    AddrOfSampMode(
3384            SampMode, SampAddrX, SampAddrY, SampAddrZ);
3385
3386    if(SampParam->m_AddrX != SampAddrX)
3387    {
3388        SampParam->m_AddrX = SampAddrX;
3389        S3D_DRV_D3D9_CHECK(
3390                &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI(
3391                    m_D3dDev, Samp, D3DSAMP_ADDRESSU, SampAddrX));
3392    }
3393    if(SampParam->m_AddrY != SampAddrY)
3394    {
3395        SampParam->m_AddrY = SampAddrY;
3396        S3D_DRV_D3D9_CHECK(
3397                &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI(
3398                    m_D3dDev, Samp, D3DSAMP_ADDRESSV, SampAddrY));
3399    }
3400    if(TexType == D3DRTYPE_VOLUMETEXTURE
3401            && SampParam->m_AddrZ != SampAddrZ)
3402    {
3403        SampParam->m_AddrZ = SampAddrZ;
3404        S3D_DRV_D3D9_CHECK(
3405                &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI(
3406                    m_D3dDev, Samp, D3DSAMP_ADDRESSW, SampAddrZ));
3407    }
3408
3409    D3DTEXTUREFILTERTYPE FilterMin, FilterMag, FilterMip;
3410    FilterOfSampMode(
3411            SampMode, Tex, FilterMin, FilterMag, FilterMip);
3412
3413    // Set first Mag, otherwise not working correctly (why?)...
3414    if(SampParam->m_FilterMag != FilterMag)
3415    {
3416        SampParam->m_FilterMag = FilterMag;
3417        S3D_DRV_D3D9_CHECK(
3418                &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI(
3419                    m_D3dDev, Samp, D3DSAMP_MAGFILTER, FilterMag));
3420    }
3421    if(SampParam->m_FilterMin != FilterMin)
3422    {
3423        SampParam->m_FilterMin = FilterMin;
3424        S3D_DRV_D3D9_CHECK(
3425                &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI(
3426                    m_D3dDev, Samp, D3DSAMP_MINFILTER, FilterMin));
3427    }
3428
3429    if(SampParam->m_FilterMip != FilterMip)
3430    {
3431        SampParam->m_FilterMip = FilterMip;
3432        S3D_DRV_D3D9_CHECK(
3433                &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI(
3434                    m_D3dDev, Samp, D3DSAMP_MIPFILTER, FilterMip));
3435    }
3436
3437    BOOL SRGBTex = BOOL(Tex->m_TexFmt.m_SRGBRead);
3438    if(SampParam->m_SRGBTex != SRGBTex)
3439    {
3440        SampParam->m_SRGBTex = SRGBTex;
3441        S3D_DRV_D3D9_CHECK(
3442                &m_Env, s3d_CDrvD3d9StateUtil::SetSamplerStateI(
3443                    m_D3dDev, Samp, D3DSAMP_SRGBTEXTURE, SRGBTex));
3444    }
3445}
3446
3447void s3d_CDrvD3d9GfxEngCLOD::AddrOfSampMode(
3448        int SampMode, D3DTEXTUREADDRESS &AddrX,
3449        D3DTEXTUREADDRESS &AddrY, D3DTEXTUREADDRESS &AddrZ)
3450{
3451    AddrX = D3DTADDRESS_WRAP;
3452    if(SampMode & s3d_CDrvGfxEng::SampMode_ClampX)
3453        AddrX = D3DTADDRESS_CLAMP;
3454    else if(SampMode & s3d_CDrvGfxEng::SampMode_MirrorX)
3455        AddrX = D3DTADDRESS_MIRROR;
3456
3457    AddrY = D3DTADDRESS_WRAP;
3458    if(SampMode & s3d_CDrvGfxEng::SampMode_ClampY)
3459        AddrY = D3DTADDRESS_CLAMP;
3460    else if(SampMode & s3d_CDrvGfxEng::SampMode_MirrorY)
3461        AddrY = D3DTADDRESS_MIRROR;
3462   
3463    AddrZ = D3DTADDRESS_WRAP;
3464    if(SampMode & s3d_CDrvGfxEng::SampMode_ClampZ)
3465        AddrZ = D3DTADDRESS_CLAMP;
3466    else if(SampMode & s3d_CDrvGfxEng::SampMode_MirrorZ)
3467        AddrZ = D3DTADDRESS_MIRROR;
3468}
3469
3470void s3d_CDrvD3d9GfxEngCLOD::FilterOfSampMode(
3471        int SampMode, const s3d_CDrvD3d9TexObjBase *Tex,
3472        D3DTEXTUREFILTERTYPE &FilterMin, D3DTEXTUREFILTERTYPE &FilterMag,
3473        D3DTEXTUREFILTERTYPE &FilterMip)
3474{
3475    FilterMin = D3DTEXF_POINT;
3476    FilterMag = D3DTEXF_POINT;
3477    FilterMip = D3DTEXF_NONE;
3478
3479    bool CanFilter = Tex->m_TexFmt.m_CanFilter;
3480    int TexProp = Tex->m_Prop;
3481    if((SampMode & s3d_CDrvGfxEng::SampMode_Filter) != 0 && CanFilter)
3482    {
3483        if((TexProp & s3d_CDrvGfxEng::TexProp_Cube) != 0)
3484        {
3485            FilterMin = m_MaxFilterMinCube;
3486            FilterMag = m_MaxFilterMagCube;
3487        }
3488        else if((TexProp & s3d_CDrvGfxEng::TexProp_Volume) != 0)
3489        {
3490            FilterMin = m_MaxFilterMinVol;
3491            FilterMag = m_MaxFilterMagVol;
3492        }
3493        else
3494        {
3495            FilterMin = m_MaxFilterMinStd;
3496            FilterMag = m_MaxFilterMagStd;
3497        }
3498    }
3499
3500    if((TexProp & s3d_CDrvGfxEng::TexProp_Mipmap) != 0)
3501    {
3502        FilterMip = D3DTEXF_POINT;
3503        if(CanFilter)
3504        {
3505            if((TexProp & s3d_CDrvGfxEng::TexProp_Cube) != 0)
3506                FilterMip = m_MaxFilterMipCube;
3507            else if((TexProp & s3d_CDrvGfxEng::TexProp_Volume) != 0)
3508                FilterMip = m_MaxFilterMipVol;
3509            else
3510                FilterMip = m_MaxFilterMipStd;
3511        }
3512    }
3513}
3514
3515///////////////////////////////////////////////////////////////////////////////
3516
3517void s3d_CDrvD3d9GfxEngCLOD::Clear(
3518        s3d_CDrvGfxClearParam_cr ClearParam)
3519{
3520    if(!ClearParam.m_MustColorAlpha
3521                && !ClearParam.m_MustDepth
3522                && !ClearParam.m_MustStencil)
3523        return;
3524
3525    if(!m_D3dDev)
3526        return;
3527
3528    SetViewRect(1);
3529    SetViewDepthRange(0, 1);
3530    SetDepthWrite(true);
3531    SetBlendMode(
3532            BlendFac_One, BlendFac_Zero, BlendOp_SrcPlusDest,
3533            BlendFac_One, BlendFac_Zero, BlendOp_SrcPlusDest);
3534    SetStencilMode(
3535            0, 0, TestMode_Always, TestMode_Always,
3536            -1,
3537            StencilOp_Keep, StencilOp_Keep, StencilOp_Keep,
3538            StencilOp_Keep, StencilOp_Keep, StencilOp_Keep);
3539
3540    m_StateMgr.Apply(m_State);
3541   
3542    D3DCOLOR D3dColor = S3D_DRV_D3D9_UTIL_COLORVALUE(
3543            ClearParam.m_ColorAlpha.m_x,
3544            ClearParam.m_ColorAlpha.m_y,
3545            ClearParam.m_ColorAlpha.m_z, 1);
3546
3547/*
3548    if(m_DestCnt)
3549        D3dColor = rand() * WORD(-1);
3550*/
3551
3552    DWORD D3dFlags;
3553    D3dFlags = D3DCLEAR_TARGET;
3554    if(ClearParam.m_MustDepth || ClearParam.m_MustStencil)
3555    {
3556        D3dFlags |= D3DCLEAR_ZBUFFER;
3557        if(m_BufStencilBits > 0)
3558            D3dFlags |= D3DCLEAR_STENCIL;
3559    }
3560    int nRect = 1;
3561    if(m_BufWidth <= 0 || m_BufHeight <= 0)
3562        nRect = 0;
3563    D3DRECT Rect = {0, 0, m_BufWidth, m_BufHeight};
3564    S3D_DRV_D3D9_CHECK(
3565            &m_Env, m_D3dDev->Clear(
3566                nRect, &Rect, D3dFlags, D3dColor,
3567                ClearParam.m_Depth, ClearParam.m_Stencil));
3568}
3569
3570///////////////////////////////////////////////////////////////////////////////
3571
3572void s3d_CDrvD3d9GfxEngCLOD::SelectBuffers(
3573        s3d_CDrvD3d9VertBufObj *VertBufObj, s3d_CDrvD3d9IdxBufObj *IdxBufObj)
3574{
3575    if(!m_D3dDev)
3576        return;
3577    if(!VertBufObj)
3578        return;
3579    if(!IdxBufObj)
3580        return;
3581    if(!m_BufMgr)
3582        return;
3583
3584    if(m_CurVertBufObj != VertBufObj)
3585    {
3586        m_CurVertBufObj = VertBufObj;
3587        UINT StreamIdx = 0;
3588        UINT Offset = 0;
3589        UINT Stride = UINT(VertBufObj->m_VertSize);
3590        S3D_DRV_D3D9_CHECK(
3591                &m_Env, m_D3dDev->SetStreamSource(
3592                StreamIdx, VertBufObj->m_VertBuf, Offset, Stride));
3593    }
3594    if(m_CurVertDecl != VertBufObj->m_VertDecl)
3595    {
3596        m_CurVertDecl = VertBufObj->m_VertDecl;
3597        S3D_DRV_D3D9_CHECK(
3598                &m_Env, m_D3dDev->SetVertexDeclaration(m_CurVertDecl));
3599    }
3600
3601    if(!m_D3dParam->m_NoDummyBoneVertexBuf)
3602    {
3603        int VertBufFmtDecl = VertBufObj->m_VertBufFmtDecl;
3604        if((VertBufFmtDecl & s3d_CDrvD3d9VertBufDesc::Decl_DummyBoneWgh)
3605            || (VertBufFmtDecl
3606                    & s3d_CDrvD3d9VertBufDesc::Decl_DummyBoneSubscr))
3607        {
3608            if(m_D3dParam->m_PixEnabled)
3609            {
3610                s3d_CDrvD3d9PixEvent::SetMarker(
3611                        "*** Using DummyBoneWghIdx ***",
3612                        S3D_DRV_D3D9_PIX_STD_COLOR);
3613            }
3614
3615            LPDIRECT3DVERTEXBUFFER9 VertBuf
3616                    = m_BufMgr->GetVertBufDummyBlendWghIdx();
3617            if(m_CurVertBufDummyBlendWghIdx != VertBuf)
3618            {
3619                m_CurVertBufDummyBlendWghIdx = VertBuf;
3620                UINT StreamIdx = S3D_DRV_D3D9_DUMMY_BLENDWGHIDX_STREAM;
3621                UINT Offset = 0;
3622                UINT Stride = 0;
3623                S3D_DRV_D3D9_CHECK(
3624                        &m_Env, m_D3dDev->SetStreamSource(
3625                            StreamIdx, m_CurVertBufDummyBlendWghIdx,
3626                            Offset, Stride));
3627            }
3628        }
3629        else if(m_CurVertBufDummyBlendWghIdx)
3630        {
3631            m_CurVertBufDummyBlendWghIdx = 0;
3632            UINT StreamIdx = S3D_DRV_D3D9_DUMMY_BLENDWGHIDX_STREAM;
3633            UINT Offset = 0;
3634            UINT Stride = 0;
3635            S3D_DRV_D3D9_CHECK(
3636                    &m_Env, m_D3dDev->SetStreamSource(
3637                        StreamIdx, 0, Offset, Stride));
3638        }
3639    }
3640
3641    if(m_CurIdxBufObj != IdxBufObj)
3642    {
3643        m_CurIdxBufObj = IdxBufObj;
3644        S3D_DRV_D3D9_CHECK(
3645                &m_Env, m_D3dDev->SetIndices(IdxBufObj->m_IdxBuf));
3646    }
3647}
3648
3649void s3d_CDrvD3d9GfxEngCLOD::SelectProg(
3650        const s3d_CSysChar *Info, s3d_CDrvGfxProg *Prog,
3651        const s3d_CSysChar *BufInfo, const s3d_CSysChar *BufDesc,
3652        const s3d_CDrvD3d9VertDecl &VertDecl,
3653        s3d_CDrvGfxParam_cr GfxParam)
3654{
3655    s3d_CDrvD3d9Prog *ProgImpl
3656            = s3d_UtilRecogCastSilent<s3d_CDrvD3d9Prog>(Prog);
3657
3658    m_ProgMgr->SelectProg(
3659            Info, ProgImpl,
3660            BufInfo, BufDesc, VertDecl, GfxParam,
3661            m_ParamBlk, m_ParamStateProg);
3662}
3663
3664void s3d_CDrvD3d9GfxEngCLOD::BeginDraw(
3665        const s3d_CSysChar *Info, int VertBufFmtDecl, bool UseFFP)
3666{
3667    m_StateMgr.Apply(m_State);
3668
3669    if(m_MatProjDirty)
3670    {
3671        m_MatProjDirty = false;
3672        m_ParamStateProg.m_DirtyMask
3673                |= s3d_CDrvD3d9ParamBlkState::Dirty_MatProj;
3674        m_ParamStateFFP.m_DirtyMask
3675                |= s3d_CDrvD3d9ParamBlkState::Dirty_MatProj;
3676
3677        // Adjust for texel->pixel mapping
3678        LPD3DXMATRIXA16 EffMatProj = &m_ParamBlk.m_MatProj;
3679        *EffMatProj = m_MatProj;
3680        EffMatProj->_11 += m_CurProjOffsX * EffMatProj->_41;
3681        EffMatProj->_12 += m_CurProjOffsX * EffMatProj->_42;
3682        EffMatProj->_13 += m_CurProjOffsX * EffMatProj->_43;
3683        EffMatProj->_14 += m_CurProjOffsX * EffMatProj->_44;
3684        EffMatProj->_21 += m_CurProjOffsY * EffMatProj->_41;
3685        EffMatProj->_22 += m_CurProjOffsY * EffMatProj->_42;
3686        EffMatProj->_23 += m_CurProjOffsY * EffMatProj->_43;
3687        EffMatProj->_24 += m_CurProjOffsY * EffMatProj->_44;
3688    }
3689
3690    if(UseFFP)
3691        BeginDrawFFP(Info, VertBufFmtDecl);
3692    else
3693        BeginDrawProg(Info, VertBufFmtDecl);
3694}
3695
3696void s3d_CDrvD3d9GfxEngCLOD::BeginDrawFFP(
3697        const s3d_CSysChar *Info, int VertBufFmtDecl)
3698{
3699    if(!m_D3dDev)
3700        return;
3701
3702    if(m_ParamStateFFP.m_DirtyMask
3703            & s3d_CDrvD3d9ParamBlkState::Dirty_MatProj)
3704    {
3705        D3DXMATRIXA16 Temp;
3706        D3DXMatrixTranspose(&Temp, &m_ParamBlk.m_MatProj);
3707        S3D_DRV_D3D9_CHECK(
3708                &m_Env, m_D3dDev->SetTransform(D3DTS_PROJECTION, &Temp));
3709    }
3710
3711    if(m_ParamStateFFP.m_DirtyMask
3712            & s3d_CDrvD3d9ParamBlkState::Dirty_MatView)
3713    {
3714        D3DXMATRIXA16 Temp;
3715        D3DXMatrixTranspose(&Temp, &m_ParamBlk.m_MatView);
3716        S3D_DRV_D3D9_CHECK(
3717                &m_Env, m_D3dDev->SetTransform(D3DTS_WORLD, &Temp));
3718    }
3719
3720    if((m_ParamStateFFP.m_DirtyMask
3721            & s3d_CDrvD3d9ParamBlkState::Dirty_Light)
3722        || !m_PrevUsedFFP)
3723    {
3724        const D3DLIGHT9 *Light = m_ParamBlk.m_LightArray;
3725        s3d_CSysIntps NewLightCnt = m_WantLightCnt;
3726        S3D_SYS_ASSERT(NewLightCnt >= 0);
3727        s3d_CSysIntps iLight;
3728        for(iLight = 0; iLight < NewLightCnt; iLight++)
3729        {
3730            // Light parameters have changed.
3731            if(m_LightDirtyArray[iLight])
3732            {
3733                m_LightDirtyArray[iLight] = false;
3734                S3D_DRV_D3D9_CHECK(
3735                        &m_Env, m_D3dDev->SetLight(DWORD(iLight), Light));
3736            }
3737            // Enabled light if its currently disabled.
3738            if(!m_LightEnabledArray[iLight])
3739            {
3740                m_LightEnabledArray[iLight] = true;
3741                S3D_DRV_D3D9_CHECK(
3742                        &m_Env, m_D3dDev->LightEnable(DWORD(iLight), TRUE));
3743            }
3744            Light++;
3745        }
3746
3747        // Disable previous lights if necessary.
3748        for(iLight = NewLightCnt; iLight < m_ParamBlk.m_CurLightCnt;
3749                iLight++)
3750        {
3751            if(m_LightEnabledArray[iLight])
3752            {
3753                m_LightEnabledArray[iLight] = false;
3754                S3D_DRV_D3D9_CHECK(
3755                        &m_Env, m_D3dDev->LightEnable(DWORD(iLight), FALSE));
3756            }
3757        }
3758       
3759        EnabledLighting(m_WantLighting);
3760        m_ParamBlk.m_CurLightCnt = NewLightCnt;
3761    }
3762
3763    // On pipeline switch set m_SampMaxWantCnt to m_SampMaxUsedCnt so we
3764    // can update tex transformflags.
3765    // If is m_SampMaxWantCnt > 0 set it to m_SampMaxUsedCnt as well, so we
3766    // can calcualte new m_SampMaxUsedCnt;
3767    if(m_SampMaxWantCnt > 0 || !m_PrevUsedFFP)
3768        s3d_SysSetToMax(m_SampMaxWantCnt, m_ParamBlk.m_SampMaxUsedCnt);
3769   
3770    s3d_CSysIntps SampUseCnt = 0;
3771    s3d_CSysIntps iSamp;
3772    for(iSamp = 0; iSamp < m_SampMaxWantCnt; iSamp++)
3773    {
3774        s3d_CDrvD3d9TexObjBase *Tex = m_WantSampTexArray[iSamp];
3775        LPDIRECT3DBASETEXTURE9 BaseTex = 0;
3776
3777        if(m_ParamBlk.m_SampTexArray[iSamp] != Tex)
3778        {
3779            m_ParamBlk.m_SampTexArray[iSamp] = Tex;
3780            if(Tex)
3781                BaseTex = Tex->m_BaseTex;
3782
3783            S3D_DRV_D3D9_CHECK(
3784                    &m_Env, m_D3dDev->SetTexture(iSamp, BaseTex));
3785        }
3786
3787        if(Tex)
3788        {
3789            s3d_SysSetToMax(SampUseCnt, iSamp + 1);
3790            // In FFP, only support 2d texture coordinates:
3791            SetTexOpTransf(iSamp, D3DTOP_MODULATE, D3DTTFF_COUNT2);
3792            UpdateSampParam(iSamp, Tex);
3793        }
3794        else
3795            SetTexOpTransf(iSamp, D3DTOP_DISABLE, D3DTTFF_DISABLE);
3796    }
3797   
3798    if(m_SampMaxWantCnt > 0)
3799    {
3800        m_ParamBlk.m_SampMaxUsedCnt = SampUseCnt;
3801        m_SampMaxWantCnt = 0;
3802    }
3803   
3804    for(iSamp = 0; iSamp < m_ParamBlk.m_SampMaxUsedCnt; iSamp++)
3805    {
3806        s3d_CDrvD3d9TexObjBase *Tex = m_ParamBlk.m_SampTexArray[iSamp];
3807        if(Tex)
3808            Tex->UpdateToFrm(m_FrmIdx);
3809    }
3810
3811    if(m_ParamStateFFP.m_DirtyMask
3812            & s3d_CDrvD3d9ParamBlkState::Dirty_MatGen)
3813    {
3814        int nAttr = s3d_SysMin(m_ParamBlk.m_SampMaxUsedCnt, m_MaxAttrCnt);
3815        for(int iAttr = 0; iAttr < nAttr; iAttr++)
3816        {
3817            LPD3DXMATRIXA16 AttrMat = &m_ParamBlk.m_MatGenArray[iAttr];
3818            D3DXMATRIXA16 Temp;
3819            if(!D3DXMatrixIsIdentity(AttrMat))
3820            {
3821                D3DXMatrixTranspose(&Temp, AttrMat);
3822                AttrMat = &Temp;
3823            }
3824            S3D_DRV_D3D9_CHECK(
3825                    &m_Env, m_D3dDev->SetTransform(
3826                        D3DTRANSFORMSTATETYPE(
3827                                iAttr + D3DTS_TEXTURE0), AttrMat));
3828        }
3829    }
3830
3831    // Const color emulation if vertex has no color info
3832    if(!m_WantLighting
3833        && (VertBufFmtDecl & s3d_CDrvD3d9VertBufDesc::Decl_ColorAlpha) == 0)
3834    {
3835        m_ParamBlk.m_UseConstColorAlpha = true;
3836
3837        D3DMATERIAL9 Mtl;
3838        Mtl.Ambient = m_ParamBlk.m_ColorAlphaVal;
3839        Mtl.Diffuse = m_ParamBlk.m_ColorAlphaVal;
3840        Mtl.Specular = m_ParamBlk.m_ColorAlphaVal;
3841        Mtl.Emissive = m_ParamBlk.m_ColorAlphaVal;
3842        Mtl.Power = 0.f;
3843        S3D_DRV_D3D9_CHECK(
3844                &m_Env, m_D3dDev->SetMaterial(&Mtl));
3845        EnabledLighting(true);
3846    }
3847    else if(m_ParamStateFFP.m_DirtyMask
3848            & s3d_CDrvD3d9ParamBlkState::Dirty_Mtl)
3849    {
3850        S3D_DRV_D3D9_CHECK(
3851                &m_Env, m_D3dDev->SetMaterial(&m_ParamBlk.m_Mtl));
3852    }
3853
3854    m_ParamStateFFP.Done();
3855}
3856
3857void s3d_CDrvD3d9GfxEngCLOD::EndDrawFFP(
3858        const s3d_CSysChar *Info)
3859{
3860    if(m_ParamBlk.m_UseConstColorAlpha)
3861    {
3862        EnabledLighting(false);
3863        m_ParamBlk.m_UseConstColorAlpha = false;
3864        m_ParamStateFFP.m_DirtyMask |= s3d_CDrvD3d9ParamBlkState::Dirty_Mtl;
3865    }
3866    m_PrevUsedFFP = true;
3867}
3868
3869void s3d_CDrvD3d9GfxEngCLOD::BeginDrawProg(
3870        const s3d_CSysChar *Info, int VertBufFmtDecl)
3871{
3872    if(!m_D3dDev)
3873        return;
3874
3875    // On pipeline switch set m_SampMaxWantCnt to m_SampMaxUsedCnt so we
3876    // can update tex transformflags.
3877    // If is m_SampMaxWantCnt > 0 set it to m_SampMaxUsedCnt as well, so we
3878    // can calcualte new m_SampMaxUsedCnt;
3879    if(m_SampMaxWantCnt > 0 || m_PrevUsedFFP)
3880        s3d_SysSetToMax(m_SampMaxWantCnt, m_ParamBlk.m_SampMaxUsedCnt);
3881   
3882    s3d_CSysIntps SampUseCnt = 0;
3883    s3d_CSysIntps iSamp;
3884    for(iSamp = 0; iSamp < m_SampMaxWantCnt; iSamp++)
3885    {
3886        s3d_CDrvD3d9TexObjBase *Tex = m_WantSampTexArray[iSamp];
3887        LPDIRECT3DBASETEXTURE9 BaseTex = 0;
3888
3889        if(m_ParamBlk.m_SampTexArray[iSamp] != Tex)
3890        {
3891            m_ParamBlk.m_SampTexArray[iSamp] = Tex;
3892            if(Tex)
3893                BaseTex = Tex->m_BaseTex;
3894
3895            S3D_DRV_D3D9_CHECK(
3896                    &m_Env, m_D3dDev->SetTexture(iSamp, BaseTex));
3897        }
3898
3899        if(Tex)
3900        {
3901            s3d_SysSetToMax(SampUseCnt, iSamp + 1);
3902            UpdateSampParam(iSamp, Tex);
3903        }
3904
3905        SetTexOpTransf(iSamp, D3DTOP_DISABLE, D3DTTFF_DISABLE);
3906    }
3907   
3908    if(m_SampMaxWantCnt > 0)
3909    {
3910        m_ParamBlk.m_SampMaxUsedCnt = SampUseCnt;
3911        m_SampMaxWantCnt = 0;
3912    }
3913   
3914    for(iSamp = 0; iSamp < m_ParamBlk.m_SampMaxUsedCnt; iSamp++)
3915    {
3916        s3d_CDrvD3d9TexObjBase *Tex = m_ParamBlk.m_SampTexArray[iSamp];
3917        if(Tex)
3918            Tex->UpdateToFrm(m_FrmIdx);
3919    }
3920
3921    // Const color emulation if vertex has no color info
3922    if(!m_WantLighting
3923        && (VertBufFmtDecl & s3d_CDrvD3d9VertBufDesc::Decl_ColorAlpha) == 0)
3924    {
3925        m_ParamBlk.m_UseConstColorAlpha = true;
3926    }
3927   
3928    m_ParamBlk.m_CurLightCnt = m_WantLightCnt;
3929    if(m_LightingEnabled)
3930    {
3931        // Disable lighting for prog pipeline.
3932        EnabledLighting(false);
3933        m_ParamStateFFP.m_DirtyMask
3934                |= s3d_CDrvD3d9ParamBlkState::Dirty_Mtl;
3935    }
3936}
3937 
3938void s3d_CDrvD3d9GfxEngCLOD::EndDrawProg(
3939        const s3d_CSysChar *Info)
3940{
3941    if(m_ParamBlk.m_UseConstColorAlpha)
3942    {
3943        m_ParamBlk.m_UseConstColorAlpha = false;
3944        m_ParamStateProg.m_DirtyMask
3945                |= s3d_CDrvD3d9ParamBlkState::Dirty_Mtl;
3946    }
3947    m_PrevUsedFFP = false;
3948}
3949
3950void s3d_CDrvD3d9GfxEngCLOD::DrawIndexedBatchPacket(
3951        D3DPRIMITIVETYPE D3dPrim,
3952        s3d_CSysIntps PacketSubCnt, s3d_CDrvD3d9Packet *PacketSubArray,
3953        s3d_CSysIntps VertexSubBase, s3d_CSysIntps IndexSubBase,
3954        s3d_CSysIntps BoneIdxSubBase,
3955        s3d_CSysIntps BoneIdxCnt, const s3d_CSysInt32u *BoneIdxData,
3956        bool TrackDummyBlendTransf)
3957{
3958    s3d_CDrvD3d9PixEvent PixEvent;
3959    if(m_D3dParam->m_PixEnabled)
3960        PixEvent.Assign("DrawIndexedBatchPacket", S3D_DRV_D3D9_PIX_STD_COLOR);
3961
3962    if(!m_D3dDev)
3963        return;
3964
3965    if(!BoneIdxData && TrackDummyBlendTransf)
3966    {
3967        s3d_CSysInt32u BoneIdxData[4];
3968        BoneIdxData[0] = 0;
3969        BoneIdxData[1] = 0;
3970        BoneIdxData[2] = 0;
3971        BoneIdxData[3] = 0;
3972        m_ProgMgr->TrackTransfBone(
3973                S3D_SYS_ARRAYCNTS(BoneIdxData), BoneIdxData,
3974                1, &m_ParamBlk.m_MatView);
3975    }
3976
3977    s3d_CDrvD3d9Packet *CurPacket = PacketSubArray;
3978    const s3d_CSysInt32u *CurBoneIdxData = 0;
3979    if(BoneIdxData)
3980        CurBoneIdxData = BoneIdxData + BoneIdxSubBase;
3981    s3d_CSysIntps CurIndexSubBase = IndexSubBase;
3982    s3d_CSysIntps CurVertexSubBase = VertexSubBase;
3983
3984    const s3d_CSysIntps MatBoneCnt = m_MatBoneArray.GetCnt();
3985    const D3DXMATRIXA16 *MatBoneData = m_MatBoneArray.GetPtrRaw();
3986
3987    s3d_CSysIntps PacketRest = PacketSubCnt;
3988    while(PacketRest > 0)
3989    {
3990        PacketRest--;
3991
3992        if(BoneIdxData)
3993        {
3994            m_ProgMgr->TrackTransfBone(
3995                    CurPacket->m_BoneIdxCnt, CurBoneIdxData,
3996                    MatBoneCnt, MatBoneData);
3997            CurBoneIdxData += CurPacket->m_BoneIdxCnt;
3998        }
3999
4000        s3d_CSysIntps PacketPrimCnt = CurPacket->m_PrimCnt;
4001        if(PacketPrimCnt > 0)
4002        {
4003            INT BaseVertexIndex = 0;
4004            UINT MinVertexIndex = UINT(CurVertexSubBase);
4005            UINT NumVertices = UINT(CurPacket->m_VertCnt);
4006            UINT StartIndex = UINT(CurIndexSubBase);
4007            UINT nPrim = UINT(PacketPrimCnt);
4008            S3D_DRV_D3D9_CHECK(
4009                    &m_Env, m_D3dDev->DrawIndexedPrimitive(
4010                        D3dPrim, BaseVertexIndex, MinVertexIndex, NumVertices,
4011                        StartIndex, nPrim));
4012        }
4013
4014        CurIndexSubBase += CurPacket->m_IdxCnt;
4015        CurVertexSubBase += CurPacket->m_VertCnt;
4016        CurPacket++;
4017    }
4018}
4019
4020void s3d_CDrvD3d9GfxEngCLOD::DrawIndexedBatchPacketUP(
4021        D3DPRIMITIVETYPE D3dPrim,
4022        s3d_CSysIntps PacketSubCnt, s3d_CDrvD3d9Packet *PacketSubArray,
4023        s3d_CSysIntps VertexSubBase,
4024        const s3d_CSysIntm *VertData, int VertSize,
4025        D3DFORMAT IdxFmt, const s3d_CSysIntm *IdxData,
4026        s3d_CSysIntps BoneIdxSubBase,
4027        s3d_CSysIntps BoneIdxCnt, const s3d_CSysInt32u *BoneIdxData,
4028        bool TrackDummyBlendTransf)
4029{
4030    s3d_CDrvD3d9PixEvent PixEvent;
4031    if(m_D3dParam->m_PixEnabled)
4032        PixEvent.Assign(
4033                "DrawIndexedBatchPacketUP", S3D_DRV_D3D9_PIX_STD_COLOR);
4034
4035    if(!m_D3dDev)
4036        return;
4037
4038    if(!BoneIdxData && TrackDummyBlendTransf)
4039    {
4040        s3d_CSysInt32u BoneIdxData[4];
4041        BoneIdxData[0] = 0;
4042        BoneIdxData[1] = 0;
4043        BoneIdxData[2] = 0;
4044        BoneIdxData[3] = 0;
4045        m_ProgMgr->TrackTransfBone(
4046                S3D_SYS_ARRAYCNTS(BoneIdxData), BoneIdxData,
4047                1, &m_ParamBlk.m_MatView);
4048    }
4049
4050    int OffsFactor = 2;
4051    if(IdxFmt == D3DFMT_INDEX32)
4052        OffsFactor = 4;
4053
4054    s3d_CDrvD3d9Packet *CurPacket = PacketSubArray;
4055    const s3d_CSysInt32u *CurBoneIdxData = 0;
4056    if(BoneIdxData)
4057        CurBoneIdxData = BoneIdxData + BoneIdxSubBase;
4058    const s3d_CSysIntm *CurIdxData = IdxData;
4059    s3d_CSysIntps CurVertexSubBase = VertexSubBase;
4060
4061    const s3d_CSysIntps MatBoneCnt = m_MatBoneArray.GetCnt();
4062    const D3DXMATRIXA16 *MatBoneData = m_MatBoneArray.GetPtrRaw();
4063
4064    s3d_CSysIntps PacketRest = PacketSubCnt;
4065    while(PacketRest > 0)
4066    {
4067        PacketRest--;
4068
4069        if(BoneIdxData)
4070        {
4071            m_ProgMgr->TrackTransfBone(
4072                    CurPacket->m_BoneIdxCnt, CurBoneIdxData,
4073                    MatBoneCnt, MatBoneData);
4074            CurBoneIdxData += CurPacket->m_BoneIdxCnt;
4075        }
4076        if(CurPacket->m_PrimCnt > 0)
4077        {
4078            INT BaseVertexIndex = 0;
4079            UINT MinVertexIndex = UINT(CurVertexSubBase);
4080            UINT NumVertices = UINT(CurPacket->m_VertCnt);
4081            UINT nPrim = UINT(CurPacket->m_PrimCnt);
4082            S3D_DRV_D3D9_CHECK(
4083                    &m_Env, m_D3dDev->DrawIndexedPrimitiveUP(
4084                        D3dPrim, MinVertexIndex, NumVertices, nPrim,
4085                        CurIdxData, IdxFmt, VertData, VertSize));
4086        }
4087
4088        CurIdxData += (CurPacket->m_IdxCnt * OffsFactor);
4089        CurVertexSubBase += CurPacket->m_VertCnt;
4090        CurPacket++;
4091    }
4092}
4093
4094///////////////////////////////////////////////////////////////////////////////
4095
4096void s3d_CDrvD3d9GfxEngCLOD::ResetDevice()
4097{
4098    if(!m_D3dDev)
4099        return;
4100
4101    HRESULT Result = m_D3dDev->TestCooperativeLevel();
4102    if(Result == D3DERR_DEVICELOST)
4103    {
4104        return;
4105    }
4106    else if(SUCCEEDED(Result) || Result == D3DERR_DEVICENOTRESET)
4107    {
4108        Park();
4109       
4110        S3D_DRV_D3D9_CHECK(
4111                &m_Env, m_D3dDev->Reset(&m_PresentParam));
4112       
4113        Unpark();
4114    }
4115    else
4116    {
4117        S3D_DRV_D3D9_CHECKHRES(&m_Env, Result);
4118    }
4119}
4120
4121///////////////////////////////////////////////////////////////////////////////
4122
4123s3d_CDrvD3d9SurfRTPtr s3d_CDrvD3d9GfxEngCLOD::FindSurfRT(
4124        int Width, int Height,
4125        D3DFORMAT Fmt, D3DMULTISAMPLE_TYPE MultiSampleType)
4126{
4127    s3d_CDrvD3d9SurfRTKey Key(Fmt, MultiSampleType);
4128    s3d_CDrvD3d9SurfRTPoolPtr SurfRTPool
4129            = m_SurfRTPoolMap.GetAtDefault(Key, 0);
4130    if(!SurfRTPool)
4131    {
4132        SurfRTPool = S3D_SYS_NEW s3d_CDrvD3d9SurfRTPool;
4133        m_SurfRTPoolMap.SetAt(Key, SurfRTPool);
4134    }
4135
4136    s3d_CDrvD3d9SurfRTPtr SurfRT;
4137    if(!SurfRTPool->m_SurfRTArray.IsEmpty())
4138        SurfRT = SurfRTPool->m_SurfRTArray.ExtractBack();
4139    else
4140        SurfRT = S3D_SYS_NEW s3d_CDrvD3d9SurfRT;
4141    SurfRT->m_SurfRTPool = SurfRTPool;
4142
4143    if(Width > SurfRT->m_Width || Height > SurfRT->m_Height)
4144    {
4145        s3d_CDrvD3d9Surf Surf;
4146        DWORD MultiSampleQuality = m_PresentParam.MultiSampleQuality;
4147        if(s3d_CDrvD3d9Util::IsDepthStencilFmt(Fmt))
4148        {
4149            BOOL Discard = FALSE;
4150            S3D_DRV_D3D9_CHECK(
4151                    &m_Env, m_D3dDev->CreateDepthStencilSurface(
4152                        Width, Height, Fmt, MultiSampleType,
4153                        MultiSampleQuality, Discard, &Surf.EmptyRef(), 0));
4154        }
4155        else
4156        {
4157            BOOL Lockable = FALSE;
4158            S3D_DRV_D3D9_CHECK(
4159                    &m_Env, m_D3dDev->CreateRenderTarget(
4160                        Width, Height, Fmt, MultiSampleType,
4161                        MultiSampleQuality, Lockable, &Surf.EmptyRef(), 0));
4162        }
4163
4164        if(!Surf)
4165            return 0;
4166 
4167        S3D_DRV_D3D9_CHECK(
4168                &m_Env, m_D3dDev->EvictManagedResources());
4169       
4170        SurfRT->m_Width = Width;
4171        SurfRT->m_Height = Height;
4172        SurfRT->m_Surf = Surf;
4173    }
4174
4175    return SurfRT;
4176}
4177
4178void s3d_CDrvD3d9GfxEngCLOD::BeginRenderTexStd(
4179        int Width, int Height,
4180        s3d_CSysIntps DestCnt, const s3d_CDrvGfxDest *DestArray)
4181{
4182    s3d_CDrvD3d9Surf SurfDepth = m_MainSurfDepth;
4183    // Depthstencil surface must be as least as big as color surface
4184    // if main depthstencil surface is too small allocate a new surface
4185    if(m_PresentParam.MultiSampleType != D3DMULTISAMPLE_NONE
4186        || Width > s3d_CSysIntps(m_PresentParam.BackBufferWidth)
4187        || Height > s3d_CSysIntps(m_PresentParam.BackBufferHeight))
4188    {
4189        s3d_CDrvD3d9SurfRTPtr SurfRTDepth = FindSurfRT(
4190                Width, Height, m_DepthStencilFmt, D3DMULTISAMPLE_NONE);
4191        if(SurfRTDepth)
4192        {
4193            m_CurSurfRTDepth = SurfRTDepth;
4194            SurfDepth = SurfRTDepth->m_Surf;
4195        }
4196    }
4197   
4198    int SurfColUsedCnt = 0;
4199    DWORD iDest;
4200    for(iDest = 0; iDest < DWORD(DestCnt); iDest++)
4201    {
4202        const s3d_CDrvGfxDest *GfxDest = &DestArray[iDest];
4203        s3d_CDrvD3d9TexObjBase *TexImpl
4204                = s3d_UtilRecogCastSilent<s3d_CDrvD3d9TexObjBase>(
4205                        GfxDest->m_Tex);
4206        if(!TexImpl)
4207            continue;
4208       
4209        UnbindTex(TexImpl);
4210
4211        s3d_CDrvD3d9Surf DestSurf;
4212        S3D_DRV_D3D9_CHECK(
4213                &m_Env, TexImpl->GetRenderTarget(DestSurf, GfxDest));
4214        if(!DestSurf)
4215            continue;
4216
4217        if(TexImpl->m_TexFmt.m_FmtCol != D3DFMT_UNKNOWN)
4218        {
4219            //S3D_DRV_D3D9_DBGPRINTF(
4220            //        "selecting RT(%d) w=%d, h=%d\n", iDest, Width, Height);
4221
4222            if(m_CurSurfColArray[iDest] != DestSurf)
4223            {
4224                HRESULT Result;
4225                S3D_DRV_D3D9_CALLCHECK(
4226                        &m_Env, Result,
4227                            m_D3dDev->SetRenderTarget(iDest, DestSurf));
4228                if(FAILED(Result))
4229                    continue;
4230                m_CurSurfColArray[iDest] = DestSurf;
4231            }
4232            SurfColUsedCnt++;
4233        }
4234        // NVIDIA depthtex
4235        else if(TexImpl->m_TexFmt.m_FmtDepth != D3DFMT_UNKNOWN)
4236        {
4237            //S3D_DRV_D3D9_DBGPRINTF(
4238            //        "selecting RT(%d) w=%d, h=%dn", iDest, Width, Height);
4239            SurfDepth = DestSurf;
4240
4241            // Only set a color buffer when we haven't set one already
4242            if(SurfColUsedCnt == 0 && DestCnt == 1)
4243            {
4244                s3d_CDrvD3d9Surf SurfCol = m_MainSurfCol;
4245                if(DWORD(Width) > m_PresentParam.BackBufferWidth
4246                    || DWORD(Height) > m_PresentParam.BackBufferHeight)
4247                {
4248                    s3d_CDrvD3d9SurfRTPtr SurfRTCol = FindSurfRT(
4249                            Width, Height, m_BackBufFmt, D3DMULTISAMPLE_NONE);
4250                    if(!SurfRTCol)
4251                        continue;
4252
4253                    m_CurSurfRTColArray.SetAtRaw(iDest, SurfRTCol);
4254                    SurfCol = SurfRTCol->m_Surf;
4255                }
4256
4257                if(m_CurSurfColArray[iDest] != SurfCol)
4258                {
4259                    HRESULT Result;
4260                    S3D_DRV_D3D9_CALLCHECK(
4261                            &m_Env, Result,
4262                                m_D3dDev->SetRenderTarget(iDest, SurfCol));
4263                    if(FAILED(Result))
4264                        continue;
4265                    m_CurSurfColArray[iDest] = SurfCol;
4266                    SurfColUsedCnt++;
4267                }
4268            }
4269        }
4270        else
4271        {
4272            S3D_SYS_ASSERT(0);
4273        }
4274    }
4275
4276    if(m_CurSurfDepth != SurfDepth)
4277    {
4278        S3D_DRV_D3D9_CALL(
4279                &m_Env, m_D3dDev->SetDepthStencilSurface(SurfDepth));
4280        m_CurSurfDepth = SurfDepth;
4281    }
4282
4283    SetRenderTargetElseNone(SurfColUsedCnt);
4284}
4285
4286void s3d_CDrvD3d9GfxEngCLOD::EndRenderTexStd()
4287{
4288}
4289
4290void s3d_CDrvD3d9GfxEngCLOD::BeginRenderTexMSAA(
4291        int Width, int Height,
4292        s3d_CSysIntps DestCnt, const s3d_CDrvGfxDest *DestArray)
4293{
4294    s3d_CDrvD3d9Surf SurfDepth = m_MainSurfDepth;
4295    if(DWORD(Width) > m_PresentParam.BackBufferWidth
4296            || DWORD(Height) > m_PresentParam.BackBufferHeight)
4297    {
4298        s3d_CDrvD3d9SurfRTPtr SurfRTDepth = FindSurfRT(
4299                Width, Height, m_DepthStencilFmt,
4300                m_PresentParam.MultiSampleType);
4301        m_CurSurfRTDepth = SurfRTDepth;
4302        SurfDepth = SurfRTDepth->m_Surf;
4303    }
4304
4305    HRESULT Result = 0;
4306    int SurfColUsedCnt = 0;
4307    DWORD iDest;
4308    for(iDest = 0; iDest < DWORD(DestCnt); iDest++)
4309    {
4310        const s3d_CDrvGfxDest *GfxDest = &DestArray[iDest];
4311        s3d_CDrvD3d9TexObjBase *TexImpl
4312                = s3d_UtilRecogCastSilent<s3d_CDrvD3d9TexObjBase>(
4313                        GfxDest->m_Tex);
4314        if(!TexImpl)
4315            continue;
4316
4317        // Shouldn't be needed as we're not using texture surface as
4318        // rendertarget.
4319        //UnbindTex(TexImpl);
4320
4321        if(TexImpl->m_TexFmt.m_FmtDepth != D3DFMT_UNKNOWN)
4322        {
4323            s3d_CDrvD3d9Error e;
4324            e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_eng.error_depthtex_msaa";
4325            e.m_StdTempl = "D3D: Can't use nvidia depth texture with MSAA.";
4326            e.AddInfo(m_Info);
4327            s3d_UtilMsgReportError(m_MsgHandler, e);
4328            continue;
4329        }
4330        if(!TexImpl->m_TexFmt.m_CanMultiSample)
4331        {
4332            s3d_CDrvD3d9Error e;
4333            e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_eng.error_depthtex_msaa";
4334            e.m_StdTempl = "D3D: Can't use texture format '[1]' with MSAA.";
4335            e.AddInfo(m_Info);
4336            e.AddInfo(s3d_CDrvD3d9Util::StrOfFmt(TexImpl->m_TexFmt.m_FmtCol));
4337            s3d_UtilMsgReportError(m_MsgHandler, e);
4338            continue;
4339        }
4340
4341        D3DFORMAT FmtCol = TexImpl->m_TexFmt.m_FmtCol;
4342        if(FmtCol == D3DFMT_UNKNOWN)
4343        {
4344            S3D_SYS_ASSERT(0);
4345            continue;
4346        }
4347
4348        s3d_CDrvD3d9Surf SurfCol;
4349        if(SurfColUsedCnt > 0 || FmtCol != m_BackBufFmt
4350                || DWORD(Width) > m_PresentParam.BackBufferWidth
4351                || DWORD(Height) > m_PresentParam.BackBufferHeight)
4352        {
4353
4354            s3d_CDrvD3d9SurfRTPtr SurfRTCol = FindSurfRT(
4355                    Width, Height, FmtCol, m_PresentParam.MultiSampleType);
4356            if(!SurfRTCol)
4357                continue;
4358
4359            m_CurSurfRTColArray.SetAtRaw(iDest, SurfRTCol);
4360            SurfCol = SurfRTCol->m_Surf;
4361        }
4362        else
4363        {
4364            SurfCol = m_MainSurfCol;
4365        }
4366
4367        if(m_CurSurfColArray[iDest] != SurfCol)
4368        {
4369            S3D_DRV_D3D9_CALLCHECK(
4370                    &m_Env, Result,
4371                        m_D3dDev->SetRenderTarget(iDest, SurfCol));
4372            if(FAILED(Result))
4373                continue;
4374            m_CurSurfColArray[iDest] = SurfCol;
4375        }
4376        SurfColUsedCnt++;
4377    }
4378
4379    if(m_CurSurfDepth != SurfDepth)
4380    {
4381        S3D_DRV_D3D9_CALL(
4382                &m_Env, m_D3dDev->SetDepthStencilSurface(SurfDepth));
4383        m_CurSurfDepth = SurfDepth;
4384    }
4385
4386    SetRenderTargetElseNone(SurfColUsedCnt);
4387}
4388
4389void s3d_CDrvD3d9GfxEngCLOD::EndRenderTexMSAA()
4390{
4391    s3d_CSysIntps iDest;
4392    for(iDest = 0; iDest < m_DestCnt; iDest++)
4393    {
4394        DWORD Idx = DWORD(iDest);
4395        const s3d_CDrvGfxDest *GfxDest = &m_DestArray[iDest];
4396        if(!GfxDest)
4397            continue;
4398
4399        s3d_CDrvD3d9TexObjBase *TexImpl
4400                = s3d_UtilRecogCastSilent<s3d_CDrvD3d9TexObjBase>(
4401                        GfxDest->m_Tex);
4402        if(!TexImpl)
4403            continue;
4404        if(!TexImpl->m_TexFmt.m_CanMultiSample)
4405            continue;
4406
4407        s3d_CDrvD3d9Surf DestSurf;
4408        S3D_DRV_D3D9_CHECK(
4409                &m_Env, TexImpl->GetRenderTarget(DestSurf, GfxDest));
4410        if(!DestSurf)
4411            return;
4412        const RECT Rect = {0, 0, m_BufWidth, m_BufHeight};
4413        HRESULT Result;
4414        S3D_DRV_D3D9_CALLCHECK(
4415                &m_Env, Result, m_D3dDev->StretchRect(
4416                    m_CurSurfColArray[iDest], &Rect,
4417                    DestSurf, &Rect, D3DTEXF_LINEAR));
4418    }
4419}
4420
4421void s3d_CDrvD3d9GfxEngCLOD::UnbindTex(
4422        s3d_CDrvD3d9TexObjBase *TexImpl)
4423{
4424    if(!TexImpl)
4425        return;
4426
4427    int iSamp;
4428    for(iSamp = 0; iSamp < m_ParamBlk.m_SampMaxUsedCnt; iSamp++)
4429    {
4430        if(m_ParamBlk.m_SampTexArray[iSamp] == TexImpl)
4431        {
4432            m_ParamBlk.m_SampTexArray[iSamp] = 0;
4433            m_WantSampTexArray[iSamp] = 0;
4434            S3D_DRV_D3D9_CHECK(
4435                    &m_Env, m_D3dDev->SetTexture(iSamp, 0));
4436            SetTexOpTransf(iSamp, D3DTOP_DISABLE, D3DTTFF_DISABLE);
4437            s3d_SysSetToMax(m_SampMaxWantCnt, iSamp + 1);
4438        }
4439    }
4440}
4441
4442void s3d_CDrvD3d9GfxEngCLOD::SetRenderTargetElseNone(
4443        int Start)
4444{
4445    s3d_CSysIntps nRT = s3d_SysMin(m_MaxSimRTCnt, m_CurSurfColUsedCnt);
4446    s3d_CSysIntps iRT;
4447    for(iRT = Start; iRT < nRT; iRT++)
4448    {
4449        if(m_CurSurfColArray[iRT])
4450        {
4451            S3D_DRV_D3D9_CHECK(
4452                    &m_Env, m_D3dDev->SetRenderTarget(DWORD(iRT), 0));
4453            m_CurSurfColArray[iRT] = 0;
4454        }
4455    }
4456    m_CurSurfColUsedCnt = Start;
4457}
4458
4459void s3d_CDrvD3d9GfxEngCLOD::InitRenderToTex()
4460{
4461    if(!m_D3dDev)
4462        return;
4463
4464    m_MaxSimRTCnt = m_DevCaps.NumSimultaneousRTs;
4465    if(m_MaxSimRTCnt > S3D_DRV_D3D9_MAX_SIM_RT_CNT)
4466    {
4467        m_MaxSimRTCnt = S3D_DRV_D3D9_MAX_SIM_RT_CNT;
4468        S3D_SYS_ASSERT(0);
4469    }
4470    s3d_CSysIntps iRT;
4471    for(iRT = 0; iRT < m_MaxSimRTCnt; iRT++)
4472        m_CurSurfColArray[iRT] = 0;
4473
4474    m_CurSurfRTColArray.SetCnt(m_MaxSimRTCnt);
4475    m_CurSurfColUsedCnt = 0;
4476    m_DestProp = 0;
4477    m_DestCnt = -1;
4478
4479    S3D_DRV_D3D9_CHECK(
4480            &m_Env, m_D3dDev->GetRenderTarget(
4481                0, &m_MainSurfCol.EmptyRef()));
4482    S3D_DRV_D3D9_CHECK(
4483            &m_Env, m_D3dDev->GetDepthStencilSurface(
4484                &m_MainSurfDepth.EmptyRef()));
4485
4486    m_CurSurfColArray[0] = m_MainSurfCol;
4487    m_CurSurfDepth = m_MainSurfDepth;
4488}
4489
4490void s3d_CDrvD3d9GfxEngCLOD::RestoreRenderTargets()
4491{
4492    if(!m_D3dDev)
4493        return;
4494
4495    S3D_SYS_ASSERT(m_DestCnt == -1);
4496
4497    // Put temporary surfaces back to freelist
4498    m_CurSurfRTColArray.Clear();
4499    m_CurSurfRTDepth = 0;
4500
4501    if(m_CurSurfDepth != m_MainSurfDepth)
4502    {
4503        S3D_DRV_D3D9_CHECK(
4504                &m_Env, m_D3dDev->SetDepthStencilSurface(m_MainSurfDepth));
4505        m_CurSurfDepth = m_MainSurfDepth;
4506    }
4507
4508    if(m_CurSurfColUsedCnt == 0)
4509        return;
4510
4511    // First unbind render targets > 0, main color surface might be bound to
4512    // one of these slots.
4513    s3d_CSysIntps nRT = s3d_SysMin(m_MaxSimRTCnt, m_CurSurfColUsedCnt);
4514    s3d_CSysIntps iRT;
4515    for(iRT = 1; iRT < nRT; iRT++)
4516    {
4517        LPDIRECT3DSURFACE9 Surf = m_CurSurfColArray[iRT];
4518        if(Surf)
4519        {
4520            S3D_DRV_D3D9_CHECK(
4521                    &m_Env, m_D3dDev->SetRenderTarget(DWORD(iRT), 0));
4522            m_CurSurfColArray[iRT] = 0;
4523        }
4524    }
4525
4526    if(m_CurSurfColArray[0] != m_MainSurfCol)
4527    {
4528        S3D_DRV_D3D9_CHECK(
4529                &m_Env, m_D3dDev->SetRenderTarget(0, m_MainSurfCol));
4530        m_CurSurfColArray[0] = m_MainSurfCol;
4531    }
4532
4533    m_CurSurfColUsedCnt = 0;
4534}
4535
4536///////////////////////////////////////////////////////////////////////////////
4537
4538void s3d_CDrvD3d9GfxEngCLOD::EnabledScissor(bool Enabled)
4539{
4540    if(m_CurScissorEnabled != Enabled)
4541    {
4542        m_CurScissorEnabled = Enabled;
4543        S3D_DRV_D3D9_CHECK(
4544                &m_Env,s3d_CDrvD3d9StateUtil::SetRenderStateI(
4545                    m_D3dDev, D3DRS_SCISSORTESTENABLE, BOOL(Enabled)));
4546    }
4547}
4548
4549///////////////////////////////////////////////////////////////////////////////
4550
4551void s3d_CDrvD3d9GfxEngCLOD::InitLighting()
4552{
4553    if(!m_D3dDev)
4554        return;
4555
4556    m_LightingEnabled = false;
4557    m_WantLighting = false;
4558    m_MaxLightCnt = S3D_DRV_D3D9_MAX_LIGHT_CNT;
4559    if(DWORD(m_MaxLightCnt) > m_DevCaps.MaxActiveLights)
4560    {
4561        S3D_SYS_ASSERT(0);
4562        m_MaxLightCnt = m_DevCaps.MaxActiveLights;
4563    }
4564
4565    m_WantLightCnt = 0;
4566    m_ParamBlk.m_CurLightCnt = 0;
4567    s3d_CSysIntps iLight;
4568    for(iLight = 0; iLight < m_MaxLightCnt; iLight++)
4569    {
4570        m_LightEnabledArray[iLight] = false;
4571        m_LightDirtyArray[iLight] = false;
4572        S3D_DRV_D3D9_CHECK(
4573                &m_Env, m_D3dDev->LightEnable(DWORD(iLight), FALSE));
4574    }
4575
4576    S3D_DRV_D3D9_CHECK(
4577            &m_Env, s3d_CDrvD3d9StateUtil::SetRenderStateI(
4578                m_D3dDev, D3DRS_LIGHTING, FALSE));
4579    S3D_DRV_D3D9_CHECK(
4580            &m_Env, s3d_CDrvD3d9StateUtil::SetRenderStateI(
4581                m_D3dDev, D3DRS_NORMALIZENORMALS, FALSE));
4582}
4583
4584void s3d_CDrvD3d9GfxEngCLOD::EnabledLighting(
4585        bool Enabled)
4586{
4587    if(!m_D3dDev)
4588        return;
4589
4590    if(m_LightingEnabled != Enabled)
4591    {
4592        m_LightingEnabled = Enabled;
4593        S3D_DRV_D3D9_CHECK(
4594                &m_Env, s3d_CDrvD3d9StateUtil::SetRenderStateI(
4595                    m_D3dDev, D3DRS_LIGHTING, BOOL(Enabled)));
4596        S3D_DRV_D3D9_CHECK(
4597                &m_Env, s3d_CDrvD3d9StateUtil::SetRenderStateI(
4598                    m_D3dDev, D3DRS_NORMALIZENORMALS, BOOL(Enabled)));
4599    }
4600}
4601
4602///////////////////////////////////////////////////////////////////////////////
4603
4604void s3d_CDrvD3d9GfxEngCLOD::InitDevCaps()
4605{
4606    m_HasNvDepthTex = false;
4607    m_CanRenderDepth = false;
4608
4609    if(!m_D3d)
4610        return;
4611
4612    HRESULT Result = 0;
4613    D3DDISPLAYMODE AdapterMode;
4614    S3D_DRV_D3D9_CALLCHECK(
4615            &m_Env, Result, m_D3d->GetAdapterDisplayMode(
4616                m_Adapter, &AdapterMode));
4617    if(FAILED(Result))
4618        return;
4619   
4620    D3DFORMAT AdapterFmt = AdapterMode.Format;
4621   
4622    // NVIDIA depthtex.
4623    if(m_D3dParam->m_NVDepthTexEnabled)
4624    {
4625        S3D_DRV_D3D9_HRESCALL(
4626                &m_Env, Result, m_D3d->CheckDeviceFormat(
4627                        m_Adapter, m_DevType, AdapterFmt,
4628                        D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE,
4629                                D3DFMT_D24S8));
4630        if(SUCCEEDED(Result))
4631            m_HasNvDepthTex = true;
4632    }
4633   
4634    // Official "depthtex".
4635    if(m_DevCaps.PixelShaderVersion >= D3DPS_VERSION(1, 1))
4636    {
4637        m_CanRenderDepth = false;
4638        S3D_DRV_D3D9_HRESCALL(
4639                &m_Env, Result, m_D3d->CheckDeviceFormat(
4640                    m_Adapter, m_DevType, AdapterFmt,
4641                    D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_R32F));
4642        if(SUCCEEDED(Result))
4643            m_CanRenderDepth = true;
4644        else
4645        {
4646            S3D_DRV_D3D9_HRESCALL(
4647                    &m_Env, Result, m_D3d->CheckDeviceFormat(
4648                        m_Adapter, m_DevType, AdapterFmt,
4649                        D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_R16F));
4650            if(SUCCEEDED(Result))
4651                m_CanRenderDepth = true;
4652        }
4653    }
4654}
4655
4656///////////////////////////////////////////////////////////////////////////////
4657
4658void s3d_CDrvD3d9GfxEngCLOD::Park()
4659{
4660    if(!m_D3dDev)
4661        return;
4662
4663    S3D_DRV_D3D9_CHECK(
4664            &m_Env, m_D3dDev->EvictManagedResources());
4665   
4666    if(m_BufMgr)
4667        m_BufMgr->Park();
4668    if(m_TexMgr)
4669        m_TexMgr->Park();
4670
4671    RestoreRenderTargets();
4672    m_CurSurfColArray[0].Reset();
4673    m_CurSurfDepth.Reset();
4674    m_MainSurfCol.Reset();
4675    m_MainSurfDepth.Reset();
4676
4677    m_CurSurfRTDepth = 0;
4678    m_CurSurfRTColArray.Clear();
4679    m_SurfRTPoolMap.Reset();
4680
4681    m_VisibMgr->Park();
4682    m_FlushEvent.Reset();
4683}
4684
4685void s3d_CDrvD3d9GfxEngCLOD::Unpark()
4686{
4687    if(!m_D3dDev)
4688        return;
4689
4690    if(m_ProgMgr)
4691        m_ProgMgr->InvalidateProg();
4692
4693    if(m_TexMgr)
4694        m_TexMgr->Unpark();
4695    if(m_BufMgr)
4696        m_BufMgr->Unpark();
4697
4698    // Invalidate buffers
4699    m_CurVertBufObj = 0;
4700    m_CurIdxBufObj = 0;
4701    m_CurVertDecl = 0;
4702
4703    // Invalidate texturing
4704    InitTexturing();
4705
4706    // Invalidate lightstate
4707    InitLighting();
4708
4709    // Invalidate render targets
4710    InitRenderToTex();
4711   
4712    SetDefaultState();
4713    m_ParamStateFFP.Invalidate();
4714    m_ParamStateProg.Invalidate();
4715
4716    m_MatProjDirty = true;
4717    m_MatBoneDirty = true;
4718
4719    m_VisibMgr->Unpark();
4720    m_FlushEvent.Init(&m_Env, m_D3dDev);
4721}
4722
4723///////////////////////////////////////////////////////////////////////////////
4724
4725s3d_CDrvD3d9GfxOut::s3d_CDrvD3d9GfxOut(
4726        s3d_CDrvD3d9GfxEngCLOD *GfxEng)
4727{
4728    m_GfxEng = GfxEng;
4729}
4730
4731s3d_CUtilStr s3d_CDrvD3d9GfxOut::GetDesc()
4732{
4733    if(m_GfxEng)
4734        return m_GfxEng->GetDesc();
4735    else
4736        return 0;
4737}
4738
4739void s3d_CDrvD3d9GfxOut::Alter(
4740        s3d_CUtilStr_cr Info,
4741        s3d_CUtilStr_cr Device, int Prop,
4742        int Left, int Top, int Width, int Height,
4743        int Depth, int Frequency, s3d_CUtilSnkChunk *Param)
4744{
4745    if(m_GfxEng)
4746        m_GfxEng->Alter(Info, Device, Prop, Top, Left, Width, Height,
4747                Depth, Frequency, Param);
4748}
4749
4750void s3d_CDrvD3d9GfxOut::Alter(
4751        s3d_CUtilStr_cr Info,
4752        s3d_CUtilStr_cr Device, int Prop,
4753        int Left, int Top, int Width, int Height,
4754        int Depth, int Frequency, s3d_CDrvD3d9Param *D3dParam)
4755{
4756    if(m_GfxEng)
4757        m_GfxEng->Alter(Info, Device, Prop, Top, Left, Width, Height,
4758                Depth, Frequency, D3dParam);
4759}
4760
4761void s3d_CDrvD3d9GfxOut::Present()
4762{
4763    if(m_GfxEng)
4764        m_GfxEng->Present();
4765}
4766
4767void s3d_CDrvD3d9GfxOut::GetSize(int &Width, int &Height) const
4768{
4769    if(m_GfxEng)
4770        m_GfxEng->GetMainSize(Width, Height);
4771    else
4772    {
4773        Width = 0;
4774        Height = 0;
4775    }
4776}
4777
4778int s3d_CDrvD3d9GfxOut::GetColorAlphaBits() const
4779{
4780    if(m_GfxEng)
4781        return m_GfxEng->GetMainColorAlphaBits();
4782    else
4783        return 0;
4784}
4785
4786void s3d_CDrvD3d9GfxOut::SetGamma(
4787        s3d_CUtilVec3f_cr Gamma)
4788{
4789    if(m_GfxEng)
4790        m_GfxEng->SetGamma(Gamma);
4791}
4792
4793///////////////////////////////////////////////////////////////////////////////
4794// NEW for GAMETOOLS
4795
4796S3D_UTIL_RTTI_TABLE_DEFINE_DERIVED(s3d_CDrvD3d9GfxEngCLOD, s3d_CDrvGfxEng)
4797
4798S3D_UTIL_RTTI_TARGET_DEFINE(s3d_CDrvD3d9GfxEngCLOD)
4799
4800void s3d_CDrvD3d9GfxEngCLOD::ManipulateBatchForLODSTRIPS(s3d_CDrvGfxBatchPtr Batch, Geometry::LodStripsLibrary *lodstrips, float lod)
4801{
4802    s3d_CDrvD3d9Batch *BatchImpl = s3d_UtilRecogCastSilent<s3d_CDrvD3d9Batch>(Batch);
4803    if(!BatchImpl)
4804    {
4805        S3D_SYS_ASSERT(0);
4806        return;
4807    }
4808
4809        //lodstrips->GoToLod(lod);
4810   
4811/*      BatchImpl->m_IdxBufObj->m_IdxCnt = 30;
4812        BatchImpl->m_IdxBufObj->m_PacketArray[0].m_IdxCnt = BatchImpl->m_IdxBufObj->m_IdxCnt;
4813        BatchImpl->m_IdxBufObj->m_PacketArray[0].m_PrimCnt = BatchImpl->m_IdxBufObj->m_PacketArray[0].m_IdxCnt - 2;*/
4814       
4815        BatchImpl->m_IdxBufObj->m_D3dPrim = D3DPT_TRIANGLESTRIP;
4816
4817}
4818
4819void s3d_CDrvD3d9GfxEngCLOD::GetViewPos(float &x, float &y, float &z)
4820{
4821        x = m_ParamBlk.m_MatView._41;
4822        y = m_ParamBlk.m_MatView._42;
4823        z = m_ParamBlk.m_MatView._43;
4824}
Note: See TracBrowser for help on using the repository browser.