Announcement

Collapse
No announcement yet.

FGLRX libGL.so.1 returns null from glGetString() unless preloaded

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • FGLRX libGL.so.1 returns null from glGetString() unless preloaded

    I've been troubleshooting a problem that I've been seeing cropping up with cogl/clutter with users who have libGL.so.1 provided by fglrx (Im using the 14.12 release).

    The problem is that when cogl starts up, it likes to determine the capabilities of the OpenGL implementation on the system. It does that by calling `ctx->glGetString(GL_VERSION)` to get the current OpenGL version, among other things. The fglrx provided implementation of libGL.so.1 returns NULL when invoking glGetString() so cogl segfaults. The problem is because it does a strcmp against a null string and glib doesnt allow that and crashes out. Its been that way for at least two years.

    The standard workaround is to define the env var `COGL_OVERRIDE_GL_VERSION=1.4` this allows cogl to skip that section and move on. The next part however is even worse, cogl calls glGetString(GL_RENDERER) and glGetString(GL_VENDOR), both of which also return null and again cogl segfaults.

    The standard workaround for that is to add `LD_PRELOAD=/usr/lib64/fglrx/fglrx-libGL.so.1.2` to your environment by adding it to `xinitrc`. That shouldnt change things, because cogl is dynamically loading `libGL.so.1` anyway, and that is symlinked to `/usr/lib64/fglrx/fglrx-libGL.so.1.2` on properly configured systems. But it works. My testing shows that by adding the ld preload, the glGetString() calls return the correct values and cogl enabled programs work correctly.

    Im trying to fix it so that I dont need to have the LD_PRELOAD string defined on my system, because I shouldnt need it. I've been messing around with the cogl source files and I've determined that without the preload, it is still correctly loading the library using g_module_open() and it is correctly finding the glGetString function.

    My first thought was maybe cogl is loading a different library which also has a glGetString function, and that function was taking priority over the one in libGL. That would explain why adding the preload works because that would cause the libGL version of glGetString to be loaded first. That is not the case however, because of all the libraries loaded by cogl during its initialization, there is only one definition of glGetString, plus it uses glxGetProcAddress from libGL itself to get the address glGetString so it has to be using the right one.

    Doing some googling about possible reasons why glGetString() might return null, most answers say that it is because the OpenGL context is not valid, or is not current. I don't think that applies in this case, I don't see how adding a the library preload would somehow make the OpenGL context more valid or more current than if cogl loads it dynamically. It still goes through exactly the same create_context method and creates and initializes the context in exactly the same way.

    My only thought left is maybe it is the environment variable itself, in the fact that it is global. By defining LD_PRELOAD in xinitrc means that on login, gnome-shell starts, it is preloading that specific library at that location and using it. When cogl loads, the library defined in LD_PRELOAD is already running, that might cause glGetString to work correctly when called. When using cogl with LD_PRELOAD='' (to clear the system-wide env var) it is causing cogl to open `libGL.so.1` which is symlinked to `fglrx/fglrx-libGL.so.1.2` but maybe it doesnt know it is the same library, and because `fglrx/fglrx-libGL.so.1.2` is already running, the newly opened `libGL.so.1` cannot initialize properly and thats my glGetString() doesnt work. I guess one way to test that would be to change the LD_PRELOAD value in xinit to the symlink `/usr/lib64/libGL.so.1` rather than the full path. Or somehow override the name of the library that cogl opens to force it to open `fglrx/fglrx-libGL.so.1.2` rather than the symlink. That's just a stab in the dark, I really dont know how all of that works.

    Thanks for any suggestions you can offer.
    Last edited by flubba86; 05-29-2015, 04:30 AM.

  • #2
    Im creating a minimal program to try to reproduce this issue, for easier debugging.
    As of now, I can get glXGetProcAddress, and I can use it to find glGetString(), and calling glGetString(GL_VENDOR) returns null.
    If I create a valid OpenGL context first, and do glXMakeCurrent() to bring the context into the calling thread, then call glGetString(GL_VENDOR) then I get the correct result.

    Cogl uses glXMakeContextCurrent() which is similar, but I need to dig deeper to see whether that might not be called before trying to use glGetString().

    Comment

    Working...
    X