egl: Add EGL_EXT_device_query_name and EGL_EXT_device_persistent_id

Adds support for the EGL extensions EGL_EXT_device_query_name and
EGL_EXT_device_persistent_id. This enables querying device name, vendor
name, renderer name and device and driver UUIDs.

Signed-off-by: Christoph Neuhauser <christoph.neuhauser@intel.com>
Reviewed-by: Tapani Pälli <tapani.palli@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/34958>
This commit is contained in:
Christoph Neuhauser 2025-06-13 14:52:42 +02:00 committed by Marge Bot
parent ee7536a1e3
commit e99446fc5e
10 changed files with 199 additions and 1 deletions

View file

@ -595,6 +595,16 @@ dri2_query_driver_config(_EGLDisplay *disp)
return ret;
}
static bool
dri2_query_device_info(const void* driver_device_identifier,
struct egl_device_info *device_info)
{
const char* drm_device_name = (const char*)driver_device_identifier;
return dri_get_drm_device_info(
drm_device_name, device_info->device_uuid, device_info->driver_uuid,
&device_info->vendor_name, &device_info->renderer_name, &device_info->driver_name);
}
void
dri2_setup_screen(_EGLDisplay *disp)
{
@ -3338,6 +3348,7 @@ const _EGLDriver _eglDriver = {
.QuerySurface = dri2_query_surface,
.QueryDriverName = dri2_query_driver_name,
.QueryDriverConfig = dri2_query_driver_config,
.QueryDeviceInfo = dri2_query_device_info,
#ifdef HAVE_LIBDRM
.CreateDRMImageMESA = dri2_create_drm_image_mesa,
.ExportDRMImageMESA = dri2_export_drm_image_mesa,

View file

@ -245,4 +245,7 @@ EGL_FUNCTIONS = (
# EGL_EXT_surface_compression
_eglFunc("eglQuerySupportedCompressionRatesEXT", "display"),
# EGL_EXT_device_persistent_id
_eglFunc("eglQueryDeviceBinaryEXT", "device"),
)

View file

@ -2714,6 +2714,22 @@ eglQueryDeviceAttribEXT(EGLDeviceEXT device, EGLint attribute, EGLAttrib *value)
RETURN_EGL_EVAL(NULL, ret);
}
static EGLBoolean EGLAPIENTRY
eglQueryDeviceBinaryEXT(EGLDeviceEXT device,
EGLint name,
EGLint max_size,
void *value,
EGLint *size)
{
_EGLDevice *dev = _eglLookupDevice(device);
_EGL_FUNC_START(NULL, EGL_NONE, NULL);
if (!dev)
RETURN_EGL_ERROR(NULL, EGL_BAD_DEVICE_EXT, EGL_FALSE);
RETURN_EGL_EVAL(NULL, _eglQueryDeviceBinaryEXT(dev, name, max_size, value, size));
}
static const char *EGLAPIENTRY
eglQueryDeviceStringEXT(EGLDeviceEXT device, EGLint name)
{

View file

@ -36,6 +36,7 @@
#include "eglglobals.h"
#include "egllog.h"
#include "egltypedefs.h"
#include "egldriver.h"
struct _egl_device {
_EGLDevice *Next;
@ -45,10 +46,15 @@ struct _egl_device {
EGLBoolean MESA_device_software;
EGLBoolean EXT_device_drm;
EGLBoolean EXT_device_drm_render_node;
EGLBoolean EXT_device_query_name;
EGLBoolean EXT_device_persistent_id;
#ifdef HAVE_LIBDRM
drmDevicePtr device;
#endif
/* Cache for EGL_EXT_device_query_name and EXT_device_persistent_id. */
struct egl_device_info device_info;
};
void
@ -74,6 +80,9 @@ _eglFiniDevice(void)
assert(_eglDeviceSupports(dev, _EGL_DEVICE_DRM));
drmFreeDevice(&dev->device);
#endif
free(dev->device_info.vendor_name);
free(dev->device_info.renderer_name);
free(dev->device_info.driver_name);
free(dev);
}
@ -104,6 +113,7 @@ _EGLDevice _eglSoftwareDevice = {
};
#ifdef HAVE_LIBDRM
extern const _EGLDriver _eglDriver;
/*
* Negative value on error, zero if newly added, one if already in list.
*/
@ -142,9 +152,23 @@ _eglAddDRMDevice(drmDevicePtr device)
return -1;
dev = dev->Next;
dev->extensions = "EGL_EXT_device_drm EGL_EXT_device_drm_render_node";
const char *node = device->nodes[DRM_NODE_RENDER];
bool supportsDrmDeviceQuery = false;
if (_eglDriver.QueryDeviceInfo)
supportsDrmDeviceQuery = _eglDriver.QueryDeviceInfo(node, &dev->device_info);
if (supportsDrmDeviceQuery)
dev->extensions =
"EGL_EXT_device_drm EGL_EXT_device_drm_render_node "
"EGL_EXT_device_query_name EGL_EXT_device_persistent_id";
else
dev->extensions = "EGL_EXT_device_drm EGL_EXT_device_drm_render_node";
dev->EXT_device_drm = EGL_TRUE;
dev->EXT_device_drm_render_node = EGL_TRUE;
if (supportsDrmDeviceQuery) {
dev->EXT_device_query_name = EGL_TRUE;
dev->EXT_device_persistent_id = EGL_TRUE;
}
dev->device = device;
return 0;
@ -236,6 +260,10 @@ _eglDeviceSupports(_EGLDevice *dev, _EGLDeviceExtension ext)
return dev->EXT_device_drm;
case _EGL_DEVICE_DRM_RENDER_NODE:
return dev->EXT_device_drm_render_node;
case _EGL_DEVICE_QUERY_NAME:
return dev->EXT_device_query_name;
case _EGL_DEVICE_PERSISTENT_ID:
return dev->EXT_device_persistent_id;
default:
assert(0);
return EGL_FALSE;
@ -252,6 +280,38 @@ _eglQueryDeviceAttribEXT(_EGLDevice *dev, EGLint attribute, EGLAttrib *value)
}
}
EGLBoolean
_eglQueryDeviceBinaryEXT(_EGLDevice *dev, EGLint name, EGLint max_size,
void *value, EGLint *size)
{
if (!_eglDeviceSupports(dev, _EGL_DEVICE_DRM) ||
!_eglDeviceSupports(dev, _EGL_DEVICE_PERSISTENT_ID) ||
!(name == EGL_DEVICE_UUID_EXT || name == EGL_DRIVER_UUID_EXT) ||
(value != NULL && max_size < EGL_UUID_SIZE) ||
size == NULL) {
_eglError(EGL_BAD_ATTRIBUTE, "eglQueryDeviceBinaryEXT");
return EGL_FALSE;
}
#ifdef HAVE_LIBDRM
if (value && name == EGL_DEVICE_UUID_EXT) {
memcpy(value, dev->device_info.device_uuid, EGL_UUID_SIZE);
}
if (value && name == EGL_DRIVER_UUID_EXT) {
memcpy(value, dev->device_info.driver_uuid, EGL_UUID_SIZE);
}
*size = EGL_UUID_SIZE;
return EGL_TRUE;
#else
/* This should never happen: we don't yet support EGL_DEVICE_DRM nor
* EGL_DEVICE_PERSISTENT_ID for the software device, and physical devices are
* only exposed when libdrm is available. */
assert(0);
_eglError(EGL_BAD_ATTRIBUTE, "eglQueryDeviceBinaryEXT");
return EGL_FALSE;
#endif
}
const char *
_eglQueryDeviceStringEXT(_EGLDevice *dev, EGLint name)
{
@ -285,6 +345,38 @@ _eglQueryDeviceStringEXT(_EGLDevice *dev, EGLint name)
/* Physical devices are only exposed when libdrm is available. */
assert(_eglDeviceSupports(dev, _EGL_DEVICE_SOFTWARE));
return NULL;
#endif
/* EGL_EXT_device_query_name */
case EGL_VENDOR:
if (!_eglDeviceSupports(dev, _EGL_DEVICE_QUERY_NAME))
break;
#ifdef HAVE_LIBDRM
return dev->device_info.vendor_name;
#else
/* Physical devices are only exposed when libdrm is available. */
assert(_eglDeviceSupports(dev, _EGL_DEVICE_SOFTWARE));
return NULL;
#endif
case EGL_RENDERER_EXT:
if (!_eglDeviceSupports(dev, _EGL_DEVICE_QUERY_NAME))
break;
#ifdef HAVE_LIBDRM
return dev->device_info.renderer_name;
#else
/* Physical devices are only exposed when libdrm is available. */
assert(_eglDeviceSupports(dev, _EGL_DEVICE_SOFTWARE));
return NULL;
#endif
/* EGL_EXT_device_persistent_id */
case EGL_DRIVER_NAME_EXT:
if (!_eglDeviceSupports(dev, _EGL_DEVICE_PERSISTENT_ID))
break;
#ifdef HAVE_LIBDRM
return dev->device_info.driver_name;
#else
/* Physical devices are only exposed when libdrm is available. */
assert(_eglDeviceSupports(dev, _EGL_DEVICE_SOFTWARE));
return NULL;
#endif
}
_eglError(EGL_BAD_PARAMETER, "eglQueryDeviceStringEXT");

