feat: expand Intel GPU display management
This commit is contained in:
@@ -213,6 +213,12 @@ namespace montauk::abi {
|
||||
static constexpr uint64_t SYS_STAT = 152;
|
||||
static constexpr uint64_t SYS_SETUNIXTIME = 153;
|
||||
|
||||
// Display/modesetting control
|
||||
static constexpr uint64_t SYS_DISPLAYINFO = 154;
|
||||
static constexpr uint64_t SYS_DISPLAYMODES = 155;
|
||||
static constexpr uint64_t SYS_DISPLAYSETMODE = 156;
|
||||
static constexpr uint64_t SYS_DISPLAYBRIGHTNESS = 157;
|
||||
|
||||
// Tunable parameters (for SYS_SDR_SETPARAM / SYS_SDR_GETPARAM).
|
||||
static constexpr int SDR_PARAM_FREQ = 0; // center frequency, Hz
|
||||
static constexpr int SDR_PARAM_SAMPLE_RATE = 1; // sample rate, Hz
|
||||
@@ -312,6 +318,51 @@ namespace montauk::abi {
|
||||
uint64_t userAddr; // filled by SYS_FBMAP (0 until mapped)
|
||||
};
|
||||
|
||||
enum DisplayConnectorType : uint8_t {
|
||||
DISPLAY_CONNECTOR_UNKNOWN = 0,
|
||||
DISPLAY_CONNECTOR_EDP = 1,
|
||||
DISPLAY_CONNECTOR_DP = 2,
|
||||
DISPLAY_CONNECTOR_HDMI = 3,
|
||||
DISPLAY_CONNECTOR_DVI = 4,
|
||||
DISPLAY_CONNECTOR_VGA = 5,
|
||||
DISPLAY_CONNECTOR_LVDS = 6,
|
||||
};
|
||||
|
||||
static constexpr uint32_t DISPLAY_CAP_MODESET = 1u << 0;
|
||||
static constexpr uint32_t DISPLAY_CAP_EDID = 1u << 1;
|
||||
static constexpr uint32_t DISPLAY_CAP_BRIGHTNESS = 1u << 2;
|
||||
static constexpr uint32_t DISPLAY_CAP_PAGE_FLIP = 1u << 3;
|
||||
static constexpr uint32_t DISPLAY_CAP_VBLANK_IRQ = 1u << 4;
|
||||
static constexpr uint32_t DISPLAY_CAP_SAFE_SWITCH = 1u << 5;
|
||||
|
||||
static constexpr uint32_t DISPLAY_MODE_PREFERRED = 1u << 0;
|
||||
static constexpr uint32_t DISPLAY_MODE_CURRENT = 1u << 1;
|
||||
static constexpr uint32_t DISPLAY_MODE_DRIVER_VALID = 1u << 2;
|
||||
|
||||
struct DisplayModeInfo {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t refreshMilliHz;
|
||||
uint32_t pixelClockKHz;
|
||||
uint32_t flags;
|
||||
uint32_t _pad;
|
||||
};
|
||||
|
||||
struct DisplayInfo {
|
||||
uint32_t capabilities;
|
||||
uint32_t modeCount;
|
||||
int32_t currentMode;
|
||||
int32_t brightness; // 0..100, or -1 when unavailable
|
||||
uint16_t deviceId;
|
||||
uint8_t generation;
|
||||
uint8_t connectorType;
|
||||
uint8_t connected;
|
||||
uint8_t _pad0[3];
|
||||
char gpuName[64];
|
||||
char connectorName[32];
|
||||
char monitorName[64];
|
||||
};
|
||||
|
||||
struct SysInfo {
|
||||
char osName[32];
|
||||
char osVersion[32];
|
||||
|
||||
@@ -161,24 +161,58 @@ struct Canvas {
|
||||
|
||||
// ---- Text ----
|
||||
|
||||
void text_bitmap(int x, int y, const char* str, Color c, int scale = 1) {
|
||||
if (!str || !font_data || scale <= 0) return;
|
||||
uint32_t pixel = c.to_pixel();
|
||||
int cx = x;
|
||||
for (int i = 0; str[i]; i++, cx += FONT_WIDTH * scale) {
|
||||
const uint8_t* glyph =
|
||||
&font_data[(unsigned char)str[i] * FONT_HEIGHT];
|
||||
for (int row = 0; row < FONT_HEIGHT; row++) {
|
||||
uint8_t bits = glyph[row];
|
||||
if (!bits) continue;
|
||||
for (int col = 0; col < FONT_WIDTH; col++) {
|
||||
if (!(bits & (0x80 >> col))) continue;
|
||||
int px = cx + col * scale;
|
||||
int py = y + row * scale;
|
||||
for (int sy = 0; sy < scale; sy++) {
|
||||
int dy = py + sy;
|
||||
if (dy < 0 || dy >= h) continue;
|
||||
for (int sx = 0; sx < scale; sx++) {
|
||||
int dx = px + sx;
|
||||
if (dx >= 0 && dx < w) pixels[dy * w + dx] = pixel;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void text(int x, int y, const char* str, Color c) {
|
||||
if (fonts::system_font && fonts::system_font->valid) {
|
||||
fonts::system_font->draw_to_buffer(pixels, w, h, x, y, str, c, fonts::UI_SIZE);
|
||||
if (fonts::system_font->draw_to_buffer(
|
||||
pixels, w, h, x, y, str, c, fonts::UI_SIZE))
|
||||
return;
|
||||
}
|
||||
text_bitmap(x, y, str, c);
|
||||
}
|
||||
|
||||
void text_2x(int x, int y, const char* str, Color c) {
|
||||
if (fonts::system_font && fonts::system_font->valid) {
|
||||
fonts::system_font->draw_to_buffer(pixels, w, h, x, y, str, c, fonts::LARGE_SIZE);
|
||||
if (fonts::system_font->draw_to_buffer(
|
||||
pixels, w, h, x, y, str, c, fonts::LARGE_SIZE))
|
||||
return;
|
||||
}
|
||||
text_bitmap(x, y, str, c, 2);
|
||||
}
|
||||
|
||||
void text_mono(int x, int y, const char* str, Color c) {
|
||||
if (fonts::mono && fonts::mono->valid) {
|
||||
fonts::mono->draw_to_buffer(pixels, w, h, x, y, str, c, fonts::TERM_SIZE);
|
||||
return;
|
||||
if (fonts::mono->draw_to_buffer(
|
||||
pixels, w, h, x, y, str, c, fonts::TERM_SIZE))
|
||||
return;
|
||||
}
|
||||
text(x, y, str, c);
|
||||
text_bitmap(x, y, str, c);
|
||||
}
|
||||
|
||||
// ---- Icons ----
|
||||
|
||||
@@ -14,8 +14,10 @@ namespace gui {
|
||||
static constexpr int FONT_WIDTH = 8;
|
||||
static constexpr int FONT_HEIGHT = 16;
|
||||
|
||||
// Defined in font_data.cpp
|
||||
extern const uint8_t font_data[256 * 16];
|
||||
// Defined by programs that ship the built-in VGA fallback. Keep the symbol
|
||||
// weak so Canvas remains usable by small apps that intentionally rely only on
|
||||
// TrueType fonts, while login/desktop can recover when TrueType setup fails.
|
||||
extern const uint8_t font_data[256 * 16] __attribute__((weak));
|
||||
|
||||
// Dynamic font height: TTF line height or 16 (bitmap fallback)
|
||||
inline int system_font_height() {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <cstdint>
|
||||
#include <montauk/syscall.h>
|
||||
#include <montauk/string.h>
|
||||
#include <montauk/config.h>
|
||||
#include "gui/gui.hpp"
|
||||
|
||||
namespace gui {
|
||||
@@ -61,6 +62,20 @@ class Framebuffer {
|
||||
return 0xFF000000 | (rr << 16) | (gg << 8) | bb;
|
||||
}
|
||||
|
||||
static bool prefer_hardware_page_flip() {
|
||||
char user[64] = {};
|
||||
if (montauk::getuser(user, sizeof(user)) > 0 && user[0]) {
|
||||
auto doc = montauk::config::load_user(user, "display");
|
||||
bool enabled = doc.get_bool("graphics.tear_free", true);
|
||||
doc.destroy();
|
||||
return enabled;
|
||||
}
|
||||
auto doc = montauk::config::load("display");
|
||||
bool enabled = doc.get_bool("graphics.tear_free", true);
|
||||
doc.destroy();
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public:
|
||||
Framebuffer() : hw_fb(nullptr), hw_fb2(nullptr), back_buf(nullptr),
|
||||
fb_width(0), fb_height(0), fb_pitch(0), hw_next(1) {
|
||||
@@ -76,7 +91,8 @@ public:
|
||||
|
||||
// Hardware page flipping: fb_map() maps the second scanout buffer
|
||||
// directly after the first when the kernel supports flipping.
|
||||
if (hw_fb && montauk::fb_flip(-1, 0) == 1) {
|
||||
if (hw_fb && prefer_hardware_page_flip()
|
||||
&& montauk::fb_flip(-1, 0) == 1) {
|
||||
uint64_t pages = ((uint64_t)fb_height * fb_pitch + 0xFFF) / 0x1000;
|
||||
hw_fb2 = (uint32_t*)((uint8_t*)hw_fb + pages * 0x1000);
|
||||
}
|
||||
|
||||
@@ -311,13 +311,14 @@ struct TrueTypeFont {
|
||||
draw(fb, x, y, text, fg, pixel_size);
|
||||
}
|
||||
|
||||
void draw_to_buffer(uint32_t* pixels, int buf_w, int buf_h,
|
||||
bool draw_to_buffer(uint32_t* pixels, int buf_w, int buf_h,
|
||||
int x, int y, const char* text,
|
||||
Color color, int pixel_size) {
|
||||
if (!valid) return;
|
||||
if (!valid) return false;
|
||||
GlyphCache* gc = get_cache(pixel_size);
|
||||
int cx = x;
|
||||
int baseline = y + gc->ascent;
|
||||
bool drew_pixel = false;
|
||||
|
||||
for (int i = 0; text[i]; i++) {
|
||||
CachedGlyph* g = get_glyph(gc, (unsigned char)text[i]);
|
||||
@@ -334,6 +335,7 @@ struct TrueTypeFont {
|
||||
if (dx < 0 || dx >= buf_w) continue;
|
||||
uint8_t alpha = g->bitmap[row * g->width + col];
|
||||
if (alpha == 0) continue;
|
||||
drew_pixel = true;
|
||||
|
||||
if (alpha == 255) {
|
||||
pixels[dy * buf_w + dx] =
|
||||
@@ -356,6 +358,7 @@ struct TrueTypeFont {
|
||||
}
|
||||
cx += g->advance;
|
||||
}
|
||||
return drew_pixel;
|
||||
}
|
||||
|
||||
// Draw text to buffer with clip rectangle (pixels outside clip_x..clip_x+clip_w are not drawn)
|
||||
|
||||
@@ -177,6 +177,10 @@ extern "C" {
|
||||
#define MTK_SYS_GETEXECPATH 151
|
||||
#define MTK_SYS_STAT 152
|
||||
#define MTK_SYS_SETUNIXTIME 153
|
||||
#define MTK_SYS_DISPLAYINFO 154
|
||||
#define MTK_SYS_DISPLAYMODES 155
|
||||
#define MTK_SYS_DISPLAYSETMODE 156
|
||||
#define MTK_SYS_DISPLAYBRIGHTNESS 157
|
||||
/* @SYSCALLS-END */
|
||||
|
||||
#define MTK_SOCK_TCP 1
|
||||
|
||||
@@ -343,6 +343,22 @@ namespace montauk {
|
||||
return syscall2(montauk::abi::SYS_FBFLIP, (uint64_t)index, flags);
|
||||
}
|
||||
|
||||
inline int display_info(montauk::abi::DisplayInfo* out) {
|
||||
return (int)syscall1(montauk::abi::SYS_DISPLAYINFO, (uint64_t)out);
|
||||
}
|
||||
inline int display_modes(montauk::abi::DisplayModeInfo* out, int maxCount) {
|
||||
return (int)syscall2(montauk::abi::SYS_DISPLAYMODES,
|
||||
(uint64_t)out, (uint64_t)maxCount);
|
||||
}
|
||||
inline int display_set_mode(int modeIndex) {
|
||||
return (int)syscall1(montauk::abi::SYS_DISPLAYSETMODE,
|
||||
(uint64_t)modeIndex);
|
||||
}
|
||||
inline int display_brightness(int percent = -1) {
|
||||
return (int)syscall1(montauk::abi::SYS_DISPLAYBRIGHTNESS,
|
||||
(uint64_t)(int64_t)percent);
|
||||
}
|
||||
|
||||
// Arguments
|
||||
inline int getargs(char* buf, uint64_t maxLen) {
|
||||
return (int)syscall2(montauk::abi::SYS_GETARGS, (uint64_t)buf, maxLen);
|
||||
|
||||
Reference in New Issue
Block a user