render/swapchain: add support for buffer age
This commit is contained in:
parent
ef846a8839
commit
c11c6c4568
|
@ -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
|
||||||
|
|
|
@ -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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue