diff --git a/runtime/src/gpu_gl_renderer.c b/runtime/src/gpu_gl_renderer.c index cd1071df..d40119dc 100644 --- a/runtime/src/gpu_gl_renderer.c +++ b/runtime/src/gpu_gl_renderer.c @@ -8301,6 +8301,10 @@ static int pt_cb_ctx(void *user, int current) { return 1; } +/* The one owned swap call: the composing thread's (direct) or the present + * thread's. */ +static void gl_window_swap(void) { SDL_GL_SwapWindow(s_win); } + static void *pt_cb_present(void *user, int slot, void *ready) { (void)user; if (s_ptp_interval_gen != s_pt_interval_gen) { @@ -8335,7 +8339,7 @@ static void *pt_cb_present(void *user, int slot, void *ready) { GL_PRESENT_THREAD_TEST_HOOK(slot); #endif void *done = p_glFenceSync(PT_SYNC_GPU_COMMANDS_COMPLETE, 0); - SDL_GL_SwapWindow(s_win); + gl_window_swap(); return done; } @@ -8412,7 +8416,7 @@ static void pt_end(void) { /* The swap: direct, or queued to the present thread. */ static void gl_present_swap(void) { - if (!s_pt_on) { SDL_GL_SwapWindow(s_win); return; } + if (!s_pt_on) { gl_window_swap(); return; } (void)pt_target_fbo(); /* a frame that never bound 0 still has its slot */ void *ready = p_glFenceSync(PT_SYNC_GPU_COMMANDS_COMPLETE, 0); glFlush(); diff --git a/runtime/tests/test_frame_interpolation_context_ownership.py b/runtime/tests/test_frame_interpolation_context_ownership.py index ca649af6..d1257630 100644 --- a/runtime/tests/test_frame_interpolation_context_ownership.py +++ b/runtime/tests/test_frame_interpolation_context_ownership.py @@ -9,9 +9,15 @@ RENDERER = (ROOT / "runtime" / "src" / "gpu_gl_renderer.c").read_text( encoding="utf-8" ) -assert RENDERER.count("SDL_GL_CreateContext(") == 1, ( +# The only second context is the present thread's ([video] present_thread, +# docs/RENDER_THREAD.md), created in pt_begin under the render thread, which +# frame interpolation makes ineligible. +assert RENDERER.count("SDL_GL_CreateContext(") == 2, ( "temporal blending must not create a second GL context" ) +_pt = RENDERER[RENDERER.index("static int pt_begin(void)"):] +_pt = _pt[:_pt.index("\n}\n")] +assert "SDL_GL_CreateContext(" in _pt, "the second GL context belongs to the present thread" assert "SDL_CreateThread(" not in RENDERER, ( "temporal blending must not create a presentation thread" ) diff --git a/runtime/tests/test_gl_frame_gen.c b/runtime/tests/test_gl_frame_gen.c index efc8d5a4..459d5d58 100644 --- a/runtime/tests/test_gl_frame_gen.c +++ b/runtime/tests/test_gl_frame_gen.c @@ -254,7 +254,11 @@ int main(int argc, char **argv) { check(gl_renderer_render_thread_start(2) == 1, "render thread started"); if (pt_mode) check(gl_renderer_present_thread_active(), "present thread started"); if (fg) { +#ifdef _WIN32 + _putenv("PSX_FRAME_GEN_FORCE=1"); +#else setenv("PSX_FRAME_GEN_FORCE", "1", 1); +#endif gl_renderer_set_frame_generation(1); check(gl_renderer_frame_generation() == 1, "frame generation on"); }