/* * 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; }