2024-06-03 21:55:09 -03:00
|
|
|
#include "xna/graphics/adapter.hpp"
|
|
|
|
#include "xna/graphics/displaymode.hpp"
|
|
|
|
#include "xna/game/gdevicemanager.hpp"
|
2024-07-07 16:06:05 -03:00
|
|
|
#include "xna/platform/dx.hpp"
|
2024-03-18 15:41:46 -03:00
|
|
|
|
|
|
|
namespace xna {
|
2024-04-23 16:11:17 -03:00
|
|
|
static size_t getDisplayModesCount(IDXGIAdapter* adapter);
|
2024-04-26 11:35:59 -03:00
|
|
|
static uptr<DisplayModeCollection> createDisplayModeCollection(std::vector<DXGI_MODE_DESC> const& source);
|
2024-03-18 15:41:46 -03:00
|
|
|
|
2024-05-19 17:52:27 -03:00
|
|
|
GraphicsAdapter::GraphicsAdapter() {
|
2024-06-22 11:52:21 -03:00
|
|
|
impl = unew<PlatformImplementation>();
|
2024-05-19 17:52:27 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
uptr<GraphicsAdapter> GraphicsAdapter::DefaultAdapter() {
|
2024-06-25 17:06:37 -03:00
|
|
|
comptr<IDXGIFactory1> pFactory = nullptr;
|
2024-04-01 16:18:18 -03:00
|
|
|
|
2024-06-25 17:06:37 -03:00
|
|
|
if FAILED(CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)pFactory.GetAddressOf()))
|
2024-07-06 12:20:54 -03:00
|
|
|
Exception::Throw(Exception::FAILED_TO_CREATE);
|
2024-04-01 16:18:18 -03:00
|
|
|
|
2024-06-25 17:06:37 -03:00
|
|
|
comptr<IDXGIAdapter1> pAdapter = nullptr;
|
2024-04-21 16:06:22 -03:00
|
|
|
|
2024-06-25 17:06:37 -03:00
|
|
|
if (pFactory->EnumAdapters1(0, pAdapter.GetAddressOf()) != DXGI_ERROR_NOT_FOUND) {
|
2024-06-22 11:52:21 -03:00
|
|
|
auto adp = unew<GraphicsAdapter>();
|
2024-04-21 16:06:22 -03:00
|
|
|
|
2024-05-19 17:52:27 -03:00
|
|
|
adp->impl->_index = 0;
|
|
|
|
adp->impl->dxadapter = pAdapter;
|
2024-04-21 16:06:22 -03:00
|
|
|
|
2024-04-22 16:14:55 -03:00
|
|
|
return adp;
|
2024-04-21 16:06:22 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2024-05-19 17:52:27 -03:00
|
|
|
void GraphicsAdapter::Adapters(std::vector<uptr<GraphicsAdapter>>& adapters) {
|
2024-06-25 17:06:37 -03:00
|
|
|
comptr<IDXGIFactory1> pFactory = nullptr;
|
2024-04-21 16:06:22 -03:00
|
|
|
|
2024-06-25 17:06:37 -03:00
|
|
|
if FAILED(CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)pFactory.GetAddressOf()))
|
2024-07-06 12:20:54 -03:00
|
|
|
Exception::Throw(Exception::FAILED_TO_CREATE);
|
2024-04-21 16:06:22 -03:00
|
|
|
|
2024-06-25 17:06:37 -03:00
|
|
|
comptr<IDXGIAdapter1> pAdapter = nullptr;
|
2024-04-21 16:06:22 -03:00
|
|
|
UINT count = 0;
|
|
|
|
|
2024-06-25 17:06:37 -03:00
|
|
|
for (; pFactory->EnumAdapters1(count, pAdapter.GetAddressOf()) != DXGI_ERROR_NOT_FOUND; ++count) {
|
2024-06-22 11:52:21 -03:00
|
|
|
auto adp = unew<GraphicsAdapter>();
|
2024-04-21 16:06:22 -03:00
|
|
|
|
2024-05-19 17:52:27 -03:00
|
|
|
adp->impl->_index = count;
|
|
|
|
adp->impl->dxadapter = pAdapter;
|
2024-04-21 16:06:22 -03:00
|
|
|
|
|
|
|
adapters.push_back(std::move(adp));
|
|
|
|
}
|
2024-05-19 17:52:27 -03:00
|
|
|
}
|
2024-04-01 16:18:18 -03:00
|
|
|
|
2024-03-18 15:41:46 -03:00
|
|
|
String GraphicsAdapter::Description() const {
|
2024-05-19 17:52:27 -03:00
|
|
|
if (!impl->dxadapter) return String();
|
2024-04-21 16:06:22 -03:00
|
|
|
|
2024-03-18 15:41:46 -03:00
|
|
|
DXGI_ADAPTER_DESC1 desc;
|
2024-05-19 17:52:27 -03:00
|
|
|
impl->dxadapter->GetDesc1(&desc);
|
2024-06-01 20:45:00 -03:00
|
|
|
String description = XnaHelper::ToString(desc.Description);
|
2024-03-18 15:41:46 -03:00
|
|
|
return description;
|
|
|
|
}
|
|
|
|
|
|
|
|
Uint GraphicsAdapter::DeviceId() const {
|
2024-05-19 17:52:27 -03:00
|
|
|
if (!impl->dxadapter) return 0;
|
2024-04-21 16:06:22 -03:00
|
|
|
|
2024-03-18 15:41:46 -03:00
|
|
|
DXGI_ADAPTER_DESC1 desc;
|
2024-05-19 17:52:27 -03:00
|
|
|
impl->dxadapter->GetDesc1(&desc);
|
2024-03-18 15:41:46 -03:00
|
|
|
|
|
|
|
return static_cast<Uint>(desc.DeviceId);
|
|
|
|
}
|
|
|
|
|
|
|
|
String GraphicsAdapter::DeviceName() const {
|
2024-05-19 17:52:27 -03:00
|
|
|
if (!impl->dxadapter) return String();
|
2024-04-21 16:06:22 -03:00
|
|
|
|
2024-03-18 15:41:46 -03:00
|
|
|
IDXGIOutput* pOutput = nullptr;
|
|
|
|
DXGI_OUTPUT_DESC outputDesc;
|
|
|
|
|
2024-05-19 17:52:27 -03:00
|
|
|
if (impl->dxadapter->EnumOutputs(0, &pOutput) != DXGI_ERROR_NOT_FOUND) {
|
2024-03-18 15:41:46 -03:00
|
|
|
pOutput->GetDesc(&outputDesc);
|
2024-06-01 20:45:00 -03:00
|
|
|
String deviceName = XnaHelper::ToString(outputDesc.DeviceName);
|
2024-03-18 15:41:46 -03:00
|
|
|
|
|
|
|
pOutput->Release();
|
|
|
|
pOutput = nullptr;
|
|
|
|
|
|
|
|
return deviceName;
|
|
|
|
}
|
|
|
|
|
|
|
|
return String();
|
|
|
|
}
|
|
|
|
|
|
|
|
intptr_t GraphicsAdapter::MonitorHandle() const {
|
2024-05-19 17:52:27 -03:00
|
|
|
if (!impl->dxadapter) return 0;
|
2024-04-21 16:06:22 -03:00
|
|
|
|
2024-03-18 15:41:46 -03:00
|
|
|
IDXGIOutput* pOutput = nullptr;
|
|
|
|
DXGI_OUTPUT_DESC outputDesc;
|
|
|
|
|
2024-05-19 17:52:27 -03:00
|
|
|
if (impl->dxadapter->EnumOutputs(0, &pOutput) != DXGI_ERROR_NOT_FOUND) {
|
2024-03-18 15:41:46 -03:00
|
|
|
pOutput->GetDesc(&outputDesc);
|
|
|
|
|
|
|
|
pOutput->Release();
|
|
|
|
pOutput = nullptr;
|
|
|
|
|
|
|
|
return reinterpret_cast<intptr_t>(outputDesc.Monitor);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Uint GraphicsAdapter::Revision() const {
|
2024-05-19 17:52:27 -03:00
|
|
|
if (!impl->dxadapter) return 0;
|
2024-04-21 16:06:22 -03:00
|
|
|
|
2024-03-18 15:41:46 -03:00
|
|
|
DXGI_ADAPTER_DESC1 desc;
|
2024-05-19 17:52:27 -03:00
|
|
|
impl->dxadapter->GetDesc1(&desc);
|
2024-03-18 15:41:46 -03:00
|
|
|
|
|
|
|
return static_cast<Uint>(desc.Revision);
|
|
|
|
}
|
|
|
|
|
|
|
|
Uint GraphicsAdapter::SubSystemId() const {
|
2024-05-19 17:52:27 -03:00
|
|
|
if (!impl->dxadapter) return 0;
|
2024-04-21 16:06:22 -03:00
|
|
|
|
2024-03-18 15:41:46 -03:00
|
|
|
DXGI_ADAPTER_DESC1 desc;
|
2024-05-19 17:52:27 -03:00
|
|
|
impl->dxadapter->GetDesc1(&desc);
|
2024-03-18 15:41:46 -03:00
|
|
|
|
|
|
|
return static_cast<Uint>(desc.SubSysId);
|
|
|
|
}
|
|
|
|
|
|
|
|
Uint GraphicsAdapter::VendorId() const {
|
2024-05-19 17:52:27 -03:00
|
|
|
if (!impl->dxadapter) return 0;
|
2024-04-21 16:06:22 -03:00
|
|
|
|
2024-03-18 15:41:46 -03:00
|
|
|
DXGI_ADAPTER_DESC1 desc;
|
2024-05-19 17:52:27 -03:00
|
|
|
impl->dxadapter->GetDesc1(&desc);
|
2024-03-18 15:41:46 -03:00
|
|
|
|
|
|
|
return static_cast<Uint>(desc.VendorId);
|
2024-04-23 16:11:17 -03:00
|
|
|
}
|
2024-04-21 21:28:07 -03:00
|
|
|
|
2024-04-26 11:35:59 -03:00
|
|
|
uptr<DisplayModeCollection> GraphicsAdapter::SupportedDisplayModes() const {
|
2024-05-19 17:52:27 -03:00
|
|
|
if (!impl->dxadapter) return nullptr;
|
2024-04-21 16:06:22 -03:00
|
|
|
|
2024-06-25 17:06:37 -03:00
|
|
|
const auto totalDisplay = getDisplayModesCount(impl->dxadapter.Get());
|
2024-04-22 11:22:18 -03:00
|
|
|
|
|
|
|
if (totalDisplay == 0)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
IDXGIOutput* pOutput = nullptr;
|
|
|
|
UINT bufferOffset = 0;
|
|
|
|
|
2024-04-21 21:28:07 -03:00
|
|
|
std::vector<DXGI_MODE_DESC> buffer(totalDisplay);
|
2024-03-18 15:41:46 -03:00
|
|
|
|
2024-05-19 17:52:27 -03:00
|
|
|
if (impl->dxadapter->EnumOutputs(0, &pOutput) != DXGI_ERROR_NOT_FOUND) {
|
2024-03-18 15:41:46 -03:00
|
|
|
for (size_t f = 0; f < SURFACE_FORMAT_COUNT; ++f) {
|
|
|
|
const auto currentSurface = static_cast<SurfaceFormat>(f);
|
2024-06-22 22:05:35 -03:00
|
|
|
DXGI_FORMAT format = DxHelpers::SurfaceFormatToDx(currentSurface);
|
2024-03-18 15:41:46 -03:00
|
|
|
|
2024-04-22 11:22:18 -03:00
|
|
|
UINT numModes = 0;
|
2024-03-18 15:41:46 -03:00
|
|
|
pOutput->GetDisplayModeList(format, 0, &numModes, nullptr);
|
|
|
|
|
|
|
|
if (numModes == 0)
|
2024-04-21 21:28:07 -03:00
|
|
|
continue;
|
2024-03-18 15:41:46 -03:00
|
|
|
|
2024-04-22 11:22:18 -03:00
|
|
|
pOutput->GetDisplayModeList(format, 0, &numModes, buffer.data() + bufferOffset);
|
2024-03-18 15:41:46 -03:00
|
|
|
|
2024-04-22 11:22:18 -03:00
|
|
|
bufferOffset += numModes;
|
2024-04-21 20:03:36 -03:00
|
|
|
}
|
|
|
|
}
|
2024-03-18 15:41:46 -03:00
|
|
|
|
2024-04-21 20:03:36 -03:00
|
|
|
if (!pOutput)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
pOutput->Release();
|
|
|
|
pOutput = nullptr;
|
|
|
|
|
2024-04-23 16:11:17 -03:00
|
|
|
return createDisplayModeCollection(buffer);
|
|
|
|
}
|
|
|
|
|
2024-04-26 11:35:59 -03:00
|
|
|
uptr<DisplayModeCollection> GraphicsAdapter::SupportedDisplayModes(SurfaceFormat surfaceFormat) const
|
2024-04-23 16:11:17 -03:00
|
|
|
{
|
2024-05-19 17:52:27 -03:00
|
|
|
if (!impl->dxadapter) return nullptr;
|
2024-04-23 16:11:17 -03:00
|
|
|
|
|
|
|
IDXGIOutput* pOutput = nullptr;
|
|
|
|
UINT bufferOffset = 0;
|
|
|
|
|
2024-05-19 17:52:27 -03:00
|
|
|
if (impl->dxadapter->EnumOutputs(0, &pOutput) != DXGI_ERROR_NOT_FOUND) {
|
2024-06-22 22:05:35 -03:00
|
|
|
DXGI_FORMAT format = DxHelpers::SurfaceFormatToDx(surfaceFormat);
|
2024-04-23 16:11:17 -03:00
|
|
|
|
|
|
|
UINT numModes = 0;
|
|
|
|
|
|
|
|
pOutput->GetDisplayModeList(format, 0, &numModes, nullptr);
|
|
|
|
|
|
|
|
if (numModes == 0)
|
2024-06-22 11:52:21 -03:00
|
|
|
return unew<DisplayModeCollection>();
|
2024-04-23 16:11:17 -03:00
|
|
|
|
|
|
|
std::vector<DXGI_MODE_DESC> buffer(numModes);
|
|
|
|
pOutput->GetDisplayModeList(format, 0, &numModes, buffer.data());
|
|
|
|
|
|
|
|
pOutput->Release();
|
|
|
|
pOutput = nullptr;
|
|
|
|
|
|
|
|
return createDisplayModeCollection(buffer);
|
|
|
|
}
|
|
|
|
|
2024-06-22 11:52:21 -03:00
|
|
|
return unew<DisplayModeCollection>();
|
2024-04-23 16:11:17 -03:00
|
|
|
}
|
|
|
|
|
2024-04-26 11:35:59 -03:00
|
|
|
sptr<DisplayMode> GraphicsAdapter::CurrentDisplayMode() {
|
2024-05-19 17:52:27 -03:00
|
|
|
if (!impl->_currentDisplayMode) {
|
2024-04-23 16:11:17 -03:00
|
|
|
CurrentDisplayMode(SurfaceFormat::Color, GraphicsDeviceManager::DefaultBackBufferWidth, GraphicsDeviceManager::DefaultBackBufferHeight);
|
|
|
|
}
|
|
|
|
|
2024-05-19 17:52:27 -03:00
|
|
|
return impl->_currentDisplayMode;
|
2024-04-23 16:11:17 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
void GraphicsAdapter::CurrentDisplayMode(SurfaceFormat surfaceFormat, Uint width, Uint height) {
|
|
|
|
const auto modes = SupportedDisplayModes(surfaceFormat);
|
|
|
|
|
2024-05-20 11:51:32 -03:00
|
|
|
for (size_t i = 0; i < modes->DisplayModes.size(); ++i) {
|
|
|
|
auto& m = modes->DisplayModes[i];
|
2024-04-23 16:11:17 -03:00
|
|
|
|
2024-05-20 11:51:32 -03:00
|
|
|
if (m->Format == surfaceFormat && m->Width == width && m->Height == height) {
|
2024-05-19 17:52:27 -03:00
|
|
|
impl->_currentDisplayMode = m;
|
2024-04-23 16:11:17 -03:00
|
|
|
}
|
2024-05-20 11:51:32 -03:00
|
|
|
else if(i + 1 == modes->DisplayModes.size()) {
|
2024-05-19 17:52:27 -03:00
|
|
|
impl->_currentDisplayMode = m;
|
2024-04-23 16:11:17 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-19 17:52:27 -03:00
|
|
|
bool GraphicsAdapter::PlatformImplementation::GetOutput(UINT slot, IDXGIOutput*& output) {
|
2024-04-23 16:11:17 -03:00
|
|
|
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<SurfaceFormat>(f);
|
2024-06-22 22:05:35 -03:00
|
|
|
DXGI_FORMAT format = DxHelpers::SurfaceFormatToDx(currentSurface);
|
2024-04-23 16:11:17 -03:00
|
|
|
|
|
|
|
UINT num = 0;
|
|
|
|
pOutput->GetDisplayModeList(format, 0, &num, nullptr);
|
|
|
|
|
|
|
|
numModes += num;
|
|
|
|
}
|
|
|
|
|
|
|
|
pOutput->Release();
|
|
|
|
pOutput = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return numModes;
|
|
|
|
}
|
|
|
|
|
2024-04-26 11:35:59 -03:00
|
|
|
static uptr<DisplayModeCollection> createDisplayModeCollection(std::vector<DXGI_MODE_DESC> const& source) {
|
2024-06-22 11:52:21 -03:00
|
|
|
auto collection = unew<DisplayModeCollection>();
|
2024-04-21 20:03:36 -03:00
|
|
|
DisplayMode currentDisplayMode;
|
2024-04-26 11:35:59 -03:00
|
|
|
std::vector<sptr<DisplayMode>> displayList;
|
|
|
|
sptr<DisplayMode> pDisplay = nullptr;
|
2024-04-21 20:03:36 -03:00
|
|
|
|
2024-04-23 16:11:17 -03:00
|
|
|
for (size_t i = 0; i < source.size(); ++i) {
|
|
|
|
auto& modedesc = source[i];
|
2024-04-21 20:03:36 -03:00
|
|
|
|
|
|
|
DisplayModeDescription description;
|
|
|
|
description._refreshRate = modedesc.RefreshRate;
|
|
|
|
description._scaling = static_cast<DisplayModeScaling>(modedesc.Scaling);
|
|
|
|
description._scanlineOrdering = static_cast<DisplayModeScanlineOrder>(modedesc.ScanlineOrdering);
|
|
|
|
|
2024-06-25 22:04:09 -03:00
|
|
|
if (pDisplay && pDisplay->Width == modedesc.Width && pDisplay->Height == modedesc.Height && pDisplay->Format == DxHelpers::SurfaceFormatToXna(modedesc.Format)) {
|
2024-05-20 11:51:32 -03:00
|
|
|
pDisplay->impl->Descriptions.push_back(description);
|
2024-04-21 20:03:36 -03:00
|
|
|
}
|
|
|
|
else {
|
2024-06-22 11:52:21 -03:00
|
|
|
pDisplay = snew<DisplayMode>();
|
2024-05-20 11:51:32 -03:00
|
|
|
pDisplay->Width = modedesc.Width;
|
|
|
|
pDisplay->Height = modedesc.Height;
|
2024-06-25 22:04:09 -03:00
|
|
|
pDisplay->Format = DxHelpers::SurfaceFormatToXna(modedesc.Format);
|
2024-05-20 11:51:32 -03:00
|
|
|
pDisplay->impl->Descriptions.push_back(description);
|
2024-04-21 20:03:36 -03:00
|
|
|
displayList.push_back(pDisplay);
|
|
|
|
}
|
2024-03-18 15:41:46 -03:00
|
|
|
}
|
|
|
|
|
2024-05-20 11:51:32 -03:00
|
|
|
collection->DisplayModes = displayList;
|
2024-04-21 20:03:36 -03:00
|
|
|
|
2024-04-23 16:11:17 -03:00
|
|
|
return collection;
|
2024-04-21 19:55:50 -03:00
|
|
|
}
|
2024-03-18 15:41:46 -03:00
|
|
|
}
|