[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