diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c index 2489a87f908..ba265320f00 100644 --- a/src/egl/drivers/dri2/egl_dri2.c +++ b/src/egl/drivers/dri2/egl_dri2.c @@ -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, diff --git a/src/egl/generate/eglFunctionList.py b/src/egl/generate/eglFunctionList.py index 77f44508436..22047e4f7f1 100644 --- a/src/egl/generate/eglFunctionList.py +++ b/src/egl/generate/eglFunctionList.py @@ -245,4 +245,7 @@ EGL_FUNCTIONS = ( # EGL_EXT_surface_compression _eglFunc("eglQuerySupportedCompressionRatesEXT", "display"), + + # EGL_EXT_device_persistent_id + _eglFunc("eglQueryDeviceBinaryEXT", "device"), ) diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c index d492fb5e79f..b0bbb3d8669 100644 --- a/src/egl/main/eglapi.c +++ b/src/egl/main/eglapi.c @@ -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) { diff --git a/src/egl/main/egldevice.c b/src/egl/main/egldevice.c index 9d0c47296c8..4b3e6fe193b 100644 --- a/src/egl/main/egldevice.c +++ b/src/egl/main/egldevice.c @@ -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"); diff --git a/src/egl/main/egldevice.h b/src/egl/main/egldevice.h index 6e0d069d6d6..30e3a552c97 100644 --- a/src/egl/main/egldevice.h +++ b/src/egl/main/egldevice.h @@ -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 diff --git a/src/egl/main/egldriver.h b/src/egl/main/egldriver.h index 3f27405cea4..3f1e7b8220c 100644 --- a/src/egl/main/egldriver.h +++ b/src/egl/main/egldriver.h @@ -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); diff --git a/src/egl/main/eglentrypoint.h b/src/egl/main/eglentrypoint.h index fa63ee7094e..d91562d949b 100644 --- a/src/egl/main/eglentrypoint.h +++ b/src/egl/main/eglentrypoint.h @@ -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) diff --git a/src/gallium/frontends/dri/dri_util.c b/src/gallium/frontends/dri/dri_util.c index 9ee8c1156c7..5e841613fbd 100644 --- a/src/gallium/frontends/dri/dri_util.c +++ b/src/gallium/frontends/dri/dri_util.c @@ -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; +} diff --git a/src/gallium/frontends/dri/dri_util.h b/src/gallium/frontends/dri/dri_util.h index 26331e2f1f6..78eed29a035 100644 --- a/src/gallium/frontends/dri/dri_util.h +++ b/src/gallium/frontends/dri/dri_util.h @@ -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_ */ diff --git a/src/gallium/targets/dri/dri.sym.in b/src/gallium/targets/dri/dri.sym.in index 13899c933bd..0a820d5dfca 100644 --- a/src/gallium/targets/dri/dri.sym.in +++ b/src/gallium/targets/dri/dri.sym.in @@ -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;