Windows have two kinds of repaints - window repaints and layer repaints.
The main difference between the two is that the former is specified in
the window-local coordinates while the latter is specified in the global
screen coordinates.
Window repaints are useful in case the position of the window doesn't
matter, for example for repainting damaged regions, etc.
But its biggest issue is that with per screen rendering, it's not
possible to determine what screens exactly have to be repainted. The
final area affected by the window repaint will be known only at
compositing time. If a window gets damaged, we have to schedule a
repaint on ALL outputs. Understandably, this costs a little bit in terms
of performance.
This change replaces the window repaints with the layer repaints. By
doing so, we can avoid scheduling repaints on outputs that don't
intersect with the dirty region and improve performance.
If there is a pending frame, the RenderLoop will delay all schedule
repaint requests to the next vblank event. This means that the render
loop needs to be notified when a frame has been presented or failed.
At the moment, the RenderLoop is notified only about successfully
presented frames. If some frame fails, no repaints will be scheduled
on that output.
In order to make frame scheduling robust, the RenderLoop has to be
notified if a frame has failed.
Currently, we estimate the expected render time purely based on the
latency policy.
The problem with doing so is that the real render time might be larger,
this can result in frame drops.
In order to avoid frame drops, we need to take into account previous
render times while estimating the next render time. For now, we just
measure how long it takes to record rendering commands on the CPU.
In the future, we might want consider using OpenGL timer queries for
measuring the real render time, but for now, it's good enough.
At the moment, our frame scheduling infrastructure is still heavily
based on Xinerama-style rendering. Specifically, we assume that painting
is driven by a single timer, etc.
This change introduces a new type - RenderLoop. Its main purpose is to
drive compositing on a specific output, or in case of X11, on the
overlay window.
With RenderLoop, compositing is synchronized to vblank events. It
exposes the last and the next estimated presentation timestamp. The
expected presentation timestamp can be used by effects to ensure that
animations are synchronized with the upcoming vblank event.
On Wayland, every outputs has its own render loop. On X11, per screen
rendering is not possible, therefore the platform exposes the render
loop for the overlay window. Ideally, the Scene has to expose the
RenderLoop, but as the first step towards better compositing scheduling
it's good as is for the time being.
The RenderLoop tries to minimize the latency by delaying compositing as
close as possible to the next vblank event. One tricky thing about it is
that if compositing is too close to the next vblank event, animations
may become a little bit choppy. However, increasing the latency reduces
the choppiness.
Given that, there is no any "silver bullet" solution for the choppiness
issue, a new option has been added in the Compositing KCM to specify the
amount of latency. By default, it's "Medium," but if a user is not
satisfied with the upstream default, they can tweak it.
In order to unlock per screen rendering, we need to track repaints for
every screen individually. While we could do this in the Compositor class,
tracking repaints in the Scene seems a better alternative in long run
because we will have to instantiate a Scene for each composited screen
one day.
In rare cases, the Compositor has to perform a compositing if there is
nothing to repaint. For example, if a client has committed a frame
callback to get notified about the next vblank event without damaging
the surface.
We want to get notified when the next page flip occurs. The problem is
that kwin will avoid queueing a page flip if nothing has been changed on
the screen. From performance point of view, that is expected behavior,
but for frame scheduling and some wayland clients that create frame
callbacks to get notified about the next vblank, it's not suitable.
EGL for X and EGL for Wayland backends are quite different. The main
motivation behind this change is to prepare the EGL backends for
monitoring vblank events. Things work quite differently depending on
if the EGL backend renders onto a toplevel window or overlay window.
With the new compositing timing, we want to start compositing some time
later after a vsync event. This doesn't go along with the video sync
based method to synchronize buffer swaps with vblank.
Since practically all drivers nowadays provide support for the swap
control extensions (GLX_EXT_swap_control, GLX_SGI_swap_control, or
GLX_MESA_swap_control), it's safe to rely on them for the purpose of
synchronizing buffer swaps to vblank.
The compositing timing algorithm assumes that glXSwapBuffers() and
eglSwapBuffers() block. While this was true long time ago with NVIDIA
drivers, nowadays, it's not the case. The NVIDIA driver queues
several buffers in advance and if the application runs out of them,
it will block. With Mesa driver, swapping buffer was never blocking.
This change makes the render backends swap buffers right after ending
a compositing cycle. This may potentially block, but it shouldn't be
an issue with modern drivers. In case it gets proven, we can move
glXSwapBuffers() and eglSwapBuffers() in a separate thread.
Note that this change breaks the compositing timing algorithm, but
it's already sort of broken with Mesa drivers.
Plasma Mobile announced that they plan to drop support for Halium
devices, see the announcement blog post [1] for the reasons that led to
such a decision.
But just to summarize, here are some of the key points from the post:
* Some of our team members no longer have access to reference LG Nexus
5X device anymore
* After KDE Neon switched to using Ubuntu 20.04 we no longer are
updating the rootfs for halium devices
* After several important architecture changes in upstream KWin, the
hwcomposer backend might be broken and we have no way of verifying it
If the community members are interested in reviving the hwcomposer
backend,
* it pretty much needs rewrite/re-thinking given differences of hwc1
and hwc2 API for hwcomposer part of it, see also [2]
* It also needs removal of Android 5 based libhardware API as we don't
think code can be kept sane with 3 different levels of ifdefs
* This backend needs better way of fixing difference between
CAF/non-CAF devices then just recompiling with different headers,
maybe env vars?
* This backend does not support various things like transformation/
rotation etc, and is not exactly feature complete as the DRM backend
[1] https://www.plasma-mobile.org/2020/12/14/plasma-mobile-technical-debt.html
[2] 83f563c339
Add the activities info to the list of properties provided by
the `queryWindowInfo()` dBus method, and suggest them to the
user when inspecting a given window.
An empty activity list means "All Activities" (null UUID)
Also get the null UUID value instead of having it hardcoded.
This convenience invokable method was removed in 66ee89855
by mistake, since it's still used in RulesEditor.qml
While at it, optimize arguments to const &
At the moment, the Screens class is convoluted with ifdefs because of
MockScreens.
The goal of this change is to reduce the number of usages of the
MockScreens class so it is possible to get rid of the ifdefs.
Change the default value from "Do Not Affect" to "Apply Initially" when
adding new properties in Window Rules.
REASON: prior "Do Not Affect" as default and occasionally I forget to
change the setting to something else when adding new properties.
Unfortunately, this means I forget to do it and so it isn't saved when
I close the window. I will then go back in to change it to Apply Initially
or in some cases have to add the new property again as it wasn't saved in
the set.
I think if Apply Initially were to be the default it would be an easier
and faster experience to add new properties.
Change the setting's type from `QString` to `QStringList`
and adjust relevant code.
Previous config requires no porting as a single string in the
config file is read as the first item in the list.
Since the Screens class is a convenience wrapper around AbstractOutput
objects that come from the Platform, it should not be platform-specific.
By dropping createScreens(), output-related code becomes simpler.
The default implementation of Screens::displaySize() returns the
bounding rectangle of all available outputs.
In case the Xrandr extension is unavailable, there will be a fake
output whose dimensions are the same as the dimensions of all screens
combined.
This is a typo that I forgot to fix, therefore not requesting code
review. After QVector::erase() has been called, we cannot use the
iterator as it will lead to undefined behavior.