diff options
Diffstat (limited to 'video/out')
-rw-r--r-- | video/out/vo_dmabuf_wayland.c | 73 |
1 files changed, 71 insertions, 2 deletions
diff --git a/video/out/vo_dmabuf_wayland.c b/video/out/vo_dmabuf_wayland.c index 269ddc2a3d..a7c6206f98 100644 --- a/video/out/vo_dmabuf_wayland.c +++ b/video/out/vo_dmabuf_wayland.c @@ -30,6 +30,7 @@ #include "mpv_talloc.h" #include "present_sync.h" #include "sub/draw_bmp.h" +#include "video/fmt-conversion.h" #include "video/mp_image.h" #include "vo.h" #include "wayland_common.h" @@ -100,6 +101,8 @@ struct priv { bool destroy_buffers; enum hwdec_type hwdec_type; + uint32_t drm_format; + uint64_t drm_modifier; }; static void buffer_handle_release(void *data, struct wl_buffer *wl_buffer) @@ -147,6 +150,33 @@ static uintptr_t vaapi_surface_id(struct mp_image *src) return id; } +static bool vaapi_drm_format(struct vo *vo, struct mp_image *src) +{ + bool format = false; +#if HAVE_VAAPI + struct priv *p = vo->priv; + VADRMPRIMESurfaceDescriptor desc = {0}; + + uintptr_t id = vaapi_surface_id(src); + VADisplay display = ra_get_native_resource(p->ctx->ra, "VADisplay"); + VAStatus status = vaExportSurfaceHandle(display, id, VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2, + VA_EXPORT_SURFACE_COMPOSED_LAYERS | VA_EXPORT_SURFACE_READ_ONLY, &desc); + + if (!CHECK_VA_STATUS(vo, "vaExportSurfaceHandle()")) { + /* invalid surface warning => composed layers not supported */ + if (status == VA_STATUS_ERROR_INVALID_SURFACE) + MP_VERBOSE(vo, "vaExportSurfaceHandle: composed layers not supported.\n"); + goto done; + } + p->drm_format = desc.layers[0].drm_format; + p->drm_modifier = desc.objects[0].drm_format_modifier; + format = true; +done: + close_file_descriptors(desc); +#endif + return format; +} + static void vaapi_dmabuf_importer(struct buffer *buf, struct mp_image *src, struct zwp_linux_buffer_params_v1 *params) { @@ -197,6 +227,20 @@ static uintptr_t drmprime_surface_id(struct mp_image *src) return id; } +static bool drmprime_drm_format(struct vo *vo, struct mp_image *src) +{ + struct priv *p = vo->priv; + struct AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)src->planes[0]; + if (!desc) + return false; + + // Just check the very first layer/plane. + p->drm_format = desc->layers[0].format; + int object_index = desc->layers[0].planes[0].object_index; + p->drm_modifier = desc->objects[object_index].format_modifier; + return true; +} + static void drmprime_dmabuf_importer(struct buffer *buf, struct mp_image *src, struct zwp_linux_buffer_params_v1 *params) { @@ -237,6 +281,18 @@ static intptr_t surface_id(struct vo *vo, struct mp_image *src) } } +static bool drm_format_check(struct vo *vo, struct mp_image *src) +{ + struct priv *p = vo->priv; + switch(p->hwdec_type) { + case HWDEC_VAAPI: + return vaapi_drm_format(vo, src); + case HWDEC_DRMPRIME: + return drmprime_drm_format(vo, src); + } + return false; +} + static struct buffer *buffer_check(struct vo *vo, struct mp_image *src) { struct priv *p = vo->priv; @@ -588,8 +644,21 @@ static int query_format(struct vo *vo, int format) return is_supported_fmt(format); } -static int reconfig(struct vo *vo, struct mp_image_params *params) +static int reconfig(struct vo *vo, struct mp_image *img) { + struct priv *p = vo->priv; + + if (!drm_format_check(vo, img)) { + MP_ERR(vo, "Unable to get drm format from hardware decoding!\n"); + return VO_ERROR; + } + + if (!ra_compatible_format(p->ctx->ra, p->drm_format, p->drm_modifier)) { + MP_ERR(vo, "Format '%s' with modifier '(%016lx)' is not supported by" + " the compositor.\n", mp_tag_str(p->drm_format), p->drm_modifier); + return VO_ERROR; + } + if (!vo_wayland_reconfig(vo)) return VO_ERROR; @@ -754,7 +823,7 @@ const struct vo_driver video_out_dmabuf_wayland = { .name = "dmabuf-wayland", .preinit = preinit, .query_format = query_format, - .reconfig = reconfig, + .reconfig2 = reconfig, .control = control, .draw_frame = draw_frame, .flip_page = flip_page, |