mirror of
https://github.com/jkdansereau/goldeneye-pc-port.git
synced 2026-10-23 15:52:42 +02:00
D952: macOS black window when started with the display asleep - VSync through CGL, not SDL3's display-link wait
This commit is contained in:
1 parent
af5e75ccbf
commit
a9feb0960f
4 files changed
+61
No files matched your search
@@ -463,6 +463,7 @@ D644,FIXED,File-select royal crest drew on an opaque dark square (#146):,"FIXED
|
|||||||
D645,FIXED,"Original 1.1: F10 ""Invert look"" did not invert vertical look (#145 a):",FIXED 2026-10-12 (F10 row and watch row synced in Original; maintainer-verified)
|
D645,FIXED,"Original 1.1: F10 ""Invert look"" did not invert vertical look (#145 a):",FIXED 2026-10-12 (F10 row and watch row synced in Original; maintainer-verified)
|
||||||
D646,FIXED,"F10 dropdown popup drew over the hint/tooltip panel (popup bounded by the screen edge, not the settings box) —",FIXED 2026-10-12 (ddGeom bounded to the box; maintainer-verified)
|
D646,FIXED,"F10 dropdown popup drew over the hint/tooltip panel (popup bounded by the screen edge, not the settings box) —",FIXED 2026-10-12 (ddGeom bounded to the box; maintainer-verified)
|
||||||
D951,OPEN,"v0.6.0 release gate: Windows golden sweep flags are timing noise in the test, not rendering changes —",OPEN (test-side; 2026-10-13)
|
D951,OPEN,"v0.6.0 release gate: Windows golden sweep flags are timing noise in the test, not rendering changes —",OPEN (test-side; 2026-10-13)
|
||||||
|
D952,FIXED,"macOS: black window, no frame, when the game starts while the display is asleep (SDL3 Cocoa VSync waits forever on a CVDisplayLink that never started) —","FIXED 2026-10-13 (port-only, gfx_sdl2.cpp; Mac A/B:"
|
||||||
D607,OPEN,Address model unified into one header:,DONE 2026-10-07 (macos branch; Windows identity gate:
|
D607,OPEN,Address model unified into one header:,DONE 2026-10-07 (macos branch; Windows identity gate:
|
||||||
D608,FIXED,D34 ANIM_DATA_x re-basing guard in assets/animationtable_data.h was __x86_64__-only:,"FIXED 2026-10-07 (macos branch; mechanical guard widening, arm64 link clean)"
|
D608,FIXED,D34 ANIM_DATA_x re-basing guard in assets/animationtable_data.h was __x86_64__-only:,"FIXED 2026-10-07 (macos branch; mechanical guard widening, arm64 link clean)"
|
||||||
D609,FIXED,macOS arm64 SIGKILL at exec:,"FIXED 2026-10-07 (macos branch; probe-confirmed; arm64 keeps the 4 GiB pagezero, floor 11.0)"
|
D609,FIXED,macOS arm64 SIGKILL at exec:,"FIXED 2026-10-07 (macos branch; probe-confirmed; arm64 keeps the 4 GiB pagezero, floor 11.0)"
|
||||||
|
|||||||
|
@@ -874,6 +874,7 @@ covers D24–D69; the log continues in §H (D32 procedure, D70–D121).
|
|||||||
| D645 | **Original 1.1: F10 "Invert look" did not invert vertical look (#145 a): D605 flipped the move stick; the game's own Look up/down drives C-button/aim pitch** — full `## D645` entry at file tail | FIXED 2026-10-12 (F10 row and watch row synced in Original; maintainer-verified) |
|
| D645 | **Original 1.1: F10 "Invert look" did not invert vertical look (#145 a): D605 flipped the move stick; the game's own Look up/down drives C-button/aim pitch** — full `## D645` entry at file tail | FIXED 2026-10-12 (F10 row and watch row synced in Original; maintainer-verified) |
|
||||||
| D646 | **F10 dropdown popup drew over the hint/tooltip panel (popup bounded by the screen edge, not the settings box)** — full `## D646` entry at file tail | FIXED 2026-10-12 (`ddGeom` bounded to the box; maintainer-verified) |
|
| D646 | **F10 dropdown popup drew over the hint/tooltip panel (popup bounded by the screen edge, not the settings box)** — full `## D646` entry at file tail | FIXED 2026-10-12 (`ddGeom` bounded to the box; maintainer-verified) |
|
||||||
| D951 | **v0.6.0 release gate: Windows golden sweep flags are timing noise in the test, not rendering changes** — full `## D951` entry at file tail | OPEN (test-side; 2026-10-13) |
|
| D951 | **v0.6.0 release gate: Windows golden sweep flags are timing noise in the test, not rendering changes** — full `## D951` entry at file tail | OPEN (test-side; 2026-10-13) |
|
||||||
|
| D952 | **macOS: black window, no frame, when the game starts while the display is asleep (SDL3 Cocoa VSync waits forever on a CVDisplayLink that never started)** — full `## D952` entry at file tail | FIXED 2026-10-13 (port-only, `gfx_sdl2.cpp`; Mac A/B: unfixed 3/3 hang, fixed 0/5) |
|
||||||
|
|
||||||
Phase 2 replaced the Phase-1 demo loop with the real `mainproc()` on real OS
|
Phase 2 replaced the Phase-1 demo loop with the real `mainproc()` on real OS
|
||||||
threads, compiled GE's real `src/sched.c`, and brought in PD's fast3d software
|
threads, compiled GE's real `src/sched.c`, and brought in PD's fast3d software
|
||||||
@@ -21999,3 +22000,17 @@ FpsCap = 60'`: 20/21 PASS; statue REGRESSION (4.66%, frame 900).
|
|||||||
**Owed (test side only).** (1) verify.sh should pin `FpsCap = 60` in its ini itself, since the goldens are 60 fps captures; (2) a flagged level should be re-run once before it counts as a regression, or the first run should be discarded as warm-up. No game-code change.
|
**Owed (test side only).** (1) verify.sh should pin `FpsCap = 60` in its ini itself, since the goldens are 60 fps captures; (2) a flagged level should be re-run once before it counts as a regression, or the first run should be discarded as warm-up. No game-code change.
|
||||||
|
|
||||||
**Status.** OPEN, test-side.
|
**Status.** OPEN, test-side.
|
||||||
|
|
||||||
|
## D952: macOS first-start black window = SDL3 VSync waiting on a CVDisplayLink that never started (display asleep) — FIXED 2026-10-13
|
||||||
|
|
||||||
|
**Symptom.** "If the window stays black on the very first start, close it and start it again" (v0.6.0 known issue): 4 hangs on 10-12 and 2 of 13 cold first launches on 10-13, always the first launch after the Mac had sat idle (which is when a new CI build arrives, so it looked like "first launch of a new binary").
|
||||||
|
|
||||||
|
**Evidence.** Hung run (`kernel heartbeat: no frame rendered`, frames=0) sampled with `sample`: the D481 render worker sits in `portRenderGfxTask -> Cocoa_GL_SwapWindow -> SDL_WaitConditionTimeoutNS -> __psynch_cvwait`; the scheduler, `amMain` (`src/audi.c` reply wait) and `bossMainloop` only wait behind it. The process has NO `CVDisplayLink` thread; a healthy run has one. SDL 3.4.14 (`SDL_cocoaopengl.m`): with a swap interval set, `Cocoa_GL_SwapWindow` waits on a condition that only the display-link callback signals, with no timeout; the link is created and started once, in `initWithFormat`, from the active displays.
|
||||||
|
|
||||||
|
**Trigger (deterministic).** `pmset displaysleepnow`, then launch: unfixed download 3/3 hang. Re-signing the binary (new cdhash) with the display awake: 0/10. The "new binary" correlation was the idle gap before it.
|
||||||
|
|
||||||
|
**Fix (`port/fast3d/gfx_sdl2.cpp`, `__APPLE__` only).** SDL's swap interval stays 0, so SDL's swap never waits; VSync is set on the context with `CGLSetParameter(kCGLCPSwapInterval)` (as SDL2 did on macOS), which blocks in `flushBuffer` on the driver's own refresh. `get_swap_interval` returns the CGL value, so D578/D600 pacing sees the same interval as before. Logs `SDL: swap interval N via CGL (read back N)`.
|
||||||
|
|
||||||
|
**Verified (Mac M3, macOS 15.6.1, fix built with the CI recipe, run against the download's own SDL 3.4.14 dylibs).** Display asleep: fixed 0/5 hang. Display awake: 60.0 presents/s as before; VSync on/off read back 1/0 from CGL. 21-level sweep (mac_sweep.sh, fixed binary): 21/21 OK. Windows build clean; Windows/Linux code paths unchanged (`#else` = the old lines).
|
||||||
|
|
||||||
|
**Status.** FIXED.
|
||||||
@@ -676,6 +676,8 @@ through a converter or a runtime bswap fixup reads scrambled.
|
|||||||
- **CPU-built RDP triangles need float vertices, not `Vtx` (D245).** Where GE builds RDP edge/texture coefficients on the CPU (sky/water), 32-bit S/T and positions are normal; squeezing them through s16 `tc`/`ob` costs visible precision on horizon-scale geometry. Use `G_FLOATVTX_EXT` (`port/include/floatvtx.h`).
|
- **CPU-built RDP triangles need float vertices, not `Vtx` (D245).** Where GE builds RDP edge/texture coefficients on the CPU (sky/water), 32-bit S/T and positions are normal; squeezing them through s16 `tc`/`ob` costs visible precision on horizon-scale geometry. Use `G_FLOATVTX_EXT` (`port/include/floatvtx.h`).
|
||||||
- **A first-run-only preset is skipped forever by any earlier launch that created the ini, and window keys are not an "untouched" signal (D283).** Seeding values *before* `configLoad()` only works when no `ge007.ini` exists; one launch in a different environment (SteamOS Desktop Mode has no `STEAMOS`) writes a plain ini and the preset never runs. Apply presets *after* the load, record a one-shot flag key, and gate on keys the user must change deliberately (`Video.Fullscreen`, `Window.Maximized`) — `Window.Width/Height` are rewritten from the live window on every clean exit (`videoSaveWindowState`), so "still at default" never holds for them.
|
- **A first-run-only preset is skipped forever by any earlier launch that created the ini, and window keys are not an "untouched" signal (D283).** Seeding values *before* `configLoad()` only works when no `ge007.ini` exists; one launch in a different environment (SteamOS Desktop Mode has no `STEAMOS`) writes a plain ini and the preset never runs. Apply presets *after* the load, record a one-shot flag key, and gate on keys the user must change deliberately (`Video.Fullscreen`, `Window.Maximized`) — `Window.Width/Height` are rewritten from the live window on every clean exit (`videoSaveWindowState`), so "still at default" never holds for them.
|
||||||
|
|
||||||
|
**SDL3 on macOS: a GL swap with VSync can wait forever (D952).** SDL3's Cocoa backend implements the GL swap interval itself: `SDL_GL_SwapWindow` waits, with no timeout, for a tick from a `CVDisplayLink` that SDL creates and starts once, with the context. If that link never runs (seen when the game starts while the display is asleep), the first swap never returns: black window, zero frames, every other thread waiting behind the render thread. Tells: `sample` shows `Cocoa_GL_SwapWindow -> SDL_WaitCondition*` on the render thread and the process has no `CVDisplayLink` thread. Fix pattern: leave SDL's interval at 0 and set `kCGLCPSwapInterval` on the context with `CGLSetParameter`, which waits in the driver (SDL2's behaviour). Reproduce with `pmset displaysleepnow` before launching.
|
||||||
|
|
||||||
## D. N64 hardware idioms fast3d does not emulate
|
## D. N64 hardware idioms fast3d does not emulate
|
||||||
|
|
||||||
- **Appending a port-owned 2D overlay to the game frame: hook inside
|
- **Appending a port-owned 2D overlay to the game frame: hook inside
|
||||||
|
|||||||
@@ -9,6 +9,9 @@
|
|||||||
#include "gfx_screen_config.h"
|
#include "gfx_screen_config.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "ge007_icon.h"
|
#include "ge007_icon.h"
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#include <OpenGL/OpenGL.h> /* D952: CGL swap interval */
|
||||||
|
#endif
|
||||||
|
|
||||||
extern "C" void videoRequestQuit(const char *why); // port/src/video.c (D344)
|
extern "C" void videoRequestQuit(const char *why); // port/src/video.c (D344)
|
||||||
extern "C" void inputRequestRescan(void); // port/src/input.c (D450)
|
extern "C" void inputRequestRescan(void); // port/src/input.c (D450)
|
||||||
@@ -18,6 +21,34 @@ static SDL_GLContext ctx;
|
|||||||
static SDL_Renderer* renderer;
|
static SDL_Renderer* renderer;
|
||||||
static int sdl_to_lus_table[512];
|
static int sdl_to_lus_table[512];
|
||||||
static bool vsync_enabled = true;
|
static bool vsync_enabled = true;
|
||||||
|
|
||||||
|
/* D952: macOS swap interval through CGL, not SDL. SDL3's Cocoa GL VSync makes
|
||||||
|
* SDL_GL_SwapWindow wait, with no timeout, for a tick from the CVDisplayLink it
|
||||||
|
* starts when the context is created. On some first launches of a never-seen
|
||||||
|
* binary that display link never starts (no CVDisplayLink thread in the hung
|
||||||
|
* process), so the first swap blocks forever: no frame, a black window. SDL's
|
||||||
|
* own interval stays 0 (its swap never waits) and CGL's kCGLCPSwapInterval does
|
||||||
|
* the VSync inside flushBuffer, as SDL2 did on macOS. Must be called with the
|
||||||
|
* context current (both callers are: init on the host thread, live config on
|
||||||
|
* the render thread). */
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
static int s_cglSwapInterval = 0;
|
||||||
|
static bool gfx_sdl_apply_swap_interval(int interval) {
|
||||||
|
SDL_GL_SetSwapInterval(0);
|
||||||
|
CGLContextObj cgl = CGLGetCurrentContext();
|
||||||
|
GLint v = interval ? 1 : 0;
|
||||||
|
if (!cgl || CGLSetParameter(cgl, kCGLCPSwapInterval, &v) != kCGLNoError) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
s_cglSwapInterval = v;
|
||||||
|
{
|
||||||
|
GLint back = -1;
|
||||||
|
CGLGetParameter(cgl, kCGLCPSwapInterval, &back);
|
||||||
|
sysLogPrintf(LOG_INFO, "SDL: swap interval %d via CGL (read back %d)", (int)v, (int)back);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
// OTRTODO: These are redundant. Info can be queried from SDL.
|
// OTRTODO: These are redundant. Info can be queried from SDL.
|
||||||
static int window_width = DESIRED_SCREEN_WIDTH;
|
static int window_width = DESIRED_SCREEN_WIDTH;
|
||||||
static int window_height = DESIRED_SCREEN_HEIGHT;
|
static int window_height = DESIRED_SCREEN_HEIGHT;
|
||||||
@@ -267,7 +298,11 @@ static void gfx_sdl_init(const struct GfxWindowInitSettings *set) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SDL_GL_MakeCurrent(wnd, ctx);
|
SDL_GL_MakeCurrent(wnd, ctx);
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
gfx_sdl_apply_swap_interval(1); /* D952 */
|
||||||
|
#else
|
||||||
SDL_GL_SetSwapInterval(1);
|
SDL_GL_SetSwapInterval(1);
|
||||||
|
#endif
|
||||||
|
|
||||||
// D550: window / taskbar icon = the project mark (generated by
|
// D550: window / taskbar icon = the project mark (generated by
|
||||||
// tools_pc/make_icon.py into ge007_icon.h; R,G,B,A byte order per
|
// tools_pc/make_icon.py into ge007_icon.h; R,G,B,A byte order per
|
||||||
@@ -631,11 +666,19 @@ static void gfx_sdl_set_window_title(const char *title) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int gfx_sdl_get_swap_interval(void) {
|
static int gfx_sdl_get_swap_interval(void) {
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
return s_cglSwapInterval; /* D952 */
|
||||||
|
#else
|
||||||
return SDL_GL_GetSwapInterval();
|
return SDL_GL_GetSwapInterval();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gfx_sdl_set_swap_interval(int interval) {
|
static bool gfx_sdl_set_swap_interval(int interval) {
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
const bool success = gfx_sdl_apply_swap_interval(interval); /* D952 */
|
||||||
|
#else
|
||||||
const bool success = SDL_GL_SetSwapInterval(interval) >= 0;
|
const bool success = SDL_GL_SetSwapInterval(interval) >= 0;
|
||||||
|
#endif
|
||||||
vsync_enabled = success && (interval != 0);
|
vsync_enabled = success && (interval != 0);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
sysLogPrintf(LOG_WARNING, "SDL: failed to set vsync %d: %s", interval, SDL_GetError());
|
sysLogPrintf(LOG_WARNING, "SDL: failed to set vsync %d: %s", interval, SDL_GetError());
|
||||||
|
|||||||
Reference in new issue
Block a user