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 <tred...@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 <tred...@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)


_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to