From c42d1a10e37cc2ff378511a058b89a6f8eddf1c0 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 27 Apr 2010 15:43:20 -0400 Subject: tests: add new vblank test Simple test for event frequency. --- configure.ac | 1 + tests/Makefile.am | 2 + tests/vbltest/Makefile.am | 13 ++++ tests/vbltest/vbltest.c | 188 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 204 insertions(+) create mode 100644 tests/vbltest/Makefile.am create mode 100644 tests/vbltest/vbltest.c diff --git a/configure.ac b/configure.ac index 3794838b..bc76603c 100644 --- a/configure.ac +++ b/configure.ac @@ -263,6 +263,7 @@ AC_OUTPUT([ tests/modeprint/Makefile tests/modetest/Makefile tests/kmstest/Makefile + tests/vbltest/Makefile include/Makefile include/drm/Makefile libdrm.pc]) diff --git a/tests/Makefile.am b/tests/Makefile.am index 3e74705e..5d240a05 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -47,6 +47,8 @@ TESTS = \ name_from_fd \ $(NULL) +SUBDIRS += vbltest $(NULL) + if HAVE_INTEL SUBDIRS += \ modeprint \ diff --git a/tests/vbltest/Makefile.am b/tests/vbltest/Makefile.am new file mode 100644 index 00000000..89bc8328 --- /dev/null +++ b/tests/vbltest/Makefile.am @@ -0,0 +1,13 @@ +AM_CFLAGS = \ + -I$(top_srcdir)/include/drm \ + -I$(top_srcdir)/intel/ \ + -I$(top_srcdir) + +noinst_PROGRAMS = \ + vbltest + +vbltest_SOURCES = \ + vbltest.c +vbltest_LDADD = \ + $(top_builddir)/libdrm.la \ + $(top_builddir)/intel/libdrm_intel.la diff --git a/tests/vbltest/vbltest.c b/tests/vbltest/vbltest.c new file mode 100644 index 00000000..1297da8b --- /dev/null +++ b/tests/vbltest/vbltest.c @@ -0,0 +1,188 @@ +/* + * DRM based mode setting test program + * Copyright 2008 Tungsten Graphics + * Jakob Bornecrantz + * Copyright 2008 Intel Corporation + * Jesse Barnes + * + * 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 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. + */ + +/* + * This fairly simple test program dumps output in a similar format to the + * "xrandr" tool everyone knows & loves. It's necessarily slightly different + * since the kernel separates outputs into encoder and connector structures, + * each with their own unique ID. The program also allows test testing of the + * memory management and mode setting APIs by allowing the user to specify a + * connector and mode to use for mode setting. If all works as expected, a + * blue background should be painted on the monitor attached to the specified + * connector after the selected mode is set. + * + * TODO: use cairo to write the mode info on the selected output once + * the mode has been programmed, along with possible test patterns. + */ +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xf86drm.h" +#include "xf86drmMode.h" + +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +extern char *optarg; +extern int optind, opterr, optopt; +static char optstr[] = "s"; + +int secondary = 0; + +struct vbl_info { + unsigned int vbl_count; + struct timeval start; +}; + +static void vblank_handler(int fd, unsigned int frame, unsigned int sec, + unsigned int usec, void *data) +{ + drmVBlank vbl; + struct timeval end; + struct vbl_info *info = data; + double t; + + vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT; + if (secondary) + vbl.request.type |= DRM_VBLANK_SECONDARY; + vbl.request.sequence = 1; + vbl.request.signal = (unsigned long)data; + + drmWaitVBlank(fd, &vbl); + + info->vbl_count++; + + if (info->vbl_count == 60) { + gettimeofday(&end, NULL); + t = end.tv_sec + end.tv_usec * 1e-6 - + (info->start.tv_sec + info->start.tv_usec * 1e-6); + fprintf(stderr, "freq: %.02fHz\n", info->vbl_count / t); + info->vbl_count = 0; + info->start = end; + } +} + +static void usage(char *name) +{ + fprintf(stderr, "usage: %s [-s]\n", name); + fprintf(stderr, "\t-s\tuse secondary pipe\n"); + exit(0); +} + +int main(int argc, char **argv) +{ + int i, c, fd; + char *modules[] = { "i915", "radeon", "nouveau" }; + drmVBlank vbl; + drmEventContext evctx; + struct vbl_info handler_info; + + opterr = 0; + while ((c = getopt(argc, argv, optstr)) != -1) { + switch (c) { + case 's': + secondary = 1; + break; + default: + usage(argv[0]); + break; + } + } + + for (i = 0; i < ARRAY_SIZE(modules); i++) { + printf("trying to load module %s...", modules[i]); + fd = drmOpen(modules[i], NULL); + if (fd < 0) { + printf("failed.\n"); + } else { + printf("success.\n"); + break; + } + } + + if (i == ARRAY_SIZE(modules)) { + fprintf(stderr, "failed to load any modules, aborting.\n"); + return -1; + } + + /* Get current count first */ + vbl.request.type = DRM_VBLANK_RELATIVE; + if (secondary) + vbl.request.type |= DRM_VBLANK_SECONDARY; + vbl.request.sequence = 0; + drmWaitVBlank(fd, &vbl); + + printf("starting count: %d\n", vbl.request.sequence); + + handler_info.vbl_count = 0; + gettimeofday(&handler_info.start, NULL); + + /* Queue an event for frame + 1 */ + vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT; + if (secondary) + vbl.request.type |= DRM_VBLANK_SECONDARY; + vbl.request.sequence = 1; + vbl.request.signal = (unsigned long)&handler_info; + drmWaitVBlank(fd, &vbl); + + /* Set up our event handler */ + memset(&evctx, 0, sizeof evctx); + evctx.version = DRM_EVENT_CONTEXT_VERSION; + evctx.vblank_handler = vblank_handler; + evctx.page_flip_handler = NULL; + + /* Poll for events */ + while (1) { + struct timeval timeout = { .tv_sec = 3, .tv_usec = 0 }; + fd_set fds; + int ret; + + FD_ZERO(&fds); + FD_SET(0, &fds); + FD_SET(fd, &fds); + ret = select(fd + 1, &fds, NULL, NULL, &timeout); + + if (ret <= 0) { + fprintf(stderr, "select timed out or error (ret %d)\n", + ret); + continue; + } else if (FD_ISSET(0, &fds)) { + break; + } + + drmHandleEvent(fd, &evctx); + } + + return 0; +} -- cgit v1.2.3