#include #include #include #include #include #define GL_GLEXT_PROTOTYPES 1 #include #include #include #include int main(int argc, char** argv) { Display *display; int screen; int error; int base; char done; /* We will request a fb config with : * - 8 bits per component * - 16 bits depth buffer * - double buffering * - associated to a window */ int attributes[] = { GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, GLX_ALPHA_SIZE, 8, GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, True, GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, 0 }; GLXFBConfig *configs; int nConfigs; int width, height; XSetWindowAttributes xWinAttributes; /* X11 window attributes */ XVisualInfo *visualInfo; /* Visual info associated to the current config */ XSizeHints sizeHints; /* We will use this to unable user to resize window :) */ Colormap cmap; Window xWindow; /* X11 window */ GLXWindow glXWindow; /* GLX Window */ GLXContext glXContext; /* GLX context */ XEvent event; /* Event */ GLfloat angle; GLdouble ratio; struct timeval start, current; unsigned long int micro; error = 0; base = 0; /* Open display */ display = XOpenDisplay( NULL ); if(display == NULL) { fprintf(stderr, "Unable to open display!\n"); error = 1; goto err_0; } /* We'll be using default screen */ screen = DefaultScreen(display); /* Check if the GLX extension is present */ if(glXQueryExtension(display, &error, &base) == False) { fprintf(stderr, "GLX extension is not supported!\n"); error = 1; goto err_1; } fprintf(stdout, "GLX extension (error base: %d, event base: %d)\n", error, base); /* Query GLX client information (version, vendor, extensions) */ fprintf(stdout, "GLX version %s vendor %s\n", glXGetClientString(display, GLX_VERSION), glXGetClientString(display, GLX_VENDOR)); fprintf(stdout, "GLX extensions %s\n", glXQueryExtensionsString(display, screen)); /* Choose the FB configs matching attributes. The first entry * in the "configs" array is the most optimized one */ configs = glXChooseFBConfig(display, screen, attributes, &nConfigs); if(configs == NULL) { fprintf(stderr, "No suitable configuration found!\n"); error = 1; goto err_1; } fprintf(stdout, "%d configuration found!\n", nConfigs); /* Get visual info associated to the fb config */ visualInfo = glXGetVisualFromFBConfig(display, configs[0]); if(visualInfo == NULL) { fprintf(stderr, "Unable to get visual infos associated to current GLX fb config!\n"); error = 2; goto err_2; } /* Set window properties */ width = 800; height = 600; cmap = XCreateColormap(display, DefaultRootWindow(display), visualInfo->visual, AllocNone); xWinAttributes.save_under = True; xWinAttributes.backing_store = Always; xWinAttributes.event_mask = KeyPressMask; xWinAttributes.colormap = cmap; /* Create XWindow */ xWindow = XCreateWindow(display, DefaultRootWindow(display), 0, 0, width, height, 0, visualInfo->depth, InputOutput, visualInfo->visual, CWBackingStore | CWSaveUnder | CWEventMask | CWColormap, &xWinAttributes); if(xWindow == None) { fprintf(stderr, "Unable to create X window!\n"); error = 3; goto err_3; } fprintf(stdout, "Window opened!\n"); /* Set size hints so that the user can't resize the window :D */ XGetNormalHints(display, xWindow, &sizeHints); sizeHints.flags = PSize | PMinSize | PMaxSize; sizeHints.width = width; sizeHints.min_width = width; sizeHints.max_width = width; sizeHints.height = height; sizeHints.min_height = height; sizeHints.max_height = height; XSetStandardProperties(display, xWindow, "Press ESC to quit", "GLX test", None, 0, 0, &sizeHints); /* Create GLX window */ glXWindow = glXCreateWindow(display, configs[0], xWindow, NULL); if(glXWindow == None) { fprintf(stderr, "Unable to create GLX Window!\n"); error = 4; goto err_4; } /* Create context (RGBA) */ glXContext = glXCreateContext(display, visualInfo, NULL, True); if(glXContext == NULL) { fprintf(stderr, "Unable to create GLX context!\n"); error = 5; goto err_5; } glXMakeCurrent(display, glXWindow, glXContext); /* Show window */ XMapWindow(display, xWindow); XFlush(display); glViewport(0, 0, width, height); glEnable(GL_DEPTH_TEST); glClearColor(0.0, 0.0, 0.0, 1.0); glClearDepth(100.0); /* Main loop */ done = 0; angle = 0.0; ratio = (GLdouble)width / height; gettimeofday(&start, NULL); do { /* Let's draw a stupid cube */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45, ratio, 0.1, 100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0.0, 0.0,-5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); glRotatef(angle,0.0f,1.0f,0.0f); glRotatef(angle,0.0f,0.0f,1.0f); glBegin(GL_QUADS); glColor3f(1.0f,0.0f,0.0f); glVertex3f( 1.0f, 1.0f,-1.0f); glVertex3f(-1.0f, 1.0f,-1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glColor3f(0.0f,1.0f,0.0f); glVertex3f( 1.0f,-1.0f, 1.0f); glVertex3f(-1.0f,-1.0f, 1.0f); glVertex3f(-1.0f,-1.0f,-1.0f); glVertex3f( 1.0f,-1.0f,-1.0f); glColor3f(0.0f,0.0f,1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glVertex3f(-1.0f,-1.0f, 1.0f); glVertex3f( 1.0f,-1.0f, 1.0f); glColor3f(1.0f,1.0f,1.0f); glVertex3f( 1.0f,-1.0f,-1.0f); glVertex3f(-1.0f,-1.0f,-1.0f); glVertex3f(-1.0f, 1.0f,-1.0f); glVertex3f( 1.0f, 1.0f,-1.0f); glColor3f(1.0f,1.0f,1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glVertex3f(-1.0f, 1.0f,-1.0f); glVertex3f(-1.0f,-1.0f,-1.0f); glVertex3f(-1.0f,-1.0f, 1.0f); glColor3f(1.0f,0.0f,1.0f); glVertex3f( 1.0f, 1.0f,-1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glVertex3f( 1.0f,-1.0f, 1.0f); glVertex3f( 1.0f,-1.0f,-1.0f); glEnd(); gettimeofday(¤t, NULL); micro = (unsigned long int)((current.tv_sec - start.tv_sec) * 1000) + (unsigned long int)((current.tv_usec - start.tv_usec) / 1000); angle = micro * 0.1; glXWaitGL(); /* X may wait for openGL to finish drawing */ glXSwapBuffers(display, glXWindow); /* Swap buffers */ /* Dummy event handling */ if(XPending(display)) { XNextEvent(display, &event); switch(event.type) { case KeyPress: if(event.xkey.keycode == 9) done = 1; break; }; } } while (!done); glXDestroyContext(display, glXContext); err_5: glXDestroyWindow(display, glXWindow); err_4: XDestroyWindow(display, xWindow); err_3: XFree(visualInfo); err_2: XFree(configs); err_1: XCloseDisplay(display); err_0: return error; }