Skip to content

Commit 3fe82fb

Browse files
committed
SDL2: hardware-accelerated gfx_display + gfx_widgets backend
Brings the SDL2 video driver to feature parity with the modern menu drivers (XMB / Ozone / MaterialUI / RGUI) plus widgets, FPS overlay, Display Statistics, input overlay, and load-content animation. Previously the SDL2 driver only supported RGUI's software bitmap path: gfx_display dispatch was wired to no driver, get_overlay_interface was NULL, set_osd_msg unconditionally went through the legacy bitmap font, and the video size was never published to video_driver_set_size. Anything beyond RGUI either silently no-op'd or rendered to the wrong place against the wrong dimensions. This adds: - gfx_display_ctx_sdl2: * blend_begin / blend_end (SDL_RenderSetDrawBlendMode) * draw - two paths: a plain-quad path for gfx_display_draw_quad callers (vtx == NULL, n == 4) and a vertex-array path for slice / 9-patch / per-vertex-color callers. Both honour the canonical gl1_menu_vertexes triangle-strip layout (vertex 0 = bottom-left in GL bottom-up coords -> bottom-left in SDL screen space after Y flip), the top-down tex_coord convention from gfx_display.c, draw->scale_factor for XMB tab zoom, and draw->rotation for the spinning hourglass (rotate corners around centre using cosf/sinf). * scissor_begin / scissor_end (SDL_RenderSetClipRect, with the bottom-up to top-down flip RA's scissor convention requires). * pipeline draws (ribbon / snow / bokeh) are stubbed - SDL's high-level renderer doesn't expose custom shaders, so these return early and XMB falls back to the static gradient. - sdl2_raster_font: * FreeType atlas uploaded as ARGB8888 with white-RGB and the FreeType alpha (so SDL_SetTextureColorMod tints crisply). * render_msg with newline splitting via a render_message wrapper that walks '\n' and offsets each segment by one line-height (XMB sublabels and Display Statistics depend on this). * get_glyph / get_message_width / get_line_metrics for upstream consumers (font_flush no-ops; bind_block is unused, every call goes through immediate-draw). - poke->set_osd_msg dispatch: * Was the bug masking proper menu/widget text - the original driver hardcoded the bitmap OSD font. Now dispatches to the supplied font's render_msg when a font_data_t* is passed, falling back to the bitmap font only for the legacy font=NULL OSD path. - poke->load_texture / unload_texture: * Was NULL. Without it, gfx_white_texture is never registered and every plain-quad call has no source texture, so widgets and menu items rendered as solid-colour blocks with no alpha modulation. - get_overlay_interface (input overlay): * Six callbacks (enable, load, tex_geom, vertex_geom, full_screen, set_alpha) plus a per-frame render path. * Coordinate convention: vertex_geom stores values verbatim (no y-flip). SDL_RenderCopy operates in y-down pixel space like GDI's AlphaBlend, so the d3d/gl-style flip would be a bug here - mirrors gdi_overlay_vertex_geom. - Display Statistics overlay: * font_driver_init_osd / free_osd to register the SDL2 raster font as video_font_driver. Renders stat_text via font_driver_render_msg with osd_stat_params, suppressed while the menu is alive (matching gdi/d3d8/d3d9). - Frame-loop wiring: * menu_driver_frame, gfx_widgets_frame, the stats overlay, and the input overlay all need the full-window viewport rather than the aspect-corrected game viewport. Wrapped each in SDL_RenderGetViewport / SetViewport / restore so the next frame's core blit lands in the right place. - video_driver_set_size in sdl_refresh_viewport: * Tells the rest of RA the actual window size. Without it video_st->width/height retain core geometry (e.g. 320x240), widgets size themselves to that tiny coordinate space, and the entire UI ends up drawing into the top-left corner of the framebuffer. Mirrors what vga / gx2 / d3d8 / d3d9 common do. - Settings whitelist (configuration.c:check_menu_driver_compatibility): * Added 's' case so XMB / Ozone / MaterialUI no longer get rejected when the active video driver is sdl2. - sdl2_raster_font registered in: * gfx/font_driver.c (FONT_DRIVER_RENDER_SDL2 dispatch) * gfx/font_driver.h (extern declaration) * gfx/video_defines.h (FONT_DRIVER_RENDER_SDL2 enum) * gfx/gfx_display.c / .h (GFX_VIDEO_DRIVER_SDL2 enum + gfx_display_ctx_sdl2 entry in the drivers table) Requires SDL >= 2.0.18 for SDL_RenderGeometry; older SDL keeps the RGUI-only behaviour via #if SDL_VERSION_ATLEAST guards. Tested at 4K@120Hz fullscreen, plus all four menu drivers, the neo-retropad touch overlay, FPS / Display Statistics overlays, and the load-content animation against d3d9_hlsl as the reference backend. Visual output matches d3d9_hlsl pixel-for-pixel except for the deliberately-stubbed XMB pipeline shaders.
1 parent 475e590 commit 3fe82fb

8 files changed

Lines changed: 1516 additions & 5 deletions

File tree

configuration.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3599,6 +3599,15 @@ static bool check_menu_driver_compatibility(settings_t *settings)
35993599
return (memcmp(video_driver, "metal", 5) == 0 && video_driver[5] == '\0');
36003600
case 'r':
36013601
return (memcmp(video_driver, "rsx", 3) == 0 && video_driver[3] == '\0');
3602+
case 's':
3603+
/* sdl2 supports the full menu set (XMB/Ozone/MaterialUI/RGUI)
3604+
* via gfx_display_ctx_sdl2 + sdl2_raster_font, gated on
3605+
* SDL_RenderGeometry (>= 2.0.18). On older SDL builds the
3606+
* driver self-disables the gfx_display backend, and only
3607+
* RGUI's bitmap path is functional - which already returned
3608+
* true via the rgui early-out above, so allowing sdl2 here
3609+
* is safe regardless of the runtime SDL version. */
3610+
return (memcmp(video_driver, "sdl2", 4) == 0 && video_driver[4] == '\0');
36023611
case 'c':
36033612
return (memcmp(video_driver, "ctr", 3) == 0 && video_driver[3] == '\0');
36043613
default:

gfx/common/sdl2_common.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,31 @@ typedef struct _sdl2_video
6464
uint8_t font_b;
6565

6666
uint8_t flags;
67+
68+
#ifdef HAVE_OVERLAY
69+
/* On-screen input overlay state. Each entry holds an SDL_Texture
70+
* uploaded as ARGB8888 (matching the supports_rgba=false byte
71+
* layout RetroArch hands us in load()) and rendered via
72+
* SDL_RenderCopy with per-texture alpha modulation each frame.
73+
*
74+
* vert_coords / tex_coords are 4-float (x, y, w, h) tuples in
75+
* 0..1 normalised space. vertex_geom flips y to (1.0f - y) and
76+
* negates h, matching d3d8 / gl / d3d9_common; vertex_geom
77+
* comments document the rationale - we undo the flip at render
78+
* time in sdl2_overlays_render. */
79+
struct sdl2_overlay
80+
{
81+
SDL_Texture *tex;
82+
unsigned tex_w;
83+
unsigned tex_h;
84+
float tex_coords[4];
85+
float vert_coords[4];
86+
float alpha_mod;
87+
bool fullscreen;
88+
} *overlays;
89+
unsigned overlays_size;
90+
bool overlays_enabled;
91+
#endif
6792
} sdl2_video_t;
6893

6994
void sdl2_set_handles(void *data, enum rarch_display_type

0 commit comments

Comments
 (0)