On 12/06/2013 07:54 PM, Matt Turner wrote: > On Fri, Dec 6, 2013 at 7:11 PM, 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. >> >> v2: >> * dladdr on public symbol __driDriverExtensions rather >> than static megadriver_stub_init. >> * Incorporate fixes and suggestions from Keith >> >> Signed-off-by: Jordan Justen <jordan.l.jus...@intel.com> >> Cc: "10.0" <mesa-sta...@lists.freedesktop.org> >> --- >> src/mesa/drivers/dri/common/megadriver_stub.c | 125 >> ++++++++++++++++++++++++++ >> 1 file changed, 125 insertions(+) >> >> diff --git a/src/mesa/drivers/dri/common/megadriver_stub.c >> b/src/mesa/drivers/dri/common/megadriver_stub.c >> index 6bf5d73..cb1078d 100644 >> --- a/src/mesa/drivers/dri/common/megadriver_stub.c >> +++ b/src/mesa/drivers/dri/common/megadriver_stub.c >> @@ -23,6 +23,131 @@ >> >> #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 > > More specifically, what extension do we use? > >> +#define MEGADRIVER_STUB_MAX_EXTENSIONS 10 >> +#define LIB_PATH_SUFFIX "_dri.so" >> +#define LIB_PATH_SUFFIX_LENGTH (sizeof(LIB_PATH_SUFFIX)-1) >> + >> +/* 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 > > constructor > >> + * is being loaded. >> + */ >> +PUBLIC const __DRIextension * >> +__driDriverExtensions[MEGADRIVER_STUB_MAX_EXTENSIONS] = { >> + NULL >> +}; >> + >> +/** >> + * This is a contructor function for the megadriver dynamic library. > > constructor > >> + * >> + * 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 enable >> + * compatibility with older DRI driver loaders. >> + */ >> +__attribute__((constructor)) static void >> +megadriver_stub_init(void) >> +{ >> + Dl_info info; >> + char *driver_name; >> + size_t name_len; >> + char *get_extensions_name; >> + const __DRIextension **(*get_extensions)(void); >> + const __DRIextension **extensions; >> + int i; >> + >> + /* Call dladdr on __driDriverExtensions. We are really >> + * interested in the returned info.dli_fname so we can >> + * figure out the path name of the library being loaded. >> + */ >> + i = dladdr((void*) __driDriverExtensions, &info); >> + if (i == 0) >> + return; >> + >> + /* Search for the last '/' character in the path. */ >> + driver_name = strrchr(info.dli_fname, '/'); >> + if (driver_name != NULL) { >> + /* Skip '/' character */ >> + driver_name++; >> + } else { >> + /* Try using the start of the path */ >> + driver_name = (char*) info.dli_fname; >> + } >> + >> + /* Make sure the path ends with _dri.so */ >> + name_len = strlen(driver_name); >> + i = name_len - LIB_PATH_SUFFIX_LENGTH; >> + if (i < 0 || strcmp(driver_name + i, LIB_PATH_SUFFIX) != 0) >> + return; >> + >> + /* Duplicate the string so we can modify it. >> + * So far we've been using info.dli_fname. >> + */ >> + driver_name = strdup(driver_name); >> + if (!driver_name) >> + return; >> + >> + /* The path ends with _dri.so. Chop this part of the >> + * string off. Then we'll have the driver's final name. >> + */ >> + driver_name[i] = '\0'; >> + >> + i = asprintf(&get_extensions_name, "%s_%s", >> + __DRI_DRIVER_GET_EXTENSIONS, driver_name); >> + free(driver_name); >> + if (i == -1) >> + return; >> + >> + /* dlsym to get the driver's get extensions function. We >> + * don't have the dlopen handle, so we have to use >> + * RTLD_DEFAULT. It seems unlikely that the symbol will >> + * be found in another library, but this isn't optimal. >> + */ >> + 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 than we reserved, then >> + * bail out. >> + */ >> + if (i == ARRAY_SIZE(__driDriverExtensions)) { >> + __driDriverExtensions[0] = NULL; >> + fprintf(stderr, "Megadriver stub did not reserve enough extension " >> + "slots.\n"); >> + return; >> + } >> +} >> + >> +#endif // #ifdef _GNU_SOURCE > > C++-style comment.
This part gets build using C99, right? If so, that should be fine. > Very cool. Have a > > Reviewed-by: Matt Turner <matts...@gmail.com> > _______________________________________________ > mesa-stable mailing list > mesa-sta...@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/mesa-stable _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev