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);
29 WL_EXPORT struct ds_buffer *
30 ds_buffer_from_resource(struct wl_resource *resource)
32 struct ds_buffer *buffer;
33 const struct ds_buffer_resource_interface *iface;
35 DS_ASSERT(resource && ds_resource_is_buffer(resource));
37 if (wl_shm_buffer_get(resource) != NULL) {
38 struct ds_shm_client_buffer *shm_client_buffer =
39 ds_shm_client_buffer_get_or_create(resource);
40 if (!shm_client_buffer) {
41 ds_err("Failed to create shm client buffer");
45 buffer = ds_buffer_lock(&shm_client_buffer->base);
48 iface = get_buffer_resource_iface(resource);
50 ds_err("Unknown buffer type");
54 buffer = iface->from_resource(resource);
56 ds_err("Failed to create %s buffer", iface->name);
60 buffer = ds_buffer_lock(buffer);
67 ds_buffer_drop(struct ds_buffer *buffer)
69 DS_ASSERT(!buffer->dropped);
70 buffer->dropped = true;
71 ds_dbg("Buffer(%p) dropped: n_locks(%zu)", buffer, buffer->n_locks);
72 buffer_consider_destroy(buffer);
75 WL_EXPORT struct ds_buffer *
76 ds_buffer_lock(struct ds_buffer *buffer)
79 ds_dbg("Buffer(%p) n_locks(%zu)", buffer, buffer->n_locks);
84 ds_buffer_unlock(struct ds_buffer *buffer)
86 DS_ASSERT(buffer->n_locks > 0);
88 ds_dbg("Buffer(%p) n_locks(%zu)", buffer, buffer->n_locks);
90 if (buffer->n_locks == 0)
91 wl_signal_emit_mutable(&buffer->events.release, NULL);
93 buffer_consider_destroy(buffer);
97 ds_buffer_begin_data_ptr_access(struct ds_buffer *buffer, uint32_t flags,
98 void **data, uint32_t *format, size_t *stride)
100 DS_ASSERT(!buffer->accessing_data_ptr);
101 if (!buffer->iface->begin_data_ptr_access)
103 if (!buffer->iface->begin_data_ptr_access(buffer,
104 flags, data, format, stride))
106 buffer->accessing_data_ptr = true;
111 ds_buffer_end_data_ptr_access(struct ds_buffer *buffer)
113 DS_ASSERT(buffer->accessing_data_ptr);
114 buffer->iface->end_data_ptr_access(buffer);
115 buffer->accessing_data_ptr = false;
119 ds_buffer_add_destroy_listener(struct ds_buffer *buffer,
120 struct wl_listener *listener)
122 wl_signal_add(&buffer->events.destroy, listener);
126 ds_buffer_add_release_listener(struct ds_buffer *buffer,
127 struct wl_listener *listener)
129 wl_signal_add(&buffer->events.release, listener);
133 ds_buffer_get_shm(struct ds_buffer *buffer, struct ds_shm_attributes *attribs)
135 if (!buffer->iface->get_shm)
138 return buffer->iface->get_shm(buffer, attribs);
142 ds_buffer_get_size(struct ds_buffer *buffer, int *out_width, int *out_height)
145 *out_width = buffer->width;
147 *out_height = buffer->height;
151 ds_buffer_register_resource_interface(
152 const struct ds_buffer_resource_interface *iface)
154 const struct ds_buffer_resource_interface **iface_ptr;
157 DS_ASSERT(iface->is_instance);
158 DS_ASSERT(iface->from_resource);
160 wl_array_for_each(iface_ptr, &buffer_resource_interfaces) {
161 if (*iface_ptr == iface) {
162 ds_dbg("ds_buffer_resource_interface %s has already "
163 "been registered", iface->name);
168 iface_ptr = wl_array_add(&buffer_resource_interfaces, sizeof(iface));
170 ds_err("Could not allocate memory");
177 WL_EXPORT struct wl_resource *
178 ds_buffer_get_resource(struct ds_buffer *buffer)
180 if (!buffer->iface->get_resource)
183 return buffer->iface->get_resource(buffer);
187 buffer_consider_destroy(struct ds_buffer *buffer)
189 if (!buffer->dropped || buffer->n_locks > 0)
192 DS_ASSERT(!buffer->accessing_data_ptr);
194 wl_signal_emit_mutable(&buffer->events.destroy, NULL);
195 buffer->iface->destroy(buffer);
199 ds_resource_is_buffer(struct wl_resource *resource)
201 return strcmp(wl_resource_get_class(resource),
202 wl_buffer_interface.name) == 0;
205 static const struct ds_buffer_resource_interface *
206 get_buffer_resource_iface(struct wl_resource *resource)
208 struct ds_buffer_resource_interface **iface_ptr;
210 wl_array_for_each(iface_ptr, &buffer_resource_interfaces) {
211 if ((*iface_ptr)->is_instance(resource)) {