dx8wrapper.cpp 102 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** 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 ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WW3D *
  23. * *
  24. * $Archive:: /Commando/Code/ww3d2/dx8wrapper.cpp $*
  25. * *
  26. * Original Author:: Jani Penttinen *
  27. * *
  28. * $Author:: Jani_p $*
  29. * *
  30. * $Modtime:: 3/12/02 4:27p $*
  31. * *
  32. * $Revision:: 170 $*
  33. * *
  34. *---------------------------------------------------------------------------------------------*
  35. * Functions: *
  36. * DX8Wrapper::_Update_Texture -- Copies a texture from system memory to video memory *
  37. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  38. //#define CREATE_DX8_MULTI_THREADED
  39. //#define CREATE_DX8_FPU_PRESERVE
  40. #define WW3D_DEVTYPE D3DDEVTYPE_HAL
  41. #include "dx8wrapper.h"
  42. #include "dx8fvf.h"
  43. #include "dx8vertexbuffer.h"
  44. #include "dx8indexbuffer.h"
  45. #include "dx8renderer.h"
  46. #include "ww3d.h"
  47. #include "camera.h"
  48. #include "wwstring.h"
  49. #include "matrix4.h"
  50. #include "vertmaterial.h"
  51. #include "rddesc.h"
  52. #include "lightenvironment.h"
  53. #include "statistics.h"
  54. #include "registry.h"
  55. #include "boxrobj.h"
  56. #include "pointgr.h"
  57. #include "render2d.h"
  58. #include "sortingrenderer.h"
  59. #include "shattersystem.h"
  60. #include "light.h"
  61. #include "assetmgr.h"
  62. #include "textureloader.h"
  63. #include "missingtexture.h"
  64. #include "thread.h"
  65. #include <stdio.h>
  66. #include <D3dx8core.h>
  67. #include "pot.h"
  68. #include "wwprofile.h"
  69. #include "ffactory.h"
  70. #include "dx8caps.h"
  71. #include "formconv.h"
  72. #include "dx8texman.h"
  73. #include "bound.h"
  74. const int DEFAULT_RESOLUTION_WIDTH = 800;
  75. const int DEFAULT_RESOLUTION_HEIGHT = 600;
  76. const int DEFAULT_BIT_DEPTH = 32;
  77. const int DEFAULT_TEXTURE_BIT_DEPTH = 16;
  78. /***********************************************************************************
  79. **
  80. ** DX8Wrapper Static Variables
  81. **
  82. ***********************************************************************************/
  83. static HWND _Hwnd = NULL;
  84. bool DX8Wrapper::IsInitted = false;
  85. bool DX8Wrapper::_EnableTriangleDraw = true;
  86. int DX8Wrapper::CurRenderDevice = -1;
  87. int DX8Wrapper::ResolutionWidth = DEFAULT_RESOLUTION_WIDTH;
  88. int DX8Wrapper::ResolutionHeight = DEFAULT_RESOLUTION_HEIGHT;
  89. int DX8Wrapper::BitDepth = DEFAULT_BIT_DEPTH;
  90. int DX8Wrapper::TextureBitDepth = DEFAULT_TEXTURE_BIT_DEPTH;
  91. bool DX8Wrapper::IsWindowed = false;
  92. D3DMATRIX DX8Wrapper::old_world;
  93. D3DMATRIX DX8Wrapper::old_view;
  94. D3DMATRIX DX8Wrapper::old_prj;
  95. bool DX8Wrapper::world_identity;
  96. unsigned DX8Wrapper::RenderStates[256];
  97. unsigned DX8Wrapper::TextureStageStates[MAX_TEXTURE_STAGES][32];
  98. IDirect3DBaseTexture8 * DX8Wrapper::Textures[MAX_TEXTURE_STAGES];
  99. RenderStateStruct DX8Wrapper::render_state;
  100. unsigned DX8Wrapper::render_state_changed;
  101. bool DX8Wrapper::FogEnable = false;
  102. D3DCOLOR DX8Wrapper::FogColor = 0;
  103. IDirect3D8 * DX8Wrapper::D3DInterface = NULL;
  104. IDirect3DDevice8 * DX8Wrapper::D3DDevice = NULL;
  105. IDirect3DSurface8 * DX8Wrapper::CurrentRenderTarget = NULL;
  106. IDirect3DSurface8 * DX8Wrapper::DefaultRenderTarget = NULL;
  107. IDirect3DSurface8 * DX8Wrapper::DefaultDepthBuffer = NULL;
  108. bool DX8Wrapper::IsRenderToTexture = false;
  109. unsigned DX8Wrapper::matrix_changes = 0;
  110. unsigned DX8Wrapper::material_changes = 0;
  111. unsigned DX8Wrapper::vertex_buffer_changes = 0;
  112. unsigned DX8Wrapper::index_buffer_changes = 0;
  113. unsigned DX8Wrapper::light_changes = 0;
  114. unsigned DX8Wrapper::texture_changes = 0;
  115. unsigned DX8Wrapper::render_state_changes = 0;
  116. unsigned DX8Wrapper::texture_stage_state_changes = 0;
  117. unsigned DX8Wrapper::_MainThreadID = 0;
  118. bool DX8Wrapper::CurrentDX8LightEnables[4];
  119. bool DX8Wrapper::IsDeviceLost;
  120. int DX8Wrapper::ZBias;
  121. float DX8Wrapper::ZNear;
  122. float DX8Wrapper::ZFar;
  123. Matrix4 DX8Wrapper::ProjectionMatrix;
  124. DX8Caps* DX8Wrapper::CurrentCaps;
  125. D3DADAPTER_IDENTIFIER8 DX8Wrapper::CurrentAdapterIdentifier;
  126. unsigned long DX8Wrapper::FrameCount = 0;
  127. bool _DX8SingleThreaded = false;
  128. unsigned number_of_DX8_calls = 0;
  129. static unsigned last_frame_matrix_changes = 0;
  130. static unsigned last_frame_material_changes = 0;
  131. static unsigned last_frame_vertex_buffer_changes = 0;
  132. static unsigned last_frame_index_buffer_changes = 0;
  133. static unsigned last_frame_light_changes = 0;
  134. static unsigned last_frame_texture_changes = 0;
  135. static unsigned last_frame_render_state_changes = 0;
  136. static unsigned last_frame_texture_stage_state_changes = 0;
  137. static unsigned last_frame_number_of_DX8_calls = 0;
  138. static D3DDISPLAYMODE DesktopMode;
  139. static D3DPRESENT_PARAMETERS _PresentParameters;
  140. static DynamicVectorClass<StringClass> _RenderDeviceNameTable;
  141. static DynamicVectorClass<StringClass> _RenderDeviceShortNameTable;
  142. static DynamicVectorClass<RenderDeviceDescClass> _RenderDeviceDescriptionTable;
  143. typedef IDirect3D8* (WINAPI *Direct3DCreate8Type) (UINT SDKVersion);
  144. Direct3DCreate8Type Direct3DCreate8Ptr = NULL;
  145. HINSTANCE D3D8Lib = NULL;
  146. /***********************************************************************************
  147. **
  148. ** DX8Wrapper Implementation
  149. **
  150. ***********************************************************************************/
  151. void Log_DX8_ErrorCode(unsigned res)
  152. {
  153. char tmp[256]="";
  154. HRESULT new_res=D3DXGetErrorStringA(
  155. res,
  156. tmp,
  157. sizeof(tmp));
  158. if (new_res==D3D_OK) {
  159. WWDEBUG_SAY((tmp));
  160. }
  161. WWASSERT(0);
  162. }
  163. void Non_Fatal_Log_DX8_ErrorCode(unsigned res,const char * file,int line)
  164. {
  165. char tmp[256]="";
  166. HRESULT new_res=D3DXGetErrorStringA(
  167. res,
  168. tmp,
  169. sizeof(tmp));
  170. if (new_res==D3D_OK) {
  171. WWDEBUG_SAY(("DX8 Error: %s, File: %s, Line: %d\r\n",tmp,file,line));
  172. }
  173. }
  174. bool DX8Wrapper::Init(void * hwnd, bool lite)
  175. {
  176. WWASSERT(!IsInitted);
  177. /*
  178. ** Initialize all variables!
  179. */
  180. _Hwnd = (HWND)hwnd;
  181. _MainThreadID=ThreadClass::_Get_Current_Thread_ID();
  182. WWDEBUG_SAY(("DX8Wrapper main thread: 0x%x\n",_MainThreadID));
  183. CurRenderDevice = -1;
  184. ResolutionWidth = DEFAULT_RESOLUTION_WIDTH;
  185. ResolutionHeight = DEFAULT_RESOLUTION_HEIGHT;
  186. // Initialize Render2DClass Screen Resolution
  187. Render2DClass::Set_Screen_Resolution( RectClass( 0, 0, ResolutionWidth, ResolutionHeight ) );
  188. BitDepth = DEFAULT_BIT_DEPTH;
  189. IsWindowed = false;
  190. for (int light=0;light<4;++light) CurrentDX8LightEnables[light]=false;
  191. ::ZeroMemory(&old_world, sizeof(D3DMATRIX));
  192. ::ZeroMemory(&old_view, sizeof(D3DMATRIX));
  193. ::ZeroMemory(&old_prj, sizeof(D3DMATRIX));
  194. //old_vertex_shader; TODO
  195. //old_sr_shader;
  196. //current_shader;
  197. //world_identity;
  198. //CurrentFogColor;
  199. D3DInterface = NULL;
  200. D3DDevice = NULL;
  201. WWDEBUG_SAY(("Reset DX8Wrapper statistics\n"));
  202. Reset_Statistics();
  203. Invalidate_Cached_Render_States();
  204. if (!lite) {
  205. D3D8Lib = LoadLibrary("D3D8.DLL");
  206. if (D3D8Lib == NULL) return false;
  207. Direct3DCreate8Ptr = (Direct3DCreate8Type) GetProcAddress(D3D8Lib, "Direct3DCreate8");
  208. if (Direct3DCreate8Ptr) {
  209. /*
  210. ** Create the D3D interface object
  211. */
  212. WWDEBUG_SAY(("Create Direct3D8\n"));
  213. D3DInterface = Direct3DCreate8Ptr(D3D_SDK_VERSION); // TODO: handle failure cases...
  214. if (D3DInterface == NULL) {
  215. return(false);
  216. }
  217. IsInitted = true;
  218. /*
  219. ** Enumerate the available devices
  220. */
  221. WWDEBUG_SAY(("Enumerate devices\n"));
  222. Enumerate_Devices();
  223. WWDEBUG_SAY(("DX8Wrapper Init completed\n"));
  224. }
  225. }
  226. return(true);
  227. }
  228. void DX8Wrapper::Shutdown(void)
  229. {
  230. if (D3DDevice) {
  231. Set_Render_Target ((IDirect3DSurface8 *)NULL);
  232. // If in full screen, reset device to windowed mode before releasing it. This is an attempt to
  233. // fix some random bugs and crashes on some devices.
  234. #if (0)
  235. if (!IsWindowed) {
  236. IsWindowed=true;
  237. ResolutionWidth=DEFAULT_RESOLUTION_WIDTH;
  238. ResolutionHeight=DEFAULT_RESOLUTION_HEIGHT;
  239. _PresentParameters.BackBufferWidth = ResolutionWidth;
  240. _PresentParameters.BackBufferHeight = ResolutionHeight;
  241. _PresentParameters.BackBufferCount = 1;
  242. _PresentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
  243. _PresentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
  244. _PresentParameters.Windowed = IsWindowed;
  245. _PresentParameters.EnableAutoDepthStencil = FALSE;
  246. _PresentParameters.Flags=0;
  247. _PresentParameters.BackBufferFormat = DesktopMode.Format;
  248. Reset_Device();
  249. }
  250. #endif //(0)
  251. Release_Device();
  252. }
  253. if (D3DInterface) {
  254. D3DInterface->Release();
  255. D3DInterface=NULL;
  256. }
  257. for (int i = 0; i < MAX_TEXTURE_STAGES; i++) {
  258. if (Textures[i]) {
  259. Textures[i]->Release();
  260. Textures[i] = NULL;
  261. }
  262. }
  263. _RenderDeviceNameTable.Delete_All();
  264. _RenderDeviceShortNameTable.Delete_All();
  265. _RenderDeviceDescriptionTable.Delete_All();
  266. if (D3D8Lib) {
  267. FreeLibrary(D3D8Lib);
  268. D3D8Lib = NULL;
  269. }
  270. IsInitted = false;
  271. }
  272. void DX8Wrapper::Do_Onetime_Device_Dependent_Inits(void)
  273. {
  274. /*
  275. ** Set Global render states (some of which depend on caps)
  276. */
  277. Compute_Caps(D3DFormat_To_WW3DFormat(_PresentParameters.BackBufferFormat));
  278. /*
  279. ** Initalize any other subsystems inside of WW3D
  280. */
  281. MissingTexture::_Init();
  282. TextureClass::_Init_Filters((TextureClass::TextureFilterMode)WW3D::Get_Texture_Filter());
  283. TheDX8MeshRenderer.Init();
  284. BoxRenderObjClass::Init();
  285. VertexMaterialClass::Init();
  286. PointGroupClass::_Init(); // This needs the VertexMaterialClass to be initted
  287. ShatterSystem::Init();
  288. TextureLoader::Init();
  289. Set_Default_Global_Render_States();
  290. }
  291. inline DWORD F2DW(float f) { return *((unsigned*)&f); }
  292. void DX8Wrapper::Set_Default_Global_Render_States(void)
  293. {
  294. DX8_THREAD_ASSERT();
  295. const D3DCAPS8 &caps = Get_Current_Caps()->Get_DX8_Caps();
  296. Set_DX8_Render_State(D3DRS_RANGEFOGENABLE, (caps.RasterCaps & D3DPRASTERCAPS_FOGRANGE) ? TRUE : FALSE);
  297. Set_DX8_Render_State(D3DRS_FOGTABLEMODE, D3DFOG_NONE);
  298. Set_DX8_Render_State(D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
  299. Set_DX8_Render_State(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL);
  300. Set_DX8_Render_State(D3DRS_COLORVERTEX, TRUE);
  301. Set_DX8_Render_State(D3DRS_ZBIAS,0);
  302. Set_DX8_Texture_Stage_State(1, D3DTSS_BUMPENVLSCALE, F2DW(1.0f));
  303. Set_DX8_Texture_Stage_State(1, D3DTSS_BUMPENVLOFFSET, F2DW(0.0f));
  304. Set_DX8_Texture_Stage_State(0, D3DTSS_BUMPENVMAT00,F2DW(1.0f));
  305. Set_DX8_Texture_Stage_State(0, D3DTSS_BUMPENVMAT01,F2DW(0.0f));
  306. Set_DX8_Texture_Stage_State(0, D3DTSS_BUMPENVMAT10,F2DW(0.0f));
  307. Set_DX8_Texture_Stage_State(0, D3DTSS_BUMPENVMAT11,F2DW(1.0f));
  308. // Set_DX8_Render_State(D3DRS_CULLMODE, D3DCULL_CW);
  309. // Set dither mode here?
  310. }
  311. void DX8Wrapper::Invalidate_Cached_Render_States(void)
  312. {
  313. int a;
  314. for (a=0;a<sizeof(RenderStates)/sizeof(unsigned);++a) {
  315. RenderStates[a]=0x12345678;
  316. }
  317. for (a=0;a<MAX_TEXTURE_STAGES;++a) {
  318. for (int b=0; b<32;b++) {
  319. TextureStageStates[a][b]=0x12345678;
  320. }
  321. Textures[a]=NULL;
  322. }
  323. ShaderClass::Invalidate();
  324. }
  325. void DX8Wrapper::Do_Onetime_Device_Dependent_Shutdowns(void)
  326. {
  327. /*
  328. ** Shutdown ww3d systems
  329. */
  330. if (render_state.vertex_buffer) render_state.vertex_buffer->Release_Engine_Ref();
  331. REF_PTR_RELEASE(render_state.vertex_buffer);
  332. if (render_state.index_buffer) render_state.index_buffer->Release_Engine_Ref();
  333. REF_PTR_RELEASE(render_state.index_buffer);
  334. REF_PTR_RELEASE(render_state.material);
  335. for (unsigned i=0;i<MAX_TEXTURE_STAGES;++i) REF_PTR_RELEASE(render_state.Textures[i]);
  336. TextureLoader::Deinit();
  337. SortingRendererClass::Deinit();
  338. DynamicVBAccessClass::_Deinit();
  339. DynamicIBAccessClass::_Deinit();
  340. ShatterSystem::Shutdown();
  341. PointGroupClass::_Shutdown();
  342. VertexMaterialClass::Shutdown();
  343. BoxRenderObjClass::Shutdown();
  344. TheDX8MeshRenderer.Shutdown();
  345. MissingTexture::_Deinit();
  346. if (CurrentCaps) {
  347. delete CurrentCaps;
  348. CurrentCaps=NULL;
  349. }
  350. }
  351. bool DX8Wrapper::Create_Device(void)
  352. {
  353. WWASSERT(D3DDevice == NULL); // for now, once you've created a device, you're stuck with it!
  354. D3DCAPS8 caps;
  355. if (FAILED( D3DInterface->GetDeviceCaps(
  356. CurRenderDevice,
  357. WW3D_DEVTYPE,
  358. &caps))) {
  359. return false;
  360. }
  361. ::ZeroMemory(&CurrentAdapterIdentifier, sizeof(D3DADAPTER_IDENTIFIER8));
  362. if (FAILED( D3DInterface->GetAdapterIdentifier(CurRenderDevice,D3DENUM_NO_WHQL_LEVEL,&CurrentAdapterIdentifier))) {
  363. return false;
  364. }
  365. unsigned vertex_processing_type=D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  366. if (caps.DevCaps&D3DDEVCAPS_HWTRANSFORMANDLIGHT) {
  367. vertex_processing_type=D3DCREATE_MIXED_VERTEXPROCESSING;
  368. }
  369. #ifdef CREATE_DX8_MULTI_THREADED
  370. vertex_processing_type|=D3DCREATE_MULTITHREADED;
  371. _DX8SingleThreaded=false;
  372. #else
  373. _DX8SingleThreaded=true;
  374. #endif
  375. #ifdef CREATE_DX8_FPU_PRESERVE
  376. vertex_processing_type|=D3DCREATE_FPU_PRESERVE;
  377. #endif
  378. // JANI HACK! Some objects flicker on ATI Radeons. This can be fixed by locking the back buffer before flipping.
  379. // For this to work the back buffers need to be created as lockable!
  380. DX8Caps dx8_caps(
  381. D3DInterface,
  382. caps,
  383. D3DFormat_To_WW3DFormat(_PresentParameters.BackBufferFormat),
  384. CurrentAdapterIdentifier);
  385. if (dx8_caps.Get_Vendor()==DX8Caps::VENDOR_ATI) {
  386. _PresentParameters.Flags=D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
  387. }
  388. HRESULT hr = D3DInterface->CreateDevice(
  389. CurRenderDevice,
  390. WW3D_DEVTYPE,
  391. _Hwnd,
  392. vertex_processing_type,
  393. &_PresentParameters,
  394. &D3DDevice );
  395. if (FAILED(hr)) {
  396. // The device selection may fail because the device lied that it supports 32 bit zbuffer with 16 bit
  397. // display. This happens at least on Voodoo2.
  398. if ((_PresentParameters.BackBufferFormat==D3DFMT_R5G6B5 ||
  399. _PresentParameters.BackBufferFormat==D3DFMT_X1R5G5B5 ||
  400. _PresentParameters.BackBufferFormat==D3DFMT_A1R5G5B5) &&
  401. (_PresentParameters.AutoDepthStencilFormat==D3DFMT_D32 ||
  402. _PresentParameters.AutoDepthStencilFormat==D3DFMT_D24S8 ||
  403. _PresentParameters.AutoDepthStencilFormat==D3DFMT_D24X8)) {
  404. _PresentParameters.AutoDepthStencilFormat=D3DFMT_D16;
  405. hr = D3DInterface->CreateDevice(
  406. CurRenderDevice,
  407. WW3D_DEVTYPE,
  408. _Hwnd,
  409. vertex_processing_type,
  410. &_PresentParameters,
  411. &D3DDevice );
  412. if (FAILED(hr)) {
  413. return false;
  414. }
  415. }
  416. }
  417. /*
  418. ** Initialize all subsystems
  419. */
  420. Do_Onetime_Device_Dependent_Inits();
  421. return true;
  422. }
  423. bool DX8Wrapper::Reset_Device(void)
  424. {
  425. WWDEBUG_SAY(("Resetting device.\n"));
  426. DX8_THREAD_ASSERT();
  427. if ((IsInitted) && (D3DDevice != NULL)) {
  428. // Release all non-MANAGED stuff
  429. WW3D::_Invalidate_Textures();
  430. Set_Vertex_Buffer (NULL);
  431. Set_Index_Buffer (NULL, 0);
  432. DynamicVBAccessClass::_Deinit();
  433. DynamicIBAccessClass::_Deinit();
  434. DX8TextureManagerClass::Release_Textures();
  435. // Reset frame count to reflect the flipping chain being reset by Reset()
  436. FrameCount = 0;
  437. DX8CALL(Reset(&_PresentParameters));
  438. DX8TextureManagerClass::Recreate_Textures();
  439. Invalidate_Cached_Render_States();
  440. Set_Default_Global_Render_States();
  441. WWDEBUG_SAY(("Device reset completed\n"));
  442. return true;
  443. }
  444. WWDEBUG_SAY(("Device reset failed\n"));
  445. return false;
  446. }
  447. void DX8Wrapper::Release_Device(void)
  448. {
  449. if (D3DDevice) {
  450. /*
  451. ** Release the current vertex and index buffers
  452. */
  453. if (render_state.vertex_buffer) render_state.vertex_buffer->Release_Engine_Ref();
  454. REF_PTR_RELEASE(render_state.vertex_buffer);
  455. if (render_state.index_buffer) render_state.index_buffer->Release_Engine_Ref();
  456. REF_PTR_RELEASE(render_state.index_buffer);
  457. /*
  458. ** Shutdown all subsystems
  459. */
  460. Do_Onetime_Device_Dependent_Shutdowns();
  461. /*
  462. ** Release the device
  463. */
  464. D3DDevice->Release();
  465. D3DDevice=NULL;
  466. }
  467. }
  468. void DX8Wrapper::Enumerate_Devices()
  469. {
  470. DX8_Assert();
  471. int adapter_count = D3DInterface->GetAdapterCount();
  472. for (int adapter_index=0; adapter_index<adapter_count; adapter_index++) {
  473. D3DADAPTER_IDENTIFIER8 id;
  474. ::ZeroMemory(&id, sizeof(D3DADAPTER_IDENTIFIER8));
  475. HRESULT res = D3DInterface->GetAdapterIdentifier(adapter_index,D3DENUM_NO_WHQL_LEVEL,&id);
  476. if (res == D3D_OK) {
  477. /*
  478. ** Set up the render device description
  479. ** TODO: Fill in more fields of the render device description? (need some lookup tables)
  480. */
  481. RenderDeviceDescClass desc;
  482. desc.set_device_name(id.Description);
  483. desc.set_driver_name(id.Driver);
  484. char buf[64];
  485. sprintf(buf,"%d.%d.%d.%d", //"%04x.%04x.%04x.%04x",
  486. HIWORD(id.DriverVersion.HighPart),
  487. LOWORD(id.DriverVersion.HighPart),
  488. HIWORD(id.DriverVersion.LowPart),
  489. LOWORD(id.DriverVersion.LowPart));
  490. desc.set_driver_version(buf);
  491. D3DInterface->GetDeviceCaps(adapter_index,WW3D_DEVTYPE,&desc.Caps);
  492. D3DInterface->GetAdapterIdentifier(adapter_index,D3DENUM_NO_WHQL_LEVEL,&desc.AdapterIdentifier);
  493. DX8Caps dx8caps(D3DInterface,desc.Caps,WW3D_FORMAT_UNKNOWN,desc.AdapterIdentifier);
  494. /*
  495. ** Enumerate the resolutions
  496. */
  497. desc.reset_resolution_list();
  498. int mode_count = D3DInterface->GetAdapterModeCount(adapter_index);
  499. for (int mode_index=0; mode_index<mode_count; mode_index++) {
  500. D3DDISPLAYMODE d3dmode;
  501. ::ZeroMemory(&d3dmode, sizeof(D3DDISPLAYMODE));
  502. HRESULT res = D3DInterface->EnumAdapterModes(adapter_index,mode_index,&d3dmode);
  503. if (res == D3D_OK) {
  504. int bits = 0;
  505. switch (d3dmode.Format)
  506. {
  507. case D3DFMT_R8G8B8:
  508. case D3DFMT_A8R8G8B8:
  509. case D3DFMT_X8R8G8B8: bits = 32; break;
  510. case D3DFMT_R5G6B5:
  511. case D3DFMT_X1R5G5B5: bits = 16; break;
  512. }
  513. // Some cards fail in certain modes, DX8Caps keeps list of those.
  514. if (!dx8caps.Is_Valid_Display_Format(d3dmode.Width,d3dmode.Height,D3DFormat_To_WW3DFormat(d3dmode.Format))) {
  515. bits=0;
  516. }
  517. /*
  518. ** If we recognize the format, add it to the list
  519. ** TODO: should we handle more formats? will any cards report more than 24 or 16 bit?
  520. */
  521. if (bits != 0) {
  522. desc.add_resolution(d3dmode.Width,d3dmode.Height,bits);
  523. }
  524. }
  525. }
  526. // IML: If the device has one or more valid resolutions add it to the device list.
  527. // NOTE: Testing has shown that there are drivers with zero resolutions.
  528. if (desc.Enumerate_Resolutions().Count() > 0) {
  529. /*
  530. ** Set up the device name
  531. */
  532. StringClass device_name(id.Description,true);
  533. _RenderDeviceNameTable.Add(device_name);
  534. _RenderDeviceShortNameTable.Add(device_name); // for now, just add the same name to the "pretty name table"
  535. /*
  536. ** Add the render device to our table
  537. */
  538. _RenderDeviceDescriptionTable.Add(desc);
  539. }
  540. }
  541. }
  542. }
  543. bool DX8Wrapper::Set_Any_Render_Device(void)
  544. {
  545. // Then fullscreen
  546. for (int dev_number = 0; dev_number < _RenderDeviceNameTable.Count(); dev_number++) {
  547. if (Set_Render_Device(dev_number,-1,-1,-1,0,false)) {
  548. return true;
  549. }
  550. }
  551. // Try windowed first
  552. for (dev_number = 0; dev_number < _RenderDeviceNameTable.Count(); dev_number++) {
  553. if (Set_Render_Device(dev_number,-1,-1,-1,1,false)) {
  554. return true;
  555. }
  556. }
  557. return false;
  558. }
  559. bool DX8Wrapper::Set_Render_Device
  560. (
  561. const char * dev_name,
  562. int width,
  563. int height,
  564. int bits,
  565. int windowed,
  566. bool resize_window
  567. )
  568. {
  569. for ( int dev_number = 0; dev_number < _RenderDeviceNameTable.Count(); dev_number++) {
  570. if ( strcmp( dev_name, _RenderDeviceNameTable[dev_number]) == 0) {
  571. return Set_Render_Device( dev_number, width, height, bits, windowed, resize_window );
  572. }
  573. if ( strcmp( dev_name, _RenderDeviceShortNameTable[dev_number]) == 0) {
  574. return Set_Render_Device( dev_number, width, height, bits, windowed, resize_window );
  575. }
  576. }
  577. return false;
  578. }
  579. bool DX8Wrapper::Set_Render_Device(int dev, int width, int height, int bits, int windowed, bool resize_window)
  580. {
  581. WWASSERT(IsInitted);
  582. WWASSERT(dev >= -1);
  583. WWASSERT(dev < _RenderDeviceNameTable.Count());
  584. /*
  585. ** If user has never selected a render device, start out with device 0
  586. */
  587. if ((CurRenderDevice == -1) && (dev == -1)) {
  588. CurRenderDevice = 0;
  589. } else if (dev != -1) {
  590. CurRenderDevice = dev;
  591. }
  592. /*
  593. ** If user doesn't want to change res, set the res variables to match the
  594. ** current resolution
  595. */
  596. if (width != -1) ResolutionWidth = width;
  597. if (height != -1) ResolutionHeight = height;
  598. // Initialize Render2DClass Screen Resolution
  599. Render2DClass::Set_Screen_Resolution( RectClass( 0, 0, ResolutionWidth, ResolutionHeight ) );
  600. if (bits != -1) BitDepth = bits;
  601. if (windowed != -1) IsWindowed = (windowed != 0);
  602. WWDEBUG_SAY(("Attempting Set_Render_Device: name: %s, width: %d, height: %d, windowed: %d\r\n",
  603. _RenderDeviceNameTable[CurRenderDevice],ResolutionWidth,ResolutionHeight,(IsWindowed ? 1 : 0)));
  604. WWASSERT(D3DDevice == NULL);
  605. /*
  606. ** Initialize values for D3DPRESENT_PARAMETERS members.
  607. */
  608. ::ZeroMemory(&_PresentParameters, sizeof(D3DPRESENT_PARAMETERS));
  609. _PresentParameters.BackBufferWidth = ResolutionWidth;
  610. _PresentParameters.BackBufferHeight = ResolutionHeight;
  611. _PresentParameters.BackBufferCount = IsWindowed ? 1 : 2;
  612. _PresentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
  613. _PresentParameters.SwapEffect = IsWindowed ? D3DSWAPEFFECT_DISCARD : D3DSWAPEFFECT_FLIP; // Shouldn't this be D3DSWAPEFFECT_FLIP?
  614. _PresentParameters.hDeviceWindow = _Hwnd;
  615. _PresentParameters.Windowed = IsWindowed;
  616. _PresentParameters.EnableAutoDepthStencil = TRUE; // Driver will attempt to match Z-buffer depth
  617. _PresentParameters.Flags=0; // We're not going to lock the backbuffer
  618. _PresentParameters.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
  619. _PresentParameters.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
  620. /*
  621. ** Set up the buffer formats. Several issues here:
  622. ** - if in windowed mode, the backbuffer must use the current display format.
  623. ** - the depth buffer must use
  624. */
  625. ::ZeroMemory(&DesktopMode, sizeof(D3DDISPLAYMODE));
  626. D3DInterface->GetAdapterDisplayMode( CurRenderDevice, &DesktopMode );
  627. _PresentParameters.BackBufferFormat = DesktopMode.Format;
  628. if (IsWindowed) {
  629. WWDEBUG_SAY(("Initializing windowed mode\r\n"));
  630. // 10/23/01 - Denzil - DX window initialization
  631. /*
  632. ** Enforce a required set of window styles and size if the main window
  633. ** IS NOT A CHILD WINDOW. :)
  634. */
  635. if ((::GetWindowLong(_Hwnd, GWL_STYLE) & WS_CHILD) == 0) {
  636. ::SetWindowLong(_Hwnd, GWL_STYLE, WS_SYSMENU|WS_CAPTION|WS_MINIMIZEBOX|WS_CLIPCHILDREN);
  637. // Always resize the window to the desired resolution in windowed mode.
  638. resize_window = true;
  639. }
  640. // End Denzil - DX window initialzaion
  641. // In windowed mode, define the bitdepth from desktop mode (as it can't be changed)
  642. switch (_PresentParameters.BackBufferFormat) {
  643. case D3DFMT_X8R8G8B8:
  644. case D3DFMT_A8R8G8B8:
  645. case D3DFMT_R8G8B8: BitDepth=32; break;
  646. case D3DFMT_A4R4G4B4:
  647. case D3DFMT_A1R5G5B5:
  648. case D3DFMT_R5G6B5: BitDepth=16; break;
  649. case D3DFMT_L8:
  650. case D3DFMT_A8:
  651. case D3DFMT_P8: BitDepth=8; break;
  652. default:
  653. // Unknown backbuffer format probably means the device can't do windowed
  654. return false;
  655. }
  656. WWDEBUG_SAY(("Using buffer format: %d\r\n",_PresentParameters.BackBufferFormat));
  657. /*
  658. ** Find an appropriate Z buffer
  659. */
  660. if (!Find_Z_Mode(_PresentParameters.BackBufferFormat,_PresentParameters.BackBufferFormat,&_PresentParameters.AutoDepthStencilFormat))
  661. {
  662. // If opening 32 bit mode failed, try 16 bit, even if the desktop happens to be 32 bit
  663. if (BitDepth==32) {
  664. WWDEBUG_SAY(("Failed to find a 32 bit mode, trying 16 bit\r\n"));
  665. BitDepth=16;
  666. _PresentParameters.BackBufferFormat=D3DFMT_R5G6B5;
  667. if (!Find_Z_Mode(_PresentParameters.BackBufferFormat,_PresentParameters.BackBufferFormat,&_PresentParameters.AutoDepthStencilFormat)) {
  668. _PresentParameters.AutoDepthStencilFormat=D3DFMT_UNKNOWN;
  669. }
  670. }
  671. else {
  672. _PresentParameters.AutoDepthStencilFormat=D3DFMT_UNKNOWN;
  673. }
  674. }
  675. } else {
  676. // 10/23/01 - Denzil - DX Window initialization
  677. // For fullscreen set the window style to WS_POPUP (Recommended in DX docs)
  678. SetWindowLong(_Hwnd, GWL_STYLE, WS_POPUP);
  679. // Set fullscreen window position to top left and resize to cover entire display.
  680. // Recommended in DX docs to prevent other windows on the desktop from attempting
  681. // to repaint. This also prevents the OS from spending time calculating invalid
  682. // rects for windows that will never been seen.
  683. SetWindowPos(_Hwnd, HWND_TOPMOST, 0, 0,
  684. GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
  685. SWP_SHOWWINDOW|SWP_NOCOPYBITS);
  686. // We already resized the window
  687. resize_window = false;
  688. // End Denzil - DX window initialization
  689. WWDEBUG_SAY(("Initializing full-screen mode\r\n"));
  690. /*
  691. ** Try to find a mode that matches the user's desired bit-depth.
  692. */
  693. Find_Color_And_Z_Mode(ResolutionWidth,ResolutionHeight,BitDepth,
  694. &_PresentParameters.BackBufferFormat,&_PresentParameters.AutoDepthStencilFormat);
  695. }
  696. #ifdef _WINDOWS
  697. // PWG 4/13/2000 - changed so that if you say to resize the window it resizes
  698. // regardless of whether its windowed or not as OpenGL resizes its self around
  699. // the caption and edges of the window type you provide, so its important to
  700. // push the client area to be the size you really want.
  701. // if ( resize_window && windowed ) {
  702. if (resize_window) {
  703. // Get the current dimensions of the 'render area' of the window
  704. RECT rect = { 0 };
  705. ::GetClientRect (_Hwnd, &rect);
  706. #if(0) // Denzil - DX Window initialization
  707. // Is the window the correct size for this resolution?
  708. if ((rect.right-rect.left) != ResolutionWidth ||
  709. (rect.bottom-rect.top) != ResolutionHeight) {
  710. // Calculate what the main window's bounding rectangle should be to
  711. // accomodate this resolution
  712. rect.left = 0;
  713. rect.top = 0;
  714. rect.right = ResolutionWidth;
  715. rect.bottom = ResolutionHeight;
  716. DWORD dwstyle = ::GetWindowLong (_Hwnd, GWL_STYLE);
  717. AdjustWindowRect (&rect, dwstyle, FALSE);
  718. // Resize the window to fit this resolution
  719. ::SetWindowPos (_Hwnd,
  720. NULL,
  721. 0,
  722. 0,
  723. rect.right-rect.left,
  724. rect.bottom-rect.top,
  725. SWP_NOZORDER | SWP_NOMOVE);
  726. }
  727. #else
  728. // Adjust the main window's client area to accomodate the resolution
  729. DWORD dwstyle = ::GetWindowLong(_Hwnd, GWL_STYLE);
  730. DWORD dwexstyle = ::GetWindowLong(_Hwnd, GWL_EXSTYLE);
  731. rect.right = ResolutionWidth;
  732. rect.bottom = ResolutionHeight;
  733. ::AdjustWindowRectEx(&rect, dwstyle, (::GetMenu(_Hwnd) != NULL), dwexstyle);
  734. ::SetWindowPos(_Hwnd, HWND_TOP, 0, 0,
  735. (rect.right - rect.left), (rect.bottom - rect.top),
  736. SWP_SHOWWINDOW|SWP_NOCOPYBITS);
  737. #endif
  738. }
  739. #endif
  740. /*
  741. ** Time to actually create the device.
  742. */
  743. if (_PresentParameters.AutoDepthStencilFormat==D3DFMT_UNKNOWN) {
  744. if (BitDepth==32) {
  745. _PresentParameters.AutoDepthStencilFormat=D3DFMT_D32;
  746. }
  747. else {
  748. _PresentParameters.AutoDepthStencilFormat=D3DFMT_D16;
  749. }
  750. }
  751. return Create_Device();
  752. }
  753. bool DX8Wrapper::Set_Next_Render_Device(void)
  754. {
  755. int new_dev = (CurRenderDevice + 1) % _RenderDeviceNameTable.Count();
  756. return Set_Render_Device(new_dev);
  757. }
  758. bool DX8Wrapper::Toggle_Windowed(void)
  759. {
  760. #ifdef WW3D_DX8
  761. // State OK?
  762. assert (IsInitted);
  763. if (IsInitted) {
  764. // Get information about the current render device's resolutions
  765. const RenderDeviceDescClass &render_device = Get_Render_Device_Desc ();
  766. const DynamicVectorClass<ResolutionDescClass> &resolutions = render_device.Enumerate_Resolutions ();
  767. // Loop through all the resolutions supported by the current device.
  768. // If we aren't currently running under one of these resolutions,
  769. // then we should probably to the closest resolution before
  770. // toggling the windowed state.
  771. int curr_res = -1;
  772. for (int res = 0;
  773. (res < resolutions.Count ()) && (curr_res == -1);
  774. res ++) {
  775. // Is this the resolution we are looking for?
  776. if ((resolutions[res].Width == ResolutionWidth) &&
  777. (resolutions[res].Height == ResolutionHeight) &&
  778. (resolutions[res].BitDepth == BitDepth)) {
  779. curr_res = res;
  780. }
  781. }
  782. if (curr_res == -1) {
  783. // We don't match any of the standard resolutions,
  784. // so set the first resolution and toggle the windowed state.
  785. return Set_Device_Resolution (resolutions[0].Width,
  786. resolutions[0].Height,
  787. resolutions[0].BitDepth,
  788. !IsWindowed, true);
  789. } else {
  790. // Toggle the windowed state
  791. return Set_Device_Resolution (-1, -1, -1, !IsWindowed, true);
  792. }
  793. }
  794. #endif //WW3D_DX8
  795. return false;
  796. }
  797. void DX8Wrapper::Set_Swap_Interval(int swap)
  798. {
  799. switch (swap) {
  800. case 0: _PresentParameters.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; break;
  801. case 1: _PresentParameters.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE ; break;
  802. case 2: _PresentParameters.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_TWO; break;
  803. case 3: _PresentParameters.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_THREE; break;
  804. default: _PresentParameters.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE ; break;
  805. }
  806. Reset_Device();
  807. }
  808. int DX8Wrapper::Get_Swap_Interval(void)
  809. {
  810. return _PresentParameters.FullScreen_PresentationInterval;
  811. }
  812. int DX8Wrapper::Get_Render_Device_Count(void)
  813. {
  814. return _RenderDeviceNameTable.Count();
  815. }
  816. int DX8Wrapper::Get_Render_Device(void)
  817. {
  818. assert(IsInitted);
  819. return CurRenderDevice;
  820. }
  821. const RenderDeviceDescClass & DX8Wrapper::Get_Render_Device_Desc(int deviceidx)
  822. {
  823. WWASSERT(IsInitted);
  824. if ((deviceidx == -1) && (CurRenderDevice == -1)) {
  825. CurRenderDevice = 0;
  826. }
  827. // if the device index is -1 then we want the current device
  828. if (deviceidx == -1) {
  829. WWASSERT(CurRenderDevice >= 0);
  830. WWASSERT(CurRenderDevice < _RenderDeviceNameTable.Count());
  831. return _RenderDeviceDescriptionTable[CurRenderDevice];
  832. }
  833. // We can only ask for multiple device information if the devices
  834. // have been detected.
  835. WWASSERT(deviceidx >= 0);
  836. WWASSERT(deviceidx < _RenderDeviceNameTable.Count());
  837. return _RenderDeviceDescriptionTable[deviceidx];
  838. }
  839. const char * DX8Wrapper::Get_Render_Device_Name(int device_index)
  840. {
  841. device_index = device_index % _RenderDeviceShortNameTable.Count();
  842. return _RenderDeviceShortNameTable[device_index];
  843. }
  844. bool DX8Wrapper::Set_Device_Resolution(int width,int height,int bits,int windowed, bool resize_window)
  845. {
  846. if (D3DDevice != NULL) {
  847. if (width != -1) {
  848. _PresentParameters.BackBufferWidth = ResolutionWidth = width;
  849. }
  850. if (height != -1) {
  851. _PresentParameters.BackBufferHeight = ResolutionHeight = height;
  852. }
  853. #pragma message("TODO: support changing windowed status and changing the bit depth")
  854. return Reset_Device();
  855. } else {
  856. return false;
  857. }
  858. }
  859. void DX8Wrapper::Get_Device_Resolution(int & set_w,int & set_h,int & set_bits,bool & set_windowed)
  860. {
  861. WWASSERT(IsInitted);
  862. set_w = ResolutionWidth;
  863. set_h = ResolutionHeight;
  864. set_bits = BitDepth;
  865. set_windowed = IsWindowed;
  866. return ;
  867. }
  868. void DX8Wrapper::Get_Render_Target_Resolution(int & set_w,int & set_h,int & set_bits,bool & set_windowed)
  869. {
  870. WWASSERT(IsInitted);
  871. if (CurrentRenderTarget != NULL) {
  872. D3DSURFACE_DESC info;
  873. CurrentRenderTarget->GetDesc (&info);
  874. set_w = info.Width;
  875. set_h = info.Height;
  876. set_bits = BitDepth; // should we get the actual bit depth of the target?
  877. set_windowed = IsWindowed; // this doesn't really make sense for render targets (shouldn't matter)...
  878. } else {
  879. Get_Device_Resolution (set_w, set_h, set_bits, set_windowed);
  880. }
  881. return ;
  882. }
  883. bool DX8Wrapper::Registry_Save_Render_Device( const char * sub_key )
  884. {
  885. int width, height, depth;
  886. bool windowed;
  887. Get_Device_Resolution(width, height, depth, windowed);
  888. return Registry_Save_Render_Device(sub_key, CurRenderDevice, ResolutionWidth, ResolutionHeight, BitDepth, IsWindowed, TextureBitDepth);
  889. }
  890. bool DX8Wrapper::Registry_Save_Render_Device( const char *sub_key, int device, int width, int height, int depth, bool windowed, int texture_depth)
  891. {
  892. RegistryClass * registry = new RegistryClass( sub_key );
  893. WWASSERT( registry );
  894. if ( !registry->Is_Valid() ) {
  895. delete registry;
  896. WWDEBUG_SAY(( "Error getting Registry\n" ));
  897. return false;
  898. }
  899. registry->Set_String( VALUE_NAME_RENDER_DEVICE_NAME,
  900. _RenderDeviceShortNameTable[device] );
  901. registry->Set_Int( VALUE_NAME_RENDER_DEVICE_WIDTH, width );
  902. registry->Set_Int( VALUE_NAME_RENDER_DEVICE_HEIGHT, height );
  903. registry->Set_Int( VALUE_NAME_RENDER_DEVICE_DEPTH, depth );
  904. registry->Set_Int( VALUE_NAME_RENDER_DEVICE_WINDOWED, windowed );
  905. registry->Set_Int( VALUE_NAME_RENDER_DEVICE_TEXTURE_DEPTH, texture_depth );
  906. delete registry;
  907. return true;
  908. }
  909. bool DX8Wrapper::Registry_Load_Render_Device( const char * sub_key, bool resize_window )
  910. {
  911. char name[ 200 ];
  912. int width,height,depth,windowed;
  913. if ( Registry_Load_Render_Device( sub_key,
  914. name,
  915. sizeof(name),
  916. width,
  917. height,
  918. depth,
  919. windowed,
  920. TextureBitDepth) &&
  921. (*name != 0))
  922. {
  923. WWDEBUG_SAY(( "Device %s (%d X %d) %d bit windowed:%d\n", name,width,height,depth,windowed));
  924. if (TextureBitDepth==16 || TextureBitDepth==32) {
  925. // WWDEBUG_SAY(( "Texture depth %d\n", TextureBitDepth));
  926. } else {
  927. WWDEBUG_SAY(( "Invalid texture depth %d, switching to 16 bits\n", TextureBitDepth));
  928. TextureBitDepth=16;
  929. }
  930. // _RenderDeviceDescriptionTable.
  931. if ( Set_Render_Device( name, width,height,depth,windowed, resize_window ) != true) {
  932. if (depth==16) depth=32;
  933. else depth=16;
  934. if ( Set_Render_Device( name, width,height,depth,windowed, resize_window ) == true) {
  935. return true;
  936. }
  937. if (depth==16) depth=32;
  938. else depth=16;
  939. // we'll test resolutions down, so if start is 640, increase to begin with...
  940. if (width==640) {
  941. width=1024;
  942. height=768;
  943. }
  944. while (true) {
  945. if (width>2048) {
  946. width=2048;
  947. height=1536;
  948. }
  949. else if (width>1920) {
  950. width=1920;
  951. height=1440;
  952. }
  953. else if (width>1600) {
  954. width=1600;
  955. height=1200;
  956. }
  957. else if (width>1280) {
  958. width=1280;
  959. height=1024;
  960. }
  961. else if (width>1024) {
  962. width=1024;
  963. height=768;
  964. }
  965. else if (width>800) {
  966. width=800;
  967. height=600;
  968. }
  969. else if (width!=640) {
  970. width=640;
  971. height=480;
  972. }
  973. else {
  974. return Set_Any_Render_Device();
  975. }
  976. for (int i=0;i<2;++i) {
  977. if ( Set_Render_Device( name, width,height,depth,windowed, resize_window ) == true) {
  978. return true;
  979. }
  980. if (depth==16) depth=32;
  981. else depth=16;
  982. }
  983. }
  984. }
  985. return true;
  986. }
  987. WWDEBUG_SAY(( "Error getting Registry\n" ));
  988. return Set_Any_Render_Device();
  989. }
  990. bool DX8Wrapper::Registry_Load_Render_Device( const char * sub_key, char *device, int device_len, int &width, int &height, int &depth, int &windowed, int &texture_depth)
  991. {
  992. RegistryClass registry( sub_key );
  993. if ( registry.Is_Valid() ) {
  994. registry.Get_String( VALUE_NAME_RENDER_DEVICE_NAME,
  995. device, device_len);
  996. width = registry.Get_Int( VALUE_NAME_RENDER_DEVICE_WIDTH, -1 );
  997. height = registry.Get_Int( VALUE_NAME_RENDER_DEVICE_HEIGHT, -1 );
  998. depth = registry.Get_Int( VALUE_NAME_RENDER_DEVICE_DEPTH, -1 );
  999. windowed = registry.Get_Int( VALUE_NAME_RENDER_DEVICE_WINDOWED, -1 );
  1000. texture_depth = registry.Get_Int( VALUE_NAME_RENDER_DEVICE_TEXTURE_DEPTH, -1 );
  1001. return true;
  1002. }
  1003. *device=0;
  1004. width=-1;
  1005. height=-1;
  1006. depth=-1;
  1007. windowed=-1;
  1008. texture_depth=-1;
  1009. return false;
  1010. }
  1011. bool DX8Wrapper::Find_Color_And_Z_Mode(int resx,int resy,int bitdepth,D3DFORMAT * set_colorbuffer,D3DFORMAT * set_zmode)
  1012. {
  1013. static D3DFORMAT _formats16[] =
  1014. {
  1015. D3DFMT_R5G6B5,
  1016. D3DFMT_X1R5G5B5,
  1017. D3DFMT_A1R5G5B5
  1018. };
  1019. static D3DFORMAT _formats32[] =
  1020. {
  1021. D3DFMT_A8R8G8B8,
  1022. D3DFMT_X8R8G8B8,
  1023. D3DFMT_R8G8B8,
  1024. };
  1025. /*
  1026. ** Select the table that we're going to use to search for a valid backbuffer format
  1027. */
  1028. D3DFORMAT * format_table = NULL;
  1029. int format_count = 0;
  1030. if (BitDepth == 16) {
  1031. format_table = _formats16;
  1032. format_count = sizeof(_formats16) / sizeof(D3DFORMAT);
  1033. } else {
  1034. format_table = _formats32;
  1035. format_count = sizeof(_formats32) / sizeof(D3DFORMAT);
  1036. }
  1037. /*
  1038. ** now search for a valid format
  1039. */
  1040. bool found = false;
  1041. unsigned int mode = 0;
  1042. for (int format_index=0; format_index < format_count; format_index++) {
  1043. found |= Find_Color_Mode(format_table[format_index],resx,resy,&mode);
  1044. if (found) break;
  1045. }
  1046. if (!found) {
  1047. return false;
  1048. } else {
  1049. *set_colorbuffer = format_table[format_index];
  1050. }
  1051. /*
  1052. ** We found a backbuffer format, now find a zbuffer format
  1053. */
  1054. return Find_Z_Mode(*set_colorbuffer,*set_colorbuffer, set_zmode);
  1055. };
  1056. // find the resolution mode with at least resx,resy with the highest supported
  1057. // refresh rate
  1058. bool DX8Wrapper::Find_Color_Mode(D3DFORMAT colorbuffer, int resx, int resy, UINT *mode)
  1059. {
  1060. UINT i,j,modemax;
  1061. UINT rx,ry;
  1062. D3DDISPLAYMODE dmode;
  1063. ::ZeroMemory(&dmode, sizeof(D3DDISPLAYMODE));
  1064. rx=(unsigned int) resx;
  1065. ry=(unsigned int) resy;
  1066. bool found=false;
  1067. modemax=D3DInterface->GetAdapterModeCount(D3DADAPTER_DEFAULT);
  1068. i=0;
  1069. while (i<modemax && !found)
  1070. {
  1071. D3DInterface->EnumAdapterModes(D3DADAPTER_DEFAULT, i, &dmode);
  1072. if (dmode.Width==rx && dmode.Height==ry && dmode.Format==colorbuffer) {
  1073. WWDEBUG_SAY(("Found valid color mode. Width = %d Height = %d Format = %d\r\n",dmode.Width,dmode.Height,dmode.Format));
  1074. found=true;
  1075. }
  1076. i++;
  1077. }
  1078. i--; // this is the first valid mode
  1079. // no match
  1080. if (!found) {
  1081. WWDEBUG_SAY(("Failed to find a valid color mode\r\n"));
  1082. return false;
  1083. }
  1084. // go to the highest refresh rate in this mode
  1085. bool stillok=true;
  1086. j=i;
  1087. while (j<modemax && stillok)
  1088. {
  1089. D3DInterface->EnumAdapterModes(D3DADAPTER_DEFAULT, j, &dmode);
  1090. if (dmode.Width==rx && dmode.Height==ry && dmode.Format==colorbuffer)
  1091. stillok=true; else stillok=false;
  1092. j++;
  1093. }
  1094. if (stillok==false) *mode=j-2;
  1095. else *mode=i;
  1096. return true;
  1097. }
  1098. // Helper function to find a Z buffer mode for the colorbuffer
  1099. // Will look for greatest Z precision
  1100. bool DX8Wrapper::Find_Z_Mode(D3DFORMAT colorbuffer,D3DFORMAT backbuffer, D3DFORMAT *zmode)
  1101. {
  1102. if (Test_Z_Mode(colorbuffer,backbuffer,D3DFMT_D32))
  1103. {
  1104. *zmode=D3DFMT_D32;
  1105. WWDEBUG_SAY(("Found zbuffer mode D3DFMT_D32\r\n"));
  1106. return true;
  1107. }
  1108. if (Test_Z_Mode(colorbuffer,backbuffer,D3DFMT_D24S8))
  1109. {
  1110. *zmode=D3DFMT_D24S8;
  1111. WWDEBUG_SAY(("Found zbuffer mode D3DFMT_D24S8\r\n"));
  1112. return true;
  1113. }
  1114. if (Test_Z_Mode(colorbuffer,backbuffer,D3DFMT_D24X8))
  1115. {
  1116. *zmode=D3DFMT_D24X8;
  1117. WWDEBUG_SAY(("Found zbuffer mode D3DFMT_D24X8\r\n"));
  1118. return true;
  1119. }
  1120. if (Test_Z_Mode(colorbuffer,backbuffer,D3DFMT_D24X4S4))
  1121. {
  1122. *zmode=D3DFMT_D24X4S4;
  1123. WWDEBUG_SAY(("Found zbuffer mode D3DFMT_D24X4S4\r\n"));
  1124. return true;
  1125. }
  1126. if (Test_Z_Mode(colorbuffer,backbuffer,D3DFMT_D16))
  1127. {
  1128. *zmode=D3DFMT_D16;
  1129. WWDEBUG_SAY(("Found zbuffer mode D3DFMT_D16\r\n"));
  1130. return true;
  1131. }
  1132. if (Test_Z_Mode(colorbuffer,backbuffer,D3DFMT_D15S1))
  1133. {
  1134. *zmode=D3DFMT_D15S1;
  1135. WWDEBUG_SAY(("Found zbuffer mode D3DFMT_D15S1\r\n"));
  1136. return true;
  1137. }
  1138. // can't find a match
  1139. WWDEBUG_SAY(("Failed to find a valid zbuffer mode\r\n"));
  1140. return false;
  1141. }
  1142. bool DX8Wrapper::Test_Z_Mode(D3DFORMAT colorbuffer,D3DFORMAT backbuffer, D3DFORMAT zmode)
  1143. {
  1144. // See if we have this mode first
  1145. if (FAILED(D3DInterface->CheckDeviceFormat(D3DADAPTER_DEFAULT,WW3D_DEVTYPE,
  1146. colorbuffer,D3DUSAGE_DEPTHSTENCIL,D3DRTYPE_SURFACE,zmode)))
  1147. {
  1148. WWDEBUG_SAY(("CheckDeviceFormat failed. Colorbuffer format = %d Zbufferformat = %d\r\n",colorbuffer,zmode));
  1149. return false;
  1150. }
  1151. // Then see if it matches the color buffer
  1152. if(FAILED(D3DInterface->CheckDepthStencilMatch(D3DADAPTER_DEFAULT, WW3D_DEVTYPE,
  1153. colorbuffer,backbuffer,zmode)))
  1154. {
  1155. WWDEBUG_SAY(("CheckDepthStencilMatch failed. Colorbuffer format = %d Backbuffer format = %d Zbufferformat = %d\r\n",colorbuffer,backbuffer,zmode));
  1156. return false;
  1157. }
  1158. return true;
  1159. }
  1160. void DX8Wrapper::Reset_Statistics()
  1161. {
  1162. matrix_changes = 0;
  1163. material_changes = 0;
  1164. vertex_buffer_changes = 0;
  1165. index_buffer_changes = 0;
  1166. light_changes = 0;
  1167. texture_changes = 0;
  1168. render_state_changes =0;
  1169. texture_stage_state_changes =0;
  1170. number_of_DX8_calls = 0;
  1171. last_frame_matrix_changes = 0;
  1172. last_frame_material_changes = 0;
  1173. last_frame_vertex_buffer_changes = 0;
  1174. last_frame_index_buffer_changes = 0;
  1175. last_frame_light_changes = 0;
  1176. last_frame_texture_changes = 0;
  1177. last_frame_render_state_changes = 0;
  1178. last_frame_texture_stage_state_changes = 0;
  1179. last_frame_number_of_DX8_calls = 0;
  1180. }
  1181. void DX8Wrapper::Begin_Statistics()
  1182. {
  1183. matrix_changes=0;
  1184. material_changes=0;
  1185. vertex_buffer_changes=0;
  1186. index_buffer_changes=0;
  1187. light_changes=0;
  1188. texture_changes = 0;
  1189. render_state_changes =0;
  1190. texture_stage_state_changes =0;
  1191. number_of_DX8_calls=0;
  1192. }
  1193. void DX8Wrapper::End_Statistics()
  1194. {
  1195. last_frame_matrix_changes=matrix_changes;
  1196. last_frame_material_changes=material_changes;
  1197. last_frame_vertex_buffer_changes=vertex_buffer_changes;
  1198. last_frame_index_buffer_changes=index_buffer_changes;
  1199. last_frame_light_changes=light_changes;
  1200. last_frame_texture_changes = texture_changes;
  1201. last_frame_render_state_changes = render_state_changes;
  1202. last_frame_texture_stage_state_changes = texture_stage_state_changes;
  1203. last_frame_number_of_DX8_calls=number_of_DX8_calls;
  1204. }
  1205. unsigned DX8Wrapper::Get_Last_Frame_Matrix_Changes() { return last_frame_matrix_changes; }
  1206. unsigned DX8Wrapper::Get_Last_Frame_Material_Changes() { return last_frame_material_changes; }
  1207. unsigned DX8Wrapper::Get_Last_Frame_Vertex_Buffer_Changes() { return last_frame_vertex_buffer_changes; }
  1208. unsigned DX8Wrapper::Get_Last_Frame_Index_Buffer_Changes() { return last_frame_index_buffer_changes; }
  1209. unsigned DX8Wrapper::Get_Last_Frame_Light_Changes() { return last_frame_light_changes; }
  1210. unsigned DX8Wrapper::Get_Last_Frame_Texture_Changes() { return last_frame_texture_changes; }
  1211. unsigned DX8Wrapper::Get_Last_Frame_Render_State_Changes() { return last_frame_render_state_changes; }
  1212. unsigned DX8Wrapper::Get_Last_Frame_Texture_Stage_State_Changes() { return last_frame_texture_stage_state_changes; }
  1213. unsigned DX8Wrapper::Get_Last_Frame_DX8_Calls() { return last_frame_number_of_DX8_calls; }
  1214. unsigned long DX8Wrapper::Get_FrameCount(void) {return FrameCount;}
  1215. void DX8_Assert()
  1216. {
  1217. WWASSERT(DX8Wrapper::_Get_D3D8());
  1218. DX8_THREAD_ASSERT();
  1219. }
  1220. void DX8Wrapper::Begin_Scene(void)
  1221. {
  1222. DX8_THREAD_ASSERT();
  1223. DX8CALL(BeginScene());
  1224. }
  1225. void DX8Wrapper::End_Scene(bool flip_frames)
  1226. {
  1227. DX8_THREAD_ASSERT();
  1228. DX8CALL(EndScene());
  1229. if (flip_frames) {
  1230. // JANI HACK! Some objects flicker on ATI Radeons. This can be fixed by locking the back buffer before flipping.
  1231. // Remember that for this to work the back buffers need to have been create as lockable!
  1232. if (Get_Current_Caps()->Get_Vendor()==DX8Caps::VENDOR_ATI) {
  1233. IDirect3DSurface8 * bb;
  1234. DX8CALL(GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO,&bb));
  1235. D3DLOCKED_RECT rect;
  1236. HRESULT res=bb->LockRect(
  1237. &rect,
  1238. NULL,
  1239. D3DLOCK_READONLY);
  1240. if (res==D3D_OK) {
  1241. bb->UnlockRect();
  1242. bb->Release();
  1243. }
  1244. }
  1245. DX8_Assert();
  1246. HRESULT hr;
  1247. {
  1248. WWPROFILE("DX8Device::Present()");
  1249. hr=_Get_D3D_Device8()->Present(NULL, NULL, NULL, NULL);
  1250. }
  1251. number_of_DX8_calls++;
  1252. if (SUCCEEDED(hr)) {
  1253. IsDeviceLost=false;
  1254. FrameCount++;
  1255. }
  1256. else {
  1257. IsDeviceLost=true;
  1258. }
  1259. // If the device was lost we need to check for cooperative level and possibly reset the device
  1260. if (hr==D3DERR_DEVICELOST) {
  1261. hr=_Get_D3D_Device8()->TestCooperativeLevel();
  1262. if (hr==D3DERR_DEVICENOTRESET) {
  1263. Reset_Device();
  1264. }
  1265. else {
  1266. // Sleep it not active
  1267. ThreadClass::Sleep_Ms(200);
  1268. }
  1269. }
  1270. else {
  1271. DX8_ErrorCode(hr);
  1272. }
  1273. }
  1274. // Each frame, release all of the buffers and textures.
  1275. Set_Vertex_Buffer(NULL);
  1276. Set_Index_Buffer(NULL,0);
  1277. for (unsigned i=0;i<MAX_TEXTURE_STAGES;++i) Set_Texture(i,NULL);
  1278. Set_Material(NULL);
  1279. }
  1280. void DX8Wrapper::Flip_To_Primary(void)
  1281. {
  1282. // If we are fullscreen and the current frame is odd then we need
  1283. // to force a page flip to ensure that the first buffer in the flipping
  1284. // chain is the one visible.
  1285. if (!IsWindowed) {
  1286. DX8_Assert();
  1287. int numBuffers = (_PresentParameters.BackBufferCount + 1);
  1288. int visibleBuffer = (FrameCount % numBuffers);
  1289. int flipCount = ((numBuffers - visibleBuffer) % numBuffers);
  1290. int resetAttempts = 0;
  1291. while ((flipCount > 0) && (resetAttempts < 3)) {
  1292. HRESULT hr = _Get_D3D_Device8()->TestCooperativeLevel();
  1293. if (FAILED(hr)) {
  1294. WWDEBUG_SAY(("TestCooperativeLevel Failed!\n"));
  1295. if (D3DERR_DEVICELOST == hr) {
  1296. IsDeviceLost=true;
  1297. WWDEBUG_SAY(("DEVICELOST: Cannot flip to primary.\n"));
  1298. return;
  1299. }
  1300. IsDeviceLost=false;
  1301. if (D3DERR_DEVICENOTRESET == hr) {
  1302. WWDEBUG_SAY(("DEVICENOTRESET\n"));
  1303. Reset_Device();
  1304. resetAttempts++;
  1305. }
  1306. } else {
  1307. WWDEBUG_SAY(("Flipping: %ld\n", FrameCount));
  1308. hr = _Get_D3D_Device8()->Present(NULL, NULL, NULL, NULL);
  1309. if (SUCCEEDED(hr)) {
  1310. IsDeviceLost=false;
  1311. FrameCount++;
  1312. WWDEBUG_SAY(("Flip to primary succeeded %ld\n", FrameCount));
  1313. }
  1314. else {
  1315. IsDeviceLost=true;
  1316. }
  1317. }
  1318. --flipCount;
  1319. }
  1320. }
  1321. }
  1322. void DX8Wrapper::Clear(bool clear_color, bool clear_z_stencil, const Vector3 &color, float z, unsigned int stencil)
  1323. {
  1324. DX8_THREAD_ASSERT();
  1325. // If we try to clear a stencil buffer which is not there, the entire call will fail
  1326. bool has_stencil = ( _PresentParameters.AutoDepthStencilFormat == D3DFMT_D15S1 ||
  1327. _PresentParameters.AutoDepthStencilFormat == D3DFMT_D24S8 ||
  1328. _PresentParameters.AutoDepthStencilFormat == D3DFMT_D24X4S4);
  1329. DWORD flags = 0;
  1330. if (clear_color) flags |= D3DCLEAR_TARGET;
  1331. if (clear_z_stencil) flags |= D3DCLEAR_ZBUFFER;
  1332. if (clear_z_stencil && has_stencil) flags |= D3DCLEAR_STENCIL;
  1333. if (flags)
  1334. {
  1335. DX8CALL(Clear(0, NULL, flags, Convert_Color(color,0.0f), z, stencil));
  1336. }
  1337. }
  1338. void DX8Wrapper::Set_Viewport(CONST D3DVIEWPORT8* pViewport)
  1339. {
  1340. DX8_THREAD_ASSERT();
  1341. DX8CALL(SetViewport(pViewport));
  1342. }
  1343. // ----------------------------------------------------------------------------
  1344. //
  1345. // Set vertex buffer. A reference to previous vertex buffer is released and
  1346. // this one is assigned the current vertex buffer. The DX8 vertex buffer will
  1347. // actually be set in Apply() which is called by Draw_Indexed_Triangles().
  1348. //
  1349. // ----------------------------------------------------------------------------
  1350. void DX8Wrapper::Set_Vertex_Buffer(const VertexBufferClass* vb)
  1351. {
  1352. render_state.vba_offset=0;
  1353. render_state.vba_count=0;
  1354. if (render_state.vertex_buffer) {
  1355. render_state.vertex_buffer->Release_Engine_Ref();
  1356. }
  1357. REF_PTR_SET(render_state.vertex_buffer,const_cast<VertexBufferClass*>(vb));
  1358. if (vb) {
  1359. vb->Add_Engine_Ref();
  1360. render_state.vertex_buffer_type=vb->Type();
  1361. }
  1362. else {
  1363. render_state.index_buffer_type=BUFFER_TYPE_INVALID;
  1364. }
  1365. render_state_changed|=VERTEX_BUFFER_CHANGED;
  1366. }
  1367. // ----------------------------------------------------------------------------
  1368. //
  1369. // Set index buffer. A reference to previous index buffer is released and
  1370. // this one is assigned the current index buffer. The DX8 index buffer will
  1371. // actually be set in Apply() which is called by Draw_Indexed_Triangles().
  1372. //
  1373. // ----------------------------------------------------------------------------
  1374. void DX8Wrapper::Set_Index_Buffer(const IndexBufferClass* ib,unsigned short index_base_offset)
  1375. {
  1376. render_state.iba_offset=0;
  1377. if (render_state.index_buffer) {
  1378. render_state.index_buffer->Release_Engine_Ref();
  1379. }
  1380. REF_PTR_SET(render_state.index_buffer,const_cast<IndexBufferClass*>(ib));
  1381. render_state.index_base_offset=index_base_offset;
  1382. if (ib) {
  1383. ib->Add_Engine_Ref();
  1384. render_state.index_buffer_type=ib->Type();
  1385. }
  1386. else {
  1387. render_state.index_buffer_type=BUFFER_TYPE_INVALID;
  1388. }
  1389. render_state_changed|=INDEX_BUFFER_CHANGED;
  1390. }
  1391. // ----------------------------------------------------------------------------
  1392. //
  1393. // Set vertex buffer using dynamic access object.
  1394. //
  1395. // ----------------------------------------------------------------------------
  1396. void DX8Wrapper::Set_Vertex_Buffer(const DynamicVBAccessClass& vba_)
  1397. {
  1398. if (render_state.vertex_buffer) render_state.vertex_buffer->Release_Engine_Ref();
  1399. DynamicVBAccessClass& vba=const_cast<DynamicVBAccessClass&>(vba_);
  1400. render_state.vertex_buffer_type=vba.Get_Type();
  1401. render_state.vba_offset=vba.VertexBufferOffset;
  1402. render_state.vba_count=vba.Get_Vertex_Count();
  1403. REF_PTR_SET(render_state.vertex_buffer,vba.VertexBuffer);
  1404. render_state.vertex_buffer->Add_Engine_Ref();
  1405. render_state_changed|=VERTEX_BUFFER_CHANGED;
  1406. render_state_changed|=INDEX_BUFFER_CHANGED; // vba_offset changes so index buffer needs to be reset as well.
  1407. }
  1408. // ----------------------------------------------------------------------------
  1409. //
  1410. // Set index buffer using dynamic access object.
  1411. //
  1412. // ----------------------------------------------------------------------------
  1413. void DX8Wrapper::Set_Index_Buffer(const DynamicIBAccessClass& iba_,unsigned short index_base_offset)
  1414. {
  1415. if (render_state.index_buffer) render_state.index_buffer->Release_Engine_Ref();
  1416. DynamicIBAccessClass& iba=const_cast<DynamicIBAccessClass&>(iba_);
  1417. render_state.index_base_offset=index_base_offset;
  1418. render_state.index_buffer_type=iba.Get_Type();
  1419. render_state.iba_offset=iba.IndexBufferOffset;
  1420. REF_PTR_SET(render_state.index_buffer,iba.IndexBuffer);
  1421. render_state.index_buffer->Add_Engine_Ref();
  1422. render_state_changed|=INDEX_BUFFER_CHANGED;
  1423. }
  1424. // ----------------------------------------------------------------------------
  1425. //
  1426. // Private function for the special case of rendering polygons from sorting
  1427. // index and vertex buffers.
  1428. //
  1429. // ----------------------------------------------------------------------------
  1430. void DX8Wrapper::Draw_Sorting_IB_VB(
  1431. unsigned primitive_type,
  1432. unsigned short start_index,
  1433. unsigned short polygon_count,
  1434. unsigned short min_vertex_index,
  1435. unsigned short vertex_count)
  1436. {
  1437. WWASSERT(render_state.vertex_buffer_type==BUFFER_TYPE_SORTING || render_state.vertex_buffer_type==BUFFER_TYPE_DYNAMIC_SORTING);
  1438. WWASSERT(render_state.index_buffer_type==BUFFER_TYPE_SORTING || render_state.index_buffer_type==BUFFER_TYPE_DYNAMIC_SORTING);
  1439. // Fill dynamic vertex buffer with sorting vertex buffer vertices
  1440. DynamicVBAccessClass dyn_vb_access(BUFFER_TYPE_DYNAMIC_DX8,dynamic_fvf_type,vertex_count);
  1441. {
  1442. DynamicVBAccessClass::WriteLockClass lock(&dyn_vb_access);
  1443. VertexFormatXYZNDUV2* src = static_cast<SortingVertexBufferClass*>(render_state.vertex_buffer)->VertexBuffer;
  1444. VertexFormatXYZNDUV2* dest= lock.Get_Formatted_Vertex_Array();
  1445. src += render_state.vba_offset + render_state.index_base_offset + min_vertex_index;
  1446. unsigned size = dyn_vb_access.FVF_Info().Get_FVF_Size()*vertex_count/sizeof(unsigned);
  1447. unsigned *dest_u =(unsigned*) dest;
  1448. unsigned *src_u = (unsigned*) src;
  1449. for (unsigned i=0;i<size;++i) {
  1450. *dest_u++=*src_u++;
  1451. }
  1452. }
  1453. DX8CALL(SetStreamSource(
  1454. 0,
  1455. static_cast<DX8VertexBufferClass*>(dyn_vb_access.VertexBuffer)->Get_DX8_Vertex_Buffer(),
  1456. dyn_vb_access.FVF_Info().Get_FVF_Size()));
  1457. DX8CALL(SetVertexShader(dyn_vb_access.FVF_Info().Get_FVF()));
  1458. DX8_RECORD_VERTEX_BUFFER_CHANGE();
  1459. unsigned index_count=0;
  1460. switch (primitive_type) {
  1461. case D3DPT_TRIANGLELIST: index_count=polygon_count*3; break;
  1462. case D3DPT_TRIANGLESTRIP: index_count=polygon_count+2; break;
  1463. case D3DPT_TRIANGLEFAN: index_count=polygon_count+2; break;
  1464. default: WWASSERT(0); break; // Unsupported primitive type
  1465. }
  1466. // Fill dynamic index buffer with sorting index buffer vertices
  1467. DynamicIBAccessClass dyn_ib_access(BUFFER_TYPE_DYNAMIC_DX8,index_count);
  1468. {
  1469. DynamicIBAccessClass::WriteLockClass lock(&dyn_ib_access);
  1470. unsigned short* dest=lock.Get_Index_Array();
  1471. unsigned short* src=NULL;
  1472. src=static_cast<SortingIndexBufferClass*>(render_state.index_buffer)->index_buffer;
  1473. src+=render_state.iba_offset+start_index;
  1474. for (unsigned short i=0;i<index_count;++i) {
  1475. unsigned short index=*src++;
  1476. index-=min_vertex_index;
  1477. WWASSERT(index<vertex_count);
  1478. *dest++=index;
  1479. }
  1480. }
  1481. DX8CALL(SetIndices(
  1482. static_cast<DX8IndexBufferClass*>(dyn_ib_access.IndexBuffer)->Get_DX8_Index_Buffer(),
  1483. dyn_vb_access.VertexBufferOffset));
  1484. DX8_RECORD_INDEX_BUFFER_CHANGE();
  1485. DX8CALL(DrawIndexedPrimitive(
  1486. D3DPT_TRIANGLELIST,
  1487. 0, // start vertex
  1488. vertex_count,
  1489. dyn_ib_access.IndexBufferOffset,
  1490. polygon_count));
  1491. DX8_RECORD_RENDER(polygon_count,vertex_count,render_state.shader);
  1492. }
  1493. // ----------------------------------------------------------------------------
  1494. //
  1495. //
  1496. //
  1497. // ----------------------------------------------------------------------------
  1498. void DX8Wrapper::Draw(
  1499. unsigned primitive_type,
  1500. unsigned short start_index,
  1501. unsigned short polygon_count,
  1502. unsigned short min_vertex_index,
  1503. unsigned short vertex_count)
  1504. {
  1505. DX8_THREAD_ASSERT();
  1506. SNAPSHOT_SAY(("DX8 - draw\n"));
  1507. Apply_Render_State_Changes();
  1508. // Debug feature to disable triangle drawing...
  1509. if (!_Is_Triangle_Draw_Enabled()) return;
  1510. #ifdef MESH_RENDER_SNAPSHOT_ENABLED
  1511. if (WW3D::Is_Snapshot_Activated()) {
  1512. unsigned long passes=0;
  1513. SNAPSHOT_SAY(("ValidateDevice: "));
  1514. HRESULT res=D3DDevice->ValidateDevice(&passes);
  1515. switch (res) {
  1516. case D3D_OK:
  1517. SNAPSHOT_SAY(("OK\n"));
  1518. break;
  1519. case D3DERR_CONFLICTINGTEXTUREFILTER:
  1520. SNAPSHOT_SAY(("D3DERR_CONFLICTINGTEXTUREFILTER\n"));
  1521. break;
  1522. case D3DERR_CONFLICTINGTEXTUREPALETTE:
  1523. SNAPSHOT_SAY(("D3DERR_CONFLICTINGTEXTUREPALETTE\n"));
  1524. break;
  1525. case D3DERR_DEVICELOST:
  1526. SNAPSHOT_SAY(("D3DERR_DEVICELOST\n"));
  1527. break;
  1528. case D3DERR_TOOMANYOPERATIONS:
  1529. SNAPSHOT_SAY(("D3DERR_TOOMANYOPERATIONS\n"));
  1530. break;
  1531. case D3DERR_UNSUPPORTEDALPHAARG:
  1532. SNAPSHOT_SAY(("D3DERR_UNSUPPORTEDALPHAARG\n"));
  1533. break;
  1534. case D3DERR_UNSUPPORTEDALPHAOPERATION:
  1535. SNAPSHOT_SAY(("D3DERR_UNSUPPORTEDALPHAOPERATION\n"));
  1536. break;
  1537. case D3DERR_UNSUPPORTEDCOLORARG:
  1538. SNAPSHOT_SAY(("D3DERR_UNSUPPORTEDCOLORARG\n"));
  1539. break;
  1540. case D3DERR_UNSUPPORTEDCOLOROPERATION:
  1541. SNAPSHOT_SAY(("D3DERR_UNSUPPORTEDCOLOROPERATION\n"));
  1542. break;
  1543. case D3DERR_UNSUPPORTEDFACTORVALUE:
  1544. SNAPSHOT_SAY(("D3DERR_UNSUPPORTEDFACTORVALUE\n"));
  1545. break;
  1546. case D3DERR_UNSUPPORTEDTEXTUREFILTER:
  1547. SNAPSHOT_SAY(("D3DERR_UNSUPPORTEDTEXTUREFILTER\n"));
  1548. break;
  1549. case D3DERR_WRONGTEXTUREFORMAT:
  1550. SNAPSHOT_SAY(("D3DERR_WRONGTEXTUREFORMAT\n"));
  1551. break;
  1552. default:
  1553. SNAPSHOT_SAY(("UNKNOWN Error\n"));
  1554. break;
  1555. }
  1556. }
  1557. #endif // MESH_RENDER_SHAPSHOT_ENABLED
  1558. SNAPSHOT_SAY(("DX8 - draw %d polygons (%d vertices)\n",polygon_count,vertex_count));
  1559. if (vertex_count<3) {
  1560. min_vertex_index=0;
  1561. switch (render_state.vertex_buffer_type) {
  1562. case BUFFER_TYPE_DX8:
  1563. case BUFFER_TYPE_SORTING:
  1564. vertex_count=render_state.vertex_buffer->Get_Vertex_Count()-render_state.index_base_offset-render_state.vba_offset-min_vertex_index;
  1565. break;
  1566. case BUFFER_TYPE_DYNAMIC_DX8:
  1567. case BUFFER_TYPE_DYNAMIC_SORTING:
  1568. vertex_count=render_state.vba_count;
  1569. break;
  1570. }
  1571. }
  1572. switch (render_state.vertex_buffer_type) {
  1573. case BUFFER_TYPE_DX8:
  1574. case BUFFER_TYPE_DYNAMIC_DX8:
  1575. switch (render_state.index_buffer_type) {
  1576. case BUFFER_TYPE_DX8:
  1577. case BUFFER_TYPE_DYNAMIC_DX8:
  1578. {
  1579. DX8_RECORD_RENDER(polygon_count,vertex_count,render_state.shader);
  1580. DX8CALL(DrawIndexedPrimitive(
  1581. (D3DPRIMITIVETYPE)primitive_type,
  1582. min_vertex_index,
  1583. vertex_count,
  1584. start_index+render_state.iba_offset,
  1585. polygon_count));
  1586. }
  1587. break;
  1588. case BUFFER_TYPE_SORTING:
  1589. case BUFFER_TYPE_DYNAMIC_SORTING:
  1590. WWASSERT_PRINT(0,"VB and IB must of same type (sorting or dx8)");
  1591. break;
  1592. case BUFFER_TYPE_INVALID:
  1593. WWASSERT(0);
  1594. break;
  1595. }
  1596. break;
  1597. case BUFFER_TYPE_SORTING:
  1598. case BUFFER_TYPE_DYNAMIC_SORTING:
  1599. switch (render_state.index_buffer_type) {
  1600. case BUFFER_TYPE_DX8:
  1601. case BUFFER_TYPE_DYNAMIC_DX8:
  1602. WWASSERT_PRINT(0,"VB and IB must of same type (sorting or dx8)");
  1603. break;
  1604. case BUFFER_TYPE_SORTING:
  1605. case BUFFER_TYPE_DYNAMIC_SORTING:
  1606. Draw_Sorting_IB_VB(primitive_type,start_index,polygon_count,min_vertex_index,vertex_count);
  1607. break;
  1608. case BUFFER_TYPE_INVALID:
  1609. WWASSERT(0);
  1610. break;
  1611. }
  1612. break;
  1613. case BUFFER_TYPE_INVALID:
  1614. WWASSERT(0);
  1615. break;
  1616. }
  1617. }
  1618. // ----------------------------------------------------------------------------
  1619. //
  1620. //
  1621. //
  1622. // ----------------------------------------------------------------------------
  1623. void DX8Wrapper::Draw_Triangles(
  1624. unsigned buffer_type,
  1625. unsigned short start_index,
  1626. unsigned short polygon_count,
  1627. unsigned short min_vertex_index,
  1628. unsigned short vertex_count)
  1629. {
  1630. if (buffer_type==BUFFER_TYPE_SORTING || buffer_type==BUFFER_TYPE_DYNAMIC_SORTING) {
  1631. SortingRendererClass::Insert_Triangles(start_index,polygon_count,min_vertex_index,vertex_count);
  1632. }
  1633. else {
  1634. Draw(D3DPT_TRIANGLELIST,start_index,polygon_count,min_vertex_index,vertex_count);
  1635. }
  1636. }
  1637. // ----------------------------------------------------------------------------
  1638. //
  1639. //
  1640. //
  1641. // ----------------------------------------------------------------------------
  1642. void DX8Wrapper::Draw_Triangles(
  1643. unsigned short start_index,
  1644. unsigned short polygon_count,
  1645. unsigned short min_vertex_index,
  1646. unsigned short vertex_count)
  1647. {
  1648. Draw(D3DPT_TRIANGLELIST,start_index,polygon_count,min_vertex_index,vertex_count);
  1649. }
  1650. // ----------------------------------------------------------------------------
  1651. //
  1652. //
  1653. //
  1654. // ----------------------------------------------------------------------------
  1655. void DX8Wrapper::Draw_Strip(
  1656. unsigned short start_index,
  1657. unsigned short polygon_count,
  1658. unsigned short min_vertex_index,
  1659. unsigned short vertex_count)
  1660. {
  1661. Draw(D3DPT_TRIANGLESTRIP,start_index,polygon_count,min_vertex_index,vertex_count);
  1662. }
  1663. // ----------------------------------------------------------------------------
  1664. //
  1665. //
  1666. //
  1667. // ----------------------------------------------------------------------------
  1668. void DX8Wrapper::Apply_Render_State_Changes()
  1669. {
  1670. if (!render_state_changed) return;
  1671. if (render_state_changed&SHADER_CHANGED) {
  1672. SNAPSHOT_SAY(("DX8 - apply shader\n"));
  1673. render_state.shader.Apply();
  1674. }
  1675. unsigned mask=TEXTURE0_CHANGED;
  1676. for (unsigned i=0;i<MAX_TEXTURE_STAGES;++i,mask<<=1) {
  1677. if (render_state_changed&mask) {
  1678. SNAPSHOT_SAY(("DX8 - apply texture %d (%s)\n",i,render_state.Textures[i] ? render_state.Textures[i]->Get_Full_Path() : "NULL"));
  1679. if (render_state.Textures[i]) render_state.Textures[i]->Apply(i);
  1680. else TextureClass::Apply_Null(i);
  1681. }
  1682. else {
  1683. SNAPSHOT_SAY(("DX8 - texture %d not changed (%s)\n",i,render_state.Textures[i] ? render_state.Textures[i]->Get_Full_Path() : "NULL"));
  1684. }
  1685. }
  1686. if (render_state_changed&MATERIAL_CHANGED) {
  1687. SNAPSHOT_SAY(("DX8 - apply material\n"));
  1688. VertexMaterialClass* material=const_cast<VertexMaterialClass*>(render_state.material);
  1689. if (material) {
  1690. material->Apply();
  1691. }
  1692. else VertexMaterialClass::Apply_Null();
  1693. }
  1694. if (render_state_changed&LIGHTS_CHANGED)
  1695. {
  1696. unsigned mask=LIGHT0_CHANGED;
  1697. for (unsigned index=0;index<4;++index,mask<<=1) {
  1698. if (render_state_changed&mask) {
  1699. SNAPSHOT_SAY(("DX8 - apply light %d\n",index));
  1700. if (render_state.LightEnable[index]) {
  1701. Set_DX8_Light(index,&render_state.Lights[index]);
  1702. }
  1703. else {
  1704. Set_DX8_Light(index,NULL);
  1705. }
  1706. }
  1707. }
  1708. }
  1709. if (render_state_changed&WORLD_CHANGED) {
  1710. SNAPSHOT_SAY(("DX8 - apply world matrix\n"));
  1711. _Set_DX8_Transform(D3DTS_WORLD,render_state.world);
  1712. }
  1713. if (render_state_changed&VIEW_CHANGED) {
  1714. SNAPSHOT_SAY(("DX8 - apply view matrix\n"));
  1715. _Set_DX8_Transform(D3DTS_VIEW,render_state.view);
  1716. }
  1717. if (render_state_changed&VERTEX_BUFFER_CHANGED) {
  1718. SNAPSHOT_SAY(("DX8 - apply vb change\n"));
  1719. if (render_state.vertex_buffer) {
  1720. switch (render_state.vertex_buffer_type) {//->Type()) {
  1721. case BUFFER_TYPE_DX8:
  1722. case BUFFER_TYPE_DYNAMIC_DX8:
  1723. DX8CALL(SetStreamSource(
  1724. 0,
  1725. static_cast<DX8VertexBufferClass*>(render_state.vertex_buffer)->Get_DX8_Vertex_Buffer(),
  1726. render_state.vertex_buffer->FVF_Info().Get_FVF_Size()));
  1727. DX8_RECORD_VERTEX_BUFFER_CHANGE();
  1728. DX8CALL(SetVertexShader(render_state.vertex_buffer->FVF_Info().Get_FVF()));
  1729. break;
  1730. case BUFFER_TYPE_SORTING:
  1731. case BUFFER_TYPE_DYNAMIC_SORTING:
  1732. break;
  1733. default:
  1734. WWASSERT(0);
  1735. }
  1736. } else {
  1737. DX8CALL(SetStreamSource(0,NULL,0));
  1738. DX8_RECORD_VERTEX_BUFFER_CHANGE();
  1739. }
  1740. }
  1741. if (render_state_changed&INDEX_BUFFER_CHANGED) {
  1742. SNAPSHOT_SAY(("DX8 - apply ib change\n"));
  1743. if (render_state.index_buffer) {
  1744. switch (render_state.index_buffer_type) {//->Type()) {
  1745. case BUFFER_TYPE_DX8:
  1746. case BUFFER_TYPE_DYNAMIC_DX8:
  1747. DX8CALL(SetIndices(
  1748. static_cast<DX8IndexBufferClass*>(render_state.index_buffer)->Get_DX8_Index_Buffer(),
  1749. render_state.index_base_offset+render_state.vba_offset));
  1750. DX8_RECORD_INDEX_BUFFER_CHANGE();
  1751. break;
  1752. case BUFFER_TYPE_SORTING:
  1753. case BUFFER_TYPE_DYNAMIC_SORTING:
  1754. break;
  1755. default:
  1756. WWASSERT(0);
  1757. }
  1758. }
  1759. else {
  1760. DX8CALL(SetIndices(
  1761. NULL,
  1762. 0));
  1763. DX8_RECORD_INDEX_BUFFER_CHANGE();
  1764. }
  1765. }
  1766. render_state_changed&=((unsigned)WORLD_IDENTITY|(unsigned)VIEW_IDENTITY);
  1767. }
  1768. IDirect3DTexture8 * DX8Wrapper::_Create_DX8_Texture(
  1769. unsigned int width,
  1770. unsigned int height,
  1771. WW3DFormat format,
  1772. TextureClass::MipCountType mip_level_count,
  1773. D3DPOOL pool,
  1774. bool rendertarget)
  1775. {
  1776. DX8_THREAD_ASSERT();
  1777. DX8_Assert();
  1778. IDirect3DTexture8 *texture = NULL;
  1779. // Paletted textures not supported!
  1780. WWASSERT(format!=D3DFMT_P8);
  1781. // NOTE: If 'format' is not supported as a texture format, this function will find the closest
  1782. // format that is supported and use that instead.
  1783. // Render target may return NOTAVAILABLE, in
  1784. // which case we return NULL.
  1785. if (rendertarget) {
  1786. unsigned ret=D3DXCreateTexture(
  1787. DX8Wrapper::_Get_D3D_Device8(),
  1788. width,
  1789. height,
  1790. mip_level_count,
  1791. D3DUSAGE_RENDERTARGET,
  1792. WW3DFormat_To_D3DFormat(format),
  1793. pool,
  1794. &texture);
  1795. if (ret==D3DERR_NOTAVAILABLE) {
  1796. Non_Fatal_Log_DX8_ErrorCode(ret,__FILE__,__LINE__);
  1797. return NULL;
  1798. }
  1799. // If ran out of texture ram, try invalidating some textures and mesh cache.
  1800. if (ret==D3DERR_OUTOFVIDEOMEMORY) {
  1801. WWDEBUG_SAY(("Error: Out of memory while creating render target. Trying to release assets...\n"));
  1802. // Free all textures that haven't been used in the last 5 seconds
  1803. TextureClass::Invalidate_Old_Unused_Textures(5000);
  1804. // Invalidate the mesh cache
  1805. WW3D::_Invalidate_Mesh_Cache();
  1806. ret=D3DXCreateTexture(
  1807. DX8Wrapper::_Get_D3D_Device8(),
  1808. width,
  1809. height,
  1810. mip_level_count,
  1811. D3DUSAGE_RENDERTARGET,
  1812. WW3DFormat_To_D3DFormat(format),
  1813. pool,
  1814. &texture);
  1815. if (SUCCEEDED(ret)) {
  1816. WWDEBUG_SAY(("...Render target creation succesful.\n"));
  1817. }
  1818. else {
  1819. WWDEBUG_SAY(("...Render target creation failed.\n"));
  1820. }
  1821. if (ret==D3DERR_OUTOFVIDEOMEMORY) {
  1822. Non_Fatal_Log_DX8_ErrorCode(ret,__FILE__,__LINE__);
  1823. return NULL;
  1824. }
  1825. }
  1826. DX8_ErrorCode(ret);
  1827. // Just return the texture, no reduction
  1828. // allowed for render targets.
  1829. return texture;
  1830. }
  1831. // We should never run out of video memory when allocating a non-rendertarget texture.
  1832. // However, it seems to happen sometimes when there are a lot of textures in memory and so
  1833. // if it happens we'll release assets and try again (anything is better than crashing).
  1834. unsigned ret=D3DXCreateTexture(
  1835. DX8Wrapper::_Get_D3D_Device8(),
  1836. width,
  1837. height,
  1838. mip_level_count,
  1839. 0,
  1840. WW3DFormat_To_D3DFormat(format),
  1841. pool,
  1842. &texture);
  1843. // If ran out of texture ram, try invalidating some textures and mesh cache.
  1844. if (ret==D3DERR_OUTOFVIDEOMEMORY) {
  1845. WWDEBUG_SAY(("Error: Out of memory while creating texture. Trying to release assets...\n"));
  1846. // Free all textures that haven't been used in the last 5 seconds
  1847. TextureClass::Invalidate_Old_Unused_Textures(5000);
  1848. // Invalidate the mesh cache
  1849. WW3D::_Invalidate_Mesh_Cache();
  1850. ret=D3DXCreateTexture(
  1851. DX8Wrapper::_Get_D3D_Device8(),
  1852. width,
  1853. height,
  1854. mip_level_count,
  1855. 0,
  1856. WW3DFormat_To_D3DFormat(format),
  1857. pool,
  1858. &texture);
  1859. if (SUCCEEDED(ret)) {
  1860. WWDEBUG_SAY(("...Texture creation succesful.\n"));
  1861. }
  1862. else {
  1863. StringClass format_name(0,true);
  1864. Get_WW3D_Format_Name(format, format_name);
  1865. WWDEBUG_SAY(("...Texture creation failed. (%d x %d, format: %s, mips: %d\n",width,height,format_name,mip_level_count));
  1866. }
  1867. }
  1868. DX8_ErrorCode(ret);
  1869. return texture;
  1870. }
  1871. IDirect3DTexture8 * DX8Wrapper::_Create_DX8_Texture(
  1872. const char *filename,
  1873. TextureClass::MipCountType mip_level_count)
  1874. {
  1875. DX8_THREAD_ASSERT();
  1876. DX8_Assert();
  1877. IDirect3DTexture8 *texture = NULL;
  1878. // NOTE: If the original image format is not supported as a texture format, it will
  1879. // automatically be converted to an appropriate format.
  1880. // NOTE: It is possible to get the size and format of the original image file from this
  1881. // function as well, so if we later want to second-guess D3DX's format conversion decisions
  1882. // we can do so after this function is called..
  1883. unsigned result = D3DXCreateTextureFromFileExA(
  1884. _Get_D3D_Device8(),
  1885. filename,
  1886. D3DX_DEFAULT,
  1887. D3DX_DEFAULT,
  1888. mip_level_count,//create_mipmaps ? 0 : 1,
  1889. 0,
  1890. D3DFMT_UNKNOWN,
  1891. D3DPOOL_MANAGED,
  1892. D3DX_FILTER_BOX,
  1893. D3DX_FILTER_BOX,
  1894. 0,
  1895. NULL,
  1896. NULL,
  1897. &texture);
  1898. if (result != D3D_OK) {
  1899. return MissingTexture::_Get_Missing_Texture();
  1900. }
  1901. // Make sure texture wasn't paletted!
  1902. D3DSURFACE_DESC desc;
  1903. texture->GetLevelDesc(0,&desc);
  1904. if (desc.Format==D3DFMT_P8) {
  1905. texture->Release();
  1906. return MissingTexture::_Get_Missing_Texture();
  1907. }
  1908. return texture;
  1909. }
  1910. IDirect3DTexture8 * DX8Wrapper::_Create_DX8_Texture(
  1911. IDirect3DSurface8 *surface,
  1912. TextureClass::MipCountType mip_level_count)
  1913. {
  1914. DX8_THREAD_ASSERT();
  1915. DX8_Assert();
  1916. IDirect3DTexture8 *texture = NULL;
  1917. D3DSURFACE_DESC surface_desc;
  1918. ::ZeroMemory(&surface_desc, sizeof(D3DSURFACE_DESC));
  1919. surface->GetDesc(&surface_desc);
  1920. // This function will create a texture with a different (but similar) format if the surface is
  1921. // not in a supported texture format.
  1922. WW3DFormat format=D3DFormat_To_WW3DFormat(surface_desc.Format);
  1923. texture = _Create_DX8_Texture(surface_desc.Width, surface_desc.Height, format, mip_level_count);
  1924. // Copy the surface to the texture
  1925. IDirect3DSurface8 *tex_surface = NULL;
  1926. texture->GetSurfaceLevel(0, &tex_surface);
  1927. DX8_ErrorCode(D3DXLoadSurfaceFromSurface(tex_surface, NULL, NULL, surface, NULL, NULL, D3DX_FILTER_BOX, 0));
  1928. tex_surface->Release();
  1929. // Create mipmaps if needed
  1930. if (mip_level_count!=TextureClass::MIP_LEVELS_1) {
  1931. DX8_ErrorCode(D3DXFilterTexture(texture, NULL, 0, D3DX_FILTER_BOX));
  1932. }
  1933. return texture;
  1934. }
  1935. IDirect3DSurface8 * DX8Wrapper::_Create_DX8_Surface(unsigned int width, unsigned int height, WW3DFormat format)
  1936. {
  1937. DX8_THREAD_ASSERT();
  1938. DX8_Assert();
  1939. IDirect3DSurface8 *surface = NULL;
  1940. // Paletted surfaces not supported!
  1941. WWASSERT(format!=D3DFMT_P8);
  1942. DX8CALL(CreateImageSurface(width, height, WW3DFormat_To_D3DFormat(format), &surface));
  1943. return surface;
  1944. }
  1945. IDirect3DSurface8 * DX8Wrapper::_Create_DX8_Surface(const char *filename_)
  1946. {
  1947. DX8_THREAD_ASSERT();
  1948. DX8_Assert();
  1949. // Note: Since there is no "D3DXCreateSurfaceFromFile" and no "GetSurfaceInfoFromFile" (the
  1950. // latter is supposed to be added to D3DX in a future version), we create a texture from the
  1951. // file (w/o mipmaps), check that its surface is equal to the original file data (which it
  1952. // will not be if the file is not in a texture-supported format or size). If so, copy its
  1953. // surface (we might be able to just get its surface and add a ref to it but I'm not sure so
  1954. // I'm not going to risk it) and release the texture. If not, create a surface according to
  1955. // the file data and use D3DXLoadSurfaceFromFile. This is a horrible hack, but it saves us
  1956. // having to write file loaders. Will fix this when D3DX provides us with the right functions.
  1957. // Create a surface the size of the file image data
  1958. IDirect3DSurface8 *surface = NULL;
  1959. {
  1960. file_auto_ptr myfile(_TheFileFactory,filename_);
  1961. // If file not found, create a surface with missing texture in it
  1962. if (!myfile->Is_Available()) {
  1963. return MissingTexture::_Create_Missing_Surface();
  1964. }
  1965. }
  1966. StringClass filename_string(filename_,true);
  1967. surface=TextureLoader::Load_Surface_Immediate(
  1968. filename_string,
  1969. WW3D_FORMAT_UNKNOWN,
  1970. true);
  1971. return surface;
  1972. }
  1973. /***********************************************************************************************
  1974. * DX8Wrapper::_Update_Texture -- Copies a texture from system memory to video memory *
  1975. * *
  1976. * *
  1977. * *
  1978. * *
  1979. * INPUT: *
  1980. * *
  1981. * OUTPUT: *
  1982. * *
  1983. * WARNINGS: *
  1984. * *
  1985. * HISTORY: *
  1986. * 4/26/2001 hy : Created. *
  1987. *=============================================================================================*/
  1988. void DX8Wrapper::_Update_Texture(TextureClass *system, TextureClass *video)
  1989. {
  1990. WWASSERT(system);
  1991. WWASSERT(video);
  1992. WWASSERT(system->Pool==TextureClass::POOL_SYSTEMMEM);
  1993. WWASSERT(video->Pool==TextureClass::POOL_DEFAULT);
  1994. DX8CALL(UpdateTexture(system->D3DTexture,video->D3DTexture));
  1995. }
  1996. void DX8Wrapper::Compute_Caps(WW3DFormat display_format)
  1997. {
  1998. DX8_THREAD_ASSERT();
  1999. DX8_Assert();
  2000. delete CurrentCaps;
  2001. CurrentCaps=new DX8Caps(_Get_D3D8(),D3DDevice,display_format,Get_Current_Adapter_Identifier());
  2002. }
  2003. void DX8Wrapper::Set_Light(unsigned index,const LightClass &light)
  2004. {
  2005. D3DLIGHT8 dlight;
  2006. Vector3 temp;
  2007. memset(&dlight,0,sizeof(D3DLIGHT8));
  2008. switch (light.Get_Type())
  2009. {
  2010. case LightClass::POINT:
  2011. {
  2012. dlight.Type=D3DLIGHT_POINT;
  2013. }
  2014. break;
  2015. case LightClass::DIRECTIONAL:
  2016. {
  2017. dlight.Type=D3DLIGHT_DIRECTIONAL;
  2018. }
  2019. break;
  2020. case LightClass::SPOT:
  2021. {
  2022. dlight.Type=D3DLIGHT_SPOT;
  2023. }
  2024. break;
  2025. }
  2026. light.Get_Diffuse(&temp);
  2027. temp*=light.Get_Intensity();
  2028. dlight.Diffuse.r=temp.X;
  2029. dlight.Diffuse.g=temp.Y;
  2030. dlight.Diffuse.b=temp.Z;
  2031. dlight.Diffuse.a=1.0f;
  2032. light.Get_Specular(&temp);
  2033. temp*=light.Get_Intensity();
  2034. dlight.Specular.r=temp.X;
  2035. dlight.Specular.g=temp.Y;
  2036. dlight.Specular.b=temp.Z;
  2037. dlight.Specular.a=1.0f;
  2038. light.Get_Ambient(&temp);
  2039. temp*=light.Get_Intensity();
  2040. dlight.Ambient.r=temp.X;
  2041. dlight.Ambient.g=temp.Y;
  2042. dlight.Ambient.b=temp.Z;
  2043. dlight.Ambient.a=1.0f;
  2044. temp=light.Get_Position();
  2045. dlight.Position=*(D3DVECTOR*) &temp;
  2046. light.Get_Spot_Direction(temp);
  2047. dlight.Direction=*(D3DVECTOR*) &temp;
  2048. dlight.Range=light.Get_Attenuation_Range();
  2049. dlight.Falloff=light.Get_Spot_Exponent();
  2050. dlight.Theta=light.Get_Spot_Angle();
  2051. dlight.Phi=light.Get_Spot_Angle();
  2052. // Inverse linear light 1/(1+D)
  2053. double a,b;
  2054. light.Get_Far_Attenuation_Range(a,b);
  2055. dlight.Attenuation0=1.0f;
  2056. if (fabs(a-b)<1e-5)
  2057. // if the attenuation range is too small assume uniform with cutoff
  2058. dlight.Attenuation1=0.0f;
  2059. else
  2060. // this will cause the light to drop to half intensity at the first far attenuation
  2061. dlight.Attenuation1=(float) 1.0/a;
  2062. dlight.Attenuation2=0.0f;
  2063. Set_Light(index,&dlight);
  2064. }
  2065. // ----------------------------------------------------------------------------
  2066. //
  2067. // Set the light environment. This is a lighting model which used up to four
  2068. // directional lights to produce the lighting.
  2069. //
  2070. // ----------------------------------------------------------------------------
  2071. void DX8Wrapper::Set_Light_Environment(LightEnvironmentClass* light_env)
  2072. {
  2073. if (light_env) {
  2074. int light_count = light_env->Get_Light_Count();
  2075. Set_DX8_Render_State(D3DRS_AMBIENT,Convert_Color(light_env->Get_Equivalent_Ambient(),0.0f));
  2076. D3DLIGHT8 light;
  2077. ::ZeroMemory(&light, sizeof(D3DLIGHT8));
  2078. light.Type=D3DLIGHT_DIRECTIONAL;
  2079. for (int l=0;l<light_count;++l) {
  2080. (Vector3&)light.Diffuse=light_env->Get_Light_Diffuse(l);
  2081. Vector3 dir=-light_env->Get_Light_Direction(l);
  2082. light.Direction=(const D3DVECTOR&)(dir);
  2083. Set_Light(l,&light);
  2084. }
  2085. for (;l<4;++l) {
  2086. Set_Light(l,NULL);
  2087. }
  2088. }
  2089. /* else {
  2090. for (int l=0;l<4;++l) {
  2091. Set_Light(l,NULL);
  2092. }
  2093. }
  2094. */
  2095. }
  2096. IDirect3DSurface8 * DX8Wrapper::_Get_DX8_Front_Buffer()
  2097. {
  2098. DX8_THREAD_ASSERT();
  2099. D3DDISPLAYMODE mode;
  2100. DX8CALL(GetDisplayMode(&mode));
  2101. IDirect3DSurface8 * fb=NULL;
  2102. DX8CALL(CreateImageSurface(mode.Width,mode.Height,D3DFMT_A8R8G8B8,&fb));
  2103. DX8CALL(GetFrontBuffer(fb));
  2104. return fb;
  2105. }
  2106. SurfaceClass * DX8Wrapper::_Get_DX8_Back_Buffer(unsigned int num)
  2107. {
  2108. DX8_THREAD_ASSERT();
  2109. IDirect3DSurface8 * bb;
  2110. SurfaceClass *surf=NULL;
  2111. DX8CALL(GetBackBuffer(num,D3DBACKBUFFER_TYPE_MONO,&bb));
  2112. if (bb)
  2113. {
  2114. surf=NEW_REF(SurfaceClass,(bb));
  2115. bb->Release();
  2116. }
  2117. return surf;
  2118. }
  2119. TextureClass *
  2120. DX8Wrapper::Create_Render_Target (int width, int height, WW3DFormat format)
  2121. {
  2122. DX8_THREAD_ASSERT();
  2123. DX8_Assert();
  2124. number_of_DX8_calls++;
  2125. // Use the current display format if format isn't specified
  2126. if (format==WW3D_FORMAT_UNKNOWN) {
  2127. D3DDISPLAYMODE mode;
  2128. DX8CALL(GetDisplayMode(&mode));
  2129. format=D3DFormat_To_WW3DFormat(mode.Format);
  2130. }
  2131. // If render target format isn't supported return NULL
  2132. if (!Get_Current_Caps()->Support_Render_To_Texture_Format(format)) {
  2133. WWDEBUG_SAY(("DX8Wrapper - Render target format is not supported\r\n"));
  2134. return NULL;
  2135. }
  2136. //
  2137. // Note: We're going to force the width and height to be powers of two and equal
  2138. //
  2139. const D3DCAPS8& dx8caps=Get_Current_Caps()->Get_DX8_Caps();
  2140. float poweroftwosize = width;
  2141. if (height > 0 && height < width) {
  2142. poweroftwosize = height;
  2143. }
  2144. poweroftwosize = ::Find_POT (poweroftwosize);
  2145. if (poweroftwosize>dx8caps.MaxTextureWidth) {
  2146. poweroftwosize=dx8caps.MaxTextureWidth;
  2147. }
  2148. if (poweroftwosize>dx8caps.MaxTextureHeight) {
  2149. poweroftwosize=dx8caps.MaxTextureHeight;
  2150. }
  2151. width = height = poweroftwosize;
  2152. //
  2153. // Attempt to create the render target
  2154. //
  2155. TextureClass * tex = NEW_REF(TextureClass,(width,height,format,TextureClass::MIP_LEVELS_1,TextureClass::POOL_DEFAULT,true));
  2156. // 3dfx drivers are lying in the CheckDeviceFormat call and claiming
  2157. // that they support render targets!
  2158. if (tex->Peek_DX8_Texture() == NULL) {
  2159. WWDEBUG_SAY(("DX8Wrapper - Render target creation failed!\r\n"));
  2160. REF_PTR_RELEASE(tex);
  2161. }
  2162. return tex;
  2163. }
  2164. void
  2165. DX8Wrapper::Set_Render_Target (TextureClass * texture)
  2166. {
  2167. WWASSERT(texture != NULL);
  2168. IDirect3DSurface8 * d3d_surf = texture->Get_D3D_Surface_Level();
  2169. WWASSERT(d3d_surf != NULL);
  2170. Set_Render_Target(d3d_surf);
  2171. d3d_surf->Release();
  2172. IsRenderToTexture = true;
  2173. }
  2174. void
  2175. DX8Wrapper::Set_Render_Target(IDirect3DSwapChain8 *swap_chain)
  2176. {
  2177. DX8_THREAD_ASSERT();
  2178. WWASSERT (swap_chain != NULL);
  2179. //
  2180. // Get the back buffer for the swap chain
  2181. //
  2182. LPDIRECT3DSURFACE8 render_target = NULL;
  2183. swap_chain->GetBackBuffer (0, D3DBACKBUFFER_TYPE_MONO, &render_target);
  2184. //
  2185. // Set this back buffer as the render targer
  2186. //
  2187. Set_Render_Target (render_target, true);
  2188. //
  2189. // Release our hold on the back buffer
  2190. //
  2191. if (render_target != NULL) {
  2192. render_target->Release ();
  2193. render_target = NULL;
  2194. }
  2195. IsRenderToTexture = false;
  2196. return ;
  2197. }
  2198. void
  2199. DX8Wrapper::Set_Render_Target(IDirect3DSurface8 *render_target, bool use_default_depth_buffer)
  2200. {
  2201. DX8_THREAD_ASSERT();
  2202. DX8_Assert();
  2203. //
  2204. // Should we restore the default render target set a new one?
  2205. //
  2206. if (render_target == NULL || render_target == DefaultRenderTarget) {
  2207. // If there is currently a custom render target, default must NOT be NULL.
  2208. if (CurrentRenderTarget) {
  2209. WWASSERT(DefaultRenderTarget!=NULL);
  2210. }
  2211. //
  2212. // Restore the default render target
  2213. //
  2214. if (DefaultRenderTarget != NULL) {
  2215. DX8CALL(SetRenderTarget (DefaultRenderTarget, DefaultDepthBuffer));
  2216. DefaultRenderTarget->Release ();
  2217. DefaultRenderTarget = NULL;
  2218. if (DefaultDepthBuffer) {
  2219. DefaultDepthBuffer->Release ();
  2220. DefaultDepthBuffer = NULL;
  2221. }
  2222. }
  2223. //
  2224. // Release our hold on the "current" render target
  2225. //
  2226. if (CurrentRenderTarget != NULL) {
  2227. CurrentRenderTarget->Release ();
  2228. CurrentRenderTarget = NULL;
  2229. }
  2230. } else if (render_target != CurrentRenderTarget) {
  2231. WWASSERT(DefaultRenderTarget==NULL);
  2232. //
  2233. // We'll need the depth buffer later...
  2234. //
  2235. if (DefaultDepthBuffer == NULL) {
  2236. // IDirect3DSurface8 *depth_buffer = NULL;
  2237. DX8CALL(GetDepthStencilSurface (&DefaultDepthBuffer));
  2238. }
  2239. //
  2240. // Get a pointer to the default render target (if necessary)
  2241. //
  2242. if (DefaultRenderTarget == NULL) {
  2243. DX8CALL(GetRenderTarget (&DefaultRenderTarget));
  2244. }
  2245. //
  2246. // Release our hold on the old "current" render target
  2247. //
  2248. if (CurrentRenderTarget != NULL) {
  2249. CurrentRenderTarget->Release ();
  2250. CurrentRenderTarget = NULL;
  2251. }
  2252. //
  2253. // Keep a copy of the current render target (for housekeeping)
  2254. //
  2255. CurrentRenderTarget = render_target;
  2256. WWASSERT (CurrentRenderTarget != NULL);
  2257. if (CurrentRenderTarget != NULL) {
  2258. CurrentRenderTarget->AddRef ();
  2259. //
  2260. // Switch render targets
  2261. //
  2262. if (use_default_depth_buffer) {
  2263. DX8CALL(SetRenderTarget (CurrentRenderTarget, DefaultDepthBuffer));
  2264. } else {
  2265. DX8CALL(SetRenderTarget (CurrentRenderTarget, NULL));
  2266. }
  2267. }
  2268. }
  2269. //
  2270. // Free our hold on the depth buffer
  2271. //
  2272. // if (depth_buffer != NULL) {
  2273. // depth_buffer->Release ();
  2274. // depth_buffer = NULL;
  2275. // }
  2276. IsRenderToTexture = false;
  2277. return ;
  2278. }
  2279. IDirect3DSwapChain8 *
  2280. DX8Wrapper::Create_Additional_Swap_Chain (HWND render_window)
  2281. {
  2282. DX8_Assert();
  2283. //
  2284. // Configure the presentation parameters for a windowed render target
  2285. //
  2286. D3DPRESENT_PARAMETERS params = { 0 };
  2287. params.BackBufferFormat = _PresentParameters.BackBufferFormat;
  2288. params.BackBufferCount = 1;
  2289. params.MultiSampleType = D3DMULTISAMPLE_NONE;
  2290. params.SwapEffect = D3DSWAPEFFECT_COPY_VSYNC;
  2291. params.hDeviceWindow = render_window;
  2292. params.Windowed = TRUE;
  2293. params.EnableAutoDepthStencil = TRUE;
  2294. params.AutoDepthStencilFormat = _PresentParameters.AutoDepthStencilFormat;
  2295. params.Flags = 0;
  2296. params.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
  2297. params.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
  2298. //
  2299. // Create the swap chain
  2300. //
  2301. IDirect3DSwapChain8 *swap_chain = NULL;
  2302. DX8CALL(CreateAdditionalSwapChain(&params, &swap_chain));
  2303. return swap_chain;
  2304. }
  2305. void DX8Wrapper::Flush_DX8_Resource_Manager(unsigned int bytes)
  2306. {
  2307. DX8_Assert();
  2308. DX8CALL(ResourceManagerDiscardBytes(bytes));
  2309. }
  2310. unsigned int DX8Wrapper::Get_Free_Texture_RAM()
  2311. {
  2312. DX8_Assert();
  2313. number_of_DX8_calls++;
  2314. return DX8Wrapper::_Get_D3D_Device8()->GetAvailableTextureMem();
  2315. }
  2316. // Converts a linear gamma ramp to one that is controlled by:
  2317. // Gamma - controls the curvature of the middle of the curve
  2318. // Bright - controls the minimum value of the curve
  2319. // Contrast - controls the difference between the maximum and the minimum of the curve
  2320. void DX8Wrapper::Set_Gamma(float gamma,float bright,float contrast,bool calibrate,bool uselimit)
  2321. {
  2322. gamma=Bound(gamma,0.6f,6.0f);
  2323. bright=Bound(bright,-0.5f,0.5f);
  2324. contrast=Bound(contrast,0.5f,2.0f);
  2325. float oo_gamma=1.0f/gamma;
  2326. DX8_Assert();
  2327. number_of_DX8_calls++;
  2328. DWORD flag=(calibrate?D3DSGR_CALIBRATE:D3DSGR_NO_CALIBRATION);
  2329. D3DGAMMARAMP ramp;
  2330. float limit;
  2331. // IML: I'm not really sure what the intent of the 'limit' variable is. It does not produce useful results for my purposes.
  2332. if (uselimit) {
  2333. limit=(contrast-1)/2*contrast;
  2334. } else {
  2335. limit = 0.0f;
  2336. }
  2337. // HY - arrived at this equation after much trial and error.
  2338. for (int i=0; i<256; i++) {
  2339. float in,out;
  2340. in=i/256.0f;
  2341. float x=in-limit;
  2342. x=Bound(x,0.0f,1.0f);
  2343. x=powf(x,oo_gamma);
  2344. out=contrast*x+bright;
  2345. out=Bound(out,0.0f,1.0f);
  2346. ramp.red[i]=(WORD) (out*65535);
  2347. ramp.green[i]=(WORD) (out*65535);
  2348. ramp.blue[i]=(WORD) (out*65535);
  2349. }
  2350. if (Get_Current_Caps()->Support_Gamma()) {
  2351. DX8Wrapper::_Get_D3D_Device8()->SetGammaRamp(flag,&ramp);
  2352. } else {
  2353. HWND hwnd = GetDesktopWindow();
  2354. HDC hdc = GetDC(hwnd);
  2355. if (hdc)
  2356. {
  2357. SetDeviceGammaRamp (hdc, &ramp);
  2358. ReleaseDC (hwnd, hdc);
  2359. }
  2360. }
  2361. }
  2362. const char* DX8Wrapper::Get_DX8_Render_State_Name(D3DRENDERSTATETYPE state)
  2363. {
  2364. switch (state) {
  2365. case D3DRS_ZENABLE : return "D3DRS_ZENABLE";
  2366. case D3DRS_FILLMODE : return "D3DRS_FILLMODE";
  2367. case D3DRS_SHADEMODE : return "D3DRS_SHADEMODE";
  2368. case D3DRS_LINEPATTERN : return "D3DRS_LINEPATTERN";
  2369. case D3DRS_ZWRITEENABLE : return "D3DRS_ZWRITEENABLE";
  2370. case D3DRS_ALPHATESTENABLE : return "D3DRS_ALPHATESTENABLE";
  2371. case D3DRS_LASTPIXEL : return "D3DRS_LASTPIXEL";
  2372. case D3DRS_SRCBLEND : return "D3DRS_SRCBLEND";
  2373. case D3DRS_DESTBLEND : return "D3DRS_DESTBLEND";
  2374. case D3DRS_CULLMODE : return "D3DRS_CULLMODE";
  2375. case D3DRS_ZFUNC : return "D3DRS_ZFUNC";
  2376. case D3DRS_ALPHAREF : return "D3DRS_ALPHAREF";
  2377. case D3DRS_ALPHAFUNC : return "D3DRS_ALPHAFUNC";
  2378. case D3DRS_DITHERENABLE : return "D3DRS_DITHERENABLE";
  2379. case D3DRS_ALPHABLENDENABLE : return "D3DRS_ALPHABLENDENABLE";
  2380. case D3DRS_FOGENABLE : return "D3DRS_FOGENABLE";
  2381. case D3DRS_SPECULARENABLE : return "D3DRS_SPECULARENABLE";
  2382. case D3DRS_ZVISIBLE : return "D3DRS_ZVISIBLE";
  2383. case D3DRS_FOGCOLOR : return "D3DRS_FOGCOLOR";
  2384. case D3DRS_FOGTABLEMODE : return "D3DRS_FOGTABLEMODE";
  2385. case D3DRS_FOGSTART : return "D3DRS_FOGSTART";
  2386. case D3DRS_FOGEND : return "D3DRS_FOGEND";
  2387. case D3DRS_FOGDENSITY : return "D3DRS_FOGDENSITY";
  2388. case D3DRS_EDGEANTIALIAS : return "D3DRS_EDGEANTIALIAS";
  2389. case D3DRS_ZBIAS : return "D3DRS_ZBIAS";
  2390. case D3DRS_RANGEFOGENABLE : return "D3DRS_RANGEFOGENABLE";
  2391. case D3DRS_STENCILENABLE : return "D3DRS_STENCILENABLE";
  2392. case D3DRS_STENCILFAIL : return "D3DRS_STENCILFAIL";
  2393. case D3DRS_STENCILZFAIL : return "D3DRS_STENCILZFAIL";
  2394. case D3DRS_STENCILPASS : return "D3DRS_STENCILPASS";
  2395. case D3DRS_STENCILFUNC : return "D3DRS_STENCILFUNC";
  2396. case D3DRS_STENCILREF : return "D3DRS_STENCILREF";
  2397. case D3DRS_STENCILMASK : return "D3DRS_STENCILMASK";
  2398. case D3DRS_STENCILWRITEMASK : return "D3DRS_STENCILWRITEMASK";
  2399. case D3DRS_TEXTUREFACTOR : return "D3DRS_TEXTUREFACTOR";
  2400. case D3DRS_WRAP0 : return "D3DRS_WRAP0";
  2401. case D3DRS_WRAP1 : return "D3DRS_WRAP1";
  2402. case D3DRS_WRAP2 : return "D3DRS_WRAP2";
  2403. case D3DRS_WRAP3 : return "D3DRS_WRAP3";
  2404. case D3DRS_WRAP4 : return "D3DRS_WRAP4";
  2405. case D3DRS_WRAP5 : return "D3DRS_WRAP5";
  2406. case D3DRS_WRAP6 : return "D3DRS_WRAP6";
  2407. case D3DRS_WRAP7 : return "D3DRS_WRAP7";
  2408. case D3DRS_CLIPPING : return "D3DRS_CLIPPING";
  2409. case D3DRS_LIGHTING : return "D3DRS_LIGHTING";
  2410. case D3DRS_AMBIENT : return "D3DRS_AMBIENT";
  2411. case D3DRS_FOGVERTEXMODE : return "D3DRS_FOGVERTEXMODE";
  2412. case D3DRS_COLORVERTEX : return "D3DRS_COLORVERTEX";
  2413. case D3DRS_LOCALVIEWER : return "D3DRS_LOCALVIEWER";
  2414. case D3DRS_NORMALIZENORMALS : return "D3DRS_NORMALIZENORMALS";
  2415. case D3DRS_DIFFUSEMATERIALSOURCE : return "D3DRS_DIFFUSEMATERIALSOURCE";
  2416. case D3DRS_SPECULARMATERIALSOURCE : return "D3DRS_SPECULARMATERIALSOURCE";
  2417. case D3DRS_AMBIENTMATERIALSOURCE : return "D3DRS_AMBIENTMATERIALSOURCE";
  2418. case D3DRS_EMISSIVEMATERIALSOURCE : return "D3DRS_EMISSIVEMATERIALSOURCE";
  2419. case D3DRS_VERTEXBLEND : return "D3DRS_VERTEXBLEND";
  2420. case D3DRS_CLIPPLANEENABLE : return "D3DRS_CLIPPLANEENABLE";
  2421. case D3DRS_SOFTWAREVERTEXPROCESSING : return "D3DRS_SOFTWAREVERTEXPROCESSING";
  2422. case D3DRS_POINTSIZE : return "D3DRS_POINTSIZE";
  2423. case D3DRS_POINTSIZE_MIN : return "D3DRS_POINTSIZE_MIN";
  2424. case D3DRS_POINTSPRITEENABLE : return "D3DRS_POINTSPRITEENABLE";
  2425. case D3DRS_POINTSCALEENABLE : return "D3DRS_POINTSCALEENABLE";
  2426. case D3DRS_POINTSCALE_A : return "D3DRS_POINTSCALE_A";
  2427. case D3DRS_POINTSCALE_B : return "D3DRS_POINTSCALE_B";
  2428. case D3DRS_POINTSCALE_C : return "D3DRS_POINTSCALE_C";
  2429. case D3DRS_MULTISAMPLEANTIALIAS : return "D3DRS_MULTISAMPLEANTIALIAS";
  2430. case D3DRS_MULTISAMPLEMASK : return "D3DRS_MULTISAMPLEMASK";
  2431. case D3DRS_PATCHEDGESTYLE : return "D3DRS_PATCHEDGESTYLE";
  2432. case D3DRS_PATCHSEGMENTS : return "D3DRS_PATCHSEGMENTS";
  2433. case D3DRS_DEBUGMONITORTOKEN : return "D3DRS_DEBUGMONITORTOKEN";
  2434. case D3DRS_POINTSIZE_MAX : return "D3DRS_POINTSIZE_MAX";
  2435. case D3DRS_INDEXEDVERTEXBLENDENABLE : return "D3DRS_INDEXEDVERTEXBLENDENABLE";
  2436. case D3DRS_COLORWRITEENABLE : return "D3DRS_COLORWRITEENABLE";
  2437. case D3DRS_TWEENFACTOR : return "D3DRS_TWEENFACTOR";
  2438. case D3DRS_BLENDOP : return "D3DRS_BLENDOP";
  2439. // case D3DRS_POSITIONORDER : return "D3DRS_POSITIONORDER";
  2440. // case D3DRS_NORMALORDER : return "D3DRS_NORMALORDER";
  2441. default : return "UNKNOWN";
  2442. }
  2443. }
  2444. const char* DX8Wrapper::Get_DX8_Texture_Stage_State_Name(D3DTEXTURESTAGESTATETYPE state)
  2445. {
  2446. switch (state) {
  2447. case D3DTSS_COLOROP : return "D3DTSS_COLOROP";
  2448. case D3DTSS_COLORARG1 : return "D3DTSS_COLORARG1";
  2449. case D3DTSS_COLORARG2 : return "D3DTSS_COLORARG2";
  2450. case D3DTSS_ALPHAOP : return "D3DTSS_ALPHAOP";
  2451. case D3DTSS_ALPHAARG1 : return "D3DTSS_ALPHAARG1";
  2452. case D3DTSS_ALPHAARG2 : return "D3DTSS_ALPHAARG2";
  2453. case D3DTSS_BUMPENVMAT00 : return "D3DTSS_BUMPENVMAT00";
  2454. case D3DTSS_BUMPENVMAT01 : return "D3DTSS_BUMPENVMAT01";
  2455. case D3DTSS_BUMPENVMAT10 : return "D3DTSS_BUMPENVMAT10";
  2456. case D3DTSS_BUMPENVMAT11 : return "D3DTSS_BUMPENVMAT11";
  2457. case D3DTSS_TEXCOORDINDEX : return "D3DTSS_TEXCOORDINDEX";
  2458. case D3DTSS_ADDRESSU : return "D3DTSS_ADDRESSU";
  2459. case D3DTSS_ADDRESSV : return "D3DTSS_ADDRESSV";
  2460. case D3DTSS_BORDERCOLOR : return "D3DTSS_BORDERCOLOR";
  2461. case D3DTSS_MAGFILTER : return "D3DTSS_MAGFILTER";
  2462. case D3DTSS_MINFILTER : return "D3DTSS_MINFILTER";
  2463. case D3DTSS_MIPFILTER : return "D3DTSS_MIPFILTER";
  2464. case D3DTSS_MIPMAPLODBIAS : return "D3DTSS_MIPMAPLODBIAS";
  2465. case D3DTSS_MAXMIPLEVEL : return "D3DTSS_MAXMIPLEVEL";
  2466. case D3DTSS_MAXANISOTROPY : return "D3DTSS_MAXANISOTROPY";
  2467. case D3DTSS_BUMPENVLSCALE : return "D3DTSS_BUMPENVLSCALE";
  2468. case D3DTSS_BUMPENVLOFFSET : return "D3DTSS_BUMPENVLOFFSET";
  2469. case D3DTSS_TEXTURETRANSFORMFLAGS : return "D3DTSS_TEXTURETRANSFORMFLAGS";
  2470. case D3DTSS_ADDRESSW : return "D3DTSS_ADDRESSW";
  2471. case D3DTSS_COLORARG0 : return "D3DTSS_COLORARG0";
  2472. case D3DTSS_ALPHAARG0 : return "D3DTSS_ALPHAARG0";
  2473. case D3DTSS_RESULTARG : return "D3DTSS_RESULTARG";
  2474. default : return "UNKNOWN";
  2475. }
  2476. }
  2477. void DX8Wrapper::Get_DX8_Render_State_Value_Name(StringClass& name, D3DRENDERSTATETYPE state, unsigned value)
  2478. {
  2479. switch (state) {
  2480. case D3DRS_ZENABLE:
  2481. name=Get_DX8_ZBuffer_Type_Name(value);
  2482. break;
  2483. case D3DRS_FILLMODE:
  2484. name=Get_DX8_Fill_Mode_Name(value);
  2485. break;
  2486. case D3DRS_SHADEMODE:
  2487. name=Get_DX8_Shade_Mode_Name(value);
  2488. break;
  2489. case D3DRS_LINEPATTERN:
  2490. case D3DRS_FOGCOLOR:
  2491. case D3DRS_ALPHAREF:
  2492. case D3DRS_STENCILMASK:
  2493. case D3DRS_STENCILWRITEMASK:
  2494. case D3DRS_TEXTUREFACTOR:
  2495. case D3DRS_AMBIENT:
  2496. case D3DRS_CLIPPLANEENABLE:
  2497. case D3DRS_MULTISAMPLEMASK:
  2498. name.Format("0x%x",value);
  2499. break;
  2500. case D3DRS_ZWRITEENABLE:
  2501. case D3DRS_ALPHATESTENABLE:
  2502. case D3DRS_LASTPIXEL:
  2503. case D3DRS_DITHERENABLE:
  2504. case D3DRS_ALPHABLENDENABLE:
  2505. case D3DRS_FOGENABLE:
  2506. case D3DRS_SPECULARENABLE:
  2507. case D3DRS_STENCILENABLE:
  2508. case D3DRS_RANGEFOGENABLE:
  2509. case D3DRS_EDGEANTIALIAS:
  2510. case D3DRS_CLIPPING:
  2511. case D3DRS_LIGHTING:
  2512. case D3DRS_COLORVERTEX:
  2513. case D3DRS_LOCALVIEWER:
  2514. case D3DRS_NORMALIZENORMALS:
  2515. case D3DRS_SOFTWAREVERTEXPROCESSING:
  2516. case D3DRS_POINTSPRITEENABLE:
  2517. case D3DRS_POINTSCALEENABLE:
  2518. case D3DRS_MULTISAMPLEANTIALIAS:
  2519. case D3DRS_INDEXEDVERTEXBLENDENABLE:
  2520. name=value ? "TRUE" : "FALSE";
  2521. break;
  2522. case D3DRS_SRCBLEND:
  2523. case D3DRS_DESTBLEND:
  2524. name=Get_DX8_Blend_Name(value);
  2525. break;
  2526. case D3DRS_CULLMODE:
  2527. name=Get_DX8_Cull_Mode_Name(value);
  2528. break;
  2529. case D3DRS_ZFUNC:
  2530. case D3DRS_ALPHAFUNC:
  2531. case D3DRS_STENCILFUNC:
  2532. name=Get_DX8_Cmp_Func_Name(value);
  2533. break;
  2534. case D3DRS_ZVISIBLE:
  2535. name="NOTSUPPORTED";
  2536. break;
  2537. case D3DRS_FOGTABLEMODE:
  2538. case D3DRS_FOGVERTEXMODE:
  2539. name=Get_DX8_Fog_Mode_Name(value);
  2540. break;
  2541. case D3DRS_FOGSTART:
  2542. case D3DRS_FOGEND:
  2543. case D3DRS_FOGDENSITY:
  2544. case D3DRS_POINTSIZE:
  2545. case D3DRS_POINTSIZE_MIN:
  2546. case D3DRS_POINTSCALE_A:
  2547. case D3DRS_POINTSCALE_B:
  2548. case D3DRS_POINTSCALE_C:
  2549. case D3DRS_PATCHSEGMENTS:
  2550. case D3DRS_POINTSIZE_MAX:
  2551. case D3DRS_TWEENFACTOR:
  2552. name.Format("%f",*(float*)&value);
  2553. break;
  2554. case D3DRS_ZBIAS:
  2555. case D3DRS_STENCILREF:
  2556. name.Format("%d",value);
  2557. break;
  2558. case D3DRS_STENCILFAIL:
  2559. case D3DRS_STENCILZFAIL:
  2560. case D3DRS_STENCILPASS:
  2561. name=Get_DX8_Stencil_Op_Name(value);
  2562. break;
  2563. case D3DRS_WRAP0:
  2564. case D3DRS_WRAP1:
  2565. case D3DRS_WRAP2:
  2566. case D3DRS_WRAP3:
  2567. case D3DRS_WRAP4:
  2568. case D3DRS_WRAP5:
  2569. case D3DRS_WRAP6:
  2570. case D3DRS_WRAP7:
  2571. name="0";
  2572. if (value&D3DWRAP_U) name+="|D3DWRAP_U";
  2573. if (value&D3DWRAP_V) name+="|D3DWRAP_V";
  2574. if (value&D3DWRAP_W) name+="|D3DWRAP_W";
  2575. break;
  2576. case D3DRS_DIFFUSEMATERIALSOURCE:
  2577. case D3DRS_SPECULARMATERIALSOURCE:
  2578. case D3DRS_AMBIENTMATERIALSOURCE:
  2579. case D3DRS_EMISSIVEMATERIALSOURCE:
  2580. name=Get_DX8_Material_Source_Name(value);
  2581. break;
  2582. case D3DRS_VERTEXBLEND:
  2583. name=Get_DX8_Vertex_Blend_Flag_Name(value);
  2584. break;
  2585. case D3DRS_PATCHEDGESTYLE:
  2586. name=Get_DX8_Patch_Edge_Style_Name(value);
  2587. break;
  2588. case D3DRS_DEBUGMONITORTOKEN:
  2589. name=Get_DX8_Debug_Monitor_Token_Name(value);
  2590. break;
  2591. case D3DRS_COLORWRITEENABLE:
  2592. name="0";
  2593. if (value&D3DCOLORWRITEENABLE_RED) name+="|D3DCOLORWRITEENABLE_RED";
  2594. if (value&D3DCOLORWRITEENABLE_GREEN) name+="|D3DCOLORWRITEENABLE_GREEN";
  2595. if (value&D3DCOLORWRITEENABLE_BLUE) name+="|D3DCOLORWRITEENABLE_BLUE";
  2596. if (value&D3DCOLORWRITEENABLE_ALPHA) name+="|D3DCOLORWRITEENABLE_ALPHA";
  2597. break;
  2598. case D3DRS_BLENDOP:
  2599. name=Get_DX8_Blend_Op_Name(value);
  2600. break;
  2601. default:
  2602. name.Format("UNKNOWN (%d)",value);
  2603. break;
  2604. }
  2605. }
  2606. void DX8Wrapper::Get_DX8_Texture_Stage_State_Value_Name(StringClass& name, D3DTEXTURESTAGESTATETYPE state, unsigned value)
  2607. {
  2608. switch (state) {
  2609. case D3DTSS_COLOROP:
  2610. case D3DTSS_ALPHAOP:
  2611. name=Get_DX8_Texture_Op_Name(value);
  2612. break;
  2613. case D3DTSS_COLORARG0:
  2614. case D3DTSS_COLORARG1:
  2615. case D3DTSS_COLORARG2:
  2616. case D3DTSS_ALPHAARG0:
  2617. case D3DTSS_ALPHAARG1:
  2618. case D3DTSS_ALPHAARG2:
  2619. case D3DTSS_RESULTARG:
  2620. name=Get_DX8_Texture_Arg_Name(value);
  2621. break;
  2622. case D3DTSS_ADDRESSU:
  2623. case D3DTSS_ADDRESSV:
  2624. case D3DTSS_ADDRESSW:
  2625. name=Get_DX8_Texture_Address_Name(value);
  2626. break;
  2627. case D3DTSS_MAGFILTER:
  2628. case D3DTSS_MINFILTER:
  2629. case D3DTSS_MIPFILTER:
  2630. name=Get_DX8_Texture_Filter_Name(value);
  2631. break;
  2632. case D3DTSS_TEXTURETRANSFORMFLAGS:
  2633. name=Get_DX8_Texture_Transform_Flag_Name(value);
  2634. // Floating point values
  2635. case D3DTSS_MIPMAPLODBIAS:
  2636. case D3DTSS_BUMPENVMAT00:
  2637. case D3DTSS_BUMPENVMAT01:
  2638. case D3DTSS_BUMPENVMAT10:
  2639. case D3DTSS_BUMPENVMAT11:
  2640. case D3DTSS_BUMPENVLSCALE:
  2641. case D3DTSS_BUMPENVLOFFSET:
  2642. name.Format("%f",*(float*)&value);
  2643. break;
  2644. case D3DTSS_TEXCOORDINDEX:
  2645. if ((value&0xffff0000)==D3DTSS_TCI_CAMERASPACENORMAL) {
  2646. name.Format("D3DTSS_TCI_CAMERASPACENORMAL|%d",value&0xffff);
  2647. }
  2648. else if ((value&0xffff0000)==D3DTSS_TCI_CAMERASPACEPOSITION) {
  2649. name.Format("D3DTSS_TCI_CAMERASPACEPOSITION|%d",value&0xffff);
  2650. }
  2651. else if ((value&0xffff0000)==D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR) {
  2652. name.Format("D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR|%d",value&0xffff);
  2653. }
  2654. else {
  2655. name.Format("%d",value);
  2656. }
  2657. break;
  2658. // Integer value
  2659. case D3DTSS_MAXMIPLEVEL:
  2660. case D3DTSS_MAXANISOTROPY:
  2661. name.Format("%d",value);
  2662. break;
  2663. // Hex values
  2664. case D3DTSS_BORDERCOLOR:
  2665. name.Format("0x%x",value);
  2666. break;
  2667. default:
  2668. name.Format("UNKNOWN (%d)",value);
  2669. break;
  2670. }
  2671. }
  2672. const char* DX8Wrapper::Get_DX8_Texture_Op_Name(unsigned value)
  2673. {
  2674. switch (value) {
  2675. case D3DTOP_DISABLE : return "D3DTOP_DISABLE";
  2676. case D3DTOP_SELECTARG1 : return "D3DTOP_SELECTARG1";
  2677. case D3DTOP_SELECTARG2 : return "D3DTOP_SELECTARG2";
  2678. case D3DTOP_MODULATE : return "D3DTOP_MODULATE";
  2679. case D3DTOP_MODULATE2X : return "D3DTOP_MODULATE2X";
  2680. case D3DTOP_MODULATE4X : return "D3DTOP_MODULATE4X";
  2681. case D3DTOP_ADD : return "D3DTOP_ADD";
  2682. case D3DTOP_ADDSIGNED : return "D3DTOP_ADDSIGNED";
  2683. case D3DTOP_ADDSIGNED2X : return "D3DTOP_ADDSIGNED2X";
  2684. case D3DTOP_SUBTRACT : return "D3DTOP_SUBTRACT";
  2685. case D3DTOP_ADDSMOOTH : return "D3DTOP_ADDSMOOTH";
  2686. case D3DTOP_BLENDDIFFUSEALPHA : return "D3DTOP_BLENDDIFFUSEALPHA";
  2687. case D3DTOP_BLENDTEXTUREALPHA : return "D3DTOP_BLENDTEXTUREALPHA";
  2688. case D3DTOP_BLENDFACTORALPHA : return "D3DTOP_BLENDFACTORALPHA";
  2689. case D3DTOP_BLENDTEXTUREALPHAPM : return "D3DTOP_BLENDTEXTUREALPHAPM";
  2690. case D3DTOP_BLENDCURRENTALPHA : return "D3DTOP_BLENDCURRENTALPHA";
  2691. case D3DTOP_PREMODULATE : return "D3DTOP_PREMODULATE";
  2692. case D3DTOP_MODULATEALPHA_ADDCOLOR : return "D3DTOP_MODULATEALPHA_ADDCOLOR";
  2693. case D3DTOP_MODULATECOLOR_ADDALPHA : return "D3DTOP_MODULATECOLOR_ADDALPHA";
  2694. case D3DTOP_MODULATEINVALPHA_ADDCOLOR : return "D3DTOP_MODULATEINVALPHA_ADDCOLOR";
  2695. case D3DTOP_MODULATEINVCOLOR_ADDALPHA : return "D3DTOP_MODULATEINVCOLOR_ADDALPHA";
  2696. case D3DTOP_BUMPENVMAP : return "D3DTOP_BUMPENVMAP";
  2697. case D3DTOP_BUMPENVMAPLUMINANCE : return "D3DTOP_BUMPENVMAPLUMINANCE";
  2698. case D3DTOP_DOTPRODUCT3 : return "D3DTOP_DOTPRODUCT3";
  2699. case D3DTOP_MULTIPLYADD : return "D3DTOP_MULTIPLYADD";
  2700. case D3DTOP_LERP : return "D3DTOP_LERP";
  2701. default : return "UNKNOWN";
  2702. }
  2703. }
  2704. const char* DX8Wrapper::Get_DX8_Texture_Arg_Name(unsigned value)
  2705. {
  2706. switch (value) {
  2707. case D3DTA_CURRENT : return "D3DTA_CURRENT";
  2708. case D3DTA_DIFFUSE : return "D3DTA_DIFFUSE";
  2709. case D3DTA_SELECTMASK : return "D3DTA_SELECTMASK";
  2710. case D3DTA_SPECULAR : return "D3DTA_SPECULAR";
  2711. case D3DTA_TEMP : return "D3DTA_TEMP";
  2712. case D3DTA_TEXTURE : return "D3DTA_TEXTURE";
  2713. case D3DTA_TFACTOR : return "D3DTA_TFACTOR";
  2714. case D3DTA_ALPHAREPLICATE : return "D3DTA_ALPHAREPLICATE";
  2715. case D3DTA_COMPLEMENT : return "D3DTA_COMPLEMENT";
  2716. default : return "UNKNOWN";
  2717. }
  2718. }
  2719. const char* DX8Wrapper::Get_DX8_Texture_Filter_Name(unsigned value)
  2720. {
  2721. switch (value) {
  2722. case D3DTEXF_NONE : return "D3DTEXF_NONE";
  2723. case D3DTEXF_POINT : return "D3DTEXF_POINT";
  2724. case D3DTEXF_LINEAR : return "D3DTEXF_LINEAR";
  2725. case D3DTEXF_ANISOTROPIC : return "D3DTEXF_ANISOTROPIC";
  2726. case D3DTEXF_FLATCUBIC : return "D3DTEXF_FLATCUBIC";
  2727. case D3DTEXF_GAUSSIANCUBIC : return "D3DTEXF_GAUSSIANCUBIC";
  2728. default : return "UNKNOWN";
  2729. }
  2730. }
  2731. const char* DX8Wrapper::Get_DX8_Texture_Address_Name(unsigned value)
  2732. {
  2733. switch (value) {
  2734. case D3DTADDRESS_WRAP : return "D3DTADDRESS_WRAP";
  2735. case D3DTADDRESS_MIRROR : return "D3DTADDRESS_MIRROR";
  2736. case D3DTADDRESS_CLAMP : return "D3DTADDRESS_CLAMP";
  2737. case D3DTADDRESS_BORDER : return "D3DTADDRESS_BORDER";
  2738. case D3DTADDRESS_MIRRORONCE: return "D3DTADDRESS_MIRRORONCE";
  2739. default : return "UNKNOWN";
  2740. }
  2741. }
  2742. const char* DX8Wrapper::Get_DX8_Texture_Transform_Flag_Name(unsigned value)
  2743. {
  2744. switch (value) {
  2745. case D3DTTFF_DISABLE : return "D3DTTFF_DISABLE";
  2746. case D3DTTFF_COUNT1 : return "D3DTTFF_COUNT1";
  2747. case D3DTTFF_COUNT2 : return "D3DTTFF_COUNT2";
  2748. case D3DTTFF_COUNT3 : return "D3DTTFF_COUNT3";
  2749. case D3DTTFF_COUNT4 : return "D3DTTFF_COUNT4";
  2750. case D3DTTFF_PROJECTED : return "D3DTTFF_PROJECTED";
  2751. default : return "UNKNOWN";
  2752. }
  2753. }
  2754. const char* DX8Wrapper::Get_DX8_ZBuffer_Type_Name(unsigned value)
  2755. {
  2756. switch (value) {
  2757. case D3DZB_FALSE : return "D3DZB_FALSE";
  2758. case D3DZB_TRUE : return "D3DZB_TRUE";
  2759. case D3DZB_USEW : return "D3DZB_USEW";
  2760. default : return "UNKNOWN";
  2761. }
  2762. }
  2763. const char* DX8Wrapper::Get_DX8_Fill_Mode_Name(unsigned value)
  2764. {
  2765. switch (value) {
  2766. case D3DFILL_POINT : return "D3DFILL_POINT";
  2767. case D3DFILL_WIREFRAME : return "D3DFILL_WIREFRAME";
  2768. case D3DFILL_SOLID : return "D3DFILL_SOLID";
  2769. default : return "UNKNOWN";
  2770. }
  2771. }
  2772. const char* DX8Wrapper::Get_DX8_Shade_Mode_Name(unsigned value)
  2773. {
  2774. switch (value) {
  2775. case D3DSHADE_FLAT : return "D3DSHADE_FLAT";
  2776. case D3DSHADE_GOURAUD : return "D3DSHADE_GOURAUD";
  2777. case D3DSHADE_PHONG : return "D3DSHADE_PHONG";
  2778. default : return "UNKNOWN";
  2779. }
  2780. }
  2781. const char* DX8Wrapper::Get_DX8_Blend_Name(unsigned value)
  2782. {
  2783. switch (value) {
  2784. case D3DBLEND_ZERO : return "D3DBLEND_ZERO";
  2785. case D3DBLEND_ONE : return "D3DBLEND_ONE";
  2786. case D3DBLEND_SRCCOLOR : return "D3DBLEND_SRCCOLOR";
  2787. case D3DBLEND_INVSRCCOLOR : return "D3DBLEND_INVSRCCOLOR";
  2788. case D3DBLEND_SRCALPHA : return "D3DBLEND_SRCALPHA";
  2789. case D3DBLEND_INVSRCALPHA : return "D3DBLEND_INVSRCALPHA";
  2790. case D3DBLEND_DESTALPHA : return "D3DBLEND_DESTALPHA";
  2791. case D3DBLEND_INVDESTALPHA : return "D3DBLEND_INVDESTALPHA";
  2792. case D3DBLEND_DESTCOLOR : return "D3DBLEND_DESTCOLOR";
  2793. case D3DBLEND_INVDESTCOLOR : return "D3DBLEND_INVDESTCOLOR";
  2794. case D3DBLEND_SRCALPHASAT : return "D3DBLEND_SRCALPHASAT";
  2795. case D3DBLEND_BOTHSRCALPHA : return "D3DBLEND_BOTHSRCALPHA";
  2796. case D3DBLEND_BOTHINVSRCALPHA : return "D3DBLEND_BOTHINVSRCALPHA";
  2797. default : return "UNKNOWN";
  2798. }
  2799. }
  2800. const char* DX8Wrapper::Get_DX8_Cull_Mode_Name(unsigned value)
  2801. {
  2802. switch (value) {
  2803. case D3DCULL_NONE : return "D3DCULL_NONE";
  2804. case D3DCULL_CW : return "D3DCULL_CW";
  2805. case D3DCULL_CCW : return "D3DCULL_CCW";
  2806. default : return "UNKNOWN";
  2807. }
  2808. }
  2809. const char* DX8Wrapper::Get_DX8_Cmp_Func_Name(unsigned value)
  2810. {
  2811. switch (value) {
  2812. case D3DCMP_NEVER : return "D3DCMP_NEVER";
  2813. case D3DCMP_LESS : return "D3DCMP_LESS";
  2814. case D3DCMP_EQUAL : return "D3DCMP_EQUAL";
  2815. case D3DCMP_LESSEQUAL : return "D3DCMP_LESSEQUAL";
  2816. case D3DCMP_GREATER : return "D3DCMP_GREATER";
  2817. case D3DCMP_NOTEQUAL : return "D3DCMP_NOTEQUAL";
  2818. case D3DCMP_GREATEREQUAL : return "D3DCMP_GREATEREQUAL";
  2819. case D3DCMP_ALWAYS : return "D3DCMP_ALWAYS";
  2820. default : return "UNKNOWN";
  2821. }
  2822. }
  2823. const char* DX8Wrapper::Get_DX8_Fog_Mode_Name(unsigned value)
  2824. {
  2825. switch (value) {
  2826. case D3DFOG_NONE : return "D3DFOG_NONE";
  2827. case D3DFOG_EXP : return "D3DFOG_EXP";
  2828. case D3DFOG_EXP2 : return "D3DFOG_EXP2";
  2829. case D3DFOG_LINEAR : return "D3DFOG_LINEAR";
  2830. default : return "UNKNOWN";
  2831. }
  2832. }
  2833. const char* DX8Wrapper::Get_DX8_Stencil_Op_Name(unsigned value)
  2834. {
  2835. switch (value) {
  2836. case D3DSTENCILOP_KEEP : return "D3DSTENCILOP_KEEP";
  2837. case D3DSTENCILOP_ZERO : return "D3DSTENCILOP_ZERO";
  2838. case D3DSTENCILOP_REPLACE : return "D3DSTENCILOP_REPLACE";
  2839. case D3DSTENCILOP_INCRSAT : return "D3DSTENCILOP_INCRSAT";
  2840. case D3DSTENCILOP_DECRSAT : return "D3DSTENCILOP_DECRSAT";
  2841. case D3DSTENCILOP_INVERT : return "D3DSTENCILOP_INVERT";
  2842. case D3DSTENCILOP_INCR : return "D3DSTENCILOP_INCR";
  2843. case D3DSTENCILOP_DECR : return "D3DSTENCILOP_DECR";
  2844. default : return "UNKNOWN";
  2845. }
  2846. }
  2847. const char* DX8Wrapper::Get_DX8_Material_Source_Name(unsigned value)
  2848. {
  2849. switch (value) {
  2850. case D3DMCS_MATERIAL : return "D3DMCS_MATERIAL";
  2851. case D3DMCS_COLOR1 : return "D3DMCS_COLOR1";
  2852. case D3DMCS_COLOR2 : return "D3DMCS_COLOR2";
  2853. default : return "UNKNOWN";
  2854. }
  2855. }
  2856. const char* DX8Wrapper::Get_DX8_Vertex_Blend_Flag_Name(unsigned value)
  2857. {
  2858. switch (value) {
  2859. case D3DVBF_DISABLE : return "D3DVBF_DISABLE";
  2860. case D3DVBF_1WEIGHTS : return "D3DVBF_1WEIGHTS";
  2861. case D3DVBF_2WEIGHTS : return "D3DVBF_2WEIGHTS";
  2862. case D3DVBF_3WEIGHTS : return "D3DVBF_3WEIGHTS";
  2863. case D3DVBF_TWEENING : return "D3DVBF_TWEENING";
  2864. case D3DVBF_0WEIGHTS : return "D3DVBF_0WEIGHTS";
  2865. default : return "UNKNOWN";
  2866. }
  2867. }
  2868. const char* DX8Wrapper::Get_DX8_Patch_Edge_Style_Name(unsigned value)
  2869. {
  2870. switch (value) {
  2871. case D3DPATCHEDGE_DISCRETE : return "D3DPATCHEDGE_DISCRETE";
  2872. case D3DPATCHEDGE_CONTINUOUS:return "D3DPATCHEDGE_CONTINUOUS";
  2873. default : return "UNKNOWN";
  2874. }
  2875. }
  2876. const char* DX8Wrapper::Get_DX8_Debug_Monitor_Token_Name(unsigned value)
  2877. {
  2878. switch (value) {
  2879. case D3DDMT_ENABLE : return "D3DDMT_ENABLE";
  2880. case D3DDMT_DISABLE : return "D3DDMT_DISABLE";
  2881. default : return "UNKNOWN";
  2882. }
  2883. }
  2884. const char* DX8Wrapper::Get_DX8_Blend_Op_Name(unsigned value)
  2885. {
  2886. switch (value) {
  2887. case D3DBLENDOP_ADD : return "D3DBLENDOP_ADD";
  2888. case D3DBLENDOP_SUBTRACT : return "D3DBLENDOP_SUBTRACT";
  2889. case D3DBLENDOP_REVSUBTRACT: return "D3DBLENDOP_REVSUBTRACT";
  2890. case D3DBLENDOP_MIN : return "D3DBLENDOP_MIN";
  2891. case D3DBLENDOP_MAX : return "D3DBLENDOP_MAX";
  2892. default : return "UNKNOWN";
  2893. }
  2894. }