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 
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