aboutsummaryrefslogtreecommitdiffstats
path: root/tests/kms
diff options
context:
space:
mode:
authorThierry Reding2015-12-09 11:37:44 -0600
committerEmil Velikov2015-12-18 11:44:10 -0600
commit89cca28dfbc0c96c13b1dfa3bc3c947876469159 (patch)
tree2585c44ad582fb133b01b20f6d4680c5a15143dd /tests/kms
parente0ec59efb12eb4e5a548f29df620c3c5e1cd6e4f (diff)
downloadexternal-libgbm-89cca28dfbc0c96c13b1dfa3bc3c947876469159.tar.gz
external-libgbm-89cca28dfbc0c96c13b1dfa3bc3c947876469159.tar.xz
external-libgbm-89cca28dfbc0c96c13b1dfa3bc3c947876469159.zip
tests: kms: Implement universal planes test
This small program allows universal planes to be tested. Currently this isn't very flexible because it allows only the first plane of a given type to be tested on the first CRTC. However it should be simple to extend this with some additional command-line arguments. Signed-off-by: Thierry Reding <treding@nvidia.com> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>
Diffstat (limited to 'tests/kms')
-rw-r--r--tests/kms/Makefile.am9
-rw-r--r--tests/kms/kms-universal-planes.c358
2 files changed, 365 insertions, 2 deletions
diff --git a/tests/kms/Makefile.am b/tests/kms/Makefile.am
index f28b729c..6645af7a 100644
--- a/tests/kms/Makefile.am
+++ b/tests/kms/Makefile.am
@@ -21,11 +21,16 @@ libkms_test_la_LIBADD = \
21 21
22if HAVE_INSTALL_TESTS 22if HAVE_INSTALL_TESTS
23bin_PROGRAMS = \ 23bin_PROGRAMS = \
24 kms-steal-crtc 24 kms-steal-crtc \
25 kms-universal-planes
25else 26else
26noinst_PROGRAMS = \ 27noinst_PROGRAMS = \
27 kms-steal-crtc 28 kms-steal-crtc \
29 kms-universal-planes
28endif 30endif
29 31
30kms_steal_crtc_SOURCES = kms-steal-crtc.c 32kms_steal_crtc_SOURCES = kms-steal-crtc.c
31kms_steal_crtc_LDADD = libkms-test.la ../util/libutil.la $(CAIRO_LIBS) 33kms_steal_crtc_LDADD = libkms-test.la ../util/libutil.la $(CAIRO_LIBS)
34
35kms_universal_planes_SOURCES = kms-universal-planes.c
36kms_universal_planes_LDADD = libkms-test.la $(CAIRO_LIBS)
diff --git a/tests/kms/kms-universal-planes.c b/tests/kms/kms-universal-planes.c
new file mode 100644
index 00000000..9151231f
--- /dev/null
+++ b/tests/kms/kms-universal-planes.c
@@ -0,0 +1,358 @@
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#ifdef HAVE_CONFIG_H
25#include "config.h"
26#endif
27
28#include <fcntl.h>
29#include <getopt.h>
30#include <stdbool.h>
31#include <stdint.h>
32#include <stdio.h>
33#include <string.h>
34#include <unistd.h>
35
36#include <drm_fourcc.h>
37#include "xf86drm.h"
38
39#include "util/common.h"
40#include "libkms-test.h"
41
42static const uint32_t formats[] = {
43 DRM_FORMAT_XRGB8888,
44 DRM_FORMAT_XBGR8888,
45 DRM_FORMAT_RGBA8888,
46};
47
48static uint32_t choose_format(struct kms_plane *plane)
49{
50 unsigned int i;
51
52 for (i = 0; i < ARRAY_SIZE(formats); i++)
53 if (kms_plane_supports_format(plane, formats[i]))
54 return formats[i];
55
56 return 0;
57}
58
59static void prepare_framebuffer(struct kms_framebuffer *fb, bool invert)
60{
61 const unsigned int block_size = 16;
62 uint32_t colors[2];
63 unsigned int i, j;
64 uint32_t *buf;
65 void *ptr;
66 int err;
67
68 switch (fb->format) {
69 case DRM_FORMAT_XRGB8888:
70 printf("using XRGB8888 format\n");
71 /* XXRRGGBB */
72 colors[0] = 0xffff0000;
73 colors[1] = 0xff0000ff;
74 break;
75
76 case DRM_FORMAT_XBGR8888:
77 printf("using XBGR8888 format\n");
78 /* XXBBGGRR */
79 colors[0] = 0xff0000ff;
80 colors[1] = 0xffff0000;
81 break;
82
83 case DRM_FORMAT_RGBA8888:
84 printf("using RGBA8888 format\n");
85 /* RRGGBBAA */
86 colors[0] = 0xff0000ff;
87 colors[1] = 0x0000ffff;
88 break;
89
90 default:
91 colors[0] = 0xffffffff;
92 colors[1] = 0xffffffff;
93 break;
94 }
95
96 err = kms_framebuffer_map(fb, &ptr);
97 if (err < 0) {
98 fprintf(stderr, "kms_framebuffer_map() failed: %s\n",
99 strerror(-err));
100 return;
101 }
102
103 buf = ptr;
104
105 for (j = 0; j < fb->height; j++) {
106 for (i = 0; i < fb->width; i++) {
107 unsigned int color = (j / block_size) ^
108 (i / block_size);
109
110 if (invert)
111 color ^= color;
112
113 *buf++ = colors[color & 1];
114 }
115 }
116
117 kms_framebuffer_unmap(fb);
118}
119
120int main(int argc, char *argv[])
121{
122 static const char opts[] = "chopv";
123 static struct option options[] = {
124 { "cursor", 0, 0, 'c' },
125 { "help", 0, 0, 'h' },
126 { "overlay", 0, 0, 'o' },
127 { "primary", 0, 0, 'p' },
128 { "verbose", 0, 0, 'v' },
129 { 0, 0, 0, 0 },
130 };
131 struct kms_framebuffer *cursor = NULL;
132 struct kms_framebuffer *root = NULL;
133 struct kms_framebuffer *fb = NULL;
134 struct kms_device *device;
135 bool use_overlay = false;
136 bool use_primary = false;
137 struct kms_plane *plane;
138 bool use_cursor = false;
139 bool verbose = false;
140 unsigned int i;
141 int opt, idx;
142 int fd, err;
143
144 while ((opt = getopt_long(argc, argv, opts, options, &idx)) != -1) {
145 switch (opt) {
146 case 'c':
147 use_cursor = true;
148 break;
149
150 case 'h':
151 break;
152
153 case 'o':
154 use_overlay = true;
155 break;
156
157 case 'p':
158 use_primary = true;
159 break;
160
161 case 'v':
162 verbose = true;
163 break;
164
165 default:
166 printf("unknown option \"%c\"\n", opt);
167 return 1;
168 }
169 }
170
171 if (optind >= argc) {
172 fprintf(stderr, "usage: %s [options] DEVICE\n", argv[0]);
173 return 1;
174 }
175
176 fd = open(argv[optind], O_RDWR);
177 if (fd < 0) {
178 fprintf(stderr, "open() failed: %m\n");
179 return 1;
180 }
181
182 err = drmSetClientCap(fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
183 if (err < 0) {
184 fprintf(stderr, "drmSetClientCap() failed: %d\n", err);
185 return 1;
186 }
187
188 device = kms_device_open(fd);
189 if (!device)
190 return 1;
191
192 if (verbose) {
193 printf("Screens: %u\n", device->num_screens);
194
195 for (i = 0; i < device->num_screens; i++) {
196 struct kms_screen *screen = device->screens[i];
197 const char *status = "disconnected";
198
199 if (screen->connected)
200 status = "connected";
201
202 printf(" %u: %x\n", i, screen->id);
203 printf(" Status: %s\n", status);
204 printf(" Name: %s\n", screen->name);
205 printf(" Resolution: %ux%u\n", screen->width,
206 screen->height);
207 }
208
209 printf("Planes: %u\n", device->num_planes);
210
211 for (i = 0; i < device->num_planes; i++) {
212 struct kms_plane *plane = device->planes[i];
213 const char *type = NULL;
214
215 switch (plane->type) {
216 case DRM_PLANE_TYPE_OVERLAY:
217 type = "overlay";
218 break;
219
220 case DRM_PLANE_TYPE_PRIMARY:
221 type = "primary";
222 break;
223
224 case DRM_PLANE_TYPE_CURSOR:
225 type = "cursor";
226 break;
227 }
228
229 printf(" %u: %p\n", i, plane);
230 printf(" ID: %x\n", plane->id);
231 printf(" CRTC: %x\n", plane->crtc->id);
232 printf(" Type: %x (%s)\n", plane->type, type);
233 }
234 }
235
236 if (use_cursor) {
237 unsigned int x, y;
238 uint32_t format;
239
240 plane = kms_device_find_plane_by_type(device,
241 DRM_PLANE_TYPE_CURSOR,
242 0);
243 if (!plane) {
244 fprintf(stderr, "no cursor plane found\n");
245 return 1;
246 }
247
248 format = choose_format(plane);
249 if (!format) {
250 fprintf(stderr, "no matching format found\n");
251 return 1;
252 }
253
254 cursor = kms_framebuffer_create(device, 32, 32, format);
255 if (!cursor) {
256 fprintf(stderr, "failed to create cursor buffer\n");
257 return 1;
258 }
259
260 prepare_framebuffer(cursor, false);
261
262 x = (device->screens[0]->width - cursor->width) / 2;
263 y = (device->screens[0]->height - cursor->height) / 2;
264
265 kms_plane_set(plane, cursor, x, y);
266 }
267
268 if (use_overlay) {
269 uint32_t format;
270
271 plane = kms_device_find_plane_by_type(device,
272 DRM_PLANE_TYPE_OVERLAY,
273 0);
274 if (!plane) {
275 fprintf(stderr, "no overlay plane found\n");
276 return 1;
277 }
278
279 format = choose_format(plane);
280 if (!format) {
281 fprintf(stderr, "no matching format found\n");
282 return 1;
283 }
284
285 fb = kms_framebuffer_create(device, 320, 240, format);
286 if (!fb)
287 return 1;
288
289 prepare_framebuffer(fb, false);
290
291 kms_plane_set(plane, fb, 0, 0);
292 }
293
294 if (use_primary) {
295 unsigned int x, y;
296 uint32_t format;
297
298 plane = kms_device_find_plane_by_type(device,
299 DRM_PLANE_TYPE_PRIMARY,
300 0);
301 if (!plane) {
302 fprintf(stderr, "no primary plane found\n");
303 return 1;
304 }
305
306 format = choose_format(plane);
307 if (!format) {
308 fprintf(stderr, "no matching format found\n");
309 return 1;
310 }
311
312 root = kms_framebuffer_create(device, 640, 480, format);
313 if (!root)
314 return 1;
315
316 prepare_framebuffer(root, true);
317
318 x = (device->screens[0]->width - root->width) / 2;
319 y = (device->screens[0]->height - root->height) / 2;
320
321 kms_plane_set(plane, root, x, y);
322 }
323
324 while (1) {
325 struct timeval timeout = { 1, 0 };
326 fd_set fds;
327
328 FD_ZERO(&fds);
329 FD_SET(STDIN_FILENO, &fds);
330
331 err = select(STDIN_FILENO + 1, &fds, NULL, NULL, &timeout);
332 if (err < 0) {
333 fprintf(stderr, "select() failed: %m\n");
334 break;
335 }
336
337 /* timeout */
338 if (err == 0)
339 continue;
340
341 if (FD_ISSET(STDIN_FILENO, &fds))
342 break;
343 }
344
345 if (cursor)
346 kms_framebuffer_free(cursor);
347
348 if (root)
349 kms_framebuffer_free(root);
350
351 if (fb)
352 kms_framebuffer_free(fb);
353
354 kms_device_close(device);
355 close(fd);
356
357 return 0;
358}