1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2010 Robert TIMM (rti) <mail@rtti.de>
6 // Copyright (C) 2013-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 // Copyright (C) 2014 Matthew LAGOE (Botanic) <cyberempires@gmail.com>
9 // This program is free software: you can redistribute it and/or modify
10 // it under the terms of the GNU Affero General Public License as
11 // published by the Free Software Foundation, either version 3 of the
12 // License, or (at your option) any later version.
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU Affero General Public License for more details.
19 // You should have received a copy of the GNU Affero General Public License
20 // along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "stddirect3d.h"
24 // by default, we disable the windows menu keys (F10, ALT and ALT+SPACE key doesn't freeze or open the menu)
25 #define NL_DISABLE_MENU
29 #include "nel/3d/vertex_buffer.h"
30 #include "nel/3d/light.h"
31 #include "nel/3d/index_buffer.h"
32 #include "nel/misc/rect.h"
33 #include "nel/misc/dynloadlib.h"
34 #include "nel/3d/viewport.h"
35 #include "nel/3d/scissor.h"
36 #include "nel/3d/u_driver.h"
38 #include "driver_direct3d.h"
45 using namespace NLMISC
;
47 #define RASTERIZER D3DDEVTYPE_HAL
48 //#define RASTERIZER D3DDEVTYPE_REF
50 #define D3D_WINDOWED_STYLE (WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX)
51 #define D3D_FULLSCREEN_STYLE (WS_POPUP)
53 // ***************************************************************************
55 // Try to allocate 16Mo by default of AGP Ram.
56 #define NL3D_DRV_VERTEXARRAY_AGP_INIT_SIZE (16384*1024)
58 // Initial volatile vertex buffer size
59 #define NL_VOLATILE_RAM_VB_SIZE 512*1024
60 #define NL_VOLATILE_AGP_VB_SIZE 128*1024
61 #define NL_VOLATILE_RAM_IB_SIZE 64*1024
62 #define NL_VOLATILE_AGP_IB_SIZE 1024
64 #define NL_VOLATILE_RAM_VB_MAXSIZE 512*1024
65 #define NL_VOLATILE_AGP_VB_MAXSIZE 2500*1024
66 #define NL_VOLATILE_RAM_IB_MAXSIZE 1024*1024
67 #define NL_VOLATILE_AGP_IB_MAXSIZE 256*1024
71 // ***************************************************************************
75 HINSTANCE HInstDLL
= NULL
;
77 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
,ULONG fdwReason
,LPVOID lpvReserved
)
84 class CDriverD3DNelLibrary
: public INelLibrary
{
85 void onLibraryLoaded(bool firstTime
) { }
86 void onLibraryUnloaded(bool lastTime
) { }
88 NLMISC_DECL_PURE_LIB(CDriverD3DNelLibrary
)
90 #endif /* #ifndef NL_STATIC */
92 // ***************************************************************************
97 // ***************************************************************************
99 // Version of the driver. Not the interface version!! Increment when implementation of the driver change.
100 const uint32
CDriverD3D::ReleaseVersion
= 0xe;
104 // ***************************************************************************
108 # pragma comment(lib, "d3dx9")
109 # pragma comment(lib, "d3d9")
110 # pragma comment(lib, "dinput8")
111 # pragma comment(lib, "dxguid")
113 IDriver
* createD3DDriverInstance ()
115 return new CDriverD3D
;
124 __declspec(dllexport
) IDriver
* NL3D_createIDriverInstance ()
126 return new CDriverD3D
;
129 __declspec(dllexport
) uint32
NL3D_interfaceVersion ()
131 return IDriver::InterfaceVersion
;
138 /*static*/ bool CDriverD3D::_CacheTest
[CacheTest_Count
] =
140 false, // CacheTest_CullMode = 0;
141 false, // CacheTest_RenderState = 1,
142 false, // CacheTest_TextureState = 2,
143 false, // CacheTest_TextureIndexMode = 3,
144 false, // CacheTest_TextureIndexUV = 4,
145 false, // CacheTest_Texture = 5,
146 false, // CacheTest_VertexProgram = 6,
147 false, // CacheTest_PixelShader = 7,
148 false, // CacheTest_VertexProgramConstant = 8,
149 false, // CacheTest_PixelShaderConstant = 9,
150 false, // CacheTest_SamplerState = 10,
151 false, // CacheTest_VertexBuffer = 11,
152 false, // CacheTest_IndexBuffer = 12,
153 false, // CacheTest_VertexDecl = 13,
154 false, // CacheTest_Matrix = 14,
155 false, // CacheTest_RenderTarget = 15,
156 false, // CacheTest_MaterialState = 16,
157 false // CacheTest_DepthRange = 17,
163 // ***************************************************************************
165 CDriverD3D::CDriverD3D()
167 _SwapBufferCounter
= 0;
168 _CurrentOcclusionQuery
= NULL
;
171 _DeviceInterface
= NULL
;
172 _DestroyWindow
= false;
173 _CurrentMode
.Width
= 640;
174 _CurrentMode
.Height
= 480;
179 _ColorDepth
= ColorDepth32
;
181 _DefaultCursor
= EmptyCursor
;
183 _AlphaBlendedCursorSupported
= false;
184 _AlphaBlendedCursorSupportRetrieved
= false;
185 _CurrCol
= CRGBA::White
;
191 _UserViewMtx
.identity();
192 _UserModelMtx
.identity();
193 _PZBCameraPos
= CVector::Null
;
194 _CurrentMaterial
= NULL
;
195 _CurrentMaterialInfo
= NULL
;
196 _CurrentShader
= NULL
;
199 _HandlePossibleSizeChangeNextSize
= false;
202 _AGPMemoryAllocated
= 0;
203 _VRAMMemoryAllocated
= 0;
204 _Rasterizer
= RASTERIZER
;
205 #ifdef NL_DISABLE_HARDWARE_VERTEX_PROGAM
206 _DisableHardwareVertexProgram
= true;
207 #else // NL_DISABLE_HARDWARE_VERTEX_PROGAM
208 _DisableHardwareVertexProgram
= false;
209 #endif // NL_DISABLE_HARDWARE_VERTEX_PROGAM
210 #ifdef NL_DISABLE_HARDWARE_PIXEL_PROGAM
211 _DisableHardwarePixelProgram
= true;
212 #else // NL_DISABLE_HARDWARE_PIXEL_PROGAM
213 _DisableHardwarePixelProgram
= false;
214 #endif // NL_DISABLE_HARDWARE_PIXEL_PROGAM
215 #ifdef NL_DISABLE_HARDWARE_VERTEX_ARRAY_AGP
216 _DisableHardwareVertexArrayAGP
= true;
217 #else // NL_DISABLE_HARDWARE_VERTEX_ARRAY_AGP
218 _DisableHardwareVertexArrayAGP
= false;
219 #endif // NL_DISABLE_HARDWARE_VERTEX_ARRAY_AGP
220 #ifdef NL_DISABLE_HARDWARE_INDEX_ARRAY_AGP
221 _DisableHardwareIndexArrayAGP
= true;
222 #else // NL_DISABLE_HARDWARE_INDEX_ARRAY_AGP
223 _DisableHardwareIndexArrayAGP
= false;
224 #endif // NL_DISABLE_HARDWARE_INDEX_ARRAY_AGP
225 #ifdef NL_DISABLE_HARDWARE_PIXEL_SHADER
226 _DisableHardwarePixelShader
= true;
227 #else // NL_DISABLE_HARDWARE_PIXEL_SHADER
228 _DisableHardwarePixelShader
= false;
229 #endif // NL_DISABLE_HARDWARE_PIXEL_SHADER
231 // Compute the Flag which say if one texture has been changed in CMaterial.
232 _MaterialAllTextureTouchedFlag
= 0;
234 for(i
=0; i
< IDRV_MAT_MAXTEXTURES
; i
++)
236 _MaterialAllTextureTouchedFlag
|= IDRV_TOUCHED_TEX
[i
];
240 _Adapter
= 0xffffffff;
241 _ModifiedRenderState
= NULL
;
243 // Create a Direct 3d object
244 if ( NULL
== (_D3D
= Direct3DCreate9(D3D_SDK_VERSION
)))
246 nlwarning ("Can't create the direct 3d 9 object.");
249 sint val
= MessageBoxA(NULL
, "Your DirectX version is too old. You need to install the latest one.\r\n\r\nPressing OK will quit the game and automatically open your browser to download the latest version of DirectX.\r\nPress Cancel will just quit the game.\r\n", "Mtp Target Error", MB_OKCANCEL
);
252 openURL("http://www.microsoft.com/downloads/details.aspx?FamilyID=4b1f5d0c-5e44-4864-93cd-464ef59da050");
258 _DepthRangeNear
= 0.f
;
259 _DepthRangeFar
= 1.f
;
260 // default for lightmap
261 _LightMapDynamicLightDirty
= false;
262 _LightMapDynamicLightEnabled
= false;
263 _CurrentMaterialSupportedShader
= CMaterial::Normal
;
264 // to avoid any problem if light0 never setuped, and ligthmap rendered
265 _UserLight0
.setupDirectional(CRGBA::Black
, CRGBA::White
, CRGBA::White
, CVector::K
);
266 // All User Light are disabled by Default
267 for(i
=0;i
<MaxLight
;i
++)
268 _UserLightEnable
[i
]= false;
270 _ScissorTouched
= true;
274 _Scissor
.Height
= -1;
276 _CurStencilTest
= false;
277 _CurStencilFunc
= D3DCMP_ALWAYS
;
279 _CurStencilMask
= std::numeric_limits
<DWORD
>::max();
280 _CurStencilOpFail
= D3DSTENCILOP_KEEP
;
281 _CurStencilOpZFail
= D3DSTENCILOP_KEEP
;
282 _CurStencilOpZPass
= D3DSTENCILOP_KEEP
;
283 _CurStencilWriteMask
= std::numeric_limits
<DWORD
>::max();
286 for(uint k
= 0; k
< MaxTexture
; ++k
)
288 _CurrentUVRouting
[k
] = (uint8
) k
;
290 _VolatileVertexBufferRAM
[0] = new CVolatileVertexBuffer
;
291 _VolatileVertexBufferRAM
[1] = new CVolatileVertexBuffer
;
292 _VolatileVertexBufferAGP
[0] = new CVolatileVertexBuffer
;
293 _VolatileVertexBufferAGP
[1] = new CVolatileVertexBuffer
;
294 _VolatileIndexBuffer16RAM
[0]= new CVolatileIndexBuffer
;
295 _VolatileIndexBuffer16RAM
[1]= new CVolatileIndexBuffer
;
296 _VolatileIndexBuffer16AGP
[0]= new CVolatileIndexBuffer
;
297 _VolatileIndexBuffer16AGP
[1]= new CVolatileIndexBuffer
;
298 _VolatileIndexBuffer32RAM
[0]= new CVolatileIndexBuffer
;
299 _VolatileIndexBuffer32RAM
[1]= new CVolatileIndexBuffer
;
300 _VolatileIndexBuffer32AGP
[0]= new CVolatileIndexBuffer
;
301 _VolatileIndexBuffer32AGP
[1]= new CVolatileIndexBuffer
;
302 _MustRestoreLight
= false;
307 _MaxNumPerStageConstantLighted
= 0;
308 _MaxNumPerStageConstantUnlighted
= 0;
309 D3DXMatrixIdentity(&_D3DMatrixIdentity
);
310 _FogColor
= 0xffffffff;
311 _CurrIndexBufferFormat
= CIndexBuffer::IndicesUnknownFormat
;
313 _NonPowerOfTwoTexturesSupported
= false;
315 _AnisotropicMinSupported
= false;
316 _AnisotropicMagSupported
= false;
317 _AnisotropicMinCubeSupported
= false;
318 _AnisotropicMagCubeSupported
= false;
323 _FrustumBottom
= -1.f
;
326 _FrustumPerspective
= false;
330 _SumTextureMemoryUsed
= false;
333 _DesktopGammaRampValid
= false;
336 // ***************************************************************************
338 CDriverD3D::~CDriverD3D()
347 delete _VolatileVertexBufferRAM
[0];
348 delete _VolatileVertexBufferRAM
[1];
349 delete _VolatileVertexBufferAGP
[0];
350 delete _VolatileVertexBufferAGP
[1];
351 delete _VolatileIndexBuffer16RAM
[0];
352 delete _VolatileIndexBuffer16RAM
[1];
353 delete _VolatileIndexBuffer16AGP
[0];
354 delete _VolatileIndexBuffer16AGP
[1];
355 delete _VolatileIndexBuffer32RAM
[0];
356 delete _VolatileIndexBuffer32RAM
[1];
357 delete _VolatileIndexBuffer32AGP
[0];
358 delete _VolatileIndexBuffer32AGP
[1];
361 // ***************************************************************************
363 void CDriverD3D::resetRenderVariables()
365 H_AUTO_D3D(CDriver3D_resetRenderVariables
);
368 for (i
=0; i
<MaxRenderState
; i
++)
370 if (_RenderStateCache
[i
].ValueSet
)
372 // here, don't use 0xcccccccc, because it is a valid value for D3DRS_TFACTOR
373 touchRenderVariable (&(_RenderStateCache
[i
]));
377 for (i
=0; i
<MaxTexture
; i
++)
380 for (j
=0; j
<MaxTextureState
; j
++)
382 if (_TextureStateCache
[i
][j
].Value
!= 0xcccccccc)
384 touchRenderVariable (&(_TextureStateCache
[i
][j
]));
385 _TextureStateCache
[i
][j
].DeviceValue
= 0xcccccccc;
389 for (i
=0; i
<MaxTexture
; i
++)
391 if (_TextureIndexStateCache
[i
].TexGenMode
!= 0xcccccccc)
392 touchRenderVariable (&(_TextureIndexStateCache
[i
]));
394 for (i
=0; i
<MaxTexture
; i
++)
396 if ((uintptr_t)(_TexturePtrStateCache
[i
].Texture
) != 0xcccccccc)
398 touchRenderVariable (&(_TexturePtrStateCache
[i
]));
399 // reset texture because it may reference an old render target
400 CTexturePtrState
&textureState
= (CTexturePtrState
&)(_TexturePtrStateCache
[i
]);
401 textureState
.Texture
= NULL
;
404 for (i
=0; i
<MaxSampler
; i
++)
407 for (j
=0; j
<MaxSamplerState
; j
++)
409 if (_SamplerStateCache
[i
][j
].Value
!= 0xcccccccc)
410 touchRenderVariable (&(_SamplerStateCache
[i
][j
]));
413 touchRenderVariable (&(_MatrixCache
[remapMatrixIndex (D3DTS_VIEW
)]));
414 touchRenderVariable (&(_MatrixCache
[remapMatrixIndex (D3DTS_PROJECTION
)]));
415 touchRenderVariable (&(_MatrixCache
[remapMatrixIndex (D3DTS_TEXTURE0
)]));
416 touchRenderVariable (&(_MatrixCache
[remapMatrixIndex (D3DTS_TEXTURE1
)]));
417 touchRenderVariable (&(_MatrixCache
[remapMatrixIndex (D3DTS_TEXTURE2
)]));
418 touchRenderVariable (&(_MatrixCache
[remapMatrixIndex (D3DTS_TEXTURE3
)]));
419 touchRenderVariable (&(_MatrixCache
[remapMatrixIndex (D3DTS_TEXTURE4
)]));
420 touchRenderVariable (&(_MatrixCache
[remapMatrixIndex (D3DTS_TEXTURE5
)]));
421 touchRenderVariable (&(_MatrixCache
[remapMatrixIndex (D3DTS_TEXTURE6
)]));
422 touchRenderVariable (&(_MatrixCache
[remapMatrixIndex (D3DTS_TEXTURE7
)]));
425 // Vertices and indexes are not valid anymore
426 _VertexBufferCache
.VertexBuffer
= NULL
;
427 _IndexBufferCache
.IndexBuffer
= NULL
;
428 _VertexDeclCache
.Decl
= NULL
;
430 touchRenderVariable (&(_VertexBufferCache
));
431 touchRenderVariable (&(_IndexBufferCache
));
432 touchRenderVariable (&(_VertexDeclCache
));
434 for (i
=0; i
<MaxLight
; i
++)
436 if (*(uintptr_t*)(&(_LightCache
[i
].Light
)) != 0xcccccccc)
438 _LightCache
[i
].EnabledTouched
= true;
439 touchRenderVariable (&(_LightCache
[i
]));
443 // Vertices and indexes are not valid anymore
444 _VertexProgramCache
.VertexProgram
= NULL
;
445 _VertexProgramCache
.VP
= NULL
;
446 touchRenderVariable (&(_VertexProgramCache
));
447 _PixelShaderCache
.PixelShader
= NULL
;
448 touchRenderVariable (&(_PixelShaderCache
));
449 touchRenderVariable(&_MaterialState
);
451 for (i
=0; i
<MaxVertexProgramConstantState
; i
++)
453 touchRenderVariable (&(_VertexProgramConstantCache
[i
]));
455 for (i
=0; i
<MaxPixelShaderConstantState
; i
++)
457 touchRenderVariable (&(_PixelShaderConstantCache
[i
]));
459 setRenderTarget (NULL
, 0, 0, 0, 0, 0, 0);
461 CVertexBuffer::TLocation vertexAgpLocation
= _DisableHardwareVertexArrayAGP
? CVertexBuffer::RAMResident
: CVertexBuffer::AGPResident
;
462 CIndexBuffer::TLocation indexAgpLocation
= _DisableHardwareIndexArrayAGP
? CIndexBuffer::RAMResident
: CIndexBuffer::AGPResident
;
464 // Init volatile vertex buffers
465 _VolatileVertexBufferRAM
[0]->init (CVertexBuffer::RAMResident
, _VolatileVertexBufferRAM
[0]->Size
, _VolatileVertexBufferRAM
[0]->MaxSize
, this);
466 _VolatileVertexBufferRAM
[0]->reset ();
467 _VolatileVertexBufferRAM
[1]->init (CVertexBuffer::RAMResident
, _VolatileVertexBufferRAM
[1]->Size
, _VolatileVertexBufferRAM
[1]->MaxSize
, this);
468 _VolatileVertexBufferRAM
[1]->reset ();
469 _VolatileVertexBufferAGP
[0]->init (vertexAgpLocation
, _VolatileVertexBufferAGP
[0]->Size
, _VolatileVertexBufferAGP
[0]->MaxSize
, this);
470 _VolatileVertexBufferAGP
[0]->reset ();
471 _VolatileVertexBufferAGP
[1]->init (vertexAgpLocation
, _VolatileVertexBufferAGP
[1]->Size
, _VolatileVertexBufferAGP
[1]->MaxSize
, this);
472 _VolatileVertexBufferAGP
[1]->reset ();
474 _VolatileIndexBuffer16RAM
[0]->init (CIndexBuffer::RAMResident
, _VolatileIndexBuffer16RAM
[0]->Size
, _VolatileIndexBuffer16RAM
[0]->MaxSize
, this, CIndexBuffer::Indices16
);
475 _VolatileIndexBuffer16RAM
[0]->reset ();
476 _VolatileIndexBuffer16RAM
[1]->init (CIndexBuffer::RAMResident
, _VolatileIndexBuffer16RAM
[1]->Size
, _VolatileIndexBuffer16RAM
[1]->MaxSize
, this, CIndexBuffer::Indices16
);
477 _VolatileIndexBuffer16RAM
[1]->reset ();
478 _VolatileIndexBuffer16AGP
[0]->init (indexAgpLocation
, _VolatileIndexBuffer16AGP
[0]->Size
, _VolatileIndexBuffer16AGP
[0]->MaxSize
, this, CIndexBuffer::Indices16
);
479 _VolatileIndexBuffer16AGP
[0]->reset ();
480 _VolatileIndexBuffer16AGP
[1]->init (indexAgpLocation
, _VolatileIndexBuffer16AGP
[1]->Size
, _VolatileIndexBuffer16AGP
[1]->MaxSize
, this, CIndexBuffer::Indices16
);
481 _VolatileIndexBuffer16AGP
[1]->reset ();
483 if (_MaxVertexIndex
> 0xffff) // supports 32 bits ?
485 _VolatileIndexBuffer32RAM
[0]->init (CIndexBuffer::RAMResident
, _VolatileIndexBuffer32RAM
[0]->Size
, _VolatileIndexBuffer32RAM
[0]->MaxSize
, this, CIndexBuffer::Indices32
);
486 _VolatileIndexBuffer32RAM
[0]->reset ();
487 _VolatileIndexBuffer32RAM
[1]->init (CIndexBuffer::RAMResident
, _VolatileIndexBuffer32RAM
[1]->Size
, _VolatileIndexBuffer32RAM
[1]->MaxSize
, this, CIndexBuffer::Indices32
);
488 _VolatileIndexBuffer32RAM
[1]->reset ();
489 _VolatileIndexBuffer32AGP
[0]->init (indexAgpLocation
, _VolatileIndexBuffer32AGP
[0]->Size
, _VolatileIndexBuffer32AGP
[0]->MaxSize
, this, CIndexBuffer::Indices32
);
490 _VolatileIndexBuffer32AGP
[0]->reset ();
491 _VolatileIndexBuffer32AGP
[1]->init (indexAgpLocation
, _VolatileIndexBuffer32AGP
[1]->Size
, _VolatileIndexBuffer32AGP
[1]->MaxSize
, this, CIndexBuffer::Indices32
);
492 _VolatileIndexBuffer32AGP
[1]->reset ();
494 _ScissorTouched
= true;
497 // ***************************************************************************
499 void CDriverD3D::initRenderVariables()
501 H_AUTO_D3D(CDriver3D_initRenderVariables
);
503 for (i
=0; i
<MaxRenderState
; i
++)
505 _RenderStateCache
[i
].StateID
= (D3DRENDERSTATETYPE
)i
;
506 _RenderStateCache
[i
].ValueSet
= false;
507 _RenderStateCache
[i
].Modified
= false;
509 for (i
=0; i
<MaxTexture
; i
++)
512 for (j
=0; j
<MaxTextureState
; j
++)
514 _TextureStateCache
[i
][j
].StageID
= i
;
515 _TextureStateCache
[i
][j
].StateID
= (D3DTEXTURESTAGESTATETYPE
)j
;
516 _TextureStateCache
[i
][j
].Value
= 0xcccccccc;
517 _TextureStateCache
[i
][j
].Modified
= false;
520 for (i
=0; i
<MaxTexture
; i
++)
522 _TextureIndexStateCache
[i
].StageID
= i
;
523 _TextureIndexStateCache
[i
].TexGen
= false;
524 _TextureIndexStateCache
[i
].TexGenMode
= 0xcccccccc;
525 _TextureIndexStateCache
[i
].UVChannel
= 0xcccccccc;
526 _TextureIndexStateCache
[i
].Modified
= false;
528 for (i
=0; i
<MaxTexture
; i
++)
530 _TexturePtrStateCache
[i
].StageID
= i
;
531 *(uintptr_t*)&(_TexturePtrStateCache
[i
].Texture
) = 0xcccccccc;
532 _TexturePtrStateCache
[i
].Modified
= false;
534 for (i
=0; i
<MaxSampler
; i
++)
537 for (j
=0; j
<MaxSamplerState
; j
++)
539 _SamplerStateCache
[i
][j
].SamplerID
= i
;
540 _SamplerStateCache
[i
][j
].StateID
= (D3DSAMPLERSTATETYPE
)j
;
541 _SamplerStateCache
[i
][j
].Value
= 0xcccccccc;
542 _SamplerStateCache
[i
][j
].Modified
= false;
545 for (i
=0; i
<MaxMatrixState
; i
++)
547 _MatrixCache
[i
].TransformType
= (D3DTRANSFORMSTATETYPE
)((i
>=MatrixStateRemap
)?i
-MatrixStateRemap
+256:i
);
548 memset (&(_MatrixCache
[i
].Matrix
), 0xcc, sizeof(D3DXMATRIX
));
549 _MatrixCache
[i
].Modified
= false;
551 _VertexBufferCache
.Modified
= false;
552 _VertexBufferCache
.VertexBuffer
= NULL
;
553 _IndexBufferCache
.Modified
= false;
554 _IndexBufferCache
.IndexBuffer
= NULL
;
555 _VertexDeclCache
.Modified
= false;
556 _VertexDeclCache
.Decl
= NULL
;
557 for (i
=0; i
<MaxLight
; ++i
)
559 _LightCache
[i
].LightIndex
= uint8(i
);
560 *(uintptr_t*)&(_LightCache
[i
].Light
) = 0xcccccccc;
561 _LightCache
[i
].Modified
= false;
563 _VertexProgramCache
.Modified
= false;
564 _VertexProgramCache
.VertexProgram
= NULL
;
565 _PixelShaderCache
.Modified
= false;
566 _PixelShaderCache
.PixelShader
= NULL
;
567 for (i
=0; i
<MaxVertexProgramConstantState
; i
++)
569 _VertexProgramConstantCache
[i
].StateID
= i
;
570 _VertexProgramConstantCache
[i
].Modified
= false;
571 _VertexProgramConstantCache
[i
].ValueType
= CVertexProgramConstantState::Undef
;
573 for (i
=0; i
<MaxPixelShaderConstantState
; i
++)
575 _PixelShaderConstantCache
[i
].StateID
= i
;
576 _PixelShaderConstantCache
[i
].Modified
= false;
577 _PixelShaderConstantCache
[i
].ValueType
= CPixelShaderConstantState::Undef
;
579 _RenderTarget
.Modified
= false;
582 // Set the render states cache to its default values
583 setRenderState (D3DRS_COLORWRITEENABLE
, D3DCOLORWRITEENABLE_ALPHA
|D3DCOLORWRITEENABLE_RED
|D3DCOLORWRITEENABLE_GREEN
|D3DCOLORWRITEENABLE_BLUE
);
584 setRenderState (D3DRS_CULLMODE
, D3DCULL_CW
);
585 setRenderState (D3DRS_FOGENABLE
, FALSE
);
589 setRenderState (D3DRS_STENCILENABLE
, _CurStencilTest
);
590 setRenderState (D3DRS_STENCILFUNC
, _CurStencilFunc
);
591 setRenderState (D3DRS_STENCILREF
, _CurStencilRef
);
592 setRenderState (D3DRS_STENCILMASK
, _CurStencilMask
);
593 setRenderState (D3DRS_STENCILFAIL
, _CurStencilOpFail
);
594 setRenderState (D3DRS_STENCILZFAIL
, _CurStencilOpZFail
);
595 setRenderState (D3DRS_STENCILPASS
, _CurStencilOpZPass
);
596 setRenderState (D3DRS_STENCILWRITEMASK
, _CurStencilWriteMask
);
599 _ForceNormalize
= false;
600 _UseVertexColor
= false;
603 _CurrentMaterial
= NULL
;
604 _CurrentMaterialInfo
= NULL
;
605 _CurrentShader
= NULL
;
608 initInternalShaders();
610 // Fog default values
613 setRenderState (D3DRS_FOGSTART
, *((DWORD
*) (&_FogStart
)));
614 setRenderState (D3DRS_FOGEND
, *((DWORD
*) (&_FogEnd
)));
615 setRenderState (D3DRS_FOGVERTEXMODE
, D3DFOG_LINEAR
);
617 // Alpha render states
618 setRenderState (D3DRS_ALPHATESTENABLE
, FALSE
);
619 setRenderState (D3DRS_ALPHAREF
, 128);
620 setRenderState (D3DRS_ALPHAFUNC
, D3DCMP_GREATER
);
623 _InvertCullMode
= false;
624 _DoubleSided
= false;
627 _DepthRangeNear
= 0.f
;
628 _DepthRangeFar
= 1.f
;
631 updateRenderVariablesInternal();
634 // ***************************************************************************
636 #define NL_SRC_OPERATORS_COUNT 6
638 // ***************************************************************************
640 static const D3DTEXTURESTAGESTATETYPE SrcOperators
[NL_SRC_OPERATORS_COUNT
]=
650 // ***************************************************************************
652 void CDriverD3D::updateRenderVariables()
654 H_AUTO_D3D(CDriver3D_updateRenderVariables
);
655 _CurrentMaterial
= NULL
;
656 _CurrentMaterialInfo
= NULL
;
658 updateRenderVariablesInternal();
661 // ***************************************************************************
663 inline void CDriverD3D::applyRenderVariable(CRenderVariable *currentRenderState)
665 switch (currentRenderState->Type)
667 case CRenderVariable::RenderState:
669 CRenderState *renderState = static_cast<CRenderState*>(currentRenderState);
670 _DeviceInterface->SetRenderState (renderState->StateID, renderState->Value);
673 case CRenderVariable::TextureState:
675 CTextureState *textureState = static_cast<CTextureState*>(currentRenderState);
676 _DeviceInterface->SetTextureStageState (textureState->StageID, textureState->StateID, textureState->Value);
679 case CRenderVariable::TextureIndexState:
681 CTextureIndexState *textureState = static_cast<CTextureIndexState*>(currentRenderState);
682 if (textureState->TexGen)
683 setTextureState (textureState->StageID, D3DTSS_TEXCOORDINDEX, textureState->TexGenMode);
685 setTextureState (textureState->StageID, D3DTSS_TEXCOORDINDEX, textureState->UVChannel);
688 case CRenderVariable::TexturePtrState:
690 CTexturePtrState *textureState = static_cast<CTexturePtrState*>(currentRenderState);
691 _DeviceInterface->SetTexture (textureState->StageID, textureState->Texture);
694 case CRenderVariable::VertexProgramPtrState:
696 CVertexProgramPtrState *vertexProgram = static_cast<CVertexProgramPtrState*>(currentRenderState);
697 _DeviceInterface->SetVertexShader(vertexProgram->VertexProgram);
700 case CRenderVariable::PixelShaderPtrState:
702 CPixelShaderPtrState *pixelShader = static_cast<CPixelShaderPtrState*>(currentRenderState);
703 _DeviceInterface->SetPixelShader(pixelShader->PixelShader);
706 case CRenderVariable::VertexProgramConstantState:
708 CVertexProgramConstantState *vertexProgramConstant = static_cast<CVertexProgramConstantState*>(currentRenderState);
709 switch (vertexProgramConstant->ValueType)
711 case CVertexProgramConstantState::Float:
712 _DeviceInterface->SetVertexShaderConstantF (vertexProgramConstant->StateID, (float*)vertexProgramConstant->Values, 1);
714 case CVertexProgramConstantState::Int:
715 _DeviceInterface->SetVertexShaderConstantI (vertexProgramConstant->StateID, (int*)vertexProgramConstant->Values, 1);
720 case CRenderVariable::PixelShaderConstantState:
722 CPixelShaderConstantState *pixelShaderConstant = static_cast<CPixelShaderConstantState*>(currentRenderState);
723 switch (pixelShaderConstant->ValueType)
725 case CPixelShaderConstantState::Float:
726 _DeviceInterface->SetPixelShaderConstantF (pixelShaderConstant->StateID, (float*)pixelShaderConstant->Values, 1);
728 case CPixelShaderConstantState::Int:
729 _DeviceInterface->SetPixelShaderConstantI (pixelShaderConstant->StateID, (int*)pixelShaderConstant->Values, 1);
734 case CRenderVariable::SamplerState:
736 CSamplerState *samplerState = static_cast<CSamplerState*>(currentRenderState);
737 _DeviceInterface->SetSamplerState (samplerState->SamplerID, samplerState->StateID, samplerState->Value);
740 case CRenderVariable::MatrixState:
742 CMatrixState *renderMatrix = static_cast<CMatrixState*>(currentRenderState);
743 _DeviceInterface->SetTransform (renderMatrix->TransformType, &(renderMatrix->Matrix));
746 case CRenderVariable::VBState:
748 CVBState *renderVB = static_cast<CVBState*>(currentRenderState);
749 if (renderVB->VertexBuffer)
751 _DeviceInterface->SetStreamSource (0, renderVB->VertexBuffer, renderVB->Offset, renderVB->Stride);
755 case CRenderVariable::IBState:
757 CIBState *renderIB = static_cast<CIBState*>(currentRenderState);
758 if (renderIB->IndexBuffer)
760 _DeviceInterface->SetIndices (renderIB->IndexBuffer);
764 case CRenderVariable::VertexDecl:
766 CVertexDeclState *renderVB = static_cast<CVertexDeclState*>(currentRenderState);
769 _DeviceInterface->SetVertexDeclaration (renderVB->Decl);
773 case CRenderVariable::LightState:
775 CLightState *renderLight = static_cast<CLightState*>(currentRenderState);
777 // Enabel state modified ?
778 if (renderLight->EnabledTouched)
779 _DeviceInterface->LightEnable (renderLight->LightIndex, renderLight->Enabled);
782 if (renderLight->Enabled)
784 if (renderLight->SettingsTouched)
787 renderLight->Light.Position.x -= _PZBCameraPos.x;
788 renderLight->Light.Position.y -= _PZBCameraPos.y;
789 renderLight->Light.Position.z -= _PZBCameraPos.z;
790 _DeviceInterface->SetLight (renderLight->LightIndex, &(renderLight->Light));
791 renderLight->SettingsTouched = false;
796 renderLight->EnabledTouched = false;
799 case CRenderVariable::RenderTargetState:
801 CRenderTargetState *renderTarget = static_cast<CRenderTargetState*>(currentRenderState);
802 _DeviceInterface->SetRenderTarget (0, renderTarget->Target);
803 setupViewport (_Viewport);
804 setupScissor (_Scissor);
813 // ***************************************************************************
817 void CDriverD3D::replaceArgumentAtStage(D3DTEXTURESTAGESTATETYPE state
, DWORD stage
, DWORD from
, DWORD to
)
819 if ((_TextureStateCache
[stage
][state
].Value
& D3DTA_SELECTMASK
) == from
)
821 setTextureState (stage
, state
, (_TextureStateCache
[stage
][state
].Value
&~D3DTA_SELECTMASK
)|to
);
825 // ***************************************************************************
826 // Replace a constant with diffuse color at the given stage
830 void CDriverD3D::replaceAllRGBArgumentAtStage(uint stage
, DWORD from
, DWORD to
, DWORD blendOpFrom
)
832 replaceArgumentAtStage(D3DTSS_COLORARG1
, stage
, from
, to
);
833 if (_CurrentMaterialInfo
->NumColorArg
[stage
] > 1)
835 replaceArgumentAtStage(D3DTSS_COLORARG2
, stage
, from
, to
);
836 if (_CurrentMaterialInfo
->NumColorArg
[stage
] > 2)
838 replaceArgumentAtStage(D3DTSS_COLORARG0
, stage
, from
, to
);
842 // Operator is D3DTOP_BLENDDIFFUSEALPHA ?
843 if (_TextureStateCache
[stage
][D3DTSS_COLOROP
].Value
== blendOpFrom
)
845 setTextureState (stage
, D3DTSS_COLOROP
, D3DTOP_LERP
);
846 setTextureState (stage
, D3DTSS_COLORARG0
, to
|D3DTA_ALPHAREPLICATE
);
854 void CDriverD3D::replaceAllAlphaArgumentAtStage(uint stage
, DWORD from
, DWORD to
, DWORD blendOpFrom
)
856 replaceArgumentAtStage(D3DTSS_ALPHAARG1
, stage
, from
, to
);
857 if (_CurrentMaterialInfo
->NumAlphaArg
[stage
] > 1)
859 replaceArgumentAtStage(D3DTSS_ALPHAARG2
, stage
, from
, to
);
860 if (_CurrentMaterialInfo
->NumAlphaArg
[stage
] > 2)
862 replaceArgumentAtStage(D3DTSS_ALPHAARG0
, stage
, from
, to
);
865 if (_TextureStateCache
[stage
][D3DTSS_ALPHAOP
].Value
== blendOpFrom
)
867 setTextureState (stage
, D3DTSS_ALPHAOP
, D3DTOP_LERP
);
868 setTextureState (stage
, D3DTSS_ALPHAARG0
, to
);
875 void CDriverD3D::replaceAllArgumentAtStage(uint stage
, DWORD from
, DWORD to
, DWORD blendOpFrom
)
877 if (_CurrentMaterialInfo
->RGBPipe
[stage
])
879 replaceAllRGBArgumentAtStage(stage
, from
, to
, blendOpFrom
);
881 if (_CurrentMaterialInfo
->AlphaPipe
[stage
])
883 replaceAllAlphaArgumentAtStage(stage
, from
, to
, blendOpFrom
);
887 // ***************************************************************************
888 // Replace all argument at relevant stages with the given value
892 void CDriverD3D::replaceAllArgument(DWORD from
, DWORD to
, DWORD blendOpFrom
)
894 const uint maxTexture
= inlGetNumTextStages();
895 // Look for texture state
896 for (uint i
=0; i
<maxTexture
; i
++)
898 if (_CurrentMaterialInfo
->ColorOp
[i
] == D3DTOP_DISABLE
) break;
899 replaceAllArgumentAtStage(i
, from
, to
, blendOpFrom
);
903 // ***************************************************************************
907 void CDriverD3D::setupConstantDiffuseColorFromLightedMaterial(D3DCOLOR color
)
909 for(uint i
=1;i
<_MaxLight
;++i
)
910 enableLightInternal(uint8(i
), false);
911 _LightMapDynamicLightDirty
= true;
913 setColor(d3dMat
.Diffuse
, 0.f
, 0.f
, 0.f
, (1.f
/ 255.f
) * (color
>> 24));
914 setColor(d3dMat
.Ambient
, 0.f
, 0.f
, 0.f
, 0.f
);
915 setColor(d3dMat
.Specular
, 0.f
, 0.f
, 0.f
, 0.f
);
916 setColor(d3dMat
.Emissive
, color
);
917 setMaterialState(d3dMat
);
918 setRenderState(D3DRS_LIGHTING
, TRUE
);
922 // ***************************************************************************
923 void CDriverD3D::updateRenderVariablesInternal()
925 H_AUTO_D3D(CDriver3D_updateRenderVariablesInternal
);
926 nlassert (_DeviceInterface
);
927 bool aliasDiffuseToSpecular
= false;
928 bool enableVertexColorFlag
= true;
929 if (_CurrentMaterialInfo
&& (_CurrentMaterialInfo
->NeedsConstantForDiffuse
|| _CurrentMaterialInfo
->MultipleConstantNoPixelShader
)) /* The "unlighted without vertex color" trick */
931 // The material IS unlighted
933 if (_CurrentMaterialInfo
->PixelShader
)
936 * We have to set the pixel shader now, because we have to choose between normal pixel shader and pixel shader without vertex color */
937 // Must have two pixel shader
938 nlassert (_CurrentMaterialInfo
->PixelShaderUnlightedNoVertexColor
);
939 if (!_UseVertexColor
&& (_VertexProgramCache
.VertexProgram
== NULL
))
941 setPixelShader (_CurrentMaterialInfo
->PixelShaderUnlightedNoVertexColor
);
945 setPixelShader (_CurrentMaterialInfo
->PixelShader
);
950 setPixelShader (NULL
);
951 if (_CurrentMaterialInfo
->NeedsConstantForDiffuse
)
954 * We have to change all texture state setuped to D3DTA_DIFFUSE into D3DTA_TFACTOR
955 * if we use a vertex buffer with diffuse color vertex with an unlighted material and no vertex program */
956 if (_VertexProgramCache
.VertexProgram
)
958 // Diffuse should be output from vertex program
959 // So we can only emulate 1 per stage constant (it has already been setup in CDriverD3D::setupMaterial)
961 nlassert(!_CurrentMaterialInfo
->MultipleConstantNoPixelShader
);
966 if (!_UseVertexColor
)
968 if (!_CurrentMaterialInfo
->MultipleConstantNoPixelShader
)
970 // Diffuse is used, but no other constant is used in the shader
972 replaceAllArgument(D3DTA_DIFFUSE
, D3DTA_TFACTOR
, D3DTOP_BLENDDIFFUSEALPHA
);
973 setRenderState (D3DRS_TEXTUREFACTOR
, _CurrentMaterialInfo
->UnlightedColor
);
978 nlassert(!_CurrentMaterialInfo
->MultiplePerStageConstant
); // Can't render this material on current hardware
980 //replaceAllArgumentAtStage(_CurrentMaterialInfo->ConstantIndex, D3DTA_TFACTOR, D3DTA_DIFFUSE, D3DTOP_BLENDFACTORALPHA);
981 setupConstantDiffuseColorFromLightedMaterial(_CurrentMaterialInfo
->UnlightedColor
);
986 if (_CurrentMaterialInfo
->MultiplePerStageConstant
)
988 // vertex color, 1st constant from CMaterial::getColor (already setuped in CDriverD3D::setupMaterial)
989 // 2nd constant from a stage constant
990 // Vertex color is aliased to the specular stream -> all references to D3DTA_DIFFUSE must be replaced with references to D3DTA_SPECULAR
991 replaceAllArgument(D3DTA_DIFFUSE
, D3DTA_SPECULAR
, 0xffffffff);
992 aliasDiffuseToSpecular
= true;
993 replaceAllArgumentAtStage(_CurrentMaterialInfo
->ConstantIndex2
, D3DTA_TFACTOR
, D3DTA_DIFFUSE
, D3DTOP_BLENDFACTORALPHA
);
994 setupConstantDiffuseColorFromLightedMaterial(NL_D3DCOLOR_RGBA(_CurrentMaterialInfo
->Constant2
)); // set 2nd per stage constant
996 nlassert(_VertexDeclCache
.DeclAliasDiffuseToSpecular
); // VB must not have specular used ... else this material can't render
998 // NB : currently this don't work with the GeForce2 (seems to be a driver bug). Fortunately, this case isn't encountered with Ryzom materials :)
999 // So it's provided for convenience.
1006 nlassert(_CurrentMaterialInfo
->MultipleConstantNoPixelShader
);
1007 // If vertex color is used, alias it to specular
1009 if (_UseVertexColor)
1011 replaceAllArgument(D3DTA_DIFFUSE, D3DTA_SPECULAR, 0xffffffff);
1012 aliasDiffuseToSpecular = true; // VB must not have specular used ... else this material can't render
1015 // up to 2 constants with no pixel shaders
1016 // look for constant at other stages and replaces then with diffuse color
1017 // first constant color has already been set yet (in CD3DDriver::setupMaterial)
1018 replaceAllArgumentAtStage(_CurrentMaterialInfo
->ConstantIndex2
, D3DTA_TFACTOR
, D3DTA_DIFFUSE
, D3DTOP_BLENDFACTORALPHA
);
1019 setupConstantDiffuseColorFromLightedMaterial(NL_D3DCOLOR_RGBA(_CurrentMaterialInfo
->Constant2
)); // set 2nd per stage constant
1025 if (_CurrentMaterialInfo
) enableVertexColorFlag
= _CurrentMaterialInfo
->VertexColorLighted
;
1029 if (_NbNeLTextureStages
== 3)
1031 // Fix (one more...) for Radeon 7xxx
1032 // Don't know why, but the lighting is broken when MULTIPLYADD is used as in the lightmap shader..
1033 // Correct behaviour with GeForce & Ref. rasterizer...
1034 // The fix is to disable the light contribution from dynamic lights
1035 if (_TextureStateCache
[0][D3DTSS_COLOROP
].Value
== D3DTOP_MULTIPLYADD
&&
1036 _TextureStateCache
[0][D3DTSS_COLORARG0
].Value
== D3DTA_DIFFUSE
1039 _TextureStateCache
[0][D3DTSS_COLOROP
].Value
= D3DTOP_MODULATE
;
1040 touchRenderVariable(&_TextureStateCache
[0][D3DTSS_COLOROP
]);
1042 // fix for radeon 7xxx -> should enable vertex color only if really used in pixel pipe
1043 setEnableVertexColor(enableVertexColorFlag
);
1045 setAliasDiffuseToSpecular(aliasDiffuseToSpecular
);
1048 // Flush all the modified render states
1049 while (_ModifiedRenderState
)
1052 CRenderVariable
*currentRenderState
= _ModifiedRenderState
;
1055 currentRenderState
->Modified
= false;
1058 _ModifiedRenderState
= currentRenderState
->NextModified
;
1059 currentRenderState
->apply(this);
1063 // Maybe it is a driver bug : in some situation with GeForce, I got vertex color set to (0, 0, 0, 0) with unlighted vertices and vertex color.
1064 // Forcing to resetup material solves the prb.. (though D3DRS_LIGHTING is set to FALSE ...)
1065 // I only have the prb with GeForce. The behaviour doesn't exhibit when using the D3D debug dll.
1068 if (_RenderStateCache
[D3DRS_LIGHTING
].Value
== FALSE
&& _VertexProgramCache
.VertexProgram
== NULL
)
1070 _MaterialState
.apply(this);
1078 // ***************************************************************************
1080 void D3DWndProc(CDriverD3D
*driver
, HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1082 H_AUTO_D3D(D3DWndProc
);
1084 // Check this message in parents
1086 if ((message
== WM_SIZE
) || (message
== WM_EXITSIZEMOVE
) || (message
== WM_MOVE
))
1090 // *** Check the hwnd is the root parent of driver->_HWnd
1092 // hwnd must be a _HWnd parent
1093 bool sameWindow
= hWnd
== driver
->_HWnd
;
1094 bool rootWindow
= false;
1095 HWND tmp
= driver
->_HWnd
;
1103 tmp
= GetParent (tmp
);
1106 // hwnd must be a top window
1107 rootWindow
&= (GetParent (hWnd
) == NULL
);
1109 // This is a root parent, not _HWnd
1112 if (message
== WM_SIZE
)
1114 if( SIZE_MAXIMIZED
== wParam
)
1116 driver
->_Maximized
= true;
1118 driver
->handlePossibleSizeChange();
1120 driver
->_HandlePossibleSizeChangeNextSize
= true;
1122 else if( SIZE_RESTORED
== wParam
)
1124 if (driver
->_Maximized
)
1126 driver
->_Maximized
= false;
1128 driver
->handlePossibleSizeChange();
1130 driver
->_HandlePossibleSizeChangeNextSize
= true;
1134 else if(message
== WM_EXITSIZEMOVE
)
1138 driver
->handlePossibleSizeChange();
1141 else if(message
== WM_MOVE
)
1146 GetWindowRect (hWnd
, &rect
);
1147 driver
->_WindowX
= rect
.left
;
1148 driver
->_WindowY
= rect
.top
;
1152 // This is the window itself
1153 else if (sameWindow
)
1155 if (message
== WM_SIZE
)
1157 if (driver
->_HandlePossibleSizeChangeNextSize
)
1159 driver
->handlePossibleSizeChange();
1160 driver
->_HandlePossibleSizeChangeNextSize
= false;
1168 if ((message
== WM_SETFOCUS
) || (message
== WM_KILLFOCUS
))
1172 driver
->_WindowFocus
= (message
== WM_SETFOCUS
);
1176 if (driver
&& driver
->_EventEmitter
.getNumEmitters() > 0)
1178 CWinEventEmitter
*we
= NLMISC::safe_cast
<CWinEventEmitter
*>(driver
->_EventEmitter
.getEmitter(0));
1179 // Process the message by the emitter
1181 we
->processMessage (hWnd
, message
, wParam
, lParam
);
1185 // ***************************************************************************
1187 bool CDriverD3D::handlePossibleSizeChange()
1189 //DUMP_AUTO(handlePossibleSizeChange);
1190 H_AUTO_D3D(CDriver3D_handlePossibleSizeChange
);
1191 // If windowed, check if the size as changed
1192 if (_CurrentMode
.Windowed
)
1195 GetClientRect (_HWnd
, &rect
);
1197 // Setup d3d resolution
1198 uint16 newWidth
= uint16(rect
.right
-rect
.left
);
1199 uint16 newHeight
= uint16(rect
.bottom
-rect
.top
);
1201 // Set the new mode. Only change the size, keep the last setDisplay/setMode settings
1202 GfxMode mode
= _CurrentMode
;
1203 mode
.Width
= newWidth
;
1204 mode
.Height
= newHeight
;
1206 if ( ( (mode
.Width
!= _CurrentMode
.Width
) || (mode
.Height
!= _CurrentMode
.Height
) ) &&
1207 ( mode
.Width
!= 0 ) &&
1208 ( mode
.Height
!= 0 ) )
1210 return reset (mode
);
1216 // ***************************************************************************
1218 static LRESULT CALLBACK
WndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1220 H_AUTO_D3D(WndProc
);
1221 // Get the driver pointer..
1222 CDriverD3D
*pDriver
=(CDriverD3D
*)GetWindowLongPtrW (hWnd
, GWLP_USERDATA
);
1223 if (pDriver
!= NULL
)
1225 D3DWndProc (pDriver
, hWnd
, message
, wParam
, lParam
);
1228 if (message
== WM_SYSCOMMAND
)
1232 #ifdef NL_DISABLE_MENU
1233 // disable menu (F10, ALT and ALT+SPACE key doesn't freeze or open the menu)
1235 #endif // NL_DISABLE_MENU
1237 // Screensaver Trying To Start?
1240 // Monitor Trying To Enter Powersave?
1241 case SC_MONITORPOWER
:
1243 // Prevent From Happening
1251 // ace: if we receive close, exit now or it'll assert after
1252 if(message
== WM_CLOSE
)
1254 if(pDriver
&& pDriver
->ExitFunc
)
1256 pDriver
->ExitFunc();
1260 #ifndef NL_DISABLE_MENU
1261 // if we don't disable menu, alt F4 make a direct exit else we discard the message
1263 #endif // NL_DISABLE_MENU
1269 // https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-unichar
1270 if (message
== WM_UNICHAR
)
1271 return (wParam
== UNICODE_NOCHAR
);
1274 return DefWindowProcW(hWnd
, message
, wParam
, lParam
);
1277 // ***************************************************************************
1279 bool CDriverD3D::init (uintptr_t windowIcon
, emptyProc exitFunc
)
1281 H_AUTO_D3D(CDriver3D_init
);
1283 ExitFunc
= exitFunc
;
1287 _WindowClass
= utf8ToWide("NLD3D" + toString(windowIcon
));
1289 // Register a window class
1292 memset(&wc
,0,sizeof(wc
));
1293 wc
.style
= 0; // CS_HREDRAW | CS_VREDRAW ;//| CS_DBLCLKS;
1294 wc
.lpfnWndProc
= (WNDPROC
)WndProc
;
1297 wc
.hInstance
= GetModuleHandleW(NULL
);
1298 wc
.hIcon
= (HICON
)windowIcon
;
1299 wc
.hCursor
= _DefaultCursor
;
1300 wc
.hbrBackground
= WHITE_BRUSH
;
1301 wc
.lpszClassName
= _WindowClass
.c_str();
1302 wc
.lpszMenuName
= NULL
;
1303 if (!RegisterClassW(&wc
))
1305 DWORD error
= GetLastError();
1306 if (error
!= ERROR_CLASS_ALREADY_EXISTS
)
1308 nlwarning("CDriverD3D::init: Can't register window class %s (error code %i)", _WindowClass
.c_str(), (sint
)error
);
1309 _WindowClass
.clear();
1317 // ***************************************************************************
1320 bool CDriverD3D::isDepthFormatOk(UINT adapter
, D3DDEVTYPE rasterizer
, D3DFORMAT DepthFormat
,
1321 D3DFORMAT AdapterFormat
,
1322 D3DFORMAT BackBufferFormat
)
1324 H_AUTO_D3D(CDriverD3D_isDepthFormatOk
);
1325 // Verify that the depth format exists
1326 HRESULT hr
= _D3D
->CheckDeviceFormat(adapter
,
1329 D3DUSAGE_DEPTHSTENCIL
,
1333 if(FAILED(hr
)) return FALSE
;
1335 // Verify that the depth format is compatible
1336 hr
= _D3D
->CheckDepthStencilMatch(adapter
,
1337 (D3DDEVTYPE
) rasterizer
,
1342 return SUCCEEDED(hr
);
1346 // ***************************************************************************
1348 const D3DFORMAT FinalPixelFormat
[ITexture::UploadFormatCount
][CDriverD3D::FinalPixelFormatChoice
]=
1350 { D3DFMT_A8R8G8B8
, D3DFMT_A8R8G8B8
, D3DFMT_A8R8G8B8
, D3DFMT_A8R8G8B8
, D3DFMT_A8R8G8B8
}, // Auto
1351 { D3DFMT_A8R8G8B8
, D3DFMT_A8R8G8B8
, D3DFMT_A8R8G8B8
, D3DFMT_A8R8G8B8
, D3DFMT_A8R8G8B8
}, // RGBA8888
1352 { D3DFMT_A4R4G4B4
, D3DFMT_A1R5G5B5
, D3DFMT_A8R3G3B2
, D3DFMT_A8R8G8B8
, D3DFMT_A8R8G8B8
}, // RGBA4444
1353 { D3DFMT_A1R5G5B5
, D3DFMT_A4R4G4B4
, D3DFMT_A8R8G8B8
, D3DFMT_A8R8G8B8
, D3DFMT_A8R8G8B8
}, // RGBA5551
1354 { D3DFMT_R8G8B8
, D3DFMT_A8R8G8B8
, D3DFMT_A8R8G8B8
, D3DFMT_A8R8G8B8
, D3DFMT_A8R8G8B8
}, // RGB888
1355 { D3DFMT_R5G6B5
, D3DFMT_A1R5G5B5
, D3DFMT_A8R8G8B8
, D3DFMT_A8R8G8B8
, D3DFMT_A8R8G8B8
}, // RGB565
1356 { D3DFMT_DXT1
, D3DFMT_R3G3B2
, D3DFMT_A1R5G5B5
, D3DFMT_R5G6B5
, D3DFMT_A8R8G8B8
}, // DXTC1
1357 { D3DFMT_DXT1
, D3DFMT_R3G3B2
, D3DFMT_A1R5G5B5
, D3DFMT_R5G6B5
, D3DFMT_A8R8G8B8
}, // DXTC1Alpha
1358 { D3DFMT_DXT3
, D3DFMT_A4R4G4B4
, D3DFMT_A8R8G8B8
, D3DFMT_A8R8G8B8
, D3DFMT_A8R8G8B8
}, // DXTC3
1359 { D3DFMT_DXT5
, D3DFMT_A4R4G4B4
, D3DFMT_A8R8G8B8
, D3DFMT_A8R8G8B8
, D3DFMT_A8R8G8B8
}, // DXTC5
1360 { D3DFMT_L8
, D3DFMT_A8L8
, D3DFMT_R5G6B5
, D3DFMT_A1R5G5B5
, D3DFMT_A8R8G8B8
}, // Luminance
1361 { D3DFMT_A8
, D3DFMT_A8L8
, D3DFMT_A8R3G3B2
, D3DFMT_A8R8G8B8
, D3DFMT_A8R8G8B8
}, // Alpha
1362 { D3DFMT_A8L8
, D3DFMT_A8R8G8B8
, D3DFMT_A8R8G8B8
, D3DFMT_A8R8G8B8
, D3DFMT_A8R8G8B8
}, // AlphaLuminance
1363 { D3DFMT_V8U8
, D3DFMT_A8R8G8B8
, D3DFMT_A8R8G8B8
, D3DFMT_A8R8G8B8
, D3DFMT_A8R8G8B8
}, // DsDt
1366 // ***************************************************************************
1368 bool CDriverD3D::setDisplay(nlWindow wnd
, const GfxMode
& mode
, bool show
, bool resizeable
)
1370 H_AUTO_D3D(CDriver3D_setDisplay
);
1372 if (!mode
.OffScreen
)
1373 NLMISC::INelContext::getInstance().setWindowedApplication(true);
1378 CFpuRestorer fpuRestorer
;
1380 // Release the driver if already setuped
1383 // Should be initialized
1384 nlassert (!_WindowClass
.empty());
1386 // Should be released
1387 nlassert (_DeviceInterface
== NULL
);
1388 nlassert (_HWnd
== NULL
);
1390 // memorize desktop gamma ramp
1391 HDC dc
= CreateDCW (L
"DISPLAY", NULL
, NULL
, NULL
);
1394 _DesktopGammaRampValid
= GetDeviceGammaRamp (dc
, _DesktopGammaRamp
) != FALSE
;
1396 ReleaseDC (NULL
, dc
);
1402 // Reset window state
1404 _HandlePossibleSizeChangeNextSize
= false;
1405 _WindowFocus
= true;
1409 // We don't have to destroy this window
1410 _DestroyWindow
= false;
1412 // Init Window Width and Height
1414 GetClientRect (_HWnd
, &clientRect
);
1415 _CurrentMode
.OffScreen
= false;
1416 _CurrentMode
.Width
= (uint16
)(clientRect
.right
-clientRect
.left
);
1417 _CurrentMode
.Height
= (uint16
)(clientRect
.bottom
-clientRect
.top
);
1418 _CurrentMode
.Frequency
= 0;
1419 _CurrentMode
.Windowed
= true;
1420 _CurrentMode
.Depth
= 32;
1424 _CurrentMode
= mode
;
1426 // We have to destroy this window
1427 _DestroyWindow
= true;
1430 //ULONG WndFlags=(mode.Windowed?D3D_WINDOWED_STYLE:D3D_FULLSCREEN_STYLE)&~WS_VISIBLE;
1434 WndFlags
= D3D_WINDOWED_STYLE
;
1437 WndFlags
&= ~(WS_THICKFRAME
|WS_MAXIMIZEBOX
);
1442 WndFlags
= D3D_FULLSCREEN_STYLE
;
1443 findNearestFullscreenVideoMode();
1446 WndFlags
&= ~WS_VISIBLE
;
1452 WndRect
.right
=_CurrentMode
.Width
;
1453 WndRect
.bottom
=_CurrentMode
.Height
;
1454 AdjustWindowRect(&WndRect
,WndFlags
,FALSE
);
1457 _HWnd
= CreateWindowW(_WindowClass
.c_str(), L
"", WndFlags
, CW_USEDEFAULT
,CW_USEDEFAULT
, WndRect
.right
-WndRect
.left
,WndRect
.bottom
-WndRect
.top
, NULL
, NULL
,
1458 GetModuleHandleW(NULL
), NULL
);
1461 nlwarning ("CreateWindowW failed");
1466 // Set the window long integer
1467 SetWindowLongPtrW (_HWnd
, GWLP_USERDATA
, (LONG_PTR
)this);
1470 if (show
|| !_CurrentMode
.Windowed
)
1474 // Choose an adapter
1475 UINT adapter
= (_Adapter
==0xffffffff)?D3DADAPTER_DEFAULT
:(UINT
)_Adapter
;
1477 // Get adapter format
1478 D3DDISPLAYMODE adapterMode
;
1479 if (_D3D
->GetAdapterDisplayMode (adapter
, &adapterMode
) != D3D_OK
)
1481 nlwarning ("GetAdapterDisplayMode failed");
1486 // The following code is taken from the NVPerfHud user guide
1487 // Set default settings
1488 _Rasterizer
= RASTERIZER
;
1489 #ifdef NL_D3D_USE_NV_PERF_HUD
1490 // Look for 'NVIDIA NVPerfHUD' adapter
1491 // If it is present, override default settings
1492 for (UINT adapterIndex
= 0; adapterIndex
< _D3D
->GetAdapterCount(); adapterIndex
++)
1494 D3DADAPTER_IDENTIFIER9 identifier
;
1495 HRESULT res
= _D3D
->GetAdapterIdentifier(adapterIndex
, 0, &identifier
);
1496 if (strstr(identifier
.Description
, "PerfHUD") != 0)
1498 adapter
= adapterIndex
;
1500 _Rasterizer
= D3DDEVTYPE_REF
;
1501 nlinfo("Using NVIDIA NVPerfHUD adapter");
1507 // Create device options
1508 D3DPRESENT_PARAMETERS parameters
;
1509 D3DFORMAT adapterFormat
;
1510 if (!fillPresentParameter (parameters
, adapterFormat
, _CurrentMode
, adapterMode
))
1517 // Look for 'NVIDIA PerfHUD' adapter
1518 // If it is present, override default settings
1519 for (UINT gAdapter
=0;gAdapter
<_D3D
->GetAdapterCount();gAdapter
++)
1521 D3DADAPTER_IDENTIFIER9 Identifier
;
1523 Res
= _D3D
->GetAdapterIdentifier(gAdapter
,0,&Identifier
);
1525 if (strstr(Identifier
.Description
,"PerfHUD") != 0)
1527 nlinfo ("Setting up with PerfHUD");
1529 _Rasterizer
=D3DDEVTYPE_REF
;
1533 #endif /* WITH_PERFHUD */
1534 // Create the D3D device
1535 HRESULT result
= _D3D
->CreateDevice (adapter
, _Rasterizer
, _HWnd
, D3DCREATE_HARDWARE_VERTEXPROCESSING
|D3DCREATE_PUREDEVICE
, ¶meters
, &_DeviceInterface
);
1536 if (result
!= D3D_OK
)
1538 nlwarning ("Can't create device hr:0x%x adap:0x%x rast:0x%x", result
, adapter
, _Rasterizer
);
1540 // Create the D3D device without puredevice
1541 HRESULT result
= _D3D
->CreateDevice (adapter
, _Rasterizer
, _HWnd
, D3DCREATE_HARDWARE_VERTEXPROCESSING
, ¶meters
, &_DeviceInterface
);
1542 if (result
!= D3D_OK
)
1544 nlwarning ("Can't create device without puredevice hr:0x%x adap:0x%x rast:0x%x", result
, adapter
, _Rasterizer
);
1546 // Create the D3D device without puredevice and hardware
1547 HRESULT result
= _D3D
->CreateDevice (adapter
, _Rasterizer
, _HWnd
, D3DCREATE_SOFTWARE_VERTEXPROCESSING
, ¶meters
, &_DeviceInterface
);
1548 if (result
!= D3D_OK
)
1550 nlwarning ("Can't create device without puredevice and hardware hr:0x%x adap:0x%x rast:0x%x", result
, adapter
, _Rasterizer
);
1559 if (_DeviceInterface
->GetDeviceCaps(&caps
) == D3D_OK
)
1561 _TextureCubeSupported
= (caps
.TextureCaps
& D3DPTEXTURECAPS_CUBEMAP
) != 0;
1562 _NbNeLTextureStages
= (caps
.MaxSimultaneousTextures
<IDRV_MAT_MAXTEXTURES
)?caps
.MaxSimultaneousTextures
:IDRV_MAT_MAXTEXTURES
;
1563 _MADOperatorSupported
= (caps
.TextureOpCaps
& D3DTEXOPCAPS_MULTIPLYADD
) != 0;
1564 _EMBMSupported
= (caps
.TextureOpCaps
& D3DTOP_BUMPENVMAP
) != 0;
1565 _PixelShaderVersion
= caps
.PixelShaderVersion
;
1566 _CubbedMipMapSupported
= (caps
.TextureCaps
& D3DPTEXTURECAPS_MIPCUBEMAP
) != 0;
1567 _MaxPrimitiveCount
= caps
.MaxPrimitiveCount
;
1568 _MaxVertexIndex
= caps
.MaxVertexIndex
;
1569 _IsGeforce
= !(caps
.DevCaps
& D3DDEVCAPS_NPATCHES
) && (caps
.PixelShaderVersion
>= D3DPS_VERSION(2, 0) || caps
.PixelShaderVersion
< D3DPS_VERSION(1, 4));
1570 _NonPowerOfTwoTexturesSupported
= !(caps
.TextureCaps
& D3DPTEXTURECAPS_POW2
) || (caps
.TextureCaps
& D3DPTEXTURECAPS_NONPOW2CONDITIONAL
);
1571 _MaxAnisotropy
= caps
.MaxAnisotropy
;
1572 _AnisotropicMinSupported
= (caps
.TextureFilterCaps
& D3DPTFILTERCAPS_MINFANISOTROPIC
) != 0;
1573 _AnisotropicMagSupported
= (caps
.TextureFilterCaps
& D3DPTFILTERCAPS_MAGFANISOTROPIC
) != 0;
1574 _AnisotropicMinCubeSupported
= (caps
.CubeTextureFilterCaps
& D3DPTFILTERCAPS_MINFANISOTROPIC
) != 0;
1575 _AnisotropicMagCubeSupported
= (caps
.CubeTextureFilterCaps
& D3DPTFILTERCAPS_MAGFANISOTROPIC
) != 0;
1579 _TextureCubeSupported
= false;
1580 _NbNeLTextureStages
= 1;
1581 _MADOperatorSupported
= false;
1582 _EMBMSupported
= false;
1583 _CubbedMipMapSupported
= false;
1584 _PixelShaderVersion
= 0;
1585 _MaxPrimitiveCount
= 0xffff;
1586 _MaxVertexIndex
= 0xffff;
1588 _NonPowerOfTwoTexturesSupported
= false;
1590 _AnisotropicMinSupported
= false;
1591 _AnisotropicMagSupported
= false;
1592 _AnisotropicMinCubeSupported
= false;
1593 _AnisotropicMagCubeSupported
= false;
1595 // If 16 bits vertices only, build a vb for quads rendering
1596 if (_MaxVertexIndex
<= 0xffff)
1598 if (!buildQuadIndexBuffer()) return false;
1601 // test for occlusion query support
1602 IDirect3DQuery9
*dummyQuery
= NULL
;
1603 if (_DeviceInterface
->CreateQuery(D3DQUERYTYPE_OCCLUSION
, &dummyQuery
) == D3DERR_NOTAVAILABLE
)
1605 _OcclusionQuerySupported
= false;
1609 _OcclusionQuerySupported
= true;
1610 if (dummyQuery
) dummyQuery
->Release();
1614 #ifdef NL_FORCE_TEXTURE_STAGE_COUNT
1615 _NbNeLTextureStages
= min ((uint
)NL_FORCE_TEXTURE_STAGE_COUNT
, (uint
)IDRV_MAT_MAXTEXTURES
);
1616 #endif // NL_FORCE_TEXTURE_STAGE_COUNT
1618 _VertexProgram
= !_DisableHardwareVertexProgram
&& ((caps
.VertexShaderVersion
&0xffff) >= 0x0100);
1619 _PixelProgramVersion
= _DisableHardwareVertexProgram
? 0x0000 : caps
.PixelShaderVersion
& 0xffff;
1620 nldebug("Pixel Program Version: %i.%i", (uint32
)((_PixelProgramVersion
& 0xFF00) >> 8), (uint32
)(_PixelProgramVersion
& 0xFF));
1621 _PixelProgram
= _PixelProgramVersion
>= 0x0101;
1622 _MaxVerticesByVertexBufferHard
= caps
.MaxVertexIndex
;
1623 _MaxLight
= caps
.MaxActiveLights
;
1625 if(_MaxLight
> 0xFF) _MaxLight
= 3;
1629 _MaxNumPerStageConstantLighted
= _NbNeLTextureStages
;
1630 _MaxNumPerStageConstantUnlighted
= _NbNeLTextureStages
;
1634 // emulation of per stage constant through diffuse
1635 _MaxNumPerStageConstantLighted
= 1;
1636 _MaxNumPerStageConstantUnlighted
= 2;
1639 if (_DisableHardwarePixelShader
&& _NbNeLTextureStages
> 3) // yes, 3 is not a bug
1641 // If pixel shader are disabled, then can't emulate the texEnvColor feature with more than 2 stages. (only 2 constant available by using material emissive in addition to the texture factor)
1642 // Radeon with 3 stages cases : let the third stage to ensure availability of the EMBM feature
1643 // There is a special fix in CMaterial::isSupportedByDriver to force the number of stages to 2 for the radeons
1644 _NbNeLTextureStages
= 2;
1647 // *** Check textures caps
1650 for (i
=0; i
<ITexture::UploadFormatCount
; i
++)
1652 // Default format : D3DFMT_A8R8G8B8
1653 _PreferedTextureFormat
[i
] = D3DFMT_A8R8G8B8
;
1655 for (j
=0; j
<CDriverD3D::FinalPixelFormatChoice
; j
++)
1657 if (isTextureFormatOk(adapter
, _Rasterizer
, FinalPixelFormat
[i
][j
], adapterFormat
))
1661 // Set the prefered pixel format
1662 if (j
<CDriverD3D::FinalPixelFormatChoice
)
1663 _PreferedTextureFormat
[i
] = FinalPixelFormat
[i
][j
];
1666 // Reset render state cache
1667 initRenderVariables();
1671 // Release old emitter
1672 while (_EventEmitter
.getNumEmitters() != 0)
1674 _EventEmitter
.removeEmitter(_EventEmitter
.getEmitter(_EventEmitter
.getNumEmitters() - 1));
1676 NLMISC::CWinEventEmitter
*we
= new NLMISC::CWinEventEmitter
;
1678 // Setup the event emitter, and try to retrieve a direct input interface
1679 _EventEmitter
.addEmitter(we
, true /*must delete*/); // the main emitter
1681 // Init some variables
1682 _ForceDXTCCompression
= false;
1683 _AnisotropicFilter
= 0;
1684 _ForceTextureResizePower
= 0;
1685 _FogEnabled
= false;
1687 // No back buffer backuped for the moment
1691 _AllocatedTextureMemory
= 0;
1692 _TextureUsed
.clear();
1693 _PrimitiveProfileIn
.reset();
1694 _PrimitiveProfileOut
.reset();
1695 _NbSetupMaterialCall
= 0;
1696 _NbSetupModelMatrixCall
= 0;
1697 _VBHardProfiling
= false;
1698 _CurVBHardLockCount
= 0;
1699 _NumVBHardProfileFrame
= 0;
1700 _IBProfiling
= false;
1702 _NumIBProfileFrame
= 0;
1704 // try to allocate 16Mo by default of AGP Ram.
1705 initVertexBufferHard(NL3D_DRV_VERTEXARRAY_AGP_INIT_SIZE
, 0);
1707 // If AGP is less than 16 mo, try to keep the max in proportion
1708 float maxAGPbufferSizeRatio
= (float) _AGPMemoryAllocated
/ (float) NL3D_DRV_VERTEXARRAY_AGP_INIT_SIZE
;
1710 // Init volatile vertex buffers
1711 _CurrentRenderPass
= 0;
1712 _VolatileVertexBufferRAM
[0]->init (CVertexBuffer::RAMResident
, NL_VOLATILE_RAM_VB_SIZE
, NL_VOLATILE_RAM_VB_MAXSIZE
, this);
1713 _VolatileVertexBufferRAM
[0]->reset ();
1714 _VolatileVertexBufferRAM
[1]->init (CVertexBuffer::RAMResident
, NL_VOLATILE_RAM_VB_SIZE
, NL_VOLATILE_RAM_VB_MAXSIZE
, this);
1715 _VolatileVertexBufferRAM
[1]->reset ();
1716 _VolatileVertexBufferAGP
[0]->init (CVertexBuffer::AGPResident
, NL_VOLATILE_AGP_VB_SIZE
, (uint
) (NL_VOLATILE_AGP_VB_MAXSIZE
* maxAGPbufferSizeRatio
), this);
1717 _VolatileVertexBufferAGP
[0]->reset ();
1718 _VolatileVertexBufferAGP
[1]->init (CVertexBuffer::AGPResident
, NL_VOLATILE_AGP_VB_SIZE
, (uint
) (NL_VOLATILE_AGP_VB_MAXSIZE
* maxAGPbufferSizeRatio
), this);
1719 _VolatileVertexBufferAGP
[1]->reset ();
1721 _VolatileIndexBuffer16RAM
[0]->init (CIndexBuffer::RAMResident
, NL_VOLATILE_RAM_IB_SIZE
, NL_VOLATILE_RAM_IB_MAXSIZE
, this, CIndexBuffer::Indices16
);
1722 _VolatileIndexBuffer16RAM
[0]->reset ();
1723 _VolatileIndexBuffer16RAM
[1]->init (CIndexBuffer::RAMResident
, NL_VOLATILE_RAM_IB_SIZE
, NL_VOLATILE_RAM_IB_MAXSIZE
, this, CIndexBuffer::Indices16
);
1724 _VolatileIndexBuffer16RAM
[1]->reset ();
1725 _VolatileIndexBuffer16AGP
[0]->init (CIndexBuffer::AGPResident
, NL_VOLATILE_AGP_IB_SIZE
, (uint
) (NL_VOLATILE_AGP_IB_MAXSIZE
* maxAGPbufferSizeRatio
), this, CIndexBuffer::Indices16
);
1726 _VolatileIndexBuffer16AGP
[0]->reset ();
1727 _VolatileIndexBuffer16AGP
[1]->init (CIndexBuffer::AGPResident
, NL_VOLATILE_AGP_IB_SIZE
, (uint
) (NL_VOLATILE_AGP_IB_MAXSIZE
* maxAGPbufferSizeRatio
), this, CIndexBuffer::Indices16
);
1728 _VolatileIndexBuffer16AGP
[1]->reset ();
1729 // 32 bits indices supported
1730 if (_MaxVertexIndex
> 0xffff)
1732 _VolatileIndexBuffer32RAM
[0]->init (CIndexBuffer::RAMResident
, NL_VOLATILE_RAM_IB_SIZE
, NL_VOLATILE_RAM_IB_MAXSIZE
, this, CIndexBuffer::Indices32
);
1733 _VolatileIndexBuffer32RAM
[0]->reset ();
1734 _VolatileIndexBuffer32RAM
[1]->init (CIndexBuffer::RAMResident
, NL_VOLATILE_RAM_IB_SIZE
, NL_VOLATILE_RAM_IB_MAXSIZE
, this, CIndexBuffer::Indices32
);
1735 _VolatileIndexBuffer32RAM
[1]->reset ();
1736 _VolatileIndexBuffer32AGP
[0]->init (CIndexBuffer::AGPResident
, NL_VOLATILE_AGP_IB_SIZE
, (uint
) (NL_VOLATILE_AGP_IB_MAXSIZE
* maxAGPbufferSizeRatio
), this, CIndexBuffer::Indices32
);
1737 _VolatileIndexBuffer32AGP
[0]->reset ();
1738 _VolatileIndexBuffer32AGP
[1]->init (CIndexBuffer::AGPResident
, NL_VOLATILE_AGP_IB_SIZE
, (uint
) (NL_VOLATILE_AGP_IB_MAXSIZE
* maxAGPbufferSizeRatio
), this, CIndexBuffer::Indices32
);
1739 _VolatileIndexBuffer32AGP
[1]->reset ();
1742 setupViewport (CViewport());
1747 //nldebug("BeginScene");
1748 if (!beginScene()) return false;
1754 // ***************************************************************************
1755 extern uint indexCount
;
1756 extern uint vertexCount
;
1758 bool CDriverD3D::release()
1760 H_AUTO_D3D(CDriver3D_release
);
1761 // Call IDriver::release() before, to destroy textures, shaders and VBs...
1764 ItShaderDrvInfoPtrList itshd
;
1765 while( (itshd
= _ShaderDrvInfos
.begin()) != _ShaderDrvInfos
.end() )
1767 // NB: at IShader deletion, this->_MatDrvInfos is updated (entry deleted);
1771 _SwapBufferCounter
= 0;
1780 while (!_OcclusionQueryList
.empty())
1782 deleteOcclusionQuery(_OcclusionQueryList
.front());
1787 _BackBuffer
->Release();
1790 // Release all the vertex declaration
1791 std::list
<CVertexDeclaration
>::iterator ite
= _VertexDeclarationList
.begin();
1792 while (ite
!= _VertexDeclarationList
.end())
1794 ite
->VertexDecl
->Release();
1797 _VertexDeclarationList
.clear ();
1799 // Release pixel shaders
1800 _NormalPixelShaders
[0].clear ();
1801 _NormalPixelShaders
[1].clear ();
1803 if( _DeviceInterface
!= NULL
)
1805 _DeviceInterface
->Release();
1806 _DeviceInterface
= NULL
;
1813 // make sure window icons are deleted
1814 std::vector
<NLMISC::CBitmap
> bitmaps
;
1815 setWindowIcon(bitmaps
);
1818 DestroyWindow (_HWnd
);
1823 nlassert (indexCount
== 0);
1824 nlassert (vertexCount
== 0);
1826 // restore desktop gamma ramp
1827 if (_DesktopGammaRampValid
)
1829 HDC dc
= CreateDCW (L
"DISPLAY", NULL
, NULL
, NULL
);
1832 SetDeviceGammaRamp (dc
, _DesktopGammaRamp
);
1834 _DesktopGammaRampValid
= false;
1839 // ***************************************************************************
1841 emptyProc
CDriverD3D::getWindowProc()
1843 return (emptyProc
)D3DWndProc
;
1846 // ***************************************************************************
1848 IDriver::TMessageBoxId
CDriverD3D::systemMessageBox (const char* message
, const char* title
, TMessageBoxType type
, TMessageBoxIcon icon
)
1850 switch (::MessageBoxW(_HWnd
, nlUtf8ToWide(message
), nlUtf8ToWide(title
), ((type
== retryCancelType
) ? MB_RETRYCANCEL
:
1851 (type
==yesNoCancelType
)?MB_YESNOCANCEL
:
1852 (type
==okCancelType
)?MB_OKCANCEL
:
1853 (type
==abortRetryIgnoreType
)?MB_ABORTRETRYIGNORE
:
1854 (type
==yesNoType
)?MB_YESNO
|MB_ICONQUESTION
:MB_OK
)|
1856 ((icon
==handIcon
)?MB_ICONHAND
:
1857 (icon
==questionIcon
)?MB_ICONQUESTION
:
1858 (icon
==exclamationIcon
)?MB_ICONEXCLAMATION
:
1859 (icon
==asteriskIcon
)?MB_ICONASTERISK
:
1860 (icon
==warningIcon
)?MB_ICONWARNING
:
1861 (icon
==errorIcon
)?MB_ICONERROR
:
1862 (icon
==informationIcon
)?MB_ICONINFORMATION
:
1863 (icon
==stopIcon
)?MB_ICONSTOP
:0)))
1883 // ***************************************************************************
1884 bool CDriverD3D::activate()
1889 // ***************************************************************************
1890 bool CDriverD3D::isActive ()
1892 return (IsWindow(_HWnd
) != 0);
1895 // ***************************************************************************
1896 nlWindow
CDriverD3D::getDisplay()
1901 // ***************************************************************************
1902 NLMISC::IEventEmitter
*CDriverD3D::getEventEmitter()
1904 return &_EventEmitter
;
1907 // ***************************************************************************
1908 void CDriverD3D::getWindowSize (uint32
&width
, uint32
&height
)
1910 H_AUTO_D3D(CDriverD3D_getWindowSize
);
1911 width
= _CurrentMode
.Width
;
1912 height
= _CurrentMode
.Height
;
1915 // ***************************************************************************
1917 void CDriverD3D::getWindowPos (sint32
&x
, sint32
&y
)
1919 H_AUTO_D3D(CDriverD3D_getWindowPos
);
1924 // ***************************************************************************
1925 uint32
CDriverD3D::getImplementationVersion () const
1927 H_AUTO_D3D(CDriverD3D_getImplementationVersion
);
1928 return ReleaseVersion
;
1931 // ***************************************************************************
1932 const char *CDriverD3D::getDriverInformation ()
1934 return "Directx 9 NeL Driver";
1937 // ***************************************************************************
1938 uint8
CDriverD3D::getBitPerPixel ()
1940 return _CurrentMode
.Depth
;
1943 // ***************************************************************************
1944 bool CDriverD3D::clear2D(CRGBA rgba
)
1946 H_AUTO_D3D(CDriverD3D_clear2D
);
1947 nlassert (_DeviceInterface
);
1950 CViewport oldViewport
= _Viewport
;
1951 setupViewport (CViewport());
1952 updateRenderVariables ();
1954 bool result
= _DeviceInterface
->Clear( 0, NULL
, D3DCLEAR_TARGET
, NL_D3DCOLOR_RGBA(rgba
), 1.0f
, 0 ) == D3D_OK
;
1956 // Restore the old viewport
1957 setupViewport (oldViewport
);
1961 // ***************************************************************************
1963 bool CDriverD3D::clearZBuffer(float zval
)
1965 H_AUTO_D3D(CDriverD3D_clearZBuffer
);
1966 nlassert (_DeviceInterface
);
1969 CViewport oldViewport
= _Viewport
;
1970 setupViewport (CViewport());
1971 updateRenderVariables ();
1973 bool result
= _DeviceInterface
->Clear( 0, NULL
, D3DCLEAR_ZBUFFER
, D3DCOLOR_ARGB(0,0,0,0), zval
, 0 ) == D3D_OK
;
1975 // Restore the old viewport
1976 setupViewport (oldViewport
);
1978 // NVidia driver 56.72 needs to reset the vertex buffer after a clear Z
1979 touchRenderVariable (&_VertexBufferCache
);
1984 // ***************************************************************************
1986 bool CDriverD3D::clearStencilBuffer(float stencilval
)
1988 H_AUTO_D3D(CDriverD3D_clearStencilBuffer
);
1989 nlassert (_DeviceInterface
);
1992 CViewport oldViewport
= _Viewport
;
1993 setupViewport (CViewport());
1994 updateRenderVariables ();
1996 bool result
= _DeviceInterface
->Clear( 0, NULL
, D3DCLEAR_STENCIL
, D3DCOLOR_ARGB(0,0,0,0), 1.0f
, (unsigned long)stencilval
) == D3D_OK
;
1998 // Restore the old viewport
1999 setupViewport (oldViewport
);
2004 // ***************************************************************************
2006 void CDriverD3D::setColorMask (bool bRed
, bool bGreen
, bool bBlue
, bool bAlpha
)
2008 H_AUTO_D3D(CDriverD3D_setColorMask
);
2009 setRenderState (D3DRS_COLORWRITEENABLE
,
2010 (bAlpha
?D3DCOLORWRITEENABLE_ALPHA
:0)|
2011 (bRed
?D3DCOLORWRITEENABLE_RED
:0)|
2012 (bGreen
?D3DCOLORWRITEENABLE_GREEN
:0)|
2013 (bBlue
?D3DCOLORWRITEENABLE_BLUE
:0)
2020 // ***************************************************************************
2021 bool CDriverD3D::swapBuffers()
2023 //DUMP_AUTO(swapBuffers);
2024 H_AUTO_D3D(CDriverD3D_swapBuffers
);
2025 nlassert (_DeviceInterface
);
2027 ++ _SwapBufferCounter
;
2028 // Swap & reset volatile buffers
2029 _CurrentRenderPass
++;
2030 _VolatileVertexBufferRAM
[_CurrentRenderPass
&1]->reset ();
2031 _VolatileVertexBufferAGP
[_CurrentRenderPass
&1]->reset ();
2032 _VolatileIndexBuffer16RAM
[_CurrentRenderPass
&1]->reset ();
2033 _VolatileIndexBuffer16AGP
[_CurrentRenderPass
&1]->reset ();
2034 _VolatileIndexBuffer32RAM
[_CurrentRenderPass
&1]->reset ();
2035 _VolatileIndexBuffer32AGP
[_CurrentRenderPass
&1]->reset ();
2037 // todo hulud volatile
2038 //_DeviceInterface->SetStreamSource(0, _VolatileVertexBufferRAM[1]->VertexBuffer, 0, 12);
2047 HRESULT result
= _DeviceInterface
->Present( NULL
, NULL
, NULL
, NULL
);
2048 if (result
!= D3D_OK
)
2051 if (result
== D3DERR_DEVICELOST
)
2054 // check if we can exit lost state
2055 if (_DeviceInterface
->TestCooperativeLevel() == D3DERR_DEVICENOTRESET
)
2058 reset (_CurrentMode
);
2063 // Check window size
2064 handlePossibleSizeChange ();
2066 // Reset the profiling counter.
2067 _PrimitiveProfileIn
.reset();
2068 _PrimitiveProfileOut
.reset();
2069 _NbSetupMaterialCall
= 0;
2070 _NbSetupModelMatrixCall
= 0;
2072 // Reset the texture set
2073 _TextureUsed
.clear();
2075 // Reset vertex program
2076 setVertexProgram (NULL
, NULL
);
2077 // Reset pixel program
2078 setPixelShader (NULL
);
2080 if (_VBHardProfiling
)
2082 ++_NumVBHardProfileFrame
;
2086 ++ _NumIBProfileFrame
;
2090 return beginScene();
2093 // ***************************************************************************
2095 void CDriverD3D::setPolygonMode (TPolygonMode mode
)
2097 H_AUTO_D3D(CDriverD3D_setPolygonMode
);
2098 IDriver::setPolygonMode (mode
);
2100 setRenderState (D3DRS_FILLMODE
, mode
==Point
?D3DFILL_POINT
:mode
==Line
?D3DFILL_WIREFRAME
:D3DFILL_SOLID
);
2103 // ***************************************************************************
2105 bool CDriverD3D::isTextureFormatOk(UINT adapter
, D3DDEVTYPE rasterizer
, D3DFORMAT TextureFormat
, D3DFORMAT AdapterFormat
)
2107 H_AUTO_D3D(CDriverD3D_isTextureFormatOk
);
2108 HRESULT hr
= _D3D
->CheckDeviceFormat( adapter
,
2115 return SUCCEEDED( hr
) != FALSE
;
2118 // ***************************************************************************
2120 void CDriverD3D::forceDXTCCompression(bool dxtcComp
)
2122 H_AUTO_D3D(CDriverD3D_forceDXTCCompression
);
2123 _ForceDXTCCompression
= dxtcComp
;
2126 // ***************************************************************************
2128 void CDriverD3D::setAnisotropicFilter(sint filter
)
2130 H_AUTO_D3D(CDriverD3D_setAnisotropicFilter
);
2132 // anisotropic filter not supported
2133 if (_MaxAnisotropy
< 2) return;
2135 if (filter
< 0 || filter
> _MaxAnisotropy
)
2137 _AnisotropicFilter
= _MaxAnisotropy
;
2141 _AnisotropicFilter
= filter
;
2145 // ***************************************************************************
2147 uint
CDriverD3D::getAnisotropicFilter() const
2149 H_AUTO_D3D(CDriverD3D_getAnisotropicFilter
);
2151 return _AnisotropicFilter
;
2154 // ***************************************************************************
2156 uint
CDriverD3D::getAnisotropicFilterMaximum() const
2158 H_AUTO_D3D(CDriverD3D_getAnisotropicFilterMaximum
);
2160 return _MaxAnisotropy
;
2163 // ***************************************************************************
2165 void CDriverD3D::forceTextureResize(uint divisor
)
2167 H_AUTO_D3D(CDriverD3D_forceTextureResize
);
2168 clamp(divisor
, 1U, 256U);
2171 _ForceTextureResizePower
= getPowerOf2(divisor
);
2174 // ***************************************************************************
2176 bool CDriverD3D::fogEnabled()
2178 H_AUTO_D3D(CDriverD3D_fogEnabled
);
2179 // Return _RenderStateCache[D3DRS_FOGENABLE].Value == TRUE;
2180 // Nico Patch : must return the _FogEnabled value here, because it MAY be
2181 // different of the one found in _RenderStateCache[D3DRS_FOGENABLE]
2182 // this happens for example when dest blend is one : the actual content of _RenderStateCache[D3DRS_FOGENABLE]
2183 // is then restored when current material alpha blending settings are modified, or when a new material is set.
2187 // ***************************************************************************
2189 void CDriverD3D::enableFog(bool enable
)
2191 H_AUTO_D3D(CDriverD3D_enableFog
);
2192 _FogEnabled
= enable
;
2193 setRenderState (D3DRS_FOGENABLE
, enable
?TRUE
:FALSE
);
2196 // ***************************************************************************
2198 void CDriverD3D::setupFog(float start
, float end
, CRGBA color
)
2200 H_AUTO_D3D(CDriverD3D_setupFog
);
2201 // Remember fog start and end
2204 _FogColor
= NL_D3DCOLOR_RGBA(color
);
2207 setRenderState (D3DRS_FOGCOLOR
, _FogColor
);
2208 setRenderState (D3DRS_FOGSTART
, *((DWORD
*) (&_FogStart
)));
2209 setRenderState (D3DRS_FOGEND
, *((DWORD
*) (&_FogEnd
)));
2212 // ***************************************************************************
2214 float CDriverD3D::getFogStart() const
2219 // ***************************************************************************
2221 float CDriverD3D::getFogEnd() const
2226 // ***************************************************************************
2228 CRGBA
CDriverD3D::getFogColor() const
2230 return D3DCOLOR_NL_RGBA(_RenderStateCache
[D3DRS_FOGCOLOR
].Value
);
2233 // ***************************************************************************
2235 CVertexBuffer::TVertexColorType
CDriverD3D::getVertexColorFormat() const
2237 return CVertexBuffer::TBGRA
;
2240 // ***************************************************************************
2242 uint
CDriverD3D::getNbTextureStages() const
2244 return _NbNeLTextureStages
;
2247 // ***************************************************************************
2249 bool CDriverD3D::getModes(std::vector
<GfxMode
> &modes
)
2251 H_AUTO_D3D(CDriverD3D_getModes
);
2252 static const D3DFORMAT format
[]=
2260 static const uint8 depth
[]=
2269 for (f
=0; f
<sizeof(format
)/sizeof(uint
); f
++)
2271 UINT adapter
= (_Adapter
==0xffffffff)?D3DADAPTER_DEFAULT
:(UINT
)_Adapter
;
2272 const uint count
= _D3D
->GetAdapterModeCount(adapter
, format
[f
]);
2274 for (i
=0; i
<count
; i
++)
2276 D3DDISPLAYMODE mode
;
2277 if (_D3D
->EnumAdapterModes( adapter
, format
[f
], i
, &mode
) == D3D_OK
)
2280 gfxMode
.Windowed
=false;
2281 gfxMode
.Width
=(uint16
)mode
.Width
;
2282 gfxMode
.Height
=(uint16
)mode
.Height
;
2283 gfxMode
.Depth
=depth
[f
];
2284 gfxMode
.Frequency
=(uint8
)mode
.RefreshRate
;
2285 modes
.push_back (gfxMode
);
2292 // ***************************************************************************
2293 bool CDriverD3D::getCurrentScreenMode(GfxMode
&gfxMode
)
2295 H_AUTO_D3D(CDriverD3D_getCurrentScreenMode
);
2296 UINT adapter
= (_Adapter
==0xffffffff)?D3DADAPTER_DEFAULT
:(UINT
)_Adapter
;
2297 D3DDISPLAYMODE mode
;
2298 _D3D
->GetAdapterDisplayMode(adapter
, &mode
);
2299 gfxMode
.Windowed
= !_FullScreen
;
2300 gfxMode
.Width
= (uint16
)mode
.Width
;
2301 gfxMode
.Height
= (uint16
)mode
.Height
;
2302 gfxMode
.Depth
= ((mode
.Format
==D3DFMT_A8R8G8B8
)||(mode
.Format
==D3DFMT_X8R8G8B8
))?32:16;
2303 gfxMode
.Frequency
= (uint8
)mode
.RefreshRate
;
2308 // ***************************************************************************
2309 void CDriverD3D::setWindowTitle(const ucstring
&title
)
2311 if (!SetWindowTextW(_HWnd
, (WCHAR
*)title
.c_str()))
2313 nlwarning("SetWindowText failed: %s", formatErrorMessage(getLastError()).c_str());
2317 // ***************************************************************************
2318 void CDriverD3D::setWindowIcon(const std::vector
<NLMISC::CBitmap
> &bitmaps
)
2323 static HICON winIconBig
= NULL
;
2324 static HICON winIconSmall
= NULL
;
2328 DestroyIcon(winIconBig
);
2334 DestroyIcon(winIconSmall
);
2335 winIconSmall
= NULL
;
2338 sint smallIndex
= -1;
2339 uint smallWidth
= GetSystemMetrics(SM_CXSMICON
);
2340 uint smallHeight
= GetSystemMetrics(SM_CYSMICON
);
2343 uint bigWidth
= GetSystemMetrics(SM_CXICON
);
2344 uint bigHeight
= GetSystemMetrics(SM_CYICON
);
2346 // find icons with the exact size
2347 for(uint i
= 0; i
< bitmaps
.size(); ++i
)
2349 if (smallIndex
== -1 && bitmaps
[i
].getWidth() == smallWidth
&& bitmaps
[i
].getHeight() == smallHeight
)
2352 if (bigIndex
== -1 && bitmaps
[i
].getWidth() == bigWidth
&& bitmaps
[i
].getHeight() == bigHeight
)
2356 // find icons with taller size (we will resize them)
2357 for(uint i
= 0; i
< bitmaps
.size(); ++i
)
2359 if (smallIndex
== -1 && bitmaps
[i
].getWidth() >= smallWidth
&& bitmaps
[i
].getHeight() >= smallHeight
)
2362 if (bigIndex
== -1 && bitmaps
[i
].getWidth() >= bigWidth
&& bitmaps
[i
].getHeight() >= bigHeight
)
2366 if (smallIndex
> -1)
2367 convertBitmapToIcon(bitmaps
[smallIndex
], winIconSmall
, smallWidth
, smallHeight
, 32);
2370 convertBitmapToIcon(bitmaps
[bigIndex
], winIconBig
, bigWidth
, bigHeight
, 32);
2374 SendMessageA(_HWnd
, WM_SETICON
, 0 /* ICON_SMALL */, (LPARAM
)winIconSmall
);
2375 SendMessageA(_HWnd
, WM_SETICON
, 1 /* ICON_BIG */, (LPARAM
)winIconBig
);
2379 SendMessageA(_HWnd
, WM_SETICON
, 0 /* ICON_SMALL */, (LPARAM
)winIconSmall
);
2380 SendMessageA(_HWnd
, WM_SETICON
, 1 /* ICON_BIG */, (LPARAM
)winIconSmall
);
2384 // ***************************************************************************
2385 void CDriverD3D::setWindowPos(sint32 x
, sint32 y
)
2389 SetWindowPos(_HWnd
, NULL
, _WindowX
, _WindowY
, 0, 0, SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOSIZE
);
2392 // ***************************************************************************
2393 void CDriverD3D::showWindow(bool show
)
2395 ShowWindow (_HWnd
, show
? SW_SHOW
:SW_HIDE
);
2398 // ***************************************************************************
2400 uint
CDriverD3D::getNumAdapter() const
2402 H_AUTO_D3D(CDriverD3D_getNumAdapter
);
2404 return _D3D
->GetAdapterCount();
2409 // ***************************************************************************
2411 bool CDriverD3D::getAdapter(uint adapter
, IDriver::CAdapter
&desc
) const
2413 H_AUTO_D3D(CDriverD3D_getAdapter
);
2416 D3DADAPTER_IDENTIFIER9 identifier
;
2417 UINT _adapter
= (adapter
==0xffffffff)?D3DADAPTER_DEFAULT
:(UINT
)adapter
;
2418 if (_D3D
->GetAdapterIdentifier(_adapter
, 0, &identifier
) == D3D_OK
)
2420 desc
.Description
= identifier
.Description
;
2421 desc
.DeviceId
= identifier
.DeviceId
;
2422 desc
.DeviceName
= identifier
.DeviceName
;
2423 desc
.Driver
= identifier
.Driver
;
2424 desc
.DriverVersion
= (((sint64
)identifier
.DriverVersion
.HighPart
<<32))|(sint64
)identifier
.DriverVersion
.LowPart
;
2425 desc
.Revision
= identifier
.Revision
;
2426 desc
.SubSysId
= identifier
.SubSysId
;
2427 desc
.VendorId
= identifier
.VendorId
;
2428 desc
.VideoMemory
= _Adapter
== _adapter
? getTotalVideoMemory():-1;
2435 // ***************************************************************************
2437 bool CDriverD3D::setAdapter(uint adapter
)
2439 H_AUTO_D3D(CDriverD3D_setAdapter
);
2442 D3DDISPLAYMODE adapterMode
;
2443 UINT _adapter
= (adapter
==0xffffffff)?D3DADAPTER_DEFAULT
:(UINT
)adapter
;
2444 if (_D3D
->GetAdapterDisplayMode (_adapter
, &adapterMode
) != D3D_OK
)
2446 nlwarning ("CDriverD3D::setDisplay: GetAdapterDisplayMode failed");
2456 // ***************************************************************************
2458 bool CDriverD3D::supportMADOperator() const
2460 H_AUTO_D3D(CDriverD3D_supportMADOperator
);
2461 if (_DeviceInterface
)
2463 return _MADOperatorSupported
;
2465 return false; // don't know..
2468 // ***************************************************************************
2470 bool CDriverD3D::setMode (const GfxMode
& mode
)
2472 H_AUTO_D3D(CDriverD3D_setMode
);
2477 // Must check if mode exist, else crash at reset() time
2478 std::vector
<GfxMode
> modes
;
2482 for(uint i
=0;i
<modes
.size();i
++)
2484 if( modes
[i
].Windowed
==mode
.Windowed
&&
2485 modes
[i
].Width
==mode
.Width
&&
2486 modes
[i
].Height
==mode
.Height
&&
2487 modes
[i
].Depth
==mode
.Depth
&&
2488 modes
[i
].Frequency
==mode
.Frequency
)
2506 // Set windowed-mode style
2507 SetWindowLongW( _HWnd
, GWL_STYLE
, D3D_WINDOWED_STYLE
|WS_VISIBLE
);
2508 _FullScreen
= false;
2512 // Set fullscreen-mode style
2513 SetWindowLongW( _HWnd
, GWL_STYLE
, D3D_FULLSCREEN_STYLE
|WS_VISIBLE
);
2517 SetWindowLongPtrW(_HWnd
, GWLP_WNDPROC
, GetWindowLongPtr(_HWnd
, GWLP_WNDPROC
));
2523 if( _CurrentMode
.Windowed
)
2527 WndRect
.left
=_WindowX
;
2528 WndRect
.top
=_WindowY
;
2529 WndRect
.right
=_WindowX
+_CurrentMode
.Width
;
2530 WndRect
.bottom
=_WindowY
+_CurrentMode
.Height
;
2531 AdjustWindowRect(&WndRect
, GetWindowLongW (_HWnd
, GWL_STYLE
), FALSE
);
2533 SetWindowPos( _HWnd
, HWND_NOTOPMOST
,
2534 std::max ((int)WndRect
.left
, 0), std::max ((int)WndRect
.top
, 0),
2535 ( WndRect
.right
- WndRect
.left
),
2536 ( WndRect
.bottom
- WndRect
.top
),
2537 SWP_NOMOVE
| SWP_SHOWWINDOW
);
2545 // ***************************************************************************
2546 void CDriverD3D::deleteIndexBuffer(CIBDrvInfosD3D
*indexBuffer
)
2548 if (!indexBuffer
) return;
2549 CIndexBuffer
*ib
= indexBuffer
->IndexBufferPtr
;
2550 // If resident in RAM, content has not been lost
2551 if (ib
->getLocation () != CIndexBuffer::RAMResident
)
2553 // Realloc local memory
2554 ib
->setLocation (CIndexBuffer::NotResident
);
2560 // ***************************************************************************
2561 bool CDriverD3D::reset (const GfxMode
& mode
)
2564 H_AUTO_D3D(CDriverD3D_reset
);
2565 if (_DeviceInterface
->TestCooperativeLevel() == D3DERR_DEVICELOST
) return false;
2567 // Choose an adapter
2568 UINT adapter
= (_Adapter
==0xffffffff)?D3DADAPTER_DEFAULT
:(UINT
)_Adapter
;
2570 // Get adapter format
2571 D3DDISPLAYMODE adapterMode
;
2572 if (_D3D
->GetAdapterDisplayMode (adapter
, &adapterMode
) != D3D_OK
)
2574 nlwarning ("CDriverD3D::reset: GetAdapterDisplayMode failed");
2580 // Increment the IDriver reset counter
2582 D3DPRESENT_PARAMETERS parameters
;
2583 D3DFORMAT adapterFormat
;
2584 if (!fillPresentParameter (parameters
, adapterFormat
, mode
, adapterMode
))
2588 _CurrentMode
= mode
;
2589 _CurrentMaterial
= NULL
;
2590 _CurrentMaterialInfo
= NULL
;
2592 // Restore non managed vertex buffer in system memory
2593 ItVBDrvInfoPtrList iteVb
= _VBDrvInfos
.begin();
2594 while (iteVb
!= _VBDrvInfos
.end())
2596 ItVBDrvInfoPtrList iteVbNext
= iteVb
;
2599 CVBDrvInfosD3D
*vertexBuffer
= static_cast<CVBDrvInfosD3D
*>(*iteVb
);
2600 CVertexBuffer
*vb
= vertexBuffer
->VertexBufferPtr
;
2602 // If resident in RAM, content has not been lost
2603 if (vb
->getLocation () != CVertexBuffer::RAMResident
)
2605 // Realloc local memory
2606 vb
->setLocation (CVertexBuffer::NotResident
); // If resident in RAM, content backuped by setLocation
2607 delete vertexBuffer
;
2613 // Restore non managed index buffer in system memory
2614 ItIBDrvInfoPtrList iteIb
= _IBDrvInfos
.begin();
2615 while (iteIb
!= _IBDrvInfos
.end())
2617 ItIBDrvInfoPtrList iteIbNext
= iteIb
;
2619 deleteIndexBuffer(static_cast<CIBDrvInfosD3D
*>(*iteIb
));
2622 deleteIndexBuffer(static_cast<CIBDrvInfosD3D
*>((IIBDrvInfos
*) _QuadIndexesAGP
.DrvInfos
));
2624 // Remove render targets
2625 ItTexDrvSharePtrList ite
= _TexDrvShares
.begin();
2626 while (ite
!= _TexDrvShares
.end())
2628 ItTexDrvSharePtrList iteNext
= ite
;
2632 nlassert ((*ite
)->DrvTexture
!= NULL
);
2633 CTextureDrvInfosD3D
*info
= static_cast<CTextureDrvInfosD3D
*>(static_cast<ITextureDrvInfos
*>((*ite
)->DrvTexture
));
2634 if (info
->RenderTarget
)
2642 // Free volatile buffers
2643 _VolatileVertexBufferRAM
[0]->release ();
2644 _VolatileVertexBufferRAM
[1]->release ();
2645 _VolatileVertexBufferAGP
[0]->release ();
2646 _VolatileVertexBufferAGP
[1]->release ();
2647 _VolatileIndexBuffer16RAM
[0]->release ();
2648 _VolatileIndexBuffer16RAM
[1]->release ();
2649 _VolatileIndexBuffer16AGP
[0]->release ();
2650 _VolatileIndexBuffer16AGP
[1]->release ();
2651 _VolatileIndexBuffer32RAM
[0]->release ();
2652 _VolatileIndexBuffer32RAM
[1]->release ();
2653 _VolatileIndexBuffer32AGP
[0]->release ();
2654 _VolatileIndexBuffer32AGP
[1]->release ();
2658 _BackBuffer
->Release();
2661 // Invalidate all occlusion queries.
2662 // TODO nico : for now, even if a result has been retrieved successfully by the query, the query is put in the lost state. See if its worth improving...
2663 for(TOcclusionQueryList::iterator it
= _OcclusionQueryList
.begin(); it
!= _OcclusionQueryList
.end(); ++it
)
2667 (*it
)->WasLost
= true;
2668 (*it
)->Query
->Release();
2669 (*it
)->Query
= NULL
;
2673 // Release internal shaders
2674 //releaseInternalShaders();
2677 notifyAllShaderDrvOfLostDevice();
2681 /* Do not reset if reset will fail */
2683 bool sceneBegun
= hasSceneBegun();
2686 //nldebug("EndScene");
2690 // delete all .fx caches
2691 for(TMatDrvInfoPtrList::iterator it
= _MatDrvInfos
.begin(); it
!= _MatDrvInfos
.end(); ++it
)
2693 CMaterialDrvInfosD3D
*mi
= NLMISC::safe_cast
<CMaterialDrvInfosD3D
*>(*it
);
2696 mi
->FXCache
->reset();
2702 CFpuRestorer fpuRestorer
; // fpu control word is changed by "Reset"
2704 if (_Rasterizer
!=D3DDEVTYPE_REF
)
2706 HRESULT hr
= _DeviceInterface
->Reset (¶meters
);
2709 nlwarning("CDriverD3D::reset: Reset on _DeviceInterface error 0x%x", hr
);
2711 nlstopex(("CDriverD3D::reset: Reset on _DeviceInterface"));
2721 //nldebug("BeginScene");
2725 notifyAllShaderDrvOfResetDevice();
2727 // Reset internal caches
2728 resetRenderVariables();
2731 //initInternalShaders();
2733 // reallocate occlusion queries
2734 for(TOcclusionQueryList::iterator it
= _OcclusionQueryList
.begin(); it
!= _OcclusionQueryList
.end(); ++it
)
2738 _DeviceInterface
->CreateQuery(D3DQUERYTYPE_OCCLUSION
, &(*it
)->Query
);
2744 // ***************************************************************************
2746 bool CDriverD3D::fillPresentParameter (D3DPRESENT_PARAMETERS
¶meters
, D3DFORMAT
&adapterFormat
, const GfxMode
& mode
, const D3DDISPLAYMODE
&adapterMode
)
2748 UINT adapter
= (_Adapter
==0xffffffff)?D3DADAPTER_DEFAULT
:(UINT
)_Adapter
;
2749 H_AUTO_D3D(CDriverD3D_fillPresentParameter
);
2750 memset (¶meters
, 0, sizeof(D3DPRESENT_PARAMETERS
));
2751 parameters
.BackBufferWidth
= mode
.Width
;
2752 parameters
.BackBufferHeight
= mode
.Height
;
2753 parameters
.BackBufferCount
= 1;
2754 parameters
.MultiSampleType
= D3DMULTISAMPLE_NONE
;
2755 parameters
.MultiSampleQuality
= 0;
2756 parameters
.SwapEffect
= D3DSWAPEFFECT_DISCARD
;
2757 parameters
.hDeviceWindow
= NULL
;
2758 parameters
.Windowed
= mode
.Windowed
;
2759 parameters
.EnableAutoDepthStencil
= TRUE
;
2760 parameters
.FullScreen_RefreshRateInHz
= mode
.Windowed
?0:mode
.Frequency
;
2764 parameters
.PresentationInterval
= D3DPRESENT_INTERVAL_IMMEDIATE
;
2767 parameters
.PresentationInterval
= D3DPRESENT_INTERVAL_ONE
;
2770 parameters
.PresentationInterval
= D3DPRESENT_INTERVAL_TWO
;
2773 parameters
.PresentationInterval
= D3DPRESENT_INTERVAL_THREE
;
2776 parameters
.PresentationInterval
= D3DPRESENT_INTERVAL_FOUR
;
2780 // Build a depth index
2781 const uint depthIndex
= (mode
.Depth
==16)?0:(mode
.Depth
==24)?1:2;
2783 // Choose a back buffer format
2784 const uint numFormat
= 4;
2785 D3DFORMAT backBufferFormats
[3][numFormat
]=
2787 {D3DFMT_R5G6B5
, D3DFMT_A1R5G5B5
, D3DFMT_X1R5G5B5
, D3DFMT_A4R4G4B4
},
2788 {D3DFMT_R8G8B8
, D3DFMT_A8R8G8B8
, D3DFMT_X8R8G8B8
, D3DFMT_X8R8G8B8
},
2789 {D3DFMT_A8R8G8B8
, D3DFMT_X8R8G8B8
, D3DFMT_X8R8G8B8
, D3DFMT_X8R8G8B8
},
2795 for (backBuffer
=0; backBuffer
<numFormat
; backBuffer
++)
2797 if (_D3D
->CheckDeviceType(adapter
, _Rasterizer
, adapterMode
.Format
, backBufferFormats
[depthIndex
][backBuffer
], TRUE
) == D3D_OK
)
2799 parameters
.BackBufferFormat
= backBufferFormats
[depthIndex
][backBuffer
];
2800 adapterFormat
= adapterMode
.Format
;
2808 // Found a pair display and back buffer format
2810 for (backBuffer
=0; backBuffer
<numFormat
; backBuffer
++)
2813 for (display
=0; display
<numFormat
; display
++)
2815 if (_D3D
->CheckDeviceType(adapter
, _Rasterizer
, backBufferFormats
[depthIndex
][display
], backBufferFormats
[depthIndex
][display
], FALSE
) == D3D_OK
)
2817 parameters
.BackBufferFormat
= backBufferFormats
[depthIndex
][backBuffer
];
2818 adapterFormat
= backBufferFormats
[depthIndex
][display
];
2831 nlwarning ("Can't create backbuffer");
2835 // Choose a zbuffer format
2836 D3DFORMAT zbufferFormats
[]=
2838 //uncomment to save zbuffer D3DFMT_D32F_LOCKABLE,
2839 //uncomment to save zbuffer D3DFMT_D16_LOCKABLE,
2848 const uint zbufferFormatCount
= sizeof(zbufferFormats
)/sizeof(D3DFORMAT
);
2850 for (i
=0; i
<zbufferFormatCount
; i
++)
2852 if (isDepthFormatOk (adapter
, _Rasterizer
, zbufferFormats
[i
], adapterFormat
, parameters
.BackBufferFormat
))
2856 if (i
>=zbufferFormatCount
)
2858 nlwarning ("Can't create zbuffer");
2862 // Set the zbuffer format
2863 parameters
.AutoDepthStencilFormat
= zbufferFormats
[i
];
2865 if(mode
.AntiAlias
== -1)
2867 parameters
.Flags
|= D3DPRESENTFLAG_LOCKABLE_BACKBUFFER
;
2872 if(mode
.AntiAlias
== 0)
2874 if(SUCCEEDED(_D3D
->CheckDeviceMultiSampleType(adapter
, _Rasterizer
, adapterFormat
, mode
.Windowed
, D3DMULTISAMPLE_NONMASKABLE
, &aa
)))
2876 parameters
.MultiSampleType
= D3DMULTISAMPLE_NONMASKABLE
;
2877 parameters
.MultiSampleQuality
= aa
- 1;
2878 nlinfo("Use AntiAlias with %d sample", aa
);
2882 nlwarning("No AntiAlias support found");
2887 parameters
.MultiSampleType
= D3DMULTISAMPLE_NONMASKABLE
;
2888 parameters
.MultiSampleQuality
= mode
.AntiAlias
- 1;
2889 nlinfo("Use AntiAlias with %d sample", mode
.AntiAlias
);
2896 // ***************************************************************************
2898 const char *CDriverD3D::getVideocardInformation ()
2900 H_AUTO_D3D(CDriverD3D_getVideocardInformation
);
2901 static char name
[1024];
2903 // if (!_DeviceInterface)
2904 // return "Direct3d isn't initialized";
2906 D3DADAPTER_IDENTIFIER9 identifier
;
2907 UINT adapter
= (_Adapter
==0xffffffff)?D3DADAPTER_DEFAULT
:(UINT
)_Adapter
;
2908 if (_D3D
->GetAdapterIdentifier(adapter
, 0, &identifier
) == D3D_OK
)
2910 uint64 version
= ((uint64
)identifier
.DriverVersion
.HighPart
) << 32;
2911 version
|= identifier
.DriverVersion
.LowPart
;
2912 smprintf (name
, 1024, "Direct3d / %s / %s / %s / driver version : %d.%d.%d.%d", identifier
.Driver
, identifier
.Description
, identifier
.DeviceName
,
2913 (uint16
)((version
>>48)&0xFFFF),(uint16
)((version
>>32)&0xFFFF),(uint16
)((version
>>16)&0xFFFF),(uint16
)(version
&0xffff));
2917 return "Can't get video card information";
2920 // ***************************************************************************
2922 sint
CDriverD3D::getTotalVideoMemory () const
2924 H_AUTO_D3D(CDriverD3D_getTotalVideoMemory
);
2926 // Can't use _DeviceInterface->GetAvailableTextureMem() because it's not reliable
2927 // Returns 4 GiB instead of 2 with my GPU
2931 // ***************************************************************************
2933 void CDriverD3D::getBuffer (CBitmap
&bitmap
)
2935 H_AUTO_D3D(CDriverD3D_getBuffer
);
2937 rect
.setWH (0, 0, _CurrentMode
.Width
, _CurrentMode
.Height
);
2938 getBufferPart (bitmap
, rect
);
2941 // ***************************************************************************
2943 void CDriverD3D::getBufferPart (CBitmap
&bitmap
, NLMISC::CRect
&rect
)
2945 H_AUTO_D3D(CDriverD3D_getBufferPart
);
2946 if (_DeviceInterface
)
2948 // Resize the bitmap
2949 const uint lineCount
= rect
.Height
;
2950 const uint width
= rect
.Width
;
2951 bitmap
.resize (width
, lineCount
, CBitmap::RGBA
);
2953 // Lock the back buffer
2954 IDirect3DSurface9
*surface
;
2955 if (_DeviceInterface
->GetBackBuffer (0, 0, D3DBACKBUFFER_TYPE_MONO
, &surface
) == D3D_OK
)
2958 D3DSURFACE_DESC desc
;
2959 if (surface
->GetDesc(&desc
) == D3D_OK
)
2961 // 32 bits format supported
2962 if ((desc
.Format
== D3DFMT_R8G8B8
) ||
2963 (desc
.Format
== D3DFMT_A8R8G8B8
) ||
2964 (desc
.Format
== D3DFMT_X8R8G8B8
) ||
2965 (desc
.Format
== D3DFMT_A8B8G8R8
) ||
2966 (desc
.Format
== D3DFMT_X8B8G8R8
))
2969 bool invertRGBA
= (desc
.Format
== D3DFMT_R8G8B8
) || (desc
.Format
== D3DFMT_A8R8G8B8
) || (desc
.Format
== D3DFMT_X8R8G8B8
);
2972 D3DLOCKED_RECT lock
;
2974 winRect
.left
= rect
.left();
2975 winRect
.right
= rect
.right();
2976 winRect
.top
= rect
.top();
2977 winRect
.bottom
= rect
.bottom();
2978 if (surface
->LockRect (&lock
, &winRect
, D3DLOCK_READONLY
) == D3D_OK
)
2981 uint8
*dest
= &(bitmap
.getPixels ()[0]);
2983 for (i
=0; i
<lineCount
; i
++)
2986 copyRGBA2BGRA ((uint32
*)dest
+(i
*width
), (uint32
*)((uint8
*)lock
.pBits
+(i
*lock
.Pitch
)), width
);
2988 memcpy (dest
+(4*i
*width
), ((uint8
*)lock
.pBits
)+(i
*lock
.Pitch
), width
*4);
2991 surface
->UnlockRect ();
3001 // ***************************************************************************
3003 IDirect3DSurface9
* CDriverD3D::getSurfaceTexture(ITexture
* text
)
3009 updateRenderVariables ();
3010 _DeviceInterface
->GetRenderTarget (0, &_BackBuffer
);
3012 nlassert(_BackBuffer
);
3016 if(text
->TextureDrvShare
==NULL
|| text
->TextureDrvShare
->DrvTexture
.getPtr()==NULL
)
3018 text
->setRenderTarget(true);
3019 setupTexture(*text
);
3021 CTextureDrvInfosD3D
* rdvInfosD3D
= (NLMISC::safe_cast
<CTextureDrvInfosD3D
*>(text
->TextureDrvShare
->DrvTexture
.getPtr()));
3023 IDirect3DTexture9
* texture
= rdvInfosD3D
->Texture2d
;
3026 IDirect3DSurface9
* surface
;
3027 HRESULT hr
= texture
->GetSurfaceLevel(0, &surface
);
3028 nlassert(hr
==D3D_OK
);
3033 void CDriverD3D::getDirect3DRect(NLMISC::CRect
&rect
, RECT
& d3dRect
)
3035 d3dRect
.left
= rect
.left();
3036 d3dRect
.top
= rect
.top();
3037 d3dRect
.right
= rect
.right();
3038 d3dRect
.bottom
= rect
.bottom();
3041 getWindowSize(w
, h
);
3043 if(d3dRect
.top
>(sint32
)h
)
3046 if(d3dRect
.right
>(sint32
)w
)
3049 if(d3dRect
.bottom
<0)
3056 bool CDriverD3D::stretchRect(ITexture
* srcText
, NLMISC::CRect
&srcRect
, ITexture
* destText
, NLMISC::CRect
&destRect
)
3058 H_AUTO_D3D(CDriverD3D_stretchRect
);
3059 if (_DeviceInterface
)
3061 IDirect3DSurface9
* srcSurface
= getSurfaceTexture(srcText
);
3062 IDirect3DSurface9
* destSurface
= getSurfaceTexture(destText
);
3064 D3DTEXTUREFILTERTYPE filterType
= D3DTEXF_LINEAR
;
3068 getDirect3DRect(srcRect
, srcD3DRect
);
3069 getDirect3DRect(destRect
, destD3DRect
);
3071 HRESULT hr
= _DeviceInterface
->StretchRect(srcSurface
, &srcD3DRect
, destSurface
, &destD3DRect
, filterType
);
3073 srcSurface
->Release();
3074 destSurface
->Release();
3076 return (hr
==D3D_OK
);
3082 // ***************************************************************************
3084 bool CDriverD3D::supportBloomEffect() const
3086 return supportVertexProgram(CVertexProgram::nelvp
);
3089 // ***************************************************************************
3091 bool CDriverD3D::supportNonPowerOfTwoTextures() const
3093 return _NonPowerOfTwoTexturesSupported
;
3096 // ***************************************************************************
3098 bool CDriverD3D::fillBuffer (NLMISC::CBitmap
&bitmap
)
3100 H_AUTO_D3D(CDriverD3D_fillBuffer
);
3101 bool result
= false;
3102 if (_DeviceInterface
)
3104 // Resize the bitmap
3105 const uint lineCount
= _CurrentMode
.Height
;
3106 const uint width
= _CurrentMode
.Width
;
3107 if ((bitmap
.getWidth() == width
) && (bitmap
.getHeight() == lineCount
))
3109 // Lock the back buffer
3110 IDirect3DSurface9
*surface
;
3111 if (_DeviceInterface
->GetBackBuffer (0, 0, D3DBACKBUFFER_TYPE_MONO
, &surface
) == D3D_OK
)
3114 D3DSURFACE_DESC desc
;
3115 if (surface
->GetDesc(&desc
) == D3D_OK
)
3117 // 32 bits format supported
3118 if ((desc
.Format
== D3DFMT_R8G8B8
) ||
3119 (desc
.Format
== D3DFMT_A8R8G8B8
) ||
3120 (desc
.Format
== D3DFMT_X8R8G8B8
) ||
3121 (desc
.Format
== D3DFMT_A8B8G8R8
) ||
3122 (desc
.Format
== D3DFMT_X8B8G8R8
))
3125 bool invertRGBA
= (desc
.Format
== D3DFMT_R8G8B8
) || (desc
.Format
== D3DFMT_A8R8G8B8
) || (desc
.Format
== D3DFMT_X8R8G8B8
);
3128 D3DLOCKED_RECT lock
;
3131 winRect
.right
= width
;
3133 winRect
.bottom
= lineCount
;
3134 if (surface
->LockRect (&lock
, &winRect
, 0) == D3D_OK
)
3137 uint8
*dest
= &(bitmap
.getPixels ()[0]);
3139 for (i
=0; i
<lineCount
; i
++)
3142 copyRGBA2BGRA ((uint32
*)((uint8
*)lock
.pBits
+(i
*lock
.Pitch
)), (uint32
*)dest
+(i
*width
), width
);
3144 memcpy (((uint8
*)lock
.pBits
)+(i
*lock
.Pitch
), dest
+(4*i
*width
), width
*4);
3147 surface
->UnlockRect ();
3160 // ***************************************************************************
3162 void CDriverD3D::setSwapVBLInterval(uint interval
)
3164 H_AUTO_D3D(CDriverD3D_setSwapVBLInterval
);
3165 if (_Interval
!= interval
)
3167 _Interval
= interval
;
3169 // Must do a reset because the vsync parameter is choosed in the D3DPRESENT structure
3170 if (_DeviceInterface
)
3171 reset (_CurrentMode
);
3175 // ***************************************************************************
3177 uint
CDriverD3D::getSwapVBLInterval()
3179 H_AUTO_D3D(CDriverD3D_getSwapVBLInterval
);
3183 // ***************************************************************************
3184 void CDriverD3D::finish()
3186 // TODO : actually do not wait until everythin is rendered
3187 H_AUTO_D3D(CDriverD3D_finish
);
3189 //nldebug("EndScene");
3191 //nldebug("BeginScene");
3195 // ***************************************************************************
3196 void CDriverD3D::flush()
3198 H_AUTO_D3D(CDriverD3D_finish
);
3200 //nldebug("EndScene");
3202 //nldebug("BeginScene");
3206 // ***************************************************************************
3208 bool CDriverD3D::setMonitorColorProperties (const CMonitorColorProperties
&properties
)
3211 H_AUTO_D3D(CDriverD3D_setMonitorColorProperties);
3215 // For each composant
3217 for( c=0; c<3; c++ )
3219 WORD *table = (c==0)?ramp.red:(c==1)?ramp.green:ramp.blue;
3221 for( i=0; i<256; i++ )
3224 float value = (float)i / 256;
3227 value = (float) max (0.0f, (value-0.5f) * (float) pow (3.f, properties.Contrast[c]) + 0.5f );
3230 value = (float) pow (value, (properties.Gamma[c]>0) ? 1 - 3 * properties.Gamma[c] / 4 : 1 - properties.Gamma[c] );
3233 value = value + properties.Luminosity[c] / 2.f;
3234 table[i] = min (65535, max (0, (int)(value * 65535)));
3239 _DeviceInterface->SetGammaRamp (0, D3DSGR_NO_CALIBRATION, &ramp);
3244 // It would be better to apply the gamma ramp only to the window and not to the whole desktop when playing in windowed mode.
3245 // This require to switch to D3D 9.0c which has a flag for that purpose in the 'Present' function.
3246 // Currently the SetGammaRamp only works in fullscreen mode, so we rely to the classic 'SetDeviceGammaRamp' instead.
3247 HDC dc
= CreateDCW (L
"DISPLAY", NULL
, NULL
, NULL
);
3253 // For each composant
3255 for( c
=0; c
<3; c
++ )
3258 for( i
=0; i
<256; i
++ )
3261 float value
= (float)i
/ 256;
3264 value
= (float) max (0.0f
, (value
-0.5f
) * (float) pow (3.f
, properties
.Contrast
[c
]) + 0.5f
);
3267 value
= (float) pow (value
, (properties
.Gamma
[c
]>0) ? 1 - 3 * properties
.Gamma
[c
] / 4 : 1 - properties
.Gamma
[c
] );
3270 value
= value
+ properties
.Luminosity
[c
] / 2.f
;
3271 ramp
[i
+(c
<<8)] = (WORD
)min (65535, max (0, (int)(value
* 65535)));
3276 bool result
= SetDeviceGammaRamp (dc
, ramp
) != FALSE
;
3279 ReleaseDC (NULL
, dc
);
3286 nlwarning ("(CDriverD3D::setMonitorColorProperties): can't create DC");
3291 // ***************************************************************************
3293 // ****************************************************************************
3294 bool CDriverD3D::supportEMBM() const
3296 H_AUTO_D3D(CDriverD3D_supportEMBM
);
3297 return _EMBMSupported
;
3300 // ****************************************************************************
3301 bool CDriverD3D::isEMBMSupportedAtStage(uint stage
) const
3303 H_AUTO_D3D(CDriverD3D_isEMBMSupportedAtStage
);
3304 // we assume EMBM is supported at all stages except the last one
3305 return stage
< _NbNeLTextureStages
- 1;
3308 // ****************************************************************************
3309 void CDriverD3D::setEMBMMatrix(const uint stage
, const float mat
[4])
3311 H_AUTO_D3D(CDriverD3D_setEMBMMatrix
);
3312 nlassert(stage
< _NbNeLTextureStages
- 1);
3313 SetTextureStageState(stage
, D3DTSS_BUMPENVMAT00
, (DWORD
&) mat
[0]);
3314 SetTextureStageState(stage
, D3DTSS_BUMPENVMAT01
, (DWORD
&) mat
[1]);
3315 SetTextureStageState(stage
, D3DTSS_BUMPENVMAT10
, (DWORD
&) mat
[2]);
3316 SetTextureStageState(stage
, D3DTSS_BUMPENVMAT11
, (DWORD
&) mat
[3]);
3319 // ***************************************************************************
3320 bool CDriverD3D::supportOcclusionQuery() const
3322 H_AUTO_D3D(CDriverD3D_supportOcclusionQuery
);
3323 return _OcclusionQuerySupported
;
3326 // ***************************************************************************
3327 IOcclusionQuery
*CDriverD3D::createOcclusionQuery()
3329 H_AUTO_D3D(CDriverD3D_createOcclusionQuery
);
3330 nlassert(_OcclusionQuerySupported
);
3331 nlassert(_DeviceInterface
);
3332 IDirect3DQuery9
*query
;
3333 if (_DeviceInterface
->CreateQuery(D3DQUERYTYPE_OCCLUSION
, &query
) != D3D_OK
) return NULL
;
3334 COcclusionQueryD3D
*oqd3d
= new COcclusionQueryD3D
;
3335 oqd3d
->Driver
= this;
3336 oqd3d
->Query
= query
;
3337 oqd3d
->VisibleCount
= 0;
3338 oqd3d
->OcclusionType
= IOcclusionQuery::NotAvailable
;
3339 oqd3d
->QueryIssued
= false;
3340 oqd3d
->WasLost
= false;
3341 _OcclusionQueryList
.push_front(oqd3d
);
3342 oqd3d
->Iterator
= _OcclusionQueryList
.begin();
3346 // ***************************************************************************
3347 void CDriverD3D::deleteOcclusionQuery(IOcclusionQuery
*oq
)
3349 H_AUTO_D3D(CDriverD3D_deleteOcclusionQuery
);
3351 COcclusionQueryD3D
*oqd3d
= NLMISC::safe_cast
<COcclusionQueryD3D
*>(oq
);
3352 nlassert((CDriverD3D
*) oqd3d
->Driver
== this); // should come from the same driver
3353 oqd3d
->Driver
= NULL
;
3356 oqd3d
->Query
->Release();
3357 oqd3d
->Query
= NULL
;
3359 _OcclusionQueryList
.erase(oqd3d
->Iterator
);
3360 if (oqd3d
== _CurrentOcclusionQuery
)
3362 _CurrentOcclusionQuery
= NULL
;
3367 // ***************************************************************************
3368 void COcclusionQueryD3D::begin()
3370 H_AUTO_D3D(COcclusionQueryD3D_begin
);
3371 if (!Query
) return; // Lost device
3373 nlassert(Driver
->_CurrentOcclusionQuery
== NULL
); // only one query at a time
3374 Query
->Issue(D3DISSUE_BEGIN
);
3375 Driver
->_CurrentOcclusionQuery
= this;
3376 OcclusionType
= NotAvailable
;
3377 QueryIssued
= false;
3381 // ***************************************************************************
3382 void COcclusionQueryD3D::end()
3384 H_AUTO_D3D(COcclusionQueryD3D_end
);
3385 if (!Query
) return; // Lost device
3387 nlassert(Driver
->_CurrentOcclusionQuery
== this); // only one query at a time
3390 Query
->Issue(D3DISSUE_END
);
3392 Driver
->_CurrentOcclusionQuery
= NULL
;
3396 // ***************************************************************************
3397 IOcclusionQuery::TOcclusionType
COcclusionQueryD3D::getOcclusionType()
3399 if (!Query
|| WasLost
) return QueryIssued
? Occluded
: NotAvailable
;
3400 H_AUTO_D3D(COcclusionQueryD3D_getOcclusionType
);
3403 nlassert(Driver
->_CurrentOcclusionQuery
!= this); // can't query result between a begin/end pair!
3404 if (OcclusionType
== NotAvailable
)
3407 if (Query
->GetData(&numPix
, sizeof(DWORD
), 0) == S_OK
)
3409 OcclusionType
= numPix
!= 0 ? NotOccluded
: Occluded
;
3410 VisibleCount
= (uint
) numPix
;
3413 return OcclusionType
;
3416 // ***************************************************************************
3417 uint
COcclusionQueryD3D::getVisibleCount()
3419 if (!Query
|| WasLost
) return 0;
3420 H_AUTO_D3D(COcclusionQueryD3D_getVisibleCount
);
3423 nlassert(Driver
->_CurrentOcclusionQuery
!= this); // can't query result between a begin/end pair!
3424 if (getOcclusionType() == NotAvailable
) return 0;
3425 return VisibleCount
;
3428 // ***************************************************************************
3429 bool CDriverD3D::supportWaterShader() const
3431 H_AUTO_D3D(CDriverD3D_supportWaterShader
);
3432 return _PixelShaderVersion
>= D3DPS_VERSION(1, 1);
3435 // ***************************************************************************
3436 void CDriverD3D::setCullMode(TCullMode cullMode
)
3438 H_AUTO_D3D(CDriver3D_cullMode
);
3439 #ifdef NL_D3D_USE_RENDER_STATE_CACHE
3440 NL_D3D_CACHE_TEST(CacheTest_CullMode
, cullMode
!= _CullMode
)
3443 if (_InvertCullMode
)
3445 setRenderState(D3DRS_CULLMODE
, _CullMode
== CCW
? D3DCULL_CW
: D3DCULL_CCW
);
3449 setRenderState(D3DRS_CULLMODE
, _CullMode
== CCW
? D3DCULL_CCW
: D3DCULL_CW
);
3451 _CullMode
= cullMode
;
3455 // ***************************************************************************
3456 IDriver::TCullMode
CDriverD3D::getCullMode() const
3458 H_AUTO_D3D(CDriver3D_CDriverD3D
);
3462 // ***************************************************************************
3463 void CDriverD3D::enableStencilTest(bool enable
)
3465 H_AUTO_D3D(CDriver3D_CDriverD3D
);
3467 _CurStencilTest
= enable
;
3468 setRenderState(D3DRS_STENCILENABLE
, enable
?TRUE
:FALSE
);
3471 // ***************************************************************************
3472 bool CDriverD3D::isStencilTestEnabled() const
3474 H_AUTO_D3D(CDriver3D_CDriverD3D
);
3475 return _CurStencilTest
?TRUE
:FALSE
;
3478 // ***************************************************************************
3479 void CDriverD3D::stencilFunc(TStencilFunc stencilFunc
, int ref
, uint mask
)
3481 H_AUTO_D3D(CDriver3D_CDriverD3D
);
3485 case IDriver::never
: _CurStencilFunc
=D3DCMP_NEVER
; break;
3486 case IDriver::less
: _CurStencilFunc
=D3DCMP_LESS
; break;
3487 case IDriver::lessequal
: _CurStencilFunc
=D3DCMP_LESSEQUAL
; break;
3488 case IDriver::equal
: _CurStencilFunc
=D3DCMP_EQUAL
; break;
3489 case IDriver::notequal
: _CurStencilFunc
=D3DCMP_NOTEQUAL
; break;
3490 case IDriver::greaterequal
: _CurStencilFunc
=D3DCMP_GREATEREQUAL
; break;
3491 case IDriver::greater
: _CurStencilFunc
=D3DCMP_GREATER
; break;
3492 case IDriver::always
: _CurStencilFunc
=D3DCMP_ALWAYS
; break;
3496 _CurStencilRef
= (DWORD
)ref
;
3497 _CurStencilMask
= (DWORD
)mask
;
3498 setRenderState(D3DRS_STENCILFUNC
, _CurStencilFunc
);
3499 setRenderState(D3DRS_STENCILREF
, _CurStencilRef
);
3500 setRenderState(D3DRS_STENCILMASK
, _CurStencilMask
);
3503 // ***************************************************************************
3504 void CDriverD3D::stencilOp(TStencilOp fail
, TStencilOp zfail
, TStencilOp zpass
)
3506 H_AUTO_D3D(CDriver3D_CDriverD3D
);
3510 case IDriver::keep
: _CurStencilOpFail
=D3DSTENCILOP_KEEP
; break;
3511 case IDriver::zero
: _CurStencilOpFail
=D3DSTENCILOP_ZERO
; break;
3512 case IDriver::replace
: _CurStencilOpFail
=D3DSTENCILOP_REPLACE
; break;
3513 case IDriver::incr
: _CurStencilOpFail
=D3DSTENCILOP_INCR
; break;
3514 case IDriver::decr
: _CurStencilOpFail
=D3DSTENCILOP_DECR
; break;
3515 case IDriver::invert
: _CurStencilOpFail
=D3DSTENCILOP_INVERT
; break;
3521 case IDriver::keep
: _CurStencilOpZFail
=D3DSTENCILOP_KEEP
; break;
3522 case IDriver::zero
: _CurStencilOpZFail
=D3DSTENCILOP_ZERO
; break;
3523 case IDriver::replace
: _CurStencilOpZFail
=D3DSTENCILOP_REPLACE
; break;
3524 case IDriver::incr
: _CurStencilOpZFail
=D3DSTENCILOP_INCR
; break;
3525 case IDriver::decr
: _CurStencilOpZFail
=D3DSTENCILOP_DECR
; break;
3526 case IDriver::invert
: _CurStencilOpZFail
=D3DSTENCILOP_INVERT
; break;
3532 case IDriver::keep
: _CurStencilOpZPass
=D3DSTENCILOP_KEEP
; break;
3533 case IDriver::zero
: _CurStencilOpZPass
=D3DSTENCILOP_ZERO
; break;
3534 case IDriver::replace
: _CurStencilOpZPass
=D3DSTENCILOP_REPLACE
; break;
3535 case IDriver::incr
: _CurStencilOpZPass
=D3DSTENCILOP_INCR
; break;
3536 case IDriver::decr
: _CurStencilOpZPass
=D3DSTENCILOP_DECR
; break;
3537 case IDriver::invert
: _CurStencilOpZPass
=D3DSTENCILOP_INVERT
; break;
3541 setRenderState(D3DRS_STENCILFAIL
, _CurStencilOpFail
);
3542 setRenderState(D3DRS_STENCILZFAIL
, _CurStencilOpZFail
);
3543 setRenderState(D3DRS_STENCILPASS
, _CurStencilOpZPass
);
3546 // ***************************************************************************
3547 void CDriverD3D::stencilMask(uint mask
)
3549 H_AUTO_D3D(CDriver3D_CDriverD3D
);
3551 _CurStencilWriteMask
= (DWORD
)mask
;
3552 setRenderState (D3DRS_STENCILWRITEMASK
, _CurStencilWriteMask
);
3555 // volatile bool preciseStateProfile = false;
3556 // ***************************************************************************
3557 void CDriverD3D::CRenderState::apply(CDriverD3D
*driver
)
3559 H_AUTO_D3D(CDriverD3D_CRenderState
);
3560 /*if (!preciseStateProfile)
3562 driver
->_DeviceInterface
->SetRenderState (StateID
, Value
);
3569 case D3DRS_ZENABLE: { H_AUTO_D3D(D3DRS_ZENABLE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3570 case D3DRS_FILLMODE: { H_AUTO_D3D(D3DRS_FILLMODE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3571 case D3DRS_SHADEMODE: { H_AUTO_D3D(D3DRS_SHADEMODE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3572 case D3DRS_ZWRITEENABLE: { H_AUTO_D3D(D3DRS_ZWRITEENABLE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3573 case D3DRS_ALPHATESTENABLE: { H_AUTO_D3D(D3DRS_ALPHATESTENABLE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3574 case D3DRS_LASTPIXEL: { H_AUTO_D3D(D3DRS_LASTPIXEL); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3575 case D3DRS_SRCBLEND: { H_AUTO_D3D(D3DRS_SRCBLEND); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3576 case D3DRS_DESTBLEND: { H_AUTO_D3D(D3DRS_DESTBLEND); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3577 case D3DRS_CULLMODE: { H_AUTO_D3D(D3DRS_CULLMODE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3578 case D3DRS_ZFUNC: { H_AUTO_D3D(D3DRS_ZFUNC); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3579 case D3DRS_ALPHAREF: { H_AUTO_D3D(D3DRS_ALPHAREF); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3580 case D3DRS_ALPHAFUNC: { H_AUTO_D3D(D3DRS_ALPHAFUNC); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3581 case D3DRS_DITHERENABLE: { H_AUTO_D3D(D3DRS_DITHERENABLE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3582 case D3DRS_ALPHABLENDENABLE: { H_AUTO_D3D(D3DRS_ALPHABLENDENABLE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3583 case D3DRS_FOGENABLE: { H_AUTO_D3D(D3DRS_FOGENABLE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3584 case D3DRS_SPECULARENABLE: { H_AUTO_D3D(D3DRS_SPECULARENABLE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3585 case D3DRS_FOGCOLOR: { H_AUTO_D3D(D3DRS_FOGCOLOR); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3586 case D3DRS_FOGTABLEMODE: { H_AUTO_D3D(D3DRS_FOGTABLEMODE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3587 case D3DRS_FOGSTART: { H_AUTO_D3D(D3DRS_FOGSTART); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3588 case D3DRS_FOGEND: { H_AUTO_D3D(D3DRS_FOGEND); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3589 case D3DRS_FOGDENSITY: { H_AUTO_D3D(D3DRS_FOGDENSITY); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3590 case D3DRS_RANGEFOGENABLE: { H_AUTO_D3D(D3DRS_RANGEFOGENABLE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3591 case D3DRS_STENCILENABLE: { H_AUTO_D3D(D3DRS_STENCILENABLE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3592 case D3DRS_STENCILFAIL: { H_AUTO_D3D(D3DRS_STENCILFAIL); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3593 case D3DRS_STENCILZFAIL: { H_AUTO_D3D(D3DRS_STENCILZFAIL); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3594 case D3DRS_STENCILPASS: { H_AUTO_D3D(D3DRS_STENCILPASS); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3595 case D3DRS_STENCILFUNC: { H_AUTO_D3D(D3DRS_STENCILFUNC); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3596 case D3DRS_STENCILREF: { H_AUTO_D3D(D3DRS_STENCILREF); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3597 case D3DRS_STENCILMASK: { H_AUTO_D3D(D3DRS_STENCILMASK); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3598 case D3DRS_STENCILWRITEMASK: { H_AUTO_D3D(D3DRS_STENCILWRITEMASK); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3599 case D3DRS_TEXTUREFACTOR: { H_AUTO_D3D(D3DRS_TEXTUREFACTOR); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3600 case D3DRS_WRAP0: { H_AUTO_D3D(D3DRS_WRAP0); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3601 case D3DRS_WRAP1: { H_AUTO_D3D(D3DRS_WRAP1); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3602 case D3DRS_WRAP2: { H_AUTO_D3D(D3DRS_WRAP2); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3603 case D3DRS_WRAP3: { H_AUTO_D3D(D3DRS_WRAP3); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3604 case D3DRS_WRAP4: { H_AUTO_D3D(D3DRS_WRAP4); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3605 case D3DRS_WRAP5: { H_AUTO_D3D(D3DRS_WRAP5); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3606 case D3DRS_WRAP6: { H_AUTO_D3D(D3DRS_WRAP6); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3607 case D3DRS_WRAP7: { H_AUTO_D3D(D3DRS_WRAP7); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3608 case D3DRS_CLIPPING: { H_AUTO_D3D(D3DRS_CLIPPING); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3609 case D3DRS_LIGHTING: { H_AUTO_D3D(D3DRS_LIGHTING); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3610 case D3DRS_AMBIENT: { H_AUTO_D3D(D3DRS_AMBIENT); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3611 case D3DRS_FOGVERTEXMODE: { H_AUTO_D3D(D3DRS_FOGVERTEXMODE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3612 case D3DRS_COLORVERTEX: { H_AUTO_D3D(D3DRS_COLORVERTEX); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3613 case D3DRS_LOCALVIEWER: { H_AUTO_D3D(D3DRS_LOCALVIEWER); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3614 case D3DRS_NORMALIZENORMALS: { H_AUTO_D3D(D3DRS_NORMALIZENORMALS); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3615 case D3DRS_DIFFUSEMATERIALSOURCE: { H_AUTO_D3D(D3DRS_DIFFUSEMATERIALSOURCE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3616 case D3DRS_SPECULARMATERIALSOURCE: { H_AUTO_D3D(D3DRS_SPECULARMATERIALSOURCE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3617 case D3DRS_AMBIENTMATERIALSOURCE: { H_AUTO_D3D(D3DRS_AMBIENTMATERIALSOURCE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3618 case D3DRS_EMISSIVEMATERIALSOURCE: { H_AUTO_D3D(D3DRS_EMISSIVEMATERIALSOURCE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3619 case D3DRS_VERTEXBLEND: { H_AUTO_D3D(D3DRS_VERTEXBLEND); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3620 case D3DRS_CLIPPLANEENABLE: { H_AUTO_D3D(D3DRS_CLIPPLANEENABLE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3621 case D3DRS_POINTSIZE: { H_AUTO_D3D(D3DRS_POINTSIZE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3622 case D3DRS_POINTSIZE_MIN: { H_AUTO_D3D(D3DRS_POINTSIZE_MIN); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3623 case D3DRS_POINTSPRITEENABLE: { H_AUTO_D3D(D3DRS_POINTSPRITEENABLE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3624 case D3DRS_POINTSCALEENABLE: { H_AUTO_D3D(D3DRS_POINTSCALEENABLE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3625 case D3DRS_POINTSCALE_A: { H_AUTO_D3D(D3DRS_POINTSCALE_A); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3626 case D3DRS_POINTSCALE_B: { H_AUTO_D3D(D3DRS_POINTSCALE_B); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3627 case D3DRS_POINTSCALE_C: { H_AUTO_D3D(D3DRS_POINTSCALE_C); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3628 case D3DRS_MULTISAMPLEANTIALIAS: { H_AUTO_D3D(D3DRS_MULTISAMPLEANTIALIAS); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3629 case D3DRS_MULTISAMPLEMASK: { H_AUTO_D3D(D3DRS_MULTISAMPLEMASK); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3630 case D3DRS_PATCHEDGESTYLE: { H_AUTO_D3D(D3DRS_PATCHEDGESTYLE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3631 case D3DRS_DEBUGMONITORTOKEN: { H_AUTO_D3D(D3DRS_DEBUGMONITORTOKEN); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3632 case D3DRS_POINTSIZE_MAX: { H_AUTO_D3D(D3DRS_POINTSIZE_MAX); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3633 case D3DRS_INDEXEDVERTEXBLENDENABLE: { H_AUTO_D3D(D3DRS_INDEXEDVERTEXBLENDENABLE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3634 case D3DRS_COLORWRITEENABLE: { H_AUTO_D3D(D3DRS_COLORWRITEENABLE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3635 case D3DRS_TWEENFACTOR: { H_AUTO_D3D(D3DRS_TWEENFACTOR); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3636 case D3DRS_BLENDOP: { H_AUTO_D3D(D3DRS_BLENDOP); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3637 case D3DRS_POSITIONDEGREE: { H_AUTO_D3D(D3DRS_POSITIONDEGREE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3638 case D3DRS_NORMALDEGREE: { H_AUTO_D3D(D3DRS_NORMALDEGREE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3639 case D3DRS_SCISSORTESTENABLE: { H_AUTO_D3D(D3DRS_SCISSORTESTENABLE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3640 case D3DRS_SLOPESCALEDEPTHBIAS: { H_AUTO_D3D(D3DRS_SLOPESCALEDEPTHBIAS); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3641 case D3DRS_ANTIALIASEDLINEENABLE: { H_AUTO_D3D(D3DRS_ANTIALIASEDLINEENABLE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3642 case D3DRS_MINTESSELLATIONLEVEL: { H_AUTO_D3D(D3DRS_MINTESSELLATIONLEVEL); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3643 case D3DRS_MAXTESSELLATIONLEVEL: { H_AUTO_D3D(D3DRS_MAXTESSELLATIONLEVEL); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3644 case D3DRS_ADAPTIVETESS_X: { H_AUTO_D3D(D3DRS_ADAPTIVETESS_X); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3645 case D3DRS_ADAPTIVETESS_Y: { H_AUTO_D3D(D3DRS_ADAPTIVETESS_Y); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3646 case D3DRS_ADAPTIVETESS_Z: { H_AUTO_D3D(D3DRS_ADAPTIVETESS_Z); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3647 case D3DRS_ADAPTIVETESS_W: { H_AUTO_D3D(D3DRS_ADAPTIVETESS_W); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3648 case D3DRS_ENABLEADAPTIVETESSELLATION: { H_AUTO_D3D(D3DRS_ENABLEADAPTIVETESSELLATION); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3649 case D3DRS_TWOSIDEDSTENCILMODE: { H_AUTO_D3D(D3DRS_TWOSIDEDSTENCILMODE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3650 case D3DRS_CCW_STENCILFAIL: { H_AUTO_D3D(D3DRS_CCW_STENCILFAIL); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3651 case D3DRS_CCW_STENCILZFAIL: { H_AUTO_D3D(D3DRS_CCW_STENCILZFAIL); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3652 case D3DRS_CCW_STENCILPASS: { H_AUTO_D3D(D3DRS_CCW_STENCILPASS); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3653 case D3DRS_CCW_STENCILFUNC: { H_AUTO_D3D(D3DRS_CCW_STENCILFUNC); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3654 case D3DRS_COLORWRITEENABLE1: { H_AUTO_D3D(D3DRS_COLORWRITEENABLE1); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3655 case D3DRS_COLORWRITEENABLE2: { H_AUTO_D3D(D3DRS_COLORWRITEENABLE2); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3656 case D3DRS_COLORWRITEENABLE3: { H_AUTO_D3D(D3DRS_COLORWRITEENABLE3); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3657 case D3DRS_BLENDFACTOR: { H_AUTO_D3D(D3DRS_BLENDFACTOR); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3658 case D3DRS_SRGBWRITEENABLE: { H_AUTO_D3D(D3DRS_SRGBWRITEENABLE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3659 case D3DRS_DEPTHBIAS: { H_AUTO_D3D(D3DRS_DEPTHBIAS); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3660 case D3DRS_WRAP8: { H_AUTO_D3D(D3DRS_WRAP8); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3661 case D3DRS_WRAP9: { H_AUTO_D3D(D3DRS_WRAP9); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3662 case D3DRS_WRAP10: { H_AUTO_D3D(D3DRS_WRAP10); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3663 case D3DRS_WRAP11: { H_AUTO_D3D(D3DRS_WRAP11); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3664 case D3DRS_WRAP12: { H_AUTO_D3D(D3DRS_WRAP12); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3665 case D3DRS_WRAP13: { H_AUTO_D3D(D3DRS_WRAP13); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3666 case D3DRS_WRAP14: { H_AUTO_D3D(D3DRS_WRAP14); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3667 case D3DRS_WRAP15: { H_AUTO_D3D(D3DRS_WRAP15); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3668 case D3DRS_SEPARATEALPHABLENDENABLE: { H_AUTO_D3D(D3DRS_SEPARATEALPHABLENDENABLE); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3669 case D3DRS_SRCBLENDALPHA: { H_AUTO_D3D(D3DRS_SRCBLENDALPHA); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3670 case D3DRS_DESTBLENDALPHA: { H_AUTO_D3D(D3DRS_DESTBLENDALPHA); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3671 case D3DRS_BLENDOPALPHA: { H_AUTO_D3D(D3DRS_BLENDOPALPHA); driver->_DeviceInterface->SetRenderState(StateID, Value); } break;
3678 // ***************************************************************************
3679 void CDriverD3D::CTextureState::apply(CDriverD3D
*driver
)
3681 H_AUTO_D3D(CDriverD3D_CTextureState
);
3682 if (Value
!= DeviceValue
)
3684 driver
->_DeviceInterface
->SetTextureStageState (StageID
, StateID
, Value
);
3685 DeviceValue
= Value
;
3689 // ***************************************************************************
3690 void CDriverD3D::CTextureIndexState::apply(CDriverD3D
*driver
)
3692 H_AUTO_D3D(CDriverD3D_CTextureIndexState
);
3694 driver
->setTextureState (StageID
, D3DTSS_TEXCOORDINDEX
, TexGenMode
);
3696 driver
->setTextureState (StageID
, D3DTSS_TEXCOORDINDEX
, UVChannel
);
3699 // ***************************************************************************
3700 void CDriverD3D::CTexturePtrState::apply(CDriverD3D
*driver
)
3702 H_AUTO_D3D(CDriverD3D_CTexturePtrState
);
3703 driver
->_DeviceInterface
->SetTexture (StageID
, Texture
);
3706 // ***************************************************************************
3707 void CDriverD3D::CVertexProgramPtrState::apply(CDriverD3D
*driver
)
3709 H_AUTO_D3D(CDriverD3D_CVertexProgramPtrState
);
3710 driver
->_DeviceInterface
->SetVertexShader(VertexProgram
);
3713 // ***************************************************************************
3714 void CDriverD3D::CPixelShaderPtrState::apply(CDriverD3D
*driver
)
3716 H_AUTO_D3D(CDriverD3D_CPixelShaderPtrState
);
3717 if (!driver
->_PixelProgram
) return;
3718 driver
->_DeviceInterface
->SetPixelShader(PixelShader
);
3721 // ***************************************************************************
3722 void CDriverD3D::CVertexProgramConstantState::apply(CDriverD3D
*driver
)
3724 H_AUTO_D3D(CDriverD3D_CVertexProgramConstantState
);
3727 case CVertexProgramConstantState::Float
:
3728 driver
->_DeviceInterface
->SetVertexShaderConstantF (StateID
, (float*)Values
, 1);
3730 case CVertexProgramConstantState::Int
:
3731 driver
->_DeviceInterface
->SetVertexShaderConstantI (StateID
, (int*)Values
, 1);
3736 // ***************************************************************************
3737 void CDriverD3D::CPixelShaderConstantState::apply(CDriverD3D
*driver
)
3739 H_AUTO_D3D(CDriverD3D_CPixelShaderConstantState
);
3742 case CPixelShaderConstantState::Float
:
3743 driver
->_DeviceInterface
->SetPixelShaderConstantF (StateID
, (float*)Values
, 1);
3745 case CPixelShaderConstantState::Int
:
3746 driver
->_DeviceInterface
->SetPixelShaderConstantI (StateID
, (int*)Values
, 1);
3751 // ***************************************************************************
3752 void CDriverD3D::CSamplerState::apply(CDriverD3D
*driver
)
3754 H_AUTO_D3D(CDriverD3D_CSamplerState
);
3755 driver
->_DeviceInterface
->SetSamplerState (SamplerID
, StateID
, Value
);
3758 // ***************************************************************************
3759 void CDriverD3D::CMatrixState::apply(CDriverD3D
*driver
)
3761 H_AUTO_D3D(CDriverD3D_CMatrixState
);
3762 driver
->_DeviceInterface
->SetTransform (TransformType
, &Matrix
);
3765 // ***************************************************************************
3766 void CDriverD3D::CVBState::apply(CDriverD3D
*driver
)
3768 H_AUTO_D3D(CDriverD3D_CVBState
);
3771 driver
->_DeviceInterface
->SetStreamSource (0, VertexBuffer
, Offset
, Stride
);
3772 // Fix for radeon 7xxx & bad vertex layout
3773 if (driver
->inlGetNumTextStages() == 3) // If there are 3 stages this is a Radeon 7xxx
3775 if (ColorOffset
!= 0 && driver
->_VertexDeclCache
.EnableVertexColor
)
3777 driver
->_DeviceInterface
->SetStreamSource (1, VertexBuffer
, Offset
+ ColorOffset
, Stride
);
3781 driver
->_DeviceInterface
->SetStreamSource (1, NULL
, 0, 0);
3786 // ***************************************************************************
3787 void CDriverD3D::CIBState::apply(CDriverD3D
*driver
)
3789 H_AUTO_D3D(CDriverD3D_CIBState
);
3792 driver
->_DeviceInterface
->SetIndices (IndexBuffer
);
3796 // ***************************************************************************
3797 void CDriverD3D::CVertexDeclState::apply(CDriverD3D
*driver
)
3799 H_AUTO_D3D(CDriverD3D_CVertexDeclState
);
3802 if (!EnableVertexColor
&& DeclAliasDiffuseToSpecular
&& driver
->inlGetNumTextStages() == 3)
3804 // Fix for radeon 7xxx -> if vertex color is not used it should not be present in the vertex declaration (example : lighted material + vertex color but, no vertexColorLighted)
3805 nlassert(DeclNoDiffuse
);
3806 driver
->_DeviceInterface
->SetVertexDeclaration (DeclNoDiffuse
);
3809 if (AliasDiffuseToSpecular
)
3811 nlassert(DeclAliasDiffuseToSpecular
);
3812 driver
->_DeviceInterface
->SetVertexDeclaration (DeclAliasDiffuseToSpecular
);
3817 driver
->_DeviceInterface
->SetVertexDeclaration (Decl
);
3822 // ***************************************************************************
3823 void CDriverD3D::CLightState::apply(CDriverD3D
*driver
)
3825 H_AUTO_D3D(CDriverD3D_CLightState
);
3826 // Enable state modified ?
3828 H_AUTO_D3D(CDriverD3D_CLightStateEnabled
);
3830 driver
->_DeviceInterface
->LightEnable (LightIndex
, Enabled
);
3833 H_AUTO_D3D(CDriverD3D_CLightStateSetup
);
3837 if (SettingsTouched
)
3840 Light
.Position
.x
-= driver
->_PZBCameraPos
.x
;
3841 Light
.Position
.y
-= driver
->_PZBCameraPos
.y
;
3842 Light
.Position
.z
-= driver
->_PZBCameraPos
.z
;
3843 driver
->_DeviceInterface
->SetLight (LightIndex
, &Light
);
3844 SettingsTouched
= false;
3848 EnabledTouched
= false;
3852 // ***************************************************************************
3853 void CDriverD3D::CRenderTargetState::apply(CDriverD3D
*driver
)
3855 H_AUTO_D3D(CDriverD3D_CRenderTargetState
);
3856 nlassert(TargetOwned
); // Can only apply once!
3857 driver
->_DeviceInterface
->SetRenderTarget(0, Target
);
3858 driver
->setupViewport(driver
->_Viewport
);
3859 driver
->setupScissor(driver
->_Scissor
);
3863 TargetOwned
= false;
3867 // ***************************************************************************
3868 void CDriverD3D::CMaterialState::apply(CDriverD3D
*driver
)
3870 H_AUTO_D3D(CDriverD3D_CMaterialState
);
3871 driver
->_DeviceInterface
->SetMaterial(&Current
);
3874 // ***************************************************************************
3875 void CDriverD3D::beginDialogMode()
3877 if (_FullScreen
&& _HWnd
)
3878 ShowWindow(_HWnd
, SW_MINIMIZE
);
3881 // ***************************************************************************
3882 void CDriverD3D::endDialogMode()
3884 if (_FullScreen
&& _HWnd
)
3885 ShowWindow(_HWnd
, SW_MAXIMIZE
);
3888 bool CDriverD3D::clipRect(NLMISC::CRect
&rect
)
3890 // Clip the wanted rectangle with window.
3891 uint32 width
, height
;
3892 getWindowSize(width
, height
);
3894 sint32 xr
=rect
.right() ,yr
=rect
.bottom();
3896 clamp((sint32
&)rect
.X
, (sint32
)0, (sint32
)width
);
3897 clamp((sint32
&)rect
.Y
, (sint32
)0, (sint32
)height
);
3898 clamp((sint32
&)xr
, (sint32
)rect
.X
, (sint32
)width
);
3899 clamp((sint32
&)yr
, (sint32
)rect
.Y
, (sint32
)height
);
3900 rect
.Width
= xr
-rect
.X
;
3901 rect
.Height
= yr
-rect
.Y
;
3903 return rect
.Width
>0 && rect
.Height
>0;
3906 void CDriverD3D::getZBuffer(std::vector
<float> &zbuffer
)
3908 H_AUTO_D3D(CDriverD3D_getZBuffer
);
3911 getWindowSize(rect
.Width
, rect
.Height
);
3912 getZBufferPart(zbuffer
, rect
);
3915 void CDriverD3D::getZBufferPart (std::vector
<float> &zbuffer
, NLMISC::CRect
&rect
)
3919 IDirect3DSurface9
*surface
;
3920 if (SUCCEEDED(_DeviceInterface
->GetDepthStencilSurface(&surface
)))
3925 winRect
.left
= rect
.left();
3926 winRect
.right
= rect
.right();
3927 winRect
.top
= rect
.top();
3928 winRect
.bottom
= rect
.bottom();
3931 D3DLOCKED_RECT lock
;
3932 if (SUCCEEDED(surface
->LockRect (&lock
, &winRect
, D3DLOCK_READONLY
)))
3934 zbuffer
.resize(rect
.Width
*rect
.Height
);
3937 D3DSURFACE_DESC desc
;
3938 if (SUCCEEDED(surface
->GetDesc(&desc
)))
3940 const uint8
* pBits
= (uint8
*)lock
.pBits
;
3942 for(uint y
=0; y
<rect
.Height
; ++y
)
3944 uint offset
= y
*rect
.Width
;
3945 uint end
= offset
+ rect
.Width
;
3947 // 32 bits format supported
3948 if (desc
.Format
== D3DFMT_D32F_LOCKABLE
)
3950 const float *src
= (float*)(pBits
+ lock
.Pitch
* y
);
3951 float *dst
= &zbuffer
[offset
];
3952 memcpy(dst
, src
, rect
.Width
* sizeof(float));
3954 else if (desc
.Format
== D3DFMT_D24S8
)
3956 uint32
* pRow
= (uint32
*)(pBits
+ lock
.Pitch
* y
);
3957 while(offset
!= end
)
3959 uint32 value
= *pRow
++;
3960 zbuffer
[offset
++] = (float)value
/ (float)std::numeric_limits
<uint32
>::max();
3963 else if (desc
.Format
== D3DFMT_D16_LOCKABLE
)
3965 uint16
* pRow
= (uint16
*)(pBits
+ lock
.Pitch
* y
);
3966 while(offset
!= end
)
3968 uint16 value
= *pRow
++;
3969 zbuffer
[offset
++] = (float)value
/ (float)std::numeric_limits
<uint16
>::max();
3975 surface
->UnlockRect ();
3984 void CDriverD3D::findNearestFullscreenVideoMode()
3986 if(_CurrentMode
.Windowed
)
3989 std::vector
<GfxMode
> modes
;
3992 sint32 nbPixels
= _CurrentMode
.Width
* _CurrentMode
.Height
;
3993 sint32 minError
= nbPixels
;
3994 uint bestMode
= (uint
)modes
.size();
3995 for(uint i
=0; i
< modes
.size(); i
++)
3997 if(!modes
[i
].Windowed
)
3999 if(modes
[i
].Width
==_CurrentMode
.Width
&& modes
[i
].Height
==_CurrentMode
.Height
)
4001 // ok we found the perfect mode
4004 sint32 currentPixels
= modes
[i
].Width
* modes
[i
].Height
;
4005 sint32 currentError
= abs(nbPixels
- currentPixels
);
4006 if(currentError
< minError
)
4008 minError
= currentError
;
4013 if(bestMode
!= modes
.size())
4015 nlwarning("The video mode %dx%d doesn't exist, use the nearest mode %dx%d", _CurrentMode
.Width
, _CurrentMode
.Height
, modes
[bestMode
].Width
, modes
[bestMode
].Height
);
4016 _CurrentMode
.Width
= modes
[bestMode
].Width
;
4017 _CurrentMode
.Height
= modes
[bestMode
].Height
;
4021 bool CDriverD3D::copyTextToClipboard(const std::string
&text
)
4023 return _EventEmitter
.copyTextToClipboard(text
);
4026 bool CDriverD3D::pasteTextFromClipboard(std::string
&text
)
4028 return _EventEmitter
.pasteTextFromClipboard(text
);
4031 bool CDriverD3D::convertBitmapToIcon(const NLMISC::CBitmap
&bitmap
, HICON
&icon
, uint iconWidth
, uint iconHeight
, uint iconDepth
, const NLMISC::CRGBA
&col
, sint hotSpotX
, sint hotSpotY
, bool cursor
)
4033 CBitmap src
= bitmap
;
4034 // resample bitmap if necessary
4035 if (src
.getWidth() != iconWidth
|| src
.getHeight() != iconHeight
)
4037 src
.resample(iconWidth
, iconHeight
);
4040 colorBm
.resize(iconWidth
, iconHeight
, CBitmap::RGBA
);
4041 const CRGBA
*srcColorPtr
= (CRGBA
*) &(src
.getPixels()[0]);
4042 const CRGBA
*srcColorPtrLast
= srcColorPtr
+ (iconWidth
* iconHeight
);
4043 CRGBA
*destColorPtr
= (CRGBA
*) &(colorBm
.getPixels()[0]);
4044 static volatile uint8 alphaThreshold
= 127;
4047 destColorPtr
->modulateFromColor(*srcColorPtr
, col
);
4048 std::swap(destColorPtr
->R
, destColorPtr
->B
);
4052 while (srcColorPtr
!= srcColorPtrLast
);
4054 HBITMAP colorHbm
= NULL
;
4055 HBITMAP maskHbm
= NULL
;
4057 if (iconDepth
== 16)
4059 std::vector
<uint16
> colorBm16(iconWidth
* iconHeight
);
4060 const CRGBA
*src32
= (const CRGBA
*) &colorBm
.getPixels(0)[0];
4062 for (uint k
= 0; k
< colorBm16
.size(); ++k
)
4064 colorBm16
[k
] = ((uint16
)(src32
[k
].R
&0xf8)>>3) | ((uint16
)(src32
[k
].G
&0xfc)<<3) | ((uint16
)(src32
[k
].B
& 0xf8)<<8);
4067 colorHbm
= CreateBitmap(iconWidth
, iconHeight
, 1, 16, &colorBm16
[0]);
4068 std::vector
<uint8
> bitMask((iconWidth
* iconHeight
+ 7) / 8, 0);
4070 for (uint k
= 0;k
< colorBm16
.size(); ++k
)
4072 if (src32
[k
].A
<= 120)
4074 bitMask
[k
/ 8] |= (0x80 >> (k
& 7));
4078 maskHbm
= CreateBitmap(iconWidth
, iconHeight
, 1, 1, &bitMask
[0]);
4082 colorHbm
= CreateBitmap(iconWidth
, iconHeight
, 1, 32, &colorBm
.getPixels(0)[0]);
4083 maskHbm
= CreateBitmap(iconWidth
, iconHeight
, 1, 32, &colorBm
.getPixels(0)[0]);
4087 iconInfo
.fIcon
= cursor
? FALSE
:TRUE
;
4088 iconInfo
.xHotspot
= (DWORD
) hotSpotX
;
4089 iconInfo
.yHotspot
= (DWORD
) hotSpotY
;
4090 iconInfo
.hbmMask
= maskHbm
;
4091 iconInfo
.hbmColor
= colorHbm
;
4093 if (colorHbm
&& maskHbm
)
4095 icon
= CreateIconIndirect(&iconInfo
);
4099 if (colorHbm
) DeleteObject(colorHbm
);
4100 if (maskHbm
) DeleteObject(maskHbm
);