Instead of trying to perform a real modeset in init_renderer,
perform an atomic test-only commit to find out whether disabling
modifiers is necessary because of bandwidth limitations.
This decouples init_renderer from the actual commit, making it
possible to modeset an output with a user-supplied buffer instead
of a black frame.
We loose the ability to make sure the buffers coming from the
swapchain will work fine when using the legacy interface. This
can break i915 when atomic is disabled and modifiers enabled.
But i915 always has atomic (so the user must explicitly disable it
to run into potential bandwidth limitations) and is the only known
problematic driver.
Instead of passing a wlr_texture to the backend, directly pass a
wlr_buffer. Use get_cursor_size and get_cursor_formats to create
a wlr_buffer that can be used as a cursor.
We don't want to pass a wlr_texture because we want to remove as
many rendering bits from the backend as possible.
Backend-initiated mode changes can use this function instead of
going through drm_connector_set_mode. drm_connector_set_mode becomes
a mere drm_connector_commit_state helper.
Replace it with a new drm_connector_state_is_modeset function that
decides whether a modeset is necessary directly from the
wlr_output_state which is going to be applied.
Populate the wlr_output_state when setting a mode. This will allow
drm_connector_set_mode to stop relying on ephemeral fields in
wlr_drm_crtc. Also drm_connector_set_mode will be able to apply
both a new buffer and a new mode atomically.
Stop assuming that the state to be applied is in output->pending in
crtc_commit. This will allow us to remove ephemeral fields in
wlr_drm_crtc, which are used scratch fields to stash temporary
per-commit data.
PRIME support for buffer sharing has become mandatory since the renderer
rewrite. Make sure we check for the appropriate capabilities in backend,
allocator and renderer.
See also #2819.
Downgrade errors to DEBUG level, because drm_fb_create is used in
test_buffer, so errors aren't always fatal. Add ERROR logs at call
sites where a failure is fatal, to make it clear something wrong
happened.
If the import to KMS succeeds, we have a better chance to be able to
scan it out.
Importing is also necessary for test-only commits, which we want to
add in the future.
Compute only the transform matrix in the output. The projection matrix
will be calculated inside the gles2 renderer when we start rendering.
The goal is to help the pixman rendering process.
In 93cd3a79b2 ("backend/drm: stop using GBM flags"), we stopped
using the GBM_BO_USE_LINEAR flag in favor of a modifier list set
to { DRM_FORMAT_MOD_LINEAR }. However, the last argument of
drm_plane_init_surface disables modifiers -- so the buffer will just
get allocated with an implicit modifier, without necessarily being
LINEAR.
To fix this, allow modifiers when allocating the cursor buffers.
wlr_drm_plane.formats should already have the necessary LINEAR
restrictions.
Fixes: 93cd3a79b2 ("backend/drm: stop using GBM flags")
This allows a compositor to get a KMS connector object ID from a
wlr_output. The compositor can then query more information about
the connector via libdrm.
This gives more freedom to compositors and allows them to read
KMS properties that wlroots doesn't know about. For instance,
they could read the EDID or the suggested_{X,Y} properties and
change their output configuration based on that.
The subconnector property indicates the connector sub-type. This is
useful because that usually indicates what kind of connector the user
has plugged in to their monitor, e.g. a DisplayPort-to-DVI cable will
indicate a DVI subconnector. Also some laptops have non-DP connectors
that are internally linked to a DP port on the GPU.
Set the output description accordingly.
See https://drmdb.emersion.fr/properties/3233857728/subconnector
Since 5b1b43c68c ("backend/drm: make wlr_drm_plane.{pending,queued,current}_fb
pointers"), current_fb can be NULL if there's no buffer. If current_fb
is not NULL, current_fb->wlr_buf is guaranteed to not be NULL.
Closes: https://github.com/swaywm/wlroots/issues/2634
Stop keeping track of buffers on the parent GPU when multi-GPU is used.
This removes support for export_dmabuf on secondary GPUs, but renderer
v6 will bring this back by managing the swapchains in wlr_output instead
of the backends.
wlr_drm_connector.crtc may be updated by the DRM backend while a
page-flip is pending. In this case, the page-flip handler won't be able
to find the right wlr_drm_connector from the CRTC ID.
Save the CRTC when performing a page-flip to ensure we always find the
right connector when we get the event.
We now properly mark the cursor plane's formats as linear-only, and we
now have a version of wlr_drm_format_intersect that handles the case of
linear-only formats and implicit modifiers.
We can remove the special drm_plane_init_surface flag we had for cursor
planes. This also allows us to use a non-linear layout for cursor planes
on drivers that support it.
Tested on amdgpu GFX9.
If the kernel driver doesn't support modifiers, it still expects cursor
FBs to have a LINEAR layout. See [1] for expectations for framebuffers
attached to the cursor plane.
[1]: https://patchwork.freedesktop.org/patch/408512/
Parse WLR_DRM_NO_MODIFIERS at startup. Don't parse IN_FORMATS when
WLR_DRM_NO_MODIFIERS is set, so that the legacy behaviour is better
reproduced.
When modifiers aren't supported, try the initial page-flip once only.
This was lost during the refactoring. We were previously calling
wlr_output_destroy, which destroyed the connector as well.
Fixes: 248c7787c7 ("backend/drm: refactor wlr_output destruction")
The DRM backend is a little special when it comes to wlr_outputs: the
wlr_drm_connectors are long-lived and are created even when no screen is
connected.
A wlr_drm_connector only advertises a wlr_output to the compositor when
a screen is connected. As such, most of wlr_output's state is invalid
when the connector is disconnected.
We want to stop using wlr_output state on disconnected connectors.
Introduce wlr_drm_connector.name which is always valid regardless of the
connector status to avoid reading wlr_output.name when disconnected.
Simplify and unify connector-specific logging with a new
wlr_drm_conn_log macro. This makes it easier to understand which
connector a failure is about, without having to explicitly integrate the
connector name in each log message.
The workaround is broken because drm_fb_acquire doesn't leave the EGL
context current anymore. We'll need to re-introduce it.
References: https://github.com/swaywm/wlroots/issues/2525
gbm_bo_create_with_modifiers doesn't take GBM flags, so our
wlr_gbm_allocator interface doesn't either. We were still internally
using GBM flags in the DRM backend, leading to awkward back-and-forth
conversions.
The only flag passed to drm_plane_init_surface was GBM_BO_USE_LINEAR, so
turn that into a bool to make sure other flags can't be passed in.
Move the "force linear" logic out of init_drm_surface, because the
supplied wlr_drm_format should already contain that information.
After discussing with Pekka and Daniel on #dri-devel, we concluded [1]
that user-space shouldn't need to force-probe connectors. Force-probing
can take some time, so using drmModeGetConnectorCurrent can result in
faster start-up.
Users can manually trigger a force-probe if necessary:
echo detect | sudo tee /sys/class/drm/card0-DP-1/status
Or just by running a tool like drm_info.
A similar change has been submitted to Weston [2].
[1]: https://lists.freedesktop.org/archives/dri-devel/2020-November/287728.html
[2]: https://gitlab.freedesktop.org/wayland/weston/-/issues/437
We would always return the GAMMA_LUT_SIZE property if available, and
only fall back to legacy gamma size otherwise. This leads to issues if
both are available in differs in size while we use the legacy backend.
Ensure that we only return the legacy size if we're using the legacy
backend.
Closes: https://github.com/swaywm/wlroots/issues/2429
When performing a modeset, the DRM backend will request a page-flip
event. However frame_pending wasn't set to true, so any subsequent
wlr_output_schedule_frame calls would imemdiately trigger a synthetic
frame event, asking the compositor to submit a new frame. Committing the
new frame fails with "a page-flip is already pending" error in the DRM
backend.
When an output is disabled one last pageflip will happen to disable it.
Currently this pageflip causes a frame event.
Since the output is disabled we don't want to send this frame event.
get_drm_prop_blob does not set path_len if it returns NULL. Check the
return value before path_len to avoid reading uninitialized memory.
(Granted, this doesn't change the logic at all, but it does make
Valgrind a bit happier.)
drm_connector_set_cursor wasn't checking the return value of the
drm_surface_make_current call. On failure, this results in a failed
assertion in wlr_renderer_begin (because no rendering context is
current).
The output backend API is now mostly state-less thanks to the atomic
hooks (commit and test). There is one exception though: attach_render.
This function makes the rendering context current. However sometimes the
compositor might decide not to render after attach_render (e.g. when
there's nothing new to render to the back buffer). Thus
wlr_output_rollback has been introduced to revert the pending state.
Because the output backend API is mostly state-less, the only thing
wlr_output_impl.rollback needs to do is revert the current rendering
context. Rename the function to rollback_render to make this clear. Add
a check in the common wlr_output code to only call rollback_render when
attach_buffer has been previously called.
On the long term, we'll be able to remove attach_render and
rollback_render together.
This patch fixes this failure:
01:57:16.642 [ERROR] [backend/drm/drm.c:360] Failed to page-flip output 'eDP-1': a page-flip is already pending
01:57:16.684 [ERROR] [backend/drm/drm.c:360] Failed to page-flip output 'eDP-1': a page-flip is already pending
01:57:16.684 [ERROR] [backend/drm/drm.c:732] Failed to initialize renderer on connector 'eDP-1': initial page-flip failed
01:57:16.684 [ERROR] [backend/drm/drm.c:805] Failed to initialize renderer for plane
01:57:16.684 [sway/config/output.c:423] Failed to commit output eDP-1
References: https://github.com/swaywm/sway/issues/5101
When the mode, status or buffer hasn't changed, drm_connector_commit was
a no-op. Because of this individual changes to the gamma LUT or adaptive
sync status were ignored (if committed without a buffer).
Instead, perform a commit to apply the changes.
A test commit doesn't apply the pending state.
The CRTC state will be populated again if the compositor decides to
perform a regular commit afterwards.
Previously, we only had the pending state (crtc->pending, crtc->mode and
crtc->active). This causes issues when a commit fails: the pending state
is left as-is, and the next commit may read stale data from it.
This will also cause issues when implementing test-only commits: we need
to rollback the pending CRTC state after a test-only commit.
Introduce separate pending and current CRTC states. Properly update the
current state after a commit.
retry_pageflip is now dead code, since drm_connector_start_renderer
isn't called anymore. It was previously called when enabling an output.
The name "retry_pageflip" was a little confusing because the function
retried a modeset and the timer wasn't set up while performing a simple
page-flip.
Let's just remove this altogether for now. We can discuss whether it's
worth it to bring it back. Should we only do it on failed page-flips?
Should we only do it on EBUSY?
After swapping buffers, it doesn't make sense to perform more rendering
operations. Unset the context to reflect this.
This commit makes it so the context is always only current between
wlr_egl_make_current and wlr_egl_swap_buffers.
This is an alternative to [1].
[1]: https://github.com/swaywm/wlroots/pull/2212
This function can be called after wlr_egl_make_current to cleanup the
EGL context. This avoids having lingering EGL contexts that make things
work by chance.
Closes: https://github.com/swaywm/wlroots/issues/2197