#include "platform-dx/implementations.hpp" #include "game/gdevicemanager.hpp" namespace xna { void reset(GraphicsDevice::PlatformImplementation& impl) { if (impl._device) { impl._device->Release(); impl._device = nullptr; } if (impl._context) { impl._context->Release(); impl._context = nullptr; } if (impl._factory) { impl._factory->Release(); impl._factory = nullptr; } impl._blendState = nullptr; impl._swapChain = nullptr; impl._renderTarget2D = nullptr; } bool createDevice(GraphicsDevice::PlatformImplementation& impl) { auto createDeviceFlags = 0; #if _DEBUG createDeviceFlags = D3D11_CREATE_DEVICE_FLAG::D3D11_CREATE_DEVICE_DEBUG; #endif auto hr = D3D11CreateDevice( impl._adapter->impl->dxadapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, createDeviceFlags, NULL, 0, D3D11_SDK_VERSION, &impl._device, &impl._featureLevel, &impl._context); if (FAILED(hr)) { OutputDebugString("---> Usando Adaptador WARP: não há suporte ao D3D11\n"); hr = D3D11CreateDevice( NULL, D3D_DRIVER_TYPE_WARP, NULL, createDeviceFlags, NULL, 0, D3D11_SDK_VERSION, &impl._device, &impl._featureLevel, &impl._context); } return SUCCEEDED(hr); } GraphicsDevice::GraphicsDevice() { impl = unew(); impl->_adapter = GraphicsAdapter::DefaultAdapter(); impl->_adapter->CurrentDisplayMode( SurfaceFormat::Color, GraphicsDeviceManager::DefaultBackBufferWidth, GraphicsDeviceManager::DefaultBackBufferHeight); } GraphicsDevice::GraphicsDevice(GraphicsDeviceInformation const& info) { impl = unew(); impl->_adapter = info.Adapter; impl->_presentationParameters = info.Parameters; impl->_adapter->CurrentDisplayMode( impl->_presentationParameters->BackBufferFormat, impl->_presentationParameters->BackBufferWidth, impl->_presentationParameters->BackBufferHeight); } GraphicsDevice::~GraphicsDevice() { impl = nullptr; } bool GraphicsDevice::Initialize(GameWindow& gameWindow) { if (!impl) impl = uptr(); reset(*impl); auto _this = shared_from_this(); if (!createDevice(*impl)) return false; auto hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&impl->_factory); if (FAILED(hr)) return false; const auto bounds = gameWindow.ClientBounds(); impl->_viewport = xna::Viewport(0.0F, 0.0F, static_cast(bounds.Width), static_cast(bounds.Height), 0.0F, 1.F); COLORREF color = gameWindow.impl->Color(); impl->_backgroundColor[0] = GetRValue(color) / 255.0f; impl->_backgroundColor[1] = GetGValue(color) / 255.0f; impl->_backgroundColor[2] = GetBValue(color) / 255.0f; impl->_backgroundColor[3] = 1.0f; impl->_swapChain = New(_this); impl->_swapChain->Initialize(); hr = impl->_factory->MakeWindowAssociation(gameWindow.impl->WindowHandle(), DXGI_MWA_NO_ALT_ENTER); if (FAILED(hr)) return false; impl->_renderTarget2D = New(_this); if (!impl->_renderTarget2D->Initialize()) return false; impl->_renderTarget2D->Apply(); D3D11_VIEWPORT view{}; view.TopLeftX = impl->_viewport.X; view.TopLeftY = impl->_viewport.Y; view.Width = impl->_viewport.Width; view.Height = impl->_viewport.Height; view.MinDepth = impl->_viewport.MinDetph; view.MaxDepth = impl->_viewport.MaxDepth; impl->_context->RSSetViewports(1, &view); impl->_blendState = BlendState::NonPremultiplied(); impl->_blendState->Bind(_this); impl->_blendState->Apply(); return true; } bool GraphicsDevice::Present() { if (!impl) return false; const auto result = impl->_swapChain->Present(impl->_usevsync); impl->_context->OMSetRenderTargets(1, &impl->_renderTarget2D->render_impl->_renderTargetView, nullptr); return result; } void GraphicsDevice::Clear() { if (!impl) return; impl->_context->ClearRenderTargetView(impl->_renderTarget2D->render_impl->_renderTargetView, impl->_backgroundColor); } void GraphicsDevice::Clear(Color const& color) { if (!impl) return; const auto v4 = color.ToVector4(); impl->_backgroundColor[0] = v4.X; impl->_backgroundColor[1] = v4.Y; impl->_backgroundColor[2] = v4.Z; impl->_backgroundColor[3] = v4.W; impl->_context->ClearRenderTargetView( impl->_renderTarget2D->render_impl->_renderTargetView, impl->_backgroundColor); } sptr GraphicsDevice::Adapter() const { if (!impl) return nullptr; return impl->_adapter; } void GraphicsDevice::Adapter(sptr const& adapter) { if (!impl) return; impl->_adapter = adapter; } xna::Viewport GraphicsDevice::Viewport() const { if (!impl) return {}; return impl->_viewport; } void GraphicsDevice::Viewport(xna::Viewport const& viewport) { if (!impl) return; impl->_viewport = viewport; } void GraphicsDevice::UseVSync(bool use) { if (!impl) return; impl->_usevsync = use; } }