gbm: split the DRI backend into a separate library and unify backend handling

This does a few things:
1. Applications linked against a non-matching GBM can load the right version of the backend
   from the environment, avoiding GBM/Mesa version mismatches in many cases
2. Distros that want to split off libgbm into a separate package from the actual drivers
   get to not ship 40MB of libgallium_dri
3. The loader logic becomes way less complex

See also: https://github.com/NixOS/nixpkgs/pull/338109 for original rationale.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/31074>
This commit is contained in:
K900 2024-09-07 13:15:31 +03:00 committed by Marge Bot
parent 67bcdbf4a1
commit 514df444eb
4 changed files with 58 additions and 106 deletions

View file

@ -53,11 +53,15 @@
#include "pipe/p_screen.h"
#include "dri_screen.h"
#include "gbm_backend_abi.h"
/* For importing wl_buffer */
#if HAVE_WAYLAND_PLATFORM
#include "wayland-drm.h"
#endif
static const struct gbm_core *core;
static GLboolean
dri_validate_egl_image(void *image, void *data)
{
@ -324,7 +328,7 @@ static const struct gbm_dri_visual gbm_dri_visuals_table[] = {
static int
gbm_format_to_dri_format(uint32_t gbm_format)
{
gbm_format = gbm_core.v0.format_canonicalize(gbm_format);
gbm_format = core->v0.format_canonicalize(gbm_format);
for (size_t i = 0; i < ARRAY_SIZE(gbm_dri_visuals_table); i++) {
if (gbm_dri_visuals_table[i].gbm_format == gbm_format)
return gbm_dri_visuals_table[i].dri_image_format;
@ -344,7 +348,7 @@ gbm_dri_is_format_supported(struct gbm_device *gbm,
if ((usage & GBM_BO_USE_CURSOR) && (usage & GBM_BO_USE_RENDERING))
return 0;
format = gbm_core.v0.format_canonicalize(format);
format = core->v0.format_canonicalize(format);
if (gbm_format_to_dri_format(format) == 0)
return 0;
@ -380,7 +384,7 @@ gbm_dri_get_format_modifier_plane_count(struct gbm_device *gbm,
if (!dri->has_dmabuf_import)
return -1;
format = gbm_core.v0.format_canonicalize(format);
format = core->v0.format_canonicalize(format);
if (gbm_format_to_dri_format(format) == 0)
return -1;
@ -702,7 +706,7 @@ gbm_dri_bo_import(struct gbm_device *gbm,
/* GBM's GBM_FORMAT_* tokens are a strict superset of the DRI FourCC
* tokens accepted by createImageFromDmaBufs, except for not supporting
* the sARGB format. */
fourcc = gbm_core.v0.format_canonicalize(fd_data->format);
fourcc = core->v0.format_canonicalize(fd_data->format);
image = dri2_from_dma_bufs(dri->screen,
fd_data->width,
@ -730,7 +734,7 @@ gbm_dri_bo_import(struct gbm_device *gbm,
/* GBM's GBM_FORMAT_* tokens are a strict superset of the DRI FourCC
* tokens accepted by createImageFromDmaBufs, except for not supporting
* the sARGB format. */
fourcc = gbm_core.v0.format_canonicalize(fd_data->format);
fourcc = core->v0.format_canonicalize(fd_data->format);
image = dri2_from_dma_bufs(dri->screen, fd_data->width,
fd_data->height, fourcc,
@ -863,7 +867,7 @@ gbm_dri_bo_create(struct gbm_device *gbm,
uint64_t *mods_filtered = NULL;
unsigned int count_filtered = 0;
format = gbm_core.v0.format_canonicalize(format);
format = core->v0.format_canonicalize(format);
if (usage & GBM_BO_USE_WRITE || !dri->has_dmabuf_export)
return create_dumb(gbm, width, height, format, usage);
@ -1095,7 +1099,7 @@ gbm_dri_surface_create(struct gbm_device *gbm,
surf->base.gbm = gbm;
surf->base.v0.width = width;
surf->base.v0.height = height;
surf->base.v0.format = gbm_core.v0.format_canonicalize(format);
surf->base.v0.format = core->v0.format_canonicalize(format);
surf->base.v0.flags = flags;
if (!modifiers) {
assert(!count);
@ -1153,13 +1157,6 @@ dri_device_create(int fd, uint32_t gbm_backend_version)
int ret;
bool force_sw;
/*
* Since the DRI backend is built-in to the loader, the loader ABI version is
* guaranteed to match this backend's ABI version
*/
assert(gbm_core.v0.core_version == GBM_BACKEND_ABI_VERSION);
assert(gbm_core.v0.core_version == gbm_backend_version);
dri = calloc(1, sizeof *dri);
if (!dri)
return NULL;
@ -1229,3 +1226,11 @@ struct gbm_backend gbm_dri_backend = {
.v0.backend_name = "dri",
.v0.create_device = dri_device_create,
};
struct gbm_backend * gbmint_get_backend(const struct gbm_core *gbm_core);
PUBLIC struct gbm_backend *
gbmint_get_backend(const struct gbm_core *gbm_core) {
core = gbm_core;
return &gbm_dri_backend;
};

View file

@ -0,0 +1,12 @@
libgbm_dri = shared_library(
'dri_gbm',
files('gbm_dri.c', 'gbm_driint.h'),
include_directories : incs_gbm,
link_args : [ld_args_gc_sections],
link_with : [libloader, libgallium_dri],
dependencies : [deps_gbm, dep_dl, dep_thread, dep_libdrm, idep_mesautil, idep_xmlconfig],
gnu_symbol_visibility : 'hidden',
install : true,
install_dir: join_paths(get_option('libdir'), 'gbm'),
name_prefix : '',
)

View file

@ -42,22 +42,12 @@
#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
#define VER_MIN(a, b) ((a) < (b) ? (a) : (b))
#ifdef HAVE_DRI
extern const struct gbm_backend gbm_dri_backend;
#endif
struct gbm_backend_desc {
const char *name;
const struct gbm_backend *backend;
void *lib;
};
static const struct gbm_backend_desc builtin_backends[] = {
#ifdef HAVE_DRI
{ "dri", &gbm_dri_backend },
#endif
};
#define BACKEND_LIB_SUFFIX "_gbm"
static const char *backend_search_path_vars[] = {
"GBM_BACKENDS_PATH",
@ -116,8 +106,16 @@ backend_create_device(const struct gbm_backend_desc *bd, int fd)
}
static struct gbm_device *
load_backend(void *lib, int fd, const char *name)
load_backend_by_name(const char *name, int fd, bool warn_on_fail)
{
void *lib = loader_open_driver_lib(name, BACKEND_LIB_SUFFIX,
backend_search_path_vars,
DEFAULT_BACKENDS_PATH,
warn_on_fail);
if (!lib)
return NULL;
struct gbm_device *dev = NULL;
struct gbm_backend_desc *backend_desc;
const struct gbm_backend *gbm_backend;
@ -146,89 +144,25 @@ fail:
return NULL;
}
static struct gbm_device *
find_backend(const char *name, int fd)
{
struct gbm_device *dev = NULL;
const struct gbm_backend_desc *bd;
void *lib;
unsigned 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;
}
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;
}
static struct gbm_device *
override_backend(int fd)
{
struct gbm_device *dev = NULL;
const char *b;
b = getenv("GBM_BACKEND");
if (b)
dev = find_backend(b, fd);
return dev;
}
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;
struct gbm_device *dev = NULL;
dev = override_backend(fd);
const char *b = getenv("GBM_BACKEND");
if (b) {
dev = load_backend_by_name(b, fd, true);
if (dev) return dev;
}
if (!dev)
dev = backend_from_driver_name(fd);
drmVersionPtr v = drmGetVersion(fd);
if (v) {
dev = load_backend_by_name(v->name, fd, false);
drmFreeVersion(v);
if (dev) return dev;
}
if (!dev)
dev = find_backend(NULL, fd);
return dev;
return load_backend_by_name("dri", fd, true);
}
void

View file

@ -22,14 +22,15 @@ incs_gbm = [
# TODO: fix includes to delete this
incs_gbm += inc_mesa
if with_dri2
files_gbm += files('backends/dri/gbm_dri.c', 'backends/dri/gbm_driint.h')
endif
if with_platform_wayland
deps_gbm += dep_wayland_server
incs_gbm += inc_wayland_drm
endif
if with_dri2
subdir('backends/dri')
endif
libgbm_name = 'gbm'
if with_platform_android and get_option('platform-sdk-version') >= 30
@ -42,7 +43,7 @@ libgbm = shared_library(
include_directories : incs_gbm,
c_args : [args_gbm],
link_args : [ld_args_gc_sections],
link_with : [libloader, libgallium_dri],
link_with : [libloader],
dependencies : [deps_gbm, dep_dl, dep_thread, dep_libdrm, idep_mesautil, idep_xmlconfig],
gnu_symbol_visibility : 'hidden',
version : '1.0.0',