[Mesa-dev] [RFC] loader: Automatic PRIME detection

Axel Davy axel.davy at ens.fr
Tue Dec 27 12:57:21 UTC 2016


Hi Thierry,

Could you explain why in this situation default_fd would be a 
non-renderable device node ?

In my understanding, for X11 DRI3 the Xserver is supposed to give you a 
renderable device node,
and for Wayland, the device path advertised is the one used by the 
server for compositing.

Yours,

Axel Davy

On 23/12/2016 21:36, Thierry Reding wrote:
> From: Thierry Reding <treding at nvidia.com>
>
> If a device doesn't support rendering and support for PRIME isn't
> enabled via the DRI_PRIME environment variable or dri.conf, attempt to
> find a render node which can be used to offload rendering.
>
> Signed-off-by: Thierry Reding <treding at nvidia.com>
> ---
> Along with platform and host1x bus support in the loader, this is the
> final piece of the puzzle to automatically allow split scanout/render
> devices to work with Wayland compositors and the X.Org server.
>
> Note that this requires that the Wayland compositor and X.Org server
> are accelerated with a DRI driver to make sure that the default file
> descriptor is properly set up.
>
>   src/loader/loader.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++---
>   1 file changed, 67 insertions(+), 4 deletions(-)
>
> diff --git a/src/loader/loader.c b/src/loader/loader.c
> index 505c33133be6..6384432970f2 100644
> --- a/src/loader/loader.c
> +++ b/src/loader/loader.c
> @@ -108,6 +108,71 @@ static char *loader_get_dri_config_device_id(void)
>   }
>   #endif
>   
> +/*
> + * For all devices that do not support rendering, try to find a different
> + * device that will.
> + *
> + * Note that the absence of a render node doesn't technically imply that
> + * the device can't render, but in practice this should work out fine.
> + */
> +static int drm_detect_prime_fd(int default_fd, int *different_device)
> +{
> +   int err, fd = -ENODEV;
> +   drmDevicePtr device;
> +
> +   err = drmGetDevice(default_fd, &device);
> +   if (err < 0)
> +      goto err;
> +
> +   if ((device->available_nodes & (1 << DRM_NODE_RENDER)) == 0) {
> +      unsigned int num_devices, i;
> +      drmDevicePtr *devices;
> +
> +      err = drmGetDevices(NULL, 0);
> +      if (err < 0)
> +         goto err;
> +
> +      num_devices = err;
> +
> +      devices = calloc(num_devices, sizeof(drmDevicePtr));
> +      if (!devices)
> +         goto err;
> +
> +      err = drmGetDevices(devices, num_devices);
> +      if (err < 0) {
> +         free(devices);
> +         goto err;
> +      }
> +
> +      num_devices = err;
> +
> +      for (i = 0; i < num_devices; i++) {
> +         if (devices[i]->available_nodes & (1 << DRM_NODE_RENDER)) {
> +            fd = loader_open_device(devices[i]->nodes[DRM_NODE_RENDER]);
> +            if (fd < 0) {
> +               fd = -errno;
> +               continue;
> +            }
> +
> +            close(default_fd);
> +            break;
> +         }
> +      }
> +
> +      drmFreeDevices(devices, num_devices);
> +      free(devices);
> +   }
> +
> +err:
> +   if (fd < 0) {
> +      *different_device = 0;
> +      return default_fd;
> +   }
> +
> +   *different_device = 1;
> +   return fd;
> +}
> +
>   static char *drm_construct_id_path_tag(drmDevicePtr device)
>   {
>   /* Length of "pci-xxxx_xx_xx_x\0" */
> @@ -213,10 +278,8 @@ int loader_get_user_preferred_fd(int default_fd, int *different_device)
>         prime = loader_get_dri_config_device_id();
>   #endif
>   
> -   if (prime == NULL) {
> -      *different_device = 0;
> -      return default_fd;
> -   }
> +   if (prime == NULL || *prime == '\0')
> +      return drm_detect_prime_fd(default_fd, different_device);
>   
>      default_tag = drm_get_id_path_tag_for_fd(default_fd);
>      if (default_tag == NULL)




More information about the mesa-dev mailing list