Currently, we store all surfaces in a single list and use linear search
to find the SurfaceInterface by its object id and client connection.
With this, we first search for the wl_resource object by its id. Once we
have a wl_resource, SurfaceInterface::get(wl_resource) can be used.
The main advantage of the proposed solution is that we don't need to
maintain a static list with all SurfaceInterface objects.
A subsurface should be considered mapped only if it has a buffer
attached and its parent is also mapped.
Currently, mapped status logic in SurfaceInterface is somewhat broken
for sub-surfaces. For example, the mapped() signal will be emitted even
if the sub-surface should be considered unmapped according to the spec.
Currently, the BufferInterface encapsulates all the kinds of client
buffers. This has become a somewhat annoying issue as we want to
reference the shm pool if a shm buffer is destroyed, or have custom
buffer readiness logic for linux dma-buf client buffers.
Implementing all of that with the current abstractions will be
challenging as there's no good separation between different client
buffer types.
This change splits the BufferInterface class in three sub-classes -
DrmClientBuffer, LinuxDmaBufV1ClientBuffer, and ShmClientBuffer.
In addition to that, this change fixes the broken buffer ref'ing api.
Currently, the swapStates() function does two things - (a) it merges one
state with another; (b) it applies the next state. This change splits the
swapStates() so it's simpler and the boolean trap can be removed.
Currently, the committed signal is emitted after the client has called
wl_surface.commit. However, this breaks with synchronized subsurfaces.
Notably, Firefox splits a web page in a bunch of smaller layers, which
can be backed by wl_subsurface objects.
All the subsurfaces are in the sync mode. If a layer needs to be
repainted, Firefox will commit the corresponding subsurface with a frame
callback.
Since the committed signal is emitted when the wl_surface.commit request
is invoked, kwin will schedule a new frame immediately. Meaning, that it
is quite likely that firefox will have old contents.
The right thing to do would be to schedule a frame when all the ancestors
of the layer subsurface have been committed.
This change re-jitters the commit logic so the committed signal is
emitted when a new state is applied to the surface. It also slightly
cleans up how SubSurfaceInterface::parentCommit() is called.
It will be nice to cleanup the commit logic further by calling the
surface role's commit hook unconditionally, i.e. not check whether it's
a subsurface. But doing so may result in infinite recursions. How to
clean up that is still TBD.
According to the spec, if the parent surface is specified in the
wl_subsurface.place_below(), the subsurface has to be rendered below the
parent surface.
At the moment, kwaylandserver doesn't handle that case properly. It is
not possible for sub-surfaces to go below the parent surface.
Another issue is that we wrongly assume that the place_above request
will put the subsurface on top of the stack if the parent surface is
specified as sibling. It doesn't seem like that's the case, not
according to the spec.
This change splits the child sub-surface list in two lists - below and
above. The alternative solution is to store the parent surface in the
children list, but it's an error prone solution and it's conceptually
weird.
This way, the compositor can batch more frame callbacks before flushing
the client connection. We attempted this before, but it broke tests.
Now, it seems like the tests pass, so we can remove the manual flush.
This way, it's less characters to type. In order to support delayed
surface commits, compositor extensions need to piggyback their state on
the state of the wl_surface. In other words, SurfaceState is going to
be used not only by SurfaceInterface, but the viewporter extension, the
xdg-shell extension, etc.
Unfortunately, we cannot just simply unset the wl_global's user data.
The compositor still needs to process client requests after the global
has been removed, for example bind requests or the requests that create
new resources.
CCBUG: 435258
I've been using kwaylandserver without this workaround for a while and
haven't experienced any issues. Also, there were some sub-surface fixes
in QtWayland.
Currently, the SurfaceInterface class has a signal that is emitted
whenever any sub-surfaces in its sub-tree changes in a way that requires
a repaint. It is emitted when a sub-surface is resized, moved, or
damaged, etc. There is no way for the compositor to track changes in the
stacking order of sub-surfaces efficiently.
This change replaces the subTreeChanged signal with a less noisy signal
that's emitted whenever the list of direct child sub-surfaces changes.
If a Wayland protocol deals with regions, they will be exposed as
QRegion objects in public API. Therefore, it makes sense to make
RegionInterface private as it's an implementation detail and it's
not intended to be used in public api.
The corresponding test was dropped because the CompositorInterface
no longer emits a signal to indicate that a wl_region has been created.
It should be also noted that wl_region stuff is already tested via
other means, e.g. surface damage, etc.
The following order of events are legal:
Typically order is:
- server announces a new output
- client binds to a new output
- server updates the surface to be on new output
But we can have events occur in the following order:
- server announces a new output
- server updates the surface to be on new output
- client binds to a new output
At which point when we update the surface there is no ID to tell the
client which output the surface is on.
This patch watches for clients binding to output and updates
appropriately.
Getting the object associated with the particular wl_resource is not
difficult, but it involves a pretty reasonable amount of boilerplate
code.
This change, introduces a helper function with an intend to reduce the
amount of boilerplate code.
It can be used as resource_cast<const ObjectPrivate *>(resource) or
just simply resource_cast<ObjectPrivate *>(resource).
This change rewrites implementation of subsurfaces with qtwaylandscanner
and fixes various smaller issues, such as proper handling of position
updates for subsurfaces in the desync mode and getting rid of QPointer in
the public API.
It is allowed to call surface_attach multiple times with the same
buffer. We want to only connect once.
Found whilst debugging a freeze, going through the list of
BufferInterface connections I had multiple to the same SurfaceInterface.
CCBUG: 428361
Some input related code in kwin is mislead by the fact that when the
input region is infinite, SurfaceInterface::input() is going to return
an empty QRegion object.
We cannot really do that because the client could have just set a valid
empty wl_region object to ignore all input events.
This change makes SurfaceInterface assign an actually infinite region
when a NULL input region has been passed to set_input_region().
If a frame callback resource is destroyed, it will unregister itself
from corresponding lists in current, pending, and cached state.
However, this means that we need to be super duper careful when the
compositor wants to destroy all frame callbacks. We need to make a copy
of a frameCallbacks list; otherwise a call to removeOne() will
invalidate iterators and the compositor may crash.
Currently, that copy is made implicitly. Some people may see that code
and add qAsConst() without realizing the consequences it will lead to.
This change improves the readability of that code by making explicit
copies of frameCallbacks in code that shuts down SurfaceInterface.
This reverts commit 3cf004b68e.
Unfortunately, 3cf004b broke a couple of tests in kwin due to Qt not
emitting QAbstractEventDispatcher::aboutToBlock() signal when macros
such as QTRY_VERIFY() or QTRY_COMPARE() spin the event loop.
Frame callbacks only indicate when the client can start rendering a new
frame, it's not meant to be precise. If the client wants to do some
black magic with frame scheduling and so on, it needs to use a protocol
such as presentation_time. This change removes the pointless flush to
prevent over-flushing client connections.
Order of a client teardown is:
- ClientConnection is removed from the static map
- All our client owned resources are torn down
- ClientConnection is deleted (via a previous deleteLater)
The recent refactor led to a behavioural change where ::client could
return a null pointer.
We want the client getter to be valid throughout the lifespan of
SurfaceInterface, by doing the lookup once we achieve that.
BUG: 424255
The main purpose behind the kwaylandserver library is to provide a set
of re-usable wayland compositor extension implementations. However, it's
worth noting that the design of kwaylandserver is far from perfect at
the moment.
KWaylandServer tries to hide all low level wayland details from the
compositor. But it's not the case with buffers, which diminishes the
whole point behind the library.
Creating OpenGL textures from Wayland buffers is the responsibility of
the compositor. So, when it comes to client buffers, we are one foot in
KWaylandServer, and the other foot in the compositor.
Since the surface size is a logical size, the compositor can't use it
for allocating memory for OpenGL textures. This change adds the buffer
size property in SurfaceInterface that can be used for allocating memory
for textures as well as monitoring buffer size changes.
I must say that the introduction of the buffer size property is a crude
hack because BufferInterface just needs to provide an OpenGL texture for
each plane. The main blocker for that is that it would involve moving
the backend, the compositor, and the wayland bits in the same place, for
example kwayland-server or ultimately kwin.
The buffer scale and the buffer transform property specify transforms
that had been applied to the buffer's contents. Neither one of those
properties apply to the surface, in other words the buffer transform
property doesn't indicate that the surface was rotated or flipped or both.
This change doesn't gain anything in terms of new features, etc. It just
attempts to make things more clear.
The compositor needs to monitor changes in the mapping between the
surface local coordinates and the buffer coordinates because texture
coordinates correspond to the latter. One way to do it is to monitor
things such as the surface size, the buffer size, the buffer scale,
etc. The main problem with doing so is that there are so many factors
that contribute to how mapping between the surface local coordinate
space and the buffer coordinate space is performed.
In order to provide a generic way for monitoring changes in the mapping
between the surface local coordinate space and the buffer coordinate
space, this patch introduces two new matrices. The first one specifies
how the surface-local coordinates are mapped to buffer coordinates, and
the other one specifies how to map the buffer coordinates to surface
local coordinates.
With the new two matrices, the compositor has a generic way to get
notified when it has to re-compute texture coordinates.
The wp_viewporter compositor extension allows clients to crop and scale
their surface. It can be useful for applications such as video players
because it may potentially reduce their power usage.
Unfortunately, in order to map a point from the surface-local coordinate
space to the buffer pixel coordinate space, one cannot divide the point
by the scale factor since the buffer might be rotated or flipped.
This change introduces a couple of helper methods for converting points,
regions, and rectangles from the surface-local coordinates to the buffer
pixel coordinates and vice versa.