1/* 2 * Copyright © 2014 NVIDIA Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24#ifdef HAVE_CONFIG_H 25#include "config.h" 26#endif 27 28#include <stdio.h> 29#include <string.h> 30#include <unistd.h> 31 32#include "util/common.h" 33#include "libkms-test.h" 34 35static const char *const connector_names[] = { 36 "Unknown", 37 "VGA", 38 "DVI-I", 39 "DVI-D", 40 "DVI-A", 41 "Composite", 42 "SVIDEO", 43 "LVDS", 44 "Component", 45 "9PinDIN", 46 "DisplayPort", 47 "HDMI-A", 48 "HDMI-B", 49 "TV", 50 "eDP", 51 "Virtual", 52 "DSI", 53}; 54 55static void kms_device_probe_screens(struct kms_device *device) 56{ 57 unsigned int counts[ARRAY_SIZE(connector_names)]; 58 struct kms_screen *screen; 59 drmModeRes *res; 60 int i; 61 62 memset(counts, 0, sizeof(counts)); 63 64 res = drmModeGetResources(device->fd); 65 if (!res) 66 return; 67 68 device->screens = calloc(res->count_connectors, sizeof(screen)); 69 if (!device->screens) 70 return; 71 72 for (i = 0; i < res->count_connectors; i++) { 73 unsigned int *count; 74 const char *type; 75 int len; 76 77 screen = kms_screen_create(device, res->connectors[i]); 78 if (!screen) 79 continue; 80 81 /* assign a unique name to this screen */ 82 type = connector_names[screen->type]; 83 count = &counts[screen->type]; 84 85 len = snprintf(NULL, 0, "%s-%u", type, *count); 86 87 screen->name = malloc(len + 1); 88 if (!screen->name) { 89 free(screen); 90 continue; 91 } 92 93 snprintf(screen->name, len + 1, "%s-%u", type, *count); 94 (*count)++; 95 96 device->screens[i] = screen; 97 device->num_screens++; 98 } 99 100 drmModeFreeResources(res); 101} 102 103static void kms_device_probe_crtcs(struct kms_device *device) 104{ 105 struct kms_crtc *crtc; 106 drmModeRes *res; 107 int i; 108 109 res = drmModeGetResources(device->fd); 110 if (!res) 111 return; 112 113 device->crtcs = calloc(res->count_crtcs, sizeof(crtc)); 114 if (!device->crtcs) 115 return; 116 117 for (i = 0; i < res->count_crtcs; i++) { 118 crtc = kms_crtc_create(device, res->crtcs[i]); 119 if (!crtc) 120 continue; 121 122 device->crtcs[i] = crtc; 123 device->num_crtcs++; 124 } 125 126 drmModeFreeResources(res); 127} 128 129static void kms_device_probe_planes(struct kms_device *device) 130{ 131 struct kms_plane *plane; 132 drmModePlaneRes *res; 133 unsigned int i; 134 135 res = drmModeGetPlaneResources(device->fd); 136 if (!res) 137 return; 138 139 device->planes = calloc(res->count_planes, sizeof(plane)); 140 if (!device->planes) 141 return; 142 143 for (i = 0; i < res->count_planes; i++) { 144 plane = kms_plane_create(device, res->planes[i]); 145 if (!plane) 146 continue; 147 148 device->planes[i] = plane; 149 device->num_planes++; 150 } 151 152 drmModeFreePlaneResources(res); 153} 154 155static void kms_device_probe(struct kms_device *device) 156{ 157 kms_device_probe_screens(device); 158 kms_device_probe_crtcs(device); 159 kms_device_probe_planes(device); 160} 161 162struct kms_device *kms_device_open(int fd) 163{ 164 struct kms_device *device; 165 166 device = calloc(1, sizeof(*device)); 167 if (!device) 168 return NULL; 169 170 device->fd = fd; 171 172 kms_device_probe(device); 173 174 return device; 175} 176 177void kms_device_close(struct kms_device *device) 178{ 179 unsigned int i; 180 181 for (i = 0; i < device->num_planes; i++) 182 kms_plane_free(device->planes[i]); 183 184 free(device->planes); 185 186 for (i = 0; i < device->num_crtcs; i++) 187 kms_crtc_free(device->crtcs[i]); 188 189 free(device->crtcs); 190 191 for (i = 0; i < device->num_screens; i++) 192 kms_screen_free(device->screens[i]); 193 194 free(device->screens); 195 196 if (device->fd >= 0) 197 close(device->fd); 198 199 free(device); 200} 201 202struct kms_plane *kms_device_find_plane_by_type(struct kms_device *device, 203 uint32_t type, 204 unsigned int index) 205{ 206 unsigned int i; 207 208 for (i = 0; i < device->num_planes; i++) { 209 if (device->planes[i]->type == type) { 210 if (index == 0) 211 return device->planes[i]; 212 213 index--; 214 } 215 } 216 217 return NULL; 218} 219