Summary:
Our Wayland compositors cannot composite an X11 pixmap. Thus even
if we succeed in creating the pixmap, the changes would not get to
the scene. The code allowed for situation where a surface is not yet
set to fall back to the X11 code path. This can happen for XWayland
windows.
Test Plan: Crash in xclipboardsynctest without the change
Reviewers: #plasma_on_wayland, #kwin
Subscribers: plasma-devel, kwin
Tags: #plasma_on_wayland, #kwin
Differential Revision: https://phabricator.kde.org/D2010
Summary:
To check which code path we should take just check whether
* we have a surface -> Wayland
* we have a pixmap -> X11
Reviewers: #plasma
Subscribers: plasma-devel
Projects: #plasma
Differential Revision: https://phabricator.kde.org/D1487
This change introduces a tree for WindowPixmap. A WindowPixmap can
have a parent WindowPixmap and children. Each child represents a
SubSurface and references the buffer of that SubSurface.
The tree of WindowPixmaps is updated each time updateBuffer is called.
If there are new SubSurfaces new WindowPixmaps are created, for removed
SubSurfaces the old WindowPixmap gets removed. Also the ordering is
updated to reflect the current state.
This is currently rather expensive and should be changed to only rebuild
the tree if it actually changed.
The screen projection matrix is needed if an effect wants to customize
the modelview projection matrix while rendering a window and keeping
the currently applied screen projection and transformation.
With this change a new ctor overload is added to ScreenPaintData
which allows passing a projection matrix through the effects. This
allows effects to put up custom shaders with a shared projection matrix
and without having to calculate it themselves.
The projection matrix is a read-only information for the effects. There
is no way to change or overwrite it.
This describes an additional offset for the client content. On X11
our client content position matches with the window - the window
decoration is part of the overall content coordinate system.
On Wayland the content is an own texture starting at 0/0. Thus a
mapping to texture coordinates will be required when server side
decorations are provided. The new information is used in the scene's
to adjust the rendering and generating of quads.
The last stage for window rendering is triggered by
Scene::finalDrawWindow. Adding a security check there if screen is locked
no non-lock screen window should be rendered.
Unfortunately this method is virtual so the check needs to be done in the
base and all implementing child methods (currently only OpenGL).
REVIEW: 126144
This change introduces a mechanism for internal windows to be rendered
to a QOpenGLFramebufferObject to be composited using the texture bound
to the FBO. This is useful for in-process rendering (e.g. QtQuick) and
at the same time bypassing the windowing system.
The OpenGL context of the QOpenGLFramebufferObject needs to be sharing
with the compositing OpenGL context.
When we don't use the buffer anymore, we should discard it. Otherwise
we start to leak buffers and that can result in clients dead locking
while waiting for more free buffers.
The concept of Buffers do not match WindowPixmap perfectly. With X11
we had a pixmap as long as the size was the sime, then it got discarded.
With Wayland we get a new Buffer whenever the window gets damaged.
Furthermore the Buffer might get destroyed any time (especially if the
client disconnects) or the data becomes invalid (it's a shm section after
all).
This adds some constraints on how the Buffer can be used. It's suggested
that the implementing sub-classes do a deep copy of the Buffer's data
when accessing it. For OpenGL that's rather obvious, for QPainter it
needs a dedicated QImage::copy.
WindowPixmap holds a pointer to the currently used Buffer, but doesn't
guarantee that it stays valid. Every time the window gets damaged, the
pointer needs to be updated.
The QPainter based scene is the first to implement support for Buffers:
on creation a deep copy is performed, on damage the changed parts are
painted into the deep copy.
Instead of getting size from displayWidth() and displayHeight() use
the information we have from Screens. This means there is only one
place to have the information and by that we can ensure that all
components use the same data to rely on. displayWidth/displayHeight
seem to provide the wrong information when unplugging an output
without disabling the output. This results in rendering artefacts.
But KWin::Screens has the correct information available.
Create and import X sync fences into GL and use them to synchronize
the kwin command stream with the X command stream.
This prevents damaged windows from being composited by kwin before
the rendering that triggered the damage events have finished on
the GPU.
Requires GL_EXT_x11_sync_object.
Tested-by: Marco Martin <notmart@gmail.com>
NOTE: this is not working completely yet, lots of code is still ifdefed
other parts are still broken.
The main difference for the new decoration API is that it is neither
QWidget nor QWindow based. It's just a QObject which processes input
events and has a paint method to render the decoration. This means all
the workarounds for the QWidget interception are removed. Also the paint
redirector is removed. Instead each compositor has now its own renderer
which can be optimized for the specific case. E.g. the OpenGL compositor
renders to a scratch image which gets copied into the combined texture,
the XRender compositor copies into the XPixmaps.
Input events are also changed. The events are composed into QMouseEvents
and passed through the decoration, which might accept them. If they are
not accpted we assume that it's a press on the decoration area allowing
us to resize/move the window. Input events are not completely working
yet, e.g. wheel events are not yet processed and double click on deco
is not yet working.
Overall KDecoration2 is way more stateful and KWin core needs more
adjustments for it. E.g. borders are allowed to be disabled at any time.
The left and right border images are rotated 90° before they are
uploaded into the atlas texture. The images are separated by a row
of transparent texels to minimize artifacts from oversampling.
With this change kwin renders the whole decoration with a single
call to glDrawArrays().
By setting the X property _KDE_NET_WM_SKIP_CLOSE_ANIMATION to 1 a window
can request to be excluded from any close animation. This property is
read in Toplevel, so that it is available to both Client and Unmanaged.
If the window has this property set the Scene suppresses the paintWindow
loop of the Deleted. Thus no effect needs to be adjusted. But an effect
using drawWindow directly would still be able to render the Deleted as
there is no suppression.
Furthermore the property is passed to the EffectWindow so that an
Effect can make use of this functionality and not start the animation
in the first place.
REVIEW: 115288
Only the X based Scenes need an overlay window, so the Compositor doesn't
need to check for it in the Wayland case.
OverlayWindow is moved from OpenGLBackend to the sub classes which need
to provide it.
The pure virtual methods windowAdded, windowClosed, windowDeleted and
windowGeometryShapeChanged had identical implementations in both XRender
and OpenGL scene. They were accessing the hash with Scene::Windows which
is nowhere else used except for creating the stacking order in ::paint.
The implementations are moved to the base class, the only Scene specific
code is a pure virtual factory method to create the Scene window. This
already existed in SceneOpenGL to create either a SceneOpenGL1 or 2
window.
Also the hash of windows is a Scene private member now and the creation
of the stacking order is provided by a method, so that the Scene sub
classes do no longer need to access the stacking order at all.
REVIEW: 111207
With QtQuick2 it's possible that the scene graph rendering context either
lives in an own thread or uses the main GUI thread. In the latter case
it's the same thread as our compositing OpenGL context lives in. This
means our basic assumption that between two rendering passes the context
stays current does not hold.
The code already ensured that before we start a rendering pass the
context is made current, but there are many more possible cases. If we
use OpenGL in areas not triggered by the rendering loop but in response
to other events the context needs to be made current. This includes the
loading and unloading of effects (some effects use OpenGL in the static
effect check, in the ctor and dtor), background loading of texture data,
lazy loading after first usage invoked by shortcut, etc. etc.
To properly handle these cases new methods are added to EffectsHandler
to make the compositing OpenGL context current. These calls delegate down
into the scene. On non-OpenGL scenes they are noop, but on OpenGL they go
into the backend and make the context current. In addition they ensure
that Qt doesn't think that it's QOpenGLContext is current by calling
doneCurrent() on the QOpenGLContext::currentContext(). This unfortunately
causes an additional call to makeCurrent with a null context, but there
is no other way to tell Qt - it doesn't notice when a different context
is made current with low level API calls. In the multi-threaded
architecture this doesn't matter as ::currentContext() returns null.
A short evaluation showed that a transition to QOpenGLContext doesn't
seem feasible. Qt only supports either GLX or EGL while KWin supports
both and when entering the transition phase for Wayland, it would become
extremely tricky if our native platform is X11, but we want a Wayland
EGL context. A future solution might be to have a "KWin-QPA plugin" which
uses either xcb or Wayland and hides everything from Qt.
The API documentation is extended to describe when the effects-framework
ensures that an OpenGL context is current. The effects are changed to
make the context current in cases where it's not guaranteed. This has
been done by looking for creation or deletion of GLTextures and Shaders.
If there are other OpenGL usages outside the rendering loop, ctor/dtor
this needs to be changed, too.
Port from kFatal to qFatal - kFatal is still in kde4support,
but lacking debug area support arguably isn't that big a
deal since fatals can't be turned off anyway.
CCMAIL:mgraesslin@kde.org
AbstractThumbnailItem inherits from QQuickPaintedItem using QPainter to
do the fallback painting of icons.
The scene is adjusted to get the information from QQuickItem instead of
QDeclarativeItem. Clipping got a little bit more complex as the clip
path does not exist any more. To get it right the ThumbnailItem needs to
specify the parent it wants to be clipped to with the clipTo property.
E.g.:
clipTo: listView
The scene uses this clipTo parent item to correctly calculate the clip
region. Also the ThumbnailItem needs to have clipping enabled.
Note: this commit currently breaks TabBox as the qml and view are not
yet adjusted. In scripting the export of the item is disabled, but any
qml script using a ThumbnailItem would obviously also fail.
Cross fading with previous pixmap is achieved by referencing the old
window pixmap. WindowPaintData has a cross-fade-factor which interpolates
between 0.0 (completely old pixmap) to 1.0 (completely new pixmap).
If a cross fading factor is set and a previous pixmap is valid this one
is rendered on top of the current pixmap with opacity adjusted. This
results in a smoother fading.
To simplify the setup the AnimationEffect is extended and also takes care
about correctly (un)referencing the previous window pixmap. The maximize
effect is adjusted to make use of this new capabilities.
Unfortunately this setup has a huge problem with the case that the window
decoration gets smaller (e.g. from normal to maximized state). In this
situation it can happen that the old window is rendered with parts outside
the content resulting in video garbage being shown. To prevent this a set
of new WindowQuads is generated with normalized texture coordinates in
the safe area which contains real content.
For OpenGL2Window a PreviousContentLeaf is added which is only set up in
case the crass fading factor is set.
REVIEW: 110578
The behavior for creating a pixmap for a window is moved from Toplevel
into a dedicated class WindowPixmap. Scene::Window holds a reference to
this class and creates a new WindowPixmap whenever the pixmap needs to be
discarded. In addition it also keeps the old WindowPixmap around for the
case that creating the new pixmap fails. The compositor can in that case
use the previous pixmap which reduces possible flickering. Also this
referencing can be used to improve transition effects like the maximize
windows effect which would benefit from starting with the old pixmap.
For XRender and OpenGL a dedicated sub-class of the WindowPixmap is
created which provides the additional mapping to an XRender picture and
OpenGL texture respectively.
BUG: 319563
FIXED-IN: 4.11
REVIEW: 110577
Split WindowQuadDecoration into WindowQuadDecorationLeftRight
and WindowQuadDecorationTopBottom.
This simplifies the code in SceneOpenGL::Window::paintDecoration().