aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/wlr/types/wlr_linux_dmabuf_v1.h7
-rw-r--r--types/wlr_linux_dmabuf_v1.c53
2 files changed, 53 insertions, 7 deletions
diff --git a/include/wlr/types/wlr_linux_dmabuf_v1.h b/include/wlr/types/wlr_linux_dmabuf_v1.h
index 17e897c3..a2db7fea 100644
--- a/include/wlr/types/wlr_linux_dmabuf_v1.h
+++ b/include/wlr/types/wlr_linux_dmabuf_v1.h
@@ -11,11 +11,16 @@
#include <stdint.h>
#include <wayland-server-core.h>
+#include <wlr/types/wlr_buffer.h>
#include <wlr/render/dmabuf.h>
struct wlr_dmabuf_v1_buffer {
- struct wl_resource *resource;
+ struct wlr_buffer base;
+
+ struct wl_resource *resource; // can be NULL if the client destroyed it
struct wlr_dmabuf_attributes attributes;
+
+ struct wl_listener release;
};
/**
diff --git a/types/wlr_linux_dmabuf_v1.c b/types/wlr_linux_dmabuf_v1.c
index c7d4510e..7b08b350 100644
--- a/types/wlr_linux_dmabuf_v1.c
+++ b/types/wlr_linux_dmabuf_v1.c
@@ -18,13 +18,13 @@ static void buffer_handle_destroy(struct wl_client *client,
wl_resource_destroy(resource);
}
-static const struct wl_buffer_interface buffer_impl = {
+static const struct wl_buffer_interface wl_buffer_impl = {
.destroy = buffer_handle_destroy,
};
bool wlr_dmabuf_v1_resource_is_buffer(struct wl_resource *resource) {
if (!wl_resource_instance_of(resource, &wl_buffer_interface,
- &buffer_impl)) {
+ &wl_buffer_impl)) {
return false;
}
return wl_resource_get_user_data(resource) != NULL;
@@ -33,15 +33,50 @@ bool wlr_dmabuf_v1_resource_is_buffer(struct wl_resource *resource) {
struct wlr_dmabuf_v1_buffer *wlr_dmabuf_v1_buffer_from_buffer_resource(
struct wl_resource *resource) {
assert(wl_resource_instance_of(resource, &wl_buffer_interface,
- &buffer_impl));
+ &wl_buffer_impl));
return wl_resource_get_user_data(resource);
}
-static void linux_dmabuf_buffer_destroy(struct wlr_dmabuf_v1_buffer *buffer) {
+static const struct wlr_buffer_impl buffer_impl;
+
+static struct wlr_dmabuf_v1_buffer *dmabuf_v1_buffer_from_buffer(
+ struct wlr_buffer *buffer) {
+ assert(buffer->impl == &buffer_impl);
+ return (struct wlr_dmabuf_v1_buffer *)buffer;
+}
+
+static void buffer_destroy(struct wlr_buffer *wlr_buffer) {
+ struct wlr_dmabuf_v1_buffer *buffer =
+ dmabuf_v1_buffer_from_buffer(wlr_buffer);
+ if (buffer->resource != NULL) {
+ wl_resource_set_user_data(buffer->resource, NULL);
+ }
wlr_dmabuf_attributes_finish(&buffer->attributes);
+ wl_list_remove(&buffer->release.link);
free(buffer);
}
+static bool buffer_get_dmabuf(struct wlr_buffer *wlr_buffer,
+ struct wlr_dmabuf_attributes *attribs) {
+ struct wlr_dmabuf_v1_buffer *buffer =
+ dmabuf_v1_buffer_from_buffer(wlr_buffer);
+ memcpy(attribs, &buffer->attributes, sizeof(buffer->attributes));
+ return true;
+}
+
+static const struct wlr_buffer_impl buffer_impl = {
+ .destroy = buffer_destroy,
+ .get_dmabuf = buffer_get_dmabuf,
+};
+
+static void buffer_handle_release(struct wl_listener *listener, void *data) {
+ struct wlr_dmabuf_v1_buffer *buffer =
+ wl_container_of(listener, buffer, release);
+ if (buffer->resource != NULL) {
+ wl_buffer_send_release(buffer->resource);
+ }
+}
+
static const struct zwp_linux_buffer_params_v1_interface buffer_params_impl;
static struct wlr_linux_buffer_params_v1 *params_from_resource(
@@ -110,7 +145,8 @@ static void params_add(struct wl_client *client,
static void buffer_handle_resource_destroy(struct wl_resource *buffer_resource) {
struct wlr_dmabuf_v1_buffer *buffer =
wlr_dmabuf_v1_buffer_from_buffer_resource(buffer_resource);
- linux_dmabuf_buffer_destroy(buffer);
+ buffer->resource = NULL;
+ wlr_buffer_drop(&buffer->base);
}
static bool check_import_dmabuf(struct wlr_linux_dmabuf_v1 *linux_dmabuf,
@@ -247,19 +283,24 @@ static void params_create_common(struct wl_resource *params_resource,
wl_resource_post_no_memory(params_resource);
goto err_failed;
}
+ wlr_buffer_init(&buffer->base, &buffer_impl, attribs.width, attribs.height);
struct wl_client *client = wl_resource_get_client(params_resource);
buffer->resource = wl_resource_create(client, &wl_buffer_interface,
1, buffer_id);
if (!buffer->resource) {
wl_resource_post_no_memory(params_resource);
+ free(buffer);
goto err_failed;
}
wl_resource_set_implementation(buffer->resource,
- &buffer_impl, buffer, buffer_handle_resource_destroy);
+ &wl_buffer_impl, buffer, buffer_handle_resource_destroy);
buffer->attributes = attribs;
+ buffer->release.notify = buffer_handle_release;
+ wl_signal_add(&buffer->base.events.release, &buffer->release);
+
/* send 'created' event when the request is not for an immediate
* import, that is buffer_id is zero */
if (buffer_id == 0) {