SDL: Make newer DRM and GBM functions optional (10b4a)

From 10b4a79379d226041781d0a825da79a296af715f Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Mon, 2 Sep 2024 08:40:53 -0700
Subject: [PATCH] Make newer DRM and GBM functions optional

Fixes https://github.com/libsdl-org/SDL/issues/10675

(cherry picked from commit d501f6db07d4a067f7261d1ef51bec199f6d421f)
---
 src/video/kmsdrm/SDL_kmsdrmdyn.c   | 14 ++++++----
 src/video/kmsdrm/SDL_kmsdrmdyn.h   |  3 +++
 src/video/kmsdrm/SDL_kmsdrmsym.h   | 19 ++++++++-----
 src/video/kmsdrm/SDL_kmsdrmvideo.c | 43 ++++++++++++++++++------------
 4 files changed, 50 insertions(+), 29 deletions(-)

diff --git a/src/video/kmsdrm/SDL_kmsdrmdyn.c b/src/video/kmsdrm/SDL_kmsdrmdyn.c
index 750babbcdeefc..f96d230904ef0 100644
--- a/src/video/kmsdrm/SDL_kmsdrmdyn.c
+++ b/src/video/kmsdrm/SDL_kmsdrmdyn.c
@@ -47,7 +47,7 @@ static kmsdrmdynlib kmsdrmlibs[] = {
     { NULL, SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC }
 };
 
