Looking at the memory improvements of KDecoration2

This week I finally moved kdecoration2 to the kde/workspace project structure and merged in the required backend code in kwin. This means the upcoming 5.2 release will ship with the new Breeze window decoration by default.

Thanks to the usage of the new library we get a nice performance boost in KWin. Some of this I already explained in my blog post announcing KDecoration2. The huge advantage here is that we do no longer use a QWindow as a backend and only require to hold an image the same size as the decoration. But there are more nice improvements around it. When I started designing KDecoration2 one of my aims was to focus it more on the use cases of a composited setup and design the API in such a way that a default decoration could be more efficient. Our previous default decoration Oxygen was rather heavy and KWin was not able to provide features to Oxygen which would make it more efficient. From a memory point of view the main issue with Oxygen were the shadows. With the old decoration API the shadows were part of the decoration. So the renderer got one big image for the shadow and the decoration part. But the shadow is the same for all inactive windows and could be defined by a much smaller image (lots of information is redundant). For KDecoration2 I looked at our existing shadow sharing mechanismn on X11 level and adopted a similar API which allows to provide a compressed shadow to the compositor. That way the shadow is no longer part of the window decoration and does not need to be part of the OpenGL texture. Of course this comes at the cost of needing more rendering calls (I deliberately moved the Time-memory-tradeoff towards better memory usage).

The real improvement comes when the decoration plugin can share the shadow between the decorations. This is being done for Breeze: there is never more than one shadow being created. In Breeze the shadow always has a size of 60×60 pixels, so we save 3600 pixels per decorated window. This is in addition to the saved memory for the compressed shadow instead of having the shadow as part of the window.

Today I went a step further and also modified the code in our OpenGL compositor to share the textures being created for the decoration shadow. So if two decorations have the same shadow, they will also use the same texture. This does not only save us some texture memory, but also means less pixel transfers from CPU to GPU. So a rather nice improvement. For our default decoration Breeze this means that only one shadow is created in the decoration plugin and also only one OpenGL texture needs to be created.

Unfortunately not all decoration plugins can benefit from this change. Also with KDecoration2 the problems outlined for Aurorae still exist and the change in the shadow mechanismn doesn’t improve the situation. The hope to improve this is in Qt 5.4 which gives us new useful features like QQuickRenderControl which allows us to integrate the OpenGL context used for QtQuick with our compositor’s OpenGL context. The hope is that we can render the QtQuick based decoration into an FBO and share the texture with our compositor, so that we can just bypass the normal decoration rendering process which is too costly in the case of Aurorae. I already switched the normal rendering to QQuickRenderControl if kwin is compiled with Qt 5.4 and the result is looking rather promising. Still the memory usage and performance of Aurorae will never be as good as the memory usage and performance of a native decoration. This has never been the aim of Aurorae.