Commit graph

39 commits

Author SHA1 Message Date
Vlad Zahorodnii
aac0609bb9 scene: Rework surface damage tracking
It's not possible to get the surface damage before calling
Scene::paint(), which is a big problem because it blocks proper surface
damage and buffer damage calculation when walking render layer tree.

This change reworks the scene compositing stages to allow getting the
next surface damage before calling Scene::paint().

The main challenge is that the effects can expand the surface damage. We
have to call prePaintWindow() and prePaintScreen() before actually
starting painting. However, prePaintWindow() is called after starting
rendering.

This change makes Scene call prePaintWindow() and prePaintScreen() so
it's possible to know the surface damage beforehand. Unfortunately, it's
also a breaking change. Some fullscreen effects will have to adapt to
the new Scene paint order. Paint hooks will be invoked in the following
order:

* prePaintScreen() once per frame
* prePaintWindow() once per frame
* paintScreen() can be called multiple times
* paintWindow() can be called as many times as paintScreen()
* postPaintWindow() once per frame
* postPaintScreen() once per frame

After walking the render layer tree, the Compositor will poke the render
backend for the back buffer repair region and combine it with the
surface damage to get the buffer damage, which can be passed to the
render backend (in order to optimize performance with tiled gpus) and
Scene::paint(), which will determine what parts of the scene have to
repainted based on the buffer damage.
2022-03-21 09:32:41 +02:00
Vlad Zahorodnii
dd6d0b22cc Port software cursor to RenderLayer
Software cursor has always been a major source of problems. Hopefully,
porting it to RenderLayer will help us with that.

Note that the cursor layer is currently visible only when using software
cursor, however it will be changed once the Compositor can allocate
a real hardware cursor plane.

Currently, software cursor uses graphics-specific APIs (OpenGL and
QPainter) to paint itself. That will be changed in the future when
rendering parts are extracted from the Scene in a reusable helper.
2022-02-21 09:33:59 +00:00
Vlad Zahorodnii
5933a21641 Introduce render layers
This is the first tiny step towards the layer-based compositing in kwin.
The RenderLayer represents a layer with some contents. The actual
contents is represented by the RenderLayerDelegate class.

Currently, the RenderLayer is just a simple class responsible for
geometry, and repaints, but it will grow in the future. For example,
render layers need to form a tree.

The next (missing) biggest component in the layer-based compositing are
output layers. When output layers are added, each render layer would
have an output layer assigned to it or have its output layer inherited
from the parent.

The render layer tree wouldn't be affected by changes to the output
layer tree so transition between software and hardware cursors can be
seamless.

The next big milestone will be to try to port some of existing kwin
functionality to the RenderLayer, e.g. software cursor or screen edges.
2022-02-21 09:33:59 +00:00
Vlad Zahorodnii
203d7b3b8a Move direct scanout management to Compositor
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.
2022-02-21 09:33:59 +00:00
Kai Uwe Broulik
2d56154fe8 kwineffects: Support setting opacity on OffscreenQuickView
Signed-off-by: Eike Hein <eike.hein@mbition.io>
2022-02-16 17:29:06 +00:00
Vlad Zahorodnii
d06746fa5c scene: Set render target rect in Scene::paintScreen()
This ensures that the render target rect is set when using qpainter
render backend.
2022-02-16 16:04:29 +00:00
Vlad Zahorodnii
0c3a8e6f29 scene: Make paintScreen() clip the damage region
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().
2022-02-16 07:49:47 +00:00
Vlad Zahorodnii
a3b5266175 Drop Platform::renderLoop()
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!
2022-02-15 18:23:52 +02:00
Vlad Zahorodnii
ba000d5a4e scene: Compute projection matrix based on the render target rect
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().
2022-02-15 14:31:28 +00:00
Vlad Zahorodnii
f4f83848b0 kwinglutils: Make GLRenderTarget not store GLTexture reference
This allows us to make the GLRenderTarget a bit nicer when using it to
wrap the default fbo as we don't know what the color attachment texture
is besides its size.

This means that the responsibility of ensuring that the color attachment
outlives the fbo is now up to the caller. However, most of kwin code
has been written that way, so it's not an issue.
2022-02-15 13:30:39 +02:00
Vlad Zahorodnii
e9af67af3e kwineffects: Add GLTexture::render() overload that takes no scissor region
In many cases, we don't care about the scissor region. This change adds
a relevant overload to make code easier to read.
2022-02-15 12:17:59 +02:00
Vlad Zahorodnii
52beb213e7 kwineffects: Make GLRenderTarget and GLVertexBuffer work without global coords and scale
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.
2022-02-15 12:17:56 +02:00
Vlad Zahorodnii
bb935aa5de Fix decoration rendering with scale factor < 1
QPainter won't let paint with a device pixel ratio less than 1. There
are used to be workarounds to force a device pixel ratio of 1, but they
were removed with fractional scaling corner fix.

