diff options
author | Simon Ser <contact@emersion.fr> | 2020-07-27 18:36:31 +0200 |
---|---|---|
committer | Simon Ser <contact@emersion.fr> | 2020-11-15 22:48:42 +0100 |
commit | c11c6c45685c96e1b525b2f944bc278be20c119e (patch) | |
tree | e36103d3af28ff714ab6cc07fdb232bd9a501f12 | |
parent | ef846a883950e59f95507daa6d3f96f0e84da3af (diff) |
render/swapchain: add support for buffer age
-rw-r--r-- | include/render/swapchain.h | 13 | ||||
-rw-r--r-- | render/swapchain.c | 46 |
2 files changed, 52 insertions, 7 deletions
diff --git a/include/render/swapchain.h b/include/render/swapchain.h index 57a0cd3f..243f0404 100644 --- a/include/render/swapchain.h +++ b/include/render/swapchain.h @@ -10,6 +10,7 @@ struct wlr_swapchain_slot { struct wlr_buffer *buffer; bool acquired; // waiting for release + int age; struct wl_listener release; }; @@ -35,7 +36,15 @@ void wlr_swapchain_destroy(struct wlr_swapchain *swapchain); * The returned buffer is locked. When the caller is done with it, they must * unlock it by calling wlr_buffer_unlock. */ -struct wlr_buffer *wlr_swapchain_acquire( - struct wlr_swapchain *swapchain); +struct wlr_buffer *wlr_swapchain_acquire(struct wlr_swapchain *swapchain, + int *age); +/** + * Mark the buffer as submitted for presentation. This needs to be called by + * swap chain users on frame boundaries. + * + * If the buffer hasn't been created via the swap chain, the call is ignored. + */ +void wlr_swapchain_set_buffer_submitted(struct wlr_swapchain *swapchain, + struct wlr_buffer *buffer); #endif diff --git a/render/swapchain.c b/render/swapchain.c index 4145efd2..fd9f8725 100644 --- a/render/swapchain.c +++ b/render/swapchain.c @@ -63,7 +63,8 @@ static void slot_handle_release(struct wl_listener *listener, void *data) { slot->acquired = false; } -static struct wlr_buffer *slot_acquire(struct wlr_swapchain_slot *slot) { +static struct wlr_buffer *slot_acquire(struct wlr_swapchain *swapchain, + struct wlr_swapchain_slot *slot, int *age) { assert(!slot->acquired); assert(slot->buffer != NULL); @@ -72,11 +73,15 @@ static struct wlr_buffer *slot_acquire(struct wlr_swapchain_slot *slot) { slot->release.notify = slot_handle_release; wl_signal_add(&slot->buffer->events.release, &slot->release); + if (age != NULL) { + *age = slot->age; + } + return wlr_buffer_lock(slot->buffer); } -struct wlr_buffer *wlr_swapchain_acquire( - struct wlr_swapchain *swapchain) { +struct wlr_buffer *wlr_swapchain_acquire(struct wlr_swapchain *swapchain, + int *age) { struct wlr_swapchain_slot *free_slot = NULL; for (size_t i = 0; i < WLR_SWAPCHAIN_CAP; i++) { struct wlr_swapchain_slot *slot = &swapchain->slots[i]; @@ -84,7 +89,7 @@ struct wlr_buffer *wlr_swapchain_acquire( continue; } if (slot->buffer != NULL) { - return slot_acquire(slot); + return slot_acquire(swapchain, slot, age); } free_slot = slot; } @@ -104,5 +109,36 @@ struct wlr_buffer *wlr_swapchain_acquire( wlr_log(WLR_ERROR, "Failed to allocate buffer"); return NULL; } - return slot_acquire(free_slot); + return slot_acquire(swapchain, free_slot, age); +} + +static bool swapchain_has_buffer(struct wlr_swapchain *swapchain, + struct wlr_buffer *buffer) { + for (size_t i = 0; i < WLR_SWAPCHAIN_CAP; i++) { + struct wlr_swapchain_slot *slot = &swapchain->slots[i]; + if (slot->buffer == buffer) { + return true; + } + } + return false; +} + +void wlr_swapchain_set_buffer_submitted(struct wlr_swapchain *swapchain, + struct wlr_buffer *buffer) { + assert(buffer != NULL); + + if (!swapchain_has_buffer(swapchain, buffer)) { + return; + } + + // See the algorithm described in: + // https://www.khronos.org/registry/EGL/extensions/EXT/EGL_EXT_buffer_age.txt + for (size_t i = 0; i < WLR_SWAPCHAIN_CAP; i++) { + struct wlr_swapchain_slot *slot = &swapchain->slots[i]; + if (slot->buffer == buffer) { + slot->age = 1; + } else if (slot->age > 0) { + slot->age++; + } + } } |