cannot get GL context > v2.10 after installing 64-bit linux driver v310.19

My 3D engine program was running with OpenGL v3.20 context before I installed the latest nvidia driver on my 64-bit ubuntu v12.04 computer (nvidia driver 310.19, which is still shown as current as of today). After I installed the new driver, my program stopped working and the first error generated by my program was glGenVertexArrays() returning a value of zero (and no error).

At first I thought the problem was with VAOs, but after inspecting the printout my program generates in the console window, I noticed it appears to say my application is no longer receiving the OpenGL v3.20 compatibility context it requests. With my new GTX680 and v310.19 driver, it should be able to get OpenGL contexts up to v4.30 as I understand things.

So the question probably is, why is my program not getting an OpenGL v3.20 context?

Since we seem to have narrowed down the problem to OpenGL context and not VAO functions, I create this new, appropriately named threat to continue this conversation.

I have always had problems initializing the combination of xlib, GLX, GLEW, OpenGL. I have never been able to sufficiently grasp everything necessary about xlib, GLX, GLEW and OpenGL and thus fully understand what is necessary, much less appropriate.

I guess the best way to attempt to resolve this is to explain exactly what I am doing now. Here goes:

#1: Before anything significant happens in my program, it executes the ig_graphics_initialize() function, which only calls old-style GLX functions and creates, then destroys an old-style GLX context and window, then initialize GLEW so all newer GLX functions become visible.

#2: Later, after everything is initialized, the program creates a default window with newer GLX functions (and should-be v3.20 compatibility context). It was creating this OpenGL v3.20 compatibility context before I updated my nvidia GPU to GTX680 and nvidia driver to v310.19 (64-bit version).

Next I’ll be more specific and show the code in the ig_graphics_initialize() function, and then the ig_window_create() function. I suspect that something “minor” changed that obsoletes my old approach, and now requires something be done in a different order, or with different functions or arguments. But what do I know? Not enough, obviously.

I’ll appreciate any tips or comments anyone might have, especially from xlib, GLX, GLEW, OpenGL initialization gurus.


