Scene redesign
On Wayland, 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.
Proposed Design
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".
-
WindowItem
is an item that represents a window and it is made ofShadowItem
,DecorationItem
and rootSurfaceItem
-
ShadowItem
represents the server-side nine-tile patch drop shadow, if there is one -
DecorationItem
represents the server-side decoration, if there is one -
SurfaceItem
represents 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.
The 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.
An 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 Cursor
and 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 wp_viewport
.
Milestone I
First, we need to introduce stripped down versions of WindowItem
, SurfaceItem
, ShadowItem
, and 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::depth()
, Toplevel::hasAlpha()
, etc. In case it's not possible because of X11, move them to X11Client
or Unmanaged
.
Milestone II
The second biggest milestone is going to be the introduction of a scene graph and porting SurfaceItem
, ShadowItem
, and DecorationItem
to it.
Milestone III
The third biggest milestone is going to be getting rid of Scene::Window
and putting all WindowItem
s 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.
Timeframe
Due to the sheer amount of work that needs to be put in this, it may take several release cycles to complete the task.