~ubuntu-branches/ubuntu/oneiric/mesa-demos/oneiric

« back to all changes in this revision

Viewing changes to src/xdemos/glsync.c

  • Committer: Bazaar Package Importer
  • Author(s): Christopher James Halse Rogers
  • Date: 2010-09-27 16:18:27 UTC
  • Revision ID: james.westby@ubuntu.com-20100927161827-1yfgolc1oy9sjhi8
Tags: upstream-8.0.1
ImportĀ upstreamĀ versionĀ 8.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright Ā© 2007 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
 * Authors:
 
24
 *    Jesse Barnes <jesse.barnes@intel.com>
 
25
 *
 
26
 */
 
27
 
 
28
/** @file glsync.c
 
29
 * The program is simple:  it paints a window alternating colors (red &
 
30
 * white) either as fast as possible or synchronized to vblank events
 
31
 *
 
32
 * If run normally, the program should display a window that exhibits
 
33
 * significant tearing between red and white colors (e.g. you might get
 
34
 * a "waterfall" effect of red and white horizontal bars).
 
35
 *
 
36
 * If run with the '-s b' option, the program should synchronize the
 
37
 * window color changes with the vertical blank period, resulting in a
 
38
 * window that looks orangish with a high frequency flicker (which may
 
39
 * be invisible).  If the window is moved to another screen, this
 
40
 * property should be preserved.  If the window spans two screens, it
 
41
 * shouldn't tear on whichever screen most of the window is on; the
 
42
 * portion on the other screen may show some tearing (like the
 
43
 * waterfall effect above).
 
44
 *
 
45
 * Other options include '-w <width>' and '-h <height' to set the
 
46
 * window size.
 
47
 */
 
48
#include <stdio.h>
 
49
#include <stdlib.h>
 
50
#include <string.h>
 
51
#include <unistd.h>
 
52
#include <GL/gl.h>
 
53
#include <GL/glu.h>
 
54
#include <GL/glx.h>
 
55
#include <GL/glxext.h>
 
56
#include <X11/X.h>
 
57
#include <X11/Xlib.h>
 
58
#include <X11/Xutil.h>
 
59
 
 
60
static PFNGLXGETVIDEOSYNCSGIPROC video_sync_get;
 
61
static PFNGLXSWAPINTERVALSGIPROC swap_interval;
 
62
static PFNGLXWAITVIDEOSYNCSGIPROC video_sync;
 
63
 
 
64
 
 
65
static int GLXExtensionSupported(Display *dpy, const char *extension)
 
66
{
 
67
        const char *extensionsString, *pos;
 
68
 
 
69
        extensionsString = glXQueryExtensionsString(dpy, DefaultScreen(dpy));
 
70
 
 
71
        pos = strstr(extensionsString, extension);
 
72
 
 
73
        if (pos != NULL && (pos == extensionsString || pos[-1] == ' ') &&
 
74
            (pos[strlen(extension)] == ' ' || pos[strlen(extension)] == '\0'))
 
75
                return 1;
 
76
 
 
77
        return 0;
 
78
}
 
79
 
 
80
extern char *optarg;
 
81
extern int optind, opterr, optopt;
 
82
static char optstr[] = "w:h:s:vi:";
 
83
 
 
84
enum sync_type {
 
85
        none = 0,
 
86
        sgi_video_sync,
 
87
        buffer_swap
 
88
};
 
89
 
 
90
static void usage(char *name)
 
91
{
 
92
        printf("usage: %s [-w <width>] [-h <height>] [-s<sync method>] "
 
93
               "[-v]\n", name);
 
94
        printf("\t-s<sync method>:\n");
 
95
        printf("\t\tn: none\n");
 
96
        printf("\t\ts: SGI video sync extension\n");
 
97
        printf("\t\tb: buffer swap\n");
 
98
        printf("\t-i<swap interval>\n");
 
99
        printf("\t-v: verbose (print count)\n");
 
100
        exit(-1);
 
101
}
 
102
 
 
103
int main(int argc, char *argv[])
 