View file

@ -64,6 +64,8 @@ enum _egl_device_extension {
_EGL_DEVICE_SOFTWARE,
_EGL_DEVICE_DRM,
_EGL_DEVICE_DRM_RENDER_NODE,
_EGL_DEVICE_QUERY_NAME,
_EGL_DEVICE_PERSISTENT_ID,
};
typedef enum _egl_device_extension _EGLDeviceExtension;
@ -94,6 +96,13 @@ EGLBoolean
_eglQueryDevicesEXT(EGLint max_devices, _EGLDevice **devices,
EGLint *num_devices);
EGLBoolean
_eglQueryDeviceBinaryEXT(_EGLDevice* dev,
EGLint name,
EGLint max_size,
void *value,
EGLint *size);
#ifdef __cplusplus
}
#endif

View file

@ -76,6 +76,20 @@ struct mesa_glinterop_export_out;
struct mesa_glinterop_flush_out;
typedef struct __GLsync *GLsync;
#define EGL_UUID_SIZE 16
/**
* For use in EGL_EXT_device_query_name and EGL_EXT_device_persistent_id
*/
struct egl_device_info {
uint8_t device_uuid[EGL_UUID_SIZE];
uint8_t driver_uuid[EGL_UUID_SIZE];
/* Data below needs to be freed manually */
char *vendor_name;
char *renderer_name;
char *driver_name;
};
/**
* The API dispatcher jumps through these functions
*/
@ -191,6 +205,10 @@ struct _egl_driver {
const char *(*QueryDriverName)(_EGLDisplay *disp);
char *(*QueryDriverConfig)(_EGLDisplay *disp);
/* for EGL_EXT_device_query_name and EGL_EXT_device_persistent_id */
bool (*QueryDeviceInfo)(const void* driver_device_identifier,
struct egl_device_info *device_info);
/* for OpenGL-OpenCL interop; see include/GL/mesa_glinterop.h */
int (*GLInteropQueryDeviceInfo)(_EGLDisplay *disp, _EGLContext *ctx,
struct mesa_glinterop_device_info *out);

View file

@ -63,6 +63,7 @@ EGL_ENTRYPOINT(eglQueryAPI)
EGL_ENTRYPOINT(eglQueryContext)
EGL_ENTRYPOINT(eglQueryDebugKHR)
EGL_ENTRYPOINT(eglQueryDeviceAttribEXT)
EGL_ENTRYPOINT(eglQueryDeviceBinaryEXT)
EGL_ENTRYPOINT(eglQueryDeviceStringEXT)
EGL_ENTRYPOINT(eglQueryDevicesEXT)
EGL_ENTRYPOINT(eglQueryDisplayAttribEXT)

View file

@ -1055,3 +1055,46 @@ driGetDriInfoXML(const char* driverName)
{
return pipe_loader_get_driinfo_xml(driverName);
}
bool
dri_get_drm_device_info(const char *device_name, uint8_t *device_uuid, uint8_t *driver_uuid,
char **vendor_name, char **renderer_name, char **driver_name)
{
struct pipe_loader_device *pldev;
struct pipe_screen *pscreen;
int fd;
fd = loader_open_device(device_name);
if (fd == -1) {
return false;
}
if (!pipe_loader_drm_probe_fd(&pldev, fd, false)) {
close(fd);
return false;
}
pscreen = pipe_loader_create_screen(pldev, true);
if (!pscreen) {
pipe_loader_release(&pldev, 1);
close(fd);
return false;
}
if (!pscreen->get_device_uuid || !pscreen->get_driver_uuid ||
!pscreen->get_device_vendor || !pscreen->get_name) {
pscreen->destroy(pscreen);
pipe_loader_release(&pldev, 1);
close(fd);
return false;
}
pscreen->get_device_uuid(pscreen, (char *)device_uuid);
pscreen->get_driver_uuid(pscreen, (char *)driver_uuid);
*vendor_name = strdup(pscreen->get_device_vendor(pscreen));
*renderer_name = strdup(pscreen->get_name(pscreen));
*driver_name = loader_get_driver_for_fd(fd);
pscreen->destroy(pscreen);
pipe_loader_release(&pldev, 1);
close(fd);
return true;
}

View file

@ -347,4 +347,8 @@ dri_get_pipe_screen(struct dri_screen *driScreen);
PUBLIC char*
driGetDriInfoXML(const char* driverName);
PUBLIC bool
dri_get_drm_device_info(const char *device_name, uint8_t *device_uuid, uint8_t *driver_uuid,
char **vendor_name, char **renderer_name, char **driver_name);
#endif /* _DRI_UTIL_H_ */

View file

@ -70,6 +70,7 @@
dri_server_wait_sync;
dri_set_blob_cache_funcs;
dri_get_pipe_screen;
dri_get_drm_device_info;
dri3*;
loader_dri3*;
dri_create_drawable;