On Fri, Dec 6, 2013 at 2:35 AM, Jordan Justen <jordan.l.jus...@intel.com> wrote: > 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.
I tested mesa master with and without this patch on a system running xserver-xorg-core 1.12.4 and gnome-shell. Without this change, gnome-shell will fail to load and metacity will load as the fallback. Xorg.0.log reports that it can't find the __driDriverExtensions symbol in i965_dri.so, as expected. With the change gnome-shell starts, and glxinfo reports that it is running Mesa i965 from master. I did not see any errors mention in Xorg.0.log. Is there anything else I should look for? -Jordan > 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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev