#include #include #include #include using namespace std; Display *const display = XOpenDisplay(0); //0 defaults to $DISPLAY Window window; bool doubleBuffer = true; void redraw() { static bool initialized = false; const GLuint n = 1; //This is list number 1. if (initialized) { //If display list already exists, just execute it. glCallList(n); } else { //Otherwise compile and execute to create the display list. glNewList(n, GL_COMPILE_AND_EXECUTE); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glBegin(GL_QUADS); //four of the six faces of a cube: glColor3f(0.0, 0.7, 0.1); //green front glVertex3f(-1.0, 1.0, 1.0); glVertex3f( 1.0, 1.0, 1.0); glVertex3f( 1.0, -1.0, 1.0); glVertex3f(-1.0, -1.0, 1.0); glColor3f(0.9, 1.0, 0.0); //yellow back glVertex3f(-1.0, 1.0, -1.0); glVertex3f( 1.0, 1.0, -1.0); glVertex3f( 1.0, -1.0, -1.0); glVertex3f(-1.0, -1.0, -1.0); glColor3f(0.2, 0.2, 1.0); //blue top glVertex3f(-1.0, 1.0, 1.0); glVertex3f( 1.0, 1.0, 1.0); glVertex3f( 1.0, 1.0, -1.0); glVertex3f(-1.0, 1.0, -1.0); glColor3f(0.7, 0.0, 0.1); //red bottom glVertex3f(-1.0, -1.0, 1.0); glVertex3f( 1.0, -1.0, 1.0); glVertex3f( 1.0, -1.0, -1.0); glVertex3f(-1.0, -1.0, -1.0); glEnd(); glEndList(); initialized = true; } if (doubleBuffer) { //buffer swap does implicit glFlush. glXSwapBuffers(display, window); } else { glFlush(); //explicit flush for single buffered case } } int main(int argc, char **argv) { if (display == 0) { cerr << "could not open display\n"; return EXIT_FAILURE; } static GLfloat xAngle = 0; static GLfloat yAngle = 0; static GLfloat zAngle = 0; cout << "Opened display, " << "protocol version == " << ProtocolVersion(display) << "\n" << "protocol revision == " << ProtocolRevision(display) << "\n" << "server vendor == \"" << XServerVendor(display) << "\"\n" << "screen count == " << ScreenCount(display) << "\n"; if (!glXQueryExtension(display, 0, 0)) { cerr << "X server has no OpenGL GLX extension.\n"; return EXIT_FAILURE; } const int screen = DefaultScreen(display); cout << "default screen == " << screen << "\n"; //Mac OS X X11.app requires GLX_RGBA (TrueColor and DirectColor). //Windows Xming disallows GLX_RGBA (PseudoColor and StaticColor). int attr[][5] = { {GLX_RGBA, GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, None}, {GLX_RGBA, GLX_DEPTH_SIZE, 16, None}, { GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, None}, { GLX_DEPTH_SIZE, 16, None} }; XVisualInfo *info; for (size_t i = 0; i < 4; ++i) { if (info = glXChooseVisual(display, screen, attr[i])) { doubleBuffer = i == 0 || i == 2; cout << "option list " << i << "\n"; goto done; } } cerr << "No rgb visual with depth buffer.\n"; return EXIT_FAILURE; done:; cout << "info->visual == " << info->visual << "\n" << "info->visual->ext_data == " << info->visual->ext_data << "\n" << "info->visualid == " << info->visualid << "\n" << "info->screen == " << info->screen << "\n" << "info->depth == " << info->depth << "\n" << "info->c_class == " << info->c_class << "\n" << hex << "info->red_mask == " << info->red_mask << "\n" << "info->green_mask == " << info->green_mask << "\n" << "info->blue_mask == " << info->blue_mask << "\n" << dec << "info->colormap_size == " << info->colormap_size << "\n" << "info->bits_per_rgb == " << info->bits_per_rgb << "\n"; //class is C++ keyword if (info->c_class != TrueColor) { cerr << "TrueColor visual required for this program.\n"; return EXIT_FAILURE; } const GLXContext context = glXCreateContext(display, info, None, GL_TRUE); if (context == 0) { cerr << "Could not create rendering context.\n"; return EXIT_FAILURE; } const Colormap map = XCreateColormap( display, RootWindow(display, info->screen), info->visual, AllocNone ); XSetWindowAttributes attributes; attributes.colormap = map; attributes.border_pixel = 0; attributes.event_mask = ExposureMask | ButtonPressMask | StructureNotifyMask; window = XCreateWindow( display, RootWindow(display, info->screen), 0, 0, 300, 300, 0, info->depth, InputOutput, info->visual, CWBorderPixel | CWColormap | CWEventMask, &attributes ); XSetStandardProperties( display, window, "glxsimple", "glxsimple", None, argv, argc, 0 ); glXMakeCurrent(display, window, context); struct mystruct { GLenum e; const char *name; }; //GL_ macros from usr/include/GL/gl.h const mystruct a[] = { {GL_VENDOR, "Vendor"}, {GL_RENDERER, "Renderer"}, {GL_VERSION, "Version"}, {GL_EXTENSIONS, "Extensions"} }; const size_t n = sizeof a / sizeof a[0]; for (size_t i = 0; i < n; ++i) { if (const GLubyte *p = glGetString(a[i].e)) { if (i < n - 1) { cout << a[i].name << " == \"" << p << "\"\n"; } else { FILE *fp = popen("tr ' ' '\\012' | sort", "w"); fprintf(fp, "%s", p); fclose(fp); } } } XMapWindow(display, window); glEnable(GL_DEPTH_TEST); //enable depth buffering glDepthFunc(GL_LESS); //pedantic, GL_LESS is the default glClearDepth(1.0); //pedantic, 1.0 is the default //frame buffer clears should be to black glClearColor(0.0, 0.0, 0.0, 0.0); //set up projection transform glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 10.0); //establish initial viewport //pedantic, full window size is default viewport glViewport(0, 0, 300, 300); for (bool recalcModelView = true;;) { bool needRedraw = false; do { XEvent event; XNextEvent(display, &event); switch (event.type) { case ButtonPress: recalcModelView = true; switch (event.xbutton.button) { case 1: //Mac mouse click: //Rotate around axis that goes through //top and bottom of cube. xAngle += 10.0; break; case 2: //Mac option mouse click //Rotate around axis that goes through //blue and red sides of cube. yAngle += 10.0; break; case 3: //Mac command mouse click //Rotate around axis that goes through //yellow and green sides of cube. zAngle += 10.0; break; } break; case ConfigureNotify: glViewport(0, 0, event.xconfigure.width, event.xconfigure.height); //no break; case Expose: needRedraw = true; break; } } while (XPending(display)); //loop to compress events if (recalcModelView) { glMatrixMode(GL_MODELVIEW); //Reset modelview matrix to the identity matrix. glLoadIdentity(); //Move the camera back 3 units. glTranslatef(0.0, 0.0, -3.0); //rotate by X, Y, and Z angles glRotatef(xAngle, 0.1, 0.0, 0.0); glRotatef(yAngle, 0.0, 0.1, 0.0); glRotatef(zAngle, 0.0, 0.0, 1.0); recalcModelView = false; needRedraw = true; } if (needRedraw) { redraw(); } } }