Home | History | Annotate | Download | only in planetest
      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 
     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 
     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 
     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 
     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 
    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 
    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