-static void *KMSDRM_GetSym(const char *fnname, int *pHasModule)
+static void *KMSDRM_GetSym(const char *fnname, int *pHasModule, SDL_bool required)
 {
     int i;
     void *fn = NULL;
@@ -67,7 +67,7 @@ static void *KMSDRM_GetSym(const char *fnname, int *pHasModule)
         SDL_Log("KMSDRM: Symbol '%s' NOT FOUND!\n", fnname);
 #endif
 
-    if (!fn) {
+    if (!fn && required) {
         *pHasModule = 0; /* kill this module. */
     }
 
@@ -80,6 +80,7 @@ static void *KMSDRM_GetSym(const char *fnname, int *pHasModule)
 #define SDL_KMSDRM_MODULE(modname)       int SDL_KMSDRM_HAVE_##modname = 0;
 #define SDL_KMSDRM_SYM(rc, fn, params)   SDL_DYNKMSDRMFN_##fn KMSDRM_##fn = NULL;
 #define SDL_KMSDRM_SYM_CONST(type, name) SDL_DYNKMSDRMCONST_##name KMSDRM_##name = NULL;
+#define SDL_KMSDRM_SYM_OPT(rc, fn, params)  SDL_DYNKMSDRMFN_##fn KMSDRM_##fn = NULL;
 #include "SDL_kmsdrmsym.h"
 
 static int kmsdrm_load_refcount = 0;
@@ -97,6 +98,7 @@ void SDL_KMSDRM_UnloadSymbols(void)
 #define SDL_KMSDRM_MODULE(modname)       SDL_KMSDRM_HAVE_##modname = 0;
 #define SDL_KMSDRM_SYM(rc, fn, params)   KMSDRM_##fn = NULL;
 #define SDL_KMSDRM_SYM_CONST(type, name) KMSDRM_##name = NULL;
+#define SDL_KMSDRM_SYM_OPT(rc, fn, params)  KMSDRM_##fn = NULL;
 #include "SDL_kmsdrmsym.h"
 
 #ifdef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC
@@ -130,9 +132,10 @@ int SDL_KMSDRM_LoadSymbols(void)
 #define SDL_KMSDRM_MODULE(modname) SDL_KMSDRM_HAVE_##modname = 1; /* default yes */
 #include "SDL_kmsdrmsym.h"
 
-#define SDL_KMSDRM_MODULE(modname)       thismod = &SDL_KMSDRM_HAVE_##modname;
-#define SDL_KMSDRM_SYM(rc, fn, params)   KMSDRM_##fn = (SDL_DYNKMSDRMFN_##fn)KMSDRM_GetSym(#fn, thismod);
-#define SDL_KMSDRM_SYM_CONST(type, name) KMSDRM_##name = *(SDL_DYNKMSDRMCONST_##name *)KMSDRM_GetSym(#name, thismod);
+#define SDL_KMSDRM_MODULE(modname)          thismod = &SDL_KMSDRM_HAVE_##modname;
+#define SDL_KMSDRM_SYM(rc, fn, params)      KMSDRM_##fn = (SDL_DYNKMSDRMFN_##fn)KMSDRM_GetSym(#fn, thismod, SDL_TRUE);
+#define SDL_KMSDRM_SYM_CONST(type, name)    KMSDRM_##name = *(SDL_DYNKMSDRMCONST_##name *)KMSDRM_GetSym(#name, thismod, SDL_TRUE);
+#define SDL_KMSDRM_SYM_OPT(rc, fn, params)  KMSDRM_##fn = (SDL_DYNKMSDRMFN_##fn)KMSDRM_GetSym(#fn, thismod, SDL_FALSE);
 #include "SDL_kmsdrmsym.h"
 
         if ((SDL_KMSDRM_HAVE_LIBDRM) && (SDL_KMSDRM_HAVE_GBM)) {
@@ -149,6 +152,7 @@ int SDL_KMSDRM_LoadSymbols(void)
 #define SDL_KMSDRM_MODULE(modname)       SDL_KMSDRM_HAVE_##modname = 1; /* default yes */
 #define SDL_KMSDRM_SYM(rc, fn, params)   KMSDRM_##fn = fn;
 #define SDL_KMSDRM_SYM_CONST(type, name) KMSDRM_##name = name;
+#define SDL_KMSDRM_SYM_OPT(rc, fn, params)  KMSDRM_##fn = fn;
 #include "SDL_kmsdrmsym.h"
 
 #endif
diff --git a/src/video/kmsdrm/SDL_kmsdrmdyn.h b/src/video/kmsdrm/SDL_kmsdrmdyn.h
index e6da337921ad2..633a20eea0686 100644
--- a/src/video/kmsdrm/SDL_kmsdrmdyn.h
+++ b/src/video/kmsdrm/SDL_kmsdrmdyn.h
@@ -42,6 +42,9 @@ void SDL_KMSDRM_UnloadSymbols(void);
 #define SDL_KMSDRM_SYM_CONST(type, name)    \
     typedef type SDL_DYNKMSDRMCONST_##name; \
     extern SDL_DYNKMSDRMCONST_##name KMSDRM_##name;
+#define SDL_KMSDRM_SYM_OPT(rc, fn, params)    \
+    typedef rc(*SDL_DYNKMSDRMFN_##fn) params; \
+    extern SDL_DYNKMSDRMFN_##fn KMSDRM_##fn;
 #include "SDL_kmsdrmsym.h"
 
 #ifdef __cplusplus
diff --git a/src/video/kmsdrm/SDL_kmsdrmsym.h b/src/video/kmsdrm/SDL_kmsdrmsym.h
index 7a99e1b6a3302..df4621207ef3f 100644
--- a/src/video/kmsdrm/SDL_kmsdrmsym.h
+++ b/src/video/kmsdrm/SDL_kmsdrmsym.h
@@ -33,6 +33,10 @@
 #define SDL_KMSDRM_SYM_CONST(type, name)
 #endif
 
+#ifndef SDL_KMSDRM_SYM_OPT
+#define SDL_KMSDRM_SYM_OPT(rc,fn,params)
+#endif
+
 
 SDL_KMSDRM_MODULE(LIBDRM)
 SDL_KMSDRM_SYM(void,drmModeFreeResources,(drmModeResPtr ptr))
@@ -49,12 +53,12 @@ SDL_KMSDRM_SYM(int,drmModeAddFB,(int fd, uint32_t width, uint32_t height, uint8_
                          uint8_t bpp, uint32_t pitch, uint32_t bo_handle,
                          uint32_t *buf_id))
 
-SDL_KMSDRM_SYM(int,drmModeAddFB2,(int fd, uint32_t width, uint32_t height,
+SDL_KMSDRM_SYM_OPT(int,drmModeAddFB2,(int fd, uint32_t width, uint32_t height,
                          uint32_t pixel_format, const uint32_t bo_handles[4],
                          const uint32_t pitches[4], const uint32_t offsets[4],
                          uint32_t *buf_id, uint32_t flags))
 
-SDL_KMSDRM_SYM(int,drmModeAddFB2WithModifiers,(int fd, uint32_t width,
+SDL_KMSDRM_SYM_OPT(int,drmModeAddFB2WithModifiers,(int fd, uint32_t width,
                          uint32_t height, uint32_t pixel_format, const uint32_t bo_handles[4],
                          const uint32_t pitches[4], const uint32_t offsets[4],
                          const uint64_t modifier[4], uint32_t *buf_id, uint32_t flags))
@@ -129,15 +133,16 @@ SDL_KMSDRM_SYM(void,gbm_surface_destroy,(struct gbm_surface *surf))
 SDL_KMSDRM_SYM(struct gbm_bo *,gbm_surface_lock_front_buffer,(struct gbm_surface *surf))
 SDL_KMSDRM_SYM(void,gbm_surface_release_buffer,(struct gbm_surface *surf, struct gbm_bo *bo))
 
-SDL_KMSDRM_SYM(uint64_t,gbm_bo_get_modifier,(struct gbm_bo *bo))
-SDL_KMSDRM_SYM(int,gbm_bo_get_plane_count,(struct gbm_bo *bo))
-SDL_KMSDRM_SYM(uint32_t,gbm_bo_get_offset,(struct gbm_bo *bo, int plane))
-SDL_KMSDRM_SYM(uint32_t,gbm_bo_get_stride_for_plane,(struct gbm_bo *bo, int plane))
-SDL_KMSDRM_SYM(union gbm_bo_handle,gbm_bo_get_handle_for_plane,(struct gbm_bo *bo, int plane);)
+SDL_KMSDRM_SYM_OPT(uint64_t,gbm_bo_get_modifier,(struct gbm_bo *bo))
+SDL_KMSDRM_SYM_OPT(int,gbm_bo_get_plane_count,(struct gbm_bo *bo))
+SDL_KMSDRM_SYM_OPT(uint32_t,gbm_bo_get_offset,(struct gbm_bo *bo, int plane))
+SDL_KMSDRM_SYM_OPT(uint32_t,gbm_bo_get_stride_for_plane,(struct gbm_bo *bo, int plane))
+SDL_KMSDRM_SYM_OPT(union gbm_bo_handle,gbm_bo_get_handle_for_plane,(struct gbm_bo *bo, int plane))
 
 #undef SDL_KMSDRM_MODULE
 #undef SDL_KMSDRM_SYM
 #undef SDL_KMSDRM_SYM_CONST
+#undef SDL_KMSDRM_SYM_OPT
 
 /* *INDENT-ON* */ /* clang-format on */
 
diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c
index b7abb4fc785f5..7cd538c942064 100644
--- a/src/video/kmsdrm/SDL_kmsdrmvideo.c
+++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c
@@ -336,8 +336,9 @@ KMSDRM_FBInfo *KMSDRM_FBFromBO(_THIS, struct gbm_bo *bo)
 {
     SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
     unsigned w, h;
-    int ret, num_planes = 0;
-    Uint32 format, strides[4] = { 0 }, handles[4] = { 0 }, offsets[4] = { 0 }, flags = 0;
+    int rc = -1;
+    int num_planes = 0;
+    uint32_t format, strides[4] = { 0 }, handles[4] = { 0 }, offsets[4] = { 0 }, flags = 0;
     uint64_t modifiers[4] = { 0 };
 
     /* Check for an existing framebuffer */
@@ -364,28 +365,36 @@ KMSDRM_FBInfo *KMSDRM_FBFromBO(_THIS, struct gbm_bo *bo)
     h = KMSDRM_gbm_bo_get_height(bo);
     format = KMSDRM_gbm_bo_get_format(bo);
 
-    modifiers[0] = KMSDRM_gbm_bo_get_modifier(bo);
-    num_planes = KMSDRM_gbm_bo_get_plane_count(bo);
-    for (int i = 0; i < num_planes; i++) {
-        strides[i] = KMSDRM_gbm_bo_get_stride_for_plane(bo, i);
-        handles[i] = KMSDRM_gbm_bo_get_handle_for_plane(bo, i).u32;
-        offsets[i] = KMSDRM_gbm_bo_get_offset(bo, i);
-        modifiers[i] = modifiers[0];
-    }
+    if (KMSDRM_drmModeAddFB2WithModifiers &&
+        KMSDRM_gbm_bo_get_modifier &&
+        KMSDRM_gbm_bo_get_plane_count &&
+        KMSDRM_gbm_bo_get_offset &&
+        KMSDRM_gbm_bo_get_stride_for_plane &&
+        KMSDRM_gbm_bo_get_handle_for_plane) {
+
+        modifiers[0] = KMSDRM_gbm_bo_get_modifier(bo);
+        num_planes = KMSDRM_gbm_bo_get_plane_count(bo);
+        for (int i = 0; i < num_planes; i++) {
+            strides[i] = KMSDRM_gbm_bo_get_stride_for_plane(bo, i);
+            handles[i] = KMSDRM_gbm_bo_get_handle_for_plane(bo, i).u32;
+            offsets[i] = KMSDRM_gbm_bo_get_offset(bo, i);
+            modifiers[i] = modifiers[0];
+        }
 
-    if (modifiers[0] && modifiers[0] != DRM_FORMAT_MOD_INVALID) {
-        flags = DRM_MODE_FB_MODIFIERS;
-    }
+        if (modifiers[0] && modifiers[0] != DRM_FORMAT_MOD_INVALID) {
+            flags = DRM_MODE_FB_MODIFIERS;
+        }
 
-    ret = KMSDRM_drmModeAddFB2WithModifiers(viddata->drm_fd, w, h, format, handles, strides, offsets, modifiers, &fb_info->fb_id, flags);
+        rc = KMSDRM_drmModeAddFB2WithModifiers(viddata->drm_fd, w, h, format, handles, strides, offsets, modifiers, &fb_info->fb_id, flags);
+    }
 
-    if (ret) {
+    if (rc < 0) {
         strides[0] = KMSDRM_gbm_bo_get_stride(bo);
         handles[0] = KMSDRM_gbm_bo_get_handle(bo).u32;
-        ret = KMSDRM_drmModeAddFB(viddata->drm_fd, w, h, 24, 32, strides[0], handles[0], &fb_info->fb_id);
+        rc = KMSDRM_drmModeAddFB(viddata->drm_fd, w, h, 24, 32, strides[0], handles[0], &fb_info->fb_id);
     }
 
-    if (ret) {
+    if (rc < 0) {
         SDL_free(fb_info);
         return NULL;
     }