diff options
author | Jesse Barnes | 2008-12-17 12:09:49 -0600 |
---|---|---|
committer | Jesse Barnes | 2008-12-17 12:11:37 -0600 |
commit | 731cd5526e5c732d51307b26e784f454a724a699 (patch) | |
tree | 215249e4aa86a3d8418b7f5cad95551d49ecce2d /tests | |
parent | c86d431fe6174b1c2de531929213ea7dbd92326d (diff) | |
download | external-libdrm-731cd5526e5c732d51307b26e784f454a724a699.tar.gz external-libdrm-731cd5526e5c732d51307b26e784f454a724a699.tar.xz external-libdrm-731cd5526e5c732d51307b26e784f454a724a699.zip |
libdrm: add mode setting files
Add mode setting files to libdrm, including xf86drmMode.* and the new
drm_mode.h header. Also add a couple of tests to sanity check the
kernel interfaces and update code to support them.
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Makefile.am | 4 | ||||
-rw-r--r-- | tests/dristat.c | 2 | ||||
-rw-r--r-- | tests/modeprint/Makefile | 14 | ||||
-rwxr-xr-x | tests/modeprint/app | bin | 0 -> 16233 bytes | |||
-rw-r--r-- | tests/modeprint/modeprint.c | 402 | ||||
-rw-r--r-- | tests/modeprint/test | 1 | ||||
-rw-r--r-- | tests/modetest/Makefile | 14 | ||||
-rw-r--r-- | tests/modetest/modetest.c | 449 | ||||
-rw-r--r-- | tests/modetest/test | 2 |
9 files changed, 887 insertions, 1 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am index 95f0f22e..02b2ef0a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am | |||
@@ -15,6 +15,10 @@ libdrmtest_la_LIBADD = \ | |||
15 | 15 | ||
16 | LDADD = libdrmtest.la | 16 | LDADD = libdrmtest.la |
17 | 17 | ||
18 | noinst_SUBDIRS = \ | ||
19 | modeprint \ | ||
20 | modetest | ||
21 | |||
18 | TESTS = auth \ | 22 | TESTS = auth \ |
19 | openclose \ | 23 | openclose \ |
20 | getversion \ | 24 | getversion \ |
diff --git a/tests/dristat.c b/tests/dristat.c index 89853164..48c3b51b 100644 --- a/tests/dristat.c +++ b/tests/dristat.c | |||
@@ -263,7 +263,7 @@ int main(int argc, char **argv) | |||
263 | 263 | ||
264 | for (i = 0; i < 16; i++) if (!minor || i == minor) { | 264 | for (i = 0; i < 16; i++) if (!minor || i == minor) { |
265 | sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, i); | 265 | sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, i); |
266 | fd = drmOpenMinor(i, 1); | 266 | fd = drmOpenMinor(i, 1, DRM_NODE_RENDER); |
267 | if (fd >= 0) { | 267 | if (fd >= 0) { |
268 | printf("%s\n", buf); | 268 | printf("%s\n", buf); |
269 | if (mask & DRM_BUSID) getbusid(fd); | 269 | if (mask & DRM_BUSID) getbusid(fd); |
diff --git a/tests/modeprint/Makefile b/tests/modeprint/Makefile new file mode 100644 index 00000000..70788dc9 --- /dev/null +++ b/tests/modeprint/Makefile | |||
@@ -0,0 +1,14 @@ | |||
1 | |||
2 | all: app | ||
3 | |||
4 | #CFLAGS = -g -ansi -pedantic -DPOSIX_C_SOURCE=199309L \ | ||
5 | # -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_BSD_SOURCE -D_SVID_SOURCE \ | ||
6 | |||
7 | app: modeprint.c | ||
8 | @gcc $(CFLAGS) -o app -Wall -I../../libdrm -I../../shared-core -L../../libdrm/.libs -ldrm modeprint.c | ||
9 | |||
10 | clean: | ||
11 | @rm -f app | ||
12 | |||
13 | run: app | ||
14 | @sudo ./test | ||
diff --git a/tests/modeprint/app b/tests/modeprint/app new file mode 100755 index 00000000..82085c85 --- /dev/null +++ b/tests/modeprint/app | |||
Binary files differ | |||
diff --git a/tests/modeprint/modeprint.c b/tests/modeprint/modeprint.c new file mode 100644 index 00000000..595d4447 --- /dev/null +++ b/tests/modeprint/modeprint.c | |||
@@ -0,0 +1,402 @@ | |||
1 | /* | ||
2 | * \file modedemo.c | ||
3 | * Test program to dump DRM kernel mode setting related information. | ||
4 | * Queries the kernel for all available information and dumps it to stdout. | ||
5 | * | ||
6 | * \author Jakob Bornecrantz <wallbraker@gmail.com> | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas. | ||
11 | * Copyright (c) 2007-2008 Jakob Bornecrantz <wallbraker@gmail.com> | ||
12 | * | ||
13 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
14 | * copy of this software and associated documentation files (the "Software"), | ||
15 | * to deal in the Software without restriction, including without limitation | ||
16 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
17 | * and/or sell copies of the Software, and to permit persons to whom the | ||
18 | * Software is furnished to do so, subject to the following conditions: | ||
19 | * | ||
20 | * The above copyright notice and this permission notice shall be included in | ||
21 | * all copies or substantial portions of the Software. | ||
22 | * | ||
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
24 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
26 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
27 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
28 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
29 | * IN THE SOFTWARE. | ||
30 | * | ||
31 | */ | ||
32 | |||
33 | #include <assert.h> | ||
34 | #include <stdio.h> | ||
35 | #include <stdlib.h> | ||
36 | #include <stdint.h> | ||
37 | #include <unistd.h> | ||
38 | #include <string.h> | ||
39 | |||
40 | #include "xf86drm.h" | ||
41 | #include "xf86drmMode.h" | ||
42 | |||
43 | int connectors; | ||
44 | int full_props; | ||
45 | int edid; | ||
46 | int modes; | ||
47 | int full_modes; | ||
48 | int encoders; | ||
49 | int crtcs; | ||
50 | int fbs; | ||
51 | char *module_name; | ||
52 | |||
53 | const char* getConnectionText(drmModeConnection conn) | ||
54 | { | ||
55 | switch (conn) { | ||
56 | case DRM_MODE_CONNECTED: | ||
57 | return "connected"; | ||
58 | case DRM_MODE_DISCONNECTED: | ||
59 | return "disconnected"; | ||
60 | default: | ||
61 | return "unknown"; | ||
62 | } | ||
63 | |||
64 | } | ||
65 | |||
66 | int printMode(struct drm_mode_modeinfo *mode) | ||
67 | { | ||
68 | if (full_modes) { | ||
69 | printf("Mode: %s\n", mode->name); | ||
70 | printf("\tclock : %i\n", mode->clock); | ||
71 | printf("\thdisplay : %i\n", mode->hdisplay); | ||
72 | printf("\thsync_start : %i\n", mode->hsync_start); | ||
73 | printf("\thsync_end : %i\n", mode->hsync_end); | ||
74 | printf("\thtotal : %i\n", mode->htotal); | ||
75 | printf("\thskew : %i\n", mode->hskew); | ||
76 | printf("\tvdisplay : %i\n", mode->vdisplay); | ||
77 | printf("\tvsync_start : %i\n", mode->vsync_start); | ||
78 | printf("\tvsync_end : %i\n", mode->vsync_end); | ||
79 | printf("\tvtotal : %i\n", mode->vtotal); | ||
80 | printf("\tvscan : %i\n", mode->vscan); | ||
81 | printf("\tvrefresh : %i\n", mode->vrefresh); | ||
82 | printf("\tflags : %i\n", mode->flags); | ||
83 | } else { | ||
84 | printf("Mode: \"%s\" %ix%i %.0f\n", mode->name, | ||
85 | mode->hdisplay, mode->vdisplay, mode->vrefresh / 1000.0); | ||
86 | } | ||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | int printProperty(int fd, drmModeResPtr res, drmModePropertyPtr props, uint64_t value) | ||
91 | { | ||
92 | const unsigned char *name = NULL; | ||
93 | int j; | ||
94 | |||
95 | printf("Property: %s\n", props->name); | ||
96 | printf("\tid : %i\n", props->prop_id); | ||
97 | printf("\tflags : %i\n", props->flags); | ||
98 | printf("\tcount_values : %d\n", props->count_values); | ||
99 | |||
100 | |||
101 | if (props->count_values) { | ||
102 | printf("\tvalues :"); | ||
103 | for (j = 0; j < props->count_values; j++) | ||
104 | printf(" %lld", props->values[j]); | ||
105 | printf("\n"); | ||
106 | } | ||
107 | |||
108 | |||
109 | printf("\tcount_enums : %d\n", props->count_enums); | ||
110 | |||
111 | if (props->flags & DRM_MODE_PROP_BLOB) { | ||
112 | drmModePropertyBlobPtr blob; | ||
113 | |||
114 | blob = drmModeGetPropertyBlob(fd, value); | ||
115 | if (blob) { | ||
116 | printf("blob is %d length, %08X\n", blob->length, *(uint32_t *)blob->data); | ||
117 | drmModeFreePropertyBlob(blob); | ||
118 | } else { | ||
119 | printf("error getting blob %lld\n", value); | ||
120 | } | ||
121 | |||
122 | } else { | ||
123 | if (!strncmp(props->name, "DPMS", 4)) | ||
124 | ; | ||
125 | |||
126 | for (j = 0; j < props->count_enums; j++) { | ||
127 | printf("\t\t%lld = %s\n", props->enums[j].value, props->enums[j].name); | ||
128 | if (props->enums[j].value == value) | ||
129 | name = props->enums[j].name; | ||
130 | } | ||
131 | |||
132 | if (props->count_enums && name) { | ||
133 | printf("\tcon_value : %s\n", name); | ||
134 | } else { | ||
135 | printf("\tcon_value : %lld\n", value); | ||
136 | } | ||
137 | } | ||
138 | |||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | int printConnector(int fd, drmModeResPtr res, drmModeConnectorPtr connector, uint32_t id) | ||
143 | { | ||
144 | int i = 0; | ||
145 | struct drm_mode_modeinfo *mode = NULL; | ||
146 | drmModePropertyPtr props; | ||
147 | |||
148 | printf("Connector: %d-%d\n", connector->connector_type, connector->connector_type_id); | ||
149 | printf("\tid : %i\n", id); | ||
150 | printf("\tencoder id : %i\n", connector->encoder_id); | ||
151 | printf("\tconn : %s\n", getConnectionText(connector->connection)); | ||
152 | printf("\tsize : %ix%i (mm)\n", connector->mmWidth, connector->mmHeight); | ||
153 | printf("\tcount_modes : %i\n", connector->count_modes); | ||
154 | printf("\tcount_props : %i\n", connector->count_props); | ||
155 | if (connector->count_props) { | ||
156 | printf("\tprops :"); | ||
157 | for (i = 0; i < connector->count_props; i++) | ||
158 | printf(" %i", connector->props[i]); | ||
159 | printf("\n"); | ||
160 | } | ||
161 | |||
162 | printf("\tcount_encoders : %i\n", connector->count_encoders); | ||
163 | if (connector->count_encoders) { | ||
164 | printf("\tencoders :"); | ||
165 | for (i = 0; i < connector->count_encoders; i++) | ||
166 | printf(" %i", connector->encoders[i]); | ||
167 | printf("\n"); | ||
168 | } | ||
169 | |||
170 | if (modes) { | ||
171 | for (i = 0; i < connector->count_modes; i++) { | ||
172 | mode = &connector->modes[i]; | ||
173 | printMode(mode); | ||
174 | } | ||
175 | } | ||
176 | |||
177 | if (full_props) { | ||
178 | for (i = 0; i < connector->count_props; i++) { | ||
179 | props = drmModeGetProperty(fd, connector->props[i]); | ||
180 | if (props) { | ||
181 | printProperty(fd, res, props, connector->prop_values[i]); | ||
182 | drmModeFreeProperty(props); | ||
183 | } | ||
184 | } | ||
185 | } | ||
186 | |||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | int printEncoder(int fd, drmModeResPtr res, drmModeEncoderPtr encoder, uint32_t id) | ||
191 | { | ||
192 | printf("Encoder\n"); | ||
193 | printf("\tid :%i\n", id); | ||
194 | printf("\tcrtc_id :%d\n", encoder->crtc_id); | ||
195 | printf("\ttype :%d\n", encoder->encoder_type); | ||
196 | printf("\tpossible_crtcs :%d\n", encoder->possible_crtcs); | ||
197 | printf("\tpossible_clones :%d\n", encoder->possible_clones); | ||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | int printCrtc(int fd, drmModeResPtr res, drmModeCrtcPtr crtc, uint32_t id) | ||
202 | { | ||
203 | printf("Crtc\n"); | ||
204 | printf("\tid : %i\n", id); | ||
205 | printf("\tx : %i\n", crtc->x); | ||
206 | printf("\ty : %i\n", crtc->y); | ||
207 | printf("\twidth : %i\n", crtc->width); | ||
208 | printf("\theight : %i\n", crtc->height); | ||
209 | printf("\tmode : %p\n", &crtc->mode); | ||
210 | printf("\tgamma size : %d\n", crtc->gamma_size); | ||
211 | |||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | int printFrameBuffer(int fd, drmModeResPtr res, drmModeFBPtr fb) | ||
216 | { | ||
217 | printf("Framebuffer\n"); | ||
218 | printf("\thandle : %i\n", fb->handle); | ||
219 | printf("\twidth : %i\n", fb->width); | ||
220 | printf("\theight : %i\n", fb->height); | ||
221 | printf("\tpitch : %i\n", fb->pitch);; | ||
222 | printf("\tbpp : %i\n", fb->bpp); | ||
223 | printf("\tdepth : %i\n", fb->depth); | ||
224 | printf("\tbuffer_id : %i\n", fb->handle); | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | int printRes(int fd, drmModeResPtr res) | ||
230 | { | ||
231 | int i; | ||
232 | drmModeFBPtr fb; | ||
233 | drmModeCrtcPtr crtc; | ||
234 | drmModeEncoderPtr encoder; | ||
235 | drmModeConnectorPtr connector; | ||
236 | |||
237 | printf("Resources\n\n"); | ||
238 | |||
239 | printf("count_connectors : %i\n", res->count_connectors); | ||
240 | printf("count_encoders : %i\n", res->count_encoders); | ||
241 | printf("count_crtcs : %i\n", res->count_crtcs); | ||
242 | printf("count_fbs : %i\n", res->count_fbs); | ||
243 | |||
244 | printf("\n"); | ||
245 | |||
246 | if (connectors) { | ||
247 | for (i = 0; i < res->count_connectors; i++) { | ||
248 | connector = drmModeGetConnector(fd, res->connectors[i]); | ||
249 | |||
250 | if (!connector) | ||
251 | printf("Could not get connector %i\n", res->connectors[i]); | ||
252 | else { | ||
253 | printConnector(fd, res, connector, res->connectors[i]); | ||
254 | drmModeFreeConnector(connector); | ||
255 | } | ||
256 | } | ||
257 | printf("\n"); | ||
258 | } | ||
259 | |||
260 | |||
261 | if (encoders) { | ||
262 | for (i = 0; i < res->count_encoders; i++) { | ||
263 | encoder = drmModeGetEncoder(fd, res->encoders[i]); | ||
264 | |||
265 | if (!encoder) | ||
266 | printf("Could not get encoder %i\n", res->encoders[i]); | ||
267 | else { | ||
268 | printEncoder(fd, res, encoder, res->encoders[i]); | ||
269 | drmModeFreeEncoder(encoder); | ||
270 | } | ||
271 | } | ||
272 | printf("\n"); | ||
273 | } | ||
274 | |||
275 | if (crtcs) { | ||
276 | for (i = 0; i < res->count_crtcs; i++) { | ||
277 | crtc = drmModeGetCrtc(fd, res->crtcs[i]); | ||
278 | |||
279 | if (!crtc) | ||
280 | printf("Could not get crtc %i\n", res->crtcs[i]); | ||
281 | else { | ||
282 | printCrtc(fd, res, crtc, res->crtcs[i]); | ||
283 | drmModeFreeCrtc(crtc); | ||
284 | } | ||
285 | } | ||
286 | printf("\n"); | ||
287 | } | ||
288 | |||
289 | if (fbs) { | ||
290 | for (i = 0; i < res->count_fbs; i++) { | ||
291 | fb = drmModeGetFB(fd, res->fbs[i]); | ||
292 | |||
293 | if (!fb) | ||
294 | printf("Could not get fb %i\n", res->fbs[i]); | ||
295 | else { | ||
296 | printFrameBuffer(fd, res, fb); | ||
297 | drmModeFreeFB(fb); | ||
298 | } | ||
299 | } | ||
300 | } | ||
301 | |||
302 | return 0; | ||
303 | } | ||
304 | |||
305 | void args(int argc, char **argv) | ||
306 | { | ||
307 | int i; | ||
308 | |||
309 | fbs = 0; | ||
310 | edid = 0; | ||
311 | crtcs = 0; | ||
312 | modes = 0; | ||
313 | encoders = 0; | ||
314 | full_modes = 0; | ||
315 | full_props = 0; | ||
316 | connectors = 0; | ||
317 | |||
318 | module_name = argv[1]; | ||
319 | |||
320 | for (i = 2; i < argc; i++) { | ||
321 | if (strcmp(argv[i], "-fb") == 0) { | ||
322 | fbs = 1; | ||
323 | } else if (strcmp(argv[i], "-crtcs") == 0) { | ||
324 | crtcs = 1; | ||
325 | } else if (strcmp(argv[i], "-cons") == 0) { | ||
326 | connectors = 1; | ||
327 | modes = 1; | ||
328 | } else if (strcmp(argv[i], "-modes") == 0) { | ||
329 | connectors = 1; | ||
330 | modes = 1; | ||
331 | } else if (strcmp(argv[i], "-full") == 0) { | ||
332 | connectors = 1; | ||
333 | modes = 1; | ||
334 | full_modes = 1; | ||
335 | } else if (strcmp(argv[i], "-props") == 0) { | ||
336 | connectors = 1; | ||
337 | full_props = 1; | ||
338 | } else if (strcmp(argv[i], "-edids") == 0) { | ||
339 | connectors = 1; | ||
340 | edid = 1; | ||
341 | } else if (strcmp(argv[i], "-encoders") == 0) { | ||
342 | encoders = 1; | ||
343 | } else if (strcmp(argv[i], "-v") == 0) { | ||
344 | fbs = 1; | ||
345 | edid = 1; | ||
346 | crtcs = 1; | ||
347 | modes = 1; | ||
348 | encoders = 1; | ||
349 | full_modes = 1; | ||
350 | full_props = 1; | ||
351 | connectors = 1; | ||
352 | } | ||
353 | } | ||
354 | |||
355 | if (argc == 2) { | ||
356 | fbs = 1; | ||
357 | edid = 1; | ||
358 | crtcs = 1; | ||
359 | modes = 1; | ||
360 | encoders = 1; | ||
361 | full_modes = 0; | ||
362 | full_props = 0; | ||
363 | connectors = 1; | ||
364 | } | ||
365 | } | ||
366 | |||
367 | int main(int argc, char **argv) | ||
368 | { | ||
369 | int fd; | ||
370 | drmModeResPtr res; | ||
371 | |||
372 | if (argc == 1) { | ||
373 | printf("Please add modulename as first argument\n"); | ||
374 | return 1; | ||
375 | } | ||
376 | |||
377 | args(argc, argv); | ||
378 | |||
379 | printf("Starting test\n"); | ||
380 | |||
381 | fd = drmOpen(module_name, NULL); | ||
382 | |||
383 | if (fd < 0) { | ||
384 | printf("Failed to open the card fd (%d)\n",fd); | ||
385 | return 1; | ||
386 | } | ||
387 | |||
388 | res = drmModeGetResources(fd); | ||
389 | if (res == 0) { | ||
390 | printf("Failed to get resources from card\n"); | ||
391 | drmClose(fd); | ||
392 | return 1; | ||
393 | } | ||
394 | |||
395 | printRes(fd, res); | ||
396 | |||
397 | drmModeFreeResources(res); | ||
398 | |||
399 | printf("Ok\n"); | ||
400 | |||
401 | return 0; | ||
402 | } | ||
diff --git a/tests/modeprint/test b/tests/modeprint/test new file mode 100644 index 00000000..bd1952cc --- /dev/null +++ b/tests/modeprint/test | |||
@@ -0,0 +1 @@ | |||
LD_PRELOAD=../../libdrm/.libs/libdrm.so ./app $@ | |||
diff --git a/tests/modetest/Makefile b/tests/modetest/Makefile new file mode 100644 index 00000000..8583ae82 --- /dev/null +++ b/tests/modetest/Makefile | |||
@@ -0,0 +1,14 @@ | |||
1 | |||
2 | all: app | ||
3 | |||
4 | #CFLAGS = -g -ansi -pedantic -DPOSIX_C_SOURCE=199309L \ | ||
5 | # -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_BSD_SOURCE -D_SVID_SOURCE \ | ||
6 | |||
7 | app: modetest.c | ||
8 | gcc $(CFLAGS) -o app -Wall -I../../libdrm -I../../libdrm/intel -I../../shared-core -L../../libdrm/.libs -L../../libdrm/intel/.libs -ldrm -ldrm_intel modetest.c | ||
9 | |||
10 | clean: | ||
11 | @rm -f app | ||
12 | |||
13 | run: app | ||
14 | sudo ./test | ||
diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c new file mode 100644 index 00000000..e5a16e1a --- /dev/null +++ b/tests/modetest/modetest.c | |||
@@ -0,0 +1,449 @@ | |||
1 | /* | ||
2 | * DRM based mode setting test program | ||
3 | * Copyright 2008 Tungsten Graphics | ||
4 | * Jakob Bornecrantz <jakob@tungstengraphics.com> | ||
5 | * Copyright 2008 Intel Corporation | ||
6 | * Jesse Barnes <jesse.barnes@intel.com> | ||
7 | * | ||
8 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
9 | * copy of this software and associated documentation files (the "Software"), | ||
10 | * to deal in the Software without restriction, including without limitation | ||
11 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
12 | * and/or sell copies of the Software, and to permit persons to whom the | ||
13 | * Software is furnished to do so, subject to the following conditions: | ||
14 | * | ||
15 | * The above copyright notice and this permission notice shall be included in | ||
16 | * all copies or substantial portions of the Software. | ||
17 | * | ||
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
23 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
24 | * IN THE SOFTWARE. | ||
25 | */ | ||
26 | |||
27 | /* | ||
28 | * This fairly simple test program dumps output in a similar format to the | ||
29 | * "xrandr" tool everyone knows & loves. It's necessarily slightly different | ||
30 | * since the kernel separates outputs into encoder and connector structures, | ||
31 | * each with their own unique ID. The program also allows test testing of the | ||
32 | * memory management and mode setting APIs by allowing the user to specify a | ||
33 | * connector and mode to use for mode setting. If all works as expected, a | ||
34 | * blue background should be painted on the monitor attached to the specified | ||
35 | * connector after the selected mode is set. | ||
36 | * | ||
37 | * TODO: use cairo to write the mode info on the selected output once | ||
38 | * the mode has been programmed, along with possible test patterns. | ||
39 | */ | ||
40 | #include <assert.h> | ||
41 | #include <stdio.h> | ||
42 | #include <stdlib.h> | ||
43 | #include <stdint.h> | ||
44 | #include <unistd.h> | ||
45 | #include <string.h> | ||
46 | #include <errno.h> | ||
47 | |||
48 | #include "xf86drm.h" | ||
49 | #include "xf86drmMode.h" | ||
50 | #include "intel_bufmgr.h" | ||
51 | |||
52 | drmModeRes *resources; | ||
53 | int fd, modes; | ||
54 | |||
55 | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) | ||
56 | |||
57 | struct type_name { | ||
58 | int type; | ||
59 | char *name; | ||
60 | }; | ||
61 | |||
62 | #define type_name_fn(res) \ | ||
63 | char * res##_str(int type) { \ | ||
64 | int i; \ | ||
65 | for (i = 0; i < ARRAY_SIZE(res##_names); i++) { \ | ||
66 | if (res##_names[i].type == type) \ | ||
67 | return res##_names[i].name; \ | ||
68 | } \ | ||
69 | return "(invalid)"; \ | ||
70 | } | ||
71 | |||
72 | struct type_name encoder_type_names[] = { | ||
73 | { DRM_MODE_ENCODER_NONE, "none" }, | ||
74 | { DRM_MODE_ENCODER_DAC, "DAC" }, | ||
75 | { DRM_MODE_ENCODER_TMDS, "TMDS" }, | ||
76 | { DRM_MODE_ENCODER_LVDS, "LVDS" }, | ||
77 | { DRM_MODE_ENCODER_TVDAC, "TVDAC" }, | ||
78 | }; | ||
79 | |||
80 | type_name_fn(encoder_type) | ||
81 | |||
82 | struct type_name connector_status_names[] = { | ||
83 | { DRM_MODE_CONNECTED, "connected" }, | ||
84 | { DRM_MODE_DISCONNECTED, "disconnected" }, | ||
85 | { DRM_MODE_UNKNOWNCONNECTION, "unknown" }, | ||
86 | }; | ||
87 | |||
88 | type_name_fn(connector_status) | ||
89 | |||
90 | struct type_name connector_type_names[] = { | ||
91 | { DRM_MODE_CONNECTOR_Unknown, "unknown" }, | ||
92 | { DRM_MODE_CONNECTOR_VGA, "VGA" }, | ||
93 | { DRM_MODE_CONNECTOR_DVII, "DVI-I" }, | ||
94 | { DRM_MODE_CONNECTOR_DVID, "DVI-D" }, | ||
95 | { DRM_MODE_CONNECTOR_DVIA, "DVI-A" }, | ||
96 | { DRM_MODE_CONNECTOR_Composite, "composite" }, | ||
97 | { DRM_MODE_CONNECTOR_SVIDEO, "s-video" }, | ||
98 | { DRM_MODE_CONNECTOR_LVDS, "LVDS" }, | ||
99 | { DRM_MODE_CONNECTOR_Component, "component" }, | ||
100 | { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" }, | ||
101 | { DRM_MODE_CONNECTOR_DisplayPort, "displayport" }, | ||
102 | { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" }, | ||
103 | { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" }, | ||
104 | }; | ||
105 | |||
106 | type_name_fn(connector_type) | ||
107 | |||
108 | void dump_encoders(void) | ||
109 | { | ||
110 | drmModeEncoder *encoder; | ||
111 | int i; | ||
112 | |||
113 | printf("Encoders:\n"); | ||
114 | printf("id\tcrtc\ttype\tpossible crtcs\tpossible clones\t\n"); | ||
115 | for (i = 0; i < resources->count_encoders; i++) { | ||
116 | encoder = drmModeGetEncoder(fd, resources->encoders[i]); | ||
117 | |||
118 | if (!encoder) { | ||
119 | fprintf(stderr, "could not get encoder %i: %s\n", | ||
120 | resources->encoders[i], strerror(errno)); | ||
121 | continue; | ||
122 | } | ||
123 | printf("%d\t%d\t%s\t0x%08x\t0x%08x\n", | ||
124 | encoder->encoder_id, | ||
125 | encoder->crtc_id, | ||
126 | encoder_type_str(encoder->encoder_type), | ||
127 | encoder->possible_crtcs, | ||
128 | encoder->possible_clones); | ||
129 | drmModeFreeEncoder(encoder); | ||
130 | } | ||
131 | } | ||
132 | |||
133 | void dump_connectors(void) | ||
134 | { | ||
135 | drmModeConnector *connector; | ||
136 | int i, j; | ||
137 | |||
138 | printf("Connectors:\n"); | ||
139 | printf("id\tencoder\tstatus\t\ttype\tsize (mm)\tmodes\n"); | ||
140 | for (i = 0; i < resources->count_connectors; i++) { | ||
141 | connector = drmModeGetConnector(fd, resources->connectors[i]); | ||
142 | |||
143 | if (!connector) { | ||
144 | fprintf(stderr, "could not get connector %i: %s\n", | ||
145 | resources->connectors[i], strerror(errno)); | ||
146 | continue; | ||
147 | } | ||
148 | |||
149 | printf("%d\t%d\t%s\t%s\t%dx%d\t\t%d\n", | ||
150 | connector->connector_id, | ||
151 | connector->encoder_id, | ||
152 | connector_status_str(connector->connection), | ||
153 | connector_type_str(connector->connector_type), | ||
154 | connector->mmWidth, connector->mmHeight, | ||
155 | connector->count_modes); | ||
156 | |||
157 | if (!connector->count_modes) | ||
158 | continue; | ||
159 | |||
160 | printf(" modes:\n"); | ||
161 | printf(" name refresh (Hz) hdisp hss hse htot vdisp " | ||
162 | "vss vse vtot)\n"); | ||
163 | for (j = 0; j < connector->count_modes; j++) { | ||
164 | struct drm_mode_modeinfo *mode; | ||
165 | |||
166 | mode = &connector->modes[j]; | ||
167 | printf(" %s %.02f %d %d %d %d %d %d %d %d\n", | ||
168 | mode->name, | ||
169 | (float)mode->vrefresh / 1000, | ||
170 | mode->hdisplay, | ||
171 | mode->hsync_start, | ||
172 | mode->hsync_end, | ||
173 | mode->htotal, | ||
174 | mode->vdisplay, | ||
175 | mode->vsync_start, | ||
176 | mode->vsync_end, | ||
177 | mode->vtotal); | ||
178 | } | ||
179 | drmModeFreeConnector(connector); | ||
180 | } | ||
181 | } | ||
182 | |||
183 | void dump_crtcs(void) | ||
184 | { | ||
185 | drmModeCrtc *crtc; | ||
186 | int i; | ||
187 | |||
188 | for (i = 0; i < resources->count_crtcs; i++) { | ||
189 | crtc = drmModeGetCrtc(fd, resources->crtcs[i]); | ||
190 | |||
191 | if (!crtc) { | ||
192 | fprintf(stderr, "could not get crtc %i: %s\n", | ||
193 | resources->crtcs[i], strerror(errno)); | ||
194 | continue; | ||
195 | } | ||
196 | drmModeFreeCrtc(crtc); | ||
197 | } | ||
198 | } | ||
199 | |||
200 | void dump_framebuffers(void) | ||
201 | { | ||
202 | drmModeFB *fb; | ||
203 | int i; | ||
204 | |||
205 | for (i = 0; i < resources->count_fbs; i++) { | ||
206 | fb = drmModeGetFB(fd, resources->fbs[i]); | ||
207 | |||
208 | if (!fb) { | ||
209 | fprintf(stderr, "could not get fb %i: %s\n", | ||
210 | resources->fbs[i], strerror(errno)); | ||
211 | continue; | ||
212 | } | ||
213 | drmModeFreeFB(fb); | ||
214 | } | ||
215 | } | ||
216 | |||
217 | /* | ||
218 | * Mode setting with the kernel interfaces is a bit of a chore. | ||
219 | * First you have to find the connector in question and make sure the | ||
220 | * requested mode is available. | ||
221 | * Then you need to find the encoder attached to that connector so you | ||
222 | * can bind it with a free crtc. | ||
223 | */ | ||
224 | void set_mode(int connector_id, char *mode_str) | ||
225 | { | ||
226 | drmModeConnector *connector; | ||
227 | drmModeEncoder *encoder = NULL; | ||
228 | struct drm_mode_modeinfo *mode = NULL; | ||
229 | drm_intel_bufmgr *bufmgr; | ||
230 | drm_intel_bo *bo; | ||
231 | unsigned int fb_id, *fb_ptr; | ||
232 | int i, j, size, ret, width, height; | ||
233 | |||
234 | /* First, find the connector & mode */ | ||
235 | for (i = 0; i < resources->count_connectors; i++) { | ||
236 | connector = drmModeGetConnector(fd, resources->connectors[i]); | ||
237 | |||
238 | if (!connector) { | ||
239 | fprintf(stderr, "could not get connector %i: %s\n", | ||
240 | resources->connectors[i], strerror(errno)); | ||
241 | drmModeFreeConnector(connector); | ||
242 | continue; | ||
243 | } | ||
244 | |||
245 | if (!connector->count_modes) { | ||
246 | drmModeFreeConnector(connector); | ||
247 | continue; | ||
248 | } | ||
249 | |||
250 | if (connector->connector_id != connector_id) { | ||
251 | drmModeFreeConnector(connector); | ||
252 | continue; | ||
253 | } | ||
254 | |||
255 | for (j = 0; j < connector->count_modes; j++) { | ||
256 | mode = &connector->modes[j]; | ||
257 | if (!strcmp(mode->name, mode_str)) | ||
258 | break; | ||
259 | } | ||
260 | |||
261 | /* Found it, break out */ | ||
262 | if (mode) | ||
263 | break; | ||
264 | |||
265 | drmModeFreeConnector(connector); | ||
266 | } | ||
267 | |||
268 | if (!mode) { | ||
269 | fprintf(stderr, "failed to find mode \"%s\"\n", mode_str); | ||
270 | return; | ||
271 | } | ||
272 | |||
273 | width = mode->hdisplay; | ||
274 | height = mode->vdisplay; | ||
275 | |||
276 | /* Now get the encoder */ | ||
277 | for (i = 0; i < resources->count_encoders; i++) { | ||
278 | encoder = drmModeGetEncoder(fd, resources->encoders[i]); | ||
279 | |||
280 | if (!encoder) { | ||
281 | fprintf(stderr, "could not get encoder %i: %s\n", | ||
282 | resources->encoders[i], strerror(errno)); | ||
283 | drmModeFreeEncoder(encoder); | ||
284 | continue; | ||
285 | } | ||
286 | |||
287 | if (encoder->encoder_id == connector->encoder_id) | ||
288 | break; | ||
289 | |||
290 | drmModeFreeEncoder(encoder); | ||
291 | } | ||
292 | |||
293 | bufmgr = drm_intel_bufmgr_gem_init(fd, 2<<20); | ||
294 | if (!bufmgr) { | ||
295 | fprintf(stderr, "failed to init bufmgr: %s\n", strerror(errno)); | ||
296 | return; | ||
297 | } | ||
298 | |||
299 | /* Mode size at 32 bpp */ | ||
300 | size = width * height * 4; | ||
301 | |||
302 | bo = drm_intel_bo_alloc(bufmgr, "frontbuffer", size, 4096); | ||
303 | if (!bo) { | ||
304 | fprintf(stderr, "failed to alloc buffer: %s\n", | ||
305 | strerror(errno)); | ||
306 | return; | ||
307 | } | ||
308 | |||
309 | ret = drm_intel_bo_pin(bo, 4096); | ||
310 | if (ret) { | ||
311 | fprintf(stderr, "failed to pin buffer: %s\n", strerror(errno)); | ||
312 | return; | ||
313 | } | ||
314 | |||
315 | ret = drm_intel_gem_bo_map_gtt(bo); | ||
316 | if (ret) { | ||
317 | fprintf(stderr, "failed to GTT map buffer: %s\n", | ||
318 | strerror(errno)); | ||
319 | return; | ||
320 | } | ||
321 | |||
322 | fb_ptr = bo->virtual; | ||
323 | |||
324 | /* paint the buffer blue */ | ||
325 | for (i = 0; i < width * height; i++) | ||
326 | fb_ptr[i] = 0xff; | ||
327 | |||
328 | ret = drmModeAddFB(fd, width, height, 32, 32, width * 4, bo->handle, | ||
329 | &fb_id); | ||
330 | if (ret) { | ||
331 | fprintf(stderr, "failed to add fb: %s\n", strerror(errno)); | ||
332 | return; | ||
333 | } | ||
334 | |||
335 | ret = drmModeSetCrtc(fd, encoder->crtc_id, fb_id, 0, 0, | ||
336 | &connector->connector_id, 1, mode); | ||
337 | if (ret) { | ||
338 | fprintf(stderr, "failed to set mode: %s\n", strerror(errno)); | ||
339 | return; | ||
340 | } | ||
341 | } | ||
342 | |||
343 | extern char *optarg; | ||
344 | extern int optind, opterr, optopt; | ||
345 | static char optstr[] = "ecpmfs:"; | ||
346 | |||
347 | void usage(char *name) | ||
348 | { | ||
349 | fprintf(stderr, "usage: %s [-ecpmf]\n", name); | ||
350 | fprintf(stderr, "\t-e\tlist encoders\n"); | ||
351 | fprintf(stderr, "\t-c\tlist connectors\n"); | ||
352 | fprintf(stderr, "\t-p\tlist CRTCs (pipes)\n"); | ||
353 | fprintf(stderr, "\t-m\tlist modes\n"); | ||
354 | fprintf(stderr, "\t-f\tlist framebuffers\n"); | ||
355 | fprintf(stderr, "\t-s <connector_id>:<mode>\tset a mode\n"); | ||
356 | fprintf(stderr, "\n\tDefault is to dump all info.\n"); | ||
357 | exit(0); | ||
358 | } | ||
359 | |||
360 | #define dump_resource(res) if (res) dump_##res() | ||
361 | |||
362 | int main(int argc, char **argv) | ||
363 | { | ||
364 | int c; | ||
365 | int encoders = 0, connectors = 0, crtcs = 0, framebuffers = 0; | ||
366 | char *modules[] = { "i915", "radeon" }; | ||
367 | char *modeset = NULL, *mode, *connector; | ||
368 | int i, connector_id; | ||
369 | |||
370 | opterr = 0; | ||
371 | while ((c = getopt(argc, argv, optstr)) != -1) { | ||
372 | switch (c) { | ||
373 | case 'e': | ||
374 | encoders = 1; | ||
375 | break; | ||
376 | case 'c': | ||
377 | connectors = 1; | ||
378 | break; | ||
379 | case 'p': | ||
380 | crtcs = 1; | ||
381 | break; | ||
382 | case 'm': | ||
383 | modes = 1; | ||
384 | break; | ||
385 | case 'f': | ||
386 | framebuffers = 1; | ||
387 | break; | ||
388 | case 's': | ||
389 | modeset = strdup(optarg); | ||
390 | break; | ||
391 | default: | ||
392 | usage(argv[0]); | ||
393 | break; | ||
394 | } | ||
395 | } | ||
396 | |||
397 | if (argc == 1) | ||
398 | encoders = connectors = crtcs = modes = framebuffers = 1; | ||
399 | |||
400 | for (i = 0; i < ARRAY_SIZE(modules); i++) { | ||
401 | printf("trying to load module %s...", modules[i]); | ||
402 | fd = drmOpen(modules[i], NULL); | ||
403 | if (fd < 0) { | ||
404 | printf("failed.\n"); | ||
405 | } else { | ||
406 | printf("success.\n"); | ||
407 | break; | ||
408 | } | ||
409 | } | ||
410 | |||
411 | if (i == ARRAY_SIZE(modules)) { | ||
412 | fprintf(stderr, "failed to load any modules, aborting.\n"); | ||
413 | return -1; | ||
414 | } | ||
415 | |||
416 | resources = drmModeGetResources(fd); | ||
417 | if (!resources) { | ||
418 | fprintf(stderr, "drmModeGetResources failed: %s\n", | ||
419 | strerror(errno)); | ||
420 | drmClose(fd); | ||
421 | return 1; | ||
422 | } | ||
423 | |||
424 | dump_resource(encoders); | ||
425 | dump_resource(connectors); | ||
426 | dump_resource(crtcs); | ||
427 | dump_resource(framebuffers); | ||
428 | |||
429 | if (modeset) { | ||
430 | connector = strtok(modeset, ":"); | ||
431 | if (!connector) | ||
432 | usage(argv[0]); | ||
433 | connector_id = atoi(connector); | ||
434 | |||
435 | mode = strtok(NULL, ":"); | ||
436 | if (!mode) | ||
437 | usage(argv[0]); | ||
438 | printf("setting connector %d to mode %s\n", connector_id, | ||
439 | mode); | ||
440 | set_mode(connector_id, mode); | ||
441 | sleep(3); | ||
442 | } | ||
443 | |||
444 | sleep(3); | ||
445 | |||
446 | drmModeFreeResources(resources); | ||
447 | |||
448 | return 0; | ||
449 | } | ||
diff --git a/tests/modetest/test b/tests/modetest/test new file mode 100644 index 00000000..5bb552ef --- /dev/null +++ b/tests/modetest/test | |||
@@ -0,0 +1,2 @@ | |||
1 | export LD_LIBRARY_PATH=../../libdrm/.libs:../../libdrm/intel/.libs | ||
2 | LD_PRELOAD=../../libdrm/.libs/libdrm.so ./app $@ | ||