[vlc-devel] [PATCH 3/3] linux: Add for kms vout plugin possibility to choose output display

Juha-Pekka Heikkila juhapekka.heikkila at gmail.com
Fri Aug 10 10:26:30 CEST 2018


Up to this point kms vout plugin chose first enumerated display to
be used for output. Now added parameter --kms-connector which will
accept number. List of available connectors are printed out by
kms vout plugin in debug prints when run in verbose mode.

Signed-off-by: Juha-Pekka Heikkila <juhapekka.heikkila at gmail.com>
---
 modules/video_output/kms.c | 179 +++++++++++++++++++++++++++------------------
 1 file changed, 108 insertions(+), 71 deletions(-)

diff --git a/modules/video_output/kms.c b/modules/video_output/kms.c
index e6e26a5..1f7f516 100644
--- a/modules/video_output/kms.c
+++ b/modules/video_output/kms.c
@@ -61,6 +61,10 @@
 #define DRM_CHROMA_TEXT "Image format used by DRM"
 #define DRM_CHROMA_LONGTEXT "Chroma fourcc override for DRM framebuffer format selection"
 
+#define DRM_CONNECTOR_PARAM "kms-connector"
+#define DRM_CONNECTOR_TEXT "Connector number"
+#define DRM_CONNECTOR_LONGTEXT "Connector number to use (defaults to first found connected)"
+
 /*
  * how many hw buffers are allocated for page flipping. I think
  * 3 is enough so we shouldn't get unexpected stall from kernel.
@@ -100,12 +104,14 @@ struct vout_display_sys_t {
     uint32_t        old_crtc_id;
     drmModeCrtc     *old_crtc;
     uint32_t        crtc;
+    uint32_t        crtc_index;
     uint32_t        plane_id;
 
 /*
  * other generic stuff
  */
     int             drm_fd;
