1
0
mirror of https://github.com/mpv-player/mpv synced 2025-03-30 07:18:17 +00:00

drm/atomic: refactor hwdec_drmprime_drm with native resources

That new API was introduced and allows to have several native resources.
Thisuses that mechanisma for drm resources rather than the deprecated
opengl-cb structs.

This patch therefore add two structs that can be used with the drm atomic interop.
 - mpv_opengl_drm_params : which will hold all the drm handles
 - mpv_opengl_drm_osd_size : which will hold osd layer size

This commit adds a drm-osd-size=WxH parameter to commandline which
allows to define the OSD plane dimension. OSD can be upscaled to
screen resolution when having OSD at video resolution is too heavy.

This is especially useful for UHD modes on embedded devices where
the GPU cannot handle UHD modes at a decent framerate.
This commit is contained in:
LongChair 2018-04-29 15:09:16 +02:00 committed by Jan Ekström
parent 11f915f5ef
commit 9f2970f28a
8 changed files with 113 additions and 35 deletions

View File

@ -488,11 +488,6 @@ Available video output drivers are:
Mode ID to use (resolution and frame rate).
(default: 0)
``--drm-overlay=<number>``
Select the DRM overlay index to use.
Overlay index is zero based, and related to crtc.
(default: 0)
``--drm-format=<xrgb8888,xrgb2101010>``
Select the DRM format to use (default: xrgb8888). This allows you to
choose the bit depth of the DRM mode. xrgb8888 is your usual 24 bit per
@ -506,6 +501,13 @@ Available video output drivers are:
This currently only has an effect when used together with the ``drm``
backend for the ``gpu`` VO. The ``drm`` VO always uses xrgb8888.
``--drm-osd-size=<[WxH]>``
Sets the OSD OpenGL size to the specified size. OSD will then be upscaled
to the current screen resolution. This option can be useful when using
several layers in high resolutions with a GPU which cannot handle it.
Note : this option is only available with DRM atomic support.
(default: display resolution)
``mediacodec_embed`` (Android)
Renders ``IMGFMT_MEDIACODEC`` frames directly to an ``android.view.Surface``.
Requires ``--hwdec=mediacodec`` for hardware decoding, along with

View File

@ -276,6 +276,18 @@ typedef enum mpv_render_param_type {
* in the same way.
*/
MPV_RENDER_PARAM_SKIP_RENDERING = 13,
/**
* DRM display, contains drm display handles.
* Valid for mpv_render_context_create().
* Type : struct mpv_opengl_drm_params*
*/
MPV_RENDER_PARAM_DRM_DISPLAY = 14,
/**
* DRM osd size, contains osd dimensions.
* Valid for mpv_render_context_create().
* Type : struct mpv_opengl_drm_osd_size*
*/
MPV_RENDER_PARAM_DRM_OSD_SIZE = 15,
} mpv_render_param_type;
/**

View File

@ -147,6 +147,37 @@ typedef struct mpv_opengl_fbo {
int internal_format;
} mpv_opengl_fbo;
typedef struct mpv_opengl_drm_params {
/**
* DRM fd (int). set this to -1 if invalid.
*/
int fd;
/**
* Currently used crtc id
*/
int crtc_id;
/**
* Currently used connector id
*/
int connector_id;
/**
* Pointer to a drmModeAtomicReq pointer that is being used for the renderloop.
* This pointer should hold a pointer to the atomic request pointer
* The atomic request pointer is usually changed at every renderloop.
*/
struct _drmModeAtomicReq **atomic_request_ptr;
} mpv_opengl_drm_params;
typedef struct mpv_opengl_drm_osd_size {
/**
* size of the OSD in pixels.
*/
int width, height;
} mpv_opengl_drm_osd_size;
#ifdef __cplusplus
}
#endif

View File

@ -51,6 +51,7 @@ const struct m_sub_options drm_conf = {
OPT_CHOICE("drm-format", drm_format, 0,
({"xrgb8888", DRM_OPTS_FORMAT_XRGB8888},
{"xrgb2101010", DRM_OPTS_FORMAT_XRGB2101010})),
OPT_SIZE_BOX("drm-osd-size", drm_osd_size, 0),
{0},
},
.size = sizeof(struct drm_opts),

