summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Kindestam <antonki@kth.se>2018-02-13 18:40:47 +0100
committerKevin Mitchell <kevmitch@gmail.com>2018-02-26 23:56:13 -0800
commit3325c7a912adda0b890315d8a9b8586907f2c73f (patch)
treeea58db3c43a49ee4acaa7c312288c94644d0b31a
parentbb07b22d4248492c859d2e4c0d2ff2941db1db86 (diff)
downloadmpv-3325c7a912adda0b890315d8a9b8586907f2c73f.tar.bz2
mpv-3325c7a912adda0b890315d8a9b8586907f2c73f.tar.xz
context_drm_egl: Introduce 30bpp support
This introduces the option --drm-format (currently used only by context_drm_egl, vo_drm implementation is pending) which allows you to pick between a xrgb8888 or a xrgb2101010 visual for --gpu-context=drm. Requires a recent mesa (18.0.0_rc4 or later) to work. This also fixes a bug when using --gpu-context=drm on a 30bpp-enabled mesa (allow_rgb10_configs set to true). Previously it would've set up an XRGB8888 format at the DRM/GBM level, while a 30bpp EGLConfig would be picked, resulting in a garbled image.
-rw-r--r--DOCS/man/vo.rst15
-rw-r--r--video/out/drm_common.c3
-rw-r--r--video/out/drm_common.h4
-rw-r--r--video/out/opengl/context_drm_egl.c111
4 files changed, 103 insertions, 30 deletions
diff --git a/DOCS/man/vo.rst b/DOCS/man/vo.rst
index d5a4ef9b26..8e8b9803be 100644
--- a/DOCS/man/vo.rst
+++ b/DOCS/man/vo.rst
@@ -484,7 +484,7 @@ Available video output drivers are:
(default: empty)
``--drm-mode=<number>``
- Mode ID to use (resolution, bit depth and frame rate).
+ Mode ID to use (resolution and frame rate).
(default: 0)
``--drm-overlay=<number>``
@@ -492,6 +492,19 @@ Available video output drivers are:
Overlay index is zero based, and related to crtc.
(default: 0)
+ ``--drm-format=<xrgb8888,xrgb2101010>``
+ Select the DRM format to use (default: xrgb8888). This allows you to
+ choose the bit depth of the DRM mode. xrgb8888 is your usual 24 bit per
+ pixel/8 bits per channel packed RGB format with 8 bits of padding.
+ xrgb2101010 is a packed 30 bits per pixel/10 bits per channel packed RGB
+ format with 2 bits of padding.
+
+ Unless you have an intel graphics card, a recent kernel and a recent
+ version of mesa (>=18) xrgb2101010 is unlikely to work for you.
+
+ This currently only has an effect when used together with the ``drm``
+ backend for the ``gpu`` VO. The ``drm`` VO always uses xrgb8888.
+
``mediacodec_embed`` (Android)
Renders ``IMGFMT_MEDIACODEC`` frames directly to an ``android.view.Surface``.
Requires ``--hwdec=mediacodec`` for hardware decoding, along with
diff --git a/video/out/drm_common.c b/video/out/drm_common.c
index 8402ac7e69..1a164f9a30 100644
--- a/video/out/drm_common.c
+++ b/video/out/drm_common.c
@@ -48,6 +48,9 @@ const struct m_sub_options drm_conf = {
0, drm_validate_connector_opt),
OPT_INT("drm-mode", drm_mode_id, 0),
OPT_INT("drm-overlay", drm_overlay_id, 0),
+ OPT_CHOICE("drm-format", drm_format, 0,
+ ({"xrgb8888", DRM_OPTS_FORMAT_XRGB8888},
+ {"xrgb2101010", DRM_OPTS_FORMAT_XRGB2101010})),
{0},
},
.size = sizeof(struct drm_opts),
diff --git a/video/out/drm_common.h b/video/out/drm_common.h
index ff913ff00c..ba1209e43c 100644
--- a/video/out/drm_common.h
+++ b/video/out/drm_common.h
@@ -24,6 +24,9 @@
#include "options/m_option.h"
#include "drm_atomic.h"
+#define DRM_OPTS_FORMAT_XRGB8888 0
+#define DRM_OPTS_FORMAT_XRGB2101010 1
+
struct kms {
struct mp_log *log;
int fd;
@@ -46,6 +49,7 @@ struct drm_opts {
char *drm_connector_spec;
int drm_mode_id;
int drm_overlay_id;
+ int drm_format;
};
bool vt_switcher_init(struct vt_switcher *s, struct mp_log *log);
diff --git a/video/out/opengl/context_drm_egl.c b/video/out/opengl/context_drm_egl.c
index 61913091d8..402257a183 100644
--- a/video/out/opengl/context_drm_egl.c
+++ b/video/out/opengl/context_drm_egl.c
@@ -25,7 +25,6 @@
#include <unistd.h>
#include <gbm.h>
-#include <drm_fourcc.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
@@ -72,7 +71,7 @@ struct priv {
struct gbm gbm;
struct framebuffer *fb;
- uint32_t primary_plane_format;
+ uint32_t gbm_format;
bool active;
bool waiting_for_flip;
@@ -83,6 +82,44 @@ struct priv {
struct mpv_opengl_cb_drm_params drm_params;
};
+// Not general. Limited to only the formats being used in this module
+static const char *gbm_format_to_string(uint32_t format)
+{
+ switch (format) {
+ case GBM_FORMAT_XRGB8888:
+ return "GBM_FORMAT_XRGB8888";
+ case GBM_FORMAT_ARGB8888:
+ return "GBM_FORMAT_ARGB8888";
+ case GBM_FORMAT_XRGB2101010:
+ return "GBM_FORMAT_XRGB2101010";
+ case GBM_FORMAT_ARGB2101010:
+ return "GBM_FORMAT_ARGB2101010";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static int match_config_to_visual(void *user_data, EGLConfig *configs, int num_configs)
+{
+ struct ra_ctx *ctx = (struct ra_ctx*)user_data;
+ struct priv *p = ctx->priv;
+ const EGLint visual_id = (EGLint)p->gbm_format;
+
+ for (unsigned int i = 0; i < num_configs; ++i) {
+ EGLint id;
+
+ if (!eglGetConfigAttrib(p->egl.display, configs[i], EGL_NATIVE_VISUAL_ID, &id))
+ continue;
+
+ if (visual_id == id)
+ return i;
+ }
+
+ MP_ERR(ctx, "Could not find EGLConfig matching the GBM visual (%s).\n",
+ gbm_format_to_string(p->gbm_format));
+ return -1;
+}
+
static bool init_egl(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
@@ -97,7 +134,11 @@ static bool init_egl(struct ra_ctx *ctx)
return false;
}
EGLConfig config;
- if (!mpegl_create_context(ctx, p->egl.display, &p->egl.context, &config))
+ if (!mpegl_create_context_cb(ctx,
+ p->egl.display,
+ (struct mpegl_cb){match_config_to_visual, ctx},
+ &p->egl.context,
+ &config))
return false;
MP_VERBOSE(ctx, "Initializing EGL surface\n");
p->egl.surface
@@ -125,7 +166,7 @@ static bool init_gbm(struct ra_ctx *ctx)
p->gbm.device,
p->kms->mode.hdisplay,
p->kms->mode.vdisplay,
- p->primary_plane_format, // drm_fourcc.h defs should be gbm-compatible
+ p->gbm_format,
GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
if (!p->gbm.surface) {
MP_ERR(ctx->vo, "Failed to create GBM surface.\n");
@@ -159,7 +200,7 @@ static void update_framebuffer_from_bo(struct ra_ctx *ctx, struct gbm_bo *bo)
uint32_t handle = gbm_bo_get_handle(bo).u32;
int ret = drmModeAddFB2(fb->fd, fb->width, fb->height,
- p->primary_plane_format,
+ p->gbm_format,
(uint32_t[4]){handle, 0, 0, 0},
(uint32_t[4]){stride, 0, 0, 0},
(uint32_t[4]){0, 0, 0, 0},
@@ -336,42 +377,43 @@ static void drm_egl_uninit(struct ra_ctx *ctx)
}
}
-// If primary plane supports ARGB8888 we want to use that, but if it doesn't we
-// fall back on XRGB8888. If the driver does not support atomic there is no
-// particular reason to be using ARGB8888, so we fall back to XRGB8888 (another
-// reason is that we do not have the convenient atomic_ctx and its convenient
-// primary_plane field).
-static bool probe_primary_plane_format(struct ra_ctx *ctx)
+// If primary plane supports ARGB we want to use that, but if it doesn't we fall
+// back on XRGB. If the driver does not support atomic there is no particular
+// reason to be using ARGB (drmprime hwdec will not work without atomic,
+// anyway), so we fall back to XRGB (another reason is that we do not have the
+// convenient atomic_ctx and its convenient primary_plane field).
+static bool probe_gbm_format(struct ra_ctx *ctx, uint32_t argb_format, uint32_t xrgb_format)
{
struct priv *p = ctx->priv;
+
if (!p->kms->atomic_context) {
- p->primary_plane_format = DRM_FORMAT_XRGB8888;
- MP_VERBOSE(ctx->vo, "Not using DRM Atomic: Use DRM_FORMAT_XRGB8888 for primary plane.\n");
+ p->gbm_format = xrgb_format;
+ MP_VERBOSE(ctx->vo, "Not using DRM Atomic: Use %s for primary plane.\n",
+ gbm_format_to_string(xrgb_format));
return true;
}
drmModePlane *drmplane =
drmModeGetPlane(p->kms->fd, p->kms->atomic_context->primary_plane->id);
- bool have_argb8888 = false;
- bool have_xrgb8888 = false;
+ bool have_argb = false;
+ bool have_xrgb = false;
bool result = false;
for (unsigned int i = 0; i < drmplane->count_formats; ++i) {
- if (drmplane->formats[i] == DRM_FORMAT_ARGB8888) {
- have_argb8888 = true;
- } else if (drmplane->formats[i] == DRM_FORMAT_XRGB8888) {
- have_xrgb8888 = true;
+ if (drmplane->formats[i] == argb_format) {
+ have_argb = true;
+ } else if (drmplane->formats[i] == xrgb_format) {
+ have_xrgb = true;
}
}
- if (have_argb8888) {
- p->primary_plane_format = DRM_FORMAT_ARGB8888;
- MP_VERBOSE(ctx->vo, "DRM_FORMAT_ARGB8888 supported by primary plane.\n");
+ if (have_argb) {
+ p->gbm_format = argb_format;
+ MP_VERBOSE(ctx->vo, "%s supported by primary plane.\n", gbm_format_to_string(argb_format));
result = true;
- } else if (have_xrgb8888) {
- p->primary_plane_format = DRM_FORMAT_XRGB8888;
- MP_VERBOSE(ctx->vo,
- "DRM_FORMAT_ARGB8888 not supported by primary plane: "
- "Falling back to DRM_FORMAT_XRGB8888.\n");
+ } else if (have_xrgb) {
+ p->gbm_format = xrgb_format;
+ MP_VERBOSE(ctx->vo, "%s not supported by primary plane: Falling back to %s.\n",
+ gbm_format_to_string(argb_format), gbm_format_to_string(xrgb_format));
result = true;
}
@@ -406,8 +448,19 @@ static bool drm_egl_init(struct ra_ctx *ctx)
return false;
}
- if (!probe_primary_plane_format(ctx)) {
- MP_ERR(ctx->vo, "No suitable format found on DRM primary plane.\n");
+ uint32_t argb_format;
+ uint32_t xrgb_format;
+ if (DRM_OPTS_FORMAT_XRGB2101010 == ctx->vo->opts->drm_opts->drm_format) {
+ argb_format = GBM_FORMAT_ARGB2101010;
+ xrgb_format = GBM_FORMAT_XRGB2101010;
+ } else {
+ argb_format = GBM_FORMAT_ARGB8888;
+ xrgb_format = GBM_FORMAT_XRGB8888;
+ }
+
+ if (!probe_gbm_format(ctx, argb_format, xrgb_format)) {
+ MP_ERR(ctx->vo, "No suitable format found on DRM primary plane (tried: %s and %s).\n",
+ gbm_format_to_string(argb_format), gbm_format_to_string(xrgb_format));
return false;
}