The intel DRM driver is known for not being able to handle multi head
setups when KMS modifiers are enabled, due to the implicitly selected
modifiers, while being more suitable for single head setups, cause
bandwidth issues when a certain number of monitor times resolution and
refresh rate is configured.
We don't yet support automatically finding a combination of modifiers
that work, and have because of this disabled KMS modifiers unless the
driver actually needs it.
Lets flip this configuration the other way around, changing the current
udev rule to decide wen to *disable* KMS modifier support, as it so that
only the Intel driver has this problem, while on the other hand, there
several drivers that requires modifiers to function at all.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1792>
This concerns only the cases when the presentation timestamp is received
directly from the device (from KMS or from GLX). In the majority of
cases this timestamp is already MONOTONIC. When it isn't, after this
commit, the current value of the MONOTONIC clock is sampled instead.
The alternative is to store the clock id alongside the timestamp, with
possible values of MONOTONIC, REALTIME (from KMS) and GETTIMEOFDAY (from
GLX; this might be the same as REALTIME, I'm not sure), and then
"convert" the timestamp to MONOTONIC when needed. An example of such a
conversion was done in compositor.c (removed in this commit). It would
also be needed for the presentation-time Wayland protocol. However, it
seems that the vast majority of up-to-date systems are using MONOTONIC
anyway, making this effort not justified.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1484>
This makes "power save" (i.e. when you make a monitor go into power save
mode, or make it come out of power save mode), a per device action when
turning on power saving (power save being set to 'off'), and implicitly
handled when turning off power saving (power save being set to 'on')
when doing a mode set.
This is needed as with atomic mode setting, the configuration of DPMS
(Display Power Management Signaling), is replaced by directly turning on
or off CRTCs, and via the CRTC drm properties. Thus in order to handle
both with a common API, make that API high level enough for both cases
being covered.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
We cannot switch DPMS state to 'on' first, then mode set later, when
using atomic KMS. So when we're turning it on, just let the eventual
mode set handle DPMS too.
When switching DPMS to 'off', do it directly, synchronously, both by
setting the DPMS state and switching off CRTCs.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
This commit consolidates DRM buffer management to the MetaDrmBuffer
types, where the base type handles the common functionality (such as
managing the framebuffer id using drmModeAdd*/RMFb()), and the sub types
their corresponding type specific behavior.
This means that drmModeAdd*/RmFB() handling is moved from meta-gpu-kms.c
to meta-drm-buffer.c; dumb buffer allocation/management from
meta-renderer-native.c.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
This contains a copy of a drmModeModeInfo, describing a mode. It also
has an unused pointer to the impl device it is associated with. It'll
later be used to get a blob ID for the mode.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
Detect displays marked as 'non-desktop' by the kernel and skip them when
creating the outputs. Mutter is not able to render images that are shown
properly on those devices anyway.
This avoids lighting up attached VR HMDs and showing the GDM login
screen between the eyes in a VR HMD instead of on the monitor.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1393
This avoids some issues which could happen on some setups[0] due to
meta-native-renderer.c:dummy_power_save_page_flip →
meta_onscreen_native_swap_drm_fb implicitly turning of the primary
plane (by destroying the KMS framebuffer assigned to it):
* drmModeObjectSetProperty could return an "Invalid argument" error
between setting a non-empty cursor with drmModeSetCursor(2) and
enabling the primary plane again:
Failed to DPMS: Failed to set connector 69 property 2: Invalid argument
(This was harmless other than the error message, as we always re-set
a mode on the CRTC after setting the DPMS property to on, which
enables the primary plane and implicitly sets the DRM property to on)
* drmModeSetCursor(2) could return an "Invalid argument" error between
setting the DPMS property to on and enabling the primary plane again:
Failed to set hardware cursor (drmModeSetCursor failed: Invalid argument), using OpenGL from now on
[0] E.g. with the amdgpu DC display code.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1240
The ID and name are just moved into the instance private, while the rest
is moved to a `MetaCrtcModeInfo` struct which is used during
construction and retrieved via a getter. Opens up the possibility to
add actual sub types.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287
Just as with MetaOutput, instead of the home baked "inheritance" system,
using a gpointer and a GDestroyNotify function to keep the what
effectively is sub type details, make MetaCrtc an abstract derivable
type, and make the implementations inherit it.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287
Instead of the home baked "inheritance" system, using a gpointer and a
GDestroyNotify function to keep the what effectively is sub type
details, make MetaOutput an abstract derivable type, and make the
implementations inherit it.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287
The output info is established during construction and will stay the
same for the lifetime of the MetaOutput object. Moving it out of the
main struct enables us to eventually clean up the MetaOutput type
inheritence to use proper GObject types.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1287
With all the three paths this is quite a handful of code, and it was mostly
duplicated in two places. A follow-up patch would need to introduce a third
copy of it. Therefore move the code into a helper function.
There are two behavioral changes:
- The format error now prints the string code as well, because it is easy to
read.
- The g_debug() in init_dumb_fb() is removed. Did not seem useful.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/810
This commit introduces, and makes use of, a transactional API used for
setting up KMS state, later to be applied, potentially atomically. From
an API point of view, so is always the case, but in the current
implementation, it still uses legacy drmMode* API to apply the state
non-atomically.
The API consists of various buliding blocks:
* MetaKmsUpdate - a set of configuration changes, the higher level
handle for handing over configuration to the impl backend. It's used to
set mode, assign framebuffers to planes, queue page flips and set
connector properties.
* MetaKmsPlaneAssignment - the assignment of a framebuffer to a plane.
Currently used to map a framebuffer to the primary plane of a CRTC. In
the legacy KMS implementation, the plane assignment is used to derive
the framebuffer used for mode setting and page flipping.
This also means various high level changes:
State, excluding configuring the cursor plane and creating/destroying
DRM framebuffer handles, are applied in the end of a clutter frame, in
one go. From an API point of view, this is done atomically, but as
mentioned, only the non-atomic implementation exists so far.
From MetaRendererNative's point of view, a page flip now initially
always succeeds; the handling of EBUSY errors are done asynchronously in
the MetaKmsImpl backend (still by retrying at refresh rate, but
postponing flip callbacks instead of manipulating the frame clock).
Handling of falling back to mode setting instead of page flipping is
notified after the fact by a more precise page flip feedback API.
EGLStream based page flipping relies on the impl backend not being
atomic, as the page flipping is done in the EGLStream backend (e.g.
nvidia driver). It uses a 'custom' page flip queueing method, keeping
the EGLStream logic inside meta-renderer-native.c.
Page flip handling is moved to meta-kms-impl-device.c from
meta-gpu-kms.c. It goes via an extra idle callback before reaching
meta-renderer-native.c to make sure callbacks are invoked outside of the
impl context.
While dummy power save page flipping is kept in meta-renderer-native.c, the
EBUSY handling is moved to meta-kms-impl-simple.c. Instead of freezing the
frame clock, actual page flip callbacks are postponed until all EBUSY retries
have either succeeded or failed due to some other error than EBUSY. This
effectively inhibits new frames to be drawn, meaning we won't stall waiting on
the file descriptor for pending page flips.
https://gitlab.gnome.org/GNOME/mutter/issues/548https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
As with CRTC state, variable connector state is now fetched via the
MetaKmsConnector. The existance of a connector state is equivalent of
the connector being connected. MetaOutputKms is changed to fetch
variable connector state via MetaKmsConnector intsead of KMS directly.
The drmModeConnector is still used for constructing the MetaOutputKms to
find properties used for applying configuration.
https://gitlab.gnome.org/GNOME/mutter/issues/548https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
Move reading state into a struct for MetaCrtcKms to use instead of
querying KMS itself. The state is fetched in the impl context, but
consists of only simple data types, so is made accessible publicly. As
of this, MetaCrtcKms construction does not involve any manual KMS
interaction outside of the MetaKms abstraction.
https://gitlab.gnome.org/GNOME/mutter/issues/548https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
Represents drmModeConnector; both connected and disconnected. Currently
only provides non-changing meta data. MetaOutputKms is changed to use
MetaKmsConnector to get basic metadata, but variable metadata, those
changing depending on what is connected (e.g. physical dimension, EDID,
etc), are still manually retrieved by MetaOutputKms.
https://gitlab.gnome.org/GNOME/mutter/issues/548https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
A plane is one of three possible: primary, overlay and cursor. Each
plane can have various properties, such as possible rotations, formats
etc. Each plane can also be used with a set of CRTCs.
A primary plane is the "backdrop" of a CRTC, i.e. the primary output for
the composited frame that covers the whole CRTC. In general, mutter
composites to a stage view frame onto a framebuffer that is then put on
the primary plane.
An overlay plane is a rectangular area that can be displayed on top of
the primary plane. Eventually it will be used to place non-fullscreen
surfaces, potentially avoiding stage redraws.
A cursor plane is a plane placed on top of all the other planes, usually
used to put the mouse cursor sprite.
Initially, we only fetch the rotation properties, and we so far
blacklist all rotations except ones that ends up with the same
dimensions as with no rotations. This is because non-180° rotations
doesn't work yet due to incorrect buffer modifiers. To make it possible
to use non-180° rotations, changes necessary include among other things
finding compatible modifiers using atomic modesetting. Until then,
simply blacklist the ones we know doesn't work.
https://gitlab.gnome.org/GNOME/mutter/issues/548https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
Add MetaKmsCrtc to represent a CRTC on the associated device. Change
MetaCrtcKms to use the ones discovered by the KMS abstraction. It still
reads the resources handed over by MetaGpuKms, but eventually it will
use only MetaKmsCrtc.
MetaKmsCrtc is a type of object that is usable both from an impl task
and from outside. All the API exposed via the non-private header is
expected to be accessible from outside of the meta-kms namespace.
https://gitlab.gnome.org/GNOME/mutter/issues/548https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
The intention with KMS abstraction is to hide away accessing the drm
functions behind an API that allows us to have different kind of KMS
implementations, including legacy non-atomic and atomic. The intention
is also that the code interacting with the drm device should be able to
be run in a different thread than the main thread. This means that we
need to make sure that all drm*() API usage must only occur from within
tasks that eventually can be run in the dedicated thread.
The idea here is that MetaKms provides a outward facing API other places
of mutter can use (e.g. MetaGpuKms and friends), while MetaKmsImpl is
an internal implementation that only gets interacted with via "tasks"
posted via the MetaKms object. These tasks will in the future
potentially be run on the dedicated KMS thread. Initially, we don't
create any new threads.
Likewise, MetaKmsDevice is a outward facing representation of a KMS
device, while MetaKmsImplDevice is the corresponding implementation,
which only runs from within the MetaKmsImpl tasks.
This commit only moves opening and closing the device to this new API,
while leaking the fd outside of the impl enclosure, effectively making
the isolation for drm*() calls pointless. This, however, is necessary to
allow gradual porting of drm interaction, and eventually the file
descriptor in MetaGpuKms will be removed. For now, it's harmless, since
everything still run in the main thread.
https://gitlab.gnome.org/GNOME/mutter/issues/548https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
DPMS is configured from a bit all over the place: via D-Bus, via X11 and
when reading the current KMS state. Each of these places did it slightly
differently, directly poking at the field in MetaMonitorManager.
To make things a bit more managable, move the field into a new
MetaMonitorManagerPrivate, and add helpers to get and set the current
value. Prior to this, there were for example situations where the DPMS
setting was changed, but without signal listeners being notified about
it.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/506
We might fail to page flip a new buffer, often after resuming, due to
the FIFO being full. Prior to this commit, we handled this by switching
over to plain mode setting instead of page flipping. This is bad because
we won't be synchronized to the refresh rate anymore, but just the
clock.
Instead, deal with this by trying again until the FIFO is no longer
full. Do this on a v-sync based interval, until it works.
This also changes the error handling code for drivers not supporting
page flipping to rely on them returning -EINVAL. The handling is moved
from pretending a page flip working to explicit mode setting in
meta-renderer-native.c.
Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/460
Add a flags field to MetaGpuKms. In following commits, the flags defined
here will be set and used for choosing the primary GPU.
Co-authored by: Emilio Pozuelo Monfort <emilio.pozuelo@collabora.co.uk>
https://gitlab.gnome.org/GNOME/mutter/merge_requests/271
DRM_EVENT_CONTEXT_VERSION is the latest context version supported by
whatever version of libdrm is present. Mutter was blindly asserting it
supported whatever version that may be, even if it actually didn't.
With libdrm 2.4.78, setting a higher context version than 2 will attempt
to call the page_flip_handler2 vfunc if it was non-NULL, which being a
random chunk of stack memory, it might well have been.
Set the version as 2, which should be bumped only with the appropriate
version checks.
https://bugzilla.gnome.org/show_bug.cgi?id=781034
Add support for getting hardware presentation times from KMS (Wayland
sessions). Also implement cogl_get_clock_time which is required to compare
and judge the age of presentation timestamps.
For single monitor systems this is straightforward. For multi-monitor
systems though we have to choose a display to sync to. The compositor
already partially solves this for us in the case of only one display
updating because it will only use the subset of monitors that are
changing. In the case of multiple monitors consuming the same frame
concurrently however, we choose the fastest one (in use at the time).
Note however that we also need !73 to land in order to fully realize
multiple monitors running at full speed.
drmModePageFlip() is guaranteed to fail for the invalid FB id 0.
Therefore it never makes sense to call this function with such argument.
Disabling a CRTC must be done with SetCrtc instead, for example.
Trying to flip to FB 0 not only fails, but it also causes Mutter to
never try page flip on this output again, using drmModeSetCrtc()
instead.
We need a way for mutter to exit if no available GPUs are going to work.
For example if gdm starts gnome-shell and we're using a DRM driver that
doesn't work with KMS then we should exit so that GDM can try with Xorg,
rather than operating in headless mode.
Related: https://gitlab.gnome.org/GNOME/mutter/issues/223