1 /*
2 * Copyright © 2021 NVIDIA Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25 #include "gbm_backend_abi.h" /* Current GBM backend ABI implementation */
26
27 #include <stddef.h> /* offsetof */
28 #include <stdio.h> /* printf */
29
30 /*
31 * The following are previous implementations of the structures defined in
32 * gbm_backend_abi.h, with their ABI version appended.
33 *
34 * DO NOT EVER CHANGE EXISTING DEFINITIONS HERE!
35 *
36 * Changing them implies breaking the GBM backend ABI. Instead, to extend the
37 * ABI, in gbm_backend_abi.h:
38 *
39 * -Add a new versioned struct
40 * -Append it to the associated top-level object's struct
41 * -Increment GBM_BACKEND_ABI_VERSION
42 *
43 * Then, here:
44 *
45 * -Add a new block of definitions below for the new ABI content
46 * -Add a new block of checks in main()
47 */
48
49 /*
50 * From: Simon Ser - "gbm: assume USE_SCANOUT in create_with_modifiers"
51 *
52 * Note: ABI 1 is identical to ABI 0, except gbm_device_v0.bo_create can
53 * provide both modifiers and usage.
54 */
55 #define GBM_BACKEND_ABI_VERSION_abi0 1
56 struct gbm_device_v0_abi0 {
57 const struct gbm_backend_desc *backend_desc;
58 uint32_t backend_version;
59 int fd;
60 const char *name;
61 void (*destroy)(struct gbm_device *gbm);
62 int (*is_format_supported)(struct gbm_device *gbm,
63 uint32_t format,
64 uint32_t usage);
65 int (*get_format_modifier_plane_count)(struct gbm_device *device,
66 uint32_t format,
67 uint64_t modifier);
68 struct gbm_bo *(*bo_create)(struct gbm_device *gbm,
69 uint32_t width, uint32_t height,
70 uint32_t format,
71 uint32_t usage,
72 const uint64_t *modifiers,
73 const unsigned int count);
74 struct gbm_bo *(*bo_import)(struct gbm_device *gbm, uint32_t type,
75 void *buffer, uint32_t usage);
76 void *(*bo_map)(struct gbm_bo *bo,
77 uint32_t x, uint32_t y,
78 uint32_t width, uint32_t height,
79 uint32_t flags, uint32_t *stride,
80 void **map_data);
81 void (*bo_unmap)(struct gbm_bo *bo, void *map_data);
82 int (*bo_write)(struct gbm_bo *bo, const void *buf, size_t data);
83 int (*bo_get_fd)(struct gbm_bo *bo);
84 int (*bo_get_planes)(struct gbm_bo *bo);
85 union gbm_bo_handle (*bo_get_handle)(struct gbm_bo *bo, int plane);
86 int (*bo_get_plane_fd)(struct gbm_bo *bo, int plane);
87 uint32_t (*bo_get_stride)(struct gbm_bo *bo, int plane);
88 uint32_t (*bo_get_offset)(struct gbm_bo *bo, int plane);
89 uint64_t (*bo_get_modifier)(struct gbm_bo *bo);
90 void (*bo_destroy)(struct gbm_bo *bo);
91 struct gbm_surface *(*surface_create)(struct gbm_device *gbm,
92 uint32_t width, uint32_t height,
93 uint32_t format, uint32_t flags,
94 const uint64_t *modifiers,
95 const unsigned count);
96 struct gbm_bo *(*surface_lock_front_buffer)(struct gbm_surface *surface);
97 void (*surface_release_buffer)(struct gbm_surface *surface,
98 struct gbm_bo *bo);
99 int (*surface_has_free_buffers)(struct gbm_surface *surface);
100 void (*surface_destroy)(struct gbm_surface *surface);
101 };
102
103 struct gbm_device_abi0 {
104 /* Hack to make a gbm_device detectable by its first element. */
105 struct gbm_device *(*dummy)(int);
106 struct gbm_device_v0_abi0 v0;
107 };
108
109 /**
110 * GBM buffer object interface corresponding to GBM_BACKEND_ABI_VERSION = 0
111 *
112 * DO NOT MODIFY THIS STRUCT. Instead, introduce a gbm_bo_v1, increment
113 * GBM_BACKEND_ABI_VERSION, and append gbm_bo_v1 to gbm_bo.
114 */
115 struct gbm_bo_v0_abi0 {
116 uint32_t width;
117 uint32_t height;
118 uint32_t stride;
119 uint32_t format;
120 union gbm_bo_handle handle;
121 void *user_data;
122 void (*destroy_user_data)(struct gbm_bo *, void *);
123 };
124
125 /**
126 * The allocated buffer object.
127 *
128 * The members in this structure should not be accessed directly.
129 *
130 * To modify this structure, introduce a new gbm_bo_v<N> structure, add it to
131 * the end of this structure, and increment GBM_BACKEND_ABI_VERSION.
132 */
133 struct gbm_bo_abi0 {
134 struct gbm_device *gbm;
135 struct gbm_bo_v0_abi0 v0;
136 };
137
138 /**
139 * GBM surface interface corresponding to GBM_BACKEND_ABI_VERSION = 0
140 *
141 * DO NOT MODIFY THIS STRUCT. Instead, introduce a gbm_surface_v1, increment
142 * GBM_BACKEND_ABI_VERSION, and append gbm_surface_v1 to gbm_surface.
143 */
144 struct gbm_surface_v0_abi0 {
145 uint32_t width;
146 uint32_t height;
147 uint32_t format;
148 uint32_t flags;
149 struct {
150 uint64_t *modifiers;
151 unsigned count;
152 };
153 };
154
155 /**
156 * An allocated GBM surface.
157 *
158 * To modify this structure, introduce a new gbm_surface_v<N> structure, add it
159 * to the end of this structure, and increment GBM_BACKEND_ABI_VERSION.
160 */
161 struct gbm_surface_abi0 {
162 struct gbm_device *gbm;
163 struct gbm_surface_v0_abi0 v0;
164 };
165
166 /**
167 * GBM backend interfaces corresponding to GBM_BACKEND_ABI_VERSION = 0
168 *
169 * DO NOT MODIFY THIS STRUCT. Instead, introduce a gbm_backend_v1, increment
170 * GBM_BACKEND_ABI_VERSION, append gbm_backend_v1 to gbm_backend.
171 */
172 struct gbm_backend_v0_abi0 {
173 /**
174 * The version of the GBM backend interface supported by this backend. This
175 * is set by the backend itself, and may be greater or less than the version
176 * supported by the loader. It is the responsibility of the GBM loader to
177 * respect this version when accessing fields in this structure.
178 */
179 uint32_t backend_version;
180
181 const char *backend_name;
182 struct gbm_device *(*create_device)(int fd, uint32_t gbm_backend_version);
183 };
184
185 /**
186 * The interface exposed by an external GBM backend.
187 *
188 * To modify this structure, introduce a new gbm_backend_v<N> structure, add it
189 * to the end of this structure, and increment GBM_BACKEND_ABI_VERSION.
190 */
191 struct gbm_backend_abi0 {
192 struct gbm_backend_v0_abi0 v0;
193 };
194
195 /**
196 * GBM interfaces exposed to GBM backends at GBM_BACKEND_ABI_VERSION >= 0
197 *
198 * DO NOT MODIFY THIS STRUCT. Instead, introduce a gbm_core_v1, increment
199 * GBM_BACKEND_ABI_VERSION, and append gbm_core_v1 to gbm_backend.
200 */
201 struct gbm_core_v0_abi0 {
202 /**
203 * The version of the GBM backend interface supported by the GBM loader. This
204 * is set by the loader, and may be greater or less than the version
205 * supported by a given backend. It is the responsibility of the backend to
206 * respect this version when accessing fields in this structure and other
207 * structures allocated or modified by the loader.
208 */
209 uint32_t core_version;
210
211 uint32_t (*format_canonicalize)(uint32_t gbm_format);
212 };
213
214 /**
215 * The interface exposed by the GBM core/loader code to GBM backends.
216 *
217 * To modify this structure, introduce a new gbm_core_v<N> structure, add it
218 * to the end of this structure, and increment GBM_BACKEND_ABI_VERSION.
219 */
220 struct gbm_core_abi0 {
221 struct gbm_core_v0_abi0 v0;
222 };
223
224 typedef const struct gbm_backend *(*GBM_GET_BACKEND_PROC_PTR_abi0)(const struct gbm_core *gbm_core);
225
226 /*
227 * Structure/member ABI-checking helper macros
228 */
229 #define MEMBER_SIZE(type, member) sizeof(((type *)0)->member)
230
231 #define CHECK_RENAMED_MEMBER_BASE(type, a_ver, b_ver, a_member, b_member) \
232 do { \
233 if (offsetof(struct type ## a_ver, a_member) != \
234 offsetof(struct type ## b_ver, b_member)) { \
235 printf("Backards incompatible change detected!\n " \
236 "offsetof(struct " #type #a_ver "::" #a_member ") != " \
237 "offsetof(struct " #type #b_ver "::" #b_member ")\n"); \
238 return 1; \
239 } \
240 \
241 if (MEMBER_SIZE(struct type ## a_ver, a_member) != \
242 MEMBER_SIZE(struct type ## b_ver, b_member)) { \
243 printf("Backards incompatible change detected!\n " \
244 "MEMBER_SIZE(struct " #type #a_ver "::" #a_member ") != " \
245 "MEMBER_SIZE(struct " #type #b_ver "::" #b_member ")\n"); \
246 return 1; \
247 } \
248 } while (0)
249
250 #define CHECK_RENAMED_MEMBER_TYPE(type, a_ver, b_ver, a_member, b_member) \
251 do { \
252 /* Compile-time type compatibility check */ \
253 struct type ## a_ver a; \
254 struct type ## b_ver b = {0}; \
255 a.a_member = b.b_member; \
256 (void)a; \
257 } while (0)
258
259 #define CHECK_RENAMED_MEMBER(type, a_ver, b_ver, a_member, b_member) \
260 do { \
261 CHECK_RENAMED_MEMBER_BASE(type, a_ver, b_ver, a_member, b_member); \
262 CHECK_RENAMED_MEMBER_TYPE(type, a_ver, b_ver, a_member, b_member); \
263 } while (0)
264 #define CHECK_RENAMED_MEMBER_NO_TYPE(type, a_ver, b_ver, a_member, b_member) \
265 CHECK_RENAMED_MEMBER_BASE(type, a_ver, b_ver, a_member, b_member);
266
267 #define CHECK_MEMBER(type, a_ver, b_ver, member) \
268 CHECK_RENAMED_MEMBER(type, a_ver, b_ver, member, member)
269 #define CHECK_MEMBER_NO_TYPE(type, a_ver, b_ver, member) \
270 CHECK_RENAMED_MEMBER_NO_TYPE(type, a_ver, b_ver, member, member)
271 #define CHECK_MEMBER_CURRENT(type, a_ver, member) \
272 CHECK_MEMBER(type, a_ver,, member)
273 #define CHECK_MEMBER_CURRENT_NO_TYPE(type, a_ver, member) \
274 CHECK_MEMBER_NO_TYPE(type, a_ver,, member)
275
276 #define CHECK_SIZE(type, a_ver, b_ver) \
277 do { \
278 if (sizeof(struct type ## a_ver) > \
279 sizeof(struct type ## b_ver)) { \
280 printf("Backards incompatible change detected!\n " \
281 "sizeof(struct " #type #a_ver ") > " \
282 "sizeof(struct " #type #b_ver ")\n"); \
283 return 1; \
284 } \
285 } while (0)
286
287 #define CHECK_SIZE_CURRENT(type, a_ver) \
288 do { \
289 if (sizeof(struct type ## a_ver) != \
290 sizeof(struct type)) { \
291 printf("Backards incompatible change detected!\n " \
292 "sizeof(struct " #type #a_ver ") != " \
293 "sizeof(struct " #type ")\n"); \
294 return 1; \
295 } \
296 } while (0)
297
298 #define CHECK_VERSION(a_ver, b_ver) \
299 do { \
300 if ((GBM_BACKEND_ABI_VERSION ## a_ver) >= \
301 (GBM_BACKEND_ABI_VERSION ## b_ver)) { \
302 printf("Backards incompatible change detected!\n " \
303 "GBM_BACKEND_ABI_VERSION" #a_ver " >= " \
304 "GBM_BACKEND_ABI_VERSION" #b_ver "\n"); \
305 return 1; \
306 } \
307 } while (0)
308
309 #define CHECK_VERSION_CURRENT(a_ver) \
310 do { \
311 if ((GBM_BACKEND_ABI_VERSION ## a_ver) != \
312 (GBM_BACKEND_ABI_VERSION)) { \
313 printf("Backards incompatible change detected!\n " \
314 "GBM_BACKEND_ABI_VERSION" #a_ver " != " \
315 "GBM_BACKEND_ABI_VERSION\n"); \
316 return 1; \
317 } \
318 } while (0)
319
320 #define CHECK_PROC(proc, a_ver, b_ver) \
321 do { \
322 proc ## a_ver a; \
323 proc ## b_ver b = NULL; \
324 a = b; \
325 (void)a; \
326 } while (0)
327
328 #define CHECK_PROC_CURRENT(proc, a_ver) \
329 CHECK_PROC(proc, a_ver,)
330
main(int argc,char ** argv)331 int main(int argc, char **argv)
332 {
333 /********************************************/
334 /*** Compare Current ABI to ABI version 0 ***/
335 /********************************************/
336
337 /* Check current gbm_device ABI against gbm_device_abi0*/
338 CHECK_MEMBER_CURRENT(gbm_device, _abi0, dummy);
339 CHECK_MEMBER_CURRENT_NO_TYPE(gbm_device, _abi0, v0);
340
341 CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, backend_desc);
342 CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, backend_version);
343 CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, fd);
344 CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, name);
345 CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, destroy);
346 CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, is_format_supported);
347 CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, get_format_modifier_plane_count);
348 CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_create);
349 CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_import);
350 CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_map);
351 CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_unmap);
352 CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_write);
353 CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_get_fd);
354 CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_get_planes);
355 CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_get_handle);
356 CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_get_plane_fd);
357 CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_get_stride);
358 CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_get_offset);
359 CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_get_modifier);
360 CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_destroy);
361 CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, surface_create);
362 CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, surface_lock_front_buffer);
363 CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, surface_release_buffer);
364 CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, surface_has_free_buffers);
365 CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, surface_destroy);
366
367 /* Size of ABI-versioned substructures verified by above member checks */
368 CHECK_SIZE_CURRENT (gbm_device, _abi0);
369
370
371 /* Check current gbm_bo ABI against gbm_bo_abi0*/
372 CHECK_MEMBER_CURRENT(gbm_bo, _abi0, gbm);
373 CHECK_MEMBER_CURRENT_NO_TYPE(gbm_bo, _abi0, v0);
374
375 CHECK_MEMBER_CURRENT(gbm_bo_v0, _abi0, width);
376 CHECK_MEMBER_CURRENT(gbm_bo_v0, _abi0, height);
377 CHECK_MEMBER_CURRENT(gbm_bo_v0, _abi0, stride);
378 CHECK_MEMBER_CURRENT(gbm_bo_v0, _abi0, format);
379 CHECK_MEMBER_CURRENT(gbm_bo_v0, _abi0, handle);
380 CHECK_MEMBER_CURRENT(gbm_bo_v0, _abi0, user_data);
381 CHECK_MEMBER_CURRENT(gbm_bo_v0, _abi0, destroy_user_data);
382
383 /* Size of ABI-versioned substructures verified by above member checks */
384 CHECK_SIZE_CURRENT (gbm_bo, _abi0);
385
386
387 /* Check current gbm_surface ABI against gbm_surface_abi0 */
388 CHECK_MEMBER_CURRENT(gbm_surface, _abi0, gbm);
389 CHECK_MEMBER_CURRENT_NO_TYPE(gbm_surface, _abi0, v0);
390
391 CHECK_MEMBER_CURRENT(gbm_surface_v0, _abi0, width);
392 CHECK_MEMBER_CURRENT(gbm_surface_v0, _abi0, height);
393 CHECK_MEMBER_CURRENT(gbm_surface_v0, _abi0, format);
394 CHECK_MEMBER_CURRENT(gbm_surface_v0, _abi0, flags);
395 CHECK_MEMBER_CURRENT(gbm_surface_v0, _abi0, modifiers);
396 CHECK_MEMBER_CURRENT(gbm_surface_v0, _abi0, count);
397
398 /* Size of ABI-versioned substructures verified by above member checks */
399 CHECK_SIZE_CURRENT (gbm_surface, _abi0);
400
401
402 /* Check current gbm_backend ABI against gbm_backend_abi0 */
403 CHECK_MEMBER_CURRENT_NO_TYPE(gbm_backend, _abi0, v0);
404
405 CHECK_MEMBER_CURRENT(gbm_backend_v0, _abi0, backend_version);
406 CHECK_MEMBER_CURRENT(gbm_backend_v0, _abi0, backend_name);
407 CHECK_MEMBER_CURRENT(gbm_backend_v0, _abi0, create_device);
408
409 /* Size of ABI-versioned substructures verified by above member checks */
410 CHECK_SIZE_CURRENT (gbm_backend, _abi0);
411
412
413 /* Check current gbm_core ABI against gbm_core_abi0 */
414 CHECK_MEMBER_CURRENT_NO_TYPE(gbm_core, _abi0, v0);
415
416 CHECK_MEMBER_CURRENT(gbm_core_v0, _abi0, core_version);
417 CHECK_MEMBER_CURRENT(gbm_core_v0, _abi0, format_canonicalize);
418
419 /* Size of ABI-versioned substructures verified by above member checks */
420 CHECK_SIZE_CURRENT (gbm_core, _abi0);
421
422
423 CHECK_PROC_CURRENT (GBM_GET_BACKEND_PROC_PTR, _abi0);
424
425 return 0;
426 }
427