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.jus...@intel.com> Cc: "10.0" <mesa-sta...@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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev