wl_surface is used not only for stuffing in the contents of a window. It is a quite universal thing, for example, it can be used as a pointer surface or it can be used as an additional drag-and-drop icon. In addition to that, surfaces can form hierarchies. At the moment, our scene abstractions are not well suited for that.
Besides that, there other issues, for example, damage tracking in surface hierarchies is inefficient; if a sub-surface sticks outside the main surface, there are going to be visual artifacts even though the spec explicitly says that it's a valid use-case.
In order to mimic surface hierarchies, the
WindowPixmap class, which represents the currently referenced buffer, was tweaked so it also forms a hierarchy. The problem with it is that if some sub-surface is resized, the entire window pixmap tree is going to be discarded.
Over the course of the last half a year or so, I was quitely moving rendering related stuff out of the
Toplevel class to the
Scene::Window class, for example, the
Toplevel class no longer keeps around repaint regions, etc. The goal is to move all things that have nothing to do with window management (depth info, manual repaints) to the scene and let it figure out how windows must be painted and what parts of the screen are dirty. In order to achieve that, we need to rework scene abstractions; in particular, we need scene "items".
WindowItemis an item that represents a window and it is made of
ShadowItemrepresents the server-side nine-tile patch drop shadow, if there is one
DecorationItemrepresents the server-side decoration, if there is one
SurfaceItemrepresents a wayland/internal/x11 surface
With this design, the
Toplevel class is concerned about generic window properties, such as the geometry, the window state, etc. While the scene items are concerned about the actual contents of the window and the structure of the contents. The
WindowItem keeps track of the
Toplevel and when necessary schedules repaints.
SurfaceItem is re-usable. In other words, it can be used on its own to represent a software cursor or a drag-and-drop additional icon on Wayland.
Item doesn't do any actual rendering. Instead, it generates scene graph nodes when the renderer asks it to do so. Similar how it's done in QtQuick.
Cursor and Overlay hardware planes
In order to properly render surface items on
Overlay hardware planes, every composited layer is going to have its own scene graph. If an item can be directly scanned out, it will be scanned out. Otherwise the renderer will fall back to OpenGL or QPainter compositing. This is needed to properly handle weird cases where the cursor surface has sub-surfaces or if it has a
First, we need to introduce stripped down versions of
DecorationItem. This is done by !656 (merged). Even though the MR doesn't achieve all what we want in this re-design, it already fixes some existing visual glitches. \o/
Things that have nothing to do with window management have to be moved out of the
Toplevel class to the scene, e.g.
Toplevel::hasAlpha(), etc. In case it's not possible because of X11, move them to
The second biggest milestone is going to be the introduction of a scene graph and porting
DecorationItem to it.
The third biggest milestone is going to be getting rid of
Scene::Window and putting all
WindowItems in a single scene. Some effects might need to be ported as well, and some of them might have to be dropped due to their enormous size, questionable usefulness (e.g. flip switch, desktop cube, etc) and limited man power of the kwin development team. The maintenance issues with those effects will be brought up to attention in the plasma-devel mailing list.
Milestone Last + 1?
It's quite possible that the plan is incomplete and the gaps will be discovered while doing the actual changes.
Compositing on different threads
If we do the redesign the right way, state updates and painting will be separated. Which means that it should be possible to perform compositing on different threads. The render threads might still need to synchronize with the main thread, but the synchronization step should be lightweight, therefore it's not a big concern. So, the idea is
- The render thread synchronizes with the main thread
- The render thread asks every item to update the scene graph nodes
- The render thread finishes synchronization and goes on with recording render commands, etc
Every render thread will most likely have to have its own scene graph otherwise the complexity will explode due to synchronization.
Due to the sheer amount of work that needs to be put in this, it may take several release cycles to complete the task.