1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
From 0f4808856ce42de4e0cf7e0c3af114165c105003 Mon Sep 17 00:00:00 2001
From: Thierry Reding <treding@nvidia.com>
Date: Fri, 23 Dec 2016 21:36:00 +0100
Subject: [PATCH 3/4] loader: Automatic PRIME detection
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@nvidia.com>
---
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 5541ccc..19e73a7 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" */
@@ -170,10 +235,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)
--
2.7.4
|