Skip to content

Commit

Permalink
vo_opengl: x11egl: Support drm hwdec
Browse files Browse the repository at this point in the history
Tested with:
mpv --hwdec=rkmpp --vo=opengl test.mp4

Change-Id: Ic49e2acaa288496180037d2ca648eb824d4a663c
Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
  • Loading branch information
JeffyCN committed Mar 12, 2021
1 parent 391edcb commit af32a0b
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 3 deletions.
3 changes: 3 additions & 0 deletions libmpv/render_gl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
145 changes: 145 additions & 0 deletions video/out/opengl/context_x11egl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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)
Expand All @@ -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);
}

Expand Down Expand Up @@ -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:
Expand All @@ -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;
}

Expand Down
11 changes: 8 additions & 3 deletions video/out/opengl/hwdec_drmprime_drm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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) {
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit af32a0b

Please sign in to comment.