/src/Device.cpp
C++ | 893 lines | 555 code | 155 blank | 183 comment | 108 complexity | 2340f5d57ec10150bc66c068e0eeeb28 MD5 | raw file
- //------------------------------------//
- //
- // Device.cpp
- //
- // Author: ayufan (ayufan[at]o2.pl)
- // Project: ayuine2
- // Date: 2006-7-31
- //
- //------------------------------------//
-
- #include "StdAfx.hpp"
-
- namespace ayuine
- {
- //------------------------------------//
- // Device: Functions
-
- bool deviceObjectSorter(DeviceObject *a, DeviceObject *b) {
- return a->type() < b->type();
- }
-
- //------------------------------------//
- // Device: Constructor
-
- Device::Device() : _deviceObjects(nullptr) {
- HRESULT hr;
-
- // Device Fields
- memset(&_d3dCaps, 0, sizeof(_d3dCaps));
- memset(&_d3dpp, 0, sizeof(_d3dpp));
- _d3d9 = nullptr;
- _d3dDev = nullptr;
- _renderTarget = nullptr;
- _depthTarget = nullptr;
- _query = nullptr;
- _defaultTexture = nullptr;
-
- // Cache State Fields
- memset(_filter, 0, sizeof(_filter));
- memset(_address, 0, sizeof(_address));
- _blendMode[0] = _blendMode[1] = bmNone;
- _textureMode[0] = _textureMode[1] = (TextureMode)-1;
- _winding[0] = _winding[1] = false;
- _depthTest[0] = _depthTest[1] = false;
- _depthWrite[0] = _depthWrite[1] = false;
- _depthLE[0] = _depthLE[1] = false;
- _depthBias[0] = _depthBias[1] = false;
- _depthScale[0] = _depthScale[1] = false;
- _cullMode[0] = _cullMode[1] = true;
- _fillMode[0] = _fillMode[1] = true;
- _colorWrite[0] = _colorWrite[1] = 0xF;
- _alphaTest[0] = _alphaTest[1] = false;
- _alphaValue[0] = _alphaValue[1] = 0;
- _scissorTest[0] = _scissorTest[1] = false;
- memset(_scissorRect, 0, sizeof(_scissorRect));
- memset(_vertexOffset, 0, sizeof(_vertexOffset));
- memset(_vertexStride, 0, sizeof(_vertexStride));
- memset(_pixelConsts, 0, sizeof(_pixelConsts));
- memset(_vertexConsts, 0, sizeof(_vertexConsts));
- _pixelConstsDirty[0] = CountOf(_pixelConsts);
- _pixelConstsDirty[1] = 0;
- _vertexConstsDirty[0] = CountOf(_vertexConsts);
- _vertexConstsDirty[1] = 0;
-
- // TODO: Pobierz okno
- //if(hWnd)
- // _d3dWnd = hWnd;
- //else {
- _d3dWnd = Engine::Window->handle();
- //}
-
- // Utwórz kontekst d3d9
- Assert(_d3d9 = Direct3DCreate9(D3D_SDK_VERSION));
-
- // Pobierz własciwości
- if(FAILED(hr = _d3d9->GetDeviceCaps(0, D3DDEVTYPE_HAL, &_d3dCaps))) {
- // Zwolnij kontekst d3d9
- if(_d3d9) {
- _d3d9->Release();
- _d3d9 = nullptr;
- }
-
- // Rzuć wyjątek
- dxe(hr);
- }
- // Zresetuj zasoby
- reset(true);
- }
-
- //------------------------------------//
- // Device: Destructor
-
- Device::~Device() {
- // Zniszcz zasoby
- lost(true);
-
- // Zniszcz kontekst
- if(_d3d9) {
- _d3d9->Release();
- _d3d9 = nullptr;
- }
- _d3dWnd = nullptr;
- }
-
- //------------------------------------//
- // Engine: Device Methods
-
- bool Device::check() {
- bool force = false;
-
- // Sprawdź, czy mamy urządzenie
- if(!_d3dDev)
- return false;
-
- // Sprawdź okno
- if(!IsWindow(_d3dWnd))
- return false;
-
- for(u32 i = 0; force || i < 10; i++) {
- // Odznacz flagę
- force = false;
-
- // Sprawdź stan urządzenia
- switch(_d3dDev->TestCooperativeLevel()) {
- // Zresetuj urządzenie i sprawdź jeszcze raz
- case D3DERR_DEVICENOTRESET:
- lost(false);
- reset(false);
- force = true;
- break;
-
- // Urządzenie zostało "zgubione", czekamy, aż będzie można je odtworzyć
- case D3DERR_DEVICELOST:
- break;
-
- // Zniszcz urządzenie i utwórz je ponownie
- case D3DERR_DRIVERINTERNALERROR:
- lost(true);
- reset(true);
- force = true;
- break;
-
- // Wszystko jest ok
- case D3D_OK:
- return true;
- }
-
- // Przeczekajmy trochę
- Sleep(10);
- }
-
- return false;
- }
-
- void Device::lost(bool theEnd) {
- // TODO: Posortuj wszystkie obiekty
- //std::sort(_deviceObjects.begin(), _deviceObjects.end(), deviceObjectSorter);
-
- // Zwolnij wszystkie obiekty w odwrotnej kolejności
- for(List<DeviceObject> *curr = _deviceObjects.Next, *next; curr != &_deviceObjects; curr = next) {
- // Sprawdź listę
- dAssert(curr->Next);
- Assert(curr->Object);
-
- // Ruszamy dalej
- next = curr->Next;
-
- // Zwolnij obiekt
- curr->Object->deviceLost(theEnd);
- }
-
- // Zwolnij cel wyświetlania
- if(_renderTarget) {
- _renderTarget->Release();
- _renderTarget = nullptr;
- }
-
- if(_depthTarget) {
- _depthTarget->Release();
- _depthTarget = nullptr;
- }
-
- // Zwolnij zdarzenie
- if(_query) {
- _query->Release();
- _query = nullptr;
- }
-
- // Zniszcz zapytanie
- if(_occlusion) {
- _occlusion->Release();
- _occlusion = nullptr;
- }
-
- // Zwolnij domyślną teksturę
- if(theEnd && _defaultTexture) {
- _defaultTexture->Release();
- _defaultTexture = nullptr;
- }
-
- // Zwolnij urządzenie
- if(theEnd && _d3dDev) {
- _d3dDev->Release();
- _d3dDev = nullptr;
- }
-
- // Wróć do trybu okienkowego
- if(theEnd && ChangeDisplaySettings(nullptr, 0) != DISP_CHANGE_SUCCESSFUL) {
- Assert("Can't back to windowed mode" && false);
- }
- }
-
- void Device::reset(bool theBegin) {
- // Zmień rozmiar okna
- if(_d3dWnd == Engine::Window->handle())
- SetWindowPos(_d3dWnd, HWND_TOP, 0, 0, Engine::Config->Width, Engine::Config->Height, SWP_NOMOVE | SWP_NOZORDER);
-
- // Wypełnij strukturę d3dpp
- memset(&_d3dpp, 0, sizeof(_d3dpp));
- _d3dpp.Windowed = Engine::Config->Windowed;
- _d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
- //_d3dpp.BackBufferWidth = _d3dCaps.MaxTextureWidth;
- //_d3dpp.BackBufferHeight = _d3dCaps.MaxTextureHeight;
- _d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
- _d3dpp.BackBufferCount = 1;
- _d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
- _d3dpp.hDeviceWindow = _d3dWnd;
-
- // Ustaw tryb wyświetlania
- if(Engine::Config->Windowed) {
- if(ChangeDisplaySettings(nullptr, 0) != DISP_CHANGE_SUCCESSFUL)
- Assert("Can't back to windowed mode" && false);
- }
- else {
- DEVMODE dmScreenSettings;
-
- // Wypełnij strukture do zmiany ekranu
- memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
- dmScreenSettings.dmSize = sizeof(dmScreenSettings);
- dmScreenSettings.dmPelsWidth = Engine::Config->Width;
- dmScreenSettings.dmPelsHeight = Engine::Config->Height;
- dmScreenSettings.dmBitsPerPel = 32;
- dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
-
- // Zmień ustawienia ekranu
- if(ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
- Engine::Log->warning("Device: Can't run in fullscreen mode (%ix%i)", Engine::Config->Width, Engine::Config->Height);
- }
-
- // Utwórz urządzenie lub zresetuj jego stan
- if(theBegin) {
- // Utwórz urządzenie
- dxe(_d3d9->CreateDevice(0, D3DDEVTYPE_HAL, _d3dWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &_d3dpp, &_d3dDev));
- }
- else {
- // Zresetuj urzadzenie
- dxe(_d3dDev->Reset(&_d3dpp));
- }
-
- // Ustaw stan rendera
- depthMode(true, true);
-
- // Pobierz obszar ekranu
- dxe(_d3dDev->GetViewport(&_d3dViewport));
-
- // Pobierz cel renderowania
- dxe(_d3dDev->GetRenderTarget(0, &_renderTarget));
-
- // Utwórz bufor głębokości o maksymalnej możliwej wielkości
- dxe(_d3dDev->CreateDepthStencilSurface(_d3dCaps.MaxTextureWidth, _d3dCaps.MaxTextureHeight, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &_depthTarget, nullptr));
-
- // Ustaw bufor głębokości
- dxe(_d3dDev->SetDepthStencilSurface(_depthTarget));
-
- // TODO: Posortuj zasoby
- //std::sort(_deviceObjects.begin(), _deviceObjects.end(), deviceObjectSorter);
-
- // Utwórz zdarzenie
- dxe(_d3dDev->CreateQuery(D3DQUERYTYPE_EVENT, &_query));
-
- // Utwórz zapytanie
- dxe(_d3dDev->CreateQuery(D3DQUERYTYPE_OCCLUSION, &_occlusion));
-
- // Załaduj domyślną teksturę
- if(theBegin && !_defaultTexture) {
- dxe(D3DXGetImageInfoFromResource(GetModuleHandle("ayuine2.dll"), MAKEINTRESOURCE(IDB_DEFAULTTEXTURE), &_defaultTextureInfo));
- dxe(D3DXCreateTextureFromResource(_d3dDev, GetModuleHandle("ayuine2.dll"), MAKEINTRESOURCE(IDB_DEFAULTTEXTURE), &_defaultTexture));
- }
-
- // Odtwórz zasoby
- for(List<DeviceObject> *curr = _deviceObjects.Next, *next; curr != &_deviceObjects; curr = next) {
- // Sprawdź listę
- dAssert(curr->Next);
- Assert(curr->Object);
-
- // Ruszamy dalej
- next = curr->Next;
-
- // Odtwórz obiekt
- curr->Object->deviceReset(theBegin);
- }
- }
-
- void Device::clear(bool target, bool depth, const vec4 &color, f32 z, const Array<RECT> &rects) {
- // Wyczyść ekran
- 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));
- }
-
- void Device::viewport(const rect &r) {
- D3DVIEWPORT9 vp;
-
- // Wypełnij strukturę
- dxe(_d3dDev->GetViewport(&_d3dViewport));
- vp.X = r.Left;
- vp.Y = r.Top;
- vp.Width = r.width();
- vp.Height = r.height();
- vp.MinZ = 0.0f;
- vp.MaxZ = 1.0f;
-
- // Ustaw obszar
- dxe(_d3dDev->SetViewport(&vp));
-
- // Zapisz obszar przycinania
- _d3dViewport = vp;
- }
-
- void Device::scissor(const rect *r) {
- const float Epsilon = 0.5f;
-
- if(r) {
- // Oblicz nożyczki :)
- _scissorRect[1].left = _d3dViewport.X + max<s32>(s32((r->Left * 0.5f + 0.5f) * _d3dViewport.Width - Epsilon), 0);
- _scissorRect[1].right = _d3dViewport.X + min<s32>(s32((r->Right * 0.5f + 0.5f) * _d3dViewport.Width + Epsilon), _d3dViewport.Width);
- _scissorRect[1].top = _d3dViewport.Y + max<s32>(s32(((- r->Bottom) * 0.5f + 0.5f) * _d3dViewport.Height - Epsilon), 0);
- _scissorRect[1].bottom = _d3dViewport.Y + min<s32>(s32(((- r->Top) * 0.5f + 0.5f) * _d3dViewport.Height + Epsilon), _d3dViewport.Height);
-
- // Włącz nożyczki
- _scissorTest[1] = true;
- }
- else {
- // Wyłącz nożyczki
- _scissorTest[1] = false;
- }
- }
-
- void Device::transform(const mat4 &projection, const mat4 &view) {
- // Oblicz transformację
- mat4::multiply(_transform[1], projection, view);
- }
-
- void Device::transform(const mat4 &transform) {
- // Ustaw transformacje
- _transform[1] = transform;
- }
-
- void Device::object(const mat4 &object) {
- // Ustaw macierz obiektu
- _object[1] = object;
- }
-
- void Device::blendMode(BlendMode mode) {
- // Ustaw blendowanie
- _blendMode[1] = mode;
- }
-
- void Device::cullMode(bool cull) {
- // Ustaw przycinanie
- _cullMode[1] = cull;
- }
-
- void Device::depthMode(bool test, bool write, bool le) {
- // Ustaw test głębokości
- _depthTest[1] = test;
- _depthWrite[1] = write;
- _depthLE[1] = le;
- }
-
- void Device::depthBias(bool bias) {
- // Ustaw korekcję głębokości
- _depthBias[1] = bias;
- }
-
- void Device::depthScale(f32 scale) {
- // Ustaw przeskalowanie głębokości
- _depthScale[1] = scale;
- }
-
- void Device::fillMode(bool fill) {
- // Ustaw wypełnianie brył
- _fillMode[1] = fill;
- }
-
- void Device::colorWrite(bool rgb, bool a) {
- // Ustaw zapisywanie koloru
- _colorWrite[1] = (rgb ? (D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED) : 0) | (a ? D3DCOLORWRITEENABLE_ALPHA : 0);
- }
-
- void Device::alphaTest(bool test, u32 value) {
- // Ustaw test przezroczystości
- _alphaTest[1] = test;
- _alphaValue[1] = value;
- }
-
- void Device::winding(bool reverse) {
- // Ustaw kierunek trójkątów
- _winding[1] = reverse;
- }
-
- void Device::colorConst(const vec4 &color) {
- // Ustaw kolor
- _color[1] = color;
- }
-
- void Device::vertexConst(u32 index, const f32 *vectors, u32 count) {
- // Skopiuj dane do podręcznego bufora
- memcpy(&_vertexConsts[index], vectors, count * sizeof(vec4));
-
- // Zapisz obszar zmian
- _vertexConstsDirty[0] = min(_vertexConstsDirty[0], index);
- _vertexConstsDirty[1] = max(_vertexConstsDirty[1], index + count);
- }
-
- void Device::vertexConst(u32 i, const vec4 &value) {
- // Ustaw stałą
- vertexConst(i, &value.X, 1);
- }
-
- void Device::pixelConst(u32 index, const f32 *vectors, u32 count) {
- // Skopiuj dane do podręcznego bufora
- memcpy(&_pixelConsts[index], vectors, count * sizeof(vec4));
-
- // Zapisz obszar zmian
- _pixelConstsDirty[0] = min(_pixelConstsDirty[0], index);
- _pixelConstsDirty[1] = max(_pixelConstsDirty[1], index + count);
- }
-
- void Device::pixelConst(u32 i, const vec4 &value) {
- // Ustaw stałą
- pixelConst(i, &value.X, 1);
- }
-
- void Device::shaderConst(VertexShaderConst vertex, PixelShaderConst pixel, const f32 *vectors, u32 count) {
- // Ustaw stałe dla cieniowania wierzchołków
- if((u32)vertex < CountOf(_vertexConsts)) {
- // Skopiuj dane do podręcznego bufora
- memcpy(&_vertexConsts[vertex], vectors, count * sizeof(vec4));
-
- // Zapisz obszar zmian
- _vertexConstsDirty[0] = min(_vertexConstsDirty[0], (u32)vertex);
- _vertexConstsDirty[1] = max(_vertexConstsDirty[1], (u32)vertex + count);
- }
-
- // Ustaw stałe dla cieniowania pikseli
- if((u32)pixel < CountOf(_pixelConsts)) {
- // Skopiuj dane do podręcznego bufora
- memcpy(&_pixelConsts[pixel], vectors, count * sizeof(vec4));
-
- // Zapisz obszar zmian
- _pixelConstsDirty[0] = min(_pixelConstsDirty[0], (u32)pixel);
- _pixelConstsDirty[1] = max(_pixelConstsDirty[1], (u32)pixel + count);
- }
- }
-
- void Device::shaderConst(VertexShaderConst vertex, PixelShaderConst pixel, const vec4 &value) {
- shaderConst(vertex, pixel, &value.X, 1);
- }
-
- f32 Device::width() {
- return _d3dViewport.Width;
- }
-
- f32 Device::height() {
- return _d3dViewport.Height;
- }
-
- f32 Device::aspect() {
- return (f32)_d3dViewport.Width / (f32)_d3dViewport.Height;
- }
-
- bool Device::swap(HWND destWnd) {
- if(!check())
- return false;
-
- // Dodaj zakończenie kolejki
- _query->Issue(D3DISSUE_END);
-
- // Czekaj na wykonanie wszystkich poleceń
- while(_query->GetData(nullptr, 0, D3DGETDATA_FLUSH) == S_FALSE);
-
- // Odswież ekran
- dxe(_d3dDev->Present(nullptr, nullptr, destWnd, nullptr));
- return true;
- }
-
- void Device::resetStates() {
-
- }
-
- void Device::updateStates() {
- // Sprawdź transformację
- if(_transform[0] != _transform[1]) {
- mat4 temp;
-
- // Zapisz transformację
- _transform[0] = _transform[1];
-
- // Zamień kolumny z wierszami
- mat4::transpose(temp, _transform[0]);
-
- // Ustaw transformację
- dxe(_d3dDev->SetTransform(D3DTS_VIEW, (D3DMATRIX*)&temp));
-
- // TODO? Ustaw stałą do vertex shadera
- shaderConst(vscTransform, pscNone, &_transform[0].m11, 4);
- }
-
- // Sprawdź macierz obiektu
- if(_object[0] != _object[1]) {
- mat4 temp;
-
- // Zapisz macierz
- _object[0] = _object[1];
-
- // Zamień kolumny z wierszami
- mat4::transpose(temp, _object[0]);
-
- // Ustaw macierz
- dxe(_d3dDev->SetTransform(D3DTS_WORLD, (D3DMATRIX*)&temp));
-
- // TODO? Ustaw stałą do vertex shadera
- shaderConst(vscObject, pscNone, &_object[0].m11, 4);
- }
-
- // Sprawdź kolor
- if(_color[0] != _color[1]) {
- // Zapisz kolor
- _color[0] = _color[1];
-
- // Ustaw kolor
- dxe(_d3dDev->SetRenderState(D3DRS_TEXTUREFACTOR, D3DCOLOR_COLORVALUE(_color[0].X, _color[0].Y, _color[0].Z, _color[0].W)));
-
- // Ustaw kolor dla shaderów
- shaderConst(vscColor, pscColor, &_color[0].X, 1);
- }
-
- // Sprawdź filtrowanie tekstury
- for(u32 i = 0; i < CountOf(_filter); i++) {
- if(_filter[i][0] != _filter[i][1]) {
- // Ustaw filtrowanie
- switch(_filter[i][0] = _filter[i][1]) {
- case tfPoint:
- dxe(_d3dDev->SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_NONE));
- dxe(_d3dDev->SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_POINT));
- dxe(_d3dDev->SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_POINT));
- break;
-
- case tfLinear:
- dxe(_d3dDev->SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_NONE));
- dxe(_d3dDev->SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_LINEAR));
- dxe(_d3dDev->SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR));
- break;
-
- case tfMipmaps:
- dxe(_d3dDev->SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR));
- dxe(_d3dDev->SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_LINEAR));
- dxe(_d3dDev->SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR));
- break;
- }
- Engine::Stats->States++;
- }
- }
-
- // Sprawdź zawijanie tekstury
- for(u32 i = 0; i < CountOf(_address); i++) {
- if(_address[i][0] != _address[i][1]) {
- // Ustaw zawijanie
- switch(_address[i][0] = _address[i][1]) {
- case taWrap:
- dxe(_d3dDev->SetSamplerState(i, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP));
- dxe(_d3dDev->SetSamplerState(i, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP));
- dxe(_d3dDev->SetSamplerState(i, D3DSAMP_ADDRESSW, D3DTADDRESS_WRAP));
- break;
-
- case taClamp:
- dxe(_d3dDev->SetSamplerState(i, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP));
- dxe(_d3dDev->SetSamplerState(i, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP));
- dxe(_d3dDev->SetSamplerState(i, D3DSAMP_ADDRESSW, D3DTADDRESS_CLAMP));
- break;
-
- case taMirror:
- dxe(_d3dDev->SetSamplerState(i, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR));
- dxe(_d3dDev->SetSamplerState(i, D3DSAMP_ADDRESSV, D3DTADDRESS_MIRROR));
- dxe(_d3dDev->SetSamplerState(i, D3DSAMP_ADDRESSW, D3DTADDRESS_MIRROR));
- break;
- }
- Engine::Stats->States++;
- }
- }
-
- // Sprawdź łączenie
- if(_blendMode[0] != _blendMode[1]) {
- // Ustaw łączenie
- switch(_blendMode[0] = _blendMode[1]) {
- case bmNone:
- dxe(_d3dDev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE));
- break;
-
- case bmBlend:
- dxe(_d3dDev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE));
- dxe(_d3dDev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA));
- dxe(_d3dDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA));
- break;
-
- case bmAdditive:
- dxe(_d3dDev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE));
- dxe(_d3dDev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE));
- dxe(_d3dDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE));
- break;
-
- case bmOverlay:
- dxe(_d3dDev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE));
- dxe(_d3dDev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA));
- dxe(_d3dDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE));
- break;
-
- case bmDecal:
- dxe(_d3dDev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE));
- dxe(_d3dDev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_DESTCOLOR));
- dxe(_d3dDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_SRCCOLOR));
- break;
- }
- Engine::Stats->States++;
- }
-
- // Sprawdź teksturowanie
- if(_textureMode[0] != _textureMode[1]) {
- // Ustaw teksturowanie
- switch(_textureMode[0] = _textureMode[1]) {
- case tmConst:
- dxe(_d3dDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1));
- dxe(_d3dDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR));
- dxe(_d3dDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1));
- dxe(_d3dDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR));
- dxe(_d3dDev->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE));
- dxe(_d3dDev->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE));
- break;
-
- case tmDiffuse:
- dxe(_d3dDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1));
- dxe(_d3dDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE));
- dxe(_d3dDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1));
- dxe(_d3dDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE));
- dxe(_d3dDev->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE));
- dxe(_d3dDev->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE));
- break;
-
- case tmTexture:
- dxe(_d3dDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1));
- dxe(_d3dDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE));
- dxe(_d3dDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1));
- dxe(_d3dDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE));
- dxe(_d3dDev->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE));
- dxe(_d3dDev->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE));
- break;
-
- case tmTextureConst:
- dxe(_d3dDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE));
- dxe(_d3dDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE));
- dxe(_d3dDev->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TFACTOR));
- dxe(_d3dDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE));
- dxe(_d3dDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE));
- dxe(_d3dDev->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TFACTOR));
- dxe(_d3dDev->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE));
- dxe(_d3dDev->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE));
- break;
-
- case tmTextureDiffuse:
- dxe(_d3dDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE));
- dxe(_d3dDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE));
- dxe(_d3dDev->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE));
- dxe(_d3dDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE));
- dxe(_d3dDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE));
- dxe(_d3dDev->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE));
- dxe(_d3dDev->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE));
- dxe(_d3dDev->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE));
- break;
-
- case tmMaskedColor:
- dxe(_d3dDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1));
- dxe(_d3dDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR));
- dxe(_d3dDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1));
- dxe(_d3dDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE));
- dxe(_d3dDev->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE));
- dxe(_d3dDev->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE));
- break;
- }
- Engine::Stats->States++;
- }
-
- // Sprawdź test bufora głębokości
- if(_depthTest[0] != _depthTest[1]) {
- // Ustaw test bufora głębokości
- dxe(_d3dDev->SetRenderState(D3DRS_ZENABLE, (_depthTest[0] = _depthTest[1]) ? TRUE : FALSE));
- Engine::Stats->States++;
- }
-
- // Sprawdź zapisywanie do bufora głębokości
- if(_depthWrite[0] != _depthWrite[1]) {
- // Ustaw test bufora głębokości
- dxe(_d3dDev->SetRenderState(D3DRS_ZWRITEENABLE, (_depthWrite[0] = _depthWrite[1]) ? TRUE : FALSE));
- Engine::Stats->States++;
- }
-
- // Sprawdź operacje wykonywaną przy testowaniu głębokości
- if(_depthLE[0] != _depthLE[1]) {
- // Ustaw test bufora głębokości
- dxe(_d3dDev->SetRenderState(D3DRS_ZFUNC, (_depthLE[0] = _depthLE[1]) ? D3DCMP_LESSEQUAL : D3DCMP_EQUAL));
- Engine::Stats->States++;
- }
-
- // Sprawdź przesunięcie bufora głębokości
- if(_depthBias[0] != _depthBias[1]) {
- f32 bias = -0.0001f;
-
- // Ustaw przesunięcie bufora głębokości
- dxe(_d3dDev->SetRenderState(D3DRS_DEPTHBIAS, (_depthBias[0] = _depthBias[1]) ? (u32&)bias : 0));
- Engine::Stats->States++;
- }
-
- // Sprawdź przeskalowanie bufora głębokości
- if(abs(_depthScale[0] - _depthScale[1]) < MathErr) {
- // TODO: Ustaw przeskalowanie bufora głębokości
- //dxe(_d3dDev->SetRenderState(D3DRS_DEPTHSCALE, (u32&)(_depthScale[0] = _depthScale[1])));
- //Engine::Stats->States++;
- }
-
- // Sprawdź przycinanie
- if(_cullMode[0] != _cullMode[1] || _winding[0] != _winding[1]) {
- // Zapisz przycinanie
- _cullMode[0] = _cullMode[1];
- _winding[0] = _winding[1];
-
- // Ustaw przycinanie
- dxe(_d3dDev->SetRenderState(D3DRS_CULLMODE, _cullMode[0] ? (_winding[0] ? D3DCULL_CW : D3DCULL_CCW) : D3DCULL_NONE));
- Engine::Stats->States++;
- }
-
- // Sprawdź wypełnienie
- if(_fillMode[0] != _fillMode[1]) {
- // Ustaw wypełnianie
- dxe(_d3dDev->SetRenderState(D3DRS_FILLMODE, (_fillMode[0] = _fillMode[1]) ? D3DFILL_SOLID : D3DFILL_WIREFRAME));
- Engine::Stats->States++;
- }
-
- // Sprawdź maskowanie
- if(_colorWrite[0] != _colorWrite[1]) {
- // Ustaw maskowanie
- dxe(_d3dDev->SetRenderState(D3DRS_COLORWRITEENABLE, _colorWrite[0] = _colorWrite[1]));
- Engine::Stats->States++;
- }
-
- // Sprawdź test przezroczystości
- if(_alphaTest[0] != _alphaTest[1]) {
- // Ustaw test przezroczystości
- if(_alphaTest[0] = _alphaTest[1]) {
- dxe(_d3dDev->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE));
- dxe(_d3dDev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER));
- Engine::Stats->States++;
- }
- else {
- dxe(_d3dDev->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE));
- Engine::Stats->States++;
- }
- }
-
- // Sprawdź wartość dla testu przezroczystości
- if(_alphaValue[0] != _alphaValue[1]) {
- // Ustaw wartość dla testu przezroczystości
- dxe(_d3dDev->SetRenderState(D3DRS_ALPHAREF, _alphaValue[0] = _alphaValue[1]));
- Engine::Stats->States++;
- }
-
- // Sprawdź nożyczki
- if(_scissorTest[0] != _scissorTest[1]) {
- // Ustaw nożyczki
- dxe(_d3dDev->SetRenderState(D3DRS_SCISSORTESTENABLE, (_scissorTest[0] = _scissorTest[1]) ? TRUE : FALSE));
- Engine::Stats->States++;
- }
-
- // Sprawdź obszar nożyczek
- if(_scissorRect[0].left != _scissorRect[1].left ||
- _scissorRect[0].right != _scissorRect[1].right ||
- _scissorRect[0].top != _scissorRect[1].top ||
- _scissorRect[0].bottom != _scissorRect[1].bottom) {
- // Zapisz obszar nożyczek
- _scissorRect[0] = _scissorRect[1];
-
- // Ustaw obszar nożyczek
- dxe(_d3dDev->SetScissorRect(&_scissorRect[0]));
- Engine::Stats->Clips++;
- }
-
- // Sprawdź format wierzchołków
- if(_decl[0] != _decl[1]) {
- // Ustaw format wierzchołków
- dxe(_d3dDev->SetVertexDeclaration(_decl[0] = _decl[1]));
- }
-
- // Sprawdź cieniowanie wierzchołków
- if(_vertexShader[0] != _vertexShader[1]) {
- // Ustaw cieniowanie wierzchołków
- dxe(_d3dDev->SetVertexShader(_vertexShader[0] = _vertexShader[1]));
- Engine::Stats->Shaders++;
- }
-
- // Sprawdź cieniowanie pikseli
- if(_pixelShader[0] != _pixelShader[1]) {
- // Ustaw cieniowanie pikseli
- dxe(_d3dDev->SetPixelShader(_pixelShader[0] = _pixelShader[1]));
- Engine::Stats->Shaders++;
- }
-
- // Sprawdź tekstury
- for(u32 i = 0; i < CountOf(_textures); i++) {
- if(_textures[i][0] != _textures[i][1]) {
- // Ustaw tekstury
- dxe(_d3dDev->SetTexture(i, _textures[i][0] = _textures[i][1]));
- Engine::Stats->Textures++;
- }
- }
-
- // Sprawdź bufor indeksów
- if(_indexBuffer[0] != _indexBuffer[1]) {
- // Ustaw bufor indeksów
- dxe(_d3dDev->SetIndices(_indexBuffer[0] = _indexBuffer[1]));
- Engine::Stats->Buffers++;
- }
-
- // Sprawdź bufory wierzchołków
- for(u32 i = 0; i < CountOf(_vertexBuffer); i++) {
- if(_vertexBuffer[i][0] != _vertexBuffer[i][1] ||
- _vertexOffset[i][0] != _vertexOffset[i][1] ||
- _vertexStride[i][0] != _vertexStride[i][1]) {
- // Ustaw bufor wierzchołków
- dxe(_d3dDev->SetStreamSource(i, _vertexBuffer[i][0] = _vertexBuffer[i][1], _vertexOffset[i][0] = _vertexOffset[i][1], _vertexStride[i][0] = _vertexStride[i][1]));
- Engine::Stats->Buffers++;
- }
- }
-
- // Sprawdź stałe dla pixel shadera
- if(_pixelConstsDirty[0] < _pixelConstsDirty[1]) {
- // Ustaw stałe
- dxe(_d3dDev->SetPixelShaderConstantF(_pixelConstsDirty[0], &_pixelConsts[_pixelConstsDirty[0]].X, _pixelConstsDirty[1] - _pixelConstsDirty[0]));
- Engine::Stats->Consts += _pixelConstsDirty[1] - _pixelConstsDirty[0];
-
- // Zresetuj ustawiony obszar
- _pixelConstsDirty[0] = CountOf(_pixelConsts);
- _pixelConstsDirty[1] = 0;
- }
-
- // Sprawdź stałe dla vertex shadera
- if(_vertexConstsDirty[0] < _vertexConstsDirty[1]) {
- // Ustaw stałe
- dxe(_d3dDev->SetVertexShaderConstantF(_vertexConstsDirty[0], &_vertexConsts[_vertexConstsDirty[0]].X, _vertexConstsDirty[1] - _vertexConstsDirty[0]));
- Engine::Stats->Consts += _vertexConstsDirty[1] - _vertexConstsDirty[0];
-
- // Zresetuj ustawiony obszar
- _vertexConstsDirty[0] = CountOf(_vertexConsts);
- _vertexConstsDirty[1] = 0;
- }
- }
-
- void Device::beginOcclusion() {
- // Rozpocznij zapytanie o widoczność
- dxe(_occlusion->Issue(D3DISSUE_BEGIN));
- }
-
- void Device::endOcclusion() {
- // Zakończ zapytanie o widoczność
- dxe(_occlusion->Issue(D3DISSUE_END));
- }
-
- bool Device::flushOcclusion(u32 &result) {
- HRESULT hr;
-
- // Pobierz wynik działania
- dxe(hr = _occlusion->GetData(&result, sizeof(u32), D3DGETDATA_FLUSH));
-
- // Sprawdź wynik
- return hr == S_OK;
- }
- };