blob: d81b63d54b23580223823ab8868956d60525cf11 [file] [log] [blame]
Pekka Paalanen230f3b12014-09-29 14:18:40 -04001/*
2 * Copyright © 2014, 2015 Collabora, Ltd.
3 *
Yong Bakos53361532017-01-23 06:17:44 -08004 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
Pekka Paalanen230f3b12014-09-29 14:18:40 -040011 *
Yong Bakos53361532017-01-23 06:17:44 -080012 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial
14 * portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
Pekka Paalanen230f3b12014-09-29 14:18:40 -040024 */
25
26#include "config.h"
27
28#include <assert.h>
Jussi Kukkonen649bbce2016-07-19 14:16:27 +030029#include <stdint.h>
Pekka Paalanen230f3b12014-09-29 14:18:40 -040030#include <unistd.h>
31#include <sys/types.h>
32
33#include "compositor.h"
34#include "linux-dmabuf.h"
Jonas Ådahl57e48f02015-11-17 16:00:28 +080035#include "linux-dmabuf-unstable-v1-server-protocol.h"
Pekka Paalanen230f3b12014-09-29 14:18:40 -040036
37static void
38linux_dmabuf_buffer_destroy(struct linux_dmabuf_buffer *buffer)
39{
40 int i;
41
Emmanuel Gil Peyrotc3996922015-11-24 19:28:24 +000042 for (i = 0; i < buffer->attributes.n_planes; i++) {
43 close(buffer->attributes.fd[i]);
44 buffer->attributes.fd[i] = -1;
Pekka Paalanen230f3b12014-09-29 14:18:40 -040045 }
46
Emmanuel Gil Peyrotc3996922015-11-24 19:28:24 +000047 buffer->attributes.n_planes = 0;
Pekka Paalanen230f3b12014-09-29 14:18:40 -040048 free(buffer);
49}
50
51static void
52destroy_params(struct wl_resource *params_resource)
53{
54 struct linux_dmabuf_buffer *buffer;
55
56 buffer = wl_resource_get_user_data(params_resource);
57
58 if (!buffer)
59 return;
60
61 linux_dmabuf_buffer_destroy(buffer);
62}
63
64static void
65params_destroy(struct wl_client *client, struct wl_resource *resource)
66{
67 wl_resource_destroy(resource);
68}
69
70static void
71params_add(struct wl_client *client,
72 struct wl_resource *params_resource,
73 int32_t name_fd,
74 uint32_t plane_idx,
75 uint32_t offset,
76 uint32_t stride,
77 uint32_t modifier_hi,
78 uint32_t modifier_lo)
79{
80 struct linux_dmabuf_buffer *buffer;
81
82 buffer = wl_resource_get_user_data(params_resource);
83 if (!buffer) {
84 wl_resource_post_error(params_resource,
Jonas Ådahl57e48f02015-11-17 16:00:28 +080085 ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ALREADY_USED,
Pekka Paalanen230f3b12014-09-29 14:18:40 -040086 "params was already used to create a wl_buffer");
87 close(name_fd);
88 return;
89 }
90
91 assert(buffer->params_resource == params_resource);
92 assert(!buffer->buffer_resource);
93
94 if (plane_idx >= MAX_DMABUF_PLANES) {
95 wl_resource_post_error(params_resource,
Jonas Ådahl57e48f02015-11-17 16:00:28 +080096 ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_IDX,
Pekka Paalanen230f3b12014-09-29 14:18:40 -040097 "plane index %u is too high", plane_idx);
98 close(name_fd);
99 return;
100 }
101
Emmanuel Gil Peyrotc3996922015-11-24 19:28:24 +0000102 if (buffer->attributes.fd[plane_idx] != -1) {
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400103 wl_resource_post_error(params_resource,
Jonas Ådahl57e48f02015-11-17 16:00:28 +0800104 ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_SET,
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400105 "a dmabuf has already been added for plane %u",
106 plane_idx);
107 close(name_fd);
108 return;
109 }
110
Emmanuel Gil Peyrotc3996922015-11-24 19:28:24 +0000111 buffer->attributes.fd[plane_idx] = name_fd;
112 buffer->attributes.offset[plane_idx] = offset;
113 buffer->attributes.stride[plane_idx] = stride;
114 buffer->attributes.modifier[plane_idx] = ((uint64_t)modifier_hi << 32) |
115 modifier_lo;
116 buffer->attributes.n_planes++;
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400117}
118
119static void
120linux_dmabuf_wl_buffer_destroy(struct wl_client *client,
121 struct wl_resource *resource)
122{
123 wl_resource_destroy(resource);
124}
125
126static const struct wl_buffer_interface linux_dmabuf_buffer_implementation = {
127 linux_dmabuf_wl_buffer_destroy
128};
129
130static void
131destroy_linux_dmabuf_wl_buffer(struct wl_resource *resource)
132{
133 struct linux_dmabuf_buffer *buffer;
134
135 buffer = wl_resource_get_user_data(resource);
136 assert(buffer->buffer_resource == resource);
137 assert(!buffer->params_resource);
138
139 if (buffer->user_data_destroy_func)
140 buffer->user_data_destroy_func(buffer);
141
142 linux_dmabuf_buffer_destroy(buffer);
143}
144
145static void
Varad Gautam65c94b82017-04-26 19:15:59 +0530146params_create_common(struct wl_client *client,
147 struct wl_resource *params_resource,
148 uint32_t buffer_id,
149 int32_t width,
150 int32_t height,
151 uint32_t format,
152 uint32_t flags)
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400153{
154 struct linux_dmabuf_buffer *buffer;
155 int i;
156
157 buffer = wl_resource_get_user_data(params_resource);
158
159 if (!buffer) {
160 wl_resource_post_error(params_resource,
Jonas Ådahl57e48f02015-11-17 16:00:28 +0800161 ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ALREADY_USED,
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400162 "params was already used to create a wl_buffer");
163 return;
164 }
165
166 assert(buffer->params_resource == params_resource);
167 assert(!buffer->buffer_resource);
168
169 /* Switch the linux_dmabuf_buffer object from params resource to
170 * eventually wl_buffer resource.
171 */
172 wl_resource_set_user_data(buffer->params_resource, NULL);
173 buffer->params_resource = NULL;
174
Emmanuel Gil Peyrotc3996922015-11-24 19:28:24 +0000175 if (!buffer->attributes.n_planes) {
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400176 wl_resource_post_error(params_resource,
Jonas Ådahl57e48f02015-11-17 16:00:28 +0800177 ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE,
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400178 "no dmabuf has been added to the params");
179 goto err_out;
180 }
181
182 /* Check for holes in the dmabufs set (e.g. [0, 1, 3]) */
Emmanuel Gil Peyrotc3996922015-11-24 19:28:24 +0000183 for (i = 0; i < buffer->attributes.n_planes; i++) {
184 if (buffer->attributes.fd[i] == -1) {
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400185 wl_resource_post_error(params_resource,
Jonas Ådahl57e48f02015-11-17 16:00:28 +0800186 ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE,
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400187 "no dmabuf has been added for plane %i", i);
188 goto err_out;
189 }
190 }
191
Emmanuel Gil Peyrotc3996922015-11-24 19:28:24 +0000192 buffer->attributes.width = width;
193 buffer->attributes.height = height;
194 buffer->attributes.format = format;
195 buffer->attributes.flags = flags;
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400196
197 if (width < 1 || height < 1) {
198 wl_resource_post_error(params_resource,
Jonas Ådahl57e48f02015-11-17 16:00:28 +0800199 ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_DIMENSIONS,
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400200 "invalid width %d or height %d", width, height);
201 goto err_out;
202 }
203
Emmanuel Gil Peyrotc3996922015-11-24 19:28:24 +0000204 for (i = 0; i < buffer->attributes.n_planes; i++) {
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400205 off_t size;
206
Emmanuel Gil Peyrotc3996922015-11-24 19:28:24 +0000207 if ((uint64_t) buffer->attributes.offset[i] + buffer->attributes.stride[i] > UINT32_MAX) {
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400208 wl_resource_post_error(params_resource,
Jonas Ådahl57e48f02015-11-17 16:00:28 +0800209 ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400210 "size overflow for plane %i", i);
211 goto err_out;
212 }
213
214 if (i == 0 &&
Emmanuel Gil Peyrotc3996922015-11-24 19:28:24 +0000215 (uint64_t) buffer->attributes.offset[i] +
216 (uint64_t) buffer->attributes.stride[i] * height > UINT32_MAX) {
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400217 wl_resource_post_error(params_resource,
Jonas Ådahl57e48f02015-11-17 16:00:28 +0800218 ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400219 "size overflow for plane %i", i);
220 goto err_out;
221 }
222
223 /* Don't report an error as it might be caused
224 * by the kernel not supporting seeking on dmabuf */
Emmanuel Gil Peyrotc3996922015-11-24 19:28:24 +0000225 size = lseek(buffer->attributes.fd[i], 0, SEEK_END);
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400226 if (size == -1)
Derek Foremanc06389a2016-04-25 09:23:24 -0500227 continue;
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400228
Emmanuel Gil Peyrotc3996922015-11-24 19:28:24 +0000229 if (buffer->attributes.offset[i] >= size) {
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400230 wl_resource_post_error(params_resource,
Jonas Ådahl57e48f02015-11-17 16:00:28 +0800231 ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400232 "invalid offset %i for plane %i",
Emmanuel Gil Peyrotc3996922015-11-24 19:28:24 +0000233 buffer->attributes.offset[i], i);
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400234 goto err_out;
235 }
236
Emmanuel Gil Peyrotc3996922015-11-24 19:28:24 +0000237 if (buffer->attributes.offset[i] + buffer->attributes.stride[i] > size) {
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400238 wl_resource_post_error(params_resource,
Jonas Ådahl57e48f02015-11-17 16:00:28 +0800239 ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400240 "invalid stride %i for plane %i",
Emmanuel Gil Peyrotc3996922015-11-24 19:28:24 +0000241 buffer->attributes.stride[i], i);
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400242 goto err_out;
243 }
244
245 /* Only valid for first plane as other planes might be
246 * sub-sampled according to fourcc format */
247 if (i == 0 &&
Emmanuel Gil Peyrotc3996922015-11-24 19:28:24 +0000248 buffer->attributes.offset[i] + buffer->attributes.stride[i] * height > size) {
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400249 wl_resource_post_error(params_resource,
Jonas Ådahl57e48f02015-11-17 16:00:28 +0800250 ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400251 "invalid buffer stride or height for plane %i", i);
252 goto err_out;
253 }
254 }
255
256 /* XXX: Some additional sanity checks could be done with respect
257 * to the fourcc format. A centralized collection (kernel or
258 * libdrm) would be useful to avoid code duplication for these
259 * checks (e.g. drm_format_num_planes).
260 */
261
262 if (!weston_compositor_import_dmabuf(buffer->compositor, buffer))
263 goto err_failed;
264
265 buffer->buffer_resource = wl_resource_create(client,
266 &wl_buffer_interface,
Varad Gautam65c94b82017-04-26 19:15:59 +0530267 1, buffer_id);
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400268 if (!buffer->buffer_resource) {
269 wl_resource_post_no_memory(params_resource);
270 goto err_buffer;
271 }
272
273 wl_resource_set_implementation(buffer->buffer_resource,
274 &linux_dmabuf_buffer_implementation,
275 buffer, destroy_linux_dmabuf_wl_buffer);
276
Varad Gautam65c94b82017-04-26 19:15:59 +0530277 /* send 'created' event when the request is not for an immediate
278 * import, ie buffer_id is zero */
279 if (buffer_id == 0)
280 zwp_linux_buffer_params_v1_send_created(params_resource,
Jonas Ådahl57e48f02015-11-17 16:00:28 +0800281 buffer->buffer_resource);
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400282
283 return;
284
285err_buffer:
286 if (buffer->user_data_destroy_func)
287 buffer->user_data_destroy_func(buffer);
288
289err_failed:
Varad Gautam65c94b82017-04-26 19:15:59 +0530290 if (buffer_id == 0)
291 zwp_linux_buffer_params_v1_send_failed(params_resource);
292 else
293 /* since the behavior is left implementation defined by the
294 * protocol in case of create_immed failure due to an unknown cause,
295 * we choose to treat it as a fatal error and immediately kill the
296 * client instead of creating an invalid handle and waiting for it
297 * to be used.
298 */
299 wl_resource_post_error(params_resource,
300 ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_WL_BUFFER,
301 "importing the supplied dmabufs failed");
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400302
303err_out:
304 linux_dmabuf_buffer_destroy(buffer);
305}
306
Varad Gautam65c94b82017-04-26 19:15:59 +0530307static void
308params_create(struct wl_client *client,
309 struct wl_resource *params_resource,
310 int32_t width,
311 int32_t height,
312 uint32_t format,
313 uint32_t flags)
314{
315 params_create_common(client, params_resource, 0, width, height, format,
316 flags);
317}
318
319static void
320params_create_immed(struct wl_client *client,
321 struct wl_resource *params_resource,
322 uint32_t buffer_id,
323 int32_t width,
324 int32_t height,
325 uint32_t format,
326 uint32_t flags)
327{
328 params_create_common(client, params_resource, buffer_id, width, height,
329 format, flags);
330}
331
Jonas Ådahl57e48f02015-11-17 16:00:28 +0800332static const struct zwp_linux_buffer_params_v1_interface
333zwp_linux_buffer_params_implementation = {
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400334 params_destroy,
335 params_add,
Varad Gautam65c94b82017-04-26 19:15:59 +0530336 params_create,
337 params_create_immed
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400338};
339
340static void
341linux_dmabuf_destroy(struct wl_client *client, struct wl_resource *resource)
342{
343 wl_resource_destroy(resource);
344}
345
346static void
347linux_dmabuf_create_params(struct wl_client *client,
348 struct wl_resource *linux_dmabuf_resource,
349 uint32_t params_id)
350{
351 struct weston_compositor *compositor;
352 struct linux_dmabuf_buffer *buffer;
353 uint32_t version;
354 int i;
355
356 version = wl_resource_get_version(linux_dmabuf_resource);
357 compositor = wl_resource_get_user_data(linux_dmabuf_resource);
358
359 buffer = zalloc(sizeof *buffer);
360 if (!buffer)
361 goto err_out;
362
363 for (i = 0; i < MAX_DMABUF_PLANES; i++)
Emmanuel Gil Peyrotc3996922015-11-24 19:28:24 +0000364 buffer->attributes.fd[i] = -1;
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400365
366 buffer->compositor = compositor;
367 buffer->params_resource =
368 wl_resource_create(client,
Jonas Ådahl57e48f02015-11-17 16:00:28 +0800369 &zwp_linux_buffer_params_v1_interface,
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400370 version, params_id);
371 if (!buffer->params_resource)
372 goto err_dealloc;
373
374 wl_resource_set_implementation(buffer->params_resource,
Jonas Ådahl57e48f02015-11-17 16:00:28 +0800375 &zwp_linux_buffer_params_implementation,
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400376 buffer, destroy_params);
377
378 return;
379
380err_dealloc:
381 free(buffer);
382
383err_out:
384 wl_resource_post_no_memory(linux_dmabuf_resource);
385}
386
387/** Get the linux_dmabuf_buffer from a wl_buffer resource
388 *
389 * If the given wl_buffer resource was created through the linux_dmabuf
390 * protocol interface, returns the linux_dmabuf_buffer object. This can
391 * be used as a type check for a wl_buffer.
392 *
393 * \param resource A wl_buffer resource.
394 * \return The linux_dmabuf_buffer if it exists, or NULL otherwise.
395 */
396WL_EXPORT struct linux_dmabuf_buffer *
397linux_dmabuf_buffer_get(struct wl_resource *resource)
398{
399 struct linux_dmabuf_buffer *buffer;
400
401 if (!resource)
402 return NULL;
403
404 if (!wl_resource_instance_of(resource, &wl_buffer_interface,
405 &linux_dmabuf_buffer_implementation))
406 return NULL;
407
408 buffer = wl_resource_get_user_data(resource);
409 assert(buffer);
410 assert(!buffer->params_resource);
411 assert(buffer->buffer_resource == resource);
412
413 return buffer;
414}
415
416/** Set renderer-private data
417 *
418 * Set the user data for the linux_dmabuf_buffer. It is invalid to overwrite
419 * a non-NULL user data with a new non-NULL pointer. This is meant to
420 * protect against renderers fighting over linux_dmabuf_buffer user data
421 * ownership.
422 *
423 * The renderer-private data is usually set from the
424 * weston_renderer::import_dmabuf hook.
425 *
426 * \param buffer The linux_dmabuf_buffer object to set for.
427 * \param data The new renderer-private data pointer.
428 * \param func Destructor function to be called for the renderer-private
429 * data when the linux_dmabuf_buffer gets destroyed.
430 *
431 * \sa weston_compositor_import_dmabuf
432 */
433WL_EXPORT void
434linux_dmabuf_buffer_set_user_data(struct linux_dmabuf_buffer *buffer,
435 void *data,
436 dmabuf_user_data_destroy_func func)
437{
438 assert(data == NULL || buffer->user_data == NULL);
439
440 buffer->user_data = data;
441 buffer->user_data_destroy_func = func;
442}
443
444/** Get renderer-private data
445 *
446 * Get the user data from the linux_dmabuf_buffer.
447 *
448 * \param buffer The linux_dmabuf_buffer to query.
449 * \return Renderer-private data pointer.
450 *
451 * \sa linux_dmabuf_buffer_set_user_data
452 */
453WL_EXPORT void *
454linux_dmabuf_buffer_get_user_data(struct linux_dmabuf_buffer *buffer)
455{
456 return buffer->user_data;
457}
458
Jonas Ådahl57e48f02015-11-17 16:00:28 +0800459static const struct zwp_linux_dmabuf_v1_interface linux_dmabuf_implementation = {
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400460 linux_dmabuf_destroy,
461 linux_dmabuf_create_params
462};
463
464static void
465bind_linux_dmabuf(struct wl_client *client,
466 void *data, uint32_t version, uint32_t id)
467{
468 struct weston_compositor *compositor = data;
469 struct wl_resource *resource;
Varad Gautam41b4b8f2017-04-26 19:17:17 +0530470 int *formats = NULL;
471 uint64_t *modifiers = NULL;
472 int num_formats, num_modifiers;
473 uint64_t modifier_invalid = DRM_FORMAT_MOD_INVALID;
474 int i, j;
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400475
Jonas Ådahl57e48f02015-11-17 16:00:28 +0800476 resource = wl_resource_create(client, &zwp_linux_dmabuf_v1_interface,
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400477 version, id);
478 if (resource == NULL) {
479 wl_client_post_no_memory(client);
480 return;
481 }
482
483 wl_resource_set_implementation(resource, &linux_dmabuf_implementation,
484 compositor, NULL);
485
Derek Foremanbbc206e2017-06-26 15:55:44 -0500486 if (version < ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION)
487 return;
Varad Gautam41b4b8f2017-04-26 19:17:17 +0530488 /*
489 * Use EGL_EXT_image_dma_buf_import_modifiers to query and advertise
490 * format/modifier codes.
491 */
492 compositor->renderer->query_dmabuf_formats(compositor, &formats,
493 &num_formats);
494
495 for (i = 0; i < num_formats; i++) {
496 compositor->renderer->query_dmabuf_modifiers(compositor,
497 formats[i],
498 &modifiers,
499 &num_modifiers);
500
501 /* send DRM_FORMAT_MOD_INVALID token when no modifiers are supported
502 * for this format */
503 if (num_modifiers == 0) {
504 num_modifiers = 1;
505 modifiers = &modifier_invalid;
506 }
507 for (j = 0; j < num_modifiers; j++) {
508 uint32_t modifier_lo = modifiers[j] & 0xFFFFFFFF;
509 uint32_t modifier_hi = modifiers[j] >> 32;
510 zwp_linux_dmabuf_v1_send_modifier(resource, formats[i],
511 modifier_hi,
512 modifier_lo);
513 }
Derek Foremancd052a62017-06-26 14:44:54 -0500514 if (modifiers != &modifier_invalid)
515 free(modifiers);
Varad Gautam41b4b8f2017-04-26 19:17:17 +0530516 }
517 free(formats);
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400518}
519
520/** Advertise linux_dmabuf support
521 *
Jonas Ådahl57e48f02015-11-17 16:00:28 +0800522 * Calling this initializes the zwp_linux_dmabuf protocol support, so that
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400523 * the interface will be advertised to clients. Essentially it creates a
524 * global. Do not call this function multiple times in the compositor's
525 * lifetime. There is no way to deinit explicitly, globals will be reaped
526 * when the wl_display gets destroyed.
527 *
528 * \param compositor The compositor to init for.
529 * \return Zero on success, -1 on failure.
530 */
531WL_EXPORT int
532linux_dmabuf_setup(struct weston_compositor *compositor)
533{
534 if (!wl_global_create(compositor->wl_display,
Varad Gautam41b4b8f2017-04-26 19:17:17 +0530535 &zwp_linux_dmabuf_v1_interface, 3,
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400536 compositor, bind_linux_dmabuf))
537 return -1;
538
539 return 0;
540}
541
542/** Resolve an internal compositor error by disconnecting the client.
543 *
544 * This function is used in cases when the dmabuf-based wl_buffer
545 * turns out unusable and there is no fallback path. This is used by
546 * renderers which are the fallback path in the first place.
547 *
548 * It is possible the fault is caused by a compositor bug, the underlying
549 * graphics stack bug or normal behaviour, or perhaps a client mistake.
550 * In any case, the options are to either composite garbage or nothing,
551 * or disconnect the client. This is a helper function for the latter.
552 *
Bryce Harringtonba63fae2016-07-06 15:30:54 -0700553 * The error is sent as an INVALID_OBJECT error on the client's wl_display.
Pekka Paalanen230f3b12014-09-29 14:18:40 -0400554 *
555 * \param buffer The linux_dmabuf_buffer that is unusable.
556 * \param msg A custom error message attached to the protocol error.
557 */
558WL_EXPORT void
559linux_dmabuf_buffer_send_server_error(struct linux_dmabuf_buffer *buffer,
560 const char *msg)
561{
562 struct wl_client *client;
563 struct wl_resource *display_resource;
564 uint32_t id;
565
566 assert(buffer->buffer_resource);
567 id = wl_resource_get_id(buffer->buffer_resource);
568 client = wl_resource_get_client(buffer->buffer_resource);
569 display_resource = wl_client_get_object(client, 1);
570
571 assert(display_resource);
572 wl_resource_post_error(display_resource,
573 WL_DISPLAY_ERROR_INVALID_OBJECT,
574 "linux_dmabuf server error with "
575 "wl_buffer@%u: %s", id, msg);
576}