CmD3D9RenderSystem.cpp 85 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622
  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 "CmD3D9RenderSystem.h"
  25. #include "CmD3D9Prerequisites.h"
  26. #include "CmD3D9DriverList.h"
  27. #include "CmD3D9Driver.h"
  28. #include "CmD3D9VideoModeList.h"
  29. #include "CmD3D9VideoMode.h"
  30. #include "CmD3D9RenderWindow.h"
  31. #include "CmD3D9TextureManager.h"
  32. #include "CmD3D9Texture.h"
  33. #include "CmMath.h"
  34. #include "CmD3D9HardwareBufferManager.h"
  35. #include "CmD3D9IndexBuffer.h"
  36. #include "CmD3D9VertexBuffer.h"
  37. #include "CmD3D9VertexDeclaration.h"
  38. #include "CmD3D9GpuProgram.h"
  39. #include "CmD3D9GpuProgramManager.h"
  40. #include "CmD3D9HLSLProgramFactory.h"
  41. #include "CmD3D9OcclusionQuery.h"
  42. #include "CmD3D9DeviceManager.h"
  43. #include "CmD3D9ResourceManager.h"
  44. #include "CmD3D9RenderWindowManager.h"
  45. #include "CmHighLevelGpuProgramManager.h"
  46. #include "CmRenderStateManager.h"
  47. #include "CmAsyncOp.h"
  48. #include "CmBlendState.h"
  49. #include "CmRasterizerState.h"
  50. #include "CmDepthStencilState.h"
  51. #include "CmGpuParams.h"
  52. #include "CmGpuParamDesc.h"
  53. #include "CmGpuParamBlockBuffer.h"
  54. #include "CmCoreThread.h"
  55. #include "CmDebug.h"
  56. #define FLOAT2DWORD(f) *((DWORD*)&f)
  57. // Formats to try, in decreasing order of preference
  58. D3DFORMAT ddDepthStencilFormats[]={
  59. D3DFMT_D24FS8,
  60. D3DFMT_D24S8,
  61. D3DFMT_D24X4S4,
  62. D3DFMT_D24X8,
  63. D3DFMT_D15S1,
  64. D3DFMT_D16,
  65. D3DFMT_D32
  66. };
  67. #define NDSFORMATS (sizeof(ddDepthStencilFormats)/sizeof(D3DFORMAT))
  68. namespace CamelotFramework
  69. {
  70. D3D9RenderSystem* D3D9RenderSystem::msD3D9RenderSystem = NULL;
  71. /************************************************************************/
  72. /* PUBLIC INTERFACE */
  73. /************************************************************************/
  74. //---------------------------------------------------------------------
  75. D3D9RenderSystem::D3D9RenderSystem( HINSTANCE hInstance )
  76. : mTexStageDesc(nullptr)
  77. , mNumTexStages(0)
  78. , mCurrentDrawOperation(DOT_TRIANGLE_LIST)
  79. , mViewportLeft(0), mViewportTop(0), mViewportWidth(0), mViewportHeight(0)
  80. {
  81. // update singleton access pointer.
  82. msD3D9RenderSystem = this;
  83. // set the instance being passed
  84. mhInstance = hInstance;
  85. // set pointers to NULL
  86. mpD3D = NULL;
  87. mDriverList = NULL;
  88. mActiveD3DDriver = NULL;
  89. mUseNVPerfHUD = false;
  90. mHLSLProgramFactory = NULL;
  91. mCgProgramFactory = NULL;
  92. mDeviceManager = NULL;
  93. mResourceManager = nullptr;
  94. mScissorRect.left = 0;
  95. mScissorRect.right = 1280;
  96. mScissorRect.top = 0;
  97. mScissorRect.bottom = 720;
  98. }
  99. //---------------------------------------------------------------------
  100. D3D9RenderSystem::~D3D9RenderSystem()
  101. {
  102. // This needs to be called from the child class, since destroy_internal is virtual
  103. gCoreThread().queueCommand(boost::bind(&D3D9RenderSystem::destroy_internal, this), true);
  104. }
  105. const String& D3D9RenderSystem::getName() const
  106. {
  107. static String strName( "D3D9RenderSystem");
  108. return strName;
  109. }
  110. const String& D3D9RenderSystem::getShadingLanguageName() const
  111. {
  112. static String strName("hlsl");
  113. return strName;
  114. }
  115. void D3D9RenderSystem::initialize_internal(AsyncOp& asyncOp)
  116. {
  117. THROW_IF_NOT_CORE_THREAD;
  118. // Create the resource manager.
  119. mResourceManager = cm_new<D3D9ResourceManager>();
  120. // Create our Direct3D object
  121. if( NULL == (mpD3D = Direct3DCreate9(D3D_SDK_VERSION)) )
  122. CM_EXCEPT(InternalErrorException, "Failed to create Direct3D9 object");
  123. RenderWindow* autoWindow = NULL;
  124. // Init using current settings
  125. mActiveD3DDriver = getDirect3DDrivers()->item(0); // TODO - We always use the first driver
  126. if( !mActiveD3DDriver )
  127. CM_EXCEPT(InvalidParametersException, "Problems finding requested Direct3D driver!" );
  128. // get driver version
  129. mDriverVersion.major = HIWORD(mActiveD3DDriver->getAdapterIdentifier().DriverVersion.HighPart);
  130. mDriverVersion.minor = LOWORD(mActiveD3DDriver->getAdapterIdentifier().DriverVersion.HighPart);
  131. mDriverVersion.release = HIWORD(mActiveD3DDriver->getAdapterIdentifier().DriverVersion.LowPart);
  132. mDriverVersion.build = LOWORD(mActiveD3DDriver->getAdapterIdentifier().DriverVersion.LowPart);
  133. // Create the device manager.
  134. mDeviceManager = cm_new<D3D9DeviceManager>();
  135. // Also create hardware buffer manager
  136. HardwareBufferManager::startUp(cm_new<D3D9HardwareBufferManager>());
  137. // Create the GPU program manager
  138. GpuProgramManager::startUp(cm_new<D3D9GpuProgramManager>());
  139. // Create & register HLSL factory
  140. mHLSLProgramFactory = cm_new<D3D9HLSLProgramFactory>();
  141. // Create & register Cg factory
  142. mCgProgramFactory = cm_new<CgProgramFactory>();
  143. // Create render window manager
  144. RenderWindowManager::startUp(cm_new<D3D9RenderWindowManager>(this));
  145. // Create render state manager
  146. RenderStateManager::startUp(cm_new<RenderStateManager>());
  147. // Create primary window and finalize initialization
  148. RenderWindowPtr primaryWindow = RenderWindow::create(mPrimaryWindowDesc);
  149. D3D9RenderWindow* d3d9renderWindow = static_cast<D3D9RenderWindow*>(primaryWindow.get());
  150. updateRenderSystemCapabilities(d3d9renderWindow);
  151. // Create the texture manager for use by others
  152. TextureManager::startUp(cm_new<D3D9TextureManager>());
  153. // call superclass method
  154. RenderSystem::initialize_internal(asyncOp);
  155. asyncOp.completeOperation(primaryWindow);
  156. }
  157. //---------------------------------------------------------------------
  158. void D3D9RenderSystem::destroy_internal()
  159. {
  160. if(mTexStageDesc != nullptr)
  161. {
  162. cm_deleteN(mTexStageDesc, mNumTexStages);
  163. mTexStageDesc = nullptr;
  164. }
  165. RenderSystem::destroy_internal();
  166. if(mDeviceManager != nullptr)
  167. {
  168. cm_delete(mDeviceManager);
  169. mDeviceManager = nullptr;
  170. }
  171. if(mDriverList != nullptr)
  172. {
  173. cm_delete(mDriverList);
  174. mDriverList = nullptr;
  175. }
  176. mActiveD3DDriver = NULL;
  177. TextureManager::shutDown();
  178. HardwareBufferManager::shutDown();
  179. GpuProgramManager::shutDown();
  180. RenderWindowManager::shutDown();
  181. RenderStateManager::shutDown();
  182. // Deleting the HLSL program factory
  183. if (mHLSLProgramFactory)
  184. {
  185. HighLevelGpuProgramManager::instance().removeFactory(mHLSLProgramFactory);
  186. cm_delete(mHLSLProgramFactory);
  187. mHLSLProgramFactory = 0;
  188. }
  189. if(mCgProgramFactory)
  190. {
  191. HighLevelGpuProgramManager::instance().removeFactory(mCgProgramFactory);
  192. cm_delete(mCgProgramFactory);
  193. mCgProgramFactory = 0;
  194. }
  195. SAFE_RELEASE( mpD3D );
  196. if(mResourceManager != nullptr)
  197. {
  198. cm_delete(mResourceManager);
  199. mResourceManager = nullptr;
  200. }
  201. msD3D9RenderSystem = NULL;
  202. }
  203. //--------------------------------------------------------------------
  204. void D3D9RenderSystem::registerWindow(RenderWindow& renderWindow)
  205. {
  206. THROW_IF_NOT_CORE_THREAD;
  207. D3D9RenderWindow* d3d9renderWindow = static_cast<D3D9RenderWindow*>(&renderWindow);
  208. String msg;
  209. mResourceManager->lockDeviceAccess();
  210. try
  211. {
  212. mDeviceManager->linkRenderWindow(d3d9renderWindow);
  213. }
  214. catch (const CamelotFramework::RenderingAPIException&)
  215. {
  216. // after catching the exception, clean up
  217. mResourceManager->unlockDeviceAccess();
  218. // re-throw
  219. throw;
  220. }
  221. mResourceManager->unlockDeviceAccess();
  222. }
  223. void D3D9RenderSystem::bindGpuProgram(HGpuProgram prg)
  224. {
  225. THROW_IF_NOT_CORE_THREAD;
  226. if(!prg.isLoaded())
  227. return;
  228. GpuProgramPtr bindingPrg = prg->getBindingDelegate();
  229. HRESULT hr;
  230. switch (bindingPrg->getType())
  231. {
  232. case GPT_VERTEX_PROGRAM:
  233. hr = getActiveD3D9Device()->SetVertexShader(
  234. static_cast<D3D9GpuVertexProgram*>(bindingPrg.get())->getVertexShader());
  235. if (FAILED(hr))
  236. {
  237. CM_EXCEPT(RenderingAPIException, "Error calling SetVertexShader");
  238. }
  239. break;
  240. case GPT_FRAGMENT_PROGRAM:
  241. hr = getActiveD3D9Device()->SetPixelShader(
  242. static_cast<D3D9GpuFragmentProgram*>(bindingPrg.get())->getPixelShader());
  243. if (FAILED(hr))
  244. {
  245. CM_EXCEPT(RenderingAPIException, "Error calling SetPixelShader");
  246. }
  247. break;
  248. };
  249. // Make sure texcoord index is equal to stage value, As SDK Doc suggests:
  250. // "When rendering using vertex shaders, each stage's texture coordinate index must be set to its default value."
  251. // This solves such an errors when working with the Debug runtime -
  252. // "Direct3D9: (ERROR) :Stage 1 - Texture coordinate index in the stage must be equal to the stage index when programmable vertex pipeline is used".
  253. for (unsigned int nStage=0; nStage < 8; ++nStage)
  254. __SetTextureStageState(nStage, D3DTSS_TEXCOORDINDEX, nStage);
  255. RenderSystem::bindGpuProgram(prg);
  256. }
  257. void D3D9RenderSystem::unbindGpuProgram(GpuProgramType gptype)
  258. {
  259. THROW_IF_NOT_CORE_THREAD;
  260. HRESULT hr;
  261. switch(gptype)
  262. {
  263. case GPT_VERTEX_PROGRAM:
  264. hr = getActiveD3D9Device()->SetVertexShader(NULL);
  265. if (FAILED(hr))
  266. {
  267. CM_EXCEPT(RenderingAPIException, "Error resetting SetVertexShader to NULL");
  268. }
  269. break;
  270. case GPT_FRAGMENT_PROGRAM:
  271. hr = getActiveD3D9Device()->SetPixelShader(NULL);
  272. if (FAILED(hr))
  273. {
  274. CM_EXCEPT(RenderingAPIException, "Error resetting SetPixelShader to NULL");
  275. }
  276. break;
  277. };
  278. RenderSystem::unbindGpuProgram(gptype);
  279. }
  280. //---------------------------------------------------------------------
  281. void D3D9RenderSystem::bindGpuParams(GpuProgramType gptype, BindableGpuParams& bindableParams)
  282. {
  283. THROW_IF_NOT_CORE_THREAD;
  284. GpuParams& params = bindableParams.getParams();
  285. params.updateHardwareBuffers();
  286. const GpuParamDesc& paramDesc = params.getParamDesc();
  287. for(auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
  288. {
  289. HSamplerState& samplerState = params.getSamplerState(iter->second.slot);
  290. if(samplerState == nullptr)
  291. setSamplerState(gptype, iter->second.slot, SamplerState::getDefault());
  292. else
  293. setSamplerState(gptype, iter->second.slot, samplerState.getInternalPtr());
  294. }
  295. for(auto iter = paramDesc.textures.begin(); iter != paramDesc.textures.end(); ++iter)
  296. {
  297. HTexture texture = params.getTexture(iter->second.slot);
  298. if(!texture.isLoaded())
  299. setTexture(gptype, iter->second.slot, false, nullptr);
  300. else
  301. setTexture(gptype, iter->second.slot, true, texture.getInternalPtr());
  302. }
  303. // Read all the buffer data so we can assign it. Not the most efficient way of accessing data
  304. // but it is required in order to have standardized buffer interface.
  305. UnorderedMap<UINT32, UINT8*>::type bufferData;
  306. for(auto& curParam : paramDesc.params)
  307. {
  308. UINT32 paramBlockSlot = curParam.second.paramBlockSlot;
  309. auto iterFind = bufferData.find(paramBlockSlot);
  310. if(iterFind == bufferData.end())
  311. {
  312. GpuParamBlockBufferPtr paramBlock = params.getParamBlockBuffer(paramBlockSlot);
  313. UINT8* data = (UINT8*)cm_alloc<ScratchAlloc>(paramBlock->getSize());
  314. paramBlock->readData(data);
  315. bufferData[paramBlockSlot] = data;
  316. }
  317. }
  318. HRESULT hr;
  319. switch(gptype)
  320. {
  321. case GPT_VERTEX_PROGRAM:
  322. {
  323. for(auto iter = paramDesc.params.begin(); iter != paramDesc.params.end(); ++iter)
  324. {
  325. const GpuParamDataDesc& paramDesc = iter->second;
  326. const UINT8* ptrData = bufferData[paramDesc.paramBlockSlot] + paramDesc.cpuMemOffset * sizeof(UINT32);
  327. switch(paramDesc.type)
  328. {
  329. case GPDT_FLOAT1:
  330. case GPDT_FLOAT2:
  331. case GPDT_FLOAT3:
  332. case GPDT_FLOAT4:
  333. case GPDT_MATRIX_2X2:
  334. case GPDT_MATRIX_2X3:
  335. case GPDT_MATRIX_2X4:
  336. case GPDT_MATRIX_3X2:
  337. case GPDT_MATRIX_3X3:
  338. case GPDT_MATRIX_3X4:
  339. case GPDT_MATRIX_4X2:
  340. case GPDT_MATRIX_4X3:
  341. case GPDT_MATRIX_4X4:
  342. {
  343. UINT32 slotCount = (paramDesc.elementSize / 4) * paramDesc.arraySize;
  344. assert (paramDesc.elementSize % 4 == 0 && "Should not have any elements less than 4 wide for D3D9");
  345. if (FAILED(hr = getActiveD3D9Device()->SetVertexShaderConstantF(paramDesc.gpuMemOffset, (const float*)ptrData, slotCount)))
  346. CM_EXCEPT(RenderingAPIException, "Unable to upload vertex shader float parameters.");
  347. break;
  348. }
  349. case GPDT_INT1:
  350. case GPDT_INT2:
  351. case GPDT_INT3:
  352. case GPDT_INT4:
  353. {
  354. UINT32 slotCount = (paramDesc.elementSize / 4) * paramDesc.arraySize;
  355. assert (paramDesc.elementSize % 4 == 0 && "Should not have any elements less than 4 wide for D3D9");
  356. if (FAILED(hr = getActiveD3D9Device()->SetVertexShaderConstantI(paramDesc.gpuMemOffset, (const INT32*)ptrData, slotCount)))
  357. CM_EXCEPT(RenderingAPIException, "Unable to upload vertex shader int parameters.");
  358. break;
  359. }
  360. case GPDT_BOOL:
  361. if (FAILED(hr = getActiveD3D9Device()->SetVertexShaderConstantB(paramDesc.gpuMemOffset, (const BOOL*)ptrData, paramDesc.arraySize)))
  362. CM_EXCEPT(RenderingAPIException, "Unable to upload vertex shader bool parameters.");
  363. break;
  364. }
  365. }
  366. }
  367. break;
  368. case GPT_FRAGMENT_PROGRAM:
  369. {
  370. for(auto iter = paramDesc.params.begin(); iter != paramDesc.params.end(); ++iter)
  371. {
  372. const GpuParamDataDesc& paramDesc = iter->second;
  373. const UINT8* ptrData = bufferData[paramDesc.paramBlockSlot] + paramDesc.cpuMemOffset * sizeof(UINT32);
  374. switch(paramDesc.type)
  375. {
  376. case GPDT_FLOAT1:
  377. case GPDT_FLOAT2:
  378. case GPDT_FLOAT3:
  379. case GPDT_FLOAT4:
  380. case GPDT_MATRIX_2X2:
  381. case GPDT_MATRIX_2X3:
  382. case GPDT_MATRIX_2X4:
  383. case GPDT_MATRIX_3X2:
  384. case GPDT_MATRIX_3X3:
  385. case GPDT_MATRIX_3X4:
  386. case GPDT_MATRIX_4X2:
  387. case GPDT_MATRIX_4X3:
  388. case GPDT_MATRIX_4X4:
  389. {
  390. UINT32 slotCount = (paramDesc.elementSize / 4) * paramDesc.arraySize;
  391. assert (paramDesc.elementSize % 4 == 0 && "Should not have any elements less than 4 wide for D3D9");
  392. if (FAILED(hr = getActiveD3D9Device()->SetPixelShaderConstantF(paramDesc.gpuMemOffset, (const float*)ptrData, slotCount)))
  393. CM_EXCEPT(RenderingAPIException, "Unable to upload pixel shader float parameters.");
  394. break;
  395. }
  396. case GPDT_INT1:
  397. case GPDT_INT2:
  398. case GPDT_INT3:
  399. case GPDT_INT4:
  400. {
  401. UINT32 slotCount = (paramDesc.elementSize / 4) * paramDesc.arraySize;
  402. assert (paramDesc.elementSize % 4 == 0 && "Should not have any elements less than 4 wide for D3D9");
  403. if (FAILED(hr = getActiveD3D9Device()->SetPixelShaderConstantI(paramDesc.gpuMemOffset, (const INT32*)ptrData, slotCount)))
  404. CM_EXCEPT(RenderingAPIException, "Unable to upload pixel shader int parameters.");
  405. break;
  406. }
  407. case GPDT_BOOL:
  408. if (FAILED(hr = getActiveD3D9Device()->SetPixelShaderConstantB(paramDesc.gpuMemOffset, (const BOOL*)ptrData, paramDesc.arraySize)))
  409. CM_EXCEPT(RenderingAPIException, "Unable to upload pixel shader bool parameters.");
  410. break;
  411. }
  412. }
  413. }
  414. break;
  415. };
  416. for(auto& curBufferData : bufferData)
  417. {
  418. cm_free<ScratchAlloc>(curBufferData.second);
  419. }
  420. }
  421. //---------------------------------------------------------------------
  422. void D3D9RenderSystem::setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr& tex)
  423. {
  424. THROW_IF_NOT_CORE_THREAD;
  425. if(!tex->isBindableAsShaderResource())
  426. CM_EXCEPT(InvalidParametersException, "Texture you have specified cannot be bound to a shader.");
  427. if(gptype != GPT_FRAGMENT_PROGRAM && gptype != GPT_VERTEX_PROGRAM)
  428. {
  429. LOGWRN("D3D9 cannot assign textures to this gpu program type: " + toString(gptype));
  430. return;
  431. }
  432. if(gptype == GPT_VERTEX_PROGRAM)
  433. {
  434. unit = D3DVERTEXTEXTURESAMPLER0 + unit; // Vertex stage uses special samplers
  435. }
  436. HRESULT hr;
  437. D3D9TexturePtr dt = std::static_pointer_cast<D3D9Texture>(tex);
  438. if (enabled && (dt != nullptr))
  439. {
  440. IDirect3DBaseTexture9 *pTex = dt->getTexture_internal();
  441. if (mTexStageDesc[unit].pTex != pTex)
  442. {
  443. hr = getActiveD3D9Device()->SetTexture(static_cast<DWORD>(unit), pTex);
  444. if( hr != S_OK )
  445. {
  446. String str = "Unable to set texture in D3D9";
  447. CM_EXCEPT(RenderingAPIException, str);
  448. }
  449. // set stage desc.
  450. mTexStageDesc[unit].pTex = pTex;
  451. mTexStageDesc[unit].texType = D3D9Mappings::get(dt->getTextureType());
  452. // Set gamma now too
  453. if (dt->isHardwareGammaReadToBeUsed())
  454. {
  455. __SetSamplerState(static_cast<DWORD>(unit), D3DSAMP_SRGBTEXTURE, TRUE);
  456. }
  457. else
  458. {
  459. __SetSamplerState(static_cast<DWORD>(unit), D3DSAMP_SRGBTEXTURE, FALSE);
  460. }
  461. }
  462. }
  463. else
  464. {
  465. if (mTexStageDesc[unit].pTex != 0)
  466. {
  467. hr = getActiveD3D9Device()->SetTexture(static_cast<DWORD>(unit), 0);
  468. if( hr != S_OK )
  469. {
  470. String str = "Unable to disable texture '" + toString(unit) + "' in D3D9";
  471. CM_EXCEPT(RenderingAPIException, str);
  472. }
  473. }
  474. hr = __SetTextureStageState(static_cast<DWORD>(unit), D3DTSS_COLOROP, D3DTOP_DISABLE);
  475. if( hr != S_OK )
  476. {
  477. String str = "Unable to disable texture '" + toString(unit) + "' in D3D9";
  478. CM_EXCEPT(RenderingAPIException, str);
  479. }
  480. // set stage desc. to defaults
  481. mTexStageDesc[unit].pTex = 0;
  482. mTexStageDesc[unit].coordIndex = 0;
  483. mTexStageDesc[unit].texType = D3D9Mappings::D3D_TEX_TYPE_NORMAL;
  484. }
  485. }
  486. //-----------------------------------------------------------------------
  487. void D3D9RenderSystem::setSamplerState(GpuProgramType gptype, UINT16 unit, const SamplerStatePtr& state)
  488. {
  489. THROW_IF_NOT_CORE_THREAD;
  490. if(gptype != GPT_FRAGMENT_PROGRAM && gptype != GPT_VERTEX_PROGRAM)
  491. {
  492. LOGWRN("D3D9 doesn't support this gpu program type: " + toString(gptype));
  493. return;
  494. }
  495. if(gptype == GPT_VERTEX_PROGRAM)
  496. {
  497. unit = D3DVERTEXTEXTURESAMPLER0 + unit; // Vertex stage uses special samplers
  498. }
  499. // Set texture layer filtering
  500. setTextureFiltering(unit, FT_MIN, state->getTextureFiltering(FT_MIN));
  501. setTextureFiltering(unit, FT_MAG, state->getTextureFiltering(FT_MAG));
  502. setTextureFiltering(unit, FT_MIP, state->getTextureFiltering(FT_MIP));
  503. // Set texture layer filtering
  504. setTextureAnisotropy(unit, state->getTextureAnisotropy());
  505. // Set mipmap biasing
  506. setTextureMipmapBias(unit, state->getTextureMipmapBias());
  507. // Texture addressing mode
  508. const UVWAddressingMode& uvw = state->getTextureAddressingMode();
  509. setTextureAddressingMode(unit, uvw);
  510. // Set border color
  511. setTextureBorderColor(unit, state->getBorderColor());
  512. }
  513. //-----------------------------------------------------------------------
  514. void D3D9RenderSystem::setBlendState(const BlendStatePtr& blendState)
  515. {
  516. THROW_IF_NOT_CORE_THREAD;
  517. // Alpha to coverage
  518. setAlphaToCoverage(blendState->getAlphaToCoverageEnabled());
  519. // Blend states
  520. // DirectX 9 doesn't allow us to specify blend state per render target, so we just use the first one.
  521. if(blendState->getBlendEnabled(0))
  522. {
  523. setSceneBlending(blendState->getSrcBlend(0), blendState->getDstBlend(0), blendState->getAlphaSrcBlend(0), blendState->getAlphaDstBlend(0)
  524. , blendState->getBlendOperation(0), blendState->getAlphaBlendOperation(0));
  525. }
  526. else
  527. {
  528. setSceneBlending(BF_ONE, BF_ZERO, BO_ADD);
  529. }
  530. // Color write mask
  531. UINT8 writeMask = blendState->getRenderTargetWriteMask(0);
  532. setColorBufferWriteEnabled((writeMask & 0x1) != 0, (writeMask & 0x2) != 0, (writeMask & 0x4) != 0, (writeMask & 0x8) != 0);
  533. }
  534. //----------------------------------------------------------------------
  535. void D3D9RenderSystem::setRasterizerState(const RasterizerStatePtr& rasterizerState)
  536. {
  537. THROW_IF_NOT_CORE_THREAD;
  538. setDepthBias((float)rasterizerState->getDepthBias(), rasterizerState->getSlopeScaledDepthBias());
  539. setCullingMode(rasterizerState->getCullMode());
  540. setPolygonMode(rasterizerState->getPolygonMode());
  541. setScissorTestEnable(rasterizerState->getScissorEnable());
  542. setMultisampleAntialiasEnable(rasterizerState->getMultisampleEnable());
  543. setAntialiasedLineEnable(rasterizerState->getAntialiasedLineEnable());
  544. }
  545. //----------------------------------------------------------------------
  546. void D3D9RenderSystem::setDepthStencilState(const DepthStencilStatePtr& depthStencilState, UINT32 stencilRefValue)
  547. {
  548. THROW_IF_NOT_CORE_THREAD;
  549. // Set stencil buffer options
  550. setStencilCheckEnabled(depthStencilState->getStencilEnable());
  551. setStencilBufferOperations(depthStencilState->getStencilFrontFailOp(), depthStencilState->getStencilFrontZFailOp(), depthStencilState->getStencilFrontPassOp(), true);
  552. setStencilBufferFunc(depthStencilState->getStencilFrontCompFunc(), true);
  553. setStencilBufferOperations(depthStencilState->getStencilBackFailOp(), depthStencilState->getStencilBackZFailOp(), depthStencilState->getStencilBackPassOp(), false);
  554. setStencilBufferFunc(depthStencilState->getStencilBackCompFunc(), false);
  555. setStencilBufferReadMask(depthStencilState->getStencilReadMask());
  556. setStencilBufferWriteMask(depthStencilState->getStencilWriteMask());
  557. // Set depth buffer options
  558. setDepthBufferCheckEnabled(depthStencilState->getDepthReadEnable());
  559. setDepthBufferWriteEnabled(depthStencilState->getDepthWriteEnable());
  560. setDepthBufferFunction(depthStencilState->getDepthComparisonFunc());
  561. // Set stencil ref value
  562. setStencilRefValue(stencilRefValue);
  563. }
  564. //---------------------------------------------------------------------
  565. void D3D9RenderSystem::setTextureMipmapBias(UINT16 unit, float bias)
  566. {
  567. THROW_IF_NOT_CORE_THREAD;
  568. if (mCurrentCapabilities->hasCapability(RSC_MIPMAP_LOD_BIAS))
  569. {
  570. // ugh - have to pass float data through DWORD with no conversion
  571. HRESULT hr = __SetSamplerState(static_cast<DWORD>(unit), D3DSAMP_MIPMAPLODBIAS,
  572. *(DWORD*)&bias);
  573. if(FAILED(hr))
  574. CM_EXCEPT(RenderingAPIException, "Unable to set texture mipmap bias");
  575. }
  576. }
  577. //---------------------------------------------------------------------
  578. void D3D9RenderSystem::setTextureAddressingMode( UINT16 stage,
  579. const UVWAddressingMode& uvw )
  580. {
  581. THROW_IF_NOT_CORE_THREAD;
  582. HRESULT hr;
  583. if( FAILED( hr = __SetSamplerState( static_cast<DWORD>(stage), D3DSAMP_ADDRESSU, D3D9Mappings::get(uvw.u, mDeviceManager->getActiveDevice()->getD3D9DeviceCaps()) ) ) )
  584. CM_EXCEPT(RenderingAPIException, "Failed to set texture addressing mode for U" );
  585. if( FAILED( hr = __SetSamplerState( static_cast<DWORD>(stage), D3DSAMP_ADDRESSV, D3D9Mappings::get(uvw.v, mDeviceManager->getActiveDevice()->getD3D9DeviceCaps()) ) ) )
  586. CM_EXCEPT(RenderingAPIException, "Failed to set texture addressing mode for V");
  587. if( FAILED( hr = __SetSamplerState( static_cast<DWORD>(stage), D3DSAMP_ADDRESSW, D3D9Mappings::get(uvw.w, mDeviceManager->getActiveDevice()->getD3D9DeviceCaps()) ) ) )
  588. CM_EXCEPT(RenderingAPIException, "Failed to set texture addressing mode for W");
  589. }
  590. //-----------------------------------------------------------------------------
  591. void D3D9RenderSystem::setTextureBorderColor(UINT16 stage,
  592. const Color& colour)
  593. {
  594. THROW_IF_NOT_CORE_THREAD;
  595. HRESULT hr;
  596. if( FAILED( hr = __SetSamplerState( static_cast<DWORD>(stage), D3DSAMP_BORDERCOLOR, colour.getAsBGRA()) ) )
  597. CM_EXCEPT(RenderingAPIException, "Failed to set texture border colour");
  598. }
  599. //---------------------------------------------------------------------
  600. void D3D9RenderSystem::setSceneBlending( BlendFactor sourceFactor, BlendFactor destFactor, BlendOperation op )
  601. {
  602. THROW_IF_NOT_CORE_THREAD;
  603. HRESULT hr;
  604. if( sourceFactor == BF_ONE && destFactor == BF_ZERO)
  605. {
  606. if (FAILED(hr = __SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE)))
  607. CM_EXCEPT(RenderingAPIException, "Failed to set alpha blending option");
  608. }
  609. else
  610. {
  611. if (FAILED(hr = __SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE)))
  612. CM_EXCEPT(RenderingAPIException, "Failed to set alpha blending option");
  613. if (FAILED(hr = __SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE)))
  614. CM_EXCEPT(RenderingAPIException, "Failed to set separate alpha blending option");
  615. if( FAILED( hr = __SetRenderState( D3DRS_SRCBLEND, D3D9Mappings::get(sourceFactor) ) ) )
  616. CM_EXCEPT(RenderingAPIException, "Failed to set source blend");
  617. if( FAILED( hr = __SetRenderState( D3DRS_DESTBLEND, D3D9Mappings::get(destFactor) ) ) )
  618. CM_EXCEPT(RenderingAPIException, "Failed to set destination blend");
  619. }
  620. if (FAILED(hr = __SetRenderState(D3DRS_BLENDOP, D3D9Mappings::get(op))))
  621. CM_EXCEPT(RenderingAPIException, "Failed to set scene blending operation option");
  622. if (FAILED(hr = __SetRenderState(D3DRS_BLENDOPALPHA, D3D9Mappings::get(op))))
  623. CM_EXCEPT(RenderingAPIException, "Failed to set scene blending operation option");
  624. }
  625. //---------------------------------------------------------------------
  626. void D3D9RenderSystem::setSceneBlending( BlendFactor sourceFactor, BlendFactor destFactor, BlendFactor sourceFactorAlpha,
  627. BlendFactor destFactorAlpha, BlendOperation op, BlendOperation alphaOp )
  628. {
  629. THROW_IF_NOT_CORE_THREAD;
  630. HRESULT hr;
  631. if( sourceFactor == BF_ONE && destFactor == BF_ZERO &&
  632. sourceFactorAlpha == BF_ONE && destFactorAlpha == BF_ZERO)
  633. {
  634. if (FAILED(hr = __SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE)))
  635. CM_EXCEPT(RenderingAPIException, "Failed to set alpha blending option");
  636. }
  637. else
  638. {
  639. if (FAILED(hr = __SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE)))
  640. CM_EXCEPT(RenderingAPIException, "Failed to set alpha blending option");
  641. if (FAILED(hr = __SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE)))
  642. CM_EXCEPT(RenderingAPIException, "Failed to set separate alpha blending option");
  643. if( FAILED( hr = __SetRenderState( D3DRS_SRCBLEND, D3D9Mappings::get(sourceFactor) ) ) )
  644. CM_EXCEPT(RenderingAPIException, "Failed to set source blend");
  645. if( FAILED( hr = __SetRenderState( D3DRS_DESTBLEND, D3D9Mappings::get(destFactor) ) ) )
  646. CM_EXCEPT(RenderingAPIException, "Failed to set destination blend");
  647. if( FAILED( hr = __SetRenderState( D3DRS_SRCBLENDALPHA, D3D9Mappings::get(sourceFactorAlpha) ) ) )
  648. CM_EXCEPT(RenderingAPIException, "Failed to set alpha source blend");
  649. if( FAILED( hr = __SetRenderState( D3DRS_DESTBLENDALPHA, D3D9Mappings::get(destFactorAlpha) ) ) )
  650. CM_EXCEPT(RenderingAPIException, "Failed to set alpha destination blend");
  651. }
  652. if (FAILED(hr = __SetRenderState(D3DRS_BLENDOP, D3D9Mappings::get(op))))
  653. CM_EXCEPT(RenderingAPIException, "Failed to set scene blending operation option");
  654. if (FAILED(hr = __SetRenderState(D3DRS_BLENDOPALPHA, D3D9Mappings::get(alphaOp))))
  655. CM_EXCEPT(RenderingAPIException, "Failed to set alpha scene blending operation option");
  656. }
  657. //---------------------------------------------------------------------
  658. void D3D9RenderSystem::setAlphaTest(CompareFunction func, unsigned char value)
  659. {
  660. THROW_IF_NOT_CORE_THREAD;
  661. HRESULT hr;
  662. if (func != CMPF_ALWAYS_PASS)
  663. {
  664. if( FAILED( hr = __SetRenderState( D3DRS_ALPHATESTENABLE, TRUE ) ) )
  665. CM_EXCEPT(RenderingAPIException, "Failed to enable alpha testing");
  666. }
  667. else
  668. {
  669. if( FAILED( hr = __SetRenderState( D3DRS_ALPHATESTENABLE, FALSE ) ) )
  670. CM_EXCEPT(RenderingAPIException, "Failed to disable alpha testing");
  671. }
  672. // Set always just be sure
  673. if( FAILED( hr = __SetRenderState( D3DRS_ALPHAFUNC, D3D9Mappings::get(func) ) ) )
  674. CM_EXCEPT(RenderingAPIException, "Failed to set alpha reject function");
  675. if( FAILED( hr = __SetRenderState( D3DRS_ALPHAREF, value ) ) )
  676. CM_EXCEPT(RenderingAPIException, "Failed to set render state D3DRS_ALPHAREF");
  677. }
  678. //---------------------------------------------------------------------
  679. void D3D9RenderSystem::setAlphaToCoverage(bool enable)
  680. {
  681. THROW_IF_NOT_CORE_THREAD;
  682. HRESULT hr;
  683. static bool lasta2c = false;
  684. // Alpha to coverage
  685. if (getCapabilities()->hasCapability(RSC_ALPHA_TO_COVERAGE))
  686. {
  687. // Vendor-specific hacks on renderstate, gotta love 'em
  688. if (getCapabilities()->getVendor() == GPU_NVIDIA)
  689. {
  690. if (enable)
  691. {
  692. if( FAILED( hr = __SetRenderState( D3DRS_ADAPTIVETESS_Y, (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C') ) ) )
  693. CM_EXCEPT(RenderingAPIException, "Failed to set alpha to coverage option");
  694. }
  695. else
  696. {
  697. if( FAILED( hr = __SetRenderState( D3DRS_ADAPTIVETESS_Y, D3DFMT_UNKNOWN ) ) )
  698. CM_EXCEPT(RenderingAPIException, "Failed to set alpha to coverage option");
  699. }
  700. }
  701. else if ((getCapabilities()->getVendor() == GPU_ATI))
  702. {
  703. if (enable)
  704. {
  705. if( FAILED( hr = __SetRenderState( D3DRS_POINTSIZE, MAKEFOURCC('A','2','M','1') ) ) )
  706. CM_EXCEPT(RenderingAPIException, "Failed to set alpha to coverage option");
  707. }
  708. else
  709. {
  710. // discovered this through trial and error, seems to work
  711. if( FAILED( hr = __SetRenderState( D3DRS_POINTSIZE, MAKEFOURCC('A','2','M','0') ) ) )
  712. CM_EXCEPT(RenderingAPIException, "Failed to set alpha to coverage option");
  713. }
  714. }
  715. lasta2c = enable;
  716. }
  717. }
  718. //---------------------------------------------------------------------
  719. void D3D9RenderSystem::setCullingMode( CullingMode mode )
  720. {
  721. THROW_IF_NOT_CORE_THREAD;
  722. mCullingMode = mode;
  723. HRESULT hr;
  724. bool flip = ((mActiveRenderTarget->requiresTextureFlipping() && !mInvertVertexWinding) ||
  725. (!mActiveRenderTarget->requiresTextureFlipping() && mInvertVertexWinding));
  726. if( FAILED (hr = __SetRenderState(D3DRS_CULLMODE,
  727. D3D9Mappings::get(mode, flip))) )
  728. CM_EXCEPT(RenderingAPIException, "Failed to set culling mode");
  729. }
  730. //---------------------------------------------------------------------
  731. void D3D9RenderSystem::setDepthBufferParams( bool depthTest, bool depthWrite, CompareFunction depthFunction )
  732. {
  733. THROW_IF_NOT_CORE_THREAD;
  734. setDepthBufferCheckEnabled( depthTest );
  735. setDepthBufferWriteEnabled( depthWrite );
  736. setDepthBufferFunction( depthFunction );
  737. }
  738. //---------------------------------------------------------------------
  739. void D3D9RenderSystem::setDepthBufferCheckEnabled( bool enabled )
  740. {
  741. THROW_IF_NOT_CORE_THREAD;
  742. HRESULT hr;
  743. if( enabled )
  744. hr = __SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE );
  745. else
  746. hr = __SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE );
  747. if( FAILED( hr ) )
  748. CM_EXCEPT(RenderingAPIException, "Error setting depth buffer test state");
  749. }
  750. //---------------------------------------------------------------------
  751. void D3D9RenderSystem::setDepthBufferWriteEnabled( bool enabled )
  752. {
  753. THROW_IF_NOT_CORE_THREAD;
  754. HRESULT hr;
  755. if( FAILED( hr = __SetRenderState( D3DRS_ZWRITEENABLE, enabled ) ) )
  756. CM_EXCEPT(RenderingAPIException, "Error setting depth buffer write state");
  757. }
  758. //---------------------------------------------------------------------
  759. void D3D9RenderSystem::setDepthBufferFunction( CompareFunction func )
  760. {
  761. THROW_IF_NOT_CORE_THREAD;
  762. HRESULT hr;
  763. if( FAILED( hr = __SetRenderState( D3DRS_ZFUNC, D3D9Mappings::get(func) ) ) )
  764. CM_EXCEPT(RenderingAPIException, "Error setting depth buffer test function");
  765. }
  766. //---------------------------------------------------------------------
  767. void D3D9RenderSystem::setDepthBias(float constantBias, float slopeScaleBias)
  768. {
  769. THROW_IF_NOT_CORE_THREAD;
  770. if ((mDeviceManager->getActiveDevice()->getD3D9DeviceCaps().RasterCaps & D3DPRASTERCAPS_DEPTHBIAS) != 0)
  771. {
  772. // Negate bias since D3D is backward
  773. // D3D also expresses the constant bias as an absolute value, rather than
  774. // relative to minimum depth unit, so scale to fit
  775. constantBias = -constantBias / 250000.0f;
  776. HRESULT hr = __SetRenderState(D3DRS_DEPTHBIAS, FLOAT2DWORD(constantBias));
  777. if (FAILED(hr))
  778. CM_EXCEPT(RenderingAPIException, "Error setting constant depth bias");
  779. }
  780. if ((mDeviceManager->getActiveDevice()->getD3D9DeviceCaps().RasterCaps & D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS) != 0)
  781. {
  782. // Negate bias since D3D is backward
  783. slopeScaleBias = -slopeScaleBias;
  784. HRESULT hr = __SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, FLOAT2DWORD(slopeScaleBias));
  785. if (FAILED(hr))
  786. CM_EXCEPT(RenderingAPIException, "Error setting slope scale depth bias");
  787. }
  788. }
  789. //---------------------------------------------------------------------
  790. void D3D9RenderSystem::setColorBufferWriteEnabled(bool red, bool green,
  791. bool blue, bool alpha)
  792. {
  793. THROW_IF_NOT_CORE_THREAD;
  794. DWORD val = 0;
  795. if (red)
  796. val |= D3DCOLORWRITEENABLE_RED;
  797. if (green)
  798. val |= D3DCOLORWRITEENABLE_GREEN;
  799. if (blue)
  800. val |= D3DCOLORWRITEENABLE_BLUE;
  801. if (alpha)
  802. val |= D3DCOLORWRITEENABLE_ALPHA;
  803. HRESULT hr = __SetRenderState(D3DRS_COLORWRITEENABLE, val);
  804. if (FAILED(hr))
  805. CM_EXCEPT(RenderingAPIException, "Error setting colour write enable flags");
  806. }
  807. //---------------------------------------------------------------------
  808. void D3D9RenderSystem::setPolygonMode(PolygonMode level)
  809. {
  810. THROW_IF_NOT_CORE_THREAD;
  811. HRESULT hr = __SetRenderState(D3DRS_FILLMODE, D3D9Mappings::get(level));
  812. if (FAILED(hr))
  813. CM_EXCEPT(RenderingAPIException, "Error setting polygon mode.");
  814. }
  815. //---------------------------------------------------------------------
  816. void D3D9RenderSystem::setStencilCheckEnabled(bool enabled)
  817. {
  818. THROW_IF_NOT_CORE_THREAD;
  819. // Allow stencilling
  820. HRESULT hr = __SetRenderState(D3DRS_STENCILENABLE, enabled);
  821. if (FAILED(hr))
  822. CM_EXCEPT(RenderingAPIException, "Error enabling / disabling stencilling.");
  823. if (mCurrentCapabilities->hasCapability(RSC_TWO_SIDED_STENCIL))
  824. {
  825. hr = __SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
  826. if (FAILED(hr))
  827. CM_EXCEPT(RenderingAPIException, "Error setting 2-sided stencil mode.");
  828. }
  829. else
  830. {
  831. hr = __SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
  832. if (FAILED(hr))
  833. CM_EXCEPT(RenderingAPIException, "Error setting 1-sided stencil mode.");
  834. }
  835. }
  836. //---------------------------------------------------------------------
  837. void D3D9RenderSystem::setStencilBufferOperations(StencilOperation stencilFailOp, StencilOperation depthFailOp, StencilOperation passOp, bool ccw)
  838. {
  839. THROW_IF_NOT_CORE_THREAD;
  840. HRESULT hr;
  841. // 2-sided operation
  842. if (ccw)
  843. {
  844. // fail op
  845. hr = __SetRenderState(D3DRS_CCW_STENCILFAIL, D3D9Mappings::get(stencilFailOp, mInvertVertexWinding));
  846. if (FAILED(hr))
  847. CM_EXCEPT(RenderingAPIException, "Error setting stencil fail operation (ccw).");
  848. // depth fail op
  849. hr = __SetRenderState(D3DRS_CCW_STENCILZFAIL, D3D9Mappings::get(depthFailOp, mInvertVertexWinding));
  850. if (FAILED(hr))
  851. CM_EXCEPT(RenderingAPIException, "Error setting stencil depth fail operation (ccw).");
  852. // pass op
  853. hr = __SetRenderState(D3DRS_CCW_STENCILPASS, D3D9Mappings::get(passOp, mInvertVertexWinding));
  854. if (FAILED(hr))
  855. CM_EXCEPT(RenderingAPIException, "Error setting stencil pass operation (ccw).");
  856. }
  857. else
  858. {
  859. // fail op
  860. hr = __SetRenderState(D3DRS_STENCILFAIL, D3D9Mappings::get(stencilFailOp, !mInvertVertexWinding));
  861. if (FAILED(hr))
  862. CM_EXCEPT(RenderingAPIException, "Error setting stencil fail operation (cw).");
  863. // depth fail op
  864. hr = __SetRenderState(D3DRS_STENCILZFAIL, D3D9Mappings::get(depthFailOp, !mInvertVertexWinding));
  865. if (FAILED(hr))
  866. CM_EXCEPT(RenderingAPIException, "Error setting stencil depth fail operation (cw).");
  867. // pass op
  868. hr = __SetRenderState(D3DRS_STENCILPASS, D3D9Mappings::get(passOp, !mInvertVertexWinding));
  869. if (FAILED(hr))
  870. CM_EXCEPT(RenderingAPIException, "Error setting stencil pass operation (cw).");
  871. }
  872. }
  873. //---------------------------------------------------------------------
  874. void D3D9RenderSystem::setStencilBufferFunc(CompareFunction func, bool ccw)
  875. {
  876. HRESULT hr;
  877. if(ccw)
  878. hr = __SetRenderState(D3DRS_CCW_STENCILFUNC, D3D9Mappings::get(func));
  879. else
  880. hr = __SetRenderState(D3DRS_STENCILFUNC, D3D9Mappings::get(func));
  881. if (FAILED(hr))
  882. CM_EXCEPT(RenderingAPIException, "Error setting stencil buffer test function.");
  883. }
  884. //---------------------------------------------------------------------
  885. void D3D9RenderSystem::setStencilBufferReadMask(UINT32 mask)
  886. {
  887. HRESULT hr = __SetRenderState(D3DRS_STENCILMASK, mask);
  888. if (FAILED(hr))
  889. CM_EXCEPT(RenderingAPIException, "Error setting stencil buffer mask.");
  890. }
  891. //--------------------------------------------------------------------
  892. void D3D9RenderSystem::setStencilBufferWriteMask(UINT32 mask)
  893. {
  894. HRESULT hr = __SetRenderState(D3DRS_STENCILWRITEMASK, mask);
  895. if (FAILED(hr))
  896. CM_EXCEPT(RenderingAPIException, "Error setting stencil buffer write mask.");
  897. }
  898. //----------------------------------------------------------------------
  899. void D3D9RenderSystem::setStencilRefValue(UINT32 refValue)
  900. {
  901. THROW_IF_NOT_CORE_THREAD;
  902. HRESULT hr = __SetRenderState(D3DRS_STENCILREF, refValue);
  903. if (FAILED(hr))
  904. CM_EXCEPT(RenderingAPIException, "Error setting stencil buffer reference value.");
  905. }
  906. //---------------------------------------------------------------------
  907. void D3D9RenderSystem::setTextureFiltering(UINT16 unit, FilterType ftype,
  908. FilterOptions filter)
  909. {
  910. THROW_IF_NOT_CORE_THREAD;
  911. HRESULT hr;
  912. D3D9Mappings::eD3DTexType texType = mTexStageDesc[unit].texType;
  913. hr = __SetSamplerState( static_cast<DWORD>(unit), D3D9Mappings::get(ftype),
  914. D3D9Mappings::get(ftype, filter, mDeviceManager->getActiveDevice()->getD3D9DeviceCaps(), texType));
  915. if (FAILED(hr))
  916. CM_EXCEPT(RenderingAPIException, "Failed to set texture filter ");
  917. }
  918. //---------------------------------------------------------------------
  919. void D3D9RenderSystem::setTextureAnisotropy(UINT16 unit, unsigned int maxAnisotropy)
  920. {
  921. THROW_IF_NOT_CORE_THREAD;
  922. if (static_cast<DWORD>(maxAnisotropy) > mDeviceManager->getActiveDevice()->getD3D9DeviceCaps().MaxAnisotropy)
  923. maxAnisotropy = mDeviceManager->getActiveDevice()->getD3D9DeviceCaps().MaxAnisotropy;
  924. if (_getCurrentAnisotropy(unit) != maxAnisotropy)
  925. __SetSamplerState( static_cast<DWORD>(unit), D3DSAMP_MAXANISOTROPY, maxAnisotropy );
  926. }
  927. //---------------------------------------------------------------------
  928. void D3D9RenderSystem::setRenderTarget(RenderTargetPtr target)
  929. {
  930. THROW_IF_NOT_CORE_THREAD;
  931. mActiveRenderTarget = target;
  932. HRESULT hr;
  933. // Possibly change device if the target is a window
  934. if (target->isWindow())
  935. {
  936. D3D9RenderWindow* window = static_cast<D3D9RenderWindow*>(target.get());
  937. mDeviceManager->setActiveRenderTargetDevice(window->_getDevice());
  938. window->_validateDevice();
  939. }
  940. // Retrieve render surfaces
  941. UINT32 maxRenderTargets = mCurrentCapabilities->getNumMultiRenderTargets();
  942. IDirect3DSurface9** pBack = cm_newN<IDirect3DSurface9*, ScratchAlloc>(maxRenderTargets);
  943. memset(pBack, 0, sizeof(IDirect3DSurface9*) * maxRenderTargets);
  944. target->getCustomAttribute( "DDBACKBUFFER", pBack );
  945. if (!pBack[0])
  946. {
  947. cm_deleteN<ScratchAlloc>(pBack, maxRenderTargets);
  948. return;
  949. }
  950. IDirect3DSurface9* pDepth = NULL;
  951. if (!pDepth)
  952. target->getCustomAttribute( "D3DZBUFFER", &pDepth );
  953. // Bind render targets
  954. for(UINT32 x = 0; x < maxRenderTargets; ++x)
  955. {
  956. hr = getActiveD3D9Device()->SetRenderTarget(x, pBack[x]);
  957. if (FAILED(hr))
  958. {
  959. String msg = DXGetErrorDescription(hr);
  960. CM_EXCEPT(RenderingAPIException, "Failed to setRenderTarget : " + msg);
  961. }
  962. }
  963. cm_deleteN<ScratchAlloc>(pBack, maxRenderTargets);
  964. hr = getActiveD3D9Device()->SetDepthStencilSurface(pDepth);
  965. if (FAILED(hr))
  966. {
  967. String msg = DXGetErrorDescription(hr);
  968. CM_EXCEPT(RenderingAPIException, "Failed to setDepthStencil : " + msg);
  969. }
  970. }
  971. //---------------------------------------------------------------------
  972. void D3D9RenderSystem::setViewport(const ViewportPtr& vp)
  973. {
  974. THROW_IF_NOT_CORE_THREAD;
  975. assert(vp != nullptr);
  976. // ok, it's different, time to set render target and viewport params
  977. D3DVIEWPORT9 d3dvp;
  978. HRESULT hr;
  979. // Set render target
  980. RenderTargetPtr target = vp->getTarget();
  981. setRenderTarget(target);
  982. setCullingMode( mCullingMode );
  983. // set viewport dimensions
  984. mViewportWidth = vp->getWidth();
  985. mViewportHeight = vp->getHeight();
  986. mViewportLeft = vp->getLeft();
  987. mViewportTop = vp->getTop();
  988. d3dvp.X = vp->getLeft();
  989. d3dvp.Y = vp->getTop();
  990. d3dvp.Width = vp->getWidth();
  991. d3dvp.Height = vp->getHeight();
  992. if (target->requiresTextureFlipping())
  993. {
  994. // Convert "top-left" to "bottom-left"
  995. d3dvp.Y = target->getHeight() - d3dvp.Height - d3dvp.Y;
  996. }
  997. // Z-values from 0.0 to 1.0 (TODO: standardise with OpenGL)
  998. d3dvp.MinZ = 0.0f;
  999. d3dvp.MaxZ = 1.0f;
  1000. if( FAILED( hr = getActiveD3D9Device()->SetViewport( &d3dvp ) ) )
  1001. CM_EXCEPT(RenderingAPIException, "Failed to set viewport.");
  1002. // Set sRGB write mode
  1003. __SetRenderState(D3DRS_SRGBWRITEENABLE, target->isHwGammaEnabled());
  1004. }
  1005. //---------------------------------------------------------------------
  1006. void D3D9RenderSystem::beginFrame()
  1007. {
  1008. THROW_IF_NOT_CORE_THREAD;
  1009. HRESULT hr;
  1010. if( FAILED( hr = getActiveD3D9Device()->BeginScene() ) )
  1011. {
  1012. String msg = DXGetErrorDescription(hr);
  1013. CM_EXCEPT(RenderingAPIException, "Error beginning frame :" + msg);
  1014. }
  1015. mDeviceManager->getActiveDevice()->clearDeviceStreams();
  1016. }
  1017. //---------------------------------------------------------------------
  1018. void D3D9RenderSystem::endFrame()
  1019. {
  1020. THROW_IF_NOT_CORE_THREAD;
  1021. HRESULT hr;
  1022. if( FAILED( hr = getActiveD3D9Device()->EndScene() ) )
  1023. CM_EXCEPT(RenderingAPIException, "Error ending frame");
  1024. mDeviceManager->destroyInactiveRenderDevices();
  1025. }
  1026. //---------------------------------------------------------------------
  1027. void D3D9RenderSystem::setVertexDeclaration(VertexDeclarationPtr decl)
  1028. {
  1029. THROW_IF_NOT_CORE_THREAD;
  1030. HRESULT hr;
  1031. std::shared_ptr<D3D9VertexDeclaration> d3ddecl =
  1032. std::static_pointer_cast<D3D9VertexDeclaration>(decl);
  1033. if (FAILED(hr = getActiveD3D9Device()->SetVertexDeclaration(d3ddecl->getD3DVertexDeclaration())))
  1034. {
  1035. CM_EXCEPT(RenderingAPIException, "Unable to set D3D9 vertex declaration");
  1036. }
  1037. }
  1038. //---------------------------------------------------------------------
  1039. void D3D9RenderSystem::setVertexBuffer(UINT32 index, const VertexBufferPtr& buffer)
  1040. {
  1041. THROW_IF_NOT_CORE_THREAD;
  1042. UINT32 maxBoundVertexBuffers = mCurrentCapabilities->getMaxBoundVertexBuffers();
  1043. if(index < 0 || index >= maxBoundVertexBuffers)
  1044. CM_EXCEPT(InvalidParametersException, "Invalid vertex index: " + toString(index) + ". Valid range is 0 .. " + toString(maxBoundVertexBuffers - 1));
  1045. HRESULT hr;
  1046. if(buffer != nullptr)
  1047. {
  1048. D3D9VertexBuffer* d3d9buf = static_cast<D3D9VertexBuffer*>(buffer.get());
  1049. hr = getActiveD3D9Device()->SetStreamSource(
  1050. static_cast<UINT>(index),
  1051. d3d9buf->getD3D9VertexBuffer(),
  1052. 0,
  1053. static_cast<UINT>(d3d9buf->getVertexSize()) // stride
  1054. );
  1055. }
  1056. else
  1057. {
  1058. hr = getActiveD3D9Device()->SetStreamSource(static_cast<UINT>(index), nullptr, 0, 0);
  1059. }
  1060. if (FAILED(hr))
  1061. CM_EXCEPT(RenderingAPIException, "Unable to set D3D9 stream source for buffer binding");
  1062. }
  1063. //---------------------------------------------------------------------
  1064. void D3D9RenderSystem::setIndexBuffer(const IndexBufferPtr& buffer)
  1065. {
  1066. THROW_IF_NOT_CORE_THREAD;
  1067. D3D9IndexBuffer* d3dIdxBuf = static_cast<D3D9IndexBuffer*>(buffer.get());
  1068. HRESULT hr = getActiveD3D9Device()->SetIndices( d3dIdxBuf->getD3DIndexBuffer() );
  1069. if (FAILED(hr))
  1070. CM_EXCEPT(RenderingAPIException, "Failed to set index buffer");
  1071. }
  1072. //---------------------------------------------------------------------
  1073. void D3D9RenderSystem::setDrawOperation(DrawOperationType op)
  1074. {
  1075. THROW_IF_NOT_CORE_THREAD;
  1076. mCurrentDrawOperation = op;
  1077. }
  1078. //---------------------------------------------------------------------
  1079. void D3D9RenderSystem::draw(UINT32 vertexCount)
  1080. {
  1081. UINT32 primCount = pointCountToPrimCount(mCurrentDrawOperation, vertexCount);
  1082. HRESULT hr = getActiveD3D9Device()->DrawPrimitive(getD3D9PrimitiveType(), 0, static_cast<UINT>(primCount));
  1083. if( FAILED( hr ) )
  1084. {
  1085. String msg = DXGetErrorDescription(hr);
  1086. CM_EXCEPT(RenderingAPIException, "Failed to DrawPrimitive : " + msg);
  1087. }
  1088. }
  1089. //---------------------------------------------------------------------
  1090. void D3D9RenderSystem::drawIndexed(UINT32 startIndex, UINT32 indexCount, UINT32 vertexCount)
  1091. {
  1092. UINT32 primCount = pointCountToPrimCount(mCurrentDrawOperation, indexCount);
  1093. // do indexed draw operation
  1094. HRESULT hr = getActiveD3D9Device()->DrawIndexedPrimitive(
  1095. getD3D9PrimitiveType(),
  1096. 0,
  1097. 0,
  1098. static_cast<UINT>(vertexCount),
  1099. static_cast<UINT>(startIndex),
  1100. static_cast<UINT>(primCount)
  1101. );
  1102. if( FAILED( hr ) )
  1103. {
  1104. String msg = DXGetErrorDescription(hr);
  1105. CM_EXCEPT(RenderingAPIException, "Failed to DrawIndexedPrimitive : " + msg);
  1106. }
  1107. }
  1108. //---------------------------------------------------------------------
  1109. void D3D9RenderSystem::setScissorRect(UINT32 left, UINT32 top, UINT32 right, UINT32 bottom)
  1110. {
  1111. THROW_IF_NOT_CORE_THREAD;
  1112. mScissorRect.left = static_cast<LONG>(left);
  1113. mScissorRect.top = static_cast<LONG>(top);
  1114. mScissorRect.bottom = static_cast<LONG>(bottom);
  1115. mScissorRect.right = static_cast<LONG>(right);
  1116. }
  1117. //--------------------------------------------------------------------
  1118. void D3D9RenderSystem::setScissorTestEnable(bool enable)
  1119. {
  1120. THROW_IF_NOT_CORE_THREAD;
  1121. HRESULT hr;
  1122. if (enable)
  1123. {
  1124. if (FAILED(hr = __SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE)))
  1125. {
  1126. CM_EXCEPT(RenderingAPIException, "Unable to enable scissor rendering state; " + getErrorDescription(hr));
  1127. }
  1128. if (FAILED(hr = getActiveD3D9Device()->SetScissorRect(&mScissorRect)))
  1129. {
  1130. CM_EXCEPT(RenderingAPIException, "Unable to set scissor rectangle; " + getErrorDescription(hr));
  1131. }
  1132. }
  1133. else
  1134. {
  1135. if (FAILED(hr = __SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE)))
  1136. {
  1137. CM_EXCEPT(RenderingAPIException, "Unable to disable scissor rendering state; " + getErrorDescription(hr));
  1138. }
  1139. }
  1140. }
  1141. //--------------------------------------------------------------------
  1142. void D3D9RenderSystem::setMultisampleAntialiasEnable(bool enable)
  1143. {
  1144. HRESULT hr;
  1145. if(enable)
  1146. {
  1147. if (FAILED(hr = __SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE)))
  1148. {
  1149. CM_EXCEPT(RenderingAPIException, "Unable to enable multisample antialiasing. Error description: " + getErrorDescription(hr));
  1150. }
  1151. }
  1152. else
  1153. {
  1154. if (FAILED(hr = __SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, FALSE)))
  1155. {
  1156. CM_EXCEPT(RenderingAPIException, "Unable to disable multisample antialiasing. Error description: " + getErrorDescription(hr));
  1157. }
  1158. }
  1159. }
  1160. //---------------------------------------------------------------------
  1161. void D3D9RenderSystem::setAntialiasedLineEnable(bool enable)
  1162. {
  1163. HRESULT hr;
  1164. if(enable)
  1165. {
  1166. if (FAILED(hr = __SetRenderState(D3DRS_ANTIALIASEDLINEENABLE, TRUE)))
  1167. {
  1168. CM_EXCEPT(RenderingAPIException, "Unable to enable line antialiasing. Error description: " + getErrorDescription(hr));
  1169. }
  1170. }
  1171. else
  1172. {
  1173. if (FAILED(hr = __SetRenderState(D3DRS_ANTIALIASEDLINEENABLE, FALSE)))
  1174. {
  1175. CM_EXCEPT(RenderingAPIException, "Unable to disable line antialiasing. Error description: " + getErrorDescription(hr));
  1176. }
  1177. }
  1178. }
  1179. void D3D9RenderSystem::clearRenderTarget(UINT32 buffers, const Color& color, float depth, UINT16 stencil)
  1180. {
  1181. if(mActiveRenderTarget == nullptr)
  1182. return;
  1183. Rect clearRect(0, 0, mActiveRenderTarget->getWidth(), mActiveRenderTarget->getHeight());
  1184. clearArea(buffers, color, depth, stencil, clearRect);
  1185. }
  1186. void D3D9RenderSystem::clearViewport(UINT32 buffers, const Color& color, float depth, UINT16 stencil)
  1187. {
  1188. Rect clearRect(mViewportLeft, mViewportTop, mViewportWidth, mViewportHeight);
  1189. clearArea(buffers, color, depth, stencil, clearRect);
  1190. }
  1191. void D3D9RenderSystem::clearArea(UINT32 buffers, const Color& color, float depth, UINT16 stencil, const Rect& clearRect)
  1192. {
  1193. THROW_IF_NOT_CORE_THREAD;
  1194. if(mActiveRenderTarget == nullptr)
  1195. return;
  1196. DWORD flags = 0;
  1197. if (buffers & FBT_COLOR)
  1198. {
  1199. flags |= D3DCLEAR_TARGET;
  1200. }
  1201. if (buffers & FBT_DEPTH)
  1202. {
  1203. flags |= D3DCLEAR_ZBUFFER;
  1204. }
  1205. // Only try to clear the stencil buffer if supported
  1206. if (buffers & FBT_STENCIL && mCurrentCapabilities->hasCapability(RSC_HWSTENCIL))
  1207. {
  1208. flags |= D3DCLEAR_STENCIL;
  1209. }
  1210. bool clearEntireTarget = clearRect.width == 0 || clearRect.height == 0;
  1211. clearEntireTarget |= (clearRect.x == 0 && clearRect.y == 0 && clearRect.width == mActiveRenderTarget->getWidth() && clearRect.height == mActiveRenderTarget->getHeight());
  1212. if(!clearEntireTarget)
  1213. {
  1214. D3DRECT clearD3DRect;
  1215. clearD3DRect.x1 = clearRect.x;
  1216. clearD3DRect.x2 = clearD3DRect.x1 + clearRect.width;
  1217. clearD3DRect.y1 = clearRect.y;
  1218. clearD3DRect.y2 = clearD3DRect.y1 + clearRect.height;
  1219. HRESULT hr;
  1220. if(FAILED( hr = getActiveD3D9Device()->Clear(1, &clearD3DRect, flags, color.getAsBGRA(), depth, stencil)))
  1221. {
  1222. String msg = DXGetErrorDescription(hr);
  1223. CM_EXCEPT(RenderingAPIException, "Error clearing frame buffer : " + msg);
  1224. }
  1225. }
  1226. else
  1227. {
  1228. HRESULT hr;
  1229. if(FAILED( hr = getActiveD3D9Device()->Clear(0, nullptr, flags, color.getAsBGRA(), depth, stencil)))
  1230. {
  1231. String msg = DXGetErrorDescription(hr);
  1232. CM_EXCEPT(RenderingAPIException, "Error clearing frame buffer : " + msg);
  1233. }
  1234. }
  1235. }
  1236. //---------------------------------------------------------------------
  1237. IDirect3D9* D3D9RenderSystem::getDirect3D9()
  1238. {
  1239. THROW_IF_NOT_CORE_THREAD;
  1240. IDirect3D9* pDirect3D9 = msD3D9RenderSystem->mpD3D;
  1241. if (pDirect3D9 == NULL)
  1242. {
  1243. CM_EXCEPT(InvalidParametersException, "Direct3D9 interface is NULL !!!");
  1244. }
  1245. return pDirect3D9;
  1246. }
  1247. //---------------------------------------------------------------------
  1248. UINT D3D9RenderSystem::getResourceCreationDeviceCount()
  1249. {
  1250. THROW_IF_NOT_CORE_THREAD;
  1251. D3D9ResourceCreationPolicy creationPolicy = msD3D9RenderSystem->mResourceManager->getCreationPolicy();
  1252. if (creationPolicy == RCP_CREATE_ON_ACTIVE_DEVICE)
  1253. {
  1254. return 1;
  1255. }
  1256. else if (creationPolicy == RCP_CREATE_ON_ALL_DEVICES)
  1257. {
  1258. return msD3D9RenderSystem->mDeviceManager->getDeviceCount();
  1259. }
  1260. CM_EXCEPT(InvalidParametersException, "Invalid resource creation policy !!!" );
  1261. return 0;
  1262. }
  1263. //---------------------------------------------------------------------
  1264. IDirect3DDevice9* D3D9RenderSystem::getResourceCreationDevice(UINT index)
  1265. {
  1266. THROW_IF_NOT_CORE_THREAD;
  1267. D3D9ResourceCreationPolicy creationPolicy = msD3D9RenderSystem->mResourceManager->getCreationPolicy();
  1268. IDirect3DDevice9* d3d9Device = NULL;
  1269. if (creationPolicy == RCP_CREATE_ON_ACTIVE_DEVICE)
  1270. {
  1271. d3d9Device = msD3D9RenderSystem->getActiveD3D9Device();
  1272. }
  1273. else if (creationPolicy == RCP_CREATE_ON_ALL_DEVICES)
  1274. {
  1275. d3d9Device = msD3D9RenderSystem->mDeviceManager->getDevice(index)->getD3D9Device();
  1276. }
  1277. else
  1278. {
  1279. CM_EXCEPT(InvalidParametersException, "Invalid resource creation policy !!!" );
  1280. }
  1281. return d3d9Device;
  1282. }
  1283. //---------------------------------------------------------------------
  1284. IDirect3DDevice9* D3D9RenderSystem::getActiveD3D9Device()
  1285. {
  1286. THROW_IF_NOT_CORE_THREAD;
  1287. D3D9Device* activeDevice = msD3D9RenderSystem->mDeviceManager->getActiveDevice();
  1288. IDirect3DDevice9* d3d9Device;
  1289. d3d9Device = activeDevice->getD3D9Device();
  1290. if (d3d9Device == NULL)
  1291. {
  1292. CM_EXCEPT(InvalidParametersException, "Current d3d9 device is NULL !!!" );
  1293. }
  1294. return d3d9Device;
  1295. }
  1296. //---------------------------------------------------------------------
  1297. D3D9ResourceManager* D3D9RenderSystem::getResourceManager()
  1298. {
  1299. // No need to check if we're on core thread as this is synced up internally
  1300. return msD3D9RenderSystem->mResourceManager;
  1301. }
  1302. //---------------------------------------------------------------------
  1303. D3D9DeviceManager* D3D9RenderSystem::getDeviceManager()
  1304. {
  1305. THROW_IF_NOT_CORE_THREAD;
  1306. return msD3D9RenderSystem->mDeviceManager;
  1307. }
  1308. /************************************************************************/
  1309. /* UTILITY METHODS */
  1310. /************************************************************************/
  1311. //---------------------------------------------------------------------
  1312. float D3D9RenderSystem::getHorizontalTexelOffset()
  1313. {
  1314. // D3D considers the origin to be in the center of a pixel
  1315. return -0.5f;
  1316. }
  1317. //---------------------------------------------------------------------
  1318. float D3D9RenderSystem::getVerticalTexelOffset()
  1319. {
  1320. // D3D considers the origin to be in the center of a pixel
  1321. return -0.5f;
  1322. }
  1323. //---------------------------------------------------------------------
  1324. float D3D9RenderSystem::getMinimumDepthInputValue()
  1325. {
  1326. // Range [0.0f, 1.0f]
  1327. return 0.0f;
  1328. }
  1329. //---------------------------------------------------------------------
  1330. float D3D9RenderSystem::getMaximumDepthInputValue()
  1331. {
  1332. // Range [0.0f, 1.0f]
  1333. // D3D inverts even identity view matrices, so maximum INPUT is -1.0
  1334. return -1.0f;
  1335. }
  1336. //---------------------------------------------------------------------
  1337. VertexElementType D3D9RenderSystem::getColorVertexElementType() const
  1338. {
  1339. return VET_COLOR_ARGB;
  1340. }
  1341. //---------------------------------------------------------------------
  1342. void D3D9RenderSystem::convertProjectionMatrix(const Matrix4& matrix,
  1343. Matrix4& dest, bool forGpuProgram)
  1344. {
  1345. dest = matrix;
  1346. // Convert depth range from [-1,+1] to [0,1]
  1347. dest[2][0] = (dest[2][0] + dest[3][0]) / 2;
  1348. dest[2][1] = (dest[2][1] + dest[3][1]) / 2;
  1349. dest[2][2] = (dest[2][2] + dest[3][2]) / 2;
  1350. dest[2][3] = (dest[2][3] + dest[3][3]) / 2;
  1351. if (!forGpuProgram)
  1352. {
  1353. // Convert right-handed to left-handed
  1354. dest[0][2] = -dest[0][2];
  1355. dest[1][2] = -dest[1][2];
  1356. dest[2][2] = -dest[2][2];
  1357. dest[3][2] = -dest[3][2];
  1358. }
  1359. }
  1360. /************************************************************************/
  1361. /* PRIVATE */
  1362. /************************************************************************/
  1363. //---------------------------------------------------------------------
  1364. D3D9DriverList* D3D9RenderSystem::getDirect3DDrivers() const
  1365. {
  1366. if( !mDriverList )
  1367. mDriverList = cm_new<D3D9DriverList>();
  1368. return mDriverList;
  1369. }
  1370. //---------------------------------------------------------------------
  1371. D3DPRIMITIVETYPE D3D9RenderSystem::getD3D9PrimitiveType() const
  1372. {
  1373. switch(mCurrentDrawOperation)
  1374. {
  1375. case DOT_POINT_LIST:
  1376. return D3DPT_POINTLIST;
  1377. case DOT_LINE_LIST:
  1378. return D3DPT_LINELIST;
  1379. case DOT_LINE_STRIP:
  1380. return D3DPT_LINESTRIP;
  1381. case DOT_TRIANGLE_LIST:
  1382. return D3DPT_TRIANGLELIST;
  1383. case DOT_TRIANGLE_STRIP:
  1384. return D3DPT_TRIANGLESTRIP;
  1385. case DOT_TRIANGLE_FAN:
  1386. return D3DPT_TRIANGLEFAN;
  1387. }
  1388. return D3DPT_TRIANGLELIST;
  1389. }
  1390. //---------------------------------------------------------------------
  1391. UINT32 D3D9RenderSystem::pointCountToPrimCount(DrawOperationType type, UINT32 elementCount) const
  1392. {
  1393. DWORD primCount = 0;
  1394. switch(type)
  1395. {
  1396. case DOT_POINT_LIST:
  1397. primCount = elementCount;
  1398. break;
  1399. case DOT_LINE_LIST:
  1400. primCount = elementCount / 2;
  1401. break;
  1402. case DOT_LINE_STRIP:
  1403. primCount = elementCount - 1;
  1404. break;
  1405. case DOT_TRIANGLE_LIST:
  1406. primCount = elementCount / 3;
  1407. break;
  1408. case DOT_TRIANGLE_STRIP:
  1409. primCount = elementCount - 2;
  1410. break;
  1411. case DOT_TRIANGLE_FAN:
  1412. primCount = elementCount - 2;
  1413. break;
  1414. }
  1415. return primCount;
  1416. }
  1417. //---------------------------------------------------------------------
  1418. bool D3D9RenderSystem::_checkMultiSampleQuality(D3DMULTISAMPLE_TYPE type, DWORD *outQuality, D3DFORMAT format, UINT adapterNum, D3DDEVTYPE deviceType, BOOL fullScreen)
  1419. {
  1420. HRESULT hr;
  1421. hr = mpD3D->CheckDeviceMultiSampleType(
  1422. adapterNum,
  1423. deviceType,
  1424. format,
  1425. fullScreen,
  1426. type,
  1427. outQuality);
  1428. if (SUCCEEDED(hr))
  1429. return true;
  1430. else
  1431. return false;
  1432. }
  1433. //---------------------------------------------------------------------
  1434. RenderSystemCapabilities* D3D9RenderSystem::updateRenderSystemCapabilities(D3D9RenderWindow* renderWindow)
  1435. {
  1436. RenderSystemCapabilities* rsc = mCurrentCapabilities;
  1437. if (rsc == NULL)
  1438. rsc = cm_new<RenderSystemCapabilities>();
  1439. rsc->setCategoryRelevant(CAPS_CATEGORY_D3D9, true);
  1440. rsc->setDriverVersion(mDriverVersion);
  1441. rsc->setDeviceName(mActiveD3DDriver->DriverDescription());
  1442. rsc->setRenderSystemName(getName());
  1443. // Supports fixed-function
  1444. rsc->setCapability(RSC_FIXED_FUNCTION);
  1445. // Init caps to maximum.
  1446. rsc->setCapability(RSC_ANISOTROPY);
  1447. rsc->setCapability(RSC_AUTOMIPMAP);
  1448. rsc->setCapability(RSC_DOT3);
  1449. rsc->setCapability(RSC_CUBEMAPPING);
  1450. rsc->setCapability(RSC_SCISSOR_TEST);
  1451. rsc->setCapability(RSC_TWO_SIDED_STENCIL);
  1452. rsc->setCapability(RSC_STENCIL_WRAP);
  1453. rsc->setCapability(RSC_HWOCCLUSION);
  1454. rsc->setCapability(RSC_USER_CLIP_PLANES);
  1455. rsc->setCapability(RSC_VERTEX_FORMAT_UBYTE4);
  1456. rsc->setCapability(RSC_TEXTURE_3D);
  1457. rsc->setCapability(RSC_NON_POWER_OF_2_TEXTURES);
  1458. rsc->setNonPOW2TexturesLimited(false);
  1459. rsc->setNumMultiRenderTargets(CM_MAX_MULTIPLE_RENDER_TARGETS);
  1460. rsc->setCapability(RSC_MRT_DIFFERENT_BIT_DEPTHS);
  1461. rsc->setCapability(RSC_POINT_SPRITES);
  1462. rsc->setCapability(RSC_POINT_EXTENDED_PARAMETERS);
  1463. rsc->setMaxPointSize(10.0);
  1464. rsc->setCapability(RSC_MIPMAP_LOD_BIAS);
  1465. rsc->setCapability(RSC_PERSTAGECONSTANT);
  1466. rsc->setCapability(RSC_HWSTENCIL);
  1467. rsc->setStencilBufferBitDepth(8);
  1468. rsc->setCapability(RSC_ADVANCED_BLEND_OPERATIONS);
  1469. for (UINT32 i=0; i < mDeviceManager->getDeviceCount(); ++i)
  1470. {
  1471. D3D9Device* device = mDeviceManager->getDevice(i);
  1472. IDirect3DDevice9* d3d9Device = device->getD3D9Device();
  1473. IDirect3DSurface9* pSurf;
  1474. // Check for hardware stencil support
  1475. d3d9Device->GetDepthStencilSurface(&pSurf);
  1476. if (pSurf != NULL)
  1477. {
  1478. D3DSURFACE_DESC surfDesc;
  1479. pSurf->GetDesc(&surfDesc);
  1480. pSurf->Release();
  1481. if (surfDesc.Format != D3DFMT_D15S1 &&
  1482. surfDesc.Format != D3DFMT_D24S8 &&
  1483. surfDesc.Format != D3DFMT_D24X4S4 &&
  1484. surfDesc.Format != D3DFMT_D24FS8)
  1485. rsc->unsetCapability(RSC_HWSTENCIL);
  1486. }
  1487. // Check for hardware occlusion support
  1488. HRESULT hr = d3d9Device->CreateQuery(D3DQUERYTYPE_OCCLUSION, NULL);
  1489. if (FAILED(hr))
  1490. rsc->unsetCapability(RSC_HWOCCLUSION);
  1491. }
  1492. // Update RS caps using the minimum value found in adapter list.
  1493. for (unsigned int i=0; i < mDriverList->count(); ++i)
  1494. {
  1495. D3D9Driver* pCurDriver = mDriverList->item(i);
  1496. const D3DCAPS9& rkCurCaps = pCurDriver->getD3D9DeviceCaps();
  1497. rsc->setNumTextureUnits(GPT_FRAGMENT_PROGRAM, 16); // We don't support anything lower than SM3, and 16 is the sampler count determined by the specification
  1498. rsc->setMaxBoundVertexBuffers(static_cast<UINT32>(rkCurCaps.MaxStreams));
  1499. // Check for Anisotropy.
  1500. if (rkCurCaps.MaxAnisotropy <= 1)
  1501. rsc->unsetCapability(RSC_ANISOTROPY);
  1502. // Check automatic mipmap generation.
  1503. if ((rkCurCaps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP) == 0)
  1504. rsc->unsetCapability(RSC_AUTOMIPMAP);
  1505. // Check Dot product 3.
  1506. if ((rkCurCaps.TextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3) == 0)
  1507. rsc->unsetCapability(RSC_DOT3);
  1508. // Scissor test
  1509. if ((rkCurCaps.RasterCaps & D3DPRASTERCAPS_SCISSORTEST) == 0)
  1510. rsc->unsetCapability(RSC_SCISSOR_TEST);
  1511. // Two-sided stencil
  1512. if ((rkCurCaps.StencilCaps & D3DSTENCILCAPS_TWOSIDED) == 0)
  1513. rsc->unsetCapability(RSC_TWO_SIDED_STENCIL);
  1514. // stencil wrap
  1515. if ((rkCurCaps.StencilCaps & D3DSTENCILCAPS_INCR) == 0 ||
  1516. (rkCurCaps.StencilCaps & D3DSTENCILCAPS_DECR) == 0)
  1517. rsc->unsetCapability(RSC_STENCIL_WRAP);
  1518. // User clip planes
  1519. if (rkCurCaps.MaxUserClipPlanes == 0)
  1520. rsc->unsetCapability(RSC_USER_CLIP_PLANES);
  1521. // UBYTE4 type?
  1522. if ((rkCurCaps.DeclTypes & D3DDTCAPS_UBYTE4) == 0)
  1523. rsc->unsetCapability(RSC_VERTEX_FORMAT_UBYTE4);
  1524. // Check cube map support.
  1525. if ((rkCurCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP) == 0)
  1526. rsc->unsetCapability(RSC_CUBEMAPPING);
  1527. // 3D textures?
  1528. if ((rkCurCaps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP) == 0)
  1529. rsc->unsetCapability(RSC_TEXTURE_3D);
  1530. if (rkCurCaps.TextureCaps & D3DPTEXTURECAPS_POW2)
  1531. {
  1532. // Conditional support for non POW2
  1533. if (rkCurCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)
  1534. rsc->setNonPOW2TexturesLimited(true);
  1535. // Only power of 2 supported.
  1536. else
  1537. rsc->unsetCapability(RSC_NON_POWER_OF_2_TEXTURES);
  1538. }
  1539. // Number of render targets
  1540. if (rkCurCaps.NumSimultaneousRTs < rsc->getNumMultiRenderTargets())
  1541. {
  1542. rsc->setNumMultiRenderTargets(std::min((UINT16)rkCurCaps.NumSimultaneousRTs, (UINT16)CM_MAX_MULTIPLE_RENDER_TARGETS));
  1543. }
  1544. if((rkCurCaps.PrimitiveMiscCaps & D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS) == 0)
  1545. {
  1546. rsc->unsetCapability(RSC_MRT_DIFFERENT_BIT_DEPTHS);
  1547. }
  1548. // Point sprites
  1549. if (rkCurCaps.MaxPointSize <= 1.0f)
  1550. {
  1551. rsc->unsetCapability(RSC_POINT_SPRITES);
  1552. // sprites and extended parameters go together in D3D
  1553. rsc->unsetCapability(RSC_POINT_EXTENDED_PARAMETERS);
  1554. }
  1555. // Take the minimum point size.
  1556. if (rkCurCaps.MaxPointSize < rsc->getMaxPointSize())
  1557. rsc->setMaxPointSize(rkCurCaps.MaxPointSize);
  1558. // Mipmap LOD biasing?
  1559. if ((rkCurCaps.RasterCaps & D3DPRASTERCAPS_MIPMAPLODBIAS) == 0)
  1560. rsc->unsetCapability(RSC_MIPMAP_LOD_BIAS);
  1561. // Do we support per-stage src_manual constants?
  1562. // HACK - ATI drivers seem to be buggy and don't support per-stage constants properly?
  1563. // TODO: move this to RSC
  1564. if((rkCurCaps.PrimitiveMiscCaps & D3DPMISCCAPS_PERSTAGECONSTANT) == 0)
  1565. rsc->unsetCapability(RSC_PERSTAGECONSTANT);
  1566. // Advanced blend operations? min max subtract rev
  1567. if((rkCurCaps.PrimitiveMiscCaps & D3DPMISCCAPS_BLENDOP) == 0)
  1568. rsc->unsetCapability(RSC_ADVANCED_BLEND_OPERATIONS);
  1569. }
  1570. // Blending between stages supported
  1571. rsc->setCapability(RSC_BLENDING);
  1572. // We always support compression, D3DX will decompress if device does not support
  1573. rsc->setCapability(RSC_TEXTURE_COMPRESSION);
  1574. rsc->setCapability(RSC_TEXTURE_COMPRESSION_DXT);
  1575. // We always support VBOs
  1576. rsc->setCapability(RSC_VBO);
  1577. convertVertexShaderCaps(rsc);
  1578. convertPixelShaderCaps(rsc);
  1579. // Adapter details
  1580. const D3DADAPTER_IDENTIFIER9& adapterID = mActiveD3DDriver->getAdapterIdentifier();
  1581. // determine vendor
  1582. // Full list of vendors here: http://www.pcidatabase.com/vendors.php?sort=id
  1583. switch(adapterID.VendorId)
  1584. {
  1585. case 0x10DE:
  1586. rsc->setVendor(GPU_NVIDIA);
  1587. break;
  1588. case 0x1002:
  1589. rsc->setVendor(GPU_ATI);
  1590. break;
  1591. case 0x163C:
  1592. case 0x8086:
  1593. rsc->setVendor(GPU_INTEL);
  1594. break;
  1595. case 0x5333:
  1596. rsc->setVendor(GPU_S3);
  1597. break;
  1598. case 0x3D3D:
  1599. rsc->setVendor(GPU_3DLABS);
  1600. break;
  1601. case 0x102B:
  1602. rsc->setVendor(GPU_MATROX);
  1603. break;
  1604. case 0x1039:
  1605. rsc->setVendor(GPU_SIS);
  1606. break;
  1607. default:
  1608. rsc->setVendor(GPU_UNKNOWN);
  1609. break;
  1610. };
  1611. // Infinite projection?
  1612. // We have no capability for this, so we have to base this on our
  1613. // experience and reports from users
  1614. // Non-vertex program capable hardware does not appear to support it
  1615. if (rsc->hasCapability(RSC_VERTEX_PROGRAM))
  1616. {
  1617. // GeForce4 Ti (and presumably GeForce3) does not
  1618. // render infinite projection properly, even though it does in GL
  1619. // So exclude all cards prior to the FX range from doing infinite
  1620. if (rsc->getVendor() != GPU_NVIDIA || // not nVidia
  1621. !((adapterID.DeviceId >= 0x200 && adapterID.DeviceId <= 0x20F) || //gf3
  1622. (adapterID.DeviceId >= 0x250 && adapterID.DeviceId <= 0x25F) || //gf4ti
  1623. (adapterID.DeviceId >= 0x280 && adapterID.DeviceId <= 0x28F) || //gf4ti
  1624. (adapterID.DeviceId >= 0x170 && adapterID.DeviceId <= 0x18F) || //gf4 go
  1625. (adapterID.DeviceId >= 0x280 && adapterID.DeviceId <= 0x28F))) //gf4ti go
  1626. {
  1627. rsc->setCapability(RSC_INFINITE_FAR_PLANE);
  1628. }
  1629. }
  1630. // We always support rendertextures bigger than the frame buffer
  1631. rsc->setCapability(RSC_HWRENDER_TO_TEXTURE);
  1632. // Determine if any floating point texture format is supported
  1633. D3DFORMAT floatFormats[6] = {D3DFMT_R16F, D3DFMT_G16R16F,
  1634. D3DFMT_A16B16G16R16F, D3DFMT_R32F, D3DFMT_G32R32F,
  1635. D3DFMT_A32B32G32R32F};
  1636. IDirect3DSurface9* bbSurf;
  1637. renderWindow->getCustomAttribute("DDBACKBUFFER", &bbSurf);
  1638. D3DSURFACE_DESC bbSurfDesc;
  1639. bbSurf->GetDesc(&bbSurfDesc);
  1640. for (int i = 0; i < 6; ++i)
  1641. {
  1642. if (SUCCEEDED(mpD3D->CheckDeviceFormat(mActiveD3DDriver->getAdapterNumber(),
  1643. D3DDEVTYPE_HAL, bbSurfDesc.Format,
  1644. 0, D3DRTYPE_TEXTURE, floatFormats[i])))
  1645. {
  1646. rsc->setCapability(RSC_TEXTURE_FLOAT);
  1647. break;
  1648. }
  1649. }
  1650. // Vertex textures
  1651. if (rsc->isShaderProfileSupported("vs_3_0"))
  1652. {
  1653. rsc->setCapability(RSC_VERTEX_TEXTURE_FETCH);
  1654. rsc->setNumTextureUnits(GPT_VERTEX_PROGRAM, 4);
  1655. rsc->setNumCombinedTextureUnits(rsc->getNumTextureUnits(GPT_FRAGMENT_PROGRAM) +
  1656. rsc->getNumTextureUnits(GPT_VERTEX_PROGRAM));
  1657. }
  1658. else
  1659. {
  1660. rsc->setNumCombinedTextureUnits(rsc->getNumTextureUnits(GPT_FRAGMENT_PROGRAM));
  1661. }
  1662. // Check alpha to coverage support
  1663. // this varies per vendor! But at least SM3 is required
  1664. if (rsc->isShaderProfileSupported("ps_3_0"))
  1665. {
  1666. // NVIDIA needs a separate check
  1667. if (rsc->getVendor() == GPU_NVIDIA)
  1668. {
  1669. if (mpD3D->CheckDeviceFormat(
  1670. D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,D3DRTYPE_SURFACE,
  1671. (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C')) == S_OK)
  1672. {
  1673. rsc->setCapability(RSC_ALPHA_TO_COVERAGE);
  1674. }
  1675. }
  1676. else if (rsc->getVendor() == GPU_ATI)
  1677. {
  1678. // There is no check on ATI, we have to assume SM3 == support
  1679. rsc->setCapability(RSC_ALPHA_TO_COVERAGE);
  1680. }
  1681. // no other cards have Dx9 hacks for alpha to coverage, as far as I know
  1682. }
  1683. if (mCurrentCapabilities == NULL)
  1684. {
  1685. mCurrentCapabilities = rsc;
  1686. mCurrentCapabilities->addShaderProfile("hlsl");
  1687. mCurrentCapabilities->addShaderProfile("cg");
  1688. initialiseFromRenderSystemCapabilities(mCurrentCapabilities);
  1689. }
  1690. return rsc;
  1691. }
  1692. //---------------------------------------------------------------------
  1693. void D3D9RenderSystem::convertVertexShaderCaps(RenderSystemCapabilities* rsc) const
  1694. {
  1695. UINT16 major = 0xFF;
  1696. UINT16 minor = 0xFF;
  1697. D3DCAPS9 minVSCaps;
  1698. // Find the device with the lowest vertex shader caps.
  1699. for (unsigned int i=0; i < mDriverList->count(); ++i)
  1700. {
  1701. D3D9Driver* pCurDriver = mDriverList->item(i);
  1702. const D3DCAPS9& rkCurCaps = pCurDriver->getD3D9DeviceCaps();
  1703. UINT16 currMajor = static_cast<UINT16>((rkCurCaps.VertexShaderVersion & 0x0000FF00) >> 8);
  1704. UINT16 currMinor = static_cast<UINT16>(rkCurCaps.VertexShaderVersion & 0x000000FF);
  1705. if (currMajor < major)
  1706. {
  1707. major = currMajor;
  1708. minor = currMinor;
  1709. minVSCaps = rkCurCaps;
  1710. }
  1711. else if (currMajor == major && currMinor < minor)
  1712. {
  1713. minor = currMinor;
  1714. minVSCaps = rkCurCaps;
  1715. }
  1716. }
  1717. // In case we didn't found any vertex shader support
  1718. // try the IDirect3DDevice9 caps instead of the IDirect3D9
  1719. // software vertex processing is reported there
  1720. if (major == 0 && minor == 0)
  1721. {
  1722. IDirect3DDevice9* lpD3DDevice9 = getActiveD3D9Device();
  1723. D3DCAPS9 d3dDeviceCaps9;
  1724. lpD3DDevice9->GetDeviceCaps(&d3dDeviceCaps9);
  1725. major = static_cast<UINT16>((d3dDeviceCaps9.VertexShaderVersion & 0x0000FF00) >> 8);
  1726. minor = static_cast<UINT16>(d3dDeviceCaps9.VertexShaderVersion & 0x000000FF);
  1727. }
  1728. bool vs2x = false;
  1729. bool vs2a = false;
  1730. // Special case detection for vs_2_x/a support
  1731. if (major >= 2)
  1732. {
  1733. if ((minVSCaps.VS20Caps.Caps & D3DVS20CAPS_PREDICATION) &&
  1734. (minVSCaps.VS20Caps.DynamicFlowControlDepth > 0) &&
  1735. (minVSCaps.VS20Caps.NumTemps >= 12))
  1736. {
  1737. vs2x = true;
  1738. }
  1739. if ((minVSCaps.VS20Caps.Caps & D3DVS20CAPS_PREDICATION) &&
  1740. (minVSCaps.VS20Caps.DynamicFlowControlDepth > 0) &&
  1741. (minVSCaps.VS20Caps.NumTemps >= 13))
  1742. {
  1743. vs2a = true;
  1744. }
  1745. }
  1746. // Populate max param count
  1747. switch (major)
  1748. {
  1749. case 1:
  1750. // No boolean params allowed
  1751. rsc->setVertexProgramConstantBoolCount(0);
  1752. // No integer params allowed
  1753. rsc->setVertexProgramConstantIntCount(0);
  1754. // float params, always 4D
  1755. rsc->setVertexProgramConstantFloatCount(static_cast<UINT16>(minVSCaps.MaxVertexShaderConst));
  1756. break;
  1757. case 2:
  1758. // 16 boolean params allowed
  1759. rsc->setVertexProgramConstantBoolCount(16);
  1760. // 16 integer params allowed, 4D
  1761. rsc->setVertexProgramConstantIntCount(16);
  1762. // float params, always 4D
  1763. rsc->setVertexProgramConstantFloatCount(static_cast<UINT16>(minVSCaps.MaxVertexShaderConst));
  1764. break;
  1765. case 3:
  1766. // 16 boolean params allowed
  1767. rsc->setVertexProgramConstantBoolCount(16);
  1768. // 16 integer params allowed, 4D
  1769. rsc->setVertexProgramConstantIntCount(16);
  1770. // float params, always 4D
  1771. rsc->setVertexProgramConstantFloatCount(static_cast<UINT16>(minVSCaps.MaxVertexShaderConst));
  1772. break;
  1773. }
  1774. // populate syntax codes in program manager (no breaks in this one so it falls through)
  1775. switch(major)
  1776. {
  1777. case 3:
  1778. rsc->addShaderProfile("vs_3_0");
  1779. rsc->addGpuProgramProfile(GPP_VS_3_0, "vs_3_0");
  1780. case 2:
  1781. if (vs2x)
  1782. {
  1783. rsc->addShaderProfile("vs_2_x");
  1784. rsc->addGpuProgramProfile(GPP_VS_2_x, "vs_2_x");
  1785. }
  1786. if (vs2a)
  1787. {
  1788. rsc->addShaderProfile("vs_2_a");
  1789. rsc->addGpuProgramProfile(GPP_VS_2_a, "vs_2_a");
  1790. }
  1791. rsc->addShaderProfile("vs_2_0");
  1792. rsc->addGpuProgramProfile(GPP_VS_2_0, "vs_2_0");
  1793. case 1:
  1794. rsc->addShaderProfile("vs_1_1");
  1795. rsc->addGpuProgramProfile(GPP_VS_1_1, "vs_1_1");
  1796. rsc->setCapability(RSC_VERTEX_PROGRAM);
  1797. }
  1798. }
  1799. //---------------------------------------------------------------------
  1800. void D3D9RenderSystem::convertPixelShaderCaps(RenderSystemCapabilities* rsc) const
  1801. {
  1802. UINT16 major = 0xFF;
  1803. UINT16 minor = 0xFF;
  1804. D3DCAPS9 minPSCaps;
  1805. // Find the device with the lowest pixel shader caps.
  1806. for (unsigned int i=0; i < mDriverList->count(); ++i)
  1807. {
  1808. D3D9Driver* pCurDriver = mDriverList->item(i);
  1809. const D3DCAPS9& currCaps = pCurDriver->getD3D9DeviceCaps();
  1810. UINT16 currMajor = static_cast<UINT16>((currCaps.PixelShaderVersion & 0x0000FF00) >> 8);
  1811. UINT16 currMinor = static_cast<UINT16>(currCaps.PixelShaderVersion & 0x000000FF);
  1812. if (currMajor < major)
  1813. {
  1814. major = currMajor;
  1815. minor = currMinor;
  1816. minPSCaps = currCaps;
  1817. }
  1818. else if (currMajor == major && currMinor < minor)
  1819. {
  1820. minor = currMinor;
  1821. minPSCaps = currCaps;
  1822. }
  1823. }
  1824. bool ps2a = false;
  1825. bool ps2b = false;
  1826. bool ps2x = false;
  1827. // Special case detection for ps_2_x/a/b support
  1828. if (major >= 2)
  1829. {
  1830. if ((minPSCaps.PS20Caps.Caps & D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT) &&
  1831. (minPSCaps.PS20Caps.NumTemps >= 32))
  1832. {
  1833. ps2b = true;
  1834. }
  1835. if ((minPSCaps.PS20Caps.Caps & D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT) &&
  1836. (minPSCaps.PS20Caps.Caps & D3DPS20CAPS_NODEPENDENTREADLIMIT) &&
  1837. (minPSCaps.PS20Caps.Caps & D3DPS20CAPS_ARBITRARYSWIZZLE) &&
  1838. (minPSCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) &&
  1839. (minPSCaps.PS20Caps.Caps & D3DPS20CAPS_PREDICATION) &&
  1840. (minPSCaps.PS20Caps.NumTemps >= 22))
  1841. {
  1842. ps2a = true;
  1843. }
  1844. // Does this enough?
  1845. if (ps2a || ps2b)
  1846. {
  1847. ps2x = true;
  1848. }
  1849. }
  1850. switch (major)
  1851. {
  1852. case 1:
  1853. // no boolean params allowed
  1854. rsc->setFragmentProgramConstantBoolCount(0);
  1855. // no integer params allowed
  1856. rsc->setFragmentProgramConstantIntCount(0);
  1857. // float params, always 4D
  1858. // NB in ps_1_x these are actually stored as fixed point values,
  1859. // but they are entered as floats
  1860. rsc->setFragmentProgramConstantFloatCount(8);
  1861. break;
  1862. case 2:
  1863. // 16 boolean params allowed
  1864. rsc->setFragmentProgramConstantBoolCount(16);
  1865. // 16 integer params allowed, 4D
  1866. rsc->setFragmentProgramConstantIntCount(16);
  1867. // float params, always 4D
  1868. rsc->setFragmentProgramConstantFloatCount(32);
  1869. break;
  1870. case 3:
  1871. // 16 boolean params allowed
  1872. rsc->setFragmentProgramConstantBoolCount(16);
  1873. // 16 integer params allowed, 4D
  1874. rsc->setFragmentProgramConstantIntCount(16);
  1875. // float params, always 4D
  1876. rsc->setFragmentProgramConstantFloatCount(224);
  1877. break;
  1878. }
  1879. // populate syntax codes in program manager (no breaks in this one so it falls through)
  1880. switch(major)
  1881. {
  1882. case 3:
  1883. if (minor > 0)
  1884. {
  1885. rsc->addShaderProfile("ps_3_x");
  1886. rsc->addGpuProgramProfile(GPP_PS_3_x, "ps_3_x");
  1887. }
  1888. rsc->addShaderProfile("ps_3_0");
  1889. rsc->addGpuProgramProfile(GPP_PS_3_0, "ps_3_0");
  1890. case 2:
  1891. if (ps2x)
  1892. {
  1893. rsc->addShaderProfile("ps_2_x");
  1894. rsc->addGpuProgramProfile(GPP_PS_2_x, "ps_2_x");
  1895. }
  1896. if (ps2a)
  1897. {
  1898. rsc->addShaderProfile("ps_2_a");
  1899. rsc->addGpuProgramProfile(GPP_PS_2_a, "ps_2_a");
  1900. }
  1901. if (ps2b)
  1902. {
  1903. rsc->addShaderProfile("ps_2_b");
  1904. rsc->addGpuProgramProfile(GPP_PS_2_b, "ps_2_b");
  1905. }
  1906. rsc->addShaderProfile("ps_2_0");
  1907. rsc->addGpuProgramProfile(GPP_PS_2_0, "ps_2_0");
  1908. case 1:
  1909. if (major > 1 || minor >= 4)
  1910. {
  1911. rsc->addShaderProfile("ps_1_4");
  1912. rsc->addGpuProgramProfile(GPP_PS_1_4, "ps_1_4");
  1913. }
  1914. if (major > 1 || minor >= 3)
  1915. {
  1916. rsc->addShaderProfile("ps_1_3");
  1917. rsc->addGpuProgramProfile(GPP_PS_1_3, "ps_1_3");
  1918. }
  1919. if (major > 1 || minor >= 2)
  1920. {
  1921. rsc->addShaderProfile("ps_1_2");
  1922. rsc->addGpuProgramProfile(GPP_PS_1_2, "ps_1_2");
  1923. }
  1924. rsc->addShaderProfile("ps_1_1");
  1925. rsc->addGpuProgramProfile(GPP_PS_1_1, "ps_1_1");
  1926. rsc->setCapability(RSC_FRAGMENT_PROGRAM);
  1927. }
  1928. }
  1929. //-----------------------------------------------------------------------
  1930. bool D3D9RenderSystem::checkVertexTextureFormats(D3D9RenderWindow* renderWindow) const
  1931. {
  1932. bool anySupported = false;
  1933. IDirect3DSurface9* bbSurf;
  1934. renderWindow->getCustomAttribute("DDBACKBUFFER", &bbSurf);
  1935. D3DSURFACE_DESC bbSurfDesc;
  1936. bbSurf->GetDesc(&bbSurfDesc);
  1937. for (UINT32 ipf = 1; ipf < static_cast<UINT32>(PF_COUNT); ++ipf)
  1938. {
  1939. PixelFormat pf = (PixelFormat)ipf;
  1940. D3DFORMAT fmt =
  1941. D3D9Mappings::_getPF(D3D9Mappings::_getClosestSupportedPF(pf));
  1942. if (SUCCEEDED(mpD3D->CheckDeviceFormat(
  1943. mActiveD3DDriver->getAdapterNumber(), D3DDEVTYPE_HAL, bbSurfDesc.Format,
  1944. D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, fmt)))
  1945. {
  1946. // cool, at least one supported
  1947. anySupported = true;
  1948. }
  1949. }
  1950. return anySupported;
  1951. }
  1952. //-----------------------------------------------------------------------
  1953. void D3D9RenderSystem::initialiseFromRenderSystemCapabilities(RenderSystemCapabilities* caps)
  1954. {
  1955. if (caps->getRenderSystemName() != getName())
  1956. {
  1957. CM_EXCEPT(InvalidParametersException,
  1958. "Trying to initialize D3D9RenderSystem from RenderSystemCapabilities that do not support Direct3D9");
  1959. }
  1960. if (caps->isShaderProfileSupported("hlsl"))
  1961. HighLevelGpuProgramManager::instance().addFactory(mHLSLProgramFactory);
  1962. if (caps->isShaderProfileSupported("cg"))
  1963. HighLevelGpuProgramManager::instance().addFactory(mCgProgramFactory);
  1964. mNumTexStages = caps->getNumCombinedTextureUnits();
  1965. mTexStageDesc = cm_newN<sD3DTextureStageDesc>(mNumTexStages);
  1966. // set stages desc. to defaults
  1967. for (UINT32 n = 0; n < mNumTexStages; n++)
  1968. {
  1969. mTexStageDesc[n].coordIndex = 0;
  1970. mTexStageDesc[n].texType = D3D9Mappings::D3D_TEX_TYPE_NORMAL;
  1971. mTexStageDesc[n].pTex = 0;
  1972. mTexStageDesc[n].pVertexTex = 0;
  1973. }
  1974. }
  1975. //-----------------------------------------------------------------------
  1976. bool D3D9RenderSystem::checkTextureFilteringSupported(TextureType ttype, PixelFormat format, int usage)
  1977. {
  1978. // Gets D3D format
  1979. D3DFORMAT d3dPF = D3D9Mappings::_getPF(format);
  1980. if (d3dPF == D3DFMT_UNKNOWN)
  1981. return false;
  1982. for (UINT32 i = 0; i < mDeviceManager->getDeviceCount(); ++i)
  1983. {
  1984. D3D9Device* currDevice = mDeviceManager->getDevice(i);
  1985. const D3D9RenderWindow* currDevicePrimaryWindow = currDevice->getPrimaryWindow();
  1986. IDirect3DSurface9* pSurface = currDevicePrimaryWindow->_getRenderSurface();
  1987. D3DSURFACE_DESC srfDesc;
  1988. // Get surface desc
  1989. if (FAILED(pSurface->GetDesc(&srfDesc)))
  1990. return false;
  1991. // Calculate usage
  1992. DWORD d3dusage = D3DUSAGE_QUERY_FILTER;
  1993. if (usage & TU_RENDERTARGET)
  1994. d3dusage |= D3DUSAGE_RENDERTARGET;
  1995. if (usage & TU_DEPTHSTENCIL)
  1996. d3dusage |= D3DUSAGE_DEPTHSTENCIL;
  1997. if (usage & TU_DYNAMIC)
  1998. d3dusage |= D3DUSAGE_DYNAMIC;
  1999. // Detect resource type
  2000. D3DRESOURCETYPE rtype;
  2001. switch(ttype)
  2002. {
  2003. case TEX_TYPE_1D:
  2004. case TEX_TYPE_2D:
  2005. rtype = D3DRTYPE_TEXTURE;
  2006. break;
  2007. case TEX_TYPE_3D:
  2008. rtype = D3DRTYPE_VOLUMETEXTURE;
  2009. break;
  2010. case TEX_TYPE_CUBE_MAP:
  2011. rtype = D3DRTYPE_CUBETEXTURE;
  2012. break;
  2013. default:
  2014. return false;
  2015. }
  2016. HRESULT hr = mpD3D->CheckDeviceFormat(
  2017. currDevice->getAdapterNumber(),
  2018. currDevice->getDeviceType(),
  2019. srfDesc.Format,
  2020. d3dusage,
  2021. rtype,
  2022. d3dPF);
  2023. if (FAILED(hr))
  2024. return false;
  2025. }
  2026. return true;
  2027. }
  2028. //---------------------------------------------------------------------
  2029. String D3D9RenderSystem::getErrorDescription( long errorNumber ) const
  2030. {
  2031. const String errMsg = DXGetErrorDescription( errorNumber );
  2032. return errMsg;
  2033. }
  2034. // ------------------------------------------------------------------
  2035. void D3D9RenderSystem::setClipPlane (UINT16 index, float A, float B, float C, float D)
  2036. {
  2037. float plane[4] = { A, B, C, D };
  2038. getActiveD3D9Device()->SetClipPlane (index, plane);
  2039. }
  2040. // ------------------------------------------------------------------
  2041. void D3D9RenderSystem::enableClipPlane (UINT16 index, bool enable)
  2042. {
  2043. DWORD prev;
  2044. getActiveD3D9Device()->GetRenderState(D3DRS_CLIPPLANEENABLE, &prev);
  2045. __SetRenderState(D3DRS_CLIPPLANEENABLE, enable?
  2046. (prev | (1 << index)) : (prev & ~(1 << index)));
  2047. }
  2048. //---------------------------------------------------------------------
  2049. void D3D9RenderSystem::notifyOnDeviceLost(D3D9Device* device)
  2050. {
  2051. }
  2052. //---------------------------------------------------------------------
  2053. void D3D9RenderSystem::notifyOnDeviceReset(D3D9Device* device)
  2054. {
  2055. // Reset state attributes.
  2056. mVertexProgramBound = false;
  2057. mFragmentProgramBound = false;
  2058. }
  2059. //---------------------------------------------------------------------
  2060. void D3D9RenderSystem::determineFSAASettings(IDirect3DDevice9* d3d9Device,
  2061. UINT32 fsaa, const String& fsaaHint, D3DFORMAT d3dPixelFormat,
  2062. bool fullScreen, D3DMULTISAMPLE_TYPE *outMultisampleType, DWORD *outMultisampleQuality) const
  2063. {
  2064. bool ok = false;
  2065. bool qualityHint = fsaaHint.find("Quality") != String::npos;
  2066. UINT32 origFSAA = fsaa;
  2067. D3D9DriverList* driverList = getDirect3DDrivers();
  2068. D3D9Driver* deviceDriver = mActiveD3DDriver;
  2069. D3D9Device* device = mDeviceManager->getDeviceFromD3D9Device(d3d9Device);
  2070. for (UINT32 i = 0; i < driverList->count(); ++i)
  2071. {
  2072. D3D9Driver* currDriver = driverList->item(i);
  2073. if (currDriver->getAdapterNumber() == device->getAdapterNumber())
  2074. {
  2075. deviceDriver = currDriver;
  2076. break;
  2077. }
  2078. }
  2079. bool tryCSAA = false;
  2080. // NVIDIA, prefer CSAA if available for 8+
  2081. // it would be tempting to use getCapabilities()->getVendor() == GPU_NVIDIA but
  2082. // if this is the first window, caps will not be initialised yet
  2083. if (deviceDriver->getAdapterIdentifier().VendorId == 0x10DE &&
  2084. fsaa >= 8)
  2085. {
  2086. tryCSAA = true;
  2087. }
  2088. while (!ok)
  2089. {
  2090. // Deal with special cases
  2091. if (tryCSAA)
  2092. {
  2093. // see http://developer.nvidia.com/object/coverage-sampled-aa.html
  2094. switch(fsaa)
  2095. {
  2096. case 8:
  2097. if (qualityHint)
  2098. {
  2099. *outMultisampleType = D3DMULTISAMPLE_8_SAMPLES;
  2100. *outMultisampleQuality = 0;
  2101. }
  2102. else
  2103. {
  2104. *outMultisampleType = D3DMULTISAMPLE_4_SAMPLES;
  2105. *outMultisampleQuality = 2;
  2106. }
  2107. break;
  2108. case 16:
  2109. if (qualityHint)
  2110. {
  2111. *outMultisampleType = D3DMULTISAMPLE_8_SAMPLES;
  2112. *outMultisampleQuality = 2;
  2113. }
  2114. else
  2115. {
  2116. *outMultisampleType = D3DMULTISAMPLE_4_SAMPLES;
  2117. *outMultisampleQuality = 4;
  2118. }
  2119. break;
  2120. }
  2121. }
  2122. else // !CSAA
  2123. {
  2124. *outMultisampleType = (D3DMULTISAMPLE_TYPE)fsaa;
  2125. *outMultisampleQuality = 0;
  2126. }
  2127. HRESULT hr;
  2128. DWORD outQuality;
  2129. hr = mpD3D->CheckDeviceMultiSampleType(
  2130. deviceDriver->getAdapterNumber(),
  2131. D3DDEVTYPE_HAL,
  2132. d3dPixelFormat,
  2133. fullScreen,
  2134. *outMultisampleType,
  2135. &outQuality);
  2136. if (SUCCEEDED(hr) &&
  2137. (!tryCSAA || outQuality > *outMultisampleQuality))
  2138. {
  2139. ok = true;
  2140. }
  2141. else
  2142. {
  2143. // downgrade
  2144. if (tryCSAA && fsaa == 8)
  2145. {
  2146. // for CSAA, we'll try downgrading with quality mode at all samples.
  2147. // then try without quality, then drop CSAA
  2148. if (qualityHint)
  2149. {
  2150. // drop quality first
  2151. qualityHint = false;
  2152. }
  2153. else
  2154. {
  2155. // drop CSAA entirely
  2156. tryCSAA = false;
  2157. }
  2158. // return to original requested samples
  2159. fsaa = origFSAA;
  2160. }
  2161. else
  2162. {
  2163. // drop samples
  2164. --fsaa;
  2165. if (fsaa == 1)
  2166. {
  2167. // ran out of options, no FSAA
  2168. fsaa = 0;
  2169. ok = true;
  2170. }
  2171. }
  2172. }
  2173. } // while !ok
  2174. }
  2175. //---------------------------------------------------------------------
  2176. RenderSystemCapabilities* D3D9RenderSystem::createRenderSystemCapabilities() const
  2177. {
  2178. return mCurrentCapabilities;
  2179. }
  2180. //---------------------------------------------------------------------
  2181. void D3D9RenderSystem::setClipPlanesImpl(const PlaneList& clipPlanes)
  2182. {
  2183. size_t i;
  2184. size_t numClipPlanes;
  2185. D3DXPLANE dx9ClipPlane;
  2186. DWORD mask = 0;
  2187. HRESULT hr;
  2188. numClipPlanes = clipPlanes.size();
  2189. for (i = 0; i < numClipPlanes; ++i)
  2190. {
  2191. const Plane& plane = clipPlanes[i];
  2192. dx9ClipPlane.a = plane.normal.x;
  2193. dx9ClipPlane.b = plane.normal.y;
  2194. dx9ClipPlane.c = plane.normal.z;
  2195. dx9ClipPlane.d = plane.d;
  2196. // TODO Low priority - Transform planes to clip space?
  2197. hr = getActiveD3D9Device()->SetClipPlane(static_cast<DWORD>(i), dx9ClipPlane);
  2198. if (FAILED(hr))
  2199. {
  2200. CM_EXCEPT(RenderingAPIException, "Unable to set clip plane");
  2201. }
  2202. mask |= (1 << i);
  2203. }
  2204. hr = __SetRenderState(D3DRS_CLIPPLANEENABLE, mask);
  2205. if (FAILED(hr))
  2206. {
  2207. CM_EXCEPT(RenderingAPIException, "Unable to set render state for clip planes");
  2208. }
  2209. }
  2210. //---------------------------------------------------------------------
  2211. HRESULT D3D9RenderSystem::__SetRenderState(D3DRENDERSTATETYPE state, DWORD value)
  2212. {
  2213. HRESULT hr;
  2214. DWORD oldVal;
  2215. if ( FAILED( hr = getActiveD3D9Device()->GetRenderState(state, &oldVal) ) )
  2216. return hr;
  2217. if ( oldVal == value )
  2218. return D3D_OK;
  2219. else
  2220. return getActiveD3D9Device()->SetRenderState(state, value);
  2221. }
  2222. //---------------------------------------------------------------------
  2223. HRESULT D3D9RenderSystem::__SetSamplerState(DWORD sampler, D3DSAMPLERSTATETYPE type, DWORD value)
  2224. {
  2225. HRESULT hr;
  2226. DWORD oldVal;
  2227. if ( FAILED( hr = getActiveD3D9Device()->GetSamplerState(sampler, type, &oldVal) ) )
  2228. return hr;
  2229. if ( oldVal == value )
  2230. return D3D_OK;
  2231. else
  2232. return getActiveD3D9Device()->SetSamplerState(sampler, type, value);
  2233. }
  2234. //---------------------------------------------------------------------
  2235. HRESULT D3D9RenderSystem::__SetTextureStageState(DWORD stage, D3DTEXTURESTAGESTATETYPE type, DWORD value)
  2236. {
  2237. HRESULT hr;
  2238. DWORD oldVal;
  2239. // can only set fixed-function texture stage state
  2240. if (stage < 8)
  2241. {
  2242. if ( FAILED( hr = getActiveD3D9Device()->GetTextureStageState(stage, type, &oldVal) ) )
  2243. return hr;
  2244. if ( oldVal == value )
  2245. return D3D_OK;
  2246. else
  2247. return getActiveD3D9Device()->SetTextureStageState(stage, type, value);
  2248. }
  2249. else
  2250. {
  2251. return D3D_OK;
  2252. }
  2253. }
  2254. //---------------------------------------------------------------------
  2255. DWORD D3D9RenderSystem::_getCurrentAnisotropy(UINT32 unit)
  2256. {
  2257. DWORD oldVal;
  2258. getActiveD3D9Device()->GetSamplerState(static_cast<DWORD>(unit), D3DSAMP_MAXANISOTROPY, &oldVal);
  2259. return oldVal;
  2260. }
  2261. }