Debugging GL Errors can be a time consuming task sometimes. Usually you need to query the OpenGL state machine with glGetError, which returns just an integer of the latest error.
First of all this requires a switch for checking the type of error, which could look like this:
When you execute this code, the loop will print all errors on the stack. This does not tell you when the error occurred, just that it happened before calling the function.
With Mesa you can do the same by setting an environment variable.
$ export MESA_DEBUG=1
This will give you debug output similar to this:
Mesa: User error: GL_INVALID_VALUE in glClear(0x5f01)
The usual solution is to create a macro function, which prints in which line you executed the query function, and you put a call to it in the end of every code that calls the OpenGL API.
This has to be done on propriatory drivers like NVIDIA’s, since you do not have debug information. A better approach is to get a backtrace to every failing GL call. For this, you need to rebuild your Mesa libGL.so with debug symbols, or install a debug package provided by your distribution.
To build Mesa with debug symbols you have to set the following compiler options:
export CFLAGS='-O0 -ggdb3' export CXXFLAGS='-O0 -ggdb3'
On Arch Linux this can be done in the build() function, when building mesa from ABS or mesa-git from AUR.
You will then be able to receive a backtrace with gdb. Do not forget to build your application with debug symbols. For cmake projects, like mesa-demos you can achieve this by doing
$ cmake . -DCMAKE_BUILD_TYPE=Debug
Run the application in GDB
$ gdb ./src/glsl/geom-outlining-150
Break with b on _mesa_error in the gdb command line
(gdb) b _mesa_error Function "_mesa_error" not defined. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 1 (_mesa_error) pending.
Run the program with r and receive a backtrace with bt
(gdb) r Starting program: mesa-demos/src/glsl/geom-outlining-150 [Thread debugging using libthread_db enabled] Using host libthread_db library "/usr/lib/libthread_db.so.1". Breakpoint 1, 0x00007ffff1f57550 in _mesa_error () from /usr/lib/xorg/modules/dri/i965_dri.so (gdb) bt #0 0x00007ffff1f57550 in _mesa_error () from /usr/lib/xorg/modules/dri/i965_dri.so #1 0x0000000000403555 in Redisplay () at mesa-demos/src/glsl/geom-outlining-150.c:119 #2 0x00007ffff7313741 in fghRedrawWindow () from /usr/lib/libglut.so.3 #3 0x00007ffff7313ba8 in ?? () from /usr/lib/libglut.so.3 #4 0x00007ffff7315179 in fgEnumWindows () from /usr/lib/libglut.so.3 #5 0x00007ffff7313c84 in glutMainLoopEvent () from /usr/lib/libglut.so.3 #6 0x00007ffff7313d24 in glutMainLoop () from /usr/lib/libglut.so.3 #7 0x0000000000403e41 in main (argc=1, argv=0x7fffffffe558) at mesa-demos/src/glsl/geom-outlining-150.c:392
Now we know that the GL error occurs in line 392 of geo-outlining-150.c.
You get GL errors when using GLEW in core GL contexts, since its calling the deprecated GL_EXTENSIONS enum for glGetString. You can continue debugging with c. If you want to use a modern way to load core context, try gl3w instead of GLEW.
Breakpoint 1, 0x00007ffff1f57550 in _mesa_error () from /usr/lib/xorg/modules/dri/i965_dri.so (gdb) bt #0 0x00007ffff1f57550 in _mesa_error () from /usr/lib/xorg/modules/dri/i965_dri.so #1 0x00007ffff1fcb7b4 in _mesa_GetString () from /usr/lib/xorg/modules/dri/i965_dri.so #2 0x00007ffff70ba76a in glewInit () from /usr/lib/libGLEW.so.1.13 #3 0x0000000000403deb in main (argc=1, argv=0x7fffffffe558) at mesa-demos/src/glsl/geom-outlining-150.c:381 (gdb) c Continuing. Mesa: User error: GL_INVALID_ENUM in glGetString(GL_EXTENSIONS)