CORE_PUBLIC_DEFINE_CPU  ig_graphics_initialize (cpu mode, cpu options) {
//
// We must initialize GLX, OpenGL and GLEW.
//
// However, apparently we cannot initialize GLEW until we have created GLX and OpenGL contexts,
// which requires we create an XWindows window, and then create a GLX/OpenGL [rendering] context.
// Therefore, during application initialization, we must create an X window (no need to map it),
// then create a GLX/OpenGL [rendering] context, then call glewInit(), then destroy the window
// and the context - then free any resources we created to do all the above.
//
// By calling glewInit() we set up the addresses of all later-version GLX and OpenGL functions,
// so henceforth we can create and manipulate GLX/OpenGL contexts with more advanced functions.

  int error = 0;
  static int glew_initialized = 0;

  Window xwindow = 0;
  Display* xdisplay = XOpenDisplay(NULL);
  int xscreen = XDefaultScreen (xdisplay);
  Window xroot = XRootWindow (xdisplay, xscreen);
  Window xwindow_root_default = XDefaultRootWindow (xdisplay);
  Screen* xscreen_default_of_display = XDefaultScreenOfDisplay (xdisplay);
  Screen* xscreen_of_display = XScreenOfDisplay (xdisplay, xscreen);
  GC xgraphics_context = XDefaultGC (xdisplay, xscreen);
  Visual* xvisual_default = XDefaultVisual (xdisplay, xscreen);
  int xdisplay_width = XDisplayWidth (xdisplay, xscreen);
  int xdisplay_height = XDisplayHeight (xdisplay, xscreen);

  Colormap xcolormap;
  GLXWindow glxwindow;
  GLXContext glxcontext;
  XVisualInfo* xvisualinfo = 0;
  GLXFBConfig* glxfbconfig = 0;
  XSetWindowAttributes xsetwindowattributes;

  int major = 0;
  int minor = 0;
  int errorbase = 0;
  int eventbase = 0;
//
// not sure what the following line is for, but see comments in various forums
//
  glewExperimental = GL_TRUE;

  error = glXQueryVersion (xdisplay, &major, &minor);
  error = glXQueryExtension (xdisplay, &errorbase, &eventbase);
  const char* extensions = glXQueryExtensionsString (xdisplay, xscreen);
  const char* clientvendor = glXGetClientString (xdisplay, GLX_VENDOR);
  const char* clientversion = glXGetClientString (xdisplay, GLX_VERSION);
  const char* clientextensions = glXGetClientString (xdisplay, GLX_EXTENSIONS);
  const char* servervendor = glXQueryServerString (xdisplay, xscreen, GLX_VENDOR);
  const char* serverversion = glXQueryServerString (xdisplay, xscreen, GLX_VERSION);
  const char* serverextensions = glXQueryServerString (xdisplay, xscreen, GLX_EXTENSIONS);

  printf ("GLX version          ::: major.minor == %d.%d\n", major, minor);
  printf ("GLX offsets          ::: errorbase : eventbase == %d %d\n", errorbase, eventbase);
  printf ("GLX extensions       ::: \n", extensions);
  printf ("GLX clientvendor     ::: \n", clientvendor);
  printf ("GLX clientversion    ::: \n", clientversion);
  printf ("GLX clientextensions ::: \n", clientextensions);
  printf ("GLX servervendor     ::: \n", servervendor);
  printf ("GLX serverversion    ::: \n", serverversion);
  printf ("GLX serverextensions ::: \n", serverextensions);
//
// set up xvisualattributes[] array needed in glXChooseVisual() argument list
//
  int xvisualattributes[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, 0 };
//
// create xvisualinfo so we can create GLX/OpenGL context so we can call glewInit()
//
  xvisualinfo = glXChooseVisual (xdisplay, xscreen, xvisualattributes);
  if (xvisualinfo == 0) {
    printf ("glXChooseVisual() : error : xvisualinfo == 0 : GLX/OpenGL initialization failed\n");
    return (CORE_ERROR_INTERNAL);
  }
//
// create colormap so we can create GLX/OpenGL context so we can call glewInit()
//
  xcolormap = XCreateColormap (xdisplay, xroot, xvisualinfo->visual, AllocNone);
  if (xcolormap == 0) {
    XFree (xvisualinfo);
    printf ("XCreateColormap() : error : xcolormap == 0 : GLX/OpenGL initialization failed\n");
    return (CORE_ERROR_INTERNAL);
  }
//
// #####  establish variables required to create the window  #####
//
// to eliminate events of one or more types, comment out the corresponding lines below (do not be an idiot and delete them)
//
  int xeventmask = 0;
  xeventmask = xeventmask | KeyPressMask;              // bit  0
  xeventmask = xeventmask | KeyReleaseMask;            // bit  1
  xeventmask = xeventmask | ButtonPressMask;           // bit  2
  xeventmask = xeventmask | ButtonReleaseMask;         // bit  3
  xeventmask = xeventmask | EnterWindowMask;           // bit  4
  xeventmask = xeventmask | LeaveWindowMask;           // bit  5
  xeventmask = xeventmask | PointerMotionMask;         // bit  6
  xeventmask = xeventmask | PointerMotionHintMask;     // bit  7
  xeventmask = xeventmask | Button1MotionMask;         // bit  8
  xeventmask = xeventmask | Button2MotionMask;         // bit  9
  xeventmask = xeventmask | Button3MotionMask;         // bit 10
  xeventmask = xeventmask | Button4MotionMask;         // bit 11
  xeventmask = xeventmask | Button5MotionMask;         // bit 12
  xeventmask = xeventmask | ButtonMotionMask;          // bit 13
  xeventmask = xeventmask | KeymapStateMask;           // bit 14
  xeventmask = xeventmask | ExposureMask;              // bit 15
  xeventmask = xeventmask | VisibilityChangeMask;      // bit 16
  xeventmask = xeventmask | StructureNotifyMask;       // bit 17
//xeventmask = xeventmask | ResizeRedirectMask;        // bit 18 !!!!!  DANGER  !!!!!  DO NOT ENABLE
  xeventmask = xeventmask | SubstructureNotifyMask;    // bit 19
  xeventmask = xeventmask | SubstructureRedirectMask;  // bit 20
  xeventmask = xeventmask | FocusChangeMask;           // bit 21
  xeventmask = xeventmask | PropertyChangeMask;        // bit 22
  xeventmask = xeventmask | ColormapChangeMask;        // bit 23
  xeventmask = xeventmask | OwnerGrabButtonMask;       // bit 24

  xsetwindowattributes.colormap = xcolormap;           // vanilla RGBA
  xsetwindowattributes.background_pixel = None;        // prevent background clear - let OpenGL glClear()
  xsetwindowattributes.background_pixmap = None;       // default = None
  xsetwindowattributes.border_pixmap = None;           // default = CopyFromParent
  xsetwindowattributes.border_pixel = None;            // default = Undefined
  xsetwindowattributes.cursor = None;                  // default = None
  xsetwindowattributes.event_mask = xeventmask;        // 0x0001FFFF if events of all types are enabled
  xsetwindowattributes.bit_gravity = StaticGravity;
//
// assign values to any arguments to XCreateWindow() that are not already specified
//
  int x = 32;
  int y = 32;
  int width = 640;
  int height = 480;
  int xselectattributes = (CWBackPixel | CWBorderPixel | CWBitGravity | CWColormap | CWEventMask);
//
// create xwindow so we can create GLX/OpenGL context so we can call glewInit()
//
  xwindow = XCreateWindow (xdisplay, xroot, x, y, width, height, 0, xvisualinfo->depth, InputOutput, xvisualinfo->visual, xselectattributes, &xsetwindowattributes);
  if (xwindow == 0) {
    XFree (xvisualinfo);
    printf ("XCreateWindow() : error : xwindow == 0 : GLX/OpenGL initialization failed\n");
    return (CORE_ERROR_INTERNAL);
  }
//
// no need for the next 2 lines
//
// XMapWindow (xdisplay, xwindow);
// XStoreName (xdisplay, xwindow, "GLX/OpenGL initialization");
//
// create GLX / OpenGL context so we can create GLX/OpenGL context so we can call glewInit()
//
  glxcontext = glXCreateContext (xdisplay, xvisualinfo, 0, GL_TRUE);
  if (glxcontext == 0) {
    XFree (xvisualinfo);
    printf ("glXCreateContext() : error : glxcontext == 0 : GLX/OpenGL initialization failed\n");
    return (CORE_ERROR_INTERNAL);
  }
//
// make GLX / OpenGL context current == active
//
  glXMakeCurrent (xdisplay, xwindow, glxcontext);
//
// call glewInit() to initialize GLX/OpenGL functions (so we can call those functions)
//
  error = glewInit();

  if (error != GLEW_OK) {
    printf("glewInit() : error : %s\n", glewGetErrorString(error));
    return (CORE_ERROR_INTERNAL);
  } else {
    glew_initialized = 1;
    printf ("status: GLEW initialized %s\n", glewGetString(GLEW_VERSION));
  }
//
// destroy window, destroy GLX/OpenGL context
//
  error = XUnmapWindow (xdisplay, xwindow); // unmap window here if window mapped previously, else not needed
  error = XDestroyWindow (xdisplay, xwindow); // figure out how the best way to destroy windows in xlib/XWindows
  glXDestroyContext (xdisplay, glxcontext); // destroy GLX/OpenGL [rendering] context
  XFree (xvisualinfo); // free allocated resource
//
// test some basic OpenGL functions - and make sure OpenGL is initialized
//
  const GLubyte* glvendor = glGetString (GL_VENDOR);
  const GLubyte* glversion = glGetString (GL_VERSION);
  const GLubyte* glrenderer = glGetString (GL_RENDERER);
  const GLubyte* glextensions = glGetString (GL_EXTENSIONS);
 
  printf ("OGL vendor           ::: %s\n", (char*)glvendor);
  printf ("OGL version          ::: %s\n", (char*)glversion);
  printf ("OGL renderer         ::: %s\n", (char*)glrenderer);
  printf ("OGL extensions       ::: %s\n", (char*)glextensions);

  return (0);
}

