Commit Graph

27910 Commits

Author SHA1 Message Date
Jonas Ådahl
e09de6787f context: Handle dealing with option entries
Users can add option entries, and it'll be part of the configuration
phase.

Create the main group manually to be able to set a user_data pointer;
this will be required to not have to rely on globals when parsing
options using a callback.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1861>
2021-07-15 11:25:21 +02:00
Jonas Ådahl
3d2160b473 tests/unit-tests: Port to MetaContext
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1861>
2021-07-15 11:25:20 +02:00
Jonas Ådahl
ccd8da336f context/test: Add 'before-tests' and 'after-tests' signals
Will be used to set up and tear down test infrastructure.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1861>
2021-07-15 10:59:40 +02:00
Jonas Ådahl
bccd93a598 tests/native-headless: Port to MetaContext
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1861>
2021-07-15 10:59:40 +02:00
Jonas Ådahl
82d9dda08a context/test: Add helper to run a test session
Takes care of setup, starting, running, and terminating, as well as
running the GLib test suite.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1861>
2021-07-15 10:59:40 +02:00
Jonas Ådahl
6732e3e585 main: Temporarily tie meta_quit() to meta_context_terminate*()
Makes it possible for mutter internally to use meta_quit() both if we're
running using a MetaContext or the scattered functions.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1861>
2021-07-15 10:59:40 +02:00
Jonas Ådahl
2e784e23a2 context: Add 'notify_ready()' vfunc and method
This intends to replace the call to `meta_register_with_session()` that
deals with X11 session management, and is called when the user is
"ready". In thet test context, doing that makes no sense, so make it a
no-op.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1861>
2021-07-15 10:59:40 +02:00
Jonas Ådahl
4cd1154b3d context/test: Respect MUTTER_SYNC envvar
It just calls meta_set_syncing() accordingly. Is currently done by
meta_init() either when the env var is set, or when a command line
argument is passed.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1861>
2021-07-15 10:59:40 +02:00
Jonas Ådahl
fddc631599 context/test: Enable 'scale-monitor-framebuffer' backend setting
This is done in all tests, so make life easier by doing it here.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1861>
2021-07-15 10:59:40 +02:00
Jonas Ådahl
8bf7d5c155 context: Init debug utils during setup phase
Is currently done during meta_init().

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1861>
2021-07-15 10:59:40 +02:00
Jonas Ådahl
ecc40e7b23 context: Init introspection paths during setup
This is currently done during meta_init().

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1861>
2021-07-15 10:59:40 +02:00
Jonas Ådahl
a32b005848 context: Change to home directory during setup
Is currently done during meta_init().

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1861>
2021-07-15 10:59:40 +02:00
Jonas Ådahl
6f4b973329 context: Initialize signal handlers during setup
Is currently done during meta_init().

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1861>
2021-07-15 10:59:40 +02:00
Jonas Ådahl
8ace1bf3ea context: Init prefs when starting
Is currently done by meta_start().

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1861>
2021-07-15 10:59:40 +02:00
Jonas Ådahl
02176eab83 context: Add start/run/terminate phases
The start phase creates the MetaDisplay object, and initializes Wayland, and
creates the main loop.

The run phase runs the main loop and handles returning an error if the
context was terminated with an error.

