[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