From 0127fcfc73048ad7f446096007e8820e1cad8328 Mon Sep 17 00:00:00 2001 From: yacineolivier-maker <234833416+yacineolivier-maker@users.noreply.github.com> Date: Tue, 20 Oct 2026 21:58:39 +0200 Subject: [PATCH] Host HUD layer: psx_host_set_hud_draw_cb, drawn under the in-game menu A title can draw its own heads-up display on the host side (ImGui, like the in-game overlay provider), once per presented frame -- real and generated frames -- under the in-game menu and with the same thread and GL rules as psx_host_overlay_set_draw_cb. Registered once at title activation; NULL unregisters. No callback registered: no change in behaviour. Used by a modern race HUD for R4 (lap, timing, tachometer, track map) drawn at window resolution instead of the 320x240 native one. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Rkyma8rbyPiccs9n2bkyG6 --- runtime/include/host_overlay.h | 8 ++++++++ runtime/src/gpu_gl_renderer.c | 6 ++++-- runtime/src/host_overlay.c | 14 ++++++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/runtime/include/host_overlay.h b/runtime/include/host_overlay.h index 06c2e504..d1bfcf3f 100644 --- a/runtime/include/host_overlay.h +++ b/runtime/include/host_overlay.h @@ -46,6 +46,14 @@ void psx_host_overlay_set_draw_cb(PsxHostOverlayDrawFn fn, void *ctx); int psx_host_overlay_has_draw(void); void psx_host_overlay_draw(int width, int height); /* renderer side */ +/* ---- Game HUD layer --------------------------------------------------------- + * A title's own heads-up display, drawn once per presented frame (real and + * generated) under the in-game menu, same thread and GL rules as the overlay + * callback above. Set once (title activation) and kept for the session; NULL + * unregisters (no wait: the registrant keeps fn and ctx alive for the session). */ +void psx_host_set_hud_draw_cb(PsxHostOverlayDrawFn fn, void *ctx); +void psx_host_hud_draw(int width, int height); /* renderer side */ + /* ---- P3: input sink ----------------------------------------------------- * The sink sees every host SDL event first (main thread), in the normal event * drain and in the host pause loop. Returning non-zero consumes the event. diff --git a/runtime/src/gpu_gl_renderer.c b/runtime/src/gpu_gl_renderer.c index dab81837..67b2f4a0 100644 --- a/runtime/src/gpu_gl_renderer.c +++ b/runtime/src/gpu_gl_renderer.c @@ -9908,8 +9908,10 @@ static void gl_swap_with_osd(void) { } if (ov_image(3, &px, &ow, &oh) && px) gl_draw_osd_image(px, ow, oh, ww, wh, 0, 0, ww, wh); - /* In-game overlay provider (host_overlay.h P2), over everything - * the host composes; no-op unless one registered. */ + /* The title's HUD layer, then the in-game overlay provider + * (host_overlay.h P2) over everything; each a no-op unless one + * registered. */ + psx_host_hud_draw(ww, wh); psx_host_overlay_draw(ww, wh); } } diff --git a/runtime/src/host_overlay.c b/runtime/src/host_overlay.c index 100f7a97..dfc7536c 100644 --- a/runtime/src/host_overlay.c +++ b/runtime/src/host_overlay.c @@ -101,6 +101,20 @@ void psx_host_overlay_draw(int width, int height) { atomic_fetch_sub(&s_draw_inflight, 1); } +/* ---- Game HUD layer ------------------------------------------------------- */ +static PsxHostOverlayDrawFn s_hud_fn = NULL; +static void *s_hud_ctx = NULL; + +void psx_host_set_hud_draw_cb(PsxHostOverlayDrawFn fn, void *ctx) { + s_hud_ctx = ctx; + s_hud_fn = fn; +} + +void psx_host_hud_draw(int width, int height) { + PsxHostOverlayDrawFn fn = s_hud_fn; + if (fn && width > 0 && height > 0) fn(width, height, s_hud_ctx); +} + /* ---- P3: input sink -------------------------------------------------------- */ static PsxHostInputSinkFn s_sink_fn = NULL; static void *s_sink_ctx = NULL;