[Mesa-dev] [RFC PATCH] dri megadriver_stub: provide compatibility with older DRI loader

Jordan Justen jordan.l.justen at intel.com
Fri Dec 6 02:35:39 PST 2013


To help the transition period when DRI loaders are being updated
to support the newer __driDriverExtensions_foo mechanism,
we populate __DRIextension with the extensions returned
by __driDriverExtensions_foo during a library contructor
function.

We find the driver foo's name by using the dladdr function
which gives the path of the dynamic library's name that
was being loaded.

Signed-off-by: Jordan Justen <jordan.l.justen at intel.com>
Cc: "10.0" <mesa-stable at lists.freedesktop.org>
---
Trying to allow Mesa 10 to be loaded by older DRI loaders.

This seems to help glxinfo get the i965 driver if Mesa 10's
i965_dri.so is added to into a Mesa 9.2 libGL stack.

It still needs to be tested more with older X servers.

 src/mesa/drivers/dri/common/megadriver_stub.c | 113 ++++++++++++++++++++++++++
 1 file changed, 113 insertions(+)

diff --git a/src/mesa/drivers/dri/common/megadriver_stub.c b/src/mesa/drivers/dri/common/megadriver_stub.c
index 6bf5d73..79d31a9 100644
--- a/src/mesa/drivers/dri/common/megadriver_stub.c
+++ b/src/mesa/drivers/dri/common/megadriver_stub.c
@@ -23,6 +23,119 @@
 
 #include <stdio.h>
 #include "dri_util.h"
+#include <dlfcn.h>
+#include "main/macros.h"
+
+/* The extensions that allow the megadriver stub to provide backward
+ * compatibility for the older DRI driver loader require GNU
+ * extensions from dlfcn.h.
+ */
+#ifdef _GNU_SOURCE
+
+#define MEGADRIVER_STUB_MAX_EXTENSIONS 10
+
+/* This is the table of extensions that the loader will dlsym() for.
+ *
+ * Initially it is empty for the megadriver stub, but the library
+ * contructor may initialize it based on the name of the library that
+ * is being loaded.
+ */
+PUBLIC const __DRIextension *
+__driDriverExtensions[MEGADRIVER_STUB_MAX_EXTENSIONS] = {
+   NULL
+};
+
+/**
+ * This is a contructor function for the megadriver dynamic library.
+ *
+ * When the driver is dlopen'ed, this function will run. It will
+ * search for the name of the foo_dri.so file that was opened using
+ * the dladdr function.
+ *
+ * After finding foo's name, it will call __driDriverGetExtensions_foo
+ * and use the return to update __driDriverExtensions to achieve
+ * compatibility with older DRI driver loaders.
+ */
+__attribute__((constructor)) static void
+megadriver_stub_init(void)
+{
+   Dl_info info;
+   char *driver_path;
+   char *driver_name;
+   size_t name_len;
+   char *get_extensions_name;
+   const __DRIextension **(*get_extensions)(void);
+   const __DRIextension **extensions;
+   int i;
+
+   i = dladdr((void*) megadriver_stub_init, &info);
+   if (i == 0)
+      return;
+
+   driver_path = strdup(info.dli_fname);
+   if (!driver_path)
+      return;
+
+   driver_name = strrchr(driver_path, '/');
+   if (driver_name != NULL) {
+      /* Skip '/' character */
+      driver_name++;
+   } else {
+      /* Try using the start of the path */
+      driver_name = driver_path;
+   }
+
+   /* Make sure the patch ends with _dri.so */
+   name_len = strlen(driver_name);
+   if (strcmp(driver_name + (name_len - 7), "_dri.so") != 0) {
+      free(driver_path);
+      return;
+   }
+
+   /* If the path ends with _dri.so, then chop this part of the
+    * string off, and then we have the name
+    */
+   driver_name[name_len - 7] = '\0';
+
+   i = asprintf(&get_extensions_name, "%s_%s",
+                __DRI_DRIVER_GET_EXTENSIONS, driver_name);
+   free(driver_path);
+   if (i == -1 || !get_extensions_name)
+      return;
+
+   get_extensions = dlsym(RTLD_DEFAULT, get_extensions_name);
+   free(get_extensions_name);
+   if (!get_extensions)
+      return;
+
+   /* Use the newer DRI loader entrypoint to find extensions.
+    * We will then expose these extensions via the older
+    * __driDriverExtensions symbol.
+    */
+   extensions = get_extensions();
+
+   /* Copy the extensions into the __driDriverExtensions array
+    * we declared.
+    */
+   for (i = 0; i < ARRAY_SIZE(__driDriverExtensions); i++) {
+      __driDriverExtensions[i] = extensions[i];
+      if (extensions[i] == NULL)
+         break;
+   }
+
+   /* If the driver had more extensions that we reserved, then
+    * bail out. This will cause the driver to fail to load using
+    * the older loader mechanism.
+    */
+   if (extensions[i] != NULL) {
+      __driDriverExtensions[0] = NULL;
+      fprintf(stderr, "An updated DRI driver loader (libGL.so or X Server) is "
+              "required for this Mesa driver.\n");
+      return;
+   }
+}
+
+#endif // #ifdef _GNU_SOURCE
 
 static const
 __DRIconfig **stub_error_init_screen(__DRIscreen *psp)
-- 
1.8.5.1



More information about the mesa-dev mailing list