We can schedule an update from the cursor manager, but that doesn't mean
there will be an actual plane assignment changed at the time of the
update processing, since for example we might have "touched" a CRTC, but
already left it before the processing started, meaning we have nothing
to change after all.
Add a test case that checks that this works properly.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2777>
This removes the old hardware cursor management code and outsources it
to MetaKmsCursorManager. What the native cursor renderer still does,
however, is the preprocessing i.e. rotating/scaling cursor that wouldn't
otherwise be fit for a cursor plane.
The cursor DRM buffers are instead of being per cursor sprite now per
CRTC, meaning we don't need to stop doing hardware cursors if part of
the cursor is on an output that doesn't support it. This is why the
whole scale/transform code changed from being per GPU to per CRTC.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2777>
It can be quite slow to set up the test environment inside the VM, as
well as outside, leaving very little time for the test itself. While
it'd be nice to not run the mock env etc outside the VM, let's just bump
the timeout for now, to avoid unnecessary timeout failures.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2777>
If we turn of a CRTC, we might have invalidated the cursor manager for
the same CRTC, but that should not mean a cursor plane is assigned when
turning off the CRTC.
Add a test case for this.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2777>
This new manager object intends to take over management of the cursor
plane from the native cursor renderer. It's API is intended to be used
from the main thread, except for the _in_input() function, but mainly
operates in the KMS context, i.e. the KMS thread.
It makes use of an "update filter" that is called before each
MetaKmsUpdate is turned into a atomic KMS commit or a set of legacy
drmMode*() API calls. When the cursor position has been invalidated,
it'll assign the cursor plane in the filter callback, using an as up to
date as possible pointer position as the source for the cursor plane
position.
Cursor updates from the input thread schedules updates for the affected
CRTCs which will cause the filter to be run, potentially for cursor-only
commits.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2777>
This adds some plumbing to get the "default" paint flags for regular
stage painting, where one either wants to paint the overlay, or not.
If inhibited, the 'no-cursors' paint flag is used, otherwise the 'none'
flag. This will be used to allow having a per stage view hw cursor
state.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2777>
This makes it possible to post KMS updates that will always defer until
just before the scanout deadline. This is useful to allow queuing cursor
updates where we don't want to post them to KMS immediately, but rather
wait until as late as possible to get lower latency.
We cannot delay primary plane compositions however, and this is due to
how the kernel may prioritize GPU work - not until a pipeline gets
attached to a atomic commit will it in some drivers get bumped to high
priority. This means we still need to post any update that depends on
OpenGL pipelines as soon as possible.
To avoid working on compositing, then getting stomped on the feet by the
deadline scheduler, the deadline timer is disarmed whenever there is a
frame currently being painted. This will still allow new cursor updates
to arrive during composition, but will delay the actual KMS commit until
the primary plane update has been posted.
Still, even for cursor-only we still need higher than default timing
capabilities, thus the deadline scheduler depends on the KMS thread
getting real-time scheduling priority. When the thread isn't realtime
scheduled, the KMS thread instead asks the main thread to "flush" the
commit as part of the regular frame update. A flushing update means one
that isn't set to always defer and has a latching CRTC.
The verbose KMS debug logging makes the processing take too long, making
us more likely to miss the deadline. Avoid this by increasing the
evasion length when debug logging is enabled. Not the best, but better
than changing the behavior completely.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2777>
This is helpful when we add callbacks that should be dispatched in the
KMS impl thread.
This invalidates an assumption about callbacks not being in the impl
context, so some asserts for that are also removed.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2777>
This signal is emitted before terminating the thread, but also when
resetting the thread type. This is to allow thread implementations to
make sure they have no stale pending callbacks to any old main contexts.
This commit "terminates" the impl thread even if there is no actual
thread; this is to trigger the "reset" signal, also when switching from
a user thread to a kernel thread.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2777>
This means we can add COGL_TRACE*() instrumentation that is grouped
correctly in sysprof. If kernel threading is enabled, they will end up
in a "Compositor (KMS thread)" group (ignoring translations).
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2777>
Real time scheduling is needed for better control of when we commit
updates to the kernel, so add a property to MetaThread that, if the
thread implementation uses a kernel thread and not a user thread, RTKit
is asked to make the thread real time scheduled using the maximum
priority allowed.
Currently RTKit doesn't support the GetAll() D-Bus properties method, so
some fall back code is added, as GDBusProxy depends on GetAll() working
to make the cached properties up to date. Once
https://github.com/heftig/rtkit/pull/30 lands and becomes widely
available in distributions, the work around can be dropped.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2777>
Also add an API to inhibit the kernel thread from being used, and make
MetaRenderDeviceEglStream inhibit the kernel thread from being used if
it's active.
The reason for this is that the MetaRenderDeviceEGlStream is used when
using EGLStreams instead of KMS for page flipping. This means the actual
page flipping happens as a side effect of using EGL/OpenGL, which can't
easily be done off thread.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2777>
This will be necessary in order to default to 'kernel' and then switch
to 'user' if the thread instance can no longer be properly multi
threaded.
To avoid having the same thread impl creating and destroying
GMainContext's, this also means always creating a GMainContext for the
thread-impl. When running in user-thread mode, the GMainContext is
wrapped in a wrapper source and dispatched as part of the real main
thread GMainContext, and when in kernel-thread mode, it runs
independently in the dedicated thread.
This has the consequence that the wrapper source will always have the
priority of the highest impl context GSource, but only after it has
dispatched once. Would we need it earlier than that, we either need a
way to introspect existing sources in a GMainContext and their
priorities, or manually track known sources in MetaThreadImpl.
The wrapper source will never be below 0, as that'd mean it could reach
INT_MAX priority if it had no more sources attached to it, meaning it'd
never be dispatched again.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2777>
While doing this, rename the old synchronous functions to more clearly
communicate that they expect to actually process the update during the
call, not just post it.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2777>
While the default when passing NULL will be the main context of the main
thread, make it possible to specify another main context, so that
result handlers can be invoked on the right thread.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2777>
Callbacks could be queued to be invoked either on the impl side or the
main thread side of the thread; change this to take a GMainContext,
which effectively means a callback can be queued to be invoked on any
thread that has a GMainLoop running on its own GMainContext.
Flushing is made to handle flushing callbacks synchronously on all
threads. This works by keeping a hash table of queued callbacks per
thread (GMainContext); when flushing (from the main thread), callbacks
on the main thread context is flushed, followed by synchronization with
all the other threads.
meta_thread_flush_callbacks() is changed to no longer return the number
of dispatched callbacks; it becomes much harder when there are N queues
spread across multiple threads. Since it wasn't used for anything, just
drop the counting, making life slightly easier.
Feedback to thread tasks are however always queued on the callers
thread.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2777>
This means each test is run 4 times:
* with atomic mode setting using a kernel thread,
* with atomic mode setting using a user thread,
* with legacy mode setting using a kernel thread, and
* with legacy mode setting using a user thread.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2777>
This isn't a problem for user space threads, as there are no race
conditions, but when kernel thread support is introduced, we must make
sure that e.g. the main loop is actually running before quitting it.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2777>