7#include "common/config.h"
9#include <simplesquirrel/simplesquirrel.hpp>
12#include <SDL2/SDL_clipboard.h>
13#include <SDL2/SDL_cpuinfo.h>
14#include <SDL2/SDL_power.h>
22#if defined(EVENGINE_WINDOWS) || defined(_WIN32)
28#elif defined(__APPLE__)
37 auto *
info = eve::cap::query<eve::caps::IGpuInfo>();
46 SDL_InitSubSystem(SDL_INIT_TIMER);
47 cap::provide<IFramePacing>(
this);
50OS::~OS() { cap::revoke<IFramePacing>(
this); }
53 if (count < 0 || count > 2)
55 "VSync count must be in [0,2]",
"count",
56 {},
"os.framePacing"));
57 verticalSyncCount_ =
count;
58 lastFrameCounter_ = 0;
63 if (target < -1 || target > 240)
65 "target FPS must be in [-1,240]",
"target",
66 {},
"os.framePacing"));
67 targetFramesPerSecond_ =
target;
68 lastFrameCounter_ = 0;
73 const uint64_t now = SDL_GetPerformanceCounter();
74 const uint64_t frequency = SDL_GetPerformanceFrequency();
75 if (lastFrameCounter_ == 0 || frequency == 0) {
76 lastFrameCounter_ = now;
79 if (verticalSyncCount_ == 0 && targetFramesPerSecond_ > 0) {
80 const double target =
static_cast<double>(frequency) /
static_cast<double>(targetFramesPerSecond_);
81 const double elapsed =
static_cast<double>(now - lastFrameCounter_);
84 static_cast<uint32_t
>((
target - elapsed) * 1000.0 /
static_cast<double>(frequency));
88 lastFrameCounter_ = SDL_GetPerformanceCounter();
94 const char *
p = SDL_GetPlatform();
95 return p ?
p :
"Unknown";
99#if defined(EVENGINE_WINDOWS)
101#elif defined(EVENGINE_IOS)
103#elif defined(EVENGINE_MACOSX)
105#elif defined(EVENGINE_ANDROID)
107#elif defined(EVENGINE_LINUX)
115 int n = SDL_GetCPUCount();
116 return n > 0 ?
n : 1;
120 int n = SDL_GetCPUCacheLineSize();
121 return n > 0 ?
n : 0;
125 int mb = SDL_GetSystemRAM();
126 return mb > 0 ? mb : 0;
130#if defined(EVENGINE_WINDOWS) || defined(_WIN32)
131 PROCESS_MEMORY_COUNTERS pmc{};
132 if (GetProcessMemoryInfo(GetCurrentProcess(), &pmc,
sizeof(pmc)))
133 return static_cast<int>(pmc.WorkingSetSize / (1024ull * 1024ull));
135#elif defined(__APPLE__)
136 task_vm_info_data_t
info{};
137 mach_msg_type_number_t
count = TASK_VM_INFO_COUNT;
138 if (task_info(mach_task_self(), TASK_VM_INFO,
reinterpret_cast<task_info_t
>(&
info), &
count) ==
140 return static_cast<int>(
info.phys_footprint / (1024ull * 1024ull));
143#elif defined(__linux__) || defined(EVENGINE_ANDROID) || defined(EVENGINE_LINUX)
144 std::ifstream in(
"/proc/self/status");
148 if (
key ==
"VmRSS:") {
151 return static_cast<int>(kb / 1024);
154 std::getline(in, rest);
163 using clock = std::chrono::system_clock;
164 auto tp = clock::now().time_since_epoch();
165 auto us = std::chrono::duration_cast<std::chrono::microseconds>(tp).count();
166 return float(
double(us) / 1'000'000.0);
170 if (ms < 0)
throw Exception(
"OS.sleepMilliseconds: ms must be >= 0");
172 SDL_Delay(
static_cast<Uint32
>(ms));
176 int secs = 0, pct = 0;
177 SDL_PowerState st = SDL_GetPowerInfo(&secs, &pct);
179 case SDL_POWERSTATE_ON_BATTERY:
return "on_battery";
180 case SDL_POWERSTATE_NO_BATTERY:
return "no_battery";
181 case SDL_POWERSTATE_CHARGING:
return "charging";
182 case SDL_POWERSTATE_CHARGED:
return "charged";
183 default:
return "unknown";
188 int secs = -1, pct = -1;
189 SDL_GetPowerInfo(&secs, &pct);
194 int secs = -1, pct = -1;
195 SDL_GetPowerInfo(&secs, &pct);
200 if (!SDL_HasClipboardText())
return {};
201 char *
t = SDL_GetClipboardText();
209 if (SDL_SetClipboardText(
text.c_str()) != 0)
210 throw Exception(
"OS.setClipboardText failed: %s", SDL_GetError());
214 auto *
info = gpuInfoOrNull();
215 return info ?
info->gpuName() : std::string();
219 auto *
info = gpuInfoOrNull();
220 return info ?
info->gpuVendor() : std::string();
224 auto *
info = gpuInfoOrNull();
225 return info ?
info->gpuDeviceType() : std::string();
229 auto *
info = gpuInfoOrNull();
230 return info ?
info->gpuMemoryTotalMB() : 0;
233void OS::expose(ssq::Table &table) {
234 auto cls = table.addClass(
"OS", OS::create,
false);
238void OS::expose(ssq::Class &
cls) {
250 cls.addFunc(
"getVerticalSyncCount", [](
const OS* os) {
return os->getVerticalSyncCount(); });
251 cls.addFunc(
"getTargetFramesPerSecond", [](
const OS* os) {
return os->getTargetFramesPerSecond(); });
252 cls.addFunc(
"setTargetFramesPerSecond", [](
OS* os,
int target) {
253 auto result = os->setTargetFramesPerSecond(
target);
254 if (!result.ok())
throw Exception(
"OS.setTargetFramesPerSecond: target must be in [-1,240]");
#define Module_IMPL(ModuleName, newExpr)
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
EVENGINE_API_FOUNDATION public API.
virtual std::string getName() const =0
Returns the name.
Move-only operation result carrying either a value or Status.
static Result success(T value)
Construct a successful result owning value.
static Result failure(Status status)
Construct a failed result from a structured status.
EVENGINE_API_FOUNDATION_INLINE public API.
OS module — host OS / hardware / wall-clock / clipboard / optional GPU info. Frame timing stays on Ti...
std::string getOS() const
Normalized OS id for games: "Windows" | "OS X" | "Linux" | "Android" | "iOS" | "Unknown"
std::string getPowerState() const
Power state string: "unknown" | "on_battery" | "no_battery" | "charging" | "charged"
int getGpuMemoryTotalMB() const
Sum of DEVICE_LOCAL heap sizes in MB (0 if unknown / not ready).
Result< void > setVerticalSyncCount(int count) override
Sets the vertical sync count.
int getSystemRAM() const
System RAM in megabytes (0 if unknown).
int getPowerPercent() const
Battery percent 0–100, or -1 if unknown.
void limitFrame() override
Limit frame.
std::string getGpuDeviceType() const
"discrete" | "integrated" | "virtual" | "cpu" | "other" | ""
int getPowerSecondsLeft() const
Estimated seconds of battery left (-1 if unknown).
void sleepMilliseconds(int ms)
Sleep milliseconds.
int getCPUCacheLineSize() const
CPU L1 cache line size in bytes (0 if unknown).
float getWallTime() const
UTC wall-clock seconds since Unix epoch (float for script).
std::string getGpuVendor() const
Returns the gpu vendor.
int getProcessMemoryMB() const
Current process resident memory in megabytes (0 if unknown).
std::string getPlatform() const
Raw SDL platform string (e.g. "Mac OS X", "Windows").
std::string getGpuName() const
GPU queries — empty/0 if Graphics not initialized yet.
std::string getEngineVersion() const
Engine version string (e.g. "v0.1.0").
int getProcessorCount() const
Returns the processor count.
void setClipboardText(const std::string &text)
Sets the clipboard text.
Result< void > setTargetFramesPerSecond(int target) override
Sets the target frames per second.
std::string getClipboardText() const
Returns the clipboard text.