7 #include "shared/pixel_format.h"
8 #include "gbm_server.h"
10 static const struct ds_buffer_resource_interface gbm_buffer_resource_iface;
11 static const struct ds_buffer_interface gbm_client_buffer_iface;
13 static struct ds_gbm_server *gbm_server;
15 WL_EXPORT struct ds_gbm_server *
16 ds_gbm_server_create(int fd)
18 struct ds_gbm_server *gbm;
21 ds_inf("gbm server already created");
25 gbm = calloc(1, sizeof *gbm);
29 gbm->gbm_device = gbm_create_device(fd);
30 if (!gbm->gbm_device) {
35 ds_buffer_register_resource_interface(&gbm_buffer_resource_iface);
43 ds_gbm_server_destroy(struct ds_gbm_server *gbm)
45 gbm_device_destroy(gbm->gbm_device);
52 WL_EXPORT struct ds_gbm_client_buffer *
53 ds_gbm_client_buffer_from_buffer(struct ds_buffer *ds_buffer)
55 if (ds_buffer->iface != &gbm_client_buffer_iface)
57 return (struct ds_gbm_client_buffer *)ds_buffer;
60 WL_EXPORT struct gbm_bo *
61 ds_gbm_client_buffer_get_gbm_bo(struct ds_gbm_client_buffer *buffer)
63 if (buffer->base.iface != &gbm_client_buffer_iface)
65 return buffer->gbm_bo;
69 gbm_client_buffer_handle_release(struct wl_listener *listener, void *data)
71 struct ds_gbm_client_buffer *buffer;
73 buffer = wl_container_of(listener, buffer, buffer_release);
75 wl_buffer_send_release(buffer->resource);
79 gbm_client_buffer_handle_resource_destroy(struct wl_listener *listener,
82 struct ds_gbm_client_buffer *buffer;
84 buffer = wl_container_of(listener, buffer, resource_destroy);
86 buffer->resource = NULL;
88 wl_list_remove(&buffer->resource_destroy.link);
89 wl_list_init(&buffer->resource_destroy.link);
91 ds_buffer_drop(&buffer->base);
94 static struct ds_gbm_client_buffer *
95 gbm_client_buffer_from_buffer(struct ds_buffer *ds_buffer)
97 assert(ds_buffer->iface == &gbm_client_buffer_iface);
98 return (struct ds_gbm_client_buffer *)ds_buffer;
102 gbm_client_buffer_iface_destroy(struct ds_buffer *ds_buffer)
104 struct ds_gbm_client_buffer *buffer;
106 buffer = gbm_client_buffer_from_buffer(ds_buffer);
108 ds_dbg("Destroy gbm client buffer(%p)", buffer);
110 gbm_bo_destroy(buffer->gbm_bo);
112 wl_list_remove(&buffer->resource_destroy.link);
113 wl_list_remove(&buffer->buffer_release.link);
118 gbm_client_buffer_iface_begin_data_ptr_access(struct ds_buffer *ds_buffer,
119 enum ds_buffer_data_ptr_access_flag flags, void **data,
120 uint32_t *format, size_t *stride)
122 struct ds_gbm_client_buffer *buffer;
123 uint32_t gbm_flags = 0, map_stride;
124 void *map, *map_data;
126 buffer = gbm_client_buffer_from_buffer(ds_buffer);
128 if (flags & DS_BUFFER_DATA_PTR_ACCESS_READ)
129 gbm_flags |= GBM_BO_TRANSFER_READ;
131 if (flags & DS_BUFFER_DATA_PTR_ACCESS_WRITE)
132 gbm_flags |= GBM_BO_TRANSFER_WRITE;
134 map = gbm_bo_map(buffer->gbm_bo, 0, 0, ds_buffer->width, ds_buffer->height,
135 gbm_flags, &map_stride, &map_data);
137 ds_err("Failed gbm_surface_map()");
141 buffer->map_data = map_data;
143 *format = convert_tbm_format_to_drm(buffer->format);
144 *stride = map_stride;
151 gbm_client_buffer_iface_end_ptr_access(struct ds_buffer *ds_buffer)
153 struct ds_gbm_client_buffer *buffer;
155 buffer = gbm_client_buffer_from_buffer(ds_buffer);
157 gbm_bo_unmap(buffer->gbm_bo, buffer->map_data);
159 buffer->map_data = NULL;
162 static struct wl_resource *
163 gbm_client_buffer_iface_get_resource(struct ds_buffer *ds_buffer)
165 struct ds_gbm_client_buffer *buffer;
167 buffer = gbm_client_buffer_from_buffer(ds_buffer);
169 return buffer->resource;
172 static const struct ds_buffer_interface gbm_client_buffer_iface = {
173 .destroy = gbm_client_buffer_iface_destroy,
174 .begin_data_ptr_access = gbm_client_buffer_iface_begin_data_ptr_access,
175 .end_data_ptr_access = gbm_client_buffer_iface_end_ptr_access,
176 .get_resource = gbm_client_buffer_iface_get_resource,
179 static struct ds_gbm_client_buffer *
180 gbm_client_buffer_create(struct wl_resource *resource)
182 struct ds_gbm_client_buffer *buffer;
183 struct gbm_bo *gbm_bo;
184 int32_t width, height;
186 gbm_bo = gbm_bo_import(gbm_server->gbm_device, GBM_BO_IMPORT_WL_BUFFER,
187 resource, GBM_BO_USE_RENDERING);
188 if (!gbm_bo) return NULL;
190 width = gbm_bo_get_width(gbm_bo);
191 height = gbm_bo_get_height(gbm_bo);
193 buffer = calloc(1, sizeof *buffer);
195 gbm_bo_destroy(gbm_bo);
199 ds_buffer_init(&buffer->base, &gbm_client_buffer_iface, width, height);
201 buffer->resource = resource;
202 buffer->gbm_bo = gbm_bo;
203 buffer->format = gbm_bo_get_format(gbm_bo);
204 buffer->stride = gbm_bo_get_stride(gbm_bo);
206 buffer->buffer_release.notify = gbm_client_buffer_handle_release;
207 ds_buffer_add_release_listener(&buffer->base, &buffer->buffer_release);
209 buffer->resource_destroy.notify =
210 gbm_client_buffer_handle_resource_destroy;
211 wl_resource_add_destroy_listener(resource, &buffer->resource_destroy);
213 ds_dbg("gbm client buffer(%p) created", buffer);
218 static struct ds_gbm_client_buffer *
219 gbm_client_buffer_get_or_create(struct wl_resource *resource)
221 struct ds_gbm_client_buffer *buffer;
222 struct wl_listener *resource_destroy_listener;
224 resource_destroy_listener = wl_resource_get_destroy_listener(resource,
225 gbm_client_buffer_handle_resource_destroy);;
226 if (resource_destroy_listener) {
227 buffer = wl_container_of(resource_destroy_listener,
228 buffer, resource_destroy);
232 return gbm_client_buffer_create(resource);
236 gbm_buffer_resource_iface_is_instance(struct wl_resource *resource)
238 if (!gbm_server) return false;
240 if (!gbm_client_buffer_get_or_create(resource))
246 static struct ds_buffer *
247 gbm_buffer_resource_iface_from_resource(struct wl_resource *resource)
249 struct ds_gbm_client_buffer *buffer;
251 buffer = gbm_client_buffer_get_or_create(resource);
253 ds_err("Could not get or create ds_gbm_client_buffer");
257 return &buffer->base;
260 static const struct ds_buffer_resource_interface gbm_buffer_resource_iface = {
262 .is_instance = gbm_buffer_resource_iface_is_instance,
263 .from_resource = gbm_buffer_resource_iface_from_resource,