From 3325c7a912adda0b890315d8a9b8586907f2c73f Mon Sep 17 00:00:00 2001 From: Anton Kindestam Date: Tue, 13 Feb 2018 18:40:47 +0100 Subject: 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. --- video/out/drm_common.c | 3 + video/out/drm_common.h | 4 ++ video/out/opengl/context_drm_egl.c | 111 +++++++++++++++++++++++++++---------- 3 files changed, 89 insertions(+), 29 deletions(-) (limited to 'video/out') 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 #include -#include #include #include @@ -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; } -- cgit v1.2.3