NOTE: You can skip the first ~130 lines below to get to the meat of the function (where real xlib, GLX, GLEW stuff happens)


CORE_PUBLIC_DEFINE_CPU  ig_window_create (cpu winid, cpu options, cpu x, cpu y, cpu width, cpu height, cpu dispid) {

  int error = 0;
  int success = 0;
  int fullscreen = 0;
  int objects = igstate.object_after;

  static cpu glew_initialized = 0;

  ig_display* display = 0;
  display = (ig_display*)igstate.object[dispid]; // get display structure

  error = ig_window_new (winid, 0); // create and initialize new window structure
  if (error < 0) { return (error); }

  ig_window* window = 0;
   window = (ig_window*)igstate.object[winid]; // get address of window structure
//
// establish display characteristics
//
  int display_width = display->width;
  int display_height = display->height;
  Display* xdisplay = display->xdisplay;
  Window xwindow = 0;
//
// NOTE: much of the following information was put into the IG display structure when the display was opened with XOpenDisplay() in ig_display_create().  In the long run we must work with the values from our display object so windows can be opened on other displays (on the same computer and across any network).
//
  int xscreen = XDefaultScreen (xdisplay);
  Window xroot = XRootWindow (xdisplay, xscreen);
  Window xwindow_root_default = XDefaultRootWindow (xdisplay);
  Screen* xscreen_default_of_display = XDefaultScreenOfDisplay (xdisplay);
  Screen* xscreen_of_display = XScreenOfDisplay (xdisplay, xscreen);
  GC xgraphics_context = XDefaultGC (xdisplay, xscreen);
  Visual* xvisual_default = XDefaultVisual (xdisplay, xscreen);
  int xdisplay_width = XDisplayWidth (xdisplay, xscreen);
  int xdisplay_height = XDisplayHeight (xdisplay, xscreen);

  Colormap xcolormap;
  XVisualInfo* xvisualinfo = 0;
  XSetWindowAttributes xsetwindowattributes;
  GLXWindow glxwindow;
  GLXContext glxcontext;
  GLXFBConfig* glxfbconfig = 0;
//
// get system metrics --- size-in-pixels of window frame and title-bar
//
  int cmo = 1;               // number of display-monitors on this/local computer
  int xfr = 4;               // frame width in pixels = 4 usually (on both left and right edges)
  int yfr = 4;               // frame height in pixels = 4 usually (on both top and bottom edges)
  int yca = 19;              // guess this value until we capture information in window message handler
  int xsc = display_width;   // full screen width - possibly reduced to support start/other bars
  int ysc = display_height;  // full screen height - possibly reduced to support start/other bars
  int xfs = display_width;   // full screen width - not reduced by start-bar or other travesties
  int yfs = display_height;  // full screen height - not reduced by start-bar or other travesties
//
// find functions to return the following values --- generally "window manager hints" in XWindows
//
  if (x < 0) { x = 0; }                                                  // fix invalid x coordinate
  if (y < 0) { y = 0; }                                                  // fix invalid y coordinate
  if (x > display_width) { x = display_width - 32; }                     // make window at least partially visible
  if (y > display_height) { y = display_height - 32; }                   // make window at least partially visible
  if (width visual, AllocNone);
  if (xcolormap == 0) { printf ("XCreateColormap() : error : xcolormap == 0 : terminate process\n"); return (CORE_ERROR_INTERNAL); }
//
// define XCreateWindow() arguments
//
  int xeventmask = 0;
  xeventmask = xeventmask | KeyPressMask;             // bit  0
  xeventmask = xeventmask | KeyReleaseMask;           // bit  1
  xeventmask = xeventmask | ButtonPressMask;          // bit  2
  xeventmask = xeventmask | ButtonReleaseMask;        // bit  3
  xeventmask = xeventmask | EnterWindowMask;          // bit  4
  xeventmask = xeventmask | LeaveWindowMask;          // bit  5
  xeventmask = xeventmask | PointerMotionMask;        // bit  6
  xeventmask = xeventmask | PointerMotionHintMask;    // bit  7
  xeventmask = xeventmask | Button1MotionMask;        // bit  8
  xeventmask = xeventmask | Button2MotionMask;        // bit  9
  xeventmask = xeventmask | Button3MotionMask;        // bit 10
  xeventmask = xeventmask | Button4MotionMask;        // bit 11
  xeventmask = xeventmask | Button5MotionMask;        // bit 12
  xeventmask = xeventmask | ButtonMotionMask;         // bit 13
  xeventmask = xeventmask | KeymapStateMask;          // bit 14
  xeventmask = xeventmask | ExposureMask;             // bit 15
  xeventmask = xeventmask | VisibilityChangeMask;     // bit 16
  xeventmask = xeventmask | StructureNotifyMask;      // bit 17
//xeventmask = xeventmask | ResizeRedirectMask;       // bit 18 DANGER ::: DO NOT ENABLE
  xeventmask = xeventmask | SubstructureNotifyMask;   // bit 19
  xeventmask = xeventmask | SubstructureRedirectMask; // bit 20
  xeventmask = xeventmask | FocusChangeMask;          // bit 21
  xeventmask = xeventmask | PropertyChangeMask;       // bit 22
  xeventmask = xeventmask | ColormapChangeMask;       // bit 23
  xeventmask = xeventmask | OwnerGrabButtonMask;      // bit 24
 
  xsetwindowattributes.colormap = xcolormap;          // vanilla RGBA
  xsetwindowattributes.background_pixel = None;       // prevent background clear - let OpenGL glClear()
  xsetwindowattributes.background_pixmap = None;      // default = None
  xsetwindowattributes.border_pixmap = None;          // default = CopyFromParent
  xsetwindowattributes.border_pixel = None;           // default = Undefined
  xsetwindowattributes.cursor = None;                 // default = None
  xsetwindowattributes.event_mask = xeventmask;       // 0x0001FFFF if events of all types are enabled
  xsetwindowattributes.bit_gravity = StaticGravity;   // what is this ???

  int xselectattributes = (CWBackPixel | CWBorderPixel | CWBitGravity | CWColormap | CWEventMask);

  xwindow = XCreateWindow (xdisplay, xroot, x, y, width, height, 0, xvisualinfo->depth, InputOutput, xvisualinfo->visual, xselectattributes, &xsetwindowattributes);
  if (xwindow == 0) { printf ("error ::: XCreateWindow()\n"); return (-1); }

  error = XSetStandardProperties (xdisplay, xwindow, "IG", "window.bmp", 0, 0, 0, 0);
  if (error == 0) { printf ("error ::: XSetStandardProperties()\n"); }

  char* STRING_WM_DELETE_WINDOW = (char*) "WM_DELETE_WINDOW";
  Atom XA_WM_DELETE_WINDOW = XInternAtom (xdisplay, STRING_WM_DELETE_WINDOW, 0);
  error = XSetWMProtocols (xdisplay, xwindow, &XA_WM_DELETE_WINDOW, 1);
  igstate.message_close_window = XA_WM_DELETE_WINDOW;
//
// #######################  in theory the glXMakeContextCurrent() should not be here, but........
// #####  IMPORTANT  #####  simple tests indicate this glXMakeContextCurrent() must be here
// #######################  because putting this in CreateNotify causes segment violation
//
  glxwindow = glXCreateWindow (xdisplay, glxfbconfig[0], xwindow, 0);
  error = glXMakeContextCurrent (xdisplay, glxwindow, glxwindow, glxcontext);
//
// do not automatically map/show/display windows --- we have a function for that == ig_window_display()
//
// error = XMapWindow (xdisplay, xwindow);
//
// populate window structure
//
  window->displayid = dispid;
  window->xdisplay = xdisplay;
  window->xwindow = xwindow;
  window->glxwindow = glxwindow;
  window->glxcontext = glxcontext;
  window->glxfbconfig = glxfbconfig[0];
  window->style = 0;
  window->type = options;
 
  if (fullscreen) {
    window->x = 0;
    window->y = 0;
    window->xdisp = x;
    window->ydisp = y;
    window->width = width;
    window->height = height;
    window->xframe = x;
    window->yframe = y;
    window->wframe = width;
    window->hframe = height;
    window->lborder = 0;
    window->tborder = 0;
    window->rborder = 0;
    window->bborder = 0;
    window->cborder = 0;
    window->resized = 1;
  } else {
    window->x = 0;
    window->y = 0;
    window->xdisp = x;
    window->ydisp = y;
    window->width = width;
    window->height = height;
    window->xframe = x - xfr;
    window->yframe = y - yfr - yca;
    window->wframe = width + xfr + xfr;
    window->hframe = height + yfr + yfr + yca;
    window->lborder = xfr;
    window->tborder = yfr;
    window->rborder = xfr;
    window->bborder = yfr;
    window->cborder = yca;
    window->resized = 1;
  }
//
//
// ###############################################################################
// #####  XWindows does NOT generate an event when a new window is created!  #####
// #####  But work must be done when windows are created, so generate event  #####
// ###############################################################################
//
  XCreateWindowEvent xmessage;
  xmessage.type = CreateNotify;
  xmessage.display = xdisplay;
  xmessage.window = xwindow;
  xmessage.parent = xroot;
  xmessage.send_event = 0;
  xmessage.serial = 0;
  xmessage.x = x;
  xmessage.y = y;
  xmessage.width = width;
  xmessage.height = height;
  xmessage.border_width = xfr;
  xmessage.override_redirect = 0;
  error = XSendEvent (xdisplay, xwindow, 0, StructureNotifyMask, (XEvent*)&xmessage);
//
// free all resources we're supposed to free according to xlib and GLX function documentation
//
  XFree (glxfbconfig);
  XFree (xvisualinfo);

  return (winid); // return window id #
}

