SDL: KMSDRM: Add hint to enable the backend without DRM master

From dfa64eadd38a6a8125290dcf121f1bc285e98dad Mon Sep 17 00:00:00 2001
From: Cameron Gutman <[EMAIL REDACTED]>
Date: Thu, 25 Feb 2021 19:22:31 -0600
Subject: [PATCH] KMSDRM: Add hint to enable the backend without DRM master

In some cases, it can be useful to have the KMSDRM backend even if it cannot
be used for rendering. An app may want to use SDL for input processing while
using another rendering API (such as an MMAL overlay on Raspberry Pi) or
using its own code to render to DRM overlays that SDL doesn't support.

This also moves the check for DRM master to an earlier point where we can fail
initialization of the backend, rather than allowing the backend to initialize
then failing the creation of a window later.
---
 include/SDL_hints.h                | 23 +++++++++++++++++++++++
 src/video/kmsdrm/SDL_kmsdrmvideo.c | 14 ++++++++------
 2 files changed, 31 insertions(+), 6 deletions(-)

diff --git a/include/SDL_hints.h b/include/SDL_hints.h
index 5c320dc29..6b3f4690e 100644
--- a/include/SDL_hints.h
+++ b/include/SDL_hints.h
@@ -1324,6 +1324,29 @@ extern "C" {
  */
 #define SDL_HINT_VIDEO_DOUBLE_BUFFER      "SDL_VIDEO_DOUBLE_BUFFER"
 
+/**
+ * \brief Determines whether SDL enforces that DRM master is required in order
+ *        to initialize the KMSDRM video backend.
+ *
+ * The DRM subsystem has a concept of a "DRM master" which is a DRM client that
+ * has the ability to set planes, set cursor, etc. When SDL is DRM master, it
+ * can draw to the screen using the SDL rendering APIs. Without DRM master, SDL
+ * is still able to process input and query attributes of attached displays,
+ * but it cannot change display state or draw to the screen directly.
+ *
+ * In some cases, it can be useful to have the KMSDRM backend even if it cannot
+ * be used for rendering. An app may want to use SDL for input processing while
+ * using another rendering API (such as an MMAL overlay on Raspberry Pi) or
+ * using its own code to render to DRM overlays that SDL doesn't support.
+ *
+ * This hint must be set before initializing the video subsystem.
+ *
+ * This variable can be set to the following values:
+ *    "0"       - SDL will allow usage of the KMSDRM backend without DRM master
+ *    "1"       - SDL Will require DRM master to use the KMSDRM backend (default)
+ */
+#define SDL_HINT_KMSDRM_REQUIRE_DRM_MASTER      "SDL_KMSDRM_REQUIRE_DRM_MASTER"
+
 /**
  *  \brief  A variable controlling what driver to use for OpenGL ES contexts.
  *
diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c
index b0967d1af..b52b545cb 100644
--- a/src/video/kmsdrm/SDL_kmsdrmvideo.c
+++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c
@@ -100,6 +100,14 @@ check_modestting(int devindex)
                         }
 
                         if (conn->connection == DRM_MODE_CONNECTED && conn->count_modes) {
+                            if (SDL_GetHintBoolean(SDL_HINT_KMSDRM_REQUIRE_DRM_MASTER, SDL_TRUE)) {
+                                /* Skip this device if we can't obtain DRM master */
+                                KMSDRM_drmSetMaster(drm_fd);
+                                if (KMSDRM_drmAuthMagic(drm_fd, 0) == -EACCES) {
+                                    continue;
+                                }
+                            }
+
                             available = SDL_TRUE;
                             break;
                         }
@@ -773,12 +781,6 @@ KMSDRM_GBMInit (_THIS, SDL_DisplayData *dispdata)
     /* Set the FD we just opened as current DRM master. */
     KMSDRM_drmSetMaster(viddata->drm_fd);
 
-    /* Check if we are the current DRM master. */
-    if (KMSDRM_drmAuthMagic(viddata->drm_fd, 0) == -EACCES) {
-        ret = SDL_SetError("DRM device is claimed by another program as master.");
-        return ret;
-    }
-
     /* Create the GBM device. */
     viddata->gbm_dev = KMSDRM_gbm_create_device(viddata->drm_fd);
     if (!viddata->gbm_dev) {