Overlay draw callback: unregister waits for in-flight draws (lifetime contract)

Review (#599): who keeps the callback context alive until render-thread
calls are quiescent. Draw calls now run inside an in-flight count, and
set_draw_cb (replace or NULL) swaps the record and waits until no call
that read the old one is running, then frees it. When it returns, the
registrant may free ctx and its GL objects; it must unregister before
destroying them or the context. A change from inside the callback does
not wait. Documented in host_overlay.h. Tests: a reader thread drawing
while the owner unregisters and frees (300 rounds; fails without the
wait), and self-unregister from the callback.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Shokunin
2026-10-13 00:10:16 -07:00
parent 8b003a591d
commit facdf01ac6
4 changed files with 120 additions and 9 deletions
+9 -1
View File
@@ -30,7 +30,15 @@ void psx_host_pause_set_refuse_probe(PsxHostPauseRefuseFn fn);
* swap, with the drawable size in pixels. It runs on the thread that owns the
* GL context (the render thread when it is on, else the main thread), with the
* window framebuffer bound. The callback must leave GL state as it found it.
* Vulkan and the SDL renderer never call it. NULL unregisters. */
* Vulkan and the SDL renderer never call it. NULL unregisters.
*
* Lifetime contract: the registrant owns ctx. psx_host_overlay_set_draw_cb
* (replace or NULL) returns only after any draw call that may still be using
* the previous fn/ctx has finished, so the registrant may free ctx and the GL
* objects it draws with right after it returns, and must keep them alive
* until then. Unregister before destroying those objects or the GL context
* (e.g. on renderer shutdown). Called from inside the callback it does not
* wait; the current call is then the last one with the old ctx. */
typedef void (*PsxHostOverlayDrawFn)(int width, int height, void *ctx);
void psx_host_overlay_set_draw_cb(PsxHostOverlayDrawFn fn, void *ctx);
int psx_host_overlay_has_draw(void);