#include "system/System.h" #include "common/Exception.h" #include "common/Module.h" #include "common/Capability.h" #include "common/GpuInfo.h" #include "common/config.h" #include #include #include #include #include #include #include #include #include #include #if defined(EVENGINE_WINDOWS) || defined(_WIN32) #ifndef NOMINMAX #define NOMINMAX #endif #include #include #elif defined(__APPLE__) #include #endif namespace eve::system { namespace { /** The graphics backend's GPU description, or nullptr when none is linked. */ eve::caps::IGpuInfo *gpuInfoOrNull() { auto *info = eve::cap::query(); return (info && info->gpuReady()) ? info : nullptr; } } // namespace Module_IMPL(System, new System()); System::System() { SDL_InitSubSystem(SDL_INIT_TIMER); } std::string System::getEngineVersion() const { return EVENGINE_VERSION; } std::string System::getPlatform() const { const char *p = SDL_GetPlatform(); return p ? p : "Unknown"; } std::string System::getOS() const { #if defined(EVENGINE_WINDOWS) return "Windows"; #elif defined(EVENGINE_IOS) return "iOS"; #elif defined(EVENGINE_MACOSX) return "OS X"; #elif defined(EVENGINE_ANDROID) return "Android"; #elif defined(EVENGINE_LINUX) return "Linux"; #else return getPlatform(); #endif } int System::getProcessorCount() const { int n = SDL_GetCPUCount(); return n > 0 ? n : 1; } int System::getCPUCacheLineSize() const { int n = SDL_GetCPUCacheLineSize(); return n > 0 ? n : 0; } int System::getSystemRAM() const { int mb = SDL_GetSystemRAM(); return mb > 0 ? mb : 0; } int System::getProcessMemoryMB() const { #if defined(EVENGINE_WINDOWS) || defined(_WIN32) PROCESS_MEMORY_COUNTERS pmc{}; if (GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) return static_cast(pmc.WorkingSetSize / (1024ull * 1024ull)); return 0; #elif defined(__APPLE__) task_vm_info_data_t info{}; mach_msg_type_number_t count = TASK_VM_INFO_COUNT; if (task_info(mach_task_self(), TASK_VM_INFO, reinterpret_cast(&info), &count) == KERN_SUCCESS) { return static_cast(info.phys_footprint / (1024ull * 1024ull)); } return 0; #elif defined(__linux__) || defined(EVENGINE_ANDROID) || defined(EVENGINE_LINUX) std::ifstream in("/proc/self/status"); if (!in) return 0; std::string key; while (in >> key) { if (key == "VmRSS:") { long kb = 0; in >> kb; return static_cast(kb / 1024); } std::string rest; std::getline(in, rest); } return 0; #else return 0; #endif } float System::getWallTime() const { using clock = std::chrono::system_clock; auto tp = clock::now().time_since_epoch(); auto us = std::chrono::duration_cast(tp).count(); return float(double(us) / 1'000'000.0); } void System::sleepMilliseconds(int ms) { if (ms < 0) throw Exception("System.sleepMilliseconds: ms must be >= 0"); if (ms == 0) return; SDL_Delay(static_cast(ms)); } std::string System::getPowerState() const { int secs = 0, pct = 0; SDL_PowerState st = SDL_GetPowerInfo(&secs, &pct); switch (st) { case SDL_POWERSTATE_ON_BATTERY: return "on_battery"; case SDL_POWERSTATE_NO_BATTERY: return "no_battery"; case SDL_POWERSTATE_CHARGING: return "charging"; case SDL_POWERSTATE_CHARGED: return "charged"; default: return "unknown"; } } int System::getPowerSecondsLeft() const { int secs = -1, pct = -1; SDL_GetPowerInfo(&secs, &pct); return secs; } int System::getPowerPercent() const { int secs = -1, pct = -1; SDL_GetPowerInfo(&secs, &pct); return pct; } std::string System::getClipboardText() const { if (!SDL_HasClipboardText()) return {}; char *t = SDL_GetClipboardText(); if (!t) return {}; std::string out(t); SDL_free(t); return out; } void System::setClipboardText(const std::string &text) { if (SDL_SetClipboardText(text.c_str()) != 0) throw Exception("System.setClipboardText failed: %s", SDL_GetError()); } std::string System::getGpuName() const { auto *info = gpuInfoOrNull(); return info ? info->gpuName() : std::string(); } std::string System::getGpuVendor() const { auto *info = gpuInfoOrNull(); return info ? info->gpuVendor() : std::string(); } std::string System::getGpuDeviceType() const { auto *info = gpuInfoOrNull(); return info ? info->gpuDeviceType() : std::string(); } int System::getGpuMemoryTotalMB() const { auto *info = gpuInfoOrNull(); return info ? info->gpuMemoryTotalMB() : 0; } void System::expose(ssq::Table &table) { auto cls = table.addClass(name, System::create, false); expose(cls); } void System::expose(ssq::Class &cls) { cls.addFunc("getName", &System::getName); cls.addFunc("getEngineVersion", &System::getEngineVersion); cls.addFunc("getPlatform", &System::getPlatform); cls.addFunc("getOS", &System::getOS); cls.addFunc("getProcessorCount", &System::getProcessorCount); cls.addFunc("getCPUCacheLineSize", &System::getCPUCacheLineSize); cls.addFunc("getSystemRAM", &System::getSystemRAM); cls.addFunc("getProcessMemoryMB", &System::getProcessMemoryMB); cls.addFunc("getWallTime", &System::getWallTime); cls.addFunc("sleepMilliseconds", &System::sleepMilliseconds); cls.addFunc("getPowerState", &System::getPowerState); cls.addFunc("getPowerSecondsLeft", &System::getPowerSecondsLeft); cls.addFunc("getPowerPercent", &System::getPowerPercent); cls.addFunc("getClipboardText", &System::getClipboardText); cls.addFunc("setClipboardText", &System::setClipboardText); cls.addFunc("getGpuName", &System::getGpuName); cls.addFunc("getGpuVendor", &System::getGpuVendor); cls.addFunc("getGpuDeviceType", &System::getGpuDeviceType); cls.addFunc("getGpuMemoryTotalMB", &System::getGpuMemoryTotalMB); } } // namespace eve::system