6 #include "libds/allocator.h"
8 #define DS_SWAPCHAIN_CAP 4
10 struct ds_swapchain_slot
12 struct ds_buffer *buffer;
14 struct wl_listener buffer_release;
22 struct ds_allocator *allocator;
24 struct ds_swapchain_slot slots[DS_SWAPCHAIN_CAP];
26 struct wl_listener allocator_destroy;
32 static void swapchain_handle_allocator_destroy(struct wl_listener *listener,
34 static bool swapchain_has_buffer(struct ds_swapchain *swapchain,
35 struct ds_buffer *buffer);
36 static struct ds_buffer *swapchain_slot_acquire(struct ds_swapchain *swapchain,
37 struct ds_swapchain_slot *slot, int *age);
38 static void swapchain_slot_reset(struct ds_swapchain_slot *slot);
41 ds_swapchain_create(struct ds_allocator *alloc, int width, int height,
44 struct ds_swapchain *swapchain;
46 swapchain = calloc(1, sizeof *swapchain);
50 swapchain->allocator = alloc;
51 swapchain->width = width;
52 swapchain->height = height;
53 swapchain->format = format;
55 swapchain->allocator_destroy.notify =
56 swapchain_handle_allocator_destroy;
57 ds_allocator_add_destroy_listener(alloc,
58 &swapchain->allocator_destroy);
60 ds_inf("Swapchain(%p) created", swapchain);
66 ds_swapchain_destroy(struct ds_swapchain *swapchain)
70 ds_dbg("Destroy swapchain(%p)", swapchain);
72 for (i = 0; i < DS_SWAPCHAIN_CAP; i++)
73 swapchain_slot_reset(&swapchain->slots[i]);
75 wl_list_remove(&swapchain->allocator_destroy.link);
80 ds_swapchain_acquire(struct ds_swapchain *swapchain, int *age)
82 struct ds_swapchain_slot *slot, *free_slot = NULL;
85 for (i = 0; i < DS_SWAPCHAIN_CAP; i++) {
86 slot = &swapchain->slots[i];
90 if (slot->buffer != NULL)
91 return swapchain_slot_acquire(swapchain, slot, age);
96 if (free_slot == NULL) {
97 ds_err("No free output buffer slot");
101 if (!swapchain->allocator)
104 free_slot->buffer = ds_allocator_create_buffer(swapchain->allocator,
105 swapchain->width, swapchain->height, swapchain->format);
106 if (!free_slot->buffer) {
107 ds_err("Failed to allocate buffer");
111 ds_dbg("Allocating new swapchain buffer(%p)", free_slot->buffer);
113 return swapchain_slot_acquire(swapchain, free_slot, age);
117 ds_swapchain_set_buffer_submitted(struct ds_swapchain *swapchain,
118 struct ds_buffer *buffer)
120 struct ds_swapchain_slot *slot;
125 if (!swapchain_has_buffer(swapchain, buffer))
128 for (i = 0; i < DS_SWAPCHAIN_CAP; i++) {
129 slot = &swapchain->slots[i];
130 if (slot->buffer == buffer)
132 else if (slot->age > 0)
138 swapchain_handle_allocator_destroy(struct wl_listener *listener, void *data)
140 struct ds_swapchain *swapchain;
142 swapchain = wl_container_of(listener, swapchain, allocator_destroy);
143 swapchain->allocator = NULL;
146 static bool swapchain_has_buffer(struct ds_swapchain *swapchain,
147 struct ds_buffer *buffer)
149 struct ds_swapchain_slot *slot;
152 for (i = 0; i < DS_SWAPCHAIN_CAP; i++) {
153 slot = &swapchain->slots[i];
154 if (slot->buffer == buffer)
162 swapchain_slot_handle_buffer_release(struct wl_listener *listener, void *data)
164 struct ds_swapchain_slot *slot;
166 slot = wl_container_of(listener, slot, buffer_release);
168 ds_dbg("Buffer(%p) released.", slot->buffer);
170 wl_list_remove(&slot->buffer_release.link);
171 slot->acquired = false;
174 static struct ds_buffer *
175 swapchain_slot_acquire(struct ds_swapchain *swapchain, struct ds_swapchain_slot *slot,
178 assert(!slot->acquired);
179 assert(slot->buffer);
181 slot->acquired = true;
183 slot->buffer_release.notify = swapchain_slot_handle_buffer_release;
184 ds_buffer_add_release_listener(slot->buffer, &slot->buffer_release);
189 return ds_buffer_lock(slot->buffer);
193 swapchain_slot_reset(struct ds_swapchain_slot *slot)
196 wl_list_remove(&slot->buffer_release.link);
199 ds_buffer_drop(slot->buffer);
201 memset(slot, 0, sizeof *slot);