What does LIBGL_ALWAYS_INDIRECT=1 actually do?
Indirect rendering means that the GLX protocol will be used to transmit OpenGL commands and the X.org will do the real drawing.
Direct rendering means that application can access hardware directly without communication with X.org first via mesa.
The direct rendering is faster as it does not require change of context into X.org process.
Clarification: In both cases the rendering is done by GPU (or technically - may be done by GPU). However in indirect rendering the process looks like:
- Program calls a command(s)
- Command(s) is/are sent to X.org by GLX protocol
- X.org calls hardware (i.e. GPU) to draw
In direct rendering
- Program calls a command(s)
- Command(s) is/are sent to GPU
Please note that because OpenGL was designed in such way that may operate over network the indirect rendering is faster then would be naive implementation of architecture i.e. allows to send a buch of commands in one go. However there is some overhead in terms of CPU time spent for context switches and handling protocol.
First, LIBGL_ALWAYS_INDIRECT
is a flag related to the Mesa 3D client-side OpenGL implementation (libGL.so). It won't work with binary drivers from other vendors (e.g. NVIDIA).
Second, to answer your question directly, last I looked at the Mesa code the flag works like this:
Pre ~2008 when Mesa was working with an indirect X server (e.g. you did ssh -X
or explicitly set your display to a non-local server) it would make the list of GLX visuals provided by the remote X server available to your GLX application. The application calls e.g. glXChooseVisual() and Mesa would find something reasonable to match, and subsequent glFoo()
calls would be sent to the remote X server where they were executed by whatever libGL the remote X server was hooked up to (likely your GPU).
Around the end of 2008 Mesa was changed so that it wanted to use its internal software OpenGL renderer (Xlib driver) for remote X connections. (Some distributions like SuSE specifically patched this to go back to the old behaviour.) This would only kick in if the remote X server offered a GLX visual that exactly matched one of the internal software renderer. (Otherwise you'd get the common, "Error: couldn't get an RGB, Double-buffered visual".) If such a visual was found then Mesa would render all glFoo()
commands with the local (to application) CPU, and push the result to the remote X server via raster images (XPutImage()
); Setting LIBGL_ALWAYS_INDIRECT=1
(prior to Mesa 17.3 any value would work, since then you must use 1 or true) tells Mesa to ignore normal direct rendering or the internal software renderer and use indirect rendering like it used to.
Choosing indirect rendering or direct software rendering will affect two things:
OpenGL Version
- Indirect rendering is generally restricted to OpenGL 1.4.
- Direct software rendering will support whatever the Mesa software rasterizer supports, probably OpenGL 2.1+
Performance
- If your application is designed for indirect connections (it uses display lists, minimizes round-trip queries) then you can get reasonable performance.
- If your application does something stupid like
glGetInteger()
100 times per frame then even on a fast LAN each of those queries will easily take up 1ms, or 100ms total per frame, meaning you could never get more than 10 FPS in your application. - That same application, if the rendering load is not too heavy, may perform very well with direct software rendering, since all those
glGetInteger()
calls are answered directly in a matter of micro or nanoseconds. - If your application creates a million-vertex display list and then does lots of rotating then indirect rendering with a real GPU on the other end will give much better performance.
- An application also may fall back to a different code path when it only has OpenGL 1.4 vs 2.x available, which also can affect performance.
So, you can see without the exact details of your application and your network characteristics, it is impossible to say whether direct software rendering or indirect rendering is better for any given situation.
In your case it seems that you're running a local kwin instance, so the effect of LIBGL_ALWAYS_INDIRECT
is to force indirect rendering to your local X server. This apparently either changes kwin
's behaviour (OpenGL 1.4 only) or avoids some other bug.
Definitely you want to remove this flag when the underlying issue is fixed.