linuxOS_AP06/debian/packages-patches/mpv/0.29.1/0004-vo_opengl-x11egl-Support-drm-hwdec.patch
2025-06-03 12:28:32 +08:00

282 lines
9.2 KiB
Diff

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