xref: /aosp_15_r20/external/igt-gpu-tools/benchmarks/kms_vblank.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
1 /*
2  * Copyright © 2015 Intel 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 /** @file kms_vblank.c
25  *
26  * This is a test of performance of drmWaitVblank.
27  */
28 
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include <fcntl.h>
34 #include <inttypes.h>
35 #include <errno.h>
36 #include <time.h>
37 #include <sys/stat.h>
38 #include <sys/time.h>
39 #include <sys/wait.h>
40 
41 #include <drm.h>
42 #include <xf86drm.h>
43 #include "drmtest.h"
44 #include "assert.h"
45 
elapsed(const struct timespec * start,const struct timespec * end,int loop)46 static double elapsed(const struct timespec *start,
47 		      const struct timespec *end,
48 		      int loop)
49 {
50 	return (1e6*(end->tv_sec - start->tv_sec) + (end->tv_nsec - start->tv_nsec)/1000)/loop;
51 }
52 
crtc0_active(int fd)53 static int crtc0_active(int fd)
54 {
55 	union drm_wait_vblank vbl;
56 
57 	memset(&vbl, 0, sizeof(vbl));
58 	vbl.request.type = DRM_VBLANK_RELATIVE;
59 	return drmIoctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl) == 0;
60 }
61 
vblank_query(int fd,int busy)62 static void vblank_query(int fd, int busy)
63 {
64 	union drm_wait_vblank vbl;
65 	struct timespec start, end;
66 	unsigned long seq, count = 0;
67 	struct drm_event_vblank event;
68 
69 	memset(&vbl, 0, sizeof(vbl));
70 
71 	if (busy) {
72 		vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT;
73 		vbl.request.sequence = 120 + 12;
74 		drmIoctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl);
75 	}
76 
77 	vbl.request.type = DRM_VBLANK_RELATIVE;
78 	vbl.request.sequence = 0;
79 	drmIoctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl);
80 	seq = vbl.reply.sequence;
81 
82 	clock_gettime(CLOCK_MONOTONIC, &start);
83 	do {
84 		vbl.request.type = DRM_VBLANK_RELATIVE;
85 		vbl.request.sequence = 0;
86 		drmIoctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl);
87 		count++;
88 	} while ((vbl.reply.sequence - seq) <= 120);
89 	clock_gettime(CLOCK_MONOTONIC, &end);
90 
91 	printf("%f\n", 1e6/elapsed(&start, &end, count));
92 	if (busy)
93 		assert(read(fd, &event, sizeof(event)) != -1);
94 }
95 
vblank_event(int fd,int busy)96 static void vblank_event(int fd, int busy)
97 {
98 	union drm_wait_vblank vbl;
99 	struct timespec start, end;
100 	unsigned long seq, count = 0;
101 	struct drm_event_vblank event;
102 
103 	memset(&vbl, 0, sizeof(vbl));
104 
105 	if (busy) {
106 		vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT;
107 		vbl.request.sequence = 120 + 12;
108 		drmIoctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl);
109 	}
110 
111 	vbl.request.type = DRM_VBLANK_RELATIVE;
112 	vbl.request.sequence = 0;
113 	drmIoctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl);
114 	seq = vbl.reply.sequence;
115 
116 	clock_gettime(CLOCK_MONOTONIC, &start);
117 	do {
118 		vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT;
119 		vbl.request.sequence = 0;
120 		drmIoctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl);
121 
122 		assert(read(fd, &event, sizeof(event)) != -1);
123 		count++;
124 	} while ((event.sequence - seq) <= 120);
125 	clock_gettime(CLOCK_MONOTONIC, &end);
126 
127 	printf("%f\n", 1e6/elapsed(&start, &end, count));
128 	if (busy)
129 		assert(read(fd, &event, sizeof(event)) != -1);
130 }
131 
main(int argc,char ** argv)132 int main(int argc, char **argv)
133 {
134 	int fd, c;
135 	int busy = 0, loops = 5;
136 	enum what { EVENTS, QUERIES } what = EVENTS;
137 
138 	while ((c = getopt (argc, argv, "b:w:r:")) != -1) {
139 		switch (c) {
140 		case 'b':
141 			if (strcmp(optarg, "busy") == 0)
142 				busy = 1;
143 			else if (strcmp(optarg, "idle") == 0)
144 				busy = 0;
145 			else
146 				abort();
147 			break;
148 
149 		case 'w':
150 			if (strcmp(optarg, "event") == 0)
151 				what = EVENTS;
152 			else if (strcmp(optarg, "query") == 0)
153 				what = QUERIES;
154 			else
155 				abort();
156 			break;
157 		case 'r':
158 			loops = atoi(optarg);
159 			if (loops < 1)
160 				loops = 1;
161 		}
162 	}
163 
164 	fd = drm_open_driver(DRIVER_INTEL);
165 	if (!crtc0_active(fd)) {
166 		fprintf(stderr, "CRTC/pipe 0 not active\n");
167 		return 77;
168 	}
169 
170 	while (loops--) {
171 		switch (what) {
172 		case EVENTS:
173 			vblank_event(fd, busy);
174 			break;
175 		case QUERIES:
176 			vblank_query(fd, busy);
177 			break;
178 		}
179 	}
180 	return 0;
181 }
182