SDL: kmsdrm: enable vrr on displays that support it

From ad874536a4be9b602a0b2bc1f95a21e4a06e1876 Mon Sep 17 00:00:00 2001
From: antonino <[EMAIL REDACTED]>
Date: Wed, 17 Aug 2022 14:56:18 +0200
Subject: [PATCH] kmsdrm: enable vrr on displays that support it

---
 src/video/kmsdrm/SDL_kmsdrmsym.h   |  3 +
 src/video/kmsdrm/SDL_kmsdrmvideo.c | 93 ++++++++++++++++++++++++++++++
 2 files changed, 96 insertions(+)

diff --git a/src/video/kmsdrm/SDL_kmsdrmsym.h b/src/video/kmsdrm/SDL_kmsdrmsym.h
index f53c5c8ead9..4fdce52927c 100644
--- a/src/video/kmsdrm/SDL_kmsdrmsym.h
+++ b/src/video/kmsdrm/SDL_kmsdrmsym.h
@@ -80,6 +80,9 @@ SDL_KMSDRM_SYM(int,drmSetClientCap,(int fd, uint64_t capability, uint64_t value)
 SDL_KMSDRM_SYM(drmModePlaneResPtr,drmModeGetPlaneResources,(int fd))
 SDL_KMSDRM_SYM(drmModePlanePtr,drmModeGetPlane,(int fd, uint32_t plane_id))
 SDL_KMSDRM_SYM(drmModeObjectPropertiesPtr,drmModeObjectGetProperties,(int fd,uint32_t object_id,uint32_t object_type))
+SDL_KMSDRM_SYM(int,drmModeObjectSetProperty,(int fd, uint32_t object_id,
+                                             uint32_t object_type, uint32_t property_id,
+                                             uint64_t value))
 SDL_KMSDRM_SYM(drmModePropertyPtr,drmModeGetProperty,(int fd, uint32_t propertyId))
 
 SDL_KMSDRM_SYM(void,drmModeFreeProperty,(drmModePropertyPtr ptr))
diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c
index def72334ba0..821dc183afb 100644
--- a/src/video/kmsdrm/SDL_kmsdrmvideo.c
+++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c
@@ -534,6 +534,93 @@ KMSDRM_DeinitDisplays (_THIS) {
     }
 }
 
+static uint32_t
+KMSDRM_CrtcGetPropId(uint32_t drm_fd,
+                         drmModeObjectPropertiesPtr props,
+                         char const* name)
+{
+    uint32_t i, prop_id = 0;
+
+    for (i = 0; !prop_id && i < props->count_props; ++i) {
+        drmModePropertyPtr drm_prop =
+                     KMSDRM_drmModeGetProperty(drm_fd, props->props[i]);
+
+        if (!drm_prop)
+            continue;
+
+        if (strcmp(drm_prop->name, name) == 0)
+            prop_id = drm_prop->prop_id;
+
+        KMSDRM_drmModeFreeProperty(drm_prop);
+   }
+
+    return prop_id;
+}
+
+static uint32_t KMSDRM_VrrPropId(uint32_t drm_fd, uint32_t crtc_id) {
+    drmModeObjectPropertiesPtr drm_props;
+    uint32_t vrr_prop_id;
+
+    drm_props = KMSDRM_drmModeObjectGetProperties(drm_fd,
+                                           crtc_id,
+                                           DRM_MODE_OBJECT_CRTC);
+
+    if (!drm_props)
+        exit(-1);
+
+    vrr_prop_id = KMSDRM_CrtcGetPropId(drm_fd,
+                                       drm_props,
+                                       "VRR_ENABLED");
+
+    KMSDRM_drmModeFreeObjectProperties(drm_props);
+
+    return vrr_prop_id;
+}
+
+static SDL_bool 
+KMSDRM_ConnectorCheckVrrCapable(uint32_t drm_fd,
+                         uint32_t output_id,
+                         char const* name)
+{
+    uint32_t i;
+    Bool found = SDL_FALSE;
+    uint64_t prop_value = 0;
+
+
+    drmModeObjectPropertiesPtr props = KMSDRM_drmModeObjectGetProperties(drm_fd,
+                                       output_id,
+                                       DRM_MODE_OBJECT_CONNECTOR);
+
+    for (i = 0; !found && i < props->count_props; ++i) {
+        drmModePropertyPtr drm_prop = KMSDRM_drmModeGetProperty(drm_fd, props->props[i]);
+
+        if (!drm_prop)
+            continue;
+
+        if (strcasecmp(drm_prop->name, name) == 0) {
+            prop_value = props->prop_values[i];
+            found = SDL_TRUE;
+        }
+
+        KMSDRM_drmModeFreeProperty(drm_prop);
+    }
+    if(found)
+        return prop_value ? SDL_TRUE: SDL_FALSE;
+
+    return SDL_FALSE;
+}
+
+void
+KMSDRM_CrtcSetVrr(uint32_t drm_fd, uint32_t crtc_id, Bool enabled)
+{
+    uint32_t vrr_prop_id = KMSDRM_VrrPropId(drm_fd, crtc_id);
+
+    KMSDRM_drmModeObjectSetProperty(drm_fd,
+                             crtc_id,
+                             DRM_MODE_OBJECT_CRTC,
+                             vrr_prop_id,
+                             enabled);
+}
 /* Gets a DRM connector, builds an SDL_Display with it, and adds it to the
    list of SDL Displays in _this->displays[]  */
 static void
@@ -701,6 +788,12 @@ KMSDRM_AddDisplay (_THIS, drmModeConnector *connector, drmModeRes *resources) {
     /* Add the display to the list of SDL displays. */
     SDL_AddVideoDisplay(&display, SDL_FALSE);
 
+    /* try to enable vrr */
+    if(KMSDRM_ConnectorCheckVrrCapable(viddata->drm_fd, connector->connector_id, "VRR_CAPABLE")) {
+        SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Enabling VRR");
+        KMSDRM_CrtcSetVrr(viddata->drm_fd, crtc->crtc_id, SDL_TRUE);
+    }
+
 cleanup:
     if (encoder)
         KMSDRM_drmModeFreeEncoder(encoder);