render/swapchain: add support for buffer age

This commit is contained in:
Simon Ser 2020-07-27 18:36:31 +02:00
parent ef846a8839
commit c11c6c4568
2 changed files with 52 additions and 7 deletions

View File

@ -10,6 +10,7 @@
struct wlr_swapchain_slot { struct wlr_swapchain_slot {
struct wlr_buffer *buffer; struct wlr_buffer *buffer;
bool acquired; // waiting for release bool acquired; // waiting for release
int age;
struct wl_listener release; 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 * The returned buffer is locked. When the caller is done with it, they must
* unlock it by calling wlr_buffer_unlock. * unlock it by calling wlr_buffer_unlock.
*/ */
struct wlr_buffer *wlr_swapchain_acquire( struct wlr_buffer *wlr_swapchain_acquire(struct wlr_swapchain *swapchain,
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 #endif

View File

@ -63,7 +63,8 @@ static void slot_handle_release(struct wl_listener *listener, void *data) {
slot->acquired = false; 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->acquired);
assert(slot->buffer != NULL); 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; slot->release.notify = slot_handle_release;
wl_signal_add(&slot->buffer->events.release, &slot->release); wl_signal_add(&slot->buffer->events.release, &slot->release);
if (age != NULL) {
*age = slot->age;
}
return wlr_buffer_lock(slot->buffer); return wlr_buffer_lock(slot->buffer);
} }
struct wlr_buffer *wlr_swapchain_acquire( struct wlr_buffer *wlr_swapchain_acquire(struct wlr_swapchain *swapchain,
struct wlr_swapchain *swapchain) { int *age) {
struct wlr_swapchain_slot *free_slot = NULL; struct wlr_swapchain_slot *free_slot = NULL;
for (size_t i = 0; i < WLR_SWAPCHAIN_CAP; i++) { for (size_t i = 0; i < WLR_SWAPCHAIN_CAP; i++) {
struct wlr_swapchain_slot *slot = &swapchain->slots[i]; struct wlr_swapchain_slot *slot = &swapchain->slots[i];
@ -84,7 +89,7 @@ struct wlr_buffer *wlr_swapchain_acquire(
continue; continue;
} }
if (slot->buffer != NULL) { if (slot->buffer != NULL) {
return slot_acquire(slot); return slot_acquire(swapchain, slot, age);
} }
free_slot = slot; free_slot = slot;
} }
@ -104,5 +109,36 @@ struct wlr_buffer *wlr_swapchain_acquire(
wlr_log(WLR_ERROR, "Failed to allocate buffer"); wlr_log(WLR_ERROR, "Failed to allocate buffer");
return NULL; 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++;
}
}
} }