2 * Copyright © 2009 Intel Corporation
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:
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
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
24 * Jesse Barnes <jesse.barnes@intel.com>
29 * Simple test for MSC functionality.
38 #include <GL/glxext.h>
41 #include <X11/Xutil.h>
43 void (*get_sync_values
)(Display
*dpy
, Window winGL
, int64_t *ust
, int64_t *msc
, int64_t *sbc
);
44 void (*wait_sync
)(Display
*dpy
, Window winGL
, int64_t target_msc
, int64_t divisor
, int64_t remainder
, int64_t *ust
, int64_t *msc
, int64_t *sbc
);
46 static int GLXExtensionSupported(Display
*dpy
, const char *extension
)
48 const char *extensionsString
, *client_extensions
, *pos
;
50 extensionsString
= glXQueryExtensionsString(dpy
, DefaultScreen(dpy
));
51 client_extensions
= glXGetClientString(dpy
, GLX_EXTENSIONS
);
53 pos
= strstr(extensionsString
, extension
);
55 if (pos
!= NULL
&& (pos
== extensionsString
|| pos
[-1] == ' ') &&
56 (pos
[strlen(extension
)] == ' ' || pos
[strlen(extension
)] == '\0'))
59 pos
= strstr(client_extensions
, extension
);
61 if (pos
!= NULL
&& (pos
== extensionsString
|| pos
[-1] == ' ') &&
62 (pos
[strlen(extension
)] == ' ' || pos
[strlen(extension
)] == '\0'))
69 extern int optind
, opterr
, optopt
;
70 static char optstr
[] = "v";
72 static void usage(char *name
)
74 printf("usage: %s\n", name
);
78 int main(int argc
, char *argv
[])
82 XSetWindowAttributes swa
;
88 int verbose
= 0, width
= 200, height
= 200;
90 int64_t ust
, msc
, sbc
;
93 while ((c
= getopt(argc
, argv
, optstr
)) != -1) {
104 disp
= XOpenDisplay(NULL
);
106 fprintf(stderr
, "failed to open display\n");
110 if (!glXQueryExtension(disp
, &dummy
, &dummy
)) {
111 fprintf(stderr
, "glXQueryExtension failed\n");
115 if (!GLXExtensionSupported(disp
, "GLX_OML_sync_control")) {
116 fprintf(stderr
, "GLX_OML_sync_control not supported, exiting\n");
120 attrib
[0] = GLX_RGBA
;
122 attrib
[2] = GLX_RED_SIZE
;
124 attrib
[4] = GLX_GREEN_SIZE
;
126 attrib
[6] = GLX_BLUE_SIZE
;
128 attrib
[8] = GLX_DOUBLEBUFFER
;
132 pvi
= glXChooseVisual(disp
, DefaultScreen(disp
), attrib
);
134 fprintf(stderr
, "failed to choose visual, exiting\n");
138 context
= glXCreateContext(disp
, pvi
, None
, GL_TRUE
);
140 fprintf(stderr
, "failed to create glx context\n");
144 pvi
->screen
= DefaultScreen(disp
);
146 swa
.colormap
= XCreateColormap(disp
, RootWindow(disp
, pvi
->screen
),
147 pvi
->visual
, AllocNone
);
148 swa
.border_pixel
= 0;
149 swa
.event_mask
= ExposureMask
| KeyPressMask
| ButtonPressMask
|
151 winGL
= XCreateWindow(disp
, RootWindow(disp
, pvi
->screen
),
154 0, pvi
->depth
, InputOutput
, pvi
->visual
,
155 CWBorderPixel
| CWColormap
| CWEventMask
, &swa
);
157 fprintf(stderr
, "window creation failed\n");
160 wmDelete
= XInternAtom(disp
, "WM_DELETE_WINDOW", True
);
161 XSetWMProtocols(disp
, winGL
, &wmDelete
, 1);
163 XSetStandardProperties(disp
, winGL
, "msc test", "msc text",
164 None
, NULL
, 0, NULL
);
166 XMapRaised(disp
, winGL
);
168 glXMakeCurrent(disp
, winGL
, context
);
170 get_sync_values
= glXGetProcAddress((unsigned char *)"glXGetSyncValuesOML");
171 wait_sync
= glXGetProcAddress((unsigned char *)"glXWaitForMscOML");
173 if (!get_sync_values
|| !wait_sync
) {
174 fprintf(stderr
, "failed to get sync values function\n");
179 get_sync_values(disp
, winGL
, &ust
, &msc
, &sbc
);
180 fprintf(stderr
, "ust: %llu, msc: %llu, sbc: %llu\n", ust
, msc
,
183 /* Alternate colors to make tearing obvious */
185 glClearColor(1.0f
, 1.0f
, 1.0f
, 1.0f
);
187 glClearColor(1.0f
, 0.0f
, 0.0f
, 0.0f
);
188 glClear(GL_COLOR_BUFFER_BIT
);
189 glXSwapBuffers(disp
, winGL
);
190 wait_sync(disp
, winGL
, 0, 60, 0, &ust
, &msc
, &sbc
);
192 "wait returned ust: %llu, msc: %llu, sbc: %llu\n",
197 XDestroyWindow(disp
, winGL
);
198 glXDestroyContext(disp
, context
);