PageRenderTime 50ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Device.cpp

https://bitbucket.org/ayufan/ayuine2b
C++ | 893 lines | 555 code | 155 blank | 183 comment | 108 complexity | 2340f5d57ec10150bc66c068e0eeeb28 MD5 | raw file
  1. //------------------------------------//
  2. //
  3. // Device.cpp
  4. //
  5. // Author: ayufan (ayufan[at]o2.pl)
  6. // Project: ayuine2
  7. // Date: 2006-7-31
  8. //
  9. //------------------------------------//
  10. #include "StdAfx.hpp"
  11. namespace ayuine
  12. {
  13. //------------------------------------//
  14. // Device: Functions
  15. bool deviceObjectSorter(DeviceObject *a, DeviceObject *b) {
  16. return a->type() < b->type();
  17. }
  18. //------------------------------------//
  19. // Device: Constructor
  20. Device::Device() : _deviceObjects(nullptr) {
  21. HRESULT hr;
  22. // Device Fields
  23. memset(&_d3dCaps, 0, sizeof(_d3dCaps));
  24. memset(&_d3dpp, 0, sizeof(_d3dpp));
  25. _d3d9 = nullptr;
  26. _d3dDev = nullptr;
  27. _renderTarget = nullptr;
  28. _depthTarget = nullptr;
  29. _query = nullptr;
  30. _defaultTexture = nullptr;
  31. // Cache State Fields
  32. memset(_filter, 0, sizeof(_filter));
  33. memset(_address, 0, sizeof(_address));
  34. _blendMode[0] = _blendMode[1] = bmNone;
  35. _textureMode[0] = _textureMode[1] = (TextureMode)-1;
  36. _winding[0] = _winding[1] = false;
  37. _depthTest[0] = _depthTest[1] = false;
  38. _depthWrite[0] = _depthWrite[1] = false;
  39. _depthLE[0] = _depthLE[1] = false;
  40. _depthBias[0] = _depthBias[1] = false;
  41. _depthScale[0] = _depthScale[1] = false;
  42. _cullMode[0] = _cullMode[1] = true;
  43. _fillMode[0] = _fillMode[1] = true;
  44. _colorWrite[0] = _colorWrite[1] = 0xF;
  45. _alphaTest[0] = _alphaTest[1] = false;
  46. _alphaValue[0] = _alphaValue[1] = 0;
  47. _scissorTest[0] = _scissorTest[1] = false;
  48. memset(_scissorRect, 0, sizeof(_scissorRect));
  49. memset(_vertexOffset, 0, sizeof(_vertexOffset));
  50. memset(_vertexStride, 0, sizeof(_vertexStride));
  51. memset(_pixelConsts, 0, sizeof(_pixelConsts));
  52. memset(_vertexConsts, 0, sizeof(_vertexConsts));
  53. _pixelConstsDirty[0] = CountOf(_pixelConsts);
  54. _pixelConstsDirty[1] = 0;
  55. _vertexConstsDirty[0] = CountOf(_vertexConsts);
  56. _vertexConstsDirty[1] = 0;
  57. // TODO: Pobierz okno
  58. //if(hWnd)
  59. // _d3dWnd = hWnd;
  60. //else {
  61. _d3dWnd = Engine::Window->handle();
  62. //}
  63. // Utwórz kontekst d3d9
  64. Assert(_d3d9 = Direct3DCreate9(D3D_SDK_VERSION));
  65. // Pobierz własciwości
  66. if(FAILED(hr = _d3d9->GetDeviceCaps(0, D3DDEVTYPE_HAL, &_d3dCaps))) {
  67. // Zwolnij kontekst d3d9
  68. if(_d3d9) {
  69. _d3d9->Release();
  70. _d3d9 = nullptr;
  71. }
  72. // Rzuć wyjątek
  73. dxe(hr);
  74. }
  75. // Zresetuj zasoby
  76. reset(true);
  77. }
  78. //------------------------------------//
  79. // Device: Destructor
  80. Device::~Device() {
  81. // Zniszcz zasoby
  82. lost(true);
  83. // Zniszcz kontekst
  84. if(_d3d9) {
  85. _d3d9->Release();
  86. _d3d9 = nullptr;
  87. }
  88. _d3dWnd = nullptr;
  89. }
  90. //------------------------------------//
  91. // Engine: Device Methods
  92. bool Device::check() {
  93. bool force = false;
  94. // Sprawdź, czy mamy urządzenie
  95. if(!_d3dDev)
  96. return false;
  97. // Sprawdź okno
  98. if(!IsWindow(_d3dWnd))
  99. return false;
  100. for(u32 i = 0; force || i < 10; i++) {
  101. // Odznacz flagę
  102. force = false;
  103. // Sprawdź stan urządzenia
  104. switch(_d3dDev->TestCooperativeLevel()) {
  105. // Zresetuj urządzenie i sprawdź jeszcze raz
  106. case D3DERR_DEVICENOTRESET:
  107. lost(false);
  108. reset(false);
  109. force = true;
  110. break;
  111. // Urządzenie zostało "zgubione", czekamy, aż będzie można je odtworzyć
  112. case D3DERR_DEVICELOST:
  113. break;
  114. // Zniszcz urządzenie i utwórz je ponownie
  115. case D3DERR_DRIVERINTERNALERROR:
  116. lost(true);
  117. reset(true);
  118. force = true;
  119. break;
  120. // Wszystko jest ok
  121. case D3D_OK:
  122. return true;
  123. }
  124. // Przeczekajmy trochę
  125. Sleep(10);
  126. }
  127. return false;
  128. }
  129. void Device::lost(bool theEnd) {
  130. // TODO: Posortuj wszystkie obiekty
  131. //std::sort(_deviceObjects.begin(), _deviceObjects.end(), deviceObjectSorter);
  132. // Zwolnij wszystkie obiekty w odwrotnej kolejności
  133. for(List<DeviceObject> *curr = _deviceObjects.Next, *next; curr != &_deviceObjects; curr = next) {
  134. // Sprawdź listę
  135. dAssert(curr->Next);
  136. Assert(curr->Object);
  137. // Ruszamy dalej
  138. next = curr->Next;
  139. // Zwolnij obiekt
  140. curr->Object->deviceLost(theEnd);
  141. }
  142. // Zwolnij cel wyświetlania
  143. if(_renderTarget) {
  144. _renderTarget->Release();
  145. _renderTarget = nullptr;
  146. }
  147. if(_depthTarget) {
  148. _depthTarget->Release();
  149. _depthTarget = nullptr;
  150. }
  151. // Zwolnij zdarzenie
  152. if(_query) {
  153. _query->Release();
  154. _query = nullptr;
  155. }
  156. // Zniszcz zapytanie
  157. if(_occlusion) {
  158. _occlusion->Release();
  159. _occlusion = nullptr;
  160. }
  161. // Zwolnij domyślną teksturę
  162. if(theEnd && _defaultTexture) {
  163. _defaultTexture->Release();
  164. _defaultTexture = nullptr;
  165. }
  166. // Zwolnij urządzenie
  167. if(theEnd && _d3dDev) {
  168. _d3dDev->Release();
  169. _d3dDev = nullptr;
  170. }
  171. // Wróć do trybu okienkowego
  172. if(theEnd && ChangeDisplaySettings(nullptr, 0) != DISP_CHANGE_SUCCESSFUL) {
  173. Assert("Can't back to windowed mode" && false);
  174. }
  175. }
  176. void Device::reset(bool theBegin) {
  177. // Zmień rozmiar okna
  178. if(_d3dWnd == Engine::Window->handle())
  179. SetWindowPos(_d3dWnd, HWND_TOP, 0, 0, Engine::Config->Width, Engine::Config->Height, SWP_NOMOVE | SWP_NOZORDER);
  180. // Wypełnij strukturę d3dpp
  181. memset(&_d3dpp, 0, sizeof(_d3dpp));
  182. _d3dpp.Windowed = Engine::Config->Windowed;
  183. _d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
  184. //_d3dpp.BackBufferWidth = _d3dCaps.MaxTextureWidth;
  185. //_d3dpp.BackBufferHeight = _d3dCaps.MaxTextureHeight;
  186. _d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
  187. _d3dpp.BackBufferCount = 1;
  188. _d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
  189. _d3dpp.hDeviceWindow = _d3dWnd;
  190. // Ustaw tryb wyświetlania
  191. if(Engine::Config->Windowed) {
  192. if(ChangeDisplaySettings(nullptr, 0) != DISP_CHANGE_SUCCESSFUL)
  193. Assert("Can't back to windowed mode" && false);
  194. }
  195. else {
  196. DEVMODE dmScreenSettings;
  197. // Wypełnij strukture do zmiany ekranu
  198. memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
  199. dmScreenSettings.dmSize = sizeof(dmScreenSettings);
  200. dmScreenSettings.dmPelsWidth = Engine::Config->Width;
  201. dmScreenSettings.dmPelsHeight = Engine::Config->Height;
  202. dmScreenSettings.dmBitsPerPel = 32;
  203. dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
  204. // Zmień ustawienia ekranu
  205. if(ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
  206. Engine::Log->warning("Device: Can't run in fullscreen mode (%ix%i)", Engine::Config->Width, Engine::Config->Height);
  207. }
  208. // Utwórz urządzenie lub zresetuj jego stan
  209. if(theBegin) {
  210. // Utwórz urządzenie
  211. dxe(_d3d9->CreateDevice(0, D3DDEVTYPE_HAL, _d3dWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &_d3dpp, &_d3dDev));
  212. }
  213. else {
  214. // Zresetuj urzadzenie
  215. dxe(_d3dDev->Reset(&_d3dpp));
  216. }
  217. // Ustaw stan rendera
  218. depthMode(true, true);
  219. // Pobierz obszar ekranu
  220. dxe(_d3dDev->GetViewport(&_d3dViewport));
  221. // Pobierz cel renderowania
  222. dxe(_d3dDev->GetRenderTarget(0, &_renderTarget));
  223. // Utwórz bufor głębokości o maksymalnej możliwej wielkości
  224. dxe(_d3dDev->CreateDepthStencilSurface(_d3dCaps.MaxTextureWidth, _d3dCaps.MaxTextureHeight, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &_depthTarget, nullptr));
  225. // Ustaw bufor głębokości
  226. dxe(_d3dDev->SetDepthStencilSurface(_depthTarget));
  227. // TODO: Posortuj zasoby
  228. //std::sort(_deviceObjects.begin(), _deviceObjects.end(), deviceObjectSorter);
  229. // Utwórz zdarzenie
  230. dxe(_d3dDev->CreateQuery(D3DQUERYTYPE_EVENT, &_query));
  231. // Utwórz zapytanie
  232. dxe(_d3dDev->CreateQuery(D3DQUERYTYPE_OCCLUSION, &_occlusion));
  233. // Załaduj domyślną teksturę
  234. if(theBegin && !_defaultTexture) {
  235. dxe(D3DXGetImageInfoFromResource(GetModuleHandle("ayuine2.dll"), MAKEINTRESOURCE(IDB_DEFAULTTEXTURE), &_defaultTextureInfo));
  236. dxe(D3DXCreateTextureFromResource(_d3dDev, GetModuleHandle("ayuine2.dll"), MAKEINTRESOURCE(IDB_DEFAULTTEXTURE), &_defaultTexture));
  237. }
  238. // Odtwórz zasoby
  239. for(List<DeviceObject> *curr = _deviceObjects.Next, *next; curr != &_deviceObjects; curr = next) {
  240. // Sprawdź listę
  241. dAssert(curr->Next);
  242. Assert(curr->Object);
  243. // Ruszamy dalej
  244. next = curr->Next;
  245. // Odtwórz obiekt
  246. curr->Object->deviceReset(theBegin);
  247. }
  248. }
  249. void Device::clear(bool target, bool depth, const vec4 &color, f32 z, const Array<RECT> &rects) {
  250. // Wyczyść ekran
  251. dxe(_d3dDev->Clear(rects.size(), rects.size() ? (const D3DRECT*)&rects[0] : nullptr, (target ? D3DCLEAR_TARGET : 0) | (depth ? D3DCLEAR_ZBUFFER : 0), D3DCOLOR_COLORVALUE(color.X, color.Y, color.Z, color.W), z, 0));
  252. }
  253. void Device::viewport(const rect &r) {
  254. D3DVIEWPORT9 vp;
  255. // Wypełnij strukturę
  256. dxe(_d3dDev->GetViewport(&_d3dViewport));
  257. vp.X = r.Left;
  258. vp.Y = r.Top;
  259. vp.Width = r.width();
  260. vp.Height = r.height();
  261. vp.MinZ = 0.0f;
  262. vp.MaxZ = 1.0f;
  263. // Ustaw obszar
  264. dxe(_d3dDev->SetViewport(&vp));
  265. // Zapisz obszar przycinania
  266. _d3dViewport = vp;
  267. }
  268. void Device::scissor(const rect *r) {
  269. const float Epsilon = 0.5f;
  270. if(r) {
  271. // Oblicz nożyczki :)
  272. _scissorRect[1].left = _d3dViewport.X + max<s32>(s32((r->Left * 0.5f + 0.5f) * _d3dViewport.Width - Epsilon), 0);
  273. _scissorRect[1].right = _d3dViewport.X + min<s32>(s32((r->Right * 0.5f + 0.5f) * _d3dViewport.Width + Epsilon), _d3dViewport.Width);
  274. _scissorRect[1].top = _d3dViewport.Y + max<s32>(s32(((- r->Bottom) * 0.5f + 0.5f) * _d3dViewport.Height - Epsilon), 0);
  275. _scissorRect[1].bottom = _d3dViewport.Y + min<s32>(s32(((- r->Top) * 0.5f + 0.5f) * _d3dViewport.Height + Epsilon), _d3dViewport.Height);
  276. // Włącz nożyczki
  277. _scissorTest[1] = true;
  278. }
  279. else {
  280. // Wyłącz nożyczki
  281. _scissorTest[1] = false;
  282. }
  283. }
  284. void Device::transform(const mat4 &projection, const mat4 &view) {
  285. // Oblicz transformację
  286. mat4::multiply(_transform[1], projection, view);
  287. }
  288. void Device::transform(const mat4 &transform) {
  289. // Ustaw transformacje
  290. _transform[1] = transform;
  291. }
  292. void Device::object(const mat4 &object) {
  293. // Ustaw macierz obiektu
  294. _object[1] = object;
  295. }
  296. void Device::blendMode(BlendMode mode) {
  297. // Ustaw blendowanie
  298. _blendMode[1] = mode;
  299. }
  300. void Device::cullMode(bool cull) {
  301. // Ustaw przycinanie
  302. _cullMode[1] = cull;
  303. }
  304. void Device::depthMode(bool test, bool write, bool le) {
  305. // Ustaw test głębokości
  306. _depthTest[1] = test;
  307. _depthWrite[1] = write;
  308. _depthLE[1] = le;
  309. }
  310. void Device::depthBias(bool bias) {
  311. // Ustaw korekcję głębokości
  312. _depthBias[1] = bias;
  313. }
  314. void Device::depthScale(f32 scale) {
  315. // Ustaw przeskalowanie głębokości
  316. _depthScale[1] = scale;
  317. }
  318. void Device::fillMode(bool fill) {
  319. // Ustaw wypełnianie brył
  320. _fillMode[1] = fill;
  321. }
  322. void Device::colorWrite(bool rgb, bool a) {
  323. // Ustaw zapisywanie koloru
  324. _colorWrite[1] = (rgb ? (D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED) : 0) | (a ? D3DCOLORWRITEENABLE_ALPHA : 0);
  325. }
  326. void Device::alphaTest(bool test, u32 value) {
  327. // Ustaw test przezroczystości
  328. _alphaTest[1] = test;
  329. _alphaValue[1] = value;
  330. }
  331. void Device::winding(bool reverse) {
  332. // Ustaw kierunek trójkątów
  333. _winding[1] = reverse;
  334. }
  335. void Device::colorConst(const vec4 &color) {
  336. // Ustaw kolor
  337. _color[1] = color;
  338. }
  339. void Device::vertexConst(u32 index, const f32 *vectors, u32 count) {
  340. // Skopiuj dane do podręcznego bufora
  341. memcpy(&_vertexConsts[index], vectors, count * sizeof(vec4));
  342. // Zapisz obszar zmian
  343. _vertexConstsDirty[0] = min(_vertexConstsDirty[0], index);
  344. _vertexConstsDirty[1] = max(_vertexConstsDirty[1], index + count);
  345. }
  346. void Device::vertexConst(u32 i, const vec4 &value) {
  347. // Ustaw stałą
  348. vertexConst(i, &value.X, 1);
  349. }
  350. void Device::pixelConst(u32 index, const f32 *vectors, u32 count) {
  351. // Skopiuj dane do podręcznego bufora
  352. memcpy(&_pixelConsts[index], vectors, count * sizeof(vec4));
  353. // Zapisz obszar zmian
  354. _pixelConstsDirty[0] = min(_pixelConstsDirty[0], index);
  355. _pixelConstsDirty[1] = max(_pixelConstsDirty[1], index + count);
  356. }
  357. void Device::pixelConst(u32 i, const vec4 &value) {
  358. // Ustaw stałą
  359. pixelConst(i, &value.X, 1);
  360. }
  361. void Device::shaderConst(VertexShaderConst vertex, PixelShaderConst pixel, const f32 *vectors, u32 count) {
  362. // Ustaw stałe dla cieniowania wierzchołków
  363. if((u32)vertex < CountOf(_vertexConsts)) {
  364. // Skopiuj dane do podręcznego bufora
  365. memcpy(&_vertexConsts[vertex], vectors, count * sizeof(vec4));
  366. // Zapisz obszar zmian
  367. _vertexConstsDirty[0] = min(_vertexConstsDirty[0], (u32)vertex);
  368. _vertexConstsDirty[1] = max(_vertexConstsDirty[1], (u32)vertex + count);
  369. }
  370. // Ustaw stałe dla cieniowania pikseli
  371. if((u32)pixel < CountOf(_pixelConsts)) {
  372. // Skopiuj dane do podręcznego bufora
  373. memcpy(&_pixelConsts[pixel], vectors, count * sizeof(vec4));
  374. // Zapisz obszar zmian
  375. _pixelConstsDirty[0] = min(_pixelConstsDirty[0], (u32)pixel);
  376. _pixelConstsDirty[1] = max(_pixelConstsDirty[1], (u32)pixel + count);
  377. }
  378. }
  379. void Device::shaderConst(VertexShaderConst vertex, PixelShaderConst pixel, const vec4 &value) {
  380. shaderConst(vertex, pixel, &value.X, 1);
  381. }
  382. f32 Device::width() {
  383. return _d3dViewport.Width;
  384. }
  385. f32 Device::height() {
  386. return _d3dViewport.Height;
  387. }
  388. f32 Device::aspect() {
  389. return (f32)_d3dViewport.Width / (f32)_d3dViewport.Height;
  390. }
  391. bool Device::swap(HWND destWnd) {
  392. if(!check())
  393. return false;
  394. // Dodaj zakończenie kolejki
  395. _query->Issue(D3DISSUE_END);
  396. // Czekaj na wykonanie wszystkich poleceń
  397. while(_query->GetData(nullptr, 0, D3DGETDATA_FLUSH) == S_FALSE);
  398. // Odswież ekran
  399. dxe(_d3dDev->Present(nullptr, nullptr, destWnd, nullptr));
  400. return true;
  401. }
  402. void Device::resetStates() {
  403. }
  404. void Device::updateStates() {
  405. // Sprawdź transformację
  406. if(_transform[0] != _transform[1]) {
  407. mat4 temp;
  408. // Zapisz transformację
  409. _transform[0] = _transform[1];
  410. // Zamień kolumny z wierszami
  411. mat4::transpose(temp, _transform[0]);
  412. // Ustaw transformację
  413. dxe(_d3dDev->SetTransform(D3DTS_VIEW, (D3DMATRIX*)&temp));
  414. // TODO? Ustaw stałą do vertex shadera
  415. shaderConst(vscTransform, pscNone, &_transform[0].m11, 4);
  416. }
  417. // Sprawdź macierz obiektu
  418. if(_object[0] != _object[1]) {
  419. mat4 temp;
  420. // Zapisz macierz
  421. _object[0] = _object[1];
  422. // Zamień kolumny z wierszami
  423. mat4::transpose(temp, _object[0]);
  424. // Ustaw macierz
  425. dxe(_d3dDev->SetTransform(D3DTS_WORLD, (D3DMATRIX*)&temp));
  426. // TODO? Ustaw stałą do vertex shadera
  427. shaderConst(vscObject, pscNone, &_object[0].m11, 4);
  428. }
  429. // Sprawdź kolor
  430. if(_color[0] != _color[1]) {
  431. // Zapisz kolor
  432. _color[0] = _color[1];
  433. // Ustaw kolor
  434. dxe(_d3dDev->SetRenderState(D3DRS_TEXTUREFACTOR, D3DCOLOR_COLORVALUE(_color[0].X, _color[0].Y, _color[0].Z, _color[0].W)));
  435. // Ustaw kolor dla shaderów
  436. shaderConst(vscColor, pscColor, &_color[0].X, 1);
  437. }
  438. // Sprawdź filtrowanie tekstury
  439. for(u32 i = 0; i < CountOf(_filter); i++) {
  440. if(_filter[i][0] != _filter[i][1]) {
  441. // Ustaw filtrowanie
  442. switch(_filter[i][0] = _filter[i][1]) {
  443. case tfPoint:
  444. dxe(_d3dDev->SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_NONE));
  445. dxe(_d3dDev->SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_POINT));
  446. dxe(_d3dDev->SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_POINT));
  447. break;
  448. case tfLinear:
  449. dxe(_d3dDev->SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_NONE));
  450. dxe(_d3dDev->SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_LINEAR));
  451. dxe(_d3dDev->SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR));
  452. break;
  453. case tfMipmaps:
  454. dxe(_d3dDev->SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR));
  455. dxe(_d3dDev->SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_LINEAR));
  456. dxe(_d3dDev->SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR));
  457. break;
  458. }
  459. Engine::Stats->States++;
  460. }
  461. }
  462. // Sprawdź zawijanie tekstury
  463. for(u32 i = 0; i < CountOf(_address); i++) {
  464. if(_address[i][0] != _address[i][1]) {
  465. // Ustaw zawijanie
  466. switch(_address[i][0] = _address[i][1]) {
  467. case taWrap:
  468. dxe(_d3dDev->SetSamplerState(i, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP));
  469. dxe(_d3dDev->SetSamplerState(i, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP));
  470. dxe(_d3dDev->SetSamplerState(i, D3DSAMP_ADDRESSW, D3DTADDRESS_WRAP));
  471. break;
  472. case taClamp:
  473. dxe(_d3dDev->SetSamplerState(i, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP));
  474. dxe(_d3dDev->SetSamplerState(i, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP));
  475. dxe(_d3dDev->SetSamplerState(i, D3DSAMP_ADDRESSW, D3DTADDRESS_CLAMP));
  476. break;
  477. case taMirror:
  478. dxe(_d3dDev->SetSamplerState(i, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR));
  479. dxe(_d3dDev->SetSamplerState(i, D3DSAMP_ADDRESSV, D3DTADDRESS_MIRROR));
  480. dxe(_d3dDev->SetSamplerState(i, D3DSAMP_ADDRESSW, D3DTADDRESS_MIRROR));
  481. break;
  482. }
  483. Engine::Stats->States++;
  484. }
  485. }
  486. // Sprawdź łączenie
  487. if(_blendMode[0] != _blendMode[1]) {
  488. // Ustaw łączenie
  489. switch(_blendMode[0] = _blendMode[1]) {
  490. case bmNone:
  491. dxe(_d3dDev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE));
  492. break;
  493. case bmBlend:
  494. dxe(_d3dDev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE));
  495. dxe(_d3dDev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA));
  496. dxe(_d3dDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA));
  497. break;
  498. case bmAdditive:
  499. dxe(_d3dDev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE));
  500. dxe(_d3dDev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE));
  501. dxe(_d3dDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE));
  502. break;
  503. case bmOverlay:
  504. dxe(_d3dDev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE));
  505. dxe(_d3dDev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA));
  506. dxe(_d3dDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE));
  507. break;
  508. case bmDecal:
  509. dxe(_d3dDev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE));
  510. dxe(_d3dDev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_DESTCOLOR));
  511. dxe(_d3dDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_SRCCOLOR));
  512. break;
  513. }
  514. Engine::Stats->States++;
  515. }
  516. // Sprawdź teksturowanie
  517. if(_textureMode[0] != _textureMode[1]) {
  518. // Ustaw teksturowanie
  519. switch(_textureMode[0] = _textureMode[1]) {
  520. case tmConst:
  521. dxe(_d3dDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1));
  522. dxe(_d3dDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR));
  523. dxe(_d3dDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1));
  524. dxe(_d3dDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR));
  525. dxe(_d3dDev->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE));
  526. dxe(_d3dDev->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE));
  527. break;
  528. case tmDiffuse:
  529. dxe(_d3dDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1));
  530. dxe(_d3dDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE));
  531. dxe(_d3dDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1));
  532. dxe(_d3dDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE));
  533. dxe(_d3dDev->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE));
  534. dxe(_d3dDev->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE));
  535. break;
  536. case tmTexture:
  537. dxe(_d3dDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1));
  538. dxe(_d3dDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE));
  539. dxe(_d3dDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1));
  540. dxe(_d3dDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE));
  541. dxe(_d3dDev->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE));
  542. dxe(_d3dDev->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE));
  543. break;
  544. case tmTextureConst:
  545. dxe(_d3dDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE));
  546. dxe(_d3dDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE));
  547. dxe(_d3dDev->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TFACTOR));
  548. dxe(_d3dDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE));
  549. dxe(_d3dDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE));
  550. dxe(_d3dDev->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TFACTOR));
  551. dxe(_d3dDev->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE));
  552. dxe(_d3dDev->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE));
  553. break;
  554. case tmTextureDiffuse:
  555. dxe(_d3dDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE));
  556. dxe(_d3dDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE));
  557. dxe(_d3dDev->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE));
  558. dxe(_d3dDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE));
  559. dxe(_d3dDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE));
  560. dxe(_d3dDev->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE));
  561. dxe(_d3dDev->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE));
  562. dxe(_d3dDev->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE));
  563. break;
  564. case tmMaskedColor:
  565. dxe(_d3dDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1));
  566. dxe(_d3dDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR));
  567. dxe(_d3dDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1));
  568. dxe(_d3dDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE));
  569. dxe(_d3dDev->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE));
  570. dxe(_d3dDev->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE));
  571. break;
  572. }
  573. Engine::Stats->States++;
  574. }
  575. // Sprawdź test bufora głębokości
  576. if(_depthTest[0] != _depthTest[1]) {
  577. // Ustaw test bufora głębokości
  578. dxe(_d3dDev->SetRenderState(D3DRS_ZENABLE, (_depthTest[0] = _depthTest[1]) ? TRUE : FALSE));
  579. Engine::Stats->States++;
  580. }
  581. // Sprawdź zapisywanie do bufora głębokości
  582. if(_depthWrite[0] != _depthWrite[1]) {
  583. // Ustaw test bufora głębokości
  584. dxe(_d3dDev->SetRenderState(D3DRS_ZWRITEENABLE, (_depthWrite[0] = _depthWrite[1]) ? TRUE : FALSE));
  585. Engine::Stats->States++;
  586. }
  587. // Sprawdź operacje wykonywaną przy testowaniu głębokości
  588. if(_depthLE[0] != _depthLE[1]) {
  589. // Ustaw test bufora głębokości
  590. dxe(_d3dDev->SetRenderState(D3DRS_ZFUNC, (_depthLE[0] = _depthLE[1]) ? D3DCMP_LESSEQUAL : D3DCMP_EQUAL));
  591. Engine::Stats->States++;
  592. }
  593. // Sprawdź przesunięcie bufora głębokości
  594. if(_depthBias[0] != _depthBias[1]) {
  595. f32 bias = -0.0001f;
  596. // Ustaw przesunięcie bufora głębokości
  597. dxe(_d3dDev->SetRenderState(D3DRS_DEPTHBIAS, (_depthBias[0] = _depthBias[1]) ? (u32&)bias : 0));
  598. Engine::Stats->States++;
  599. }
  600. // Sprawdź przeskalowanie bufora głębokości
  601. if(abs(_depthScale[0] - _depthScale[1]) < MathErr) {
  602. // TODO: Ustaw przeskalowanie bufora głębokości
  603. //dxe(_d3dDev->SetRenderState(D3DRS_DEPTHSCALE, (u32&)(_depthScale[0] = _depthScale[1])));
  604. //Engine::Stats->States++;
  605. }
  606. // Sprawdź przycinanie
  607. if(_cullMode[0] != _cullMode[1] || _winding[0] != _winding[1]) {
  608. // Zapisz przycinanie
  609. _cullMode[0] = _cullMode[1];
  610. _winding[0] = _winding[1];
  611. // Ustaw przycinanie
  612. dxe(_d3dDev->SetRenderState(D3DRS_CULLMODE, _cullMode[0] ? (_winding[0] ? D3DCULL_CW : D3DCULL_CCW) : D3DCULL_NONE));
  613. Engine::Stats->States++;
  614. }
  615. // Sprawdź wypełnienie
  616. if(_fillMode[0] != _fillMode[1]) {
  617. // Ustaw wypełnianie
  618. dxe(_d3dDev->SetRenderState(D3DRS_FILLMODE, (_fillMode[0] = _fillMode[1]) ? D3DFILL_SOLID : D3DFILL_WIREFRAME));
  619. Engine::Stats->States++;
  620. }
  621. // Sprawdź maskowanie
  622. if(_colorWrite[0] != _colorWrite[1]) {
  623. // Ustaw maskowanie
  624. dxe(_d3dDev->SetRenderState(D3DRS_COLORWRITEENABLE, _colorWrite[0] = _colorWrite[1]));
  625. Engine::Stats->States++;
  626. }
  627. // Sprawdź test przezroczystości
  628. if(_alphaTest[0] != _alphaTest[1]) {
  629. // Ustaw test przezroczystości
  630. if(_alphaTest[0] = _alphaTest[1]) {
  631. dxe(_d3dDev->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE));
  632. dxe(_d3dDev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER));
  633. Engine::Stats->States++;
  634. }
  635. else {
  636. dxe(_d3dDev->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE));
  637. Engine::Stats->States++;
  638. }
  639. }
  640. // Sprawdź wartość dla testu przezroczystości
  641. if(_alphaValue[0] != _alphaValue[1]) {
  642. // Ustaw wartość dla testu przezroczystości
  643. dxe(_d3dDev->SetRenderState(D3DRS_ALPHAREF, _alphaValue[0] = _alphaValue[1]));
  644. Engine::Stats->States++;
  645. }
  646. // Sprawdź nożyczki
  647. if(_scissorTest[0] != _scissorTest[1]) {
  648. // Ustaw nożyczki
  649. dxe(_d3dDev->SetRenderState(D3DRS_SCISSORTESTENABLE, (_scissorTest[0] = _scissorTest[1]) ? TRUE : FALSE));
  650. Engine::Stats->States++;
  651. }
  652. // Sprawdź obszar nożyczek
  653. if(_scissorRect[0].left != _scissorRect[1].left ||
  654. _scissorRect[0].right != _scissorRect[1].right ||
  655. _scissorRect[0].top != _scissorRect[1].top ||
  656. _scissorRect[0].bottom != _scissorRect[1].bottom) {
  657. // Zapisz obszar nożyczek
  658. _scissorRect[0] = _scissorRect[1];
  659. // Ustaw obszar nożyczek
  660. dxe(_d3dDev->SetScissorRect(&_scissorRect[0]));
  661. Engine::Stats->Clips++;
  662. }
  663. // Sprawdź format wierzchołków
  664. if(_decl[0] != _decl[1]) {
  665. // Ustaw format wierzchołków
  666. dxe(_d3dDev->SetVertexDeclaration(_decl[0] = _decl[1]));
  667. }
  668. // Sprawdź cieniowanie wierzchołków
  669. if(_vertexShader[0] != _vertexShader[1]) {
  670. // Ustaw cieniowanie wierzchołków
  671. dxe(_d3dDev->SetVertexShader(_vertexShader[0] = _vertexShader[1]));
  672. Engine::Stats->Shaders++;
  673. }
  674. // Sprawdź cieniowanie pikseli
  675. if(_pixelShader[0] != _pixelShader[1]) {
  676. // Ustaw cieniowanie pikseli
  677. dxe(_d3dDev->SetPixelShader(_pixelShader[0] = _pixelShader[1]));
  678. Engine::Stats->Shaders++;
  679. }
  680. // Sprawdź tekstury
  681. for(u32 i = 0; i < CountOf(_textures); i++) {
  682. if(_textures[i][0] != _textures[i][1]) {
  683. // Ustaw tekstury
  684. dxe(_d3dDev->SetTexture(i, _textures[i][0] = _textures[i][1]));
  685. Engine::Stats->Textures++;
  686. }
  687. }
  688. // Sprawdź bufor indeksów
  689. if(_indexBuffer[0] != _indexBuffer[1]) {
  690. // Ustaw bufor indeksów
  691. dxe(_d3dDev->SetIndices(_indexBuffer[0] = _indexBuffer[1]));
  692. Engine::Stats->Buffers++;
  693. }
  694. // Sprawdź bufory wierzchołków
  695. for(u32 i = 0; i < CountOf(_vertexBuffer); i++) {
  696. if(_vertexBuffer[i][0] != _vertexBuffer[i][1] ||
  697. _vertexOffset[i][0] != _vertexOffset[i][1] ||
  698. _vertexStride[i][0] != _vertexStride[i][1]) {
  699. // Ustaw bufor wierzchołków
  700. dxe(_d3dDev->SetStreamSource(i, _vertexBuffer[i][0] = _vertexBuffer[i][1], _vertexOffset[i][0] = _vertexOffset[i][1], _vertexStride[i][0] = _vertexStride[i][1]));
  701. Engine::Stats->Buffers++;
  702. }
  703. }
  704. // Sprawdź stałe dla pixel shadera
  705. if(_pixelConstsDirty[0] < _pixelConstsDirty[1]) {
  706. // Ustaw stałe
  707. dxe(_d3dDev->SetPixelShaderConstantF(_pixelConstsDirty[0], &_pixelConsts[_pixelConstsDirty[0]].X, _pixelConstsDirty[1] - _pixelConstsDirty[0]));
  708. Engine::Stats->Consts += _pixelConstsDirty[1] - _pixelConstsDirty[0];
  709. // Zresetuj ustawiony obszar
  710. _pixelConstsDirty[0] = CountOf(_pixelConsts);
  711. _pixelConstsDirty[1] = 0;
  712. }
  713. // Sprawdź stałe dla vertex shadera
  714. if(_vertexConstsDirty[0] < _vertexConstsDirty[1]) {
  715. // Ustaw stałe
  716. dxe(_d3dDev->SetVertexShaderConstantF(_vertexConstsDirty[0], &_vertexConsts[_vertexConstsDirty[0]].X, _vertexConstsDirty[1] - _vertexConstsDirty[0]));
  717. Engine::Stats->Consts += _vertexConstsDirty[1] - _vertexConstsDirty[0];
  718. // Zresetuj ustawiony obszar
  719. _vertexConstsDirty[0] = CountOf(_vertexConsts);
  720. _vertexConstsDirty[1] = 0;
  721. }
  722. }
  723. void Device::beginOcclusion() {
  724. // Rozpocznij zapytanie o widoczność
  725. dxe(_occlusion->Issue(D3DISSUE_BEGIN));
  726. }
  727. void Device::endOcclusion() {
  728. // Zakończ zapytanie o widoczność
  729. dxe(_occlusion->Issue(D3DISSUE_END));
  730. }
  731. bool Device::flushOcclusion(u32 &result) {
  732. HRESULT hr;
  733. // Pobierz wynik działania
  734. dxe(hr = _occlusion->GetData(&result, sizeof(u32), D3DGETDATA_FLUSH));
  735. // Sprawdź wynik
  736. return hr == S_OK;
  737. }
  738. };