Merge branch 'export-dmabuf-release' into 'master'

export-dmabuf: Implement release semantics

See merge request wlroots/wlroots!5030
This commit is contained in:
Andri Yngvason 2025-12-23 18:38:48 +00:00
commit 2298bbec92
5 changed files with 33 additions and 5 deletions

View file

@ -46,5 +46,9 @@ struct wlr_buffer *wlr_swapchain_acquire(struct wlr_swapchain *swapchain);
*/
bool wlr_swapchain_has_buffer(struct wlr_swapchain *swapchain,
struct wlr_buffer *buffer);
/**
* Count how many free slots there are left in the swapchain.
*/
int wlr_swapchain_count_free_slots(const struct wlr_swapchain *swapchain);
#endif

View file

@ -32,6 +32,7 @@ struct wlr_export_dmabuf_frame_v1 {
struct wl_list link; // wlr_export_dmabuf_manager_v1.frames
struct wlr_output *output;
struct wlr_buffer *buffer;
bool cursor_locked;

View file

@ -36,7 +36,7 @@
interface version number is reset.
</description>
<interface name="zwlr_export_dmabuf_manager_v1" version="1">
<interface name="zwlr_export_dmabuf_manager_v1" version="2">
<description summary="manager to inform clients and begin capturing">
This object is a manager with which to start capturing from sources.
</description>
@ -59,7 +59,7 @@
</request>
</interface>
<interface name="zwlr_export_dmabuf_frame_v1" version="1">
<interface name="zwlr_export_dmabuf_frame_v1" version="2">
<description summary="a DMA-BUF frame">
This object represents a single DMA-BUF frame.
@ -195,6 +195,10 @@
Unreferences the frame. This request must be called as soon as its no
longer used.
Starting from version 2, this indicates that the client has finished
processing the frame. The client must not access the underlying buffer
after destroying the zwlr_export_dmabuf_frame_v1 object.
It can be called at any time by the client. The client will still have
to close any FDs it has been given.
</description>

View file

@ -120,3 +120,12 @@ bool wlr_swapchain_has_buffer(struct wlr_swapchain *swapchain,
}
return false;
}
int wlr_swapchain_count_free_slots(const struct wlr_swapchain *swapchain)
{
int count = 0;
for (size_t i = 0; i < WLR_SWAPCHAIN_CAP; i++) {
count += !swapchain->slots[i].acquired;
}
return count;
}

View file

@ -3,11 +3,12 @@
#include <unistd.h>
#include <wlr/interfaces/wlr_output.h>
#include <wlr/render/dmabuf.h>
#include <wlr/render/swapchain.h>
#include <wlr/types/wlr_export_dmabuf_v1.h>
#include <wlr/util/log.h>
#include "wlr-export-dmabuf-unstable-v1-protocol.h"
#define EXPORT_DMABUF_MANAGER_VERSION 1
#define EXPORT_DMABUF_MANAGER_VERSION 2
static const struct zwlr_export_dmabuf_frame_v1_interface frame_impl;
@ -32,6 +33,7 @@ static void frame_destroy(struct wlr_export_dmabuf_frame_v1 *frame) {
if (frame == NULL) {
return;
}
wlr_buffer_unlock(frame->buffer);
if (frame->output != NULL) {
wlr_output_lock_attach_render(frame->output, false);
if (frame->cursor_locked) {
@ -64,8 +66,11 @@ static void frame_output_handle_commit(struct wl_listener *listener,
wl_list_remove(&frame->output_commit.link);
wl_list_init(&frame->output_commit.link);
uint32_t version = wl_resource_get_version(frame->resource);
struct wlr_dmabuf_attributes attribs = {0};
if (!wlr_buffer_get_dmabuf(event->state->buffer, &attribs)) {
if (!wlr_buffer_get_dmabuf(event->state->buffer, &attribs) ||
(version >= 2 && wlr_swapchain_count_free_slots(frame->output->swapchain) < 2)) {
zwlr_export_dmabuf_frame_v1_send_cancel(frame->resource,
ZWLR_EXPORT_DMABUF_FRAME_V1_CANCEL_REASON_TEMPORARY);
frame_destroy(frame);
@ -90,7 +95,12 @@ static void frame_output_handle_commit(struct wl_listener *listener,
uint32_t tv_sec_lo = tv_sec & 0xFFFFFFFF;
zwlr_export_dmabuf_frame_v1_send_ready(frame->resource,
tv_sec_hi, tv_sec_lo, event->when.tv_nsec);
frame_destroy(frame);
if (version < 2) {
frame_destroy(frame);
} else {
frame->buffer = wlr_buffer_lock(event->state->buffer);
}
}
static void frame_output_handle_destroy(struct wl_listener *listener, void *data) {