1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <fcntl.h>
4 #include <unistd.h>
5 #include <string.h>
6 #include <getopt.h>
7
8 #include <drm.h>
9 #include <drm_fourcc.h>
10 #include <errno.h>
11 #include <xf86drm.h>
12 #include <xf86drmMode.h>
13
14 #include "bo.h"
15 #include "dev.h"
16 #include "modeset.h"
17
show_usage(char * name)18 static void show_usage(char *name)
19 {
20 printf("Usage: %s [OPTION]\n", name);
21 printf(" -c, --card Index of dri card (ie: /dev/dri/cardN)\n");
22 printf(" -r, --crtc Index of crtc to use for test\n");
23 printf("\n\n");
24 }
25
parse_arguments(int argc,char * argv[],int * card,int * crtc)26 void parse_arguments(int argc, char *argv[], int *card, int *crtc)
27 {
28 static struct option options[] = {
29 { "card", required_argument, NULL, 'c' },
30 { "crtc", required_argument, NULL, 'r' },
31 { "help", no_argument, NULL, 'h' },
32 };
33 int option_index = 0;
34 int c;
35
36 *card = -1;
37 *crtc = -1;
38 do {
39 c = getopt_long(argc, argv, "c:r:h", options, &option_index);
40 switch (c) {
41 case 0:
42 case 'h':
43 show_usage(argv[0]);
44 exit(0);
45 case -1:
46 break;
47 case 'c':
48 if (optarg[0] < '0' || optarg[0] > '9') {
49 printf("Invalid card value '%s'!\n", optarg);
50 show_usage(argv[0]);
51 exit(-1);
52 }
53 *card = optarg[0] - '0';
54 break;
55 case 'r':
56 if (optarg[0] < '0' || optarg[0] > '9') {
57 printf("Invalid crtc value '%s'!\n", optarg);
58 show_usage(argv[0]);
59 exit(-1);
60 }
61 *crtc = optarg[0] - '0';
62 break;
63 }
64 } while (c != -1);
65
66 if (*card < 0 || *crtc < 0) {
67 show_usage(argv[0]);
68 exit(-1);
69 }
70 }
71
get_prop_id(struct sp_dev * dev,drmModeObjectPropertiesPtr props,const char * name)72 static uint32_t get_prop_id(struct sp_dev *dev,
73 drmModeObjectPropertiesPtr props, const char *name)
74 {
75 drmModePropertyPtr p;
76 uint32_t i, prop_id = 0; /* Property ID should always be > 0 */
77
78 for (i = 0; !prop_id && i < props->count_props; i++) {
79 p = drmModeGetProperty(dev->fd, props->props[i]);
80 if (!strcmp(p->name, name))
81 prop_id = p->prop_id;
82 drmModeFreeProperty(p);
83 }
84 if (!prop_id)
85 printf("Could not find %s property\n", name);
86 return prop_id;
87 }
88
get_supported_format(struct sp_plane * plane,uint32_t * format)89 static int get_supported_format(struct sp_plane *plane, uint32_t *format)
90 {
91 uint32_t i;
92
93 for (i = 0; i < plane->plane->count_formats; i++) {
94 if (plane->plane->formats[i] == DRM_FORMAT_XRGB8888 ||
95 plane->plane->formats[i] == DRM_FORMAT_ARGB8888 ||
96 plane->plane->formats[i] == DRM_FORMAT_RGBA8888) {
97 *format = plane->plane->formats[i];
98 return 0;
99 }
100 }
101 printf("No suitable formats found!\n");
102 return -ENOENT;
103 }
104
create_sp_dev(int card)105 struct sp_dev *create_sp_dev(int card)
106 {
107 struct sp_dev *dev;
108 int ret, fd, i, j;
109 drmModeRes *r = NULL;
110 drmModePlaneRes *pr = NULL;
111 char card_path[256];
112
113 snprintf(card_path, sizeof(card_path), "/dev/dri/card%d", card);
114
115 fd = open(card_path, O_RDWR);
116 if (fd < 0) {
117 printf("failed to open card0\n");
118 return NULL;
119 }
120
121 dev = calloc(1, sizeof(*dev));
122 if (!dev) {
123 printf("failed to allocate dev\n");
124 return NULL;
125 }
126
127 dev->fd = fd;
128
129 ret = drmSetClientCap(dev->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
130 if (ret) {
131 printf("failed to set client cap\n");
132 goto err;
133 }
134
135 ret = drmSetClientCap(dev->fd, DRM_CLIENT_CAP_ATOMIC, 1);
136 if (ret) {
137 printf("Failed to set atomic cap %d", ret);
138 goto err;
139 }
140
141 r = drmModeGetResources(dev->fd);
142 if (!r) {
143 printf("failed to get r\n");
144 goto err;
145 }
146
147 dev->num_connectors = r->count_connectors;
148 dev->connectors = calloc(dev->num_connectors,
149 sizeof(struct sp_connector));
150 if (!dev->connectors) {
151 printf("failed to allocate connectors\n");
152 goto err;
153 }
154 for (i = 0; i < dev->num_connectors; i++) {
155 drmModeObjectPropertiesPtr props;
156 dev->connectors[i].conn = drmModeGetConnector(dev->fd,
157 r->connectors[i]);
158 if (!dev->connectors[i].conn) {
159 printf("failed to get connector %d\n", i);
160 goto err;
161 }
162
163 props = drmModeObjectGetProperties(dev->fd, r->connectors[i],
164 DRM_MODE_OBJECT_CONNECTOR);
165 if (!props) {
166 printf("failed to get connector properties\n");
167 goto err;
168 }
169
170 dev->connectors[i].crtc_id_pid = get_prop_id(dev, props,
171 "CRTC_ID");
172 drmModeFreeObjectProperties(props);
173 if (!dev->connectors[i].crtc_id_pid)
174 goto err;
175 }
176
177 dev->num_encoders = r->count_encoders;
178 dev->encoders = calloc(dev->num_encoders, sizeof(*dev->encoders));
179 if (!dev->encoders) {
180 printf("failed to allocate encoders\n");
181 goto err;
182 }
183 for (i = 0; i < dev->num_encoders; i++) {
184 dev->encoders[i] = drmModeGetEncoder(dev->fd, r->encoders[i]);
185 if (!dev->encoders[i]) {
186 printf("failed to get encoder %d\n", i);
187 goto err;
188 }
189 }
190
191 dev->num_crtcs = r->count_crtcs;
192 dev->crtcs = calloc(dev->num_crtcs, sizeof(struct sp_crtc));
193 if (!dev->crtcs) {
194 printf("failed to allocate crtcs\n");
195 goto err;
196 }
197 for (i = 0; i < dev->num_crtcs; i++) {
198 drmModeObjectPropertiesPtr props;
199
200 dev->crtcs[i].crtc = drmModeGetCrtc(dev->fd, r->crtcs[i]);
201 if (!dev->crtcs[i].crtc) {
202 printf("failed to get crtc %d\n", i);
203 goto err;
204 }
205 dev->crtcs[i].pipe = i;
206 dev->crtcs[i].num_planes = 0;
207
208 props = drmModeObjectGetProperties(dev->fd, r->crtcs[i],
209 DRM_MODE_OBJECT_CRTC);
210 if (!props) {
211 printf("failed to get crtc properties\n");
212 goto err;
213 }
214
215 dev->crtcs[i].mode_pid = get_prop_id(dev, props, "MODE_ID");
216 dev->crtcs[i].active_pid = get_prop_id(dev, props, "ACTIVE");
217 drmModeFreeObjectProperties(props);
218 if (!dev->crtcs[i].mode_pid || !dev->crtcs[i].active_pid)
219 goto err;
220 }
221
222 pr = drmModeGetPlaneResources(dev->fd);
223 if (!pr) {
224 printf("failed to get plane resources\n");
225 goto err;
226 }
227 dev->num_planes = pr->count_planes;
228 dev->planes = calloc(dev->num_planes, sizeof(struct sp_plane));
229 for(i = 0; i < dev->num_planes; i++) {
230 drmModeObjectPropertiesPtr props;
231 struct sp_plane *plane = &dev->planes[i];
232
233 plane->dev = dev;
234 plane->plane = drmModeGetPlane(dev->fd, pr->planes[i]);
235 if (!plane->plane) {
236 printf("failed to get plane %d\n", i);
237 goto err;
238 }
239 plane->bo = NULL;
240 plane->in_use = 0;
241
242 ret = get_supported_format(plane, &plane->format);
243 if (ret) {
244 printf("failed to get supported format: %d\n", ret);
245 goto err;
246 }
247
248 for (j = 0; j < dev->num_crtcs; j++) {
249 if (plane->plane->possible_crtcs & (1 << j))
250 dev->crtcs[j].num_planes++;
251 }
252
253 props = drmModeObjectGetProperties(dev->fd, pr->planes[i],
254 DRM_MODE_OBJECT_PLANE);
255 if (!props) {
256 printf("failed to get plane properties\n");
257 goto err;
258 }
259 plane->crtc_pid = get_prop_id(dev, props, "CRTC_ID");
260 if (!plane->crtc_pid) {
261 drmModeFreeObjectProperties(props);
262 goto err;
263 }
264 plane->fb_pid = get_prop_id(dev, props, "FB_ID");
265 if (!plane->fb_pid) {
266 drmModeFreeObjectProperties(props);
267 goto err;
268 }
269 plane->crtc_x_pid = get_prop_id(dev, props, "CRTC_X");
270 if (!plane->crtc_x_pid) {
271 drmModeFreeObjectProperties(props);
272 goto err;
273 }
274 plane->crtc_y_pid = get_prop_id(dev, props, "CRTC_Y");
275 if (!plane->crtc_y_pid) {
276 drmModeFreeObjectProperties(props);
277 goto err;
278 }
279 plane->crtc_w_pid = get_prop_id(dev, props, "CRTC_W");
280 if (!plane->crtc_w_pid) {
281 drmModeFreeObjectProperties(props);
282 goto err;
283 }
284 plane->crtc_h_pid = get_prop_id(dev, props, "CRTC_H");
285 if (!plane->crtc_h_pid) {
286 drmModeFreeObjectProperties(props);
287 goto err;
288 }
289 plane->src_x_pid = get_prop_id(dev, props, "SRC_X");
290 if (!plane->src_x_pid) {
291 drmModeFreeObjectProperties(props);
292 goto err;
293 }
294 plane->src_y_pid = get_prop_id(dev, props, "SRC_Y");
295 if (!plane->src_y_pid) {
296 drmModeFreeObjectProperties(props);
297 goto err;
298 }
299 plane->src_w_pid = get_prop_id(dev, props, "SRC_W");
300 if (!plane->src_w_pid) {
301 drmModeFreeObjectProperties(props);
302 goto err;
303 }
304 plane->src_h_pid = get_prop_id(dev, props, "SRC_H");
305 if (!plane->src_h_pid) {
306 drmModeFreeObjectProperties(props);
307 goto err;
308 }
309 drmModeFreeObjectProperties(props);
310 }
311
312 if (pr)
313 drmModeFreePlaneResources(pr);
314 if (r)
315 drmModeFreeResources(r);
316
317 return dev;
318 err:
319 if (pr)
320 drmModeFreePlaneResources(pr);
321 if (r)
322 drmModeFreeResources(r);
323 destroy_sp_dev(dev);
324 return NULL;
325 }
326
destroy_sp_dev(struct sp_dev * dev)327 void destroy_sp_dev(struct sp_dev *dev)
328 {
329 int i;
330
331 if (dev->planes) {
332 for (i = 0; i< dev->num_planes; i++) {
333 if (dev->planes[i].in_use)
334 put_sp_plane(&dev->planes[i]);
335 if (dev->planes[i].plane)
336 drmModeFreePlane(dev->planes[i].plane);
337 if (dev->planes[i].bo)
338 free_sp_bo(dev->planes[i].bo);
339 }
340 free(dev->planes);
341 }
342 if (dev->crtcs) {
343 for (i = 0; i< dev->num_crtcs; i++) {
344 if (dev->crtcs[i].crtc)
345 drmModeFreeCrtc(dev->crtcs[i].crtc);
346 }
347 free(dev->crtcs);
348 }
349 if (dev->encoders) {
350 for (i = 0; i< dev->num_encoders; i++) {
351 if (dev->encoders[i])
352 drmModeFreeEncoder(dev->encoders[i]);
353 }
354 free(dev->encoders);
355 }
356 if (dev->connectors) {
357 for (i = 0; i< dev->num_connectors; i++) {
358 if (dev->connectors[i].conn)
359 drmModeFreeConnector(dev->connectors[i].conn);
360 }
361 free(dev->connectors);
362 }
363
364 close(dev->fd);
365 free(dev);
366 }
367