5 #include "client_buffer.h"
7 #include "libds/interfaces/buffer.h"
9 static struct wl_array buffer_resource_interfaces = {0};
11 static void buffer_consider_destroy(struct ds_buffer *buffer);
12 static bool ds_resource_is_buffer(struct wl_resource *resource);
13 static const struct ds_buffer_resource_interface *
14 get_buffer_resource_iface(struct wl_resource *resource);
17 ds_buffer_init(struct ds_buffer *buffer, const struct ds_buffer_interface *iface,
18 int width, int height)
20 buffer->iface = iface;
21 buffer->width = width;
22 buffer->height = height;
24 wl_signal_init(&buffer->events.destroy);
25 wl_signal_init(&buffer->events.release);
28 WL_EXPORT struct ds_buffer *
29 ds_buffer_from_resource(struct wl_resource *resource)
31 struct ds_buffer *buffer;
32 const struct ds_buffer_resource_interface *iface;
34 assert(resource && ds_resource_is_buffer(resource));
36 if (wl_shm_buffer_get(resource) != NULL) {
37 struct ds_shm_client_buffer *shm_client_buffer =
38 ds_shm_client_buffer_get_or_create(resource);
39 if (!shm_client_buffer) {
40 ds_err("Failed to create shm client buffer");
44 buffer = ds_buffer_lock(&shm_client_buffer->base);
47 iface = get_buffer_resource_iface(resource);
49 ds_err("Unknown buffer type");
53 buffer = iface->from_resource(resource);
55 ds_err("Failed to create %s buffer", iface->name);
59 buffer = ds_buffer_lock(buffer);
66 ds_buffer_drop(struct ds_buffer *buffer)
68 assert(!buffer->dropped);
69 buffer->dropped = true;
70 ds_dbg("Buffer(%p) dropped: n_locks(%zu)", buffer, buffer->n_locks);
71 buffer_consider_destroy(buffer);
74 WL_EXPORT struct ds_buffer *
75 ds_buffer_lock(struct ds_buffer *buffer)
78 ds_dbg("Buffer(%p) n_locks(%zu)", buffer, buffer->n_locks);
83 ds_buffer_unlock(struct ds_buffer *buffer)
85 assert(buffer->n_locks > 0);
87 ds_dbg("Buffer(%p) n_locks(%zu)", buffer, buffer->n_locks);
89 if (buffer->n_locks == 0)
90 wl_signal_emit(&buffer->events.release, NULL);
92 buffer_consider_destroy(buffer);
96 ds_buffer_begin_data_ptr_access(struct ds_buffer *buffer, uint32_t flags,
97 void **data, uint32_t *format, size_t *stride)
99 assert(!buffer->accessing_data_ptr);
100 if (!buffer->iface->begin_data_ptr_access)
102 if (!buffer->iface->begin_data_ptr_access(buffer, flags, data, format, stride))
104 buffer->accessing_data_ptr = true;
109 ds_buffer_end_data_ptr_access(struct ds_buffer *buffer)
111 assert(buffer->accessing_data_ptr);
112 buffer->iface->end_data_ptr_access(buffer);
113 buffer->accessing_data_ptr = false;
117 ds_buffer_add_destroy_listener(struct ds_buffer *buffer,
118 struct wl_listener *listener)
120 wl_signal_add(&buffer->events.destroy, listener);
124 ds_buffer_add_release_listener(struct ds_buffer *buffer,
125 struct wl_listener *listener)
127 wl_signal_add(&buffer->events.release, listener);
131 ds_buffer_get_shm(struct ds_buffer *buffer, struct ds_shm_attributes *attribs)
133 if (!buffer->iface->get_shm)
136 return buffer->iface->get_shm(buffer, attribs);
140 ds_buffer_get_size(struct ds_buffer *buffer, int *out_width, int *out_height)
143 *out_width = buffer->width;
145 *out_height = buffer->height;
149 ds_buffer_register_resource_interface(
150 const struct ds_buffer_resource_interface *iface)
152 const struct ds_buffer_resource_interface **iface_ptr;
155 assert(iface->is_instance);
156 assert(iface->from_resource);
158 wl_array_for_each(iface_ptr, &buffer_resource_interfaces) {
159 if (*iface_ptr == iface) {
160 ds_dbg("ds_buffer_resource_interface %s has already "
161 "been registered", iface->name);
166 iface_ptr = wl_array_add(&buffer_resource_interfaces, sizeof(iface));
171 buffer_consider_destroy(struct ds_buffer *buffer)
173 if (!buffer->dropped || buffer->n_locks > 0)
176 assert(!buffer->accessing_data_ptr);
178 wl_signal_emit(&buffer->events.destroy, NULL);
179 buffer->iface->destroy(buffer);
183 ds_resource_is_buffer(struct wl_resource *resource)
185 return strcmp(wl_resource_get_class(resource),
186 wl_buffer_interface.name) == 0;
189 static const struct ds_buffer_resource_interface *
190 get_buffer_resource_iface(struct wl_resource *resource)
192 struct ds_buffer_resource_interface **iface_ptr;
194 wl_array_for_each(iface_ptr, &buffer_resource_interfaces) {
195 if ((*iface_ptr)->is_instance(resource)) {