This replaces functionality that MetaRenderDevice and friends has
learned, e.g. buffer allocation, EGLDisplay creation, with the usage of
those helper objects. The main objective is to shrink
meta-renderer-native.c and by extension meta-onscreen-native.c, moving
its functionality into more isolated objects.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1854>
This changes the setup phase of clutter to not be result of calling an
init function that sets up a few global singletons, via global singleton
setup vfuncs.
The way it worked was that mutter first did some initial setup
(connecting to the X11 server), then set a "custom backend" setup vfunc
global, before calling clutter_init().
During the clutter_init() call, the context and backend was setup by
calling the global singleton getters, which implicitly created the
backend and context on-demand.
This has now changed to mutter explicitly creating a `ClutterContext`
(which is actually a `ClutterMainContext`, but with the name shortened to
be consistent with `CoglContext` and `MetaContext`), calling it with a
backend constructor vfunc and user data pointer.
This function now explicitly creates the backend, without having to go
via the previously set global vfunc.
This changes the behavior of some "get_default()" like functions, which
will now fail if called after mutter has shut down, as when it does so,
it now destroys the backends and contexts, not only its own, but the
clutter ones too.
The "ownership" of the clutter backend is also moved to
`ClutterContext`, and MetaBackend is changed to fetch it via the clutter
context.
This also removed the unused option parsing that existed in clutter.
In some places, NULL checks for fetching the clutter context, or
backend, and fetching the cogl context from the clutter backend, had to
be added.
The reason for this is that some code that handles EGL contexts attempts
to restore the cogl EGL context tracking so that the right EGL context
is used by cogl the next time. This makes no sense to do before Cogl and
Clutter are even initialized, which was the case. It wasn't noticed
because the relevant singletons were initialized on demand via their
"getters".
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2002>
In order to make it possible to e.g. unload an unused DRM device, we
need to make sure that we don't keep the file descriptor open if we
don't need it; otherwise we block anyone from unloading the
corresponding module.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1828>
The DRM buffers aren't really tied to mode setting, so they shouldn't
need to have an associated mode setting device. Now that we have a
device file level object that can fill this role, port over
MetaDrmBuffer and friends away from MetaKmsDevice to MetaDeviceFile.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1828>
Keep a private MetaDeviceFile instance for the GPU's managed by the
renderer. This is a step towards decoupling rendering from mode setting,
as well as on-demand holding of device file descriptors.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1828>
A view is only a 'CoglOnscreen' if it ends up on a CRTC, thus needs a
mode. Other views are for virtual monitors, and require no mode setting,
so exclude them from the pending mode set list.
This avoids a dead lock when we'll be waiting indefinitely for mode
setting on a virtual monitor.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1891>
With atomic mode setting, commits don't work when CRTCs aren't enabled,
which they aren't when we're power saving. This means the gamma state
fails to being update. To fix night light and for whatever other reason
gamma ramps was changed during power saving by marking the CRTC gamma
state as invalid when leaving power saving, as well as when resuming.
This means that the next frame will append the CRTC gamma state to the
KMS commit.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1755
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1835>
When a device only had mode sets which turned off monitors, not enabling
anything, there would be no KMS update created and posted, and the
active monitors would remain on.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1821>
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 eliminates the need for any render node or device nodes, thus can
be used without any graphics hardware available at all, or with a
graphics driver without any render node available.
The surfaceless mode currently requires EGL_KHR_no_config_context to
configure the initial EGL display.
This also means we can enable the native backend tests in CI, as it
should work without any additional privileges.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1698>
Virtual monitors are monitors that isn't backed by any monitor like
hardware. It would typically be backed by e.g. a remote desktop service,
or a network display.
It is currently only supported by the native backend, and whether the
X11 backend will ever see virtual monitors is an open question. This
rest of this commit message describes how it works under the native
backend.
Each virutal monitor consists of virtualized mode setting components:
* A virtual CRTC mode (MetaCrtcModeVirtual)
* A virtual CRTC (MetaCrtcVirtual)
* A virtual connector (MetaOutputVirtual)
In difference to the corresponding mode setting objects that represents
KMS objects, the virtual ones isn't directly tied to a MetaGpu, other
than the CoglFramebuffer being part of the GPU context of the primary
GPU, which is the case for all monitors no matter what GPU they are
connected to. Part of the reason for this is that a MetaGpu in practice
represents a mode setting device, and its CRTCs and outputs, are all
backed by real mode setting objects, while a virtual monitor is only
backed by a framebuffer that is tied to the primary GPU. Maybe this will
be reevaluated in the future, but since a virtual monitor is not tied to
any GPU currently, so is the case for the virtual mode setting objects.
The native rendering backend, including the cursor renderer, is adapted
to handle the situation where a CRTC does not have a GPU associated with
it; this in practice means that it e.g. will not try to upload HW cursor
buffers when the cursor is only on a virtual monitor. The same applies
to the native renderer, which is made to avoid creating
MetaOnscreenNative for views that are backed by virtual CRTCs, as well
as to avoid trying to mode set on such views.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1698>
Instead of calling "init_onscreen()" on two different separate vtables
from the allocate() funtion, just have the CoglOnscreen sub types
themself implement allocate() and initialize in there.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1514>
Thins means that e.g. MetaOnscreenNative now inherits CoglOnscreenEgl,
which inherits CoglOnscreen which inherits CoglFramebuffer, all being
the same GObject instance.
This makes it necessary to the one creating the onscreen to know what it
wants to create. For the X11 backend, the type of renderer (Xlib EGL or
GLX) determines the type, and for the native backend, it's currently
always MetaOnscreenNative.
The "winsys" vfunc entries related to onscreens hasn't been moved yet,
that will come later.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1514>
To get meta-renderer-native.c down to a bit more managable size, and to
isolate "onscreen" functionality from other (at least partly), move out
the things related to CoglOnscreen to meta-onscreen-native.[ch].
A couple of structs are moved to a new shared header file, as
abstracting those types (e.g. (primary, secondary) render devices) will
be dealt with later.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1514>
The mutter naming convention for types and their instance variables is:
Type name:
[Namespace][BaseName][SubType]
Instance name:
[base_name]_[sub_type]
This means that e.g. CoglOnscreenGLX is renamed CoglOnscreenGlx, and
glx_onscreen is renamed onscreen_glx. This is in preparation for
GObjectification.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1514>
This adds a MetaKmsImplDevice backend using atomic drmMode* API in constrast to
non-atomic legacy drmMode* API used in MetaKmsImplDeviceSimple.
This has various behavioral differences worth noting, compared to the
simple backend:
* We can only commit once per CRTC per page flip.
This means that we can only update the cursor plane once. If a primary
plane composition missed a dead line, we cannot commit only a cursor
update that would be presented earlier.
* Partial success is not possible with the atomic backend.
Cursor planes may fail with the simple backend. This is not the case
with the atomic backend. This will instead later be handled using API
specific to the atomic backend, that will effectively translate into
TEST_ONLY commits.
For testing and debugging purposes, the environment variable
MUTTER_DEBUG_ENABLE_ATOMIC_KMS can be set to either 1 or 0 to
force-enable or force-disable atomic mode setting. Setting it to some
other value will cause mutter to abort().
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/548
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
In order to reliably manage the reference count of the user data passed
to page flip listeners - being the stage view - make the ownership of
this data travel through the different objects that take responsibility
of the next step.
Initially this is the MetaKmsPageFlipListener that belongs to a
MetaKmsUpdate.
When a page flip is successfully queued, the ownership is transferred to
a MetaKmsPageFlipClosure that is part of a MetaKmsPageFlipData. In the
simple impl device, the MetaKmsPageFlipData is passed to
drmModePageFlip(), then returned back via the DRM event. In the future
atomic impl device, the MetaKmsPageFlipData is stored in a table, then
retrieved when DRM event are handled.
When the DRM events are handled, the page flip listener's interface
callbacks are invoked, and after that, the user data is freed using the
passed GDestroyNotify function, in the main context, the same as where
the interface callbacks were called.
When a page flip fails, the ownership is also transferred to a
MetaKmsPageFlipClosure that is part of a MetaKmsPageFlipData. This page
flip data will be passed to the main context via a callback, where it
will discard the page flip, and free the user data using the provided
GDestroyNotify.
Note that this adds back a page flip listener type flag for telling the
KMS implementation whether to actively discard a page flip via the
interface, or just free the user data. Avoiding discarding via the
interface is needed for the direct scanout case, where we immediately
need to know the result in order to fall back to the composite pipeline
if the direct scanout failed. We do in fact also need active discard via
the interface paths, e.g. in the simple impl device when we're
asynchronously retrying a page flip, so replace the ad-hoc discard paths
in meta-renderer-native.c and replace them by not asking for no-discard
page flip error handling.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
Destroying an onscreen destroyes the gbm_surface, the gbm_bo's, and the
fb_id's. Doing this (drmModeRmFB() of the fb_id specifically), may on
some hw implicitly disable the CRTC of the plane that framebuffer was
assigned to. This would cause following atomic commit that attempts to
disable the CRTC to fail as disabling an already disabled CRTC is not
allowed.
It'd also mean we'd always disable the plane before having finished next
mode set, leaving it monitor content potentially empty when not really
necessary.
Solve this by keeping the CoglOnscreens (thus the gbm_surface, gbm_bo
and fb_id) alive until the following global mode set has completed, i.e.
the new state has been fully committed and applied.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
Before we received new gamma updates via D-Bus and posted the update to
KMS directly. This won't be possible with atomic KMS, since one can only
update the state of a CRTC once per cycle.
Thus, to handle this, when configured by D-Bus, only cache the value,
and mark it as invalid. The next frame, the native renderer will pick
up the newly cached gamma value and configure the CRTCs accordingly.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
Before each frame is maybe redrawn, push any new cursor KMS state to the
pending update. It'll then either be posted during the next page flip,
or when the same frame finishes, in case nothing was redrawn.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
This makes it possible to post a symbolic page flip and frame callback,
meant to be used by immediate symbolic page flip reply when emulating
cursor plane changes using legacy drmMode* functions.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
Don't mode set each CRTC in separate KMS updates, as reconfiguring one
CRTC might cause other CRTCs to be implicitly reset thus as well,
causing KMS return EBUSY if using atomic modesetting.
Prepare for this by compositing each CRTC first including adding steps
to the KMS update, but wait until all views has rendered at least once
before posting the initial update. After this each CRTC is posted
separately.
Using EGLStreams instead of normal page flipping seems to fail when
doing this though, so handle that the old way for the EGLStream case,
i.e. eglSwapBuffers() -> mode set with dumb buffer -> eglStream
"acquire" (resulting in page flip under the hood).
For this we also introduce a new error code so that we don't use client
buffers when doing mode sets, which could accidentally configure the
CRTC in a way that is incompatible with the primary plane buffers.
Do the same also when we're in power save mode, to only have one special
case path for this scenario in the regular swap-buffer path.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
Instead of setting the frame result in the most generic layer, have the
backends do it themselves. This is necessary to communicate that a
swap-buffer call didn't really succeed completely to present the swapped
buffer, e.g. errors from KMS.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
This argument is intended to be used by clutter to be able to
communicate with the onscreen backend, that happens to be the native
backend. It will be used to pass a ClutterFrame pointer, where the
result of page flips, mode sets etc can be communicated whenever it is
available.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
When we e.g. try to post an direct client buffer scanout update, it
might arbitrarily fail; when this happen we still will want to post the
rest of the update when we try again after having composited the primary
plane. To do this, add a way to preserve the metadata of an update if it
failed, only dropping the failed plane assignments. This involves
unlocking a previously locked MetaKmsUpdate, so that e.g. a new primary
plane can be assigned.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
If a modeset is pending, it's likely that the cursor update will not
work; thus, wait with updating the cursor so that it's applied together
with the mode set update.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
Page flipping shouldn't necessarily be an actively requested action, but
happen implicitly depending on the given state. Thus, change the "page
flip" update into adding listeners for page flip feedback instead.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
If posting an update resulted in an immediate error, don't communicate
this failure using the page flip feedback callbacks, but directly as a
return value.
This makes it possible for the direct client buffer scanout path not to
pass around flags triggering this behavior, meaning we can handle such
direct scanouts better.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>