diff --git a/CMakeLists.txt b/CMakeLists.txt index 3757379..562ba32 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,6 @@ project ("xna") include_directories(${PROJECT_INCLUDES_DIR}) add_subdirectory ("framework") -#add_subdirectory ("samples") +add_subdirectory ("samples") diff --git a/framework/CMakeLists.txt b/framework/CMakeLists.txt index 9d2d114..0c82e8a 100644 --- a/framework/CMakeLists.txt +++ b/framework/CMakeLists.txt @@ -40,7 +40,7 @@ add_library (Xn65 STATIC "platform-dx/audioengine.cpp" "graphics/gresource.cpp" "platform-dx/effect.cpp" - "exception.cpp") + "exception.cpp" "platform-dx/screen.cpp" ) if (CMAKE_VERSION VERSION_GREATER 3.12) set_property(TARGET Xn65 PROPERTY CXX_STANDARD 20) diff --git a/framework/platform-dx/adapter.cpp b/framework/platform-dx/adapter.cpp index a5e4132..e522a20 100644 --- a/framework/platform-dx/adapter.cpp +++ b/framework/platform-dx/adapter.cpp @@ -1,11 +1,11 @@ -#include "xna/graphics/adapter.hpp" -#include "xna/graphics/displaymode.hpp" -#include "xna/game/gdevicemanager.hpp" #include "xna/xna-dx.hpp" -namespace xna { +namespace xna { + static void setOutputVars(comptr const& adapter, String& deviceName, intptr_t& monitorHandle); static size_t getDisplayModesCount(IDXGIAdapter* adapter); - static uptr createDisplayModeCollection(std::vector const& source); + static sptr createDisplayModeCollection(std::vector const& source); + static void setCurrentDisplayMode(DisplayModeCollection& displayModes, SurfaceFormat surfaceFormat, Uint width, Uint height, sptr& currentDisplayMode); + static sptr getSupportedDisplayModes(comptr& dxAdapter); GraphicsAdapter::GraphicsAdapter() { impl = unew(); @@ -18,12 +18,32 @@ namespace xna { Exception::Throw(Exception::FAILED_TO_CREATE); comptr pAdapter = nullptr; - - if (pFactory->EnumAdapters1(0, pAdapter.GetAddressOf()) != DXGI_ERROR_NOT_FOUND) { - auto adp = unew(); - adp->impl->_index = 0; - adp->impl->dxadapter = pAdapter; + if (pFactory->EnumAdapters1(0, pAdapter.GetAddressOf()) != DXGI_ERROR_NOT_FOUND) { + auto adp = uptr(new GraphicsAdapter()); + + adp->impl->dxAdapter = pAdapter; + adp->impl->dxFactory = pFactory; + + DXGI_ADAPTER_DESC1 desc{}; + pAdapter->GetDesc1(&desc); + + adp->description = XnaHelper::ToString(desc.Description); + adp->deviceId = static_cast(desc.DeviceId); + adp->isDefault = true; + adp->revision = static_cast(desc.Revision); + adp->subSystemId = static_cast(desc.SubSysId); + adp->vendorId = static_cast(desc.VendorId); + + setOutputVars(pAdapter, adp->deviceName, adp->monitorHandle); + + adp->supportedDisplayModes = getSupportedDisplayModes(pAdapter); + + if (adp->supportedDisplayModes && adp->supportedDisplayModes->Count() > 0) { + setCurrentDisplayMode(*adp->supportedDisplayModes, SurfaceFormat::Color, + GraphicsDeviceManager::DefaultBackBufferWidth, + GraphicsDeviceManager::DefaultBackBufferHeight, adp->currentDisplayMode); + } return adp; } @@ -38,247 +58,185 @@ namespace xna { Exception::Throw(Exception::FAILED_TO_CREATE); comptr pAdapter = nullptr; - UINT count = 0; - for (; pFactory->EnumAdapters1(count, pAdapter.GetAddressOf()) != DXGI_ERROR_NOT_FOUND; ++count) { - auto adp = unew(); + for (UINT count = 0; pFactory->EnumAdapters1(count, pAdapter.GetAddressOf()) != DXGI_ERROR_NOT_FOUND; ++count) { + auto adp = uptr(new GraphicsAdapter()); - adp->impl->_index = count; - adp->impl->dxadapter = pAdapter; + adp->impl->dxAdapter = pAdapter; + adp->impl->dxFactory = pFactory; + + DXGI_ADAPTER_DESC1 desc{}; + pAdapter->GetDesc1(&desc); + + adp->description = XnaHelper::ToString(desc.Description); + adp->deviceId = static_cast(desc.DeviceId); + adp->isDefault = count == 0; + adp->revision = static_cast(desc.Revision); + adp->subSystemId = static_cast(desc.SubSysId); + adp->vendorId = static_cast(desc.VendorId); + + setOutputVars(pAdapter, adp->deviceName, adp->monitorHandle); + + adp->supportedDisplayModes = getSupportedDisplayModes(pAdapter); + + if (adp->supportedDisplayModes && adp->supportedDisplayModes->Count() > 0) { + setCurrentDisplayMode(*adp->supportedDisplayModes, SurfaceFormat::Color, + GraphicsDeviceManager::DefaultBackBufferWidth, + GraphicsDeviceManager::DefaultBackBufferHeight, adp->currentDisplayMode); + } adapters.push_back(std::move(adp)); } - } - - 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.Get()); - - 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::SurfaceFormatToDx(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 + bool GraphicsAdapter::QueryBackBufferFormat( + GraphicsProfile graphicsProfile, SurfaceFormat format, + DepthFormat depthFormat, Int multiSampleCount, + SurfaceFormat& selectedFormat, DepthFormat& selectedDepthFormat, + Int& selectedMultiSampleCount) const { - if (!impl->dxadapter) return nullptr; + selectedFormat = format; + selectedDepthFormat = depthFormat; + selectedMultiSampleCount = multiSampleCount; - IDXGIOutput* pOutput = nullptr; - UINT bufferOffset = 0; + comptr pOutput = nullptr; - if (impl->dxadapter->EnumOutputs(0, &pOutput) != DXGI_ERROR_NOT_FOUND) { - DXGI_FORMAT format = DxHelpers::SurfaceFormatToDx(surfaceFormat); + if (impl->dxAdapter->EnumOutputs(0, pOutput.GetAddressOf()) != DXGI_ERROR_NOT_FOUND){ + comptr pOutput1 = nullptr; - UINT numModes = 0; + pOutput->QueryInterface(IID_IDXGIOutput1, (void**)pOutput1.GetAddressOf()); - pOutput->GetDisplayModeList(format, 0, &numModes, nullptr); + DXGI_MODE_DESC1 modeToMath{}; + modeToMath.Format = DxHelpers::SurfaceFormatToDx(format); - if (numModes == 0) - return unew(); + //If pConcernedDevice is NULL, the Format member of DXGI_MODE_DESC1 cannot be DXGI_FORMAT_UNKNOWN. + if (modeToMath.Format == DXGI_FORMAT_UNKNOWN) + return false; - std::vector buffer(numModes); - pOutput->GetDisplayModeList(format, 0, &numModes, buffer.data()); + DXGI_MODE_DESC1 closestMath; + const auto hresult = pOutput1->FindClosestMatchingMode1(&modeToMath, &closestMath, nullptr); - pOutput->Release(); - pOutput = nullptr; + if FAILED(hresult) + return false; - return createDisplayModeCollection(buffer); - } + selectedFormat = DxHelpers::SurfaceFormatToXna(closestMath.Format); - return unew(); - } - - sptr GraphicsAdapter::CurrentDisplayMode() { - if (!impl->_currentDisplayMode) { - CurrentDisplayMode(SurfaceFormat::Color, GraphicsDeviceManager::DefaultBackBufferWidth, GraphicsDeviceManager::DefaultBackBufferHeight); + return selectedFormat == format; } - 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; + sptr getSupportedDisplayModes(comptr& dxAdapter) { + const auto totalDisplay = getDisplayModesCount(dxAdapter.Get()); - if (adapter->EnumOutputs(0, &pOutput) != DXGI_ERROR_NOT_FOUND) { + if (totalDisplay == 0) + return nullptr; + + comptr pOutput = nullptr; + comptr pOutput1 = nullptr; + UINT bufferOffset = 0; + + std::vector buffer(totalDisplay); + + if (dxAdapter->EnumOutputs(0, pOutput.GetAddressOf()) != DXGI_ERROR_NOT_FOUND) { + for (size_t f = 0; f < SURFACE_FORMAT_COUNT; ++f) { + const auto currentSurface = static_cast(f); + DXGI_FORMAT format = DxHelpers::SurfaceFormatToDx(currentSurface); + + UINT numModes = 0; + + 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); + + if (numModes == 0) + continue; + + pOutput1->GetDisplayModeList1(format, 0, &numModes, buffer.data() + bufferOffset); + + bufferOffset += numModes; + } + } + + if (!pOutput) + return nullptr; + + return createDisplayModeCollection(buffer); + } + + void setCurrentDisplayMode(DisplayModeCollection& displayModes, SurfaceFormat surfaceFormat, Uint width, Uint height, sptr& currentDisplayMode) { + auto modes = displayModes.Query(surfaceFormat); + + for (size_t i = 0; i < modes.size(); ++i) { + auto& m = modes[i]; + + if (m->Format() == surfaceFormat && m->Width() == width && m->Height() == height) { + currentDisplayMode = m; + } + else if (i + 1 == modes.size()) { + currentDisplayMode = m; + } + } + } + + size_t getDisplayModesCount(IDXGIAdapter* adapter) { + comptr pOutput = nullptr; + comptr pOutput1 = nullptr; + size_t numModes = 0; + + + if (adapter->EnumOutputs(0, pOutput.GetAddressOf()) != DXGI_ERROR_NOT_FOUND) { for (size_t f = 0; f < SURFACE_FORMAT_COUNT; ++f) { const auto currentSurface = static_cast(f); DXGI_FORMAT format = DxHelpers::SurfaceFormatToDx(currentSurface); UINT num = 0; - pOutput->GetDisplayModeList(format, 0, &num, nullptr); + + 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); numModes += num; } - - pOutput->Release(); - pOutput = nullptr; } return numModes; } - static uptr createDisplayModeCollection(std::vector const& source) { - auto collection = unew(); - DisplayMode currentDisplayMode; + sptr createDisplayModeCollection(std::vector const& source) { + auto collection = snew(); + 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); + DisplayModeRate rate; + rate.RefreshRate.Denominator = modedesc.RefreshRate.Denominator; + rate.RefreshRate.Numerator = modedesc.RefreshRate.Numerator; + rate.Scaling = static_cast(modedesc.Scaling); + rate.ScanlineOrdering = static_cast(modedesc.ScanlineOrdering); - if (pDisplay && pDisplay->Width == modedesc.Width && pDisplay->Height == modedesc.Height && pDisplay->Format == DxHelpers::SurfaceFormatToXna(modedesc.Format)) { - pDisplay->impl->Descriptions.push_back(description); + if (pDisplay && pDisplay->Width() == modedesc.Width && pDisplay->Height() == modedesc.Height && pDisplay->Format() == DxHelpers::SurfaceFormatToXna(modedesc.Format)) { + pDisplay->Rates.push_back(rate); } else { - pDisplay = snew(); - pDisplay->Width = modedesc.Width; - pDisplay->Height = modedesc.Height; - pDisplay->Format = DxHelpers::SurfaceFormatToXna(modedesc.Format); - pDisplay->impl->Descriptions.push_back(description); + pDisplay = snew( + modedesc.Width, + modedesc.Height, + DxHelpers::SurfaceFormatToXna(modedesc.Format)); + + pDisplay->Rates.push_back(rate); displayList.push_back(pDisplay); } } @@ -286,5 +244,17 @@ namespace xna { collection->DisplayModes = displayList; return collection; + } + + static void setOutputVars(comptr const& adapter, String& deviceName, intptr_t& monitorHandle) { + comptr pOutput = nullptr; + + if (adapter->EnumOutputs(0, pOutput.GetAddressOf()) != DXGI_ERROR_NOT_FOUND) { + DXGI_OUTPUT_DESC outputDesc; + pOutput->GetDesc(&outputDesc); + + deviceName = XnaHelper::ToString(outputDesc.DeviceName); + monitorHandle = reinterpret_cast(outputDesc.Monitor); + } } } \ No newline at end of file diff --git a/framework/platform-dx/device.cpp b/framework/platform-dx/device.cpp index 2ee9001..5cbc57a 100644 --- a/framework/platform-dx/device.cpp +++ b/framework/platform-dx/device.cpp @@ -21,43 +21,61 @@ namespace xna { } static void createDevice(GraphicsDevice::PlatformImplementation& impl) { + // + // See ref + // + // D3D_DRIVER_TYPE + // https://learn.microsoft.com/en-us/windows/win32/api/d3dcommon/ne-d3dcommon-d3d_driver_type + // + // D3D11CreateDevice function + // https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-d3d11createdevice + // + auto createDeviceFlags = 0; #if _DEBUG createDeviceFlags = D3D11_CREATE_DEVICE_FLAG::D3D11_CREATE_DEVICE_DEBUG; #endif + + const auto& currentAdapter = impl._adapter; + const auto& pAdapter = GraphicsAdapter::UseNullDevice() ? NULL : currentAdapter->impl->dxAdapter.Get(); + + // + // if pAdapter is not NULL driverType must be D3D_DRIVER_TYPE_UNKNOWN + // + auto driverType = D3D_DRIVER_TYPE_UNKNOWN; + + if (GraphicsAdapter::UseReferenceDevice()) + driverType = D3D_DRIVER_TYPE_WARP; + else if (GraphicsAdapter::UseNullDevice()) + driverType = D3D_DRIVER_TYPE_HARDWARE; + auto hr = D3D11CreateDevice( - impl._adapter->impl->dxadapter.Get(), - D3D_DRIVER_TYPE_UNKNOWN, + //_In_opt_ IDXGIAdapter* pAdapter, + pAdapter, + //D3D_DRIVER_TYPE DriverType, + driverType, + //HMODULE Software, NULL, + //UINT Flags, createDeviceFlags, - NULL, - 0, + //_In_reads_opt_( FeatureLevels ) CONST D3D_FEATURE_LEVEL* pFeatureLevels, + impl.featureLevels, + //UINT FeatureLevels, + 7, + //UINT SDKVersion, D3D11_SDK_VERSION, + //_COM_Outptr_opt_ ID3D11Device** ppDevice impl._device.GetAddressOf(), - &impl._featureLevel, + //_Out_opt_ D3D_FEATURE_LEVEL* pFeatureLevel, + &impl.currentFeatureLevel, + //_COM_Outptr_opt_ ID3D11DeviceContext** ppImmediateContext impl._context.GetAddressOf()); - if (FAILED(hr)) { - OutputDebugString("---> Usando Adaptador WARP: não há suporte ao D3D11\n"); - - hr = D3D11CreateDevice( - NULL, - D3D_DRIVER_TYPE_WARP, - NULL, - createDeviceFlags, - NULL, - 0, - D3D11_SDK_VERSION, - impl._device.GetAddressOf(), - &impl._featureLevel, - impl._context.GetAddressOf()); - - if FAILED(hr) - Exception::Throw(Exception::FAILED_TO_CREATE); - } + if FAILED(hr) + Exception::Throw(Exception::FAILED_TO_CREATE); } - void initAndApplyState(GraphicsDevice::PlatformImplementation& impl, PGraphicsDevice const& device) { + static void initAndApplyState(GraphicsDevice::PlatformImplementation& impl, PGraphicsDevice const& device) { impl._blendState->Bind(device); impl._blendState->Initialize(); impl._blendState->Apply(); @@ -75,25 +93,22 @@ namespace xna { GraphicsDevice::GraphicsDevice() { impl = unew(); - impl->_adapter = GraphicsAdapter::DefaultAdapter(); - impl->_adapter->CurrentDisplayMode( - SurfaceFormat::Color, - GraphicsDeviceManager::DefaultBackBufferWidth, - GraphicsDeviceManager::DefaultBackBufferHeight); + impl->_adapter = GraphicsAdapter::DefaultAdapter(); } GraphicsDevice::GraphicsDevice(GraphicsDeviceInformation const& info) { impl = unew(); impl->_adapter = info.Adapter; - impl->_gameWindow = info.Window; - impl->_presentationParameters = info.Parameters; - impl->_adapter->CurrentDisplayMode( - impl->_presentationParameters->BackBufferFormat, - impl->_presentationParameters->BackBufferWidth, - impl->_presentationParameters->BackBufferHeight); + impl->_presentationParameters = info.PresentParameters; } + GraphicsDevice::GraphicsDevice(sptr const& adapter, GraphicsProfile const& graphicsProfile, sptr const& presentationParameters) { + impl = unew(); + impl->_adapter = adapter; + impl->_presentationParameters = presentationParameters; + } + bool GraphicsDevice::Initialize() { auto _this = shared_from_this(); @@ -109,23 +124,27 @@ namespace xna { if FAILED(hr) Exception::Throw(Exception::FAILED_TO_CREATE); - const auto bounds = impl->_gameWindow->ClientBounds(); + //const auto bounds = impl->_gameWindow->ClientBounds(); impl->_viewport = xna::Viewport(0.0F, 0.0F, - static_cast(bounds.Width), - static_cast(bounds.Height), + impl->_presentationParameters->BackBufferWidth, + impl->_presentationParameters->BackBufferHeight, 0.0F, 1.F); - COLORREF color = impl->_gameWindow->impl->Color(); - impl->_backgroundColor[0] = GetRValue(color) / 255.0f; - impl->_backgroundColor[1] = GetGValue(color) / 255.0f; - impl->_backgroundColor[2] = GetBValue(color) / 255.0f; + //COLORREF color = impl->_gameWindow->impl->Color(); + const auto backColor = Colors::CornflowerBlue; + const auto backColorV3 = backColor.ToVector3(); + + impl->_backgroundColor[0] = backColorV3.X; + impl->_backgroundColor[1] = backColorV3.Y; + impl->_backgroundColor[2] = backColorV3.Z; impl->_backgroundColor[3] = 1.0f; impl->_swapChain = snew(_this); impl->_swapChain->Initialize(); - hr = impl->_factory->MakeWindowAssociation(impl->_gameWindow->impl->WindowHandle(), DXGI_MWA_NO_ALT_ENTER); + auto hwnd = reinterpret_cast(impl->_presentationParameters->DeviceWindowHandle); + hr = impl->_factory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER); if (FAILED(hr)) Exception::Throw(Exception::FAILED_TO_MAKE_WINDOW_ASSOCIATION); @@ -264,4 +283,12 @@ namespace xna { void GraphicsDevice::MultiSampleMask(Int value) { impl->_multiSampleMask = value; } + + void GraphicsDevice::Reset(sptr const& presentationParameters, sptr const& graphicsAdapter){ + impl = unew(); + impl->_adapter = graphicsAdapter; + impl->_presentationParameters = presentationParameters; + + Initialize(); + } } \ No newline at end of file diff --git a/framework/platform-dx/displaymode.cpp b/framework/platform-dx/displaymode.cpp index fbebf57..80a56c4 100644 --- a/framework/platform-dx/displaymode.cpp +++ b/framework/platform-dx/displaymode.cpp @@ -2,16 +2,12 @@ #include "xna/graphics/displaymode.hpp" namespace xna { - DisplayMode::DisplayMode() { - impl = unew(); - } - size_t DisplayModeCollection::SurfaceCount(SurfaceFormat format) const { size_t counter = 0; for (size_t i = 0; i < DisplayModes.size(); ++i) { - if (DisplayModes[i]->Format == format) { + if (DisplayModes[i]->Format() == format) { ++counter; } } @@ -27,7 +23,7 @@ namespace xna { std::vector> modes(count); for (size_t i = 0; i < DisplayModes.size(); ++i) { - if (DisplayModes[i]->Format == format) { + if (DisplayModes[i]->Format() == format) { modes[index] = DisplayModes[i]; ++index; } @@ -46,10 +42,10 @@ namespace xna { for (size_t i = 0; i < DisplayModes.size(); ++i) { const auto& mode = DisplayModes[i]; - if (mode->Format == format && mode->Width == width && mode->Height == height) { + if (mode->Format() == format && mode->Width() == width && mode->Height() == height) { return DisplayModes[i]; } - else if(mode->Format == format && mode->Width == width) { + else if(mode->Format() == format && mode->Width() == width) { matched = mode; } } diff --git a/framework/platform-dx/effect.cpp b/framework/platform-dx/effect.cpp index 28c3311..e67ed90 100644 --- a/framework/platform-dx/effect.cpp +++ b/framework/platform-dx/effect.cpp @@ -30,7 +30,7 @@ namespace xna { } void BasicEffect::Alpha(float value) { - const auto a = MathHelper::Clamp(value, 0.0f, 1.0); + const auto a = MathHelper::Clamp(value, 0.0F, 1.0F); impl->dxBasicEffect->SetAlpha(a); } @@ -116,7 +116,7 @@ namespace xna { void BasicEffect::SetDirectionalLight(Int index, DirectionalLight const& direction) { DxVec vec3 = DxHelpers::VectorToDx(direction.Direction); - const auto value = (int)MathHelper::Clamp(index, 0, impl->dxBasicEffect->MaxDirectionalLights); + const auto value = MathHelper::Clamp(index, 0, impl->dxBasicEffect->MaxDirectionalLights); impl->dxBasicEffect->SetLightDirection(value, vec3); } diff --git a/framework/platform-dx/game.cpp b/framework/platform-dx/game.cpp index 6892f0b..51389c5 100644 --- a/framework/platform-dx/game.cpp +++ b/framework/platform-dx/game.cpp @@ -64,7 +64,12 @@ namespace xna { int Game::Run() { try { - Initialize(); + if (!_gameWindow->impl->Create()) { + Exception::Throw(Exception::FAILED_TO_CREATE); + return false; + } + + Initialize(); if (graphicsDevice == nullptr) { MessageBox(nullptr, "O dispositivo gráfico não foi inicializado corretamente", "XN65", MB_OK); diff --git a/framework/platform-dx/gdevicemanager.cpp b/framework/platform-dx/gdevicemanager.cpp index 0c0f447..b124720 100644 --- a/framework/platform-dx/gdevicemanager.cpp +++ b/framework/platform-dx/gdevicemanager.cpp @@ -1,41 +1,35 @@ -#include "xna/game/gdevicemanager.hpp" -#include "xna/graphics/presentparams.hpp" -#include "xna/graphics/swapchain.hpp" #include "xna/xna-dx.hpp" namespace xna { - GraphicsDeviceManager::GraphicsDeviceManager(sptr const& game) : _game(game) + static bool IsWindowOnAdapter(intptr_t windowHandle, GraphicsAdapter const& adapter); + + GraphicsDeviceManager::GraphicsDeviceManager(sptr const& game) : game(game) { sptr adp = GraphicsAdapter::DefaultAdapter(); - _information.Adapter = adp; - _information.Profile = xna::GraphicsProfile::HiDef; + information.Adapter = adp; + information.Profile = xna::GraphicsProfile::HiDef; auto parameters = snew(); - parameters->BackBufferWidth = _backBufferWidth; - parameters->BackBufferHeight = _backBufferHeight; + parameters->BackBufferWidth = backBufferWidth; + parameters->BackBufferHeight = backBufferHeight; parameters->BackBufferFormat = SurfaceFormat::Color; - parameters->Fullscreen = false; - _information.Parameters = parameters; - - if (_game) - _information.Window = _game->Window(); - } - - bool GraphicsDeviceManager::Initialize() { - if (!_game) - return false; - - return CreateDevice(); - } + parameters->IsFullscreen = false; + information.PresentParameters = parameters; + information.Window = game->Window(); + } void GraphicsDeviceManager::ApplyChanges() { + if (device && !isDeviceDirty) + return; + + ChangeDevice(false); } bool GraphicsDeviceManager::ToggleFullScreen() { - if (!_game || !_game->graphicsDevice || !_game->graphicsDevice->impl->_swapChain) + if (!game || !game->graphicsDevice || !game->graphicsDevice->impl->_swapChain) return false; - auto& swap = _game->graphicsDevice->impl->_swapChain; + auto& swap = game->graphicsDevice->impl->_swapChain; BOOL state = false; auto hr = swap->impl->dxSwapChain->GetFullscreenState(&state, nullptr); @@ -46,73 +40,351 @@ namespace xna { if (FAILED(hr)) return false; - _isFullScreen = !state; + isFullScreen = !state; return true; - } + } - void GraphicsDeviceManager::PreferredBackBufferWidth(Int value) { - _backBufferWidth = value; - _isDeviceDirty = true; - } + void GraphicsDeviceManager::ChangeDevice(bool forceCreate) { + if (!game) + Exception::Throw(Exception::INVALID_OPERATION); - void GraphicsDeviceManager::PreferredBackBufferHeight(Int value) { - _backBufferHeight = value; - _isDeviceDirty = true; - } - - bool initWindow(GraphicsDeviceInformation& info, Game& game, int backWidth, int backHeight) - { - auto window = info.Window; + inDeviceTransition = true; + auto screenDeviceName = game->Window()->ScreenDeviceName(); + int clientWidth = game->Window()->ClientBounds().Width; + int clientHeight = game->Window()->ClientBounds().Height; + bool flag1 = false; - if (!window) { - window = game.Window(); - info.Window = window; + //this.game.Window.SetSupportedOrientations(Helpers.ChooseOrientation(this.supportedOrientations, this.PreferredBackBufferWidth, this.PreferredBackBufferHeight, true)); + auto bestDevice = FindBestDevice(forceCreate); + //this.game.Window.BeginScreenDeviceChange(bestDevice.PresentationParameters.IsFullScreen); + flag1 = true; + bool flag2 = true; + + if (!forceCreate && device) { + //this.OnPreparingDeviceSettings((object) this, new PreparingDeviceSettingsEventArgs(bestDevice)); + + if (CanResetDevice(*bestDevice)) { + auto deviceInformation = snew(*bestDevice); + MassagePresentParameters(*bestDevice->PresentParameters); + ValidateGraphicsDeviceInformation(*bestDevice); + device->Reset(deviceInformation->PresentParameters, deviceInformation->Adapter); + //GraphicsDeviceManager.ConfigureTouchInput(deviceInformation.PresentationParameters); + flag2 = false; + } } - window->impl->Size(backWidth, backHeight); + if (flag2) + CreateDevice(*bestDevice); - if (!window->impl->Create()) { - MessageBox(nullptr, "Falha na criação da janela", "XN65", MB_OK); - return false; - } + auto presentationParameters = device->PresentParameters(); - info.Parameters->DeviceWindowHandle = reinterpret_cast(window->impl->WindowHandle()); + screenDeviceName = device->Adapter()->DeviceName(); - return true; - } + isReallyFullScreen = presentationParameters.IsFullscreen; - bool initDevice(GraphicsDeviceInformation& info, Game& game, sptr& device) - { - device = snew(info); + if (presentationParameters.BackBufferWidth != 0) + clientWidth = presentationParameters.BackBufferWidth; - if (!device->Initialize()) { - MessageBox(info.Window->impl->WindowHandle(), "Falha na inicialização do dispositivo gráfico", "XN65", MB_OK); - device = nullptr; - return false; - } + if (presentationParameters.BackBufferHeight != 0) + clientHeight = presentationParameters.BackBufferHeight; - game.graphicsDevice = device; + isDeviceDirty = false; - return true; - } + //if (flag1) game->Window()->EndScreenDeviceChange(screenDeviceName, clientWidth, clientHeight); - - bool GraphicsDeviceManager::CreateDevice() { - if (_isDeviceDirty) { - _information.Parameters->BackBufferWidth = _backBufferWidth; - _information.Parameters->BackBufferHeight = _backBufferHeight; - } - - auto result = initWindow(_information, *_game, _backBufferWidth, _backBufferHeight); - - if (!result) return false; + currentWindowOrientation = game->Window()->CurrentOrientation(); - return initDevice(_information, *_game, _device); + inDeviceTransition = false; } - void GraphicsDeviceManager::ChangeDevice() { + void GraphicsDeviceManager::CreateDevice(GraphicsDeviceInformation& newInfo) { + if (device) { + device = nullptr; + } + + //this.OnPreparingDeviceSettings((object)this, new PreparingDeviceSettingsEventArgs(newInfo)); + MassagePresentParameters(*newInfo.PresentParameters); + ValidateGraphicsDeviceInformation(newInfo); + + const auto windowBounds = game->Window()->ClientBounds(); + + if (windowBounds.Width != newInfo.PresentParameters->BackBufferWidth || windowBounds.Height != newInfo.PresentParameters->BackBufferHeight) { + game->Window()->impl->Size( + newInfo.PresentParameters->BackBufferWidth, + newInfo.PresentParameters->BackBufferHeight); + game->Window()->impl->Update(); + } + + device = snew(newInfo.Adapter, newInfo.Profile, newInfo.PresentParameters); + device->Initialize(); + + game->graphicsDevice = this->device; + + //device.DeviceResetting += new EventHandler(this.HandleDeviceResetting); + //device.DeviceReset += new EventHandler(this.HandleDeviceReset); + //device.DeviceLost += new EventHandler(this.HandleDeviceLost); + //device.Disposing += new EventHandler(this.HandleDisposing); + + //GraphicsDeviceManager.ConfigureTouchInput(newInfo.PresentationParameters); + //this.OnDeviceCreated((object)this, EventArgs.Empty);*/ } - + void GraphicsDeviceManager::AddDevices(bool anySuitableDevice, std::vector>& foundDevices) { + const auto handle = game->Window()->Handle(); + + std::vector> adapters; + GraphicsAdapter::Adapters(adapters); + + for (size_t i = 0; i < adapters.size(); ++i) { + auto& adapter = adapters[i]; + + if (!anySuitableDevice) { + if (!IsWindowOnAdapter(handle, *adapter)) + continue; + } + + if (adapter->IsProfileSupported(graphicsProfile)) { + auto baseDeviceInfo = snew(); + baseDeviceInfo->Adapter = std::move(adapter); + baseDeviceInfo->Profile = graphicsProfile; + baseDeviceInfo->PresentParameters = snew(); + 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& baseDeviceInfo, std::vector>& foundDevices) const { + auto deviceInformation = snew(*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 GraphicsDeviceManager::FindBestPlatformDevice(bool anySuitableDevice) { + auto foundDevices = std::vector>(); + + 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 const& a, sptr 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(backFormat1) <= static_cast(backFormat2); + + if (presentationParameters1->MultiSampleCount != presentationParameters2->MultiSampleCount) + return presentationParameters1->MultiSampleCount <= presentationParameters2->MultiSampleCount; + + const auto num3 = graphics->PreferredBackBufferWidth() == 0 || graphics->PreferredBackBufferHeight() == 0 + ? GraphicsDeviceManager::DefaultBackBufferWidth / static_cast(GraphicsDeviceManager::DefaultBackBufferHeight) + : graphics->PreferredBackBufferWidth() / static_cast(graphics->PreferredBackBufferHeight()); + + const auto num4 = presentationParameters1->BackBufferWidth / static_cast(presentationParameters1->BackBufferHeight); + const auto num5 = presentationParameters2->BackBufferWidth / static_cast(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>& foundDevices) { + GraphicsDeviceInformationComparer comparer; + comparer.graphics = this; + + std::sort(foundDevices.begin(), foundDevices.end(), comparer); + } + + bool GraphicsDeviceManager::CanResetDevice(GraphicsDeviceInformation& newDeviceInfo) { + return device->Profile() == newDeviceInfo.Profile; + } + + void GraphicsDeviceManager::MassagePresentParameters(PresentationParameters& pp) { + const auto flag1 = pp.BackBufferWidth == 0; + const auto flag2 = pp.BackBufferHeight == 0; + + if (pp.IsFullscreen) + return; + + auto hWnd = pp.DeviceWindowHandle; + + if (hWnd == 0) { + if (!game) + Exception::Throw(Exception::INVALID_OPERATION); + + hWnd = game->Window()->Handle(); + } + + /*NativeMethods.RECT rect; + NativeMethods.GetClientRect(hWnd, out rect); + if (flag1 && rect.Right == 0) + pp.BackBufferWidth = 1; + if (!flag2 || rect.Bottom != 0) + return; + pp.BackBufferHeight = 1;*/ + } + + void GraphicsDeviceManager::ValidateGraphicsDeviceInformation(GraphicsDeviceInformation& devInfo) { + const auto& adapter = devInfo.Adapter; + auto& presentationParameters = devInfo.PresentParameters; + + if (!presentationParameters->IsFullscreen) + return; + + if (presentationParameters->BackBufferWidth == 0 || presentationParameters->BackBufferHeight == 0) + Exception::Throw(Exception::INVALID_OPERATION); + + bool flag = true; + + const auto& currentDisplayMode = adapter->CurrentDisplayMode(); + + if (currentDisplayMode->Format() != presentationParameters->BackBufferFormat && currentDisplayMode->Width() != presentationParameters->BackBufferWidth + && currentDisplayMode->Height() != presentationParameters->BackBufferHeight) + { + flag = false; + + const auto& supportedDisplayModes = adapter->SupportedDisplayModes(); + const size_t count = supportedDisplayModes->Count(); + + for (size_t i = 0; i < count; ++i) { + const auto& displayMode = supportedDisplayModes->DisplayModes[i]; + + if (displayMode->Width() == presentationParameters->BackBufferWidth && displayMode->Height() == presentationParameters->BackBufferHeight) { + flag = true; + break; + } + } + } + if (!flag) + Exception::Throw(Exception::INVALID_OPERATION); + } + + bool IsWindowOnAdapter(intptr_t windowHandle, GraphicsAdapter const& adapter) { + const auto fromAdapter = GameWindow::ScreenFromAdapter(adapter); + const auto fromHandle = GameWindow::ScreenFromHandle(windowHandle); + + return (fromAdapter && fromHandle) && (*fromAdapter == *fromHandle); + } } \ No newline at end of file diff --git a/framework/platform-dx/rasterizerstate.cpp b/framework/platform-dx/rasterizerstate.cpp index 039ae67..777963f 100644 --- a/framework/platform-dx/rasterizerstate.cpp +++ b/framework/platform-dx/rasterizerstate.cpp @@ -68,11 +68,11 @@ namespace xna { } float RasterizerState::DepthBias() const { - return impl->dxDescription.DepthBias; + return static_cast(impl->dxDescription.DepthBias); } void RasterizerState::DepthBias(float value) { - impl->dxDescription.DepthBias = value; + impl->dxDescription.DepthBias = static_cast(value); } float RasterizerState::SlopeScaleDepthBias() const { diff --git a/framework/platform-dx/samplerstate.cpp b/framework/platform-dx/samplerstate.cpp index f624144..5209173 100644 --- a/framework/platform-dx/samplerstate.cpp +++ b/framework/platform-dx/samplerstate.cpp @@ -65,7 +65,10 @@ namespace xna { states[i]->AddRef(); } - device.impl->_context->PSSetSamplers(0, states.size(), states.data()); + device.impl->_context->PSSetSamplers( + 0, + static_cast(states.size()), + states.data()); for (size_t i = 0; i < samplers.size(); ++i) { states[i]->Release(); diff --git a/framework/platform-dx/screen.cpp b/framework/platform-dx/screen.cpp new file mode 100644 index 0000000..1af1482 --- /dev/null +++ b/framework/platform-dx/screen.cpp @@ -0,0 +1,59 @@ +#include "xna/xna-dx.hpp" + +namespace xna { + + //See ref + // + //https://learn.microsoft.com/pt-br/windows/win32/api/winuser/nf-winuser-getmonitorinfoa + //https://learn.microsoft.com/pt-br/windows/win32/api/winuser/ns-winuser-monitorinfoexa + //https://stackoverflow.com/questions/7767036/how-do-i-get-the-number-of-displays-in-windows + // + + static BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) + { + auto screens = (std::vector>*)dwData; + + MONITORINFOEX monitorInfo{}; + monitorInfo.cbSize = sizeof(MONITORINFOEX); + GetMonitorInfo(hMonitor, &monitorInfo); + + const auto hmonitor = reinterpret_cast(hMonitor); + + const auto primary = monitorInfo.dwFlags == MONITORINFOF_PRIMARY; + + Rectangle bounds; + bounds.X = monitorInfo.rcMonitor.left; + bounds.Y = monitorInfo.rcMonitor.top; + bounds.Width = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left; + bounds.Height = monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top; + + Rectangle workingArea; + workingArea.X = monitorInfo.rcWork.left; + workingArea.Y = monitorInfo.rcWork.top; + workingArea.Width = monitorInfo.rcWork.right - monitorInfo.rcWork.left; + workingArea.Height = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top; + + const auto deviceName = String(monitorInfo.szDevice); + + auto screen = unew( + hmonitor, + primary, + bounds, + workingArea, + deviceName + ); + + screens->push_back(std::move(screen)); + + return TRUE; + } + + + std::vector> Screen::AllScreens() { + std::vector> screens; + if (EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&screens)) + return screens; + + return std::vector>(); + } +} \ No newline at end of file diff --git a/framework/platform-dx/sprite.cpp b/framework/platform-dx/sprite.cpp index 26a2461..866eb37 100644 --- a/framework/platform-dx/sprite.cpp +++ b/framework/platform-dx/sprite.cpp @@ -1,11 +1,3 @@ -#include "xna/graphics/rasterizerstate.hpp" -#include "xna/graphics/samplerstate.hpp" -#include "xna/common/color.hpp" -#include "xna/common/numerics.hpp" -#include "xna/graphics/sprite.hpp" -#include "xna/graphics/viewport.hpp" -#include "xna/graphics/blendstate.hpp" -#include "xna/graphics/depthstencilstate.hpp" #include "xna/xna-dx.hpp" #include @@ -31,11 +23,11 @@ namespace xna { std::vector const& kerning, std::optional const& defaultCharacter) { - if (!texture || !texture->impl->dxShaderResource) - throw std::invalid_argument("SpriteFont: texture is null."); + Exception::ThrowIfNull(texture, nameof(texture)); + Exception::ThrowIfNull(texture->impl->dxShaderResource.Get(), nameof(texture->impl->dxShaderResource)); if(cropping.size() != glyphs.size() || charMap.size() != glyphs.size() || (!kerning.empty() && kerning.size() != glyphs.size())) - throw std::invalid_argument("SpriteFont: cropping, charmap and kerning (if not empty) must all be the same size."); + Exception::Throw("Cropping, charmap and kerning (if not empty) must all be the same size."); std::vector dxGlyps(glyphs.size()); @@ -62,7 +54,7 @@ namespace xna { } impl = unew(); - impl->_dxSpriteFont = unew( + impl->dxSpriteFont = unew( //ID3D11ShaderResourceView* texture texture->impl->dxShaderResource.Get(), //Glyph const* glyphs @@ -75,16 +67,12 @@ namespace xna { if (defaultCharacter.has_value()) { const auto defChar = static_cast(defaultCharacter.value()); - impl->_dxSpriteFont->SetDefaultCharacter(defChar); + impl->dxSpriteFont->SetDefaultCharacter(defChar); } } - Vector2 SpriteFont::MeasureString(String const& text, bool ignoreWhiteSpace) - { - if (!impl->_dxSpriteFont) - return Vector2(); - - const auto size = impl->_dxSpriteFont->MeasureString(text.c_str(), ignoreWhiteSpace); + Vector2 SpriteFont::MeasureString(String const& text, bool ignoreWhiteSpace) { + const auto size = impl->dxSpriteFont->MeasureString(text.c_str(), ignoreWhiteSpace); Vector2 vec2{}; vec2.X = size.m128_f32[0]; vec2.Y = size.m128_f32[1]; @@ -92,12 +80,8 @@ namespace xna { return vec2; } - Vector2 SpriteFont::MeasureString(WString const& text, bool ignoreWhiteSpace) - { - if (!impl->_dxSpriteFont) - return Vector2(); - - const auto size = impl->_dxSpriteFont->MeasureString(text.c_str(), ignoreWhiteSpace); + Vector2 SpriteFont::MeasureString(WString const& text, bool ignoreWhiteSpace){ + const auto size = impl->dxSpriteFont->MeasureString(text.c_str(), ignoreWhiteSpace); Vector2 vec2{}; vec2.X = size.m128_f32[0]; vec2.Y = size.m128_f32[1]; @@ -106,30 +90,30 @@ namespace xna { } Char SpriteFont::DefaultCharacter() const { - const auto defChar = impl->_dxSpriteFont->GetDefaultCharacter(); + const auto defChar = impl->dxSpriteFont->GetDefaultCharacter(); return static_cast(defChar); } void SpriteFont::DefaultCharacter(Char value) { const auto defChar = static_cast(value); - impl->_dxSpriteFont->SetDefaultCharacter(defChar); + impl->dxSpriteFont->SetDefaultCharacter(defChar); } Int SpriteFont::LineSpacing() const { - const auto space = impl->_dxSpriteFont->GetLineSpacing(); + const auto space = impl->dxSpriteFont->GetLineSpacing(); return static_cast(space); } - void SpriteFont::LineSpacing(Int value) { - impl->_dxSpriteFont->SetLineSpacing(static_cast(value)); + void SpriteFont::LineSpacing(float value) { + impl->dxSpriteFont->SetLineSpacing(value); } SpriteBatch::SpriteBatch(sptr const& device) : GraphicsResource(device) { - if (!device->impl->_context) - return; + Exception::ThrowIfNull(device, nameof(device)); + Exception::ThrowIfNull(device->impl->_context.Get(), nameof(device->impl->_context)); impl = unew(); - impl->_dxspriteBatch = snew( + impl->dxSpriteBatch = snew( //ID3D11DeviceContext* deviceContext device->impl->_context.Get() ); @@ -138,31 +122,18 @@ namespace xna { } void SpriteBatch::Begin(SpriteSortMode sortMode, BlendState* blendState, SamplerState* samplerState, DepthStencilState* depthStencil, RasterizerState* rasterizerState, Effect* effect, Matrix const& transformMatrix) { - - if (!impl->_dxspriteBatch) - return; - - DxSpriteSortMode sort = DxHelpers::SpriteSortToDx(sortMode); - - const auto& t = transformMatrix; - DxMatrix matrix = DxMatrix( - t.M11, t.M12, t.M13, t.M14, - t.M21, t.M22, t.M23, t.M24, - t.M31, t.M32, t.M33, t.M34, - t.M41, t.M42, t.M43, t.M44); - std::function effectFunc = nullptr; - //if Effect is not null set effectBuffer and inputLayout - if (effect && effect->impl) { - bool effectBufferChanged = false; + //if Effect is not null set dxEffectBuffer and inputLayout + if (effect) { + bool dxEffectBufferChanged = false; - if (!impl->effectBuffer || impl->effectBuffer != effect->impl->dxEffect) { - impl->effectBuffer = effect->impl->dxEffect; - effectBufferChanged = true; + if (!impl->dxEffectBuffer || impl->dxEffectBuffer != effect->impl->dxEffect) { + impl->dxEffectBuffer = effect->impl->dxEffect; + dxEffectBufferChanged = true; } - if (effectBufferChanged) { + if (!impl->dxInputLayout || dxEffectBufferChanged) { void const* shaderByteCode; size_t byteCodeLength; @@ -178,68 +149,53 @@ namespace xna { auto& context = m_device->impl->_context; effectFunc = [=] { - impl->effectBuffer->Apply(context.Get()); + impl->dxEffectBuffer->Apply(context.Get()); context->IASetInputLayout(impl->dxInputLayout.Get()); }; } - impl->_dxspriteBatch->Begin( - sort, + auto _sortMode = DxHelpers::SpriteSortToDx(sortMode); + auto _transformMatrix = DxHelpers::MatrixToDx(transformMatrix); + + impl->dxSpriteBatch->Begin( + _sortMode, blendState ? blendState->impl->dxBlendState.Get() : nullptr, samplerState ? samplerState->impl->_samplerState.Get() : nullptr, depthStencil ? depthStencil->impl->dxDepthStencil.Get() : nullptr, rasterizerState ? rasterizerState->impl->dxRasterizerState.Get() : nullptr, effectFunc, - matrix + _transformMatrix ); } void SpriteBatch::End() { - if (!impl->_dxspriteBatch) - return; - - impl->_dxspriteBatch->End(); + impl->dxSpriteBatch->End(); } void SpriteBatch::Draw(Texture2D& texture, Vector2 const& position, Color const& color) { - if (!impl->_dxspriteBatch) - return; - - if (!texture.impl->dxShaderResource) - return; - - const auto _position = XMFLOAT2(position.X, position.Y); + const auto _position = DxHelpers::VectorToDx(position); const auto v4 = color.ToVector4(); - XMVECTORF32 _color = { v4.X, v4.Y, v4.Z, v4.W }; + const auto _color = DxHelpers::VectorToDx(v4); - impl->_dxspriteBatch->Draw( + impl->dxSpriteBatch->Draw( texture.impl->dxShaderResource.Get(), _position, _color ); } - void SpriteBatch::Draw(Texture2D& texture, Vector2 const& position, std::optional const& sourceRectangle, Color const& color) { - if (!impl->_dxspriteBatch) - return; - - if (!texture.impl->dxShaderResource) - return; - - const auto _position = XMFLOAT2(position.X, position.Y); + void SpriteBatch::Draw(Texture2D& texture, Vector2 const& position, std::optional const& sourceRectangle, Color const& color) { + const auto _position = DxHelpers::VectorToDx(position); const auto v4 = color.ToVector4(); - const XMVECTORF32 _color = { v4.X, v4.Y, v4.Z, v4.W }; + const auto _color = DxHelpers::VectorToDx(v4); RECT _sourceRect{}; if (sourceRectangle.has_value()) { - _sourceRect.top = sourceRectangle->Y; - _sourceRect.left = sourceRectangle->X; - _sourceRect.right = sourceRectangle->X + sourceRectangle->Width; - _sourceRect.bottom = sourceRectangle->Y + sourceRectangle->Height; + _sourceRect = DxHelpers::RectangleToDx(sourceRectangle.value()); }; - impl->_dxspriteBatch->Draw( + impl->dxSpriteBatch->Draw( texture.impl->dxShaderResource.Get(), _position, sourceRectangle ? &_sourceRect : nullptr, @@ -247,29 +203,20 @@ namespace xna { } void SpriteBatch::Draw(Texture2D& texture, Vector2 const& position, std::optional const& sourceRectangle, Color const& color, float rotation, Vector2 const& origin, float scale, SpriteEffects effects, float layerDepth) { - if (!impl->_dxspriteBatch) - return; - - if (!texture.impl->dxShaderResource) - return; - - const auto _position = XMFLOAT2(position.X, position.Y); - const auto _origin = XMFLOAT2(origin.X, origin.Y); + const auto _position = DxHelpers::VectorToDx(position); + const auto _origin = DxHelpers::VectorToDx(origin); const auto v4 = color.ToVector4(); - const XMVECTORF32 _color = { v4.X, v4.Y, v4.Z, v4.W }; + const auto _color = DxHelpers::VectorToDx(v4); RECT _sourceRect{}; if (sourceRectangle.has_value()) { - _sourceRect.top = sourceRectangle->Y; - _sourceRect.left = sourceRectangle->X; - _sourceRect.right = sourceRectangle->X + sourceRectangle->Width; - _sourceRect.bottom = sourceRectangle->Y + sourceRectangle->Height; + _sourceRect = DxHelpers::RectangleToDx(sourceRectangle.value()); }; const DxSpriteEffects _effects = static_cast(effects); - impl->_dxspriteBatch->Draw( + impl->dxSpriteBatch->Draw( texture.impl->dxShaderResource.Get(), _position, sourceRectangle ? &_sourceRect : nullptr, @@ -282,12 +229,6 @@ namespace xna { } void SpriteBatch::Draw(Texture2D& texture, Vector2 const& position, std::optional const& sourceRectangle, Color const& color, float rotation, Vector2 const& origin, Vector2 const& scale, SpriteEffects effects, float layerDepth) { - if (!impl->_dxspriteBatch) - return; - - if (!texture.impl->dxShaderResource) - return; - const auto _position = XMFLOAT2(position.X, position.Y); const auto _origin = XMFLOAT2(origin.X, origin.Y); const auto v4 = color.ToVector4(); @@ -296,16 +237,13 @@ namespace xna { RECT _sourceRect{}; if (sourceRectangle.has_value()) { - _sourceRect.top = sourceRectangle->Y; - _sourceRect.left = sourceRectangle->X; - _sourceRect.right = sourceRectangle->X + sourceRectangle->Width; - _sourceRect.bottom = sourceRectangle->Y + sourceRectangle->Height; + _sourceRect = DxHelpers::RectangleToDx(sourceRectangle.value()); }; const auto _effects = static_cast(effects); const XMFLOAT2 _scale = { scale.X, scale.Y }; - impl->_dxspriteBatch->Draw( + impl->dxSpriteBatch->Draw( texture.impl->dxShaderResource.Get(), _position, sourceRectangle ? &_sourceRect : nullptr, @@ -318,36 +256,16 @@ namespace xna { } void SpriteBatch::Draw(Texture2D& texture, Rectangle const& destinationRectangle, Color const& color) { - if (!impl->_dxspriteBatch) - return; - - if (!texture.impl->dxShaderResource) - return; - - RECT _destinationRect{}; - _destinationRect.left = destinationRectangle.X; - _destinationRect.top = destinationRectangle.Y; - _destinationRect.right = destinationRectangle.X + destinationRectangle.Width; - _destinationRect.bottom = destinationRectangle.Y + destinationRectangle.Height; + RECT _destinationRect = DxHelpers::RectangleToDx(destinationRectangle); const auto v4 = color.ToVector4(); const XMVECTORF32 _color = { v4.X, v4.Y, v4.Z, v4.W }; - impl->_dxspriteBatch->Draw(texture.impl->dxShaderResource.Get(), _destinationRect, _color); + impl->dxSpriteBatch->Draw(texture.impl->dxShaderResource.Get(), _destinationRect, _color); } void SpriteBatch::Draw(Texture2D& texture, Rectangle const& destinationRectangle, std::optional const& sourceRectangle, Color const& color) { - if (!impl->_dxspriteBatch) - return; - - if (!texture.impl->dxShaderResource) - return; - - RECT _destinationRect{}; - _destinationRect.left = destinationRectangle.X; - _destinationRect.top = destinationRectangle.Y; - _destinationRect.right = destinationRectangle.X + destinationRectangle.Width; - _destinationRect.bottom = destinationRectangle.Y + destinationRectangle.Height; + RECT _destinationRect = DxHelpers::RectangleToDx(destinationRectangle); const auto v4 = color.ToVector4(); const XMVECTORF32 _color = { v4.X, v4.Y, v4.Z, v4.W }; @@ -361,21 +279,11 @@ namespace xna { _sourceRect.bottom = sourceRectangle->Y + sourceRectangle->Height; }; - impl->_dxspriteBatch->Draw(texture.impl->dxShaderResource.Get(), _destinationRect, sourceRectangle ? &_sourceRect : nullptr, _color); + impl->dxSpriteBatch->Draw(texture.impl->dxShaderResource.Get(), _destinationRect, sourceRectangle ? &_sourceRect : nullptr, _color); } void SpriteBatch::Draw(Texture2D& texture, Rectangle const& destinationRectangle, std::optional const& sourceRectangle, Color const& color, float rotation, Vector2 const& origin, SpriteEffects effects, float layerDepth) { - if (!impl->_dxspriteBatch) - return; - - if (!texture.impl->dxShaderResource) - return; - - RECT _destinationRect{}; - _destinationRect.left = destinationRectangle.X; - _destinationRect.top = destinationRectangle.Y; - _destinationRect.right = destinationRectangle.X + destinationRectangle.Width; - _destinationRect.bottom = destinationRectangle.Y + destinationRectangle.Height; + RECT _destinationRect = DxHelpers::RectangleToDx(destinationRectangle); const auto v4 = color.ToVector4(); const XMVECTORF32 _color = { v4.X, v4.Y, v4.Z, v4.W }; @@ -383,16 +291,13 @@ namespace xna { RECT _sourceRect{}; if (sourceRectangle.has_value()) { - _sourceRect.top = sourceRectangle->Y; - _sourceRect.left = sourceRectangle->X; - _sourceRect.right = sourceRectangle->X + sourceRectangle->Width; - _sourceRect.bottom = sourceRectangle->Y + sourceRectangle->Height; + _sourceRect = DxHelpers::RectangleToDx(sourceRectangle.value()); }; auto _origin = XMFLOAT2(origin.X, origin.Y); const auto _effects = static_cast(effects); - impl->_dxspriteBatch->Draw( + impl->dxSpriteBatch->Draw( texture.impl->dxShaderResource.Get(), _destinationRect, sourceRectangle ? &_sourceRect : nullptr, @@ -404,30 +309,17 @@ namespace xna { } void SpriteBatch::Viewport(xna::Viewport const& value) { - if (!impl->_dxspriteBatch) - return; - - D3D11_VIEWPORT _view{}; - _view.TopLeftX = value.X; - _view.TopLeftY = value.Y; - _view.Width = value.Width; - _view.Height = value.Height; - _view.MinDepth = value.MinDetph; - _view.MaxDepth = value.MaxDepth; - - impl->_dxspriteBatch->SetViewport(_view); + const auto _view = DxHelpers::ViewportToDx(value); + impl->dxSpriteBatch->SetViewport(_view); } void SpriteBatch::DrawString(SpriteFont& spriteFont, String const& text, Vector2 const& position, Color const& color) { - if (!impl->_dxspriteBatch || !spriteFont.impl->_dxSpriteFont) - return; - const auto _position = XMFLOAT2(position.X, position.Y); const auto v4 = color.ToVector4(); const XMVECTORF32 _color = { v4.X, v4.Y, v4.Z, v4.W }; - spriteFont.impl->_dxSpriteFont->DrawString( - impl->_dxspriteBatch.get(), + spriteFont.impl->dxSpriteFont->DrawString( + impl->dxSpriteBatch.get(), text.c_str(), _position, _color @@ -436,17 +328,14 @@ namespace xna { void SpriteBatch::DrawString(SpriteFont& spriteFont, String const& text, Vector2 const& position, Color const& color, float rotation, Vector2 const& origin, float scale, SpriteEffects effects, float layerDepth) { - if (!impl->_dxspriteBatch || !spriteFont.impl->_dxSpriteFont) - return; - const auto _position = XMFLOAT2(position.X, position.Y); const auto _origin = XMFLOAT2(origin.X, origin.Y); const auto v4 = color.ToVector4(); const XMVECTORF32 _color = { v4.X, v4.Y, v4.Z, v4.W }; const auto _effects = static_cast(effects); - spriteFont.impl->_dxSpriteFont->DrawString( - impl->_dxspriteBatch.get(), + spriteFont.impl->dxSpriteFont->DrawString( + impl->dxSpriteBatch.get(), text.c_str(), _position, _color, diff --git a/framework/platform-dx/swapchain.cpp b/framework/platform-dx/swapchain.cpp index 19aacb3..6ac7818 100644 --- a/framework/platform-dx/swapchain.cpp +++ b/framework/platform-dx/swapchain.cpp @@ -24,18 +24,13 @@ namespace xna { swapChain.ReleaseAndGetAddressOf(); } - auto adapter = device.Adapter(); - auto dxAdapter = adapter->impl->dxadapter; + auto adapter = device.Adapter(); - IDXGIFactory1* dxFactory1 = nullptr; - auto hr = dxAdapter->GetParent(IID_IDXGIFactory1, (void**)&dxFactory1); + comptr dxFactory2 = nullptr; + const auto hr = adapter->impl->dxFactory->QueryInterface(IID_IDXGIFactory2, (void**)&dxFactory2); - if (FAILED(hr)) return false; - - IDXGIFactory2* dxFactory2 = nullptr; - hr = dxFactory1->QueryInterface(IID_IDXGIFactory2, (void**)&dxFactory2); - - if (FAILED(hr)) return false; + if (FAILED(hr)) + return false; dxFactory2->CreateSwapChainForHwnd( device.impl->_device.Get(), @@ -45,7 +40,6 @@ namespace xna { nullptr, swapChain.GetAddressOf()); - return true; } @@ -70,7 +64,7 @@ namespace xna { impl->dxFullScreenDescription.RefreshRate.Denominator = 1; impl->dxFullScreenDescription.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; impl->dxFullScreenDescription.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; - impl->dxFullScreenDescription.Windowed = !parameters->Fullscreen; + impl->dxFullScreenDescription.Windowed = !parameters->IsFullscreen; HWND hwnd = reinterpret_cast(parameters->DeviceWindowHandle); return internalInit(*m_device, hwnd, impl->dxSwapChain, impl->dxDescription, impl->dxFullScreenDescription); diff --git a/framework/platform-dx/window.cpp b/framework/platform-dx/window.cpp index 99ea44f..3f54760 100644 --- a/framework/platform-dx/window.cpp +++ b/framework/platform-dx/window.cpp @@ -2,20 +2,17 @@ namespace xna { GameWindow::GameWindow() { - impl = unew(); + impl = unew(this); impl->_hInstance = GetModuleHandle(NULL); impl->_windowIcon = LoadIcon(NULL, IDI_APPLICATION); impl->_windowCursor = LoadCursor(NULL, IDC_ARROW); impl->_windowStyle = static_cast(GameWindowMode::Windowed); impl->_windowCenterX = impl->_windowWidth / 2.0F; - impl->_windowCenterY = impl->_windowHeight / 2.0F; - - } - - GameWindow::~GameWindow() { - impl = nullptr; - } + impl->_windowCenterY = impl->_windowHeight / 2.0F; + impl->_windowWidth = GameWindow::DefaultClientWidth; + impl->_windowHeight = GameWindow::DefaultClientHeight; + } void GameWindow::PlatformImplementation::Position(int width, int height, bool update) { _windowPosX = width; @@ -34,9 +31,8 @@ namespace xna { if(update) Update(); } - void GameWindow::Title(String const& title) { - if (!impl) return; - + void GameWindow::Title(String const& value) { + title = value; impl->_windowTitle = title; } @@ -89,9 +85,35 @@ namespace xna { winRect.bottom - winRect.top, TRUE); - return _windowHandle ? true : false; + if (!_windowHandle) + return false; } + + // + // GameWindow + // + + const auto handle = reinterpret_cast(_windowHandle); + + gameWindow->handle = handle; + gameWindow->title = _windowTitle; + gameWindow->clientBounds = { _windowPosX, _windowPosY, _windowWidth, _windowHeight }; + gameWindow->currentOrientation = DisplayOrientation::Default; + + auto screens = Screen::AllScreens(); + + if (screens.size() == 1) + gameWindow->screenDeviceName = screens[0]->DeviceName(); + else { + for (size_t i = 0; i < screens.size(); ++i) { + const auto& screen = screens[i]; + + if (screen->Primary()) + gameWindow->screenDeviceName = screen->DeviceName(); + } + } + return true; } @@ -118,30 +140,13 @@ namespace xna { return _windowHandle ? true : false; } + gameWindow->clientBounds = { _windowPosX, _windowPosY, _windowWidth, _windowHeight }; + return true; - } + } - String GameWindow::Title() const { - if (!impl) return String(); - - return impl->_windowTitle; - } - - Rectangle GameWindow::ClientBounds() const { - if (!impl) return {}; - - return Rectangle( - impl->_windowPosX, - impl->_windowPosY, - impl->_windowWidth, - impl->_windowHeight - ); - } - - intptr_t GameWindow::Handle() const { - if (!impl) return 0; - - return reinterpret_cast(impl->_windowHandle); + bool GameWindow::IsWindowMinimized() const { + return IsIconic(impl->_windowHandle); } LRESULT GameWindow::PlatformImplementation::WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) @@ -189,4 +194,61 @@ namespace xna { } return DefWindowProc(hWnd, msg, wParam, lParam); } + + uptr GameWindow::ScreenFromAdapter(GraphicsAdapter const& adapter) { + auto screens = Screen::AllScreens(); + + for (size_t i = 0; i < screens.size(); ++i) { + auto& screen = screens[i]; + + if (screen->DeviceName() == adapter.DeviceName()) + return std::move(screen); + } + + return nullptr; + } + + uptr GameWindow::ScreenFromHandle(intptr_t windowHandle) { + const auto handle = reinterpret_cast(windowHandle); + auto hMonitor = MonitorFromWindow(handle, MONITOR_DEFAULTTOPRIMARY); + + if (!hMonitor) + return nullptr; + + MONITORINFOEX monitorInfo{}; + monitorInfo.cbSize = sizeof(MONITORINFOEX); + GetMonitorInfo(hMonitor, &monitorInfo); + + const auto hmonitor = reinterpret_cast(hMonitor); + const auto primary = monitorInfo.dwFlags == MONITORINFOF_PRIMARY; + + Rectangle bounds; + bounds.X = monitorInfo.rcMonitor.left; + bounds.Y = monitorInfo.rcMonitor.top; + bounds.Width = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left; + bounds.Height = monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top; + + Rectangle workingArea; + workingArea.X = monitorInfo.rcWork.left; + workingArea.Y = monitorInfo.rcWork.top; + workingArea.Width = monitorInfo.rcWork.right - monitorInfo.rcWork.left; + workingArea.Height = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top; + + const auto deviceName = String(monitorInfo.szDevice); + + auto screen = unew( + hmonitor, + primary, + bounds, + workingArea, + deviceName + ); + + return screen; + } + + String GameWindow::ScreenDeviceName() const { + const auto screen = ScreenFromHandle(handle); + return screen->DeviceName(); + } } \ No newline at end of file diff --git a/inc/xna/common/math.hpp b/inc/xna/common/math.hpp index afaec53..e677068 100644 --- a/inc/xna/common/math.hpp +++ b/inc/xna/common/math.hpp @@ -17,11 +17,12 @@ namespace xna { static constexpr float Min(float value1, float value2) { return (std::min)(value1, value2); } static constexpr float Max(float value1, float value2) { return (std::max)(value1, value2); } - static constexpr float Clamp(float value, float min, float max) { + template + static constexpr T Clamp(T value, T min, T max) { value = value > max ? max : value; value = value < min ? min : value; return value; - } + } static constexpr float Lerp(float value1, float value2, float amount) { return value1 + (value2 - value1) * amount; diff --git a/inc/xna/common/numerics.hpp b/inc/xna/common/numerics.hpp index d637230..bd1d63f 100644 --- a/inc/xna/common/numerics.hpp +++ b/inc/xna/common/numerics.hpp @@ -6,6 +6,23 @@ #include namespace xna { + //Represents a rational number. + struct RationalNumber { + constexpr RationalNumber() = default; + + constexpr RationalNumber(Uint numerator, Uint denominator) + : Numerator(numerator), Denominator(denominator) {} + + constexpr bool operator==(const RationalNumber& other) const { + return Numerator == other.Numerator && Denominator == other.Denominator; + } + + //An unsigned integer value representing the top of the rational number. + Uint Numerator{ 0 }; + //An unsigned integer value representing the bottom of the rational number. + Uint Denominator{ 0 }; + }; + struct Point { Int X{ 0 }; Int Y{ 0 }; diff --git a/inc/xna/content/reader.hpp b/inc/xna/content/reader.hpp index a96f6d1..ff4b3f7 100644 --- a/inc/xna/content/reader.hpp +++ b/inc/xna/content/reader.hpp @@ -176,7 +176,7 @@ namespace xna { if (typeReader.TargetIsValueType) return InvokeReader(typeReader, existingInstance); - ReadObjectInternal(existingInstance); + return ReadObjectInternal(existingInstance); } } diff --git a/inc/xna/csharp/eventhandler.hpp b/inc/xna/csharp/eventhandler.hpp new file mode 100644 index 0000000..eb696b2 --- /dev/null +++ b/inc/xna/csharp/eventhandler.hpp @@ -0,0 +1,44 @@ +#ifndef XNA_CSHARP_EVENTHANDLER_HPP +#define XNA_CSHARP_EVENTHANDLER_HPP + +#include +#include + +namespace xna { + struct EventArgs { + virtual ~EventArgs() { + sender = nullptr; + } + + void** sender = nullptr; + }; + + template + struct EventHandler { + + template + using HANDLER_CALLBACK = void(_Ptr::*&)(TEventArgs& args); + + template + void Add(HANDLER_CALLBACK<_Ptr> function, _Ptr* ptr) { + using std::placeholders::_1; + std::function func = std::bind(function, ptr, _1); + funcs.push_back(func); + } + + void operator()(TEventArgs& args) { + for (size_t i = 0; i < funcs.size(); ++i) + { + auto& func = funcs[i]; + + if (func) + func(args); + } + } + + private: + std::vector> funcs; + }; +} + +#endif \ No newline at end of file diff --git a/inc/xna/csharp/screen.hpp b/inc/xna/csharp/screen.hpp new file mode 100644 index 0000000..54b788b --- /dev/null +++ b/inc/xna/csharp/screen.hpp @@ -0,0 +1,47 @@ +#ifndef XNA_CSHARP_SCREEN_HPP +#define XNA_CSHARP_SCREEN_HPP + +#include "../default.hpp" +#include "../common/numerics.hpp" + +namespace xna { + //A simplified port of System.Windows.Forms.Screen. + //Represents a display device or multiple display devices on a single system. + class Screen { + public: + Screen(intptr_t hmonitor, bool primary, Rectangle bounds, Rectangle workingArea, String const& deviceName) : + hmonitor(hmonitor), primary(primary), bounds(bounds), workingArea(workingArea), deviceName(deviceName) {} + + //Gets an array of all displays on the system. + static std::vector> AllScreens(); + + //Gets the bounds of the display. + constexpr Rectangle Bounds() const { return bounds; } + + //Gets the working area of the display.The working area is the desktop area of + //the display, excluding taskbars, docked windows, and docked tool bars. + constexpr Rectangle WorkingArea() const { return workingArea; } + + //Gets the monitor handler. + constexpr intptr_t HMonitor() const { return hmonitor; } + + // Gets a value indicating whether a particular display is the primary device. + constexpr bool Primary() const { return primary; } + + // Gets the device name associated with a display. + constexpr String DeviceName() const { return deviceName; } + + constexpr bool operator==(Screen const& other) const { + return hmonitor == other.hmonitor; + } + + private: + intptr_t hmonitor{ 0 }; + bool primary{ false }; + Rectangle bounds{}; + Rectangle workingArea{}; + String deviceName; + }; +} + +#endif \ No newline at end of file diff --git a/inc/xna/csharp/stream.hpp b/inc/xna/csharp/stream.hpp index 4e33bfe..103f881 100644 --- a/inc/xna/csharp/stream.hpp +++ b/inc/xna/csharp/stream.hpp @@ -47,7 +47,8 @@ namespace xna { class MemoryStream : public Stream { public: constexpr MemoryStream(std::vector const& bytes): - _buffer(bytes), _length(bytes.size()){} + _buffer(bytes), + _length(static_cast(bytes.size())){} ~MemoryStream() override { Close(); diff --git a/inc/xna/default.hpp b/inc/xna/default.hpp index 86f50a1..ad0327a 100644 --- a/inc/xna/default.hpp +++ b/inc/xna/default.hpp @@ -151,7 +151,7 @@ namespace xna { class GameClock; class GameTime; class GameWindow; - class GraphicsDeviceInformation; + struct GraphicsDeviceInformation; class GraphicsDeviceManager; class IGameTime; class IGameComponent; @@ -168,7 +168,6 @@ namespace xna { class Effect; class GraphicsAdapter; class GraphicsDevice; - class GraphicsDeviceInformation; struct PresentationParameters; class RenderTarget2D; class SwapChain; diff --git a/inc/xna/enumerations.hpp b/inc/xna/enumerations.hpp index 51bf886..17f1471 100644 --- a/inc/xna/enumerations.hpp +++ b/inc/xna/enumerations.hpp @@ -193,19 +193,6 @@ namespace xna { Portrait = 4, }; - enum class DisplayModeScanlineOrder { - Unspecified = 0, - Progressive = 1, - UpperFieldFirst = 2, - LowerFieldFirst = 3 - }; - - enum class DisplayModeScaling { - Unspecified = 0, - Centered = 1, - Stretched = 2 - }; - enum class EffectParameterClass { Matrix, Object, @@ -268,8 +255,12 @@ namespace xna { None, }; + //Identifies the set of supported devices for the game based on device capabilities. enum class GraphicsProfile { + //Use a limited set of graphic features and capabilities, allowing the game to support the widest variety of devices, including all Windows-based computers. Reach, + //Use the largest available set of graphic features and capabilities to target devices, + //such as an Xbox 360 console and a Windows-based computer, that have more enhanced graphic capabilities. HiDef }; diff --git a/inc/xna/game/gdeviceinfo.hpp b/inc/xna/game/gdeviceinfo.hpp index f815e5f..a3a5d07 100644 --- a/inc/xna/game/gdeviceinfo.hpp +++ b/inc/xna/game/gdeviceinfo.hpp @@ -4,13 +4,16 @@ #include "../default.hpp" namespace xna { - class GraphicsDeviceInformation { - public: + struct GraphicsDeviceInformation { + GraphicsDeviceInformation() { + PresentParameters = snew(); + } + sptr Adapter = nullptr; xna::GraphicsProfile Profile{ xna::GraphicsProfile::Reach }; - sptr Parameters = nullptr; - sptr Window = nullptr; - }; + sptr PresentParameters = nullptr; + sptr Window = nullptr; + }; } #endif \ No newline at end of file diff --git a/inc/xna/game/gdevicemanager.hpp b/inc/xna/game/gdevicemanager.hpp index 4f00060..0c09a22 100644 --- a/inc/xna/game/gdevicemanager.hpp +++ b/inc/xna/game/gdevicemanager.hpp @@ -3,36 +3,183 @@ #include "../default.hpp" #include "gdeviceinfo.hpp" +#include "../csharp/eventhandler.hpp" namespace xna { - class GraphicsDeviceManager { + struct IGraphicsDeviceService { + virtual sptr GetGraphicsDevice() = 0; + + //EventHandler DeviceDisposing; + //EventHandler DeviceReset; + //EventHandler DeviceResetting; + //EventHandler DeviceCreated; + }; + + class IGraphicsDeviceManager { + virtual void CreateDevice() = 0; + //virtual bool BeginDraw() = 0; + //virtual void EndDraw() = 0; + }; + + class GraphicsDeviceManager : public IGraphicsDeviceService, public IGraphicsDeviceManager { public: + //Creates a new GraphicsDeviceManager and registers it to handle the configuration and management of the graphics device for the specified Game. GraphicsDeviceManager(sptr const& game); - ~GraphicsDeviceManager() {} - void ApplyChanges(); - bool Initialize(); - bool ToggleFullScreen(); - Int PreferredBackBufferWidth() const; - Int PreferredBackBufferHeight() const; - void PreferredBackBufferWidth(Int value); - void PreferredBackBufferHeight(Int value); public: + //Specifies the default minimum back-buffer width. static constexpr int DefaultBackBufferWidth = 800; + //Specifies the default minimum back-buffer height. static constexpr int DefaultBackBufferHeight = 480; - protected: - bool CreateDevice(); - void ChangeDevice(); + public: + //Gets the GraphicsDevice associated with the GraphicsDeviceManager. + sptr GetGraphicsDevice() override { + return device; + } + + //Gets or sets the graphics profile, which determines the graphics feature set. + constexpr GraphicsProfile PreferredGraphicsProfile() const { + return graphicsProfile; + } + + //Gets or sets the graphics profile, which determines the graphics feature set. + constexpr void PreferredGraphicsProfile(xna::GraphicsProfile value) { + graphicsProfile = value; + isDeviceDirty = true; + } + + //Gets or sets a value that indicates whether the device should start in full-screen mode. + constexpr bool IsFullScreen() const { + return isFullScreen; + } + + //Gets or sets a value that indicates whether the device should start in full-screen mode. + constexpr void IsFullScreen(bool value) { + isFullScreen = value; + isDeviceDirty = true; + } + + //Gets or sets the format of the back buffer. + constexpr SurfaceFormat PreferredBackBufferFormat() const { + return backBufferFormat; + } + + //Gets or sets the format of the back buffer. + constexpr void PreferredBackBufferFormat(SurfaceFormat value) { + backBufferFormat = value; + isDeviceDirty = true; + } + + //Gets or sets the preferred back-buffer height. + constexpr Int PreferredBackBufferHeight() const { + return backBufferHeight; + } + + //Gets or sets the preferred back-buffer height. + constexpr void PreferredBackBufferHeight(Int value) { + backBufferHeight = value; + isDeviceDirty = true; + } + + //Gets or sets the preferred back-buffer width. + constexpr Int PreferredBackBufferWidth() const { + return backBufferWidth; + } + + //Gets or sets the preferred back-buffer width. + constexpr void PreferredBackBufferWidth(Int value) { + backBufferWidth = value; + isDeviceDirty = true; + } + + //Gets or sets the format of the depth stencil. + constexpr DepthFormat PreferredDepthStencilFormat() const { + return depthStencilFormat; + } + + //Gets or sets the format of the depth stencil. + constexpr void PreferredDepthStencilFormat(DepthFormat value) { + depthStencilFormat = value; + isDeviceDirty = true; + } + + //Gets or sets a value that indicates whether to enable a multisampled back buffer. + constexpr bool PreferMultiSampling() const { + return allowMultiSampling; + } + + //Gets or sets a value that indicates whether to enable a multisampled back buffer. + constexpr void PreferMultiSampling(bool value) { + allowMultiSampling = value; + isDeviceDirty = true; + } + + //Gets or sets the display orientations that are available if automatic rotation and scaling is enabled. + constexpr DisplayOrientation SupportedOrientations() const { + return supportedOrientations; + } + + //Gets or sets the display orientations that are available if automatic rotation and scaling is enabled. + constexpr void SupportedOrientations(DisplayOrientation value) { + supportedOrientations = value; + isDeviceDirty = true; + } + + //Gets or sets a value that indicates whether to sync to the vertical trace (vsync) when presenting the back buffer. + constexpr bool SynchronizeWithVerticalRetrace() const { + return synchronizeWithVerticalRetrace; + } + + // Gets or sets a value that indicates whether to sync to the vertical trace(vsync) when presenting the back buffer. + constexpr void SynchronizeWithVerticalRetrace(bool value) { + synchronizeWithVerticalRetrace = value; + isDeviceDirty = true; + } + + public: + //Applies any changes to device-related properties, changing the graphics device as necessary. + void ApplyChanges(); + //Toggles between full screen and windowed mode. + bool ToggleFullScreen(); + + protected: + inline virtual void RankDevices(std::vector>& foundDevices) { RankDevicesPlatform(foundDevices); } + inline virtual sptr FindBestDevice(bool anySuitableDevice) { return FindBestPlatformDevice(anySuitableDevice); } + virtual bool CanResetDevice(GraphicsDeviceInformation& newDeviceInfo); private: - sptr _game = nullptr; - Int _backBufferWidth{ DefaultBackBufferWidth }; - Int _backBufferHeight{ DefaultBackBufferHeight }; - bool _isDeviceDirty{ false }; - sptr _device = nullptr; - bool _isFullScreen{ false }; - GraphicsDeviceInformation _information{}; + inline void CreateDevice() { ChangeDevice(true); } + void ChangeDevice(bool forceCreate); + void AddDevices(bool anySuitableDevice, std::vector>& foundDevices); + void AddDevices(GraphicsAdapter const& adapter, DisplayMode const& mode, sptr& baseDeviceInfo, std::vector>& foundDevices) const; + sptr FindBestPlatformDevice(bool anySuitableDevice); + void RankDevicesPlatform(std::vector>& foundDevices); + void CreateDevice(GraphicsDeviceInformation& newInfo); + void MassagePresentParameters(PresentationParameters& pp); + void ValidateGraphicsDeviceInformation(GraphicsDeviceInformation& devInfo); + + private: + sptr game = nullptr; + bool isDeviceDirty{ false }; + sptr device = nullptr; + GraphicsDeviceInformation information{}; + bool isFullScreen{ false }; + Int backBufferWidth{ DefaultBackBufferWidth }; + Int backBufferHeight{ DefaultBackBufferHeight }; + GraphicsProfile graphicsProfile{GraphicsProfile::HiDef}; + DepthFormat depthStencilFormat{ DepthFormat::Depth24 }; + SurfaceFormat backBufferFormat{SurfaceFormat::Color}; + DisplayOrientation supportedOrientations{DisplayOrientation::Default}; + bool synchronizeWithVerticalRetrace{ true }; + bool useResizedBackBuffer{ false }; + Int resizedBackBufferWidth{ 0 }; + Int resizedBackBufferHeight{ 0 }; + bool allowMultiSampling{ false }; + bool inDeviceTransition{ false }; + bool isReallyFullScreen{ false }; + DisplayOrientation currentWindowOrientation{ DisplayOrientation::Default }; + std::vector> foundDevices; }; } diff --git a/inc/xna/game/window.hpp b/inc/xna/game/window.hpp index 7dc99eb..f9f7329 100644 --- a/inc/xna/game/window.hpp +++ b/inc/xna/game/window.hpp @@ -3,19 +3,57 @@ #include "../default.hpp" #include "../common/numerics.hpp" +#include "../csharp/screen.hpp" namespace xna { class GameWindow { public: GameWindow(); - ~GameWindow(); - String Title() const; - void Title(String const& title); - Rectangle ClientBounds() const; - intptr_t Handle() const; + + //Gets the current display orientation, which reflects the physical orientation of the phone in the user's hand. + constexpr DisplayOrientation CurrentOrientation() const { + return currentOrientation; + } + + //Gets and sets the title of the system window. + constexpr String Title() const { + return title; + } + + //Gets and sets the title of the system window. + void Title(String const& value); + + //Gets the handle to the system window. + constexpr intptr_t Handle() const { + return handle; + } + + //The screen dimensions of the game window's client rectangle. + constexpr Rectangle ClientBounds() const { + return clientBounds; + } + + //Gets the device name of the screen the window is currently in. + String ScreenDeviceName() const; + + static uptr ScreenFromAdapter(GraphicsAdapter const& adapter); + static uptr ScreenFromHandle(intptr_t windowHandle); + bool IsWindowMinimized() const; + + inline static constexpr Int DefaultClientWidth = 800; + inline static constexpr Int DefaultClientHeight = 480; + + private: + String title; + intptr_t handle{ 0 }; + Rectangle clientBounds{}; + String screenDeviceName; + DisplayOrientation currentOrientation{ DisplayOrientation::Default }; + public: struct PlatformImplementation; + friend struct PlatformImplementation; uptr impl = nullptr; }; } diff --git a/inc/xna/graphics/adapter.hpp b/inc/xna/graphics/adapter.hpp index c0dad93..55f978e 100644 --- a/inc/xna/graphics/adapter.hpp +++ b/inc/xna/graphics/adapter.hpp @@ -2,45 +2,95 @@ #define XNA_GRAPHICS_ADAPTER_HPP #include "../default.hpp" +#include "displaymode.hpp" namespace xna { //Provides methods to retrieve and manipulate graphics adapters. class GraphicsAdapter { public: - GraphicsAdapter(); + //Collection of available adapters on the system. + static void Adapters(std::vector>& adapters); - //Retrieves a string used for presentation to the user. - String Description() const; - //Retrieves a value that is used to help identify a particular chip set. - Uint DeviceId() const; - //Retrieves a string that contains the device name. - String DeviceName() const; - //Determines if this instance of GraphicsAdapter is the default adapter. - bool IsDefaultAdapter() const; - //Retrieves the handle of the monitor - intptr_t MonitorHandle() const; - //Retrieves a value used to help identify the revision level of a particular chip set. - Uint Revision() const; - //Retrieves a value used to identify the subsystem. - Uint SubSystemId() const; - //Retrieves a value used to identify the manufacturer. - Uint VendorId() const; - - //Returns a collection of supported display modes for the current adapter. - uptr SupportedDisplayModes() const; - //Returns a collection of supported display modes for the current adapter. - uptr SupportedDisplayModes(SurfaceFormat surfaceFormat) const; - //Gets the current display mode. - sptr CurrentDisplayMode(); - //Gets the current display mode. - void CurrentDisplayMode(SurfaceFormat surfaceFormat, Uint width, Uint height); + inline sptr CurrentDisplayMode() const { return currentDisplayMode; } //Gets the default adapter. static uptr DefaultAdapter(); + + //Retrieves a string used for presentation to the user. + constexpr String Description() const { return description; } + + //Retrieves a value that is used to help identify a particular chip set. + constexpr Uint DeviceId() const { return deviceId; } - //Collection of available adapters on the system. - static void Adapters(std::vector>& adapters); + //Retrieves a string that contains the device name. + constexpr String DeviceName() const { return deviceName; } + + //Determines if this instance of GraphicsAdapter is the default adapter. + constexpr bool IsDefaultAdapter() const { return isDefault; } + + //Determines if the graphics adapter is in widescreen mode. + inline bool IsWideScreen() const { + return currentDisplayMode->AspectRatio() > 1.6000000238418579; + } + + //Retrieves the handle of the monitor + constexpr intptr_t MonitorHandle() const { return monitorHandle; } + + //Retrieves a value used to help identify the revision level of a particular chip set. + constexpr Uint Revision() const { return revision; } + + //Retrieves a value used to identify the subsystem. + constexpr Uint SubSystemId() const { return subSystemId; } + + //Returns a collection of supported display modes for the current adapter. + inline sptr SupportedDisplayModes() const { return supportedDisplayModes; } + + //Retrieves a value used to identify the manufacturer. + constexpr Uint VendorId() const { return vendorId; } + + //Gets or sets a NULL device. + static bool UseNullDevice() { return useNullDevice; } + //Gets or sets a NULL device. + static void UseNullDevice(bool value) { useNullDevice = value; } + + //Gets or sets a reference device. + constexpr static bool UseReferenceDevice() { return useReferenceDevice; } + //Gets or sets a reference device. + constexpr static void UseReferenceDevice(bool value) { useReferenceDevice = value; } + + //Tests to see if the adapter supports the requested profile. + bool IsProfileSupported(GraphicsProfile graphicsProfile) { + return true; + } + + //Queries the adapter for support for the requested back buffer format. + bool QueryBackBufferFormat( + GraphicsProfile graphicsProfile, + SurfaceFormat format, + DepthFormat depthFormat, + Int multiSampleCount, + SurfaceFormat& selectedFormat, + DepthFormat& selectedDepthFormat, + Int& selectedMultiSampleCount + ) const; + + private: + String description; + Uint deviceId{0}; + String deviceName; + bool isDefault{ false }; + intptr_t monitorHandle{ 0 }; + Uint revision{ 0 }; + Uint subSystemId{ 0 }; + Uint vendorId{ 0 }; + sptr currentDisplayMode{ nullptr }; + sptr supportedDisplayModes{ nullptr }; + + inline static bool useNullDevice = false; + inline static bool useReferenceDevice = false; + + GraphicsAdapter(); public: struct PlatformImplementation; diff --git a/inc/xna/graphics/device.hpp b/inc/xna/graphics/device.hpp index 1d78173..6ce3e31 100644 --- a/inc/xna/graphics/device.hpp +++ b/inc/xna/graphics/device.hpp @@ -2,6 +2,7 @@ #define XNA_GRAPHICS_DEVICE_HPP #include "../default.hpp" +#include "presentparams.hpp" namespace xna { //Performs primitive-based rendering, creates resources, handles system-level variables, adjusts gamma ramp levels, and creates shaders. @@ -9,6 +10,7 @@ namespace xna { public: GraphicsDevice(); GraphicsDevice(GraphicsDeviceInformation const& info); + GraphicsDevice(sptr const& adapter, GraphicsProfile const& graphicsProfile, sptr const& presentationParameters); //Gets the graphics adapter. sptr Adapter() const; @@ -32,13 +34,23 @@ namespace xna { Int MultiSampleMask() const; //Gets or sets a bitmask controlling modification of the samples in a multisample render target. The default value is -1 (0xffffffff). void MultiSampleMask(Int value); + + constexpr GraphicsProfile Profile() const { + return GraphicsProfile::HiDef; + } + constexpr PresentationParameters PresentParameters() const { + return PresentationParameters(); + } + void Clear(Color const& color); void Clear(ClearOptions options, Color const& color, float depth, Int stencil); void Clear(ClearOptions options, Vector4 const& color, float depth, Int stencil); bool Initialize(); bool Present(); + void Reset(sptr const& presentationParameters, sptr const& graphicsAdapter); + xna::Viewport Viewport() const; void Viewport(xna::Viewport const& viewport); void UseVSync(bool use); diff --git a/inc/xna/graphics/displaymode.hpp b/inc/xna/graphics/displaymode.hpp index 8861a7f..a5422d9 100644 --- a/inc/xna/graphics/displaymode.hpp +++ b/inc/xna/graphics/displaymode.hpp @@ -2,40 +2,82 @@ #define XNA_GRAPHICS_DISPLAYMODE_HPP #include "../default.hpp" +#include "../common/numerics.hpp" namespace xna { - struct DisplayModeDescription; + //Flags indicating the method the raster uses to create an image on a surface + enum class DisplayModeScanlineOrder { + Unspecified = 0, + Progressive = 1, + UpperFieldFirst = 2, + LowerFieldFirst = 3 + }; + + //Flags indicating how an image is stretched to fit a given monitor's resolution + enum class DisplayModeScaling { + Unspecified = 0, + Centered = 1, + Stretched = 2 + }; + + struct DisplayModeRate { + constexpr DisplayModeRate() = default; + + constexpr DisplayModeRate(DisplayModeScanlineOrder scanlineOrdering, DisplayModeScaling scaling, RationalNumber refreshRate, bool stereo) : + ScanlineOrdering(scanlineOrdering), Scaling(scaling), RefreshRate(refreshRate), Stereo(stereo){} + + constexpr bool operator==(const DisplayModeRate& other) const { + return ScanlineOrdering == other.ScanlineOrdering && Scaling == other.Scaling && RefreshRate == other.RefreshRate; + } + + //Gets the method the raster uses to create an image on a surface + DisplayModeScanlineOrder ScanlineOrdering{ DisplayModeScanlineOrder::Unspecified }; + //Gets how an image is stretched to fit a given monitor's resolution + DisplayModeScaling Scaling{ DisplayModeScaling::Unspecified }; + //Describing the refresh rate in hertz. + RationalNumber RefreshRate{}; + //Specifies whether the full-screen display mode is stereo. TRUE if stereo; otherwise, FALSE. + bool Stereo{ false }; + }; //Describes the display mode. class DisplayMode { public: - DisplayMode(); + constexpr DisplayMode(); + + constexpr DisplayMode(Int width, Int height, SurfaceFormat format): + width(width), height(height), format(format){} //Gets the aspect ratio used by the graphics device. constexpr float AspectRatio() const { - if (Height == 0 || Width == 0) + if (height == 0 || width == 0) return 0; - return static_cast(Width) / static_cast(Height); + return static_cast(width) / static_cast(height); } + //Gets a value indicating the screen width, in pixels. + constexpr Int Width() const { return width; } + //Gets a value indicating the screen height, in pixels. + constexpr Int Height() const { return height; } + //Gets a value indicating the surface format of the display mode. + constexpr SurfaceFormat Format() const { return format; } + constexpr bool operator==(const DisplayMode& other) const { - return Width == other.Width - && Height == other.Height - && Format == other.Format; + return width == other.width + && height == other.height + && format == other.format; } - public: - //Gets a value indicating the screen width, in pixels. - Int Width{ 0 }; - //Gets a value indicating the screen height, in pixels. - Int Height{ 0 }; - //Gets a value indicating the surface format of the display mode. - SurfaceFormat Format{ SurfaceFormat::Color }; + private: + friend class GraphicsAdapter; + Int width{ 0 }; + Int height{ 0 }; + SurfaceFormat format{ SurfaceFormat::Color }; + public: - struct PlatformImplementation; - uptr impl; + std::vector Rates; }; //Manipulates a collection of DisplayMode structures. @@ -53,6 +95,10 @@ namespace xna { std::vector> Query(SurfaceFormat format) const; sptr Query(SurfaceFormat format, Uint width, Uint height) const; + constexpr size_t Count() const { + return DisplayModes.size(); + } + public: std::vector> DisplayModes; }; diff --git a/inc/xna/graphics/presentparams.hpp b/inc/xna/graphics/presentparams.hpp index 774fd97..2306f12 100644 --- a/inc/xna/graphics/presentparams.hpp +++ b/inc/xna/graphics/presentparams.hpp @@ -7,12 +7,15 @@ namespace xna { struct PresentationParameters { constexpr PresentationParameters() = default; - Uint BackBufferWidth{ 0 }; - Uint BackBufferHeight{ 0 }; + Int BackBufferWidth{ 0 }; + Int BackBufferHeight{ 0 }; SurfaceFormat BackBufferFormat{ SurfaceFormat::Color }; SwapEffect PresentationSwapEffect{ SwapEffect::FlipDiscard }; intptr_t DeviceWindowHandle{ 0 }; - bool Fullscreen{ false }; + bool IsFullscreen{ false }; + Int MultiSampleCount{ 0 }; + PresentInterval PresentationInterval{ PresentInterval::Default }; + DepthFormat DepthStencilFormat{ DepthFormat::None }; }; } diff --git a/inc/xna/graphics/sprite.hpp b/inc/xna/graphics/sprite.hpp index f25cf66..90a2964 100644 --- a/inc/xna/graphics/sprite.hpp +++ b/inc/xna/graphics/sprite.hpp @@ -154,7 +154,7 @@ namespace xna { //Gets or sets the vertical distance (in pixels) between the base lines of two consecutive lines of text Int LineSpacing() const; //Gets or sets the vertical distance (in pixels) between the base lines of two consecutive lines of text - void LineSpacing(Int value); + void LineSpacing(float value); public: struct PlatformImplementation; diff --git a/inc/xna/xna-dx.hpp b/inc/xna/xna-dx.hpp index a3bf2f3..da05180 100644 --- a/inc/xna/xna-dx.hpp +++ b/inc/xna/xna-dx.hpp @@ -1,5 +1,5 @@ -#ifndef XNA_XNA_DX_HPP -#define XNA_XNA_DX_HPP +#ifndef XNA_XNADX_HPP +#define XNA_XNADX_HPP #define NOMINMAX @@ -64,6 +64,28 @@ namespace xna { //---------------- HELPERS ----------------// struct DxHelpers { + static constexpr RECT RectangleToDx(Rectangle const& value) { + RECT rect{}; + rect.top = value.Top(); + rect.left = value.Left(); + rect.right = value.Right(); + rect.bottom = value.Bottom(); + + return rect; + } + + static constexpr D3D11_VIEWPORT ViewportToDx(Viewport const& value) { + D3D11_VIEWPORT _view{}; + _view.TopLeftX = value.X; + _view.TopLeftY = value.Y; + _view.Width = value.Width; + _view.Height = value.Height; + _view.MinDepth = value.MinDetph; + _view.MaxDepth = value.MaxDepth; + + return _view; + } + static constexpr DirectX::XMVECTOR VectorToDx(Vector2 const& value) { DirectX::XMVECTOR v{}; @@ -73,7 +95,6 @@ namespace xna { return v; } - static constexpr DirectX::XMVECTOR VectorToDx(Vector3 const& value) { DirectX::XMVECTOR v{}; @@ -128,7 +149,6 @@ namespace xna { return m; } - static constexpr DirectX::SpriteSortMode SpriteSortToDx(SpriteSortMode value) { return static_cast(static_cast(value)); } @@ -342,7 +362,8 @@ namespace xna { static constexpr TextureAddressMode TextureAddresModeToXna(D3D11_TEXTURE_ADDRESS_MODE value) { return static_cast(value - 1); - } + } + }; struct PlatformInit { @@ -560,25 +581,18 @@ namespace xna { //---------------- IMPLEMENTATIONS ----------------// struct SpriteFont::PlatformImplementation { - uptr _dxSpriteFont{ nullptr }; + uptr dxSpriteFont{ nullptr }; }; struct SpriteBatch::PlatformImplementation { - sptr _dxspriteBatch = nullptr; + sptr dxSpriteBatch = nullptr; comptr dxInputLayout = nullptr; - sptr effectBuffer = nullptr; + sptr dxEffectBuffer = nullptr; }; struct GraphicsAdapter::PlatformImplementation { - comptr dxadapter = nullptr; - - private: - friend class GraphicsAdapter; - Uint _index{ 0 }; - sptr _currentDisplayMode = nullptr; - - public: - bool GetOutput(UINT slot, IDXGIOutput*& output); + comptr dxAdapter = nullptr; + comptr dxFactory = nullptr; }; struct BlendRenderTarget { @@ -606,40 +620,6 @@ namespace xna { D3D11_DEPTH_STENCIL_DESC dxDescription{}; }; - struct DisplayModeRefreshRate { - constexpr DisplayModeRefreshRate() = default; - - constexpr DisplayModeRefreshRate(DXGI_RATIONAL const& dxrational) { - Numerator = dxrational.Numerator; - Denominator = dxrational.Denominator; - } - constexpr DisplayModeRefreshRate(Uint numerator, Uint denominator) - : Numerator(numerator), Denominator(denominator) {} - - Uint Numerator{ 0 }; - Uint Denominator{ 0 }; - - constexpr bool operator==(const DisplayModeRefreshRate& other) const - { - return Numerator == other.Numerator && Denominator == other.Denominator; - } - }; - - struct DisplayModeDescription { - DisplayModeScanlineOrder _scanlineOrdering{ DisplayModeScanlineOrder::Unspecified }; - DisplayModeScaling _scaling{ DisplayModeScaling::Unspecified }; - DisplayModeRefreshRate _refreshRate{}; - - constexpr bool operator==(const DisplayModeDescription& other) const - { - return _scanlineOrdering == other._scanlineOrdering && _scaling == other._scaling && _refreshRate == other._refreshRate; - } - }; - - struct DisplayMode::PlatformImplementation { - std::vector Descriptions; - }; - struct GamePad::PlatformImplementation { uptr _dxGamePad = unew(); @@ -718,6 +698,8 @@ namespace xna { struct GameWindow::PlatformImplementation { public: + PlatformImplementation(GameWindow* gameWindow): gameWindow(gameWindow){} + constexpr void Mode(GameWindowMode mode) { _windowStyle = static_cast(mode); } @@ -787,7 +769,7 @@ namespace xna { constexpr void Color(BYTE r, BYTE g, BYTE b) { _windowColor = RGB(r, g, b); - } + } bool Create(); bool Update(); @@ -796,6 +778,7 @@ namespace xna { private: friend class GameWindow; + GameWindow* gameWindow = nullptr; HINSTANCE _hInstance{ nullptr }; HWND _windowHandle{ nullptr }; @@ -862,10 +845,22 @@ namespace xna { sptr _swapChain = nullptr; sptr _adapter = nullptr; sptr _renderTarget2D = nullptr; - sptr _gameWindow = nullptr; + intptr_t windowHandle{ 0 }; xna::Viewport _viewport{}; sptr _presentationParameters; - D3D_FEATURE_LEVEL _featureLevel{ D3D_FEATURE_LEVEL::D3D_FEATURE_LEVEL_11_0 }; + + D3D_FEATURE_LEVEL featureLevels[7] = + { + D3D_FEATURE_LEVEL_11_1, + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, + D3D_FEATURE_LEVEL_9_3, + D3D_FEATURE_LEVEL_9_2, + D3D_FEATURE_LEVEL_9_1, + }; + + D3D_FEATURE_LEVEL currentFeatureLevel{ D3D_FEATURE_LEVEL_11_1 }; private: friend class GraphicsDevice; diff --git a/inc/xna/xna.hpp b/inc/xna/xna.hpp index 427eb79..fd43a6f 100644 --- a/inc/xna/xna.hpp +++ b/inc/xna/xna.hpp @@ -23,6 +23,8 @@ #include "csharp/stream.hpp" #include "csharp/timespan.hpp" #include "csharp/type.hpp" +#include "csharp/screen.hpp" +#include "csharp/eventhandler.hpp" #include "exception.hpp" #include "game/component.hpp" #include "game/game.hpp" diff --git a/samples/01_blank/xna.cpp b/samples/01_blank/xna.cpp index dc97e81..ae50f89 100644 --- a/samples/01_blank/xna.cpp +++ b/samples/01_blank/xna.cpp @@ -16,8 +16,9 @@ namespace xna { void Initialize() override { auto game = reinterpret_cast(this); - graphics = snew(game->shared_from_this()); - graphics->Initialize(); + graphics = snew(game->shared_from_this()); + //graphics->Initialize(); + graphics->ApplyChanges(); std::any device = graphicsDevice; services->AddService(*typeof(), device); @@ -45,7 +46,7 @@ namespace xna { private: sptr graphics = nullptr; sptr spriteBatch = nullptr; - sptr texture = nullptr; + sptr texture = nullptr; }; } diff --git a/samples/02_PlatfformerStarterKit/circle.hpp b/samples/02_PlatfformerStarterKit/circle.hpp index 8fbc889..a04dd8d 100644 --- a/samples/02_PlatfformerStarterKit/circle.hpp +++ b/samples/02_PlatfformerStarterKit/circle.hpp @@ -14,8 +14,9 @@ namespace PlatformerStarterKit { Center(position), Radius(radius){} constexpr bool Intersects(xna::Rectangle const& rectangle) const { - const auto v = xna::Vector2(xna::MathHelper::Clamp(Center.X, rectangle.Left(), rectangle.Right()), - xna::MathHelper::Clamp(Center.Y, rectangle.Top(), rectangle.Bottom())); + const auto v = + xna::Vector2(xna::MathHelper::Clamp(Center.X, static_cast(rectangle.Left()), static_cast(rectangle.Right())), + xna::MathHelper::Clamp(Center.Y, static_cast(rectangle.Top()), static_cast(rectangle.Bottom()))); const auto direction = Center - v; auto distanceSquared = direction.LengthSquared(); diff --git a/samples/02_PlatfformerStarterKit/game.cpp b/samples/02_PlatfformerStarterKit/game.cpp index 958688f..cd3d5fd 100644 --- a/samples/02_PlatfformerStarterKit/game.cpp +++ b/samples/02_PlatfformerStarterKit/game.cpp @@ -22,7 +22,7 @@ namespace PlatformerStarterKit { void Initialize() override { auto game = reinterpret_cast(this); graphics = snew(game->shared_from_this()); - graphics->Initialize(); + graphics->ApplyChanges(); std::any device = graphicsDevice; services->AddService(*typeof(), device);