summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/vo.rst14
-rw-r--r--options/options.c9
-rw-r--r--options/options.h3
-rw-r--r--video/out/drm_common.c290
-rw-r--r--video/out/drm_common.h20
-rw-r--r--video/out/opengl/context_drm_egl.c52
-rw-r--r--video/out/vo_drm.c74
7 files changed, 293 insertions, 169 deletions
diff --git a/DOCS/man/vo.rst b/DOCS/man/vo.rst
index f352c46608..34302f9a3f 100644
--- a/DOCS/man/vo.rst
+++ b/DOCS/man/vo.rst
@@ -495,13 +495,13 @@ Available video output drivers are:
The following global options are supported by this video output:
- ``--drm-connector=<number>``
- Select the connector to use (usually this is a monitor.) If set to -1,
- mpv renders the output on the first available connector. (default: -1)
-
- ``--drm-devpath=<filename>``
- Path to graphic card device.
- (default: /dev/dri/card0)
+ ``--drm-connector=[<gpu_number>.]<name>``
+ Select the connector to use (usually this is a monitor.) If ``<name>``
+ is empty or ``auto``, mpv renders the output on the first available
+ connector. Use ``--drm-connector=help`` to get list of available
+ connectors. When using multiple graphic cards, use the ``<gpu_number>``
+ argument to disambiguate.
+ (default: empty)
``--drm-mode=<number>``
Mode ID to use (resolution, bit depth and frame rate).
diff --git a/options/options.c b/options/options.c
index 93a76e5d41..38f5d16721 100644
--- a/options/options.c
+++ b/options/options.c
@@ -48,6 +48,10 @@
#include "player/command.h"
#include "stream/stream.h"
+#if HAVE_DRM
+#include "video/out/drm_common.h"
+#endif
+
extern const char mp_help_text[];
static void print_version(struct mp_log *log)
@@ -190,6 +194,11 @@ static const m_option_t mp_vo_opt_list[] = {
#if HAVE_WIN32
OPT_STRING("vo-mmcss-profile", mmcss_profile, 0),
#endif
+#if HAVE_DRM
+ OPT_STRING_VALIDATE("drm-connector", drm_connector_spec,
+ 0, drm_validate_connector_opt),
+ OPT_INT("drm-mode", drm_mode_id, 0),
+#endif
{0}
};
diff --git a/options/options.h b/options/options.h
index db12742f2b..160223d3e1 100644
--- a/options/options.h
+++ b/options/options.h
@@ -51,6 +51,9 @@ typedef struct mp_vo_opts {
struct sws_opts *sws_opts;
// vo_opengl, vo_opengl_cb
int hwdec_preload_api;
+ // vo_drm
+ char *drm_connector_spec;
+ int drm_mode_id;
} mp_vo_opts;
struct mp_cache_opts {
diff --git a/video/out/drm_common.c b/video/out/drm_common.c
index 8a4e017d28..44e017e4b2 100644
--- a/video/out/drm_common.c
+++ b/video/out/drm_common.c
@@ -16,9 +16,11 @@
*/
#include <errno.h>
+#include <string.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/poll.h>
+#include <sys/stat.h>
#include <sys/vt.h>
#include <unistd.h>
@@ -35,71 +37,114 @@
#define HANDLER_RELEASE 1
#define RELEASE_SIGNAL SIGUSR1
#define ACQUIRE_SIGNAL SIGUSR2
+#define MAX_CONNECTOR_NAME_LEN 20
static int vt_switcher_pipe[2];
+static const char *connector_names[] = {
+ "Unknown", // DRM_MODE_CONNECTOR_Unknown
+ "VGA", // DRM_MODE_CONNECTOR_VGA
+ "DVI-I", // DRM_MODE_CONNECTOR_DVII
+ "DVI-D", // DRM_MODE_CONNECTOR_DVID
+ "DVI-A", // DRM_MODE_CONNECTOR_DVIA
+ "Composite", // DRM_MODE_CONNECTOR_Composite
+ "SVIDEO", // DRM_MODE_CONNECTOR_SVIDEO
+ "LVDS", // DRM_MODE_CONNECTOR_LVDS
+ "Component", // DRM_MODE_CONNECTOR_Component
+ "DIN", // DRM_MODE_CONNECTOR_9PinDIN
+ "DP", // DRM_MODE_CONNECTOR_DisplayPort
+ "HDMI-A", // DRM_MODE_CONNECTOR_HDMIA
+ "HDMI-B", // DRM_MODE_CONNECTOR_HDMIB
+ "TV", // DRM_MODE_CONNECTOR_TV
+ "eDP", // DRM_MODE_CONNECTOR_eDP
+ "Virtual", // DRM_MODE_CONNECTOR_VIRTUAL
+ "DSI", // DRM_MODE_CONNECTOR_DSI
+ "DPI", // DRM_MODE_CONNECTOR_DPI
+};
+
// KMS ------------------------------------------------------------------------
-static bool is_connector_valid(struct kms *kms, int connector_id,
- drmModeConnector *connector, bool silent)
+static void get_connector_name(
+ drmModeConnector *connector, char ret[MAX_CONNECTOR_NAME_LEN])
{
- if (!connector) {
- if (!silent) {
- MP_ERR(kms, "Cannot get connector %d: %s\n", connector_id,
- mp_strerror(errno));
- }
- return false;
- }
+ snprintf(ret, MAX_CONNECTOR_NAME_LEN, "%s-%d",
+ connector_names[connector->connector_type],
+ connector->connector_type_id);
+}
- if (connector->connection != DRM_MODE_CONNECTED) {
- if (!silent) {
- MP_ERR(kms, "Connector %d is disconnected\n", connector_id);
- }
- return false;
+// Gets the first connector whose name matches the input parameter.
+// The returned connector may be disconnected.
+// Result must be freed with drmModeFreeConnector.
+static drmModeConnector *get_connector_by_name(const struct kms *kms,
+ const drmModeRes *res,
+ const char *connector_name)
+{
+ for (int i = 0; i < res->count_connectors; i++) {
+ drmModeConnector *connector
+ = drmModeGetConnector(kms->fd, res->connectors[i]);
+ if (!connector)
+ continue;
+ char other_connector_name[MAX_CONNECTOR_NAME_LEN];
+ get_connector_name(connector, other_connector_name);
+ if (!strcmp(connector_name, other_connector_name))
+ return connector;
+ drmModeFreeConnector(connector);
}
+ return NULL;
+}
- if (connector->count_modes == 0) {
- if (!silent) {
- MP_ERR(kms, "Connector %d has no valid modes\n", connector_id);
+// Gets the first connected connector.
+// Result must be freed with drmModeFreeConnector.
+static drmModeConnector *get_first_connected_connector(const struct kms *kms,
+ const drmModeRes *res)
+{
+ for (int i = 0; i < res->count_connectors; i++) {
+ drmModeConnector *connector
+ = drmModeGetConnector(kms->fd, res->connectors[i]);
+ if (!connector)
+ continue;
+ if (connector->connection == DRM_MODE_CONNECTED
+ && connector->count_modes > 0) {
+ return connector;
}
- return false;
+ drmModeFreeConnector(connector);
}
-
- return true;
+ return NULL;
}
-static bool setup_connector(
- struct kms *kms, const drmModeRes *res, int connector_id)
+static bool setup_connector(struct kms *kms, const drmModeRes *res,
+ const char *connector_name)
{
- drmModeConnector *connector = NULL;
- if (connector_id == -1) {
- // get the first connected connector
- for (int i = 0; i < res->count_connectors; i++) {
- connector = drmModeGetConnector(kms->fd, res->connectors[i]);
- if (is_connector_valid(kms, i, connector, true)) {
- connector_id = i;
- break;
- }
- if (connector) {
- drmModeFreeConnector(connector);
- connector = NULL;
- }
+ drmModeConnector *connector;
+
+ if (connector_name
+ && strcmp(connector_name, "")
+ && strcmp(connector_name, "auto")) {
+ connector = get_connector_by_name(kms, res, connector_name);
+ if (!connector) {
+ MP_ERR(kms, "No connector with name %s found\n", connector_name);
+ kms_show_available_connectors(kms->log, kms->card_no);
+ return false;
}
- if (connector_id == -1) {
+ } else {
+ connector = get_first_connected_connector(kms, res);
+ if (!connector) {
MP_ERR(kms, "No connected connectors found\n");
return false;
}
}
- if (connector_id < 0 || connector_id >= res->count_connectors) {
- MP_ERR(kms, "Bad connector ID. Max valid connector ID = %u\n",
- res->count_connectors);
+ if (connector->connection != DRM_MODE_CONNECTED) {
+ drmModeFreeConnector(connector);
+ MP_ERR(kms, "Chosen connector is disconnected\n");
return false;
}
- connector = drmModeGetConnector(kms->fd, res->connectors[connector_id]);
- if (!is_connector_valid(kms, connector_id, connector, false))
+ if (connector->count_modes == 0) {
+ drmModeFreeConnector(connector);
+ MP_ERR(kms, "Chosen connector has no valid modes\n");
return false;
+ }
kms->connector = connector;
return true;
@@ -130,8 +175,7 @@ static bool setup_crtc(struct kms *kms, const drmModeRes *res)
drmModeFreeEncoder(encoder);
}
- MP_ERR(kms,
- "Connector %u has no suitable CRTC\n",
+ MP_ERR(kms, "Connector %u has no suitable CRTC\n",
kms->connector->connector_id);
return false;
}
@@ -139,20 +183,10 @@ static bool setup_crtc(struct kms *kms, const drmModeRes *res)
static bool setup_mode(struct kms *kms, int mode_id)
{
if (mode_id < 0 || mode_id >= kms->connector->count_modes) {
- MP_ERR(
- kms,
- "Bad mode ID (max = %d).\n",
- kms->connector->count_modes - 1);
-
- MP_INFO(kms, "Available modes:\n");
- for (unsigned int i = 0; i < kms->connector->count_modes; i++) {
- MP_INFO(kms,
- "Mode %d: %s (%dx%d)\n",
- i,
- kms->connector->modes[i].name,
- kms->connector->modes[i].hdisplay,
- kms->connector->modes[i].vdisplay);
- }
+ MP_ERR(kms, "Bad mode ID (max = %d).\n",
+ kms->connector->count_modes - 1);
+
+ kms_show_available_modes(kms->log, kms->connector);
return false;
}
@@ -160,36 +194,66 @@ static bool setup_mode(struct kms *kms, int mode_id)
return true;
}
+static int open_card(int card_no)
+{
+ char card_path[128];
+ snprintf(card_path, sizeof(card_path), DRM_DEV_NAME, DRM_DIR_NAME, card_no);
+ return open(card_path, O_RDWR | O_CLOEXEC);
+}
-struct kms *kms_create(struct mp_log *log)
+static void parse_connector_spec(struct mp_log *log,
+ const char *connector_spec,
+ int *card_no, char **connector_name)
{
- struct kms *ret = talloc(NULL, struct kms);
- *ret = (struct kms) {
- .log = mp_log_new(ret, log, "kms"),
- .fd = -1,
+ if (!connector_spec) {
+ *card_no = 0;
+ *connector_name = NULL;
+ return;
+ }
+ char *dot_ptr = strchr(connector_spec, '.');
+ if (dot_ptr) {
+ *card_no = atoi(connector_spec);
+ *connector_name = talloc_strdup(log, dot_ptr + 1);
+ } else {
+ *card_no = 0;
+ *connector_name = talloc_strdup(log, connector_spec);
+ }
+}
+
+
+struct kms *kms_create(struct mp_log *log, const char *connector_spec,
+ int mode_id)
+{
+ int card_no = -1;
+ char *connector_name = NULL;
+ parse_connector_spec(log, connector_spec, &card_no, &connector_name);
+
+ struct kms *kms = talloc(NULL, struct kms);
+ *kms = (struct kms) {
+ .log = mp_log_new(kms, log, "kms"),
+ .fd = open_card(card_no),
.connector = NULL,
.encoder = NULL,
.mode = { 0 },
.crtc_id = -1,
+ .card_no = card_no,
};
- return ret;
-}
-bool kms_setup(struct kms *kms, const char *device_path, int connector_id, int mode_id)
-{
- kms->fd = open(device_path, O_RDWR | O_CLOEXEC);
+ drmModeRes *res = NULL;
+
if (kms->fd < 0) {
- MP_ERR(kms, "Cannot open \"%s\": %s.\n", device_path, mp_strerror(errno));
- return false;
+ mp_err(log, "Cannot open card \"%d\": %s.\n",
+ card_no, mp_strerror(errno));
+ goto err;
}
- drmModeRes *res = drmModeGetResources(kms->fd);
+ res = drmModeGetResources(kms->fd);
if (!res) {
- MP_ERR(kms, "Cannot retrieve DRM resources: %s\n", mp_strerror(errno));
- return false;
+ mp_err(log, "Cannot retrieve DRM resources: %s\n", mp_strerror(errno));
+ goto err;
}
- if (!setup_connector(kms, res, connector_id))
+ if (!setup_connector(kms, res, connector_name))
goto err;
if (!setup_crtc(kms, res))
goto err;
@@ -197,11 +261,15 @@ bool kms_setup(struct kms *kms, const char *device_path, int connector_id, int m
goto err;
drmModeFreeResources(res);
- return true;
+ return kms;
err:
- drmModeFreeResources(res);
- return false;
+ if (res)
+ drmModeFreeResources(res);
+ if (connector_name)
+ talloc_free(connector_name);
+ kms_destroy(kms);
+ return NULL;
}
void kms_destroy(struct kms *kms)
@@ -220,11 +288,81 @@ void kms_destroy(struct kms *kms)
talloc_free(kms);
}
+void kms_show_available_modes(
+ struct mp_log *log, const drmModeConnector *connector)
+{
+ mp_info(log, "Available modes:\n");
+ for (unsigned int i = 0; i < connector->count_modes; i++) {
+ mp_info(log, "Mode %d: %s (%dx%d)\n", i,
+ connector->modes[i].name,
+ connector->modes[i].hdisplay,
+ connector->modes[i].vdisplay);
+ }
+}
+
+void kms_show_available_connectors(struct mp_log *log, int card_no)
+{
+ mp_info(log, "Available connectors for card %d:\n", card_no);
+
+ int fd = open_card(card_no);
+ if (fd < 0) {
+ mp_err(log, "Failed to open card %d\n", card_no);
+ return;
+ }
+
+ drmModeRes *res = drmModeGetResources(fd);
+ if (!res) {
+ mp_err(log, "Cannot retrieve DRM resources: %s\n", mp_strerror(errno));
+ goto err;
+ }
+
+ for (int i = 0; i < res->count_connectors; i++) {
+ drmModeConnector *connector
+ = drmModeGetConnector(fd, res->connectors[i]);
+ if (!connector)
+ continue;
+ char other_connector_name[MAX_CONNECTOR_NAME_LEN];
+ get_connector_name(connector, other_connector_name);
+ mp_info(log, "%s (%s)\n", other_connector_name,
+ connector->connection == DRM_MODE_CONNECTED
+ ? "connected"
+ : "disconnected");
+ drmModeFreeConnector(connector);
+ }
+
+err:
+ if (fd >= 0)
+ close(fd);
+ if (res)
+ drmModeFreeResources(res);
+}
+
+void kms_show_available_cards_and_connectors(struct mp_log *log)
+{
+ for (int card_no = 0; card_no < DRM_MAX_MINOR; card_no++) {
+ int fd = open_card(card_no);
+ if (fd < 0)
+ break;
+ close(fd);
+ kms_show_available_connectors(log, card_no);
+ }
+}
+
double kms_get_display_fps(const struct kms *kms)
{
return kms->mode.clock * 1000.0 / kms->mode.htotal / kms->mode.vtotal;
}
+int drm_validate_connector_opt(struct mp_log *log, const struct m_option *opt,
+ struct bstr name, struct bstr param)
+{
+ if (bstr_equals0(param, "help")) {
+ kms_show_available_cards_and_connectors(log);
+ return M_OPT_EXIT;
+ }
+ return 1;
+}
+
// VT switcher ----------------------------------------------------------------
diff --git a/video/out/drm_common.h b/video/out/drm_common.h
index 53ec9e35df..6796472cfc 100644
--- a/video/out/drm_common.h
+++ b/video/out/drm_common.h
@@ -21,6 +21,7 @@
#include <stdbool.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
+#include "options/m_option.h"
struct kms {
struct mp_log *log;
@@ -29,6 +30,7 @@ struct kms {
drmModeEncoder *encoder;
drmModeModeInfo mode;
uint32_t crtc_id;
+ int card_no;
};
struct vt_switcher {
@@ -43,12 +45,22 @@ void vt_switcher_destroy(struct vt_switcher *s);
void vt_switcher_poll(struct vt_switcher *s, int timeout_ms);
void vt_switcher_interrupt_poll(struct vt_switcher *s);
-void vt_switcher_acquire(struct vt_switcher *s, void (*handler)(void*), void *user_data);
-void vt_switcher_release(struct vt_switcher *s, void (*handler)(void*), void *user_data);
+void vt_switcher_acquire(struct vt_switcher *s, void (*handler)(void*),
+ void *user_data);
+void vt_switcher_release(struct vt_switcher *s, void (*handler)(void*),
+ void *user_data);
-struct kms *kms_create(struct mp_log *log);
-bool kms_setup(struct kms *kms, const char *device_path, int conn_id, int mode_id);
+struct kms *kms_create(struct mp_log *log, const char *connector_spec,
+ int mode_id);
void kms_destroy(struct kms *kms);
double kms_get_display_fps(const struct kms *kms);
+void kms_show_available_connectors(struct mp_log *log, int card_no);
+void kms_show_available_modes(struct mp_log *log,
+ const drmModeConnector *connector);
+void kms_show_available_cards_and_connectors(struct mp_log *log);
+
+int drm_validate_connector_opt(struct mp_log *log, const struct m_option *opt,
+ struct bstr name, struct bstr param);
+
#endif
diff --git a/video/out/opengl/context_drm_egl.c b/video/out/opengl/context_drm_egl.c
index a6609681d3..e5fd7b8354 100644
--- a/video/out/opengl/context_drm_egl.c
+++ b/video/out/opengl/context_drm_egl.c
@@ -94,7 +94,8 @@ static bool init_egl(struct MPGLContext *ctx, int flags)
&p->egl.context, &config))
return -1;
MP_VERBOSE(ctx->vo, "Initializing EGL surface\n");
- p->egl.surface = eglCreateWindowSurface(p->egl.display, config, p->gbm.surface, NULL);
+ p->egl.surface
+ = eglCreateWindowSurface(p->egl.display, config, p->gbm.surface, NULL);
if (p->egl.surface == EGL_NO_SURFACE) {
MP_ERR(ctx->vo, "Failed to create EGL surface.\n");
return false;
@@ -147,7 +148,7 @@ static void update_framebuffer_from_bo(
int handle = gbm_bo_get_handle(bo).u32;
int ret = drmModeAddFB(p->kms->fd, p->fb.width, p->fb.height,
- 24, 32, stride, handle, &p->fb.id);
+ 24, 32, stride, handle, &p->fb.id);
if (ret) {
MP_ERR(ctx->vo, "Failed to create framebuffer: %s\n", mp_strerror(errno));
}
@@ -155,7 +156,7 @@ static void update_framebuffer_from_bo(
}
static void page_flipped(int fd, unsigned int frame, unsigned int sec,
- unsigned int usec, void *data)
+ unsigned int usec, void *data)
{
struct priv *p = data;
p->waiting_for_flip = false;
@@ -167,12 +168,8 @@ static bool crtc_setup(struct MPGLContext *ctx)
if (p->active)
return true;
p->old_crtc = drmModeGetCrtc(p->kms->fd, p->kms->crtc_id);
- int ret = drmModeSetCrtc(p->kms->fd, p->kms->crtc_id,
- p->fb.id,
- 0,
- 0,
- &p->kms->connector->connector_id,
- 1,
+ int ret = drmModeSetCrtc(p->kms->fd, p->kms->crtc_id, p->fb.id,
+ 0, 0, &p->kms->connector->connector_id, 1,
&p->kms->mode);
p->active = true;
return ret == 0;
@@ -197,12 +194,9 @@ static void crtc_release(struct MPGLContext *ctx)
if (p->old_crtc) {
drmModeSetCrtc(p->kms->fd,
- p->old_crtc->crtc_id,
- p->old_crtc->buffer_id,
- p->old_crtc->x,
- p->old_crtc->y,
- &p->kms->connector->connector_id,
- 1,
+ p->old_crtc->crtc_id, p->old_crtc->buffer_id,
+ p->old_crtc->x, p->old_crtc->y,
+ &p->kms->connector->connector_id, 1,
&p->old_crtc->mode);
drmModeFreeCrtc(p->old_crtc);
p->old_crtc = NULL;
@@ -220,7 +214,8 @@ static void release_vt(void *data)
//until things change, this is commented.
struct priv *p = ctx->priv;
if (drmDropMaster(p->kms->fd)) {
- MP_WARN(ctx->vo, "Failed to drop DRM master: %s\n", mp_strerror(errno));
+ MP_WARN(ctx->vo, "Failed to drop DRM master: %s\n",
+ mp_strerror(errno));
}
}
}
@@ -232,7 +227,8 @@ static void acquire_vt(void *data)
if (USE_MASTER) {
struct priv *p = ctx->priv;
if (drmSetMaster(p->kms->fd)) {
- MP_WARN(ctx->vo, "Failed to acquire DRM master: %s\n", mp_strerror(errno));
+ MP_WARN(ctx->vo, "Failed to acquire DRM master: %s\n",
+ mp_strerror(errno));
}
}
@@ -247,7 +243,8 @@ static void drm_egl_uninit(MPGLContext *ctx)
if (p->vt_switcher_active)
vt_switcher_destroy(&p->vt_switcher);
- eglMakeCurrent(p->egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglMakeCurrent(p->egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE,
+ EGL_NO_CONTEXT);
eglDestroyContext(p->egl.display, p->egl.context);
eglDestroySurface(p->egl.display, p->egl.surface);
gbm_surface_destroy(p->gbm.surface);
@@ -287,18 +284,13 @@ static int drm_egl_init(struct MPGLContext *ctx, int flags)
}
MP_VERBOSE(ctx->vo, "Initializing KMS\n");
- p->kms = kms_create(ctx->vo->log);
+ p->kms = kms_create(ctx->vo->log, ctx->vo->opts->drm_connector_spec,
+ ctx->vo->opts->drm_mode_id);
if (!p->kms) {
MP_ERR(ctx->vo, "Failed to create KMS.\n");
return -1;
}
- // TODO: arguments should be configurable
- if (!kms_setup(p->kms, "/dev/dri/card0", -1, 0)) {
- MP_ERR(ctx->vo, "Failed to configure KMS.\n");
- return -1;
- }
-
if (!init_gbm(ctx)) {
MP_ERR(ctx->vo, "Failed to setup GBM.\n");
return -1;
@@ -309,7 +301,8 @@ static int drm_egl_init(struct MPGLContext *ctx, int flags)
return -1;
}
- if (!eglMakeCurrent(p->egl.display, p->egl.surface, p->egl.surface, p->egl.context)) {
+ if (!eglMakeCurrent(p->egl.display, p->egl.surface, p->egl.surface,
+ p->egl.context)) {
MP_ERR(ctx->vo, "Failed to make context current.\n");
return -1;
}
@@ -337,11 +330,8 @@ static int drm_egl_init(struct MPGLContext *ctx, int flags)
}
if (!crtc_setup(ctx)) {
- MP_ERR(
- ctx->vo,
- "Failed to set CRTC for connector %u: %s\n",
- p->kms->connector->connector_id,
- mp_strerror(errno));
+ MP_ERR(ctx->vo, "Failed to set CRTC for connector %u: %s\n",
+ p->kms->connector->connector_id, mp_strerror(errno));
return -1;
}
diff --git a/video/out/vo_drm.c b/video/out/vo_drm.c
index 60b3869d5b..7e642e391c 100644
--- a/video/out/vo_drm.c
+++ b/video/out/vo_drm.c
@@ -54,8 +54,7 @@ struct framebuffer {
};
struct priv {
- char *device_path;
- int connector_id;
+ char *connector_spec;
int mode_id;
struct kms *kms;
@@ -70,8 +69,8 @@ struct priv {
bool active;
bool pflip_happening;
- int32_t device_w;
- int32_t device_h;
+ int32_t screen_w;
+ int32_t screen_h;
struct mp_image *last_input;
struct mp_image *cur_frame;
struct mp_rect src;
@@ -158,8 +157,7 @@ static bool fb_setup_double_buffering(struct vo *vo)
for (unsigned int i = 0; i < BUF_COUNT; i++) {
if (!fb_setup_single(vo, p->kms->fd, &p->bufs[i])) {
- MP_ERR(vo, "Cannot create framebuffer for connector %d\n",
- p->kms->connector->connector_id);
+ MP_ERR(vo, "Cannot create framebuffer\n");
for (unsigned int j = 0; j < i; j++) {
fb_destroy(p->kms->fd, &p->bufs[j]);
}
@@ -171,7 +169,7 @@ static bool fb_setup_double_buffering(struct vo *vo)
}
static void page_flipped(int fd, unsigned int frame, unsigned int sec,
- unsigned int usec, void *data)
+ unsigned int usec, void *data)
{
struct priv *p = data;
p->pflip_happening = false;
@@ -185,10 +183,7 @@ static bool crtc_setup(struct vo *vo)
p->old_crtc = drmModeGetCrtc(p->kms->fd, p->kms->crtc_id);
int ret = drmModeSetCrtc(p->kms->fd, p->kms->crtc_id,
p->bufs[p->front_buf + BUF_COUNT - 1].fb,
- 0,
- 0,
- &p->kms->connector->connector_id,
- 1,
+ 0, 0, &p->kms->connector->connector_id, 1,
&p->kms->mode);
p->active = true;
return ret == 0;
@@ -212,13 +207,10 @@ static void crtc_release(struct vo *vo)
}
if (p->old_crtc) {
- drmModeSetCrtc(p->kms->fd,
- p->old_crtc->crtc_id,
+ drmModeSetCrtc(p->kms->fd, p->old_crtc->crtc_id,
p->old_crtc->buffer_id,
- p->old_crtc->x,
- p->old_crtc->y,
- &p->kms->connector->connector_id,
- 1,
+ p->old_crtc->x, p->old_crtc->y,
+ &p->kms->connector->connector_id, 1,
&p->old_crtc->mode);
drmModeFreeCrtc(p->old_crtc);
p->old_crtc = NULL;
@@ -274,8 +266,8 @@ static int reconfig(struct vo *vo, struct mp_image_params *params)
{
struct priv *p = vo->priv;
- vo->dwidth = p->device_w;
- vo->dheight = p->device_h;
+ vo->dwidth = p->screen_w;
+ vo->dheight = p->screen_h;
vo_get_src_dst_rects(vo, &p->src, &p->dst, &p->osd);
int w = p->dst.x1 - p->dst.x0;
@@ -302,7 +294,7 @@ static int reconfig(struct vo *vo, struct mp_image_params *params)
};
talloc_free(p->cur_frame);
- p->cur_frame = mp_image_alloc(IMGFMT, p->device_w, p->device_h);
+ p->cur_frame = mp_image_alloc(IMGFMT, p->screen_w, p->screen_h);
mp_image_params_guess_csp(&p->sws->dst);
mp_image_set_params(p->cur_frame, &p->sws->dst);
@@ -338,14 +330,11 @@ static void draw_image(struct vo *vo, mp_image_t *mpi)
struct framebuffer *front_buf = &p->bufs[p->front_buf];
int w = p->dst.x1 - p->dst.x0;
int h = p->dst.y1 - p->dst.y0;
- int x = (p->device_w - w) >> 1;
- int y = (p->device_h - h) >> 1;
+ int x = (p->screen_w - w) >> 1;
+ int y = (p->screen_h - h) >> 1;
int shift = y * front_buf->stride + x * BYTES_PER_PIXEL;
- memcpy_pic(front_buf->map + shift,
- p->cur_frame->planes[0],
- w * BYTES_PER_PIXEL,
- h,
- front_buf->stride,
+ memcpy_pic(front_buf->map + shift, p->cur_frame->planes[0],
+ w * BYTES_PER_PIXEL, h, front_buf->stride,
p->cur_frame->stride[0]);
}
@@ -422,17 +411,13 @@ static int preinit(struct vo *vo)
MP_WARN(vo, "Failed to set up VT switcher. Terminal switching will be unavailable.\n");
}
- p->kms = kms_create(vo->log);
+ p->kms = kms_create(
+ vo->log, vo->opts->drm_connector_spec, vo->opts->drm_mode_id);
if (!p->kms) {
MP_ERR(vo, "Failed to create KMS.\n");
goto err;
}
- if (!kms_setup(p->kms, p->device_path, p->connector_id, p->mode_id)) {
- MP_ERR(vo, "Failed to configure KMS.\n");
- goto err;
- }
-
if (!fb_setup_double_buffering(vo)) {
MP_ERR(vo, "Failed to set up double buffering.\n");
goto err;
@@ -440,18 +425,16 @@ static int preinit(struct vo *vo)
uint64_t has_dumb;
if (drmGetCap(p->kms->fd, DRM_CAP_DUMB_BUFFER, &has_dumb) < 0) {
- MP_ERR(vo, "Device \"%s\" does not support dumb buffers.\n", p->device_path);
+ MP_ERR(vo, "Card \"%d\" does not support dumb buffers.\n",
+ p->kms->card_no);
goto err;
}
- p->device_w = p->bufs[0].width;
- p->device_h = p->bufs[0].height;
+ p->screen_w = p->bufs[0].width;
+ p->screen_h = p->bufs[0].height;
if (!crtc_setup(vo)) {
- MP_ERR(vo,
- "Cannot set CRTC for connector %u: %s\n",
- p->kms->connector->connector_id,
- mp_strerror(errno));
+ MP_ERR(vo, "Cannot set CRTC: %s\n", mp_strerror(errno));
goto err;
}
@@ -507,16 +490,5 @@ const struct vo_driver video_out_drm = {
.wait_events = wait_events,
.wakeup = wakeup,
.priv_size = sizeof(struct priv),
- .options = (const struct m_option[]) {
- OPT_STRING("devpath", device_path, 0),
- OPT_INT("connector", connector_id, 0),
- OPT_INT("mode", mode_id, 0),
- {0},
- },
- .priv_defaults = &(const struct priv) {
- .device_path = "/dev/dri/card0",
- .connector_id = -1,
- .mode_id = 0,
- },
.legacy_prefix = "drm",
};