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 #include <stdio.h>
25 #include <string.h>
26 #include <unistd.h>
27
28 #include "util/common.h"
29 #include "libkms-test.h"
30
31 static const char *const connector_names[] = {
32 "Unknown",
33 "VGA",
34 "DVI-I",
35 "DVI-D",
36 "DVI-A",
37 "Composite",
38 "SVIDEO",
39 "LVDS",
40 "Component",
41 "9PinDIN",
42 "DisplayPort",
43 "HDMI-A",
44 "HDMI-B",
45 "TV",
46 "eDP",
47 "Virtual",
48 "DSI",
49 };
50
kms_device_probe_screens(struct kms_device * device)51 static void kms_device_probe_screens(struct kms_device *device)
52 {
53 unsigned int counts[ARRAY_SIZE(connector_names)];
54 struct kms_screen *screen;
55 drmModeRes *res;
56 int i;
57
58 memset(counts, 0, sizeof(counts));
59
60 res = drmModeGetResources(device->fd);
61 if (!res)
62 return;
63
64 device->screens = calloc(res->count_connectors, sizeof(screen));
65 if (!device->screens)
66 goto err_free_resources;
67
68 for (i = 0; i < res->count_connectors; i++) {
69 unsigned int *count;
70 const char *type;
71 int len;
72
73 screen = kms_screen_create(device, res->connectors[i]);
74 if (!screen)
75 continue;
76
77 /* assign a unique name to this screen */
78 type = connector_names[screen->type];
79 count = &counts[screen->type];
80
81 len = snprintf(NULL, 0, "%s-%u", type, *count);
82
83 screen->name = malloc(len + 1);
84 if (!screen->name) {
85 free(screen);
86 continue;
87 }
88
89 snprintf(screen->name, len + 1, "%s-%u", type, *count);
90 (*count)++;
91
92 device->screens[i] = screen;
93 device->num_screens++;
94 }
95
96 err_free_resources:
97 drmModeFreeResources(res);
98 }
99
kms_device_probe_crtcs(struct kms_device * device)100 static void kms_device_probe_crtcs(struct kms_device *device)
101 {
102 struct kms_crtc *crtc;
103 drmModeRes *res;
104 int i;
105
106 res = drmModeGetResources(device->fd);
107 if (!res)
108 return;
109
110 device->crtcs = calloc(res->count_crtcs, sizeof(crtc));
111 if (!device->crtcs)
112 goto err_free_resources;
113
114 for (i = 0; i < res->count_crtcs; i++) {
115 crtc = kms_crtc_create(device, res->crtcs[i]);
116 if (!crtc)
117 continue;
118
119 device->crtcs[i] = crtc;
120 device->num_crtcs++;
121 }
122
123 err_free_resources:
124 drmModeFreeResources(res);
125 }
126
kms_device_probe_planes(struct kms_device * device)127 static void kms_device_probe_planes(struct kms_device *device)
128 {
129 struct kms_plane *plane;
130 drmModePlaneRes *res;
131 unsigned int i;
132
133 res = drmModeGetPlaneResources(device->fd);
134 if (!res)
135 return;
136
137 device->planes = calloc(res->count_planes, sizeof(plane));
138 if (!device->planes)
139 goto err_free_resources;
140
141 for (i = 0; i < res->count_planes; i++) {
142 plane = kms_plane_create(device, res->planes[i]);
143 if (!plane)
144 continue;
145
146 device->planes[i] = plane;
147 device->num_planes++;
148 }
149
150 err_free_resources:
151 drmModeFreePlaneResources(res);
152 }
153
kms_device_probe(struct kms_device * device)154 static void kms_device_probe(struct kms_device *device)
155 {
156 kms_device_probe_screens(device);
157 kms_device_probe_crtcs(device);
158 kms_device_probe_planes(device);
159 }
160
kms_device_open(int fd)161 struct kms_device *kms_device_open(int fd)
162 {
163 struct kms_device *device;
164
165 device = calloc(1, sizeof(*device));
166 if (!device)
167 return NULL;
168
169 device->fd = fd;
170
171 kms_device_probe(device);
172
173 return device;
174 }
175
kms_device_close(struct kms_device * device)176 void kms_device_close(struct kms_device *device)
177 {
178 unsigned int i;
179
180 for (i = 0; i < device->num_planes; i++)
181 kms_plane_free(device->planes[i]);
182
183 free(device->planes);
184
185 for (i = 0; i < device->num_crtcs; i++)
186 kms_crtc_free(device->crtcs[i]);
187
188 free(device->crtcs);
189
190 for (i = 0; i < device->num_screens; i++)
191 kms_screen_free(device->screens[i]);
192
193 free(device->screens);
194
195 if (device->fd >= 0)
196 close(device->fd);
197
198 free(device);
199 }
200
kms_device_find_plane_by_type(struct kms_device * device,uint32_t type,unsigned int index)201 struct kms_plane *kms_device_find_plane_by_type(struct kms_device *device,
202 uint32_t type,
203 unsigned int index)
204 {
205 unsigned int i;
206
207 for (i = 0; i < device->num_planes; i++) {
208 if (device->planes[i]->type == type) {
209 if (index == 0)
210 return device->planes[i];
211
212 index--;
213 }
214 }
215
216 return NULL;
217 }
218