1
0
mirror of https://github.com/borgesdan/xn65 synced 2024-12-29 21:54:47 +01:00
xn65/framework/platform-dx/gdevicemanager.cpp
2024-07-30 14:21:35 -03:00

302 lines
10 KiB
C++

#include "xna/xna-dx.hpp"
namespace xna {
static bool IsWindowOnAdapter(intptr_t windowHandle, GraphicsAdapter const& adapter);
GraphicsDeviceManager::GraphicsDeviceManager(sptr<Game> const& game) : game(game)
{
sptr<GraphicsAdapter> adp = GraphicsAdapter::DefaultAdapter();
_information.Adapter = adp;
_information.Profile = xna::GraphicsProfile::HiDef;
auto parameters = snew<PresentationParameters>();
parameters->BackBufferWidth = backBufferWidth;
parameters->BackBufferHeight = backBufferHeight;
parameters->BackBufferFormat = SurfaceFormat::Color;
parameters->IsFullscreen = false;
_information.PresentParameters = parameters;
if (game)
_information.Window = game->Window();
}
bool GraphicsDeviceManager::Initialize() {
if (!game)
return false;
CreateDevice();
return true;
}
void GraphicsDeviceManager::ApplyChanges() {
if (device && !isDeviceDirty)
return;
ChangeDevice(false);
}
bool GraphicsDeviceManager::ToggleFullScreen() {
if (!game || !game->graphicsDevice || !game->graphicsDevice->impl->_swapChain)
return false;
auto& swap = game->graphicsDevice->impl->_swapChain;
BOOL state = false;
auto hr = swap->impl->dxSwapChain->GetFullscreenState(&state, nullptr);
if (FAILED(hr)) return false;
hr = swap->impl->dxSwapChain->SetFullscreenState(!state, nullptr);
if (FAILED(hr)) return false;
isFullScreen = !state;
return true;
}
bool initWindow(GraphicsDeviceInformation& info, Game& game, int backWidth, int backHeight)
{
auto window = info.Window;
if (!window) {
window = game.Window();
info.Window = window;
}
window->impl->Size(backWidth, backHeight);
if (!window->impl->Create()) {
MessageBox(nullptr, "Falha na criação da janela", "XN65", MB_OK);
return false;
}
info.PresentParameters->DeviceWindowHandle = reinterpret_cast<intptr_t>(window->impl->WindowHandle());
return true;
}
bool initDevice(GraphicsDeviceInformation& info, Game& game, sptr<GraphicsDevice>& device)
{
device = snew<GraphicsDevice>(info);
if (!device->Initialize()) {
MessageBox(info.Window->impl->WindowHandle(), "Falha na inicialização do dispositivo gráfico", "XN65", MB_OK);
device = nullptr;
return false;
}
game.graphicsDevice = device;
return true;
}
void GraphicsDeviceManager::CreateDevice() {
if (isDeviceDirty) {
_information.PresentParameters->BackBufferWidth = backBufferWidth;
_information.PresentParameters->BackBufferHeight = backBufferHeight;
}
auto result = initWindow(_information, *game, backBufferWidth, backBufferHeight);
//if (!result) return false;
initDevice(_information, *game, device);
}
void GraphicsDeviceManager::ChangeDevice() {
}
void GraphicsDeviceManager::AddDevices(bool anySuitableDevice, std::vector<sptr<GraphicsDeviceInformation>>& foundDevices) {
const auto handle = game->Window()->Handle();
std::vector<uptr<GraphicsAdapter>> adapters;
GraphicsAdapter::Adapters(adapters);
for (size_t i = 0; adapters.size(); ++i) {
auto& adapter = adapters[i];
if (!anySuitableDevice) {
if (!IsWindowOnAdapter(handle, *adapter))
continue;
}
if (adapter->IsProfileSupported(graphicsProfile)) {
auto baseDeviceInfo = snew<GraphicsDeviceInformation>();
baseDeviceInfo->Adapter = std::move(adapter);
baseDeviceInfo->Profile = graphicsProfile;
baseDeviceInfo->PresentParameters = snew<PresentationParameters>();
baseDeviceInfo->PresentParameters->DeviceWindowHandle = handle;
baseDeviceInfo->PresentParameters->MultiSampleCount = 0;
baseDeviceInfo->PresentParameters->IsFullscreen = isFullScreen;
baseDeviceInfo->PresentParameters->PresentationInterval = synchronizeWithVerticalRetrace ? PresentInterval::One : PresentInterval::Immediate;
const auto& currentDisplayMode = baseDeviceInfo->Adapter->CurrentDisplayMode();
AddDevices(*baseDeviceInfo->Adapter, *currentDisplayMode, baseDeviceInfo, foundDevices);
if (isFullScreen) {
const auto& supportedDisplayModes = adapter->SupportedDisplayModes();
const auto count = supportedDisplayModes->Count();
for (size_t i = 0; i < count; ++i) {
auto& supportedDisplayMode = supportedDisplayModes->DisplayModes[i];
if (supportedDisplayMode->Width() >= 640 && supportedDisplayMode->Height() >= 480) {
AddDevices(*baseDeviceInfo->Adapter, *supportedDisplayMode, baseDeviceInfo, foundDevices);
}
}
}
}
}
}
void GraphicsDeviceManager::AddDevices(GraphicsAdapter const& adapter, DisplayMode const& mode, sptr<GraphicsDeviceInformation>& baseDeviceInfo, std::vector<sptr<GraphicsDeviceInformation>>& foundDevices) const {
auto deviceInformation = snew<GraphicsDeviceInformation>(*baseDeviceInfo);
if (isFullScreen)
{
deviceInformation->PresentParameters->BackBufferWidth = mode.Width();
deviceInformation->PresentParameters->BackBufferHeight = mode.Height();
}
else if (useResizedBackBuffer) {
deviceInformation->PresentParameters->BackBufferWidth = resizedBackBufferWidth;
deviceInformation->PresentParameters->BackBufferHeight = resizedBackBufferHeight;
}
else {
deviceInformation->PresentParameters->BackBufferWidth = backBufferWidth;
deviceInformation->PresentParameters->BackBufferHeight = backBufferHeight;
}
SurfaceFormat selectedFormat;
DepthFormat selectedDepthFormat;
int selectedMultiSampleCount;
adapter.QueryBackBufferFormat(deviceInformation->Profile, mode.Format(), depthStencilFormat, allowMultiSampling ? 16 : 0, selectedFormat, selectedDepthFormat, selectedMultiSampleCount);
deviceInformation->PresentParameters->BackBufferFormat = selectedFormat;
deviceInformation->PresentParameters->DepthStencilFormat = selectedDepthFormat;
deviceInformation->PresentParameters->MultiSampleCount = selectedMultiSampleCount;
if (std::find(foundDevices.begin(), foundDevices.end(), deviceInformation) != foundDevices.end())
return;
foundDevices.push_back(deviceInformation);
}
sptr<GraphicsDeviceInformation> GraphicsDeviceManager::FindBestPlatformDevice(bool anySuitableDevice) {
auto foundDevices = std::vector<sptr<GraphicsDeviceInformation>>();
AddDevices(anySuitableDevice, foundDevices);
if (foundDevices.size() == 0 && allowMultiSampling) {
PreferMultiSampling(false);
AddDevices(anySuitableDevice, foundDevices);
}
if (foundDevices.size() == 0) {
Exception::Throw("No Suitable Graphics Device");
}
RankDevices(foundDevices);
if (foundDevices.size() == 0)
Exception::Throw("No Suitable Graphics Device");
return foundDevices[0];
}
struct GraphicsDeviceInformationComparer
{
GraphicsDeviceManager* graphics = nullptr;
bool operator()(GraphicsDeviceInformation const& d1, GraphicsDeviceInformation const& d2) const {
return comparator(d1, d2);
}
bool operator()(sptr<GraphicsDeviceInformation> const& a, sptr<GraphicsDeviceInformation> const& b) const {
return comparator(*a, *b);
}
private:
bool comparator(GraphicsDeviceInformation const& d1, GraphicsDeviceInformation const& d2) const {
if (d1.Profile != d2.Profile)
return d1.Profile <= d2.Profile;
auto& presentationParameters1 = d1.PresentParameters;
auto& presentationParameters2 = d2.PresentParameters;
if (presentationParameters1 && presentationParameters2 && presentationParameters1->IsFullscreen != presentationParameters2->IsFullscreen)
return graphics->IsFullScreen() != presentationParameters1->IsFullscreen;
const auto& backFormat1 = presentationParameters1->BackBufferFormat;
const auto& backFormat2 = presentationParameters2->BackBufferFormat;
if (backFormat1 != backFormat2)
return static_cast<int>(backFormat1) <= static_cast<int>(backFormat2);
if (presentationParameters1->MultiSampleCount != presentationParameters2->MultiSampleCount)
return presentationParameters1->MultiSampleCount <= presentationParameters2->MultiSampleCount;
const auto num3 = graphics->PreferredBackBufferWidth() == 0 || graphics->PreferredBackBufferHeight() == 0
? GraphicsDeviceManager::DefaultBackBufferWidth / static_cast<float>(GraphicsDeviceManager::DefaultBackBufferHeight)
: graphics->PreferredBackBufferWidth() / static_cast<float>(graphics->PreferredBackBufferHeight());
const auto num4 = presentationParameters1->BackBufferWidth / static_cast<float>(presentationParameters1->BackBufferHeight);
const auto num5 = presentationParameters2->BackBufferWidth / static_cast<float>(presentationParameters2->BackBufferHeight);
const auto num6 = std::abs(num4 - num3);
const auto num7 = std::abs(num5 - num3);
if (std::abs(num6 - num7) > 0.20000000298023224)
return num6 <= num7;
Int num8;
Int num9;
if (graphics->IsFullScreen())
{
if (graphics->PreferredBackBufferWidth() == 0 || graphics->PreferredBackBufferHeight() == 0) {
const auto& adapter1 = d1.Adapter;
num8 = adapter1->CurrentDisplayMode()->Width() * adapter1->CurrentDisplayMode()->Height();
const auto& adapter2 = d2.Adapter;
num9 = adapter2->CurrentDisplayMode()->Width() * adapter2->CurrentDisplayMode()->Height();
}
else
num8 = num9 = graphics->PreferredBackBufferWidth() * graphics->PreferredBackBufferHeight();
}
else
num8 = graphics->PreferredBackBufferWidth() == 0 || graphics->PreferredBackBufferHeight() == 0
? (num9 = GraphicsDeviceManager::DefaultBackBufferWidth * GraphicsDeviceManager::DefaultBackBufferHeight)
: (num9 = graphics->PreferredBackBufferWidth() * graphics->PreferredBackBufferHeight());
const auto num10 = std::abs(presentationParameters1->BackBufferWidth * presentationParameters1->BackBufferHeight - num8);
const auto num11 = std::abs(presentationParameters2->BackBufferWidth * presentationParameters2->BackBufferHeight - num9);
if (num10 != num11)
return num10 <= num11;
if (d1.Adapter != d2.Adapter) {
if (d1.Adapter->IsDefaultAdapter())
return false;
if (d2.Adapter->IsDefaultAdapter())
return true;
}
return false;
}
};
void GraphicsDeviceManager::RankDevicesPlatform(std::vector<sptr<GraphicsDeviceInformation>>& foundDevices) {
GraphicsDeviceInformationComparer comparer;
comparer.graphics = this;
std::sort(foundDevices.begin(), foundDevices.end(), comparer);
}
bool IsWindowOnAdapter(intptr_t windowHandle, GraphicsAdapter const& adapter) {
return GameWindow::ScreenFromAdapter(adapter) == GameWindow::ScreenFromHandle(windowHandle);
}
}