The terminate phase terminates the main loop, with or without an error.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1861>
2021-07-15 10:59:40 +02:00
Jonas Ådahl
fe652518af context: Load plugin during setup phase
The plugin must be configured by the context implementation during the
configure phase.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1861>
2021-07-15 10:59:40 +02:00
Jonas Ådahl
75f9085ab9 context: Add setup phase
During this phase, the backend is created and configured. Currently only
configured, but will gain more logic that currently main.c does with
various helpers.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1861>
2021-07-15 10:59:40 +02:00
Jonas Ådahl
df8074c636 util: Export meta_set_syncing() symbol
Will be set by MetaContextTest, until we can move away from the function
completely.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1861>
2021-07-15 10:59:40 +02:00
Jonas Ådahl
c45a1619f5 context: Set up locale on init
Taken from main.c, which does that when getting the main option context,
which happens to happen early in a process's lifetime.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1861>
2021-07-15 10:59:40 +02:00
Jonas Ådahl
6e4d3e0f85 context: Add create_backend() vfunc
This lets the context implementation create a backend. Will later be
used in a 'setup' phase.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1861>
2021-07-15 10:59:40 +02:00
Jonas Ådahl
434f5e5b7b context/test: Add test context type enum
A test context type will later determine what kind of backend the test
case should use; i.e. whether the nested or headless backend should be
used.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1861>
2021-07-15 10:43:28 +02:00
Jonas Ådahl
8cb177499d context/test: Configure test setup during configuration
This includes setting up the GLib test framework, overriding the X11
and Wayland display names.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1861>
2021-07-15 10:43:28 +02:00
Jonas Ådahl
bbf6d88d54 test-utils: Expose helper for ensuring client path
Will be used by the test context to reduce boiler plate.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1861>
2021-07-15 10:43:28 +02:00
Jonas Ådahl
6c6b5b9a48 context: Add entry points for context configuration
Configuration is the first step of the lifetime of a context, after
creation; it's here where argc/argv is processed, and it's determined
what kind of compositor, etc, it is going to be.

The tests always run as Wayand compositors, so the configuration is
quite simple, but will involve more steps later on.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1861>
2021-07-15 10:43:28 +02:00
Jonas Ådahl
bf84b2423d main: Move MetaCompositorType to a new meta-enums.h
It'll be part of and owned by MetaContext, intending to replace
`meta_is_wayland_compositor()`, but place it in a new file for public
enums so that it can be used from wherever.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1861>
2021-07-15 10:43:28 +02:00
Jonas Ådahl
e17bf88d5e tests: Introduce MetaContextTest
This introduces a MetaContext implementation aimed to be used for test
cases, with as little boiler plate as possible needed in the test.

It currently doesn't do anything, just fills out the GObject boiler
plate and sets a name.

Build it into every core test, for compilation, even though it isn't
used anywhere yet.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1861>
2021-07-15 10:43:28 +02:00
Jonas Ådahl
e020fdfddf Introduce mostly empty MetaContext type
This type is intended to replace the scattered functions used to
configure how the Mutter compositor is run. It currently doesn't do
anything, and only has a human readable name, intended to be set to e.g.
"GNOME Shell".

It's an abstract type, and is intended to be used via either a future
`MetaContextMain` for real display server use cases, and a
`MetaContextTest` for test cases.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1861>
2021-07-15 10:43:28 +02:00
Carlos Garnacho
5e8c808cfb ci: Add job for pushing coverity reports
This job does:
1. Download the coverity bundle and untar it
2. Build mutter using clang and the coverity tool
3. Compress the coverity report
4. Upload for analysis

Things to note:
- Analysis are throttled, as per https://scan.coverity.com/faq#frequency
  we qualify for 21 weekly builds, 3 daily. Mutter is sometimes a busy
  project, so it seems we'd get often those consumed early in the day.
  This is something we can resign to, but the times we'll try to upload
  a report to have it rejected make the operation kinda pointless and
  probably better throttled by ourselves.
- The task is manual, given the restrictions above.
- The task only applies on master, as the envvar holding the coverity
  token is protected in gitlab.
- I had to use clang as the coverity tool doesn't seem to work ATM with
  gcc as per recent Fedora.
- The coverity tarball is 1.2GB in size, which is a bit too big to have
  it downloaded each time. As per their upload instructions, the tarball
  gets updated twice yearly, so this is cached to minimize downloads.
- The coverity token for mutter is kept private/hidden in gitlab CI
  settings.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1100>
2021-07-13 15:14:21 +00:00
Jonas Ådahl
23b79f33fa launcher: Remove open/close restricted file API
It has since some time been replaced with MetaDevicePool, and isn't used
by anything anymore, so remove it.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1929>
2021-07-13 12:19:14 +00:00
Daniel van Vugt
0555a5bbc1 clutter/frame-clock: Apply error diffusion (dithering) to dispatch times
But only the dispatch times used when `last_presentation_time_us == 0`
(Nvidia + Xorg).

This ensures the average dispatch interval is always precisely equal
to the refresh interval, regardless of any jitter in the mainloop.

