OgreD3D9RenderSystem.cpp 136 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004
  1. /*
  2. -----------------------------------------------------------------------------
  3. This source file is part of OGRE
  4. (Object-oriented Graphics Rendering Engine)
  5. For the latest info, see http://www.ogre3d.org
  6. Copyright (c) 2000-2011 Torus Knot Software Ltd
  7. Permission is hereby granted, free of charge, to any person obtaining a copy
  8. of this software and associated documentation files (the "Software"), to deal
  9. in the Software without restriction, including without limitation the rights
  10. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. copies of the Software, and to permit persons to whom the Software is
  12. furnished to do so, subject to the following conditions:
  13. The above copyright notice and this permission notice shall be included in
  14. all copies or substantial portions of the Software.
  15. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. THE SOFTWARE.
  22. -----------------------------------------------------------------------------
  23. */
  24. #include "OgreD3D9RenderSystem.h"
  25. #include "OgreD3D9Prerequisites.h"
  26. #include "OgreD3D9DriverList.h"
  27. #include "OgreD3D9Driver.h"
  28. #include "OgreD3D9VideoModeList.h"
  29. #include "OgreD3D9VideoMode.h"
  30. #include "OgreD3D9RenderWindow.h"
  31. #include "OgreD3D9TextureManager.h"
  32. #include "OgreD3D9Texture.h"
  33. #include "OgreMath.h"
  34. #include "OgreD3D9HardwareBufferManager.h"
  35. #include "OgreD3D9HardwareIndexBuffer.h"
  36. #include "OgreD3D9HardwareVertexBuffer.h"
  37. #include "OgreD3D9VertexDeclaration.h"
  38. #include "OgreD3D9GpuProgram.h"
  39. #include "OgreD3D9GpuProgramManager.h"
  40. #include "OgreD3D9HLSLProgramFactory.h"
  41. #include "OgreD3D9HardwareOcclusionQuery.h"
  42. #include "OgreFrustum.h"
  43. #include "OgreD3D9MultiRenderTarget.h"
  44. #include "OgreD3D9DeviceManager.h"
  45. #include "OgreD3D9ResourceManager.h"
  46. #define FLOAT2DWORD(f) *((DWORD*)&f)
  47. namespace Ogre
  48. {
  49. D3D9RenderSystem* D3D9RenderSystem::msD3D9RenderSystem = NULL;
  50. //---------------------------------------------------------------------
  51. D3D9RenderSystem::D3D9RenderSystem( HINSTANCE hInstance )
  52. {
  53. // update singleton access pointer.
  54. msD3D9RenderSystem = this;
  55. // set the instance being passed
  56. mhInstance = hInstance;
  57. // set pointers to NULL
  58. mpD3D = NULL;
  59. mDriverList = NULL;
  60. mActiveD3DDriver = NULL;
  61. mTextureManager = NULL;
  62. mHardwareBufferManager = NULL;
  63. mGpuProgramManager = NULL;
  64. mUseNVPerfHUD = false;
  65. mHLSLProgramFactory = NULL;
  66. mDeviceManager = NULL;
  67. // Create the resource manager.
  68. mResourceManager = new D3D9ResourceManager();
  69. // init lights
  70. for(int i = 0; i < MAX_LIGHTS; i++ )
  71. mLights[i] = 0;
  72. // Create our Direct3D object
  73. if( NULL == (mpD3D = Direct3DCreate9(D3D_SDK_VERSION)) )
  74. OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR, "Failed to create Direct3D9 object", "D3D9RenderSystem::D3D9RenderSystem" );
  75. // set config options defaults
  76. initConfigOptions();
  77. // fsaa options
  78. mFSAAHint = "";
  79. mFSAASamples = 0;
  80. // set stages desc. to defaults
  81. for (size_t n = 0; n < OGRE_MAX_TEXTURE_LAYERS; n++)
  82. {
  83. mTexStageDesc[n].autoTexCoordType = TEXCALC_NONE;
  84. mTexStageDesc[n].coordIndex = 0;
  85. mTexStageDesc[n].texType = D3D9Mappings::D3D_TEX_TYPE_NORMAL;
  86. mTexStageDesc[n].pTex = 0;
  87. mTexStageDesc[n].pVertexTex = 0;
  88. }
  89. mLastVertexSourceCount = 0;
  90. mCurrentLights.clear();
  91. // Enumerate events
  92. mEventNames.push_back("DeviceLost");
  93. mEventNames.push_back("DeviceRestored");
  94. }
  95. //---------------------------------------------------------------------
  96. D3D9RenderSystem::~D3D9RenderSystem()
  97. {
  98. shutdown();
  99. // Deleting the HLSL program factory
  100. if (mHLSLProgramFactory)
  101. {
  102. // TODO PORT - If i'll be supporting factories in this way, enable this
  103. //// Remove from manager safely
  104. //if (HighLevelGpuProgramManager::getSingletonPtr())
  105. // HighLevelGpuProgramManager::getSingleton().removeFactory(mHLSLProgramFactory);
  106. delete mHLSLProgramFactory;
  107. mHLSLProgramFactory = 0;
  108. }
  109. SAFE_RELEASE( mpD3D );
  110. SAFE_DELETE ( mResourceManager );
  111. msD3D9RenderSystem = NULL;
  112. }
  113. //---------------------------------------------------------------------
  114. const String& D3D9RenderSystem::getName() const
  115. {
  116. static String strName( "Direct3D9 Rendering Subsystem");
  117. return strName;
  118. }
  119. //---------------------------------------------------------------------
  120. D3D9DriverList* D3D9RenderSystem::getDirect3DDrivers()
  121. {
  122. if( !mDriverList )
  123. mDriverList = new D3D9DriverList();
  124. return mDriverList;
  125. }
  126. //---------------------------------------------------------------------
  127. bool D3D9RenderSystem::_checkMultiSampleQuality(D3DMULTISAMPLE_TYPE type, DWORD *outQuality, D3DFORMAT format, UINT adapterNum, D3DDEVTYPE deviceType, BOOL fullScreen)
  128. {
  129. HRESULT hr;
  130. hr = mpD3D->CheckDeviceMultiSampleType(
  131. adapterNum,
  132. deviceType,
  133. format,
  134. fullScreen,
  135. type,
  136. outQuality);
  137. if (SUCCEEDED(hr))
  138. return true;
  139. else
  140. return false;
  141. }
  142. //---------------------------------------------------------------------
  143. void D3D9RenderSystem::initConfigOptions()
  144. {
  145. D3D9DriverList* driverList;
  146. D3D9Driver* driver;
  147. // TODO PORT - I'm not going to use these config options, but I need to find another way to initialize the render system
  148. // ConfigOption optDevice;
  149. // ConfigOption optVideoMode;
  150. // ConfigOption optFullScreen;
  151. // ConfigOption optVSync;
  152. // ConfigOption optVSyncInterval;
  153. // ConfigOption optAA;
  154. // ConfigOption optFPUMode;
  155. // ConfigOption optNVPerfHUD;
  156. // ConfigOption optSRGB;
  157. // ConfigOption optResourceCeationPolicy;
  158. //
  159. // driverList = this->getDirect3DDrivers();
  160. //
  161. // optDevice.name = "Rendering Device";
  162. // optDevice.currentValue.clear();
  163. // optDevice.possibleValues.clear();
  164. // optDevice.immutable = false;
  165. //
  166. // optVideoMode.name = "Video Mode";
  167. // optVideoMode.currentValue = "800 x 600 @ 32-bit colour";
  168. // optVideoMode.immutable = false;
  169. //
  170. // optFullScreen.name = "Full Screen";
  171. // optFullScreen.possibleValues.push_back( "Yes" );
  172. // optFullScreen.possibleValues.push_back( "No" );
  173. // optFullScreen.currentValue = "Yes";
  174. // optFullScreen.immutable = false;
  175. //
  176. // optResourceCeationPolicy.name = "Resource Creation Policy";
  177. // optResourceCeationPolicy.possibleValues.push_back( "Create on all devices" );
  178. // optResourceCeationPolicy.possibleValues.push_back( "Create on active device" );
  179. //
  180. // if (mResourceManager->getCreationPolicy() == RCP_CREATE_ON_ACTIVE_DEVICE)
  181. // optResourceCeationPolicy.currentValue = "Create on active device";
  182. // else if (mResourceManager->getCreationPolicy() == RCP_CREATE_ON_ALL_DEVICES)
  183. // optResourceCeationPolicy.currentValue = "Create on all devices";
  184. // else
  185. // optResourceCeationPolicy.currentValue = "N/A";
  186. // optResourceCeationPolicy.immutable = false;
  187. //
  188. // for( unsigned j=0; j < driverList->count(); j++ )
  189. // {
  190. // driver = driverList->item(j);
  191. // optDevice.possibleValues.push_back( driver->DriverDescription() );
  192. // // Make first one default
  193. // if( j==0 )
  194. // optDevice.currentValue = driver->DriverDescription();
  195. // }
  196. //
  197. // optVSync.name = "VSync";
  198. // optVSync.immutable = false;
  199. // optVSync.possibleValues.push_back( "Yes" );
  200. // optVSync.possibleValues.push_back( "No" );
  201. // optVSync.currentValue = "No";
  202. //
  203. // optVSyncInterval.name = "VSync Interval";
  204. // optVSyncInterval.immutable = false;
  205. // optVSyncInterval.possibleValues.push_back( "1" );
  206. // optVSyncInterval.possibleValues.push_back( "2" );
  207. // optVSyncInterval.possibleValues.push_back( "3" );
  208. // optVSyncInterval.possibleValues.push_back( "4" );
  209. // optVSyncInterval.currentValue = "1";
  210. //
  211. // optAA.name = "FSAA";
  212. // optAA.immutable = false;
  213. // optAA.possibleValues.push_back( "None" );
  214. // optAA.currentValue = "None";
  215. //
  216. // optFPUMode.name = "Floating-point mode";
  217. //#if OGRE_DOUBLE_PRECISION
  218. // optFPUMode.currentValue = "Consistent";
  219. //#else
  220. // optFPUMode.currentValue = "Fastest";
  221. //#endif
  222. // optFPUMode.possibleValues.clear();
  223. // optFPUMode.possibleValues.push_back("Fastest");
  224. // optFPUMode.possibleValues.push_back("Consistent");
  225. // optFPUMode.immutable = false;
  226. //
  227. // optNVPerfHUD.currentValue = "No";
  228. // optNVPerfHUD.immutable = false;
  229. // optNVPerfHUD.name = "Allow NVPerfHUD";
  230. // optNVPerfHUD.possibleValues.push_back( "Yes" );
  231. // optNVPerfHUD.possibleValues.push_back( "No" );
  232. //
  233. //
  234. // // SRGB on auto window
  235. // optSRGB.name = "sRGB Gamma Conversion";
  236. // optSRGB.possibleValues.push_back("Yes");
  237. // optSRGB.possibleValues.push_back("No");
  238. // optSRGB.currentValue = "No";
  239. // optSRGB.immutable = false;
  240. //
  241. // mOptions[optDevice.name] = optDevice;
  242. // mOptions[optVideoMode.name] = optVideoMode;
  243. // mOptions[optFullScreen.name] = optFullScreen;
  244. // mOptions[optVSync.name] = optVSync;
  245. // mOptions[optVSyncInterval.name] = optVSyncInterval;
  246. // mOptions[optAA.name] = optAA;
  247. // mOptions[optFPUMode.name] = optFPUMode;
  248. // mOptions[optNVPerfHUD.name] = optNVPerfHUD;
  249. // mOptions[optSRGB.name] = optSRGB;
  250. // mOptions[optResourceCeationPolicy.name] = optResourceCeationPolicy;
  251. refreshD3DSettings();
  252. }
  253. //---------------------------------------------------------------------
  254. void D3D9RenderSystem::refreshD3DSettings()
  255. {
  256. // TODO PORT - I'm not going to use these config options, but I need to find another way to initialize the render system
  257. //ConfigOption* optVideoMode;
  258. //D3D9Driver* driver = 0;
  259. //D3D9VideoMode* videoMode;
  260. //ConfigOptionMap::iterator opt = mOptions.find( "Rendering Device" );
  261. //if( opt != mOptions.end() )
  262. //{
  263. // for( unsigned j=0; j < getDirect3DDrivers()->count(); j++ )
  264. // {
  265. // D3D9Driver* curDriver = getDirect3DDrivers()->item(j);
  266. // if( curDriver->DriverDescription() == opt->second.currentValue )
  267. // {
  268. // driver = curDriver;
  269. // break;
  270. // }
  271. // }
  272. // if (driver)
  273. // {
  274. // opt = mOptions.find( "Video Mode" );
  275. // optVideoMode = &opt->second;
  276. // optVideoMode->possibleValues.clear();
  277. // // get vide modes for this device
  278. // for( unsigned k=0; k < driver->getVideoModeList()->count(); k++ )
  279. // {
  280. // videoMode = driver->getVideoModeList()->item( k );
  281. // optVideoMode->possibleValues.push_back( videoMode->getDescription() );
  282. // }
  283. // // Reset video mode to default if previous doesn't avail in new possible values
  284. // StringVector::const_iterator itValue =
  285. // std::find(optVideoMode->possibleValues.begin(),
  286. // optVideoMode->possibleValues.end(),
  287. // optVideoMode->currentValue);
  288. // if (itValue == optVideoMode->possibleValues.end())
  289. // {
  290. // optVideoMode->currentValue = "800 x 600 @ 32-bit colour";
  291. // }
  292. // // Also refresh FSAA options
  293. // refreshFSAAOptions();
  294. // }
  295. //}
  296. }
  297. //---------------------------------------------------------------------
  298. void D3D9RenderSystem::setConfigOption( const String &name, const String &value )
  299. {
  300. // TODO PORT - I'm not going to use these config options, but I need to find another way to initialize the render system
  301. //bool viewModeChanged = false;
  302. //// Find option
  303. //ConfigOptionMap::iterator it = mOptions.find( name );
  304. //// Update
  305. //if( it != mOptions.end() )
  306. // it->second.currentValue = value;
  307. //else
  308. //{
  309. // StringUtil::StrStreamType str;
  310. // str << "Option named '" << name << "' does not exist.";
  311. // OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS, str.str(), "D3D9RenderSystem::setConfigOption" );
  312. //}
  313. //// Refresh other options if D3DDriver changed
  314. //if( name == "Rendering Device" )
  315. // refreshD3DSettings();
  316. //if( name == "Full Screen" )
  317. //{
  318. // // Video mode is applicable
  319. // it = mOptions.find( "Video Mode" );
  320. // if (it->second.currentValue.empty())
  321. // {
  322. // it->second.currentValue = "800 x 600 @ 32-bit colour";
  323. // viewModeChanged = true;
  324. // }
  325. //}
  326. //if( name == "FSAA" )
  327. //{
  328. // StringVector values = StringUtil::split(value, " ", 1);
  329. // mFSAASamples = StringConverter::parseUnsignedInt(values[0]);
  330. // if (values.size() > 1)
  331. // mFSAAHint = values[1];
  332. //}
  333. //if( name == "VSync" )
  334. //{
  335. // if (value == "Yes")
  336. // mVSync = true;
  337. // else
  338. // mVSync = false;
  339. //}
  340. //if( name == "VSync Interval" )
  341. //{
  342. // mVSyncInterval = StringConverter::parseUnsignedInt(value);
  343. //}
  344. //if( name == "Allow NVPerfHUD" )
  345. //{
  346. // if (value == "Yes")
  347. // mUseNVPerfHUD = true;
  348. // else
  349. // mUseNVPerfHUD = false;
  350. //}
  351. //if (viewModeChanged || name == "Video Mode")
  352. //{
  353. // refreshFSAAOptions();
  354. //}
  355. //if (name == "Resource Creation Policy")
  356. //{
  357. // if (value == "Create on active device")
  358. // mResourceManager->setCreationPolicy(RCP_CREATE_ON_ACTIVE_DEVICE);
  359. // else if (value == "Create on all devices")
  360. // mResourceManager->setCreationPolicy(RCP_CREATE_ON_ALL_DEVICES);
  361. //}
  362. }
  363. //---------------------------------------------------------------------
  364. void D3D9RenderSystem::refreshFSAAOptions()
  365. {
  366. // TODO PORT - I'm not going to use these config options, but I need to find another way to initialize the render system
  367. //ConfigOptionMap::iterator it = mOptions.find( "FSAA" );
  368. //ConfigOption* optFSAA = &it->second;
  369. //optFSAA->possibleValues.clear();
  370. //optFSAA->possibleValues.push_back("0");
  371. //it = mOptions.find("Rendering Device");
  372. //D3D9Driver *driver = getDirect3DDrivers()->item(it->second.currentValue);
  373. //if (driver)
  374. //{
  375. // it = mOptions.find("Video Mode");
  376. // D3D9VideoMode *videoMode = driver->getVideoModeList()->item(it->second.currentValue);
  377. // if (videoMode)
  378. // {
  379. // DWORD numLevels = 0;
  380. // bool bOK;
  381. // for (unsigned int n = 2; n < 25; n++)
  382. // {
  383. // bOK = this->_checkMultiSampleQuality(
  384. // (D3DMULTISAMPLE_TYPE)n,
  385. // &numLevels,
  386. // videoMode->getFormat(),
  387. // driver->getAdapterNumber(),
  388. // D3DDEVTYPE_HAL,
  389. // TRUE);
  390. // if (bOK)
  391. // {
  392. // optFSAA->possibleValues.push_back(StringConverter::toString(n));
  393. // if (n >= 8)
  394. // optFSAA->possibleValues.push_back(StringConverter::toString(n) + " [Quality]");
  395. // }
  396. // }
  397. // }
  398. //}
  399. //// Reset FSAA to none if previous doesn't avail in new possible values
  400. //StringVector::const_iterator itValue =
  401. // std::find(optFSAA->possibleValues.begin(),
  402. // optFSAA->possibleValues.end(),
  403. // optFSAA->currentValue);
  404. //if (itValue == optFSAA->possibleValues.end())
  405. //{
  406. // optFSAA->currentValue = "0";
  407. //}
  408. }
  409. //---------------------------------------------------------------------
  410. String D3D9RenderSystem::validateConfigOptions()
  411. {
  412. // TODO PORT - I'm not going to use these config options, but I need to find another way to initialize the render system
  413. //ConfigOptionMap::iterator it;
  414. //// check if video mode is selected
  415. //it = mOptions.find( "Video Mode" );
  416. //if (it->second.currentValue.empty())
  417. // return "A video mode must be selected.";
  418. //it = mOptions.find( "Rendering Device" );
  419. //bool foundDriver = false;
  420. //D3D9DriverList* driverList = getDirect3DDrivers();
  421. //for( ushort j=0; j < driverList->count(); j++ )
  422. //{
  423. // if( driverList->item(j)->DriverDescription() == it->second.currentValue )
  424. // {
  425. // foundDriver = true;
  426. // break;
  427. // }
  428. //}
  429. //if (!foundDriver)
  430. //{
  431. // // Just pick the first driver
  432. // setConfigOption("Rendering Device", driverList->item(0)->DriverDescription());
  433. // return "Your DirectX driver name has changed since the last time you ran OGRE; "
  434. // "the 'Rendering Device' has been changed.";
  435. //}
  436. //it = mOptions.find( "VSync" );
  437. //if( it->second.currentValue == "Yes" )
  438. // mVSync = true;
  439. //else
  440. // mVSync = false;
  441. return StringUtil::BLANK;
  442. }
  443. //---------------------------------------------------------------------
  444. RenderWindow* D3D9RenderSystem::_initialise( bool autoCreateWindow, const String& windowTitle )
  445. {
  446. RenderWindow* autoWindow = NULL;
  447. // Init using current settings
  448. mActiveD3DDriver = NULL;
  449. //ConfigOptionMap::iterator opt = mOptions.find( "Rendering Device" );
  450. //for( uint j=0; j < getDirect3DDrivers()->count(); j++ )
  451. //{
  452. // if( getDirect3DDrivers()->item(j)->DriverDescription() == opt->second.currentValue )
  453. // {
  454. // mActiveD3DDriver = getDirect3DDrivers()->item(j);
  455. // break;
  456. // }
  457. //}
  458. if( !mActiveD3DDriver )
  459. OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS, "Problems finding requested Direct3D driver!", "D3D9RenderSystem::initialise" );
  460. // get driver version
  461. mDriverVersion.major = HIWORD(mActiveD3DDriver->getAdapterIdentifier().DriverVersion.HighPart);
  462. mDriverVersion.minor = LOWORD(mActiveD3DDriver->getAdapterIdentifier().DriverVersion.HighPart);
  463. mDriverVersion.release = HIWORD(mActiveD3DDriver->getAdapterIdentifier().DriverVersion.LowPart);
  464. mDriverVersion.build = LOWORD(mActiveD3DDriver->getAdapterIdentifier().DriverVersion.LowPart);
  465. // Create the device manager.
  466. mDeviceManager = new D3D9DeviceManager();
  467. // Create the texture manager for use by others
  468. // TODO PORT - Texture manager is null! This is bound to cause problems but I need to get this compiling
  469. //mTextureManager = new D3D9TextureManager();
  470. // Also create hardware buffer manager
  471. mHardwareBufferManager = new D3D9HardwareBufferManager();
  472. // Create the GPU program manager
  473. mGpuProgramManager = new D3D9GpuProgramManager();
  474. // Create & register HLSL factory
  475. mHLSLProgramFactory = new D3D9HLSLProgramFactory();
  476. if( autoCreateWindow )
  477. {
  478. //bool fullScreen;
  479. //opt = mOptions.find( "Full Screen" );
  480. //if( opt == mOptions.end() )
  481. // OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR, "Can't find full screen option!", "D3D9RenderSystem::initialise" );
  482. //fullScreen = opt->second.currentValue == "Yes";
  483. // TODO PORT - Not loading fullscreen from options, assume its false
  484. bool fullScreen = false;
  485. D3D9VideoMode* videoMode = NULL;
  486. unsigned int width, height;
  487. String temp;
  488. // TODO - Not loading video mode from the list, instead we assume 800x600 @ 32-bit
  489. //opt = mOptions.find( "Video Mode" );
  490. //if( opt == mOptions.end() )
  491. // OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR, "Can't find Video Mode option!", "D3D9RenderSystem::initialise" );
  492. //// The string we are manipulating looks like this :width x height @ colourDepth
  493. //// Pull out the colour depth by getting what comes after the @ and a space
  494. //String colourDepth = opt->second.currentValue.substr(opt->second.currentValue.rfind('@')+1);
  495. //// Now we know that the width starts a 0, so if we can find the end we can parse that out
  496. //String::size_type widthEnd = opt->second.currentValue.find(' ');
  497. //// we know that the height starts 3 characters after the width and goes until the next space
  498. //String::size_type heightEnd = opt->second.currentValue.find(' ', widthEnd+3);
  499. //// Now we can parse out the values
  500. //width = StringConverter::parseInt(opt->second.currentValue.substr(0, widthEnd));
  501. //height = StringConverter::parseInt(opt->second.currentValue.substr(widthEnd+3, heightEnd));
  502. width = 800;
  503. height = 600;
  504. String colourDepth = "32-bit";
  505. String resValue = "800 x 600 @ 32-bit";
  506. for( unsigned j=0; j < mActiveD3DDriver->getVideoModeList()->count(); j++ )
  507. {
  508. temp = mActiveD3DDriver->getVideoModeList()->item(j)->getDescription();
  509. // In full screen we only want to allow supported resolutions, so temp and opt->second.currentValue need to
  510. // match exactly, but in windowed mode we can allow for arbitrary window sized, so we only need
  511. // to match the colour values
  512. if(fullScreen && (temp == resValue) ||
  513. !fullScreen && (temp.substr(temp.rfind('@')+1) == colourDepth))
  514. {
  515. videoMode = mActiveD3DDriver->getVideoModeList()->item(j);
  516. break;
  517. }
  518. }
  519. if( !videoMode )
  520. OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR, "Can't find requested video mode.", "D3D9RenderSystem::initialise" );
  521. // sRGB window option
  522. bool hwGamma = false;
  523. // TODO PORT - Not loading this from config so assume false for now
  524. //opt = mOptions.find( "sRGB Gamma Conversion" );
  525. //if( opt == mOptions.end() )
  526. // OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR, "Can't find sRGB option!", "D3D9RenderSystem::initialise" );
  527. //hwGamma = opt->second.currentValue == "Yes";
  528. NameValuePairList miscParams;
  529. miscParams["colourDepth"] = StringConverter::toString(videoMode->getColourDepth());
  530. miscParams["FSAA"] = StringConverter::toString(mFSAASamples);
  531. miscParams["FSAAHint"] = mFSAAHint;
  532. miscParams["vsync"] = StringConverter::toString(mVSync);
  533. miscParams["vsyncInterval"] = StringConverter::toString(mVSyncInterval);
  534. miscParams["useNVPerfHUD"] = StringConverter::toString(mUseNVPerfHUD);
  535. miscParams["gamma"] = StringConverter::toString(hwGamma);
  536. miscParams["monitorIndex"] = StringConverter::toString(static_cast<int>(mActiveD3DDriver->getAdapterNumber()));
  537. autoWindow = _createRenderWindow( windowTitle, width, height,
  538. fullScreen, &miscParams );
  539. // If we have 16bit depth buffer enable w-buffering.
  540. assert( autoWindow );
  541. if ( autoWindow->getColourDepth() == 16 )
  542. {
  543. mWBuffer = true;
  544. }
  545. else
  546. {
  547. mWBuffer = false;
  548. }
  549. }
  550. // call superclass method
  551. RenderSystem::_initialise( autoCreateWindow );
  552. return autoWindow;
  553. }
  554. //---------------------------------------------------------------------
  555. void D3D9RenderSystem::reinitialise()
  556. {
  557. this->shutdown();
  558. this->_initialise( true );
  559. }
  560. //---------------------------------------------------------------------
  561. void D3D9RenderSystem::shutdown()
  562. {
  563. RenderSystem::shutdown();
  564. SAFE_DELETE( mDeviceManager );
  565. SAFE_DELETE( mDriverList );
  566. mActiveD3DDriver = NULL;
  567. SAFE_DELETE( mTextureManager );
  568. SAFE_DELETE( mHardwareBufferManager );
  569. SAFE_DELETE( mGpuProgramManager );
  570. }
  571. //---------------------------------------------------------------------
  572. RenderWindow* D3D9RenderSystem::_createRenderWindow(const String &name,
  573. unsigned int width, unsigned int height, bool fullScreen,
  574. const NameValuePairList *miscParams)
  575. {
  576. // Log a message
  577. StringStream ss;
  578. ss << "D3D9RenderSystem::_createRenderWindow \"" << name << "\", " <<
  579. width << "x" << height << " ";
  580. if(fullScreen)
  581. ss << "fullscreen ";
  582. else
  583. ss << "windowed ";
  584. if(miscParams)
  585. {
  586. ss << " miscParams: ";
  587. NameValuePairList::const_iterator it;
  588. for(it=miscParams->begin(); it!=miscParams->end(); ++it)
  589. {
  590. ss << it->first << "=" << it->second << " ";
  591. }
  592. }
  593. String msg;
  594. // Make sure we don't already have a render target of the
  595. // same name as the one supplied
  596. if( mRenderTargets.find( name ) != mRenderTargets.end() )
  597. {
  598. msg = "A render target of the same name '" + name + "' already "
  599. "exists. You cannot create a new window with this name.";
  600. OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR, msg, "D3D9RenderSystem::_createRenderWindow" );
  601. }
  602. D3D9RenderWindow* renderWindow = new D3D9RenderWindow(mhInstance);
  603. renderWindow->create(name, width, height, fullScreen, miscParams);
  604. mResourceManager->lockDeviceAccess();
  605. try
  606. {
  607. mDeviceManager->linkRenderWindow(renderWindow);
  608. }
  609. catch (const Ogre::RenderingAPIException&)
  610. {
  611. // after catching the exception, clean up
  612. mResourceManager->unlockDeviceAccess();
  613. renderWindow->destroy();
  614. // re-throw
  615. throw;
  616. }
  617. mResourceManager->unlockDeviceAccess();
  618. mRenderWindows.push_back(renderWindow);
  619. updateRenderSystemCapabilities(renderWindow);
  620. attachRenderTarget( *renderWindow );
  621. return renderWindow;
  622. }
  623. //---------------------------------------------------------------------
  624. bool D3D9RenderSystem::_createRenderWindows(const RenderWindowDescriptionList& renderWindowDescriptions,
  625. RenderWindowList& createdWindows)
  626. {
  627. // Call base render system method.
  628. if (false == RenderSystem::_createRenderWindows(renderWindowDescriptions, createdWindows))
  629. return false;
  630. // Simply call _createRenderWindow in a loop.
  631. for (size_t i = 0; i < renderWindowDescriptions.size(); ++i)
  632. {
  633. const RenderWindowDescription& curRenderWindowDescription = renderWindowDescriptions[i];
  634. RenderWindow* curWindow = NULL;
  635. curWindow = _createRenderWindow(curRenderWindowDescription.name,
  636. curRenderWindowDescription.width,
  637. curRenderWindowDescription.height,
  638. curRenderWindowDescription.useFullScreen,
  639. &curRenderWindowDescription.miscParams);
  640. createdWindows.push_back(curWindow);
  641. }
  642. return true;
  643. }
  644. //---------------------------------------------------------------------
  645. RenderSystemCapabilities* D3D9RenderSystem::updateRenderSystemCapabilities(D3D9RenderWindow* renderWindow)
  646. {
  647. RenderSystemCapabilities* rsc = mRealCapabilities;
  648. if (rsc == NULL)
  649. rsc = new RenderSystemCapabilities();
  650. rsc->setCategoryRelevant(CAPS_CATEGORY_D3D9, true);
  651. rsc->setDriverVersion(mDriverVersion);
  652. rsc->setDeviceName(mActiveD3DDriver->DriverDescription());
  653. rsc->setRenderSystemName(getName());
  654. // Supports fixed-function
  655. rsc->setCapability(RSC_FIXED_FUNCTION);
  656. // Init caps to maximum.
  657. rsc->setNumTextureUnits(1024);
  658. rsc->setCapability(RSC_ANISOTROPY);
  659. rsc->setCapability(RSC_AUTOMIPMAP);
  660. rsc->setCapability(RSC_DOT3);
  661. rsc->setCapability(RSC_CUBEMAPPING);
  662. rsc->setCapability(RSC_SCISSOR_TEST);
  663. rsc->setCapability(RSC_TWO_SIDED_STENCIL);
  664. rsc->setCapability(RSC_STENCIL_WRAP);
  665. rsc->setCapability(RSC_HWOCCLUSION);
  666. rsc->setCapability(RSC_USER_CLIP_PLANES);
  667. rsc->setCapability(RSC_VERTEX_FORMAT_UBYTE4);
  668. rsc->setCapability(RSC_TEXTURE_3D);
  669. rsc->setCapability(RSC_NON_POWER_OF_2_TEXTURES);
  670. rsc->setNonPOW2TexturesLimited(false);
  671. rsc->setNumMultiRenderTargets(OGRE_MAX_MULTIPLE_RENDER_TARGETS);
  672. rsc->setCapability(RSC_MRT_DIFFERENT_BIT_DEPTHS);
  673. rsc->setCapability(RSC_POINT_SPRITES);
  674. rsc->setCapability(RSC_POINT_EXTENDED_PARAMETERS);
  675. rsc->setMaxPointSize(10.0);
  676. rsc->setCapability(RSC_MIPMAP_LOD_BIAS);
  677. rsc->setCapability(RSC_PERSTAGECONSTANT);
  678. rsc->setCapability(RSC_HWSTENCIL);
  679. rsc->setStencilBufferBitDepth(8);
  680. rsc->setCapability(RSC_ADVANCED_BLEND_OPERATIONS);
  681. for (uint i=0; i < mDeviceManager->getDeviceCount(); ++i)
  682. {
  683. D3D9Device* device = mDeviceManager->getDevice(i);
  684. IDirect3DDevice9* d3d9Device = device->getD3D9Device();
  685. IDirect3DSurface9* pSurf;
  686. // Check for hardware stencil support
  687. d3d9Device->GetDepthStencilSurface(&pSurf);
  688. if (pSurf != NULL)
  689. {
  690. D3DSURFACE_DESC surfDesc;
  691. pSurf->GetDesc(&surfDesc);
  692. pSurf->Release();
  693. if (surfDesc.Format != D3DFMT_D15S1 &&
  694. surfDesc.Format != D3DFMT_D24S8 &&
  695. surfDesc.Format != D3DFMT_D24X4S4 &&
  696. surfDesc.Format != D3DFMT_D24FS8)
  697. rsc->unsetCapability(RSC_HWSTENCIL);
  698. }
  699. // Check for hardware occlusion support
  700. HRESULT hr = d3d9Device->CreateQuery(D3DQUERYTYPE_OCCLUSION, NULL);
  701. if (FAILED(hr))
  702. rsc->unsetCapability(RSC_HWOCCLUSION);
  703. }
  704. // Update RS caps using the minimum value found in adapter list.
  705. for (unsigned int i=0; i < mDriverList->count(); ++i)
  706. {
  707. D3D9Driver* pCurDriver = mDriverList->item(i);
  708. const D3DCAPS9& rkCurCaps = pCurDriver->getD3D9DeviceCaps();
  709. if (rkCurCaps.MaxSimultaneousTextures < rsc->getNumTextureUnits())
  710. {
  711. rsc->setNumTextureUnits(static_cast<ushort>(rkCurCaps.MaxSimultaneousTextures));
  712. }
  713. // Check for Anisotropy.
  714. if (rkCurCaps.MaxAnisotropy <= 1)
  715. rsc->unsetCapability(RSC_ANISOTROPY);
  716. // Check automatic mipmap generation.
  717. if ((rkCurCaps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP) == 0)
  718. rsc->unsetCapability(RSC_AUTOMIPMAP);
  719. // Check Dot product 3.
  720. if ((rkCurCaps.TextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3) == 0)
  721. rsc->unsetCapability(RSC_DOT3);
  722. // Scissor test
  723. if ((rkCurCaps.RasterCaps & D3DPRASTERCAPS_SCISSORTEST) == 0)
  724. rsc->unsetCapability(RSC_SCISSOR_TEST);
  725. // Two-sided stencil
  726. if ((rkCurCaps.StencilCaps & D3DSTENCILCAPS_TWOSIDED) == 0)
  727. rsc->unsetCapability(RSC_TWO_SIDED_STENCIL);
  728. // stencil wrap
  729. if ((rkCurCaps.StencilCaps & D3DSTENCILCAPS_INCR) == 0 ||
  730. (rkCurCaps.StencilCaps & D3DSTENCILCAPS_DECR) == 0)
  731. rsc->unsetCapability(RSC_STENCIL_WRAP);
  732. // User clip planes
  733. if (rkCurCaps.MaxUserClipPlanes == 0)
  734. rsc->unsetCapability(RSC_USER_CLIP_PLANES);
  735. // UBYTE4 type?
  736. if ((rkCurCaps.DeclTypes & D3DDTCAPS_UBYTE4) == 0)
  737. rsc->unsetCapability(RSC_VERTEX_FORMAT_UBYTE4);
  738. // Check cube map support.
  739. if ((rkCurCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP) == 0)
  740. rsc->unsetCapability(RSC_CUBEMAPPING);
  741. // 3D textures?
  742. if ((rkCurCaps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP) == 0)
  743. rsc->unsetCapability(RSC_TEXTURE_3D);
  744. if (rkCurCaps.TextureCaps & D3DPTEXTURECAPS_POW2)
  745. {
  746. // Conditional support for non POW2
  747. if (rkCurCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)
  748. rsc->setNonPOW2TexturesLimited(true);
  749. // Only power of 2 supported.
  750. else
  751. rsc->unsetCapability(RSC_NON_POWER_OF_2_TEXTURES);
  752. }
  753. // Number of render targets
  754. if (rkCurCaps.NumSimultaneousRTs < rsc->getNumMultiRenderTargets())
  755. {
  756. rsc->setNumMultiRenderTargets(std::min((ushort)rkCurCaps.NumSimultaneousRTs, (ushort)OGRE_MAX_MULTIPLE_RENDER_TARGETS));
  757. }
  758. if((rkCurCaps.PrimitiveMiscCaps & D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS) == 0)
  759. {
  760. rsc->unsetCapability(RSC_MRT_DIFFERENT_BIT_DEPTHS);
  761. }
  762. // Point sprites
  763. if (rkCurCaps.MaxPointSize <= 1.0f)
  764. {
  765. rsc->unsetCapability(RSC_POINT_SPRITES);
  766. // sprites and extended parameters go together in D3D
  767. rsc->unsetCapability(RSC_POINT_EXTENDED_PARAMETERS);
  768. }
  769. // Take the minimum point size.
  770. if (rkCurCaps.MaxPointSize < rsc->getMaxPointSize())
  771. rsc->setMaxPointSize(rkCurCaps.MaxPointSize);
  772. // Mipmap LOD biasing?
  773. if ((rkCurCaps.RasterCaps & D3DPRASTERCAPS_MIPMAPLODBIAS) == 0)
  774. rsc->unsetCapability(RSC_MIPMAP_LOD_BIAS);
  775. // Do we support per-stage src_manual constants?
  776. // HACK - ATI drivers seem to be buggy and don't support per-stage constants properly?
  777. // TODO: move this to RSC
  778. if((rkCurCaps.PrimitiveMiscCaps & D3DPMISCCAPS_PERSTAGECONSTANT) == 0)
  779. rsc->unsetCapability(RSC_PERSTAGECONSTANT);
  780. // Advanced blend operations? min max subtract rev
  781. if((rkCurCaps.PrimitiveMiscCaps & D3DPMISCCAPS_BLENDOP) == 0)
  782. rsc->unsetCapability(RSC_ADVANCED_BLEND_OPERATIONS);
  783. }
  784. // Blending between stages supported
  785. rsc->setCapability(RSC_BLENDING);
  786. // We always support compression, D3DX will decompress if device does not support
  787. rsc->setCapability(RSC_TEXTURE_COMPRESSION);
  788. rsc->setCapability(RSC_TEXTURE_COMPRESSION_DXT);
  789. // We always support VBOs
  790. rsc->setCapability(RSC_VBO);
  791. convertVertexShaderCaps(rsc);
  792. convertPixelShaderCaps(rsc);
  793. // Adapter details
  794. const D3DADAPTER_IDENTIFIER9& adapterID = mActiveD3DDriver->getAdapterIdentifier();
  795. // determine vendor
  796. // Full list of vendors here: http://www.pcidatabase.com/vendors.php?sort=id
  797. switch(adapterID.VendorId)
  798. {
  799. case 0x10DE:
  800. rsc->setVendor(GPU_NVIDIA);
  801. break;
  802. case 0x1002:
  803. rsc->setVendor(GPU_ATI);
  804. break;
  805. case 0x163C:
  806. case 0x8086:
  807. rsc->setVendor(GPU_INTEL);
  808. break;
  809. case 0x5333:
  810. rsc->setVendor(GPU_S3);
  811. break;
  812. case 0x3D3D:
  813. rsc->setVendor(GPU_3DLABS);
  814. break;
  815. case 0x102B:
  816. rsc->setVendor(GPU_MATROX);
  817. break;
  818. case 0x1039:
  819. rsc->setVendor(GPU_SIS);
  820. break;
  821. default:
  822. rsc->setVendor(GPU_UNKNOWN);
  823. break;
  824. };
  825. // Infinite projection?
  826. // We have no capability for this, so we have to base this on our
  827. // experience and reports from users
  828. // Non-vertex program capable hardware does not appear to support it
  829. if (rsc->hasCapability(RSC_VERTEX_PROGRAM))
  830. {
  831. // GeForce4 Ti (and presumably GeForce3) does not
  832. // render infinite projection properly, even though it does in GL
  833. // So exclude all cards prior to the FX range from doing infinite
  834. if (rsc->getVendor() != GPU_NVIDIA || // not nVidia
  835. !((adapterID.DeviceId >= 0x200 && adapterID.DeviceId <= 0x20F) || //gf3
  836. (adapterID.DeviceId >= 0x250 && adapterID.DeviceId <= 0x25F) || //gf4ti
  837. (adapterID.DeviceId >= 0x280 && adapterID.DeviceId <= 0x28F) || //gf4ti
  838. (adapterID.DeviceId >= 0x170 && adapterID.DeviceId <= 0x18F) || //gf4 go
  839. (adapterID.DeviceId >= 0x280 && adapterID.DeviceId <= 0x28F))) //gf4ti go
  840. {
  841. rsc->setCapability(RSC_INFINITE_FAR_PLANE);
  842. }
  843. }
  844. // We always support rendertextures bigger than the frame buffer
  845. rsc->setCapability(RSC_HWRENDER_TO_TEXTURE);
  846. // Determine if any floating point texture format is supported
  847. D3DFORMAT floatFormats[6] = {D3DFMT_R16F, D3DFMT_G16R16F,
  848. D3DFMT_A16B16G16R16F, D3DFMT_R32F, D3DFMT_G32R32F,
  849. D3DFMT_A32B32G32R32F};
  850. IDirect3DSurface9* bbSurf;
  851. renderWindow->getCustomAttribute("DDBACKBUFFER", &bbSurf);
  852. D3DSURFACE_DESC bbSurfDesc;
  853. bbSurf->GetDesc(&bbSurfDesc);
  854. for (int i = 0; i < 6; ++i)
  855. {
  856. if (SUCCEEDED(mpD3D->CheckDeviceFormat(mActiveD3DDriver->getAdapterNumber(),
  857. D3DDEVTYPE_HAL, bbSurfDesc.Format,
  858. 0, D3DRTYPE_TEXTURE, floatFormats[i])))
  859. {
  860. rsc->setCapability(RSC_TEXTURE_FLOAT);
  861. break;
  862. }
  863. }
  864. // TODO: make convertVertex/Fragment fill in rsc
  865. // TODO: update the below line to use rsc
  866. // Vertex textures
  867. if (rsc->isShaderProfileSupported("vs_3_0"))
  868. {
  869. // Run through all the texture formats looking for any which support
  870. // vertex texture fetching. Must have at least one!
  871. // All ATI Radeon up to X1n00 say they support vs_3_0,
  872. // but they support no texture formats for vertex texture fetch (cheaters!)
  873. if (checkVertexTextureFormats(renderWindow))
  874. {
  875. rsc->setCapability(RSC_VERTEX_TEXTURE_FETCH);
  876. // always 4 vertex texture units in vs_3_0, and never shared
  877. rsc->setNumVertexTextureUnits(4);
  878. rsc->setVertexTextureUnitsShared(false);
  879. }
  880. }
  881. // Check alpha to coverage support
  882. // this varies per vendor! But at least SM3 is required
  883. if (rsc->isShaderProfileSupported("ps_3_0"))
  884. {
  885. // NVIDIA needs a separate check
  886. if (rsc->getVendor() == GPU_NVIDIA)
  887. {
  888. if (mpD3D->CheckDeviceFormat(
  889. D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,D3DRTYPE_SURFACE,
  890. (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C')) == S_OK)
  891. {
  892. rsc->setCapability(RSC_ALPHA_TO_COVERAGE);
  893. }
  894. }
  895. else if (rsc->getVendor() == GPU_ATI)
  896. {
  897. // There is no check on ATI, we have to assume SM3 == support
  898. rsc->setCapability(RSC_ALPHA_TO_COVERAGE);
  899. }
  900. // no other cards have Dx9 hacks for alpha to coverage, as far as I know
  901. }
  902. if (mRealCapabilities == NULL)
  903. {
  904. mRealCapabilities = rsc;
  905. mRealCapabilities->addShaderProfile("hlsl");
  906. // if we are using custom capabilities, then
  907. // mCurrentCapabilities has already been loaded
  908. if(!mUseCustomCapabilities)
  909. mCurrentCapabilities = mRealCapabilities;
  910. initialiseFromRenderSystemCapabilities(mCurrentCapabilities, renderWindow);
  911. }
  912. return rsc;
  913. }
  914. //---------------------------------------------------------------------
  915. void D3D9RenderSystem::convertVertexShaderCaps(RenderSystemCapabilities* rsc) const
  916. {
  917. ushort major = 0xFF;
  918. ushort minor = 0xFF;
  919. D3DCAPS9 minVSCaps;
  920. // Find the device with the lowest vertex shader caps.
  921. for (unsigned int i=0; i < mDriverList->count(); ++i)
  922. {
  923. D3D9Driver* pCurDriver = mDriverList->item(i);
  924. const D3DCAPS9& rkCurCaps = pCurDriver->getD3D9DeviceCaps();
  925. ushort currMajor = static_cast<ushort>((rkCurCaps.VertexShaderVersion & 0x0000FF00) >> 8);
  926. ushort currMinor = static_cast<ushort>(rkCurCaps.VertexShaderVersion & 0x000000FF);
  927. if (currMajor < major)
  928. {
  929. major = currMajor;
  930. minor = currMinor;
  931. minVSCaps = rkCurCaps;
  932. }
  933. else if (currMajor == major && currMinor < minor)
  934. {
  935. minor = currMinor;
  936. minVSCaps = rkCurCaps;
  937. }
  938. }
  939. // In case we didn't found any vertex shader support
  940. // try the IDirect3DDevice9 caps instead of the IDirect3D9
  941. // software vertex processing is reported there
  942. if (major == 0 && minor == 0)
  943. {
  944. IDirect3DDevice9* lpD3DDevice9 = getActiveD3D9Device();
  945. D3DCAPS9 d3dDeviceCaps9;
  946. lpD3DDevice9->GetDeviceCaps(&d3dDeviceCaps9);
  947. major = static_cast<ushort>((d3dDeviceCaps9.VertexShaderVersion & 0x0000FF00) >> 8);
  948. minor = static_cast<ushort>(d3dDeviceCaps9.VertexShaderVersion & 0x000000FF);
  949. }
  950. bool vs2x = false;
  951. bool vs2a = false;
  952. // Special case detection for vs_2_x/a support
  953. if (major >= 2)
  954. {
  955. if ((minVSCaps.VS20Caps.Caps & D3DVS20CAPS_PREDICATION) &&
  956. (minVSCaps.VS20Caps.DynamicFlowControlDepth > 0) &&
  957. (minVSCaps.VS20Caps.NumTemps >= 12))
  958. {
  959. vs2x = true;
  960. }
  961. if ((minVSCaps.VS20Caps.Caps & D3DVS20CAPS_PREDICATION) &&
  962. (minVSCaps.VS20Caps.DynamicFlowControlDepth > 0) &&
  963. (minVSCaps.VS20Caps.NumTemps >= 13))
  964. {
  965. vs2a = true;
  966. }
  967. }
  968. // Populate max param count
  969. switch (major)
  970. {
  971. case 1:
  972. // No boolean params allowed
  973. rsc->setVertexProgramConstantBoolCount(0);
  974. // No integer params allowed
  975. rsc->setVertexProgramConstantIntCount(0);
  976. // float params, always 4D
  977. rsc->setVertexProgramConstantFloatCount(static_cast<ushort>(minVSCaps.MaxVertexShaderConst));
  978. break;
  979. case 2:
  980. // 16 boolean params allowed
  981. rsc->setVertexProgramConstantBoolCount(16);
  982. // 16 integer params allowed, 4D
  983. rsc->setVertexProgramConstantIntCount(16);
  984. // float params, always 4D
  985. rsc->setVertexProgramConstantFloatCount(static_cast<ushort>(minVSCaps.MaxVertexShaderConst));
  986. break;
  987. case 3:
  988. // 16 boolean params allowed
  989. rsc->setVertexProgramConstantBoolCount(16);
  990. // 16 integer params allowed, 4D
  991. rsc->setVertexProgramConstantIntCount(16);
  992. // float params, always 4D
  993. rsc->setVertexProgramConstantFloatCount(static_cast<ushort>(minVSCaps.MaxVertexShaderConst));
  994. break;
  995. }
  996. // populate syntax codes in program manager (no breaks in this one so it falls through)
  997. switch(major)
  998. {
  999. case 3:
  1000. rsc->addShaderProfile("vs_3_0");
  1001. case 2:
  1002. if (vs2x)
  1003. rsc->addShaderProfile("vs_2_x");
  1004. if (vs2a)
  1005. rsc->addShaderProfile("vs_2_a");
  1006. rsc->addShaderProfile("vs_2_0");
  1007. case 1:
  1008. rsc->addShaderProfile("vs_1_1");
  1009. rsc->setCapability(RSC_VERTEX_PROGRAM);
  1010. }
  1011. }
  1012. //---------------------------------------------------------------------
  1013. void D3D9RenderSystem::convertPixelShaderCaps(RenderSystemCapabilities* rsc) const
  1014. {
  1015. ushort major = 0xFF;
  1016. ushort minor = 0xFF;
  1017. D3DCAPS9 minPSCaps;
  1018. // Find the device with the lowest pixel shader caps.
  1019. for (unsigned int i=0; i < mDriverList->count(); ++i)
  1020. {
  1021. D3D9Driver* pCurDriver = mDriverList->item(i);
  1022. const D3DCAPS9& currCaps = pCurDriver->getD3D9DeviceCaps();
  1023. ushort currMajor = static_cast<ushort>((currCaps.PixelShaderVersion & 0x0000FF00) >> 8);
  1024. ushort currMinor = static_cast<ushort>(currCaps.PixelShaderVersion & 0x000000FF);
  1025. if (currMajor < major)
  1026. {
  1027. major = currMajor;
  1028. minor = currMinor;
  1029. minPSCaps = currCaps;
  1030. }
  1031. else if (currMajor == major && currMinor < minor)
  1032. {
  1033. minor = currMinor;
  1034. minPSCaps = currCaps;
  1035. }
  1036. }
  1037. bool ps2a = false;
  1038. bool ps2b = false;
  1039. bool ps2x = false;
  1040. // Special case detection for ps_2_x/a/b support
  1041. if (major >= 2)
  1042. {
  1043. if ((minPSCaps.PS20Caps.Caps & D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT) &&
  1044. (minPSCaps.PS20Caps.NumTemps >= 32))
  1045. {
  1046. ps2b = true;
  1047. }
  1048. if ((minPSCaps.PS20Caps.Caps & D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT) &&
  1049. (minPSCaps.PS20Caps.Caps & D3DPS20CAPS_NODEPENDENTREADLIMIT) &&
  1050. (minPSCaps.PS20Caps.Caps & D3DPS20CAPS_ARBITRARYSWIZZLE) &&
  1051. (minPSCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) &&
  1052. (minPSCaps.PS20Caps.Caps & D3DPS20CAPS_PREDICATION) &&
  1053. (minPSCaps.PS20Caps.NumTemps >= 22))
  1054. {
  1055. ps2a = true;
  1056. }
  1057. // Does this enough?
  1058. if (ps2a || ps2b)
  1059. {
  1060. ps2x = true;
  1061. }
  1062. }
  1063. switch (major)
  1064. {
  1065. case 1:
  1066. // no boolean params allowed
  1067. rsc->setFragmentProgramConstantBoolCount(0);
  1068. // no integer params allowed
  1069. rsc->setFragmentProgramConstantIntCount(0);
  1070. // float params, always 4D
  1071. // NB in ps_1_x these are actually stored as fixed point values,
  1072. // but they are entered as floats
  1073. rsc->setFragmentProgramConstantFloatCount(8);
  1074. break;
  1075. case 2:
  1076. // 16 boolean params allowed
  1077. rsc->setFragmentProgramConstantBoolCount(16);
  1078. // 16 integer params allowed, 4D
  1079. rsc->setFragmentProgramConstantIntCount(16);
  1080. // float params, always 4D
  1081. rsc->setFragmentProgramConstantFloatCount(32);
  1082. break;
  1083. case 3:
  1084. // 16 boolean params allowed
  1085. rsc->setFragmentProgramConstantBoolCount(16);
  1086. // 16 integer params allowed, 4D
  1087. rsc->setFragmentProgramConstantIntCount(16);
  1088. // float params, always 4D
  1089. rsc->setFragmentProgramConstantFloatCount(224);
  1090. break;
  1091. }
  1092. // populate syntax codes in program manager (no breaks in this one so it falls through)
  1093. switch(major)
  1094. {
  1095. case 3:
  1096. if (minor > 0)
  1097. rsc->addShaderProfile("ps_3_x");
  1098. rsc->addShaderProfile("ps_3_0");
  1099. case 2:
  1100. if (ps2x)
  1101. rsc->addShaderProfile("ps_2_x");
  1102. if (ps2a)
  1103. rsc->addShaderProfile("ps_2_a");
  1104. if (ps2b)
  1105. rsc->addShaderProfile("ps_2_b");
  1106. rsc->addShaderProfile("ps_2_0");
  1107. case 1:
  1108. if (major > 1 || minor >= 4)
  1109. rsc->addShaderProfile("ps_1_4");
  1110. if (major > 1 || minor >= 3)
  1111. rsc->addShaderProfile("ps_1_3");
  1112. if (major > 1 || minor >= 2)
  1113. rsc->addShaderProfile("ps_1_2");
  1114. rsc->addShaderProfile("ps_1_1");
  1115. rsc->setCapability(RSC_FRAGMENT_PROGRAM);
  1116. }
  1117. }
  1118. //-----------------------------------------------------------------------
  1119. bool D3D9RenderSystem::checkVertexTextureFormats(D3D9RenderWindow* renderWindow) const
  1120. {
  1121. bool anySupported = false;
  1122. IDirect3DSurface9* bbSurf;
  1123. renderWindow->getCustomAttribute("DDBACKBUFFER", &bbSurf);
  1124. D3DSURFACE_DESC bbSurfDesc;
  1125. bbSurf->GetDesc(&bbSurfDesc);
  1126. for (uint ipf = static_cast<uint>(PF_L8); ipf < static_cast<uint>(PF_COUNT); ++ipf)
  1127. {
  1128. PixelFormat pf = (PixelFormat)ipf;
  1129. D3DFORMAT fmt =
  1130. D3D9Mappings::_getPF(D3D9Mappings::_getClosestSupportedPF(pf));
  1131. if (SUCCEEDED(mpD3D->CheckDeviceFormat(
  1132. mActiveD3DDriver->getAdapterNumber(), D3DDEVTYPE_HAL, bbSurfDesc.Format,
  1133. D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, fmt)))
  1134. {
  1135. // cool, at least one supported
  1136. anySupported = true;
  1137. }
  1138. }
  1139. return anySupported;
  1140. }
  1141. //-----------------------------------------------------------------------
  1142. void D3D9RenderSystem::initialiseFromRenderSystemCapabilities(RenderSystemCapabilities* caps, RenderTarget* primary)
  1143. {
  1144. if (caps->getRenderSystemName() != getName())
  1145. {
  1146. OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
  1147. "Trying to initialize D3D9RenderSystem from RenderSystemCapabilities that do not support Direct3D9",
  1148. "D3D9RenderSystem::initialiseFromRenderSystemCapabilities");
  1149. }
  1150. // TODO PORT - If i'll be supporting factories enable this
  1151. //if (caps->isShaderProfileSupported("hlsl"))
  1152. // HighLevelGpuProgramManager::getSingleton().addFactory(mHLSLProgramFactory);
  1153. }
  1154. //-----------------------------------------------------------------------
  1155. bool D3D9RenderSystem::_checkTextureFilteringSupported(TextureType ttype, PixelFormat format, int usage)
  1156. {
  1157. // Gets D3D format
  1158. D3DFORMAT d3dPF = D3D9Mappings::_getPF(format);
  1159. if (d3dPF == D3DFMT_UNKNOWN)
  1160. return false;
  1161. for (uint i = 0; i < mDeviceManager->getDeviceCount(); ++i)
  1162. {
  1163. D3D9Device* currDevice = mDeviceManager->getDevice(i);
  1164. D3D9RenderWindow* currDevicePrimaryWindow = currDevice->getPrimaryWindow();
  1165. IDirect3DSurface9* pSurface = currDevicePrimaryWindow->getRenderSurface();
  1166. D3DSURFACE_DESC srfDesc;
  1167. // Get surface desc
  1168. if (FAILED(pSurface->GetDesc(&srfDesc)))
  1169. return false;
  1170. // Calculate usage
  1171. DWORD d3dusage = D3DUSAGE_QUERY_FILTER;
  1172. if (usage & TU_RENDERTARGET)
  1173. d3dusage |= D3DUSAGE_RENDERTARGET;
  1174. if (usage & TU_DYNAMIC)
  1175. d3dusage |= D3DUSAGE_DYNAMIC;
  1176. // Detect resource type
  1177. D3DRESOURCETYPE rtype;
  1178. switch(ttype)
  1179. {
  1180. case TEX_TYPE_1D:
  1181. case TEX_TYPE_2D:
  1182. rtype = D3DRTYPE_TEXTURE;
  1183. break;
  1184. case TEX_TYPE_3D:
  1185. rtype = D3DRTYPE_VOLUMETEXTURE;
  1186. break;
  1187. case TEX_TYPE_CUBE_MAP:
  1188. rtype = D3DRTYPE_CUBETEXTURE;
  1189. break;
  1190. default:
  1191. return false;
  1192. }
  1193. HRESULT hr = mpD3D->CheckDeviceFormat(
  1194. currDevice->getAdapterNumber(),
  1195. currDevice->getDeviceType(),
  1196. srfDesc.Format,
  1197. d3dusage,
  1198. rtype,
  1199. d3dPF);
  1200. if (FAILED(hr))
  1201. return false;
  1202. }
  1203. return true;
  1204. }
  1205. //-----------------------------------------------------------------------
  1206. MultiRenderTarget * D3D9RenderSystem::createMultiRenderTarget(const String & name)
  1207. {
  1208. MultiRenderTarget *retval;
  1209. retval = new D3D9MultiRenderTarget(name);
  1210. attachRenderTarget(*retval);
  1211. return retval;
  1212. }
  1213. //---------------------------------------------------------------------
  1214. void D3D9RenderSystem::destroyRenderTarget(const String& name)
  1215. {
  1216. D3D9RenderWindow* renderWindow = NULL;
  1217. // Check render windows
  1218. D3D9RenderWindowList::iterator sw;
  1219. for (sw = mRenderWindows.begin(); sw != mRenderWindows.end(); ++sw)
  1220. {
  1221. if ((*sw)->getName() == name)
  1222. {
  1223. renderWindow = (*sw);
  1224. mRenderWindows.erase(sw);
  1225. break;
  1226. }
  1227. }
  1228. // Do the real removal
  1229. RenderSystem::destroyRenderTarget(name);
  1230. }
  1231. //---------------------------------------------------------------------
  1232. String D3D9RenderSystem::getErrorDescription( long errorNumber ) const
  1233. {
  1234. const String errMsg = DXGetErrorDescription( errorNumber );
  1235. return errMsg;
  1236. }
  1237. //---------------------------------------------------------------------
  1238. VertexElementType D3D9RenderSystem::getColourVertexElementType() const
  1239. {
  1240. return VET_COLOUR_ARGB;
  1241. }
  1242. //---------------------------------------------------------------------
  1243. void D3D9RenderSystem::_convertProjectionMatrix(const Matrix4& matrix,
  1244. Matrix4& dest, bool forGpuProgram)
  1245. {
  1246. dest = matrix;
  1247. // Convert depth range from [-1,+1] to [0,1]
  1248. dest[2][0] = (dest[2][0] + dest[3][0]) / 2;
  1249. dest[2][1] = (dest[2][1] + dest[3][1]) / 2;
  1250. dest[2][2] = (dest[2][2] + dest[3][2]) / 2;
  1251. dest[2][3] = (dest[2][3] + dest[3][3]) / 2;
  1252. if (!forGpuProgram)
  1253. {
  1254. // Convert right-handed to left-handed
  1255. dest[0][2] = -dest[0][2];
  1256. dest[1][2] = -dest[1][2];
  1257. dest[2][2] = -dest[2][2];
  1258. dest[3][2] = -dest[3][2];
  1259. }
  1260. }
  1261. //---------------------------------------------------------------------
  1262. void D3D9RenderSystem::_makeProjectionMatrix(const Radian& fovy, Real aspect, Real nearPlane,
  1263. Real farPlane, Matrix4& dest, bool forGpuProgram)
  1264. {
  1265. Radian theta ( fovy * 0.5 );
  1266. Real h = 1 / Math::Tan(theta);
  1267. Real w = h / aspect;
  1268. Real q, qn;
  1269. if (farPlane == 0)
  1270. {
  1271. q = 1 - Frustum::INFINITE_FAR_PLANE_ADJUST;
  1272. qn = nearPlane * (Frustum::INFINITE_FAR_PLANE_ADJUST - 1);
  1273. }
  1274. else
  1275. {
  1276. q = farPlane / ( farPlane - nearPlane );
  1277. qn = -q * nearPlane;
  1278. }
  1279. dest = Matrix4::ZERO;
  1280. dest[0][0] = w;
  1281. dest[1][1] = h;
  1282. if (forGpuProgram)
  1283. {
  1284. dest[2][2] = -q;
  1285. dest[3][2] = -1.0f;
  1286. }
  1287. else
  1288. {
  1289. dest[2][2] = q;
  1290. dest[3][2] = 1.0f;
  1291. }
  1292. dest[2][3] = qn;
  1293. }
  1294. //---------------------------------------------------------------------
  1295. void D3D9RenderSystem::_makeOrthoMatrix(const Radian& fovy, Real aspect, Real nearPlane, Real farPlane,
  1296. Matrix4& dest, bool forGpuProgram )
  1297. {
  1298. Radian thetaY (fovy / 2.0f);
  1299. Real tanThetaY = Math::Tan(thetaY);
  1300. //Real thetaX = thetaY * aspect;
  1301. Real tanThetaX = tanThetaY * aspect; //Math::Tan(thetaX);
  1302. Real half_w = tanThetaX * nearPlane;
  1303. Real half_h = tanThetaY * nearPlane;
  1304. Real iw = static_cast<Real>(1.0 / half_w);
  1305. Real ih = static_cast<Real>(1.0 / half_h);
  1306. Real q;
  1307. if (farPlane == 0)
  1308. {
  1309. q = 0;
  1310. }
  1311. else
  1312. {
  1313. q = static_cast<Real>(1.0 / (farPlane - nearPlane));
  1314. }
  1315. dest = Matrix4::ZERO;
  1316. dest[0][0] = iw;
  1317. dest[1][1] = ih;
  1318. dest[2][2] = q;
  1319. dest[2][3] = -nearPlane / (farPlane - nearPlane);
  1320. dest[3][3] = 1;
  1321. if (forGpuProgram)
  1322. {
  1323. dest[2][2] = -dest[2][2];
  1324. }
  1325. }
  1326. //---------------------------------------------------------------------
  1327. void D3D9RenderSystem::setAmbientLight( float r, float g, float b )
  1328. {
  1329. HRESULT hr = __SetRenderState( D3DRS_AMBIENT, D3DCOLOR_COLORVALUE( r, g, b, 1.0f ) );
  1330. if( FAILED( hr ) )
  1331. OGRE_EXCEPT( Exception::ERR_RENDERINGAPI_ERROR,
  1332. "Failed to set render stat D3DRS_AMBIENT", "D3D9RenderSystem::setAmbientLight" );
  1333. }
  1334. //---------------------------------------------------------------------
  1335. void D3D9RenderSystem::_useLights(const LightList& lights, unsigned short limit)
  1336. {
  1337. IDirect3DDevice9* activeDevice = getActiveD3D9Device();
  1338. LightList::const_iterator i, iend;
  1339. iend = lights.end();
  1340. unsigned short num = 0;
  1341. for (i = lights.begin(); i != iend && num < limit; ++i, ++num)
  1342. {
  1343. setD3D9Light(num, *i);
  1344. }
  1345. // Disable extra lights
  1346. for (; num < mCurrentLights[activeDevice]; ++num)
  1347. {
  1348. setD3D9Light(num, NULL);
  1349. }
  1350. mCurrentLights[activeDevice] = std::min(limit, static_cast<unsigned short>(lights.size()));
  1351. }
  1352. //---------------------------------------------------------------------
  1353. void D3D9RenderSystem::setShadingType( ShadeOptions so )
  1354. {
  1355. HRESULT hr = __SetRenderState( D3DRS_SHADEMODE, D3D9Mappings::get(so) );
  1356. if( FAILED( hr ) )
  1357. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  1358. "Failed to set render stat D3DRS_SHADEMODE", "D3D9RenderSystem::setShadingType" );
  1359. }
  1360. //---------------------------------------------------------------------
  1361. void D3D9RenderSystem::setLightingEnabled( bool enabled )
  1362. {
  1363. HRESULT hr;
  1364. if( FAILED( hr = __SetRenderState( D3DRS_LIGHTING, enabled ) ) )
  1365. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  1366. "Failed to set render state D3DRS_LIGHTING", "D3D9RenderSystem::setLightingEnabled" );
  1367. }
  1368. //---------------------------------------------------------------------
  1369. void D3D9RenderSystem::setD3D9Light( size_t index, Light* lt )
  1370. {
  1371. // TODO PORT - D3D9 lights not supported
  1372. assert(false);
  1373. }
  1374. //---------------------------------------------------------------------
  1375. void D3D9RenderSystem::_setViewMatrix( const Matrix4 &m )
  1376. {
  1377. // save latest view matrix
  1378. mViewMatrix = m;
  1379. mViewMatrix[2][0] = -mViewMatrix[2][0];
  1380. mViewMatrix[2][1] = -mViewMatrix[2][1];
  1381. mViewMatrix[2][2] = -mViewMatrix[2][2];
  1382. mViewMatrix[2][3] = -mViewMatrix[2][3];
  1383. mDxViewMat = D3D9Mappings::makeD3DXMatrix( mViewMatrix );
  1384. HRESULT hr;
  1385. if( FAILED( hr = getActiveD3D9Device()->SetTransform( D3DTS_VIEW, &mDxViewMat ) ) )
  1386. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Cannot set D3D9 view matrix", "D3D9RenderSystem::_setViewMatrix" );
  1387. // also mark clip planes dirty
  1388. if (!mClipPlanes.empty())
  1389. mClipPlanesDirty = true;
  1390. }
  1391. //---------------------------------------------------------------------
  1392. void D3D9RenderSystem::_setProjectionMatrix( const Matrix4 &m )
  1393. {
  1394. // save latest matrix
  1395. mDxProjMat = D3D9Mappings::makeD3DXMatrix( m );
  1396. if( mActiveRenderTarget->requiresTextureFlipping() )
  1397. {
  1398. // Invert transformed y
  1399. mDxProjMat._12 = - mDxProjMat._12;
  1400. mDxProjMat._22 = - mDxProjMat._22;
  1401. mDxProjMat._32 = - mDxProjMat._32;
  1402. mDxProjMat._42 = - mDxProjMat._42;
  1403. }
  1404. HRESULT hr;
  1405. if( FAILED( hr = getActiveD3D9Device()->SetTransform( D3DTS_PROJECTION, &mDxProjMat ) ) )
  1406. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Cannot set D3D9 projection matrix", "D3D9RenderSystem::_setProjectionMatrix" );
  1407. // also mark clip planes dirty
  1408. if (!mClipPlanes.empty())
  1409. mClipPlanesDirty = true;
  1410. }
  1411. //---------------------------------------------------------------------
  1412. void D3D9RenderSystem::_setWorldMatrix( const Matrix4 &m )
  1413. {
  1414. // save latest matrix
  1415. mDxWorldMat = D3D9Mappings::makeD3DXMatrix( m );
  1416. HRESULT hr;
  1417. if( FAILED( hr = getActiveD3D9Device()->SetTransform( D3DTS_WORLD, &mDxWorldMat ) ) )
  1418. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Cannot set D3D9 world matrix", "D3D9RenderSystem::_setWorldMatrix" );
  1419. }
  1420. //---------------------------------------------------------------------
  1421. void D3D9RenderSystem::_setSurfaceParams( const ColourValue &ambient, const ColourValue &diffuse,
  1422. const ColourValue &specular, const ColourValue &emissive, Real shininess,
  1423. TrackVertexColourType tracking )
  1424. {
  1425. D3DMATERIAL9 material;
  1426. material.Diffuse = D3DXCOLOR( diffuse.r, diffuse.g, diffuse.b, diffuse.a );
  1427. material.Ambient = D3DXCOLOR( ambient.r, ambient.g, ambient.b, ambient.a );
  1428. material.Specular = D3DXCOLOR( specular.r, specular.g, specular.b, specular.a );
  1429. material.Emissive = D3DXCOLOR( emissive.r, emissive.g, emissive.b, emissive.a );
  1430. material.Power = shininess;
  1431. HRESULT hr = getActiveD3D9Device()->SetMaterial( &material );
  1432. if( FAILED( hr ) )
  1433. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error setting D3D material", "D3D9RenderSystem::_setSurfaceParams" );
  1434. if(tracking != TVC_NONE)
  1435. {
  1436. __SetRenderState(D3DRS_COLORVERTEX, TRUE);
  1437. __SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, (tracking&TVC_AMBIENT)?D3DMCS_COLOR1:D3DMCS_MATERIAL);
  1438. __SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, (tracking&TVC_DIFFUSE)?D3DMCS_COLOR1:D3DMCS_MATERIAL);
  1439. __SetRenderState(D3DRS_SPECULARMATERIALSOURCE, (tracking&TVC_SPECULAR)?D3DMCS_COLOR1:D3DMCS_MATERIAL);
  1440. __SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, (tracking&TVC_EMISSIVE)?D3DMCS_COLOR1:D3DMCS_MATERIAL);
  1441. }
  1442. else
  1443. {
  1444. __SetRenderState(D3DRS_COLORVERTEX, FALSE);
  1445. }
  1446. }
  1447. //---------------------------------------------------------------------
  1448. void D3D9RenderSystem::_setPointParameters(Real size,
  1449. bool attenuationEnabled, Real constant, Real linear, Real quadratic,
  1450. Real minSize, Real maxSize)
  1451. {
  1452. if(attenuationEnabled)
  1453. {
  1454. // scaling required
  1455. __SetRenderState(D3DRS_POINTSCALEENABLE, TRUE);
  1456. __SetFloatRenderState(D3DRS_POINTSCALE_A, constant);
  1457. __SetFloatRenderState(D3DRS_POINTSCALE_B, linear);
  1458. __SetFloatRenderState(D3DRS_POINTSCALE_C, quadratic);
  1459. }
  1460. else
  1461. {
  1462. // no scaling required
  1463. __SetRenderState(D3DRS_POINTSCALEENABLE, FALSE);
  1464. }
  1465. __SetFloatRenderState(D3DRS_POINTSIZE, size);
  1466. __SetFloatRenderState(D3DRS_POINTSIZE_MIN, minSize);
  1467. if (maxSize == 0.0f)
  1468. maxSize = mCurrentCapabilities->getMaxPointSize();
  1469. __SetFloatRenderState(D3DRS_POINTSIZE_MAX, maxSize);
  1470. }
  1471. //---------------------------------------------------------------------
  1472. void D3D9RenderSystem::_setPointSpritesEnabled(bool enabled)
  1473. {
  1474. if (enabled)
  1475. {
  1476. __SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
  1477. }
  1478. else
  1479. {
  1480. __SetRenderState(D3DRS_POINTSPRITEENABLE, FALSE);
  1481. }
  1482. }
  1483. //---------------------------------------------------------------------
  1484. void D3D9RenderSystem::_setTexture( size_t stage, bool enabled, const TexturePtr& tex )
  1485. {
  1486. HRESULT hr;
  1487. D3D9TexturePtr dt = tex;
  1488. if (enabled && !dt.isNull())
  1489. {
  1490. IDirect3DBaseTexture9 *pTex = dt->getTexture();
  1491. if (mTexStageDesc[stage].pTex != pTex)
  1492. {
  1493. hr = getActiveD3D9Device()->SetTexture(static_cast<DWORD>(stage), pTex);
  1494. if( hr != S_OK )
  1495. {
  1496. String str = "Unable to set texture in D3D9";
  1497. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, str, "D3D9RenderSystem::_setTexture" );
  1498. }
  1499. // set stage desc.
  1500. mTexStageDesc[stage].pTex = pTex;
  1501. mTexStageDesc[stage].texType = D3D9Mappings::get(dt->getTextureType());
  1502. // Set gamma now too
  1503. if (dt->isHardwareGammaReadToBeUsed())
  1504. {
  1505. __SetSamplerState(static_cast<DWORD>(stage), D3DSAMP_SRGBTEXTURE, TRUE);
  1506. }
  1507. else
  1508. {
  1509. __SetSamplerState(static_cast<DWORD>(stage), D3DSAMP_SRGBTEXTURE, FALSE);
  1510. }
  1511. }
  1512. }
  1513. else
  1514. {
  1515. if (mTexStageDesc[stage].pTex != 0)
  1516. {
  1517. hr = getActiveD3D9Device()->SetTexture(static_cast<DWORD>(stage), 0);
  1518. if( hr != S_OK )
  1519. {
  1520. String str = "Unable to disable texture '" + StringConverter::toString(stage) + "' in D3D9";
  1521. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, str, "D3D9RenderSystem::_setTexture" );
  1522. }
  1523. }
  1524. hr = __SetTextureStageState(static_cast<DWORD>(stage), D3DTSS_COLOROP, D3DTOP_DISABLE);
  1525. if( hr != S_OK )
  1526. {
  1527. String str = "Unable to disable texture '" + StringConverter::toString(stage) + "' in D3D9";
  1528. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, str, "D3D9RenderSystem::_setTexture" );
  1529. }
  1530. // set stage desc. to defaults
  1531. mTexStageDesc[stage].pTex = 0;
  1532. mTexStageDesc[stage].autoTexCoordType = TEXCALC_NONE;
  1533. mTexStageDesc[stage].coordIndex = 0;
  1534. mTexStageDesc[stage].texType = D3D9Mappings::D3D_TEX_TYPE_NORMAL;
  1535. }
  1536. }
  1537. //---------------------------------------------------------------------
  1538. void D3D9RenderSystem::_setVertexTexture(size_t stage, const TexturePtr& tex)
  1539. {
  1540. if (tex.isNull())
  1541. {
  1542. if (mTexStageDesc[stage].pVertexTex != 0)
  1543. {
  1544. HRESULT hr = getActiveD3D9Device()->SetTexture(D3DVERTEXTEXTURESAMPLER0 + static_cast<DWORD>(stage), 0);
  1545. if( hr != S_OK )
  1546. {
  1547. String str = "Unable to disable vertex texture '"
  1548. + StringConverter::toString(stage) + "' in D3D9";
  1549. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, str, "D3D9RenderSystem::_setVertexTexture" );
  1550. }
  1551. }
  1552. // set stage desc. to defaults
  1553. mTexStageDesc[stage].pVertexTex = 0;
  1554. }
  1555. else
  1556. {
  1557. D3D9TexturePtr dt = tex;
  1558. IDirect3DBaseTexture9 *pTex = dt->getTexture();
  1559. if (mTexStageDesc[stage].pVertexTex != pTex)
  1560. {
  1561. HRESULT hr = getActiveD3D9Device()->SetTexture(D3DVERTEXTEXTURESAMPLER0 + static_cast<DWORD>(stage), pTex);
  1562. if( hr != S_OK )
  1563. {
  1564. String str = "Unable to set vertex texture in D3D9";
  1565. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, str, "D3D9RenderSystem::_setVertexTexture" );
  1566. }
  1567. // set stage desc.
  1568. mTexStageDesc[stage].pVertexTex = pTex;
  1569. }
  1570. }
  1571. }
  1572. //---------------------------------------------------------------------
  1573. void D3D9RenderSystem::_disableTextureUnit(size_t texUnit)
  1574. {
  1575. RenderSystem::_disableTextureUnit(texUnit);
  1576. // also disable vertex texture unit
  1577. static TexturePtr nullPtr;
  1578. _setVertexTexture(texUnit, nullPtr);
  1579. }
  1580. //---------------------------------------------------------------------
  1581. void D3D9RenderSystem::_setTextureCoordSet( size_t stage, size_t index )
  1582. {
  1583. // if vertex shader is being used, stage and index must match
  1584. if (mVertexProgramBound)
  1585. index = stage;
  1586. HRESULT hr;
  1587. // Record settings
  1588. mTexStageDesc[stage].coordIndex = index;
  1589. hr = __SetTextureStageState( static_cast<DWORD>(stage), D3DTSS_TEXCOORDINDEX, D3D9Mappings::get(mTexStageDesc[stage].autoTexCoordType, mDeviceManager->getActiveDevice()->getD3D9DeviceCaps()) | index );
  1590. if( FAILED( hr ) )
  1591. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Unable to set texture coord. set index", "D3D9RenderSystem::_setTextureCoordSet" );
  1592. }
  1593. //---------------------------------------------------------------------
  1594. void D3D9RenderSystem::_setTextureCoordCalculation( size_t stage, TexCoordCalcMethod m,
  1595. const Frustum* frustum)
  1596. {
  1597. HRESULT hr;
  1598. // record the stage state
  1599. mTexStageDesc[stage].autoTexCoordType = m;
  1600. mTexStageDesc[stage].frustum = frustum;
  1601. hr = __SetTextureStageState( static_cast<DWORD>(stage), D3DTSS_TEXCOORDINDEX, D3D9Mappings::get(m, mDeviceManager->getActiveDevice()->getD3D9DeviceCaps()) | mTexStageDesc[stage].coordIndex );
  1602. if(FAILED(hr))
  1603. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Unable to set texture auto tex.coord. generation mode", "D3D9RenderSystem::_setTextureCoordCalculation" );
  1604. }
  1605. //---------------------------------------------------------------------
  1606. void D3D9RenderSystem::_setTextureMipmapBias(size_t unit, float bias)
  1607. {
  1608. if (mCurrentCapabilities->hasCapability(RSC_MIPMAP_LOD_BIAS))
  1609. {
  1610. // ugh - have to pass float data through DWORD with no conversion
  1611. HRESULT hr = __SetSamplerState(static_cast<DWORD>(unit), D3DSAMP_MIPMAPLODBIAS,
  1612. *(DWORD*)&bias);
  1613. if(FAILED(hr))
  1614. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Unable to set texture mipmap bias",
  1615. "D3D9RenderSystem::_setTextureMipmapBias" );
  1616. }
  1617. }
  1618. //---------------------------------------------------------------------
  1619. void D3D9RenderSystem::_setTextureMatrix( size_t stage, const Matrix4& xForm )
  1620. {
  1621. HRESULT hr;
  1622. D3DXMATRIX d3dMat; // the matrix we'll maybe apply
  1623. Matrix4 newMat = xForm; // the matrix we'll apply after conv. to D3D format
  1624. // Cache texcoord calc method to register
  1625. TexCoordCalcMethod autoTexCoordType = mTexStageDesc[stage].autoTexCoordType;
  1626. // if a vertex program is bound, we mustn't set texture transforms
  1627. if (mVertexProgramBound)
  1628. {
  1629. hr = __SetTextureStageState( static_cast<DWORD>(stage), D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
  1630. if( FAILED( hr ) )
  1631. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Unable to disable texture coordinate transform", "D3D9RenderSystem::_setTextureMatrix" );
  1632. return;
  1633. }
  1634. if (autoTexCoordType == TEXCALC_ENVIRONMENT_MAP)
  1635. {
  1636. if (mDeviceManager->getActiveDevice()->getD3D9DeviceCaps().VertexProcessingCaps & D3DVTXPCAPS_TEXGEN_SPHEREMAP)
  1637. {
  1638. /** Invert the texture for the spheremap */
  1639. Matrix4 ogreMatEnvMap = Matrix4::IDENTITY;
  1640. // set env_map values
  1641. ogreMatEnvMap[1][1] = -1.0f;
  1642. // concatenate with the xForm
  1643. newMat = newMat.concatenate(ogreMatEnvMap);
  1644. }
  1645. else
  1646. {
  1647. /* If envmap is applied, but device doesn't support spheremap,
  1648. then we have to use texture transform to make the camera space normal
  1649. reference the envmap properly. This isn't exactly the same as spheremap
  1650. (it looks nasty on flat areas because the camera space normals are the same)
  1651. but it's the best approximation we have in the absence of a proper spheremap */
  1652. // concatenate with the xForm
  1653. newMat = newMat.concatenate(Matrix4::CLIPSPACE2DTOIMAGESPACE);
  1654. }
  1655. }
  1656. // If this is a cubic reflection, we need to modify using the view matrix
  1657. if (autoTexCoordType == TEXCALC_ENVIRONMENT_MAP_REFLECTION)
  1658. {
  1659. // Get transposed 3x3
  1660. // We want to transpose since that will invert an orthonormal matrix ie rotation
  1661. Matrix4 ogreViewTransposed;
  1662. ogreViewTransposed[0][0] = mViewMatrix[0][0];
  1663. ogreViewTransposed[0][1] = mViewMatrix[1][0];
  1664. ogreViewTransposed[0][2] = mViewMatrix[2][0];
  1665. ogreViewTransposed[0][3] = 0.0f;
  1666. ogreViewTransposed[1][0] = mViewMatrix[0][1];
  1667. ogreViewTransposed[1][1] = mViewMatrix[1][1];
  1668. ogreViewTransposed[1][2] = mViewMatrix[2][1];
  1669. ogreViewTransposed[1][3] = 0.0f;
  1670. ogreViewTransposed[2][0] = mViewMatrix[0][2];
  1671. ogreViewTransposed[2][1] = mViewMatrix[1][2];
  1672. ogreViewTransposed[2][2] = mViewMatrix[2][2];
  1673. ogreViewTransposed[2][3] = 0.0f;
  1674. ogreViewTransposed[3][0] = 0.0f;
  1675. ogreViewTransposed[3][1] = 0.0f;
  1676. ogreViewTransposed[3][2] = 0.0f;
  1677. ogreViewTransposed[3][3] = 1.0f;
  1678. newMat = newMat.concatenate(ogreViewTransposed);
  1679. }
  1680. if (autoTexCoordType == TEXCALC_PROJECTIVE_TEXTURE)
  1681. {
  1682. // Derive camera space to projector space transform
  1683. // To do this, we need to undo the camera view matrix, then
  1684. // apply the projector view & projection matrices
  1685. newMat = mViewMatrix.inverse();
  1686. if(mTexProjRelative)
  1687. {
  1688. Matrix4 viewMatrix;
  1689. mTexStageDesc[stage].frustum->calcViewMatrixRelative(mTexProjRelativeOrigin, viewMatrix);
  1690. newMat = viewMatrix * newMat;
  1691. }
  1692. else
  1693. {
  1694. newMat = mTexStageDesc[stage].frustum->getViewMatrix() * newMat;
  1695. }
  1696. newMat = mTexStageDesc[stage].frustum->getProjectionMatrix() * newMat;
  1697. newMat = Matrix4::CLIPSPACE2DTOIMAGESPACE * newMat;
  1698. newMat = xForm * newMat;
  1699. }
  1700. // need this if texture is a cube map, to invert D3D's z coord
  1701. if (autoTexCoordType != TEXCALC_NONE &&
  1702. autoTexCoordType != TEXCALC_PROJECTIVE_TEXTURE)
  1703. {
  1704. newMat[2][0] = -newMat[2][0];
  1705. newMat[2][1] = -newMat[2][1];
  1706. newMat[2][2] = -newMat[2][2];
  1707. newMat[2][3] = -newMat[2][3];
  1708. }
  1709. // convert our matrix to D3D format
  1710. d3dMat = D3D9Mappings::makeD3DXMatrix(newMat);
  1711. // set the matrix if it's not the identity
  1712. if (!D3DXMatrixIsIdentity(&d3dMat))
  1713. {
  1714. /* It's seems D3D automatically add a texture coordinate with value 1,
  1715. and fill up the remaining texture coordinates with 0 for the input
  1716. texture coordinates before pass to texture coordinate transformation.
  1717. NOTE: It's difference with D3DDECLTYPE enumerated type expand in
  1718. DirectX SDK documentation!
  1719. So we should prepare the texcoord transform, make the transformation
  1720. just like standardized vector expand, thus, fill w with value 1 and
  1721. others with 0.
  1722. */
  1723. if (autoTexCoordType == TEXCALC_NONE)
  1724. {
  1725. /* FIXME: The actually input texture coordinate dimensions should
  1726. be determine by texture coordinate vertex element. Now, just trust
  1727. user supplied texture type matchs texture coordinate vertex element.
  1728. */
  1729. if (mTexStageDesc[stage].texType == D3D9Mappings::D3D_TEX_TYPE_NORMAL)
  1730. {
  1731. /* It's 2D input texture coordinate:
  1732. texcoord in vertex buffer D3D expanded to We are adjusted to
  1733. --> -->
  1734. (u, v) (u, v, 1, 0) (u, v, 0, 1)
  1735. */
  1736. std::swap(d3dMat._31, d3dMat._41);
  1737. std::swap(d3dMat._32, d3dMat._42);
  1738. std::swap(d3dMat._33, d3dMat._43);
  1739. std::swap(d3dMat._34, d3dMat._44);
  1740. }
  1741. }
  1742. else
  1743. {
  1744. // All texgen generate 3D input texture coordinates.
  1745. }
  1746. // tell D3D the dimension of tex. coord.
  1747. int texCoordDim = D3DTTFF_COUNT2;
  1748. if (mTexStageDesc[stage].autoTexCoordType == TEXCALC_PROJECTIVE_TEXTURE)
  1749. {
  1750. /* We want texcoords (u, v, w, q) always get divided by q, but D3D
  1751. projected texcoords is divided by the last element (in the case of
  1752. 2D texcoord, is w). So we tweak the transform matrix, transform the
  1753. texcoords with w and q swapped: (u, v, q, w), and then D3D will
  1754. divide u, v by q. The w and q just ignored as it wasn't used by
  1755. rasterizer.
  1756. */
  1757. switch (mTexStageDesc[stage].texType)
  1758. {
  1759. case D3D9Mappings::D3D_TEX_TYPE_NORMAL:
  1760. std::swap(d3dMat._13, d3dMat._14);
  1761. std::swap(d3dMat._23, d3dMat._24);
  1762. std::swap(d3dMat._33, d3dMat._34);
  1763. std::swap(d3dMat._43, d3dMat._44);
  1764. texCoordDim = D3DTTFF_PROJECTED | D3DTTFF_COUNT3;
  1765. break;
  1766. case D3D9Mappings::D3D_TEX_TYPE_CUBE:
  1767. case D3D9Mappings::D3D_TEX_TYPE_VOLUME:
  1768. // Yes, we support 3D projective texture.
  1769. texCoordDim = D3DTTFF_PROJECTED | D3DTTFF_COUNT4;
  1770. break;
  1771. }
  1772. }
  1773. else
  1774. {
  1775. switch (mTexStageDesc[stage].texType)
  1776. {
  1777. case D3D9Mappings::D3D_TEX_TYPE_NORMAL:
  1778. texCoordDim = D3DTTFF_COUNT2;
  1779. break;
  1780. case D3D9Mappings::D3D_TEX_TYPE_CUBE:
  1781. case D3D9Mappings::D3D_TEX_TYPE_VOLUME:
  1782. texCoordDim = D3DTTFF_COUNT3;
  1783. break;
  1784. }
  1785. }
  1786. hr = __SetTextureStageState( static_cast<DWORD>(stage), D3DTSS_TEXTURETRANSFORMFLAGS, texCoordDim );
  1787. if (FAILED(hr))
  1788. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Unable to set texture coord. dimension", "D3D9RenderSystem::_setTextureMatrix" );
  1789. hr = getActiveD3D9Device()->SetTransform( (D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0 + stage), &d3dMat );
  1790. if (FAILED(hr))
  1791. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Unable to set texture matrix", "D3D9RenderSystem::_setTextureMatrix" );
  1792. }
  1793. else
  1794. {
  1795. // disable all of this
  1796. hr = __SetTextureStageState( static_cast<DWORD>(stage), D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
  1797. if( FAILED( hr ) )
  1798. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Unable to disable texture coordinate transform", "D3D9RenderSystem::_setTextureMatrix" );
  1799. // Needless to sets texture transform here, it's never used at all
  1800. }
  1801. }
  1802. //---------------------------------------------------------------------
  1803. void D3D9RenderSystem::_setTextureAddressingMode( size_t stage,
  1804. const TextureUnitState::UVWAddressingMode& uvw )
  1805. {
  1806. HRESULT hr;
  1807. if( FAILED( hr = __SetSamplerState( static_cast<DWORD>(stage), D3DSAMP_ADDRESSU, D3D9Mappings::get(uvw.u, mDeviceManager->getActiveDevice()->getD3D9DeviceCaps()) ) ) )
  1808. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set texture addressing mode for U", "D3D9RenderSystem::_setTextureAddressingMode" );
  1809. if( FAILED( hr = __SetSamplerState( static_cast<DWORD>(stage), D3DSAMP_ADDRESSV, D3D9Mappings::get(uvw.v, mDeviceManager->getActiveDevice()->getD3D9DeviceCaps()) ) ) )
  1810. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set texture addressing mode for V", "D3D9RenderSystem::_setTextureAddressingMode" );
  1811. if( FAILED( hr = __SetSamplerState( static_cast<DWORD>(stage), D3DSAMP_ADDRESSW, D3D9Mappings::get(uvw.w, mDeviceManager->getActiveDevice()->getD3D9DeviceCaps()) ) ) )
  1812. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set texture addressing mode for W", "D3D9RenderSystem::_setTextureAddressingMode" );
  1813. }
  1814. //-----------------------------------------------------------------------------
  1815. void D3D9RenderSystem::_setTextureBorderColour(size_t stage,
  1816. const ColourValue& colour)
  1817. {
  1818. HRESULT hr;
  1819. if( FAILED( hr = __SetSamplerState( static_cast<DWORD>(stage), D3DSAMP_BORDERCOLOR, colour.getAsARGB()) ) )
  1820. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set texture border colour", "D3D9RenderSystem::_setTextureBorderColour" );
  1821. }
  1822. //---------------------------------------------------------------------
  1823. void D3D9RenderSystem::_setTextureBlendMode( size_t stage, const LayerBlendModeEx& bm )
  1824. {
  1825. HRESULT hr = S_OK;
  1826. D3DTEXTURESTAGESTATETYPE tss;
  1827. D3DCOLOR manualD3D;
  1828. // choose type of blend.
  1829. if( bm.blendType == LBT_COLOUR )
  1830. tss = D3DTSS_COLOROP;
  1831. else if( bm.blendType == LBT_ALPHA )
  1832. tss = D3DTSS_ALPHAOP;
  1833. else
  1834. OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
  1835. "Invalid blend type", "D3D9RenderSystem::_setTextureBlendMode");
  1836. // set manual factor if required by operation
  1837. if (bm.operation == LBX_BLEND_MANUAL)
  1838. {
  1839. hr = __SetRenderState( D3DRS_TEXTUREFACTOR, D3DXCOLOR(0.0, 0.0, 0.0, bm.factor) );
  1840. if (FAILED(hr))
  1841. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set manual factor", "D3D9RenderSystem::_setTextureBlendMode" );
  1842. }
  1843. // set operation
  1844. hr = __SetTextureStageState( static_cast<DWORD>(stage), tss, D3D9Mappings::get(bm.operation, mDeviceManager->getActiveDevice()->getD3D9DeviceCaps()) );
  1845. if (FAILED(hr))
  1846. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set operation", "D3D9RenderSystem::_setTextureBlendMode" );
  1847. // choose source 1
  1848. if( bm.blendType == LBT_COLOUR )
  1849. {
  1850. tss = D3DTSS_COLORARG1;
  1851. manualD3D = D3DXCOLOR( bm.colourArg1.r, bm.colourArg1.g, bm.colourArg1.b, bm.colourArg1.a );
  1852. mManualBlendColours[stage][0] = bm.colourArg1;
  1853. }
  1854. else if( bm.blendType == LBT_ALPHA )
  1855. {
  1856. tss = D3DTSS_ALPHAARG1;
  1857. manualD3D = D3DXCOLOR( mManualBlendColours[stage][0].r,
  1858. mManualBlendColours[stage][0].g,
  1859. mManualBlendColours[stage][0].b, bm.alphaArg1 );
  1860. }
  1861. else
  1862. {
  1863. OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
  1864. "Invalid blend type", "D3D9RenderSystem::_setTextureBlendMode");
  1865. }
  1866. // Set manual factor if required
  1867. if (bm.source1 == LBS_MANUAL)
  1868. {
  1869. if (mCurrentCapabilities->hasCapability(RSC_PERSTAGECONSTANT))
  1870. {
  1871. // Per-stage state
  1872. hr = __SetTextureStageState(static_cast<DWORD>(stage), D3DTSS_CONSTANT, manualD3D);
  1873. }
  1874. else
  1875. {
  1876. // Global state
  1877. hr = __SetRenderState( D3DRS_TEXTUREFACTOR, manualD3D );
  1878. }
  1879. if (FAILED(hr))
  1880. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set manual factor", "D3D9RenderSystem::_setTextureBlendMode" );
  1881. }
  1882. // set source 1
  1883. hr = __SetTextureStageState( static_cast<DWORD>(stage), tss, D3D9Mappings::get(bm.source1, mCurrentCapabilities->hasCapability(RSC_PERSTAGECONSTANT)) );
  1884. if (FAILED(hr))
  1885. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set source1", "D3D9RenderSystem::_setTextureBlendMode" );
  1886. // choose source 2
  1887. if( bm.blendType == LBT_COLOUR )
  1888. {
  1889. tss = D3DTSS_COLORARG2;
  1890. manualD3D = D3DXCOLOR( bm.colourArg2.r, bm.colourArg2.g, bm.colourArg2.b, bm.colourArg2.a );
  1891. mManualBlendColours[stage][1] = bm.colourArg2;
  1892. }
  1893. else if( bm.blendType == LBT_ALPHA )
  1894. {
  1895. tss = D3DTSS_ALPHAARG2;
  1896. manualD3D = D3DXCOLOR( mManualBlendColours[stage][1].r,
  1897. mManualBlendColours[stage][1].g,
  1898. mManualBlendColours[stage][1].b,
  1899. bm.alphaArg2 );
  1900. }
  1901. // Set manual factor if required
  1902. if (bm.source2 == LBS_MANUAL)
  1903. {
  1904. if (mCurrentCapabilities->hasCapability(RSC_PERSTAGECONSTANT))
  1905. {
  1906. // Per-stage state
  1907. hr = __SetTextureStageState(static_cast<DWORD>(stage), D3DTSS_CONSTANT, manualD3D);
  1908. }
  1909. else
  1910. {
  1911. hr = __SetRenderState( D3DRS_TEXTUREFACTOR, manualD3D );
  1912. }
  1913. if (FAILED(hr))
  1914. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set manual factor", "D3D9RenderSystem::_setTextureBlendMode" );
  1915. }
  1916. // Now set source 2
  1917. hr = __SetTextureStageState( static_cast<DWORD>(stage), tss, D3D9Mappings::get(bm.source2, mCurrentCapabilities->hasCapability(RSC_PERSTAGECONSTANT)) );
  1918. if (FAILED(hr))
  1919. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set source 2", "D3D9RenderSystem::_setTextureBlendMode" );
  1920. // Set interpolation factor if lerping
  1921. if (bm.operation == LBX_BLEND_DIFFUSE_COLOUR &&
  1922. mDeviceManager->getActiveDevice()->getD3D9DeviceCaps().TextureOpCaps & D3DTEXOPCAPS_LERP)
  1923. {
  1924. // choose source 0 (lerp factor)
  1925. if( bm.blendType == LBT_COLOUR )
  1926. {
  1927. tss = D3DTSS_COLORARG0;
  1928. }
  1929. else if( bm.blendType == LBT_ALPHA )
  1930. {
  1931. tss = D3DTSS_ALPHAARG0;
  1932. }
  1933. hr = __SetTextureStageState(static_cast<DWORD>(stage), tss, D3DTA_DIFFUSE);
  1934. if (FAILED(hr))
  1935. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set lerp source 0",
  1936. "D3D9RenderSystem::_setTextureBlendMode" );
  1937. }
  1938. }
  1939. //---------------------------------------------------------------------
  1940. void D3D9RenderSystem::_setSceneBlending( SceneBlendFactor sourceFactor, SceneBlendFactor destFactor, SceneBlendOperation op )
  1941. {
  1942. HRESULT hr;
  1943. if( sourceFactor == SBF_ONE && destFactor == SBF_ZERO)
  1944. {
  1945. if (FAILED(hr = __SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE)))
  1946. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set alpha blending option", "D3D9RenderSystem::_setSceneBlending" );
  1947. }
  1948. else
  1949. {
  1950. if (FAILED(hr = __SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE)))
  1951. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set alpha blending option", "D3D9RenderSystem::_setSceneBlending" );
  1952. if (FAILED(hr = __SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE)))
  1953. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set separate alpha blending option", "D3D9RenderSystem::_setSceneBlending" );
  1954. if( FAILED( hr = __SetRenderState( D3DRS_SRCBLEND, D3D9Mappings::get(sourceFactor) ) ) )
  1955. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set source blend", "D3D9RenderSystem::_setSceneBlending" );
  1956. if( FAILED( hr = __SetRenderState( D3DRS_DESTBLEND, D3D9Mappings::get(destFactor) ) ) )
  1957. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set destination blend", "D3D9RenderSystem::_setSceneBlending" );
  1958. }
  1959. if (FAILED(hr = __SetRenderState(D3DRS_BLENDOP, D3D9Mappings::get(op))))
  1960. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set scene blending operation option", "D3D9RenderSystem::_setSceneBlendingOperation" );
  1961. if (FAILED(hr = __SetRenderState(D3DRS_BLENDOPALPHA, D3D9Mappings::get(op))))
  1962. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set scene blending operation option", "D3D9RenderSystem::_setSceneBlendingOperation" );
  1963. }
  1964. //---------------------------------------------------------------------
  1965. void D3D9RenderSystem::_setSeparateSceneBlending( SceneBlendFactor sourceFactor, SceneBlendFactor destFactor, SceneBlendFactor sourceFactorAlpha,
  1966. SceneBlendFactor destFactorAlpha, SceneBlendOperation op, SceneBlendOperation alphaOp )
  1967. {
  1968. HRESULT hr;
  1969. if( sourceFactor == SBF_ONE && destFactor == SBF_ZERO &&
  1970. sourceFactorAlpha == SBF_ONE && destFactorAlpha == SBF_ZERO)
  1971. {
  1972. if (FAILED(hr = __SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE)))
  1973. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set alpha blending option", "D3D9RenderSystem::_setSceneBlending" );
  1974. }
  1975. else
  1976. {
  1977. if (FAILED(hr = __SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE)))
  1978. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set alpha blending option", "D3D9RenderSystem::_setSeperateSceneBlending" );
  1979. if (FAILED(hr = __SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE)))
  1980. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set separate alpha blending option", "D3D9RenderSystem::_setSeperateSceneBlending" );
  1981. if( FAILED( hr = __SetRenderState( D3DRS_SRCBLEND, D3D9Mappings::get(sourceFactor) ) ) )
  1982. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set source blend", "D3D9RenderSystem::_setSeperateSceneBlending" );
  1983. if( FAILED( hr = __SetRenderState( D3DRS_DESTBLEND, D3D9Mappings::get(destFactor) ) ) )
  1984. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set destination blend", "D3D9RenderSystem::_setSeperateSceneBlending" );
  1985. if( FAILED( hr = __SetRenderState( D3DRS_SRCBLENDALPHA, D3D9Mappings::get(sourceFactorAlpha) ) ) )
  1986. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set alpha source blend", "D3D9RenderSystem::_setSeperateSceneBlending" );
  1987. if( FAILED( hr = __SetRenderState( D3DRS_DESTBLENDALPHA, D3D9Mappings::get(destFactorAlpha) ) ) )
  1988. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set alpha destination blend", "D3D9RenderSystem::_setSeperateSceneBlending" );
  1989. }
  1990. if (FAILED(hr = __SetRenderState(D3DRS_BLENDOP, D3D9Mappings::get(op))))
  1991. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set scene blending operation option", "D3D9RenderSystem::_setSceneBlendingOperation" );
  1992. if (FAILED(hr = __SetRenderState(D3DRS_BLENDOPALPHA, D3D9Mappings::get(alphaOp))))
  1993. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set alpha scene blending operation option", "D3D9RenderSystem::_setSceneBlendingOperation" );
  1994. }
  1995. //---------------------------------------------------------------------
  1996. void D3D9RenderSystem::_setAlphaRejectSettings( CompareFunction func, unsigned char value, bool alphaToCoverage )
  1997. {
  1998. HRESULT hr;
  1999. bool a2c = false;
  2000. static bool lasta2c = false;
  2001. if (func != CMPF_ALWAYS_PASS)
  2002. {
  2003. if( FAILED( hr = __SetRenderState( D3DRS_ALPHATESTENABLE, TRUE ) ) )
  2004. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to enable alpha testing",
  2005. "D3D9RenderSystem::_setAlphaRejectSettings" );
  2006. a2c = alphaToCoverage;
  2007. }
  2008. else
  2009. {
  2010. if( FAILED( hr = __SetRenderState( D3DRS_ALPHATESTENABLE, FALSE ) ) )
  2011. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to disable alpha testing",
  2012. "D3D9RenderSystem::_setAlphaRejectSettings" );
  2013. }
  2014. // Set always just be sure
  2015. if( FAILED( hr = __SetRenderState( D3DRS_ALPHAFUNC, D3D9Mappings::get(func) ) ) )
  2016. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set alpha reject function", "D3D9RenderSystem::_setAlphaRejectSettings" );
  2017. if( FAILED( hr = __SetRenderState( D3DRS_ALPHAREF, value ) ) )
  2018. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set render state D3DRS_ALPHAREF", "D3D9RenderSystem::_setAlphaRejectSettings" );
  2019. // Alpha to coverage
  2020. if (getCapabilities()->hasCapability(RSC_ALPHA_TO_COVERAGE))
  2021. {
  2022. // Vendor-specific hacks on renderstate, gotta love 'em
  2023. if (getCapabilities()->getVendor() == GPU_NVIDIA)
  2024. {
  2025. if (a2c)
  2026. {
  2027. if( FAILED( hr = __SetRenderState( D3DRS_ADAPTIVETESS_Y, (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C') ) ) )
  2028. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set alpha to coverage option", "D3D9RenderSystem::_setAlphaRejectSettings" );
  2029. }
  2030. else
  2031. {
  2032. if( FAILED( hr = __SetRenderState( D3DRS_ADAPTIVETESS_Y, D3DFMT_UNKNOWN ) ) )
  2033. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set alpha to coverage option", "D3D9RenderSystem::_setAlphaRejectSettings" );
  2034. }
  2035. }
  2036. else if ((getCapabilities()->getVendor() == GPU_ATI))
  2037. {
  2038. if (a2c)
  2039. {
  2040. if( FAILED( hr = __SetRenderState( D3DRS_POINTSIZE, MAKEFOURCC('A','2','M','1') ) ) )
  2041. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set alpha to coverage option", "D3D9RenderSystem::_setAlphaRejectSettings" );
  2042. }
  2043. else
  2044. {
  2045. // discovered this through trial and error, seems to work
  2046. if( FAILED( hr = __SetRenderState( D3DRS_POINTSIZE, MAKEFOURCC('A','2','M','0') ) ) )
  2047. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set alpha to coverage option", "D3D9RenderSystem::_setAlphaRejectSettings" );
  2048. }
  2049. }
  2050. // no hacks available for any other vendors?
  2051. lasta2c = a2c;
  2052. }
  2053. }
  2054. //---------------------------------------------------------------------
  2055. void D3D9RenderSystem::_setCullingMode( CullingMode mode )
  2056. {
  2057. mCullingMode = mode;
  2058. HRESULT hr;
  2059. bool flip = ((mActiveRenderTarget->requiresTextureFlipping() && !mInvertVertexWinding) ||
  2060. (!mActiveRenderTarget->requiresTextureFlipping() && mInvertVertexWinding));
  2061. if( FAILED (hr = __SetRenderState(D3DRS_CULLMODE,
  2062. D3D9Mappings::get(mode, flip))) )
  2063. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set culling mode", "D3D9RenderSystem::_setCullingMode" );
  2064. }
  2065. //---------------------------------------------------------------------
  2066. void D3D9RenderSystem::_setDepthBufferParams( bool depthTest, bool depthWrite, CompareFunction depthFunction )
  2067. {
  2068. _setDepthBufferCheckEnabled( depthTest );
  2069. _setDepthBufferWriteEnabled( depthWrite );
  2070. _setDepthBufferFunction( depthFunction );
  2071. }
  2072. //---------------------------------------------------------------------
  2073. void D3D9RenderSystem::_setDepthBufferCheckEnabled( bool enabled )
  2074. {
  2075. HRESULT hr;
  2076. if( enabled )
  2077. {
  2078. // Use w-buffer if available and enabled
  2079. if( mWBuffer && mDeviceManager->getActiveDevice()->getD3D9DeviceCaps().RasterCaps & D3DPRASTERCAPS_WBUFFER )
  2080. hr = __SetRenderState( D3DRS_ZENABLE, D3DZB_USEW );
  2081. else
  2082. hr = __SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE );
  2083. }
  2084. else
  2085. hr = __SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE );
  2086. if( FAILED( hr ) )
  2087. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error setting depth buffer test state", "D3D9RenderSystem::_setDepthBufferCheckEnabled" );
  2088. }
  2089. //---------------------------------------------------------------------
  2090. void D3D9RenderSystem::_setDepthBufferWriteEnabled( bool enabled )
  2091. {
  2092. HRESULT hr;
  2093. if( FAILED( hr = __SetRenderState( D3DRS_ZWRITEENABLE, enabled ) ) )
  2094. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error setting depth buffer write state", "D3D9RenderSystem::_setDepthBufferWriteEnabled" );
  2095. }
  2096. //---------------------------------------------------------------------
  2097. void D3D9RenderSystem::_setDepthBufferFunction( CompareFunction func )
  2098. {
  2099. HRESULT hr;
  2100. if( FAILED( hr = __SetRenderState( D3DRS_ZFUNC, D3D9Mappings::get(func) ) ) )
  2101. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error setting depth buffer test function", "D3D9RenderSystem::_setDepthBufferFunction" );
  2102. }
  2103. //---------------------------------------------------------------------
  2104. void D3D9RenderSystem::_setDepthBias(float constantBias, float slopeScaleBias)
  2105. {
  2106. if ((mDeviceManager->getActiveDevice()->getD3D9DeviceCaps().RasterCaps & D3DPRASTERCAPS_DEPTHBIAS) != 0)
  2107. {
  2108. // Negate bias since D3D is backward
  2109. // D3D also expresses the constant bias as an absolute value, rather than
  2110. // relative to minimum depth unit, so scale to fit
  2111. constantBias = -constantBias / 250000.0f;
  2112. HRESULT hr = __SetRenderState(D3DRS_DEPTHBIAS, FLOAT2DWORD(constantBias));
  2113. if (FAILED(hr))
  2114. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error setting constant depth bias",
  2115. "D3D9RenderSystem::_setDepthBias");
  2116. }
  2117. if ((mDeviceManager->getActiveDevice()->getD3D9DeviceCaps().RasterCaps & D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS) != 0)
  2118. {
  2119. // Negate bias since D3D is backward
  2120. slopeScaleBias = -slopeScaleBias;
  2121. HRESULT hr = __SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, FLOAT2DWORD(slopeScaleBias));
  2122. if (FAILED(hr))
  2123. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error setting slope scale depth bias",
  2124. "D3D9RenderSystem::_setDepthBias");
  2125. }
  2126. }
  2127. //---------------------------------------------------------------------
  2128. void D3D9RenderSystem::_setColourBufferWriteEnabled(bool red, bool green,
  2129. bool blue, bool alpha)
  2130. {
  2131. DWORD val = 0;
  2132. if (red)
  2133. val |= D3DCOLORWRITEENABLE_RED;
  2134. if (green)
  2135. val |= D3DCOLORWRITEENABLE_GREEN;
  2136. if (blue)
  2137. val |= D3DCOLORWRITEENABLE_BLUE;
  2138. if (alpha)
  2139. val |= D3DCOLORWRITEENABLE_ALPHA;
  2140. HRESULT hr = __SetRenderState(D3DRS_COLORWRITEENABLE, val);
  2141. if (FAILED(hr))
  2142. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error setting colour write enable flags",
  2143. "D3D9RenderSystem::_setColourBufferWriteEnabled");
  2144. }
  2145. //---------------------------------------------------------------------
  2146. void D3D9RenderSystem::_setFog( FogMode mode, const ColourValue& colour, Real densitiy, Real start, Real end )
  2147. {
  2148. HRESULT hr;
  2149. D3DRENDERSTATETYPE fogType, fogTypeNot;
  2150. if (mDeviceManager->getActiveDevice()->getD3D9DeviceCaps().RasterCaps & D3DPRASTERCAPS_FOGTABLE)
  2151. {
  2152. fogType = D3DRS_FOGTABLEMODE;
  2153. fogTypeNot = D3DRS_FOGVERTEXMODE;
  2154. }
  2155. else
  2156. {
  2157. fogType = D3DRS_FOGVERTEXMODE;
  2158. fogTypeNot = D3DRS_FOGTABLEMODE;
  2159. }
  2160. if( mode == FOG_NONE)
  2161. {
  2162. // just disable
  2163. hr = __SetRenderState(fogType, D3DFOG_NONE );
  2164. hr = __SetRenderState(D3DRS_FOGENABLE, FALSE);
  2165. }
  2166. else
  2167. {
  2168. // Allow fog
  2169. hr = __SetRenderState( D3DRS_FOGENABLE, TRUE );
  2170. hr = __SetRenderState( fogTypeNot, D3DFOG_NONE );
  2171. hr = __SetRenderState( fogType, D3D9Mappings::get(mode) );
  2172. hr = __SetRenderState( D3DRS_FOGCOLOR, colour.getAsARGB() );
  2173. hr = __SetFloatRenderState( D3DRS_FOGSTART, start );
  2174. hr = __SetFloatRenderState( D3DRS_FOGEND, end );
  2175. hr = __SetFloatRenderState( D3DRS_FOGDENSITY, densitiy );
  2176. }
  2177. if( FAILED( hr ) )
  2178. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error setting render state", "D3D9RenderSystem::_setFog" );
  2179. }
  2180. //---------------------------------------------------------------------
  2181. void D3D9RenderSystem::_setPolygonMode(PolygonMode level)
  2182. {
  2183. HRESULT hr = __SetRenderState(D3DRS_FILLMODE, D3D9Mappings::get(level));
  2184. if (FAILED(hr))
  2185. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error setting polygon mode.", "D3D9RenderSystem::setPolygonMode");
  2186. }
  2187. //---------------------------------------------------------------------
  2188. void D3D9RenderSystem::setStencilCheckEnabled(bool enabled)
  2189. {
  2190. // Allow stencilling
  2191. HRESULT hr = __SetRenderState(D3DRS_STENCILENABLE, enabled);
  2192. if (FAILED(hr))
  2193. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error enabling / disabling stencilling.",
  2194. "D3D9RenderSystem::setStencilCheckEnabled");
  2195. }
  2196. //---------------------------------------------------------------------
  2197. void D3D9RenderSystem::setStencilBufferParams(CompareFunction func,
  2198. uint32 refValue, uint32 mask, StencilOperation stencilFailOp,
  2199. StencilOperation depthFailOp, StencilOperation passOp,
  2200. bool twoSidedOperation)
  2201. {
  2202. HRESULT hr;
  2203. bool flip;
  2204. // 2-sided operation
  2205. if (twoSidedOperation)
  2206. {
  2207. if (!mCurrentCapabilities->hasCapability(RSC_TWO_SIDED_STENCIL))
  2208. OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "2-sided stencils are not supported",
  2209. "D3D9RenderSystem::setStencilBufferParams");
  2210. hr = __SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
  2211. if (FAILED(hr))
  2212. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error setting 2-sided stencil mode.",
  2213. "D3D9RenderSystem::setStencilBufferParams");
  2214. // NB: We should always treat CCW as front face for consistent with default
  2215. // culling mode. Therefore, we must take care with two-sided stencil settings.
  2216. flip = (mInvertVertexWinding && mActiveRenderTarget->requiresTextureFlipping()) ||
  2217. (!mInvertVertexWinding && !mActiveRenderTarget->requiresTextureFlipping());
  2218. // Set alternative versions of ops
  2219. // fail op
  2220. hr = __SetRenderState(D3DRS_CCW_STENCILFAIL, D3D9Mappings::get(stencilFailOp, !flip));
  2221. if (FAILED(hr))
  2222. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error setting stencil fail operation (2-sided).",
  2223. "D3D9RenderSystem::setStencilBufferParams");
  2224. // depth fail op
  2225. hr = __SetRenderState(D3DRS_CCW_STENCILZFAIL, D3D9Mappings::get(depthFailOp, !flip));
  2226. if (FAILED(hr))
  2227. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error setting stencil depth fail operation (2-sided).",
  2228. "D3D9RenderSystem::setStencilBufferParams");
  2229. // pass op
  2230. hr = __SetRenderState(D3DRS_CCW_STENCILPASS, D3D9Mappings::get(passOp, !flip));
  2231. if (FAILED(hr))
  2232. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error setting stencil pass operation (2-sided).",
  2233. "D3D9RenderSystem::setStencilBufferParams");
  2234. }
  2235. else
  2236. {
  2237. hr = __SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
  2238. if (FAILED(hr))
  2239. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error setting 1-sided stencil mode.",
  2240. "D3D9RenderSystem::setStencilBufferParams");
  2241. flip = false;
  2242. }
  2243. // func
  2244. hr = __SetRenderState(D3DRS_STENCILFUNC, D3D9Mappings::get(func));
  2245. if (FAILED(hr))
  2246. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error setting stencil buffer test function.",
  2247. "D3D9RenderSystem::setStencilBufferParams");
  2248. // reference value
  2249. hr = __SetRenderState(D3DRS_STENCILREF, refValue);
  2250. if (FAILED(hr))
  2251. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error setting stencil buffer reference value.",
  2252. "D3D9RenderSystem::setStencilBufferParams");
  2253. // mask
  2254. hr = __SetRenderState(D3DRS_STENCILMASK, mask);
  2255. if (FAILED(hr))
  2256. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error setting stencil buffer mask.",
  2257. "D3D9RenderSystem::setStencilBufferParams");
  2258. // fail op
  2259. hr = __SetRenderState(D3DRS_STENCILFAIL, D3D9Mappings::get(stencilFailOp, flip));
  2260. if (FAILED(hr))
  2261. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error setting stencil fail operation.",
  2262. "D3D9RenderSystem::setStencilBufferParams");
  2263. // depth fail op
  2264. hr = __SetRenderState(D3DRS_STENCILZFAIL, D3D9Mappings::get(depthFailOp, flip));
  2265. if (FAILED(hr))
  2266. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error setting stencil depth fail operation.",
  2267. "D3D9RenderSystem::setStencilBufferParams");
  2268. // pass op
  2269. hr = __SetRenderState(D3DRS_STENCILPASS, D3D9Mappings::get(passOp, flip));
  2270. if (FAILED(hr))
  2271. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error setting stencil pass operation.",
  2272. "D3D9RenderSystem::setStencilBufferParams");
  2273. }
  2274. //---------------------------------------------------------------------
  2275. void D3D9RenderSystem::_setTextureUnitFiltering(size_t unit, FilterType ftype,
  2276. FilterOptions filter)
  2277. {
  2278. HRESULT hr;
  2279. D3D9Mappings::eD3DTexType texType = mTexStageDesc[unit].texType;
  2280. hr = __SetSamplerState( static_cast<DWORD>(unit), D3D9Mappings::get(ftype),
  2281. D3D9Mappings::get(ftype, filter, mDeviceManager->getActiveDevice()->getD3D9DeviceCaps(), texType));
  2282. if (FAILED(hr))
  2283. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set texture filter ", "D3D9RenderSystem::_setTextureUnitFiltering");
  2284. }
  2285. //---------------------------------------------------------------------
  2286. DWORD D3D9RenderSystem::_getCurrentAnisotropy(size_t unit)
  2287. {
  2288. DWORD oldVal;
  2289. getActiveD3D9Device()->GetSamplerState(static_cast<DWORD>(unit), D3DSAMP_MAXANISOTROPY, &oldVal);
  2290. return oldVal;
  2291. }
  2292. //---------------------------------------------------------------------
  2293. void D3D9RenderSystem::_setTextureLayerAnisotropy(size_t unit, unsigned int maxAnisotropy)
  2294. {
  2295. if (static_cast<DWORD>(maxAnisotropy) > mDeviceManager->getActiveDevice()->getD3D9DeviceCaps().MaxAnisotropy)
  2296. maxAnisotropy = mDeviceManager->getActiveDevice()->getD3D9DeviceCaps().MaxAnisotropy;
  2297. if (_getCurrentAnisotropy(unit) != maxAnisotropy)
  2298. __SetSamplerState( static_cast<DWORD>(unit), D3DSAMP_MAXANISOTROPY, maxAnisotropy );
  2299. }
  2300. //---------------------------------------------------------------------
  2301. HRESULT D3D9RenderSystem::__SetRenderState(D3DRENDERSTATETYPE state, DWORD value)
  2302. {
  2303. HRESULT hr;
  2304. DWORD oldVal;
  2305. if ( FAILED( hr = getActiveD3D9Device()->GetRenderState(state, &oldVal) ) )
  2306. return hr;
  2307. if ( oldVal == value )
  2308. return D3D_OK;
  2309. else
  2310. return getActiveD3D9Device()->SetRenderState(state, value);
  2311. }
  2312. //---------------------------------------------------------------------
  2313. HRESULT D3D9RenderSystem::__SetSamplerState(DWORD sampler, D3DSAMPLERSTATETYPE type, DWORD value)
  2314. {
  2315. HRESULT hr;
  2316. DWORD oldVal;
  2317. if ( FAILED( hr = getActiveD3D9Device()->GetSamplerState(sampler, type, &oldVal) ) )
  2318. return hr;
  2319. if ( oldVal == value )
  2320. return D3D_OK;
  2321. else
  2322. return getActiveD3D9Device()->SetSamplerState(sampler, type, value);
  2323. }
  2324. //---------------------------------------------------------------------
  2325. HRESULT D3D9RenderSystem::__SetTextureStageState(DWORD stage, D3DTEXTURESTAGESTATETYPE type, DWORD value)
  2326. {
  2327. HRESULT hr;
  2328. DWORD oldVal;
  2329. // can only set fixed-function texture stage state
  2330. if (stage < 8)
  2331. {
  2332. if ( FAILED( hr = getActiveD3D9Device()->GetTextureStageState(stage, type, &oldVal) ) )
  2333. return hr;
  2334. if ( oldVal == value )
  2335. return D3D_OK;
  2336. else
  2337. return getActiveD3D9Device()->SetTextureStageState(stage, type, value);
  2338. }
  2339. else
  2340. {
  2341. return D3D_OK;
  2342. }
  2343. }
  2344. //---------------------------------------------------------------------
  2345. void D3D9RenderSystem::_setRenderTarget(RenderTarget *target)
  2346. {
  2347. mActiveRenderTarget = target;
  2348. HRESULT hr;
  2349. // If this is called without going through RenderWindow::update, then
  2350. // the device will not have been set. Calling it twice is safe, the
  2351. // implementation ensures nothing happens if the same device is set twice
  2352. if (std::find(mRenderWindows.begin(), mRenderWindows.end(), target) != mRenderWindows.end())
  2353. {
  2354. D3D9RenderWindow *window = static_cast<D3D9RenderWindow*>(target);
  2355. mDeviceManager->setActiveRenderTargetDevice(window->getDevice());
  2356. // also make sure we validate the device; if this never went
  2357. // through update() it won't be set
  2358. window->_validateDevice();
  2359. }
  2360. // Retrieve render surfaces (up to OGRE_MAX_MULTIPLE_RENDER_TARGETS)
  2361. IDirect3DSurface9* pBack[OGRE_MAX_MULTIPLE_RENDER_TARGETS];
  2362. memset(pBack, 0, sizeof(pBack));
  2363. target->getCustomAttribute( "DDBACKBUFFER", &pBack );
  2364. if (!pBack[0])
  2365. return;
  2366. IDirect3DSurface9* pDepth = NULL;
  2367. //Check if we saved a depth buffer for this target
  2368. TargetDepthStencilMap::iterator savedTexture = mCheckedOutTextures.find(target);
  2369. if (savedTexture != mCheckedOutTextures.end())
  2370. {
  2371. pDepth = savedTexture->second.surface;
  2372. }
  2373. if (!pDepth)
  2374. target->getCustomAttribute( "D3DZBUFFER", &pDepth );
  2375. if (!pDepth)
  2376. {
  2377. /// No depth buffer provided, use our own
  2378. /// Request a depth stencil that is compatible with the format, multisample type and
  2379. /// dimensions of the render target.
  2380. D3DSURFACE_DESC srfDesc;
  2381. if(FAILED(pBack[0]->GetDesc(&srfDesc)))
  2382. return; // ?
  2383. pDepth = _getDepthStencilFor(srfDesc.Format, srfDesc.MultiSampleType, srfDesc.MultiSampleQuality, srfDesc.Width, srfDesc.Height);
  2384. }
  2385. // Bind render targets
  2386. uint count = mCurrentCapabilities->getNumMultiRenderTargets();
  2387. for(uint x=0; x<count; ++x)
  2388. {
  2389. hr = getActiveD3D9Device()->SetRenderTarget(x, pBack[x]);
  2390. if (FAILED(hr))
  2391. {
  2392. String msg = DXGetErrorDescription(hr);
  2393. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to setRenderTarget : " + msg, "D3D9RenderSystem::_setViewport" );
  2394. }
  2395. }
  2396. hr = getActiveD3D9Device()->SetDepthStencilSurface(pDepth);
  2397. if (FAILED(hr))
  2398. {
  2399. String msg = DXGetErrorDescription(hr);
  2400. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to setDepthStencil : " + msg, "D3D9RenderSystem::_setViewport" );
  2401. }
  2402. }
  2403. //---------------------------------------------------------------------
  2404. void D3D9RenderSystem::_setViewport( Viewport *vp )
  2405. {
  2406. if( vp != mActiveViewport || vp->_isUpdated() )
  2407. {
  2408. mActiveViewport = vp;
  2409. // ok, it's different, time to set render target and viewport params
  2410. D3DVIEWPORT9 d3dvp;
  2411. HRESULT hr;
  2412. // Set render target
  2413. RenderTarget* target = vp->getTarget();
  2414. _setRenderTarget(target);
  2415. _setCullingMode( mCullingMode );
  2416. // set viewport dimensions
  2417. d3dvp.X = vp->getActualLeft();
  2418. d3dvp.Y = vp->getActualTop();
  2419. d3dvp.Width = vp->getActualWidth();
  2420. d3dvp.Height = vp->getActualHeight();
  2421. if (target->requiresTextureFlipping())
  2422. {
  2423. // Convert "top-left" to "bottom-left"
  2424. d3dvp.Y = target->getHeight() - d3dvp.Height - d3dvp.Y;
  2425. }
  2426. // Z-values from 0.0 to 1.0 (TODO: standardise with OpenGL)
  2427. d3dvp.MinZ = 0.0f;
  2428. d3dvp.MaxZ = 1.0f;
  2429. if( FAILED( hr = getActiveD3D9Device()->SetViewport( &d3dvp ) ) )
  2430. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set viewport.", "D3D9RenderSystem::_setViewport" );
  2431. // Set sRGB write mode
  2432. __SetRenderState(D3DRS_SRGBWRITEENABLE, target->isHardwareGammaEnabled());
  2433. vp->_clearUpdatedFlag();
  2434. }
  2435. }
  2436. //---------------------------------------------------------------------
  2437. void D3D9RenderSystem::_beginFrame()
  2438. {
  2439. HRESULT hr;
  2440. if( !mActiveViewport )
  2441. OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR, "Cannot begin frame - no viewport selected.", "D3D9RenderSystem::_beginFrame" );
  2442. if( FAILED( hr = getActiveD3D9Device()->BeginScene() ) )
  2443. {
  2444. String msg = DXGetErrorDescription(hr);
  2445. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error beginning frame :" + msg, "D3D9RenderSystem::_beginFrame" );
  2446. }
  2447. mLastVertexSourceCount = 0;
  2448. // Clear left overs of previous viewport.
  2449. // I.E: Viewport A can use 3 different textures and light states
  2450. // When trying to render viewport B these settings should be cleared, otherwise
  2451. // graphical artifacts might occur.
  2452. mDeviceManager->getActiveDevice()->clearDeviceStreams();
  2453. }
  2454. //---------------------------------------------------------------------
  2455. void D3D9RenderSystem::_endFrame()
  2456. {
  2457. HRESULT hr;
  2458. if( FAILED( hr = getActiveD3D9Device()->EndScene() ) )
  2459. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error ending frame", "D3D9RenderSystem::_endFrame" );
  2460. mDeviceManager->destroyInactiveRenderDevices();
  2461. }
  2462. //---------------------------------------------------------------------
  2463. struct D3D9RenderContext : public RenderSystem::RenderSystemContext
  2464. {
  2465. RenderTarget* target;
  2466. };
  2467. //---------------------------------------------------------------------
  2468. D3D9RenderSystem::ZBufferIdentifier D3D9RenderSystem::getZBufferIdentifier(RenderTarget* rt)
  2469. {
  2470. // Retrieve render surfaces (up to OGRE_MAX_MULTIPLE_RENDER_TARGETS)
  2471. IDirect3DSurface9* pBack[OGRE_MAX_MULTIPLE_RENDER_TARGETS];
  2472. memset(pBack, 0, sizeof(pBack));
  2473. rt->getCustomAttribute( "DDBACKBUFFER", &pBack );
  2474. assert(pBack[0]);
  2475. /// Request a depth stencil that is compatible with the format, multisample type and
  2476. /// dimensions of the render target.
  2477. D3DSURFACE_DESC srfDesc;
  2478. HRESULT hr = pBack[0]->GetDesc(&srfDesc);
  2479. assert(!(FAILED(hr)));
  2480. D3DFORMAT dsfmt = _getDepthStencilFormatFor(srfDesc.Format);
  2481. assert(dsfmt != D3DFMT_UNKNOWN);
  2482. /// Build identifier and return
  2483. ZBufferIdentifier zBufferIdentifier;
  2484. zBufferIdentifier.format = dsfmt;
  2485. zBufferIdentifier.multisampleType = srfDesc.MultiSampleType;
  2486. zBufferIdentifier.device = getActiveD3D9Device();
  2487. return zBufferIdentifier;
  2488. }
  2489. //---------------------------------------------------------------------
  2490. RenderSystem::RenderSystemContext* D3D9RenderSystem::_pauseFrame(void)
  2491. {
  2492. //Stop rendering
  2493. _endFrame();
  2494. D3D9RenderContext* context = new D3D9RenderContext;
  2495. context->target = mActiveRenderTarget;
  2496. //Don't do this to backbuffers. Is there a more elegant way to check?
  2497. if (!dynamic_cast<D3D9RenderWindow*>(mActiveRenderTarget))
  2498. {
  2499. //Get the matching z buffer identifier and queue
  2500. ZBufferIdentifier zBufferIdentifier = getZBufferIdentifier(mActiveRenderTarget);
  2501. ZBufferRefQueue& zBuffers = mZBufferHash[zBufferIdentifier];
  2502. #ifdef OGRE_DEBUG_MODE
  2503. //Check that queue handling works as expected
  2504. IDirect3DSurface9* pDepth;
  2505. getActiveD3D9Device()->GetDepthStencilSurface(&pDepth);
  2506. // Release immediately -> each get increase the ref count.
  2507. if (pDepth != NULL)
  2508. pDepth->Release();
  2509. assert(zBuffers.front().surface == pDepth);
  2510. #endif
  2511. //Store the depth buffer in the side and remove it from the queue
  2512. mCheckedOutTextures[mActiveRenderTarget] = zBuffers.front();
  2513. zBuffers.pop_front();
  2514. }
  2515. return context;
  2516. }
  2517. //---------------------------------------------------------------------
  2518. void D3D9RenderSystem::_resumeFrame(RenderSystemContext* context)
  2519. {
  2520. //Resume rendering
  2521. _beginFrame();
  2522. D3D9RenderContext* d3dContext = static_cast<D3D9RenderContext*>(context);
  2523. //Don't do this to backbuffers. Is there a more elegant way to check?
  2524. if (!dynamic_cast<D3D9RenderWindow*>(d3dContext->target))
  2525. {
  2526. ///Find the stored depth buffer
  2527. ZBufferIdentifier zBufferIdentifier = getZBufferIdentifier(d3dContext->target);
  2528. ZBufferRefQueue& zBuffers = mZBufferHash[zBufferIdentifier];
  2529. assert(mCheckedOutTextures.find(d3dContext->target) != mCheckedOutTextures.end());
  2530. //Return it to the general queue
  2531. zBuffers.push_front(mCheckedOutTextures[d3dContext->target]);
  2532. mCheckedOutTextures.erase(d3dContext->target);
  2533. }
  2534. delete context;
  2535. }
  2536. //---------------------------------------------------------------------
  2537. void D3D9RenderSystem::setVertexDeclaration(VertexDeclaration* decl)
  2538. {
  2539. HRESULT hr;
  2540. D3D9VertexDeclaration* d3ddecl =
  2541. static_cast<D3D9VertexDeclaration*>(decl);
  2542. if (FAILED(hr = getActiveD3D9Device()->SetVertexDeclaration(d3ddecl->getD3DVertexDeclaration())))
  2543. {
  2544. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Unable to set D3D9 vertex declaration",
  2545. "D3D9RenderSystem::setVertexDeclaration");
  2546. }
  2547. }
  2548. //---------------------------------------------------------------------
  2549. void D3D9RenderSystem::setVertexBufferBinding(VertexBufferBinding* binding)
  2550. {
  2551. HRESULT hr;
  2552. // TODO: attempt to detect duplicates
  2553. const VertexBufferBinding::VertexBufferBindingMap& binds = binding->getBindings();
  2554. VertexBufferBinding::VertexBufferBindingMap::const_iterator i, iend;
  2555. size_t source = 0;
  2556. iend = binds.end();
  2557. for (i = binds.begin(); i != iend; ++i, ++source)
  2558. {
  2559. // Unbind gap sources
  2560. for ( ; source < i->first; ++source)
  2561. {
  2562. hr = getActiveD3D9Device()->SetStreamSource(static_cast<UINT>(source), NULL, 0, 0);
  2563. if (FAILED(hr))
  2564. {
  2565. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Unable to reset unused D3D9 stream source",
  2566. "D3D9RenderSystem::setVertexBufferBinding");
  2567. }
  2568. }
  2569. D3D9HardwareVertexBuffer* d3d9buf =
  2570. static_cast<D3D9HardwareVertexBuffer*>(i->second.get());
  2571. hr = getActiveD3D9Device()->SetStreamSource(
  2572. static_cast<UINT>(source),
  2573. d3d9buf->getD3D9VertexBuffer(),
  2574. 0, // no stream offset, this is handled in _render instead
  2575. static_cast<UINT>(d3d9buf->getVertexSize()) // stride
  2576. );
  2577. if (FAILED(hr))
  2578. {
  2579. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Unable to set D3D9 stream source for buffer binding",
  2580. "D3D9RenderSystem::setVertexBufferBinding");
  2581. }
  2582. }
  2583. // Unbind any unused sources
  2584. for (size_t unused = source; unused < mLastVertexSourceCount; ++unused)
  2585. {
  2586. hr = getActiveD3D9Device()->SetStreamSource(static_cast<UINT>(unused), NULL, 0, 0);
  2587. if (FAILED(hr))
  2588. {
  2589. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Unable to reset unused D3D9 stream source",
  2590. "D3D9RenderSystem::setVertexBufferBinding");
  2591. }
  2592. }
  2593. mLastVertexSourceCount = source;
  2594. }
  2595. //---------------------------------------------------------------------
  2596. void D3D9RenderSystem::_render(const RenderOperation& op)
  2597. {
  2598. // Exit immediately if there is nothing to render
  2599. // This caused a problem on FireGL 8800
  2600. if (op.vertexData->vertexCount == 0)
  2601. return;
  2602. // Call super class
  2603. RenderSystem::_render(op);
  2604. // To think about: possibly remove setVertexDeclaration and
  2605. // setVertexBufferBinding from RenderSystem since the sequence is
  2606. // a bit too D3D9-specific?
  2607. setVertexDeclaration(op.vertexData->vertexDeclaration);
  2608. setVertexBufferBinding(op.vertexData->vertexBufferBinding);
  2609. // Determine rendering operation
  2610. D3DPRIMITIVETYPE primType = D3DPT_TRIANGLELIST;
  2611. DWORD primCount = 0;
  2612. switch( op.operationType )
  2613. {
  2614. case RenderOperation::OT_POINT_LIST:
  2615. primType = D3DPT_POINTLIST;
  2616. primCount = static_cast<DWORD>(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount);
  2617. break;
  2618. case RenderOperation::OT_LINE_LIST:
  2619. primType = D3DPT_LINELIST;
  2620. primCount = static_cast<DWORD>(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) / 2;
  2621. break;
  2622. case RenderOperation::OT_LINE_STRIP:
  2623. primType = D3DPT_LINESTRIP;
  2624. primCount = static_cast<DWORD>(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) - 1;
  2625. break;
  2626. case RenderOperation::OT_TRIANGLE_LIST:
  2627. primType = D3DPT_TRIANGLELIST;
  2628. primCount = static_cast<DWORD>(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) / 3;
  2629. break;
  2630. case RenderOperation::OT_TRIANGLE_STRIP:
  2631. primType = D3DPT_TRIANGLESTRIP;
  2632. primCount = static_cast<DWORD>(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) - 2;
  2633. break;
  2634. case RenderOperation::OT_TRIANGLE_FAN:
  2635. primType = D3DPT_TRIANGLEFAN;
  2636. primCount = static_cast<DWORD>(op.useIndexes ? op.indexData->indexCount : op.vertexData->vertexCount) - 2;
  2637. break;
  2638. }
  2639. if (!primCount)
  2640. return;
  2641. // Issue the op
  2642. HRESULT hr;
  2643. if( op.useIndexes )
  2644. {
  2645. D3D9HardwareIndexBuffer* d3dIdxBuf =
  2646. static_cast<D3D9HardwareIndexBuffer*>(op.indexData->indexBuffer.get());
  2647. hr = getActiveD3D9Device()->SetIndices( d3dIdxBuf->getD3DIndexBuffer() );
  2648. if (FAILED(hr))
  2649. {
  2650. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to set index buffer", "D3D9RenderSystem::_render" );
  2651. }
  2652. do
  2653. {
  2654. // Update derived depth bias
  2655. if (mDerivedDepthBias && mCurrentPassIterationNum > 0)
  2656. {
  2657. _setDepthBias(mDerivedDepthBiasBase +
  2658. mDerivedDepthBiasMultiplier * mCurrentPassIterationNum,
  2659. mDerivedDepthBiasSlopeScale);
  2660. }
  2661. // do indexed draw operation
  2662. hr = getActiveD3D9Device()->DrawIndexedPrimitive(
  2663. primType,
  2664. static_cast<INT>(op.vertexData->vertexStart),
  2665. 0, // Min vertex index - assume we can go right down to 0
  2666. static_cast<UINT>(op.vertexData->vertexCount),
  2667. static_cast<UINT>(op.indexData->indexStart),
  2668. static_cast<UINT>(primCount)
  2669. );
  2670. } while (updatePassIterationRenderState());
  2671. }
  2672. else
  2673. {
  2674. // nfz: gpu_iterate
  2675. do
  2676. {
  2677. // Update derived depth bias
  2678. if (mDerivedDepthBias && mCurrentPassIterationNum > 0)
  2679. {
  2680. _setDepthBias(mDerivedDepthBiasBase +
  2681. mDerivedDepthBiasMultiplier * mCurrentPassIterationNum,
  2682. mDerivedDepthBiasSlopeScale);
  2683. }
  2684. // Unindexed, a little simpler!
  2685. hr = getActiveD3D9Device()->DrawPrimitive(
  2686. primType,
  2687. static_cast<UINT>(op.vertexData->vertexStart),
  2688. static_cast<UINT>(primCount)
  2689. );
  2690. } while (updatePassIterationRenderState());
  2691. }
  2692. if( FAILED( hr ) )
  2693. {
  2694. String msg = DXGetErrorDescription(hr);
  2695. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Failed to DrawPrimitive : " + msg, "D3D9RenderSystem::_render" );
  2696. }
  2697. }
  2698. //---------------------------------------------------------------------
  2699. void D3D9RenderSystem::setNormaliseNormals(bool normalise)
  2700. {
  2701. __SetRenderState(D3DRS_NORMALIZENORMALS,
  2702. normalise ? TRUE : FALSE);
  2703. }
  2704. //---------------------------------------------------------------------
  2705. void D3D9RenderSystem::bindGpuProgram(GpuProgram* prg)
  2706. {
  2707. HRESULT hr;
  2708. switch (prg->getType())
  2709. {
  2710. case GPT_VERTEX_PROGRAM:
  2711. hr = getActiveD3D9Device()->SetVertexShader(
  2712. static_cast<D3D9GpuVertexProgram*>(prg)->getVertexShader());
  2713. if (FAILED(hr))
  2714. {
  2715. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error calling SetVertexShader", "D3D9RenderSystem::bindGpuProgram");
  2716. }
  2717. break;
  2718. case GPT_FRAGMENT_PROGRAM:
  2719. hr = getActiveD3D9Device()->SetPixelShader(
  2720. static_cast<D3D9GpuFragmentProgram*>(prg)->getPixelShader());
  2721. if (FAILED(hr))
  2722. {
  2723. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error calling SetPixelShader", "D3D9RenderSystem::bindGpuProgram");
  2724. }
  2725. break;
  2726. };
  2727. // Make sure texcoord index is equal to stage value, As SDK Doc suggests:
  2728. // "When rendering using vertex shaders, each stage's texture coordinate index must be set to its default value."
  2729. // This solves such an errors when working with the Debug runtime -
  2730. // "Direct3D9: (ERROR) :Stage 1 - Texture coordinate index in the stage must be equal to the stage index when programmable vertex pipeline is used".
  2731. for (unsigned int nStage=0; nStage < 8; ++nStage)
  2732. __SetTextureStageState(nStage, D3DTSS_TEXCOORDINDEX, nStage);
  2733. RenderSystem::bindGpuProgram(prg);
  2734. }
  2735. //---------------------------------------------------------------------
  2736. void D3D9RenderSystem::unbindGpuProgram(GpuProgramType gptype)
  2737. {
  2738. HRESULT hr;
  2739. switch(gptype)
  2740. {
  2741. case GPT_VERTEX_PROGRAM:
  2742. mActiveVertexGpuProgramParameters.setNull();
  2743. hr = getActiveD3D9Device()->SetVertexShader(NULL);
  2744. if (FAILED(hr))
  2745. {
  2746. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error resetting SetVertexShader to NULL",
  2747. "D3D9RenderSystem::unbindGpuProgram");
  2748. }
  2749. break;
  2750. case GPT_FRAGMENT_PROGRAM:
  2751. mActiveFragmentGpuProgramParameters.setNull();
  2752. hr = getActiveD3D9Device()->SetPixelShader(NULL);
  2753. if (FAILED(hr))
  2754. {
  2755. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error resetting SetPixelShader to NULL",
  2756. "D3D9RenderSystem::unbindGpuProgram");
  2757. }
  2758. break;
  2759. };
  2760. RenderSystem::unbindGpuProgram(gptype);
  2761. }
  2762. //---------------------------------------------------------------------
  2763. void D3D9RenderSystem::bindGpuProgramParameters(GpuProgramType gptype,
  2764. GpuProgramParametersSharedPtr params, uint16 variability)
  2765. {
  2766. // special case pass iteration
  2767. if (variability == (uint16)GPV_PASS_ITERATION_NUMBER)
  2768. {
  2769. bindGpuProgramPassIterationParameters(gptype);
  2770. return;
  2771. }
  2772. if (variability & (uint16)GPV_GLOBAL)
  2773. {
  2774. // D3D9 doesn't support shared constant buffers, so use copy routine
  2775. params->_copySharedParams();
  2776. }
  2777. HRESULT hr;
  2778. GpuLogicalBufferStructPtr floatLogical = params->getFloatLogicalBufferStruct();
  2779. GpuLogicalBufferStructPtr intLogical = params->getIntLogicalBufferStruct();
  2780. switch(gptype)
  2781. {
  2782. case GPT_VERTEX_PROGRAM:
  2783. mActiveVertexGpuProgramParameters = params;
  2784. {
  2785. OGRE_LOCK_MUTEX(floatLogical->mutex)
  2786. for (GpuLogicalIndexUseMap::const_iterator i = floatLogical->map.begin();
  2787. i != floatLogical->map.end(); ++i)
  2788. {
  2789. if (i->second.variability & variability)
  2790. {
  2791. size_t logicalIndex = i->first;
  2792. const float* pFloat = params->getFloatPointer(i->second.physicalIndex);
  2793. size_t slotCount = i->second.currentSize / 4;
  2794. assert (i->second.currentSize % 4 == 0 && "Should not have any "
  2795. "elements less than 4 wide for D3D9");
  2796. if (FAILED(hr = getActiveD3D9Device()->SetVertexShaderConstantF(
  2797. (UINT)logicalIndex, pFloat, (UINT)slotCount)))
  2798. {
  2799. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  2800. "Unable to upload vertex shader float parameters",
  2801. "D3D9RenderSystem::bindGpuProgramParameters");
  2802. }
  2803. }
  2804. }
  2805. }
  2806. // bind ints
  2807. {
  2808. OGRE_LOCK_MUTEX(intLogical->mutex)
  2809. for (GpuLogicalIndexUseMap::const_iterator i = intLogical->map.begin();
  2810. i != intLogical->map.end(); ++i)
  2811. {
  2812. if (i->second.variability & variability)
  2813. {
  2814. size_t logicalIndex = i->first;
  2815. const int* pInt = params->getIntPointer(i->second.physicalIndex);
  2816. size_t slotCount = i->second.currentSize / 4;
  2817. assert (i->second.currentSize % 4 == 0 && "Should not have any "
  2818. "elements less than 4 wide for D3D9");
  2819. if (FAILED(hr = getActiveD3D9Device()->SetVertexShaderConstantI(
  2820. static_cast<UINT>(logicalIndex), pInt, static_cast<UINT>(slotCount))))
  2821. {
  2822. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  2823. "Unable to upload vertex shader int parameters",
  2824. "D3D9RenderSystem::bindGpuProgramParameters");
  2825. }
  2826. }
  2827. }
  2828. }
  2829. break;
  2830. case GPT_FRAGMENT_PROGRAM:
  2831. mActiveFragmentGpuProgramParameters = params;
  2832. {
  2833. OGRE_LOCK_MUTEX(floatLogical->mutex)
  2834. for (GpuLogicalIndexUseMap::const_iterator i = floatLogical->map.begin();
  2835. i != floatLogical->map.end(); ++i)
  2836. {
  2837. if (i->second.variability & variability)
  2838. {
  2839. size_t logicalIndex = i->first;
  2840. const float* pFloat = params->getFloatPointer(i->second.physicalIndex);
  2841. size_t slotCount = i->second.currentSize / 4;
  2842. assert (i->second.currentSize % 4 == 0 && "Should not have any "
  2843. "elements less than 4 wide for D3D9");
  2844. if (FAILED(hr = getActiveD3D9Device()->SetPixelShaderConstantF(
  2845. static_cast<UINT>(logicalIndex), pFloat, static_cast<UINT>(slotCount))))
  2846. {
  2847. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  2848. "Unable to upload pixel shader float parameters",
  2849. "D3D9RenderSystem::bindGpuProgramParameters");
  2850. }
  2851. }
  2852. }
  2853. }
  2854. // bind ints
  2855. {
  2856. OGRE_LOCK_MUTEX(intLogical->mutex)
  2857. for (GpuLogicalIndexUseMap::const_iterator i = intLogical->map.begin();
  2858. i != intLogical->map.end(); ++i)
  2859. {
  2860. if (i->second.variability & variability)
  2861. {
  2862. size_t logicalIndex = i->first;
  2863. const int* pInt = params->getIntPointer(i->second.physicalIndex);
  2864. size_t slotCount = i->second.currentSize / 4;
  2865. assert (i->second.currentSize % 4 == 0 && "Should not have any "
  2866. "elements less than 4 wide for D3D9");
  2867. if (FAILED(hr = getActiveD3D9Device()->SetPixelShaderConstantI(
  2868. static_cast<UINT>(logicalIndex), pInt, static_cast<UINT>(slotCount))))
  2869. {
  2870. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  2871. "Unable to upload pixel shader int parameters",
  2872. "D3D9RenderSystem::bindGpuProgramParameters");
  2873. }
  2874. }
  2875. }
  2876. }
  2877. break;
  2878. };
  2879. }
  2880. //---------------------------------------------------------------------
  2881. void D3D9RenderSystem::bindGpuProgramPassIterationParameters(GpuProgramType gptype)
  2882. {
  2883. HRESULT hr;
  2884. size_t physicalIndex = 0;
  2885. size_t logicalIndex = 0;
  2886. const float* pFloat;
  2887. switch(gptype)
  2888. {
  2889. case GPT_VERTEX_PROGRAM:
  2890. if (mActiveVertexGpuProgramParameters->hasPassIterationNumber())
  2891. {
  2892. physicalIndex = mActiveVertexGpuProgramParameters->getPassIterationNumberIndex();
  2893. logicalIndex = mActiveVertexGpuProgramParameters->getFloatLogicalIndexForPhysicalIndex(physicalIndex);
  2894. pFloat = mActiveVertexGpuProgramParameters->getFloatPointer(physicalIndex);
  2895. if (FAILED(hr = getActiveD3D9Device()->SetVertexShaderConstantF(
  2896. static_cast<UINT>(logicalIndex), pFloat, 1)))
  2897. {
  2898. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  2899. "Unable to upload vertex shader multi pass parameters",
  2900. "D3D9RenderSystem::bindGpuProgramMultiPassParameters");
  2901. }
  2902. }
  2903. break;
  2904. case GPT_FRAGMENT_PROGRAM:
  2905. if (mActiveFragmentGpuProgramParameters->hasPassIterationNumber())
  2906. {
  2907. physicalIndex = mActiveFragmentGpuProgramParameters->getPassIterationNumberIndex();
  2908. logicalIndex = mActiveFragmentGpuProgramParameters->getFloatLogicalIndexForPhysicalIndex(physicalIndex);
  2909. pFloat = mActiveFragmentGpuProgramParameters->getFloatPointer(physicalIndex);
  2910. if (FAILED(hr = getActiveD3D9Device()->SetPixelShaderConstantF(
  2911. static_cast<UINT>(logicalIndex), pFloat, 1)))
  2912. {
  2913. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  2914. "Unable to upload pixel shader multi pass parameters",
  2915. "D3D9RenderSystem::bindGpuProgramMultiPassParameters");
  2916. }
  2917. }
  2918. break;
  2919. }
  2920. }
  2921. //---------------------------------------------------------------------
  2922. void D3D9RenderSystem::setClipPlanesImpl(const PlaneList& clipPlanes)
  2923. {
  2924. size_t i;
  2925. size_t numClipPlanes;
  2926. D3DXPLANE dx9ClipPlane;
  2927. DWORD mask = 0;
  2928. HRESULT hr;
  2929. numClipPlanes = clipPlanes.size();
  2930. for (i = 0; i < numClipPlanes; ++i)
  2931. {
  2932. const Plane& plane = clipPlanes[i];
  2933. dx9ClipPlane.a = plane.normal.x;
  2934. dx9ClipPlane.b = plane.normal.y;
  2935. dx9ClipPlane.c = plane.normal.z;
  2936. dx9ClipPlane.d = plane.d;
  2937. if (mVertexProgramBound)
  2938. {
  2939. // programmable clips in clip space (ugh)
  2940. // must transform worldspace planes by view/proj
  2941. D3DXMATRIX xform;
  2942. D3DXMatrixMultiply(&xform, &mDxViewMat, &mDxProjMat);
  2943. D3DXMatrixInverse(&xform, NULL, &xform);
  2944. D3DXMatrixTranspose(&xform, &xform);
  2945. D3DXPlaneTransform(&dx9ClipPlane, &dx9ClipPlane, &xform);
  2946. }
  2947. hr = getActiveD3D9Device()->SetClipPlane(static_cast<DWORD>(i), dx9ClipPlane);
  2948. if (FAILED(hr))
  2949. {
  2950. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Unable to set clip plane",
  2951. "D3D9RenderSystem::setClipPlanes");
  2952. }
  2953. mask |= (1 << i);
  2954. }
  2955. hr = __SetRenderState(D3DRS_CLIPPLANEENABLE, mask);
  2956. if (FAILED(hr))
  2957. {
  2958. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Unable to set render state for clip planes",
  2959. "D3D9RenderSystem::setClipPlanes");
  2960. }
  2961. }
  2962. //---------------------------------------------------------------------
  2963. void D3D9RenderSystem::setScissorTest(bool enabled, size_t left, size_t top, size_t right,
  2964. size_t bottom)
  2965. {
  2966. HRESULT hr;
  2967. if (enabled)
  2968. {
  2969. if (FAILED(hr = __SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE)))
  2970. {
  2971. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Unable to enable scissor rendering state; " + getErrorDescription(hr),
  2972. "D3D9RenderSystem::setScissorTest");
  2973. }
  2974. RECT rect;
  2975. rect.left = static_cast<LONG>(left);
  2976. rect.top = static_cast<LONG>(top);
  2977. rect.bottom = static_cast<LONG>(bottom);
  2978. rect.right = static_cast<LONG>(right);
  2979. if (FAILED(hr = getActiveD3D9Device()->SetScissorRect(&rect)))
  2980. {
  2981. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Unable to set scissor rectangle; " + getErrorDescription(hr),
  2982. "D3D9RenderSystem::setScissorTest");
  2983. }
  2984. }
  2985. else
  2986. {
  2987. if (FAILED(hr = __SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE)))
  2988. {
  2989. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Unable to disable scissor rendering state; " + getErrorDescription(hr),
  2990. "D3D9RenderSystem::setScissorTest");
  2991. }
  2992. }
  2993. }
  2994. //---------------------------------------------------------------------
  2995. void D3D9RenderSystem::clearFrameBuffer(unsigned int buffers,
  2996. const ColourValue& colour, Real depth, unsigned short stencil)
  2997. {
  2998. DWORD flags = 0;
  2999. if (buffers & FBT_COLOUR)
  3000. {
  3001. flags |= D3DCLEAR_TARGET;
  3002. }
  3003. if (buffers & FBT_DEPTH)
  3004. {
  3005. flags |= D3DCLEAR_ZBUFFER;
  3006. }
  3007. // Only try to clear the stencil buffer if supported
  3008. if (buffers & FBT_STENCIL && mCurrentCapabilities->hasCapability(RSC_HWSTENCIL))
  3009. {
  3010. flags |= D3DCLEAR_STENCIL;
  3011. }
  3012. HRESULT hr;
  3013. if( FAILED( hr = getActiveD3D9Device()->Clear(
  3014. 0,
  3015. NULL,
  3016. flags,
  3017. colour.getAsARGB(),
  3018. depth,
  3019. stencil ) ) )
  3020. {
  3021. String msg = DXGetErrorDescription(hr);
  3022. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error clearing frame buffer : "
  3023. + msg, "D3D9RenderSystem::clearFrameBuffer" );
  3024. }
  3025. }
  3026. //---------------------------------------------------------------------
  3027. void D3D9RenderSystem::_makeProjectionMatrix(Real left, Real right,
  3028. Real bottom, Real top, Real nearPlane, Real farPlane, Matrix4& dest,
  3029. bool forGpuProgram)
  3030. {
  3031. // Correct position for off-axis projection matrix
  3032. if (!forGpuProgram)
  3033. {
  3034. Real offsetX = left + right;
  3035. Real offsetY = top + bottom;
  3036. left -= offsetX;
  3037. right -= offsetX;
  3038. top -= offsetY;
  3039. bottom -= offsetY;
  3040. }
  3041. Real width = right - left;
  3042. Real height = top - bottom;
  3043. Real q, qn;
  3044. if (farPlane == 0)
  3045. {
  3046. q = 1 - Frustum::INFINITE_FAR_PLANE_ADJUST;
  3047. qn = nearPlane * (Frustum::INFINITE_FAR_PLANE_ADJUST - 1);
  3048. }
  3049. else
  3050. {
  3051. q = farPlane / ( farPlane - nearPlane );
  3052. qn = -q * nearPlane;
  3053. }
  3054. dest = Matrix4::ZERO;
  3055. dest[0][0] = 2 * nearPlane / width;
  3056. dest[0][2] = (right+left) / width;
  3057. dest[1][1] = 2 * nearPlane / height;
  3058. dest[1][2] = (top+bottom) / height;
  3059. if (forGpuProgram)
  3060. {
  3061. dest[2][2] = -q;
  3062. dest[3][2] = -1.0f;
  3063. }
  3064. else
  3065. {
  3066. dest[2][2] = q;
  3067. dest[3][2] = 1.0f;
  3068. }
  3069. dest[2][3] = qn;
  3070. }
  3071. // ------------------------------------------------------------------
  3072. void D3D9RenderSystem::setClipPlane (ushort index, Real A, Real B, Real C, Real D)
  3073. {
  3074. float plane[4] = { A, B, C, D };
  3075. getActiveD3D9Device()->SetClipPlane (index, plane);
  3076. }
  3077. // ------------------------------------------------------------------
  3078. void D3D9RenderSystem::enableClipPlane (ushort index, bool enable)
  3079. {
  3080. DWORD prev;
  3081. getActiveD3D9Device()->GetRenderState(D3DRS_CLIPPLANEENABLE, &prev);
  3082. __SetRenderState(D3DRS_CLIPPLANEENABLE, enable?
  3083. (prev | (1 << index)) : (prev & ~(1 << index)));
  3084. }
  3085. //---------------------------------------------------------------------
  3086. HardwareOcclusionQuery* D3D9RenderSystem::createHardwareOcclusionQuery()
  3087. {
  3088. D3D9HardwareOcclusionQuery* ret = new D3D9HardwareOcclusionQuery();
  3089. mHwOcclusionQueries.push_back(ret);
  3090. return ret;
  3091. }
  3092. //---------------------------------------------------------------------
  3093. Real D3D9RenderSystem::getHorizontalTexelOffset()
  3094. {
  3095. // D3D considers the origin to be in the center of a pixel
  3096. return -0.5f;
  3097. }
  3098. //---------------------------------------------------------------------
  3099. Real D3D9RenderSystem::getVerticalTexelOffset()
  3100. {
  3101. // D3D considers the origin to be in the center of a pixel
  3102. return -0.5f;
  3103. }
  3104. //---------------------------------------------------------------------
  3105. void D3D9RenderSystem::_applyObliqueDepthProjection(Matrix4& matrix, const Plane& plane,
  3106. bool forGpuProgram)
  3107. {
  3108. // Thanks to Eric Lenyel for posting this calculation at www.terathon.com
  3109. // Calculate the clip-space corner point opposite the clipping plane
  3110. // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
  3111. // transform it into camera space by multiplying it
  3112. // by the inverse of the projection matrix
  3113. /* generalised version
  3114. Vector4 q = matrix.inverse() *
  3115. Vector4(Math::Sign(plane.normal.x), Math::Sign(plane.normal.y), 1.0f, 1.0f);
  3116. */
  3117. Vector4 q;
  3118. q.x = Math::Sign(plane.normal.x) / matrix[0][0];
  3119. q.y = Math::Sign(plane.normal.y) / matrix[1][1];
  3120. q.z = 1.0F;
  3121. // flip the next bit from Lengyel since we're right-handed
  3122. if (forGpuProgram)
  3123. {
  3124. q.w = (1.0F - matrix[2][2]) / matrix[2][3];
  3125. }
  3126. else
  3127. {
  3128. q.w = (1.0F + matrix[2][2]) / matrix[2][3];
  3129. }
  3130. // Calculate the scaled plane vector
  3131. Vector4 clipPlane4d(plane.normal.x, plane.normal.y, plane.normal.z, plane.d);
  3132. Vector4 c = clipPlane4d * (1.0F / (clipPlane4d.dotProduct(q)));
  3133. // Replace the third row of the projection matrix
  3134. matrix[2][0] = c.x;
  3135. matrix[2][1] = c.y;
  3136. // flip the next bit from Lengyel since we're right-handed
  3137. if (forGpuProgram)
  3138. {
  3139. matrix[2][2] = c.z;
  3140. }
  3141. else
  3142. {
  3143. matrix[2][2] = -c.z;
  3144. }
  3145. matrix[2][3] = c.w;
  3146. }
  3147. //---------------------------------------------------------------------
  3148. Real D3D9RenderSystem::getMinimumDepthInputValue()
  3149. {
  3150. // Range [0.0f, 1.0f]
  3151. return 0.0f;
  3152. }
  3153. //---------------------------------------------------------------------
  3154. Real D3D9RenderSystem::getMaximumDepthInputValue()
  3155. {
  3156. // Range [0.0f, 1.0f]
  3157. // D3D inverts even identity view matrices, so maximum INPUT is -1.0
  3158. return -1.0f;
  3159. }
  3160. //---------------------------------------------------------------------
  3161. IDirect3D9* D3D9RenderSystem::getDirect3D9()
  3162. {
  3163. IDirect3D9* pDirect3D9 = msD3D9RenderSystem->mpD3D;
  3164. if (pDirect3D9 == NULL)
  3165. {
  3166. OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS,
  3167. "Direct3D9 interface is NULL !!!",
  3168. "D3D9RenderSystem::getDirect3D9" );
  3169. }
  3170. return pDirect3D9;
  3171. }
  3172. //---------------------------------------------------------------------
  3173. UINT D3D9RenderSystem::getResourceCreationDeviceCount()
  3174. {
  3175. D3D9ResourceCreationPolicy creationPolicy = msD3D9RenderSystem->mResourceManager->getCreationPolicy();
  3176. if (creationPolicy == RCP_CREATE_ON_ACTIVE_DEVICE)
  3177. {
  3178. return 1;
  3179. }
  3180. else if (creationPolicy == RCP_CREATE_ON_ALL_DEVICES)
  3181. {
  3182. return msD3D9RenderSystem->mDeviceManager->getDeviceCount();
  3183. }
  3184. OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS,
  3185. "Invalid resource creation policy !!!",
  3186. "D3D9RenderSystem::getResourceCreationDeviceCount" );
  3187. return 0;
  3188. }
  3189. //---------------------------------------------------------------------
  3190. IDirect3DDevice9* D3D9RenderSystem::getResourceCreationDevice(UINT index)
  3191. {
  3192. D3D9ResourceCreationPolicy creationPolicy = msD3D9RenderSystem->mResourceManager->getCreationPolicy();
  3193. IDirect3DDevice9* d3d9Device = NULL;
  3194. if (creationPolicy == RCP_CREATE_ON_ACTIVE_DEVICE)
  3195. {
  3196. d3d9Device = msD3D9RenderSystem->getActiveD3D9Device();
  3197. }
  3198. else if (creationPolicy == RCP_CREATE_ON_ALL_DEVICES)
  3199. {
  3200. d3d9Device = msD3D9RenderSystem->mDeviceManager->getDevice(index)->getD3D9Device();
  3201. }
  3202. else
  3203. {
  3204. OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS,
  3205. "Invalid resource creation policy !!!",
  3206. "D3D9RenderSystem::getResourceCreationDevice" );
  3207. }
  3208. return d3d9Device;
  3209. }
  3210. //---------------------------------------------------------------------
  3211. IDirect3DDevice9* D3D9RenderSystem::getActiveD3D9Device()
  3212. {
  3213. D3D9Device* activeDevice = msD3D9RenderSystem->mDeviceManager->getActiveDevice();
  3214. IDirect3DDevice9* d3d9Device;
  3215. d3d9Device = activeDevice->getD3D9Device();
  3216. if (d3d9Device == NULL)
  3217. {
  3218. OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS,
  3219. "Current d3d9 device is NULL !!!",
  3220. "D3D9RenderSystem::getActiveD3D9Device" );
  3221. }
  3222. return d3d9Device;
  3223. }
  3224. //---------------------------------------------------------------------
  3225. // Formats to try, in decreasing order of preference
  3226. D3DFORMAT ddDepthStencilFormats[]={
  3227. D3DFMT_D24FS8,
  3228. D3DFMT_D24S8,
  3229. D3DFMT_D24X4S4,
  3230. D3DFMT_D24X8,
  3231. D3DFMT_D15S1,
  3232. D3DFMT_D16,
  3233. D3DFMT_D32
  3234. };
  3235. #define NDSFORMATS (sizeof(ddDepthStencilFormats)/sizeof(D3DFORMAT))
  3236. D3DFORMAT D3D9RenderSystem::_getDepthStencilFormatFor(D3DFORMAT fmt)
  3237. {
  3238. /// Check if result is cached
  3239. DepthStencilHash::iterator i = mDepthStencilHash.find((unsigned int)fmt);
  3240. if(i != mDepthStencilHash.end())
  3241. return i->second;
  3242. /// If not, probe with CheckDepthStencilMatch
  3243. D3DFORMAT dsfmt = D3DFMT_UNKNOWN;
  3244. /// Get description of primary render target
  3245. D3D9Device* activeDevice = mDeviceManager->getActiveDevice();
  3246. IDirect3DSurface9* mSurface = activeDevice->getPrimaryWindow()->getRenderSurface();
  3247. D3DSURFACE_DESC srfDesc;
  3248. if(!FAILED(mSurface->GetDesc(&srfDesc)))
  3249. {
  3250. /// Probe all depth stencil formats
  3251. /// Break on first one that matches
  3252. for(size_t x=0; x<NDSFORMATS; ++x)
  3253. {
  3254. // Verify that the depth format exists
  3255. if (mpD3D->CheckDeviceFormat(
  3256. activeDevice->getAdapterNumber(),
  3257. activeDevice->getDeviceType(),
  3258. srfDesc.Format,
  3259. D3DUSAGE_DEPTHSTENCIL,
  3260. D3DRTYPE_SURFACE,
  3261. ddDepthStencilFormats[x]) != D3D_OK)
  3262. {
  3263. continue;
  3264. }
  3265. // Verify that the depth format is compatible
  3266. if(mpD3D->CheckDepthStencilMatch(
  3267. activeDevice->getAdapterNumber(),
  3268. activeDevice->getDeviceType(),
  3269. srfDesc.Format,
  3270. fmt, ddDepthStencilFormats[x]) == D3D_OK)
  3271. {
  3272. dsfmt = ddDepthStencilFormats[x];
  3273. break;
  3274. }
  3275. }
  3276. }
  3277. /// Cache result
  3278. mDepthStencilHash[(unsigned int)fmt] = dsfmt;
  3279. return dsfmt;
  3280. }
  3281. IDirect3DSurface9* D3D9RenderSystem::_getDepthStencilFor(D3DFORMAT fmt,
  3282. D3DMULTISAMPLE_TYPE multisample, DWORD multisample_quality, size_t width, size_t height)
  3283. {
  3284. D3DFORMAT dsfmt = _getDepthStencilFormatFor(fmt);
  3285. if(dsfmt == D3DFMT_UNKNOWN)
  3286. return 0;
  3287. IDirect3DSurface9 *surface = 0;
  3288. /// Check if result is cached
  3289. ZBufferIdentifier zBufferIdentifer;
  3290. zBufferIdentifer.format = dsfmt;
  3291. zBufferIdentifer.multisampleType = multisample;
  3292. zBufferIdentifer.device = getActiveD3D9Device();
  3293. ZBufferRefQueue& zBuffers = mZBufferHash[zBufferIdentifer];
  3294. if(!zBuffers.empty())
  3295. {
  3296. const ZBufferRef& zBuffer = zBuffers.front();
  3297. /// Check if size is larger or equal
  3298. if(zBuffer.width >= width && zBuffer.height >= height)
  3299. {
  3300. surface = zBuffer.surface;
  3301. }
  3302. else
  3303. {
  3304. /// If not, destroy current buffer
  3305. zBuffer.surface->Release();
  3306. zBuffers.pop_front();
  3307. }
  3308. }
  3309. if(!surface)
  3310. {
  3311. /// If not, create the depthstencil surface
  3312. HRESULT hr = getActiveD3D9Device()->CreateDepthStencilSurface(
  3313. static_cast<UINT>(width),
  3314. static_cast<UINT>(height),
  3315. dsfmt,
  3316. multisample,
  3317. multisample_quality,
  3318. TRUE, // discard true or false?
  3319. &surface,
  3320. NULL);
  3321. if(FAILED(hr))
  3322. {
  3323. String msg = DXGetErrorDescription(hr);
  3324. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Error CreateDepthStencilSurface : " + msg, "D3D9RenderSystem::_getDepthStencilFor" );
  3325. }
  3326. /// And cache it
  3327. ZBufferRef zb;
  3328. zb.surface = surface;
  3329. zb.width = width;
  3330. zb.height = height;
  3331. zBuffers.push_front(zb);
  3332. }
  3333. return surface;
  3334. }
  3335. //---------------------------------------------------------------------
  3336. void D3D9RenderSystem::_cleanupDepthStencils(IDirect3DDevice9* d3d9Device)
  3337. {
  3338. for(ZBufferHash::iterator i = mZBufferHash.begin(); i != mZBufferHash.end();)
  3339. {
  3340. /// Release buffer
  3341. if (i->first.device == d3d9Device)
  3342. {
  3343. while (!i->second.empty())
  3344. {
  3345. IDirect3DSurface9* surface = i->second.front().surface;
  3346. surface->Release();
  3347. i->second.pop_front();
  3348. }
  3349. ZBufferHash::iterator deadi = i++;
  3350. mZBufferHash.erase(deadi);
  3351. }
  3352. else
  3353. {
  3354. ++i;
  3355. }
  3356. }
  3357. }
  3358. //---------------------------------------------------------------------
  3359. void D3D9RenderSystem::registerThread()
  3360. {
  3361. // nothing to do - D3D9 shares rendering context already
  3362. }
  3363. //---------------------------------------------------------------------
  3364. void D3D9RenderSystem::unregisterThread()
  3365. {
  3366. // nothing to do - D3D9 shares rendering context already
  3367. }
  3368. //---------------------------------------------------------------------
  3369. void D3D9RenderSystem::preExtraThreadsStarted()
  3370. {
  3371. // nothing to do - D3D9 shares rendering context already
  3372. }
  3373. //---------------------------------------------------------------------
  3374. void D3D9RenderSystem::postExtraThreadsStarted()
  3375. {
  3376. // nothing to do - D3D9 shares rendering context already
  3377. }
  3378. //---------------------------------------------------------------------
  3379. D3D9ResourceManager* D3D9RenderSystem::getResourceManager()
  3380. {
  3381. return msD3D9RenderSystem->mResourceManager;
  3382. }
  3383. //---------------------------------------------------------------------
  3384. D3D9DeviceManager* D3D9RenderSystem::getDeviceManager()
  3385. {
  3386. return msD3D9RenderSystem->mDeviceManager;
  3387. }
  3388. //---------------------------------------------------------------------
  3389. RenderSystemCapabilities* D3D9RenderSystem::createRenderSystemCapabilities() const
  3390. {
  3391. return mRealCapabilities;
  3392. }
  3393. //---------------------------------------------------------------------
  3394. unsigned int D3D9RenderSystem::getDisplayMonitorCount() const
  3395. {
  3396. return mpD3D->GetAdapterCount();
  3397. }
  3398. //---------------------------------------------------------------------
  3399. void D3D9RenderSystem::notifyOnDeviceLost(D3D9Device* device)
  3400. {
  3401. // you need to stop the physics or game engines after this event
  3402. fireEvent("DeviceLost");
  3403. }
  3404. //---------------------------------------------------------------------
  3405. void D3D9RenderSystem::notifyOnDeviceReset(D3D9Device* device)
  3406. {
  3407. // Reset state attributes.
  3408. mVertexProgramBound = false;
  3409. mFragmentProgramBound = false;
  3410. mLastVertexSourceCount = 0;
  3411. // Restore previous active device.
  3412. // Invalidate active view port.
  3413. mActiveViewport = NULL;
  3414. // Reset the texture stages, they will need to be rebound
  3415. for (size_t i = 0; i < OGRE_MAX_TEXTURE_LAYERS; ++i)
  3416. _setTexture(i, false, TexturePtr());
  3417. fireEvent("DeviceRestored");
  3418. }
  3419. //---------------------------------------------------------------------
  3420. bool D3D9RenderSystem::ZBufferIdentifierComparator::operator()( const ZBufferIdentifier& z0, const ZBufferIdentifier& z1 ) const
  3421. {
  3422. if (z0.device < z1.device)
  3423. return true;
  3424. if (z0.device == z1.device)
  3425. {
  3426. if (z0.format < z1.format)
  3427. return true;
  3428. if (z0.format == z1.format)
  3429. {
  3430. if (z0.multisampleType < z1.multisampleType)
  3431. return true;
  3432. }
  3433. }
  3434. return false;
  3435. }
  3436. //---------------------------------------------------------------------
  3437. void D3D9RenderSystem::determineFSAASettings(IDirect3DDevice9* d3d9Device,
  3438. size_t fsaa, const String& fsaaHint, D3DFORMAT d3dPixelFormat,
  3439. bool fullScreen, D3DMULTISAMPLE_TYPE *outMultisampleType, DWORD *outMultisampleQuality)
  3440. {
  3441. bool ok = false;
  3442. bool qualityHint = fsaaHint.find("Quality") != String::npos;
  3443. size_t origFSAA = fsaa;
  3444. D3D9DriverList* driverList = getDirect3DDrivers();
  3445. D3D9Driver* deviceDriver = mActiveD3DDriver;
  3446. D3D9Device* device = mDeviceManager->getDeviceFromD3D9Device(d3d9Device);
  3447. for (uint i = 0; i < driverList->count(); ++i)
  3448. {
  3449. D3D9Driver* currDriver = driverList->item(i);
  3450. if (currDriver->getAdapterNumber() == device->getAdapterNumber())
  3451. {
  3452. deviceDriver = currDriver;
  3453. break;
  3454. }
  3455. }
  3456. bool tryCSAA = false;
  3457. // NVIDIA, prefer CSAA if available for 8+
  3458. // it would be tempting to use getCapabilities()->getVendor() == GPU_NVIDIA but
  3459. // if this is the first window, caps will not be initialised yet
  3460. if (deviceDriver->getAdapterIdentifier().VendorId == 0x10DE &&
  3461. fsaa >= 8)
  3462. {
  3463. tryCSAA = true;
  3464. }
  3465. while (!ok)
  3466. {
  3467. // Deal with special cases
  3468. if (tryCSAA)
  3469. {
  3470. // see http://developer.nvidia.com/object/coverage-sampled-aa.html
  3471. switch(fsaa)
  3472. {
  3473. case 8:
  3474. if (qualityHint)
  3475. {
  3476. *outMultisampleType = D3DMULTISAMPLE_8_SAMPLES;
  3477. *outMultisampleQuality = 0;
  3478. }
  3479. else
  3480. {
  3481. *outMultisampleType = D3DMULTISAMPLE_4_SAMPLES;
  3482. *outMultisampleQuality = 2;
  3483. }
  3484. break;
  3485. case 16:
  3486. if (qualityHint)
  3487. {
  3488. *outMultisampleType = D3DMULTISAMPLE_8_SAMPLES;
  3489. *outMultisampleQuality = 2;
  3490. }
  3491. else
  3492. {
  3493. *outMultisampleType = D3DMULTISAMPLE_4_SAMPLES;
  3494. *outMultisampleQuality = 4;
  3495. }
  3496. break;
  3497. }
  3498. }
  3499. else // !CSAA
  3500. {
  3501. *outMultisampleType = (D3DMULTISAMPLE_TYPE)fsaa;
  3502. *outMultisampleQuality = 0;
  3503. }
  3504. HRESULT hr;
  3505. DWORD outQuality;
  3506. hr = mpD3D->CheckDeviceMultiSampleType(
  3507. deviceDriver->getAdapterNumber(),
  3508. D3DDEVTYPE_HAL,
  3509. d3dPixelFormat,
  3510. fullScreen,
  3511. *outMultisampleType,
  3512. &outQuality);
  3513. if (SUCCEEDED(hr) &&
  3514. (!tryCSAA || outQuality > *outMultisampleQuality))
  3515. {
  3516. ok = true;
  3517. }
  3518. else
  3519. {
  3520. // downgrade
  3521. if (tryCSAA && fsaa == 8)
  3522. {
  3523. // for CSAA, we'll try downgrading with quality mode at all samples.
  3524. // then try without quality, then drop CSAA
  3525. if (qualityHint)
  3526. {
  3527. // drop quality first
  3528. qualityHint = false;
  3529. }
  3530. else
  3531. {
  3532. // drop CSAA entirely
  3533. tryCSAA = false;
  3534. }
  3535. // return to original requested samples
  3536. fsaa = origFSAA;
  3537. }
  3538. else
  3539. {
  3540. // drop samples
  3541. --fsaa;
  3542. if (fsaa == 1)
  3543. {
  3544. // ran out of options, no FSAA
  3545. fsaa = 0;
  3546. ok = true;
  3547. }
  3548. }
  3549. }
  3550. } // while !ok
  3551. }
  3552. }