haskell-opengl / OpenGL

Haskell bindings to OpenGL
http://www.haskell.org/haskellwiki/OpenGL
BSD 3-Clause "New" or "Revised" License
147 stars 26 forks source link

Problems with GHCi and NVIDIA drivers on Ubuntu 12.04 #42

Closed dagit closed 9 years ago

dagit commented 11 years ago

From HOpenGL mailing list: http://www.haskell.org/pipermail/hopengl/2013-July/001055.html

When I try to run OpenGL examples on Ubuntu 12.04 with the latest Haskell platform (2013.2.0.0, incl. GHC 7.6.3), the following happens:

svenpanne@svenpanne:~/haskell-platform-2013.2.0.0/packages/GLUT-2.4.0.0/examples/RedBook$
runhaskell Smooth.hs
freeglut (Smooth.hs):  ERROR:  Internal error <FBConfig with necessary
capabilities not found> in function fgOpenWindow
X Error of failed request:  BadWindow (invalid Window parameter)
  Major opcode of failed request:  4 (X_DestroyWindow)
  Resource id in failed request:  0x0
  Serial number of failed request:  37
  Current serial number in output stream:  40

I am using an x86_64 Ubuntu 12.04 distro (with some minor corporate modifications, but they probably don't matter here) with NVIDIA drivers. This means that the dynamic linker will load NVIDIA's libGL.so, as can be seen e.g. here:

svenpanne@svenpanne:~$ ldd /usr/lib/x86_64-linux-gnu/libglut.so | grep libGL
libGL.so.1 => /usr/lib/nvidia-current/libGL.so.1 (0x00007f1ddc76e000)
svenpanne@svenpanne:~$ dpkg -S /usr/lib/nvidia-current/libGL.*
nvidia-current: /usr/lib/nvidia-current/libGL.so
nvidia-current: /usr/lib/nvidia-current/libGL.so.1
nvidia-current: /usr/lib/nvidia-current/libGL.so.310.51

This is OK, and this is the libGL.so which will be found by 'ld' when one simply specifies '-lglut' for compilation via gcc. This can be seen e.g. when tracing things during the linking stage of the "Hello, world!" example from the Red Book:

svenpanne@svenpanne:~/redbook$ strace -f gcc hello.o -lglut 2>&1 |
grep 'libglut\|libGL' | grep -v ENOENT
[pid  7782] stat("/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/libglut.so",
{st_mode=S_IFREG|0644, st_size=287720, ...}) = 0
[pid  7782] open("/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/libglut.so",
O_RDONLY) = 8
[pid  7782] open("/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/libglut.so",
O_RDONLY) = 13
[pid  7782] stat("/usr/lib/nvidia-current/libGL.so.1",
{st_mode=S_IFREG|0644, st_size=1099504, ...}) = 0
[pid  7782] open("/usr/lib/nvidia-current/libGL.so.1", O_RDONLY) = 14
[pid  7782] open("/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/libglut.so",
O_RDONLY) = 5
[pid  7782] open("/usr/lib/nvidia-current/libGL.so.1", O_RDONLY) = 12
[pid  7782] open("/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/libglut.so",
O_RDONLY) = 8
...

But things get weird when one explicitly specifies '-lGLU and -lGL' in addition to '-lglut' (something GHC's package system is actually doing behind the scenes, too):

svenpanne@svenpanne:~/redbook$ strace -f gcc hello.o -lglut -lGLU -lGL
2>&1 | grep 'libglut\|libGL' | grep -v ENOENT
[pid  7943] stat("/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/libglut.so",
{st_mode=S_IFREG|0644, st_size=287720, ...}) = 0
[pid  7943] open("/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/libglut.so",
O_RDONLY) = 8
[pid  7943] stat("/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/libGLU.so",
{st_mode=S_IFREG|0644, st_size=449168, ...}) = 0
[pid  7943] open("/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/libGLU.so",
O_RDONLY) = 9
[pid  7943] stat("/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/libGL.so",
{st_mode=S_IFREG|0644, st_size=390352, ...}) = 0
[pid  7943] open("/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/libGL.so",
O_RDONLY) = 10
[pid  7943] open("/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/libglut.so",
O_RDONLY) = 4
[pid  7943] open("/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/libGL.so",
O_RDONLY) = 5
...

This happens because of there is a symbolic link in the standard library search path for gcc, which is part of a Mesa package:

svenpanne@svenpanne:~$ ll /usr/lib/x86_64-linux-gnu/libGL.so
lrwxrwxrwx 1 root root 13 Jun 18 22:54
/usr/lib/x86_64-linux-gnu/libGL.so -> mesa/libGL.so
svenpanne@svenpanne:~$ dpkg -S /usr/lib/x86_64-linux-gnu/libGL.so
libgl1-mesa-dev: /usr/lib/x86_64-linux-gnu/libGL.so

Funnily enough, when you run the application later, it will use NVIDIA's libGL.so, because the dynamic linker consults /etc/ld.so.{cache,conf} and of course does not look into gcc's library search path:

svenpanne@svenpanne:~/redbook$ ldd a.out | grep libGL
libGL.so.1 => /usr/lib/nvidia-current/libGL.so.1 (0x00007f7841b34000)

So in a nutshell: If you are explicit about your library dependencies, things are inconsistent on Ubuntu. Because of this, GHCi loads Mesa's libGL.so (found via 'gcc --print-names), which does not work with NVIDIA drivers.

The question is: What to do about this? Adding /usr/lib/nvidia-current to OpenGLRaw's library-dirs is wrong, because this will fail when you e.g. temporarily switch to Mesa for OpenGL. I have the very strong feeling that this is a Ubuntu bug: The link '/usr/lib/x86_64-linux-gnu/libGL.so => mesa/libGL.so' is simply wrong in the presence of NVIDIA drivers, and one should fix this by making it point to /usr/lib/nvidia-current/libGL.so. A quick Google search found that other people have similar problems:

https://answers.launchpad.net/ubuntu/+source/nvidia-graphics-drivers/+question/182181 http://techtidings.blogspot.de/2012/01/problem-with-libglso-on-64-bit-ubuntu.html http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=630527

svenpanne commented 9 years ago

Closing this, I don't think it is relevant anymore.