diff --git a/DOCS/interface-changes.rst b/DOCS/interface-changes.rst index 08641b046a..4a21d3ba5c 100644 --- a/DOCS/interface-changes.rst +++ b/DOCS/interface-changes.rst @@ -41,7 +41,7 @@ Interface changes - add `dolbyvision` sub-parameter to `format` video filter - `--sub-visibility` no longer has any effect on secondary subtitles - add `film-grain` sub-parameter to `format` video filter - - add experimental `--vo=vaapi-wayland` video output driver + - add experimental `--vo=dmabuf-wayland` video output driver - add `--x11-present` for controlling whether to use xorg's present extension - add `engine` option to the `rubberband` audio filter to support the new engine introduced in rubberband 3.0.0. Defaults to `finer` (new engine). diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index 11e5cd732d..ed55dbfeae 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -1249,7 +1249,7 @@ Video :videotoolbox: requires ``--vo=gpu`` (macOS 10.8 and up), or ``--vo=libmpv`` (iOS 9.0 and up) :videotoolbox-copy: copies video back into system RAM (macOS 10.8 or iOS 9.0 and up) - :vaapi: requires ``--vo=gpu``, ``--vo=vaapi`` or ``--vo=vaapi-wayland`` (Linux only) + :vaapi: requires ``--vo=gpu``, ``--vo=vaapi`` or ``--vo=dmabuf-wayland`` (Linux only) :vaapi-copy: copies video back into system RAM (Linux with some GPUs only) :nvdec: requires ``--vo=gpu`` (Any platform CUDA is available) :nvdec-copy: copies video back to system RAM (Any platform CUDA is available) diff --git a/DOCS/man/vo.rst b/DOCS/man/vo.rst index c71ebd4c45..06e80c4ea2 100644 --- a/DOCS/man/vo.rst +++ b/DOCS/man/vo.rst @@ -286,12 +286,13 @@ Available video output drivers are: ``--sdl-switch-mode`` Instruct SDL to switch the monitor video mode when going fullscreen. -``vaapi-wayland`` - Experimental Wayland output driver designed for use with VA API hardware decoding. - The driver is designed to avoid any GPU to CPU copies, and to perform scaling and - color space conversion using fixed-function hardware, if available, - rather than GPU shaders. This frees up GPU resources for other tasks. - Currently this driver is experimental and only works with the ``--hwdec=vaapi`` driver; +``dmabuf-wayland`` + Experimental Wayland output driver designed for use with either drm stateless + or VA API hardware decoding. The driver is designed to avoid any GPU to CPU copies, + and to perform scaling and color space conversion using fixed-function hardware, + if available, rather than GPU shaders. This frees up GPU resources for other tasks. + Currently this driver is experimental and only works with the ``--hwdec=vaapi`` + or ``hwdec=drm`` drivers; OSD is also not supported. Supported compositors : Weston and Sway. ``vaapi`` diff --git a/ci/build-freebsd.sh b/ci/build-freebsd.sh index 3f1ed6a455..2a7d2f1813 100755 --- a/ci/build-freebsd.sh +++ b/ci/build-freebsd.sh @@ -12,7 +12,7 @@ meson build \ -Dopenal=enabled \ -Dsdl2=enabled \ -Dsndio=enabled \ - -Dvaapi-wayland=enabled \ + -Ddmabuf-wayland=enabled \ -Dvdpau=enabled \ -Dvulkan=enabled \ -Doss-audio=enabled \ @@ -36,7 +36,7 @@ python3 ./waf configure \ --enable-openal \ --enable-sdl2 \ --enable-sndio \ - --enable-vaapi-wayland \ + --enable-dmabuf-wayland \ --enable-vdpau \ --enable-vulkan \ --enable-oss-audio \ diff --git a/meson.build b/meson.build index c3b8c256c5..629e374a66 100644 --- a/meson.build +++ b/meson.build @@ -1375,11 +1375,6 @@ if features['vaapi-wayland'] dependencies += vaapi_wayland endif -features += {'vaapi-wayland-memfd': features['vaapi-wayland'] and features['memfd_create']} -if features['vaapi-wayland-memfd'] - sources += files('video/out/vo_vaapi_wayland.c') -endif - vaapi_x11 = dependency('libva-x11', version: '>= 1.1.0', required: get_option('vaapi-x11')) features += {'vaapi-x11': features['vaapi'] and features['x11'] and vaapi_x11.found()} if features['vaapi-x11'] diff --git a/video/out/vo.c b/video/out/vo.c index f4ecd3d7bf..4e999d0754 100644 --- a/video/out/vo.c +++ b/video/out/vo.c @@ -62,7 +62,6 @@ extern const struct vo_driver video_out_drm; extern const struct vo_driver video_out_direct3d; extern const struct vo_driver video_out_sdl; extern const struct vo_driver video_out_vaapi; -extern const struct vo_driver video_out_vaapi_wayland; extern const struct vo_driver video_out_dmabuf_wayland; extern const struct vo_driver video_out_wlshm; extern const struct vo_driver video_out_rpi; @@ -97,9 +96,6 @@ const struct vo_driver *const video_out_drivers[] = #if HAVE_DMABUF_WAYLAND &video_out_dmabuf_wayland, #endif -#if HAVE_VAAPI_WAYLAND - &video_out_vaapi_wayland, -#endif #if HAVE_VAAPI_X11 && HAVE_GPL &video_out_vaapi, #endif diff --git a/video/out/vo_vaapi_wayland.c b/video/out/vo_vaapi_wayland.c deleted file mode 100644 index ad88d50e55..0000000000 --- a/video/out/vo_vaapi_wayland.c +++ /dev/null @@ -1,393 +0,0 @@ -/* - * This file is part of mpv video player. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * mpv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with mpv. If not, see . - */ - -#include -#include -#include -#include -#include - -#include "present_sync.h" -#include "sub/osd.h" -#include "video/vaapi.h" -#include "wayland_common.h" - -#include "generated/wayland/linux-dmabuf-unstable-v1.h" -#include "generated/wayland/viewporter.h" - -#define VA_POOL_NUM_ALLOCATED_INIT 30 - -struct va_pool_entry { - /* key */ - VASurfaceID surface; - - VADRMPRIMESurfaceDescriptor desc; - struct wl_buffer *buffer; - struct zwp_linux_buffer_params_v1 *params; - uint32_t drm_format; -}; - -struct va_pool { - struct vo *vo; - struct va_pool_entry **entries; - int num_entries; - int num_allocated; -}; - -struct priv { - struct vo *vo; - struct mp_rect src; - struct mp_rect dst; - struct mp_osd_res osd; - struct mp_log *log; - - VADisplay display; - struct mp_vaapi_ctx *mpvaapi; - struct wl_shm_pool *solid_buffer_pool; - struct wl_buffer *solid_buffer; - struct va_pool *va_pool; -}; - -static void va_close_surface_descriptor(VADRMPRIMESurfaceDescriptor desc) -{ - for (int i = 0; i < desc.num_objects; i++) { - close(desc.objects[i].fd); - desc.objects[i].fd = 0; - } -} - -static void va_free_entry(struct va_pool_entry *entry) -{ - if (!entry) - return; - va_close_surface_descriptor(entry->desc); - if (entry->buffer) - wl_buffer_destroy(entry->buffer); - if (entry->params) - zwp_linux_buffer_params_v1_destroy(entry->params); - talloc_free(entry); -} - -static VAStatus va_export_surface_handle(VADisplay display, VASurfaceID surface, - VADRMPRIMESurfaceDescriptor *desc) -{ - return vaExportSurfaceHandle(display, surface, - VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2, - VA_EXPORT_SURFACE_COMPOSED_LAYERS | - VA_EXPORT_SURFACE_READ_ONLY, - desc); -} - -static struct va_pool_entry *va_alloc_entry(struct vo *vo, struct mp_image *src) -{ - struct priv *p = vo->priv; - struct vo_wayland_state *wl = vo->wl; - VAStatus status; - struct va_pool_entry *entry = talloc(NULL, struct va_pool_entry); - memset(entry, 0, sizeof(struct va_pool_entry)); - - /* extract dmabuf surface descriptor */ - entry->surface = va_surface_id(src); - status = va_export_surface_handle(p->display, entry->surface, &entry->desc); - if (status == VA_STATUS_ERROR_INVALID_SURFACE) { - MP_VERBOSE(vo, "VA export to composed layers not supported.\n"); - va_free_entry(entry); - return NULL; - } else if (!vo_wayland_supported_format(vo, entry->desc.layers[0].drm_format)) { - MP_VERBOSE(vo, "%s is not supported.\n", - mp_tag_str(entry->desc.layers[0].drm_format)); - va_free_entry(entry); - return NULL; - } else if (!CHECK_VA_STATUS(vo, "vaExportSurfaceHandle()")) { - va_free_entry(entry); - return NULL; - } else { - int i, j, plane = 0; - - entry->params = zwp_linux_dmabuf_v1_create_params(wl->dmabuf); - for (i = 0; i < entry->desc.num_layers; i++) { - entry->drm_format = entry->desc.layers[i].drm_format; - for (j = 0; j < entry->desc.layers[i].num_planes; ++j) { - int object = entry->desc.layers[i].object_index[j]; - uint64_t modifier = entry->desc.objects[object].drm_format_modifier; - zwp_linux_buffer_params_v1_add(entry->params, - entry->desc.objects[object].fd, plane++, - entry->desc.layers[i].offset[j], - entry->desc.layers[i].pitch[j], - modifier >> 32, - modifier & 0xffffffff); - } - } - } - - entry->buffer = zwp_linux_buffer_params_v1_create_immed(entry->params, - src->params.w, - src->params.h, - entry->drm_format, 0); - - return entry; -} -static void va_pool_clean(struct va_pool *pool) -{ - if (!pool) - return; - - for (int i = 0; i < pool->num_entries; ++i) - va_free_entry(pool->entries[i]); - pool->num_entries = 0; -} - -static void va_pool_free(struct va_pool *pool) -{ - if (!pool) - return; - - va_pool_clean(pool); - talloc_free(pool); -} - -static struct va_pool *va_pool_alloc(struct vo *vo) -{ - struct va_pool *pool = talloc(NULL, struct va_pool); - memset(pool, 0, sizeof(struct va_pool)); - pool->num_allocated = VA_POOL_NUM_ALLOCATED_INIT; - pool->entries = talloc_array(pool, struct va_pool_entry *, pool->num_allocated); - memset(pool->entries, 0, pool->num_allocated * sizeof(struct va_pool_entry *)); - pool->vo = vo; - - return pool; -} - -static struct va_pool_entry *va_pool_alloc_entry(struct vo *vo, struct va_pool *pool, - struct mp_image *src) -{ - VASurfaceID surface; - - if (!pool) - return NULL; - - surface = va_surface_id(src); - for (int i = 0; i < pool->num_entries; ++i) { - struct va_pool_entry *item = pool->entries[i]; - if (item->surface == surface) - return pool->entries[i]; - } - - struct va_pool_entry *entry = va_alloc_entry(pool->vo, src); - if (!entry) - return NULL; - - if (pool->num_entries == pool->num_allocated) { - int current_num_allocated = pool->num_allocated; - pool->num_allocated *= 2; - pool->entries = talloc_realloc(pool, pool->entries, struct va_pool_entry *, - pool->num_allocated); - for (int i = current_num_allocated; i < pool->num_allocated; ++i) - pool->entries[i] = NULL; - } - pool->entries[pool->num_entries++] = entry; - - return entry; -} - -static void uninit(struct vo *vo) -{ - struct priv *p = vo->priv; - - va_pool_free(p->va_pool); - - if (p->solid_buffer_pool) - wl_shm_pool_destroy(p->solid_buffer_pool); - if (p->solid_buffer) - wl_buffer_destroy(p->solid_buffer); - - vo_wayland_uninit(vo); - - if (vo->hwdec_devs) { - hwdec_devices_remove(vo->hwdec_devs, &p->mpvaapi->hwctx); - hwdec_devices_destroy(vo->hwdec_devs); - } - if (p->mpvaapi) - va_destroy(p->mpvaapi); -} - -static int preinit(struct vo *vo) -{ - struct priv *p = vo->priv; - - p->vo = vo; - p->log = vo->log; - if (!vo_wayland_init(vo)) - return VO_ERROR; - - p->display = vaGetDisplayWl(vo->wl->display); - if (!p->display) { - MP_ERR(vo, "Unable to get the VA Display.\n"); - return VO_ERROR; - } - - p->mpvaapi = va_initialize(p->display, p->log, false); - if (!p->mpvaapi) { - vaTerminate(p->display); - p->display = NULL; - goto fail; - } - - vo->hwdec_devs = hwdec_devices_create(); - hwdec_devices_add(vo->hwdec_devs, &p->mpvaapi->hwctx); - p->va_pool = va_pool_alloc(vo); - - return 0; - -fail: - uninit(vo); - - return VO_ERROR; -} - -static int query_format(struct vo *vo, int format) -{ - return format == IMGFMT_VAAPI; -} - -static int reconfig(struct vo *vo, struct mp_image_params *params) -{ - struct priv *p = vo->priv; - struct vo_wayland_state *wl = vo->wl; - - if (!p->solid_buffer_pool) { - int width = 1; - int height = 1; - int stride = MP_ALIGN_UP(width * 4, 16); - int fd = vo_wayland_allocate_memfd(vo, stride); - if (fd < 0) - return VO_ERROR; - p->solid_buffer_pool = wl_shm_create_pool(wl->shm, fd, height * stride); - if (!p->solid_buffer_pool) - return VO_ERROR; - p->solid_buffer = wl_shm_pool_create_buffer(p->solid_buffer_pool, 0, - width, height, stride, - WL_SHM_FORMAT_XRGB8888); - if (!p->solid_buffer) - return VO_ERROR; - wl_surface_attach(wl->surface, p->solid_buffer, 0, 0); - } - - if (!vo_wayland_reconfig(vo)) - return VO_ERROR; - - return 0; -} - -static int resize(struct vo *vo) -{ - struct vo_wayland_state *wl = vo->wl; - struct priv *p = vo->priv; - - vo_wayland_set_opaque_region(wl, 0); - const int width = wl->scaling * mp_rect_w(wl->geometry); - const int height = wl->scaling * mp_rect_h(wl->geometry); - vo->dwidth = width; - vo->dheight = height; - vo_get_src_dst_rects(vo, &p->src, &p->dst, &p->osd); - - wp_viewport_set_destination(wl->viewport, - (p->dst.x0 << 1) + mp_rect_w(p->dst), - (p->dst.y0 << 1) + mp_rect_h(p->dst)); - wp_viewport_set_destination(wl->video_viewport, mp_rect_w(p->dst), - mp_rect_h(p->dst)); - wl_subsurface_set_position(wl->video_subsurface, p->dst.x0, p->dst.y0); - - vo->want_redraw = true; - - return VO_TRUE; -} - -static int control(struct vo *vo, uint32_t request, void *data) -{ - struct priv *p = vo->priv; - int events = 0; - int ret; - - switch (request) { - /* need to clean pool after seek to avoid artifacts */ - case VOCTRL_RESET: - va_pool_clean(p->va_pool); - break; - default: - break; - } - ret = vo_wayland_control(vo, &events, request, data); - if (events & VO_EVENT_RESIZE) - ret = resize(vo); - if (events & VO_EVENT_EXPOSE) - vo->want_redraw = true; - vo_event(vo, events); - - return ret; -} - -static void draw_frame(struct vo *vo, struct vo_frame *frame) -{ - struct priv *p = vo->priv; - struct vo_wayland_state *wl = vo->wl; - - if (!vo_wayland_check_visible(vo)) - return; - - struct va_pool_entry *entry = va_pool_alloc_entry(vo, p->va_pool, - frame->current); - if (!entry) - return; - - wl_surface_attach(wl->video_surface, entry->buffer, 0, 0); - wl_surface_damage_buffer(wl->video_surface, 0, 0, INT32_MAX, INT32_MAX); - wl_surface_commit(wl->video_surface); - wl_surface_commit(wl->surface); - - if (!wl->opts->disable_vsync) - vo_wayland_wait_frame(wl); - if (wl->use_present) - present_sync_swap(wl->present); -} -static void flip_page(struct vo *vo) -{ - /* no-op */ -} - -static void get_vsync(struct vo *vo, struct vo_vsync_info *info) -{ - struct vo_wayland_state *wl = vo->wl; - if (wl->use_present) - present_sync_get_info(wl->present, info); -} - -const struct vo_driver video_out_vaapi_wayland = { - .description = "VA API with Wayland video output", - .name = "vaapi-wayland", - .preinit = preinit, - .query_format = query_format, - .reconfig = reconfig, - .control = control, - .draw_frame = draw_frame, - .flip_page = flip_page, - .get_vsync = get_vsync, - .wakeup = vo_wayland_wakeup, - .wait_events = vo_wayland_wait_events, - .uninit = uninit, - .priv_size = sizeof(struct priv) -}; diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c index 8a9158e2b1..ba2fba7f78 100644 --- a/video/out/wayland_common.c +++ b/video/out/wayland_common.c @@ -1491,9 +1491,9 @@ static int set_screensaver_inhibitor(struct vo_wayland_state *wl, int state) static void set_surface_scaling(struct vo_wayland_state *wl) { - bool vaapi_wayland = !strcmp(wl->vo->driver->name, "vaapi-wayland"); + bool dmabuf_wayland = !strcmp(wl->vo->driver->name, "dmabuf-wayland"); int old_scale = wl->scaling; - if (wl->vo_opts->hidpi_window_scale && !vaapi_wayland) { + if (wl->vo_opts->hidpi_window_scale && !dmabuf_wayland) { wl->scaling = wl->current_output->scale; } else { wl->scaling = 1; diff --git a/wscript b/wscript index a9f3927eaa..22abd31314 100644 --- a/wscript +++ b/wscript @@ -664,11 +664,6 @@ video_output_features = [ 'desc': 'VAAPI (Wayland support)', 'deps': 'vaapi && gl-wayland', 'func': check_pkg_config('libva-wayland', '>= 1.1.0'), - }, { - 'deps': 'vaapi-wayland && memfd_create', - 'name': 'vaapi-wayland-memfd', - 'desc': 'Wayland vaapi support', - 'func': check_true, }, { 'name': 'dmabuf-wayland', 'desc': 'Wayland dmabuf support', diff --git a/wscript_build.py b/wscript_build.py index 7588ed7e47..16c8cf0895 100644 --- a/wscript_build.py +++ b/wscript_build.py @@ -527,7 +527,6 @@ def build(ctx): ( "video/out/vo_sixel.c", "sixel" ), ( "video/out/vo_tct.c" ), ( "video/out/vo_vaapi.c", "vaapi-x11 && gpl" ), - ( "video/out/vo_vaapi_wayland.c", "vaapi-wayland-memfd" ), ( "video/out/vo_dmabuf_wayland.c", "dmabuf-wayland" ), ( "video/out/vo_vdpau.c", "vdpau" ), ( "video/out/vo_wlshm.c", "wayland && memfd_create" ),