#include #include #define GL_GLEXT_PROTOTYPES #include #include #include #include #include #include #include #include #include #define _countof(X) (sizeof X / sizeof X[0]) static int context_error_handler(Display *display, XErrorEvent *ev) { static char msg[2048]; XGetErrorText(display, ev->error_code, &msg[0], sizeof msg); std::cerr << "GLX Error: " << msg << std::endl; assert(0); return 0; } static bool is_extension_available(const char * whole_extensions, const char * extension_name) { const char * bottom = whole_extensions + strlen(whole_extensions); const char * p = whole_extensions, * found; while( p < bottom ) { found = strstr(p, extension_name); if(!found) return false; const char * token_bottom = found+strlen(extension_name); if( (p==whole_extensions || p[-1]==' ') && (*token_bottom==' ' || bottom <= token_bottom) ) return true; p = token_bottom; } return false; } GLXFBConfig choose_fbconfig(Display * display) { int major, minor; if(!glXQueryVersion(display, &major, &minor)) { std::cerr << "Failed to get GLX version." << std::endl; exit(1); } if(major<1 || (major==1 && minor<3)) { std::cerr << "GLX 1.3 or higher is required for FBConfigs interface." << std::endl; exit(1); } static int vi_attr[] = { GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT, GLX_RENDER_TYPE , GLX_RGBA_BIT, GLX_RED_SIZE , 8, GLX_GREEN_SIZE , 8, GLX_BLUE_SIZE , 8, GLX_ALPHA_SIZE , 8, GLX_DOUBLEBUFFER , True, GLX_FLOAT_COMPONENTS_NV, GL_FALSE, None }; int num_fb; GLXFBConfig* fbc = glXChooseFBConfig(display, DefaultScreen(display), vi_attr, &num_fb); if (!fbc) { printf( "Failed to retrieve a framebuffer config\n" ); exit(1); } static struct { int id_; const char * name; } check_targets[] = { {GLX_RED_SIZE, "RED"}, {GLX_GREEN_SIZE, "GREEN"}, {GLX_BLUE_SIZE, "BLUE"}, {GLX_ALPHA_SIZE, "ALPHA"}, }; int i; for(i=0; i < num_fb; i++) { int value; size_t j; for(j=0; j<_countof(check_targets); ++j) { if (glXGetFBConfigAttrib(display, fbc[i], check_targets[j].id_, &value)) { std::cerr << "glXGetFBConfigAttrib on " << check_targets[i].name << " has failed." << std::endl; exit(1); } if (value != 8) break; } if(j==_countof(check_targets)) break; } if(num_fb<=i) { std::cerr << "No matching config found." << std::endl; exit(1); } GLXFBConfig r = fbc[i]; XFree(fbc); return r; } Bool check_window_mapping(Display* d, XEvent* ev, char* arg) { return ev->xmap.window == (Window)arg && ev->type == MapNotify; } int main(int argc, const char* argv[]) { Display * display = XOpenDisplay(NULL); //*oldHandler = (XErrorHandler)XSetErrorHandler(context_error_handler); typedef GLXContext (*glXCreateContextAttribsARBProc) (Display*, GLXFBConfig, GLXContext, Bool, const int*); glXCreateContextAttribsARBProc glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" ); if(!glXCreateContextAttribsARB) { std::cerr << "glXCreateContextAttribsARB() is not available." << std::endl; exit(1); } const char * available_extensions = glXQueryExtensionsString(display, DefaultScreen(display)); if (!is_extension_available(available_extensions,"GLX_ARB_create_context")){ std::cout << "Context-creation extension is not available." << std::endl; exit(1); } int gl_major_version = 3; int gl_minor_version = 2; std::cout << "Creating OpenGL " << gl_major_version << '.' << gl_minor_version << " context with DEBUG flag" << std::endl; std::vector attrs; attrs.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB); attrs.push_back(gl_major_version); attrs.push_back(GLX_CONTEXT_MINOR_VERSION_ARB); attrs.push_back(gl_minor_version); attrs.push_back(GLX_CONTEXT_FLAGS_ARB); attrs.push_back(GLX_CONTEXT_DEBUG_BIT_ARB); attrs.push_back(None); GLXFBConfig fbconfig = choose_fbconfig(display); XVisualInfo *vi; // Get visual from FB config. if((vi = glXGetVisualFromFBConfig(display, fbconfig)) == NULL) { std::cout << "No suitable visuals found." << std::endl; exit(1); } XSetWindowAttributes winattrs; Colormap colormap = XCreateColormap (display, RootWindow(display, vi->screen), vi->visual, AllocNone); winattrs.colormap = colormap; winattrs.background_pixmap = None ; winattrs.border_pixel= 0; winattrs.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask | KeyReleaseMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask; Window window = XCreateWindow (display, RootWindow(display, vi->screen), 0, 0, 640, 480, 0, vi->depth, InputOutput, vi->visual, CWBackPixel | CWBorderPixel | CWColormap | CWEventMask, &winattrs); if(!window) { std::cerr << "XCreateWindow() has failed." << std::endl; exit(1); } XStoreName(display, window, "debug-leak"); XMapWindow(display, window); // Wait for the window to be mapped on screen. XEvent event; XIfEvent(display, &event, check_window_mapping, (char*)window); XFree(vi); // Flush command queue and get errors reported if any. XSync(display, False); GLXContext glx_context = glXCreateContextAttribsARB (display, fbconfig, 0, True, &attrs[0]); glXMakeCurrent(display, window , glx_context); { glGetString(GL_EXTENSIONS); } glXMakeCurrent(display, 0, 0); glXDestroyContext(display, glx_context); return 0; }