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