mirror of
https://github.com/subhobhai943/SUB-OS.git
synced 2026-10-26 17:12:35 +00:00
perf(gui): scene-dirty compositor + cursor overlay + 60 FPS pacer + animations
Rework the compositor so it stops repainting the whole screen every frame, tripling the frame rate (17 -> 54 FPS at HD) and adding smooth animation. - Scene-dirty skipping (gui/gui_desktop.c): the full scene is recomposited only when something other than the bare pointer changed -- input, an open animation, or a ~10 Hz heartbeat for live content (clock, graphs). Idle and pointer-only frames skip the recomposite entirely. - Cursor save-under (gui/gui_cursor.c): the pointer is an overlay that stashes and restores the pixels beneath it, so moving the mouse never forces a full repaint -- pointer motion runs at the frame cap. - 60 FPS frame pacer: each iteration is timed against the monotonic clock and padded to a 16.666 ms budget with the new ktime_delay_us() (HPET-precise busy-wait), giving consistent pacing instead of a free-running spin. - Window open animation (gui/gui_wm.c): new windows grow from 60% to full size with a cubic ease-out over ~160 ms; gui_wm_update() drives it and reports while any window is still animating so the compositor keeps redrawing. - Default display mode set to 1280x720 (HD) -- the sweet spot where the software compositor sustains a near-60 FPS cursor with headroom for effects. Kernel: kernel/time/ktime.c gains ktime_delay_us(), a precise HPET-based delay (bounded PIT fallback) used by the pacer. Verified live (screenshotted): boots to 1280x720, logs in, tray reads ~54 FPS (green) while the pointer moves, no cursor ghosting, windows render cleanly. Clean build on x86_64/aarch64/armv8i; 0 panics / 0 OOM. Co-Authored-By: Claude Opus 4.8 <[email protected]> Claude-Session: https://claude.ai/code/session_01Fh5z6V7nGPbHvqVG5p4CXX
This commit is contained in:
1 parent
4ecf119377
commit
2c2e2d536e
8 files changed
+200
-13
No files matched your search
@@ -10,6 +10,9 @@
|
||||
#include <drivers/keyboard.h>
|
||||
#include <lib/string.h>
|
||||
#include <mm/kmalloc.h>
|
||||
#include <kernel/ktime.h>
|
||||
|
||||
#define WM_OPEN_ANIM_MS 160
|
||||
|
||||
#define BTN_SIZE 14
|
||||
#define BTN_GAP 4
|
||||
@@ -85,9 +88,63 @@ gui_window_t* gui_wm_create_window(const char* title, int x, int y, int w, int h
|
||||
|
||||
g_window_order[g_num_windows++] = win->id;
|
||||
gui_wm_focus_window(win->id);
|
||||
|
||||
// Kick off the grow-open animation: remember the final geometry and centre,
|
||||
// then start small. gui_wm_update() eases it back to full over ~160 ms.
|
||||
win->target_w = win->width;
|
||||
win->target_h = win->height;
|
||||
win->center_x = win->x + win->width / 2;
|
||||
win->center_y = win->y + win->height / 2;
|
||||
win->anim_open_ns = ktime_ns();
|
||||
win->width = win->target_w * 6 / 10;
|
||||
win->height = win->target_h * 6 / 10;
|
||||
win->x = win->center_x - win->width / 2;
|
||||
win->y = win->center_y - win->height / 2;
|
||||
if (win->x < 0) win->x = 0;
|
||||
if (win->y < 0) win->y = 0;
|
||||
return win;
|
||||
}
|
||||
|
||||
// Advance open animations. Returns true while any window is still animating.
|
||||
bool gui_wm_update(void) {
|
||||
bool animating = false;
|
||||
uint64_t now = ktime_ns();
|
||||
|
||||
for (int i = 0; i < g_num_windows; i++) {
|
||||
gui_window_t* win = gui_wm_get_window(g_window_order[i]);
|
||||
if (!win || win->anim_open_ns == 0) continue;
|
||||
|
||||
uint64_t elapsed_ms = (now - win->anim_open_ns) / 1000000ULL;
|
||||
if (elapsed_ms >= WM_OPEN_ANIM_MS) {
|
||||
// Snap to the final geometry and stop animating.
|
||||
win->width = win->target_w;
|
||||
win->height = win->target_h;
|
||||
win->x = win->center_x - win->target_w / 2;
|
||||
win->y = win->center_y - win->target_h / 2;
|
||||
win->anim_open_ns = 0;
|
||||
} else {
|
||||
animating = true;
|
||||
int p = (int)(elapsed_ms * 1000 / WM_OPEN_ANIM_MS); // 0..1000
|
||||
int inv = 1000 - p;
|
||||
int ease = 1000 - (inv * inv / 1000) * inv / 1000; // cubic ease-out
|
||||
int scale = 600 + 400 * ease / 1000; // 600..1000 permille
|
||||
win->width = win->target_w * scale / 1000;
|
||||
win->height = win->target_h * scale / 1000;
|
||||
win->x = win->center_x - win->width / 2;
|
||||
win->y = win->center_y - win->height / 2;
|
||||
}
|
||||
|
||||
// Keep the animating window on screen.
|
||||
if (win->x < 0) win->x = 0;
|
||||
if (win->y < 0) win->y = 0;
|
||||
if (win->x + win->width > g_work_w) win->x = g_work_w - win->width;
|
||||
if (win->y + win->height > g_work_h) win->y = g_work_h - win->height;
|
||||
if (win->x < 0) win->x = 0;
|
||||
if (win->y < 0) win->y = 0;
|
||||
}
|
||||
return animating;
|
||||
}
|
||||
|
||||
static int order_index_of(int win_id) {
|
||||
for (int i = 0; i < g_num_windows; i++) {
|
||||
if (g_window_order[i] == win_id) return i;
|
||||
|
||||
Reference in new issue
Block a user