dx8wrapper.cpp 132 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451
  1. /*
  2. ** Command & Conquer Generals Zero Hour(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:: Kenny Mitchell *
  29. * *
  30. * $Modtime:: 08/05/02 1:27p $*
  31. * *
  32. * $Revision:: 170 $*
  33. * *
  34. * 06/26/02 KM Matrix name change to avoid MAX conflicts *
  35. * 06/27/02 KM Render to shadow buffer texture support *
  36. * 06/27/02 KM Shader system updates *
  37. * 08/05/02 KM Texture class redesign
  38. *---------------------------------------------------------------------------------------------*
  39. * Functions: *
  40. * DX8Wrapper::_Update_Texture -- Copies a texture from system memory to video memory *
  41. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  42. //#define CREATE_DX8_MULTI_THREADED
  43. //#define CREATE_DX8_FPU_PRESERVE
  44. #define WW3D_DEVTYPE D3DDEVTYPE_HAL
  45. #include "dx8wrapper.h"
  46. #include "dx8webbrowser.h"
  47. #include "dx8fvf.h"
  48. #include "dx8vertexbuffer.h"
  49. #include "dx8indexbuffer.h"
  50. #include "dx8renderer.h"
  51. #include "ww3d.h"
  52. #include "camera.h"
  53. #include "wwstring.h"
  54. #include "matrix4.h"
  55. #include "vertmaterial.h"
  56. #include "rddesc.h"
  57. #include "lightenvironment.h"
  58. #include "statistics.h"
  59. #include "registry.h"
  60. #include "boxrobj.h"
  61. #include "pointgr.h"
  62. #include "render2d.h"
  63. #include "sortingrenderer.h"
  64. #include "shattersystem.h"
  65. #include "light.h"
  66. #include "assetmgr.h"
  67. #include "textureloader.h"
  68. #include "missingtexture.h"
  69. #include "thread.h"
  70. #include <stdio.h>
  71. #include <D3dx8core.h>
  72. #include "pot.h"
  73. #include "wwprofile.h"
  74. #include "ffactory.h"
  75. #include "dx8caps.h"
  76. #include "formconv.h"
  77. #include "dx8texman.h"
  78. #include "bound.h"
  79. #include "dx8webbrowser.h"
  80. #include "shdlib.h"
  81. const int DEFAULT_RESOLUTION_WIDTH = 640;
  82. const int DEFAULT_RESOLUTION_HEIGHT = 480;
  83. const int DEFAULT_BIT_DEPTH = 32;
  84. const int DEFAULT_TEXTURE_BIT_DEPTH = 16;
  85. bool DX8Wrapper_IsWindowed = true;
  86. // FPU_PRESERVE
  87. int DX8Wrapper_PreserveFPU = 0;
  88. /***********************************************************************************
  89. **
  90. ** DX8Wrapper Static Variables
  91. **
  92. ***********************************************************************************/
  93. static HWND _Hwnd = NULL;
  94. bool DX8Wrapper::IsInitted = false;
  95. bool DX8Wrapper::_EnableTriangleDraw = true;
  96. int DX8Wrapper::CurRenderDevice = -1;
  97. int DX8Wrapper::ResolutionWidth = DEFAULT_RESOLUTION_WIDTH;
  98. int DX8Wrapper::ResolutionHeight = DEFAULT_RESOLUTION_HEIGHT;
  99. int DX8Wrapper::BitDepth = DEFAULT_BIT_DEPTH;
  100. int DX8Wrapper::TextureBitDepth = DEFAULT_TEXTURE_BIT_DEPTH;
  101. bool DX8Wrapper::IsWindowed = false;
  102. D3DFORMAT DX8Wrapper::DisplayFormat = D3DFMT_UNKNOWN;
  103. D3DMATRIX DX8Wrapper::old_world;
  104. D3DMATRIX DX8Wrapper::old_view;
  105. D3DMATRIX DX8Wrapper::old_prj;
  106. // shader system additions KJM v
  107. DWORD DX8Wrapper::Vertex_Shader = 0;
  108. DWORD DX8Wrapper::Pixel_Shader = 0;
  109. Vector4 DX8Wrapper::Vertex_Shader_Constants[MAX_VERTEX_SHADER_CONSTANTS];
  110. Vector4 DX8Wrapper::Pixel_Shader_Constants[MAX_PIXEL_SHADER_CONSTANTS];
  111. LightEnvironmentClass* DX8Wrapper::Light_Environment = NULL;
  112. RenderInfoClass* DX8Wrapper::Render_Info = NULL;
  113. DWORD DX8Wrapper::Vertex_Processing_Behavior = 0;
  114. ZTextureClass* DX8Wrapper::Shadow_Map[MAX_SHADOW_MAPS];
  115. Vector3 DX8Wrapper::Ambient_Color;
  116. // shader system additions KJM ^
  117. bool DX8Wrapper::world_identity;
  118. unsigned DX8Wrapper::RenderStates[256];
  119. unsigned DX8Wrapper::TextureStageStates[MAX_TEXTURE_STAGES][32];
  120. IDirect3DBaseTexture8 * DX8Wrapper::Textures[MAX_TEXTURE_STAGES];
  121. RenderStateStruct DX8Wrapper::render_state;
  122. unsigned DX8Wrapper::render_state_changed;
  123. bool DX8Wrapper::FogEnable = false;
  124. D3DCOLOR DX8Wrapper::FogColor = 0;
  125. IDirect3D8 * DX8Wrapper::D3DInterface = NULL;
  126. IDirect3DDevice8 * DX8Wrapper::D3DDevice = NULL;
  127. IDirect3DSurface8 * DX8Wrapper::CurrentRenderTarget = NULL;
  128. IDirect3DSurface8 * DX8Wrapper::CurrentDepthBuffer = NULL;
  129. IDirect3DSurface8 * DX8Wrapper::DefaultRenderTarget = NULL;
  130. IDirect3DSurface8 * DX8Wrapper::DefaultDepthBuffer = NULL;
  131. bool DX8Wrapper::IsRenderToTexture = false;
  132. unsigned DX8Wrapper::matrix_changes = 0;
  133. unsigned DX8Wrapper::material_changes = 0;
  134. unsigned DX8Wrapper::vertex_buffer_changes = 0;
  135. unsigned DX8Wrapper::index_buffer_changes = 0;
  136. unsigned DX8Wrapper::light_changes = 0;
  137. unsigned DX8Wrapper::texture_changes = 0;
  138. unsigned DX8Wrapper::render_state_changes = 0;
  139. unsigned DX8Wrapper::texture_stage_state_changes = 0;
  140. unsigned DX8Wrapper::draw_calls = 0;
  141. unsigned DX8Wrapper::_MainThreadID = 0;
  142. bool DX8Wrapper::CurrentDX8LightEnables[4];
  143. bool DX8Wrapper::IsDeviceLost;
  144. int DX8Wrapper::ZBias;
  145. float DX8Wrapper::ZNear;
  146. float DX8Wrapper::ZFar;
  147. Matrix4x4 DX8Wrapper::ProjectionMatrix;
  148. Matrix4x4 DX8Wrapper::DX8Transforms[D3DTS_WORLD+1];
  149. DX8Caps* DX8Wrapper::CurrentCaps = 0;
  150. // Hack test... this disables rendering of batches of too few polygons.
  151. unsigned DX8Wrapper::DrawPolygonLowBoundLimit=0;
  152. D3DADAPTER_IDENTIFIER8 DX8Wrapper::CurrentAdapterIdentifier;
  153. unsigned long DX8Wrapper::FrameCount = 0;
  154. bool _DX8SingleThreaded = false;
  155. unsigned number_of_DX8_calls = 0;
  156. static unsigned last_frame_matrix_changes = 0;
  157. static unsigned last_frame_material_changes = 0;
  158. static unsigned last_frame_vertex_buffer_changes = 0;
  159. static unsigned last_frame_index_buffer_changes = 0;
  160. static unsigned last_frame_light_changes = 0;
  161. static unsigned last_frame_texture_changes = 0;
  162. static unsigned last_frame_render_state_changes = 0;
  163. static unsigned last_frame_texture_stage_state_changes = 0;
  164. static unsigned last_frame_number_of_DX8_calls = 0;
  165. static unsigned last_frame_draw_calls = 0;
  166. static D3DDISPLAYMODE DesktopMode;
  167. static D3DPRESENT_PARAMETERS _PresentParameters;
  168. static DynamicVectorClass<StringClass> _RenderDeviceNameTable;
  169. static DynamicVectorClass<StringClass> _RenderDeviceShortNameTable;
  170. static DynamicVectorClass<RenderDeviceDescClass> _RenderDeviceDescriptionTable;
  171. typedef IDirect3D8* (WINAPI *Direct3DCreate8Type) (UINT SDKVersion);
  172. Direct3DCreate8Type Direct3DCreate8Ptr = NULL;
  173. HINSTANCE D3D8Lib = NULL;
  174. DX8_CleanupHook *DX8Wrapper::m_pCleanupHook=NULL;
  175. #ifdef EXTENDED_STATS
  176. DX8_Stats DX8Wrapper::stats;
  177. #endif
  178. /***********************************************************************************
  179. **
  180. ** DX8Wrapper Implementation
  181. **
  182. ***********************************************************************************/
  183. void Log_DX8_ErrorCode(unsigned res)
  184. {
  185. char tmp[256]="";
  186. HRESULT new_res=D3DXGetErrorStringA(
  187. res,
  188. tmp,
  189. sizeof(tmp));
  190. if (new_res==D3D_OK) {
  191. WWDEBUG_SAY((tmp));
  192. }
  193. WWASSERT(0);
  194. }
  195. void Non_Fatal_Log_DX8_ErrorCode(unsigned res,const char * file,int line)
  196. {
  197. char tmp[256]="";
  198. HRESULT new_res=D3DXGetErrorStringA(
  199. res,
  200. tmp,
  201. sizeof(tmp));
  202. if (new_res==D3D_OK) {
  203. WWDEBUG_SAY(("DX8 Error: %s, File: %s, Line: %d\n",tmp,file,line));
  204. }
  205. }
  206. bool DX8Wrapper::Init(void * hwnd, bool lite)
  207. {
  208. WWASSERT(!IsInitted);
  209. // zero memory
  210. memset(Textures,0,sizeof(IDirect3DBaseTexture8*)*MAX_TEXTURE_STAGES);
  211. memset(RenderStates,0,sizeof(unsigned)*256);
  212. memset(TextureStageStates,0,sizeof(unsigned)*32*MAX_TEXTURE_STAGES);
  213. memset(Vertex_Shader_Constants,0,sizeof(Vector4)*MAX_VERTEX_SHADER_CONSTANTS);
  214. memset(Pixel_Shader_Constants,0,sizeof(Vector4)*MAX_PIXEL_SHADER_CONSTANTS);
  215. memset(&render_state,0,sizeof(RenderStateStruct));
  216. memset(Shadow_Map,0,sizeof(ZTextureClass*)*MAX_SHADOW_MAPS);
  217. /*
  218. ** Initialize all variables!
  219. */
  220. _Hwnd = (HWND)hwnd;
  221. _MainThreadID=ThreadClass::_Get_Current_Thread_ID();
  222. WWDEBUG_SAY(("DX8Wrapper main thread: 0x%x\n",_MainThreadID));
  223. CurRenderDevice = -1;
  224. ResolutionWidth = DEFAULT_RESOLUTION_WIDTH;
  225. ResolutionHeight = DEFAULT_RESOLUTION_HEIGHT;
  226. // Initialize Render2DClass Screen Resolution
  227. Render2DClass::Set_Screen_Resolution( RectClass( 0, 0, ResolutionWidth, ResolutionHeight ) );
  228. BitDepth = DEFAULT_BIT_DEPTH;
  229. IsWindowed = false;
  230. DX8Wrapper_IsWindowed = false;
  231. for (int light=0;light<4;++light) CurrentDX8LightEnables[light]=false;
  232. ::ZeroMemory(&old_world, sizeof(D3DMATRIX));
  233. ::ZeroMemory(&old_view, sizeof(D3DMATRIX));
  234. ::ZeroMemory(&old_prj, sizeof(D3DMATRIX));
  235. //old_vertex_shader; TODO
  236. //old_sr_shader;
  237. //current_shader;
  238. //world_identity;
  239. //CurrentFogColor;
  240. D3DInterface = NULL;
  241. D3DDevice = NULL;
  242. WWDEBUG_SAY(("Reset DX8Wrapper statistics\n"));
  243. Reset_Statistics();
  244. Invalidate_Cached_Render_States();
  245. if (!lite) {
  246. D3D8Lib = LoadLibrary("D3D8.DLL");
  247. if (D3D8Lib == NULL) return false; // Return false at this point if init failed
  248. Direct3DCreate8Ptr = (Direct3DCreate8Type) GetProcAddress(D3D8Lib, "Direct3DCreate8");
  249. if (Direct3DCreate8Ptr == NULL) return false;
  250. /*
  251. ** Create the D3D interface object
  252. */
  253. WWDEBUG_SAY(("Create Direct3D8\n"));
  254. D3DInterface = Direct3DCreate8Ptr(D3D_SDK_VERSION); // TODO: handle failure cases...
  255. if (D3DInterface == NULL) {
  256. return(false);
  257. }
  258. IsInitted = true;
  259. /*
  260. ** Enumerate the available devices
  261. */
  262. WWDEBUG_SAY(("Enumerate devices\n"));
  263. Enumerate_Devices();
  264. WWDEBUG_SAY(("DX8Wrapper Init completed\n"));
  265. }
  266. return(true);
  267. }
  268. void DX8Wrapper::Shutdown(void)
  269. {
  270. if (D3DDevice) {
  271. Set_Render_Target ((IDirect3DSurface8 *)NULL);
  272. Release_Device();
  273. }
  274. if (D3DInterface) {
  275. D3DInterface->Release();
  276. D3DInterface=NULL;
  277. }
  278. if (CurrentCaps)
  279. {
  280. int max=CurrentCaps->Get_Max_Textures_Per_Pass();
  281. for (int i = 0; i < max; i++)
  282. {
  283. if (Textures[i])
  284. {
  285. Textures[i]->Release();
  286. Textures[i] = NULL;
  287. }
  288. }
  289. }
  290. if (D3DInterface) {
  291. UINT newRefCount=D3DInterface->Release();
  292. D3DInterface=NULL;
  293. }
  294. if (D3D8Lib) {
  295. FreeLibrary(D3D8Lib);
  296. D3D8Lib = NULL;
  297. }
  298. _RenderDeviceNameTable.Clear(); // note - Delete_All() resizes the vector, causing a reallocation. Clear is better. jba.
  299. _RenderDeviceShortNameTable.Clear();
  300. _RenderDeviceDescriptionTable.Clear();
  301. DX8Caps::Shutdown();
  302. IsInitted = false; // 010803 srj
  303. }
  304. void DX8Wrapper::Do_Onetime_Device_Dependent_Inits(void)
  305. {
  306. /*
  307. ** Set Global render states (some of which depend on caps)
  308. */
  309. Compute_Caps(D3DFormat_To_WW3DFormat(DisplayFormat));
  310. /*
  311. ** Initalize any other subsystems inside of WW3D
  312. */
  313. MissingTexture::_Init();
  314. TextureFilterClass::_Init_Filters((TextureFilterClass::TextureFilterMode)WW3D::Get_Texture_Filter());
  315. TheDX8MeshRenderer.Init();
  316. SHD_INIT;
  317. BoxRenderObjClass::Init();
  318. VertexMaterialClass::Init();
  319. PointGroupClass::_Init(); // This needs the VertexMaterialClass to be initted
  320. ShatterSystem::Init();
  321. TextureLoader::Init();
  322. Set_Default_Global_Render_States();
  323. }
  324. inline DWORD F2DW(float f) { return *((unsigned*)&f); }
  325. void DX8Wrapper::Set_Default_Global_Render_States(void)
  326. {
  327. DX8_THREAD_ASSERT();
  328. const D3DCAPS8 &caps = Get_Current_Caps()->Get_DX8_Caps();
  329. Set_DX8_Render_State(D3DRS_RANGEFOGENABLE, (caps.RasterCaps & D3DPRASTERCAPS_FOGRANGE) ? TRUE : FALSE);
  330. Set_DX8_Render_State(D3DRS_FOGTABLEMODE, D3DFOG_NONE);
  331. Set_DX8_Render_State(D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
  332. Set_DX8_Render_State(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL);
  333. Set_DX8_Render_State(D3DRS_COLORVERTEX, TRUE);
  334. Set_DX8_Render_State(D3DRS_ZBIAS,0);
  335. Set_DX8_Texture_Stage_State(1, D3DTSS_BUMPENVLSCALE, F2DW(1.0f));
  336. Set_DX8_Texture_Stage_State(1, D3DTSS_BUMPENVLOFFSET, F2DW(0.0f));
  337. Set_DX8_Texture_Stage_State(0, D3DTSS_BUMPENVMAT00,F2DW(1.0f));
  338. Set_DX8_Texture_Stage_State(0, D3DTSS_BUMPENVMAT01,F2DW(0.0f));
  339. Set_DX8_Texture_Stage_State(0, D3DTSS_BUMPENVMAT10,F2DW(0.0f));
  340. Set_DX8_Texture_Stage_State(0, D3DTSS_BUMPENVMAT11,F2DW(1.0f));
  341. // Set_DX8_Render_State(D3DRS_CULLMODE, D3DCULL_CW);
  342. // Set dither mode here?
  343. }
  344. //MW: I added this for 'Generals'.
  345. bool DX8Wrapper::Validate_Device(void)
  346. { DWORD numPasses=0;
  347. HRESULT hRes;
  348. hRes=_Get_D3D_Device8()->ValidateDevice(&numPasses);
  349. return (hRes == D3D_OK);
  350. }
  351. void DX8Wrapper::Invalidate_Cached_Render_States(void)
  352. {
  353. render_state_changed=0;
  354. int a;
  355. for (a=0;a<sizeof(RenderStates)/sizeof(unsigned);++a) {
  356. RenderStates[a]=0x12345678;
  357. }
  358. for (a=0;a<MAX_TEXTURE_STAGES;++a)
  359. {
  360. for (int b=0; b<32;b++)
  361. {
  362. TextureStageStates[a][b]=0x12345678;
  363. }
  364. //Need to explicitly set texture to NULL, otherwise app will not be able to
  365. //set it to null because of redundant state checker. MW
  366. if (_Get_D3D_Device8())
  367. _Get_D3D_Device8()->SetTexture(a,NULL);
  368. if (Textures[a] != NULL) {
  369. Textures[a]->Release();
  370. }
  371. Textures[a]=NULL;
  372. }
  373. ShaderClass::Invalidate();
  374. //Need to explicitly set render_state texture pointers to NULL. MW
  375. Release_Render_State();
  376. // (gth) clear the matrix shadows too
  377. for (int i=0; i<D3DTS_WORLD+1; i++) {
  378. DX8Transforms[i][0].Set(0,0,0,0);
  379. DX8Transforms[i][1].Set(0,0,0,0);
  380. DX8Transforms[i][2].Set(0,0,0,0);
  381. DX8Transforms[i][3].Set(0,0,0,0);
  382. }
  383. }
  384. void DX8Wrapper::Do_Onetime_Device_Dependent_Shutdowns(void)
  385. {
  386. /*
  387. ** Shutdown ww3d systems
  388. */
  389. int i;
  390. for (i=0;i<MAX_VERTEX_STREAMS;++i) {
  391. if (render_state.vertex_buffers[i]) render_state.vertex_buffers[i]->Release_Engine_Ref();
  392. REF_PTR_RELEASE(render_state.vertex_buffers[i]);
  393. }
  394. if (render_state.index_buffer) render_state.index_buffer->Release_Engine_Ref();
  395. REF_PTR_RELEASE(render_state.index_buffer);
  396. REF_PTR_RELEASE(render_state.material);
  397. for (i=0;i<CurrentCaps->Get_Max_Textures_Per_Pass();++i) REF_PTR_RELEASE(render_state.Textures[i]);
  398. TextureLoader::Deinit();
  399. SortingRendererClass::Deinit();
  400. DynamicVBAccessClass::_Deinit();
  401. DynamicIBAccessClass::_Deinit();
  402. ShatterSystem::Shutdown();
  403. PointGroupClass::_Shutdown();
  404. VertexMaterialClass::Shutdown();
  405. BoxRenderObjClass::Shutdown();
  406. SHD_SHUTDOWN;
  407. TheDX8MeshRenderer.Shutdown();
  408. MissingTexture::_Deinit();
  409. if (CurrentCaps) {
  410. delete CurrentCaps;
  411. CurrentCaps=NULL;
  412. }
  413. }
  414. bool DX8Wrapper::Create_Device(void)
  415. {
  416. WWASSERT(D3DDevice==NULL); // for now, once you've created a device, you're stuck with it!
  417. D3DCAPS8 caps;
  418. if
  419. (
  420. FAILED
  421. (
  422. D3DInterface->GetDeviceCaps
  423. (
  424. CurRenderDevice,
  425. WW3D_DEVTYPE,
  426. &caps
  427. )
  428. )
  429. )
  430. {
  431. return false;
  432. }
  433. ::ZeroMemory(&CurrentAdapterIdentifier, sizeof(D3DADAPTER_IDENTIFIER8));
  434. if
  435. (
  436. FAILED
  437. (
  438. D3DInterface->GetAdapterIdentifier
  439. (
  440. CurRenderDevice,
  441. D3DENUM_NO_WHQL_LEVEL,
  442. &CurrentAdapterIdentifier
  443. )
  444. )
  445. )
  446. {
  447. return false;
  448. }
  449. #ifndef _XBOX
  450. Vertex_Processing_Behavior=(caps.DevCaps&D3DDEVCAPS_HWTRANSFORMANDLIGHT) ?
  451. D3DCREATE_MIXED_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  452. // enable this when all 'get' dx calls are removed KJM
  453. /*if (caps.DevCaps&D3DDEVCAPS_PUREDEVICE)
  454. {
  455. Vertex_Processing_Behavior|=D3DCREATE_PUREDEVICE;
  456. }*/
  457. #else // XBOX
  458. Vertex_Processing_Behavior=D3DCREATE_PUREDEVICE;
  459. #endif // XBOX
  460. #ifdef CREATE_DX8_MULTI_THREADED
  461. Vertex_Processing_Behavior|=D3DCREATE_MULTITHREADED;
  462. _DX8SingleThreaded=false;
  463. #else
  464. _DX8SingleThreaded=true;
  465. #endif
  466. if (DX8Wrapper_PreserveFPU)
  467. Vertex_Processing_Behavior |= D3DCREATE_FPU_PRESERVE;
  468. #ifdef CREATE_DX8_FPU_PRESERVE
  469. Vertex_Processing_Behavior|=D3DCREATE_FPU_PRESERVE;
  470. #endif
  471. HRESULT hr=D3DInterface->CreateDevice
  472. (
  473. CurRenderDevice,
  474. WW3D_DEVTYPE,
  475. _Hwnd,
  476. Vertex_Processing_Behavior,
  477. &_PresentParameters,
  478. &D3DDevice
  479. );
  480. if (FAILED(hr))
  481. {
  482. // The device selection may fail because the device lied that it supports 32 bit zbuffer with 16 bit
  483. // display. This happens at least on Voodoo2.
  484. if ((_PresentParameters.BackBufferFormat==D3DFMT_R5G6B5 ||
  485. _PresentParameters.BackBufferFormat==D3DFMT_X1R5G5B5 ||
  486. _PresentParameters.BackBufferFormat==D3DFMT_A1R5G5B5) &&
  487. (_PresentParameters.AutoDepthStencilFormat==D3DFMT_D32 ||
  488. _PresentParameters.AutoDepthStencilFormat==D3DFMT_D24S8 ||
  489. _PresentParameters.AutoDepthStencilFormat==D3DFMT_D24X8))
  490. {
  491. _PresentParameters.AutoDepthStencilFormat=D3DFMT_D16;
  492. hr = D3DInterface->CreateDevice
  493. (
  494. CurRenderDevice,
  495. WW3D_DEVTYPE,
  496. _Hwnd,
  497. Vertex_Processing_Behavior,
  498. &_PresentParameters,
  499. &D3DDevice
  500. );
  501. if (FAILED(hr))
  502. {
  503. return false;
  504. }
  505. }
  506. else
  507. {
  508. return false;
  509. }
  510. }
  511. /*
  512. ** Initialize all subsystems
  513. */
  514. Do_Onetime_Device_Dependent_Inits();
  515. return true;
  516. }
  517. bool DX8Wrapper::Reset_Device(bool reload_assets)
  518. {
  519. WWDEBUG_SAY(("Resetting device.\n"));
  520. DX8_THREAD_ASSERT();
  521. if ((IsInitted) && (D3DDevice != NULL)) {
  522. // Release all non-MANAGED stuff
  523. WW3D::_Invalidate_Textures();
  524. for (unsigned i=0;i<MAX_VERTEX_STREAMS;++i)
  525. {
  526. Set_Vertex_Buffer (NULL,i);
  527. }
  528. Set_Index_Buffer (NULL, 0);
  529. if (m_pCleanupHook) {
  530. m_pCleanupHook->ReleaseResources();
  531. }
  532. DynamicVBAccessClass::_Deinit();
  533. DynamicIBAccessClass::_Deinit();
  534. DX8TextureManagerClass::Release_Textures();
  535. SHD_SHUTDOWN_SHADERS;
  536. // Reset frame count to reflect the flipping chain being reset by Reset()
  537. FrameCount = 0;
  538. memset(Vertex_Shader_Constants,0,sizeof(Vector4)*MAX_VERTEX_SHADER_CONSTANTS);
  539. memset(Pixel_Shader_Constants,0,sizeof(Vector4)*MAX_PIXEL_SHADER_CONSTANTS);
  540. HRESULT hr=_Get_D3D_Device8()->TestCooperativeLevel();
  541. if (hr != D3DERR_DEVICELOST )
  542. { DX8CALL_HRES(Reset(&_PresentParameters),hr)
  543. if (hr != D3D_OK)
  544. return false; //reset failed.
  545. }
  546. else
  547. return false; //device is lost and can't be reset.
  548. if (reload_assets)
  549. {
  550. DX8TextureManagerClass::Recreate_Textures();
  551. if (m_pCleanupHook) {
  552. m_pCleanupHook->ReAcquireResources();
  553. }
  554. }
  555. Invalidate_Cached_Render_States();
  556. Set_Default_Global_Render_States();
  557. SHD_INIT_SHADERS;
  558. WWDEBUG_SAY(("Device reset completed\n"));
  559. return true;
  560. }
  561. WWDEBUG_SAY(("Device reset failed\n"));
  562. return false;
  563. }
  564. void DX8Wrapper::Release_Device(void)
  565. {
  566. if (D3DDevice) {
  567. for (int a=0;a<MAX_TEXTURE_STAGES;++a)
  568. { //release references to any textures that were used in last rendering call
  569. DX8CALL(SetTexture(a,NULL));
  570. }
  571. DX8CALL(SetStreamSource(0, NULL, 0)); //release reference count on last rendered vertex buffer
  572. DX8CALL(SetIndices(NULL,0)); //release reference count on last rendered index buffer
  573. /*
  574. ** Release the current vertex and index buffers
  575. */
  576. for (unsigned i=0;i<MAX_VERTEX_STREAMS;++i)
  577. {
  578. if (render_state.vertex_buffers[i]) render_state.vertex_buffers[i]->Release_Engine_Ref();
  579. REF_PTR_RELEASE(render_state.vertex_buffers[i]);
  580. }
  581. if (render_state.index_buffer) render_state.index_buffer->Release_Engine_Ref();
  582. REF_PTR_RELEASE(render_state.index_buffer);
  583. /*
  584. ** Shutdown all subsystems
  585. */
  586. Do_Onetime_Device_Dependent_Shutdowns();
  587. /*
  588. ** Release the device
  589. */
  590. D3DDevice->Release();
  591. D3DDevice=NULL;
  592. }
  593. }
  594. void DX8Wrapper::Enumerate_Devices()
  595. {
  596. DX8_Assert();
  597. int adapter_count = D3DInterface->GetAdapterCount();
  598. for (int adapter_index=0; adapter_index<adapter_count; adapter_index++) {
  599. D3DADAPTER_IDENTIFIER8 id;
  600. ::ZeroMemory(&id, sizeof(D3DADAPTER_IDENTIFIER8));
  601. HRESULT res = D3DInterface->GetAdapterIdentifier(adapter_index,D3DENUM_NO_WHQL_LEVEL,&id);
  602. if (res == D3D_OK) {
  603. /*
  604. ** Set up the render device description
  605. ** TODO: Fill in more fields of the render device description? (need some lookup tables)
  606. */
  607. RenderDeviceDescClass desc;
  608. desc.set_device_name(id.Description);
  609. desc.set_driver_name(id.Driver);
  610. char buf[64];
  611. sprintf(buf,"%d.%d.%d.%d", //"%04x.%04x.%04x.%04x",
  612. HIWORD(id.DriverVersion.HighPart),
  613. LOWORD(id.DriverVersion.HighPart),
  614. HIWORD(id.DriverVersion.LowPart),
  615. LOWORD(id.DriverVersion.LowPart));
  616. desc.set_driver_version(buf);
  617. D3DInterface->GetDeviceCaps(adapter_index,WW3D_DEVTYPE,&desc.Caps);
  618. D3DInterface->GetAdapterIdentifier(adapter_index,D3DENUM_NO_WHQL_LEVEL,&desc.AdapterIdentifier);
  619. DX8Caps dx8caps(D3DInterface,desc.Caps,WW3D_FORMAT_UNKNOWN,desc.AdapterIdentifier);
  620. /*
  621. ** Enumerate the resolutions
  622. */
  623. desc.reset_resolution_list();
  624. int mode_count = D3DInterface->GetAdapterModeCount(adapter_index);
  625. for (int mode_index=0; mode_index<mode_count; mode_index++) {
  626. D3DDISPLAYMODE d3dmode;
  627. ::ZeroMemory(&d3dmode, sizeof(D3DDISPLAYMODE));
  628. HRESULT res = D3DInterface->EnumAdapterModes(adapter_index,mode_index,&d3dmode);
  629. if (res == D3D_OK) {
  630. int bits = 0;
  631. switch (d3dmode.Format)
  632. {
  633. case D3DFMT_R8G8B8:
  634. case D3DFMT_A8R8G8B8:
  635. case D3DFMT_X8R8G8B8: bits = 32; break;
  636. case D3DFMT_R5G6B5:
  637. case D3DFMT_X1R5G5B5: bits = 16; break;
  638. }
  639. // Some cards fail in certain modes, DX8Caps keeps list of those.
  640. if (!dx8caps.Is_Valid_Display_Format(d3dmode.Width,d3dmode.Height,D3DFormat_To_WW3DFormat(d3dmode.Format))) {
  641. bits=0;
  642. }
  643. /*
  644. ** If we recognize the format, add it to the list
  645. ** TODO: should we handle more formats? will any cards report more than 24 or 16 bit?
  646. */
  647. if (bits != 0) {
  648. desc.add_resolution(d3dmode.Width,d3dmode.Height,bits);
  649. }
  650. }
  651. }
  652. // IML: If the device has one or more valid resolutions add it to the device list.
  653. // NOTE: Testing has shown that there are drivers with zero resolutions.
  654. if (desc.Enumerate_Resolutions().Count() > 0) {
  655. /*
  656. ** Set up the device name
  657. */
  658. StringClass device_name(id.Description,true);
  659. _RenderDeviceNameTable.Add(device_name);
  660. _RenderDeviceShortNameTable.Add(device_name); // for now, just add the same name to the "pretty name table"
  661. /*
  662. ** Add the render device to our table
  663. */
  664. _RenderDeviceDescriptionTable.Add(desc);
  665. }
  666. }
  667. }
  668. }
  669. bool DX8Wrapper::Set_Any_Render_Device(void)
  670. {
  671. // Then fullscreen
  672. for (int dev_number = 0; dev_number < _RenderDeviceNameTable.Count(); dev_number++) {
  673. if (Set_Render_Device(dev_number,-1,-1,-1,0,false)) {
  674. return true;
  675. }
  676. }
  677. // Try windowed first
  678. for (dev_number = 0; dev_number < _RenderDeviceNameTable.Count(); dev_number++) {
  679. if (Set_Render_Device(dev_number,-1,-1,-1,1,false)) {
  680. return true;
  681. }
  682. }
  683. return false;
  684. }
  685. bool DX8Wrapper::Set_Render_Device
  686. (
  687. const char * dev_name,
  688. int width,
  689. int height,
  690. int bits,
  691. int windowed,
  692. bool resize_window
  693. )
  694. {
  695. for ( int dev_number = 0; dev_number < _RenderDeviceNameTable.Count(); dev_number++) {
  696. if ( strcmp( dev_name, _RenderDeviceNameTable[dev_number]) == 0) {
  697. return Set_Render_Device( dev_number, width, height, bits, windowed, resize_window );
  698. }
  699. if ( strcmp( dev_name, _RenderDeviceShortNameTable[dev_number]) == 0) {
  700. return Set_Render_Device( dev_number, width, height, bits, windowed, resize_window );
  701. }
  702. }
  703. return false;
  704. }
  705. void DX8Wrapper::Get_Format_Name(unsigned int format, StringClass *tex_format)
  706. {
  707. *tex_format="Unknown";
  708. switch (format) {
  709. case D3DFMT_A8R8G8B8: *tex_format="D3DFMT_A8R8G8B8"; break;
  710. case D3DFMT_R8G8B8: *tex_format="D3DFMT_R8G8B8"; break;
  711. case D3DFMT_A4R4G4B4: *tex_format="D3DFMT_A4R4G4B4"; break;
  712. case D3DFMT_A1R5G5B5: *tex_format="D3DFMT_A1R5G5B5"; break;
  713. case D3DFMT_R5G6B5: *tex_format="D3DFMT_R5G6B5"; break;
  714. case D3DFMT_L8: *tex_format="D3DFMT_L8"; break;
  715. case D3DFMT_A8: *tex_format="D3DFMT_A8"; break;
  716. case D3DFMT_P8: *tex_format="D3DFMT_P8"; break;
  717. case D3DFMT_X8R8G8B8: *tex_format="D3DFMT_X8R8G8B8"; break;
  718. case D3DFMT_X1R5G5B5: *tex_format="D3DFMT_X1R5G5B5"; break;
  719. case D3DFMT_R3G3B2: *tex_format="D3DFMT_R3G3B2"; break;
  720. case D3DFMT_A8R3G3B2: *tex_format="D3DFMT_A8R3G3B2"; break;
  721. case D3DFMT_X4R4G4B4: *tex_format="D3DFMT_X4R4G4B4"; break;
  722. case D3DFMT_A8P8: *tex_format="D3DFMT_A8P8"; break;
  723. case D3DFMT_A8L8: *tex_format="D3DFMT_A8L8"; break;
  724. case D3DFMT_A4L4: *tex_format="D3DFMT_A4L4"; break;
  725. case D3DFMT_V8U8: *tex_format="D3DFMT_V8U8"; break;
  726. case D3DFMT_L6V5U5: *tex_format="D3DFMT_L6V5U5"; break;
  727. case D3DFMT_X8L8V8U8: *tex_format="D3DFMT_X8L8V8U8"; break;
  728. case D3DFMT_Q8W8V8U8: *tex_format="D3DFMT_Q8W8V8U8"; break;
  729. case D3DFMT_V16U16: *tex_format="D3DFMT_V16U16"; break;
  730. case D3DFMT_W11V11U10: *tex_format="D3DFMT_W11V11U10"; break;
  731. case D3DFMT_UYVY: *tex_format="D3DFMT_UYVY"; break;
  732. case D3DFMT_YUY2: *tex_format="D3DFMT_YUY2"; break;
  733. case D3DFMT_DXT1: *tex_format="D3DFMT_DXT1"; break;
  734. case D3DFMT_DXT2: *tex_format="D3DFMT_DXT2"; break;
  735. case D3DFMT_DXT3: *tex_format="D3DFMT_DXT3"; break;
  736. case D3DFMT_DXT4: *tex_format="D3DFMT_DXT4"; break;
  737. case D3DFMT_DXT5: *tex_format="D3DFMT_DXT5"; break;
  738. case D3DFMT_D16_LOCKABLE: *tex_format="D3DFMT_D16_LOCKABLE"; break;
  739. case D3DFMT_D32: *tex_format="D3DFMT_D32"; break;
  740. case D3DFMT_D15S1: *tex_format="D3DFMT_D15S1"; break;
  741. case D3DFMT_D24S8: *tex_format="D3DFMT_D24S8"; break;
  742. case D3DFMT_D16: *tex_format="D3DFMT_D16"; break;
  743. case D3DFMT_D24X8: *tex_format="D3DFMT_D24X8"; break;
  744. case D3DFMT_D24X4S4: *tex_format="D3DFMT_D24X4S4"; break;
  745. default: break;
  746. }
  747. }
  748. bool DX8Wrapper::Set_Render_Device(int dev, int width, int height, int bits, int windowed,
  749. bool resize_window,bool reset_device, bool restore_assets)
  750. {
  751. WWASSERT(IsInitted);
  752. WWASSERT(dev >= -1);
  753. WWASSERT(dev < _RenderDeviceNameTable.Count());
  754. /*
  755. ** If user has never selected a render device, start out with device 0
  756. */
  757. if ((CurRenderDevice == -1) && (dev == -1)) {
  758. CurRenderDevice = 0;
  759. } else if (dev != -1) {
  760. CurRenderDevice = dev;
  761. }
  762. /*
  763. ** If user doesn't want to change res, set the res variables to match the
  764. ** current resolution
  765. */
  766. if (width != -1) ResolutionWidth = width;
  767. if (height != -1) ResolutionHeight = height;
  768. // Initialize Render2DClass Screen Resolution
  769. Render2DClass::Set_Screen_Resolution( RectClass( 0, 0, ResolutionWidth, ResolutionHeight ) );
  770. if (bits != -1) BitDepth = bits;
  771. if (windowed != -1) IsWindowed = (windowed != 0);
  772. DX8Wrapper_IsWindowed = IsWindowed;
  773. WWDEBUG_SAY(("Attempting Set_Render_Device: name: %s (%s:%s), width: %d, height: %d, windowed: %d\n",
  774. _RenderDeviceNameTable[CurRenderDevice],_RenderDeviceDescriptionTable[CurRenderDevice].Get_Driver_Name(),
  775. _RenderDeviceDescriptionTable[CurRenderDevice].Get_Driver_Version(),ResolutionWidth,ResolutionHeight,(IsWindowed ? 1 : 0)));
  776. #ifdef _WINDOWS
  777. // PWG 4/13/2000 - changed so that if you say to resize the window it resizes
  778. // regardless of whether its windowed or not as OpenGL resizes its self around
  779. // the caption and edges of the window type you provide, so its important to
  780. // push the client area to be the size you really want.
  781. // if ( resize_window && windowed ) {
  782. if (resize_window) {
  783. // Get the current dimensions of the 'render area' of the window
  784. RECT rect = { 0 };
  785. ::GetClientRect (_Hwnd, &rect);
  786. // Is the window the correct size for this resolution?
  787. if ((rect.right-rect.left) != ResolutionWidth ||
  788. (rect.bottom-rect.top) != ResolutionHeight) {
  789. // Calculate what the main window's bounding rectangle should be to
  790. // accomodate this resolution
  791. rect.left = 0;
  792. rect.top = 0;
  793. rect.right = ResolutionWidth;
  794. rect.bottom = ResolutionHeight;
  795. DWORD dwstyle = ::GetWindowLong (_Hwnd, GWL_STYLE);
  796. AdjustWindowRect (&rect, dwstyle, FALSE);
  797. // Resize the window to fit this resolution
  798. if (!windowed)
  799. ::SetWindowPos(_Hwnd, HWND_TOPMOST, 0, 0, rect.right-rect.left, rect.bottom-rect.top,SWP_NOSIZE |SWP_NOMOVE);
  800. else
  801. ::SetWindowPos (_Hwnd,
  802. NULL,
  803. 0,
  804. 0,
  805. rect.right-rect.left,
  806. rect.bottom-rect.top,
  807. SWP_NOZORDER | SWP_NOMOVE);
  808. }
  809. }
  810. #endif
  811. //must be either resetting existing device or creating a new one.
  812. WWASSERT(reset_device || D3DDevice == NULL);
  813. /*
  814. ** Initialize values for D3DPRESENT_PARAMETERS members.
  815. */
  816. ::ZeroMemory(&_PresentParameters, sizeof(D3DPRESENT_PARAMETERS));
  817. _PresentParameters.BackBufferWidth = ResolutionWidth;
  818. _PresentParameters.BackBufferHeight = ResolutionHeight;
  819. _PresentParameters.BackBufferCount = IsWindowed ? 1 : 2;
  820. _PresentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
  821. //I changed this to discard all the time (even when full-screen) since that the most efficient. 07-16-03 MW:
  822. _PresentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;//IsWindowed ? D3DSWAPEFFECT_DISCARD : D3DSWAPEFFECT_FLIP; // Shouldn't this be D3DSWAPEFFECT_FLIP?
  823. _PresentParameters.hDeviceWindow = _Hwnd;
  824. _PresentParameters.Windowed = IsWindowed;
  825. _PresentParameters.EnableAutoDepthStencil = TRUE; // Driver will attempt to match Z-buffer depth
  826. _PresentParameters.Flags=0; // We're not going to lock the backbuffer
  827. _PresentParameters.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
  828. _PresentParameters.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
  829. /*
  830. ** Set up the buffer formats. Several issues here:
  831. ** - if in windowed mode, the backbuffer must use the current display format.
  832. ** - the depth buffer must use
  833. */
  834. if (IsWindowed) {
  835. D3DDISPLAYMODE desktop_mode;
  836. ::ZeroMemory(&desktop_mode, sizeof(D3DDISPLAYMODE));
  837. D3DInterface->GetAdapterDisplayMode( CurRenderDevice, &desktop_mode );
  838. DisplayFormat=_PresentParameters.BackBufferFormat = desktop_mode.Format;
  839. // In windowed mode, define the bitdepth from desktop mode (as it can't be changed)
  840. switch (_PresentParameters.BackBufferFormat) {
  841. case D3DFMT_X8R8G8B8:
  842. case D3DFMT_A8R8G8B8:
  843. case D3DFMT_R8G8B8: BitDepth=32; break;
  844. case D3DFMT_A4R4G4B4:
  845. case D3DFMT_A1R5G5B5:
  846. case D3DFMT_R5G6B5: BitDepth=16; break;
  847. case D3DFMT_L8:
  848. case D3DFMT_A8:
  849. case D3DFMT_P8: BitDepth=8; break;
  850. default:
  851. // Unknown backbuffer format probably means the device can't do windowed
  852. return false;
  853. }
  854. if (BitDepth==32 && D3DInterface->CheckDeviceType(0,D3DDEVTYPE_HAL,desktop_mode.Format,D3DFMT_A8R8G8B8, TRUE) == D3D_OK)
  855. { //promote 32-bit modes to include destination alpha
  856. _PresentParameters.BackBufferFormat = D3DFMT_A8R8G8B8;
  857. }
  858. /*
  859. ** Find a appropriate Z buffer
  860. */
  861. if (!Find_Z_Mode(DisplayFormat,_PresentParameters.BackBufferFormat,&_PresentParameters.AutoDepthStencilFormat))
  862. {
  863. // If opening 32 bit mode failed, try 16 bit, even if the desktop happens to be 32 bit
  864. if (BitDepth==32) {
  865. BitDepth=16;
  866. _PresentParameters.BackBufferFormat=D3DFMT_R5G6B5;
  867. if (!Find_Z_Mode(_PresentParameters.BackBufferFormat,_PresentParameters.BackBufferFormat,&_PresentParameters.AutoDepthStencilFormat)) {
  868. _PresentParameters.AutoDepthStencilFormat=D3DFMT_UNKNOWN;
  869. }
  870. }
  871. else {
  872. _PresentParameters.AutoDepthStencilFormat=D3DFMT_UNKNOWN;
  873. }
  874. }
  875. } else {
  876. /*
  877. ** Try to find a mode that matches the user's desired bit-depth.
  878. */
  879. Find_Color_And_Z_Mode(ResolutionWidth,ResolutionHeight,BitDepth,&DisplayFormat,
  880. &_PresentParameters.BackBufferFormat,&_PresentParameters.AutoDepthStencilFormat);
  881. }
  882. /*
  883. ** Time to actually create the device.
  884. */
  885. if (_PresentParameters.AutoDepthStencilFormat==D3DFMT_UNKNOWN) {
  886. if (BitDepth==32) {
  887. _PresentParameters.AutoDepthStencilFormat=D3DFMT_D32;
  888. }
  889. else {
  890. _PresentParameters.AutoDepthStencilFormat=D3DFMT_D16;
  891. }
  892. }
  893. StringClass displayFormat;
  894. StringClass backbufferFormat;
  895. Get_Format_Name(DisplayFormat,&displayFormat);
  896. Get_Format_Name(_PresentParameters.BackBufferFormat,&backbufferFormat);
  897. WWDEBUG_SAY(("Using Display/BackBuffer Formats: %s/%s\n",displayFormat,backbufferFormat));
  898. bool ret;
  899. if (reset_device)
  900. ret = Reset_Device(restore_assets); //reset device without restoring data - we're likely switching out of the app.
  901. else
  902. ret = Create_Device();
  903. WWDEBUG_SAY(("Reset/Create_Device done, reset_device=%d, restore_assets=%d\n", reset_device, restore_assets));
  904. return ret;
  905. }
  906. bool DX8Wrapper::Set_Next_Render_Device(void)
  907. {
  908. int new_dev = (CurRenderDevice + 1) % _RenderDeviceNameTable.Count();
  909. return Set_Render_Device(new_dev);
  910. }
  911. bool DX8Wrapper::Toggle_Windowed(void)
  912. {
  913. #ifdef WW3D_DX8
  914. // State OK?
  915. assert (IsInitted);
  916. if (IsInitted) {
  917. // Get information about the current render device's resolutions
  918. const RenderDeviceDescClass &render_device = Get_Render_Device_Desc ();
  919. const DynamicVectorClass<ResolutionDescClass> &resolutions = render_device.Enumerate_Resolutions ();
  920. // Loop through all the resolutions supported by the current device.
  921. // If we aren't currently running under one of these resolutions,
  922. // then we should probably to the closest resolution before
  923. // toggling the windowed state.
  924. int curr_res = -1;
  925. for (int res = 0;
  926. (res < resolutions.Count ()) && (curr_res == -1);
  927. res ++) {
  928. // Is this the resolution we are looking for?
  929. if ((resolutions[res].Width == ResolutionWidth) &&
  930. (resolutions[res].Height == ResolutionHeight) &&
  931. (resolutions[res].BitDepth == BitDepth)) {
  932. curr_res = res;
  933. }
  934. }
  935. if (curr_res == -1) {
  936. // We don't match any of the standard resolutions,
  937. // so set the first resolution and toggle the windowed state.
  938. return Set_Device_Resolution (resolutions[0].Width,
  939. resolutions[0].Height,
  940. resolutions[0].BitDepth,
  941. !IsWindowed, true);
  942. } else {
  943. // Toggle the windowed state
  944. return Set_Device_Resolution (-1, -1, -1, !IsWindowed, true);
  945. }
  946. }
  947. #endif //WW3D_DX8
  948. return false;
  949. }
  950. void DX8Wrapper::Set_Swap_Interval(int swap)
  951. {
  952. switch (swap) {
  953. case 0: _PresentParameters.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; break;
  954. case 1: _PresentParameters.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE ; break;
  955. case 2: _PresentParameters.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_TWO; break;
  956. case 3: _PresentParameters.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_THREE; break;
  957. default: _PresentParameters.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE ; break;
  958. }
  959. Reset_Device();
  960. }
  961. int DX8Wrapper::Get_Swap_Interval(void)
  962. {
  963. return _PresentParameters.FullScreen_PresentationInterval;
  964. }
  965. bool DX8Wrapper::Has_Stencil(void)
  966. {
  967. bool has_stencil = (_PresentParameters.AutoDepthStencilFormat == D3DFMT_D24S8 ||
  968. _PresentParameters.AutoDepthStencilFormat == D3DFMT_D24X4S4);
  969. return has_stencil;
  970. }
  971. int DX8Wrapper::Get_Render_Device_Count(void)
  972. {
  973. return _RenderDeviceNameTable.Count();
  974. }
  975. int DX8Wrapper::Get_Render_Device(void)
  976. {
  977. assert(IsInitted);
  978. return CurRenderDevice;
  979. }
  980. const RenderDeviceDescClass & DX8Wrapper::Get_Render_Device_Desc(int deviceidx)
  981. {
  982. WWASSERT(IsInitted);
  983. if ((deviceidx == -1) && (CurRenderDevice == -1)) {
  984. CurRenderDevice = 0;
  985. }
  986. // if the device index is -1 then we want the current device
  987. if (deviceidx == -1) {
  988. WWASSERT(CurRenderDevice >= 0);
  989. WWASSERT(CurRenderDevice < _RenderDeviceNameTable.Count());
  990. return _RenderDeviceDescriptionTable[CurRenderDevice];
  991. }
  992. // We can only ask for multiple device information if the devices
  993. // have been detected.
  994. WWASSERT(deviceidx >= 0);
  995. WWASSERT(deviceidx < _RenderDeviceNameTable.Count());
  996. return _RenderDeviceDescriptionTable[deviceidx];
  997. }
  998. const char * DX8Wrapper::Get_Render_Device_Name(int device_index)
  999. {
  1000. device_index = device_index % _RenderDeviceShortNameTable.Count();
  1001. return _RenderDeviceShortNameTable[device_index];
  1002. }
  1003. bool DX8Wrapper::Set_Device_Resolution(int width,int height,int bits,int windowed, bool resize_window)
  1004. {
  1005. if (D3DDevice != NULL) {
  1006. if (width != -1) {
  1007. _PresentParameters.BackBufferWidth = ResolutionWidth = width;
  1008. }
  1009. if (height != -1) {
  1010. _PresentParameters.BackBufferHeight = ResolutionHeight = height;
  1011. }
  1012. if (resize_window)
  1013. {
  1014. // Get the current dimensions of the 'render area' of the window
  1015. RECT rect = { 0 };
  1016. ::GetClientRect (_Hwnd, &rect);
  1017. // Is the window the correct size for this resolution?
  1018. if ((rect.right-rect.left) != ResolutionWidth ||
  1019. (rect.bottom-rect.top) != ResolutionHeight)
  1020. {
  1021. // Calculate what the main window's bounding rectangle should be to
  1022. // accomodate this resolution
  1023. rect.left = 0;
  1024. rect.top = 0;
  1025. rect.right = ResolutionWidth;
  1026. rect.bottom = ResolutionHeight;
  1027. DWORD dwstyle = ::GetWindowLong (_Hwnd, GWL_STYLE);
  1028. AdjustWindowRect (&rect, dwstyle, FALSE);
  1029. // Resize the window to fit this resolution
  1030. if (!windowed)
  1031. ::SetWindowPos(_Hwnd, HWND_TOPMOST, 0, 0, rect.right-rect.left, rect.bottom-rect.top,SWP_NOSIZE |SWP_NOMOVE);
  1032. else
  1033. ::SetWindowPos (_Hwnd,
  1034. NULL,
  1035. 0,
  1036. 0,
  1037. rect.right-rect.left,
  1038. rect.bottom-rect.top,
  1039. SWP_NOZORDER | SWP_NOMOVE);
  1040. }
  1041. }
  1042. #pragma message("TODO: support changing windowed status and changing the bit depth")
  1043. return Reset_Device();
  1044. } else {
  1045. return false;
  1046. }
  1047. }
  1048. void DX8Wrapper::Get_Device_Resolution(int & set_w,int & set_h,int & set_bits,bool & set_windowed)
  1049. {
  1050. WWASSERT(IsInitted);
  1051. set_w = ResolutionWidth;
  1052. set_h = ResolutionHeight;
  1053. set_bits = BitDepth;
  1054. set_windowed = IsWindowed;
  1055. return ;
  1056. }
  1057. void DX8Wrapper::Get_Render_Target_Resolution(int & set_w,int & set_h,int & set_bits,bool & set_windowed)
  1058. {
  1059. WWASSERT(IsInitted);
  1060. if (CurrentRenderTarget != NULL) {
  1061. D3DSURFACE_DESC info;
  1062. CurrentRenderTarget->GetDesc (&info);
  1063. set_w = info.Width;
  1064. set_h = info.Height;
  1065. set_bits = BitDepth; // should we get the actual bit depth of the target?
  1066. set_windowed = IsWindowed; // this doesn't really make sense for render targets (shouldn't matter)...
  1067. } else {
  1068. Get_Device_Resolution (set_w, set_h, set_bits, set_windowed);
  1069. }
  1070. return ;
  1071. }
  1072. bool DX8Wrapper::Registry_Save_Render_Device( const char * sub_key )
  1073. {
  1074. int width, height, depth;
  1075. bool windowed;
  1076. Get_Device_Resolution(width, height, depth, windowed);
  1077. return Registry_Save_Render_Device(sub_key, CurRenderDevice, ResolutionWidth, ResolutionHeight, BitDepth, IsWindowed, TextureBitDepth);
  1078. }
  1079. bool DX8Wrapper::Registry_Save_Render_Device( const char *sub_key, int device, int width, int height, int depth, bool windowed, int texture_depth)
  1080. {
  1081. RegistryClass * registry = W3DNEW RegistryClass( sub_key );
  1082. WWASSERT( registry );
  1083. if ( !registry->Is_Valid() ) {
  1084. delete registry;
  1085. WWDEBUG_SAY(( "Error getting Registry\n" ));
  1086. return false;
  1087. }
  1088. registry->Set_String( VALUE_NAME_RENDER_DEVICE_NAME,
  1089. _RenderDeviceShortNameTable[device] );
  1090. registry->Set_Int( VALUE_NAME_RENDER_DEVICE_WIDTH, width );
  1091. registry->Set_Int( VALUE_NAME_RENDER_DEVICE_HEIGHT, height );
  1092. registry->Set_Int( VALUE_NAME_RENDER_DEVICE_DEPTH, depth );
  1093. registry->Set_Int( VALUE_NAME_RENDER_DEVICE_WINDOWED, windowed );
  1094. registry->Set_Int( VALUE_NAME_RENDER_DEVICE_TEXTURE_DEPTH, texture_depth );
  1095. delete registry;
  1096. return true;
  1097. }
  1098. bool DX8Wrapper::Registry_Load_Render_Device( const char * sub_key, bool resize_window )
  1099. {
  1100. char name[ 200 ];
  1101. int width,height,depth,windowed;
  1102. if ( Registry_Load_Render_Device( sub_key,
  1103. name,
  1104. sizeof(name),
  1105. width,
  1106. height,
  1107. depth,
  1108. windowed,
  1109. TextureBitDepth) &&
  1110. (*name != 0))
  1111. {
  1112. WWDEBUG_SAY(( "Device %s (%d X %d) %d bit windowed:%d\n", name,width,height,depth,windowed));
  1113. if (TextureBitDepth==16 || TextureBitDepth==32) {
  1114. // WWDEBUG_SAY(( "Texture depth %d\n", TextureBitDepth));
  1115. } else {
  1116. WWDEBUG_SAY(( "Invalid texture depth %d, switching to 16 bits\n", TextureBitDepth));
  1117. TextureBitDepth=16;
  1118. }
  1119. // _RenderDeviceDescriptionTable.
  1120. if ( Set_Render_Device( name, width,height,depth,windowed, resize_window ) != true) {
  1121. if (depth==16) depth=32;
  1122. else depth=16;
  1123. if ( Set_Render_Device( name, width,height,depth,windowed, resize_window ) == true) {
  1124. return true;
  1125. }
  1126. if (depth==16) depth=32;
  1127. else depth=16;
  1128. // we'll test resolutions down, so if start is 640, increase to begin with...
  1129. if (width==640) {
  1130. width=1024;
  1131. height=768;
  1132. }
  1133. for(;;) {
  1134. if (width>2048) {
  1135. width=2048;
  1136. height=1536;
  1137. }
  1138. else if (width>1920) {
  1139. width=1920;
  1140. height=1440;
  1141. }
  1142. else if (width>1600) {
  1143. width=1600;
  1144. height=1200;
  1145. }
  1146. else if (width>1280) {
  1147. width=1280;
  1148. height=1024;
  1149. }
  1150. else if (width>1024) {
  1151. width=1024;
  1152. height=768;
  1153. }
  1154. else if (width>800) {
  1155. width=800;
  1156. height=600;
  1157. }
  1158. else if (width!=640) {
  1159. width=640;
  1160. height=480;
  1161. }
  1162. else {
  1163. return Set_Any_Render_Device();
  1164. }
  1165. for (int i=0;i<2;++i) {
  1166. if ( Set_Render_Device( name, width,height,depth,windowed, resize_window ) == true) {
  1167. return true;
  1168. }
  1169. if (depth==16) depth=32;
  1170. else depth=16;
  1171. }
  1172. }
  1173. }
  1174. return true;
  1175. }
  1176. WWDEBUG_SAY(( "Error getting Registry\n" ));
  1177. return Set_Any_Render_Device();
  1178. }
  1179. 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)
  1180. {
  1181. RegistryClass registry( sub_key );
  1182. if ( registry.Is_Valid() ) {
  1183. registry.Get_String( VALUE_NAME_RENDER_DEVICE_NAME,
  1184. device, device_len);
  1185. width = registry.Get_Int( VALUE_NAME_RENDER_DEVICE_WIDTH, -1 );
  1186. height = registry.Get_Int( VALUE_NAME_RENDER_DEVICE_HEIGHT, -1 );
  1187. depth = registry.Get_Int( VALUE_NAME_RENDER_DEVICE_DEPTH, -1 );
  1188. windowed = registry.Get_Int( VALUE_NAME_RENDER_DEVICE_WINDOWED, -1 );
  1189. texture_depth = registry.Get_Int( VALUE_NAME_RENDER_DEVICE_TEXTURE_DEPTH, -1 );
  1190. return true;
  1191. }
  1192. *device=0;
  1193. width=-1;
  1194. height=-1;
  1195. depth=-1;
  1196. windowed=-1;
  1197. texture_depth=-1;
  1198. return false;
  1199. }
  1200. bool DX8Wrapper::Find_Color_And_Z_Mode(int resx,int resy,int bitdepth,D3DFORMAT * set_colorbuffer,D3DFORMAT * set_backbuffer,D3DFORMAT * set_zmode)
  1201. {
  1202. static D3DFORMAT _formats16[] =
  1203. {
  1204. D3DFMT_R5G6B5,
  1205. D3DFMT_X1R5G5B5,
  1206. D3DFMT_A1R5G5B5
  1207. };
  1208. static D3DFORMAT _formats32[] =
  1209. {
  1210. D3DFMT_A8R8G8B8,
  1211. D3DFMT_X8R8G8B8,
  1212. D3DFMT_R8G8B8,
  1213. };
  1214. /*
  1215. ** Select the table that we're going to use to search for a valid backbuffer format
  1216. */
  1217. D3DFORMAT * format_table = NULL;
  1218. int format_count = 0;
  1219. if (BitDepth == 16) {
  1220. format_table = _formats16;
  1221. format_count = sizeof(_formats16) / sizeof(D3DFORMAT);
  1222. } else {
  1223. format_table = _formats32;
  1224. format_count = sizeof(_formats32) / sizeof(D3DFORMAT);
  1225. }
  1226. /*
  1227. ** now search for a valid format
  1228. */
  1229. bool found = false;
  1230. unsigned int mode = 0;
  1231. for (int format_index=0; format_index < format_count; format_index++) {
  1232. found |= Find_Color_Mode(format_table[format_index],resx,resy,&mode);
  1233. if (found) break;
  1234. }
  1235. if (!found) {
  1236. return false;
  1237. } else {
  1238. *set_backbuffer=*set_colorbuffer = format_table[format_index];
  1239. }
  1240. if (bitdepth==32 && *set_colorbuffer == D3DFMT_X8R8G8B8 && D3DInterface->CheckDeviceType(0,D3DDEVTYPE_HAL,*set_colorbuffer,D3DFMT_A8R8G8B8, TRUE) == D3D_OK)
  1241. { //promote 32-bit modes to include destination alpha when supported
  1242. *set_backbuffer = D3DFMT_A8R8G8B8;
  1243. }
  1244. /*
  1245. ** We found a backbuffer format, now find a zbuffer format
  1246. */
  1247. return Find_Z_Mode(*set_colorbuffer,*set_backbuffer, set_zmode);
  1248. };
  1249. // find the resolution mode with at least resx,resy with the highest supported
  1250. // refresh rate
  1251. bool DX8Wrapper::Find_Color_Mode(D3DFORMAT colorbuffer, int resx, int resy, UINT *mode)
  1252. {
  1253. UINT i,j,modemax;
  1254. UINT rx,ry;
  1255. D3DDISPLAYMODE dmode;
  1256. ::ZeroMemory(&dmode, sizeof(D3DDISPLAYMODE));
  1257. rx=(unsigned int) resx;
  1258. ry=(unsigned int) resy;
  1259. bool found=false;
  1260. modemax=D3DInterface->GetAdapterModeCount(D3DADAPTER_DEFAULT);
  1261. i=0;
  1262. while (i<modemax && !found)
  1263. {
  1264. D3DInterface->EnumAdapterModes(D3DADAPTER_DEFAULT, i, &dmode);
  1265. if (dmode.Width==rx && dmode.Height==ry && dmode.Format==colorbuffer) {
  1266. WWDEBUG_SAY(("Found valid color mode. Width = %d Height = %d Format = %d\r\n",dmode.Width,dmode.Height,dmode.Format));
  1267. found=true;
  1268. }
  1269. i++;
  1270. }
  1271. i--; // this is the first valid mode
  1272. // no match
  1273. if (!found) {
  1274. WWDEBUG_SAY(("Failed to find a valid color mode\r\n"));
  1275. return false;
  1276. }
  1277. // go to the highest refresh rate in this mode
  1278. bool stillok=true;
  1279. j=i;
  1280. while (j<modemax && stillok)
  1281. {
  1282. D3DInterface->EnumAdapterModes(D3DADAPTER_DEFAULT, j, &dmode);
  1283. if (dmode.Width==rx && dmode.Height==ry && dmode.Format==colorbuffer)
  1284. stillok=true; else stillok=false;
  1285. j++;
  1286. }
  1287. if (stillok==false) *mode=j-2;
  1288. else *mode=i;
  1289. return true;
  1290. }
  1291. // Helper function to find a Z buffer mode for the colorbuffer
  1292. // Will look for greatest Z precision
  1293. bool DX8Wrapper::Find_Z_Mode(D3DFORMAT colorbuffer,D3DFORMAT backbuffer, D3DFORMAT *zmode)
  1294. {
  1295. //MW: Swapped the next 2 tests so that Stencil modes get tested first.
  1296. if (Test_Z_Mode(colorbuffer,backbuffer,D3DFMT_D24S8))
  1297. {
  1298. *zmode=D3DFMT_D24S8;
  1299. WWDEBUG_SAY(("Found zbuffer mode D3DFMT_D24S8\n"));
  1300. return true;
  1301. }
  1302. if (Test_Z_Mode(colorbuffer,backbuffer,D3DFMT_D32))
  1303. {
  1304. *zmode=D3DFMT_D32;
  1305. WWDEBUG_SAY(("Found zbuffer mode D3DFMT_D32\n"));
  1306. return true;
  1307. }
  1308. if (Test_Z_Mode(colorbuffer,backbuffer,D3DFMT_D24X8))
  1309. {
  1310. *zmode=D3DFMT_D24X8;
  1311. WWDEBUG_SAY(("Found zbuffer mode D3DFMT_D24X8\n"));
  1312. return true;
  1313. }
  1314. if (Test_Z_Mode(colorbuffer,backbuffer,D3DFMT_D24X4S4))
  1315. {
  1316. *zmode=D3DFMT_D24X4S4;
  1317. WWDEBUG_SAY(("Found zbuffer mode D3DFMT_D24X4S4\n"));
  1318. return true;
  1319. }
  1320. if (Test_Z_Mode(colorbuffer,backbuffer,D3DFMT_D16))
  1321. {
  1322. *zmode=D3DFMT_D16;
  1323. WWDEBUG_SAY(("Found zbuffer mode D3DFMT_D16\n"));
  1324. return true;
  1325. }
  1326. if (Test_Z_Mode(colorbuffer,backbuffer,D3DFMT_D15S1))
  1327. {
  1328. *zmode=D3DFMT_D15S1;
  1329. WWDEBUG_SAY(("Found zbuffer mode D3DFMT_D15S1\n"));
  1330. return true;
  1331. }
  1332. // can't find a match
  1333. WWDEBUG_SAY(("Failed to find a valid zbuffer mode\r\n"));
  1334. return false;
  1335. }
  1336. bool DX8Wrapper::Test_Z_Mode(D3DFORMAT colorbuffer,D3DFORMAT backbuffer, D3DFORMAT zmode)
  1337. {
  1338. // See if we have this mode first
  1339. if (FAILED(D3DInterface->CheckDeviceFormat(D3DADAPTER_DEFAULT,WW3D_DEVTYPE,
  1340. colorbuffer,D3DUSAGE_DEPTHSTENCIL,D3DRTYPE_SURFACE,zmode)))
  1341. {
  1342. WWDEBUG_SAY(("CheckDeviceFormat failed. Colorbuffer format = %d Zbufferformat = %d\n",colorbuffer,zmode));
  1343. return false;
  1344. }
  1345. // Then see if it matches the color buffer
  1346. if(FAILED(D3DInterface->CheckDepthStencilMatch(D3DADAPTER_DEFAULT, WW3D_DEVTYPE,
  1347. colorbuffer,backbuffer,zmode)))
  1348. {
  1349. WWDEBUG_SAY(("CheckDepthStencilMatch failed. Colorbuffer format = %d Backbuffer format = %d Zbufferformat = %d\n",colorbuffer,backbuffer,zmode));
  1350. return false;
  1351. }
  1352. return true;
  1353. }
  1354. void DX8Wrapper::Reset_Statistics()
  1355. {
  1356. matrix_changes = 0;
  1357. material_changes = 0;
  1358. vertex_buffer_changes = 0;
  1359. index_buffer_changes = 0;
  1360. light_changes = 0;
  1361. texture_changes = 0;
  1362. render_state_changes =0;
  1363. texture_stage_state_changes =0;
  1364. draw_calls =0;
  1365. number_of_DX8_calls = 0;
  1366. last_frame_matrix_changes = 0;
  1367. last_frame_material_changes = 0;
  1368. last_frame_vertex_buffer_changes = 0;
  1369. last_frame_index_buffer_changes = 0;
  1370. last_frame_light_changes = 0;
  1371. last_frame_texture_changes = 0;
  1372. last_frame_render_state_changes = 0;
  1373. last_frame_texture_stage_state_changes = 0;
  1374. last_frame_number_of_DX8_calls = 0;
  1375. last_frame_draw_calls =0;
  1376. }
  1377. void DX8Wrapper::Begin_Statistics()
  1378. {
  1379. matrix_changes=0;
  1380. material_changes=0;
  1381. vertex_buffer_changes=0;
  1382. index_buffer_changes=0;
  1383. light_changes=0;
  1384. texture_changes = 0;
  1385. render_state_changes =0;
  1386. texture_stage_state_changes =0;
  1387. number_of_DX8_calls=0;
  1388. draw_calls=0;
  1389. }
  1390. void DX8Wrapper::End_Statistics()
  1391. {
  1392. last_frame_matrix_changes=matrix_changes;
  1393. last_frame_material_changes=material_changes;
  1394. last_frame_vertex_buffer_changes=vertex_buffer_changes;
  1395. last_frame_index_buffer_changes=index_buffer_changes;
  1396. last_frame_light_changes=light_changes;
  1397. last_frame_texture_changes = texture_changes;
  1398. last_frame_render_state_changes = render_state_changes;
  1399. last_frame_texture_stage_state_changes = texture_stage_state_changes;
  1400. last_frame_number_of_DX8_calls=number_of_DX8_calls;
  1401. last_frame_draw_calls=draw_calls;
  1402. }
  1403. unsigned DX8Wrapper::Get_Last_Frame_Matrix_Changes() { return last_frame_matrix_changes; }
  1404. unsigned DX8Wrapper::Get_Last_Frame_Material_Changes() { return last_frame_material_changes; }
  1405. unsigned DX8Wrapper::Get_Last_Frame_Vertex_Buffer_Changes() { return last_frame_vertex_buffer_changes; }
  1406. unsigned DX8Wrapper::Get_Last_Frame_Index_Buffer_Changes() { return last_frame_index_buffer_changes; }
  1407. unsigned DX8Wrapper::Get_Last_Frame_Light_Changes() { return last_frame_light_changes; }
  1408. unsigned DX8Wrapper::Get_Last_Frame_Texture_Changes() { return last_frame_texture_changes; }
  1409. unsigned DX8Wrapper::Get_Last_Frame_Render_State_Changes() { return last_frame_render_state_changes; }
  1410. unsigned DX8Wrapper::Get_Last_Frame_Texture_Stage_State_Changes() { return last_frame_texture_stage_state_changes; }
  1411. unsigned DX8Wrapper::Get_Last_Frame_DX8_Calls() { return last_frame_number_of_DX8_calls; }
  1412. unsigned DX8Wrapper::Get_Last_Frame_Draw_Calls() { return last_frame_draw_calls; }
  1413. unsigned long DX8Wrapper::Get_FrameCount(void) {return FrameCount;}
  1414. void DX8_Assert()
  1415. {
  1416. WWASSERT(DX8Wrapper::_Get_D3D8());
  1417. DX8_THREAD_ASSERT();
  1418. }
  1419. void DX8Wrapper::Begin_Scene(void)
  1420. {
  1421. DX8_THREAD_ASSERT();
  1422. #if ENABLE_EMBEDDED_BROWSER
  1423. DX8WebBrowser::Update();
  1424. #endif
  1425. DX8CALL(BeginScene());
  1426. DX8WebBrowser::Update();
  1427. }
  1428. void DX8Wrapper::End_Scene(bool flip_frames)
  1429. {
  1430. DX8_THREAD_ASSERT();
  1431. DX8CALL(EndScene());
  1432. DX8WebBrowser::Render(0);
  1433. if (flip_frames) {
  1434. DX8_Assert();
  1435. HRESULT hr;
  1436. {
  1437. WWPROFILE("DX8Device::Present()");
  1438. hr=_Get_D3D_Device8()->Present(NULL, NULL, NULL, NULL);
  1439. }
  1440. number_of_DX8_calls++;
  1441. if (SUCCEEDED(hr)) {
  1442. #ifdef EXTENDED_STATS
  1443. if (stats.m_sleepTime) {
  1444. ::Sleep(stats.m_sleepTime);
  1445. }
  1446. #endif
  1447. IsDeviceLost=false;
  1448. FrameCount++;
  1449. }
  1450. else {
  1451. IsDeviceLost=true;
  1452. }
  1453. // If the device was lost we need to check for cooperative level and possibly reset the device
  1454. if (hr==D3DERR_DEVICELOST) {
  1455. hr=_Get_D3D_Device8()->TestCooperativeLevel();
  1456. if (hr==D3DERR_DEVICENOTRESET) {
  1457. Reset_Device();
  1458. }
  1459. else {
  1460. // Sleep it not active
  1461. ThreadClass::Sleep_Ms(200);
  1462. }
  1463. }
  1464. else {
  1465. DX8_ErrorCode(hr);
  1466. }
  1467. }
  1468. // Each frame, release all of the buffers and textures.
  1469. Set_Vertex_Buffer(NULL);
  1470. Set_Index_Buffer(NULL,0);
  1471. for (int i=0;i<CurrentCaps->Get_Max_Textures_Per_Pass();++i) Set_Texture(i,NULL);
  1472. Set_Material(NULL);
  1473. }
  1474. void DX8Wrapper::Flip_To_Primary(void)
  1475. {
  1476. // If we are fullscreen and the current frame is odd then we need
  1477. // to force a page flip to ensure that the first buffer in the flipping
  1478. // chain is the one visible.
  1479. if (!IsWindowed) {
  1480. DX8_Assert();
  1481. int numBuffers = (_PresentParameters.BackBufferCount + 1);
  1482. int visibleBuffer = (FrameCount % numBuffers);
  1483. int flipCount = ((numBuffers - visibleBuffer) % numBuffers);
  1484. int resetAttempts = 0;
  1485. while ((flipCount > 0) && (resetAttempts < 3)) {
  1486. HRESULT hr = _Get_D3D_Device8()->TestCooperativeLevel();
  1487. if (FAILED(hr)) {
  1488. WWDEBUG_SAY(("TestCooperativeLevel Failed!\n"));
  1489. if (D3DERR_DEVICELOST == hr) {
  1490. IsDeviceLost=true;
  1491. WWDEBUG_SAY(("DEVICELOST: Cannot flip to primary.\n"));
  1492. return;
  1493. }
  1494. IsDeviceLost=false;
  1495. if (D3DERR_DEVICENOTRESET == hr) {
  1496. WWDEBUG_SAY(("DEVICENOTRESET\n"));
  1497. Reset_Device();
  1498. resetAttempts++;
  1499. }
  1500. } else {
  1501. WWDEBUG_SAY(("Flipping: %ld\n", FrameCount));
  1502. hr = _Get_D3D_Device8()->Present(NULL, NULL, NULL, NULL);
  1503. if (SUCCEEDED(hr)) {
  1504. IsDeviceLost=false;
  1505. FrameCount++;
  1506. WWDEBUG_SAY(("Flip to primary succeeded %ld\n", FrameCount));
  1507. }
  1508. else {
  1509. IsDeviceLost=true;
  1510. }
  1511. }
  1512. --flipCount;
  1513. }
  1514. }
  1515. }
  1516. //**********************************************************************************************
  1517. //! Clear current render device
  1518. /*! KM
  1519. /* 5/17/02 KM Fixed support for render to texture with depth/stencil buffers
  1520. */
  1521. void DX8Wrapper::Clear(bool clear_color, bool clear_z_stencil, const Vector3 &color, float dest_alpha, float z, unsigned int stencil)
  1522. {
  1523. DX8_THREAD_ASSERT();
  1524. // If we try to clear a stencil buffer which is not there, the entire call will fail
  1525. // KJM fixed this to get format from back buffer (incase render to texture is used)
  1526. /*bool has_stencil = ( _PresentParameters.AutoDepthStencilFormat == D3DFMT_D15S1 ||
  1527. _PresentParameters.AutoDepthStencilFormat == D3DFMT_D24S8 ||
  1528. _PresentParameters.AutoDepthStencilFormat == D3DFMT_D24X4S4);*/
  1529. bool has_stencil=false;
  1530. IDirect3DSurface8* depthbuffer;
  1531. _Get_D3D_Device8()->GetDepthStencilSurface(&depthbuffer);
  1532. number_of_DX8_calls++;
  1533. if (depthbuffer)
  1534. {
  1535. D3DSURFACE_DESC desc;
  1536. depthbuffer->GetDesc(&desc);
  1537. has_stencil=
  1538. (
  1539. desc.Format==D3DFMT_D15S1 ||
  1540. desc.Format==D3DFMT_D24S8 ||
  1541. desc.Format==D3DFMT_D24X4S4
  1542. );
  1543. // release ref
  1544. depthbuffer->Release();
  1545. }
  1546. DWORD flags = 0;
  1547. if (clear_color) flags |= D3DCLEAR_TARGET;
  1548. if (clear_z_stencil) flags |= D3DCLEAR_ZBUFFER;
  1549. if (clear_z_stencil && has_stencil) flags |= D3DCLEAR_STENCIL;
  1550. if (flags)
  1551. {
  1552. DX8CALL(Clear(0, NULL, flags, Convert_Color(color,dest_alpha), z, stencil));
  1553. }
  1554. }
  1555. void DX8Wrapper::Set_Viewport(CONST D3DVIEWPORT8* pViewport)
  1556. {
  1557. DX8_THREAD_ASSERT();
  1558. DX8CALL(SetViewport(pViewport));
  1559. }
  1560. // ----------------------------------------------------------------------------
  1561. //
  1562. // Set vertex buffer. A reference to previous vertex buffer is released and
  1563. // this one is assigned the current vertex buffer. The DX8 vertex buffer will
  1564. // actually be set in Apply() which is called by Draw_Indexed_Triangles().
  1565. //
  1566. // ----------------------------------------------------------------------------
  1567. void DX8Wrapper::Set_Vertex_Buffer(const VertexBufferClass* vb, unsigned stream)
  1568. {
  1569. render_state.vba_offset=0;
  1570. render_state.vba_count=0;
  1571. if (render_state.vertex_buffers[stream]) {
  1572. render_state.vertex_buffers[stream]->Release_Engine_Ref();
  1573. }
  1574. REF_PTR_SET(render_state.vertex_buffers[stream],const_cast<VertexBufferClass*>(vb));
  1575. if (vb) {
  1576. vb->Add_Engine_Ref();
  1577. render_state.vertex_buffer_types[stream]=vb->Type();
  1578. }
  1579. else {
  1580. render_state.vertex_buffer_types[stream]=BUFFER_TYPE_INVALID;
  1581. }
  1582. render_state_changed|=VERTEX_BUFFER_CHANGED;
  1583. }
  1584. // ----------------------------------------------------------------------------
  1585. //
  1586. // Set index buffer. A reference to previous index buffer is released and
  1587. // this one is assigned the current index buffer. The DX8 index buffer will
  1588. // actually be set in Apply() which is called by Draw_Indexed_Triangles().
  1589. //
  1590. // ----------------------------------------------------------------------------
  1591. void DX8Wrapper::Set_Index_Buffer(const IndexBufferClass* ib,unsigned short index_base_offset)
  1592. {
  1593. render_state.iba_offset=0;
  1594. if (render_state.index_buffer) {
  1595. render_state.index_buffer->Release_Engine_Ref();
  1596. }
  1597. REF_PTR_SET(render_state.index_buffer,const_cast<IndexBufferClass*>(ib));
  1598. render_state.index_base_offset=index_base_offset;
  1599. if (ib) {
  1600. ib->Add_Engine_Ref();
  1601. render_state.index_buffer_type=ib->Type();
  1602. }
  1603. else {
  1604. render_state.index_buffer_type=BUFFER_TYPE_INVALID;
  1605. }
  1606. render_state_changed|=INDEX_BUFFER_CHANGED;
  1607. }
  1608. // ----------------------------------------------------------------------------
  1609. //
  1610. // Set vertex buffer using dynamic access object.
  1611. //
  1612. // ----------------------------------------------------------------------------
  1613. void DX8Wrapper::Set_Vertex_Buffer(const DynamicVBAccessClass& vba_)
  1614. {
  1615. // Release all streams (only one stream allowed in the legacy pipeline)
  1616. for (int i=1;i<MAX_VERTEX_STREAMS;++i) {
  1617. DX8Wrapper::Set_Vertex_Buffer(NULL, i);
  1618. }
  1619. if (render_state.vertex_buffers[0]) render_state.vertex_buffers[0]->Release_Engine_Ref();
  1620. DynamicVBAccessClass& vba=const_cast<DynamicVBAccessClass&>(vba_);
  1621. render_state.vertex_buffer_types[0]=vba.Get_Type();
  1622. render_state.vba_offset=vba.VertexBufferOffset;
  1623. render_state.vba_count=vba.Get_Vertex_Count();
  1624. REF_PTR_SET(render_state.vertex_buffers[0],vba.VertexBuffer);
  1625. render_state.vertex_buffers[0]->Add_Engine_Ref();
  1626. render_state_changed|=VERTEX_BUFFER_CHANGED;
  1627. render_state_changed|=INDEX_BUFFER_CHANGED; // vba_offset changes so index buffer needs to be reset as well.
  1628. }
  1629. // ----------------------------------------------------------------------------
  1630. //
  1631. // Set index buffer using dynamic access object.
  1632. //
  1633. // ----------------------------------------------------------------------------
  1634. void DX8Wrapper::Set_Index_Buffer(const DynamicIBAccessClass& iba_,unsigned short index_base_offset)
  1635. {
  1636. if (render_state.index_buffer) render_state.index_buffer->Release_Engine_Ref();
  1637. DynamicIBAccessClass& iba=const_cast<DynamicIBAccessClass&>(iba_);
  1638. render_state.index_base_offset=index_base_offset;
  1639. render_state.index_buffer_type=iba.Get_Type();
  1640. render_state.iba_offset=iba.IndexBufferOffset;
  1641. REF_PTR_SET(render_state.index_buffer,iba.IndexBuffer);
  1642. render_state.index_buffer->Add_Engine_Ref();
  1643. render_state_changed|=INDEX_BUFFER_CHANGED;
  1644. }
  1645. // ----------------------------------------------------------------------------
  1646. //
  1647. // Private function for the special case of rendering polygons from sorting
  1648. // index and vertex buffers.
  1649. //
  1650. // ----------------------------------------------------------------------------
  1651. void DX8Wrapper::Draw_Sorting_IB_VB(
  1652. unsigned primitive_type,
  1653. unsigned short start_index,
  1654. unsigned short polygon_count,
  1655. unsigned short min_vertex_index,
  1656. unsigned short vertex_count)
  1657. {
  1658. WWASSERT(render_state.vertex_buffer_types[0]==BUFFER_TYPE_SORTING || render_state.vertex_buffer_types[0]==BUFFER_TYPE_DYNAMIC_SORTING);
  1659. WWASSERT(render_state.index_buffer_type==BUFFER_TYPE_SORTING || render_state.index_buffer_type==BUFFER_TYPE_DYNAMIC_SORTING);
  1660. // Fill dynamic vertex buffer with sorting vertex buffer vertices
  1661. DynamicVBAccessClass dyn_vb_access(BUFFER_TYPE_DYNAMIC_DX8,dynamic_fvf_type,vertex_count);
  1662. {
  1663. DynamicVBAccessClass::WriteLockClass lock(&dyn_vb_access);
  1664. VertexFormatXYZNDUV2* src = static_cast<SortingVertexBufferClass*>(render_state.vertex_buffers[0])->VertexBuffer;
  1665. VertexFormatXYZNDUV2* dest= lock.Get_Formatted_Vertex_Array();
  1666. src += render_state.vba_offset + render_state.index_base_offset + min_vertex_index;
  1667. unsigned size = dyn_vb_access.FVF_Info().Get_FVF_Size()*vertex_count/sizeof(unsigned);
  1668. unsigned *dest_u =(unsigned*) dest;
  1669. unsigned *src_u = (unsigned*) src;
  1670. for (unsigned i=0;i<size;++i) {
  1671. *dest_u++=*src_u++;
  1672. }
  1673. }
  1674. DX8CALL(SetStreamSource(
  1675. 0,
  1676. static_cast<DX8VertexBufferClass*>(dyn_vb_access.VertexBuffer)->Get_DX8_Vertex_Buffer(),
  1677. dyn_vb_access.FVF_Info().Get_FVF_Size()));
  1678. // If using FVF format VB, set the FVF as vertex shader (may not be needed here KM)
  1679. unsigned fvf=dyn_vb_access.FVF_Info().Get_FVF();
  1680. if (fvf!=0) {
  1681. DX8CALL(SetVertexShader(fvf));
  1682. }
  1683. DX8_RECORD_VERTEX_BUFFER_CHANGE();
  1684. unsigned index_count=0;
  1685. switch (primitive_type) {
  1686. case D3DPT_TRIANGLELIST: index_count=polygon_count*3; break;
  1687. case D3DPT_TRIANGLESTRIP: index_count=polygon_count+2; break;
  1688. case D3DPT_TRIANGLEFAN: index_count=polygon_count+2; break;
  1689. default: WWASSERT(0); break; // Unsupported primitive type
  1690. }
  1691. // Fill dynamic index buffer with sorting index buffer vertices
  1692. DynamicIBAccessClass dyn_ib_access(BUFFER_TYPE_DYNAMIC_DX8,index_count);
  1693. {
  1694. DynamicIBAccessClass::WriteLockClass lock(&dyn_ib_access);
  1695. unsigned short* dest=lock.Get_Index_Array();
  1696. unsigned short* src=NULL;
  1697. src=static_cast<SortingIndexBufferClass*>(render_state.index_buffer)->index_buffer;
  1698. src+=render_state.iba_offset+start_index;
  1699. try {
  1700. for (unsigned short i=0;i<index_count;++i) {
  1701. unsigned short index=*src++;
  1702. index-=min_vertex_index;
  1703. WWASSERT(index<vertex_count);
  1704. *dest++=index;
  1705. }
  1706. IndexBufferExceptionFunc();
  1707. } catch(...) {
  1708. IndexBufferExceptionFunc();
  1709. }
  1710. }
  1711. DX8CALL(SetIndices(
  1712. static_cast<DX8IndexBufferClass*>(dyn_ib_access.IndexBuffer)->Get_DX8_Index_Buffer(),
  1713. dyn_vb_access.VertexBufferOffset));
  1714. DX8_RECORD_INDEX_BUFFER_CHANGE();
  1715. DX8_RECORD_DRAW_CALLS();
  1716. DX8CALL(DrawIndexedPrimitive(
  1717. D3DPT_TRIANGLELIST,
  1718. 0, // start vertex
  1719. vertex_count,
  1720. dyn_ib_access.IndexBufferOffset,
  1721. polygon_count));
  1722. DX8_RECORD_RENDER(polygon_count,vertex_count,render_state.shader);
  1723. }
  1724. // ----------------------------------------------------------------------------
  1725. //
  1726. //
  1727. //
  1728. // ----------------------------------------------------------------------------
  1729. void DX8Wrapper::Draw(
  1730. unsigned primitive_type,
  1731. unsigned short start_index,
  1732. unsigned short polygon_count,
  1733. unsigned short min_vertex_index,
  1734. unsigned short vertex_count)
  1735. {
  1736. if (DrawPolygonLowBoundLimit && DrawPolygonLowBoundLimit>=polygon_count) return;
  1737. DX8_THREAD_ASSERT();
  1738. SNAPSHOT_SAY(("DX8 - draw\n"));
  1739. Apply_Render_State_Changes();
  1740. // Debug feature to disable triangle drawing...
  1741. if (!_Is_Triangle_Draw_Enabled()) return;
  1742. #ifdef MESH_RENDER_SNAPSHOT_ENABLED
  1743. if (WW3D::Is_Snapshot_Activated()) {
  1744. unsigned long passes=0;
  1745. SNAPSHOT_SAY(("ValidateDevice: "));
  1746. HRESULT res=D3DDevice->ValidateDevice(&passes);
  1747. switch (res) {
  1748. case D3D_OK:
  1749. SNAPSHOT_SAY(("OK\n"));
  1750. break;
  1751. case D3DERR_CONFLICTINGTEXTUREFILTER:
  1752. SNAPSHOT_SAY(("D3DERR_CONFLICTINGTEXTUREFILTER\n"));
  1753. break;
  1754. case D3DERR_CONFLICTINGTEXTUREPALETTE:
  1755. SNAPSHOT_SAY(("D3DERR_CONFLICTINGTEXTUREPALETTE\n"));
  1756. break;
  1757. case D3DERR_DEVICELOST:
  1758. SNAPSHOT_SAY(("D3DERR_DEVICELOST\n"));
  1759. break;
  1760. case D3DERR_TOOMANYOPERATIONS:
  1761. SNAPSHOT_SAY(("D3DERR_TOOMANYOPERATIONS\n"));
  1762. break;
  1763. case D3DERR_UNSUPPORTEDALPHAARG:
  1764. SNAPSHOT_SAY(("D3DERR_UNSUPPORTEDALPHAARG\n"));
  1765. break;
  1766. case D3DERR_UNSUPPORTEDALPHAOPERATION:
  1767. SNAPSHOT_SAY(("D3DERR_UNSUPPORTEDALPHAOPERATION\n"));
  1768. break;
  1769. case D3DERR_UNSUPPORTEDCOLORARG:
  1770. SNAPSHOT_SAY(("D3DERR_UNSUPPORTEDCOLORARG\n"));
  1771. break;
  1772. case D3DERR_UNSUPPORTEDCOLOROPERATION:
  1773. SNAPSHOT_SAY(("D3DERR_UNSUPPORTEDCOLOROPERATION\n"));
  1774. break;
  1775. case D3DERR_UNSUPPORTEDFACTORVALUE:
  1776. SNAPSHOT_SAY(("D3DERR_UNSUPPORTEDFACTORVALUE\n"));
  1777. break;
  1778. case D3DERR_UNSUPPORTEDTEXTUREFILTER:
  1779. SNAPSHOT_SAY(("D3DERR_UNSUPPORTEDTEXTUREFILTER\n"));
  1780. break;
  1781. case D3DERR_WRONGTEXTUREFORMAT:
  1782. SNAPSHOT_SAY(("D3DERR_WRONGTEXTUREFORMAT\n"));
  1783. break;
  1784. default:
  1785. SNAPSHOT_SAY(("UNKNOWN Error\n"));
  1786. break;
  1787. }
  1788. }
  1789. #endif // MESH_RENDER_SHAPSHOT_ENABLED
  1790. SNAPSHOT_SAY(("DX8 - draw %d polygons (%d vertices)\n",polygon_count,vertex_count));
  1791. if (vertex_count<3) {
  1792. min_vertex_index=0;
  1793. switch (render_state.vertex_buffer_types[0]) {
  1794. case BUFFER_TYPE_DX8:
  1795. case BUFFER_TYPE_SORTING:
  1796. vertex_count=render_state.vertex_buffers[0]->Get_Vertex_Count()-render_state.index_base_offset-render_state.vba_offset-min_vertex_index;
  1797. break;
  1798. case BUFFER_TYPE_DYNAMIC_DX8:
  1799. case BUFFER_TYPE_DYNAMIC_SORTING:
  1800. vertex_count=render_state.vba_count;
  1801. break;
  1802. }
  1803. }
  1804. switch (render_state.vertex_buffer_types[0]) {
  1805. case BUFFER_TYPE_DX8:
  1806. case BUFFER_TYPE_DYNAMIC_DX8:
  1807. switch (render_state.index_buffer_type) {
  1808. case BUFFER_TYPE_DX8:
  1809. case BUFFER_TYPE_DYNAMIC_DX8:
  1810. {
  1811. /* if ((start_index+render_state.iba_offset+polygon_count*3) > render_state.index_buffer->Get_Index_Count())
  1812. { WWASSERT_PRINT(0,"OVERFLOWING INDEX BUFFER");
  1813. ///@todo: MUST FIND OUT WHY THIS HAPPENS WITH LOTS OF PARTICLES ON BIG FIGHT! -MW
  1814. break;
  1815. }*/
  1816. DX8_RECORD_RENDER(polygon_count,vertex_count,render_state.shader);
  1817. DX8_RECORD_DRAW_CALLS();
  1818. DX8CALL(DrawIndexedPrimitive(
  1819. (D3DPRIMITIVETYPE)primitive_type,
  1820. min_vertex_index,
  1821. vertex_count,
  1822. start_index+render_state.iba_offset,
  1823. polygon_count));
  1824. }
  1825. break;
  1826. case BUFFER_TYPE_SORTING:
  1827. case BUFFER_TYPE_DYNAMIC_SORTING:
  1828. WWASSERT_PRINT(0,"VB and IB must of same type (sorting or dx8)");
  1829. break;
  1830. case BUFFER_TYPE_INVALID:
  1831. WWASSERT(0);
  1832. break;
  1833. }
  1834. break;
  1835. case BUFFER_TYPE_SORTING:
  1836. case BUFFER_TYPE_DYNAMIC_SORTING:
  1837. switch (render_state.index_buffer_type) {
  1838. case BUFFER_TYPE_DX8:
  1839. case BUFFER_TYPE_DYNAMIC_DX8:
  1840. WWASSERT_PRINT(0,"VB and IB must of same type (sorting or dx8)");
  1841. break;
  1842. case BUFFER_TYPE_SORTING:
  1843. case BUFFER_TYPE_DYNAMIC_SORTING:
  1844. Draw_Sorting_IB_VB(primitive_type,start_index,polygon_count,min_vertex_index,vertex_count);
  1845. break;
  1846. case BUFFER_TYPE_INVALID:
  1847. WWASSERT(0);
  1848. break;
  1849. }
  1850. break;
  1851. case BUFFER_TYPE_INVALID:
  1852. WWASSERT(0);
  1853. break;
  1854. }
  1855. }
  1856. // ----------------------------------------------------------------------------
  1857. //
  1858. //
  1859. //
  1860. // ----------------------------------------------------------------------------
  1861. void DX8Wrapper::Draw_Triangles(
  1862. unsigned buffer_type,
  1863. unsigned short start_index,
  1864. unsigned short polygon_count,
  1865. unsigned short min_vertex_index,
  1866. unsigned short vertex_count)
  1867. {
  1868. if (buffer_type==BUFFER_TYPE_SORTING || buffer_type==BUFFER_TYPE_DYNAMIC_SORTING) {
  1869. SortingRendererClass::Insert_Triangles(start_index,polygon_count,min_vertex_index,vertex_count);
  1870. }
  1871. else {
  1872. Draw(D3DPT_TRIANGLELIST,start_index,polygon_count,min_vertex_index,vertex_count);
  1873. }
  1874. }
  1875. // ----------------------------------------------------------------------------
  1876. //
  1877. //
  1878. //
  1879. // ----------------------------------------------------------------------------
  1880. void DX8Wrapper::Draw_Triangles(
  1881. unsigned short start_index,
  1882. unsigned short polygon_count,
  1883. unsigned short min_vertex_index,
  1884. unsigned short vertex_count)
  1885. {
  1886. Draw(D3DPT_TRIANGLELIST,start_index,polygon_count,min_vertex_index,vertex_count);
  1887. }
  1888. // ----------------------------------------------------------------------------
  1889. //
  1890. //
  1891. //
  1892. // ----------------------------------------------------------------------------
  1893. void DX8Wrapper::Draw_Strip(
  1894. unsigned short start_index,
  1895. unsigned short polygon_count,
  1896. unsigned short min_vertex_index,
  1897. unsigned short vertex_count)
  1898. {
  1899. Draw(D3DPT_TRIANGLESTRIP,start_index,polygon_count,min_vertex_index,vertex_count);
  1900. }
  1901. // ----------------------------------------------------------------------------
  1902. //
  1903. //
  1904. //
  1905. // ----------------------------------------------------------------------------
  1906. void DX8Wrapper::Apply_Render_State_Changes()
  1907. {
  1908. SNAPSHOT_SAY(("DX8Wrapper::Apply_Render_State_Changes()\n"));
  1909. if (!render_state_changed) return;
  1910. if (render_state_changed&SHADER_CHANGED) {
  1911. SNAPSHOT_SAY(("DX8 - apply shader\n"));
  1912. render_state.shader.Apply();
  1913. }
  1914. unsigned mask=TEXTURE0_CHANGED;
  1915. for (int i=0;i<CurrentCaps->Get_Max_Textures_Per_Pass();++i,mask<<=1)
  1916. {
  1917. if (render_state_changed&mask)
  1918. {
  1919. SNAPSHOT_SAY(("DX8 - apply texture %d (%s)\n",i,render_state.Textures[i] ? render_state.Textures[i]->Get_Full_Path() : "NULL"));
  1920. if (render_state.Textures[i])
  1921. {
  1922. render_state.Textures[i]->Apply(i);
  1923. }
  1924. else
  1925. {
  1926. TextureBaseClass::Apply_Null(i);
  1927. }
  1928. }
  1929. }
  1930. if (render_state_changed&MATERIAL_CHANGED)
  1931. {
  1932. SNAPSHOT_SAY(("DX8 - apply material\n"));
  1933. VertexMaterialClass* material=const_cast<VertexMaterialClass*>(render_state.material);
  1934. if (material)
  1935. {
  1936. material->Apply();
  1937. }
  1938. else VertexMaterialClass::Apply_Null();
  1939. }
  1940. if (render_state_changed&LIGHTS_CHANGED)
  1941. {
  1942. unsigned mask=LIGHT0_CHANGED;
  1943. for (unsigned index=0;index<4;++index,mask<<=1) {
  1944. if (render_state_changed&mask) {
  1945. SNAPSHOT_SAY(("DX8 - apply light %d\n",index));
  1946. if (render_state.LightEnable[index]) {
  1947. #ifdef MESH_RENDER_SNAPSHOT_ENABLED
  1948. if ( WW3D::Is_Snapshot_Activated() ) {
  1949. D3DLIGHT8 * light = &(render_state.Lights[index]);
  1950. static char * _light_types[] = { "Unknown", "Point","Spot", "Directional" };
  1951. WWASSERT((light->Type >= 0) && (light->Type <= 3));
  1952. SNAPSHOT_SAY((" type = %s amb = %4.2f,%4.2f,%4.2f diff = %4.2f,%4.2f,%4.2f spec = %4.2f, %4.2f, %4.2f\n",
  1953. _light_types[light->Type],
  1954. light->Ambient.r,light->Ambient.g,light->Ambient.b,
  1955. light->Diffuse.r,light->Diffuse.g,light->Diffuse.b,
  1956. light->Specular.r,light->Specular.g,light->Specular.b ));
  1957. SNAPSHOT_SAY((" pos = %f, %f, %f dir = %f, %f, %f\n",
  1958. light->Position.x, light->Position.y, light->Position.z,
  1959. light->Direction.x, light->Direction.y, light->Direction.z ));
  1960. }
  1961. #endif
  1962. Set_DX8_Light(index,&render_state.Lights[index]);
  1963. }
  1964. else {
  1965. Set_DX8_Light(index,NULL);
  1966. SNAPSHOT_SAY((" clearing light to NULL\n"));
  1967. }
  1968. }
  1969. }
  1970. }
  1971. if (render_state_changed&WORLD_CHANGED) {
  1972. SNAPSHOT_SAY(("DX8 - apply world matrix\n"));
  1973. _Set_DX8_Transform(D3DTS_WORLD,render_state.world);
  1974. }
  1975. if (render_state_changed&VIEW_CHANGED) {
  1976. SNAPSHOT_SAY(("DX8 - apply view matrix\n"));
  1977. _Set_DX8_Transform(D3DTS_VIEW,render_state.view);
  1978. }
  1979. if (render_state_changed&VERTEX_BUFFER_CHANGED) {
  1980. SNAPSHOT_SAY(("DX8 - apply vb change\n"));
  1981. for (i=0;i<MAX_VERTEX_STREAMS;++i) {
  1982. if (render_state.vertex_buffers[i]) {
  1983. switch (render_state.vertex_buffer_types[i]) {//->Type()) {
  1984. case BUFFER_TYPE_DX8:
  1985. case BUFFER_TYPE_DYNAMIC_DX8:
  1986. DX8CALL(SetStreamSource(
  1987. i,
  1988. static_cast<DX8VertexBufferClass*>(render_state.vertex_buffers[i])->Get_DX8_Vertex_Buffer(),
  1989. render_state.vertex_buffers[i]->FVF_Info().Get_FVF_Size()));
  1990. DX8_RECORD_VERTEX_BUFFER_CHANGE();
  1991. {
  1992. // If the VB format is FVF, set the FVF as a vertex shader
  1993. unsigned fvf=render_state.vertex_buffers[i]->FVF_Info().Get_FVF();
  1994. if (fvf!=0) {
  1995. Set_Vertex_Shader(fvf);
  1996. }
  1997. }
  1998. break;
  1999. case BUFFER_TYPE_SORTING:
  2000. case BUFFER_TYPE_DYNAMIC_SORTING:
  2001. break;
  2002. default:
  2003. WWASSERT(0);
  2004. }
  2005. } else {
  2006. DX8CALL(SetStreamSource(i,NULL,0));
  2007. DX8_RECORD_VERTEX_BUFFER_CHANGE();
  2008. }
  2009. }
  2010. }
  2011. if (render_state_changed&INDEX_BUFFER_CHANGED) {
  2012. SNAPSHOT_SAY(("DX8 - apply ib change\n"));
  2013. if (render_state.index_buffer) {
  2014. switch (render_state.index_buffer_type) {//->Type()) {
  2015. case BUFFER_TYPE_DX8:
  2016. case BUFFER_TYPE_DYNAMIC_DX8:
  2017. DX8CALL(SetIndices(
  2018. static_cast<DX8IndexBufferClass*>(render_state.index_buffer)->Get_DX8_Index_Buffer(),
  2019. render_state.index_base_offset+render_state.vba_offset));
  2020. DX8_RECORD_INDEX_BUFFER_CHANGE();
  2021. break;
  2022. case BUFFER_TYPE_SORTING:
  2023. case BUFFER_TYPE_DYNAMIC_SORTING:
  2024. break;
  2025. default:
  2026. WWASSERT(0);
  2027. }
  2028. }
  2029. else {
  2030. DX8CALL(SetIndices(
  2031. NULL,
  2032. 0));
  2033. DX8_RECORD_INDEX_BUFFER_CHANGE();
  2034. }
  2035. }
  2036. render_state_changed&=((unsigned)WORLD_IDENTITY|(unsigned)VIEW_IDENTITY);
  2037. SNAPSHOT_SAY(("DX8Wrapper::Apply_Render_State_Changes() - finished\n"));
  2038. }
  2039. IDirect3DTexture8 * DX8Wrapper::_Create_DX8_Texture
  2040. (
  2041. unsigned int width,
  2042. unsigned int height,
  2043. WW3DFormat format,
  2044. MipCountType mip_level_count,
  2045. D3DPOOL pool,
  2046. bool rendertarget
  2047. )
  2048. {
  2049. DX8_THREAD_ASSERT();
  2050. DX8_Assert();
  2051. IDirect3DTexture8 *texture = NULL;
  2052. // Paletted textures not supported!
  2053. WWASSERT(format!=D3DFMT_P8);
  2054. // NOTE: If 'format' is not supported as a texture format, this function will find the closest
  2055. // format that is supported and use that instead.
  2056. // Render target may return NOTAVAILABLE, in
  2057. // which case we return NULL.
  2058. if (rendertarget) {
  2059. unsigned ret=D3DXCreateTexture(
  2060. DX8Wrapper::_Get_D3D_Device8(),
  2061. width,
  2062. height,
  2063. mip_level_count,
  2064. D3DUSAGE_RENDERTARGET,
  2065. WW3DFormat_To_D3DFormat(format),
  2066. pool,
  2067. &texture);
  2068. if (ret==D3DERR_NOTAVAILABLE) {
  2069. Non_Fatal_Log_DX8_ErrorCode(ret,__FILE__,__LINE__);
  2070. return NULL;
  2071. }
  2072. // If ran out of texture ram, try invalidating some textures and mesh cache.
  2073. if (ret==D3DERR_OUTOFVIDEOMEMORY) {
  2074. WWDEBUG_SAY(("Error: Out of memory while creating render target. Trying to release assets...\n"));
  2075. // Free all textures that haven't been used in the last 5 seconds
  2076. TextureClass::Invalidate_Old_Unused_Textures(5000);
  2077. // Invalidate the mesh cache
  2078. WW3D::_Invalidate_Mesh_Cache();
  2079. ret=D3DXCreateTexture(
  2080. DX8Wrapper::_Get_D3D_Device8(),
  2081. width,
  2082. height,
  2083. mip_level_count,
  2084. D3DUSAGE_RENDERTARGET,
  2085. WW3DFormat_To_D3DFormat(format),
  2086. pool,
  2087. &texture);
  2088. if (SUCCEEDED(ret)) {
  2089. WWDEBUG_SAY(("...Render target creation succesful.\n"));
  2090. }
  2091. else {
  2092. WWDEBUG_SAY(("...Render target creation failed.\n"));
  2093. }
  2094. if (ret==D3DERR_OUTOFVIDEOMEMORY) {
  2095. Non_Fatal_Log_DX8_ErrorCode(ret,__FILE__,__LINE__);
  2096. return NULL;
  2097. }
  2098. }
  2099. DX8_ErrorCode(ret);
  2100. // Just return the texture, no reduction
  2101. // allowed for render targets.
  2102. return texture;
  2103. }
  2104. // We should never run out of video memory when allocating a non-rendertarget texture.
  2105. // However, it seems to happen sometimes when there are a lot of textures in memory and so
  2106. // if it happens we'll release assets and try again (anything is better than crashing).
  2107. unsigned ret=D3DXCreateTexture(
  2108. DX8Wrapper::_Get_D3D_Device8(),
  2109. width,
  2110. height,
  2111. mip_level_count,
  2112. 0,
  2113. WW3DFormat_To_D3DFormat(format),
  2114. pool,
  2115. &texture);
  2116. // If ran out of texture ram, try invalidating some textures and mesh cache.
  2117. if (ret==D3DERR_OUTOFVIDEOMEMORY) {
  2118. WWDEBUG_SAY(("Error: Out of memory while creating texture. Trying to release assets...\n"));
  2119. // Free all textures that haven't been used in the last 5 seconds
  2120. TextureClass::Invalidate_Old_Unused_Textures(5000);
  2121. // Invalidate the mesh cache
  2122. WW3D::_Invalidate_Mesh_Cache();
  2123. ret=D3DXCreateTexture(
  2124. DX8Wrapper::_Get_D3D_Device8(),
  2125. width,
  2126. height,
  2127. mip_level_count,
  2128. 0,
  2129. WW3DFormat_To_D3DFormat(format),
  2130. pool,
  2131. &texture);
  2132. if (SUCCEEDED(ret)) {
  2133. WWDEBUG_SAY(("...Texture creation succesful.\n"));
  2134. }
  2135. else {
  2136. StringClass format_name(0,true);
  2137. Get_WW3D_Format_Name(format, format_name);
  2138. WWDEBUG_SAY(("...Texture creation failed. (%d x %d, format: %s, mips: %d\n",width,height,format_name,mip_level_count));
  2139. }
  2140. }
  2141. DX8_ErrorCode(ret);
  2142. return texture;
  2143. }
  2144. IDirect3DTexture8 * DX8Wrapper::_Create_DX8_Texture
  2145. (
  2146. const char *filename,
  2147. MipCountType mip_level_count
  2148. )
  2149. {
  2150. DX8_THREAD_ASSERT();
  2151. DX8_Assert();
  2152. IDirect3DTexture8 *texture = NULL;
  2153. // NOTE: If the original image format is not supported as a texture format, it will
  2154. // automatically be converted to an appropriate format.
  2155. // NOTE: It is possible to get the size and format of the original image file from this
  2156. // function as well, so if we later want to second-guess D3DX's format conversion decisions
  2157. // we can do so after this function is called..
  2158. unsigned result = D3DXCreateTextureFromFileExA(
  2159. _Get_D3D_Device8(),
  2160. filename,
  2161. D3DX_DEFAULT,
  2162. D3DX_DEFAULT,
  2163. mip_level_count,//create_mipmaps ? 0 : 1,
  2164. 0,
  2165. D3DFMT_UNKNOWN,
  2166. D3DPOOL_MANAGED,
  2167. D3DX_FILTER_BOX,
  2168. D3DX_FILTER_BOX,
  2169. 0,
  2170. NULL,
  2171. NULL,
  2172. &texture);
  2173. if (result != D3D_OK) {
  2174. return MissingTexture::_Get_Missing_Texture();
  2175. }
  2176. // Make sure texture wasn't paletted!
  2177. D3DSURFACE_DESC desc;
  2178. texture->GetLevelDesc(0,&desc);
  2179. if (desc.Format==D3DFMT_P8) {
  2180. texture->Release();
  2181. return MissingTexture::_Get_Missing_Texture();
  2182. }
  2183. return texture;
  2184. }
  2185. IDirect3DTexture8 * DX8Wrapper::_Create_DX8_Texture
  2186. (
  2187. IDirect3DSurface8 *surface,
  2188. MipCountType mip_level_count
  2189. )
  2190. {
  2191. DX8_THREAD_ASSERT();
  2192. DX8_Assert();
  2193. IDirect3DTexture8 *texture = NULL;
  2194. D3DSURFACE_DESC surface_desc;
  2195. ::ZeroMemory(&surface_desc, sizeof(D3DSURFACE_DESC));
  2196. surface->GetDesc(&surface_desc);
  2197. // This function will create a texture with a different (but similar) format if the surface is
  2198. // not in a supported texture format.
  2199. WW3DFormat format=D3DFormat_To_WW3DFormat(surface_desc.Format);
  2200. texture = _Create_DX8_Texture(surface_desc.Width, surface_desc.Height, format, mip_level_count);
  2201. // Copy the surface to the texture
  2202. IDirect3DSurface8 *tex_surface = NULL;
  2203. texture->GetSurfaceLevel(0, &tex_surface);
  2204. DX8_ErrorCode(D3DXLoadSurfaceFromSurface(tex_surface, NULL, NULL, surface, NULL, NULL, D3DX_FILTER_BOX, 0));
  2205. tex_surface->Release();
  2206. // Create mipmaps if needed
  2207. if (mip_level_count!=MIP_LEVELS_1)
  2208. {
  2209. DX8_ErrorCode(D3DXFilterTexture(texture, NULL, 0, D3DX_FILTER_BOX));
  2210. }
  2211. return texture;
  2212. }
  2213. /*!
  2214. * KJM create depth stencil texture
  2215. */
  2216. IDirect3DTexture8 * DX8Wrapper::_Create_DX8_ZTexture
  2217. (
  2218. unsigned int width,
  2219. unsigned int height,
  2220. WW3DZFormat zformat,
  2221. MipCountType mip_level_count,
  2222. D3DPOOL pool
  2223. )
  2224. {
  2225. DX8_THREAD_ASSERT();
  2226. DX8_Assert();
  2227. IDirect3DTexture8* texture = NULL;
  2228. D3DFORMAT zfmt=WW3DZFormat_To_D3DFormat(zformat);
  2229. unsigned ret=DX8Wrapper::_Get_D3D_Device8()->CreateTexture
  2230. (
  2231. width,
  2232. height,
  2233. mip_level_count,
  2234. D3DUSAGE_DEPTHSTENCIL,
  2235. zfmt,
  2236. pool,
  2237. &texture
  2238. );
  2239. if (ret==D3DERR_NOTAVAILABLE)
  2240. {
  2241. Non_Fatal_Log_DX8_ErrorCode(ret,__FILE__,__LINE__);
  2242. return NULL;
  2243. }
  2244. // If ran out of texture ram, try invalidating some textures and mesh cache.
  2245. if (ret==D3DERR_OUTOFVIDEOMEMORY)
  2246. {
  2247. WWDEBUG_SAY(("Error: Out of memory while creating render target. Trying to release assets...\n"));
  2248. // Free all textures that haven't been used in the last 5 seconds
  2249. TextureClass::Invalidate_Old_Unused_Textures(5000);
  2250. // Invalidate the mesh cache
  2251. WW3D::_Invalidate_Mesh_Cache();
  2252. ret=DX8Wrapper::_Get_D3D_Device8()->CreateTexture
  2253. (
  2254. width,
  2255. height,
  2256. mip_level_count,
  2257. D3DUSAGE_DEPTHSTENCIL,
  2258. zfmt,
  2259. pool,
  2260. &texture
  2261. );
  2262. if (SUCCEEDED(ret))
  2263. {
  2264. WWDEBUG_SAY(("...Render target creation succesful.\n"));
  2265. }
  2266. else
  2267. {
  2268. WWDEBUG_SAY(("...Render target creation failed.\n"));
  2269. }
  2270. if (ret==D3DERR_OUTOFVIDEOMEMORY)
  2271. {
  2272. Non_Fatal_Log_DX8_ErrorCode(ret,__FILE__,__LINE__);
  2273. return NULL;
  2274. }
  2275. }
  2276. DX8_ErrorCode(ret);
  2277. texture->AddRef(); // don't release this texture
  2278. // Just return the texture, no reduction
  2279. // allowed for render targets.
  2280. return texture;
  2281. }
  2282. /*!
  2283. * KJM create cube map texture
  2284. */
  2285. IDirect3DCubeTexture8* DX8Wrapper::_Create_DX8_Cube_Texture
  2286. (
  2287. unsigned int width,
  2288. unsigned int height,
  2289. WW3DFormat format,
  2290. MipCountType mip_level_count,
  2291. D3DPOOL pool,
  2292. bool rendertarget
  2293. )
  2294. {
  2295. WWASSERT(width==height);
  2296. DX8_THREAD_ASSERT();
  2297. DX8_Assert();
  2298. IDirect3DCubeTexture8* texture=NULL;
  2299. // Paletted textures not supported!
  2300. WWASSERT(format!=D3DFMT_P8);
  2301. // NOTE: If 'format' is not supported as a texture format, this function will find the closest
  2302. // format that is supported and use that instead.
  2303. // Render target may return NOTAVAILABLE, in
  2304. // which case we return NULL.
  2305. if (rendertarget)
  2306. {
  2307. unsigned ret=D3DXCreateCubeTexture
  2308. (
  2309. DX8Wrapper::_Get_D3D_Device8(),
  2310. width,
  2311. mip_level_count,
  2312. D3DUSAGE_RENDERTARGET,
  2313. WW3DFormat_To_D3DFormat(format),
  2314. pool,
  2315. &texture
  2316. );
  2317. if (ret==D3DERR_NOTAVAILABLE)
  2318. {
  2319. Non_Fatal_Log_DX8_ErrorCode(ret,__FILE__,__LINE__);
  2320. return NULL;
  2321. }
  2322. // If ran out of texture ram, try invalidating some textures and mesh cache.
  2323. if (ret==D3DERR_OUTOFVIDEOMEMORY)
  2324. {
  2325. WWDEBUG_SAY(("Error: Out of memory while creating render target. Trying to release assets...\n"));
  2326. // Free all textures that haven't been used in the last 5 seconds
  2327. TextureClass::Invalidate_Old_Unused_Textures(5000);
  2328. // Invalidate the mesh cache
  2329. WW3D::_Invalidate_Mesh_Cache();
  2330. ret=D3DXCreateCubeTexture
  2331. (
  2332. DX8Wrapper::_Get_D3D_Device8(),
  2333. width,
  2334. mip_level_count,
  2335. D3DUSAGE_RENDERTARGET,
  2336. WW3DFormat_To_D3DFormat(format),
  2337. pool,
  2338. &texture
  2339. );
  2340. if (SUCCEEDED(ret))
  2341. {
  2342. WWDEBUG_SAY(("...Render target creation succesful.\n"));
  2343. }
  2344. else
  2345. {
  2346. WWDEBUG_SAY(("...Render target creation failed.\n"));
  2347. }
  2348. if (ret==D3DERR_OUTOFVIDEOMEMORY)
  2349. {
  2350. Non_Fatal_Log_DX8_ErrorCode(ret,__FILE__,__LINE__);
  2351. return NULL;
  2352. }
  2353. }
  2354. DX8_ErrorCode(ret);
  2355. // Just return the texture, no reduction
  2356. // allowed for render targets.
  2357. return texture;
  2358. }
  2359. // We should never run out of video memory when allocating a non-rendertarget texture.
  2360. // However, it seems to happen sometimes when there are a lot of textures in memory and so
  2361. // if it happens we'll release assets and try again (anything is better than crashing).
  2362. unsigned ret=D3DXCreateCubeTexture
  2363. (
  2364. DX8Wrapper::_Get_D3D_Device8(),
  2365. width,
  2366. mip_level_count,
  2367. 0,
  2368. WW3DFormat_To_D3DFormat(format),
  2369. pool,
  2370. &texture
  2371. );
  2372. // If ran out of texture ram, try invalidating some textures and mesh cache.
  2373. if (ret==D3DERR_OUTOFVIDEOMEMORY)
  2374. {
  2375. WWDEBUG_SAY(("Error: Out of memory while creating texture. Trying to release assets...\n"));
  2376. // Free all textures that haven't been used in the last 5 seconds
  2377. TextureClass::Invalidate_Old_Unused_Textures(5000);
  2378. // Invalidate the mesh cache
  2379. WW3D::_Invalidate_Mesh_Cache();
  2380. ret=D3DXCreateCubeTexture
  2381. (
  2382. DX8Wrapper::_Get_D3D_Device8(),
  2383. width,
  2384. mip_level_count,
  2385. 0,
  2386. WW3DFormat_To_D3DFormat(format),
  2387. pool,
  2388. &texture
  2389. );
  2390. if (SUCCEEDED(ret))
  2391. {
  2392. WWDEBUG_SAY(("...Texture creation succesful.\n"));
  2393. }
  2394. else
  2395. {
  2396. StringClass format_name(0,true);
  2397. Get_WW3D_Format_Name(format, format_name);
  2398. WWDEBUG_SAY(("...Texture creation failed. (%d x %d, format: %s, mips: %d\n",width,height,format_name,mip_level_count));
  2399. }
  2400. }
  2401. DX8_ErrorCode(ret);
  2402. return texture;
  2403. }
  2404. /*!
  2405. * KJM create volume texture
  2406. */
  2407. IDirect3DVolumeTexture8* DX8Wrapper::_Create_DX8_Volume_Texture
  2408. (
  2409. unsigned int width,
  2410. unsigned int height,
  2411. unsigned int depth,
  2412. WW3DFormat format,
  2413. MipCountType mip_level_count,
  2414. D3DPOOL pool
  2415. )
  2416. {
  2417. DX8_THREAD_ASSERT();
  2418. DX8_Assert();
  2419. IDirect3DVolumeTexture8* texture=NULL;
  2420. // Paletted textures not supported!
  2421. WWASSERT(format!=D3DFMT_P8);
  2422. // NOTE: If 'format' is not supported as a texture format, this function will find the closest
  2423. // format that is supported and use that instead.
  2424. // We should never run out of video memory when allocating a non-rendertarget texture.
  2425. // However, it seems to happen sometimes when there are a lot of textures in memory and so
  2426. // if it happens we'll release assets and try again (anything is better than crashing).
  2427. unsigned ret=D3DXCreateVolumeTexture
  2428. (
  2429. DX8Wrapper::_Get_D3D_Device8(),
  2430. width,
  2431. height,
  2432. depth,
  2433. mip_level_count,
  2434. 0,
  2435. WW3DFormat_To_D3DFormat(format),
  2436. pool,
  2437. &texture
  2438. );
  2439. // If ran out of texture ram, try invalidating some textures and mesh cache.
  2440. if (ret==D3DERR_OUTOFVIDEOMEMORY)
  2441. {
  2442. WWDEBUG_SAY(("Error: Out of memory while creating texture. Trying to release assets...\n"));
  2443. // Free all textures that haven't been used in the last 5 seconds
  2444. TextureClass::Invalidate_Old_Unused_Textures(5000);
  2445. // Invalidate the mesh cache
  2446. WW3D::_Invalidate_Mesh_Cache();
  2447. ret=D3DXCreateVolumeTexture
  2448. (
  2449. DX8Wrapper::_Get_D3D_Device8(),
  2450. width,
  2451. height,
  2452. depth,
  2453. mip_level_count,
  2454. 0,
  2455. WW3DFormat_To_D3DFormat(format),
  2456. pool,
  2457. &texture
  2458. );
  2459. if (SUCCEEDED(ret))
  2460. {
  2461. WWDEBUG_SAY(("...Texture creation succesful.\n"));
  2462. }
  2463. else
  2464. {
  2465. StringClass format_name(0,true);
  2466. Get_WW3D_Format_Name(format, format_name);
  2467. WWDEBUG_SAY(("...Texture creation failed. (%d x %d, format: %s, mips: %d\n",width,height,format_name,mip_level_count));
  2468. }
  2469. }
  2470. DX8_ErrorCode(ret);
  2471. return texture;
  2472. }
  2473. IDirect3DSurface8 * DX8Wrapper::_Create_DX8_Surface(unsigned int width, unsigned int height, WW3DFormat format)
  2474. {
  2475. DX8_THREAD_ASSERT();
  2476. DX8_Assert();
  2477. IDirect3DSurface8 *surface = NULL;
  2478. // Paletted surfaces not supported!
  2479. WWASSERT(format!=D3DFMT_P8);
  2480. DX8CALL(CreateImageSurface(width, height, WW3DFormat_To_D3DFormat(format), &surface));
  2481. return surface;
  2482. }
  2483. IDirect3DSurface8 * DX8Wrapper::_Create_DX8_Surface(const char *filename_)
  2484. {
  2485. DX8_THREAD_ASSERT();
  2486. DX8_Assert();
  2487. // Note: Since there is no "D3DXCreateSurfaceFromFile" and no "GetSurfaceInfoFromFile" (the
  2488. // latter is supposed to be added to D3DX in a future version), we create a texture from the
  2489. // file (w/o mipmaps), check that its surface is equal to the original file data (which it
  2490. // will not be if the file is not in a texture-supported format or size). If so, copy its
  2491. // surface (we might be able to just get its surface and add a ref to it but I'm not sure so
  2492. // I'm not going to risk it) and release the texture. If not, create a surface according to
  2493. // the file data and use D3DXLoadSurfaceFromFile. This is a horrible hack, but it saves us
  2494. // having to write file loaders. Will fix this when D3DX provides us with the right functions.
  2495. // Create a surface the size of the file image data
  2496. IDirect3DSurface8 *surface = NULL;
  2497. {
  2498. file_auto_ptr myfile(_TheFileFactory,filename_);
  2499. // If file not found, create a surface with missing texture in it
  2500. if (!myfile->Is_Available()) {
  2501. // If file not found, try the dds format
  2502. // else create a surface with missing texture in it
  2503. char compressed_name[200];
  2504. strncpy(compressed_name,filename_, 200);
  2505. char *ext = strstr(compressed_name, ".");
  2506. if ( (strlen(ext)==4) &&
  2507. ( (ext[1] == 't') || (ext[1] == 'T') ) &&
  2508. ( (ext[2] == 'g') || (ext[2] == 'G') ) &&
  2509. ( (ext[3] == 'a') || (ext[3] == 'A') ) ) {
  2510. ext[1]='d';
  2511. ext[2]='d';
  2512. ext[3]='s';
  2513. }
  2514. file_auto_ptr myfile2(_TheFileFactory,compressed_name);
  2515. if (!myfile2->Is_Available())
  2516. return MissingTexture::_Create_Missing_Surface();
  2517. }
  2518. }
  2519. StringClass filename_string(filename_,true);
  2520. surface=TextureLoader::Load_Surface_Immediate(
  2521. filename_string,
  2522. WW3D_FORMAT_UNKNOWN,
  2523. true);
  2524. return surface;
  2525. }
  2526. /***********************************************************************************************
  2527. * DX8Wrapper::_Update_Texture -- Copies a texture from system memory to video memory *
  2528. * *
  2529. * *
  2530. * *
  2531. * *
  2532. * INPUT: *
  2533. * *
  2534. * OUTPUT: *
  2535. * *
  2536. * WARNINGS: *
  2537. * *
  2538. * HISTORY: *
  2539. * 4/26/2001 hy : Created. *
  2540. *=============================================================================================*/
  2541. void DX8Wrapper::_Update_Texture(TextureClass *system, TextureClass *video)
  2542. {
  2543. WWASSERT(system);
  2544. WWASSERT(video);
  2545. WWASSERT(system->Get_Pool()==TextureClass::POOL_SYSTEMMEM);
  2546. WWASSERT(video->Get_Pool()==TextureClass::POOL_DEFAULT);
  2547. DX8CALL(UpdateTexture(system->Peek_D3D_Base_Texture(),video->Peek_D3D_Base_Texture()));
  2548. }
  2549. void DX8Wrapper::Compute_Caps(WW3DFormat display_format)
  2550. {
  2551. DX8_THREAD_ASSERT();
  2552. DX8_Assert();
  2553. delete CurrentCaps;
  2554. CurrentCaps=new DX8Caps(_Get_D3D8(),D3DDevice,display_format,Get_Current_Adapter_Identifier());
  2555. }
  2556. void DX8Wrapper::Set_Light(unsigned index, const D3DLIGHT8* light)
  2557. {
  2558. if (light) {
  2559. render_state.Lights[index]=*light;
  2560. render_state.LightEnable[index]=true;
  2561. }
  2562. else {
  2563. render_state.LightEnable[index]=false;
  2564. }
  2565. render_state_changed|=(LIGHT0_CHANGED<<index);
  2566. }
  2567. void DX8Wrapper::Set_Light(unsigned index,const LightClass &light)
  2568. {
  2569. D3DLIGHT8 dlight;
  2570. Vector3 temp;
  2571. memset(&dlight,0,sizeof(D3DLIGHT8));
  2572. switch (light.Get_Type())
  2573. {
  2574. case LightClass::POINT:
  2575. {
  2576. dlight.Type=D3DLIGHT_POINT;
  2577. }
  2578. break;
  2579. case LightClass::DIRECTIONAL:
  2580. {
  2581. dlight.Type=D3DLIGHT_DIRECTIONAL;
  2582. }
  2583. break;
  2584. case LightClass::SPOT:
  2585. {
  2586. dlight.Type=D3DLIGHT_SPOT;
  2587. }
  2588. break;
  2589. }
  2590. light.Get_Diffuse(&temp);
  2591. temp*=light.Get_Intensity();
  2592. dlight.Diffuse.r=temp.X;
  2593. dlight.Diffuse.g=temp.Y;
  2594. dlight.Diffuse.b=temp.Z;
  2595. dlight.Diffuse.a=1.0f;
  2596. light.Get_Specular(&temp);
  2597. temp*=light.Get_Intensity();
  2598. dlight.Specular.r=temp.X;
  2599. dlight.Specular.g=temp.Y;
  2600. dlight.Specular.b=temp.Z;
  2601. dlight.Specular.a=1.0f;
  2602. light.Get_Ambient(&temp);
  2603. temp*=light.Get_Intensity();
  2604. dlight.Ambient.r=temp.X;
  2605. dlight.Ambient.g=temp.Y;
  2606. dlight.Ambient.b=temp.Z;
  2607. dlight.Ambient.a=1.0f;
  2608. temp=light.Get_Position();
  2609. dlight.Position=*(D3DVECTOR*) &temp;
  2610. light.Get_Spot_Direction(temp);
  2611. dlight.Direction=*(D3DVECTOR*) &temp;
  2612. dlight.Range=light.Get_Attenuation_Range();
  2613. dlight.Falloff=light.Get_Spot_Exponent();
  2614. dlight.Theta=light.Get_Spot_Angle();
  2615. dlight.Phi=light.Get_Spot_Angle();
  2616. // Inverse linear light 1/(1+D)
  2617. double a,b;
  2618. light.Get_Far_Attenuation_Range(a,b);
  2619. dlight.Attenuation0=1.0f;
  2620. if (fabs(a-b)<1e-5)
  2621. // if the attenuation range is too small assume uniform with cutoff
  2622. dlight.Attenuation1=0.0f;
  2623. else
  2624. // this will cause the light to drop to half intensity at the first far attenuation
  2625. dlight.Attenuation1=(float) 1.0/a;
  2626. dlight.Attenuation2=0.0f;
  2627. Set_Light(index,&dlight);
  2628. }
  2629. //**********************************************************************************************
  2630. //! Set the light environment. This is a lighting model which used up to four
  2631. //! directional lights to produce the lighting.
  2632. /*! 5/27/02 KJM Added shader light environment support
  2633. */
  2634. void DX8Wrapper::Set_Light_Environment(LightEnvironmentClass* light_env)
  2635. {
  2636. // Shader light environment support *
  2637. // if (Light_Environment && light_env && (*Light_Environment)==(*light_env)) return;
  2638. Light_Environment=light_env;
  2639. if (light_env)
  2640. {
  2641. int light_count = light_env->Get_Light_Count();
  2642. unsigned int color=Convert_Color(light_env->Get_Equivalent_Ambient(),0.0f);
  2643. if (RenderStates[D3DRS_AMBIENT]!=color)
  2644. {
  2645. Set_DX8_Render_State(D3DRS_AMBIENT,color);
  2646. //buggy Radeon 9700 driver doesn't apply new ambient unless the material also changes.
  2647. #if 1
  2648. render_state_changed|=MATERIAL_CHANGED;
  2649. #endif
  2650. }
  2651. D3DLIGHT8 light;
  2652. for (int l=0;l<light_count;++l) {
  2653. ::ZeroMemory(&light, sizeof(D3DLIGHT8));
  2654. light.Type=D3DLIGHT_DIRECTIONAL;
  2655. (Vector3&)light.Diffuse=light_env->Get_Light_Diffuse(l);
  2656. Vector3 dir=-light_env->Get_Light_Direction(l);
  2657. light.Direction=(const D3DVECTOR&)(dir);
  2658. // (gth) TODO: put specular into LightEnvironment? Much work to be done on lights :-)'
  2659. if (l==0) {
  2660. light.Specular.r = light.Specular.g = light.Specular.b = 1.0f;
  2661. }
  2662. if (light_env->isPointLight(l)) {
  2663. light.Type = D3DLIGHT_POINT;
  2664. (Vector3&)light.Diffuse=light_env->getPointDiffuse(l);
  2665. (Vector3&)light.Ambient=light_env->getPointAmbient(l);
  2666. light.Position = (const D3DVECTOR&)light_env->getPointCenter(l);
  2667. light.Range = light_env->getPointOrad(l);
  2668. // Inverse linear light 1/(1+D)
  2669. double a,b;
  2670. b = light_env->getPointOrad(l);
  2671. a = light_env->getPointIrad(l);
  2672. //(gth) CNC3 Generals code for the attenuation factors is causing the lights to over-brighten
  2673. //I'm changing the Attenuation0 parameter to 1.0 to avoid this problem.
  2674. #if 0
  2675. light.Attenuation0=0.01f;
  2676. #else
  2677. light.Attenuation0=1.0f;
  2678. #endif
  2679. if (fabs(a-b)<1e-5)
  2680. // if the attenuation range is too small assume uniform with cutoff
  2681. light.Attenuation1=0.0f;
  2682. else
  2683. // this will cause the light to drop to half intensity at the first far attenuation
  2684. light.Attenuation1=(float) 0.1/a;
  2685. light.Attenuation2=8.0f/(b*b);
  2686. }
  2687. Set_Light(l,&light);
  2688. }
  2689. for (;l<4;++l) {
  2690. Set_Light(l,NULL);
  2691. }
  2692. }
  2693. /* else {
  2694. for (int l=0;l<4;++l) {
  2695. Set_Light(l,NULL);
  2696. }
  2697. }
  2698. */
  2699. }
  2700. IDirect3DSurface8 * DX8Wrapper::_Get_DX8_Front_Buffer()
  2701. {
  2702. DX8_THREAD_ASSERT();
  2703. D3DDISPLAYMODE mode;
  2704. DX8CALL(GetDisplayMode(&mode));
  2705. IDirect3DSurface8 * fb=NULL;
  2706. DX8CALL(CreateImageSurface(mode.Width,mode.Height,D3DFMT_A8R8G8B8,&fb));
  2707. DX8CALL(GetFrontBuffer(fb));
  2708. return fb;
  2709. }
  2710. SurfaceClass * DX8Wrapper::_Get_DX8_Back_Buffer(unsigned int num)
  2711. {
  2712. DX8_THREAD_ASSERT();
  2713. IDirect3DSurface8 * bb;
  2714. SurfaceClass *surf=NULL;
  2715. DX8CALL(GetBackBuffer(num,D3DBACKBUFFER_TYPE_MONO,&bb));
  2716. if (bb)
  2717. {
  2718. surf=NEW_REF(SurfaceClass,(bb));
  2719. bb->Release();
  2720. }
  2721. return surf;
  2722. }
  2723. TextureClass *
  2724. DX8Wrapper::Create_Render_Target (int width, int height, WW3DFormat format)
  2725. {
  2726. DX8_THREAD_ASSERT();
  2727. DX8_Assert();
  2728. number_of_DX8_calls++;
  2729. // Use the current display format if format isn't specified
  2730. if (format==WW3D_FORMAT_UNKNOWN) {
  2731. D3DDISPLAYMODE mode;
  2732. DX8CALL(GetDisplayMode(&mode));
  2733. format=D3DFormat_To_WW3DFormat(mode.Format);
  2734. }
  2735. // If render target format isn't supported return NULL
  2736. if (!Get_Current_Caps()->Support_Render_To_Texture_Format(format)) {
  2737. WWDEBUG_SAY(("DX8Wrapper - Render target format is not supported\r\n"));
  2738. return NULL;
  2739. }
  2740. //
  2741. // Note: We're going to force the width and height to be powers of two and equal
  2742. //
  2743. const D3DCAPS8& dx8caps=Get_Current_Caps()->Get_DX8_Caps();
  2744. float poweroftwosize = width;
  2745. if (height > 0 && height < width) {
  2746. poweroftwosize = height;
  2747. }
  2748. poweroftwosize = ::Find_POT (poweroftwosize);
  2749. if (poweroftwosize>dx8caps.MaxTextureWidth) {
  2750. poweroftwosize=dx8caps.MaxTextureWidth;
  2751. }
  2752. if (poweroftwosize>dx8caps.MaxTextureHeight) {
  2753. poweroftwosize=dx8caps.MaxTextureHeight;
  2754. }
  2755. width = height = poweroftwosize;
  2756. //
  2757. // Attempt to create the render target
  2758. //
  2759. TextureClass * tex = NEW_REF(TextureClass,(width,height,format,MIP_LEVELS_1,TextureClass::POOL_DEFAULT,true));
  2760. // 3dfx drivers are lying in the CheckDeviceFormat call and claiming
  2761. // that they support render targets!
  2762. if (tex->Peek_D3D_Base_Texture() == NULL)
  2763. {
  2764. WWDEBUG_SAY(("DX8Wrapper - Render target creation failed!\r\n"));
  2765. REF_PTR_RELEASE(tex);
  2766. }
  2767. return tex;
  2768. }
  2769. //**********************************************************************************************
  2770. //! Create render target with associated depth stencil buffer
  2771. /*! KJM
  2772. */
  2773. void DX8Wrapper::Create_Render_Target
  2774. (
  2775. int width,
  2776. int height,
  2777. WW3DFormat format,
  2778. WW3DZFormat zformat,
  2779. TextureClass** target,
  2780. ZTextureClass** depth_buffer
  2781. )
  2782. {
  2783. DX8_THREAD_ASSERT();
  2784. DX8_Assert();
  2785. number_of_DX8_calls++;
  2786. // Use the current display format if format isn't specified
  2787. if (format==WW3D_FORMAT_UNKNOWN)
  2788. {
  2789. *target=NULL;
  2790. *depth_buffer=NULL;
  2791. return;
  2792. /* D3DDISPLAYMODE mode;
  2793. DX8CALL(GetDisplayMode(&mode));
  2794. format=D3DFormat_To_WW3DFormat(mode.Format);*/
  2795. }
  2796. // If render target format isn't supported return NULL
  2797. if (!Get_Current_Caps()->Support_Render_To_Texture_Format(format) ||
  2798. !Get_Current_Caps()->Support_Depth_Stencil_Format(zformat))
  2799. {
  2800. WWDEBUG_SAY(("DX8Wrapper - Render target with depth format is not supported\r\n"));
  2801. return;
  2802. }
  2803. // Note: We're going to force the width and height to be powers of two and equal
  2804. const D3DCAPS8& dx8caps=Get_Current_Caps()->Get_DX8_Caps();
  2805. float poweroftwosize = width;
  2806. if (height > 0 && height < width)
  2807. {
  2808. poweroftwosize = height;
  2809. }
  2810. poweroftwosize = ::Find_POT (poweroftwosize);
  2811. if (poweroftwosize>dx8caps.MaxTextureWidth)
  2812. {
  2813. poweroftwosize=dx8caps.MaxTextureWidth;
  2814. }
  2815. if (poweroftwosize>dx8caps.MaxTextureHeight)
  2816. {
  2817. poweroftwosize=dx8caps.MaxTextureHeight;
  2818. }
  2819. width = height = poweroftwosize;
  2820. // Attempt to create the render target
  2821. TextureClass* tex=NEW_REF(TextureClass,(width,height,format,MIP_LEVELS_1,TextureClass::POOL_DEFAULT,true));
  2822. // 3dfx drivers are lying in the CheckDeviceFormat call and claiming
  2823. // that they support render targets!
  2824. if (tex->Peek_D3D_Base_Texture() == NULL)
  2825. {
  2826. WWDEBUG_SAY(("DX8Wrapper - Render target creation failed!\r\n"));
  2827. REF_PTR_RELEASE(tex);
  2828. }
  2829. *target=tex;
  2830. // attempt to create the depth stencil buffer
  2831. *depth_buffer=NEW_REF
  2832. (
  2833. ZTextureClass,
  2834. (
  2835. width,
  2836. height,
  2837. zformat,
  2838. MIP_LEVELS_1,
  2839. TextureClass::POOL_DEFAULT
  2840. )
  2841. );
  2842. }
  2843. /*!
  2844. * Set render target
  2845. * KM Added optional custom z target
  2846. */
  2847. void DX8Wrapper::Set_Render_Target_With_Z
  2848. (
  2849. TextureClass* texture,
  2850. ZTextureClass* ztexture
  2851. )
  2852. {
  2853. WWASSERT(texture!=NULL);
  2854. IDirect3DSurface8 * d3d_surf = texture->Get_D3D_Surface_Level();
  2855. WWASSERT(d3d_surf != NULL);
  2856. IDirect3DSurface8* d3d_zbuf=NULL;
  2857. if (ztexture!=NULL)
  2858. {
  2859. d3d_zbuf=ztexture->Get_D3D_Surface_Level();
  2860. WWASSERT(d3d_zbuf!=NULL);
  2861. Set_Render_Target(d3d_surf,d3d_zbuf);
  2862. d3d_zbuf->Release();
  2863. }
  2864. else
  2865. {
  2866. Set_Render_Target(d3d_surf,true);
  2867. }
  2868. d3d_surf->Release();
  2869. IsRenderToTexture = true;
  2870. }
  2871. void
  2872. DX8Wrapper::Set_Render_Target(IDirect3DSwapChain8 *swap_chain)
  2873. {
  2874. DX8_THREAD_ASSERT();
  2875. WWASSERT (swap_chain != NULL);
  2876. //
  2877. // Get the back buffer for the swap chain
  2878. //
  2879. LPDIRECT3DSURFACE8 render_target = NULL;
  2880. swap_chain->GetBackBuffer (0, D3DBACKBUFFER_TYPE_MONO, &render_target);
  2881. //
  2882. // Set this back buffer as the render targer
  2883. //
  2884. Set_Render_Target (render_target, true);
  2885. //
  2886. // Release our hold on the back buffer
  2887. //
  2888. if (render_target != NULL) {
  2889. render_target->Release ();
  2890. render_target = NULL;
  2891. }
  2892. IsRenderToTexture = false;
  2893. return ;
  2894. }
  2895. void
  2896. DX8Wrapper::Set_Render_Target(IDirect3DSurface8 *render_target, bool use_default_depth_buffer)
  2897. {
  2898. //#ifndef _XBOX
  2899. DX8_THREAD_ASSERT();
  2900. DX8_Assert();
  2901. //
  2902. // Should we restore the default render target set a new one?
  2903. //
  2904. if (render_target == NULL || render_target == DefaultRenderTarget)
  2905. {
  2906. // If there is currently a custom render target, default must NOT be NULL.
  2907. if (CurrentRenderTarget)
  2908. {
  2909. WWASSERT(DefaultRenderTarget!=NULL);
  2910. }
  2911. //
  2912. // Restore the default render target
  2913. //
  2914. if (DefaultRenderTarget != NULL)
  2915. {
  2916. DX8CALL(SetRenderTarget (DefaultRenderTarget, DefaultDepthBuffer));
  2917. DefaultRenderTarget->Release ();
  2918. DefaultRenderTarget = NULL;
  2919. if (DefaultDepthBuffer)
  2920. {
  2921. DefaultDepthBuffer->Release ();
  2922. DefaultDepthBuffer = NULL;
  2923. }
  2924. }
  2925. //
  2926. // Release our hold on the "current" render target
  2927. //
  2928. if (CurrentRenderTarget != NULL)
  2929. {
  2930. CurrentRenderTarget->Release ();
  2931. CurrentRenderTarget = NULL;
  2932. }
  2933. if (CurrentDepthBuffer!=NULL)
  2934. {
  2935. CurrentDepthBuffer->Release();
  2936. CurrentDepthBuffer=NULL;
  2937. }
  2938. }
  2939. else if (render_target != CurrentRenderTarget)
  2940. {
  2941. WWASSERT(DefaultRenderTarget==NULL);
  2942. //
  2943. // We'll need the depth buffer later...
  2944. //
  2945. if (DefaultDepthBuffer == NULL)
  2946. {
  2947. // IDirect3DSurface8 *depth_buffer = NULL;
  2948. DX8CALL(GetDepthStencilSurface (&DefaultDepthBuffer));
  2949. }
  2950. //
  2951. // Get a pointer to the default render target (if necessary)
  2952. //
  2953. if (DefaultRenderTarget == NULL)
  2954. {
  2955. DX8CALL(GetRenderTarget (&DefaultRenderTarget));
  2956. }
  2957. //
  2958. // Release our hold on the old "current" render target
  2959. //
  2960. if (CurrentRenderTarget != NULL)
  2961. {
  2962. CurrentRenderTarget->Release ();
  2963. CurrentRenderTarget = NULL;
  2964. }
  2965. if (CurrentDepthBuffer!=NULL)
  2966. {
  2967. CurrentDepthBuffer->Release();
  2968. CurrentDepthBuffer=NULL;
  2969. }
  2970. //
  2971. // Keep a copy of the current render target (for housekeeping)
  2972. //
  2973. CurrentRenderTarget = render_target;
  2974. WWASSERT (CurrentRenderTarget != NULL);
  2975. if (CurrentRenderTarget != NULL)
  2976. {
  2977. CurrentRenderTarget->AddRef ();
  2978. //
  2979. // Switch render targets
  2980. //
  2981. if (use_default_depth_buffer)
  2982. {
  2983. DX8CALL(SetRenderTarget (CurrentRenderTarget, DefaultDepthBuffer));
  2984. }
  2985. else
  2986. {
  2987. DX8CALL(SetRenderTarget (CurrentRenderTarget, NULL));
  2988. }
  2989. }
  2990. }
  2991. //
  2992. // Free our hold on the depth buffer
  2993. //
  2994. // if (depth_buffer != NULL) {
  2995. // depth_buffer->Release ();
  2996. // depth_buffer = NULL;
  2997. // }
  2998. IsRenderToTexture = false;
  2999. return ;
  3000. //#endif // XBOX
  3001. }
  3002. //**********************************************************************************************
  3003. //! Set render target with depth stencil buffer
  3004. /*! KJM
  3005. */
  3006. void DX8Wrapper::Set_Render_Target
  3007. (
  3008. IDirect3DSurface8* render_target,
  3009. IDirect3DSurface8* depth_buffer
  3010. )
  3011. {
  3012. //#ifndef _XBOX
  3013. DX8_THREAD_ASSERT();
  3014. DX8_Assert();
  3015. //
  3016. // Should we restore the default render target set a new one?
  3017. //
  3018. if (render_target == NULL || render_target == DefaultRenderTarget)
  3019. {
  3020. // If there is currently a custom render target, default must NOT be NULL.
  3021. if (CurrentRenderTarget)
  3022. {
  3023. WWASSERT(DefaultRenderTarget!=NULL);
  3024. }
  3025. //
  3026. // Restore the default render target
  3027. //
  3028. if (DefaultRenderTarget != NULL)
  3029. {
  3030. DX8CALL(SetRenderTarget (DefaultRenderTarget, DefaultDepthBuffer));
  3031. DefaultRenderTarget->Release ();
  3032. DefaultRenderTarget = NULL;
  3033. if (DefaultDepthBuffer)
  3034. {
  3035. DefaultDepthBuffer->Release ();
  3036. DefaultDepthBuffer = NULL;
  3037. }
  3038. }
  3039. //
  3040. // Release our hold on the "current" render target
  3041. //
  3042. if (CurrentRenderTarget != NULL)
  3043. {
  3044. CurrentRenderTarget->Release ();
  3045. CurrentRenderTarget = NULL;
  3046. }
  3047. if (CurrentDepthBuffer!=NULL)
  3048. {
  3049. CurrentDepthBuffer->Release();
  3050. CurrentDepthBuffer=NULL;
  3051. }
  3052. }
  3053. else if (render_target != CurrentRenderTarget)
  3054. {
  3055. WWASSERT(DefaultRenderTarget==NULL);
  3056. //
  3057. // We'll need the depth buffer later...
  3058. //
  3059. if (DefaultDepthBuffer == NULL)
  3060. {
  3061. // IDirect3DSurface8 *depth_buffer = NULL;
  3062. DX8CALL(GetDepthStencilSurface (&DefaultDepthBuffer));
  3063. }
  3064. //
  3065. // Get a pointer to the default render target (if necessary)
  3066. //
  3067. if (DefaultRenderTarget == NULL)
  3068. {
  3069. DX8CALL(GetRenderTarget (&DefaultRenderTarget));
  3070. }
  3071. //
  3072. // Release our hold on the old "current" render target
  3073. //
  3074. if (CurrentRenderTarget != NULL)
  3075. {
  3076. CurrentRenderTarget->Release ();
  3077. CurrentRenderTarget = NULL;
  3078. }
  3079. if (CurrentDepthBuffer!=NULL)
  3080. {
  3081. CurrentDepthBuffer->Release();
  3082. CurrentDepthBuffer=NULL;
  3083. }
  3084. //
  3085. // Keep a copy of the current render target (for housekeeping)
  3086. //
  3087. CurrentRenderTarget = render_target;
  3088. CurrentDepthBuffer = depth_buffer;
  3089. WWASSERT (CurrentRenderTarget != NULL);
  3090. if (CurrentRenderTarget != NULL)
  3091. {
  3092. CurrentRenderTarget->AddRef ();
  3093. CurrentDepthBuffer->AddRef();
  3094. //
  3095. // Switch render targets
  3096. //
  3097. DX8CALL(SetRenderTarget (CurrentRenderTarget, CurrentDepthBuffer));
  3098. }
  3099. }
  3100. IsRenderToTexture=true;
  3101. //#endif // XBOX
  3102. }
  3103. IDirect3DSwapChain8 *
  3104. DX8Wrapper::Create_Additional_Swap_Chain (HWND render_window)
  3105. {
  3106. DX8_Assert();
  3107. //
  3108. // Configure the presentation parameters for a windowed render target
  3109. //
  3110. D3DPRESENT_PARAMETERS params = { 0 };
  3111. params.BackBufferFormat = _PresentParameters.BackBufferFormat;
  3112. params.BackBufferCount = 1;
  3113. params.MultiSampleType = D3DMULTISAMPLE_NONE;
  3114. params.SwapEffect = D3DSWAPEFFECT_COPY_VSYNC;
  3115. params.hDeviceWindow = render_window;
  3116. params.Windowed = TRUE;
  3117. params.EnableAutoDepthStencil = TRUE;
  3118. params.AutoDepthStencilFormat = _PresentParameters.AutoDepthStencilFormat;
  3119. params.Flags = 0;
  3120. params.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
  3121. params.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
  3122. //
  3123. // Create the swap chain
  3124. //
  3125. IDirect3DSwapChain8 *swap_chain = NULL;
  3126. DX8CALL(CreateAdditionalSwapChain(&params, &swap_chain));
  3127. return swap_chain;
  3128. }
  3129. void DX8Wrapper::Flush_DX8_Resource_Manager(unsigned int bytes)
  3130. {
  3131. DX8_Assert();
  3132. DX8CALL(ResourceManagerDiscardBytes(bytes));
  3133. }
  3134. unsigned int DX8Wrapper::Get_Free_Texture_RAM()
  3135. {
  3136. DX8_Assert();
  3137. number_of_DX8_calls++;
  3138. return DX8Wrapper::_Get_D3D_Device8()->GetAvailableTextureMem();
  3139. }
  3140. // Converts a linear gamma ramp to one that is controlled by:
  3141. // Gamma - controls the curvature of the middle of the curve
  3142. // Bright - controls the minimum value of the curve
  3143. // Contrast - controls the difference between the maximum and the minimum of the curve
  3144. void DX8Wrapper::Set_Gamma(float gamma,float bright,float contrast,bool calibrate,bool uselimit)
  3145. {
  3146. gamma=Bound(gamma,0.6f,6.0f);
  3147. bright=Bound(bright,-0.5f,0.5f);
  3148. contrast=Bound(contrast,0.5f,2.0f);
  3149. float oo_gamma=1.0f/gamma;
  3150. DX8_Assert();
  3151. number_of_DX8_calls++;
  3152. DWORD flag=(calibrate?D3DSGR_CALIBRATE:D3DSGR_NO_CALIBRATION);
  3153. D3DGAMMARAMP ramp;
  3154. float limit;
  3155. // IML: I'm not really sure what the intent of the 'limit' variable is. It does not produce useful results for my purposes.
  3156. if (uselimit) {
  3157. limit=(contrast-1)/2*contrast;
  3158. } else {
  3159. limit = 0.0f;
  3160. }
  3161. // HY - arrived at this equation after much trial and error.
  3162. for (int i=0; i<256; i++) {
  3163. float in,out;
  3164. in=i/256.0f;
  3165. float x=in-limit;
  3166. x=Bound(x,0.0f,1.0f);
  3167. x=powf(x,oo_gamma);
  3168. out=contrast*x+bright;
  3169. out=Bound(out,0.0f,1.0f);
  3170. ramp.red[i]=(WORD) (out*65535);
  3171. ramp.green[i]=(WORD) (out*65535);
  3172. ramp.blue[i]=(WORD) (out*65535);
  3173. }
  3174. if (Get_Current_Caps()->Support_Gamma()) {
  3175. DX8Wrapper::_Get_D3D_Device8()->SetGammaRamp(flag,&ramp);
  3176. } else {
  3177. HWND hwnd = GetDesktopWindow();
  3178. HDC hdc = GetDC(hwnd);
  3179. if (hdc)
  3180. {
  3181. SetDeviceGammaRamp (hdc, &ramp);
  3182. ReleaseDC (hwnd, hdc);
  3183. }
  3184. }
  3185. }
  3186. //**********************************************************************************************
  3187. //! Resets render device to default state
  3188. /*!
  3189. */
  3190. void DX8Wrapper::Apply_Default_State()
  3191. {
  3192. SNAPSHOT_SAY(("DX8Wrapper::Apply_Default_State()\n"));
  3193. // only set states used in game
  3194. Set_DX8_Render_State(D3DRS_ZENABLE, TRUE);
  3195. // Set_DX8_Render_State(D3DRS_FILLMODE, D3DFILL_SOLID);
  3196. Set_DX8_Render_State(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
  3197. //Set_DX8_Render_State(D3DRS_LINEPATTERN, 0);
  3198. Set_DX8_Render_State(D3DRS_ZWRITEENABLE, TRUE);
  3199. Set_DX8_Render_State(D3DRS_ALPHATESTENABLE, FALSE);
  3200. //Set_DX8_Render_State(D3DRS_LASTPIXEL, FALSE);
  3201. Set_DX8_Render_State(D3DRS_SRCBLEND, D3DBLEND_ONE);
  3202. Set_DX8_Render_State(D3DRS_DESTBLEND, D3DBLEND_ZERO);
  3203. Set_DX8_Render_State(D3DRS_CULLMODE, D3DCULL_CW);
  3204. Set_DX8_Render_State(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
  3205. Set_DX8_Render_State(D3DRS_ALPHAREF, 0);
  3206. Set_DX8_Render_State(D3DRS_ALPHAFUNC, D3DCMP_LESSEQUAL);
  3207. Set_DX8_Render_State(D3DRS_DITHERENABLE, FALSE);
  3208. Set_DX8_Render_State(D3DRS_ALPHABLENDENABLE, FALSE);
  3209. Set_DX8_Render_State(D3DRS_FOGENABLE, FALSE);
  3210. Set_DX8_Render_State(D3DRS_SPECULARENABLE, FALSE);
  3211. // Set_DX8_Render_State(D3DRS_ZVISIBLE, FALSE);
  3212. // Set_DX8_Render_State(D3DRS_FOGCOLOR, 0);
  3213. // Set_DX8_Render_State(D3DRS_FOGTABLEMODE, D3DFOG_NONE);
  3214. // Set_DX8_Render_State(D3DRS_FOGSTART, 0);
  3215. // Set_DX8_Render_State(D3DRS_FOGEND, WWMath::Float_As_Int(1.0f));
  3216. // Set_DX8_Render_State(D3DRS_FOGDENSITY, WWMath::Float_As_Int(1.0f));
  3217. //Set_DX8_Render_State(D3DRS_EDGEANTIALIAS, FALSE);
  3218. Set_DX8_Render_State(D3DRS_ZBIAS, 0);
  3219. // Set_DX8_Render_State(D3DRS_RANGEFOGENABLE, FALSE);
  3220. Set_DX8_Render_State(D3DRS_STENCILENABLE, FALSE);
  3221. Set_DX8_Render_State(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
  3222. Set_DX8_Render_State(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
  3223. Set_DX8_Render_State(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
  3224. Set_DX8_Render_State(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
  3225. Set_DX8_Render_State(D3DRS_STENCILREF, 0);
  3226. Set_DX8_Render_State(D3DRS_STENCILMASK, 0xffffffff);
  3227. Set_DX8_Render_State(D3DRS_STENCILWRITEMASK, 0xffffffff);
  3228. Set_DX8_Render_State(D3DRS_TEXTUREFACTOR, 0);
  3229. /* Set_DX8_Render_State(D3DRS_WRAP0, D3DWRAP_U| D3DWRAP_V);
  3230. Set_DX8_Render_State(D3DRS_WRAP1, D3DWRAP_U| D3DWRAP_V);
  3231. Set_DX8_Render_State(D3DRS_WRAP2, D3DWRAP_U| D3DWRAP_V);
  3232. Set_DX8_Render_State(D3DRS_WRAP3, D3DWRAP_U| D3DWRAP_V);
  3233. Set_DX8_Render_State(D3DRS_WRAP4, D3DWRAP_U| D3DWRAP_V);
  3234. Set_DX8_Render_State(D3DRS_WRAP5, D3DWRAP_U| D3DWRAP_V);
  3235. Set_DX8_Render_State(D3DRS_WRAP6, D3DWRAP_U| D3DWRAP_V);
  3236. Set_DX8_Render_State(D3DRS_WRAP7, D3DWRAP_U| D3DWRAP_V);*/
  3237. Set_DX8_Render_State(D3DRS_CLIPPING, TRUE);
  3238. Set_DX8_Render_State(D3DRS_LIGHTING, FALSE);
  3239. //Set_DX8_Render_State(D3DRS_AMBIENT, 0);
  3240. // Set_DX8_Render_State(D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
  3241. Set_DX8_Render_State(D3DRS_COLORVERTEX, TRUE);
  3242. /* Set_DX8_Render_State(D3DRS_LOCALVIEWER, TRUE);
  3243. Set_DX8_Render_State(D3DRS_NORMALIZENORMALS, FALSE);
  3244. Set_DX8_Render_State(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
  3245. Set_DX8_Render_State(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR2);
  3246. Set_DX8_Render_State(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
  3247. Set_DX8_Render_State(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL);
  3248. Set_DX8_Render_State(D3DRS_VERTEXBLEND, D3DVBF_DISABLE);*/
  3249. //Set_DX8_Render_State(D3DRS_CLIPPLANEENABLE, 0);
  3250. Set_DX8_Render_State(D3DRS_SOFTWAREVERTEXPROCESSING, FALSE);
  3251. //Set_DX8_Render_State(D3DRS_POINTSIZE, 0x3f800000);
  3252. //Set_DX8_Render_State(D3DRS_POINTSIZE_MIN, 0);
  3253. //Set_DX8_Render_State(D3DRS_POINTSPRITEENABLE, FALSE);
  3254. //Set_DX8_Render_State(D3DRS_POINTSCALEENABLE, FALSE);
  3255. //Set_DX8_Render_State(D3DRS_POINTSCALE_A, 0);
  3256. //Set_DX8_Render_State(D3DRS_POINTSCALE_B, 0);
  3257. //Set_DX8_Render_State(D3DRS_POINTSCALE_C, 0);
  3258. //Set_DX8_Render_State(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
  3259. //Set_DX8_Render_State(D3DRS_MULTISAMPLEMASK, 0xffffffff);
  3260. //Set_DX8_Render_State(D3DRS_PATCHEDGESTYLE, D3DPATCHEDGE_DISCRETE);
  3261. //Set_DX8_Render_State(D3DRS_PATCHSEGMENTS, 0x3f800000);
  3262. //Set_DX8_Render_State(D3DRS_DEBUGMONITORTOKEN, D3DDMT_ENABLE);
  3263. //Set_DX8_Render_State(D3DRS_POINTSIZE_MAX, Float_At_Int(64.0f));
  3264. //Set_DX8_Render_State(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
  3265. Set_DX8_Render_State(D3DRS_COLORWRITEENABLE, 0x0000000f);
  3266. //Set_DX8_Render_State(D3DRS_TWEENFACTOR, 0);
  3267. Set_DX8_Render_State(D3DRS_BLENDOP, D3DBLENDOP_ADD);
  3268. //Set_DX8_Render_State(D3DRS_POSITIONORDER, D3DORDER_CUBIC);
  3269. //Set_DX8_Render_State(D3DRS_NORMALORDER, D3DORDER_LINEAR);
  3270. // disable TSS stages
  3271. int i;
  3272. for (i=0; i<CurrentCaps->Get_Max_Textures_Per_Pass(); i++)
  3273. {
  3274. Set_DX8_Texture_Stage_State(i, D3DTSS_COLOROP, D3DTOP_DISABLE);
  3275. Set_DX8_Texture_Stage_State(i, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  3276. Set_DX8_Texture_Stage_State(i, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
  3277. Set_DX8_Texture_Stage_State(i, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
  3278. Set_DX8_Texture_Stage_State(i, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  3279. Set_DX8_Texture_Stage_State(i, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
  3280. /*Set_DX8_Texture_Stage_State(i, D3DTSS_BUMPENVMAT00, 0);
  3281. Set_DX8_Texture_Stage_State(i, D3DTSS_BUMPENVMAT01, 0);
  3282. Set_DX8_Texture_Stage_State(i, D3DTSS_BUMPENVMAT10, 0);
  3283. Set_DX8_Texture_Stage_State(i, D3DTSS_BUMPENVMAT11, 0);
  3284. Set_DX8_Texture_Stage_State(i, D3DTSS_BUMPENVLSCALE, 0);
  3285. Set_DX8_Texture_Stage_State(i, D3DTSS_BUMPENVLOFFSET, 0);*/
  3286. Set_DX8_Texture_Stage_State(i, D3DTSS_TEXCOORDINDEX, i);
  3287. Set_DX8_Texture_Stage_State(i, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
  3288. Set_DX8_Texture_Stage_State(i, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
  3289. Set_DX8_Texture_Stage_State(i, D3DTSS_BORDERCOLOR, 0);
  3290. // Set_DX8_Texture_Stage_State(i, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
  3291. // Set_DX8_Texture_Stage_State(i, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
  3292. // Set_DX8_Texture_Stage_State(i, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
  3293. // Set_DX8_Texture_Stage_State(i, D3DTSS_MIPMAPLODBIAS, 0);
  3294. // Set_DX8_Texture_Stage_State(i, D3DTSS_MAXMIPLEVEL, 0);
  3295. // Set_DX8_Texture_Stage_State(i, D3DTSS_MAXANISOTROPY, 1);
  3296. //Set_DX8_Texture_Stage_State(i, D3DTSS_ADDRESSW, D3DTADDRESS_WRAP);
  3297. //Set_DX8_Texture_Stage_State(i, D3DTSS_COLORARG0, D3DTA_CURRENT);
  3298. //Set_DX8_Texture_Stage_State(i, D3DTSS_ALPHAARG0, D3DTA_CURRENT);
  3299. //Set_DX8_Texture_Stage_State(i, D3DTSS_RESULTARG, D3DTA_CURRENT);
  3300. Set_DX8_Texture_Stage_State(i, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
  3301. Set_Texture(i,NULL);
  3302. }
  3303. // DX8Wrapper::Set_Material(NULL);
  3304. VertexMaterialClass::Apply_Null();
  3305. for (unsigned index=0;index<4;++index) {
  3306. SNAPSHOT_SAY(("Clearing light %d to NULL\n",index));
  3307. Set_DX8_Light(index,NULL);
  3308. }
  3309. // set up simple default TSS
  3310. Vector4 vconst[MAX_VERTEX_SHADER_CONSTANTS];
  3311. memset(vconst,0,sizeof(Vector4)*MAX_VERTEX_SHADER_CONSTANTS);
  3312. Set_Vertex_Shader_Constant(0, vconst, MAX_VERTEX_SHADER_CONSTANTS);
  3313. Vector4 pconst[MAX_PIXEL_SHADER_CONSTANTS];
  3314. memset(pconst,0,sizeof(Vector4)*MAX_PIXEL_SHADER_CONSTANTS);
  3315. Set_Pixel_Shader_Constant(0, pconst, MAX_PIXEL_SHADER_CONSTANTS);
  3316. Set_Vertex_Shader(DX8_FVF_XYZNDUV2);
  3317. Set_Pixel_Shader(0);
  3318. ShaderClass::Invalidate();
  3319. }
  3320. const char* DX8Wrapper::Get_DX8_Render_State_Name(D3DRENDERSTATETYPE state)
  3321. {
  3322. switch (state) {
  3323. case D3DRS_ZENABLE : return "D3DRS_ZENABLE";
  3324. case D3DRS_FILLMODE : return "D3DRS_FILLMODE";
  3325. case D3DRS_SHADEMODE : return "D3DRS_SHADEMODE";
  3326. case D3DRS_LINEPATTERN : return "D3DRS_LINEPATTERN";
  3327. case D3DRS_ZWRITEENABLE : return "D3DRS_ZWRITEENABLE";
  3328. case D3DRS_ALPHATESTENABLE : return "D3DRS_ALPHATESTENABLE";
  3329. case D3DRS_LASTPIXEL : return "D3DRS_LASTPIXEL";
  3330. case D3DRS_SRCBLEND : return "D3DRS_SRCBLEND";
  3331. case D3DRS_DESTBLEND : return "D3DRS_DESTBLEND";
  3332. case D3DRS_CULLMODE : return "D3DRS_CULLMODE";
  3333. case D3DRS_ZFUNC : return "D3DRS_ZFUNC";
  3334. case D3DRS_ALPHAREF : return "D3DRS_ALPHAREF";
  3335. case D3DRS_ALPHAFUNC : return "D3DRS_ALPHAFUNC";
  3336. case D3DRS_DITHERENABLE : return "D3DRS_DITHERENABLE";
  3337. case D3DRS_ALPHABLENDENABLE : return "D3DRS_ALPHABLENDENABLE";
  3338. case D3DRS_FOGENABLE : return "D3DRS_FOGENABLE";
  3339. case D3DRS_SPECULARENABLE : return "D3DRS_SPECULARENABLE";
  3340. case D3DRS_ZVISIBLE : return "D3DRS_ZVISIBLE";
  3341. case D3DRS_FOGCOLOR : return "D3DRS_FOGCOLOR";
  3342. case D3DRS_FOGTABLEMODE : return "D3DRS_FOGTABLEMODE";
  3343. case D3DRS_FOGSTART : return "D3DRS_FOGSTART";
  3344. case D3DRS_FOGEND : return "D3DRS_FOGEND";
  3345. case D3DRS_FOGDENSITY : return "D3DRS_FOGDENSITY";
  3346. case D3DRS_EDGEANTIALIAS : return "D3DRS_EDGEANTIALIAS";
  3347. case D3DRS_ZBIAS : return "D3DRS_ZBIAS";
  3348. case D3DRS_RANGEFOGENABLE : return "D3DRS_RANGEFOGENABLE";
  3349. case D3DRS_STENCILENABLE : return "D3DRS_STENCILENABLE";
  3350. case D3DRS_STENCILFAIL : return "D3DRS_STENCILFAIL";
  3351. case D3DRS_STENCILZFAIL : return "D3DRS_STENCILZFAIL";
  3352. case D3DRS_STENCILPASS : return "D3DRS_STENCILPASS";
  3353. case D3DRS_STENCILFUNC : return "D3DRS_STENCILFUNC";
  3354. case D3DRS_STENCILREF : return "D3DRS_STENCILREF";
  3355. case D3DRS_STENCILMASK : return "D3DRS_STENCILMASK";
  3356. case D3DRS_STENCILWRITEMASK : return "D3DRS_STENCILWRITEMASK";
  3357. case D3DRS_TEXTUREFACTOR : return "D3DRS_TEXTUREFACTOR";
  3358. case D3DRS_WRAP0 : return "D3DRS_WRAP0";
  3359. case D3DRS_WRAP1 : return "D3DRS_WRAP1";
  3360. case D3DRS_WRAP2 : return "D3DRS_WRAP2";
  3361. case D3DRS_WRAP3 : return "D3DRS_WRAP3";
  3362. case D3DRS_WRAP4 : return "D3DRS_WRAP4";
  3363. case D3DRS_WRAP5 : return "D3DRS_WRAP5";
  3364. case D3DRS_WRAP6 : return "D3DRS_WRAP6";
  3365. case D3DRS_WRAP7 : return "D3DRS_WRAP7";
  3366. case D3DRS_CLIPPING : return "D3DRS_CLIPPING";
  3367. case D3DRS_LIGHTING : return "D3DRS_LIGHTING";
  3368. case D3DRS_AMBIENT : return "D3DRS_AMBIENT";
  3369. case D3DRS_FOGVERTEXMODE : return "D3DRS_FOGVERTEXMODE";
  3370. case D3DRS_COLORVERTEX : return "D3DRS_COLORVERTEX";
  3371. case D3DRS_LOCALVIEWER : return "D3DRS_LOCALVIEWER";
  3372. case D3DRS_NORMALIZENORMALS : return "D3DRS_NORMALIZENORMALS";
  3373. case D3DRS_DIFFUSEMATERIALSOURCE : return "D3DRS_DIFFUSEMATERIALSOURCE";
  3374. case D3DRS_SPECULARMATERIALSOURCE : return "D3DRS_SPECULARMATERIALSOURCE";
  3375. case D3DRS_AMBIENTMATERIALSOURCE : return "D3DRS_AMBIENTMATERIALSOURCE";
  3376. case D3DRS_EMISSIVEMATERIALSOURCE : return "D3DRS_EMISSIVEMATERIALSOURCE";
  3377. case D3DRS_VERTEXBLEND : return "D3DRS_VERTEXBLEND";
  3378. case D3DRS_CLIPPLANEENABLE : return "D3DRS_CLIPPLANEENABLE";
  3379. case D3DRS_SOFTWAREVERTEXPROCESSING : return "D3DRS_SOFTWAREVERTEXPROCESSING";
  3380. case D3DRS_POINTSIZE : return "D3DRS_POINTSIZE";
  3381. case D3DRS_POINTSIZE_MIN : return "D3DRS_POINTSIZE_MIN";
  3382. case D3DRS_POINTSPRITEENABLE : return "D3DRS_POINTSPRITEENABLE";
  3383. case D3DRS_POINTSCALEENABLE : return "D3DRS_POINTSCALEENABLE";
  3384. case D3DRS_POINTSCALE_A : return "D3DRS_POINTSCALE_A";
  3385. case D3DRS_POINTSCALE_B : return "D3DRS_POINTSCALE_B";
  3386. case D3DRS_POINTSCALE_C : return "D3DRS_POINTSCALE_C";
  3387. case D3DRS_MULTISAMPLEANTIALIAS : return "D3DRS_MULTISAMPLEANTIALIAS";
  3388. case D3DRS_MULTISAMPLEMASK : return "D3DRS_MULTISAMPLEMASK";
  3389. case D3DRS_PATCHEDGESTYLE : return "D3DRS_PATCHEDGESTYLE";
  3390. case D3DRS_PATCHSEGMENTS : return "D3DRS_PATCHSEGMENTS";
  3391. case D3DRS_DEBUGMONITORTOKEN : return "D3DRS_DEBUGMONITORTOKEN";
  3392. case D3DRS_POINTSIZE_MAX : return "D3DRS_POINTSIZE_MAX";
  3393. case D3DRS_INDEXEDVERTEXBLENDENABLE : return "D3DRS_INDEXEDVERTEXBLENDENABLE";
  3394. case D3DRS_COLORWRITEENABLE : return "D3DRS_COLORWRITEENABLE";
  3395. case D3DRS_TWEENFACTOR : return "D3DRS_TWEENFACTOR";
  3396. case D3DRS_BLENDOP : return "D3DRS_BLENDOP";
  3397. // case D3DRS_POSITIONORDER : return "D3DRS_POSITIONORDER";
  3398. // case D3DRS_NORMALORDER : return "D3DRS_NORMALORDER";
  3399. default : return "UNKNOWN";
  3400. }
  3401. }
  3402. const char* DX8Wrapper::Get_DX8_Texture_Stage_State_Name(D3DTEXTURESTAGESTATETYPE state)
  3403. {
  3404. switch (state) {
  3405. case D3DTSS_COLOROP : return "D3DTSS_COLOROP";
  3406. case D3DTSS_COLORARG1 : return "D3DTSS_COLORARG1";
  3407. case D3DTSS_COLORARG2 : return "D3DTSS_COLORARG2";
  3408. case D3DTSS_ALPHAOP : return "D3DTSS_ALPHAOP";
  3409. case D3DTSS_ALPHAARG1 : return "D3DTSS_ALPHAARG1";
  3410. case D3DTSS_ALPHAARG2 : return "D3DTSS_ALPHAARG2";
  3411. case D3DTSS_BUMPENVMAT00 : return "D3DTSS_BUMPENVMAT00";
  3412. case D3DTSS_BUMPENVMAT01 : return "D3DTSS_BUMPENVMAT01";
  3413. case D3DTSS_BUMPENVMAT10 : return "D3DTSS_BUMPENVMAT10";
  3414. case D3DTSS_BUMPENVMAT11 : return "D3DTSS_BUMPENVMAT11";
  3415. case D3DTSS_TEXCOORDINDEX : return "D3DTSS_TEXCOORDINDEX";
  3416. case D3DTSS_ADDRESSU : return "D3DTSS_ADDRESSU";
  3417. case D3DTSS_ADDRESSV : return "D3DTSS_ADDRESSV";
  3418. case D3DTSS_BORDERCOLOR : return "D3DTSS_BORDERCOLOR";
  3419. case D3DTSS_MAGFILTER : return "D3DTSS_MAGFILTER";
  3420. case D3DTSS_MINFILTER : return "D3DTSS_MINFILTER";
  3421. case D3DTSS_MIPFILTER : return "D3DTSS_MIPFILTER";
  3422. case D3DTSS_MIPMAPLODBIAS : return "D3DTSS_MIPMAPLODBIAS";
  3423. case D3DTSS_MAXMIPLEVEL : return "D3DTSS_MAXMIPLEVEL";
  3424. case D3DTSS_MAXANISOTROPY : return "D3DTSS_MAXANISOTROPY";
  3425. case D3DTSS_BUMPENVLSCALE : return "D3DTSS_BUMPENVLSCALE";
  3426. case D3DTSS_BUMPENVLOFFSET : return "D3DTSS_BUMPENVLOFFSET";
  3427. case D3DTSS_TEXTURETRANSFORMFLAGS : return "D3DTSS_TEXTURETRANSFORMFLAGS";
  3428. case D3DTSS_ADDRESSW : return "D3DTSS_ADDRESSW";
  3429. case D3DTSS_COLORARG0 : return "D3DTSS_COLORARG0";
  3430. case D3DTSS_ALPHAARG0 : return "D3DTSS_ALPHAARG0";
  3431. case D3DTSS_RESULTARG : return "D3DTSS_RESULTARG";
  3432. default : return "UNKNOWN";
  3433. }
  3434. }
  3435. void DX8Wrapper::Get_DX8_Render_State_Value_Name(StringClass& name, D3DRENDERSTATETYPE state, unsigned value)
  3436. {
  3437. switch (state) {
  3438. case D3DRS_ZENABLE:
  3439. name=Get_DX8_ZBuffer_Type_Name(value);
  3440. break;
  3441. case D3DRS_FILLMODE:
  3442. name=Get_DX8_Fill_Mode_Name(value);
  3443. break;
  3444. case D3DRS_SHADEMODE:
  3445. name=Get_DX8_Shade_Mode_Name(value);
  3446. break;
  3447. case D3DRS_LINEPATTERN:
  3448. case D3DRS_FOGCOLOR:
  3449. case D3DRS_ALPHAREF:
  3450. case D3DRS_STENCILMASK:
  3451. case D3DRS_STENCILWRITEMASK:
  3452. case D3DRS_TEXTUREFACTOR:
  3453. case D3DRS_AMBIENT:
  3454. case D3DRS_CLIPPLANEENABLE:
  3455. case D3DRS_MULTISAMPLEMASK:
  3456. name.Format("0x%x",value);
  3457. break;
  3458. case D3DRS_ZWRITEENABLE:
  3459. case D3DRS_ALPHATESTENABLE:
  3460. case D3DRS_LASTPIXEL:
  3461. case D3DRS_DITHERENABLE:
  3462. case D3DRS_ALPHABLENDENABLE:
  3463. case D3DRS_FOGENABLE:
  3464. case D3DRS_SPECULARENABLE:
  3465. case D3DRS_STENCILENABLE:
  3466. case D3DRS_RANGEFOGENABLE:
  3467. case D3DRS_EDGEANTIALIAS:
  3468. case D3DRS_CLIPPING:
  3469. case D3DRS_LIGHTING:
  3470. case D3DRS_COLORVERTEX:
  3471. case D3DRS_LOCALVIEWER:
  3472. case D3DRS_NORMALIZENORMALS:
  3473. case D3DRS_SOFTWAREVERTEXPROCESSING:
  3474. case D3DRS_POINTSPRITEENABLE:
  3475. case D3DRS_POINTSCALEENABLE:
  3476. case D3DRS_MULTISAMPLEANTIALIAS:
  3477. case D3DRS_INDEXEDVERTEXBLENDENABLE:
  3478. name=value ? "TRUE" : "FALSE";
  3479. break;
  3480. case D3DRS_SRCBLEND:
  3481. case D3DRS_DESTBLEND:
  3482. name=Get_DX8_Blend_Name(value);
  3483. break;
  3484. case D3DRS_CULLMODE:
  3485. name=Get_DX8_Cull_Mode_Name(value);
  3486. break;
  3487. case D3DRS_ZFUNC:
  3488. case D3DRS_ALPHAFUNC:
  3489. case D3DRS_STENCILFUNC:
  3490. name=Get_DX8_Cmp_Func_Name(value);
  3491. break;
  3492. case D3DRS_ZVISIBLE:
  3493. name="NOTSUPPORTED";
  3494. break;
  3495. case D3DRS_FOGTABLEMODE:
  3496. case D3DRS_FOGVERTEXMODE:
  3497. name=Get_DX8_Fog_Mode_Name(value);
  3498. break;
  3499. case D3DRS_FOGSTART:
  3500. case D3DRS_FOGEND:
  3501. case D3DRS_FOGDENSITY:
  3502. case D3DRS_POINTSIZE:
  3503. case D3DRS_POINTSIZE_MIN:
  3504. case D3DRS_POINTSCALE_A:
  3505. case D3DRS_POINTSCALE_B:
  3506. case D3DRS_POINTSCALE_C:
  3507. case D3DRS_PATCHSEGMENTS:
  3508. case D3DRS_POINTSIZE_MAX:
  3509. case D3DRS_TWEENFACTOR:
  3510. name.Format("%f",*(float*)&value);
  3511. break;
  3512. case D3DRS_ZBIAS:
  3513. case D3DRS_STENCILREF:
  3514. name.Format("%d",value);
  3515. break;
  3516. case D3DRS_STENCILFAIL:
  3517. case D3DRS_STENCILZFAIL:
  3518. case D3DRS_STENCILPASS:
  3519. name=Get_DX8_Stencil_Op_Name(value);
  3520. break;
  3521. case D3DRS_WRAP0:
  3522. case D3DRS_WRAP1:
  3523. case D3DRS_WRAP2:
  3524. case D3DRS_WRAP3:
  3525. case D3DRS_WRAP4:
  3526. case D3DRS_WRAP5:
  3527. case D3DRS_WRAP6:
  3528. case D3DRS_WRAP7:
  3529. name="0";
  3530. if (value&D3DWRAP_U) name+="|D3DWRAP_U";
  3531. if (value&D3DWRAP_V) name+="|D3DWRAP_V";
  3532. if (value&D3DWRAP_W) name+="|D3DWRAP_W";
  3533. break;
  3534. case D3DRS_DIFFUSEMATERIALSOURCE:
  3535. case D3DRS_SPECULARMATERIALSOURCE:
  3536. case D3DRS_AMBIENTMATERIALSOURCE:
  3537. case D3DRS_EMISSIVEMATERIALSOURCE:
  3538. name=Get_DX8_Material_Source_Name(value);
  3539. break;
  3540. case D3DRS_VERTEXBLEND:
  3541. name=Get_DX8_Vertex_Blend_Flag_Name(value);
  3542. break;
  3543. case D3DRS_PATCHEDGESTYLE:
  3544. name=Get_DX8_Patch_Edge_Style_Name(value);
  3545. break;
  3546. case D3DRS_DEBUGMONITORTOKEN:
  3547. name=Get_DX8_Debug_Monitor_Token_Name(value);
  3548. break;
  3549. case D3DRS_COLORWRITEENABLE:
  3550. name="0";
  3551. if (value&D3DCOLORWRITEENABLE_RED) name+="|D3DCOLORWRITEENABLE_RED";
  3552. if (value&D3DCOLORWRITEENABLE_GREEN) name+="|D3DCOLORWRITEENABLE_GREEN";
  3553. if (value&D3DCOLORWRITEENABLE_BLUE) name+="|D3DCOLORWRITEENABLE_BLUE";
  3554. if (value&D3DCOLORWRITEENABLE_ALPHA) name+="|D3DCOLORWRITEENABLE_ALPHA";
  3555. break;
  3556. case D3DRS_BLENDOP:
  3557. name=Get_DX8_Blend_Op_Name(value);
  3558. break;
  3559. default:
  3560. name.Format("UNKNOWN (%d)",value);
  3561. break;
  3562. }
  3563. }
  3564. void DX8Wrapper::Get_DX8_Texture_Stage_State_Value_Name(StringClass& name, D3DTEXTURESTAGESTATETYPE state, unsigned value)
  3565. {
  3566. switch (state) {
  3567. case D3DTSS_COLOROP:
  3568. case D3DTSS_ALPHAOP:
  3569. name=Get_DX8_Texture_Op_Name(value);
  3570. break;
  3571. case D3DTSS_COLORARG0:
  3572. case D3DTSS_COLORARG1:
  3573. case D3DTSS_COLORARG2:
  3574. case D3DTSS_ALPHAARG0:
  3575. case D3DTSS_ALPHAARG1:
  3576. case D3DTSS_ALPHAARG2:
  3577. case D3DTSS_RESULTARG:
  3578. name=Get_DX8_Texture_Arg_Name(value);
  3579. break;
  3580. case D3DTSS_ADDRESSU:
  3581. case D3DTSS_ADDRESSV:
  3582. case D3DTSS_ADDRESSW:
  3583. name=Get_DX8_Texture_Address_Name(value);
  3584. break;
  3585. case D3DTSS_MAGFILTER:
  3586. case D3DTSS_MINFILTER:
  3587. case D3DTSS_MIPFILTER:
  3588. name=Get_DX8_Texture_Filter_Name(value);
  3589. break;
  3590. case D3DTSS_TEXTURETRANSFORMFLAGS:
  3591. name=Get_DX8_Texture_Transform_Flag_Name(value);
  3592. // Floating point values
  3593. case D3DTSS_MIPMAPLODBIAS:
  3594. case D3DTSS_BUMPENVMAT00:
  3595. case D3DTSS_BUMPENVMAT01:
  3596. case D3DTSS_BUMPENVMAT10:
  3597. case D3DTSS_BUMPENVMAT11:
  3598. case D3DTSS_BUMPENVLSCALE:
  3599. case D3DTSS_BUMPENVLOFFSET:
  3600. name.Format("%f",*(float*)&value);
  3601. break;
  3602. case D3DTSS_TEXCOORDINDEX:
  3603. if ((value&0xffff0000)==D3DTSS_TCI_CAMERASPACENORMAL) {
  3604. name.Format("D3DTSS_TCI_CAMERASPACENORMAL|%d",value&0xffff);
  3605. }
  3606. else if ((value&0xffff0000)==D3DTSS_TCI_CAMERASPACEPOSITION) {
  3607. name.Format("D3DTSS_TCI_CAMERASPACEPOSITION|%d",value&0xffff);
  3608. }
  3609. else if ((value&0xffff0000)==D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR) {
  3610. name.Format("D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR|%d",value&0xffff);
  3611. }
  3612. else {
  3613. name.Format("%d",value);
  3614. }
  3615. break;
  3616. // Integer value
  3617. case D3DTSS_MAXMIPLEVEL:
  3618. case D3DTSS_MAXANISOTROPY:
  3619. name.Format("%d",value);
  3620. break;
  3621. // Hex values
  3622. case D3DTSS_BORDERCOLOR:
  3623. name.Format("0x%x",value);
  3624. break;
  3625. default:
  3626. name.Format("UNKNOWN (%d)",value);
  3627. break;
  3628. }
  3629. }
  3630. const char* DX8Wrapper::Get_DX8_Texture_Op_Name(unsigned value)
  3631. {
  3632. switch (value) {
  3633. case D3DTOP_DISABLE : return "D3DTOP_DISABLE";
  3634. case D3DTOP_SELECTARG1 : return "D3DTOP_SELECTARG1";
  3635. case D3DTOP_SELECTARG2 : return "D3DTOP_SELECTARG2";
  3636. case D3DTOP_MODULATE : return "D3DTOP_MODULATE";
  3637. case D3DTOP_MODULATE2X : return "D3DTOP_MODULATE2X";
  3638. case D3DTOP_MODULATE4X : return "D3DTOP_MODULATE4X";
  3639. case D3DTOP_ADD : return "D3DTOP_ADD";
  3640. case D3DTOP_ADDSIGNED : return "D3DTOP_ADDSIGNED";
  3641. case D3DTOP_ADDSIGNED2X : return "D3DTOP_ADDSIGNED2X";
  3642. case D3DTOP_SUBTRACT : return "D3DTOP_SUBTRACT";
  3643. case D3DTOP_ADDSMOOTH : return "D3DTOP_ADDSMOOTH";
  3644. case D3DTOP_BLENDDIFFUSEALPHA : return "D3DTOP_BLENDDIFFUSEALPHA";
  3645. case D3DTOP_BLENDTEXTUREALPHA : return "D3DTOP_BLENDTEXTUREALPHA";
  3646. case D3DTOP_BLENDFACTORALPHA : return "D3DTOP_BLENDFACTORALPHA";
  3647. case D3DTOP_BLENDTEXTUREALPHAPM : return "D3DTOP_BLENDTEXTUREALPHAPM";
  3648. case D3DTOP_BLENDCURRENTALPHA : return "D3DTOP_BLENDCURRENTALPHA";
  3649. case D3DTOP_PREMODULATE : return "D3DTOP_PREMODULATE";
  3650. case D3DTOP_MODULATEALPHA_ADDCOLOR : return "D3DTOP_MODULATEALPHA_ADDCOLOR";
  3651. case D3DTOP_MODULATECOLOR_ADDALPHA : return "D3DTOP_MODULATECOLOR_ADDALPHA";
  3652. case D3DTOP_MODULATEINVALPHA_ADDCOLOR : return "D3DTOP_MODULATEINVALPHA_ADDCOLOR";
  3653. case D3DTOP_MODULATEINVCOLOR_ADDALPHA : return "D3DTOP_MODULATEINVCOLOR_ADDALPHA";
  3654. case D3DTOP_BUMPENVMAP : return "D3DTOP_BUMPENVMAP";
  3655. case D3DTOP_BUMPENVMAPLUMINANCE : return "D3DTOP_BUMPENVMAPLUMINANCE";
  3656. case D3DTOP_DOTPRODUCT3 : return "D3DTOP_DOTPRODUCT3";
  3657. case D3DTOP_MULTIPLYADD : return "D3DTOP_MULTIPLYADD";
  3658. case D3DTOP_LERP : return "D3DTOP_LERP";
  3659. default : return "UNKNOWN";
  3660. }
  3661. }
  3662. const char* DX8Wrapper::Get_DX8_Texture_Arg_Name(unsigned value)
  3663. {
  3664. switch (value) {
  3665. case D3DTA_CURRENT : return "D3DTA_CURRENT";
  3666. case D3DTA_DIFFUSE : return "D3DTA_DIFFUSE";
  3667. case D3DTA_SELECTMASK : return "D3DTA_SELECTMASK";
  3668. case D3DTA_SPECULAR : return "D3DTA_SPECULAR";
  3669. case D3DTA_TEMP : return "D3DTA_TEMP";
  3670. case D3DTA_TEXTURE : return "D3DTA_TEXTURE";
  3671. case D3DTA_TFACTOR : return "D3DTA_TFACTOR";
  3672. case D3DTA_ALPHAREPLICATE : return "D3DTA_ALPHAREPLICATE";
  3673. case D3DTA_COMPLEMENT : return "D3DTA_COMPLEMENT";
  3674. default : return "UNKNOWN";
  3675. }
  3676. }
  3677. const char* DX8Wrapper::Get_DX8_Texture_Filter_Name(unsigned value)
  3678. {
  3679. switch (value) {
  3680. case D3DTEXF_NONE : return "D3DTEXF_NONE";
  3681. case D3DTEXF_POINT : return "D3DTEXF_POINT";
  3682. case D3DTEXF_LINEAR : return "D3DTEXF_LINEAR";
  3683. case D3DTEXF_ANISOTROPIC : return "D3DTEXF_ANISOTROPIC";
  3684. case D3DTEXF_FLATCUBIC : return "D3DTEXF_FLATCUBIC";
  3685. case D3DTEXF_GAUSSIANCUBIC : return "D3DTEXF_GAUSSIANCUBIC";
  3686. default : return "UNKNOWN";
  3687. }
  3688. }
  3689. const char* DX8Wrapper::Get_DX8_Texture_Address_Name(unsigned value)
  3690. {
  3691. switch (value) {
  3692. case D3DTADDRESS_WRAP : return "D3DTADDRESS_WRAP";
  3693. case D3DTADDRESS_MIRROR : return "D3DTADDRESS_MIRROR";
  3694. case D3DTADDRESS_CLAMP : return "D3DTADDRESS_CLAMP";
  3695. case D3DTADDRESS_BORDER : return "D3DTADDRESS_BORDER";
  3696. case D3DTADDRESS_MIRRORONCE: return "D3DTADDRESS_MIRRORONCE";
  3697. default : return "UNKNOWN";
  3698. }
  3699. }
  3700. const char* DX8Wrapper::Get_DX8_Texture_Transform_Flag_Name(unsigned value)
  3701. {
  3702. switch (value) {
  3703. case D3DTTFF_DISABLE : return "D3DTTFF_DISABLE";
  3704. case D3DTTFF_COUNT1 : return "D3DTTFF_COUNT1";
  3705. case D3DTTFF_COUNT2 : return "D3DTTFF_COUNT2";
  3706. case D3DTTFF_COUNT3 : return "D3DTTFF_COUNT3";
  3707. case D3DTTFF_COUNT4 : return "D3DTTFF_COUNT4";
  3708. case D3DTTFF_PROJECTED : return "D3DTTFF_PROJECTED";
  3709. default : return "UNKNOWN";
  3710. }
  3711. }
  3712. const char* DX8Wrapper::Get_DX8_ZBuffer_Type_Name(unsigned value)
  3713. {
  3714. switch (value) {
  3715. case D3DZB_FALSE : return "D3DZB_FALSE";
  3716. case D3DZB_TRUE : return "D3DZB_TRUE";
  3717. case D3DZB_USEW : return "D3DZB_USEW";
  3718. default : return "UNKNOWN";
  3719. }
  3720. }
  3721. const char* DX8Wrapper::Get_DX8_Fill_Mode_Name(unsigned value)
  3722. {
  3723. switch (value) {
  3724. case D3DFILL_POINT : return "D3DFILL_POINT";
  3725. case D3DFILL_WIREFRAME : return "D3DFILL_WIREFRAME";
  3726. case D3DFILL_SOLID : return "D3DFILL_SOLID";
  3727. default : return "UNKNOWN";
  3728. }
  3729. }
  3730. const char* DX8Wrapper::Get_DX8_Shade_Mode_Name(unsigned value)
  3731. {
  3732. switch (value) {
  3733. case D3DSHADE_FLAT : return "D3DSHADE_FLAT";
  3734. case D3DSHADE_GOURAUD : return "D3DSHADE_GOURAUD";
  3735. case D3DSHADE_PHONG : return "D3DSHADE_PHONG";
  3736. default : return "UNKNOWN";
  3737. }
  3738. }
  3739. const char* DX8Wrapper::Get_DX8_Blend_Name(unsigned value)
  3740. {
  3741. switch (value) {
  3742. case D3DBLEND_ZERO : return "D3DBLEND_ZERO";
  3743. case D3DBLEND_ONE : return "D3DBLEND_ONE";
  3744. case D3DBLEND_SRCCOLOR : return "D3DBLEND_SRCCOLOR";
  3745. case D3DBLEND_INVSRCCOLOR : return "D3DBLEND_INVSRCCOLOR";
  3746. case D3DBLEND_SRCALPHA : return "D3DBLEND_SRCALPHA";
  3747. case D3DBLEND_INVSRCALPHA : return "D3DBLEND_INVSRCALPHA";
  3748. case D3DBLEND_DESTALPHA : return "D3DBLEND_DESTALPHA";
  3749. case D3DBLEND_INVDESTALPHA : return "D3DBLEND_INVDESTALPHA";
  3750. case D3DBLEND_DESTCOLOR : return "D3DBLEND_DESTCOLOR";
  3751. case D3DBLEND_INVDESTCOLOR : return "D3DBLEND_INVDESTCOLOR";
  3752. case D3DBLEND_SRCALPHASAT : return "D3DBLEND_SRCALPHASAT";
  3753. case D3DBLEND_BOTHSRCALPHA : return "D3DBLEND_BOTHSRCALPHA";
  3754. case D3DBLEND_BOTHINVSRCALPHA : return "D3DBLEND_BOTHINVSRCALPHA";
  3755. default : return "UNKNOWN";
  3756. }
  3757. }
  3758. const char* DX8Wrapper::Get_DX8_Cull_Mode_Name(unsigned value)
  3759. {
  3760. switch (value) {
  3761. case D3DCULL_NONE : return "D3DCULL_NONE";
  3762. case D3DCULL_CW : return "D3DCULL_CW";
  3763. case D3DCULL_CCW : return "D3DCULL_CCW";
  3764. default : return "UNKNOWN";
  3765. }
  3766. }
  3767. const char* DX8Wrapper::Get_DX8_Cmp_Func_Name(unsigned value)
  3768. {
  3769. switch (value) {
  3770. case D3DCMP_NEVER : return "D3DCMP_NEVER";
  3771. case D3DCMP_LESS : return "D3DCMP_LESS";
  3772. case D3DCMP_EQUAL : return "D3DCMP_EQUAL";
  3773. case D3DCMP_LESSEQUAL : return "D3DCMP_LESSEQUAL";
  3774. case D3DCMP_GREATER : return "D3DCMP_GREATER";
  3775. case D3DCMP_NOTEQUAL : return "D3DCMP_NOTEQUAL";
  3776. case D3DCMP_GREATEREQUAL : return "D3DCMP_GREATEREQUAL";
  3777. case D3DCMP_ALWAYS : return "D3DCMP_ALWAYS";
  3778. default : return "UNKNOWN";
  3779. }
  3780. }
  3781. const char* DX8Wrapper::Get_DX8_Fog_Mode_Name(unsigned value)
  3782. {
  3783. switch (value) {
  3784. case D3DFOG_NONE : return "D3DFOG_NONE";
  3785. case D3DFOG_EXP : return "D3DFOG_EXP";
  3786. case D3DFOG_EXP2 : return "D3DFOG_EXP2";
  3787. case D3DFOG_LINEAR : return "D3DFOG_LINEAR";
  3788. default : return "UNKNOWN";
  3789. }
  3790. }
  3791. const char* DX8Wrapper::Get_DX8_Stencil_Op_Name(unsigned value)
  3792. {
  3793. switch (value) {
  3794. case D3DSTENCILOP_KEEP : return "D3DSTENCILOP_KEEP";
  3795. case D3DSTENCILOP_ZERO : return "D3DSTENCILOP_ZERO";
  3796. case D3DSTENCILOP_REPLACE : return "D3DSTENCILOP_REPLACE";
  3797. case D3DSTENCILOP_INCRSAT : return "D3DSTENCILOP_INCRSAT";
  3798. case D3DSTENCILOP_DECRSAT : return "D3DSTENCILOP_DECRSAT";
  3799. case D3DSTENCILOP_INVERT : return "D3DSTENCILOP_INVERT";
  3800. case D3DSTENCILOP_INCR : return "D3DSTENCILOP_INCR";
  3801. case D3DSTENCILOP_DECR : return "D3DSTENCILOP_DECR";
  3802. default : return "UNKNOWN";
  3803. }
  3804. }
  3805. const char* DX8Wrapper::Get_DX8_Material_Source_Name(unsigned value)
  3806. {
  3807. switch (value) {
  3808. case D3DMCS_MATERIAL : return "D3DMCS_MATERIAL";
  3809. case D3DMCS_COLOR1 : return "D3DMCS_COLOR1";
  3810. case D3DMCS_COLOR2 : return "D3DMCS_COLOR2";
  3811. default : return "UNKNOWN";
  3812. }
  3813. }
  3814. const char* DX8Wrapper::Get_DX8_Vertex_Blend_Flag_Name(unsigned value)
  3815. {
  3816. switch (value) {
  3817. case D3DVBF_DISABLE : return "D3DVBF_DISABLE";
  3818. case D3DVBF_1WEIGHTS : return "D3DVBF_1WEIGHTS";
  3819. case D3DVBF_2WEIGHTS : return "D3DVBF_2WEIGHTS";
  3820. case D3DVBF_3WEIGHTS : return "D3DVBF_3WEIGHTS";
  3821. case D3DVBF_TWEENING : return "D3DVBF_TWEENING";
  3822. case D3DVBF_0WEIGHTS : return "D3DVBF_0WEIGHTS";
  3823. default : return "UNKNOWN";
  3824. }
  3825. }
  3826. const char* DX8Wrapper::Get_DX8_Patch_Edge_Style_Name(unsigned value)
  3827. {
  3828. switch (value) {
  3829. case D3DPATCHEDGE_DISCRETE : return "D3DPATCHEDGE_DISCRETE";
  3830. case D3DPATCHEDGE_CONTINUOUS:return "D3DPATCHEDGE_CONTINUOUS";
  3831. default : return "UNKNOWN";
  3832. }
  3833. }
  3834. const char* DX8Wrapper::Get_DX8_Debug_Monitor_Token_Name(unsigned value)
  3835. {
  3836. switch (value) {
  3837. case D3DDMT_ENABLE : return "D3DDMT_ENABLE";
  3838. case D3DDMT_DISABLE : return "D3DDMT_DISABLE";
  3839. default : return "UNKNOWN";
  3840. }
  3841. }
  3842. const char* DX8Wrapper::Get_DX8_Blend_Op_Name(unsigned value)
  3843. {
  3844. switch (value) {
  3845. case D3DBLENDOP_ADD : return "D3DBLENDOP_ADD";
  3846. case D3DBLENDOP_SUBTRACT : return "D3DBLENDOP_SUBTRACT";
  3847. case D3DBLENDOP_REVSUBTRACT: return "D3DBLENDOP_REVSUBTRACT";
  3848. case D3DBLENDOP_MIN : return "D3DBLENDOP_MIN";
  3849. case D3DBLENDOP_MAX : return "D3DBLENDOP_MAX";
  3850. default : return "UNKNOWN";
  3851. }
  3852. }
  3853. //============================================================================
  3854. // DX8Wrapper::getBackBufferFormat
  3855. //============================================================================
  3856. WW3DFormat DX8Wrapper::getBackBufferFormat( void )
  3857. {
  3858. return D3DFormat_To_WW3DFormat( _PresentParameters.BackBufferFormat );
  3859. }