compositor-drm: cache gem handle in dmabuf object
cache gem handle in dmabuf object to avoid re-import
dmabuf fd every time
Upstream-Status: Inappropriate [i.MX-specific]
Signed-off-by: Haihua Hu <jared.hu@nxp.com>
diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
index 8c1fd34..78b5b2a 100644
--- a/libweston/compositor-drm.c
+++ b/libweston/compositor-drm.c
@@ -1089,6 +1089,21 @@
drm_fb_destroy(fb);
}
+static void
+drm_close_gem_handle(struct linux_dmabuf_buffer *dmabuf)
+{
+ struct drm_backend *b = to_drm_backend(dmabuf->compositor);
+ int i;
+
+ if (dmabuf->gem_handles[0] != 0) {
+ for (i = 0; i < dmabuf->attributes.n_planes; i++) {
+ struct drm_gem_close arg = { dmabuf->gem_handles[i], };
+ drmIoctl (b->drm.fd, DRM_IOCTL_GEM_CLOSE, &arg);
+ dmabuf->gem_handles[i] = 0;
+ }
+ }
+}
+
static struct drm_fb *
drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
struct drm_backend *backend, bool is_opaque)
@@ -1168,17 +1183,23 @@
goto err_free;
}
- for (i = 0; i < dmabuf->attributes.n_planes; i++) {
- int ret;
- ret = drmPrimeFDToHandle (fb->fd, dmabuf->attributes.fd[i], &gem_handle[i]);
- if (ret) {
- weston_log ("got gem_handle %x\n", gem_handle[i]);
- goto err_free;
+ if (dmabuf->gem_handles[0] == 0) {
+ for (i = 0; i < dmabuf->attributes.n_planes; i++) {
+ int ret;
+ ret = drmPrimeFDToHandle (fb->fd, dmabuf->attributes.fd[i], &gem_handle[i]);
+ if (ret) {
+ weston_log ("got gem_handle %x\n", gem_handle[i]);
+ goto err_free;
+ }
+ fb->handles[i] = dmabuf->gem_handles[i] = gem_handle[i];
}
- fb->handles[i] = gem_handle[i];
+ linux_dmabuf_buffer_gem_handle_close_cb (dmabuf, drm_close_gem_handle);
+ } else {
+ for (i = 0; i < dmabuf->attributes.n_planes; i++)
+ fb->handles[i] = dmabuf->gem_handles[i];
}
- if (gem_handle[0] != 0)
+ if (fb->handles[0] != 0)
goto add_fb;
static_assert(ARRAY_LENGTH(import_mod.fds) ==
@@ -1232,13 +1253,6 @@
add_fb:
ret = drm_fb_addfb(fb);
- if (gem_handle[0] != 0) {
- for (i = 0; i < dmabuf->attributes.n_planes; i++) {
- struct drm_gem_close arg = { gem_handle[i], };
- drmIoctl (fb->fd, DRM_IOCTL_GEM_CLOSE, &arg);
- }
- }
-
if (ret != 0)
goto err_free;
diff --git a/libweston/linux-dmabuf.c b/libweston/linux-dmabuf.c
index fefd6b1..947465c 100644
--- a/libweston/linux-dmabuf.c
+++ b/libweston/linux-dmabuf.c
@@ -141,6 +141,9 @@
assert(buffer->buffer_resource == resource);
assert(!buffer->params_resource);
+ if (buffer->gem_handle_close_func)
+ buffer->gem_handle_close_func(buffer);
+
if (buffer->user_data_destroy_func)
buffer->user_data_destroy_func(buffer);
@@ -441,6 +444,21 @@
return buffer;
}
+/** Set drmbackend-private data
+ *
+ * set the drm gem handle close callback in the linux_dmabuf_buffer
+ *
+ * \param buffer The linux_dmabuf_buffer object to set for.
+ * \param func Destructor function to be called to close gem handle
+ * when the linux_dmabuf_buffer gets destroyed.
+ */
+WL_EXPORT void
+linux_dmabuf_buffer_gem_handle_close_cb(struct linux_dmabuf_buffer *buffer,
+ dmabuf_gem_handle_close_func func)
+{
+ buffer->gem_handle_close_func = func;
+}
+
/** Set renderer-private data
*
* Set the user data for the linux_dmabuf_buffer. It is invalid to overwrite
diff --git a/libweston/linux-dmabuf.h b/libweston/linux-dmabuf.h
index cbd83dc..5b1574b 100644
--- a/libweston/linux-dmabuf.h
+++ b/libweston/linux-dmabuf.h
@@ -39,6 +39,8 @@
struct linux_dmabuf_buffer;
typedef void (*dmabuf_user_data_destroy_func)(
struct linux_dmabuf_buffer *buffer);
+typedef void (*dmabuf_gem_handle_close_func)(
+ struct linux_dmabuf_buffer *buffer);
struct dmabuf_attributes {
int32_t width;
@@ -76,6 +78,8 @@
* feasible to scan it out directly. This would improve the
* possibilities to successfully scan out, avoiding compositing.
*/
+ uint32_t gem_handles[MAX_DMABUF_PLANES];
+ dmabuf_gem_handle_close_func gem_handle_close_func;
};
int
@@ -85,6 +89,10 @@
linux_dmabuf_buffer_get(struct wl_resource *resource);
void
+linux_dmabuf_buffer_gem_handle_close_cb(struct linux_dmabuf_buffer *buffer,
+ dmabuf_gem_handle_close_func func);
+
+void
linux_dmabuf_buffer_set_user_data(struct linux_dmabuf_buffer *buffer,
void *data,
dmabuf_user_data_destroy_func func);