aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/render/swapchain.h13
-rw-r--r--render/swapchain.c46
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++;
+ }
+ }
}