#ifndef PSX_GPU_GL_RENDERER_H #define PSX_GPU_GL_RENDERER_H /* GL backend context + present entry points, called from main.cpp's window * setup and present path when [video] renderer = "opengl". The backend's * rasterization vtable is obtained separately via gl_backend_get() * (gpu_render.h). SDL_Window is forward-declared (SDL typedefs it from this * same struct tag) so this header needs no SDL include. */ #include struct SDL_Window; #ifdef __cplusplus extern "C" { #endif /* Create the GL context on a window made with SDL_WINDOW_OPENGL. * Returns 1 on success, 0 to fall back to the SDL_Renderer present path. */ int gl_renderer_init_context(struct SDL_Window *win); /* Set the GL swap interval / vsync mode (1=vsync, 0=immediate, -1=adaptive). * Safe before or after context creation; applies live when a context exists. */ void gl_renderer_set_swap_interval(int interval); /* Present an ARGB8888 image (BGRA byte order) as a letterboxed quad + swap. * Used for 24-bit (FMV) frames and the PSX_GL_FORCE_CPU_PRESENT diagnostic. * force_4_3 = pillarbox at native 4:3 even on a wide display aspect (FMVs * are authored 4:3 and get no GTE squash to compensate the stretch). */ void gl_renderer_present(const uint32_t *pixels, int src_w, int src_h, int linear, int force_4_3); /* Clear to black + swap (display-disabled frame). */ void gl_renderer_present_blank(void); /* Sync the authoritative FBO down to CPU VRAM if the GPU side is ahead (else * a no-op). The 24-bit (FMV) present path, screenshots, and the debug server * call this before reading CPU VRAM. */ void gl_renderer_sync_cpu(void); /* THE present path for 15-bit frames: blit the display region straight from * the authoritative VRAM FBO into a letterboxed rect (no readback). * Deterministic — used for every 15-bit frame. linear = filter on scale. * force_4_3 pins to native 4:3 (15-bit MDEC FMV frames on a wide aspect). */ void gl_renderer_present_vram(int disp_x, int disp_y, int w, int h, int linear, int force_4_3); /* GPU-direct native-wide present: blit the displayed buffer's wide FBO (key = * disp_x) straight to the window, no CPU readback. Returns 0 if no wide surface * exists for disp_x (caller falls back to the CPU readout path). */ int gl_renderer_present_wide_fbo(int disp_x, int disp_y, int disp_h, int linear); /* Display aspect for the present letterbox (default 4:3). A wide aspect * stretches the 4:3 frame; pair with gte_set_display_aspect (cpu_state.h) * for the widescreen field-of-view hack. */ void gl_renderer_set_display_aspect(int num, int den); void gl_renderer_shutdown(void); /* Diagnostics (debug server): read GPU-side VRAM without touching the CPU * array; report coherency flags + dirty rects. fbo_peek returns 0 when the * GL pipeline is inactive. */ int gl_renderer_fbo_peek(int x, int y, int w, int h, uint16_t *out); void gl_renderer_diag(int *gpu_dirty, int pending[5], int pack[5]); /* Always-on coherency event ring (debug server "gl_coh_ring"): every upload * flush, fill, copy, draw bbox, pack, full readback, present, and probe * perturbation, with rect + frame. An op that flushes internally records its * own event AFTER the FLUSH it caused (the event after a FLUSH = trigger). */ enum { GL_COH_FLUSH = 1, /* CPU->FBO upload flush (pending box) */ GL_COH_FILL = 2, /* GP0(02) fill rect */ GL_COH_COPY_SRC = 3, /* GP0(80) copy, source rect */ GL_COH_COPY = 4, /* GP0(80) copy, dest rect */ GL_COH_DRAW = 5, /* drawn prim bbox (clipped to draw area) */ GL_COH_PACK = 6, /* hr FBO -> raw mirror pack (dirty box) */ GL_COH_ENSURE = 7, /* full FBO -> CPU VRAM readback */ GL_COH_PRESENT = 8, /* 15-bit present blit (display rect) */ GL_COH_UPLOAD = 9, /* bulk CPU->VRAM transfer_in dest rect */ GL_COH_PEEK = 10, /* gl_fbo_peek probe (perturbs: flushes) */ GL_COH_DIFF = 11, /* gl_vram_diff probe (perturbs: flushes) */ }; typedef struct { uint32_t frame; uint8_t kind; int16_t x0, y0, x1, y1; /* native VRAM coords, inclusive */ } GlCohEvent; uint64_t gl_renderer_coh_total(void); /* Fetch event by absolute sequence number; 0 if evicted or out of range. */ int gl_renderer_coh_get(uint64_t seq, GlCohEvent *out); /* frame_perf: aggregate the per-frame GPU/CPU phase-timing ring (debug server * "frame_perf"). wide_filter: -1 = all frames, 0 = 4:3 present, 1 = native-wide. * Fills out[9]: [0]=count, [1]=total_ms avg, [2]=total_ms max, [3]=emu_cpu_ms avg * (frame minus the present call), [4]=present_wall_ms avg, [5]=scene_gpu_ms avg, * [6]=scene_gpu_ms max, [7]=present_gpu_ms avg, [8]=present_gpu_ms max, * [9]=scene primitives/frame avg (pre double-draw). GPU phases are true * GL_TIME_ELAPSED times (CPU-overhead independent). Returns the count. */ int gl_renderer_perf_aggregate(int wide_filter, double out[10]); /* Cumulative textured fraction of scene primitives since boot (flat vs textured * batching decision). Sets *out_tex_frac; returns total prim count. */ uint64_t gl_renderer_perf_prim_split(double *out_tex_frac); #ifdef __cplusplus } #endif #endif /* PSX_GPU_GL_RENDERER_H */