+    int             requested_connector;
 };
 
 typedef struct {
@@ -242,10 +248,16 @@ static deviceRval FindCRTC(vout_display_t *vd, drmModeRes const *res,
         enc = drmModeGetEncoder(sys->drm_fd, conn->encoder_id);
         if (enc) {
             if (enc->crtc_id) {
-                msg_Dbg(vd, "Got CRTC %d from current encoder", enc->crtc_id);
-
                 sys->crtc = enc->crtc_id;
+                for (i = 0; i < res->count_crtcs; i++) {
+                    if (res->crtcs[i] == sys->crtc) {
+                        sys->crtc_index = i;
+                        break;
+                    }
+                }
                 drmModeFreeEncoder(enc);
+                msg_Dbg(vd, "Got CRTC %d:%d from current encoder",
+                        sys->crtc_index, sys->crtc);
                 return drvSuccess;
             }
             drmModeFreeEncoder(enc);
@@ -260,6 +272,15 @@ static deviceRval FindCRTC(vout_display_t *vd, drmModeRes const *res,
 
         for (j = 0; enc && j < res->count_crtcs; j++) {
             if (enc->possible_crtcs & (1 << j)) {
+
+                /* here maybe should be checked if now discovered CRTC is in
+                 * use somewhere else. When execution reach this point things
+                 * are bit fishy in any case so we'll skip that for now.
+                 * Result of 'stealing' CRTC is that other display will go
+                 * blank and to powersaving mode.
+                 */
+
+                sys->crtc_index = j;
                 sys->crtc = res->crtcs[j];
                 drmModeFreeEncoder(enc);
                 return drvSuccess;
@@ -273,45 +294,6 @@ static deviceRval FindCRTC(vout_display_t *vd, drmModeRes const *res,
 }
 
 
-static deviceRval SetupDevice(vout_display_t *vd, drmModeRes const *res,
-                             drmModeConnector const *conn)
-{
-    vout_display_sys_t *sys = vd->sys;
-    deviceRval ret;
-    int c, c2;
-
-    if (conn->connection != DRM_MODE_CONNECTED || conn->count_modes == 0)
-        return drvTryNext;
-
-    memcpy(&sys->used_mode, &conn->modes[0], sizeof(sys->used_mode));
-    sys->width = sys->used_mode.hdisplay;
-    sys->height = sys->used_mode.vdisplay;
-    msg_Dbg(vd, "Mode resolution is %ux%u", sys->width, sys->height);
-
-    ret = FindCRTC(vd, res, conn);
-    if (ret != drvSuccess) {
-        msg_Dbg(vd , "No valid CRTC for connector %d", conn->connector_id);
-        return ret;
-    }
-
-    for (c = 0; c < MAXHWBUF; c++) {
-        ret = CreateFB(vd, c);
-        if (ret != drvSuccess) {
-            msg_Err(vd, "Cannot create framebuffer %d for connector %d", c,
-                    conn->connector_id);
-            for (c2 = 0; c2 < c; c2++)
-                DestroyFB(sys, c2);
-
-            return ret;
-        } else {
-            msg_Dbg(vd, "Created HW framebuffer %d/%d", c+1, MAXHWBUF);
-        }
-    }
-    sys->connector_id = conn->connector_id;
-    return drvSuccess;
-}
-
-
 /** fourccmatching, matching drm to vlc fourccs and see if it was present
  * in HW. Here really is two lists, one in RGB and second in YUV. They're
  * listed in order of preference.
@@ -383,7 +365,7 @@ static bool ChromaNegotiation(vout_display_t *vd)
     sys->plane_id = 0;
 
     if (plane_res != NULL && plane_res->count_planes > 0) {
-        msg_Dbg(vd, "List of DRM supported modes on this machine:");
+        msg_Dbg(vd, "List of DRM supported modes on this CRTC:");
         for (c = 0; c < plane_res->count_planes; c++) {
 
             plane = drmModeGetPlane(sys->drm_fd, plane_res->planes[c]);
@@ -407,23 +389,25 @@ static bool ChromaNegotiation(vout_display_t *vd)
                     planetype = props->prop_values[propi];
                 }
 
-                for (i = 0; i < plane->count_formats; i++) {
-                    CheckFourCCList(plane->formats[i], plane->plane_id);
-
-                    if (sys->forced_drm_fourcc && sys->plane_id == 0 &&
-                            plane->formats[i] == sys->drm_fourcc) {
-                        sys->plane_id = plane->plane_id;
-                    }
-
-                    /*
-                     * we don't advertise about cursor plane because
-                     * of its special limitations.
-                     */
-                    if (planetype != DRM_PLANE_TYPE_CURSOR) {
-                        msg_Dbg(vd, "plane id %d type %s pipe %c format %2d: %.4s",
-                                plane->plane_id, types[planetype],
-                                ('@'+ffs(plane->possible_crtcs)), i,
-                                (char*)&plane->formats[i]);
+                if (plane->possible_crtcs & (1 << sys->crtc_index)) {
+                    for (i = 0; i < plane->count_formats; i++) {
+                        CheckFourCCList(plane->formats[i], plane->plane_id);
+
+                        if (sys->forced_drm_fourcc && sys->plane_id == 0 &&
+                                plane->formats[i] == sys->drm_fourcc) {
+                            sys->plane_id = plane->plane_id;
+                        }
+
+                        /*
+                         * we don't advertise about cursor plane because
+                         * of its special limitations.
+                         */
+                        if (planetype != DRM_PLANE_TYPE_CURSOR) {
+                            msg_Dbg(vd, "plane id %d type %s pipe %c format %2d: %.4s",
+                                    plane->plane_id, types[planetype],
+                                    ('@'+ffs(plane->possible_crtcs)), i,
+                                    (char*)&plane->formats[i]);
+                        }
                     }
                 }
                 drmModeFreePlane(plane);
@@ -502,6 +486,50 @@ static bool ChromaNegotiation(vout_display_t *vd)
 }
 
 
+static deviceRval SetupDevice(vout_display_t *vd, drmModeRes const *res,
+                             drmModeConnector const *conn)
+{
+    vout_display_sys_t *sys = vd->sys;
+    deviceRval ret;
+    int c, c2;
+
+    if (conn->connection != DRM_MODE_CONNECTED || conn->count_modes == 0)
+        return drvTryNext;
+
+    memcpy(&sys->used_mode, &conn->modes[1], sizeof(sys->used_mode));
+    sys->width = sys->used_mode.hdisplay;
+    sys->height = sys->used_mode.vdisplay;
+    msg_Dbg(vd, "Mode resolution is %ux%u", sys->width, sys->height);
+
+    ret = FindCRTC(vd, res, conn);
+    if (ret != drvSuccess) {
+        msg_Dbg(vd , "No valid CRTC for connector %d", conn->connector_id);
+        return ret;
+    }
+
+    sys->connector_id = conn->connector_id;
+
+    if (!ChromaNegotiation(vd))
+        return drvFail;
+
+
+    for (c = 0; c < MAXHWBUF; c++) {
+        ret = CreateFB(vd, c);
+        if (ret != drvSuccess) {
+            msg_Err(vd, "Cannot create framebuffer %d for connector %d", c,
+                    conn->connector_id);
+            for (c2 = 0; c2 < c; c2++)
+                DestroyFB(sys, c2);
+
+            return ret;
+        } else {
+            msg_Dbg(vd, "Created HW framebuffer %d/%d", c+1, MAXHWBUF);
+        }
+    }
+    return drvSuccess;
+}
+
+
 static int OpenDisplay(vout_display_t *vd)
 {
     vout_display_sys_t *sys = vd->sys;
@@ -558,12 +586,6 @@ static int OpenDisplay(vout_display_t *vd)
 
     drmSetClientCap(sys->drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
 
-    if (!ChromaNegotiation(vd))
-        goto err_out;
-
-    msg_Dbg(vd, "Using VLC chroma '%.4s', DRM chroma '%.4s'",
-            (char*)&sys->vlc_fourcc, (char*)&sys->drm_fourcc);
-
     ret = drmGetCap(sys->drm_fd, DRM_CAP_DUMB_BUFFER, &dumbRet);
     if (ret < 0 || !dumbRet) {
         msg_Err(vd, "Device '%s' does not support dumb buffers", psz_device);
@@ -589,7 +611,8 @@ static int OpenDisplay(vout_display_t *vd)
                 connectors[i].name,
                 (conn->connection==DRM_MODE_CONNECTED)?'X':' ');
 
-        if (sys->crtc != 0)
+        if (sys->crtc != 0 || (sys->requested_connector > 0 &&
+                               sys->requested_connector != c))
             continue;
 
         found_connector = true;
@@ -615,6 +638,9 @@ static int OpenDisplay(vout_display_t *vd)
     if (!found_connector)
         goto err_out;
 
+    msg_Dbg(vd, "Using VLC chroma '%.4s', DRM chroma '%.4s'",
+            (char*)&sys->vlc_fourcc, (char*)&sys->drm_fourcc);
+
     return VLC_SUCCESS;
 err_out:
     drmDropMaster(sys->drm_fd);
@@ -666,6 +692,7 @@ static picture_pool_t *Pool(vout_display_t *vd, unsigned count)
                           &sys->connector_id, 1,
                           &sys->used_mode)) {
             msg_Err(vd, "Cannot do modesetting");
+            drmModeFreeCrtc(sys->old_crtc);
             return NULL;
         }
 
@@ -678,8 +705,10 @@ static picture_pool_t *Pool(vout_display_t *vd, unsigned count)
         }
 
         psys = calloc(1, sizeof(*psys));
-        if (psys == NULL)
+        if (psys == NULL) {
+            drmModeFreeCrtc(sys->old_crtc);
             return NULL;
+        }
 
         psys->p_voutsys = sys;
         rsc.p_sys = psys;
@@ -688,13 +717,16 @@ static picture_pool_t *Pool(vout_display_t *vd, unsigned count)
         sys->picture = picture_NewFromResource(&vd->fmt, &rsc);
 
         if (!sys->picture) {
+            drmModeFreeCrtc(sys->old_crtc);
             free((void*)psys);
             return NULL;
         }
 
         sys->pool = picture_pool_New(1, &sys->picture);
-        if (!sys->pool)
+        if (!sys->pool) {
             picture_Release(sys->picture);
+            drmModeFreeCrtc(sys->old_crtc);
+        }
     }
 
     return sys->pool;
@@ -732,15 +764,14 @@ static void CloseDisplay(vout_display_t *vd)
     vout_display_sys_t *sys = vd->sys;
 
     if (sys->pool) {
-        if(drmModeSetCrtc(sys->drm_fd,
+        drmModeSetCrtc(sys->drm_fd,
                    sys->old_crtc->crtc_id,
                    sys->old_crtc->buffer_id,
                    sys->old_crtc->x,
                    sys->old_crtc->y,
                    &sys->connector_id,
                    1,
-                   &sys->old_crtc->mode))
-            msg_Err(vd, "error modeset xit");
+                   &sys->old_crtc->mode);
         drmModeFreeCrtc(sys->old_crtc);
 
         picture_pool_Release(sys->pool);
@@ -786,6 +817,10 @@ static int Open(vlc_object_t *object)
     if (!sys)
         return VLC_ENOMEM;
 
+    sys->requested_connector = var_InheritInteger(vd, DRM_CONNECTOR_PARAM);
+    if (sys->requested_connector > 0)
+        msg_Dbg(vd, "Requested connector #%d", sys->requested_connector);
+
     chroma = var_InheritString(vd, VLC_CHROMA_PARAM);
     if (chroma) {
         local_vlc_chroma = vlc_fourcc_GetCodecFromString(VIDEO_ES, chroma);
@@ -856,6 +891,8 @@ vlc_module_begin ()
                 true)
     add_string(DRM_CHROMA_PARAM, NULL, DRM_CHROMA_TEXT, DRM_CHROMA_LONGTEXT,
                 true)
+    add_integer(DRM_CONNECTOR_PARAM, -1, DRM_CONNECTOR_TEXT,
+                DRM_CONNECTOR_LONGTEXT, true)
     set_description("Linux kernel mode setting video output")
     set_capability("vout display", 30)
     set_callbacks(Open, Close)
-- 
2.7.4



More information about the vlc-devel mailing list