#include "xna/graphics/adapter.hpp" #include "xna/graphics/displaymode.hpp" #include "xna/game/gdevicemanager.hpp" #include "xna/platform-dx/dx.hpp" namespace xna { static size_t getDisplayModesCount(IDXGIAdapter* adapter); static uptr createDisplayModeCollection(std::vector const& source); GraphicsAdapter::GraphicsAdapter() { impl = unew(); } GraphicsAdapter::~GraphicsAdapter() { impl = nullptr; } uptr GraphicsAdapter::DefaultAdapter() { IDXGIFactory1* pFactory = nullptr; if FAILED(CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&pFactory)) Exception::Throw(ExMessage::CreateComponent); IDXGIAdapter1* pAdapter = nullptr; if (pFactory->EnumAdapters1(0, &pAdapter) != DXGI_ERROR_NOT_FOUND) { auto adp = unew(); adp->impl->_index = 0; adp->impl->dxadapter = pAdapter; return adp; } pFactory->Release(); pFactory = nullptr; return nullptr; } void GraphicsAdapter::Adapters(std::vector>& adapters){ IDXGIFactory1* pFactory = nullptr; if FAILED(CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&pFactory)) Exception::Throw(ExMessage::CreateComponent); IDXGIAdapter1* pAdapter = nullptr; UINT count = 0; for (; pFactory->EnumAdapters1(count, &pAdapter) != DXGI_ERROR_NOT_FOUND; ++count) { auto adp = snew(); adp->impl->_index = count; adp->impl->dxadapter = pAdapter; adapters.push_back(adp); } pFactory->Release(); pFactory = nullptr; } void GraphicsAdapter::Adapters(std::vector>& adapters) { IDXGIFactory1* pFactory = nullptr; if FAILED(CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&pFactory)) Exception::Throw(ExMessage::CreateComponent); IDXGIAdapter1* pAdapter = nullptr; UINT count = 0; for (; pFactory->EnumAdapters1(count, &pAdapter) != DXGI_ERROR_NOT_FOUND; ++count) { auto adp = unew(); adp->impl->_index = count; adp->impl->dxadapter = pAdapter; adapters.push_back(std::move(adp)); } pFactory->Release(); pFactory = nullptr; } String GraphicsAdapter::Description() const { if (!impl->dxadapter) return String(); DXGI_ADAPTER_DESC1 desc; impl->dxadapter->GetDesc1(&desc); String description = XnaHelper::ToString(desc.Description); return description; } Uint GraphicsAdapter::DeviceId() const { if (!impl->dxadapter) return 0; DXGI_ADAPTER_DESC1 desc; impl->dxadapter->GetDesc1(&desc); return static_cast(desc.DeviceId); } String GraphicsAdapter::DeviceName() const { if (!impl->dxadapter) return String(); IDXGIOutput* pOutput = nullptr; DXGI_OUTPUT_DESC outputDesc; if (impl->dxadapter->EnumOutputs(0, &pOutput) != DXGI_ERROR_NOT_FOUND) { pOutput->GetDesc(&outputDesc); String deviceName = XnaHelper::ToString(outputDesc.DeviceName); pOutput->Release(); pOutput = nullptr; return deviceName; } return String(); } intptr_t GraphicsAdapter::MonitorHandle() const { if (!impl->dxadapter) return 0; IDXGIOutput* pOutput = nullptr; DXGI_OUTPUT_DESC outputDesc; if (impl->dxadapter->EnumOutputs(0, &pOutput) != DXGI_ERROR_NOT_FOUND) { pOutput->GetDesc(&outputDesc); pOutput->Release(); pOutput = nullptr; return reinterpret_cast(outputDesc.Monitor); } return 0; } Uint GraphicsAdapter::Revision() const { if (!impl->dxadapter) return 0; DXGI_ADAPTER_DESC1 desc; impl->dxadapter->GetDesc1(&desc); return static_cast(desc.Revision); } Uint GraphicsAdapter::SubSystemId() const { if (!impl->dxadapter) return 0; DXGI_ADAPTER_DESC1 desc; impl->dxadapter->GetDesc1(&desc); return static_cast(desc.SubSysId); } Uint GraphicsAdapter::VendorId() const { if (!impl->dxadapter) return 0; DXGI_ADAPTER_DESC1 desc; impl->dxadapter->GetDesc1(&desc); return static_cast(desc.VendorId); } uptr GraphicsAdapter::SupportedDisplayModes() const { if (!impl->dxadapter) return nullptr; const auto totalDisplay = getDisplayModesCount(impl->dxadapter); if (totalDisplay == 0) return nullptr; IDXGIOutput* pOutput = nullptr; UINT bufferOffset = 0; std::vector buffer(totalDisplay); if (impl->dxadapter->EnumOutputs(0, &pOutput) != DXGI_ERROR_NOT_FOUND) { for (size_t f = 0; f < SURFACE_FORMAT_COUNT; ++f) { const auto currentSurface = static_cast(f); DXGI_FORMAT format = DxHelpers::ConvertSurfaceToDXGIFORMAT(currentSurface); UINT numModes = 0; pOutput->GetDisplayModeList(format, 0, &numModes, nullptr); if (numModes == 0) continue; pOutput->GetDisplayModeList(format, 0, &numModes, buffer.data() + bufferOffset); bufferOffset += numModes; } } if (!pOutput) return nullptr; pOutput->Release(); pOutput = nullptr; return createDisplayModeCollection(buffer); } uptr GraphicsAdapter::SupportedDisplayModes(SurfaceFormat surfaceFormat) const { if (!impl->dxadapter) return nullptr; IDXGIOutput* pOutput = nullptr; UINT bufferOffset = 0; if (impl->dxadapter->EnumOutputs(0, &pOutput) != DXGI_ERROR_NOT_FOUND) { DXGI_FORMAT format = DxHelpers::ConvertSurfaceToDXGIFORMAT(surfaceFormat); UINT numModes = 0; pOutput->GetDisplayModeList(format, 0, &numModes, nullptr); if (numModes == 0) return unew(); std::vector buffer(numModes); pOutput->GetDisplayModeList(format, 0, &numModes, buffer.data()); pOutput->Release(); pOutput = nullptr; return createDisplayModeCollection(buffer); } return unew(); } sptr GraphicsAdapter::CurrentDisplayMode() { if (!impl->_currentDisplayMode) { CurrentDisplayMode(SurfaceFormat::Color, GraphicsDeviceManager::DefaultBackBufferWidth, GraphicsDeviceManager::DefaultBackBufferHeight); } return impl->_currentDisplayMode; } void GraphicsAdapter::CurrentDisplayMode(SurfaceFormat surfaceFormat, Uint width, Uint height) { const auto modes = SupportedDisplayModes(surfaceFormat); for (size_t i = 0; i < modes->DisplayModes.size(); ++i) { auto& m = modes->DisplayModes[i]; if (m->Format == surfaceFormat && m->Width == width && m->Height == height) { impl->_currentDisplayMode = m; } else if(i + 1 == modes->DisplayModes.size()) { impl->_currentDisplayMode = m; } } } bool GraphicsAdapter::PlatformImplementation::GetOutput(UINT slot, IDXGIOutput*& output) { if (!dxadapter) return false; if (dxadapter->EnumOutputs(slot, &output) != DXGI_ERROR_NOT_FOUND) return true; return false; } //INTERNAL FUNCTIONS static size_t getDisplayModesCount(IDXGIAdapter* adapter) { IDXGIOutput* pOutput = nullptr; size_t numModes = 0; if (adapter->EnumOutputs(0, &pOutput) != DXGI_ERROR_NOT_FOUND) { for (size_t f = 0; f < SURFACE_FORMAT_COUNT; ++f) { const auto currentSurface = static_cast(f); DXGI_FORMAT format = DxHelpers::ConvertSurfaceToDXGIFORMAT(currentSurface); UINT num = 0; pOutput->GetDisplayModeList(format, 0, &num, nullptr); numModes += num; } pOutput->Release(); pOutput = nullptr; } return numModes; } static uptr createDisplayModeCollection(std::vector const& source) { auto collection = unew(); DisplayMode currentDisplayMode; std::vector> displayList; sptr pDisplay = nullptr; for (size_t i = 0; i < source.size(); ++i) { auto& modedesc = source[i]; DisplayModeDescription description; description._refreshRate = modedesc.RefreshRate; description._scaling = static_cast(modedesc.Scaling); description._scanlineOrdering = static_cast(modedesc.ScanlineOrdering); if (pDisplay && pDisplay->Width == modedesc.Width && pDisplay->Height == modedesc.Height && pDisplay->Format == DxHelpers::ConvertDXGIFORMATToSurface(modedesc.Format)) { pDisplay->impl->Descriptions.push_back(description); } else { pDisplay = snew(); pDisplay->Width = modedesc.Width; pDisplay->Height = modedesc.Height; pDisplay->Format = DxHelpers::ConvertDXGIFORMATToSurface(modedesc.Format); pDisplay->impl->Descriptions.push_back(description); displayList.push_back(pDisplay); } } collection->DisplayModes = displayList; return collection; } }