1
0
mirror of https://github.com/borgesdan/xn65 synced 2024-12-29 21:54:47 +01:00
xn65/framework/platform-dx/adapter.cpp

324 lines
8.4 KiB
C++
Raw Normal View History

2024-05-19 17:52:27 -03:00
#include "graphics/adapter.hpp"
2024-05-20 11:51:32 -03:00
#include "graphics/displaymode.hpp"
2024-05-25 11:23:41 -03:00
#include "platform-dx/headers.hpp"
#include "platform-dx/helpers.hpp"
2024-05-20 11:51:32 -03:00
#include "platform-dx/implementations.hpp"
2024-05-24 14:42:12 -03:00
#include "game/gdevicemanager.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() {
impl = uNew<PlatformImplementation>();
}
GraphicsAdapter::~GraphicsAdapter() {
impl = nullptr;
}
uptr<GraphicsAdapter> GraphicsAdapter::DefaultAdapter() {
2024-04-21 16:06:22 -03:00
IDXGIFactory1* pFactory = nullptr;
2024-04-01 16:18:18 -03:00
2024-04-21 16:06:22 -03:00
if FAILED(CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&pFactory))
2024-04-01 16:18:18 -03:00
return nullptr;
2024-04-21 16:06:22 -03:00
IDXGIAdapter1* pAdapter = nullptr;
if (pFactory->EnumAdapters1(0, &pAdapter) != DXGI_ERROR_NOT_FOUND) {
auto adp = uNew<GraphicsAdapter>();
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
}
pFactory->Release();
pFactory = nullptr;
return nullptr;
}
2024-05-19 17:52:27 -03:00
void GraphicsAdapter::Adapters(std::vector<sptr<GraphicsAdapter>>& adapters){
2024-04-21 16:06:22 -03:00
IDXGIFactory1* pFactory = nullptr;
if FAILED(CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&pFactory))
return;
IDXGIAdapter1* pAdapter = nullptr;
UINT count = 0;
for (; pFactory->EnumAdapters1(count, &pAdapter) != DXGI_ERROR_NOT_FOUND; ++count) {
auto adp = New<GraphicsAdapter>();
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(adp);
}
pFactory->Release();
pFactory = nullptr;
}
2024-05-19 17:52:27 -03:00
void GraphicsAdapter::Adapters(std::vector<uptr<GraphicsAdapter>>& adapters) {
2024-04-21 16:06:22 -03:00
IDXGIFactory1* pFactory = nullptr;
if FAILED(CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&pFactory))
return;
IDXGIAdapter1* pAdapter = nullptr;
UINT count = 0;
for (; pFactory->EnumAdapters1(count, &pAdapter) != DXGI_ERROR_NOT_FOUND; ++count) {
auto adp = uNew<GraphicsAdapter>();
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));
}
pFactory->Release();
pFactory = nullptr;
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-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-05-19 17:52:27 -03:00
const auto totalDisplay = getDisplayModesCount(impl->dxadapter);
2024-04-22 11:22:18 -03:00
if (totalDisplay == 0)
return nullptr;
IDXGIOutput* pOutput = nullptr;
UINT bufferOffset = 0;
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-05-20 10:41:40 -03:00
DXGI_FORMAT format = DxHelpers::ConvertSurfaceToDXGIFORMAT(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)
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-05-20 10:41:40 -03:00
DXGI_FORMAT format = DxHelpers::ConvertSurfaceToDXGIFORMAT(surfaceFormat);
2024-04-23 16:11:17 -03:00
UINT numModes = 0;
pOutput->GetDisplayModeList(format, 0, &numModes, nullptr);
if (numModes == 0)
return uNew<DisplayModeCollection>();
std::vector<DXGI_MODE_DESC> buffer(numModes);
pOutput->GetDisplayModeList(format, 0, &numModes, buffer.data());
pOutput->Release();
pOutput = nullptr;
return createDisplayModeCollection(buffer);
}
return uNew<DisplayModeCollection>();
}
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-05-20 10:41:40 -03:00
DXGI_FORMAT format = DxHelpers::ConvertSurfaceToDXGIFORMAT(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-04-21 20:03:36 -03:00
auto collection = uNew<DisplayModeCollection>();
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-05-20 11:51:32 -03:00
if (pDisplay && pDisplay->Width == modedesc.Width && pDisplay->Height == modedesc.Height && pDisplay->Format == DxHelpers::ConvertDXGIFORMATToSurface(modedesc.Format)) {
pDisplay->impl->Descriptions.push_back(description);
2024-04-21 20:03:36 -03:00
}
else {
pDisplay = New<DisplayMode>();
2024-05-20 11:51:32 -03:00
pDisplay->Width = modedesc.Width;
pDisplay->Height = modedesc.Height;
pDisplay->Format = DxHelpers::ConvertDXGIFORMATToSurface(modedesc.Format);
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
}