• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 		    plane->plane->formats[i] == DRM_FORMAT_NV12) {
98 			*format = plane->plane->formats[i];
99 			return 0;
100 		}
101 	}
102 	printf("No suitable formats found!\n");
103 	return -ENOENT;
104 }
105 
create_sp_dev(int card)106 struct sp_dev *create_sp_dev(int card)
107 {
108 	struct sp_dev *dev;
109 	int ret, fd, i, j;
110 	drmModeRes *r = NULL;
111 	drmModePlaneRes *pr = NULL;
112 	char card_path[256];
113 
114 	snprintf(card_path, sizeof(card_path), "/dev/dri/card%d", card);
115 
116 	fd = open(card_path, O_RDWR);
117 	if (fd < 0) {
118 		printf("failed to open card0\n");
119 		return NULL;
120 	}
121 
122 	dev = calloc(1, sizeof(*dev));
123 	if (!dev) {
124 		printf("failed to allocate dev\n");
125 		return NULL;
126 	}
127 
128 	dev->fd = fd;
129 
130 	ret = drmSetClientCap(dev->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
131 	if (ret) {
132 		printf("failed to set client cap\n");
133 		goto err;
134 	}
135 
136 	ret = drmSetClientCap(dev->fd, DRM_CLIENT_CAP_ATOMIC, 1);
137 	if (ret) {
138 		printf("Failed to set atomic cap %d", ret);
139 		goto err;
140 	}
141 
142 	r = drmModeGetResources(dev->fd);
143 	if (!r) {
144 		printf("failed to get r\n");
145 		goto err;
146 	}
147 
148 	dev->num_connectors = r->count_connectors;
149 	dev->connectors = calloc(dev->num_connectors,
150 				sizeof(struct sp_connector));
151 	if (!dev->connectors) {
152 		printf("failed to allocate connectors\n");
153 		goto err;
154 	}
155 	for (i = 0; i < dev->num_connectors; i++) {
156 		drmModeObjectPropertiesPtr props;
157 		dev->connectors[i].conn = drmModeGetConnector(dev->fd,
158 					r->connectors[i]);
159 		if (!dev->connectors[i].conn) {
160 			printf("failed to get connector %d\n", i);
161 			goto err;
162 		}
163 
164 		props = drmModeObjectGetProperties(dev->fd, r->connectors[i],
165 				DRM_MODE_OBJECT_CONNECTOR);
166 		if (!props) {
167 			printf("failed to get connector properties\n");
168 			goto err;
169 		}
170 
171 		dev->connectors[i].crtc_id_pid = get_prop_id(dev, props,
172 								"CRTC_ID");
173 		drmModeFreeObjectProperties(props);
174 		if (!dev->connectors[i].crtc_id_pid)
175 			goto err;
176 	}
177 
178 	dev->num_encoders = r->count_encoders;
179 	dev->encoders = calloc(dev->num_encoders, sizeof(*dev->encoders));
180 	if (!dev->encoders) {
181 		printf("failed to allocate encoders\n");
182 		goto err;
183 	}
184 	for (i = 0; i < dev->num_encoders; i++) {
185 		dev->encoders[i] = drmModeGetEncoder(dev->fd, r->encoders[i]);
186 		if (!dev->encoders[i]) {
187 			printf("failed to get encoder %d\n", i);
188 			goto err;
189 		}
190 	}
191 
192 	dev->num_crtcs = r->count_crtcs;
193 	dev->crtcs = calloc(dev->num_crtcs, sizeof(struct sp_crtc));
194 	if (!dev->crtcs) {
195 		printf("failed to allocate crtcs\n");
196 		goto err;
197 	}
198 	for (i = 0; i < dev->num_crtcs; i++) {
199 		drmModeObjectPropertiesPtr props;
200 
201 		dev->crtcs[i].crtc = drmModeGetCrtc(dev->fd, r->crtcs[i]);
202 		if (!dev->crtcs[i].crtc) {
203 			printf("failed to get crtc %d\n", i);
204 			goto err;
205 		}
206 		dev->crtcs[i].pipe = i;
207 		dev->crtcs[i].num_planes = 0;
208 
209 		props = drmModeObjectGetProperties(dev->fd, r->crtcs[i],
210 				DRM_MODE_OBJECT_CRTC);
211 		if (!props) {
212 			printf("failed to get crtc properties\n");
213 			goto err;
214 		}
215 
216 		dev->crtcs[i].mode_pid = get_prop_id(dev, props, "MODE_ID");
217 		dev->crtcs[i].active_pid = get_prop_id(dev, props, "ACTIVE");
218 		drmModeFreeObjectProperties(props);
219 		if (!dev->crtcs[i].mode_pid || !dev->crtcs[i].active_pid)
220 			goto err;
221 	}
222 
223 	pr = drmModeGetPlaneResources(dev->fd);
224 	if (!pr) {
225 		printf("failed to get plane resources\n");
226 		goto err;
227 	}
228 	dev->num_planes = pr->count_planes;
229 	dev->planes = calloc(dev->num_planes, sizeof(struct sp_plane));
230 	for(i = 0; i < dev->num_planes; i++) {
231 		drmModeObjectPropertiesPtr props;
232 		struct sp_plane *plane = &dev->planes[i];
233 
234 		plane->dev = dev;
235 		plane->plane = drmModeGetPlane(dev->fd, pr->planes[i]);
236 		if (!plane->plane) {
237 			printf("failed to get plane %d\n", i);
238 			goto err;
239 		}
240 		plane->bo = NULL;
241 		plane->in_use = 0;
242 
243 		ret = get_supported_format(plane, &plane->format);
244 		if (ret) {
245 			printf("failed to get supported format: %d\n", ret);
246 			goto err;
247 		}
248 
249 		for (j = 0; j < dev->num_crtcs; j++) {
250 			if (plane->plane->possible_crtcs & (1 << j))
251 				dev->crtcs[j].num_planes++;
252 		}
253 
254 		props = drmModeObjectGetProperties(dev->fd, pr->planes[i],
255 				DRM_MODE_OBJECT_PLANE);
256 		if (!props) {
257 			printf("failed to get plane properties\n");
258 			goto err;
259 		}
260 		plane->crtc_pid = get_prop_id(dev, props, "CRTC_ID");
261 		if (!plane->crtc_pid) {
262 			drmModeFreeObjectProperties(props);
263 			goto err;
264 		}
265 		plane->fb_pid = get_prop_id(dev, props, "FB_ID");
266 		if (!plane->fb_pid) {
267 			drmModeFreeObjectProperties(props);
268 			goto err;
269 		}
270 		plane->crtc_x_pid = get_prop_id(dev, props, "CRTC_X");
271 		if (!plane->crtc_x_pid) {
272 			drmModeFreeObjectProperties(props);
273 			goto err;
274 		}
275 		plane->crtc_y_pid = get_prop_id(dev, props, "CRTC_Y");
276 		if (!plane->crtc_y_pid) {
277 			drmModeFreeObjectProperties(props);
278 			goto err;
279 		}
280 		plane->crtc_w_pid = get_prop_id(dev, props, "CRTC_W");
281 		if (!plane->crtc_w_pid) {
282 			drmModeFreeObjectProperties(props);
283 			goto err;
284 		}
285 		plane->crtc_h_pid = get_prop_id(dev, props, "CRTC_H");
286 		if (!plane->crtc_h_pid) {
287 			drmModeFreeObjectProperties(props);
288 			goto err;
289 		}
290 		plane->src_x_pid = get_prop_id(dev, props, "SRC_X");
291 		if (!plane->src_x_pid) {
292 			drmModeFreeObjectProperties(props);
293 			goto err;
294 		}
295 		plane->src_y_pid = get_prop_id(dev, props, "SRC_Y");
296 		if (!plane->src_y_pid) {
297 			drmModeFreeObjectProperties(props);
298 			goto err;
299 		}
300 		plane->src_w_pid = get_prop_id(dev, props, "SRC_W");
301 		if (!plane->src_w_pid) {
302 			drmModeFreeObjectProperties(props);
303 			goto err;
304 		}
305 		plane->src_h_pid = get_prop_id(dev, props, "SRC_H");
306 		if (!plane->src_h_pid) {
307 			drmModeFreeObjectProperties(props);
308 			goto err;
309 		}
310 		drmModeFreeObjectProperties(props);
311 	}
312 
313 	if (pr)
314 		drmModeFreePlaneResources(pr);
315 	if (r)
316 		drmModeFreeResources(r);
317 
318 	return dev;
319 err:
320 	if (pr)
321 		drmModeFreePlaneResources(pr);
322 	if (r)
323 		drmModeFreeResources(r);
324 	destroy_sp_dev(dev);
325 	return NULL;
326 }
327 
destroy_sp_dev(struct sp_dev * dev)328 void destroy_sp_dev(struct sp_dev *dev)
329 {
330 	int i;
331 
332 	if (dev->planes) {
333 		for (i = 0; i< dev->num_planes; i++) {
334 			if (dev->planes[i].in_use)
335 				put_sp_plane(&dev->planes[i]);
336 			if (dev->planes[i].plane)
337 				drmModeFreePlane(dev->planes[i].plane);
338 			if (dev->planes[i].bo)
339 				free_sp_bo(dev->planes[i].bo);
340 		}
341 		free(dev->planes);
342 	}
343 	if (dev->crtcs) {
344 		for (i = 0; i< dev->num_crtcs; i++) {
345 			if (dev->crtcs[i].crtc)
346 				drmModeFreeCrtc(dev->crtcs[i].crtc);
347 		}
348 		free(dev->crtcs);
349 	}
350 	if (dev->encoders) {
351 		for (i = 0; i< dev->num_encoders; i++) {
352 			if (dev->encoders[i])
353 				drmModeFreeEncoder(dev->encoders[i]);
354 		}
355 		free(dev->encoders);
356 	}
357 	if (dev->connectors) {
358 		for (i = 0; i< dev->num_connectors; i++) {
359 			if (dev->connectors[i].conn)
360 				drmModeFreeConnector(dev->connectors[i].conn);
361 		}
362 		free(dev->connectors);
363 	}
364 
365 	close(dev->fd);
366 	free(dev);
367 }
368