/* * 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. */ #include #include #include #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) goto err_free_resources; 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++; } err_free_resources: 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) goto err_free_resources; 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++; } err_free_resources: 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) goto err_free_resources; 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++; } err_free_resources: 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; }