From 2ef604c32e0ffca464a60463112ed56f4f51f96e Mon Sep 17 00:00:00 2001 From: johndoe6345789 Date: Tue, 6 Jan 2026 21:53:52 +0000 Subject: [PATCH] Add platform service enhancements and logging capabilities - Introduced IPlatformService interface with methods for retrieving platform information, current video driver, and available video/render drivers. - Implemented PlatformService to gather and log detailed system information, including CPU capabilities, environment variables, and SDL video driver support. - Updated BgfxGraphicsBackend to utilize IPlatformService for platform-specific data. - Enhanced SdlWindowService to log system information upon window creation. - Added utility functions for string formatting and feature value retrieval. --- src/app/service_based_app.cpp | 1 + src/services/impl/bgfx_graphics_backend.cpp | 351 ++++++++- src/services/impl/bgfx_graphics_backend.hpp | 17 + src/services/impl/platform_service.cpp | 735 ++++++++++++++++++ src/services/impl/platform_service.hpp | 5 + src/services/impl/sdl_window_service.cpp | 4 + .../interfaces/i_platform_service.hpp | 6 + 7 files changed, 1099 insertions(+), 20 deletions(-) diff --git a/src/app/service_based_app.cpp b/src/app/service_based_app.cpp index 50453b0..fbcc03b 100644 --- a/src/app/service_based_app.cpp +++ b/src/app/service_based_app.cpp @@ -271,6 +271,7 @@ void ServiceBasedApp::RegisterServices() { auto graphicsBackend = std::make_shared( registry_.GetService(), + registry_.GetService(), registry_.GetService()); // Graphics service (facade) diff --git a/src/services/impl/bgfx_graphics_backend.cpp b/src/services/impl/bgfx_graphics_backend.cpp index e65e2fe..d87beb2 100644 --- a/src/services/impl/bgfx_graphics_backend.cpp +++ b/src/services/impl/bgfx_graphics_backend.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -54,15 +55,41 @@ void SetUniformIfValid(bgfx::UniformHandle handle, const void* data, uint16_t co } } -bgfx::RendererType::Enum RendererFromString(const std::string& value) { +bool TryParseRendererType(const std::string& value, bgfx::RendererType::Enum& out) { const std::string lower = ToLower(value); - if (lower == "vulkan") { - return bgfx::RendererType::Vulkan; - } if (lower == "auto") { - return bgfx::RendererType::Count; + out = bgfx::RendererType::Count; + return true; } - return bgfx::RendererType::Vulkan; + if (lower == "vulkan") { + out = bgfx::RendererType::Vulkan; + return true; + } + if (lower == "opengl") { + out = bgfx::RendererType::OpenGL; + return true; + } + if (lower == "opengles" || lower == "opengles2") { + out = bgfx::RendererType::OpenGLES; + return true; + } + if (lower == "direct3d11" || lower == "d3d11") { + out = bgfx::RendererType::Direct3D11; + return true; + } + if (lower == "direct3d12" || lower == "d3d12") { + out = bgfx::RendererType::Direct3D12; + return true; + } + if (lower == "metal") { + out = bgfx::RendererType::Metal; + return true; + } + if (lower == "noop") { + out = bgfx::RendererType::Noop; + return true; + } + return false; } std::string RendererTypeName(bgfx::RendererType::Enum type) { @@ -100,15 +127,148 @@ std::string JoinRendererNames(const std::vector& rende return result; } +const char* HandleTypeName(bgfx::NativeWindowHandleType::Enum type) { + switch (type) { + case bgfx::NativeWindowHandleType::Default: + return "default"; + case bgfx::NativeWindowHandleType::Wayland: + return "wayland"; + case bgfx::NativeWindowHandleType::Count: + return "count"; + default: + return "unknown"; + } +} + +const char* RendererConfigName(bgfx::RendererType::Enum type) { + switch (type) { + case bgfx::RendererType::Vulkan: + return "vulkan"; + case bgfx::RendererType::OpenGL: + return "opengl"; + case bgfx::RendererType::OpenGLES: + return "opengles"; + case bgfx::RendererType::Direct3D11: + return "direct3d11"; + case bgfx::RendererType::Direct3D12: + return "direct3d12"; + case bgfx::RendererType::Metal: + return "metal"; + case bgfx::RendererType::Noop: + return "noop"; + case bgfx::RendererType::Count: + default: + return "auto"; + } +} + +bool IsNoopRenderer(bgfx::RendererType::Enum type) { + return type == bgfx::RendererType::Noop; +} + +bool ContainsRenderer(const std::vector& renderers, + bgfx::RendererType::Enum type) { + return std::find(renderers.begin(), renderers.end(), type) != renderers.end(); +} + +bool IsRendererAllowedOnPlatform(bgfx::RendererType::Enum type, const std::string& platformName) { + if (type == bgfx::RendererType::Count || type == bgfx::RendererType::Noop) { + return true; + } + const std::string platformLower = ToLower(platformName); + if (platformLower.find("windows") != std::string::npos) { + return type == bgfx::RendererType::Direct3D11 || + type == bgfx::RendererType::Direct3D12 || + type == bgfx::RendererType::Vulkan || + type == bgfx::RendererType::OpenGL || + type == bgfx::RendererType::OpenGLES; + } + if (platformLower.find("mac") != std::string::npos || + platformLower.find("darwin") != std::string::npos) { + return type == bgfx::RendererType::Metal || + type == bgfx::RendererType::OpenGL || + type == bgfx::RendererType::Vulkan; + } + return type == bgfx::RendererType::Vulkan || + type == bgfx::RendererType::OpenGL || + type == bgfx::RendererType::OpenGLES; +} + +void AddRendererIfSupported(std::vector& ordered, + const std::vector& supported, + bgfx::RendererType::Enum type) { + if (IsNoopRenderer(type) || type == bgfx::RendererType::Count) { + return; + } + if (!ContainsRenderer(supported, type)) { + return; + } + if (!ContainsRenderer(ordered, type)) { + ordered.push_back(type); + } +} + +std::vector BuildPreferredRenderers( + const std::vector& supportedRenderers, + const std::string& platformName, + const std::string& videoDriverName) { + std::vector preferred; + const std::string platformLower = ToLower(platformName); + const std::string videoLower = ToLower(videoDriverName); + + if (platformLower.find("windows") != std::string::npos) { + AddRendererIfSupported(preferred, supportedRenderers, bgfx::RendererType::Direct3D12); + AddRendererIfSupported(preferred, supportedRenderers, bgfx::RendererType::Direct3D11); + AddRendererIfSupported(preferred, supportedRenderers, bgfx::RendererType::Vulkan); + AddRendererIfSupported(preferred, supportedRenderers, bgfx::RendererType::OpenGL); + } else if (platformLower.find("mac") != std::string::npos || + platformLower.find("darwin") != std::string::npos) { + AddRendererIfSupported(preferred, supportedRenderers, bgfx::RendererType::Metal); + AddRendererIfSupported(preferred, supportedRenderers, bgfx::RendererType::OpenGL); + AddRendererIfSupported(preferred, supportedRenderers, bgfx::RendererType::Vulkan); + } else { + const bool waylandOrX11 = (videoLower == "wayland") || (videoLower == "x11"); + const bool kmsdrm = (videoLower == "kmsdrm"); + if (waylandOrX11 || kmsdrm) { + AddRendererIfSupported(preferred, supportedRenderers, bgfx::RendererType::Vulkan); + AddRendererIfSupported(preferred, supportedRenderers, bgfx::RendererType::OpenGL); + AddRendererIfSupported(preferred, supportedRenderers, bgfx::RendererType::OpenGLES); + } else { + AddRendererIfSupported(preferred, supportedRenderers, bgfx::RendererType::Vulkan); + AddRendererIfSupported(preferred, supportedRenderers, bgfx::RendererType::OpenGL); + AddRendererIfSupported(preferred, supportedRenderers, bgfx::RendererType::OpenGLES); + } + } + + return preferred; +} + +std::optional RecommendFallbackRenderer( + bgfx::RendererType::Enum requested, + const std::vector& supportedRenderers, + const std::string& platformName, + const std::string& videoDriverName) { + const auto preferred = BuildPreferredRenderers(supportedRenderers, platformName, videoDriverName); + for (bgfx::RendererType::Enum type : preferred) { + if (type != requested) { + return type; + } + } + return std::nullopt; +} + } // namespace BgfxGraphicsBackend::BgfxGraphicsBackend(std::shared_ptr configService, + std::shared_ptr platformService, std::shared_ptr logger) : configService_(std::move(configService)), + platformService_(std::move(platformService)), logger_(std::move(logger)) { if (logger_) { logger_->Trace("BgfxGraphicsBackend", "BgfxGraphicsBackend", - "configService=" + std::string(configService_ ? "set" : "null")); + "configService=" + std::string(configService_ ? "set" : "null") + + ", platformService=" + std::string(platformService_ ? "set" : "null")); } vertexLayout_.begin() .add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float) @@ -139,8 +299,15 @@ BgfxGraphicsBackend::~BgfxGraphicsBackend() { void BgfxGraphicsBackend::SetupPlatformData(void* window) { bgfx::PlatformData pd{}; + platformHandleInfo_ = PlatformHandleInfo{}; + platformHandleInfo_.handleType = bgfx::NativeWindowHandleType::Default; SDL_Window* sdlWindow = static_cast(window); if (!sdlWindow) { + if (logger_) { + logger_->Trace("BgfxGraphicsBackend", "SetupPlatformData", "windowIsNull=true"); + } + platformHandleInfo_.hasWindowHandle = false; + platformHandleInfo_.hasDisplayHandle = false; bgfx::setPlatformData(pd); return; } @@ -153,20 +320,45 @@ void BgfxGraphicsBackend::SetupPlatformData(void* window) { #elif defined(__linux__) void* wlDisplay = SDL_GetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_DISPLAY_POINTER, nullptr); void* wlSurface = SDL_GetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, nullptr); - if (wlDisplay && wlSurface) { + void* x11Display = SDL_GetPointerProperty(props, SDL_PROP_WINDOW_X11_DISPLAY_POINTER, nullptr); + Sint64 x11Window = SDL_GetNumberProperty(props, SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0); + const bool hasWayland = wlDisplay && wlSurface; + const bool hasX11 = x11Display && x11Window != 0; + platformHandleInfo_.hasWayland = hasWayland; + platformHandleInfo_.hasX11 = hasX11; + if (logger_) { + logger_->Trace("BgfxGraphicsBackend", "SetupPlatformData", + "waylandAvailable=" + std::string(hasWayland ? "true" : "false") + + ", x11Available=" + std::string(hasX11 ? "true" : "false")); + } + if (hasWayland) { pd.ndt = wlDisplay; pd.nwh = wlSurface; - } else { - void* x11Display = SDL_GetPointerProperty(props, SDL_PROP_WINDOW_X11_DISPLAY_POINTER, nullptr); - Sint64 x11Window = SDL_GetNumberProperty(props, SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0); - if (x11Display && x11Window != 0) { - pd.ndt = x11Display; - pd.nwh = reinterpret_cast(static_cast(x11Window)); + pd.type = bgfx::NativeWindowHandleType::Wayland; + platformHandleInfo_.handleType = bgfx::NativeWindowHandleType::Wayland; + if (logger_) { + logger_->Trace("BgfxGraphicsBackend", "SetupPlatformData", "selectedHandleType=Wayland"); + } + } else if (hasX11) { + pd.ndt = x11Display; + pd.nwh = reinterpret_cast(static_cast(x11Window)); + pd.type = bgfx::NativeWindowHandleType::Default; + platformHandleInfo_.handleType = bgfx::NativeWindowHandleType::Default; + if (logger_) { + logger_->Trace("BgfxGraphicsBackend", "SetupPlatformData", "selectedHandleType=X11"); } } #else pd.nwh = SDL_GetPointerProperty(props, SDL_PROP_WINDOW_WIN32_HWND_POINTER, nullptr); #endif + platformHandleInfo_.hasWindowHandle = pd.nwh != nullptr; + platformHandleInfo_.hasDisplayHandle = pd.ndt != nullptr; + if (logger_) { + logger_->Trace("BgfxGraphicsBackend", "SetupPlatformData", + "nwh=" + std::to_string(reinterpret_cast(pd.nwh)) + + ", ndt=" + std::to_string(reinterpret_cast(pd.ndt)) + + ", handleType=" + std::string(HandleTypeName(platformHandleInfo_.handleType))); + } bgfx::setPlatformData(pd); } @@ -175,7 +367,67 @@ bgfx::RendererType::Enum BgfxGraphicsBackend::ResolveRendererType() const { return bgfx::RendererType::Vulkan; } const auto& config = configService_->GetBgfxConfig(); - return RendererFromString(config.renderer); + bgfx::RendererType::Enum resolved = bgfx::RendererType::Vulkan; + const bool parsed = TryParseRendererType(config.renderer, resolved); + if (logger_) { + logger_->Trace("BgfxGraphicsBackend", "ResolveRendererType", + "renderer=" + config.renderer + + ", resolved=" + RendererTypeName(resolved) + + ", parsed=" + std::string(parsed ? "true" : "false")); + } + if (!parsed && logger_) { + logger_->Warn("BgfxGraphicsBackend::ResolveRendererType: Unknown renderer '" + + config.renderer + "', defaulting to Vulkan"); + } + return resolved; +} + +void BgfxGraphicsBackend::LogRendererFailureDetails( + bgfx::RendererType::Enum renderer, + const std::vector& supportedRenderers, + const std::string& platformName, + const std::string& videoDriverName) { + if (!logger_) { + return; + } + + logger_->Warn("BgfxGraphicsBackend::Initialize: Renderer " + + RendererTypeName(renderer) + " failed (platform=" + + platformName + ", videoDriver=" + videoDriverName + + ", handleType=" + + std::string(HandleTypeName(platformHandleInfo_.handleType)) + + ", windowHandle=" + + std::string(platformHandleInfo_.hasWindowHandle ? "set" : "null") + + ", displayHandle=" + + std::string(platformHandleInfo_.hasDisplayHandle ? "set" : "null") + + ", supportedRenderers=" + JoinRendererNames(supportedRenderers) + ")"); + + const auto fallback = RecommendFallbackRenderer(renderer, supportedRenderers, + platformName, videoDriverName); + if (fallback.has_value()) { + logger_->Warn("BgfxGraphicsBackend::Initialize: Recommended fallback renderer=" + + RendererTypeName(fallback.value()) + + " (set bgfx.renderer=" + std::string(RendererConfigName(fallback.value())) + ")"); + } + + if (renderer == bgfx::RendererType::Vulkan) { + if (!platformHandleInfo_.hasWindowHandle) { + logger_->Warn("BgfxGraphicsBackend::Initialize: Vulkan requires a native window handle"); + } + if (videoDriverName == "wayland" && !platformHandleInfo_.hasWayland) { + logger_->Warn("BgfxGraphicsBackend::Initialize: SDL reports Wayland, but no Wayland " + "window handle was provided"); + } + if (videoDriverName == "x11" && !platformHandleInfo_.hasX11) { + logger_->Warn("BgfxGraphicsBackend::Initialize: SDL reports X11, but no X11 " + "window handle was provided"); + } + } + + if (platformService_ && !loggedInitFailureDiagnostics_) { + platformService_->LogSystemInfo(); + loggedInitFailureDiagnostics_ = true; + } } void BgfxGraphicsBackend::Initialize(void* window, const GraphicsConfig& config) { @@ -200,10 +452,32 @@ void BgfxGraphicsBackend::Initialize(void* window, const GraphicsConfig& config) const auto requestedRenderer = ResolveRendererType(); const auto supportedRenderers = GetSupportedRenderers(); + const std::string platformName = platformService_ + ? platformService_->GetPlatformName() + : "unknown"; + const std::string videoDriverName = platformService_ + ? platformService_->GetCurrentVideoDriverName() + : "unknown"; if (logger_) { logger_->Trace("BgfxGraphicsBackend", "Initialize", "requestedRenderer=" + RendererTypeName(requestedRenderer) + - ", supportedRenderers=" + JoinRendererNames(supportedRenderers)); + ", supportedRenderers=" + JoinRendererNames(supportedRenderers) + + ", platform=" + platformName + + ", videoDriver=" + videoDriverName); + } + if (requestedRenderer != bgfx::RendererType::Count && + !ContainsRenderer(supportedRenderers, requestedRenderer) && + logger_) { + logger_->Warn("BgfxGraphicsBackend::Initialize: Requested renderer=" + + RendererTypeName(requestedRenderer) + + " is not in the supported renderers list"); + } + if (requestedRenderer != bgfx::RendererType::Count && + !IsRendererAllowedOnPlatform(requestedRenderer, platformName) && + logger_) { + logger_->Warn("BgfxGraphicsBackend::Initialize: Requested renderer=" + + RendererTypeName(requestedRenderer) + + " is not recommended for platform=" + platformName); } bgfx::Init init{}; @@ -218,17 +492,38 @@ void BgfxGraphicsBackend::Initialize(void* window, const GraphicsConfig& config) } }; - if (requestedRenderer == bgfx::RendererType::Count) { - addCandidate(bgfx::RendererType::Count); - } else { + const auto preferredRenderers = + BuildPreferredRenderers(supportedRenderers, platformName, videoDriverName); + if (logger_) { + logger_->Trace("BgfxGraphicsBackend", "Initialize", + "preferredRenderers=" + JoinRendererNames(preferredRenderers)); + } + + if (requestedRenderer != bgfx::RendererType::Count) { addCandidate(requestedRenderer); } - for (bgfx::RendererType::Enum renderer : supportedRenderers) { + for (bgfx::RendererType::Enum renderer : preferredRenderers) { addCandidate(renderer); } + for (bgfx::RendererType::Enum renderer : supportedRenderers) { + if (!IsNoopRenderer(renderer) && renderer != bgfx::RendererType::Count && + IsRendererAllowedOnPlatform(renderer, platformName)) { + addCandidate(renderer); + } + } addCandidate(bgfx::RendererType::Count); + if (ContainsRenderer(supportedRenderers, bgfx::RendererType::Noop) || + requestedRenderer == bgfx::RendererType::Noop) { + addCandidate(bgfx::RendererType::Noop); + } + if (logger_) { + logger_->Trace("BgfxGraphicsBackend", "Initialize", + "candidateRenderers=" + JoinRendererNames(candidates)); + } bool initialized = false; + bool requestedFailed = false; + const bool requestedExplicit = requestedRenderer != bgfx::RendererType::Count; for (bgfx::RendererType::Enum renderer : candidates) { init.type = renderer; if (logger_) { @@ -243,15 +538,31 @@ void BgfxGraphicsBackend::Initialize(void* window, const GraphicsConfig& config) logger_->Warn("BgfxGraphicsBackend::Initialize: bgfx init failed for renderer=" + RendererTypeName(renderer)); } + if (renderer == requestedRenderer && !requestedFailed) { + requestedFailed = true; + LogRendererFailureDetails(renderer, supportedRenderers, platformName, videoDriverName); + } } if (!initialized) { + if (platformService_ && !loggedInitFailureDiagnostics_) { + platformService_->LogSystemInfo(); + loggedInitFailureDiagnostics_ = true; + } throw std::runtime_error("Failed to initialize bgfx"); } if (logger_) { logger_->Trace("BgfxGraphicsBackend", "Initialize", "selectedRenderer=" + RendererTypeName(bgfx::getRendererType())); } + if (requestedExplicit && bgfx::getRendererType() != requestedRenderer && logger_) { + logger_->Warn("BgfxGraphicsBackend::Initialize: Requested renderer=" + + RendererTypeName(requestedRenderer) + ", using=" + + RendererTypeName(bgfx::getRendererType())); + } + if (bgfx::getRendererType() == bgfx::RendererType::Noop && logger_) { + logger_->Warn("BgfxGraphicsBackend::Initialize: Noop renderer selected; rendering disabled"); + } bgfx::setViewClear(viewId_, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x1f1f1fff, 1.0f, 0); bgfx::setDebug(BGFX_DEBUG_TEXT); diff --git a/src/services/impl/bgfx_graphics_backend.hpp b/src/services/impl/bgfx_graphics_backend.hpp index 888db09..cb1241b 100644 --- a/src/services/impl/bgfx_graphics_backend.hpp +++ b/src/services/impl/bgfx_graphics_backend.hpp @@ -3,6 +3,7 @@ #include "../interfaces/i_config_service.hpp" #include "../interfaces/i_graphics_backend.hpp" #include "../interfaces/i_logger.hpp" +#include "../interfaces/i_platform_service.hpp" #include "../../core/vertex.hpp" #include #include @@ -15,6 +16,7 @@ namespace sdl3cpp::services::impl { class BgfxGraphicsBackend : public IGraphicsBackend { public: BgfxGraphicsBackend(std::shared_ptr configService, + std::shared_ptr platformService, std::shared_ptr logger); ~BgfxGraphicsBackend() override; @@ -72,8 +74,20 @@ private: bgfx::UniformHandle viewPosition = BGFX_INVALID_HANDLE; }; + struct PlatformHandleInfo { + bool hasWayland = false; + bool hasX11 = false; + bool hasWindowHandle = false; + bool hasDisplayHandle = false; + bgfx::NativeWindowHandleType::Enum handleType = bgfx::NativeWindowHandleType::Default; + }; + void SetupPlatformData(void* window); bgfx::RendererType::Enum ResolveRendererType() const; + void LogRendererFailureDetails(bgfx::RendererType::Enum renderer, + const std::vector& supportedRenderers, + const std::string& platformName, + const std::string& videoDriverName); std::vector ReadShaderSource(const std::string& path, const std::string& source) const; bgfx::ShaderHandle CreateShader(const std::string& label, @@ -86,6 +100,7 @@ private: void DestroyBuffers(); std::shared_ptr configService_; + std::shared_ptr platformService_; std::shared_ptr logger_; bgfx::VertexLayout vertexLayout_; std::unordered_map> pipelines_; @@ -97,6 +112,8 @@ private: uint32_t viewportHeight_ = 0; bool initialized_ = false; bgfx::ViewId viewId_ = 0; + PlatformHandleInfo platformHandleInfo_{}; + bool loggedInitFailureDiagnostics_ = false; }; } // namespace sdl3cpp::services::impl diff --git a/src/services/impl/platform_service.cpp b/src/services/impl/platform_service.cpp index 2e49f71..6d2706c 100644 --- a/src/services/impl/platform_service.cpp +++ b/src/services/impl/platform_service.cpp @@ -1,13 +1,451 @@ #include "platform_service.hpp" +#include + #include +#include #include +#include #ifdef _WIN32 #include #endif +#if defined(__linux__) +#include +#endif + namespace sdl3cpp::services::impl { +namespace { + +std::string EnvValueOrUnset(const char* name) { + const char* value = std::getenv(name); + if (!value || *value == '\0') { + return "unset"; + } + return value; +} + +std::string HintValueOrUnset(const char* name) { + const char* value = SDL_GetHint(name); + if (!value || *value == '\0') { + return "unset"; + } + return value; +} + +std::string SystemThemeName(SDL_SystemTheme theme) { + switch (theme) { + case SDL_SYSTEM_THEME_LIGHT: + return "light"; + case SDL_SYSTEM_THEME_DARK: + return "dark"; + case SDL_SYSTEM_THEME_UNKNOWN: + default: + return "unknown"; + } +} + +std::string JoinStrings(const std::vector& values) { + if (values.empty()) { + return "none"; + } + std::string result; + for (size_t i = 0; i < values.size(); ++i) { + if (i > 0) { + result += ", "; + } + result += values[i]; + } + return result; +} + +bool ContainsDriver(const std::vector& drivers, const char* name) { + if (!name || *name == '\0') { + return false; + } + for (const auto& driver : drivers) { + if (driver == name) { + return true; + } + } + return false; +} + +std::string FormatBounds(const SDL_Rect& bounds) { + return std::to_string(bounds.w) + "x" + std::to_string(bounds.h) + + "+" + std::to_string(bounds.x) + "+" + std::to_string(bounds.y); +} + +enum class FeatureKey { + PointerBits, + PlatformName, + SdlVersion, + SdlVersionMajor, + SdlVersionMinor, + SdlVersionMicro, + SdlRevision, + CpuCount, + CpuCacheLineSize, + SystemRamMb, + CpuHasSse, + CpuHasSse2, + CpuHasSse3, + CpuHasSse41, + CpuHasSse42, + CpuHasAvx, + CpuHasAvx2, + CpuHasAvx512f, + CpuHasNeon, + CpuHasArmSimd, + CpuHasAltivec, + CpuHasLsx, + CpuHasLasx, + EnvXdgSessionType, + EnvWaylandDisplay, + EnvX11Display, + EnvDesktopSession, + EnvXdgCurrentDesktop, + EnvXdgRuntimeDir, + EnvSdlVideoDriver, + EnvSdlRenderDriver, + HintVideoDriver, + HintRenderDriver, + HintWaylandPreferLibdecor, + SdlVideoDriverCount, + SdlVideoDrivers, + SdlVideoInitialized, + SdlVideoBackendSupportsWayland, + SdlVideoBackendSupportsX11, + SdlVideoBackendSupportsKmsdrm, + SdlVideoBackendSupportsWindows, + SdlVideoBackendSupportsCocoa, + SdlVideoBackendIsWayland, + SdlVideoBackendIsX11, + SdlVideoBackendIsKmsdrm, + SdlVideoBackendIsWindows, + SdlVideoBackendIsCocoa, + SdlCurrentVideoDriver, + SdlSystemTheme, + SdlRenderDriverCount, + SdlRenderDrivers, + SdlRenderSupportsOpenGL, + SdlRenderSupportsOpenGLES2, + SdlRenderSupportsDirect3D11, + SdlRenderSupportsDirect3D12, + SdlRenderSupportsMetal, + SdlRenderSupportsSoftware, + SdlDisplayCount, + SdlPrimaryDisplayId, + SdlDisplaySummary, + SdlDisplayError, + UnameSysname, + UnameRelease, + UnameVersion, + UnameMachine +}; + +struct FeatureDefinition { + FeatureKey key; + const char* name; +}; + +struct FeatureValues { + int pointerBits = 0; + std::string platformName; + int sdlVersion = 0; + int sdlVersionMajor = 0; + int sdlVersionMinor = 0; + int sdlVersionMicro = 0; + std::string sdlRevision; + int cpuCount = 0; + int cpuCacheLineSize = 0; + int systemRamMb = 0; + bool cpuHasSse = false; + bool cpuHasSse2 = false; + bool cpuHasSse3 = false; + bool cpuHasSse41 = false; + bool cpuHasSse42 = false; + bool cpuHasAvx = false; + bool cpuHasAvx2 = false; + bool cpuHasAvx512f = false; + bool cpuHasNeon = false; + bool cpuHasArmSimd = false; + bool cpuHasAltivec = false; + bool cpuHasLsx = false; + bool cpuHasLasx = false; + std::string envXdgSessionType; + std::string envWaylandDisplay; + std::string envX11Display; + std::string envDesktopSession; + std::string envXdgCurrentDesktop; + std::string envXdgRuntimeDir; + std::string envSdlVideoDriver; + std::string envSdlRenderDriver; + std::string hintVideoDriver; + std::string hintRenderDriver; + std::string hintWaylandPreferLibdecor; + int sdlVideoDriverCount = 0; + std::string sdlVideoDrivers; + bool sdlVideoInitialized = false; + bool sdlVideoBackendSupportsWayland = false; + bool sdlVideoBackendSupportsX11 = false; + bool sdlVideoBackendSupportsKmsdrm = false; + bool sdlVideoBackendSupportsWindows = false; + bool sdlVideoBackendSupportsCocoa = false; + bool sdlVideoBackendIsWayland = false; + bool sdlVideoBackendIsX11 = false; + bool sdlVideoBackendIsKmsdrm = false; + bool sdlVideoBackendIsWindows = false; + bool sdlVideoBackendIsCocoa = false; + std::string sdlCurrentVideoDriver; + std::string sdlSystemTheme; + int sdlRenderDriverCount = 0; + std::string sdlRenderDrivers; + bool sdlRenderSupportsOpenGL = false; + bool sdlRenderSupportsOpenGLES2 = false; + bool sdlRenderSupportsDirect3D11 = false; + bool sdlRenderSupportsDirect3D12 = false; + bool sdlRenderSupportsMetal = false; + bool sdlRenderSupportsSoftware = false; + int sdlDisplayCount = 0; + int sdlPrimaryDisplayId = 0; + std::string sdlDisplaySummary = "none"; + std::string sdlDisplayError = "none"; + std::string unameSysname; + std::string unameRelease; + std::string unameVersion; + std::string unameMachine; +}; + +std::string BoolToString(bool value) { + return value ? "true" : "false"; +} + +std::string StringOrUnset(const std::string& value) { + if (value.empty()) { + return "unset"; + } + return value; +} + +std::string FeatureValue(FeatureKey key, const FeatureValues& values) { + switch (key) { + case FeatureKey::PointerBits: + return std::to_string(values.pointerBits); + case FeatureKey::PlatformName: + return StringOrUnset(values.platformName); + case FeatureKey::SdlVersion: + return std::to_string(values.sdlVersion); + case FeatureKey::SdlVersionMajor: + return std::to_string(values.sdlVersionMajor); + case FeatureKey::SdlVersionMinor: + return std::to_string(values.sdlVersionMinor); + case FeatureKey::SdlVersionMicro: + return std::to_string(values.sdlVersionMicro); + case FeatureKey::SdlRevision: + return StringOrUnset(values.sdlRevision); + case FeatureKey::CpuCount: + return std::to_string(values.cpuCount); + case FeatureKey::CpuCacheLineSize: + return std::to_string(values.cpuCacheLineSize); + case FeatureKey::SystemRamMb: + return std::to_string(values.systemRamMb); + case FeatureKey::CpuHasSse: + return BoolToString(values.cpuHasSse); + case FeatureKey::CpuHasSse2: + return BoolToString(values.cpuHasSse2); + case FeatureKey::CpuHasSse3: + return BoolToString(values.cpuHasSse3); + case FeatureKey::CpuHasSse41: + return BoolToString(values.cpuHasSse41); + case FeatureKey::CpuHasSse42: + return BoolToString(values.cpuHasSse42); + case FeatureKey::CpuHasAvx: + return BoolToString(values.cpuHasAvx); + case FeatureKey::CpuHasAvx2: + return BoolToString(values.cpuHasAvx2); + case FeatureKey::CpuHasAvx512f: + return BoolToString(values.cpuHasAvx512f); + case FeatureKey::CpuHasNeon: + return BoolToString(values.cpuHasNeon); + case FeatureKey::CpuHasArmSimd: + return BoolToString(values.cpuHasArmSimd); + case FeatureKey::CpuHasAltivec: + return BoolToString(values.cpuHasAltivec); + case FeatureKey::CpuHasLsx: + return BoolToString(values.cpuHasLsx); + case FeatureKey::CpuHasLasx: + return BoolToString(values.cpuHasLasx); + case FeatureKey::EnvXdgSessionType: + return StringOrUnset(values.envXdgSessionType); + case FeatureKey::EnvWaylandDisplay: + return StringOrUnset(values.envWaylandDisplay); + case FeatureKey::EnvX11Display: + return StringOrUnset(values.envX11Display); + case FeatureKey::EnvDesktopSession: + return StringOrUnset(values.envDesktopSession); + case FeatureKey::EnvXdgCurrentDesktop: + return StringOrUnset(values.envXdgCurrentDesktop); + case FeatureKey::EnvXdgRuntimeDir: + return StringOrUnset(values.envXdgRuntimeDir); + case FeatureKey::EnvSdlVideoDriver: + return StringOrUnset(values.envSdlVideoDriver); + case FeatureKey::EnvSdlRenderDriver: + return StringOrUnset(values.envSdlRenderDriver); + case FeatureKey::HintVideoDriver: + return StringOrUnset(values.hintVideoDriver); + case FeatureKey::HintRenderDriver: + return StringOrUnset(values.hintRenderDriver); + case FeatureKey::HintWaylandPreferLibdecor: + return StringOrUnset(values.hintWaylandPreferLibdecor); + case FeatureKey::SdlVideoDriverCount: + return std::to_string(values.sdlVideoDriverCount); + case FeatureKey::SdlVideoDrivers: + return StringOrUnset(values.sdlVideoDrivers); + case FeatureKey::SdlVideoInitialized: + return BoolToString(values.sdlVideoInitialized); + case FeatureKey::SdlVideoBackendSupportsWayland: + return BoolToString(values.sdlVideoBackendSupportsWayland); + case FeatureKey::SdlVideoBackendSupportsX11: + return BoolToString(values.sdlVideoBackendSupportsX11); + case FeatureKey::SdlVideoBackendSupportsKmsdrm: + return BoolToString(values.sdlVideoBackendSupportsKmsdrm); + case FeatureKey::SdlVideoBackendSupportsWindows: + return BoolToString(values.sdlVideoBackendSupportsWindows); + case FeatureKey::SdlVideoBackendSupportsCocoa: + return BoolToString(values.sdlVideoBackendSupportsCocoa); + case FeatureKey::SdlVideoBackendIsWayland: + return BoolToString(values.sdlVideoBackendIsWayland); + case FeatureKey::SdlVideoBackendIsX11: + return BoolToString(values.sdlVideoBackendIsX11); + case FeatureKey::SdlVideoBackendIsKmsdrm: + return BoolToString(values.sdlVideoBackendIsKmsdrm); + case FeatureKey::SdlVideoBackendIsWindows: + return BoolToString(values.sdlVideoBackendIsWindows); + case FeatureKey::SdlVideoBackendIsCocoa: + return BoolToString(values.sdlVideoBackendIsCocoa); + case FeatureKey::SdlCurrentVideoDriver: + return StringOrUnset(values.sdlCurrentVideoDriver); + case FeatureKey::SdlSystemTheme: + return StringOrUnset(values.sdlSystemTheme); + case FeatureKey::SdlRenderDriverCount: + return std::to_string(values.sdlRenderDriverCount); + case FeatureKey::SdlRenderDrivers: + return StringOrUnset(values.sdlRenderDrivers); + case FeatureKey::SdlRenderSupportsOpenGL: + return BoolToString(values.sdlRenderSupportsOpenGL); + case FeatureKey::SdlRenderSupportsOpenGLES2: + return BoolToString(values.sdlRenderSupportsOpenGLES2); + case FeatureKey::SdlRenderSupportsDirect3D11: + return BoolToString(values.sdlRenderSupportsDirect3D11); + case FeatureKey::SdlRenderSupportsDirect3D12: + return BoolToString(values.sdlRenderSupportsDirect3D12); + case FeatureKey::SdlRenderSupportsMetal: + return BoolToString(values.sdlRenderSupportsMetal); + case FeatureKey::SdlRenderSupportsSoftware: + return BoolToString(values.sdlRenderSupportsSoftware); + case FeatureKey::SdlDisplayCount: + return std::to_string(values.sdlDisplayCount); + case FeatureKey::SdlPrimaryDisplayId: + return std::to_string(values.sdlPrimaryDisplayId); + case FeatureKey::SdlDisplaySummary: + return StringOrUnset(values.sdlDisplaySummary); + case FeatureKey::SdlDisplayError: + return StringOrUnset(values.sdlDisplayError); + case FeatureKey::UnameSysname: + return StringOrUnset(values.unameSysname); + case FeatureKey::UnameRelease: + return StringOrUnset(values.unameRelease); + case FeatureKey::UnameVersion: + return StringOrUnset(values.unameVersion); + case FeatureKey::UnameMachine: + return StringOrUnset(values.unameMachine); + default: + return "unset"; + } +} + +std::string BuildFeatureTable(const FeatureValues& values) { + static constexpr FeatureDefinition kFeatures[] = { + {FeatureKey::PointerBits, "platform.pointerBits"}, + {FeatureKey::PlatformName, "platform.name"}, + {FeatureKey::SdlVersion, "platform.sdl.version"}, + {FeatureKey::SdlVersionMajor, "platform.sdl.version.major"}, + {FeatureKey::SdlVersionMinor, "platform.sdl.version.minor"}, + {FeatureKey::SdlVersionMicro, "platform.sdl.version.micro"}, + {FeatureKey::SdlRevision, "platform.sdl.revision"}, + {FeatureKey::CpuCount, "platform.cpu.count"}, + {FeatureKey::CpuCacheLineSize, "platform.cpu.cacheLineSize"}, + {FeatureKey::SystemRamMb, "platform.systemRamMB"}, + {FeatureKey::CpuHasSse, "platform.cpu.hasSSE"}, + {FeatureKey::CpuHasSse2, "platform.cpu.hasSSE2"}, + {FeatureKey::CpuHasSse3, "platform.cpu.hasSSE3"}, + {FeatureKey::CpuHasSse41, "platform.cpu.hasSSE41"}, + {FeatureKey::CpuHasSse42, "platform.cpu.hasSSE42"}, + {FeatureKey::CpuHasAvx, "platform.cpu.hasAVX"}, + {FeatureKey::CpuHasAvx2, "platform.cpu.hasAVX2"}, + {FeatureKey::CpuHasAvx512f, "platform.cpu.hasAVX512F"}, + {FeatureKey::CpuHasNeon, "platform.cpu.hasNEON"}, + {FeatureKey::CpuHasArmSimd, "platform.cpu.hasARMSIMD"}, + {FeatureKey::CpuHasAltivec, "platform.cpu.hasAltiVec"}, + {FeatureKey::CpuHasLsx, "platform.cpu.hasLSX"}, + {FeatureKey::CpuHasLasx, "platform.cpu.hasLASX"}, + {FeatureKey::EnvXdgSessionType, "env.xdgSessionType"}, + {FeatureKey::EnvWaylandDisplay, "env.waylandDisplay"}, + {FeatureKey::EnvX11Display, "env.x11Display"}, + {FeatureKey::EnvDesktopSession, "env.desktopSession"}, + {FeatureKey::EnvXdgCurrentDesktop, "env.xdgCurrentDesktop"}, + {FeatureKey::EnvXdgRuntimeDir, "env.xdgRuntimeDir"}, + {FeatureKey::EnvSdlVideoDriver, "env.sdlVideoDriver"}, + {FeatureKey::EnvSdlRenderDriver, "env.sdlRenderDriver"}, + {FeatureKey::HintVideoDriver, "sdl.hint.videoDriver"}, + {FeatureKey::HintRenderDriver, "sdl.hint.renderDriver"}, + {FeatureKey::HintWaylandPreferLibdecor, "sdl.hint.waylandPreferLibdecor"}, + {FeatureKey::SdlVideoDriverCount, "sdl.videoDriverCount"}, + {FeatureKey::SdlVideoDrivers, "sdl.videoDrivers"}, + {FeatureKey::SdlVideoInitialized, "sdl.videoInitialized"}, + {FeatureKey::SdlVideoBackendSupportsWayland, "sdl.videoBackend.supportsWayland"}, + {FeatureKey::SdlVideoBackendSupportsX11, "sdl.videoBackend.supportsX11"}, + {FeatureKey::SdlVideoBackendSupportsKmsdrm, "sdl.videoBackend.supportsKmsdrm"}, + {FeatureKey::SdlVideoBackendSupportsWindows, "sdl.videoBackend.supportsWindows"}, + {FeatureKey::SdlVideoBackendSupportsCocoa, "sdl.videoBackend.supportsCocoa"}, + {FeatureKey::SdlVideoBackendIsWayland, "sdl.videoBackend.isWayland"}, + {FeatureKey::SdlVideoBackendIsX11, "sdl.videoBackend.isX11"}, + {FeatureKey::SdlVideoBackendIsKmsdrm, "sdl.videoBackend.isKmsdrm"}, + {FeatureKey::SdlVideoBackendIsWindows, "sdl.videoBackend.isWindows"}, + {FeatureKey::SdlVideoBackendIsCocoa, "sdl.videoBackend.isCocoa"}, + {FeatureKey::SdlCurrentVideoDriver, "sdl.currentVideoDriver"}, + {FeatureKey::SdlSystemTheme, "sdl.systemTheme"}, + {FeatureKey::SdlRenderDriverCount, "sdl.renderDriverCount"}, + {FeatureKey::SdlRenderDrivers, "sdl.renderDrivers"}, + {FeatureKey::SdlRenderSupportsOpenGL, "sdl.render.supportsOpenGL"}, + {FeatureKey::SdlRenderSupportsOpenGLES2, "sdl.render.supportsOpenGLES2"}, + {FeatureKey::SdlRenderSupportsDirect3D11, "sdl.render.supportsDirect3D11"}, + {FeatureKey::SdlRenderSupportsDirect3D12, "sdl.render.supportsDirect3D12"}, + {FeatureKey::SdlRenderSupportsMetal, "sdl.render.supportsMetal"}, + {FeatureKey::SdlRenderSupportsSoftware, "sdl.render.supportsSoftware"}, + {FeatureKey::SdlDisplayCount, "sdl.displayCount"}, + {FeatureKey::SdlPrimaryDisplayId, "sdl.primaryDisplayId"}, + {FeatureKey::SdlDisplaySummary, "sdl.displaySummary"}, + {FeatureKey::SdlDisplayError, "sdl.displayError"}, + {FeatureKey::UnameSysname, "platform.uname.sysname"}, + {FeatureKey::UnameRelease, "platform.uname.release"}, + {FeatureKey::UnameVersion, "platform.uname.version"}, + {FeatureKey::UnameMachine, "platform.uname.machine"} + }; + + std::string table = "feature\tvalue\n"; + for (const auto& feature : kFeatures) { + table += feature.name; + table += "\t"; + table += FeatureValue(feature.key, values); + table += "\n"; + } + return table; +} + +} // namespace PlatformService::PlatformService(std::shared_ptr logger) : logger_(std::move(logger)) { @@ -84,4 +522,301 @@ std::string PlatformService::GetPlatformError() const { #endif } +std::string PlatformService::GetPlatformName() const { + if (logger_) { + logger_->Trace("PlatformService", "GetPlatformName"); + } + const char* platformName = SDL_GetPlatform(); + if (platformName && *platformName != '\0') { + return platformName; + } + return "unknown"; +} + +std::string PlatformService::GetCurrentVideoDriverName() const { + if (logger_) { + logger_->Trace("PlatformService", "GetCurrentVideoDriverName"); + } + const char* driver = SDL_GetCurrentVideoDriver(); + if (driver && *driver != '\0') { + return driver; + } + return "unknown"; +} + +std::vector PlatformService::GetAvailableVideoDrivers() const { + if (logger_) { + logger_->Trace("PlatformService", "GetAvailableVideoDrivers"); + } + const int count = SDL_GetNumVideoDrivers(); + std::vector drivers; + if (count <= 0) { + return drivers; + } + drivers.reserve(static_cast(count)); + for (int i = 0; i < count; ++i) { + const char* driver = SDL_GetVideoDriver(i); + if (driver && *driver != '\0') { + drivers.emplace_back(driver); + } + } + return drivers; +} + +std::vector PlatformService::GetAvailableRenderDrivers() const { + if (logger_) { + logger_->Trace("PlatformService", "GetAvailableRenderDrivers"); + } + const int count = SDL_GetNumRenderDrivers(); + std::vector drivers; + if (count <= 0) { + return drivers; + } + drivers.reserve(static_cast(count)); + for (int i = 0; i < count; ++i) { + const char* driver = SDL_GetRenderDriver(i); + if (driver && *driver != '\0') { + drivers.emplace_back(driver); + } + } + return drivers; +} + +void PlatformService::LogSystemInfo() const { + if (!logger_) { + return; + } + + logger_->Trace("PlatformService", "LogSystemInfo"); + FeatureValues values; + const int pointerBits = static_cast(sizeof(void*) * 8); + logger_->TraceVariable("platform.pointerBits", pointerBits); + values.pointerBits = pointerBits; + + const std::string platformName = GetPlatformName(); + values.platformName = platformName; + logger_->TraceVariable("platform.name", values.platformName); + + const int sdlVersion = SDL_GetVersion(); + logger_->TraceVariable("platform.sdl.version", sdlVersion); + values.sdlVersion = sdlVersion; + values.sdlVersionMajor = SDL_VERSIONNUM_MAJOR(sdlVersion); + values.sdlVersionMinor = SDL_VERSIONNUM_MINOR(sdlVersion); + values.sdlVersionMicro = SDL_VERSIONNUM_MICRO(sdlVersion); + + const char* revision = SDL_GetRevision(); + if (revision && *revision != '\0') { + logger_->TraceVariable("platform.sdl.revision", std::string(revision)); + values.sdlRevision = revision; + } + + const int cpuCount = SDL_GetCPUCount(); + const int cpuCacheLineSize = SDL_GetCPUCacheLineSize(); + const int systemRamMb = SDL_GetSystemRAM(); + logger_->TraceVariable("platform.cpu.count", cpuCount); + logger_->TraceVariable("platform.cpu.cacheLineSize", cpuCacheLineSize); + logger_->TraceVariable("platform.systemRamMB", systemRamMb); + values.cpuCount = cpuCount; + values.cpuCacheLineSize = cpuCacheLineSize; + values.systemRamMb = systemRamMb; + + const bool hasSse = SDL_HasSSE(); + const bool hasSse2 = SDL_HasSSE2(); + const bool hasSse3 = SDL_HasSSE3(); + const bool hasSse41 = SDL_HasSSE41(); + const bool hasSse42 = SDL_HasSSE42(); + const bool hasAvx = SDL_HasAVX(); + const bool hasAvx2 = SDL_HasAVX2(); + const bool hasAvx512f = SDL_HasAVX512F(); + const bool hasNeon = SDL_HasNEON(); + const bool hasArmSimd = SDL_HasARMSIMD(); + const bool hasAltivec = SDL_HasAltiVec(); + const bool hasLsx = SDL_HasLSX(); + const bool hasLasx = SDL_HasLASX(); + logger_->TraceVariable("platform.cpu.hasSSE", hasSse); + logger_->TraceVariable("platform.cpu.hasSSE2", hasSse2); + logger_->TraceVariable("platform.cpu.hasSSE3", hasSse3); + logger_->TraceVariable("platform.cpu.hasSSE41", hasSse41); + logger_->TraceVariable("platform.cpu.hasSSE42", hasSse42); + logger_->TraceVariable("platform.cpu.hasAVX", hasAvx); + logger_->TraceVariable("platform.cpu.hasAVX2", hasAvx2); + logger_->TraceVariable("platform.cpu.hasAVX512F", hasAvx512f); + logger_->TraceVariable("platform.cpu.hasNEON", hasNeon); + logger_->TraceVariable("platform.cpu.hasARMSIMD", hasArmSimd); + logger_->TraceVariable("platform.cpu.hasAltiVec", hasAltivec); + logger_->TraceVariable("platform.cpu.hasLSX", hasLsx); + logger_->TraceVariable("platform.cpu.hasLASX", hasLasx); + values.cpuHasSse = hasSse; + values.cpuHasSse2 = hasSse2; + values.cpuHasSse3 = hasSse3; + values.cpuHasSse41 = hasSse41; + values.cpuHasSse42 = hasSse42; + values.cpuHasAvx = hasAvx; + values.cpuHasAvx2 = hasAvx2; + values.cpuHasAvx512f = hasAvx512f; + values.cpuHasNeon = hasNeon; + values.cpuHasArmSimd = hasArmSimd; + values.cpuHasAltivec = hasAltivec; + values.cpuHasLsx = hasLsx; + values.cpuHasLasx = hasLasx; + + const std::string envSessionType = EnvValueOrUnset("XDG_SESSION_TYPE"); + const std::string envWaylandDisplay = EnvValueOrUnset("WAYLAND_DISPLAY"); + const std::string envX11Display = EnvValueOrUnset("DISPLAY"); + const std::string envDesktopSession = EnvValueOrUnset("DESKTOP_SESSION"); + const std::string envCurrentDesktop = EnvValueOrUnset("XDG_CURRENT_DESKTOP"); + const std::string envRuntimeDir = EnvValueOrUnset("XDG_RUNTIME_DIR"); + const std::string envSdlVideoDriver = EnvValueOrUnset("SDL_VIDEODRIVER"); + const std::string envSdlRenderDriver = EnvValueOrUnset("SDL_RENDER_DRIVER"); + logger_->TraceVariable("env.xdgSessionType", envSessionType); + logger_->TraceVariable("env.waylandDisplay", envWaylandDisplay); + logger_->TraceVariable("env.x11Display", envX11Display); + logger_->TraceVariable("env.desktopSession", envDesktopSession); + logger_->TraceVariable("env.xdgCurrentDesktop", envCurrentDesktop); + logger_->TraceVariable("env.xdgRuntimeDir", envRuntimeDir); + logger_->TraceVariable("env.sdlVideoDriver", envSdlVideoDriver); + logger_->TraceVariable("env.sdlRenderDriver", envSdlRenderDriver); + values.envXdgSessionType = envSessionType; + values.envWaylandDisplay = envWaylandDisplay; + values.envX11Display = envX11Display; + values.envDesktopSession = envDesktopSession; + values.envXdgCurrentDesktop = envCurrentDesktop; + values.envXdgRuntimeDir = envRuntimeDir; + values.envSdlVideoDriver = envSdlVideoDriver; + values.envSdlRenderDriver = envSdlRenderDriver; + + const std::string hintVideoDriver = HintValueOrUnset(SDL_HINT_VIDEO_DRIVER); + const std::string hintRenderDriver = HintValueOrUnset(SDL_HINT_RENDER_DRIVER); + const std::string hintWaylandLibdecor = HintValueOrUnset(SDL_HINT_VIDEO_WAYLAND_PREFER_LIBDECOR); + logger_->TraceVariable("sdl.hint.videoDriver", hintVideoDriver); + logger_->TraceVariable("sdl.hint.renderDriver", hintRenderDriver); + logger_->TraceVariable("sdl.hint.waylandPreferLibdecor", hintWaylandLibdecor); + values.hintVideoDriver = hintVideoDriver; + values.hintRenderDriver = hintRenderDriver; + values.hintWaylandPreferLibdecor = hintWaylandLibdecor; + + std::vector videoDrivers = GetAvailableVideoDrivers(); + values.sdlVideoDriverCount = static_cast(videoDrivers.size()); + logger_->TraceVariable("sdl.videoDriverCount", values.sdlVideoDriverCount); + if (!videoDrivers.empty()) { + const std::string joinedDrivers = JoinStrings(videoDrivers); + logger_->TraceVariable("sdl.videoDrivers", joinedDrivers); + values.sdlVideoDrivers = joinedDrivers; + } + values.sdlVideoBackendSupportsWayland = ContainsDriver(videoDrivers, "wayland"); + values.sdlVideoBackendSupportsX11 = ContainsDriver(videoDrivers, "x11"); + values.sdlVideoBackendSupportsKmsdrm = ContainsDriver(videoDrivers, "kmsdrm"); + values.sdlVideoBackendSupportsWindows = ContainsDriver(videoDrivers, "windows"); + values.sdlVideoBackendSupportsCocoa = ContainsDriver(videoDrivers, "cocoa"); + logger_->TraceVariable("sdl.videoBackend.supportsWayland", values.sdlVideoBackendSupportsWayland); + logger_->TraceVariable("sdl.videoBackend.supportsX11", values.sdlVideoBackendSupportsX11); + logger_->TraceVariable("sdl.videoBackend.supportsKmsdrm", values.sdlVideoBackendSupportsKmsdrm); + logger_->TraceVariable("sdl.videoBackend.supportsWindows", values.sdlVideoBackendSupportsWindows); + logger_->TraceVariable("sdl.videoBackend.supportsCocoa", values.sdlVideoBackendSupportsCocoa); + + const bool videoInitialized = (SDL_WasInit(SDL_INIT_VIDEO) & SDL_INIT_VIDEO) != 0; + logger_->TraceVariable("sdl.videoInitialized", videoInitialized); + values.sdlVideoInitialized = videoInitialized; + + const std::string currentDriverName = GetCurrentVideoDriverName(); + logger_->TraceVariable("sdl.currentVideoDriver", currentDriverName); + values.sdlCurrentVideoDriver = currentDriverName; + values.sdlVideoBackendIsWayland = currentDriverName == "wayland"; + values.sdlVideoBackendIsX11 = currentDriverName == "x11"; + values.sdlVideoBackendIsKmsdrm = currentDriverName == "kmsdrm"; + values.sdlVideoBackendIsWindows = currentDriverName == "windows"; + values.sdlVideoBackendIsCocoa = currentDriverName == "cocoa"; + logger_->TraceVariable("sdl.videoBackend.isWayland", values.sdlVideoBackendIsWayland); + logger_->TraceVariable("sdl.videoBackend.isX11", values.sdlVideoBackendIsX11); + logger_->TraceVariable("sdl.videoBackend.isKmsdrm", values.sdlVideoBackendIsKmsdrm); + logger_->TraceVariable("sdl.videoBackend.isWindows", values.sdlVideoBackendIsWindows); + logger_->TraceVariable("sdl.videoBackend.isCocoa", values.sdlVideoBackendIsCocoa); + const std::string systemTheme = SystemThemeName(SDL_GetSystemTheme()); + logger_->TraceVariable("sdl.systemTheme", systemTheme); + values.sdlSystemTheme = systemTheme; + + std::vector renderDrivers = GetAvailableRenderDrivers(); + values.sdlRenderDriverCount = static_cast(renderDrivers.size()); + logger_->TraceVariable("sdl.renderDriverCount", values.sdlRenderDriverCount); + if (!renderDrivers.empty()) { + const std::string joinedDrivers = JoinStrings(renderDrivers); + logger_->TraceVariable("sdl.renderDrivers", joinedDrivers); + values.sdlRenderDrivers = joinedDrivers; + } + values.sdlRenderSupportsOpenGL = ContainsDriver(renderDrivers, "opengl"); + values.sdlRenderSupportsOpenGLES2 = ContainsDriver(renderDrivers, "opengles2"); + values.sdlRenderSupportsDirect3D11 = ContainsDriver(renderDrivers, "direct3d11"); + values.sdlRenderSupportsDirect3D12 = ContainsDriver(renderDrivers, "direct3d12"); + values.sdlRenderSupportsMetal = ContainsDriver(renderDrivers, "metal"); + values.sdlRenderSupportsSoftware = ContainsDriver(renderDrivers, "software"); + logger_->TraceVariable("sdl.render.supportsOpenGL", values.sdlRenderSupportsOpenGL); + logger_->TraceVariable("sdl.render.supportsOpenGLES2", values.sdlRenderSupportsOpenGLES2); + logger_->TraceVariable("sdl.render.supportsDirect3D11", values.sdlRenderSupportsDirect3D11); + logger_->TraceVariable("sdl.render.supportsDirect3D12", values.sdlRenderSupportsDirect3D12); + logger_->TraceVariable("sdl.render.supportsMetal", values.sdlRenderSupportsMetal); + logger_->TraceVariable("sdl.render.supportsSoftware", values.sdlRenderSupportsSoftware); + + if (!videoInitialized) { + logger_->Info("PlatformService::FeatureTable\n" + BuildFeatureTable(values)); + return; + } + + int displayCount = 0; + SDL_DisplayID* displays = SDL_GetDisplays(&displayCount); + logger_->TraceVariable("sdl.displayCount", displayCount); + values.sdlDisplayCount = displayCount; + if (displays) { + SDL_DisplayID primaryDisplay = SDL_GetPrimaryDisplay(); + logger_->TraceVariable("sdl.primaryDisplayId", static_cast(primaryDisplay)); + values.sdlPrimaryDisplayId = static_cast(primaryDisplay); + std::string displaySummary; + for (int i = 0; i < displayCount; ++i) { + SDL_DisplayID displayId = displays[i]; + const char* name = SDL_GetDisplayName(displayId); + SDL_Rect bounds{}; + const bool hasBounds = SDL_GetDisplayBounds(displayId, &bounds); + const std::string index = std::to_string(i); + logger_->TraceVariable("sdl.display." + index + ".id", + static_cast(displayId)); + logger_->TraceVariable("sdl.display." + index + ".isPrimary", + displayId == primaryDisplay); + logger_->TraceVariable("sdl.display." + index + ".name", + name && *name != '\0' ? std::string(name) : "unknown"); + logger_->TraceVariable("sdl.display." + index + ".bounds", + hasBounds ? FormatBounds(bounds) : "unavailable"); + if (i > 0) { + displaySummary += " | "; + } + displaySummary += index; + displaySummary += ":"; + displaySummary += name && *name != '\0' ? name : "unknown"; + displaySummary += "@"; + displaySummary += hasBounds ? FormatBounds(bounds) : "unavailable"; + } + values.sdlDisplaySummary = displaySummary.empty() ? "none" : displaySummary; + SDL_free(displays); + } else { + const char* error = SDL_GetError(); + const std::string displayError = error && *error != '\0' ? std::string(error) : "unknown"; + logger_->TraceVariable("sdl.displayError", displayError); + values.sdlDisplayError = displayError; + } + +#if defined(__linux__) + struct utsname systemInfo {}; + if (uname(&systemInfo) == 0) { + logger_->TraceVariable("platform.uname.sysname", std::string(systemInfo.sysname)); + logger_->TraceVariable("platform.uname.release", std::string(systemInfo.release)); + logger_->TraceVariable("platform.uname.version", std::string(systemInfo.version)); + logger_->TraceVariable("platform.uname.machine", std::string(systemInfo.machine)); + values.unameSysname = systemInfo.sysname; + values.unameRelease = systemInfo.release; + values.unameVersion = systemInfo.version; + values.unameMachine = systemInfo.machine; + } +#endif + + logger_->Info("PlatformService::FeatureTable\n" + BuildFeatureTable(values)); +} + } // namespace sdl3cpp::services::impl diff --git a/src/services/impl/platform_service.hpp b/src/services/impl/platform_service.hpp index 6e2055b..729e115 100644 --- a/src/services/impl/platform_service.hpp +++ b/src/services/impl/platform_service.hpp @@ -13,6 +13,11 @@ public: std::optional GetUserConfigDirectory() const override; std::string GetPlatformError() const override; + std::string GetPlatformName() const override; + std::string GetCurrentVideoDriverName() const override; + std::vector GetAvailableVideoDrivers() const override; + std::vector GetAvailableRenderDrivers() const override; + void LogSystemInfo() const override; private: std::shared_ptr logger_; diff --git a/src/services/impl/sdl_window_service.cpp b/src/services/impl/sdl_window_service.cpp index 3de5cd3..efe2e16 100644 --- a/src/services/impl/sdl_window_service.cpp +++ b/src/services/impl/sdl_window_service.cpp @@ -174,6 +174,10 @@ void SdlWindowService::CreateWindow(const WindowConfig& config) { } } + if (platformService_) { + platformService_->LogSystemInfo(); + } + uint32_t flags = 0; if (config.resizable) { flags |= SDL_WINDOW_RESIZABLE; diff --git a/src/services/interfaces/i_platform_service.hpp b/src/services/interfaces/i_platform_service.hpp index f6c37ce..f8d5e5d 100644 --- a/src/services/interfaces/i_platform_service.hpp +++ b/src/services/interfaces/i_platform_service.hpp @@ -3,6 +3,7 @@ #include #include #include +#include namespace sdl3cpp::services { @@ -12,6 +13,11 @@ public: virtual std::optional GetUserConfigDirectory() const = 0; virtual std::string GetPlatformError() const = 0; + virtual std::string GetPlatformName() const = 0; + virtual std::string GetCurrentVideoDriverName() const = 0; + virtual std::vector GetAvailableVideoDrivers() const = 0; + virtual std::vector GetAvailableRenderDrivers() const = 0; + virtual void LogSystemInfo() const = 0; }; } // namespace sdl3cpp::services