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