This change makes sure that the decoration renderer forces a device
pixel ratio of 1 if the output's scale factor is less than 1 so
calculated texture coordinates match where window borders are rendered
in the texture atlas.

BUG: 449681
2022-02-07 11:45:31 +00:00
Vlad Zahorodnii
e2a393ce2d Move utils.h file to utils directory 2022-01-25 16:56:33 +00:00
Vlad Zahorodnii
293b2244ac Move xcbutils to utils directory 2022-01-25 16:56:33 +00:00
Vlad Zahorodnii
e20f09666b scenes/qpainter: Fix software cursor check in paintCursor()
Hopefully this will fix SceneQPainterTest.
2022-01-14 08:33:37 +00:00
Vlad Zahorodnii
6494db75e9 scenes/opengl: Port lanczos filter to ShaderManager::generateShaderFromFile() 2022-01-13 12:04:37 +00:00
Vlad Zahorodnii
9e97c06758 Move graphics reset handling to RenderBackend
This makes the Scene less overloaded and it's needed for things such as
render layers.

In hindsight, it would be great to merge checkGraphicsReset() and
beginFrame(), e.g. make beginFrame() return the status like in QRhi or
VkSwapchain. If it's OUT_OF_DATE or something, reinitialize the
compositor.
2022-01-02 22:29:36 +02:00
Julius Zint
3b4d558371 Improve window decorations in OpenGL scene
When creating the texture containing the window decorations, the drawing
code now directly handles the rotation for the left and right
decoration, instead of rotating the image after it has been drawn.

The padding, to prevent texture bleeding, is now a fixed value instead
of being scaled. With this change, there are no longer visual artifacts
for window decorations with rounded corners, when the scaling value is
fractional.
2021-12-30 09:07:42 +00:00
Vlad Zahorodnii
84690a0de6 scenes/opengl: Move copying front buffer to back buffer to X11 specific code
On X11, if buffer age is unsupported, kwin can do some quirks like
copying parts of the front buffer to back buffer to avoid repainting the
whole screen.

Currently, the copying is performed in the opengl scene, which is not
perfect because it makes the scene responsible not only for painting the
scene but also some low level platform specific shenanigans.

This change moves the copying step to the glx and egl backends. It
simplifies the opengl scene, makes it less overloaded and more open to
changes, but it also duplicates code, which is not ideal. However, given
the de-facto deprecated state of the X11 platform, it's sort of acceptable
as the main focus is now on wayland session and the things that are
needed to make it fly as expected.
2021-12-29 15:11:40 +00:00
Xaver Hugl
6a99bfd2f4 make software cursors work per output 2021-12-28 18:42:29 +00:00
Vlad Zahorodnii
cbad78a360 Kill Toplevel::screenScale()
Tracking AbstractOutput properties in Toplevel is not extensible. Since
DecorationItem is the only one who needs Toplevel::screenScale(), make
it track the output device pixel ratio.
2021-11-29 13:14:01 +00:00
Vlad Zahorodnii
3ad7bf01c8 Allow specifying scene geometry
The main motivation behind this change is to decouple the scene a bit
further from Screens, which is also obsolete.
2021-11-26 07:48:47 +00:00
Vlad Zahorodnii
ec5950aedb Rename EffectQuickScene to OffscreenQuickScene
EffectQuickScene is not used strictly by effects, aurorae decorations
use it too to render window decorations.

This change renames the EffectQuickView/Scene to
OffscreenQuickView/Scene to clear up the naming scheme.
2021-11-23 09:53:18 +00:00
Aleix Pol
19df0996f5 scene: Do not clamp 1x1 windows
Without the margins, they become 0x0 and we crash.
2021-11-17 16:01:16 +00:00
Vlad Zahorodnii
7228e9aefd Unify beginFrame() and endFrame() hooks for OpenGL and QPainter backends
This unifies frame hooks for OpenGL and QPainter render backends. There
are a couple of reasons why it's a good idea - it provides one mental
framework to start painting a frame, the Compositor will be able to
start and submit frames. The last one is very cool because it gives the
Compositor more power over compositing.

Besides unifying frame hooks, this cleans up a bit the arg naming mess
in endFrame(). As is, "damage" and "damagedRegion" are very confusing
names. "damage" arg has been renamed to "renderedRegion," because that's
what it is. The renderedRegion arg specifies the region that has been
repainted by the Scene. It's different from the damagedRegion as that
one specifies the surface damage, i.e. the difference between the
current and the next frame, while the renderedRegion may include a
region that had to be repainted to repair the back buffer. The main
reason why we need renderedRegion is the X11 platform. On Wayland, it's
unused.

