/* * https://www.khronos.org/opengl/wiki/Tutorial:_OpenGL_3.0_Context_Creation_(GLX) * * Modified to use an indirect context * * $ gcc -g gl3.cxx -o gl3 $(pkg-config --cflags --libs x11) -lGL -lGLU */ #include #include #include #include #include #include #include #include #define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 #define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*); // Helper to check for extension string presence. Adapted from: // http://www.opengl.org/resources/features/OGLextensions/ static bool isExtensionSupported(const char *extList, const char *extension) { const char *start; const char *where, *terminator; where = strchr(extension, ' '); if (where || *extension == '\0') return false; for (start=extList;;) { where = strstr(start, extension); if (!where) break; terminator = where + strlen(extension); if ( where == start || *(where - 1) == ' ' ) if ( *terminator == ' ' || *terminator == '\0' ) return true; start = terminator; } return false; } int main(int argc, char* argv[]) { Display *display = XOpenDisplay(NULL); if (!display) { printf("Failed to open X display\n"); exit(1); } // Get a matching FB config static int visual_attribs[] = { GLX_X_RENDERABLE , True, GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT, GLX_RENDER_TYPE , GLX_RGBA_BIT, GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR, GLX_RED_SIZE , 8, GLX_GREEN_SIZE , 8, GLX_BLUE_SIZE , 8, GLX_ALPHA_SIZE , 8, GLX_DEPTH_SIZE , 24, GLX_STENCIL_SIZE , 8, GLX_DOUBLEBUFFER , True, None }; static int context_attribs[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, 1, GLX_CONTEXT_MINOR_VERSION_ARB, 0, None }; int glx_major, glx_minor; int fbcount; GLXFBConfig* fbc = glXChooseFBConfig(display, DefaultScreen(display), visual_attribs, &fbcount); if (!fbc) { printf( "Failed to retrieve a framebuffer config\n" ); exit(1); } int best_fbc = -1, worst_fbc = -1, best_num_samp = -1, worst_num_samp = 999; int i; for (i=0; i best_num_samp ) best_fbc = i, best_num_samp = samples; if ( worst_fbc < 0 || !samp_buf || samples < worst_num_samp ) worst_fbc = i, worst_num_samp = samples; } XFree( vi ); } GLXFBConfig bestFbc = fbc[ best_fbc ]; XFree( fbc ); XVisualInfo *vi = glXGetVisualFromFBConfig( display, bestFbc ); XSetWindowAttributes swa; Colormap cmap; swa.colormap = cmap = XCreateColormap( display, RootWindow( display, vi->screen ), vi->visual, AllocNone ); swa.background_pixmap = None ; swa.border_pixel = 0; swa.event_mask = StructureNotifyMask; Window win = XCreateWindow( display, RootWindow( display, vi->screen ), 0, 0, 100, 100, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel|CWColormap|CWEventMask, &swa ); if ( !win ) { printf( "Failed to create window.\n" ); exit(1); } // Done with the visual info data XFree( vi ); XStoreName( display, win, "https://bugs.freedesktop.org/show_bug.cgi?id=107508" ); XMapWindow( display, win ); const char *glxExts = glXQueryExtensionsString( display, DefaultScreen( display ) ); glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0; glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" ); GLXContext ctx = 0; if ( !isExtensionSupported( glxExts, "GLX_ARB_create_context" ) || !glXCreateContextAttribsARB ) { printf( "glXCreateContextAttribsARB() not found\n" ); exit (1); } ctx = glXCreateContextAttribsARB( display, bestFbc, 0, False, context_attribs ); if ( ! glXIsDirect ( display, ctx ) ) { printf( "Indirect GLX rendering context\n" ); } else { printf( "Direct GLX rendering context\n" ); } glXMakeCurrent( display, win, ctx ); glClearColor( 0, 0.5, 1, 1 ); glClear( GL_COLOR_BUFFER_BIT ); glXSwapBuffers ( display, win ); sleep( 1 ); glClearColor ( 1, 0.5, 0, 1 ); glClear ( GL_COLOR_BUFFER_BIT ); glXSwapBuffers ( display, win ); sleep( 1 ); glXMakeCurrent( display, 0, 0 ); glXDestroyContext( display, ctx ); XDestroyWindow( display, win ); XFreeColormap( display, cmap ); XCloseDisplay( display ); return 0; }