5 #include <tbm_bufmgr.h>
8 #include "shared/pixel_format.h"
9 #include "tbm_server.h"
11 static const struct ds_buffer_resource_interface tbm_buffer_resource_iface;
12 static const struct ds_buffer_interface tbm_client_buffer_iface;
14 static void tbm_server_handle_display_destroy(struct wl_listener *listener,
17 WL_EXPORT struct ds_tbm_server *
18 ds_tbm_server_create(struct wl_display *display)
20 struct ds_tbm_server *tbm;
23 tbm = calloc(1, sizeof *tbm);
27 wl_signal_init(&tbm->events.destroy);
29 tbm->wl_tbm = wayland_tbm_server_init(display, NULL, -1, 0);
34 bufmgr = wayland_tbm_server_get_bufmgr(tbm->wl_tbm);
39 if (!tbm_bufmgr_bind_native_display(bufmgr, (void *)display)) {
43 tbm->display_destroy.notify = tbm_server_handle_display_destroy;
44 wl_display_add_destroy_listener(display, &tbm->display_destroy);
46 ds_buffer_register_resource_interface(&tbm_buffer_resource_iface);
51 wayland_tbm_server_deinit(tbm->wl_tbm);
59 ds_tbm_server_add_destroy_listener(struct ds_tbm_server *tbm,
60 struct wl_listener *listener)
62 wl_signal_add(&tbm->events.destroy, listener);
65 WL_EXPORT struct ds_tbm_client_buffer *
66 ds_tbm_client_buffer_from_buffer(struct ds_buffer *ds_buffer)
68 if (ds_buffer->iface != &tbm_client_buffer_iface)
70 return (struct ds_tbm_client_buffer *)ds_buffer;
73 WL_EXPORT tbm_surface_h
74 ds_tbm_client_buffer_get_tbm_surface(struct ds_tbm_client_buffer *buffer)
76 if (buffer->base.iface != &tbm_client_buffer_iface)
78 return buffer->surface;
82 tbm_server_handle_display_destroy(struct wl_listener *listener, void *data)
84 struct ds_tbm_server *tbm;
86 tbm = wl_container_of(listener, tbm, display_destroy);
88 wl_signal_emit_mutable(&tbm->events.destroy, tbm);
90 wayland_tbm_server_deinit(tbm->wl_tbm);
95 tbm_client_buffer_handle_release(struct wl_listener *listener, void *data)
97 struct ds_tbm_client_buffer *buffer;
99 buffer = wl_container_of(listener, buffer, buffer_release);
100 if (buffer->resource)
101 wl_buffer_send_release(buffer->resource);
105 tbm_client_buffer_handle_resource_destroy(struct wl_listener *listener,
108 struct ds_tbm_client_buffer *buffer;
110 buffer = wl_container_of(listener, buffer, resource_destroy);
112 buffer->resource = NULL;
113 wl_list_remove(&buffer->resource_destroy.link);
114 wl_list_init(&buffer->resource_destroy.link);
116 ds_buffer_drop(&buffer->base);
119 static struct ds_tbm_client_buffer *
120 tbm_client_buffer_from_buffer(struct ds_buffer *ds_buffer)
122 assert(ds_buffer->iface == &tbm_client_buffer_iface);
123 return (struct ds_tbm_client_buffer *)ds_buffer;
127 tbm_client_buffer_iface_destroy(struct ds_buffer *ds_buffer)
129 struct ds_tbm_client_buffer *buffer;
131 buffer = tbm_client_buffer_from_buffer(ds_buffer);
133 ds_dbg("Destroy TBM client buffer(%p)", buffer);
135 tbm_surface_internal_unref(buffer->surface);
136 wl_list_remove(&buffer->resource_destroy.link);
137 wl_list_remove(&buffer->buffer_release.link);
142 tbm_client_buffer_iface_begin_data_ptr_access(struct ds_buffer *ds_buffer,
143 enum ds_buffer_data_ptr_access_flag flags, void **data,
144 uint32_t *format, size_t *stride)
146 struct ds_tbm_client_buffer *buffer;
147 tbm_surface_info_s info;
148 tbm_bo_access_option op = TBM_OPTION_NONE;
151 buffer = tbm_client_buffer_from_buffer(ds_buffer);
153 if (flags & DS_BUFFER_DATA_PTR_ACCESS_READ)
154 op |= TBM_OPTION_READ;
156 if (flags & DS_BUFFER_DATA_PTR_ACCESS_WRITE)
157 op |= TBM_OPTION_WRITE;
159 err = tbm_surface_map(buffer->surface, op, &info);
160 if (err != TBM_SURFACE_ERROR_NONE) {
161 ds_err("Failed tbm_surface_map()");
165 *format = convert_tbm_format_to_drm(buffer->format);
166 *stride = info.planes[0].stride;
167 *data = info.planes[0].ptr;
173 tbm_client_buffer_iface_end_ptr_access(struct ds_buffer *ds_buffer)
175 struct ds_tbm_client_buffer *buffer;
177 buffer = tbm_client_buffer_from_buffer(ds_buffer);
179 tbm_surface_unmap(buffer->surface);
182 static struct wl_resource *
183 tbm_client_buffer_iface_get_resource(struct ds_buffer *ds_buffer)
185 struct ds_tbm_client_buffer *buffer;
187 buffer = tbm_client_buffer_from_buffer(ds_buffer);
189 return buffer->resource;
192 static const struct ds_buffer_interface tbm_client_buffer_iface = {
193 .destroy = tbm_client_buffer_iface_destroy,
194 .begin_data_ptr_access = tbm_client_buffer_iface_begin_data_ptr_access,
195 .end_data_ptr_access = tbm_client_buffer_iface_end_ptr_access,
196 .get_resource = tbm_client_buffer_iface_get_resource,
199 static struct ds_tbm_client_buffer *
200 tbm_client_buffer_create(struct wl_resource *resource)
202 struct ds_tbm_client_buffer *buffer;
203 tbm_surface_h surface;
204 int32_t width, height;
206 surface = wayland_tbm_server_get_surface(NULL, resource);
208 ds_err("Could not get tbm_surface from wl_resource@%d",
209 wl_resource_get_id(resource));
213 width = tbm_surface_get_width(surface);
214 height = tbm_surface_get_height(surface);
216 buffer = calloc(1, sizeof *buffer);
220 ds_buffer_init(&buffer->base, &tbm_client_buffer_iface, width, height);
222 buffer->resource = resource;
223 tbm_surface_internal_ref(surface);
224 buffer->surface = surface;
225 buffer->format = tbm_surface_get_format(surface);
227 buffer->buffer_release.notify = tbm_client_buffer_handle_release;
228 ds_buffer_add_release_listener(&buffer->base, &buffer->buffer_release);
230 buffer->resource_destroy.notify =
231 tbm_client_buffer_handle_resource_destroy;
232 wl_resource_add_destroy_listener(resource, &buffer->resource_destroy);
234 ds_dbg("TBM client buffer(%p) created", buffer);
239 static struct ds_tbm_client_buffer *
240 tbm_client_buffer_get_or_create(struct wl_resource *resource)
242 struct ds_tbm_client_buffer *buffer;
243 struct wl_listener *resource_destroy_listener;
245 resource_destroy_listener = wl_resource_get_destroy_listener(resource,
246 tbm_client_buffer_handle_resource_destroy);;
247 if (resource_destroy_listener) {
248 buffer = wl_container_of(resource_destroy_listener,
249 buffer, resource_destroy);
253 return tbm_client_buffer_create(resource);
257 tbm_buffer_resource_iface_is_instance(struct wl_resource *resource)
259 return !!wayland_tbm_server_get_surface(NULL, resource);
262 static struct ds_buffer *
263 tbm_buffer_resource_iface_from_resource(struct wl_resource *resource)
265 struct ds_tbm_client_buffer *buffer;
267 buffer = tbm_client_buffer_get_or_create(resource);
269 ds_err("Could not get or create ds_tbm_client_buffer");
273 return &buffer->base;
276 static const struct ds_buffer_resource_interface tbm_buffer_resource_iface = {
278 .is_instance = tbm_buffer_resource_iface_is_instance,
279 .from_resource = tbm_buffer_resource_iface_from_resource,