2024-07-13 22:55:36 -03:00
|
|
|
#include "xna/xna-dx.hpp"
|
2024-03-18 15:41:46 -03:00
|
|
|
|
2024-07-20 19:08:40 -03:00
|
|
|
namespace xna {
|
|
|
|
static void setOutputVars(comptr<IDXGIAdapter1> const& adapter, String& deviceName, intptr_t& monitorHandle);
|
2024-04-23 16:11:17 -03:00
|
|
|
static size_t getDisplayModesCount(IDXGIAdapter* adapter);
|
2024-07-20 22:20:18 -03:00
|
|
|
static sptr<DisplayModeCollection> createDisplayModeCollection(std::vector<DXGI_MODE_DESC1> const& source);
|
|
|
|
static void setCurrentDisplayMode(DisplayModeCollection& displayModes, SurfaceFormat surfaceFormat, Uint width, Uint height, sptr<DisplayMode>& currentDisplayMode);
|
|
|
|
static sptr<DisplayModeCollection> getSupportedDisplayModes(comptr<IDXGIAdapter1>& dxAdapter);
|
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-07-20 19:08:40 -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-07-20 19:08:40 -03:00
|
|
|
|
2024-06-25 17:06:37 -03:00
|
|
|
if (pFactory->EnumAdapters1(0, pAdapter.GetAddressOf()) != DXGI_ERROR_NOT_FOUND) {
|
2024-07-20 19:08:40 -03:00
|
|
|
auto adp = uptr<GraphicsAdapter>(new GraphicsAdapter());
|
|
|
|
|
2024-07-16 12:28:03 -03:00
|
|
|
adp->impl->dxAdapter = pAdapter;
|
2024-07-20 19:08:40 -03:00
|
|
|
adp->impl->dxFactory = pFactory;
|
|
|
|
|
|
|
|
DXGI_ADAPTER_DESC1 desc{};
|
|
|
|
pAdapter->GetDesc1(&desc);
|
|
|
|
|
|
|
|
adp->description = XnaHelper::ToString(desc.Description);
|
|
|
|
adp->deviceId = static_cast<Uint>(desc.DeviceId);
|
2024-07-19 22:11:57 -03:00
|
|
|
adp->isDefault = true;
|
2024-07-20 19:08:40 -03:00
|
|
|
adp->revision = static_cast<Uint>(desc.Revision);
|
|
|
|
adp->subSystemId = static_cast<Uint>(desc.SubSysId);
|
|
|
|
adp->vendorId = static_cast<Uint>(desc.VendorId);
|
|
|
|
|
|
|
|
setOutputVars(pAdapter, adp->deviceName, adp->monitorHandle);
|
|
|
|
|
2024-07-21 21:54:50 -03:00
|
|
|
adp->supportedDisplayModes = getSupportedDisplayModes(pAdapter);
|
|
|
|
|
2024-07-31 16:30:47 -03:00
|
|
|
if (adp->supportedDisplayModes && adp->supportedDisplayModes->Count() > 0) {
|
|
|
|
setCurrentDisplayMode(*adp->supportedDisplayModes, SurfaceFormat::Color,
|
|
|
|
GraphicsDeviceManager::DefaultBackBufferWidth,
|
|
|
|
GraphicsDeviceManager::DefaultBackBufferHeight, adp->currentDisplayMode);
|
|
|
|
}
|
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-07-20 19:08:40 -03:00
|
|
|
comptr<IDXGIAdapter1> pAdapter = nullptr;
|
2024-04-21 16:06:22 -03:00
|
|
|
|
2024-07-16 12:28:03 -03:00
|
|
|
for (UINT count = 0; pFactory->EnumAdapters1(count, pAdapter.GetAddressOf()) != DXGI_ERROR_NOT_FOUND; ++count) {
|
2024-07-20 19:08:40 -03:00
|
|
|
auto adp = uptr<GraphicsAdapter>(new GraphicsAdapter());
|
2024-04-21 16:06:22 -03:00
|
|
|
|
2024-07-16 12:28:03 -03:00
|
|
|
adp->impl->dxAdapter = pAdapter;
|
|
|
|
adp->impl->dxFactory = pFactory;
|
2024-04-21 16:06:22 -03:00
|
|
|
|
2024-07-20 19:08:40 -03:00
|
|
|
DXGI_ADAPTER_DESC1 desc{};
|
|
|
|
pAdapter->GetDesc1(&desc);
|
|
|
|
|
|
|
|
adp->description = XnaHelper::ToString(desc.Description);
|
|
|
|
adp->deviceId = static_cast<Uint>(desc.DeviceId);
|
2024-07-19 22:11:57 -03:00
|
|
|
adp->isDefault = count == 0;
|
2024-07-20 19:08:40 -03:00
|
|
|
adp->revision = static_cast<Uint>(desc.Revision);
|
|
|
|
adp->subSystemId = static_cast<Uint>(desc.SubSysId);
|
|
|
|
adp->vendorId = static_cast<Uint>(desc.VendorId);
|
|
|
|
|
|
|
|
setOutputVars(pAdapter, adp->deviceName, adp->monitorHandle);
|
|
|
|
|
2024-07-20 22:20:18 -03:00
|
|
|
adp->supportedDisplayModes = getSupportedDisplayModes(pAdapter);
|
|
|
|
|
2024-07-31 16:30:47 -03:00
|
|
|
if (adp->supportedDisplayModes && adp->supportedDisplayModes->Count() > 0) {
|
|
|
|
setCurrentDisplayMode(*adp->supportedDisplayModes, SurfaceFormat::Color,
|
|
|
|
GraphicsDeviceManager::DefaultBackBufferWidth,
|
|
|
|
GraphicsDeviceManager::DefaultBackBufferHeight, adp->currentDisplayMode);
|
|
|
|
}
|
|
|
|
|
2024-07-19 22:11:57 -03:00
|
|
|
adapters.push_back(std::move(adp));
|
2024-03-18 15:41:46 -03:00
|
|
|
}
|
2024-07-20 19:08:40 -03:00
|
|
|
}
|
2024-04-21 21:28:07 -03:00
|
|
|
|
2024-07-20 23:44:10 -03:00
|
|
|
bool GraphicsAdapter::QueryBackBufferFormat(
|
|
|
|
GraphicsProfile graphicsProfile, SurfaceFormat format,
|
|
|
|
DepthFormat depthFormat, Int multiSampleCount,
|
|
|
|
SurfaceFormat& selectedFormat, DepthFormat& selectedDepthFormat,
|
|
|
|
Int& selectedMultiSampleCount) const
|
|
|
|
{
|
2024-07-21 20:37:16 -03:00
|
|
|
selectedFormat = format;
|
|
|
|
selectedDepthFormat = depthFormat;
|
|
|
|
selectedMultiSampleCount = multiSampleCount;
|
|
|
|
|
2024-07-20 23:44:10 -03:00
|
|
|
comptr<IDXGIOutput> pOutput = nullptr;
|
|
|
|
|
|
|
|
if (impl->dxAdapter->EnumOutputs(0, pOutput.GetAddressOf()) != DXGI_ERROR_NOT_FOUND){
|
|
|
|
comptr<IDXGIOutput1> pOutput1 = nullptr;
|
|
|
|
|
|
|
|
pOutput->QueryInterface(IID_IDXGIOutput1, (void**)pOutput1.GetAddressOf());
|
|
|
|
|
|
|
|
DXGI_MODE_DESC1 modeToMath{};
|
2024-07-21 20:37:16 -03:00
|
|
|
modeToMath.Format = DxHelpers::SurfaceFormatToDx(format);
|
|
|
|
|
|
|
|
//If pConcernedDevice is NULL, the Format member of DXGI_MODE_DESC1 cannot be DXGI_FORMAT_UNKNOWN.
|
|
|
|
if (modeToMath.Format == DXGI_FORMAT_UNKNOWN)
|
|
|
|
return false;
|
2024-07-20 23:44:10 -03:00
|
|
|
|
|
|
|
DXGI_MODE_DESC1 closestMath;
|
2024-07-21 20:37:16 -03:00
|
|
|
const auto hresult = pOutput1->FindClosestMatchingMode1(&modeToMath, &closestMath, nullptr);
|
|
|
|
|
|
|
|
if FAILED(hresult)
|
|
|
|
return false;
|
2024-07-20 23:44:10 -03:00
|
|
|
|
|
|
|
selectedFormat = DxHelpers::SurfaceFormatToXna(closestMath.Format);
|
|
|
|
|
|
|
|
return selectedFormat == format;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-07-20 22:20:18 -03:00
|
|
|
//INTERNAL FUNCTIONS
|
2024-04-21 16:06:22 -03:00
|
|
|
|
2024-07-20 22:20:18 -03:00
|
|
|
sptr<DisplayModeCollection> getSupportedDisplayModes(comptr<IDXGIAdapter1>& dxAdapter) {
|
|
|
|
const auto totalDisplay = getDisplayModesCount(dxAdapter.Get());
|
2024-04-22 11:22:18 -03:00
|
|
|
|
|
|
|
if (totalDisplay == 0)
|
|
|
|
return nullptr;
|
|
|
|
|
2024-07-16 12:28:03 -03:00
|
|
|
comptr<IDXGIOutput> pOutput = nullptr;
|
2024-07-20 22:20:18 -03:00
|
|
|
comptr<IDXGIOutput1> pOutput1 = nullptr;
|
2024-04-22 11:22:18 -03:00
|
|
|
UINT bufferOffset = 0;
|
2024-07-20 19:08:40 -03:00
|
|
|
|
2024-07-20 22:20:18 -03:00
|
|
|
std::vector<DXGI_MODE_DESC1> buffer(totalDisplay);
|
2024-07-20 19:08:40 -03:00
|
|
|
|
2024-07-20 22:20:18 -03:00
|
|
|
if (dxAdapter->EnumOutputs(0, pOutput.GetAddressOf()) != 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-07-20 22:20:18 -03:00
|
|
|
|
|
|
|
if (!pOutput1) {
|
|
|
|
pOutput->QueryInterface(IID_IDXGIOutput1, (void**)pOutput1.GetAddressOf());
|
|
|
|
}
|
|
|
|
|
|
|
|
//See ref: https://learn.microsoft.com/en-us/windows/win32/api/dxgi/nf-dxgi-idxgioutput-getdisplaymodelist?redirectedfrom=MSDN
|
|
|
|
pOutput1->GetDisplayModeList1(format, 0, &numModes, nullptr);
|
2024-03-18 15:41:46 -03:00
|
|
|
|
|
|
|
if (numModes == 0)
|
2024-07-20 19:08:40 -03:00
|
|
|
continue;
|
2024-03-18 15:41:46 -03:00
|
|
|
|
2024-07-20 22:20:18 -03:00
|
|
|
pOutput1->GetDisplayModeList1(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-07-20 19:08:40 -03:00
|
|
|
}
|
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;
|
|
|
|
|
2024-04-23 16:11:17 -03:00
|
|
|
return createDisplayModeCollection(buffer);
|
2024-07-20 22:20:18 -03:00
|
|
|
}
|
2024-04-23 16:11:17 -03:00
|
|
|
|
2024-07-20 22:20:18 -03:00
|
|
|
void setCurrentDisplayMode(DisplayModeCollection& displayModes, SurfaceFormat surfaceFormat, Uint width, Uint height, sptr<DisplayMode>& currentDisplayMode) {
|
|
|
|
auto modes = displayModes.Query(surfaceFormat);
|
2024-04-23 16:11:17 -03:00
|
|
|
|
2024-07-20 22:20:18 -03:00
|
|
|
for (size_t i = 0; i < modes.size(); ++i) {
|
|
|
|
auto& m = modes[i];
|
2024-07-19 22:11:57 -03:00
|
|
|
|
2024-07-19 23:21:25 -03:00
|
|
|
if (m->Format() == surfaceFormat && m->Width() == width && m->Height() == height) {
|
2024-07-19 22:11:57 -03:00
|
|
|
currentDisplayMode = m;
|
|
|
|
}
|
2024-07-20 22:20:18 -03:00
|
|
|
else if (i + 1 == modes.size()) {
|
2024-07-19 22:11:57 -03:00
|
|
|
currentDisplayMode = m;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t getDisplayModesCount(IDXGIAdapter* adapter) {
|
2024-07-20 22:20:18 -03:00
|
|
|
comptr<IDXGIOutput> pOutput = nullptr;
|
|
|
|
comptr<IDXGIOutput1> pOutput1 = nullptr;
|
|
|
|
size_t numModes = 0;
|
2024-04-23 16:11:17 -03:00
|
|
|
|
2024-07-20 22:20:18 -03:00
|
|
|
|
2024-07-16 12:28:03 -03:00
|
|
|
if (adapter->EnumOutputs(0, pOutput.GetAddressOf()) != DXGI_ERROR_NOT_FOUND) {
|
2024-04-23 16:11:17 -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-04-23 16:11:17 -03:00
|
|
|
|
|
|
|
UINT num = 0;
|
2024-07-20 22:20:18 -03:00
|
|
|
|
|
|
|
if (!pOutput1) {
|
|
|
|
pOutput->QueryInterface(IID_IDXGIOutput1, (void**)pOutput1.GetAddressOf());
|
|
|
|
}
|
|
|
|
|
|
|
|
//See ref: https://learn.microsoft.com/en-us/windows/win32/api/dxgi/nf-dxgi-idxgioutput-getdisplaymodelist?redirectedfrom=MSDN
|
|
|
|
pOutput1->GetDisplayModeList1(format, 0, &num, nullptr);
|
2024-04-23 16:11:17 -03:00
|
|
|
|
|
|
|
numModes += num;
|
2024-07-20 19:08:40 -03:00
|
|
|
}
|
2024-04-23 16:11:17 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
return numModes;
|
|
|
|
}
|
|
|
|
|
2024-07-20 22:20:18 -03:00
|
|
|
sptr<DisplayModeCollection> createDisplayModeCollection(std::vector<DXGI_MODE_DESC1> const& source) {
|
|
|
|
auto collection = snew<DisplayModeCollection>();
|
2024-07-20 19:08:40 -03:00
|
|
|
|
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
|
|
|
|
2024-07-19 23:21:25 -03:00
|
|
|
DisplayModeRate rate;
|
|
|
|
rate.RefreshRate.Denominator = modedesc.RefreshRate.Denominator;
|
|
|
|
rate.RefreshRate.Numerator = modedesc.RefreshRate.Numerator;
|
|
|
|
rate.Scaling = static_cast<DisplayModeScaling>(modedesc.Scaling);
|
|
|
|
rate.ScanlineOrdering = static_cast<DisplayModeScanlineOrder>(modedesc.ScanlineOrdering);
|
2024-04-21 20:03:36 -03:00
|
|
|
|
2024-07-19 23:21:25 -03:00
|
|
|
if (pDisplay && pDisplay->Width() == modedesc.Width && pDisplay->Height() == modedesc.Height && pDisplay->Format() == DxHelpers::SurfaceFormatToXna(modedesc.Format)) {
|
|
|
|
pDisplay->Rates.push_back(rate);
|
2024-04-21 20:03:36 -03:00
|
|
|
}
|
|
|
|
else {
|
2024-07-19 23:21:25 -03:00
|
|
|
pDisplay = snew<DisplayMode>(
|
|
|
|
modedesc.Width,
|
2024-07-20 19:08:40 -03:00
|
|
|
modedesc.Height,
|
2024-07-19 23:21:25 -03:00
|
|
|
DxHelpers::SurfaceFormatToXna(modedesc.Format));
|
2024-07-20 19:08:40 -03:00
|
|
|
|
2024-07-19 23:21:25 -03:00
|
|
|
pDisplay->Rates.push_back(rate);
|
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-07-20 19:08:40 -03:00
|
|
|
}
|
2024-07-19 22:11:57 -03:00
|
|
|
|
2024-07-20 19:08:40 -03:00
|
|
|
static void setOutputVars(comptr<IDXGIAdapter1> const& adapter, String& deviceName, intptr_t& monitorHandle) {
|
2024-07-19 22:11:57 -03:00
|
|
|
comptr<IDXGIOutput> pOutput = nullptr;
|
|
|
|
|
|
|
|
if (adapter->EnumOutputs(0, pOutput.GetAddressOf()) != DXGI_ERROR_NOT_FOUND) {
|
|
|
|
DXGI_OUTPUT_DESC outputDesc;
|
|
|
|
pOutput->GetDesc(&outputDesc);
|
|
|
|
|
2024-07-20 19:08:40 -03:00
|
|
|
deviceName = XnaHelper::ToString(outputDesc.DeviceName);
|
|
|
|
monitorHandle = reinterpret_cast<intptr_t>(outputDesc.Monitor);
|
2024-07-19 22:11:57 -03:00
|
|
|
}
|
|
|
|
}
|
2024-03-18 15:41:46 -03:00
|
|
|
}
|