Fixes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1751,
       https://gitlab.gnome.org/GNOME/mutter/-/issues/1758,
       https://gitlab.gnome.org/GNOME/mutter/-/issues/1870

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1826>
2021-07-13 17:18:17 +08:00
Daniel van Vugt
ba1490ec9c clutter/frame-clock: Remember the refresh interval
Instead of recalculating it every time we need it. The performance
gain is not important; this is more because it will be needed in
multiple functions soon.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1826>
2021-07-13 17:18:14 +08:00
Ivan Molodetskikh
a5d1d48bf1 clutter: Add a max render time debug HUD
Not sure how to update the damage or redraw clip or something; at least
this works properly when under a constantly-redrawing window, which is
ok for debugging purposes.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
2021-07-13 08:09:43 +00:00
Ivan Molodetskikh
f55c9af618 clutter: Add an lg command to set max render time constant
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
2021-07-13 08:09:43 +00:00
Ivan Molodetskikh
565e34b4d2 clutter: Add a flag to disable heuristic max render time
Debugging purposes: allows to check if frame drops are caused by
heuristic max render time or if they are there even with the old
behavior.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
2021-07-13 08:09:43 +00:00
Ivan Molodetskikh
592fbee065 clutter: Compute max render time heuristically
Max render time shows how early the frame clock needs to be dispatched
to make it to the predicted next presentation time. Before this commit
it was set to refresh interval minus 2 ms. This means Mutter would
always start compositing 14.7 ms before a display refresh on a 60 Hz
screen or 4.9 ms before a display refresh on a 144 Hz screen. However,
Mutter frequently does not need as much time to finish compositing and
submit buffer to KMS:

      max render time
      /------------\
---|---------------|---------------|---> presentations
      D----S          D--S

      D - frame clock dispatch
      S - buffer submission

This commit aims to automatically compute a shorter max render time to
make Mutter start compositing as late as possible (but still making it
in time for the presentation):

         max render time
             /-----\
---|---------------|---------------|---> presentations
             D----S          D--S

Why is this better? First of all, Mutter gets application contents to
draw at the time when compositing starts. If new application buffer
arrives after the compositing has started, but before the next
presentation, it won't make it on screen:

---|---------------|---------------|---> presentations
      D----S          D--S
        A-------------X----------->

                   ^ doesn't make it for this presentation

        A - application buffer commit
        X - application buffer sampled by Mutter

Here the application committed just a few ms too late and didn't make on
screen until the next presentation. If compositing starts later in the
frame cycle, applications can commit buffers closer to the presentation.
These buffers will be more up-to-date thereby reducing input latency.

---|---------------|---------------|---> presentations
             D----S          D--S
        A----X---->

                   ^ made it!

Moreover, applications are recommended to render their frames on frame
callbacks, which Mutter sends right after compositing is done. Since
this commit delays the compositing, it also reduces the latency for
applications drawing on frame callbacks. Compare:

---|---------------|---------------|---> presentations
      D----S          D--S
           F--A-------X----------->
              \____________________/
                     latency

---|---------------|---------------|---> presentations
             D----S          D--S
                  F--A-------X---->
                     \_____________/
                      less latency

           F - frame callback received, application starts rendering

So how do we actually estimate max render time? We want it to be as low
as possible, but still large enough so as not to miss any frames by
accident:

         max render time
             /-----\
---|---------------|---------------|---> presentations
             D------S------------->
                   oops, took a little too long

For a successful presentation, the frame needs to be submitted to KMS
and the GPU work must be completed before the vblank. This deadline can
be computed by subtracting the vblank duration (calculated from display
mode) from the predicted next presentation time.

We don't know how long compositing will take, and we also don't know how
long the GPU work will take, since clients can submit buffers with
unfinished GPU work. So we measure and estimate these values.

The frame clock dispatch can be split into two phases:
1. From start of the dispatch to all GPU commands being submitted (but
   not finished)—until the call to eglSwapBuffers().
2. From eglSwapBuffers() to submitting the buffer to KMS and to GPU
   work completing. These happen in parallel, and we want the latest of
   the two to be done before the vblank.

We measure these three durations and store them for the last 16 frames.
The estimate for each duration is a maximum of these last 16 durations.
Usually even taking just the last frame's durations as the estimates
works well enough, but I found that screen-capturing with OBS Studio
increases duration variability enough to cause frequent missed frames
when using that method. Taking a maximum of the last 16 frames smoothes
out this variability.

