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 		    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 
    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 
    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