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.
This commit is contained in:
2026-01-06 21:53:52 +00:00
parent c48b9cb1a4
commit 2ef604c32e
7 changed files with 1099 additions and 20 deletions

View File

@@ -271,6 +271,7 @@ void ServiceBasedApp::RegisterServices() {
auto graphicsBackend = std::make_shared<services::impl::BgfxGraphicsBackend>(
registry_.GetService<services::IConfigService>(),
registry_.GetService<services::IPlatformService>(),
registry_.GetService<services::ILogger>());
// Graphics service (facade)

View File

@@ -16,6 +16,7 @@
#include <glm/gtc/matrix_inverse.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <iterator>
#include <optional>
#include <string>
#include <stdexcept>
#include <vector>
@@ -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<bgfx::RendererType::Enum>& 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<bgfx::RendererType::Enum>& 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<bgfx::RendererType::Enum>& ordered,
const std::vector<bgfx::RendererType::Enum>& 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<bgfx::RendererType::Enum> BuildPreferredRenderers(
const std::vector<bgfx::RendererType::Enum>& supportedRenderers,
const std::string& platformName,
const std::string& videoDriverName) {
std::vector<bgfx::RendererType::Enum> 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<bgfx::RendererType::Enum> RecommendFallbackRenderer(
bgfx::RendererType::Enum requested,
const std::vector<bgfx::RendererType::Enum>& 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<IConfigService> configService,
std::shared_ptr<IPlatformService> platformService,
std::shared_ptr<ILogger> 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<SDL_Window*>(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<void*>(static_cast<uintptr_t>(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<void*>(static_cast<uintptr_t>(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<uintptr_t>(pd.nwh)) +
", ndt=" + std::to_string(reinterpret_cast<uintptr_t>(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<bgfx::RendererType::Enum>& 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);

View File

@@ -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 <bgfx/bgfx.h>
#include <array>
@@ -15,6 +16,7 @@ namespace sdl3cpp::services::impl {
class BgfxGraphicsBackend : public IGraphicsBackend {
public:
BgfxGraphicsBackend(std::shared_ptr<IConfigService> configService,
std::shared_ptr<IPlatformService> platformService,
std::shared_ptr<ILogger> 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<bgfx::RendererType::Enum>& supportedRenderers,
const std::string& platformName,
const std::string& videoDriverName);
std::vector<uint8_t> 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<IConfigService> configService_;
std::shared_ptr<IPlatformService> platformService_;
std::shared_ptr<ILogger> logger_;
bgfx::VertexLayout vertexLayout_;
std::unordered_map<GraphicsPipelineHandle, std::unique_ptr<PipelineEntry>> 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

View File

@@ -1,13 +1,451 @@
#include "platform_service.hpp"
#include <SDL3/SDL.h>
#include <cstdlib>
#include <string>
#include <utility>
#include <vector>
#ifdef _WIN32
#include <windows.h>
#endif
#if defined(__linux__)
#include <sys/utsname.h>
#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<std::string>& 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<std::string>& 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<ILogger> 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<std::string> PlatformService::GetAvailableVideoDrivers() const {
if (logger_) {
logger_->Trace("PlatformService", "GetAvailableVideoDrivers");
}
const int count = SDL_GetNumVideoDrivers();
std::vector<std::string> drivers;
if (count <= 0) {
return drivers;
}
drivers.reserve(static_cast<size_t>(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<std::string> PlatformService::GetAvailableRenderDrivers() const {
if (logger_) {
logger_->Trace("PlatformService", "GetAvailableRenderDrivers");
}
const int count = SDL_GetNumRenderDrivers();
std::vector<std::string> drivers;
if (count <= 0) {
return drivers;
}
drivers.reserve(static_cast<size_t>(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<int>(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<std::string> videoDrivers = GetAvailableVideoDrivers();
values.sdlVideoDriverCount = static_cast<int>(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<std::string> renderDrivers = GetAvailableRenderDrivers();
values.sdlRenderDriverCount = static_cast<int>(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<int>(primaryDisplay));
values.sdlPrimaryDisplayId = static_cast<int>(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<int>(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

View File

@@ -13,6 +13,11 @@ public:
std::optional<std::filesystem::path> GetUserConfigDirectory() const override;
std::string GetPlatformError() const override;
std::string GetPlatformName() const override;
std::string GetCurrentVideoDriverName() const override;
std::vector<std::string> GetAvailableVideoDrivers() const override;
std::vector<std::string> GetAvailableRenderDrivers() const override;
void LogSystemInfo() const override;
private:
std::shared_ptr<ILogger> logger_;

View File

@@ -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;

View File

@@ -3,6 +3,7 @@
#include <filesystem>
#include <optional>
#include <string>
#include <vector>
namespace sdl3cpp::services {
@@ -12,6 +13,11 @@ public:
virtual std::optional<std::filesystem::path> GetUserConfigDirectory() const = 0;
virtual std::string GetPlatformError() const = 0;
virtual std::string GetPlatformName() const = 0;
virtual std::string GetCurrentVideoDriverName() const = 0;
virtual std::vector<std::string> GetAvailableVideoDrivers() const = 0;
virtual std::vector<std::string> GetAvailableRenderDrivers() const = 0;
virtual void LogSystemInfo() const = 0;
};
} // namespace sdl3cpp::services