forked from TheSuperHackers/GeneralsGameCode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdx8wrapper.h
More file actions
1477 lines (1243 loc) · 46.4 KB
/
dx8wrapper.h
File metadata and controls
1477 lines (1243 loc) · 46.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : ww3d *
* *
* $Archive:: /Commando/Code/ww3d2/dx8wrapper.h $*
* *
* Original Author:: Jani Penttinen *
* *
* Author : Kenny Mitchell *
* *
* $Modtime:: 08/05/02 2:40p $*
* *
* $Revision:: 92 $*
* *
* 06/26/02 KM Matrix name change to avoid MAX conflicts *
* 06/27/02 KM Render to shadow buffer texture support *
* 08/05/02 KM Texture class redesign
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#pragma once
#include "always.h"
#include "dllist.h"
#include "d3d8.h"
#include "matrix4.h"
#include "statistics.h"
#include "wwstring.h"
#include "lightenvironment.h"
#include "shader.h"
#include "vector4.h"
#include "cpudetect.h"
#include "dx8caps.h"
#include "texture.h"
#include "dx8vertexbuffer.h"
#include "dx8indexbuffer.h"
#include "vertmaterial.h"
/*
** Registry value names
*/
#define VALUE_NAME_RENDER_DEVICE_NAME "RenderDeviceName"
#define VALUE_NAME_RENDER_DEVICE_WIDTH "RenderDeviceWidth"
#define VALUE_NAME_RENDER_DEVICE_HEIGHT "RenderDeviceHeight"
#define VALUE_NAME_RENDER_DEVICE_DEPTH "RenderDeviceDepth"
#define VALUE_NAME_RENDER_DEVICE_WINDOWED "RenderDeviceWindowed"
#define VALUE_NAME_RENDER_DEVICE_TEXTURE_DEPTH "RenderDeviceTextureDepth"
const unsigned MAX_TEXTURE_STAGES=8;
const unsigned MAX_VERTEX_STREAMS=2;
const unsigned MAX_VERTEX_SHADER_CONSTANTS=96;
const unsigned MAX_PIXEL_SHADER_CONSTANTS=8;
const unsigned MAX_SHADOW_MAPS=1;
#define prevVer
#define nextVer
enum {
BUFFER_TYPE_DX8,
BUFFER_TYPE_SORTING,
BUFFER_TYPE_DYNAMIC_DX8,
BUFFER_TYPE_DYNAMIC_SORTING,
BUFFER_TYPE_INVALID
};
class VertexMaterialClass;
class CameraClass;
class LightEnvironmentClass;
class RenderDeviceDescClass;
class VertexBufferClass;
class DynamicVBAccessClass;
class IndexBufferClass;
class DynamicIBAccessClass;
class TextureClass;
class ZTextureClass;
class LightClass;
class SurfaceClass;
class DX8Caps;
#define DX8_RECORD_MATRIX_CHANGE() matrix_changes++
#define DX8_RECORD_MATERIAL_CHANGE() material_changes++
#define DX8_RECORD_VERTEX_BUFFER_CHANGE() vertex_buffer_changes++
#define DX8_RECORD_INDEX_BUFFER_CHANGE() index_buffer_changes++
#define DX8_RECORD_LIGHT_CHANGE() light_changes++
#define DX8_RECORD_TEXTURE_CHANGE() texture_changes++
#define DX8_RECORD_RENDER_STATE_CHANGE() render_state_changes++
#define DX8_RECORD_TEXTURE_STAGE_STATE_CHANGE() texture_stage_state_changes++
#define DX8_RECORD_DRAW_CALLS() draw_calls++
extern unsigned number_of_DX8_calls;
extern bool _DX8SingleThreaded;
void DX8_Assert();
void Log_DX8_ErrorCode(unsigned res);
WWINLINE void DX8_ErrorCode(unsigned res)
{
if (res==D3D_OK) return;
Log_DX8_ErrorCode(res);
}
#ifdef WWDEBUG
#define DX8CALL_HRES(x,res) DX8_Assert(); res = DX8Wrapper::_Get_D3D_Device8()->x; DX8_ErrorCode(res); number_of_DX8_calls++;
#define DX8CALL(x) DX8_Assert(); DX8_ErrorCode(DX8Wrapper::_Get_D3D_Device8()->x); number_of_DX8_calls++;
#define DX8CALL_D3D(x) DX8_Assert(); DX8_ErrorCode(DX8Wrapper::_Get_D3D8()->x); number_of_DX8_calls++;
#define DX8_THREAD_ASSERT() if (_DX8SingleThreaded) { WWASSERT_PRINT(DX8Wrapper::_Get_Main_Thread_ID()==ThreadClass::_Get_Current_Thread_ID(),"DX8Wrapper::DX8 calls must be called from the main thread!"); }
#else
#define DX8CALL_HRES(x,res) res = DX8Wrapper::_Get_D3D_Device8()->x; number_of_DX8_calls++;
#define DX8CALL(x) DX8Wrapper::_Get_D3D_Device8()->x; number_of_DX8_calls++;
#define DX8CALL_D3D(x) DX8Wrapper::_Get_D3D8()->x; number_of_DX8_calls++;
#define DX8_THREAD_ASSERT() ;
#endif
#define no_EXTENDED_STATS
// EXTENDED_STATS collects additional timing statistics by turning off parts
// of the 3D drawing system (terrain, objects, etc.)
#ifdef EXTENDED_STATS
class DX8_Stats
{
public:
bool m_showingStats;
bool m_disableTerrain;
bool m_disableWater;
bool m_disableObjects;
bool m_disableOverhead;
bool m_disableConsole;
int m_debugLinesToShow;
int m_sleepTime;
public:
DX8_Stats::DX8_Stats() {
m_disableConsole = m_showingStats = m_disableTerrain = m_disableWater = m_disableOverhead = m_disableObjects = false;
m_sleepTime = 0;
m_debugLinesToShow = -1; // -1 means show all expected lines of output
}
};
#endif
// This virtual interface was added for the Generals RTS.
// It is called before resetting the dx8 device to ensure
// that all dx8 resources are released. Otherwise reset fails. jba.
class DX8_CleanupHook
{
public:
virtual void ReleaseResources()=0;
virtual void ReAcquireResources()=0;
};
struct RenderStateStruct
{
ShaderClass shader;
VertexMaterialClass* material;
TextureBaseClass * Textures[MAX_TEXTURE_STAGES];
D3DLIGHT8 Lights[4];
bool LightEnable[4];
//unsigned lightsHash;
D3DMATRIX world;
D3DMATRIX view;
unsigned vertex_buffer_types[MAX_VERTEX_STREAMS];
unsigned index_buffer_type;
unsigned short vba_offset;
unsigned short vba_count;
unsigned short iba_offset;
VertexBufferClass* vertex_buffers[MAX_VERTEX_STREAMS];
IndexBufferClass* index_buffer;
unsigned short index_base_offset;
RenderStateStruct();
~RenderStateStruct();
RenderStateStruct& operator= (const RenderStateStruct& src);
};
/**
** DX8Wrapper
**
** DX8 interface wrapper class. This encapsulates the DX8 interface; adding redundant state
** detection, stat tracking, etc etc. In general, we will wrap all DX8 calls with at least
** an WWINLINE function so that we can add stat tracking, etc if needed. Direct access to the
** D3D device will require "friend" status and should be granted only in extreme circumstances :-)
*/
class DX8Wrapper
{
enum ChangedStates {
WORLD_CHANGED = 1<<0,
VIEW_CHANGED = 1<<1,
LIGHT0_CHANGED = 1<<2,
LIGHT1_CHANGED = 1<<3,
LIGHT2_CHANGED = 1<<4,
LIGHT3_CHANGED = 1<<5,
TEXTURE0_CHANGED= 1<<6,
TEXTURE1_CHANGED= 1<<7,
TEXTURE2_CHANGED= 1<<8,
TEXTURE3_CHANGED= 1<<9,
MATERIAL_CHANGED= 1<<14,
SHADER_CHANGED = 1<<15,
VERTEX_BUFFER_CHANGED = 1<<16,
INDEX_BUFFER_CHANGED = 1 << 17,
WORLD_IDENTITY= 1<<18,
VIEW_IDENTITY= 1<<19,
TEXTURES_CHANGED=
TEXTURE0_CHANGED|TEXTURE1_CHANGED|TEXTURE2_CHANGED|TEXTURE3_CHANGED,
LIGHTS_CHANGED=
LIGHT0_CHANGED|LIGHT1_CHANGED|LIGHT2_CHANGED|LIGHT3_CHANGED,
};
static void Draw_Sorting_IB_VB(
unsigned primitive_type,
unsigned short start_index,
unsigned short polygon_count,
unsigned short min_vertex_index,
unsigned short vertex_count);
static void Draw(
unsigned primitive_type,
unsigned short start_index,
unsigned short polygon_count,
unsigned short min_vertex_index=0,
unsigned short vertex_count=0);
public:
#ifdef EXTENDED_STATS
static DX8_Stats stats;
#endif
static bool Init(void * hwnd, bool lite = false);
static void Shutdown();
static void SetCleanupHook(DX8_CleanupHook *pCleanupHook) {m_pCleanupHook = pCleanupHook;};
/*
** Some WW3D sub-systems need to be initialized after the device is created and shutdown
** before the device is released.
*/
static void Do_Onetime_Device_Dependent_Inits();
static void Do_Onetime_Device_Dependent_Shutdowns();
static bool Is_Device_Lost() { return IsDeviceLost; }
static bool Is_Initted() { return IsInitted; }
static bool Has_Stencil ();
static void Get_Format_Name(unsigned int format, StringClass *tex_format);
/*
** Rendering
*/
static void Begin_Scene();
static void End_Scene(bool flip_frame = true);
// Flip until the primary buffer is visible.
static void Flip_To_Primary();
static void Clear(bool clear_color, bool clear_z_stencil, const Vector3 &color, float dest_alpha=0.0f, float z=1.0f, unsigned int stencil=0);
static void Set_Viewport(CONST D3DVIEWPORT8* pViewport);
static void Set_Vertex_Buffer(const VertexBufferClass* vb, unsigned stream=0);
static void Set_Vertex_Buffer(const DynamicVBAccessClass& vba);
static void Set_Index_Buffer(const IndexBufferClass* ib,unsigned short index_base_offset);
static void Set_Index_Buffer(const DynamicIBAccessClass& iba,unsigned short index_base_offset);
static void Set_Index_Buffer_Index_Offset(unsigned offset);
static void Get_Render_State(RenderStateStruct& state);
static void Set_Render_State(const RenderStateStruct& state);
static void Release_Render_State();
static void Set_DX8_Material(const D3DMATERIAL8* mat);
static void Set_Gamma(float gamma,float bright,float contrast,bool calibrate=true,bool uselimit=true);
// Set_ and Get_Transform() functions take the matrix in Westwood convention format.
static void Set_DX8_ZBias(int zbias);
static void Set_Projection_Transform_With_Z_Bias(const Matrix4x4& matrix,float znear, float zfar); // pointer to 16 matrices
static void Set_Transform(D3DTRANSFORMSTATETYPE transform,const Matrix4x4& m);
static void Set_Transform(D3DTRANSFORMSTATETYPE transform,const Matrix3D& m);
static void Get_Transform(D3DTRANSFORMSTATETYPE transform, Matrix4x4& m);
static void Set_World_Identity();
static void Set_View_Identity();
static bool Is_World_Identity();
static bool Is_View_Identity();
// Note that *_DX8_Transform() functions take the matrix in DX8 format - transposed from Westwood convention.
static void _Set_DX8_Transform(D3DTRANSFORMSTATETYPE transform, const D3DMATRIX& m);
static void _Get_DX8_Transform(D3DTRANSFORMSTATETYPE transform, D3DMATRIX& m);
static void Set_DX8_Light(int index,D3DLIGHT8* light);
static void Set_DX8_Render_State(D3DRENDERSTATETYPE state, unsigned value);
static void Set_DX8_Clip_Plane(DWORD Index, CONST float* pPlane);
static void Set_DX8_Texture_Stage_State(unsigned stage, D3DTEXTURESTAGESTATETYPE state, unsigned value);
static void Set_DX8_Texture(unsigned int stage, IDirect3DBaseTexture8* texture);
static void Set_Light_Environment(LightEnvironmentClass* light_env);
static LightEnvironmentClass* Get_Light_Environment() { return Light_Environment; }
static void Set_Fog(bool enable, const Vector3 &color, float start, float end);
static WWINLINE const D3DLIGHT8& Peek_Light(unsigned index);
static WWINLINE bool Is_Light_Enabled(unsigned index);
static bool Validate_Device();
// Deferred
static void Set_Shader(const ShaderClass& shader);
static void Get_Shader(ShaderClass& shader);
static void Set_Texture(unsigned stage,TextureBaseClass* texture);
static void Set_Material(const VertexMaterialClass* material);
static void Set_Light(unsigned index,const D3DLIGHT8* light);
static void Set_Light(unsigned index,const LightClass &light);
static void Apply_Render_State_Changes(); // Apply deferred render state changes (will be called automatically by Draw...)
static void Draw_Triangles(
unsigned buffer_type,
unsigned short start_index,
unsigned short polygon_count,
unsigned short min_vertex_index,
unsigned short vertex_count);
static void Draw_Triangles(
unsigned short start_index,
unsigned short polygon_count,
unsigned short min_vertex_index,
unsigned short vertex_count);
static void Draw_Strip(
unsigned short start_index,
unsigned short index_count,
unsigned short min_vertex_index,
unsigned short vertex_count);
/*
** Resources
*/
static IDirect3DVolumeTexture8* _Create_DX8_Volume_Texture
(
unsigned int width,
unsigned int height,
unsigned int depth,
WW3DFormat format,
MipCountType mip_level_count,
D3DPOOL pool=D3DPOOL_MANAGED
);
static IDirect3DCubeTexture8* _Create_DX8_Cube_Texture
(
unsigned int width,
unsigned int height,
WW3DFormat format,
MipCountType mip_level_count,
D3DPOOL pool=D3DPOOL_MANAGED,
bool rendertarget=false
);
static IDirect3DTexture8* _Create_DX8_ZTexture
(
unsigned int width,
unsigned int height,
WW3DZFormat zformat,
MipCountType mip_level_count,
D3DPOOL pool=D3DPOOL_MANAGED
);
static IDirect3DTexture8 * _Create_DX8_Texture
(
unsigned int width,
unsigned int height,
WW3DFormat format,
MipCountType mip_level_count,
D3DPOOL pool=D3DPOOL_MANAGED,
bool rendertarget=false
);
static IDirect3DTexture8 * _Create_DX8_Texture(const char *filename, MipCountType mip_level_count);
static IDirect3DTexture8 * _Create_DX8_Texture(IDirect3DSurface8 *surface, MipCountType mip_level_count);
static IDirect3DSurface8 * _Create_DX8_Surface(unsigned int width, unsigned int height, WW3DFormat format);
static IDirect3DSurface8 * _Create_DX8_Surface(const char *filename);
static IDirect3DSurface8 * _Get_DX8_Front_Buffer();
static SurfaceClass * _Get_DX8_Back_Buffer(unsigned int num=0);
static void _Copy_DX8_Rects(
IDirect3DSurface8* pSourceSurface,
CONST RECT* pSourceRectsArray,
UINT cRects,
IDirect3DSurface8* pDestinationSurface,
CONST POINT* pDestPointsArray
);
static void _Update_Texture(TextureClass *system, TextureClass *video);
static void Flush_DX8_Resource_Manager(unsigned int bytes=0);
static unsigned int Get_Free_Texture_RAM();
static unsigned _Get_Main_Thread_ID() { return _MainThreadID; }
static const D3DADAPTER_IDENTIFIER8& Get_Current_Adapter_Identifier() { return CurrentAdapterIdentifier; }
/*
** Statistics
*/
static void Begin_Statistics();
static void End_Statistics();
static unsigned Get_Last_Frame_Matrix_Changes();
static unsigned Get_Last_Frame_Material_Changes();
static unsigned Get_Last_Frame_Vertex_Buffer_Changes();
static unsigned Get_Last_Frame_Index_Buffer_Changes();
static unsigned Get_Last_Frame_Light_Changes();
static unsigned Get_Last_Frame_Texture_Changes();
static unsigned Get_Last_Frame_Render_State_Changes();
static unsigned Get_Last_Frame_Texture_Stage_State_Changes();
static unsigned Get_Last_Frame_DX8_Calls();
static unsigned Get_Last_Frame_Draw_Calls();
static unsigned long Get_FrameCount();
// Needed by shader class
static bool Get_Fog_Enable() { return FogEnable; }
static D3DCOLOR Get_Fog_Color() { return FogColor; }
// Utilities
static Vector4 Convert_Color(unsigned color);
static unsigned int Convert_Color(const Vector4& color);
static unsigned int Convert_Color(const Vector3& color, const float alpha);
static void Clamp_Color(Vector4& color);
static unsigned int Convert_Color_Clamp(const Vector4& color);
static void Set_Alpha (const float alpha, unsigned int &color);
static void _Enable_Triangle_Draw(bool enable) { _EnableTriangleDraw=enable; }
static bool _Is_Triangle_Draw_Enabled() { return _EnableTriangleDraw; }
/*
** Additional swap chain interface
**
** Use this interface to render to multiple windows (in windowed mode).
** To render to an additional window, the sequence of calls should look
** something like this:
**
** DX8Wrapper::Set_Render_Target (swap_chain_ptr);
**
** WW3D::Begin_Render (true, true, Vector3 (0, 0, 0));
** WW3D::Render (scene, camera, FALSE, FALSE);
** WW3D::End_Render ();
**
** swap_chain_ptr->Present (nullptr, nullptr, nullptr, nullptr);
**
** DX8Wrapper::Set_Render_Target ((IDirect3DSurface8 *)nullptr);
**
*/
static IDirect3DSwapChain8 * Create_Additional_Swap_Chain (HWND render_window);
/*
** Render target interface. If render target format is WW3D_FORMAT_UNKNOWN, current display format is used.
*/
static TextureClass * Create_Render_Target (int width, int height, WW3DFormat format = WW3D_FORMAT_UNKNOWN);
static void Set_Render_Target (IDirect3DSurface8 *render_target, bool use_default_depth_buffer = false);
static void Set_Render_Target (IDirect3DSurface8* render_target, IDirect3DSurface8* dpeth_buffer);
static void Set_Render_Target (IDirect3DSwapChain8 *swap_chain);
static bool Is_Render_To_Texture() { return IsRenderToTexture; }
// for depth map support KJM V
static void Create_Render_Target
(
int width,
int height,
WW3DFormat format,
WW3DZFormat zformat,
TextureClass** target,
ZTextureClass** depth_buffer
);
static void Set_Render_Target_With_Z (TextureClass * texture, ZTextureClass* ztexture=nullptr);
static void Set_Shadow_Map(int idx, ZTextureClass* ztex) { Shadow_Map[idx]=ztex; }
static ZTextureClass* Get_Shadow_Map(int idx) { return Shadow_Map[idx]; }
// for depth map support KJM ^
// shader system updates KJM v
static void Apply_Default_State();
static void Set_Vertex_Shader(DWORD vertex_shader);
static void Set_Pixel_Shader(DWORD pixel_shader);
static void Set_Vertex_Shader_Constant(int reg, const void* data, int count);
static void Set_Pixel_Shader_Constant(int reg, const void* data, int count);
static DWORD Get_Vertex_Processing_Behavior() { return Vertex_Processing_Behavior; }
// Needed by scene lighting class
static void Set_Ambient(const Vector3& color);
static const Vector3& Get_Ambient() { return Ambient_Color; }
// shader system updates KJM ^
static IDirect3DDevice8* _Get_D3D_Device8() { return D3DDevice; }
static IDirect3D8* _Get_D3D8() { return D3DInterface; }
/// Returns the display format - added by TR for video playback - not part of W3D
static WW3DFormat getBackBufferFormat();
static bool Reset_Device(bool reload_assets=true);
static const DX8Caps* Get_Current_Caps() { WWASSERT(CurrentCaps); return CurrentCaps; }
static bool Registry_Save_Render_Device( const char * sub_key );
static bool Registry_Load_Render_Device( const char * sub_key, bool resize_window );
static const char* Get_DX8_Render_State_Name(D3DRENDERSTATETYPE state);
static const char* Get_DX8_Texture_Stage_State_Name(D3DTEXTURESTAGESTATETYPE state);
static unsigned Get_DX8_Render_State(D3DRENDERSTATETYPE state) { return RenderStates[state]; }
// Names of the specific values of render states and texture stage states
static void Get_DX8_Texture_Stage_State_Value_Name(StringClass& name, D3DTEXTURESTAGESTATETYPE state, unsigned value);
static void Get_DX8_Render_State_Value_Name(StringClass& name, D3DRENDERSTATETYPE state, unsigned value);
static const char* Get_DX8_Texture_Address_Name(unsigned value);
static const char* Get_DX8_Texture_Filter_Name(unsigned value);
static const char* Get_DX8_Texture_Arg_Name(unsigned value);
static const char* Get_DX8_Texture_Op_Name(unsigned value);
static const char* Get_DX8_Texture_Transform_Flag_Name(unsigned value);
static const char* Get_DX8_ZBuffer_Type_Name(unsigned value);
static const char* Get_DX8_Fill_Mode_Name(unsigned value);
static const char* Get_DX8_Shade_Mode_Name(unsigned value);
static const char* Get_DX8_Blend_Name(unsigned value);
static const char* Get_DX8_Cull_Mode_Name(unsigned value);
static const char* Get_DX8_Cmp_Func_Name(unsigned value);
static const char* Get_DX8_Fog_Mode_Name(unsigned value);
static const char* Get_DX8_Stencil_Op_Name(unsigned value);
static const char* Get_DX8_Material_Source_Name(unsigned value);
static const char* Get_DX8_Vertex_Blend_Flag_Name(unsigned value);
static const char* Get_DX8_Patch_Edge_Style_Name(unsigned value);
static const char* Get_DX8_Debug_Monitor_Token_Name(unsigned value);
static const char* Get_DX8_Blend_Op_Name(unsigned value);
static void Invalidate_Cached_Render_States();
static void Set_Draw_Polygon_Low_Bound_Limit(unsigned n) { DrawPolygonLowBoundLimit=n; }
static void Set_MultiSample_Type(D3DMULTISAMPLE_TYPE type) { MultiSampleType = type; }
protected:
static bool Create_Device();
static void Release_Device();
static void Reset_Statistics();
static void Enumerate_Devices();
static void Set_Default_Global_Render_States();
/*
** Device Selection Code.
** For backward compatibility, the public interface for these functions is in the ww3d.
** header file. These functions are protected so that we aren't exposing two interfaces.
*/
static bool Set_Any_Render_Device();
static bool Set_Render_Device(const char * dev_name,int width=-1,int height=-1,int bits=-1,int windowed=-1,bool resize_window=false);
static bool Set_Render_Device(int dev=-1,int resx=-1,int resy=-1,int bits=-1,int windowed=-1,bool resize_window = false, bool reset_device = false, bool restore_assets=true);
static bool Set_Next_Render_Device();
static bool Toggle_Windowed();
static int Get_Render_Device_Count();
static int Get_Render_Device();
static const RenderDeviceDescClass & Get_Render_Device_Desc(int deviceidx);
static const char * Get_Render_Device_Name(int device_index);
static bool Set_Device_Resolution(int width=-1,int height=-1,int bits=-1,int windowed=-1, bool resize_window=false);
static void Get_Device_Resolution(int & set_w,int & set_h,int & set_bits,bool & set_windowed);
static void Get_Render_Target_Resolution(int & set_w,int & set_h,int & set_bits,bool & set_windowed);
static int Get_Device_Resolution_Width() { return ResolutionWidth; }
static int Get_Device_Resolution_Height() { return ResolutionHeight; }
static bool Registry_Save_Render_Device( const char *sub_key, int device, int width, int height, int depth, bool windowed, int texture_depth);
static bool Registry_Load_Render_Device( const char * sub_key, char *device, int device_len, int &width, int &height, int &depth, int &windowed, int &texture_depth);
static bool Is_Windowed() { return IsWindowed; }
static void Set_Texture_Bitdepth(int depth) { WWASSERT(depth==16 || depth==32); TextureBitDepth = depth; }
static int Get_Texture_Bitdepth() { return TextureBitDepth; }
static void Set_Swap_Interval(int swap);
static int Get_Swap_Interval();
static void Set_Polygon_Mode(int mode);
/*
** Internal functions
*/
static void Resize_And_Position_Window();
static bool Find_Color_And_Z_Mode(int resx,int resy,int bitdepth,D3DFORMAT * set_colorbuffer,D3DFORMAT * set_backbuffer, D3DFORMAT * set_zmode);
static bool Find_Color_Mode(D3DFORMAT colorbuffer, int resx, int resy, UINT *mode);
static bool Find_Z_Mode(D3DFORMAT colorbuffer,D3DFORMAT backbuffer, D3DFORMAT *zmode);
static bool Test_Z_Mode(D3DFORMAT colorbuffer,D3DFORMAT backbuffer, D3DFORMAT zmode);
static void Compute_Caps(WW3DFormat display_format);
/*
** Protected Member Variables
*/
static DX8_CleanupHook *m_pCleanupHook;
static RenderStateStruct render_state;
static unsigned render_state_changed;
static D3DMATRIX DX8Transforms[D3DTS_WORLD+1];
static bool IsInitted;
static bool IsDeviceLost;
static void * Hwnd;
static unsigned _MainThreadID;
static bool _EnableTriangleDraw;
static int CurRenderDevice;
static int ResolutionWidth;
static int ResolutionHeight;
static int BitDepth;
static int TextureBitDepth;
static bool IsWindowed;
static D3DMULTISAMPLE_TYPE MultiSampleType;
static D3DFORMAT DisplayFormat;
static D3DMATRIX old_world;
static D3DMATRIX old_view;
static D3DMATRIX old_prj;
// shader system updates KJM v
static DWORD Vertex_Shader;
static DWORD Pixel_Shader;
static Vector4 Vertex_Shader_Constants[MAX_VERTEX_SHADER_CONSTANTS];
static Vector4 Pixel_Shader_Constants[MAX_PIXEL_SHADER_CONSTANTS];
static LightEnvironmentClass* Light_Environment;
static RenderInfoClass* Render_Info;
static DWORD Vertex_Processing_Behavior;
static ZTextureClass* Shadow_Map[MAX_SHADOW_MAPS];
static Vector3 Ambient_Color;
// shader system updates KJM ^
static bool world_identity;
static unsigned RenderStates[256];
static unsigned TextureStageStates[MAX_TEXTURE_STAGES][32];
static IDirect3DBaseTexture8 * Textures[MAX_TEXTURE_STAGES];
// These fog settings are constant for all objects in a given scene,
// unlike the matching renderstates which vary based on shader settings.
static bool FogEnable;
static D3DCOLOR FogColor;
static unsigned matrix_changes;
static unsigned material_changes;
static unsigned vertex_buffer_changes;
static unsigned index_buffer_changes;
static unsigned light_changes;
static unsigned texture_changes;
static unsigned render_state_changes;
static unsigned texture_stage_state_changes;
static unsigned draw_calls;
static bool CurrentDX8LightEnables[4];
static unsigned long FrameCount;
static DX8Caps* CurrentCaps;
static D3DADAPTER_IDENTIFIER8 CurrentAdapterIdentifier;
static IDirect3D8 * D3DInterface; //d3d8;
static IDirect3DDevice8 * D3DDevice; //d3ddevice8;
static IDirect3DSurface8 * CurrentRenderTarget;
static IDirect3DSurface8 * CurrentDepthBuffer;
static IDirect3DSurface8 * DefaultRenderTarget;
static IDirect3DSurface8 * DefaultDepthBuffer;
static unsigned DrawPolygonLowBoundLimit;
static bool IsRenderToTexture;
static int ZBias;
static float ZNear;
static float ZFar;
static D3DMATRIX ProjectionMatrix;
friend void DX8_Assert();
friend class WW3D;
friend class DX8IndexBufferClass;
friend class DX8VertexBufferClass;
};
// shader system updates KJM v
WWINLINE void DX8Wrapper::Set_Vertex_Shader(DWORD vertex_shader)
{
#if 0 //(gth) some code is bypassing this accessor function so we can't count on this variable...
// may be incorrect if shaders are created and destroyed dynamically
if (Vertex_Shader==vertex_shader) return;
#endif
Vertex_Shader=vertex_shader;
DX8CALL(SetVertexShader(Vertex_Shader));
}
WWINLINE void DX8Wrapper::Set_Pixel_Shader(DWORD pixel_shader)
{
// may be incorrect if shaders are created and destroyed dynamically
if (Pixel_Shader==pixel_shader) return;
Pixel_Shader=pixel_shader;
DX8CALL(SetPixelShader(Pixel_Shader));
}
WWINLINE void DX8Wrapper::Set_Vertex_Shader_Constant(int reg, const void* data, int count)
{
int memsize=sizeof(Vector4)*count;
// may be incorrect if shaders are created and destroyed dynamically
if (memcmp(data, &Vertex_Shader_Constants[reg],memsize)==0) return;
memcpy(&Vertex_Shader_Constants[reg],data,memsize);
DX8CALL(SetVertexShaderConstant(reg,data,count));
}
WWINLINE void DX8Wrapper::Set_Pixel_Shader_Constant(int reg, const void* data, int count)
{
int memsize=sizeof(Vector4)*count;
// may be incorrect if shaders are created and destroyed dynamically
if (memcmp(data, &Pixel_Shader_Constants[reg],memsize)==0) return;
memcpy(&Pixel_Shader_Constants[reg],data,memsize);
DX8CALL(SetPixelShaderConstant(reg,data,count));
}
// shader system updates KJM ^
WWINLINE void DX8Wrapper::_Set_DX8_Transform(D3DTRANSFORMSTATETYPE transform, const D3DMATRIX& m)
{
WWASSERT(transform<=D3DTS_WORLD);
#if 0 // (gth) this optimization is breaking generals because they set the transform behind our backs.
if (mtx!=DX8Transforms[transform])
#endif
{
DX8Transforms[transform]=m;
SNAPSHOT_SAY(("DX8 - SetTransform %d [%f,%f,%f,%f][%f,%f,%f,%f][%f,%f,%f,%f]",
transform,
m.m[0][0],m.m[0][1],m.m[0][2],m.m[0][3],
m.m[1][0],m.m[1][1],m.m[1][2],m.m[1][3],
m.m[2][0],m.m[2][1],m.m[2][2],m.m[2][3]));
DX8_RECORD_MATRIX_CHANGE();
DX8CALL(SetTransform(transform,&m));
}
}
WWINLINE void DX8Wrapper::_Get_DX8_Transform(D3DTRANSFORMSTATETYPE transform, D3DMATRIX& m)
{
DX8CALL(GetTransform(transform,&m));
}
// ----------------------------------------------------------------------------
//
// Set the index offset for the current index buffer
//
// ----------------------------------------------------------------------------
WWINLINE void DX8Wrapper::Set_Index_Buffer_Index_Offset(unsigned offset)
{
if (render_state.index_base_offset==offset) return;
render_state.index_base_offset=offset;
render_state_changed|=INDEX_BUFFER_CHANGED;
}
// ----------------------------------------------------------------------------
// Set the fog settings. This function should be used, rather than setting the
// appropriate renderstates directly, because the shader sets some of the
// renderstates on a per-mesh / per-pass basis depending on global fog states
// (stored in the wrapper) as well as the shader settings.
// This function should be called rarely - once per scene would be appropriate.
// ----------------------------------------------------------------------------
WWINLINE void DX8Wrapper::Set_Fog(bool enable, const Vector3 &color, float start, float end)
{
// Set global states
FogEnable = enable;
FogColor = Convert_Color(color,0.0f);
// Invalidate the current shader (since the renderstates set by the shader
// depend on the global fog settings as well as the actual shader settings)
ShaderClass::Invalidate();
// Set renderstates which are not affected by the shader
Set_DX8_Render_State(D3DRS_FOGSTART, *(DWORD *)(&start));
Set_DX8_Render_State(D3DRS_FOGEND, *(DWORD *)(&end));
}
WWINLINE void DX8Wrapper::Set_Ambient(const Vector3& color)
{
Ambient_Color=color;
Set_DX8_Render_State(D3DRS_AMBIENT, DX8Wrapper::Convert_Color(color,0.0f));
}
// ----------------------------------------------------------------------------
//
// Set vertex buffer to be used in the subsequent render calls. If there was
// a vertex buffer being used earlier, release the reference to it. Passing
// nullptr just will release the vertex buffer.
//
// ----------------------------------------------------------------------------
WWINLINE void DX8Wrapper::Set_DX8_Material(const D3DMATERIAL8* mat)
{
DX8_RECORD_MATERIAL_CHANGE();
WWASSERT(mat);
SNAPSHOT_SAY(("DX8 - SetMaterial"));
DX8CALL(SetMaterial(mat));
}
WWINLINE void DX8Wrapper::Set_DX8_Light(int index, D3DLIGHT8* light)
{
if (light) {
DX8_RECORD_LIGHT_CHANGE();
DX8CALL(SetLight(index,light));
DX8CALL(LightEnable(index,TRUE));
CurrentDX8LightEnables[index]=true;
SNAPSHOT_SAY(("DX8 - SetLight %d",index));
}
else if (CurrentDX8LightEnables[index]) {
DX8_RECORD_LIGHT_CHANGE();
CurrentDX8LightEnables[index]=false;
DX8CALL(LightEnable(index,FALSE));
SNAPSHOT_SAY(("DX8 - DisableLight %d",index));
}
}
WWINLINE void DX8Wrapper::Set_DX8_Render_State(D3DRENDERSTATETYPE state, unsigned value)
{
// Can't monitor state changes because setShader call to GERD may change the states!
if (RenderStates[state]==value) return;
#ifdef MESH_RENDER_SNAPSHOT_ENABLED
if (WW3D::Is_Snapshot_Activated()) {
StringClass value_name(0,true);
Get_DX8_Render_State_Value_Name(value_name,state,value);
SNAPSHOT_SAY(("DX8 - SetRenderState(state: %s, value: %s)",
Get_DX8_Render_State_Name(state),
value_name.str()));
}
#endif
RenderStates[state]=value;
DX8CALL(SetRenderState( state, value ));
DX8_RECORD_RENDER_STATE_CHANGE();
}
WWINLINE void DX8Wrapper::Set_DX8_Clip_Plane(DWORD Index, CONST float* pPlane)
{
DX8CALL(SetClipPlane( Index, pPlane ));
}
WWINLINE void DX8Wrapper::Set_DX8_Texture_Stage_State(unsigned stage, D3DTEXTURESTAGESTATETYPE state, unsigned value)
{
if (stage >= MAX_TEXTURE_STAGES)
{ DX8CALL(SetTextureStageState( stage, state, value ));
return;
}
// Can't monitor state changes because setShader call to GERD may change the states!
if (TextureStageStates[stage][(unsigned int)state]==value) return;
#ifdef MESH_RENDER_SNAPSHOT_ENABLED
if (WW3D::Is_Snapshot_Activated()) {
StringClass value_name(0,true);
Get_DX8_Texture_Stage_State_Value_Name(value_name,state,value);
SNAPSHOT_SAY(("DX8 - SetTextureStageState(stage: %d, state: %s, value: %s)",
stage,
Get_DX8_Texture_Stage_State_Name(state),
value_name.str()));
}
#endif
TextureStageStates[stage][(unsigned int)state]=value;
DX8CALL(SetTextureStageState( stage, state, value ));
DX8_RECORD_TEXTURE_STAGE_STATE_CHANGE();
}
WWINLINE void DX8Wrapper::Set_DX8_Texture(unsigned int stage, IDirect3DBaseTexture8* texture)
{
if (stage >= MAX_TEXTURE_STAGES)
{ DX8CALL(SetTexture(stage, texture));
return;
}
if (Textures[stage]==texture) return;
SNAPSHOT_SAY(("DX8 - SetTexture(%x) ",texture));
if (Textures[stage]) Textures[stage]->Release();
Textures[stage] = texture;
if (Textures[stage]) Textures[stage]->AddRef();
DX8CALL(SetTexture(stage, texture));
DX8_RECORD_TEXTURE_CHANGE();
}
WWINLINE void DX8Wrapper::_Copy_DX8_Rects(
IDirect3DSurface8* pSourceSurface,
CONST RECT* pSourceRectsArray,
UINT cRects,
IDirect3DSurface8* pDestinationSurface,
CONST POINT* pDestPointsArray
)
{
DX8CALL(CopyRects(
pSourceSurface,
pSourceRectsArray,
cRects,
pDestinationSurface,
pDestPointsArray));
}
WWINLINE Vector4 DX8Wrapper::Convert_Color(unsigned color)
{
Vector4 col;
col[3]=((color&0xff000000)>>24)/255.0f;
col[0]=((color&0xff0000)>>16)/255.0f;
col[1]=((color&0xff00)>>8)/255.0f;
col[2]=((color&0xff)>>0)/255.0f;
// col=Vector4(1.0f,1.0f,1.0f,1.0f);
return col;
}
#if 0
WWINLINE unsigned int DX8Wrapper::Convert_Color(const Vector3& color, const float alpha)
{
WWASSERT(color.X<=1.0f);
WWASSERT(color.Y<=1.0f);
WWASSERT(color.Z<=1.0f);
WWASSERT(alpha<=1.0f);
WWASSERT(color.X>=0.0f);
WWASSERT(color.Y>=0.0f);
WWASSERT(color.Z>=0.0f);
WWASSERT(alpha>=0.0f);
return D3DCOLOR_COLORVALUE(color.X,color.Y,color.Z,alpha);
}
WWINLINE unsigned int DX8Wrapper::Convert_Color(const Vector4& color)
{
WWASSERT(color.X<=1.0f);
WWASSERT(color.Y<=1.0f);
WWASSERT(color.Z<=1.0f);
WWASSERT(color.W<=1.0f);
WWASSERT(color.X>=0.0f);
WWASSERT(color.Y>=0.0f);
WWASSERT(color.Z>=0.0f);
WWASSERT(color.W>=0.0f);
return D3DCOLOR_COLORVALUE(color.X,color.Y,color.Z,color.W);
}
#else
// ----------------------------------------------------------------------------
//
// Convert RGBA color from float vector to 32 bit integer
// Note: Color vector needs to be clamped to [0...1] range!
//
// ----------------------------------------------------------------------------
WWINLINE unsigned int DX8Wrapper::Convert_Color(const Vector3& color,float alpha)
{
#if defined(_MSC_VER) && _MSC_VER < 1300
const float scale = 255.0;
unsigned int col;
// Multiply r, g, b and a components (0.0,...,1.0) by 255 and convert to integer. Or the integer values togerher
// such that 32 bit integer has AAAAAAAARRRRRRRRGGGGGGGGBBBBBBBB.
__asm
{
sub esp,20 // space for a, r, g and b float plus fpu rounding mode
// Store the fpu rounding mode