| /* | |
| * Copyright © 2014 NVIDIA Corporation | |
| * | |
| * Permission is hereby granted, free of charge, to any person obtaining a | |
| * copy of this software and associated documentation files (the "Software"), | |
| * to deal in the Software without restriction, including without limitation | |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| * and/or sell copies of the Software, and to permit persons to whom the | |
| * Software is furnished to do so, subject to the following conditions: | |
| * | |
| * The above copyright notice and this permission notice (including the next | |
| * paragraph) shall be included in all copies or substantial portions of the | |
| * Software. | |
| * | |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | |
| * IN THE SOFTWARE. | |
| */ | |
| #ifdef HAVE_CONFIG_H | |
| #include "config.h" | |
| #endif | |
| #include <stdio.h> | |
| #include <string.h> | |
| #include <unistd.h> | |
| #include "util/common.h" | |
| #include "libkms-test.h" | |
| static const char *const connector_names[] = { | |
| "Unknown", | |
| "VGA", | |
| "DVI-I", | |
| "DVI-D", | |
| "DVI-A", | |
| "Composite", | |
| "SVIDEO", | |
| "LVDS", | |
| "Component", | |
| "9PinDIN", | |
| "DisplayPort", | |
| "HDMI-A", | |
| "HDMI-B", | |
| "TV", | |
| "eDP", | |
| "Virtual", | |
| "DSI", | |
| }; | |
| static void kms_device_probe_screens(struct kms_device *device) | |
| { | |
| unsigned int counts[ARRAY_SIZE(connector_names)]; | |
| struct kms_screen *screen; | |
| drmModeRes *res; | |
| int i; | |
| memset(counts, 0, sizeof(counts)); | |
| res = drmModeGetResources(device->fd); | |
| if (!res) | |
| return; | |
| device->screens = calloc(res->count_connectors, sizeof(screen)); | |
| if (!device->screens) | |
| return; | |
| for (i = 0; i < res->count_connectors; i++) { | |
| unsigned int *count; | |
| const char *type; | |
| int len; | |
| screen = kms_screen_create(device, res->connectors[i]); | |
| if (!screen) | |
| continue; | |
| /* assign a unique name to this screen */ | |
| type = connector_names[screen->type]; | |
| count = &counts[screen->type]; | |
| len = snprintf(NULL, 0, "%s-%u", type, *count); | |
| screen->name = malloc(len + 1); | |
| if (!screen->name) { | |
| free(screen); | |
| continue; | |
| } | |
| snprintf(screen->name, len + 1, "%s-%u", type, *count); | |
| (*count)++; | |
| device->screens[i] = screen; | |
| device->num_screens++; | |
| } | |
| drmModeFreeResources(res); | |
| } | |
| static void kms_device_probe_crtcs(struct kms_device *device) | |
| { | |
| struct kms_crtc *crtc; | |
| drmModeRes *res; | |
| int i; | |
| res = drmModeGetResources(device->fd); | |
| if (!res) | |
| return; | |
| device->crtcs = calloc(res->count_crtcs, sizeof(crtc)); | |
| if (!device->crtcs) | |
| return; | |
| for (i = 0; i < res->count_crtcs; i++) { | |
| crtc = kms_crtc_create(device, res->crtcs[i]); | |
| if (!crtc) | |
| continue; | |
| device->crtcs[i] = crtc; | |
| device->num_crtcs++; | |
| } | |
| drmModeFreeResources(res); | |
| } | |
| static void kms_device_probe_planes(struct kms_device *device) | |
| { | |
| struct kms_plane *plane; | |
| drmModePlaneRes *res; | |
| unsigned int i; | |
| res = drmModeGetPlaneResources(device->fd); | |
| if (!res) | |
| return; | |
| device->planes = calloc(res->count_planes, sizeof(plane)); | |
| if (!device->planes) | |
| return; | |
| for (i = 0; i < res->count_planes; i++) { | |
| plane = kms_plane_create(device, res->planes[i]); | |
| if (!plane) | |
| continue; | |
| device->planes[i] = plane; | |
| device->num_planes++; | |
| } | |
| drmModeFreePlaneResources(res); | |
| } | |
| static void kms_device_probe(struct kms_device *device) | |
| { | |
| kms_device_probe_screens(device); | |
| kms_device_probe_crtcs(device); | |
| kms_device_probe_planes(device); | |
| } | |
| struct kms_device *kms_device_open(int fd) | |
| { | |
| struct kms_device *device; | |
| device = calloc(1, sizeof(*device)); | |
| if (!device) | |
| return NULL; | |
| device->fd = fd; | |
| kms_device_probe(device); | |
| return device; | |
| } | |
| void kms_device_close(struct kms_device *device) | |
| { | |
| unsigned int i; | |
| for (i = 0; i < device->num_planes; i++) | |
| kms_plane_free(device->planes[i]); | |
| free(device->planes); | |
| for (i = 0; i < device->num_crtcs; i++) | |
| kms_crtc_free(device->crtcs[i]); | |
| free(device->crtcs); | |
| for (i = 0; i < device->num_screens; i++) | |
| kms_screen_free(device->screens[i]); | |
| free(device->screens); | |
| if (device->fd >= 0) | |
| close(device->fd); | |
| free(device); | |
| } | |
| struct kms_plane *kms_device_find_plane_by_type(struct kms_device *device, | |
| uint32_t type, | |
| unsigned int index) | |
| { | |
| unsigned int i; | |
| for (i = 0; i < device->num_planes; i++) { | |
| if (device->planes[i]->type == type) { | |
| if (index == 0) | |
| return device->planes[i]; | |
| index--; | |
| } | |
| } | |
| return NULL; | |
| } |