The responsibilities of the Scene must be reduced to painting only so we
can move forward with the layer-based compositing.
This change moves direct scanout logic from the opengl scene to the base
scene class and the compositor. It makes the opengl scene less
overloaded and allows to share direct scanout logic.
paintScreen() already tries to ensure that the damage region doesn't go
outside the scene geometry. With this change, it will try to clip the
damage region to the render target rect, which saves us an extra region
intersection and simplifies code that calls paintScreen().
Having a render loop in the Platform has always been awkward. Another
way to interpret the platform not supporting per screen rendering would
be that all outputs share the same render loop.
On X11, Scene::painted_screen is going to correspond to the primary
screen, we should not rely on this assumption though!
Neither SceneQPainter nor SceneOpenGL have to compute the projection
matrix by themselves. It can be done by the Scene when setting the
projection matrix. The main benefit behind this change is that it
reduces the amount of custom setup code around paintScreen(), which
makes us one step closer to getting rid of graphics-specific paint()
function and just calling paintScreen().
Because the GLRenderTarget and the GLVertexBuffer use the global
coordinate system, they are not ergonomic in render layers.
Assigning the device pixel ratio to GLRenderTarget and GLVertexBuffer is
an interesting api design choice too. Scaling is a window system
abstraction, which is absent in OpenGL or Vulkan. For example, it's not
possible to create an OpenGL texture with a scale factor of 2. It only
works with device pixels.
This change makes the GLRenderTarget and the GLVertexBuffer more
ergonomic for usages other than rendering the workspace by removing all
the global coordinate system and scaling stuff. That's the
responsibility of the users of those two classes.
On Wayland, a window can have subsurfaces. The spec doesn't require the
main surface and its sub-surfaces to have the same scale factor.
Given that Toplevel::bufferScale() makes no sense with Wayland windows,
this change drops it to make code more reasonable and to prevent people
from using Toplevel::bufferScale().
The Compositor contains nothing that can potentially get dirty and need
repainting.
As is, the advantages of this move aren't really noticeable, but it
makes sense with multiple scenes.
Backend parts are far from ideal, they can be improved later on as we
progress with the scene redesign.
Currently, the scene owns the renderer, which puts more
responsibilities on the scene other than painting windows and it also
puts some limitations on what we can do, for example, there can be only
one scene, etc.
This change decouples the scene and the renderer so the scene is more
swappable.
Scenes are no longer implemented as plugins because opengl backend
and scene creation needs to be wrapped in opengl safety points. We
could still create the render backend and then go through the list
of scene plugins, but accessing concrete scene implementation is
much much simpler. Besides that, having scenes implemented as plugins
is not worthwhile because there are only two scenes and each contributes
very small amount of binary size. On the other hand, we still need to
take into account how many times kwin accesses the hard drive to load
plugins in order to function as expected.
This decouples the management of Shadow from the scene window and allows
multiple items share the same Shadow.
Currently, kwin has a single scene graph, but it makes sense to create a
scene graph per output as they could have different layers, etc. This
would also allow QtQuick share more textures with kwin, which is worth
doing for optimization purposes in the future.
We use surfaceless contexts with internal windows. We also require
the EGL_KHR_surfaceless_context extension for making context current
without outputs.
Arguably, we could use pbuffers, but since mainstream drivers (Mesa and
NVIDIA) support surfaceless contexts, the extra complexity doesn't buy
us anything.
This further decouples scene items from scene windows. The SurfaceItem
still needs to access the underlying window, I would like to re-iterate
over that later.
With this change, it will be possible to introduce WindowItem factory
function in the Toplevel class.
Makes it possible to apply the dpms settings per screen instead of
applying it to all of them, which is wrong at many levels.
Will be even more important with other effects like rotation.
Currently, thumbnail items are rendered by kwin. This means that qtquick
code cannot do things such as applying shader effects to window thumbnails
or simply draw custom controls on top of thumbnails.
With this change, task switchers and qml extensions will be able to
place their own contents on top of thumbnails and apply custom effects
to them.
In order to integrate window thumbnails, a window is rendered on kwin
side using its own opengl context. A fence is inserted in the command
stream to ensure that the qtquick machinery doesn't start using the
offscreen texture while there are still rendering commands being executed.
Thumbnails are rendered into offscreen textures as we don't have full
control over when qtquick windows render their contents and to work around
the fact that things such as VAOs can't be shared across OpenGL contexts.
WindowThumbnailItem and DesktopThumbnailItem act as texture providers.
At the moment, we handle window quads inefficiently. Window quads from
all items are merged into a single list just to be broken up again.
This change removes window quads from libkwineffects. This allows us to
handle window quads efficiently. Furthermore, we could optimize methods
such as WindowVertex::left() and so on. KWin spends reasonable amount
of time in those methods when many windows have to be composited.
It's a necessary prerequisite for making wl_surface painting code role
agnostic.
The scene items depend on the scene windows for caching window quads.
The goal of this change is to move window quads management to item.
Merging window quads in one list and then splitting them is inefficient,
it will be highly desirable if window quads are removed from the public
api so we can optimize window quad management.
With this change, the window quad type becomes irrelevant to render
backends for the most part. Note that the Xrender backend is a bit
nitpicky about window quads, so the shadow item doesn't create generic
"WindowQuadShadow" quads anymore.
The Xrender backend was added at the time when OpenGL drivers were not
particularly stable. Nowadays though, it's a totally different situation.
The OpenGL render backend has been the default one for many years. It's
quite stable, and it allows implementing many advanced features that
other render backends don't.
Many features are not tested with it during the development cycle; the
only time when it is noticed is when changes in other parts of kwin break
the build in the xrender backend. Effectively, the xrender backend is
unmaintained nowadays.
Given that the xrender backend is effectively unmaintained and our focus
being shifted towards wayland, this change drops the xrender backend in
favor of the opengl backend.
Besides being de-facto unmaintained, another issue is that QtQuick does
not support and most likely will never support the Xrender API. This
poses a problem as we want thumbnail items to be natively integrated in
the qtquick scene graph.
Currently, the frameRendered() signal is emitted every time an effect
calls paintScreen(). This means that the frameRendered() signal can be
emitted more than once when effects such as slide are active. However,
we'd like if it's emitted only once before buffers are swapped.
Currently, the implementation of the DecoratedClient and the decoration
renderer are strongly coupled. This poses a problem with the item based
design as the ultimate goal is to have scene items construct paint nodes
which are then fed to the renderer. The DecorationItem has to have
control over the decoration texture. Another issue is that the scene
cannot smoothly cross-fade between two window states if the decoration
is removed, e.g. from fullscreen mode to normal and vice versa.
This change moves the decoration renderer to the decoration item. With
the introduction of a generic scene texture atlas, we hope to get rid of
the decoration renderer altogether.
They are used only by X11Client, so make X11Client call relevants
methods on the surface item directly instead. In hindsight, it will be a
really good idea to make SurfaceItemX11 and SurfaceItemXwayland(?)
automatically manage the window pixmap. However, it can be done once
an item freezing api is added and we fix the cross-fade animation.
Currently, items depend on scene windows for creating pixmaps, repaint
scheduling, and caching quads.
This change moves repaint scheduling from scene windows to items to
make the scene items depend less on scene windows.
In hindsight, we may clean up the repaint scheduling machinery further
by introducing view objects.
One of the scene redesign goals is to make wayland surface items
re-usable. So we have the same rendering path for drag-and-drop icons,
software cursors, and window surfaces.
The biggest issue at the moment is that window pixmaps are tightly
coupled with scene windows.
This change de-couples window pixmaps from scene windows. In order to
achieve that, some architecture changes were made.
The WindowPixmap class was replaced with the SurfacePixmap class. A
surface pixmap is created by a surface item.
Under the hood, a SurfacePixmap will create a PlatformSurfaceTexture
object, which contains all the information necessary for the renderer.
The SceneOpenGLTexture class was removed. However, the GLX and the EGL
on X11 backends still mess with GLTexture's internals.
Currently, dealing with sub-surfaces is very difficult due to the scene
design being heavily influenced by X11 requirements.
The goal of this change is to re-work scene abstractions to make improving
the wayland support easier.
The Item class is based on the QQuickItem class. My hope is that one day
we will be able to transition to QtQuick for painting scene, but in
meanwhile it makes more sense to have a minimalistic internal item class.
The WindowItem class represents a window. The SurfaceItem class represents
the contents of either an X11, or a Wayland, or an internal surface. The
DecorationItem and the ShadowItem class represent the server-side deco and
drop-shadow, respectively.
At the moment, the SurfaceItem is bound to the scene window, but the long
term plan is to break that connection so we could re-use the SurfaceItem
for things such as software cursors and drag-and-drop additional icons.
One of the responsibilities of the Item is to schedule repaints as needed.
Ideally, there shouldn't be any addRepaint() calls in the core code. The
Item class schedules repaints on geometry updates. In the future, it also
has to request an update if its opacity or visibility changes.