4 #include "libds/interfaces/buffer.h"
8 #include "client_buffer.h"
10 static struct wl_array buffer_resource_interfaces = {0};
12 static void buffer_consider_destroy(struct ds_buffer *buffer);
13 static bool ds_resource_is_buffer(struct wl_resource *resource);
14 static const struct ds_buffer_resource_interface *
15 get_buffer_resource_iface(struct wl_resource *resource);
18 ds_buffer_init(struct ds_buffer *buffer,
19 const struct ds_buffer_interface *iface, int width, int height)
21 buffer->iface = iface;
22 buffer->width = width;
23 buffer->height = height;
25 wl_signal_init(&buffer->events.destroy);
26 wl_signal_init(&buffer->events.release);
28 ds_addon_set_init(&buffer->addons);
31 WL_EXPORT struct ds_buffer *
32 ds_buffer_from_resource(struct wl_resource *resource)
34 struct ds_buffer *buffer;
35 const struct ds_buffer_resource_interface *iface;
37 DS_ASSERT(resource && ds_resource_is_buffer(resource));
39 if (wl_shm_buffer_get(resource) != NULL) {
40 struct ds_shm_client_buffer *shm_client_buffer =
41 ds_shm_client_buffer_get_or_create(resource);
42 if (!shm_client_buffer) {
43 ds_err("Failed to create shm client buffer");
47 buffer = ds_buffer_lock(&shm_client_buffer->base);
50 iface = get_buffer_resource_iface(resource);
52 ds_err("Unknown buffer type");
56 buffer = iface->from_resource(resource);
58 ds_err("Failed to create %s buffer", iface->name);
62 buffer = ds_buffer_lock(buffer);
69 ds_buffer_drop(struct ds_buffer *buffer)
71 DS_ASSERT(!buffer->dropped);
72 buffer->dropped = true;
73 ds_dbg("Buffer(%p) dropped: n_locks(%zu)", buffer, buffer->n_locks);
74 buffer_consider_destroy(buffer);
77 WL_EXPORT struct ds_buffer *
78 ds_buffer_lock(struct ds_buffer *buffer)
81 ds_dbg("Buffer(%p) n_locks(%zu)", buffer, buffer->n_locks);
86 ds_buffer_unlock(struct ds_buffer *buffer)
88 DS_ASSERT(buffer->n_locks > 0);
90 ds_dbg("Buffer(%p) n_locks(%zu)", buffer, buffer->n_locks);
92 if (buffer->n_locks == 0)
93 wl_signal_emit_mutable(&buffer->events.release, NULL);
95 buffer_consider_destroy(buffer);
99 ds_buffer_begin_data_ptr_access(struct ds_buffer *buffer, uint32_t flags,
100 void **data, uint32_t *format, size_t *stride)
102 DS_ASSERT(!buffer->accessing_data_ptr);
103 if (!buffer->iface->begin_data_ptr_access)
105 if (!buffer->iface->begin_data_ptr_access(buffer,
106 flags, data, format, stride))
108 buffer->accessing_data_ptr = true;
113 ds_buffer_end_data_ptr_access(struct ds_buffer *buffer)
115 DS_ASSERT(buffer->accessing_data_ptr);
116 buffer->iface->end_data_ptr_access(buffer);
117 buffer->accessing_data_ptr = false;
121 ds_buffer_add_destroy_listener(struct ds_buffer *buffer,
122 struct wl_listener *listener)
124 wl_signal_add(&buffer->events.destroy, listener);
128 ds_buffer_add_release_listener(struct ds_buffer *buffer,
129 struct wl_listener *listener)
131 wl_signal_add(&buffer->events.release, listener);
135 ds_buffer_get_shm(struct ds_buffer *buffer, struct ds_shm_attributes *attribs)
137 if (!buffer->iface->get_shm)
140 return buffer->iface->get_shm(buffer, attribs);
144 ds_buffer_get_size(struct ds_buffer *buffer, int *out_width, int *out_height)
147 *out_width = buffer->width;
149 *out_height = buffer->height;
153 ds_buffer_register_resource_interface(
154 const struct ds_buffer_resource_interface *iface)
156 const struct ds_buffer_resource_interface **iface_ptr;
159 DS_ASSERT(iface->is_instance);
160 DS_ASSERT(iface->from_resource);
162 wl_array_for_each(iface_ptr, &buffer_resource_interfaces) {
163 if (*iface_ptr == iface) {
164 ds_dbg("ds_buffer_resource_interface %s has already "
165 "been registered", iface->name);
170 iface_ptr = wl_array_add(&buffer_resource_interfaces, sizeof(iface));
172 ds_err("Could not allocate memory");
179 WL_EXPORT struct wl_resource *
180 ds_buffer_get_resource(struct ds_buffer *buffer)
182 if (!buffer->iface->get_resource)
185 return buffer->iface->get_resource(buffer);
189 buffer_consider_destroy(struct ds_buffer *buffer)
191 if (!buffer->dropped || buffer->n_locks > 0)
194 DS_ASSERT(!buffer->accessing_data_ptr);
196 ds_addon_set_finish(&buffer->addons);
198 wl_signal_emit_mutable(&buffer->events.destroy, NULL);
199 buffer->iface->destroy(buffer);
203 ds_resource_is_buffer(struct wl_resource *resource)
205 return strcmp(wl_resource_get_class(resource),
206 wl_buffer_interface.name) == 0;
209 static const struct ds_buffer_resource_interface *
210 get_buffer_resource_iface(struct wl_resource *resource)
212 struct ds_buffer_resource_interface **iface_ptr;
214 wl_array_for_each(iface_ptr, &buffer_resource_interfaces) {
215 if ((*iface_ptr)->is_instance(resource)) {