1From 379ba7eeda0a213093100e910e73eef86444356a Mon Sep 17 00:00:00 2001 2From: Jeffy Chen <jeffy.chen@rock-chips.com> 3Date: Tue, 16 Jun 2020 17:14:54 +0800 4Subject: [PATCH 4/4] vo_opengl: x11egl: Support drm hwdec 5 6Tested with: 7mpv --hwdec=rkmpp --vo=opengl test.mp4 8 9Change-Id: Ic49e2acaa288496180037d2ca648eb824d4a663c 10Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> 11--- 12 libmpv/render_gl.h | 3 + 13 video/out/opengl/context_x11egl.c | 145 ++++++++++++++++++++++++++ 14 video/out/opengl/hwdec_drmprime_drm.c | 11 +- 15 3 files changed, 156 insertions(+), 3 deletions(-) 16 17diff --git a/libmpv/render_gl.h b/libmpv/render_gl.h 18index 4d771f2958..da3bbccfc4 100644 19--- a/libmpv/render_gl.h 20+++ b/libmpv/render_gl.h 21@@ -175,6 +175,9 @@ typedef struct mpv_opengl_drm_params { 22 * Set to a negative number if invalid. 23 */ 24 int render_fd; 25+ 26+ int x; 27+ int y; 28 } mpv_opengl_drm_params; 29 30 typedef struct mpv_opengl_drm_osd_size { 31diff --git a/video/out/opengl/context_x11egl.c b/video/out/opengl/context_x11egl.c 32index 32530cc11d..5ced169cd2 100644 33--- a/video/out/opengl/context_x11egl.c 34+++ b/video/out/opengl/context_x11egl.c 35@@ -31,16 +31,45 @@ 36 #include "context.h" 37 #include "egl_helpers.h" 38 39+#if HAVE_DRM 40+#include <errno.h> 41+#include <fcntl.h> 42+#include <unistd.h> 43+ 44+#include "libmpv/render_gl.h" 45+#include "video/out/drm_common.h" 46+#endif 47+ 48 struct priv { 49 GL gl; 50 EGLDisplay egl_display; 51 EGLContext egl_context; 52 EGLSurface egl_surface; 53+ 54+#if HAVE_DRM 55+ struct kms *kms; 56+ struct mpv_opengl_drm_params drm_params; 57+ 58+ int x; 59+ int y; 60+#endif 61 }; 62 63 static void mpegl_uninit(struct ra_ctx *ctx) 64 { 65 struct priv *p = ctx->priv; 66+ 67+#if HAVE_DRM 68+ struct drm_atomic_context *atomic_ctx = p->kms->atomic_context; 69+ 70+ if (atomic_ctx) { 71+ int ret = drmModeAtomicCommit(p->kms->fd, atomic_ctx->request, 0, NULL); 72+ if (ret) 73+ MP_ERR(ctx->vo, "Failed to commit atomic request (%d)\n", ret); 74+ drmModeAtomicFree(atomic_ctx->request); 75+ } 76+#endif 77+ 78 ra_gl_ctx_uninit(ctx); 79 80 if (p->egl_context) { 81@@ -49,7 +78,20 @@ static void mpegl_uninit(struct ra_ctx *ctx) 82 eglDestroyContext(p->egl_display, p->egl_context); 83 } 84 p->egl_context = EGL_NO_CONTEXT; 85+ if (p->egl_display != EGL_NO_DISPLAY) 86+ eglTerminate(p->egl_display); 87+ p->egl_display = EGL_NO_DISPLAY; 88+ 89 vo_x11_uninit(ctx->vo); 90+ 91+#if HAVE_DRM 92+ close(p->drm_params.render_fd); 93+ 94+ if (p->kms) { 95+ kms_destroy(p->kms); 96+ p->kms = 0; 97+ } 98+#endif 99 } 100 101 static int pick_xrgba_config(void *user_data, EGLConfig *configs, int num_configs) 102@@ -75,9 +117,65 @@ static int pick_xrgba_config(void *user_data, EGLConfig *configs, int num_config 103 return 0; 104 } 105 106+#if HAVE_DRM 107+static bool mpegl_update_position(struct ra_ctx *ctx) 108+{ 109+ struct priv *p = ctx->priv; 110+ struct vo_x11_state *x11 = ctx->vo->x11; 111+ int x = 0, y = 0; 112+ bool moved = false; 113+ Window dummy_win; 114+ Window win = x11->parent ? x11->parent : x11->window; 115+ 116+ if (win) 117+ XTranslateCoordinates(x11->display, win, x11->rootwin, 0, 0, 118+ &x, &y, &dummy_win); 119+ 120+ moved = p->x != x || p->y != y; 121+ p->drm_params.x = p->x = x; 122+ p->drm_params.y = p->y = y; 123+ 124+ return moved; 125+} 126+ 127+static bool drm_atomic_egl_start_frame(struct ra_swapchain *sw, struct ra_fbo *out_fbo) 128+{ 129+ struct priv *p = sw->ctx->priv; 130+ 131+ mpegl_update_position(sw->ctx); 132+ 133+ if (p->kms->atomic_context) { 134+ if (!p->kms->atomic_context->request) { 135+ p->kms->atomic_context->request = drmModeAtomicAlloc(); 136+ p->drm_params.atomic_request_ptr = &p->kms->atomic_context->request; 137+ } 138+ return ra_gl_ctx_start_frame(sw, out_fbo); 139+ } 140+ return false; 141+} 142+ 143+static const struct ra_swapchain_fns drm_atomic_swapchain = { 144+ .start_frame = drm_atomic_egl_start_frame, 145+}; 146+#endif 147+ 148 static void mpegl_swap_buffers(struct ra_ctx *ctx) 149 { 150 struct priv *p = ctx->priv; 151+#if HAVE_DRM 152+ struct drm_atomic_context *atomic_ctx = p->kms->atomic_context; 153+ int ret; 154+ 155+ if (atomic_ctx) { 156+ ret = drmModeAtomicCommit(p->kms->fd, atomic_ctx->request, 0, NULL); 157+ if (ret) 158+ MP_WARN(ctx->vo, "Failed to commit atomic request (%d)\n", ret); 159+ 160+ drmModeAtomicFree(atomic_ctx->request); 161+ atomic_ctx->request = drmModeAtomicAlloc(); 162+ } 163+#endif 164+ 165 eglSwapBuffers(p->egl_display, p->egl_surface); 166 } 167 168@@ -140,15 +238,56 @@ static bool mpegl_init(struct ra_ctx *ctx) 169 170 mpegl_load_functions(&p->gl, ctx->log); 171 172+#if HAVE_DRM 173+ MP_VERBOSE(ctx, "Initializing KMS\n"); 174+ p->kms = kms_create(ctx->log, ctx->vo->opts->drm_opts->drm_connector_spec, 175+ ctx->vo->opts->drm_opts->drm_mode_id, 176+ ctx->vo->opts->drm_opts->drm_osd_plane_id, 177+ ctx->vo->opts->drm_opts->drm_video_plane_id); 178+ if (!p->kms) { 179+ MP_ERR(ctx, "Failed to create KMS.\n"); 180+ return false; 181+ } 182+ 183+ p->drm_params.fd = p->kms->fd; 184+ p->drm_params.crtc_id = p->kms->crtc_id; 185+ p->drm_params.connector_id = p->kms->connector->connector_id; 186+ if (p->kms->atomic_context) 187+ p->drm_params.atomic_request_ptr = &p->kms->atomic_context->request; 188+ char *rendernode_path = drmGetRenderDeviceNameFromFd(p->kms->fd); 189+ if (rendernode_path) { 190+ MP_VERBOSE(ctx, "Opening render node \"%s\"\n", rendernode_path); 191+ p->drm_params.render_fd = open(rendernode_path, O_RDWR | O_CLOEXEC); 192+ if (p->drm_params.render_fd < 0) { 193+ MP_WARN(ctx, "Cannot open render node \"%s\": %s. VAAPI hwdec will be disabled\n", 194+ rendernode_path, mp_strerror(errno)); 195+ } 196+ free(rendernode_path); 197+ } else { 198+ p->drm_params.render_fd = -1; 199+ MP_VERBOSE(ctx, "Could not find path to render node. VAAPI hwdec will be disabled\n"); 200+ } 201+ 202+ struct ra_gl_ctx_params params = { 203+ .swap_buffers = mpegl_swap_buffers, 204+ .external_swapchain = p->kms->atomic_context ? &drm_atomic_swapchain : 205+ NULL, 206+ }; 207+#else 208 struct ra_gl_ctx_params params = { 209 .swap_buffers = mpegl_swap_buffers, 210 }; 211+#endif 212 213 if (!ra_gl_ctx_init(ctx, &p->gl, params)) 214 goto uninit; 215 216 ra_add_native_resource(ctx->ra, "x11", vo->x11->display); 217 218+#if HAVE_DRM 219+ ra_add_native_resource(ctx->ra, "drm_params", &p->drm_params); 220+#endif 221+ 222 return true; 223 224 uninit: 225@@ -174,6 +313,12 @@ static int mpegl_control(struct ra_ctx *ctx, int *events, int request, 226 int ret = vo_x11_control(ctx->vo, events, request, arg); 227 if (*events & VO_EVENT_RESIZE) 228 resize(ctx); 229+ 230+#if HAVE_DRM 231+ if (mpegl_update_position(ctx)) 232+ ctx->vo->want_redraw = true; 233+#endif 234+ 235 return ret; 236 } 237 238diff --git a/video/out/opengl/hwdec_drmprime_drm.c b/video/out/opengl/hwdec_drmprime_drm.c 239index d4543b0f47..2b34f7781c 100644 240--- a/video/out/opengl/hwdec_drmprime_drm.c 241+++ b/video/out/opengl/hwdec_drmprime_drm.c 242@@ -139,6 +139,8 @@ static int overlay_frame(struct ra_hwdec *hw, struct mp_image *hw_image, 243 AVDRMFrameDescriptor *desc = NULL; 244 drmModeAtomicReq *request = NULL; 245 struct drm_frame next_frame = {0}; 246+ int dx = dst ? dst->x0 : 0; 247+ int dy = dst ? dst->y0 : 0; 248 int ret; 249 250 // grab atomic request from native resources 251@@ -155,6 +157,9 @@ static int overlay_frame(struct ra_hwdec *hw, struct mp_image *hw_image, 252 MP_ERR(hw, "drm params pointer to atomic request is invalid"); 253 return -1; 254 } 255+ 256+ dx += drm_params->x; 257+ dy += drm_params->y; 258 } 259 260 if (hw_image) { 261@@ -190,14 +195,14 @@ static int overlay_frame(struct ra_hwdec *hw, struct mp_image *hw_image, 262 drm_object_set_property(request, p->ctx->video_plane, "SRC_Y", p->src.y0 << 16); 263 drm_object_set_property(request, p->ctx->video_plane, "SRC_W", srcw << 16); 264 drm_object_set_property(request, p->ctx->video_plane, "SRC_H", srch << 16); 265- drm_object_set_property(request, p->ctx->video_plane, "CRTC_X", MP_ALIGN_DOWN(p->dst.x0, 2)); 266- drm_object_set_property(request, p->ctx->video_plane, "CRTC_Y", MP_ALIGN_DOWN(p->dst.y0, 2)); 267+ drm_object_set_property(request, p->ctx->video_plane, "CRTC_X", MP_ALIGN_DOWN(dx, 2)); 268+ drm_object_set_property(request, p->ctx->video_plane, "CRTC_Y", MP_ALIGN_DOWN(dy, 2)); 269 drm_object_set_property(request, p->ctx->video_plane, "CRTC_W", dstw); 270 drm_object_set_property(request, p->ctx->video_plane, "CRTC_H", dsth); 271 drm_object_set_property(request, p->ctx->video_plane, "ZPOS", 0); 272 } else { 273 ret = drmModeSetPlane(p->ctx->fd, p->ctx->video_plane->id, p->ctx->crtc->id, next_frame.fb.fb_id, 0, 274- MP_ALIGN_DOWN(p->dst.x0, 2), MP_ALIGN_DOWN(p->dst.y0, 2), dstw, dsth, 275+ MP_ALIGN_DOWN(dx, 2), MP_ALIGN_DOWN(dy, 2), dstw, dsth, 276 p->src.x0 << 16, p->src.y0 << 16 , srcw << 16, srch << 16); 277 if (ret < 0) { 278 MP_ERR(hw, "Failed to set the plane %d (buffer %d).\n", p->ctx->video_plane->id, 279-- 2802.17.1 281 282