source: GTP/trunk/App/Demos/Illum/Shark3D/version164x12u/shark3Dchanges/src/drv/imp/directx/d3d9/drv_d3d9_eng.cpp @ 2196

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