Prior to [1], if an entry in a DRM format set was different than a
single LINEAR modifier, implicit modifiers were always allowed. This
has changed and now implicit modifiers are only allowed if INVALID
is in the list of modifiers.
So now we can safely enable explicit modifiers for cross-GPU imports,
without risking receiving buffers with an implicit modifier. This
should improve perf a bit on setups where two GPUs from the same vendor
are used.
This fixes the first bullet point from [2].
[1]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3231
[2]: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3331
Maintaining our internal table up-to-date is tedious: one needs to
manually go through the PnP ID registry [1] and check whether we're
missing any entry.
udev_hwdb already has an API to fetch a manufacturer name from its
PnP ID. Use that instead.
[1]: https://uefi.org/pnp_id_list
The BO handle table exists to avoid double-closing a BO handle,
which aren't reference-counted by the kernel. But if we can
guarantee that there is only ever a single ref for each BO handle,
then we don't need the BO handle table anymore.
This is possible if we create the handle right before the ADDFB2
IOCTL, and close the handle right after. The handles are very
short-lived and we don't need to track their lifetime.
Because of multi-planar FBs, we need to be a bit careful: some
FB planes might share the same handle. But with a small check, it's
easy to avoid double-closing the same handle (which wouldn't be a
big deal anyways).
There's one gotcha though: drmModeSetCursor2 takes a BO handle as
input. Saving the handles until drmModeSetCursor2 time would require
us to track BO handle lifetimes, so we wouldn't be able to get rid
of the BO handle table. As a workaround, use drmModeGetFB to turn the
FB ID back to a BO handle, call drmModeSetCursor2 and then immediately
close the BO handle. The overhead should be minimal since these IOCTLs
are pretty cheap.
Closes: https://github.com/swaywm/wlroots/issues/3164
Instead of ensuring the renderer and allocator are initialized in each
backend, do it in wlr_backend_autocreate. This allows compositors to
create backends without any renderer/allocator if they side-step
wlr_backend_autocreate.
Since the wlr_backend_get_renderer and backend_get_allocator end up
calling wlr_renderer_autocreate and wlr_allocator_autocreate, it sounds
like a good idea to centralize all of the opimionated bits in one place.
Using GBM to import DRM dumb buffers tends to not work well. By
using GBM we're calling some driver-specific functions in Mesa.
These functions check whether Mesa can work with the buffer.
Sometimes Mesa has requirements which differ from DRM dumb buffers
and the GBM import will fail (e.g. on amdgpu).
Instead, drop GBM and use drmPrimeFDToHandle directly. But there's
a twist: BO handles are not ref'counted by the kernel and need to
be ref'counted in user-space [1]. libdrm usually performs this
bookkeeping and is used under-the-hood by Mesa.
We can't re-use libdrm for this task without using driver-specific
APIs. So let's just re-implement the ref'counting logic in wlroots.
The wlroots implementation is inspired from amdgpu's in libdrm [2].
Closes: https://github.com/swaywm/wlroots/issues/2916
[1]: https://gitlab.freedesktop.org/mesa/drm/-/merge_requests/110
[2]: 1a4c0ec9ae/amdgpu/handle_table.c
Unless we're dealing with a multi-GPU setup and the backend being
initialized is secondary, we don't need a renderer nor an allocator.
Stop initializing these.
This is the cause of the spurious "drmHandleEvent failed" messages
at exit. restore_drm_outputs calls handle_drm_event in a loop without
checking whether the FD is readable, so drmHandleEvent ends up with a
short read (0 bytes) and returns an error.
The loop's goal is to wait for all queued page-flip events to complete,
to allow drmModeSetCrtc calls to succeed without EBUSY. The
drmModeSetCrtc calls are supposed to restore whatever KMS state we were
started with. But it's not clear from my PoV that restoring the KMS
state on exit is desirable.
KMS clients are supposed to save and restore the (full) KMS state on VT
switch, but not on exit. Leaving our KMS state on exit avoids unnecessary
modesets and allows flicker-free transitions between clients. See [1]
for more details, and note that with Pekka we've concluded that a new
flag to reset some KMS props to their default value on compositor
start-up is the best way forward. As a side note, Weston doesn't restore
the CRTC by does disable the cursor plane on exit (see
drm_output_deinit_planes, I still think disabling the cursor plane
shouldn't be necessary on exit).
Additionally, restore_drm_outputs only a subset of the KMS state.
Gamma and other atomic properties aren't accounted for. If the previous
KMS client had some outputs disabled, restore_drm_outputs would restore
a garbage mode.
[1]: https://blog.ffwll.ch/2016/01/vt-switching-with-atomic-modeset.html
wl_event_loop_add_fd was called with a NULL data argument, but the
function expects the data argument to be set to the wlr_drm_backend.
Fixes: 053ebe7c27 ("backend/drm: terminate display on drmHandleEvent failure")
Some buffers need to be copied across GPUs. Such buffers need to be
allocated with a format and modifier suitable for both the source
and the destination.
When explicit modifiers aren't supported, we were forcing the buffers
to be allocated with a linear layout, because implicit modifiers
aren't portable across GPUs. All is well with this case.
When explicit modifiers are supported, we were advertising the whole
list of destination modifiers, in the hope that the source might
have some in common and might be able to allocate a buffer with a
more optimized layout. This works well if the source supports explicit
modifiers. However, if the source doesn't, then wlr_drm_format_intersect
will fallback to implicit modifiers, and everything goes boom: the
source uses a GPU-specific tiling and the destination interprets it
as linear.
To avoid this, just force linear unconditionally. We'll be able to
revert this once we have a good way to indicate that an implicit modifier
isn't supported in wlr_drm_format_set, see [1].
[1]: https://github.com/swaywm/wlroots/pull/2815
Closes: https://github.com/swaywm/wlroots/issues/3030
Custom backends and renderers need to implement
wlr_backend_impl.get_buffer_caps and
wlr_renderer_impl.get_render_buffer_caps. They can't if enum
wlr_buffer_cap isn't made public.
This new functions cleans up the common backend state. While this
currently only emits the destroy signal, this will also clean up
the renderer and allocator in upcoming patches.
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.
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.
When the session is inactive, we can't change the KMS state. Ignore
hotplug events so that compositors don't try to perform a modeset when
a connector is plugged in. We already re-scan connectors when the
session becomes active.
To test, run a wlroots compositor on VT 1, switch to VT 2, unplug a
connector, re-plug it, switch back to VT 1. Without this patch the
screen is black on VT 1.
References: https://github.com/swaywm/wlroots/issues/2370
This callback allowed compositors to customize the EGL config used by
the renderer. However with renderer v6 EGL configs aren't used anymore.
Instead, buffers are allocated via GBM and GL FBOs are rendered to. So
customizing the EGL config is a no-op.
Instead of operating on FDs in {open,close}_device, operate on
wlr_devices. This avoids the device lookup in wlr_session and allows
callers to have access to wlr_device fields.
For now, we use it to remove wlr_session_signal_add and replace it with
a more idiomatic wlr_session.events.change field. In the future, other
events will be added.
conn->crtc is NULL in case the output is disabled.
However, the DRM backend will set the GAMMA_LUT property anyway. On each
commit the whole state is sent to KMS. Adding WLR_DRM_CRTC_GAMMA_LUT to
the pending state would just make the backend re-create the blob
containing the gamma LUT.
This is a type which manages gbm_surfaces and imported dmabufs in the
same place, and makes the lifetime management between the two shared. It
should lead to easier to understand code, and fewer special cases.
This also contains a fair bit of refactoring to start using this new
type.
Co-authored-by: Simon Ser <contact@emersion.fr>
This fixes a segfault in drm_connector_set_mode (mode = NULL).
This happens because we set wlr_output.enabled to true if the connector
is attached to the CRTC. When the user disables an output in the
wlroots-based compositor, switches to another VT (enabling the output),
then switches back, wlroots sets wlr_output.enabled to true but
wlr_output.current_mode is NULL.
We should consider not reading properties from KMS after a TTY switch,
disabling all connectors. However this may result in flickering (outputs
being disabled then re-enabled).
Closes: https://github.com/swaywm/wlroots/issues/1874
This fixes a heap-use-after-free when the session is destroyed before
the backend during wl_display_destroy:
==1085==ERROR: AddressSanitizer: heap-use-after-free on address 0x614000000180 at pc 0x7f88e3590c2d bp 0x7ffdc4e33f90 sp 0x7ffdc4e33f80
READ of size 8 at 0x614000000180 thread T0
#0 0x7f88e3590c2c in find_device ../subprojects/wlroots/backend/session/session.c:192
#1 0x7f88e3590e85 in wlr_session_close_file ../subprojects/wlroots/backend/session/session.c:204
#2 0x7f88e357b80c in libinput_close_restricted ../subprojects/wlroots/backend/libinput/backend.c:24
#3 0x7f88e21af274 (/lib64/libinput.so.10+0x28274)
#4 0x7f88e21aff1d (/lib64/libinput.so.10+0x28f1d)
#5 0x7f88e219ddac (/lib64/libinput.so.10+0x16dac)
#6 0x7f88e21b415d in libinput_unref (/lib64/libinput.so.10+0x2d15d)
#7 0x7f88e357c9d6 in backend_destroy ../subprojects/wlroots/backend/libinput/backend.c:130
#8 0x7f88e3545a09 in wlr_backend_destroy ../subprojects/wlroots/backend/backend.c:50
#9 0x7f88e358981a in multi_backend_destroy ../subprojects/wlroots/backend/multi/backend.c:54
#10 0x7f88e358a059 in handle_display_destroy ../subprojects/wlroots/backend/multi/backend.c:107
#11 0x7f88e314acde (/lib64/libwayland-server.so.0+0x8cde)
#12 0x7f88e314b466 in wl_display_destroy (/lib64/libwayland-server.so.0+0x9466)
#13 0x559fefb52385 in main ../main.c:67
#14 0x7f88e2639152 in __libc_start_main (/lib64/libc.so.6+0x27152)
#15 0x559fefb4297d in _start (/home/simon/src/glider/build/glider+0x2297d)
0x614000000180 is located 320 bytes inside of 416-byte region [0x614000000040,0x6140000001e0)
freed by thread T0 here:
#0 0x7f88e3d0a6b0 in __interceptor_free /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:122
#1 0x7f88e35b51fb in logind_session_destroy ../subprojects/wlroots/backend/session/logind.c:270
#2 0x7f88e35905a4 in wlr_session_destroy ../subprojects/wlroots/backend/session/session.c:156
#3 0x7f88e358f440 in handle_display_destroy ../subprojects/wlroots/backend/session/session.c:65
#4 0x7f88e314acde (/lib64/libwayland-server.so.0+0x8cde)
previously allocated by thread T0 here:
#0 0x7f88e3d0acd8 in __interceptor_calloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:153
#1 0x7f88e35b911c in logind_session_create ../subprojects/wlroots/backend/session/logind.c:746
#2 0x7f88e358f6b4 in wlr_session_create ../subprojects/wlroots/backend/session/session.c:91
#3 0x559fefb51ea6 in main ../main.c:20
#4 0x7f88e2639152 in __libc_start_main (/lib64/libc.so.6+0x27152)