commit bf1a520

Michael Forney  ·  2014-12-25 09:07:14 +0000 UTC
parent 28f2da3
drm: Use render nodes for rendering
1 files changed,  +44, -31
+44, -31
  1@@ -31,6 +31,7 @@
  2 #include "wayland_buffer.h"
  3 
  4 #include <dirent.h>
  5+#include <errno.h>
  6 #include <stdio.h>
  7 #include <stdlib.h>
  8 #include <string.h>
  9@@ -47,7 +48,7 @@ struct swc_drm swc_drm;
 10 
 11 static struct
 12 {
 13-    char * path;
 14+    char path[128];
 15 
 16     uint32_t taken_ids;
 17 
 18@@ -58,15 +59,6 @@ static struct
 19 static void authenticate(struct wl_client * client,
 20                          struct wl_resource * resource, uint32_t magic)
 21 {
 22-    int ret;
 23-
 24-    if ((ret = drmAuthMagic(swc.drm->fd, magic)) == 0)
 25-        wl_drm_send_authenticated(resource);
 26-    else
 27-    {
 28-        wl_resource_post_error(resource, WL_DRM_ERROR_AUTHENTICATE_FAIL,
 29-                               "drmAuthMagic failed: %d\n", ret);
 30-    }
 31 }
 32 
 33 static void create_buffer(struct wl_client * client,
 34@@ -138,12 +130,11 @@ static int select_card(const struct dirent * entry)
 35     return sscanf(entry->d_name, "card%u", &num) == 1;
 36 }
 37 
 38-static bool find_primary_drm_device(char ** device_path)
 39+static bool find_primary_drm_device(char * path, size_t size)
 40 {
 41     struct dirent ** cards, * card = NULL;
 42     int num_cards, ret;
 43     unsigned index;
 44-    char path[64];
 45     FILE * file;
 46     unsigned char boot_vga;
 47 
 48@@ -154,8 +145,8 @@ static bool find_primary_drm_device(char ** device_path)
 49 
 50     for (index = 0; index < num_cards; ++index)
 51     {
 52-        snprintf(path, sizeof path,
 53-                 "/sys/class/drm/%s/device/boot_vga", cards[index]->d_name);
 54+        snprintf(path, size, "/sys/class/drm/%s/device/boot_vga",
 55+                 cards[index]->d_name);
 56 
 57         if ((file = fopen(path, "r")))
 58         {
 59@@ -182,14 +173,10 @@ static bool find_primary_drm_device(char ** device_path)
 60     if (!card)
 61         return false;
 62 
 63-    *device_path = malloc(sizeof "/dev/dri/" + strlen(card->d_name));
 64-
 65-    if (!*device_path)
 66+    if (snprintf(path, size, "/dev/dri/%s", card->d_name) >= size)
 67         return false;
 68 
 69-    sprintf(*device_path, "/dev/dri/%s", card->d_name);
 70     free(card);
 71-
 72     return true;
 73 }
 74 
 75@@ -282,7 +269,9 @@ static void bind_drm(struct wl_client * client, void * data, uint32_t version,
 76 
 77 bool swc_drm_initialize()
 78 {
 79-    if (!find_primary_drm_device(&drm.path))
 80+    struct stat master, render;
 81+
 82+    if (!find_primary_drm_device(drm.path, sizeof drm.path))
 83     {
 84         ERROR("Could not find DRM device\n");
 85         goto error0;
 86@@ -294,19 +283,46 @@ bool swc_drm_initialize()
 87     if (swc.drm->fd == -1)
 88     {
 89         ERROR("Could not open DRM device at %s\n", drm.path);
 90+        goto error0;
 91+    }
 92+
 93+    if (fstat(swc.drm->fd, &master) != 0)
 94+    {
 95+        ERROR("Could not fstat DRM FD: %s\n", strerror(errno));
 96+        goto error1;
 97+    }
 98+
 99+    if (snprintf(drm.path, sizeof drm.path, "/dev/dri/renderD%d",
100+                 minor(master.st_rdev) + 0x80) >= sizeof drm.path)
101+    {
102+        ERROR("Render node path is too long");
103+        goto error1;
104+    }
105+
106+    if (stat(drm.path, &render) != 0)
107+    {
108+        ERROR("Could not stat render node for primary DRM device: %s\n",
109+              strerror(errno));
110+        goto error1;
111+    }
112+
113+    if (master.st_mode != render.st_mode
114+        || minor(master.st_rdev) + 0x80 != minor(render.st_rdev))
115+    {
116+        ERROR("Render node does not have expected mode or minor number\n");
117         goto error1;
118     }
119 
120     if (!(swc.drm->context = wld_drm_create_context(swc.drm->fd)))
121     {
122         ERROR("Could not create WLD DRM context\n");
123-        goto error2;
124+        goto error1;
125     }
126 
127     if (!(swc.drm->renderer = wld_create_renderer(swc.drm->context)))
128     {
129         ERROR("Could not create WLD DRM renderer\n");
130-        goto error3;
131+        goto error2;
132     }
133 
134     drm.event_source = wl_event_loop_add_fd
135@@ -315,7 +331,7 @@ bool swc_drm_initialize()
136     if (!drm.event_source)
137     {
138         ERROR("Could not create DRM event source\n");
139-        goto error4;
140+        goto error3;
141     }
142 
143     if (!wld_drm_is_dumb(swc.drm->context))
144@@ -326,22 +342,20 @@ bool swc_drm_initialize()
145         if (!drm.global)
146         {
147             ERROR("Could not create wl_drm global\n");
148-            goto error5;
149+            goto error4;
150         }
151     }
152 
153     return true;
154 
155-  error5:
156-    wl_event_source_remove(drm.event_source);
157   error4:
158-    wld_destroy_renderer(swc.drm->renderer);
159+    wl_event_source_remove(drm.event_source);
160   error3:
161-    wld_destroy_context(swc.drm->context);
162+    wld_destroy_renderer(swc.drm->renderer);
163   error2:
164-    close(swc.drm->fd);
165+    wld_destroy_context(swc.drm->context);
166   error1:
167-    free(drm.path);
168+    close(swc.drm->fd);
169   error0:
170     return false;
171 }
172@@ -353,7 +367,6 @@ void swc_drm_finalize()
173     wl_event_source_remove(drm.event_source);
174     wld_destroy_renderer(swc.drm->renderer);
175     wld_destroy_context(swc.drm->context);
176-    free(drm.path);
177     close(swc.drm->fd);
178 }
179