104
{
 
105
        Display *disp;
 
106
        XVisualInfo *pvi;
 
107
        XSetWindowAttributes swa;
 
108
        GLint last_val = -1;
 
109
        unsigned int count = 0;
 
110
        Window winGL;
 
111
        GLXContext context;
 
112
        int dummy;
 
113
        Atom wmDelete;
 
114
        enum sync_type waitforsync = none;
 
115
        int width = 500, height = 500, verbose = 0, interval = 1;
 
116
        int c, i = 1;
 
117
        int ret;
 
118
        int attribs[] = { GLX_RGBA,
 
119
                     GLX_RED_SIZE, 1,
 
120
                     GLX_GREEN_SIZE, 1,
 
121
                     GLX_BLUE_SIZE, 1,
 
122
                     None };
 
123
        int db_attribs[] = { GLX_RGBA,
 
124
                     GLX_RED_SIZE, 1,
 
125
                     GLX_GREEN_SIZE, 1,
 
126
                     GLX_BLUE_SIZE, 1,
 
127
                     GLX_DOUBLEBUFFER,
 
128
                     GLX_DEPTH_SIZE, 1,
 
129
                     None };
 
130
        XSizeHints sizehints;
 
131
 
 
132
        opterr = 0;
 
133
        while ((c = getopt(argc, argv, optstr)) != -1) {
 
134
                switch (c) {
 
135
                case 'w':
 
136
                        width = atoi(optarg);
 
137
                        break;
 
138
                case 'h':
 
139
                        height = atoi(optarg);
 
140
                        break;
 
141
                case 's':
 
142
                        switch (optarg[0]) {
 
143
                        case 'n':
 
144
                                waitforsync = none;
 
145
                                break;
 
146
                        case 's':
 
147
                                waitforsync = sgi_video_sync;
 
148
                                break;
 
149
                        case 'b':
 
150
                                waitforsync = buffer_swap;
 
151
                                break;
 
152
                        default:
 
153
                                usage(argv[0]);
 
154
                                break;
 
155
                        }
 
156
                        break;
 
157
                case 'v':
 
158
                        verbose = 1;
 
159
                        break;
 
160
                case 'i':
 
161
                        interval = atoi(optarg);
 
162
                        break;
 
163
                default:
 
164
                        usage(argv[0]);
 
165
                        break;
 
166
                }
 
167
        }
 
168
 
 
169
        disp = XOpenDisplay(NULL);
 
170
        if (!disp) {
 
171
                fprintf(stderr, "failed to open display\n");
 
172
                return -1;
 
173
        }
 
174
 
 
175
        if (!glXQueryExtension(disp, &dummy, &dummy)) {
 
176
                fprintf(stderr, "glXQueryExtension failed\n");
 
177
                return -1;
 
178
        }
 
179
 
 
180
        if (!GLXExtensionSupported(disp, "GLX_SGI_video_sync")) {
 
181
                fprintf(stderr, "GLX_SGI_video_sync not supported, exiting\n");
 
182
                return -1;
 
183
        }
 
184
 
 
185
        if (waitforsync != buffer_swap) {
 
186
                pvi = glXChooseVisual(disp, DefaultScreen(disp), attribs);
 
187
        } else {
 
188
                pvi = glXChooseVisual(disp, DefaultScreen(disp), db_attribs);
 
189
        }
 
190
 
 
191
        if (!pvi) {
 
192
                fprintf(stderr, "failed to choose visual, exiting\n");
 
193
                return -1;
 
194
        }
 
195
 
 
196
        pvi->screen = DefaultScreen(disp);
 
197
 
 
198
        swa.colormap = XCreateColormap(disp, RootWindow(disp, pvi->screen),
 
199
                                       pvi->visual, AllocNone);
 
200
        swa.border_pixel = 0;
 
201
        swa.event_mask = ExposureMask | KeyPressMask | ButtonPressMask |
 
202
                StructureNotifyMask;
 
203
        winGL = XCreateWindow(disp, RootWindow(disp, pvi->screen),
 
204
                              0, 0,
 
205
                              width, height,
 
206
                              0, pvi->depth, InputOutput, pvi->visual,
 
207
                              CWBorderPixel | CWColormap | CWEventMask, &swa);
 
208
        if (!winGL) {
 
209
                fprintf(stderr, "window creation failed\n");
 
210
                return -1;
 
211
        }
 
212
        wmDelete = XInternAtom(disp, "WM_DELETE_WINDOW", True);
 
213
        XSetWMProtocols(disp, winGL, &wmDelete, 1);
 
214
 
 
215
        sizehints.x = 0;
 
216
        sizehints.y = 0;
 
217
        sizehints.width  = width;
 
218
        sizehints.height = height;
 
219
        sizehints.flags = USSize | USPosition;
 
220
 
 
221
        XSetNormalHints(disp, winGL, &sizehints);
 
222
        XSetStandardProperties(disp, winGL, "glsync test", "glsync text",
 
223
                               None, NULL, 0, &sizehints);
 
224
 
 
225
        context = glXCreateContext(disp, pvi, NULL, GL_TRUE);
 
226
        if (!context) {
 
227
                fprintf(stderr, "failed to create glx context\n");
 
228
                return -1;
 
229
        }
 
230
 
 
231
        XMapWindow(disp, winGL);
 
232
        ret = glXMakeCurrent(disp, winGL, context);
 
233
        if (!ret) {
 
234
                fprintf(stderr, "failed to make context current: %d\n", ret);
 
235
        }
 
236
 
 
237
        video_sync_get = (PFNGLXGETVIDEOSYNCSGIPROC) glXGetProcAddress((unsigned char *)"glXGetVideoSyncSGI");
 
238
        video_sync = (PFNGLXWAITVIDEOSYNCSGIPROC) glXGetProcAddress((unsigned char *)"glXWaitVideoSyncSGI");
 
239
 
 
240
        swap_interval = (PFNGLXSWAPINTERVALSGIPROC) glXGetProcAddress((unsigned char *)"glXSwapIntervalSGI");
 
241
 
 
242
        if (!video_sync_get || !video_sync || !swap_interval) {
 
243
                fprintf(stderr, "failed to get sync functions\n");
 
244
                return -1;
 
245
        }
 
246
 
 
247
        if (waitforsync == buffer_swap) {
 
248
                swap_interval(interval);
 
249
                fprintf(stderr, "set swap interval to %d\n", interval);
 
250
        }
 
251
        video_sync_get(&count);
 
252
        count++;
 
253
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
254
        while (i++) {
 
255
                /* Alternate colors to make tearing obvious */
 
256
                if (i & 1) {
 
257
                        glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
 
258
                        glColor3f(1.0f, 1.0f, 1.0f);
 
259
                } else {
 
260
                        glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
 
261
                        glColor3f(1.0f, 0.0f, 0.0f);
 
262
                }
 
263
 
 
264
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
265
                glRectf(0, 0, width, height);
 
266
 
 
267
                /* Wait for vsync */
 
268
                if (waitforsync == sgi_video_sync) {
 
269
                        if (verbose)
 
270
                                fprintf(stderr, "waiting on count %d\n", count);
 
271
                        video_sync(2, (count + 1) % 2, &count);
 
272
                        if (count < last_val)
 
273
                                fprintf(stderr, "error:  vblank count went backwards: %d -> %d\n", last_val, count);
 
274
                        if (count == last_val)
 
275
                                fprintf(stderr, "error:  count didn't change: %d\n", count);
 
276
                        last_val = count;
 
277
                        glFlush();
 
278
                } else if (waitforsync == buffer_swap) {
 
279
                        glXSwapBuffers(disp, winGL);
 
280
                } else {
 
281
                        video_sync_get(&count);
 
282
                        sleep(1);
 
283
                        glFinish();
 
284
                }
 
285
 
 
286
                if (verbose) {
 
287
                        video_sync_get(&count);
 
288
                        fprintf(stderr, "current count: %d\n", count);
 
289
                }
 
290
        }
 
291
 
 
292
        XDestroyWindow(disp, winGL);
 
293
        glXDestroyContext(disp, context);
 
294
        XCloseDisplay(disp);
 
295
 
 
296
        return 0;
 
297
}