The durations are naturally quite variable and the estimates aren't
perfect. To take this into account, an additional constant 2 ms is added
to the max render time.

How does it perform in practice? On my desktop with 144 Hz monitors I
get a max render time of 4–5 ms instead of the default 4.9 ms (I had
1 ms manually configured in sway) and on my laptop with a 60 Hz screen I
get a max render time of 4.8–5.5 ms instead of the default 14.7 ms (I
had 5–6 ms manually configured in sway). Weston [1] went with a 7 ms
default.

The main downside is that if there's a sudden heavy batch of work in the
compositing, which would've made it in default 14.7 ms, but doesn't make
it in reduced 6 ms, there is a delayed frame which would otherwise not
be there. Arguably, this happens rarely enough to be a good trade-off
for reduced latency. One possible solution is a "next frame is expected
to be heavy" function which manually increases max render time for the
next frame. This would avoid this single dropped frame at the start of
complex animations.

[1]: https://www.collabora.com/about-us/blog/2015/02/12/weston-repaint-scheduling/

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
2021-07-13 08:09:43 +00:00
Ivan Molodetskikh
4a4e61c1f1 clutter: Add FRAME_TIMINGS debug key
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
2021-07-13 08:09:43 +00:00
Ivan Molodetskikh
8d51c5ac55 clutter/frame-clock: Store dispatch timings
Will be used to adjust max render time dynamically.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
2021-07-13 08:09:43 +00:00
Ivan Molodetskikh
8c4a91ddd6 clutter: Add swap time and GPU rendering duration to FrameInfo
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
2021-07-13 08:09:43 +00:00
Ivan Molodetskikh
1116b14f38 backends/native: Get rendering and swap timings during scanout
Scanout doesn't go through the usual path of compositing and doing
eglSwapBuffers, therefore it doesn't hit the timestamp query placed in
that path. Instead, get the timings by binding the scanout buffer to an
FBO and doing a timestamp query on the FBO.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
2021-07-13 08:09:42 +00:00
Ivan Molodetskikh
5a0d3ed4dd backends/native: Remove unneeded NULL check
There seems to be no way to construct this type with an invalid bo.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
2021-07-13 08:09:42 +00:00
Ivan Molodetskikh
f1024564a2 cogl: Store CPU and GPU rendering timestamps in frame info
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
2021-07-13 08:09:42 +00:00
Ivan Molodetskikh
8c258d1de1 cogl: Add CPU swap time and GPU rendering query to CoglFrameInfo
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
2021-07-13 08:09:42 +00:00
Ivan Molodetskikh
fbe6740df1 cogl: Add GPU timestamp querying utilities
Add utilities that allow getting the current GPU timestamp and creating
a query which completes upon completion of all operations currently
submitted on a framebuffer. Combined, these two allow measuring how long
it took the GPU to finish rendering something to a framebuffer.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
2021-07-13 08:09:42 +00:00
Ivan Molodetskikh
cc08af48f6 cogl: Add prototypes for getting timestamp queries
Will be used for measuring GPU rendering duration.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
2021-07-13 08:09:42 +00:00
Ivan Molodetskikh
3aa0e3074f clutter: Store vblank duration in ClutterFrameClock
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
2021-07-13 08:09:42 +00:00
Ivan Molodetskikh
d10567ea3e clutter: Add vblank duration to ClutterStageView
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
2021-07-13 08:09:42 +00:00
Ivan Molodetskikh
2d939754b1 crtc-mode-info: Add vblank duration field
Only populated for KMS backed modes, as that's where it's relevant.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
2021-07-13 08:09:42 +00:00
Ivan Molodetskikh
e40ff9d8b7 backends/native: Add meta_calculate_drm_mode_vblank_duration_us()
Computes the vblank duration from mode timings.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
2021-07-13 08:09:42 +00:00
Ivan Molodetskikh
63b9ac2724 clutter: Record flip time
Will be used for intelligent max render time computation (aka repaint
scheduling).

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1762>
2021-07-13 08:09:42 +00:00
Daniel van Vugt
9f492a0ee0 kms: Add fixed point formatting to MUTTER_DEBUG=kms printing
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1923>
2021-07-13 15:29:14 +08:00