summaryrefslogtreecommitdiffstats
path: root/video/out/wlbuf_pool.c
diff options
context:
space:
mode:
authorAaron Boxer <boxerab@protonmail.com>2022-09-27 12:12:54 -0400
committerDudemanguy <random342@airmail.cc>2022-10-26 18:41:47 +0000
commit7358b9d37126e824cbc3a226d832e9cc1d7b01ea (patch)
treec477ad6f03145563f31e9877e583a9a50c4c6946 /video/out/wlbuf_pool.c
parent964692ad4cec90888bb437064c53d8844db9f590 (diff)
downloadmpv-7358b9d37126e824cbc3a226d832e9cc1d7b01ea.tar.bz2
mpv-7358b9d37126e824cbc3a226d832e9cc1d7b01ea.tar.xz
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
Diffstat (limited to 'video/out/wlbuf_pool.c')
-rw-r--r--video/out/wlbuf_pool.c190
1 files changed, 190 insertions, 0 deletions
diff --git a/video/out/wlbuf_pool.c b/video/out/wlbuf_pool.c
new file mode 100644
index 0000000000..6f0d43752e
--- /dev/null
+++ b/video/out/wlbuf_pool.c
@@ -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;
+}