In the future, we will need to extend this api with output layers.
2021-11-16 10:43:56 +00:00
Vlad Zahorodnii
aaf88cd906 scenes/opengl: Keep lanczos filter after changing outputs
The lanczos filter checks the screen size before rendering in
LanczosFilter::updateOffscreenSurfaces(), so this is not needed.

This simplifies lifetime handling of the lanczos filter, e.g. we
don't need to bother with opengl context anymore, and makes the
scene use less Screens' features.
2021-11-16 10:42:58 +00:00
Vlad Zahorodnii
7013c1473c kwinglutils: Clean up persistent vbo fences at the start of the frame
With a persistent vbo, kwin will allocate one big enough buffer and
allocate memory out of it.

In order to prevent overwriting vertex buffer data that is currently
being accessed by the GPU, fences are inserted at the end of frame.

The signaled fences are destroyed after the buffer swap operation, which
seems a bit odd because the just inserted fence most likely won't be
signaled. Perhaps it's a historical artifact?

This change rearranges fence cleanup so it's performed right before
starting a new frame. With it, kwin will most likely re-use the
previously used memory chunk because there will be plenty of time for
the fence to become signaled.

Another motivation behind this change is to make refactoring SceneOpenGL
code easier. As is, m_backend->endFrame() is wrapped in
GLVertexBuffer::endOfFrame() and GLVertexBuffer::framePosted(). With
that, the Compositor can't call m_backend->endFrame(), which can be
desired for cleaning up render backend abstractions.
2021-11-16 07:25:20 +00:00
Vlad Zahorodnii
8518a7ea8c Drop Scene::Window::windowTexture() 2021-11-16 07:24:03 +00:00
Vlad Zahorodnii
affb640bcb Move OverlayWindow getter to RenderBackend 2021-11-11 11:49:13 +02:00
Vlad Zahorodnii
48f943bd75 Introduce explicit base render backend type
The main idea behind the render backend is to decouple low level bits
from scenes. The end goal is to make the render backend provide render
targets where the scene can render.

Design-wise, such a split is more flexible than the current state, for
example we could start experimenting with using qtquick (assuming that
the legacy scene is properly encapsulated) or creating multiple scenes,
for example for each output layer, etc.

So far, the RenderBackend class only contains one getter, more stuff will
be moved from the Scene as it makes sense.
2021-11-11 08:55:29 +00:00
Vlad Zahorodnii
7580d6c6e0 scenes/opengl: Remove NPOT extension check
NPOT textures are in core spec in OpenGL 2.0+.
2021-11-10 06:05:10 +00:00
Vlad Zahorodnii
c478722655 scenes/opengl: Remove redundant debug message
The Compositor will print whether opengl compositing has been
initialized successfully.
2021-11-09 09:22:12 +02:00
Vlad Zahorodnii
3ade20eea5 Make Compositor responsible for syncing the GlStrictBinding flag
The GlStrictBinding flag indicates whether it's okay not to re-bind the X11
pixmap to the OpenGL surface texture if the corresponding window is damaged.
It doesn't really affect the SceneOpenGL, only low level backend stuff.
2021-11-09 07:16:56 +00:00
Vlad Zahorodnii
dabcb558b4 Move opengl debug output initialization to kwinglutils
kwinglutils is a better place as the debug output is initialized for the
render backend's context, not scene's context.
2021-11-09 07:16:56 +00:00
Vlad Zahorodnii
cff74b568b Decouple render backend from scene
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.
2021-11-08 18:27:22 +00:00
Vlad Zahorodnii
3485eb6200 cmake: Move base render backend classes to libkwin
This allows using base opengl backends in libkwin, which can be useful
later on for the purpose of moving the ownership of render backends from
the Scene class to the Compositor class.
2021-11-08 18:27:22 +00:00
Vlad Zahorodnii
0eb56fff6e kwineffects: Remove ShaderManager::selfTest()
It has been disabled with Mesa for almost half a decade due to false
positives and even if it weren't disabled, it contributes to the startup
time.

The commit message that added the self test doesn't explain why it was
added, but if it was added to detect unstable drivers, it's not worth it.
2021-11-08 10:29:51 +00:00
Vlad Zahorodnii
aead97c39f Move scenes to the src directory
Similar to the backends, it's far more intuitive to have scenes in the
toplevel source directory rather than the plugins directory.
2021-11-08 10:22:07 +00:00