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