4 #include <sys/eventfd.h>
7 #include "libds/interfaces/buffer.h"
9 #include "tdm_internal.h"
10 #include "tdm_buffer_queue.h"
13 buffer_queue_handle_acquirable(tbm_surface_queue_h surface_queue,
15 static struct ds_tdm_queue_buffer *
16 create_queue_buffer(struct ds_tdm_buffer_queue *queue,
17 tbm_surface_h surface);
18 static void queue_buffer_destroy(struct ds_tdm_queue_buffer *buffer);
19 static void queue_buffer_drop(struct ds_tdm_queue_buffer *buffer);
20 static struct ds_buffer *
21 queue_buffer_acquire(struct ds_tdm_queue_buffer *buffer);
22 static int buffer_queue_handle_acquirable_efd(int fd, uint32_t mask,
26 ds_tdm_buffer_queue_get_native_queue(struct ds_tdm_buffer_queue *queue)
28 return (void *)queue->tbm_surface_queue;
31 WL_EXPORT struct ds_buffer *
32 ds_tdm_buffer_queue_acquire(struct ds_tdm_buffer_queue *queue)
34 struct ds_tdm_queue_buffer *buffer;
35 tbm_surface_h surface;
36 tbm_surface_queue_error_e err;
38 if (!tbm_surface_queue_can_acquire(queue->tbm_surface_queue, 0))
41 err = tbm_surface_queue_acquire(queue->tbm_surface_queue, &surface);
42 if (err != TBM_SURFACE_QUEUE_ERROR_NONE ||
44 ds_err("Could not acquire tbm_surface from queue(%p)", queue);
48 wl_list_for_each(buffer, &queue->buffers, link) {
49 if (buffer->surface == surface)
50 return queue_buffer_acquire(buffer);
53 buffer = create_queue_buffer(queue, surface);
55 ds_err("Could not create tbm_queue_buffer with queue(%p)", queue);
59 wl_list_insert(&queue->buffers, &buffer->link);
61 return queue_buffer_acquire(buffer);
65 ds_tdm_buffer_queue_add_acquirable_listener(struct ds_tdm_buffer_queue *queue,
66 struct wl_listener *listener)
68 wl_signal_add(&queue->events.acquirable, listener);
71 struct ds_tdm_buffer_queue *
72 create_buffer_queue(struct ds_tdm_output *output)
74 struct ds_tdm_buffer_queue *queue;
77 queue = calloc(1, sizeof *queue);
81 wl_list_init(&queue->buffers);
83 wl_signal_init(&queue->events.acquirable);
85 queue->tbm_surface_queue =
86 tdm_hwc_get_client_target_buffer_queue(output->tdm.hwc, &err);
87 if (err != TDM_ERROR_NONE ||
88 queue->tbm_surface_queue == NULL) {
89 ds_err("Could not get target buffer queue: err(%d)", err);
94 tbm_surface_queue_reset(queue->tbm_surface_queue,
95 output->base.pending.mode->width,
96 output->base.pending.mode->height,
97 tbm_surface_queue_get_format(queue->tbm_surface_queue));
99 /* The callback function for tbm_surface_queue_add_acquirable_cb() may be
100 * called on different thread. This eventfd is to emit a signal of
101 * events.acquirable on the thread getting this buffer queue. */
102 queue->acquirable_efd = eventfd(0, EFD_NONBLOCK);
103 if (queue->acquirable_efd < 0) {
105 "Could not create eventfd for acquirable callback");
110 queue->acquirable_source = wl_event_loop_add_fd(
111 wl_display_get_event_loop(output->backend->wl_display),
112 queue->acquirable_efd,
114 buffer_queue_handle_acquirable_efd,
117 tbm_surface_queue_add_acquirable_cb(queue->tbm_surface_queue,
118 buffer_queue_handle_acquirable, (void *)queue);
124 buffer_queue_destroy(struct ds_tdm_buffer_queue *queue)
126 struct ds_tdm_queue_buffer *buffer, *buffer_tmp;
128 wl_list_for_each_safe(buffer, buffer_tmp, &queue->buffers, link)
129 queue_buffer_drop(buffer);
131 wl_event_source_remove(queue->acquirable_source);
132 close(queue->acquirable_efd);
133 tbm_surface_queue_destroy(queue->tbm_surface_queue);
137 struct ds_tdm_queue_buffer *
138 buffer_queue_find_buffer(struct ds_tdm_buffer_queue *queue,
139 struct ds_buffer *ds_buffer)
141 struct ds_tdm_queue_buffer *buffer;
143 wl_list_for_each(buffer, &queue->buffers, link) {
144 if (&buffer->base == ds_buffer)
152 buffer_queue_handle_acquirable(tbm_surface_queue_h surface_queue, void *data)
154 struct ds_tdm_buffer_queue *queue = data;
155 uint64_t acquirable = 1;
158 ret = write(queue->acquirable_efd, &acquirable, sizeof(acquirable));
160 ds_log_errno(DS_ERR, "Could not write eventfd for acquirable buffer");
163 static const struct ds_buffer_interface queue_buffer_iface;
165 static struct ds_tdm_queue_buffer *
166 create_queue_buffer(struct ds_tdm_buffer_queue *queue, tbm_surface_h surface)
168 struct ds_tdm_queue_buffer *buffer;
170 buffer = calloc(1, sizeof *buffer);
174 ds_buffer_init(&buffer->base, &queue_buffer_iface,
175 tbm_surface_get_width(surface),
176 tbm_surface_get_height(surface));
178 buffer->queue = queue;
179 buffer->surface = surface;
185 queue_buffer_destroy(struct ds_tdm_queue_buffer *buffer)
190 static struct ds_tdm_queue_buffer *
191 queue_buffer_from_buffer(struct ds_buffer *ds_buffer)
193 assert(ds_buffer->iface == &queue_buffer_iface);
194 return (struct ds_tdm_queue_buffer *)ds_buffer;
198 queue_buffer_iface_destroy(struct ds_buffer *ds_buffer)
200 struct ds_tdm_queue_buffer *buffer;
202 buffer = queue_buffer_from_buffer(ds_buffer);
203 queue_buffer_destroy(buffer);
207 queue_buffer_iface_begin_data_ptr_access(struct ds_buffer *ds_buffer,
208 uint32_t flags, void **data, uint32_t *format, size_t *stride)
210 struct ds_tdm_queue_buffer *buffer;
211 tbm_surface_info_s info;
212 int tbm_access_flags = 0;
215 buffer = queue_buffer_from_buffer(ds_buffer);
217 if (!buffer->surface) {
218 ds_err("No tbm_surface. It's a dropped buffer(%p)", buffer);
222 if (flags & DS_BUFFER_DATA_PTR_ACCESS_READ)
223 tbm_access_flags |= TBM_OPTION_READ;
224 else if (flags & DS_BUFFER_DATA_PTR_ACCESS_WRITE)
225 tbm_access_flags |= TBM_OPTION_WRITE;
227 ret = tbm_surface_map(buffer->surface, tbm_access_flags, &info);
228 if (ret != TBM_SURFACE_ERROR_NONE) {
229 ds_err("Could not map tbm_surface of buffer(%p)", buffer);
233 *data = info.planes[0].ptr;
234 *format = info.format;
235 *stride = info.planes[0].stride;
241 queue_buffer_iface_end_data_ptr_access(struct ds_buffer *ds_buffer)
243 struct ds_tdm_queue_buffer *buffer;
245 buffer = queue_buffer_from_buffer(ds_buffer);
246 if (!buffer->surface) {
247 ds_err("No tbm_surface. It's a dropped buffer(%p)", buffer);
251 tbm_surface_unmap(buffer->surface);
254 static const struct ds_buffer_interface queue_buffer_iface =
256 .destroy = queue_buffer_iface_destroy,
257 .begin_data_ptr_access = queue_buffer_iface_begin_data_ptr_access,
258 .end_data_ptr_access = queue_buffer_iface_end_data_ptr_access,
262 queue_buffer_handle_buffer_release(struct wl_listener *listener, void *data)
264 struct ds_tdm_queue_buffer *buffer;
266 buffer = wl_container_of(listener, buffer, buffer_release);
268 wl_list_remove(&buffer->buffer_release.link);
269 buffer->acquired = false;
271 tbm_surface_queue_release(buffer->queue->tbm_surface_queue,
276 queue_buffer_drop(struct ds_tdm_queue_buffer *buffer)
278 if (buffer->acquired)
279 wl_list_remove(&buffer->buffer_release.link);
281 wl_list_remove(&buffer->link);
282 ds_buffer_drop(&buffer->base);
283 buffer->surface = NULL;
286 static struct ds_buffer *
287 queue_buffer_acquire(struct ds_tdm_queue_buffer *buffer)
289 assert(!buffer->acquired);
291 buffer->acquired = true;
292 buffer->buffer_release.notify = queue_buffer_handle_buffer_release;
293 ds_buffer_add_release_listener(&buffer->base, &buffer->buffer_release);
295 return ds_buffer_lock(&buffer->base);
299 buffer_queue_handle_acquirable_efd(int fd, uint32_t mask, void *data)
301 struct ds_tdm_buffer_queue *queue = data;
302 uint64_t acquirable_event;
305 len = read(fd, &acquirable_event, sizeof(acquirable_event));
306 if (len < 0 && errno != EAGAIN)
309 wl_signal_emit(&queue->events.acquirable, queue);