#include #include #include #include # define GLX_GLXEXT_PROTOTYPES #include #include #include #include #include #include #include PFNGLXSWAPINTERVALMESAPROC set_swap_interval = NULL; static int GLXExtensionSupported(Display *dpy, const char *extension) { const char *extensionsString, *pos; extensionsString = glXQueryExtensionsString(dpy, DefaultScreen(dpy)); pos = strstr(extensionsString, extension); return pos != NULL && (pos == extensionsString || pos[-1] == ' ') && (pos[strlen(extension)] == ' ' || pos[strlen(extension)] == '\0'); } int main(int argc, char *argv[]) { Display *disp; XVisualInfo *pvi; XSetWindowAttributes swa; int attrib[]= { GLX_RGBA, GLX_DOUBLEBUFFER, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, None }; GLXContext context; Window winGL; unsigned int count; int dummy; Atom wmDelete; int width = 500, height = 500, waitforsync = 0, swapcontrol = 0; int c, i = 1; opterr = 0; disp = XOpenDisplay(NULL); if (!disp) { fprintf(stderr, "failed to open display\n"); return -1; } if (!glXQueryExtension(disp, &dummy, &dummy)) { fprintf(stderr, "glXQueryExtension failed\n"); return -1; } if (!GLXExtensionSupported(disp, "GLX_SGI_swap_control")) { fprintf(stderr, "GLX_SGI_swap_control not supported, exiting\n"); return -1; } pvi = glXChooseVisual(disp, DefaultScreen(disp), attrib); if (!pvi) { fprintf(stderr, "failed to choose visual, exiting\n"); return -1; } context = glXCreateContext(disp, pvi, None, GL_TRUE); if (!context) { fprintf(stderr, "failed to create glx context\n"); return -1; } pvi->screen = DefaultScreen(disp); swa.colormap = XCreateColormap(disp, RootWindow(disp, pvi->screen), pvi->visual, AllocNone); swa.border_pixel = 0; swa.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask; winGL = XCreateWindow(disp, RootWindow(disp, pvi->screen), 0, 0, width, height, 0, pvi->depth, InputOutput, pvi->visual, CWBorderPixel | CWColormap | CWEventMask, &swa); if (!winGL) { fprintf(stderr, "window creation failed\n"); return -1; } wmDelete = XInternAtom(disp, "WM_DELETE_WINDOW", True); XSetWMProtocols(disp, winGL, &wmDelete, 1); XSetStandardProperties(disp, winGL, "glswap test", "glswap text", None, NULL, 0, NULL); XMapRaised(disp, winGL); glXMakeCurrent(disp, winGL, context); set_swap_interval = (PFNGLXSWAPINTERVALMESAPROC) glXGetProcAddressARB( (const GLubyte *) "glXSwapIntervalSGI" ); swapcontrol = 1; if (set_swap_interval && swapcontrol) (*set_swap_interval)( 1 ); while (i++) { /* Alternate colors to make tearing obvious */ if (i & 1) glClearColor(1.0f, 1.0f, 1.0f, 1.0f); else glClearColor(1.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); glFlush(); glXSwapBuffers(disp, winGL); } XDestroyWindow(disp, winGL); glXDestroyContext(disp, context); XCloseDisplay(disp); return 0; }