Tutorial: OpenGL 3.0 Context Creation (GLX)

From OpenGL.org
Revision as of 22:00, 12 July 2009 by Dark Photon (Talk | contribs) (New page: == Overview == This tutorial illustrates (with a working program) how to create an OpenGL 3.0 context using the new <code>glXCreateContextAttribsARB()</code> API. In the event that this ...)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Overview

This tutorial illustrates (with a working program) how to create an OpenGL 3.0 context using the new glXCreateContextAttribsARB() API. In the event that this API is unsupported or fails, we fall back and create a standard (old-style) GL 2.1 context.

The Code

#include <stdio.h>

  1. include <stdlib.h>
  2. include <string.h>
  3. include <unistd.h>
  4. define GL_GLEXT_PROTOTYPES 1
  5. define GLX_GLXEXT_PROTOTYPES 1
  6. include <X11/Xlib.h>
  7. include <X11/Xutil.h>
  8. include <GL/gl.h>
  9. include <GL/glx.h>
  1. define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
  2. define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092

typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);

int main (int argc, char ** argv) {

 Display *display = XOpenDisplay(0);
 if ( !display )
 {
   printf( "Failed to open X display\n" );
   exit(1);
 }
 // // Query/print GLX version
 // int major, minor;
 // 
 // if ( !glXQueryVersion( display, &major, &minor ) )
 // {
 //   printf( "glXQueryVersion failed\n" );
 //   exit(1);
 // }
 // printf( "GLX version = %d.%d\n", major, minor );
 // 
 // if ( major < 1 || major == 1 && minor < 3 )
 // {
 //   printf( "GLX version is too old; must be > 1.3\n" );
 //   exit(1);
 // }
 // // Print GLX extensions
 // const char *extensions = glXQueryExtensionsString( display, 
 //                                                 DefaultScreen( display ) );
 // printf( "%s\n", extensions );
 // 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,
     //GLX_SAMPLE_BUFFERS  , 1,
     //GLX_SAMPLES         , 4,
     None
   };
 printf( "Getting matching framebuffer configs\n" );
 int fbcount;
 GLXFBConfig *fbc = glXChooseFBConfig( display, DefaultScreen( display ), 
                                       visual_attribs, &fbcount );
 if ( !fbc )
 {
   printf( "Failed to retrieve a framebuffer config\n" );
   exit(1);
 }
 printf( "Found %d matching FB configs.\n", fbcount );
 // Pick the FB config/visual with the most samples per pixel
 printf( "Getting XVisualInfos\n" );
 int best_fbc = -1, worst_fbc = -1, best_num_samp = -1, worst_num_samp = 999;
 for ( int i = 0; i < fbcount; i++ )
 {
   XVisualInfo *vi = glXGetVisualFromFBConfig( display, fbc[i] );
   if ( vi )
   {
     int samp_buf, samples;
     glXGetFBConfigAttrib( display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf );
     glXGetFBConfigAttrib( display, fbc[i], GLX_SAMPLES       , &samples  );
     
     printf( "  Matching fbconfig %d, visual ID 0x%2x: SAMPLE_BUFFERS = %d,"
             " SAMPLES = %d\n", 
             i, vi -> visualid, samp_buf, samples );
     if ( best_fbc < 0 || samp_buf && samples > 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 );
 }
 // Get a visual
 int fbc_id = best_fbc;
 //int fbc_id = worst_fbc;
 XVisualInfo *vi = glXGetVisualFromFBConfig( display, fbc[ fbc_id ]  );
 printf( "Chosen visual ID = 0x%x\n", vi->visualid );
 printf( "Creating colormap\n" );
 XSetWindowAttributes swa;
 swa.colormap = XCreateColormap( display, RootWindow( display, vi->screen ), 
                                 vi->visual, AllocNone );
 swa.background_pixmap = None ;
 swa.border_pixel      = 0;
 swa.event_mask        = StructureNotifyMask;
 printf( "Creating window\n" );
 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);
 }
 XStoreName( display, win, "GL 3.0 Window");
 printf( "Mapping window\n" );
 XMapWindow( display, win );
 // See if GL driver supports glXCreateContextAttribsARB()
 //   Create an old-style GLX context first, to get the correct function ptr.
 glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
 GLXContext ctx_old = glXCreateContext( display, vi, 0, True );
 glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)
          glXGetProcAddress( (const GLubyte *) "glXCreateContextAttribsARB" );
 GLXContext ctx = 0;
 // If it doesn't, just use the old-style 2.x GLX context
 if ( !glXCreateContextAttribsARB )
 {
   printf( "glXCreateContextAttribsARB() not found"
           " ... using old-style GLX context\n" );
   ctx = ctx_old;
 }
 // If it "does", try to get a GL 3.0 context!
 else
 {
   glXMakeCurrent( display, 0, 0 );
   glXDestroyContext( display, ctx_old );
   static int context_attribs[] =
     {
       GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
       GLX_CONTEXT_MINOR_VERSION_ARB, 0,
       //GLX_CONTEXT_FLAGS_ARB        , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
       None
     };
   printf( "Creating context\n" );
   ctx = glXCreateContextAttribsARB( display, fbc[ fbc_id ], 0, 
                                     True, context_attribs );
   if ( ctx )
     printf( "Created GL 3.0 context\n" );
   else
   {
     // Couldn't create GL 3.0 context.  Fall back to old-style 2.x context.
     printf( "Failed to create GL 3.0 context"
             " ... using old-style GLX context\n" );
     ctx = glXCreateContext( display, vi, 0, True );
   }
 }
 XFree( fbc );
 // Verifying that context is a direct context
 printf( "Verifying that context is direct\n" );
 if ( ! glXIsDirect ( display, ctx ) )
 {
   printf( "Indirect GLX rendering context obtained" );
   exit(1);
 }
 printf( "Making context current\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 );
 ctx = glXGetCurrentContext(  );
 glXMakeCurrent( display, 0, 0 );
 glXDestroyContext( display, ctx );

}

Compilation

 g++ -o gl3 gl3.cxx -lGL

Execution

 > gl3
 GLX version = 1.3
 Getting matching framebuffer configs
 Found 3 matching FB configs.
 Getting XVisualInfos
   Matching fbconfig 0, visual ID 0x23: SAMPLE_BUFFERS = 0, SAMPLES = 0
   Matching fbconfig 1, visual ID 0x37: SAMPLE_BUFFERS = 1, SAMPLES = 2
   Matching fbconfig 2, visual ID 0x39: SAMPLE_BUFFERS = 1, SAMPLES = 4
 Chosen visual ID = 0x39
 Creating colormap
 Creating window
 Mapping window
 Creating context
 Created GL 3.0 context
 Verifying that context is direct
 Making context current