This week we finally released Plasma 5.0 including KWin 5.0 and also a new design called “Breeze”. While Breeze provides a window decoration, KWin still defaults to Oxygen and that’s for a good reason. As I had been asked quite often why that’s the case and on the other side got lots of feedback from disappointed users using the Breeze decoration I think it’s needed to explain in a blog post the technical background.
I start with explaining how our window decorations work in KWin 4. KWin is a so-called re-parenting window manager. This means the managed X11 window is put into another X11 window providing the windwow frame. In KWin we use a QWidget for the window frame. Thus we are also restricted to what QWidget provides us. Our window decoration API predates the Compositing support and this adds quite some restrictions to it. Our solution is to intercept all paint events on the decoration’s QWidget and suppress it, trigger a repaint of the compositor and in the rendering pass ensure the decoration widget repaints to a temp image which then gets copied into a texture to be rendered by the Compositor.
The Breeze window decoration theme is based on the Aurorae theme engine. As I’m the main author of Aurorae I can bash it in this blog post without feeling sorry about it Aurorae was designed to make it very easy to style a decoration and to make use of the new added translucency features. Being a solution which could be used as a default decoration was never the aim. The idea was to allow users who want the customizability this feature while the majority of the users could use the faster native themes. Aurorae was never fast and will never be fast. Over the time the performance improved, especially thanks to using QML. But also in that case it was only usable with the raster graphics system in KWin 4 times.
Now in KWin 5 the usage of QML is the main problem which makes it difficult to use Aurorae at all. QtQuick uses the SceneGraph and uses QWindow instead of QWidget. That’s quite a bummer for our QWidget based API. We adjusted the internal usage to support QWindow based decorations but that was quite a tough road as there are differences in the behavior of the windows. As it’s no longer QWidget based our interception of paint events is broken and we needed a new solution for it. And this solution is even more ugly than the old one because QtQuick is nowadays rendering through OpenGL. Due to limitations in Qt’s OpenGL implementation (might be addressed in Qt 5.4) we cannot share with the OpenGL context used by QtQuick. But we need to get the content from the Aurorae window into our OpenGL texture. The solution is to render to a QOpenGLFrameBufferObject and read it back into a QImage just to upload back to a texture. Not only is this a huge overhead to copy the content from GPU to RAM and back to GPU it’s also wasting lots of memory. The frame buffer object has the same size as the window and that’s way larger than the actual window decoration. In case of a maximized window it’s not just the title bar area but the complete window. And that overhead exists for each window.
That alone might render Aurorae completely unusable. I’m currently using the Breeze theme and KWin needs more than 200 MB of RAM – not really acceptable. But the situation is even worse. With QWindow we don’t get to know which areas got updated. So whenever e.g. a button gets updated we have to repaint the complete window including the complete copy of the decoration content. Which especially in animation situations is quite a problem.
The last problem to mention is OpenGL. QtQuick is supposed to use a dedicated rendering thread, but Qt disables that for all Mesa drivers and instead uses the main thread. But that’s also the thread KWin’s compositing OpenGL context lives in. That’s quite a performance problem and also introduces lots of instability problems (might also be addressed in Qt 5.4).
Overall the situation is so bad that colleagues recommended to disable Aurorae overall in the 5.0 release. As we released with it you can see that I disagree in that point. There is hardware where it’s working quite fine – on my system it doesn’t matter that it uses lots of RAM and if your driver supports Qt’s threaded rendering the performance problems are mostly gone and also all stability problems are gone. So the situation hasn’t changed: for users who want to customize there is a solution but it might introduce a loss of performance. But as a default theme like Breeze it’s clearly not an option.
So what’s the road forward? I started implementing a new decoration API removing the restriction of the decoration being QWidget based and at the same time I started implementing the Breeze decoration with this new API. I hope that we can introduce this in KWin 5.1. I’ll write another blog post about it soon and also prepare lots of small and easy tasks for new developers to join in this effort and help making a kick-ass decoration solution for 5.1