diff options
-rw-r--r-- | include/types/wlr_buffer.h | 19 | ||||
-rw-r--r-- | types/wlr_buffer.c | 64 |
2 files changed, 83 insertions, 0 deletions
diff --git a/include/types/wlr_buffer.h b/include/types/wlr_buffer.h index 85a8d8b4..b5210bfb 100644 --- a/include/types/wlr_buffer.h +++ b/include/types/wlr_buffer.h @@ -53,6 +53,25 @@ struct wlr_readonly_data_buffer *readonly_data_buffer_create(uint32_t format, */ bool readonly_data_buffer_drop(struct wlr_readonly_data_buffer *buffer); +struct wlr_dmabuf_buffer { + struct wlr_buffer base; + struct wlr_dmabuf_attributes dmabuf; + bool saved; +}; + +/** + * Wraps a DMA-BUF into a wlr_buffer. The DMA-BUF may be accessed until + * dmabuf_buffer_drop() is called. + */ +struct wlr_dmabuf_buffer *dmabuf_buffer_create( + struct wlr_dmabuf_attributes *dmabuf); +/** + * Drops ownership of the buffer (see wlr_buffer_drop() for more details) and + * takes a reference to the DMA-BUF (by dup'ing its file descriptors) if a + * consumer still has the buffer locked. + */ +bool dmabuf_buffer_drop(struct wlr_dmabuf_buffer *buffer); + /** * Buffer capabilities. * diff --git a/types/wlr_buffer.c b/types/wlr_buffer.c index ca5c743c..e0fea23d 100644 --- a/types/wlr_buffer.c +++ b/types/wlr_buffer.c @@ -528,3 +528,67 @@ bool readonly_data_buffer_drop(struct wlr_readonly_data_buffer *buffer) { wlr_buffer_drop(&buffer->base); return ok; } + +static const struct wlr_buffer_impl dmabuf_buffer_impl; + +static struct wlr_dmabuf_buffer *dmabuf_buffer_from_buffer( + struct wlr_buffer *buffer) { + assert(buffer->impl == &dmabuf_buffer_impl); + return (struct wlr_dmabuf_buffer *)buffer; +} + +static void dmabuf_buffer_destroy(struct wlr_buffer *wlr_buffer) { + struct wlr_dmabuf_buffer *buffer = dmabuf_buffer_from_buffer(wlr_buffer); + if (buffer->saved) { + wlr_dmabuf_attributes_finish(&buffer->dmabuf); + } + free(buffer); +} + +static bool dmabuf_buffer_get_dmabuf(struct wlr_buffer *wlr_buffer, + struct wlr_dmabuf_attributes *dmabuf) { + struct wlr_dmabuf_buffer *buffer = dmabuf_buffer_from_buffer(wlr_buffer); + if (buffer->dmabuf.n_planes == 0) { + return false; + } + *dmabuf = buffer->dmabuf; + return true; +} + +static const struct wlr_buffer_impl dmabuf_buffer_impl = { + .destroy = dmabuf_buffer_destroy, + .get_dmabuf = dmabuf_buffer_get_dmabuf, +}; + +struct wlr_dmabuf_buffer *dmabuf_buffer_create( + struct wlr_dmabuf_attributes *dmabuf) { + struct wlr_dmabuf_buffer *buffer = calloc(1, sizeof(*buffer)); + if (buffer == NULL) { + return NULL; + } + wlr_buffer_init(&buffer->base, &dmabuf_buffer_impl, + dmabuf->width, dmabuf->height); + + buffer->dmabuf = *dmabuf; + + return buffer; +} + +bool dmabuf_buffer_drop(struct wlr_dmabuf_buffer *buffer) { + bool ok = true; + + if (buffer->base.n_locks > 0) { + struct wlr_dmabuf_attributes saved_dmabuf = {0}; + if (!wlr_dmabuf_attributes_copy(&saved_dmabuf, &buffer->dmabuf)) { + wlr_log(WLR_ERROR, "Failed to save DMA-BUF"); + ok = false; + memset(&buffer->dmabuf, 0, sizeof(buffer->dmabuf)); + } else { + buffer->dmabuf = saved_dmabuf; + buffer->saved = true; + } + } + + wlr_buffer_drop(&buffer->base); + return ok; +} |