Submitted by:            Zeckma
Date:                    2026-06-13
Initial Package Version: 1.7.0
Origin:                  Upstream,
                         https://gitlab.freedesktop.org/glvnd/libglvnd/-/merge_requests/298
Upstream Status:         Not merged yet
Description:             Exposes all of the device EGL extensions if just one
                         is advertised. Necessary for drivers that don't expose
                         all three, but rather one or two. Required for
                         Mesa-less.

diff --git a/src/EGL/libegl.c b/src/EGL/libegl.c
index 2a62f092ca2723cc42a38408423e6be789207391..311f3a071d4e9bea40770cfd9c9b78874c6d5b5a 100644
--- a/src/EGL/libegl.c
+++ b/src/EGL/libegl.c
@@ -59,9 +59,6 @@
  */
 static const char *SUPPORTED_CLIENT_EXTENSIONS =
     "EGL_EXT_platform_base"
-    " EGL_EXT_device_base"
-    " EGL_EXT_device_enumeration"
-    " EGL_EXT_device_query"
     " EGL_EXT_platform_device"
 
     // FIXME: Include the other platform extensions here to make testing
@@ -872,6 +869,8 @@ static char *GetClientExtensionString(void)
     struct glvnd_list *vendorList = __eglLoadVendors();
     __EGLvendorInfo *vendor;
     char *result = NULL;
+    EGLBoolean supportsDeviceEnum = EGL_FALSE;
+    EGLBoolean supportsDeviceQuery = EGL_FALSE;
 
     // First, find the union of all available vendor libraries. Start with an
     // empty string, then merge the extension string from every vendor library.
@@ -890,6 +889,9 @@ static char *GetClientExtensionString(void)
                 return NULL;
             }
         }
+
+        supportsDeviceEnum = supportsDeviceEnum || vendor->supportsDeviceEnum;
+        supportsDeviceQuery = supportsDeviceQuery || vendor->supportsDeviceQuery;
     }
 
     // Next, take the intersection of the client extensions from the vendors
@@ -902,6 +904,26 @@ static char *GetClientExtensionString(void)
         return NULL;
     }
 
+    // Add the appropriate set of device extensions.
+    if (supportsDeviceEnum) {
+        result = UnionExtensionStrings(result, "EGL_EXT_device_enumeration");
+        if (result == NULL) {
+            return NULL;
+        }
+    }
+    if (supportsDeviceQuery) {
+        result = UnionExtensionStrings(result, "EGL_EXT_device_query");
+        if (result == NULL) {
+            return NULL;
+        }
+    }
+    if (supportsDeviceEnum && supportsDeviceQuery) {
+        result = UnionExtensionStrings(result, "EGL_EXT_device_base");
+        if (result == NULL) {
+            return NULL;
+        }
+    }
+
     glvnd_list_for_each_entry(vendor, vendorList, entry) {
         const char *vendorString = NULL;
         if (vendor->eglvc.getVendorString != NULL) {
@@ -963,7 +985,7 @@ static EGLBoolean QueryVendorDevices(__EGLvendorInfo *vendor, EGLint max_devices
     EGLint vendorCount = 0;
     EGLint i;
 
-    if (!vendor->supportsDevice) {
+    if (!vendor->supportsDeviceEnum) {
         return EGL_TRUE;
     }
 
diff --git a/src/EGL/libeglvendor.c b/src/EGL/libeglvendor.c
index acece59708ab03b9623c5b0ecd39839b6a43ced5..3cfb7065f74fe7535c295aa0e506176904f4c3fe 100644
--- a/src/EGL/libeglvendor.c
+++ b/src/EGL/libeglvendor.c
@@ -385,6 +385,7 @@ static void CheckVendorExtensionString(__EGLvendorInfo *vendor, const char *str)
 {
     static const char NAME_DEVICE_BASE[] = "EGL_EXT_device_base";
     static const char NAME_DEVICE_ENUM[] = "EGL_EXT_device_enumeration";
+    static const char NAME_DEVICE_QUERY[] = "EGL_EXT_device_query";
     static const char NAME_PLATFORM_DEVICE[] = "EGL_EXT_platform_device";
     static const char NAME_MESA_PLATFORM_GBM[] = "EGL_MESA_platform_gbm";
     static const char NAME_KHR_PLATFORM_GBM[] = "EGL_KHR_platform_gbm";
@@ -397,10 +398,24 @@ static void CheckVendorExtensionString(__EGLvendorInfo *vendor, const char *str)
         return;
     }
 
-    if (!vendor->supportsDevice) {
-        if (IsTokenInString(str, NAME_DEVICE_BASE, sizeof(NAME_DEVICE_BASE) - 1, " ")
-                || IsTokenInString(str, NAME_DEVICE_ENUM, sizeof(NAME_DEVICE_ENUM) - 1, " ")) {
-            vendor->supportsDevice = EGL_TRUE;
+    if (!vendor->supportsDeviceEnum || !vendor->supportsDeviceQuery) {
+        /*
+         * EGL_EXT_device_base is equivalent to supporting both
+         * EGL_EXT_device_enumeration and EGL_EXT_device_query.
+         *
+         * Keep track of both so that we know which to include when we
+         * construct the client extension string.
+         */
+        if (IsTokenInString(str, NAME_DEVICE_BASE, sizeof(NAME_DEVICE_BASE) - 1, " ")) {
+            vendor->supportsDeviceEnum = EGL_TRUE;
+            vendor->supportsDeviceQuery = EGL_TRUE;
+        } else {
+            if (IsTokenInString(str, NAME_DEVICE_ENUM, sizeof(NAME_DEVICE_ENUM) - 1, " ")) {
+                vendor->supportsDeviceEnum = EGL_TRUE;
+            }
+            if (IsTokenInString(str, NAME_DEVICE_QUERY, sizeof(NAME_DEVICE_QUERY) - 1, " ")) {
+                vendor->supportsDeviceQuery = EGL_TRUE;
+            }
         }
     }
 
@@ -443,10 +458,12 @@ static void CheckVendorExtensions(__EGLvendorInfo *vendor)
     }
 
     if (vendor->staticDispatch.queryDevicesEXT == NULL) {
-        vendor->supportsDevice = EGL_FALSE;
+        vendor->supportsDeviceEnum = EGL_FALSE;
     }
 
-    if (!vendor->supportsDevice) {
+    if (!vendor->supportsDeviceEnum && !vendor->supportsDeviceQuery) {
+        // If we don't have either of the device extensions, then there's no
+        // way to get an EGLDeviceEXT handle from this vendor.
         vendor->supportsPlatformDevice = EGL_FALSE;
     }
 }
diff --git a/src/EGL/libeglvendor.h b/src/EGL/libeglvendor.h
index 443f285e20ff86100d7134158d740f791f710a10..bc3fdef18b831869cb44ef258e9bea573d01f86c 100644
--- a/src/EGL/libeglvendor.h
+++ b/src/EGL/libeglvendor.h
@@ -29,7 +29,8 @@ struct __EGLvendorInfoRec {
     EGLBoolean supportsGL;
     EGLBoolean supportsGLES;
 
-    EGLBoolean supportsDevice;
+    EGLBoolean supportsDeviceEnum;
+    EGLBoolean supportsDeviceQuery;
     EGLBoolean supportsPlatformDevice;
     EGLBoolean supportsPlatformGbm;
     EGLBoolean supportsPlatformX11;
