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

Jordan Justen jljusten at gmail.com
Fri Dec 6 13:12:28 PST 2013


On Fri, Dec 6, 2013 at 2:35 AM, Jordan Justen <jordan.l.justen at 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.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.

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 at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list