There is a bug in GLEW. It uses glGetString(GL_EXTENSIONS) and GL_EXTENSIONS is deprecated. Seems it’s been around since 2010 without anyone actually fixing it. Possibly a fix will be in GLEW 1.9.2 (although I’m not holding my breath).

http://sourceforge.net/p/glew/bugs/120/
http://sourceforge.net/p/glew/bugs/174/
http://www.geeks3d.com/20100721/glew-does-not-work-with-an-opengl-3-or-4-core-profile/

You can try and patch it yourself or look at using another extension loader like gl3w or glee (OpenGL 3.0 only).

SOLVED

Ah, just shoot me! I hate when this kind of nonsense happens. Maybe/Probably my fault.

In my IDE, I had directory “/usr/lib” specified as a linker search path… probably from before they switched over to /usr/lib/i386-linux-gnu and /usr/lib/x64-linux-gnu a year or so ago. I had both specified, but “/usr/lib” was first in the list (which might matter).

So presumably what was happening was one or another of the libraries my 3D engine was linking to was an older version in the “/usr/lib” directory, while a newer version exists in the “/usr/lib/i386-linux-gnu” and “/usr/lib/x64-linux-gnu” directories.

It also seems to me like the codeblocks IDE (or perhaps the GNU tools/linker) has gotten “smarter” (maybe too smart) about what directories to search for shared libraries. I forgot to put any linker library names or search directories in my test program, yet somehow it linked to xlib and GL (neither of which is that standard a library, nothing like the C standard libraries or something).

Anyhow, that was the problem all along. Gads, can’t believe how much BS I went through where no problems in my programs existed.

Probably the new nvidia drivers put their shared libraries in the /usr/lib/i386-linux-gnu and /usr/lib/x64-linux-gnu directories… while older versions of the shared libraries got put in /usr/lib directly (or something along those lines). Otherwise, who freaking knows.

Nice to have it solved, but I hate when I waste a day or three on something as stupid as this. Sigh.