mirror of
https://github.com/mpv-player/mpv
synced 2025-03-20 02:09:52 +00:00
vo_dmabuf_wayland: wayland VO displaying dmabuf buffers
Wayland VO that can display images from either vaapi or drm hwdec The PR adds the following changes: 1. a context_wldmabuf context with no gl dependencies 2. no-op ra_wldmabuf and dmabuf_interop_wldmabuf objects no-op because there is no need to map/unmap the drmprime buffer, and there is no need to manage any textures. Tested on both x86_64 and rk3399 AArch64
This commit is contained in:
parent
964692ad4c
commit
7358b9d371
@ -6150,6 +6150,8 @@ them.
|
||||
X11/EGL
|
||||
android
|
||||
Android/EGL. Requires ``--wid`` be set to an ``android.view.Surface``.
|
||||
wldmabuf
|
||||
dmabuf buffers are rendered directly by Wayland compositor
|
||||
|
||||
``--gpu-api=<type>``
|
||||
Controls which type of graphics APIs will be accepted:
|
||||
@ -6162,6 +6164,9 @@ them.
|
||||
Allow only Vulkan (requires a valid/working ``--spirv-compiler``)
|
||||
d3d11
|
||||
Allow only ``--gpu-context=d3d11``
|
||||
none
|
||||
No graphics API is used - Wayland alone is used for rendering
|
||||
(requires Wayland compositor)
|
||||
|
||||
``--opengl-es=<mode>``
|
||||
Controls which type of OpenGL context will be accepted:
|
||||
|
@ -195,12 +195,13 @@ static bool build_image_converter(struct mp_autoconvert *c, struct mp_log *log,
|
||||
bool hw_to_sw = !imgfmt_is_sw && dst_have_sw;
|
||||
|
||||
if (dst_all_hw && num_fmts > 0) {
|
||||
bool upload_created = false;
|
||||
int sw_fmt = imgfmt_is_sw ? img->imgfmt : img->params.hw_subfmt;
|
||||
|
||||
for (int i = 0; i < num_fmts; i++) {
|
||||
// We can probably use this! Very lazy and very approximate.
|
||||
struct mp_hwupload *upload = mp_hwupload_create(conv, fmts[i]);
|
||||
if (upload) {
|
||||
int sw_fmt = imgfmt_is_sw ? img->imgfmt : img->params.hw_subfmt;
|
||||
|
||||
mp_info(log, "HW-uploading to %s\n", mp_imgfmt_to_name(fmts[i]));
|
||||
filters[2] = upload->f;
|
||||
hwupload_fmt = mp_hwupload_find_upload_format(upload, sw_fmt);
|
||||
@ -215,9 +216,16 @@ static bool build_image_converter(struct mp_autoconvert *c, struct mp_log *log,
|
||||
mp_err(log, "Format %s is not supported by %s\n",
|
||||
mp_imgfmt_to_name(sw_fmt),
|
||||
mp_imgfmt_to_name(p->imgfmts[i]));
|
||||
continue;
|
||||
}
|
||||
upload_created = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!upload_created) {
|
||||
mp_err(log, "Failed to create HW uploader for format %s\n",
|
||||
mp_imgfmt_to_name(sw_fmt));
|
||||
}
|
||||
}
|
||||
|
||||
int src_fmt = img->imgfmt;
|
||||
|
@ -309,7 +309,7 @@ static bool probe_formats(struct mp_hwupload *u, int hw_imgfmt)
|
||||
}
|
||||
|
||||
if (!ctx) {
|
||||
MP_ERR(u->f, "no support for this hw format\n");
|
||||
MP_INFO(u->f, "no support for this hw format\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -410,12 +410,12 @@ struct mp_hwupload *mp_hwupload_create(struct mp_filter *parent, int hw_imgfmt)
|
||||
mp_filter_add_pin(f, MP_PIN_OUT, "out");
|
||||
|
||||
if (!probe_formats(u, hw_imgfmt)) {
|
||||
MP_ERR(f, "hardware format not supported\n");
|
||||
goto error;
|
||||
MP_INFO(f, "hardware format not supported\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return u;
|
||||
error:
|
||||
fail:
|
||||
talloc_free(f);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -996,6 +996,9 @@ features += {'wayland': wayland_deps and wayland['header'] and wayland['scanner'
|
||||
|
||||
if features['wayland']
|
||||
subdir(join_paths('generated', 'wayland'))
|
||||
sources += files('video/out/wldmabuf/context_wldmabuf.c')
|
||||
sources += files('video/out/wldmabuf/ra_wldmabuf.c')
|
||||
sources += files('video/out/wlbuf_pool.c')
|
||||
endif
|
||||
|
||||
features += {'memfd_create': false}
|
||||
@ -1404,6 +1407,12 @@ if features['dmabuf-interop-pl']
|
||||
sources += files('video/out/hwdec/dmabuf_interop_pl.c')
|
||||
endif
|
||||
|
||||
features += {'dmabuf-wayland' : features['wayland'] and features['memfd_create'] and (features['vaapi-wayland'] or features['drm'])}
|
||||
if features['dmabuf-wayland']
|
||||
sources += files('video/out/vo_dmabuf_wayland.c')
|
||||
sources += files('video/out/hwdec/dmabuf_interop_wl.c')
|
||||
endif
|
||||
|
||||
vdpau_opt = get_option('vdpau').require(
|
||||
features['x11'],
|
||||
error_message: 'x11 was not found!',
|
||||
|
@ -55,6 +55,9 @@ extern const struct ra_ctx_fns ra_ctx_vulkan_display;
|
||||
/* Direct3D 11 */
|
||||
extern const struct ra_ctx_fns ra_ctx_d3d11;
|
||||
|
||||
/* No API */
|
||||
extern const struct ra_ctx_fns ra_ctx_wldmabuf;
|
||||
|
||||
static const struct ra_ctx_fns *contexts[] = {
|
||||
#if HAVE_D3D11
|
||||
&ra_ctx_d3d11,
|
||||
@ -108,7 +111,11 @@ static const struct ra_ctx_fns *contexts[] = {
|
||||
&ra_ctx_vulkan_xlib,
|
||||
#endif
|
||||
&ra_ctx_vulkan_display,
|
||||
#endif
|
||||
|
||||
/* No API contexts: */
|
||||
#if HAVE_WAYLAND
|
||||
&ra_ctx_wldmabuf,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -53,3 +53,5 @@ bool dmabuf_interop_gl_init(const struct ra_hwdec *hw,
|
||||
struct dmabuf_interop *dmabuf_interop);
|
||||
bool dmabuf_interop_pl_init(const struct ra_hwdec *hw,
|
||||
struct dmabuf_interop *dmabuf_interop);
|
||||
bool dmabuf_interop_wl_init(const struct ra_hwdec *hw,
|
||||
struct dmabuf_interop *dmabuf_interop);
|
||||
|
57
video/out/hwdec/dmabuf_interop_wl.c
Normal file
57
video/out/hwdec/dmabuf_interop_wl.c
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This file is part of mpv.
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "video/out/wldmabuf/ra_wldmabuf.h"
|
||||
#include "config.h"
|
||||
#include "dmabuf_interop.h"
|
||||
|
||||
static bool mapper_init(struct ra_hwdec_mapper *mapper,
|
||||
const struct ra_imgfmt_desc *desc)
|
||||
{
|
||||
struct dmabuf_interop_priv *p = mapper->priv;
|
||||
|
||||
p->num_planes = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void mapper_uninit(const struct ra_hwdec_mapper *mapper)
|
||||
{
|
||||
}
|
||||
|
||||
static bool map(struct ra_hwdec_mapper *mapper,
|
||||
struct dmabuf_interop *dmabuf_interop,
|
||||
bool probing)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void unmap(struct ra_hwdec_mapper *mapper)
|
||||
{
|
||||
}
|
||||
|
||||
bool dmabuf_interop_wl_init(const struct ra_hwdec *hw,
|
||||
struct dmabuf_interop *dmabuf_interop)
|
||||
{
|
||||
if (!ra_is_wldmabuf(hw->ra))
|
||||
return false;
|
||||
|
||||
dmabuf_interop->interop_init = mapper_init;
|
||||
dmabuf_interop->interop_uninit = mapper_uninit;
|
||||
dmabuf_interop->interop_map = map;
|
||||
dmabuf_interop->interop_unmap = unmap;
|
||||
|
||||
return true;
|
||||
}
|
@ -55,6 +55,9 @@ const static dmabuf_interop_init interop_inits[] = {
|
||||
#endif
|
||||
#if HAVE_DMABUF_INTEROP_PL
|
||||
dmabuf_interop_pl_init,
|
||||
#endif
|
||||
#if HAVE_DMABUF_WAYLAND
|
||||
dmabuf_interop_wl_init,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
@ -167,7 +170,8 @@ static int mapper_init(struct ra_hwdec_mapper *mapper)
|
||||
|
||||
struct ra_imgfmt_desc desc = {0};
|
||||
|
||||
if (!ra_get_imgfmt_desc(mapper->ra, mapper->dst_params.imgfmt, &desc))
|
||||
if (mapper->ra->num_formats &&
|
||||
!ra_get_imgfmt_desc(mapper->ra, mapper->dst_params.imgfmt, &desc))
|
||||
return -1;
|
||||
|
||||
p->num_planes = desc.num_planes;
|
||||
|
@ -52,7 +52,11 @@ static VADisplay *create_x11_va_display(struct ra *ra)
|
||||
static VADisplay *create_wayland_va_display(struct ra *ra)
|
||||
{
|
||||
struct wl_display *wl = ra_get_native_resource(ra, "wl");
|
||||
return wl ? vaGetDisplayWl(wl) : NULL;
|
||||
VADisplay rc = wl ? vaGetDisplayWl(wl) : NULL;
|
||||
if (rc)
|
||||
ra_add_native_resource(ra, "VADisplay", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -123,6 +127,9 @@ const static dmabuf_interop_init interop_inits[] = {
|
||||
#endif
|
||||
#if HAVE_DMABUF_INTEROP_PL
|
||||
dmabuf_interop_pl_init,
|
||||
#endif
|
||||
#if HAVE_DMABUF_WAYLAND
|
||||
dmabuf_interop_wl_init,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
@ -217,8 +224,9 @@ static int mapper_init(struct ra_hwdec_mapper *mapper)
|
||||
|
||||
struct ra_imgfmt_desc desc = {0};
|
||||
|
||||
if (!ra_get_imgfmt_desc(mapper->ra, mapper->dst_params.imgfmt, &desc))
|
||||
return -1;
|
||||
if (mapper->ra->num_formats &&
|
||||
!ra_get_imgfmt_desc(mapper->ra, mapper->dst_params.imgfmt, &desc))
|
||||
return -1;
|
||||
|
||||
p->num_planes = desc.num_planes;
|
||||
mp_image_set_params(&p->layout, &mapper->dst_params);
|
||||
|
@ -63,6 +63,7 @@ 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;
|
||||
extern const struct vo_driver video_out_tct;
|
||||
@ -93,7 +94,10 @@ const struct vo_driver *const video_out_drivers[] =
|
||||
#if HAVE_SDL2_VIDEO
|
||||
&video_out_sdl,
|
||||
#endif
|
||||
#if HAVE_VAAPI_WAYLAND && HAVE_MEMFD_CREATE
|
||||
#if HAVE_DMABUF_WAYLAND
|
||||
&video_out_dmabuf_wayland,
|
||||
#endif
|
||||
#if HAVE_VAAPI_WAYLAND
|
||||
&video_out_vaapi_wayland,
|
||||
#endif
|
||||
#if HAVE_VAAPI_X11 && HAVE_GPL
|
||||
|
361
video/out/vo_dmabuf_wayland.c
Normal file
361
video/out/vo_dmabuf_wayland.c
Normal file
@ -0,0 +1,361 @@
|
||||
/*
|
||||
* Based on vo_gl.c by Reimar Doeffinger.
|
||||
*
|
||||
* This file is part of mpv.
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <unistd.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_VAAPI
|
||||
#include <va/va_drmcommon.h>
|
||||
#include <libavutil/hwcontext_drm.h>
|
||||
#endif
|
||||
|
||||
#include "mpv_talloc.h"
|
||||
#include "common/global.h"
|
||||
#include "vo.h"
|
||||
#include "video/mp_image.h"
|
||||
|
||||
#include "gpu/hwdec.h"
|
||||
#include "gpu/video.h"
|
||||
|
||||
#include "video/vaapi.h"
|
||||
#include "present_sync.h"
|
||||
#include "wayland_common.h"
|
||||
#include "generated/wayland/linux-dmabuf-unstable-v1.h"
|
||||
#include "generated/wayland/viewporter.h"
|
||||
#include "wlbuf_pool.h"
|
||||
|
||||
struct priv {
|
||||
struct mp_log *log;
|
||||
struct ra_ctx *ctx;
|
||||
struct mpv_global *global;
|
||||
struct ra_hwdec_ctx hwdec_ctx;
|
||||
int events;
|
||||
|
||||
struct wl_shm_pool *solid_buffer_pool;
|
||||
struct wl_buffer *solid_buffer;
|
||||
struct wlbuf_pool *wlbuf_pool;
|
||||
bool want_reset;
|
||||
uint64_t reset_count;
|
||||
|
||||
#ifdef HAVE_VAAPI
|
||||
VADisplay display;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef HAVE_VAAPI
|
||||
static uintptr_t vaapi_key_provider(struct mp_image *src)
|
||||
{
|
||||
return va_surface_id(src);
|
||||
}
|
||||
|
||||
/* va-api dmabuf importer */
|
||||
static bool vaapi_dmabuf_importer(struct mp_image *src, struct wlbuf_pool_entry* entry,
|
||||
struct zwp_linux_buffer_params_v1 *params)
|
||||
{
|
||||
struct priv *p = entry->vo->priv;
|
||||
VADRMPRIMESurfaceDescriptor desc;
|
||||
bool dmabuf_imported = false;
|
||||
/* composed has single layer */
|
||||
int layer_no = 0;
|
||||
VAStatus status = vaExportSurfaceHandle(p->display, entry->key, VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
|
||||
VA_EXPORT_SURFACE_COMPOSED_LAYERS | VA_EXPORT_SURFACE_READ_ONLY, &desc);
|
||||
|
||||
if (status == VA_STATUS_ERROR_INVALID_SURFACE) {
|
||||
MP_VERBOSE(entry->vo, "VA export to composed layers not supported.\n");
|
||||
} else if (!vo_wayland_supported_format(entry->vo, desc.layers[layer_no].drm_format)) {
|
||||
MP_VERBOSE(entry->vo, "%s is not supported.\n", mp_tag_str(desc.layers[layer_no].drm_format));
|
||||
} else if (CHECK_VA_STATUS(entry->vo, "vaExportSurfaceHandle()")) {
|
||||
entry->drm_format = desc.layers[layer_no].drm_format;
|
||||
for (int plane_no = 0; plane_no < desc.layers[layer_no].num_planes; ++plane_no) {
|
||||
int object = desc.layers[layer_no].object_index[plane_no];
|
||||
uint64_t modifier = desc.objects[object].drm_format_modifier;
|
||||
zwp_linux_buffer_params_v1_add(params, desc.objects[object].fd, plane_no, desc.layers[layer_no].offset[plane_no],
|
||||
desc.layers[layer_no].pitch[plane_no], modifier >> 32, modifier & 0xffffffff);
|
||||
}
|
||||
dmabuf_imported = true;
|
||||
}
|
||||
|
||||
/* clean up descriptor */
|
||||
if (status != VA_STATUS_ERROR_INVALID_SURFACE) {
|
||||
for (int i = 0; i < desc.num_objects; i++) {
|
||||
close(desc.objects[i].fd);
|
||||
desc.objects[i].fd = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return dmabuf_imported;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_DRM
|
||||
|
||||
static uintptr_t drmprime_key_provider(struct mp_image *src)
|
||||
{
|
||||
struct AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)src->planes[0];
|
||||
|
||||
AVDRMObjectDescriptor object = desc->objects[0];
|
||||
return (uintptr_t)object.fd;
|
||||
}
|
||||
|
||||
static bool drmprime_dmabuf_importer(struct mp_image *src, struct wlbuf_pool_entry *entry,
|
||||
struct zwp_linux_buffer_params_v1 *params)
|
||||
{
|
||||
int layer_no, plane_no;
|
||||
const AVDRMFrameDescriptor *avdesc = (AVDRMFrameDescriptor *)src->planes[0];
|
||||
|
||||
for (layer_no = 0; layer_no < avdesc->nb_layers; layer_no++) {
|
||||
AVDRMLayerDescriptor layer = avdesc->layers[layer_no];
|
||||
|
||||
entry->drm_format = layer.format;
|
||||
for (plane_no = 0; plane_no < layer.nb_planes; ++plane_no) {
|
||||
AVDRMPlaneDescriptor plane = layer.planes[plane_no];
|
||||
int object_index = plane.object_index;
|
||||
AVDRMObjectDescriptor object = avdesc->objects[object_index];
|
||||
uint64_t modifier = object.format_modifier;
|
||||
|
||||
zwp_linux_buffer_params_v1_add(params, object.fd, plane_no, plane.offset,
|
||||
plane.pitch, modifier >> 32, modifier & 0xffffffff);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void resize(struct vo *vo)
|
||||
{
|
||||
struct vo_wayland_state *wl = vo->wl;
|
||||
struct mp_rect src;
|
||||
struct mp_rect dst;
|
||||
struct mp_osd_res osd;
|
||||
const int width = wl->scaling * mp_rect_w(wl->geometry);
|
||||
const int height = wl->scaling * mp_rect_h(wl->geometry);
|
||||
|
||||
vo_wayland_set_opaque_region(wl, 0);
|
||||
vo->dwidth = width;
|
||||
vo->dheight = height;
|
||||
vo_get_src_dst_rects(vo, &src, &dst, &osd);
|
||||
|
||||
if (wl->viewport)
|
||||
wp_viewport_set_destination(wl->viewport, 2 * dst.x0 + mp_rect_w(dst), 2 * dst.y0 + mp_rect_h(dst));
|
||||
|
||||
if (wl->video_viewport)
|
||||
wp_viewport_set_destination(wl->video_viewport, mp_rect_w(dst), mp_rect_h(dst));
|
||||
wl_subsurface_set_position(wl->video_subsurface, dst.x0, dst.y0);
|
||||
vo->want_redraw = true;
|
||||
}
|
||||
|
||||
static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
{
|
||||
struct priv *p = vo->priv;
|
||||
struct vo_wayland_state *wl = vo->wl;
|
||||
struct wlbuf_pool_entry *entry;
|
||||
|
||||
if (!vo_wayland_check_visible(vo))
|
||||
return;
|
||||
|
||||
// ensure the pool is reset after hwdec seek,
|
||||
// to avoid stutter artifact
|
||||
p->reset_count++;
|
||||
if (p->want_reset && p->reset_count <= 2){
|
||||
wlbuf_pool_clean(p->wlbuf_pool);
|
||||
if (p->reset_count == 2)
|
||||
p->want_reset = false;
|
||||
}
|
||||
|
||||
/* lazy initialization of buffer pool */
|
||||
if (!p->wlbuf_pool) {
|
||||
#if HAVE_VAAPI
|
||||
p->display = (VADisplay)ra_get_native_resource(p->ctx->ra, "VADisplay");
|
||||
if (p->display)
|
||||
p->wlbuf_pool = wlbuf_pool_alloc(vo, wl, vaapi_key_provider, vaapi_dmabuf_importer);
|
||||
#endif
|
||||
#if HAVE_DRM
|
||||
if (!p->wlbuf_pool)
|
||||
p->wlbuf_pool = wlbuf_pool_alloc(vo, wl, drmprime_key_provider, drmprime_dmabuf_importer);
|
||||
#endif
|
||||
}
|
||||
entry = wlbuf_pool_get_entry(p->wlbuf_pool, frame->current);
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
MP_VERBOSE(entry->vo, "Schedule buffer pool entry : %lu\n",entry->key );
|
||||
wl_surface_attach(wl->video_surface, entry->buffer, 0, 0);
|
||||
wl_surface_damage_buffer(wl->video_surface, 0, 0, INT32_MAX, INT32_MAX);
|
||||
}
|
||||
|
||||
static void flip_page(struct vo *vo)
|
||||
{
|
||||
struct vo_wayland_state *wl = vo->wl;
|
||||
|
||||
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 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);
|
||||
}
|
||||
|
||||
static bool is_supported_fmt(int fmt)
|
||||
{
|
||||
return (fmt == IMGFMT_DRMPRIME || fmt == IMGFMT_VAAPI);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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 void call_request_hwdec_api(void *ctx, struct hwdec_imgfmt_request *params)
|
||||
{
|
||||
// Roundabout way to run hwdec loading on the VO thread.
|
||||
// Redirects to request_hwdec_api().
|
||||
vo_control(ctx, VOCTRL_LOAD_HWDEC_API, params);
|
||||
}
|
||||
|
||||
static int control(struct vo *vo, uint32_t request, void *data)
|
||||
{
|
||||
struct priv *p = vo->priv;
|
||||
int events = 0;
|
||||
int ret;
|
||||
|
||||
switch (request) {
|
||||
case VOCTRL_LOAD_HWDEC_API:
|
||||
assert(p->hwdec_ctx.ra);
|
||||
struct hwdec_imgfmt_request* req = (struct hwdec_imgfmt_request*)data;
|
||||
if (!is_supported_fmt(req->imgfmt))
|
||||
return 0;
|
||||
ra_hwdec_ctx_load_fmt(&p->hwdec_ctx, vo->hwdec_devs, req);
|
||||
return (p->hwdec_ctx.num_hwdecs > 0);
|
||||
break;
|
||||
case VOCTRL_RESET:
|
||||
p->want_reset = true;
|
||||
p->reset_count = 0;
|
||||
return VO_TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = vo_wayland_control(vo, &events, request, data);
|
||||
if (events & VO_EVENT_RESIZE)
|
||||
resize(vo);
|
||||
if (events & VO_EVENT_EXPOSE)
|
||||
vo->want_redraw = true;
|
||||
vo_event(vo, events);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void uninit(struct vo *vo)
|
||||
{
|
||||
struct priv *p = vo->priv;
|
||||
|
||||
if (p->solid_buffer_pool)
|
||||
wl_shm_pool_destroy(p->solid_buffer_pool);
|
||||
if (p->solid_buffer)
|
||||
wl_buffer_destroy(p->solid_buffer);
|
||||
ra_hwdec_ctx_uninit(&p->hwdec_ctx);
|
||||
if (vo->hwdec_devs) {
|
||||
hwdec_devices_set_loader(vo->hwdec_devs, NULL, NULL);
|
||||
hwdec_devices_destroy(vo->hwdec_devs);
|
||||
}
|
||||
wlbuf_pool_free(p->wlbuf_pool);
|
||||
vo_wayland_uninit(vo);
|
||||
ra_ctx_destroy(&p->ctx);
|
||||
}
|
||||
|
||||
static int preinit(struct vo *vo)
|
||||
{
|
||||
struct priv *p = vo->priv;
|
||||
struct ra_ctx_opts ctx_opts;
|
||||
|
||||
p->log = vo->log;
|
||||
p->global = vo->global;
|
||||
ctx_opts.context_name = "wldmabuf";
|
||||
ctx_opts.context_type = "none";
|
||||
ctx_opts.probing = false;
|
||||
p->ctx = ra_ctx_create(vo, ctx_opts);
|
||||
if (!p->ctx)
|
||||
goto err_out;
|
||||
assert(p->ctx->ra);
|
||||
vo->hwdec_devs = hwdec_devices_create();
|
||||
hwdec_devices_set_loader(vo->hwdec_devs, call_request_hwdec_api, vo);
|
||||
assert(!p->hwdec_ctx.ra);
|
||||
p->hwdec_ctx = (struct ra_hwdec_ctx) {
|
||||
.log = p->log,
|
||||
.global = p->global,
|
||||
.ra = p->ctx->ra,
|
||||
};
|
||||
ra_hwdec_ctx_init(&p->hwdec_ctx, vo->hwdec_devs, NULL, false);
|
||||
|
||||
return 0;
|
||||
err_out:
|
||||
uninit(vo);
|
||||
|
||||
return VO_ERROR;
|
||||
}
|
||||
|
||||
const struct vo_driver video_out_dmabuf_wayland = {
|
||||
.description = "Wayland dmabuf video output",
|
||||
.name = "dmabuf-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),
|
||||
};
|
190
video/out/wlbuf_pool.c
Normal file
190
video/out/wlbuf_pool.c
Normal file
@ -0,0 +1,190 @@
|
||||
/*
|
||||
* This file is part of mpv.
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <unistd.h>
|
||||
|
||||
#include "mpv_talloc.h"
|
||||
#include "common/global.h"
|
||||
#include "vo.h"
|
||||
#include "video/mp_image.h"
|
||||
|
||||
#include "wayland_common.h"
|
||||
#include "generated/wayland/linux-dmabuf-unstable-v1.h"
|
||||
#include "pthread.h"
|
||||
#include "wlbuf_pool.h"
|
||||
|
||||
#define WLBUF_POOL_NUM_ALLOCATED_INIT 30
|
||||
|
||||
static void wlbuf_pool_entry_free(struct wlbuf_pool_entry *entry);
|
||||
|
||||
struct wlbuf_pool *wlbuf_pool_alloc(struct vo *vo, struct vo_wayland_state *wl, wlbuf_pool_key_provider key_provider,
|
||||
wlbuf_pool_dmabuf_importer dmabuf_importer)
|
||||
{
|
||||
struct wlbuf_pool *pool = talloc(NULL, struct wlbuf_pool);
|
||||
memset(pool, 0, sizeof(struct wlbuf_pool));
|
||||
pool->num_allocated = WLBUF_POOL_NUM_ALLOCATED_INIT;
|
||||
pool->entries = talloc_array(pool, struct wlbuf_pool_entry *, pool->num_allocated);
|
||||
memset(pool->entries, 0, pool->num_allocated * sizeof(struct wlbuf_pool_entry *));
|
||||
pool->vo = vo;
|
||||
pool->key_provider = key_provider;
|
||||
pool->dmabuf_importer = dmabuf_importer;
|
||||
pthread_mutex_init(&pool->lock, NULL);
|
||||
pool->wl = wl;
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
void wlbuf_pool_clean(struct wlbuf_pool *pool)
|
||||
{
|
||||
int i;
|
||||
if (!pool)
|
||||
return;
|
||||
pthread_mutex_lock(&pool->lock);
|
||||
MP_VERBOSE(pool->vo, "Begin clean pool\n");
|
||||
for (i = 0; i < pool->num_allocated; ++i) {
|
||||
struct wlbuf_pool_entry *entry = pool->entries[i];
|
||||
if (!entry)
|
||||
continue;
|
||||
// force frame unref
|
||||
if (pool->final_clean && entry->frame){
|
||||
mp_image_unrefp(&entry->frame);
|
||||
entry->frame = NULL;
|
||||
}
|
||||
wlbuf_pool_entry_free(entry);
|
||||
pool->entries[i] = NULL;
|
||||
}
|
||||
pool->num_entries = 0;
|
||||
MP_VERBOSE(pool->vo, "End clean pool\n");
|
||||
pthread_mutex_unlock(&pool->lock);
|
||||
}
|
||||
|
||||
void wlbuf_pool_free(struct wlbuf_pool *pool)
|
||||
{
|
||||
if (!pool)
|
||||
return;
|
||||
pool->final_clean = true;
|
||||
wlbuf_pool_clean(pool);
|
||||
pthread_mutex_destroy(&pool->lock);
|
||||
talloc_free(pool);
|
||||
}
|
||||
|
||||
static void wlbuf_pool_entry_free(struct wlbuf_pool_entry *entry)
|
||||
{
|
||||
if (!entry)
|
||||
return;
|
||||
if (entry->frame) {
|
||||
MP_VERBOSE(entry->vo, "Pending free buffer pool entry : %lu\n",entry->key );
|
||||
entry->pending_delete = true;
|
||||
}
|
||||
else {
|
||||
MP_VERBOSE(entry->vo, "Free buffer pool entry : %lu\n",entry->key );
|
||||
if (entry->buffer)
|
||||
wl_buffer_destroy(entry->buffer);
|
||||
entry->buffer = NULL;
|
||||
talloc_free(entry);
|
||||
}
|
||||
}
|
||||
|
||||
static void wlbuf_pool_entry_release(void *data, struct wl_buffer *wl_buffer)
|
||||
{
|
||||
struct wlbuf_pool_entry *entry = (struct wlbuf_pool_entry*)data;
|
||||
struct mp_image *frame;
|
||||
pthread_mutex_t *lock = entry->pool_lock;
|
||||
|
||||
MP_VERBOSE(entry->vo, "Release buffer pool entry : %lu\n",entry->key );
|
||||
pthread_mutex_lock(lock);
|
||||
frame = entry->frame;
|
||||
entry->frame = NULL;
|
||||
if (entry->pending_delete)
|
||||
wlbuf_pool_entry_free(entry);
|
||||
if (frame)
|
||||
mp_image_unrefp(&frame);
|
||||
pthread_mutex_unlock(lock);
|
||||
}
|
||||
|
||||
static const struct wl_buffer_listener wlbuf_pool_listener = {
|
||||
wlbuf_pool_entry_release,
|
||||
};
|
||||
|
||||
struct wlbuf_pool_entry *wlbuf_pool_get_entry(struct wlbuf_pool *pool, struct mp_image *src)
|
||||
{
|
||||
uintptr_t key;
|
||||
struct wlbuf_pool_entry *entry;
|
||||
struct vo_wayland_state *wl = pool->wl;
|
||||
bool import_successful;
|
||||
struct zwp_linux_buffer_params_v1 *params;
|
||||
|
||||
if (!pool || !src)
|
||||
return NULL;
|
||||
|
||||
/* 1. try to find existing entry in pool */
|
||||
src = mp_image_new_ref(src);
|
||||
key = pool->key_provider(src);
|
||||
pthread_mutex_lock(&pool->lock);
|
||||
for (int i = 0; i < pool->num_entries; ++i) {
|
||||
struct wlbuf_pool_entry *item = pool->entries[i];
|
||||
if (item->key == key) {
|
||||
pthread_mutex_unlock(&pool->lock);
|
||||
if (item->frame){
|
||||
mp_image_unrefp(&src);
|
||||
return NULL;
|
||||
} else {
|
||||
item->frame = src;
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&pool->lock);
|
||||
/* 2. otherwise allocate new entry and buffer */
|
||||
entry = talloc(pool, struct wlbuf_pool_entry);
|
||||
memset(entry, 0, sizeof(struct wlbuf_pool_entry));
|
||||
entry->vo = pool->vo;
|
||||
entry->key = pool->key_provider(src);
|
||||
entry->pool_lock = &pool->lock;
|
||||
MP_VERBOSE(entry->vo, "Allocate buffer pool entry : %lu\n",entry->key );
|
||||
params = zwp_linux_dmabuf_v1_create_params(wl->dmabuf);
|
||||
import_successful = pool->dmabuf_importer(src,entry,params);
|
||||
if (!import_successful) {
|
||||
MP_VERBOSE(entry->vo, "Failed to import\n");
|
||||
wlbuf_pool_entry_free(entry);
|
||||
} else {
|
||||
entry->buffer = zwp_linux_buffer_params_v1_create_immed(params, src->params.w, src->params.h,
|
||||
entry->drm_format, 0);
|
||||
}
|
||||
zwp_linux_buffer_params_v1_destroy(params);
|
||||
if (!import_successful){
|
||||
mp_image_unrefp(&src);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* 3. add new entry to pool */
|
||||
if (pool->num_entries == pool->num_allocated) {
|
||||
int current_num_allocated = pool->num_allocated;
|
||||
pool->num_allocated *= 2;
|
||||
pthread_mutex_lock(&pool->lock);
|
||||
pool->entries = talloc_realloc(pool, pool->entries, struct wlbuf_pool_entry *, pool->num_allocated);
|
||||
for (int i = current_num_allocated; i < pool->num_allocated; ++i)
|
||||
pool->entries[i] = NULL;
|
||||
pthread_mutex_unlock(&pool->lock);
|
||||
}
|
||||
wl_buffer_add_listener(entry->buffer, &wlbuf_pool_listener, entry);
|
||||
entry->frame = src;
|
||||
pthread_mutex_lock(&pool->lock);
|
||||
pool->entries[pool->num_entries++] = entry;
|
||||
pthread_mutex_unlock(&pool->lock);
|
||||
|
||||
return entry;
|
||||
}
|
65
video/out/wlbuf_pool.h
Normal file
65
video/out/wlbuf_pool.h
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* This file is part of mpv.
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
struct wlbuf_pool_entry;
|
||||
|
||||
typedef uintptr_t (*wlbuf_pool_key_provider)(struct mp_image *src);
|
||||
typedef bool (*wlbuf_pool_dmabuf_importer)(struct mp_image *src, struct wlbuf_pool_entry* entry,
|
||||
struct zwp_linux_buffer_params_v1 *params);
|
||||
|
||||
struct wlbuf_pool {
|
||||
struct vo *vo;
|
||||
struct vo_wayland_state *wl;
|
||||
struct wlbuf_pool_entry **entries;
|
||||
int num_entries;
|
||||
int num_allocated;
|
||||
wlbuf_pool_key_provider key_provider;
|
||||
wlbuf_pool_dmabuf_importer dmabuf_importer;
|
||||
pthread_mutex_t lock;
|
||||
bool final_clean;
|
||||
};
|
||||
|
||||
struct wlbuf_pool_entry {
|
||||
uintptr_t key;
|
||||
struct vo *vo;
|
||||
struct wl_buffer *buffer;
|
||||
uint32_t drm_format;
|
||||
struct mp_image *frame;
|
||||
bool pending_delete;
|
||||
pthread_mutex_t *pool_lock;
|
||||
};
|
||||
|
||||
/**
|
||||
* Allocate pool
|
||||
*/
|
||||
struct wlbuf_pool *wlbuf_pool_alloc(struct vo *vo, struct vo_wayland_state *wl, wlbuf_pool_key_provider key_provider,
|
||||
wlbuf_pool_dmabuf_importer dmabuf_importer);
|
||||
|
||||
/**
|
||||
* Free pool entries but leave pool itself intact
|
||||
*/
|
||||
void wlbuf_pool_clean(struct wlbuf_pool *pool);
|
||||
|
||||
/**
|
||||
* Free pool
|
||||
*/
|
||||
void wlbuf_pool_free(struct wlbuf_pool *pool);
|
||||
|
||||
/**
|
||||
* Get pool entry - will allocate entry if not present in pool.
|
||||
*/
|
||||
struct wlbuf_pool_entry *wlbuf_pool_get_entry(struct wlbuf_pool *pool, struct mp_image *src);
|
44
video/out/wldmabuf/context_wldmabuf.c
Normal file
44
video/out/wldmabuf/context_wldmabuf.c
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "video/out/wayland_common.h"
|
||||
#include "video/out/opengl/context.h"
|
||||
#include "ra_wldmabuf.h"
|
||||
|
||||
static void uninit(struct ra_ctx *ctx)
|
||||
{
|
||||
ra_free(&ctx->ra);
|
||||
vo_wayland_uninit(ctx->vo);
|
||||
}
|
||||
|
||||
static bool init(struct ra_ctx *ctx)
|
||||
{
|
||||
if (!vo_wayland_init(ctx->vo)) {
|
||||
vo_wayland_uninit(ctx->vo);
|
||||
return false;
|
||||
}
|
||||
ctx->ra = ra_create_wayland(ctx->log, ctx->vo->wl->display);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const struct ra_ctx_fns ra_ctx_wldmabuf = {
|
||||
.type = "none",
|
||||
.name = "wldmabuf",
|
||||
.init = init,
|
||||
.uninit = uninit,
|
||||
};
|
44
video/out/wldmabuf/ra_wldmabuf.c
Normal file
44
video/out/wldmabuf/ra_wldmabuf.c
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* This file is part of mpv.
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "video/out/wayland_common.h"
|
||||
#include "video/out/gpu/ra.h"
|
||||
#include "ra_wldmabuf.h"
|
||||
|
||||
static void destroy(struct ra *ra)
|
||||
{
|
||||
}
|
||||
|
||||
static struct ra_fns ra_fns_wldmabuf = {
|
||||
.destroy = destroy,
|
||||
};
|
||||
|
||||
struct ra *ra_create_wayland(struct mp_log *log, struct wl_display *display)
|
||||
{
|
||||
struct ra *ra = talloc_zero(NULL, struct ra);
|
||||
|
||||
ra->fns = &ra_fns_wldmabuf;
|
||||
ra->log = log;
|
||||
ra_add_native_resource(ra, "wl", display);
|
||||
|
||||
return ra;
|
||||
}
|
||||
|
||||
bool ra_is_wldmabuf(struct ra *ra)
|
||||
{
|
||||
return (ra->fns == &ra_fns_wldmabuf);
|
||||
}
|
22
video/out/wldmabuf/ra_wldmabuf.h
Normal file
22
video/out/wldmabuf/ra_wldmabuf.h
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* This file is part of mpv.
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "video/out/wayland_common.h"
|
||||
|
||||
struct ra *ra_create_wayland(struct mp_log *log, struct wl_display *display);
|
||||
bool ra_is_wldmabuf(struct ra *ra);
|
9
wscript
9
wscript
@ -665,9 +665,14 @@ video_output_features = [
|
||||
'deps': 'vaapi && gl-wayland',
|
||||
'func': check_pkg_config('libva-wayland', '>= 1.1.0'),
|
||||
}, {
|
||||
'name': 'vaapi-wayland-memfd',
|
||||
'desc': 'VAAPI (Wayland dmabuf support)',
|
||||
'deps': 'vaapi-wayland && memfd_create',
|
||||
'name': 'vaapi-wayland-memfd',
|
||||
'desc': 'Wayland vaapi support',
|
||||
'func': check_true,
|
||||
}, {
|
||||
'name': 'dmabuf-wayland',
|
||||
'desc': 'Wayland dmabuf support',
|
||||
'deps': 'wayland && memfd_create && (vaapi-wayland || drm)',
|
||||
'func': check_true,
|
||||
}, {
|
||||
'name': '--vaapi-drm',
|
||||
|
@ -478,6 +478,7 @@ def build(ctx):
|
||||
( "video/out/hwdec/hwdec_vaapi.c", "vaapi-egl || vaapi-libplacebo" ),
|
||||
( "video/out/hwdec/dmabuf_interop_gl.c", "dmabuf-interop-gl" ),
|
||||
( "video/out/hwdec/dmabuf_interop_pl.c", "dmabuf-interop-pl" ),
|
||||
( "video/out/hwdec/dmabuf_interop_wl.c", "dmabuf-wayland" ),
|
||||
( "video/out/libmpv_sw.c" ),
|
||||
( "video/out/placebo/ra_pl.c", "libplacebo" ),
|
||||
( "video/out/placebo/utils.c", "libplacebo" ),
|
||||
@ -507,6 +508,9 @@ def build(ctx):
|
||||
( "video/out/opengl/ra_gl.c", "gl" ),
|
||||
( "video/out/opengl/utils.c", "gl" ),
|
||||
( "video/out/present_sync.c", "wayland || x11" ),
|
||||
( "video/out/wldmabuf/context_wldmabuf.c", "dmabuf-wayland" ),
|
||||
( "video/out/wldmabuf/ra_wldmabuf.c", "dmabuf-wayland" ),
|
||||
( "video/out/wlbuf_pool.c", "dmabuf-wayland" ),
|
||||
( "video/out/vo.c" ),
|
||||
( "video/out/vo_caca.c", "caca" ),
|
||||
( "video/out/vo_direct3d.c", "direct3d" ),
|
||||
@ -524,6 +528,7 @@ def build(ctx):
|
||||
( "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" ),
|
||||
( "video/out/vo_x11.c" , "x11" ),
|
||||
|
Loading…
Reference in New Issue
Block a user