• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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