View File

@ -50,6 +50,7 @@ struct drm_opts {
int drm_mode_id;
int drm_overlay_id;
int drm_format;
struct m_geometry drm_osd_size;
};
bool vt_switcher_init(struct vt_switcher *s, struct mp_log *log);

View File

@ -1,6 +1,7 @@
#include "config.h"
#include "hwdec.h"
#include "libmpv_gpu.h"
#include "libmpv/render_gl.h"
#include "video.h"
#include "video/out/libmpv.h"
@ -31,6 +32,14 @@ static const struct native_resource_entry native_resource_map[] = {
.name = "wl",
.size = 0,
},
[MPV_RENDER_PARAM_DRM_DISPLAY] = {
.name = "drm_params",
.size = sizeof (mpv_opengl_drm_params),
},
[MPV_RENDER_PARAM_DRM_OSD_SIZE] = {
.name = "drm_osd_size",
.size = sizeof (mpv_opengl_drm_osd_size),
},
};
static int init(struct render_backend *ctx, mpv_render_param *params)

View File

@ -28,7 +28,7 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include "libmpv/opengl_cb.h"
#include "libmpv/render_gl.h"
#include "video/out/drm_common.h"
#include "common/common.h"
#include "osdep/timer.h"
@ -80,7 +80,8 @@ struct priv {
bool vt_switcher_active;
struct vt_switcher vt_switcher;
struct mpv_opengl_cb_drm_params drm_params;
struct mpv_opengl_drm_params drm_params;
struct mpv_opengl_drm_osd_size osd_size;
};
// Not general. Limited to only the formats being used in this module
@ -194,11 +195,11 @@ static bool init_gbm(struct ra_ctx *ctx)
}
MP_VERBOSE(ctx->vo, "Initializing GBM surface (%d x %d)\n",
p->kms->mode.hdisplay, p->kms->mode.vdisplay);
p->osd_size.width, p->osd_size.height);
p->gbm.surface = gbm_surface_create(
p->gbm.device,
p->kms->mode.hdisplay,
p->kms->mode.vdisplay,
p->osd_size.width,
p->osd_size.height,
p->gbm_format,
GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
if (!p->gbm.surface) {
@ -325,7 +326,7 @@ static bool drm_atomic_egl_start_frame(struct ra_swapchain *sw, struct ra_fbo *o
if (p->kms->atomic_context) {
if (!p->kms->atomic_context->request) {
p->kms->atomic_context->request = drmModeAtomicAlloc();
p->drm_params.atomic_request = p->kms->atomic_context->request;
p->drm_params.atomic_request_ptr = &p->kms->atomic_context->request;
}
return ra_gl_ctx_start_frame(sw, out_fbo);
}
@ -383,7 +384,7 @@ static void drm_egl_swap_buffers(struct ra_ctx *ctx)
if (atomic_ctx) {
drmModeAtomicFree(atomic_ctx->request);
p->drm_params.atomic_request = atomic_ctx->request = drmModeAtomicAlloc();
atomic_ctx->request = drmModeAtomicAlloc();
}
gbm_surface_release_buffer(p->gbm.surface, p->gbm.bo);
@ -495,6 +496,20 @@ static bool drm_egl_init(struct ra_ctx *ctx)
return false;
}
if (ctx->vo->opts->drm_opts->drm_osd_size.wh_valid) {
if (p->kms->atomic_context) {
p->osd_size.width = ctx->vo->opts->drm_opts->drm_osd_size.w;
p->osd_size.height = ctx->vo->opts->drm_opts->drm_osd_size.h;
} else {
p->osd_size.width = p->kms->mode.hdisplay;
p->osd_size.height = p->kms->mode.vdisplay;
MP_WARN(ctx, "Setting OSD size is only available with DRM atomic, defaulting to screen resolution\n");
}
} else {
p->osd_size.width = p->kms->mode.hdisplay;
p->osd_size.height = p->kms->mode.vdisplay;
}
uint32_t argb_format;
uint32_t xrgb_format;
if (DRM_OPTS_FORMAT_XRGB2101010 == ctx->vo->opts->drm_opts->drm_format) {
@ -550,9 +565,10 @@ static bool drm_egl_init(struct ra_ctx *ctx)
}
p->drm_params.fd = p->kms->fd;
p->drm_params.connector_id = p->kms->connector->connector_id;
p->drm_params.crtc_id = p->kms->crtc_id;
if (p->kms->atomic_context)
p->drm_params.atomic_request = p->kms->atomic_context->request;
p->drm_params.atomic_request_ptr = &p->kms->atomic_context->request;
struct ra_gl_ctx_params params = {
.swap_buffers = drm_egl_swap_buffers,
.external_swapchain = p->kms->atomic_context ? &drm_atomic_swapchain :
@ -561,7 +577,8 @@ static bool drm_egl_init(struct ra_ctx *ctx)
if (!ra_gl_ctx_init(ctx, &p->gl, params))
return false;
ra_add_native_resource(ctx->ra, "opengl-cb-drm-params", &p->drm_params);
ra_add_native_resource(ctx->ra, "drm_params", &p->drm_params);
ra_add_native_resource(ctx->ra, "drm_osd_size", &p->osd_size);
return true;
}

View File

@ -29,7 +29,7 @@
#include "video/hwdec.h"
#include "common/msg.h"
#include "options/m_config.h"
#include "libmpv/opengl_cb.h"
#include "libmpv/render_gl.h"
#include "video/out/drm_common.h"
#include "video/out/drm_prime.h"
#include "video/out/gpu/hwdec.h"
@ -117,25 +117,34 @@ static int overlay_frame(struct ra_hwdec *hw, struct mp_image *hw_image,
struct drm_frame next_frame = {0};
int ret;
// grab atomic request from native resources
if (p->ctx) {
struct mpv_opengl_drm_params *drm_params;
drm_params = (mpv_opengl_drm_params *)ra_get_native_resource(hw->ra, "drm_params");
if (!drm_params) {
MP_ERR(hw, "Failed to retrieve drm params from native resources\n");
return -1;
}
if (drm_params->atomic_request_ptr) {
request = *drm_params->atomic_request_ptr;
} else {
MP_ERR(hw, "drm params pointer to atomic request is invalid");
return -1;
}
}
if (hw_image) {
// grab opengl-cb windowing info to eventually upscale the overlay
// as egl windows could be upscaled to primary plane.
struct mpv_opengl_cb_window_pos *glparams =
ra_get_native_resource(hw->ra, "opengl-cb-window-pos");
if (glparams) {
scale_dst_rect(hw, glparams->width, glparams->height, dst, &p->dst);
// grab osd windowing info to eventually upscale the overlay
// as egl windows could be upscaled to osd plane.
struct mpv_opengl_drm_osd_size *osd_size = ra_get_native_resource(hw->ra, "drm_osd_size");
if (osd_size) {
scale_dst_rect(hw, osd_size->width, osd_size->height, dst, &p->dst);
} else {
p->dst = *dst;
}
p->src = *src;
// grab drm interop info
struct mpv_opengl_cb_drm_params *drmparams =
ra_get_native_resource(hw->ra, "opengl-cb-drm-params");
if (drmparams)
request = (drmModeAtomicReq *)drmparams->atomic_request;
next_frame.image = hw_image;
desc = (AVDRMFrameDescriptor *)hw_image->planes[0];
@ -210,15 +219,11 @@ static int init(struct ra_hwdec *hw)
drm_overlay = opts->drm_overlay_id;
talloc_free(tmp);
struct mpv_opengl_cb_drm_params *params =
ra_get_native_resource(hw->ra, "opengl-cb-drm-params");
if (!params) {
MP_VERBOSE(hw, "Could not get drm interop info.\n");
goto err;
}
struct mpv_opengl_drm_params *drm_params;
if (params->fd) {
p->ctx = drm_atomic_create_context(p->log, params->fd, params->crtc_id,
drm_params = ra_get_native_resource(hw->ra, "drm_params");
if (drm_params) {
p->ctx = drm_atomic_create_context(p->log, drm_params->fd, drm_params->crtc_id,
drm_overlay);
if (!p->ctx) {
mp_err(p->log, "Failed to retrieve DRM atomic context.\n");