1d722e3fbSopenharmony_ci/* 2d722e3fbSopenharmony_ci * DRM based vblank test program 3d722e3fbSopenharmony_ci * Copyright 2008 Tungsten Graphics 4d722e3fbSopenharmony_ci * Jakob Bornecrantz <jakob@tungstengraphics.com> 5d722e3fbSopenharmony_ci * Copyright 2008 Intel Corporation 6d722e3fbSopenharmony_ci * Jesse Barnes <jesse.barnes@intel.com> 7d722e3fbSopenharmony_ci * 8d722e3fbSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 9d722e3fbSopenharmony_ci * copy of this software and associated documentation files (the "Software"), 10d722e3fbSopenharmony_ci * to deal in the Software without restriction, including without limitation 11d722e3fbSopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12d722e3fbSopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 13d722e3fbSopenharmony_ci * Software is furnished to do so, subject to the following conditions: 14d722e3fbSopenharmony_ci * 15d722e3fbSopenharmony_ci * The above copyright notice and this permission notice shall be included in 16d722e3fbSopenharmony_ci * all copies or substantial portions of the Software. 17d722e3fbSopenharmony_ci * 18d722e3fbSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19d722e3fbSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20d722e3fbSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21d722e3fbSopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22d722e3fbSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23d722e3fbSopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 24d722e3fbSopenharmony_ci * IN THE SOFTWARE. 25d722e3fbSopenharmony_ci */ 26d722e3fbSopenharmony_ci 27d722e3fbSopenharmony_ci#include <assert.h> 28d722e3fbSopenharmony_ci#include <stdio.h> 29d722e3fbSopenharmony_ci#include <stdlib.h> 30d722e3fbSopenharmony_ci#include <stdint.h> 31d722e3fbSopenharmony_ci#include <unistd.h> 32d722e3fbSopenharmony_ci#include <string.h> 33d722e3fbSopenharmony_ci#include <errno.h> 34d722e3fbSopenharmony_ci#include <poll.h> 35d722e3fbSopenharmony_ci#include <sys/time.h> 36d722e3fbSopenharmony_ci#if HAVE_SYS_SELECT_H 37d722e3fbSopenharmony_ci#include <sys/select.h> 38d722e3fbSopenharmony_ci#endif 39d722e3fbSopenharmony_ci 40d722e3fbSopenharmony_ci#include "xf86drm.h" 41d722e3fbSopenharmony_ci#include "xf86drmMode.h" 42d722e3fbSopenharmony_ci 43d722e3fbSopenharmony_ci#include "util/common.h" 44d722e3fbSopenharmony_ci#include "util/kms.h" 45d722e3fbSopenharmony_ci 46d722e3fbSopenharmony_ciextern char *optarg; 47d722e3fbSopenharmony_ciextern int optind, opterr, optopt; 48d722e3fbSopenharmony_cistatic char optstr[] = "D:M:s"; 49d722e3fbSopenharmony_ci 50d722e3fbSopenharmony_ciint secondary = 0; 51d722e3fbSopenharmony_ci 52d722e3fbSopenharmony_cistruct vbl_info { 53d722e3fbSopenharmony_ci unsigned int vbl_count; 54d722e3fbSopenharmony_ci struct timeval start; 55d722e3fbSopenharmony_ci}; 56d722e3fbSopenharmony_ci 57d722e3fbSopenharmony_cistatic void vblank_handler(int fd, unsigned int frame, unsigned int sec, 58d722e3fbSopenharmony_ci unsigned int usec, void *data) 59d722e3fbSopenharmony_ci{ 60d722e3fbSopenharmony_ci drmVBlank vbl; 61d722e3fbSopenharmony_ci struct timeval end; 62d722e3fbSopenharmony_ci struct vbl_info *info = data; 63d722e3fbSopenharmony_ci double t; 64d722e3fbSopenharmony_ci 65d722e3fbSopenharmony_ci vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT; 66d722e3fbSopenharmony_ci if (secondary) 67d722e3fbSopenharmony_ci vbl.request.type |= DRM_VBLANK_SECONDARY; 68d722e3fbSopenharmony_ci vbl.request.sequence = 1; 69d722e3fbSopenharmony_ci vbl.request.signal = (unsigned long)data; 70d722e3fbSopenharmony_ci 71d722e3fbSopenharmony_ci drmWaitVBlank(fd, &vbl); 72d722e3fbSopenharmony_ci 73d722e3fbSopenharmony_ci info->vbl_count++; 74d722e3fbSopenharmony_ci 75d722e3fbSopenharmony_ci if (info->vbl_count == 60) { 76d722e3fbSopenharmony_ci gettimeofday(&end, NULL); 77d722e3fbSopenharmony_ci t = end.tv_sec + end.tv_usec * 1e-6 - 78d722e3fbSopenharmony_ci (info->start.tv_sec + info->start.tv_usec * 1e-6); 79d722e3fbSopenharmony_ci fprintf(stderr, "freq: %.02fHz\n", info->vbl_count / t); 80d722e3fbSopenharmony_ci info->vbl_count = 0; 81d722e3fbSopenharmony_ci info->start = end; 82d722e3fbSopenharmony_ci } 83d722e3fbSopenharmony_ci} 84d722e3fbSopenharmony_ci 85d722e3fbSopenharmony_cistatic void usage(char *name) 86d722e3fbSopenharmony_ci{ 87d722e3fbSopenharmony_ci fprintf(stderr, "usage: %s [-DMs]\n", name); 88d722e3fbSopenharmony_ci fprintf(stderr, "\n"); 89d722e3fbSopenharmony_ci fprintf(stderr, "options:\n"); 90d722e3fbSopenharmony_ci fprintf(stderr, " -D DEVICE open the given device\n"); 91d722e3fbSopenharmony_ci fprintf(stderr, " -M MODULE open the given module\n"); 92d722e3fbSopenharmony_ci fprintf(stderr, " -s use secondary pipe\n"); 93d722e3fbSopenharmony_ci exit(0); 94d722e3fbSopenharmony_ci} 95d722e3fbSopenharmony_ci 96d722e3fbSopenharmony_ciint main(int argc, char **argv) 97d722e3fbSopenharmony_ci{ 98d722e3fbSopenharmony_ci const char *device = NULL, *module = NULL; 99d722e3fbSopenharmony_ci int c, fd, ret; 100d722e3fbSopenharmony_ci drmVBlank vbl; 101d722e3fbSopenharmony_ci drmEventContext evctx; 102d722e3fbSopenharmony_ci struct vbl_info handler_info; 103d722e3fbSopenharmony_ci 104d722e3fbSopenharmony_ci opterr = 0; 105d722e3fbSopenharmony_ci while ((c = getopt(argc, argv, optstr)) != -1) { 106d722e3fbSopenharmony_ci switch (c) { 107d722e3fbSopenharmony_ci case 'D': 108d722e3fbSopenharmony_ci device = optarg; 109d722e3fbSopenharmony_ci break; 110d722e3fbSopenharmony_ci case 'M': 111d722e3fbSopenharmony_ci module = optarg; 112d722e3fbSopenharmony_ci break; 113d722e3fbSopenharmony_ci case 's': 114d722e3fbSopenharmony_ci secondary = 1; 115d722e3fbSopenharmony_ci break; 116d722e3fbSopenharmony_ci default: 117d722e3fbSopenharmony_ci usage(argv[0]); 118d722e3fbSopenharmony_ci break; 119d722e3fbSopenharmony_ci } 120d722e3fbSopenharmony_ci } 121d722e3fbSopenharmony_ci 122d722e3fbSopenharmony_ci fd = util_open(device, module); 123d722e3fbSopenharmony_ci if (fd < 0) 124d722e3fbSopenharmony_ci return 1; 125d722e3fbSopenharmony_ci 126d722e3fbSopenharmony_ci /* Get current count first */ 127d722e3fbSopenharmony_ci vbl.request.type = DRM_VBLANK_RELATIVE; 128d722e3fbSopenharmony_ci if (secondary) 129d722e3fbSopenharmony_ci vbl.request.type |= DRM_VBLANK_SECONDARY; 130d722e3fbSopenharmony_ci vbl.request.sequence = 0; 131d722e3fbSopenharmony_ci ret = drmWaitVBlank(fd, &vbl); 132d722e3fbSopenharmony_ci if (ret != 0) { 133d722e3fbSopenharmony_ci printf("drmWaitVBlank (relative) failed ret: %i\n", ret); 134d722e3fbSopenharmony_ci return -1; 135d722e3fbSopenharmony_ci } 136d722e3fbSopenharmony_ci 137d722e3fbSopenharmony_ci printf("starting count: %d\n", vbl.request.sequence); 138d722e3fbSopenharmony_ci 139d722e3fbSopenharmony_ci handler_info.vbl_count = 0; 140d722e3fbSopenharmony_ci gettimeofday(&handler_info.start, NULL); 141d722e3fbSopenharmony_ci 142d722e3fbSopenharmony_ci /* Queue an event for frame + 1 */ 143d722e3fbSopenharmony_ci vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT; 144d722e3fbSopenharmony_ci if (secondary) 145d722e3fbSopenharmony_ci vbl.request.type |= DRM_VBLANK_SECONDARY; 146d722e3fbSopenharmony_ci vbl.request.sequence = 1; 147d722e3fbSopenharmony_ci vbl.request.signal = (unsigned long)&handler_info; 148d722e3fbSopenharmony_ci ret = drmWaitVBlank(fd, &vbl); 149d722e3fbSopenharmony_ci if (ret != 0) { 150d722e3fbSopenharmony_ci printf("drmWaitVBlank (relative, event) failed ret: %i\n", ret); 151d722e3fbSopenharmony_ci return -1; 152d722e3fbSopenharmony_ci } 153d722e3fbSopenharmony_ci 154d722e3fbSopenharmony_ci /* Set up our event handler */ 155d722e3fbSopenharmony_ci memset(&evctx, 0, sizeof evctx); 156d722e3fbSopenharmony_ci evctx.version = DRM_EVENT_CONTEXT_VERSION; 157d722e3fbSopenharmony_ci evctx.vblank_handler = vblank_handler; 158d722e3fbSopenharmony_ci evctx.page_flip_handler = NULL; 159d722e3fbSopenharmony_ci 160d722e3fbSopenharmony_ci /* Poll for events */ 161d722e3fbSopenharmony_ci while (1) { 162d722e3fbSopenharmony_ci struct timeval timeout = { .tv_sec = 3, .tv_usec = 0 }; 163d722e3fbSopenharmony_ci fd_set fds; 164d722e3fbSopenharmony_ci 165d722e3fbSopenharmony_ci FD_ZERO(&fds); 166d722e3fbSopenharmony_ci FD_SET(0, &fds); 167d722e3fbSopenharmony_ci FD_SET(fd, &fds); 168d722e3fbSopenharmony_ci ret = select(fd + 1, &fds, NULL, NULL, &timeout); 169d722e3fbSopenharmony_ci 170d722e3fbSopenharmony_ci if (ret <= 0) { 171d722e3fbSopenharmony_ci fprintf(stderr, "select timed out or error (ret %d)\n", 172d722e3fbSopenharmony_ci ret); 173d722e3fbSopenharmony_ci continue; 174d722e3fbSopenharmony_ci } else if (FD_ISSET(0, &fds)) { 175d722e3fbSopenharmony_ci break; 176d722e3fbSopenharmony_ci } 177d722e3fbSopenharmony_ci 178d722e3fbSopenharmony_ci ret = drmHandleEvent(fd, &evctx); 179d722e3fbSopenharmony_ci if (ret != 0) { 180d722e3fbSopenharmony_ci printf("drmHandleEvent failed: %i\n", ret); 181d722e3fbSopenharmony_ci return -1; 182d722e3fbSopenharmony_ci } 183d722e3fbSopenharmony_ci } 184d722e3fbSopenharmony_ci 185d722e3fbSopenharmony_ci return 0; 186d722e3fbSopenharmony_ci} 187