summaryrefslogtreecommitdiff
path: root/lib/mesa/src/gbm
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2022-02-24 01:57:18 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2022-02-24 01:57:18 +0000
commitb24b5b9049e889ee4eb39b565bcc8d48bd45ab48 (patch)
tree658ca4e6b41655f49463c85edbaeda48979c394c /lib/mesa/src/gbm
parent57768bbb154c2879d34ec20e401b19472e77aaf7 (diff)
Import Mesa 21.3.7
Diffstat (limited to 'lib/mesa/src/gbm')
-rw-r--r--lib/mesa/src/gbm/gbm-symbols.txt2
-rw-r--r--lib/mesa/src/gbm/main/backend.c200
-rw-r--r--lib/mesa/src/gbm/main/backend.h3
-rw-r--r--lib/mesa/src/gbm/main/gbm_abi_check.c426
-rw-r--r--lib/mesa/src/gbm/main/gbm_backend_abi.h305
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