diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2022-02-24 01:57:18 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2022-02-24 01:57:18 +0000 |
commit | b24b5b9049e889ee4eb39b565bcc8d48bd45ab48 (patch) | |
tree | 658ca4e6b41655f49463c85edbaeda48979c394c /lib/mesa/src/gbm | |
parent | 57768bbb154c2879d34ec20e401b19472e77aaf7 (diff) |
Import Mesa 21.3.7
Diffstat (limited to 'lib/mesa/src/gbm')
-rw-r--r-- | lib/mesa/src/gbm/gbm-symbols.txt | 2 | ||||
-rw-r--r-- | lib/mesa/src/gbm/main/backend.c | 200 | ||||
-rw-r--r-- | lib/mesa/src/gbm/main/backend.h | 3 | ||||
-rw-r--r-- | lib/mesa/src/gbm/main/gbm_abi_check.c | 426 | ||||
-rw-r--r-- | lib/mesa/src/gbm/main/gbm_backend_abi.h | 305 |
5 files changed, 903 insertions, 33 deletions
diff --git a/lib/mesa/src/gbm/gbm-symbols.txt b/lib/mesa/src/gbm/gbm-symbols.txt index 8cdbc21fc..d3c99b0c3 100644 --- a/lib/mesa/src/gbm/gbm-symbols.txt +++ b/lib/mesa/src/gbm/gbm-symbols.txt @@ -1,5 +1,6 @@ gbm_bo_create gbm_bo_create_with_modifiers +gbm_bo_create_with_modifiers2 gbm_bo_destroy gbm_bo_get_bpp gbm_bo_get_device @@ -30,6 +31,7 @@ gbm_device_is_format_supported gbm_format_get_name gbm_surface_create gbm_surface_create_with_modifiers +gbm_surface_create_with_modifiers2 gbm_surface_destroy gbm_surface_has_free_buffers gbm_surface_lock_front_buffer diff --git a/lib/mesa/src/gbm/main/backend.c b/lib/mesa/src/gbm/main/backend.c index 37ec9c16f..974d0a76a 100644 --- a/lib/mesa/src/gbm/main/backend.c +++ b/lib/mesa/src/gbm/main/backend.c @@ -1,5 +1,6 @@ /* * Copyright © 2011 Intel Corporation + * Copyright © 2021 NVIDIA Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -23,6 +24,7 @@ * * Authors: * Benjamin Franzke <benjaminfranzke@googlemail.com> + * James Jones <jajones@nvidia.com> */ #include <stdio.h> @@ -30,75 +32,207 @@ #include <stdlib.h> #include <string.h> #include <limits.h> +#include <assert.h> +#include <dlfcn.h> +#include <xf86drm.h> +#include "loader.h" #include "backend.h" #define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0])) +#define VER_MIN(a, b) ((a) < (b) ? (a) : (b)) extern const struct gbm_backend gbm_dri_backend; -struct backend_desc { +struct gbm_backend_desc { const char *name; - const struct gbm_backend *builtin; + const struct gbm_backend *backend; + void *lib; }; -static const struct backend_desc backends[] = { - { "gbm_dri.so", &gbm_dri_backend }, +static const struct gbm_backend_desc builtin_backends[] = { + { "dri", &gbm_dri_backend }, }; -static const void * -load_backend(const struct backend_desc *backend) +#define BACKEND_LIB_SUFFIX "_gbm" +static const char *backend_search_path_vars[] = { + "GBM_BACKENDS_PATH", + NULL +}; + +static void +free_backend_desc(const struct gbm_backend_desc *backend_desc) { - const void *init = NULL; + assert(backend_desc->lib); - if (backend == NULL) + dlclose(backend_desc->lib); + free((void *)backend_desc->name); + free((void *)backend_desc); +} + +static struct gbm_backend_desc * +create_backend_desc(const char *name, + const struct gbm_backend *backend, + void *lib) +{ + struct gbm_backend_desc *new_desc = calloc(1, sizeof(*new_desc)); + + if (!new_desc) return NULL; - if (backend->builtin) { - init = backend->builtin; + new_desc->name = strdup(name); + + if (!new_desc->name) { + free(new_desc); + return NULL; } - return init; + new_desc->backend = backend; + new_desc->lib = lib; + + return new_desc; +} + +static struct gbm_device * +backend_create_device(const struct gbm_backend_desc *bd, int fd) +{ + const uint32_t abi_ver = VER_MIN(GBM_BACKEND_ABI_VERSION, + bd->backend->v0.backend_version); + struct gbm_device *dev = bd->backend->v0.create_device(fd, abi_ver); + + if (dev) { + if (abi_ver != dev->v0.backend_version) { + _gbm_device_destroy(dev); + return NULL; + } + dev->v0.backend_desc = bd; + } + + return dev; +} + +static struct gbm_device * +load_backend(void *lib, int fd, const char *name) +{ + struct gbm_device *dev = NULL; + struct gbm_backend_desc *backend_desc; + const struct gbm_backend *gbm_backend; + GBM_GET_BACKEND_PROC_PTR get_backend; + + get_backend = dlsym(lib, GBM_GET_BACKEND_PROC_NAME); + + if (!get_backend) + goto fail; + + gbm_backend = get_backend(&gbm_core); + backend_desc = create_backend_desc(name, gbm_backend, lib); + + if (!backend_desc) + goto fail; + + dev = backend_create_device(backend_desc, fd); + + if (!dev) + free_backend_desc(backend_desc); + + return dev; + +fail: + dlclose(lib); + return NULL; } -static const struct backend_desc * -find_backend(const char *name) +static struct gbm_device * +find_backend(const char *name, int fd) { - const struct backend_desc *backend = NULL; + struct gbm_device *dev = NULL; + const struct gbm_backend_desc *bd; + void *lib; unsigned i; - for (i = 0; i < ARRAY_SIZE(backends); ++i) { - if (strcmp(backends[i].name, name) == 0) { - backend = &backends[i]; + for (i = 0; i < ARRAY_SIZE(builtin_backends); ++i) { + bd = &builtin_backends[i]; + + if (name && strcmp(bd->name, name)) + continue; + + dev = backend_create_device(bd, fd); + + if (dev) break; - } } - return backend; + if (name && !dev) { + lib = loader_open_driver_lib(name, BACKEND_LIB_SUFFIX, + backend_search_path_vars, + DEFAULT_BACKENDS_PATH, + true); + + if (lib) + dev = load_backend(lib, fd, name); + } + + return dev; } -struct gbm_device * -_gbm_create_device(int fd) +static struct gbm_device * +override_backend(int fd) { - const struct gbm_backend *backend = NULL; struct gbm_device *dev = NULL; - unsigned i; const char *b; b = getenv("GBM_BACKEND"); if (b) - backend = load_backend(find_backend(b)); + dev = find_backend(b, fd); - if (backend) - dev = backend->create_device(fd); + return dev; +} - for (i = 0; i < ARRAY_SIZE(backends) && dev == NULL; ++i) { - backend = load_backend(&backends[i]); - if (backend == NULL) - continue; +static struct gbm_device * +backend_from_driver_name(int fd) +{ + struct gbm_device *dev = NULL; + drmVersionPtr v = drmGetVersion(fd); + void *lib; + + if (!v) + return NULL; + + lib = loader_open_driver_lib(v->name, BACKEND_LIB_SUFFIX, + backend_search_path_vars, + DEFAULT_BACKENDS_PATH, + false); + + if (lib) + dev = load_backend(lib, fd, v->name); + + drmFreeVersion(v); + + return dev; +} + +struct gbm_device * +_gbm_create_device(int fd) +{ + struct gbm_device *dev; + + dev = override_backend(fd); + + if (!dev) + dev = backend_from_driver_name(fd); + + if (!dev) + dev = find_backend(NULL, fd); - dev = backend->create_device(fd); - } - return dev; } + +void +_gbm_device_destroy(struct gbm_device *gbm) +{ + const struct gbm_backend_desc *backend_desc = gbm->v0.backend_desc; + gbm->v0.destroy(gbm); + + if (backend_desc && backend_desc->lib) + free_backend_desc(backend_desc); +} diff --git a/lib/mesa/src/gbm/main/backend.h b/lib/mesa/src/gbm/main/backend.h index 4a6437503..325c4123f 100644 --- a/lib/mesa/src/gbm/main/backend.h +++ b/lib/mesa/src/gbm/main/backend.h @@ -33,4 +33,7 @@ struct gbm_device * _gbm_create_device(int fd); +void +_gbm_device_destroy(struct gbm_device *gbm); + #endif diff --git a/lib/mesa/src/gbm/main/gbm_abi_check.c b/lib/mesa/src/gbm/main/gbm_abi_check.c new file mode 100644 index 000000000..feca0998d --- /dev/null +++ b/lib/mesa/src/gbm/main/gbm_abi_check.c @@ -0,0 +1,426 @@ +/* + * Copyright © 2021 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "gbm_backend_abi.h" /* Current GBM backend ABI implementation */ + +#include <stddef.h> /* offsetof */ +#include <stdio.h> /* printf */ + +/* + * The following are previous implementations of the structures defined in + * gbm_backend_abi.h, with their ABI version appended. + * + * DO NOT EVER CHANGE EXISTING DEFINITIONS HERE! + * + * Changing them implies breaking the GBM backend ABI. Instead, to extend the + * ABI, in gbm_backend_abi.h: + * + * -Add a new versioned struct + * -Append it to the associated top-level object's struct + * -Increment GBM_BACKEND_ABI_VERSION + * + * Then, here: + * + * -Add a new block of definitions below for the new ABI content + * -Add a new block of checks in main() + */ + +/* + * From: Simon Ser - "gbm: assume USE_SCANOUT in create_with_modifiers" + * + * Note: ABI 1 is identical to ABI 0, except gbm_device_v0.bo_create can + * provide both modifiers and usage. + */ +#define GBM_BACKEND_ABI_VERSION_abi0 1 +struct gbm_device_v0_abi0 { + const struct gbm_backend_desc *backend_desc; + uint32_t backend_version; + int fd; + const char *name; + void (*destroy)(struct gbm_device *gbm); + int (*is_format_supported)(struct gbm_device *gbm, + uint32_t format, + uint32_t usage); + int (*get_format_modifier_plane_count)(struct gbm_device *device, + uint32_t format, + uint64_t modifier); + struct gbm_bo *(*bo_create)(struct gbm_device *gbm, + uint32_t width, uint32_t height, + uint32_t format, + uint32_t usage, + const uint64_t *modifiers, + const unsigned int count); + struct gbm_bo *(*bo_import)(struct gbm_device *gbm, uint32_t type, + void *buffer, uint32_t usage); + void *(*bo_map)(struct gbm_bo *bo, + uint32_t x, uint32_t y, + uint32_t width, uint32_t height, + uint32_t flags, uint32_t *stride, + void **map_data); + void (*bo_unmap)(struct gbm_bo *bo, void *map_data); + int (*bo_write)(struct gbm_bo *bo, const void *buf, size_t data); + int (*bo_get_fd)(struct gbm_bo *bo); + int (*bo_get_planes)(struct gbm_bo *bo); + union gbm_bo_handle (*bo_get_handle)(struct gbm_bo *bo, int plane); + int (*bo_get_plane_fd)(struct gbm_bo *bo, int plane); + uint32_t (*bo_get_stride)(struct gbm_bo *bo, int plane); + uint32_t (*bo_get_offset)(struct gbm_bo *bo, int plane); + uint64_t (*bo_get_modifier)(struct gbm_bo *bo); + void (*bo_destroy)(struct gbm_bo *bo); + struct gbm_surface *(*surface_create)(struct gbm_device *gbm, + uint32_t width, uint32_t height, + uint32_t format, uint32_t flags, + const uint64_t *modifiers, + const unsigned count); + struct gbm_bo *(*surface_lock_front_buffer)(struct gbm_surface *surface); + void (*surface_release_buffer)(struct gbm_surface *surface, + struct gbm_bo *bo); + int (*surface_has_free_buffers)(struct gbm_surface *surface); + void (*surface_destroy)(struct gbm_surface *surface); +}; + +struct gbm_device_abi0 { + /* Hack to make a gbm_device detectable by its first element. */ + struct gbm_device *(*dummy)(int); + struct gbm_device_v0_abi0 v0; +}; + +/** + * GBM buffer object interface corresponding to GBM_BACKEND_ABI_VERSION = 0 + * + * DO NOT MODIFY THIS STRUCT. Instead, introduce a gbm_bo_v1, increment + * GBM_BACKEND_ABI_VERSION, and append gbm_bo_v1 to gbm_bo. + */ +struct gbm_bo_v0_abi0 { + uint32_t width; + uint32_t height; + uint32_t stride; + uint32_t format; + union gbm_bo_handle handle; + void *user_data; + void (*destroy_user_data)(struct gbm_bo *, void *); +}; + +/** + * The allocated buffer object. + * + * The members in this structure should not be accessed directly. + * + * To modify this structure, introduce a new gbm_bo_v<N> structure, add it to + * the end of this structure, and increment GBM_BACKEND_ABI_VERSION. + */ +struct gbm_bo_abi0 { + struct gbm_device *gbm; + struct gbm_bo_v0_abi0 v0; +}; + +/** + * GBM surface interface corresponding to GBM_BACKEND_ABI_VERSION = 0 + * + * DO NOT MODIFY THIS STRUCT. Instead, introduce a gbm_surface_v1, increment + * GBM_BACKEND_ABI_VERSION, and append gbm_surface_v1 to gbm_surface. + */ +struct gbm_surface_v0_abi0 { + uint32_t width; + uint32_t height; + uint32_t format; + uint32_t flags; + struct { + uint64_t *modifiers; + unsigned count; + }; +}; + +/** + * An allocated GBM surface. + * + * To modify this structure, introduce a new gbm_surface_v<N> structure, add it + * to the end of this structure, and increment GBM_BACKEND_ABI_VERSION. + */ +struct gbm_surface_abi0 { + struct gbm_device *gbm; + struct gbm_surface_v0_abi0 v0; +}; + +/** + * GBM backend interfaces corresponding to GBM_BACKEND_ABI_VERSION = 0 + * + * DO NOT MODIFY THIS STRUCT. Instead, introduce a gbm_backend_v1, increment + * GBM_BACKEND_ABI_VERSION, append gbm_backend_v1 to gbm_backend. + */ +struct gbm_backend_v0_abi0 { + /** + * The version of the GBM backend interface supported by this backend. This + * is set by the backend itself, and may be greater or less than the version + * supported by the loader. It is the responsibility of the GBM loader to + * respect this version when accessing fields in this structure. + */ + uint32_t backend_version; + + const char *backend_name; + struct gbm_device *(*create_device)(int fd, uint32_t gbm_backend_version); +}; + +/** + * The interface exposed by an external GBM backend. + * + * To modify this structure, introduce a new gbm_backend_v<N> structure, add it + * to the end of this structure, and increment GBM_BACKEND_ABI_VERSION. + */ +struct gbm_backend_abi0 { + struct gbm_backend_v0_abi0 v0; +}; + +/** + * GBM interfaces exposed to GBM backends at GBM_BACKEND_ABI_VERSION >= 0 + * + * DO NOT MODIFY THIS STRUCT. Instead, introduce a gbm_core_v1, increment + * GBM_BACKEND_ABI_VERSION, and append gbm_core_v1 to gbm_backend. + */ +struct gbm_core_v0_abi0 { + /** + * The version of the GBM backend interface supported by the GBM loader. This + * is set by the loader, and may be greater or less than the version + * supported by a given backend. It is the responsibility of the backend to + * respect this version when accessing fields in this structure and other + * structures allocated or modified by the loader. + */ + uint32_t core_version; + + uint32_t (*format_canonicalize)(uint32_t gbm_format); +}; + +/** + * The interface exposed by the GBM core/loader code to GBM backends. + * + * To modify this structure, introduce a new gbm_core_v<N> structure, add it + * to the end of this structure, and increment GBM_BACKEND_ABI_VERSION. + */ +struct gbm_core_abi0 { + struct gbm_core_v0_abi0 v0; +}; + +typedef const struct gbm_backend *(*GBM_GET_BACKEND_PROC_PTR_abi0)(const struct gbm_core *gbm_core); + +/* + * Structure/member ABI-checking helper macros + */ +#define MEMBER_SIZE(type, member) sizeof(((type *)0)->member) + +#define CHECK_RENAMED_MEMBER_BASE(type, a_ver, b_ver, a_member, b_member) \ + do { \ + if (offsetof(struct type ## a_ver, a_member) != \ + offsetof(struct type ## b_ver, b_member)) { \ + printf("Backards incompatible change detected!\n " \ + "offsetof(struct " #type #a_ver "::" #a_member ") != " \ + "offsetof(struct " #type #b_ver "::" #b_member ")\n"); \ + return 1; \ + } \ + \ + if (MEMBER_SIZE(struct type ## a_ver, a_member) != \ + MEMBER_SIZE(struct type ## b_ver, b_member)) { \ + printf("Backards incompatible change detected!\n " \ + "MEMBER_SIZE(struct " #type #a_ver "::" #a_member ") != " \ + "MEMBER_SIZE(struct " #type #b_ver "::" #b_member ")\n"); \ + return 1; \ + } \ + } while (0) + +#define CHECK_RENAMED_MEMBER_TYPE(type, a_ver, b_ver, a_member, b_member) \ + do { \ + /* Compile-time type compatibility check */ \ + struct type ## a_ver a; \ + struct type ## b_ver b = {0}; \ + a.a_member = b.b_member; \ + (void)a; \ + } while (0) + +#define CHECK_RENAMED_MEMBER(type, a_ver, b_ver, a_member, b_member) \ + do { \ + CHECK_RENAMED_MEMBER_BASE(type, a_ver, b_ver, a_member, b_member); \ + CHECK_RENAMED_MEMBER_TYPE(type, a_ver, b_ver, a_member, b_member); \ + } while (0) +#define CHECK_RENAMED_MEMBER_NO_TYPE(type, a_ver, b_ver, a_member, b_member) \ + CHECK_RENAMED_MEMBER_BASE(type, a_ver, b_ver, a_member, b_member); + +#define CHECK_MEMBER(type, a_ver, b_ver, member) \ + CHECK_RENAMED_MEMBER(type, a_ver, b_ver, member, member) +#define CHECK_MEMBER_NO_TYPE(type, a_ver, b_ver, member) \ + CHECK_RENAMED_MEMBER_NO_TYPE(type, a_ver, b_ver, member, member) +#define CHECK_MEMBER_CURRENT(type, a_ver, member) \ + CHECK_MEMBER(type, a_ver,, member) +#define CHECK_MEMBER_CURRENT_NO_TYPE(type, a_ver, member) \ + CHECK_MEMBER_NO_TYPE(type, a_ver,, member) + +#define CHECK_SIZE(type, a_ver, b_ver) \ + do { \ + if (sizeof(struct type ## a_ver) > \ + sizeof(struct type ## b_ver)) { \ + printf("Backards incompatible change detected!\n " \ + "sizeof(struct " #type #a_ver ") > " \ + "sizeof(struct " #type #b_ver ")\n"); \ + return 1; \ + } \ + } while (0) + +#define CHECK_SIZE_CURRENT(type, a_ver) \ + do { \ + if (sizeof(struct type ## a_ver) != \ + sizeof(struct type)) { \ + printf("Backards incompatible change detected!\n " \ + "sizeof(struct " #type #a_ver ") != " \ + "sizeof(struct " #type ")\n"); \ + return 1; \ + } \ + } while (0) + +#define CHECK_VERSION(a_ver, b_ver) \ + do { \ + if ((GBM_BACKEND_ABI_VERSION ## a_ver) >= \ + (GBM_BACKEND_ABI_VERSION ## b_ver)) { \ + printf("Backards incompatible change detected!\n " \ + "GBM_BACKEND_ABI_VERSION" #a_ver " >= " \ + "GBM_BACKEND_ABI_VERSION" #b_ver "\n"); \ + return 1; \ + } \ + } while (0) + +#define CHECK_VERSION_CURRENT(a_ver) \ + do { \ + if ((GBM_BACKEND_ABI_VERSION ## a_ver) != \ + (GBM_BACKEND_ABI_VERSION)) { \ + printf("Backards incompatible change detected!\n " \ + "GBM_BACKEND_ABI_VERSION" #a_ver " != " \ + "GBM_BACKEND_ABI_VERSION\n"); \ + return 1; \ + } \ + } while (0) + +#define CHECK_PROC(proc, a_ver, b_ver) \ + do { \ + proc ## a_ver a; \ + proc ## b_ver b = NULL; \ + a = b; \ + (void)a; \ + } while (0) + +#define CHECK_PROC_CURRENT(proc, a_ver) \ + CHECK_PROC(proc, a_ver,) + +int main(int argc, char **argv) +{ + /********************************************/ + /*** Compare Current ABI to ABI version 0 ***/ + /********************************************/ + + /* Check current gbm_device ABI against gbm_device_abi0*/ + CHECK_MEMBER_CURRENT(gbm_device, _abi0, dummy); + CHECK_MEMBER_CURRENT_NO_TYPE(gbm_device, _abi0, v0); + + CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, backend_desc); + CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, backend_version); + CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, fd); + CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, name); + CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, destroy); + CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, is_format_supported); + CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, get_format_modifier_plane_count); + CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_create); + CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_import); + CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_map); + CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_unmap); + CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_write); + CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_get_fd); + CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_get_planes); + CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_get_handle); + CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_get_plane_fd); + CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_get_stride); + CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_get_offset); + CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_get_modifier); + CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, bo_destroy); + CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, surface_create); + CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, surface_lock_front_buffer); + CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, surface_release_buffer); + CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, surface_has_free_buffers); + CHECK_MEMBER_CURRENT(gbm_device_v0, _abi0, surface_destroy); + + /* Size of ABI-versioned substructures verified by above member checks */ + CHECK_SIZE_CURRENT (gbm_device, _abi0); + + + /* Check current gbm_bo ABI against gbm_bo_abi0*/ + CHECK_MEMBER_CURRENT(gbm_bo, _abi0, gbm); + CHECK_MEMBER_CURRENT_NO_TYPE(gbm_bo, _abi0, v0); + + CHECK_MEMBER_CURRENT(gbm_bo_v0, _abi0, width); + CHECK_MEMBER_CURRENT(gbm_bo_v0, _abi0, height); + CHECK_MEMBER_CURRENT(gbm_bo_v0, _abi0, stride); + CHECK_MEMBER_CURRENT(gbm_bo_v0, _abi0, format); + CHECK_MEMBER_CURRENT(gbm_bo_v0, _abi0, handle); + CHECK_MEMBER_CURRENT(gbm_bo_v0, _abi0, user_data); + CHECK_MEMBER_CURRENT(gbm_bo_v0, _abi0, destroy_user_data); + + /* Size of ABI-versioned substructures verified by above member checks */ + CHECK_SIZE_CURRENT (gbm_bo, _abi0); + + + /* Check current gbm_surface ABI against gbm_surface_abi0 */ + CHECK_MEMBER_CURRENT(gbm_surface, _abi0, gbm); + CHECK_MEMBER_CURRENT_NO_TYPE(gbm_surface, _abi0, v0); + + CHECK_MEMBER_CURRENT(gbm_surface_v0, _abi0, width); + CHECK_MEMBER_CURRENT(gbm_surface_v0, _abi0, height); + CHECK_MEMBER_CURRENT(gbm_surface_v0, _abi0, format); + CHECK_MEMBER_CURRENT(gbm_surface_v0, _abi0, flags); + CHECK_MEMBER_CURRENT(gbm_surface_v0, _abi0, modifiers); + CHECK_MEMBER_CURRENT(gbm_surface_v0, _abi0, count); + + /* Size of ABI-versioned substructures verified by above member checks */ + CHECK_SIZE_CURRENT (gbm_surface, _abi0); + + + /* Check current gbm_backend ABI against gbm_backend_abi0 */ + CHECK_MEMBER_CURRENT_NO_TYPE(gbm_backend, _abi0, v0); + + CHECK_MEMBER_CURRENT(gbm_backend_v0, _abi0, backend_version); + CHECK_MEMBER_CURRENT(gbm_backend_v0, _abi0, backend_name); + CHECK_MEMBER_CURRENT(gbm_backend_v0, _abi0, create_device); + + /* Size of ABI-versioned substructures verified by above member checks */ + CHECK_SIZE_CURRENT (gbm_backend, _abi0); + + + /* Check current gbm_core ABI against gbm_core_abi0 */ + CHECK_MEMBER_CURRENT_NO_TYPE(gbm_core, _abi0, v0); + + CHECK_MEMBER_CURRENT(gbm_core_v0, _abi0, core_version); + CHECK_MEMBER_CURRENT(gbm_core_v0, _abi0, format_canonicalize); + + /* Size of ABI-versioned substructures verified by above member checks */ + CHECK_SIZE_CURRENT (gbm_core, _abi0); + + + CHECK_PROC_CURRENT (GBM_GET_BACKEND_PROC_PTR, _abi0); + + return 0; +} diff --git a/lib/mesa/src/gbm/main/gbm_backend_abi.h b/lib/mesa/src/gbm/main/gbm_backend_abi.h new file mode 100644 index 000000000..222ce3404 --- /dev/null +++ b/lib/mesa/src/gbm/main/gbm_backend_abi.h @@ -0,0 +1,305 @@ +/* + * Copyright © 2011 Intel Corporation + * Copyright © 2021 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Benjamin Franzke <benjaminfranzke@googlemail.com> + * James Jones <jajones@nvidia.com> + */ + +#ifndef GBM_BACKEND_ABI_H_ +#define GBM_BACKEND_ABI_H_ + +#include "gbm.h" + +/** + * \file gbm_backend_abi.h + * \brief ABI between the GBM loader and its backends + */ + +struct gbm_backend_desc; + +/** + * The GBM backend interface version defined by this file. + * + * The GBM device interface version must be incremented whenever the structures + * defined in this file are modified. To preserve ABI compatibility with + * backends that support only older versions, modifications to this file must + * consist only of appending new fields to the end of the structures defined in + * it, defining new structures, or declaring new exported functions or global + * variables. + * + * Note this version applies to ALL structures in this file, not just the core, + * backend, and device structures which contain it explicitly. Buffer objects, + * surfaces, and any other new structures introduced to this file are also part + * of the backend ABI. The ABI version of an instance of any object in this file + * is defined as the minimum of the version of the backend associated with the + * object instance and the loader's core object version. Hence, any new objects + * added to this file should contain either a reference to an existing object + * defined here, or an explicit version field. + * + * A few examples of object versions: + * + * Backend ABI version: 0 + * Core ABI version: 3 + * ABI version of a device created by the backend: 0 + * + * Backend ABI version: 2 + * Core ABI version: 1 + * ABI version of a surface created by a device from the backend: 1 + * + * Backend ABI version: 4 + * Core ABI version: 4 + * ABI version of a buffer object created by a device from the backend: 4 + */ +#define GBM_BACKEND_ABI_VERSION 1 + +/** + * GBM device interface corresponding to GBM_BACKEND_ABI_VERSION = 0 + * + * DO NOT MODIFY THIS STRUCT. Instead, introduce a gbm_bo_v1, increment + * GBM_BACKEND_ABI_VERSION, and append gbm_bo_v1 to gbm_bo. + */ +struct gbm_device_v0 { + const struct gbm_backend_desc *backend_desc; + + /** + * The version of the GBM backend interface supported by this device and its + * child objects. This may be less than the maximum version supported by the + * GBM loader if the device was created by an older backend, or less than the + * maximum version supported by the backend if the device was created by an + * older loader. In other words, this will be: + * + * MIN(backend GBM interface version, loader GBM interface version) + * + * It is the backend's responsibility to assign this field the value passed + * in by the GBM loader to the backend's create_device function. The GBM + * loader will pre-clamp the value based on the loader version and the + * version reported by the backend in its gbm_backend_v0::backend_version + * field. It is the loader's responsibility to respect this version when + * directly accessing a device instance or any child objects instantiated by + * a device instance. + */ + uint32_t backend_version; + + int fd; + const char *name; + + void (*destroy)(struct gbm_device *gbm); + int (*is_format_supported)(struct gbm_device *gbm, + uint32_t format, + uint32_t usage); + int (*get_format_modifier_plane_count)(struct gbm_device *device, + uint32_t format, + uint64_t modifier); + + /** + * Since version 1, usage is properly populated when modifiers are + * supplied. Version 0 always set usage to 0 in this case. + */ + struct gbm_bo *(*bo_create)(struct gbm_device *gbm, + uint32_t width, uint32_t height, + uint32_t format, + uint32_t usage, + const uint64_t *modifiers, + const unsigned int count); + struct gbm_bo *(*bo_import)(struct gbm_device *gbm, uint32_t type, + void *buffer, uint32_t usage); + void *(*bo_map)(struct gbm_bo *bo, + uint32_t x, uint32_t y, + uint32_t width, uint32_t height, + uint32_t flags, uint32_t *stride, + void **map_data); + void (*bo_unmap)(struct gbm_bo *bo, void *map_data); + int (*bo_write)(struct gbm_bo *bo, const void *buf, size_t data); + int (*bo_get_fd)(struct gbm_bo *bo); + int (*bo_get_planes)(struct gbm_bo *bo); + union gbm_bo_handle (*bo_get_handle)(struct gbm_bo *bo, int plane); + int (*bo_get_plane_fd)(struct gbm_bo *bo, int plane); + uint32_t (*bo_get_stride)(struct gbm_bo *bo, int plane); + uint32_t (*bo_get_offset)(struct gbm_bo *bo, int plane); + uint64_t (*bo_get_modifier)(struct gbm_bo *bo); + void (*bo_destroy)(struct gbm_bo *bo); + + /** + * Since version 1, flags are properly populated when modifiers are + * supplied. Version 0 always set flags to 0 in this case. + */ + struct gbm_surface *(*surface_create)(struct gbm_device *gbm, + uint32_t width, uint32_t height, + uint32_t format, uint32_t flags, + const uint64_t *modifiers, + const unsigned count); + struct gbm_bo *(*surface_lock_front_buffer)(struct gbm_surface *surface); + void (*surface_release_buffer)(struct gbm_surface *surface, + struct gbm_bo *bo); + int (*surface_has_free_buffers)(struct gbm_surface *surface); + void (*surface_destroy)(struct gbm_surface *surface); +}; + +/** + * The device used for the memory allocation. + * + * The members of this structure should be not accessed directly + * + * To modify this structure, introduce a new gbm_device_v<N> structure, add it + * to the end of this structure, and increment GBM_BACKEND_ABI_VERSION. + */ +struct gbm_device { + /* Hack to make a gbm_device detectable by its first element. */ + struct gbm_device *(*dummy)(int); + struct gbm_device_v0 v0; +}; + +/** + * GBM buffer object interface corresponding to GBM_BACKEND_ABI_VERSION = 0 + * + * DO NOT MODIFY THIS STRUCT. Instead, introduce a gbm_bo_v1, increment + * GBM_BACKEND_ABI_VERSION, and append gbm_bo_v1 to gbm_bo. + */ +struct gbm_bo_v0 { + uint32_t width; + uint32_t height; + uint32_t stride; + uint32_t format; + union gbm_bo_handle handle; + void *user_data; + void (*destroy_user_data)(struct gbm_bo *, void *); +}; + +/** + * The allocated buffer object. + * + * The members in this structure should not be accessed directly. + * + * To modify this structure, introduce a new gbm_bo_v<N> structure, add it to + * the end of this structure, and increment GBM_BACKEND_ABI_VERSION. + */ +struct gbm_bo { + struct gbm_device *gbm; + struct gbm_bo_v0 v0; +}; + +/** + * GBM surface interface corresponding to GBM_BACKEND_ABI_VERSION = 0 + * + * DO NOT MODIFY THIS STRUCT. Instead, introduce a gbm_surface_v1, increment + * GBM_BACKEND_ABI_VERSION, and append gbm_surface_v1 to gbm_surface. + */ +struct gbm_surface_v0 { + uint32_t width; + uint32_t height; + uint32_t format; + uint32_t flags; + struct { + uint64_t *modifiers; + unsigned count; + }; +}; + +/** + * An allocated GBM surface. + * + * To modify this structure, introduce a new gbm_surface_v<N> structure, add it + * to the end of this structure, and increment GBM_BACKEND_ABI_VERSION. + */ +struct gbm_surface { + struct gbm_device *gbm; + struct gbm_surface_v0 v0; +}; + +/** + * GBM backend interfaces corresponding to GBM_BACKEND_ABI_VERSION = 0 + * + * DO NOT MODIFY THIS STRUCT. Instead, introduce a gbm_backend_v1, increment + * GBM_BACKEND_ABI_VERSION, append gbm_backend_v1 to gbm_backend. + */ +struct gbm_backend_v0 { + /** + * The version of the GBM backend interface supported by this backend. This + * is set by the backend itself, and may be greater or less than the version + * supported by the loader. It is the responsibility of the GBM loader to + * respect this version when accessing fields in this structure. + */ + uint32_t backend_version; + + const char *backend_name; + struct gbm_device *(*create_device)(int fd, uint32_t gbm_backend_version); +}; + +/** + * The interface exposed by an external GBM backend. + * + * To modify this structure, introduce a new gbm_backend_v<N> structure, add it + * to the end of this structure, and increment GBM_BACKEND_ABI_VERSION. + */ +struct gbm_backend { + struct gbm_backend_v0 v0; +}; + +/** + * GBM interfaces exposed to GBM backends at GBM_BACKEND_ABI_VERSION >= 0 + * + * DO NOT MODIFY THIS STRUCT. Instead, introduce a gbm_core_v1, increment + * GBM_BACKEND_ABI_VERSION, and append gbm_core_v1 to gbm_backend. + */ +struct gbm_core_v0 { + /** + * The version of the GBM backend interface supported by the GBM loader. This + * is set by the loader, and may be greater or less than the version + * supported by a given backend. It is the responsibility of the backend to + * respect this version when accessing fields in this structure and other + * structures allocated or modified by the loader. + */ + uint32_t core_version; + + uint32_t (*format_canonicalize)(uint32_t gbm_format); +}; + +/** + * The interface exposed by the GBM core/loader code to GBM backends. + * + * To modify this structure, introduce a new gbm_core_v<N> structure, add it + * to the end of this structure, and increment GBM_BACKEND_ABI_VERSION. + */ +struct gbm_core { + struct gbm_core_v0 v0; +}; + +/** + * The entrypoint an external GBM backend exports. + * + * Prior to creating any devices using the backend, GBM will look up and call + * this function to request the backend's interface and convey the loader's + * version and exported interface to the backend. + * + * DO NOT MODIFY THIS FUNCTION NAME OR PROTOTYPE. It must remain unchanged to + * preserve backwards compatibility with existing GBM backends. + */ +#define GBM_GET_BACKEND_PROC gbmint_get_backend +#define _GBM_MKSTRX(s) _GBM_MKSTR(s) +#define _GBM_MKSTR(s) #s +#define GBM_GET_BACKEND_PROC_NAME _GBM_MKSTRX(GBM_GET_BACKEND_PROC) +typedef const struct gbm_backend *(*GBM_GET_BACKEND_PROC_PTR)(const struct gbm_core *gbm_core); + +#endif |