About two years ago I started with bringing KWin to the world of embedded devices by implementing OpenGL ES 2.0/EGL support. Till then the compositor supported only an OpenGL 1/GLX backend which allowed effects to use Shaders emulating the fixed functionality.
The initial idea was to make this a compile time replacement. For OpenGL ES 2.0 one needs compile time checks anyway and so it seemed reasonable to just ifdef the main differences: GLX vs EGL. Our compositor itself already supported Shaders so this could all be done at runtime selection.
But as those who have used OpenGL know, the difference between OpenGL 1 and OpenGL (ES) 2 is rather large. The one is using the fixed functionality and the other is using the programmable pipeline. While we had support for Shaders we actually did not yet have support for the programmable pipeline (e.g. geometries got specified in the fixed functionality way).
The best approach would have been to just go to OpenGL 2 and the programmable pipeline directly, but back then, this seemed to be not suitable. There were (and still are) quite a lot of hardware which cannot support OpenGL 2 and the free drivers just gained support for OpenGL 2. This meant that I actually planned to have the default as it used to be on OpenGL 1 and only use the OpenGL 2 when compiled for embedded.
Quite a challenge in the adjustments were the effects which already used Shaders. Of course I did not want to have two sets of Shaders – one for desktop and one for embedded. That would have increased the maintenance costs in a way I could not have justified. The Shaders therefore got adjusted to be for the programmable pipeline, to no longer emulate fixed functionality.
The result of this and other adjustments were that instead of gaining one additional backend for EGL we also got a new OpenGL 2/GLX backend and it turned into the default and OpenGL 1 into the legacy backend.
Now fast forward two years. In the meantime quite a lot has happened which I could not foresee when I started the OpenGL ES efforts. One happening is QtQuick 2 which will be used with Qt 5. KWin is already a heavy user of QtQuick 1 and of course we want to use QtQuick 2. But this will bring in a runtime dependency for OpenGL 2. So no matter whether we actually support OpenGL 1 or not, once we are using Qt 5, we will need OpenGL 2. This puts an end-of-life warning to our OpenGL 1 based legacy compositor.
Another important development is of course Wayland which will open a complete new world of compositing to us. We will in future have to composite without an X Server. It’s still more distant future than Qt 5, but still it’s something to consider.
And also it seems to become more clear that EGL is no longer only for embedded. It becomes possible to use OpenGL on top of EGL instead of GLX and that basically throws one of my assumptions from the porting over board. Concerning EGL we have also seen in the recent past that being able to do EGL is just one part of the game: the driver also needs to support doing EGL with X. Especially if the driver is only meant to be used for Android that is unfortunately not the case.
Given all that I’m very unsatisfied with the design decisions I took two years ago and the way how the OpenGL scene is split into the GLX and EGL parts.
Recently I started a refactoring session for the Compositor and did not stop there but continued into the OpenGL scene. One of the issues I wanted to tackle was to prepare KWin to be able to use EGL as a backend for OpenGL and to be able to add more EGL backends to get that problem mentioned above solved (also I recently got a Raspberry Pi and I want to see KWin running on it).
An abstract OpenGLBackend got split out of the SceneOpenGL which is responsible for creating/releasing the OpenGL context, create Textures from window pixmaps and do the buffer swapping in the window system specific way. There are now two concrete implementations: GlxBackend and EglOnXBackend (you might guess what is the next Backend I want to implement). The advantage is now that the actual compositor does no longer need to care about the windowing system abstraction.
The second major refactoring in that area was to separate the OpenGL 1 and OpenGL 2 code paths. While in the past it made sense to have just one code path, this is for quite some time no longer the case. Everywhere there were checks whether we are in OpenGL 1 or 2 mode and overall it were mutual exclusive paths with some shared code. This is now nicely separated which makes the code cleaner and hopefully easier to maintain. It also means that we can move the OpenGL 2 compositor forward without doing compromises for the OpenGL 1 compositor.
A nice addition is that first the OpenGLBackend is created (still EGL only for ES and GLX for desktop) and then the Compositor is asked whether it can use the backend. E.g. the OpenGL 2 compositor now checks whether the backend provides a direct rendering context and just refuses if this requirement is not met. This will hopefully result in some code to have better detection which driver should use OpenGL 2 and which OpenGL 1. Up to now the detection was whether the driver supports GLSL and if the Shader compilation succeeded, the GL2 compositor got used. My idea for 4.10 is to use our GLPlatform information system to tell us whether the driver should use OpenGL 2 or 1. That way we can give users of older hardware a better experience even if their hardware is – theoretically – able to do the OpenGL 2 compositing. This needs some further adjustments like an environment variable to enforce a compositor (config option already exists).
The change also nicely grouped all the OpenGL 1 code into one area which will be easier to remove once we decide that the End of Life is reached. Removing code is not as easy as one might expect and that is actually quite a project. To go to that direction I plan to introduce a new build option to build KWin without OpenGL 1 support, which is basically the same as the build option for OpenGL ES, but the existing build option could be used for actual differences between OpenGL 2 and OpenGL ES 2.0. And of course EGL needs to be uncoupled from the OpenGL ES build option – it is totally valid to compile the EGL backend for OpenGL.