From 379ba7eeda0a213093100e910e73eef86444356a Mon Sep 17 00:00:00 2001
|
From: Jeffy Chen <jeffy.chen@rock-chips.com>
|
Date: Tue, 16 Jun 2020 17:14:54 +0800
|
Subject: [PATCH 4/4] vo_opengl: x11egl: Support drm hwdec
|
|
Tested with:
|
mpv --hwdec=rkmpp --vo=opengl test.mp4
|
|
Change-Id: Ic49e2acaa288496180037d2ca648eb824d4a663c
|
Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
|
---
|
libmpv/render_gl.h | 3 +
|
video/out/opengl/context_x11egl.c | 145 ++++++++++++++++++++++++++
|
video/out/opengl/hwdec_drmprime_drm.c | 11 +-
|
3 files changed, 156 insertions(+), 3 deletions(-)
|
|
diff --git a/libmpv/render_gl.h b/libmpv/render_gl.h
|
index 4d771f2958..da3bbccfc4 100644
|
--- a/libmpv/render_gl.h
|
+++ b/libmpv/render_gl.h
|
@@ -175,6 +175,9 @@ typedef struct mpv_opengl_drm_params {
|
* Set to a negative number if invalid.
|
*/
|
int render_fd;
|
+
|
+ int x;
|
+ int y;
|
} mpv_opengl_drm_params;
|
|
typedef struct mpv_opengl_drm_osd_size {
|
diff --git a/video/out/opengl/context_x11egl.c b/video/out/opengl/context_x11egl.c
|
index 32530cc11d..5ced169cd2 100644
|
--- a/video/out/opengl/context_x11egl.c
|
+++ b/video/out/opengl/context_x11egl.c
|
@@ -31,16 +31,45 @@
|
#include "context.h"
|
#include "egl_helpers.h"
|
|
+#if HAVE_DRM
|
+#include <errno.h>
|
+#include <fcntl.h>
|
+#include <unistd.h>
|
+
|
+#include "libmpv/render_gl.h"
|
+#include "video/out/drm_common.h"
|
+#endif
|
+
|
struct priv {
|
GL gl;
|
EGLDisplay egl_display;
|
EGLContext egl_context;
|
EGLSurface egl_surface;
|
+
|
+#if HAVE_DRM
|
+ struct kms *kms;
|
+ struct mpv_opengl_drm_params drm_params;
|
+
|
+ int x;
|
+ int y;
|
+#endif
|
};
|
|
static void mpegl_uninit(struct ra_ctx *ctx)
|
{
|
struct priv *p = ctx->priv;
|
+
|
+#if HAVE_DRM
|
+ struct drm_atomic_context *atomic_ctx = p->kms->atomic_context;
|
+
|
+ if (atomic_ctx) {
|
+ int ret = drmModeAtomicCommit(p->kms->fd, atomic_ctx->request, 0, NULL);
|
+ if (ret)
|
+ MP_ERR(ctx->vo, "Failed to commit atomic request (%d)\n", ret);
|
+ drmModeAtomicFree(atomic_ctx->request);
|
+ }
|
+#endif
|
+
|
ra_gl_ctx_uninit(ctx);
|
|
if (p->egl_context) {
|
@@ -49,7 +78,20 @@ static void mpegl_uninit(struct ra_ctx *ctx)
|
eglDestroyContext(p->egl_display, p->egl_context);
|
}
|
p->egl_context = EGL_NO_CONTEXT;
|
+ if (p->egl_display != EGL_NO_DISPLAY)
|
+ eglTerminate(p->egl_display);
|
+ p->egl_display = EGL_NO_DISPLAY;
|
+
|
vo_x11_uninit(ctx->vo);
|
+
|
+#if HAVE_DRM
|
+ close(p->drm_params.render_fd);
|
+
|
+ if (p->kms) {
|
+ kms_destroy(p->kms);
|
+ p->kms = 0;
|
+ }
|
+#endif
|
}
|
|
static int pick_xrgba_config(void *user_data, EGLConfig *configs, int num_configs)
|
@@ -75,9 +117,65 @@ static int pick_xrgba_config(void *user_data, EGLConfig *configs, int num_config
|
return 0;
|
}
|
|
+#if HAVE_DRM
|
+static bool mpegl_update_position(struct ra_ctx *ctx)
|
+{
|
+ struct priv *p = ctx->priv;
|
+ struct vo_x11_state *x11 = ctx->vo->x11;
|
+ int x = 0, y = 0;
|
+ bool moved = false;
|
+ Window dummy_win;
|
+ Window win = x11->parent ? x11->parent : x11->window;
|
+
|
+ if (win)
|
+ XTranslateCoordinates(x11->display, win, x11->rootwin, 0, 0,
|
+ &x, &y, &dummy_win);
|
+
|
+ moved = p->x != x || p->y != y;
|
+ p->drm_params.x = p->x = x;
|
+ p->drm_params.y = p->y = y;
|
+
|
+ return moved;
|
+}
|
+
|
+static bool drm_atomic_egl_start_frame(struct ra_swapchain *sw, struct ra_fbo *out_fbo)
|
+{
|
+ struct priv *p = sw->ctx->priv;
|
+
|
+ mpegl_update_position(sw->ctx);
|
+
|
+ if (p->kms->atomic_context) {
|
+ if (!p->kms->atomic_context->request) {
|
+ p->kms->atomic_context->request = drmModeAtomicAlloc();
|
+ p->drm_params.atomic_request_ptr = &p->kms->atomic_context->request;
|
+ }
|
+ return ra_gl_ctx_start_frame(sw, out_fbo);
|
+ }
|
+ return false;
|
+}
|
+
|
+static const struct ra_swapchain_fns drm_atomic_swapchain = {
|
+ .start_frame = drm_atomic_egl_start_frame,
|
+};
|
+#endif
|
+
|
static void mpegl_swap_buffers(struct ra_ctx *ctx)
|
{
|
struct priv *p = ctx->priv;
|
+#if HAVE_DRM
|
+ struct drm_atomic_context *atomic_ctx = p->kms->atomic_context;
|
+ int ret;
|
+
|
+ if (atomic_ctx) {
|
+ ret = drmModeAtomicCommit(p->kms->fd, atomic_ctx->request, 0, NULL);
|
+ if (ret)
|
+ MP_WARN(ctx->vo, "Failed to commit atomic request (%d)\n", ret);
|
+
|
+ drmModeAtomicFree(atomic_ctx->request);
|
+ atomic_ctx->request = drmModeAtomicAlloc();
|
+ }
|
+#endif
|
+
|
eglSwapBuffers(p->egl_display, p->egl_surface);
|
}
|
|
@@ -140,15 +238,56 @@ static bool mpegl_init(struct ra_ctx *ctx)
|
|
mpegl_load_functions(&p->gl, ctx->log);
|
|
+#if HAVE_DRM
|
+ MP_VERBOSE(ctx, "Initializing KMS\n");
|
+ p->kms = kms_create(ctx->log, ctx->vo->opts->drm_opts->drm_connector_spec,
|
+ ctx->vo->opts->drm_opts->drm_mode_id,
|
+ ctx->vo->opts->drm_opts->drm_osd_plane_id,
|
+ ctx->vo->opts->drm_opts->drm_video_plane_id);
|
+ if (!p->kms) {
|
+ MP_ERR(ctx, "Failed to create KMS.\n");
|
+ return false;
|
+ }
|
+
|
+ p->drm_params.fd = p->kms->fd;
|
+ p->drm_params.crtc_id = p->kms->crtc_id;
|
+ p->drm_params.connector_id = p->kms->connector->connector_id;
|
+ if (p->kms->atomic_context)
|
+ p->drm_params.atomic_request_ptr = &p->kms->atomic_context->request;
|
+ char *rendernode_path = drmGetRenderDeviceNameFromFd(p->kms->fd);
|
+ if (rendernode_path) {
|
+ MP_VERBOSE(ctx, "Opening render node \"%s\"\n", rendernode_path);
|
+ p->drm_params.render_fd = open(rendernode_path, O_RDWR | O_CLOEXEC);
|
+ if (p->drm_params.render_fd < 0) {
|
+ MP_WARN(ctx, "Cannot open render node \"%s\": %s. VAAPI hwdec will be disabled\n",
|
+ rendernode_path, mp_strerror(errno));
|
+ }
|
+ free(rendernode_path);
|
+ } else {
|
+ p->drm_params.render_fd = -1;
|
+ MP_VERBOSE(ctx, "Could not find path to render node. VAAPI hwdec will be disabled\n");
|
+ }
|
+
|
+ struct ra_gl_ctx_params params = {
|
+ .swap_buffers = mpegl_swap_buffers,
|
+ .external_swapchain = p->kms->atomic_context ? &drm_atomic_swapchain :
|
+ NULL,
|
+ };
|
+#else
|
struct ra_gl_ctx_params params = {
|
.swap_buffers = mpegl_swap_buffers,
|
};
|
+#endif
|
|
if (!ra_gl_ctx_init(ctx, &p->gl, params))
|
goto uninit;
|
|
ra_add_native_resource(ctx->ra, "x11", vo->x11->display);
|
|
+#if HAVE_DRM
|
+ ra_add_native_resource(ctx->ra, "drm_params", &p->drm_params);
|
+#endif
|
+
|
return true;
|
|
uninit:
|
@@ -174,6 +313,12 @@ static int mpegl_control(struct ra_ctx *ctx, int *events, int request,
|
int ret = vo_x11_control(ctx->vo, events, request, arg);
|
if (*events & VO_EVENT_RESIZE)
|
resize(ctx);
|
+
|
+#if HAVE_DRM
|
+ if (mpegl_update_position(ctx))
|
+ ctx->vo->want_redraw = true;
|
+#endif
|
+
|
return ret;
|
}
|
|
diff --git a/video/out/opengl/hwdec_drmprime_drm.c b/video/out/opengl/hwdec_drmprime_drm.c
|
index d4543b0f47..2b34f7781c 100644
|
--- a/video/out/opengl/hwdec_drmprime_drm.c
|
+++ b/video/out/opengl/hwdec_drmprime_drm.c
|
@@ -139,6 +139,8 @@ static int overlay_frame(struct ra_hwdec *hw, struct mp_image *hw_image,
|
AVDRMFrameDescriptor *desc = NULL;
|
drmModeAtomicReq *request = NULL;
|
struct drm_frame next_frame = {0};
|
+ int dx = dst ? dst->x0 : 0;
|
+ int dy = dst ? dst->y0 : 0;
|
int ret;
|
|
// grab atomic request from native resources
|
@@ -155,6 +157,9 @@ static int overlay_frame(struct ra_hwdec *hw, struct mp_image *hw_image,
|
MP_ERR(hw, "drm params pointer to atomic request is invalid");
|
return -1;
|
}
|
+
|
+ dx += drm_params->x;
|
+ dy += drm_params->y;
|
}
|
|
if (hw_image) {
|
@@ -190,14 +195,14 @@ static int overlay_frame(struct ra_hwdec *hw, struct mp_image *hw_image,
|
drm_object_set_property(request, p->ctx->video_plane, "SRC_Y", p->src.y0 << 16);
|
drm_object_set_property(request, p->ctx->video_plane, "SRC_W", srcw << 16);
|
drm_object_set_property(request, p->ctx->video_plane, "SRC_H", srch << 16);
|
- drm_object_set_property(request, p->ctx->video_plane, "CRTC_X", MP_ALIGN_DOWN(p->dst.x0, 2));
|
- drm_object_set_property(request, p->ctx->video_plane, "CRTC_Y", MP_ALIGN_DOWN(p->dst.y0, 2));
|
+ drm_object_set_property(request, p->ctx->video_plane, "CRTC_X", MP_ALIGN_DOWN(dx, 2));
|
+ drm_object_set_property(request, p->ctx->video_plane, "CRTC_Y", MP_ALIGN_DOWN(dy, 2));
|
drm_object_set_property(request, p->ctx->video_plane, "CRTC_W", dstw);
|
drm_object_set_property(request, p->ctx->video_plane, "CRTC_H", dsth);
|
drm_object_set_property(request, p->ctx->video_plane, "ZPOS", 0);
|
} else {
|
ret = drmModeSetPlane(p->ctx->fd, p->ctx->video_plane->id, p->ctx->crtc->id, next_frame.fb.fb_id, 0,
|
- MP_ALIGN_DOWN(p->dst.x0, 2), MP_ALIGN_DOWN(p->dst.y0, 2), dstw, dsth,
|
+ MP_ALIGN_DOWN(dx, 2), MP_ALIGN_DOWN(dy, 2), dstw, dsth,
|
p->src.x0 << 16, p->src.y0 << 16 , srcw << 16, srch << 16);
|
if (ret < 0) {
|
MP_ERR(hw, "Failed to set the plane %d (buffer %d).\n", p->ctx->video_plane->id,
|
--
|
2.17.1
|