Files
RedBear-OS/recipes/wip/monitors/htop/source/GPUMeter.c
T
vasilito ff4ff35918 feat: track all source trees in git — full fork offline-first model
Red Bear OS is a full fork. All sources must be available from git clone
with zero network access. Removed gitignore rules that excluded fetched
source trees under recipes/*/source/, local/recipes/kde/*/source/,
local/recipes/qt/*/source/, and vendor source trees.

Build artifacts (target/, build/, source.tar, *.o, *.so) remain excluded.

127291 files added — kernel, relibc, base, bootloader, pkgar, all KDE/Qt
frameworks, mesa, wayland, DRM drivers, and every other recipe source.
2026-05-14 10:55:53 +01:00

165 lines
4.6 KiB
C

/*
htop - GPUMeter.c
(C) 2023 htop dev team
Released under the GNU GPLv2+, see the COPYING file
in the source distribution for its full text.
*/
#include "config.h" // IWYU pragma: keep
#include "GPUMeter.h"
#include <math.h>
#include "CRT.h"
#include "Platform.h"
#include "RichString.h"
#include "XUtils.h"
struct GPUMeterEngineData GPUMeter_engineData[4];
static double totalUsage = NAN;
static unsigned long long int totalGPUTimeDiff = -1ULL;
static const int GPUMeter_attributes[] = {
GPU_ENGINE_1,
GPU_ENGINE_2,
GPU_ENGINE_3,
GPU_ENGINE_4,
GPU_RESIDUE,
};
static size_t activeMeters;
bool GPUMeter_active(void) {
return activeMeters > 0;
}
static int humanTimeUnit(char* buffer, size_t size, unsigned long long int value) {
if (value < 1000)
return xSnprintf(buffer, size, "%3lluns", value);
if (value < 10000)
return xSnprintf(buffer, size, "%1llu.%1lluus", value / 1000, (value % 1000) / 100);
value /= 1000;
if (value < 1000)
return xSnprintf(buffer, size, "%3lluus", value);
if (value < 10000)
return xSnprintf(buffer, size, "%1llu.%1llums", value / 1000, (value % 1000) / 100);
value /= 1000;
if (value < 1000)
return xSnprintf(buffer, size, "%3llums", value);
if (value < 10000)
return xSnprintf(buffer, size, "%1llu.%1llus", value / 1000, (value % 1000) / 100);
value /= 1000;
if (value < 600)
return xSnprintf(buffer, size, "%3llus", value);
value /= 60;
if (value < 600)
return xSnprintf(buffer, size, "%3llum", value);
value /= 60;
if (value < 96)
return xSnprintf(buffer, size, "%3lluh", value);
value /= 24;
return xSnprintf(buffer, size, "%3llud", value);
}
static void GPUMeter_updateValues(Meter* this) {
assert(ARRAYSIZE(GPUMeter_engineData) <= ARRAYSIZE(GPUMeter_attributes) - 1);
Platform_setGPUValues(this, &totalUsage, &totalGPUTimeDiff);
if (!isNonnegative(totalUsage)) {
xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "N/A");
return;
}
xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%.1f%%", totalUsage);
}
static void GPUMeter_display(const Object* cast, RichString* out) {
const Meter* this = (const Meter*)cast;
char buffer[50];
int written;
RichString_writeAscii(out, CRT_colors[METER_TEXT], ":");
if (!isNonnegative(totalUsage)) {
RichString_appendAscii(out, CRT_colors[METER_VALUE], " N/A");
return;
}
written = xSnprintf(buffer, sizeof(buffer), "%4.1f", totalUsage);
RichString_appendnAscii(out, CRT_colors[METER_VALUE], buffer, written);
RichString_appendAscii(out, CRT_colors[METER_TEXT], "%");
if (totalGPUTimeDiff != -1ULL) {
RichString_appendAscii(out, CRT_colors[METER_TEXT], "(");
written = humanTimeUnit(buffer, sizeof(buffer), totalGPUTimeDiff);
RichString_appendnAscii(out, CRT_colors[METER_VALUE], buffer, written);
RichString_appendAscii(out, CRT_colors[METER_TEXT], ")");
}
for (size_t i = 0; i < ARRAYSIZE(GPUMeter_engineData); i++) {
if (!GPUMeter_engineData[i].key)
break;
RichString_appendAscii(out, CRT_colors[METER_TEXT], " ");
RichString_appendAscii(out, CRT_colors[METER_TEXT], GPUMeter_engineData[i].key);
RichString_appendAscii(out, CRT_colors[METER_TEXT], ":");
if (isNonnegative(this->values[i]))
written = xSnprintf(buffer, sizeof(buffer), "%4.1f", this->values[i]);
else
written = xSnprintf(buffer, sizeof(buffer), " N/A");
RichString_appendnAscii(out, CRT_colors[METER_VALUE], buffer, written);
RichString_appendAscii(out, CRT_colors[METER_TEXT], "%");
if (GPUMeter_engineData[i].timeDiff != -1ULL) {
RichString_appendAscii(out, CRT_colors[METER_TEXT], "(");
written = humanTimeUnit(buffer, sizeof(buffer), GPUMeter_engineData[i].timeDiff);
RichString_appendnAscii(out, CRT_colors[METER_VALUE], buffer, written);
RichString_appendAscii(out, CRT_colors[METER_TEXT], ")");
}
}
}
static void GPUMeter_init(Meter* this ATTR_UNUSED) {
activeMeters++;
}
static void GPUMeter_done(Meter* this ATTR_UNUSED) {
assert(activeMeters > 0);
activeMeters--;
}
const MeterClass GPUMeter_class = {
.super = {
.extends = Class(Meter),
.delete = Meter_delete,
.display = GPUMeter_display,
},
.init = GPUMeter_init,
.done = GPUMeter_done,
.updateValues = GPUMeter_updateValues,
.defaultMode = BAR_METERMODE,
.supportedModes = METERMODE_DEFAULT_SUPPORTED,
.maxItems = ARRAYSIZE(GPUMeter_attributes),
.total = 100.0,
.attributes = GPUMeter_attributes,
.name = "GPU",
.uiName = "GPU usage",
.caption = "GPU"
};