This commit changes `scan_drm_connectors` to add new outputs to the end of the
list. That way, it's easier to understand what's going on with indices.
When we need to destroy outputs, we now walk the list in reverse order. This
ensures indices remain correct while iterating and removing items from the
list.
We now also make outputs without a CRTC disappear (those are in
WLR_DRM_CONN_NEEDS_MODESET state).
The renderer redesign is going to need the render fd before the backend
is fully started, so we have to move the wl registry code to when the
backend is created instead of when it is started.
We also need to stash the wl_keyboard and emit it to library users
later, once they've added their listeners and started the backend.
There was a missing copy_drm_surface_mgpu call in drm_connector_schedule_frame
so we asked for a pageflip with an unknown BO, resulting in ENOENT.
Additionally, this commit makes schedule_frame return a bool indicating
failures. This allows schedule_frame_handle_idle_timer to only set
frame_pending to true if a frame has been successfully scheduled. Thus, if a
pageflip fails, rendering won't be blocked forever anymore.
In case a pageflip is already pending, true is returned because a frame has
already been scheduled and will be sent sometime soon.
This allows the legacy interface to be used instead of atomic if needed. This
is a workaround to make some Intel GPUs work (if this variable is unset) as
well as to make some AMD GPUs work (if this variable is set).
If a pageflip is pending before cleanup, it's still pending after. This
is used line 1177: drm_connector_cleanup is called and
conn->pageflip_pending is checked afterwards.
Fixes#1297
This prevents the idle event to be activated on a destroyed
output.
This also makes the backend responsible for free-ing modes, as it
is the one allocating them and adding them to the list. Note that
the DRM backend (the only one using modes) already frees them.
This desynchronizes our rendering loop with the vblank cycle.
In case a compositor doesn't swap buffers but schedules a frame,
emitting a frame event immediately enters a busy-loop.
Instead, ask the backend to send a frame when appropriate. On
Wayland we can just register a frame callback on our surface. On
DRM we can do a no-op pageflip.
Fixes#617Fixesswaywm/sway#2748
When a pageflip is pending, we'll get a DRM event for the connector
in the future. We don't want to free the connector immediately
otherwise we'll use-after-free in the pageflip handler.
This commit adds a new state, "DISAPPEARED". This asks the pageflip
handler to destroy the output after it's done pageflipping.
Sessions can now be retrieved from a backend in a more general manner.
Multi-backend gets back its `session` field that contains the session
if one was created, removing the interfacing from multi backend with the
drm backend directly. This adds the possibility to use sessions even
without the drm backend.
It additionally fixes the bug that 2 session objects got created when
WLR_BACKENDS were set to "libinput,drm".
To allow vt switching without drm backend (and drm fd) on logind, start
listening to PropertiesChanged signals from dbus and parse the session
"Active" property when no master fd was created (this does not change
current drm backend behaviour in any way).
This commit allows outputs that need a CRTC to steal it from
user-disabled outputs. Note that in the case there are enough
CRTCs, disabled outputs don't loose it (so there's no modeset
and plane initialization needed after DPMS). CRTC allocation
still prefers to keep the old configuration, even if that means
allocating an extra CRTC to a disabled output.
CRTC reallocation now happen when enabling/disabling an output as
well as when trying to modeset. When enabling an output without a
CRTC, we realloc to try to steal a CRTC from a disabled output
(that doesn't really need the CRTC). When disabling an output, we
try to give our CRTC to an output that needs one. Modesetting is
similar to enabling.
A new DRM connector field has been added: `desired_enabled`.
Outputs without CRTCs get automatically disabled. This field keeps
track of the state desired by the user, allowing to automatically
re-enable outputs when a CRTC becomes free.
This required some changes to the allocation algorithm. Previously,
the algorithm tried to keep the previous configuration even if a
new configuration with a better score was possible (it only changed
configuration when the old one didn't work anymore). This is now
changed and the old configuration (still preferred) is only
retained without considering new possibilities when it's perfect
(all outputs have CRTCs).
User-disabled outputs now have `possible_crtcs` set to 0, meaning
they can only retain a previous CRTC (not acquire a new one). The
allocation algorithm has been updated to do not bump the score
when assigning a CRTC to a disabled output.
This commit implements device type discovery by calling two ioctls
(DRM_IOCTL_VERSION and EVIOCGVERSION) on the device. These iocts are
specific to drm and input devices respectively, therefore we can
determine the device type based on which one returns an error.
This commit handles better situations in which the number of
connected outputs is greater than the number of available CRTCs.
It'll enable as many outputs as possible, and transfer CRTCs to
outputs that need one on unplug.
This changes CRTC and plane reallocation to happen after scanning
DRM connectors instead of on modeset.
This cleanups CRTCs and planes on unplug to allow them to be
re-used for other outputs.
On modeset, if an output doesn't have a CRTC, the desired mode is
saved and used later when the output gains a CRTC.
Future work includes giving priority to enabled outputs over
disabled ones for CRTC allocation. This requires the compositor to
know about all outputs (even outputs without CRTCs) to properly
modeset outputs enabled in the compositor config file and disable
outputs disabled in the config file.
The VT the compositor was started from was not activated after exiting
the compositor, which resulted in arriving on a blank VT. This commit
fixes that by introducing a new field in direct_session struct that
stores the last active VT so that it can be activated in
direct_session_destroy.
This prevents receiving modesetting requests from the compositor
while we don't have the whole picture (ie. while we haven't yet
scanned all connectors).
This also makes connectors without CRTCs disabled (they can't be
enabled yet even if some CRTCs are free'd -- this is future work).
A few pedantic changes and unused variables (1-4), and genuine bugs (5,
6).
The reports with the corresponding files and lines numbers are as
follows.
1. backend/libinput/tablet_pad.c@31,44,57
"Allocator sizeof operand mismatch"
"Result of 'calloc' is converted to a pointer of type 'unsigned int',
which is incompatible with sizeof operand type 'int'"
2. types/tablet_v2/wlr_tablet_v2_pad.c@371
"Allocator sizeof operand mismatch"
"Result of 'calloc' is converted to a pointer of type 'uint32_t', which
is incompatible with sizeof operand type 'int'"
3. types/wlr_cursor.c@335
"Dead initialization"
"Value stored to 'dx'/'dy' during its initialization is never read"
4. rootston/xdg_shell.c@510
"Dead initialization"
"Value stored to 'desktop' during its initialization is never read"
5. types/tablet_v2/wlr_tablet_v2_pad.c@475
"Dereference of null pointer"
"Access to field 'strips' results in a dereference of a null pointer
(loaded from field 'current_client')"
The boolean logic was incorrect (c.f. the check in the following
function).
6. examples/idle.c@163,174,182
"Uninitialized argument value"
"1st function call argument is an uninitialized value"
If close_timeout != 0, but simulate_activity_timeout >= close_timeout,
the program would segfault at pthread_cancel(t1).
The major device number does not indicate the device type on FreeBSD,
and AFAIK the only way to differentiate between DRM, input, and other
devices is checking the fd path. This commit implements that.
The drmDropmaster and drmSetmaster calls are necessary, because the
implicit drop (that should occur when the DRM fd is closed) seems not
to be working in some scenarios (e.g. if you have a tmux session
running - maybe the fd is retained somehow by tmux?). This is a
problem, because once you exit the compositor, you can't start it (or
any other program that wants to be DRM master) again until you close
all your tmux sessions.
On some systems (most notably laptops with two GPUs) there are GPUs that
don't have attached outputs. However, we still want to load those GPUs
because they could still be used by the compositor for rendering.
All screens on secondary GPU in multiple GPU configurations
was flipped 180.
The flipped screens was always on secondary card (the primary card
was always correct).
Tested on nouveau with:
WLR_DRM_DEVICES=/dev/dri/card1:/dev/dri/card2
WLR_DRM_DEVICES=/dev/dri/card2:/dev/dri/card1
The commit is fixing this problem. Now all screens are "normal".
backend_get_renderer() is now returning the renderer of the primary GPU, instead
of its own renderer, since that's the thing which actually does all of the "real"
rendering
wlr_multi_backend_add() is now adding all subbackends (otherwise only one GPU
is handled).
credits: @ascent12
The previous naming was based on the input-device capability names from
libinput.
With code that uses the libinput_tablet_tool and mapping into tablet-v2,
this is confusing, so the name is changed to follow the names used in
the protocol.
This adds the management code to manage tablet tools lifetimes from
libinput.
It follows the suggestion made in the tablet-unstable-v2.xml to destroy
tablet_tools once all tablets that it got into contact with were removed
from the system. This is implemented via a refcount.
If a tool is *not* unique, it will be destroyed on proximity out. This
is libinput specific and mentioned in libinput docs that tools will not
be found again, so we shouldn't keep a reference to them.
Also they can't be on other tablets as well, because they cannot be
tracked.
The naming in this commit is a bit off (to not break things).
The wlr names stay the same, tablet_tool is the libinput_device with
capaiblity LIBINPUT_DEVICE_CAP_TABLET_TOOL which is more akin to
"tablet" in the tablet-unstable-v2 protocol.
The struct that corresponds to the tablet_tool in tablet-unstable-v2 is
called tablet_tool_tool, a rename should be done at some point in the
future.
Otherwise running under Xvfb will not deliver any events. This results
in e.g. weston-info reporting a 0x0 window size (which results in all
sorts of problems).
We cannot handle just one of the two being NULL later down the road
(e.g. divide by zero in matrix projection code),
just ignore any such configure request.
Found through static analysis
The test was done after dereferencing output in pointer_handle_enter,
just move it up one line.
No reason pointer_handle_leave would not need the check if enter needs
it, add it there.
Found through static analysis.
These operations are done in 32-bit arithmetics before being casted to 64-bit,
thus can overflow before the cast.
Casting early fixes the issue.
Found through static analysis
recvmsg(3) returns 0 if the connection partner has shut down its socket.
The communicate function considered 0 a successful message, though, and
keeps calling recvmsg(3) again and again.
Compositors now have more control over how the backend creates its
renderer. Currently all backends create an EGL/GLES2 renderer, so
the necessary attributes for creating the context are passed to a
user-provided callback function. It is responsible for initializing
provided wlr_egl and to return a renderer. On fail, return 0.
Fixes#987
Updates the projection matrix for the cursor plane in the DRM backend,
when the cursor is set, so new cursor are uploaded with the correct
transformation.
This changes the `wlr_output_impl.set_cursor` function to take a
`wlr_texture` instead of a byte buffer. This simplifies the
DRM and Wayland backends since they were creating textures from
the byte buffer anyway.
With this commit, performance should be improved when moving the
cursor since outputs don't need to be re-rendered anymore.
When the X11 server sends an expose event, that means that "this
rectangle here (the event contains x,y,width,height) has undefined
contents on your window; please redraw that". This means that we need a
swap. However, so far the code does not actually enforce that a swap
happens.
For example, start rootston, switch to another workspace and then switch
back. The rootston window will not be redrawn (before commit
52b058c2a3, it would just be fully white; after that commit it will
show whatever was visible on the old workspace). This is because the
drawing code concludes that nothing needs to be done. However, in fact a
swap is necessary.
This reverts commit e79d924588, because its optimisation is already
done now: wlr_output_update_needs_swap() emits a signal, which is
handled by wlr_output_damage with a call to wlr_output_schedule_frame().
This function does nothing if a frame is already pending. Thus, the
optimisation from commit e79d924588 now happens implicitly.
Signed-off-by: Uli Schlachter <psychon@znc.in>
When resizing rootston with the mouse, the result is really slow. One
can see that rootston needs quite a while for drawing the newly visible
area. This is because every single expose event is handled on its own
and causes (apparently) a full repaint or at least a swap.
This commit improves things by only causing a new frame if none is
pending already.
With this change, there is almost no delay in rootston drawing the newly
visible area.
Signed-off-by: Uli Schlachter <psychon@znc.in>
Before this commit, the x11 server would fill any exposed area with
white before the wlroots x11 backend got a chance to do anything. This
was e.g. visible when running rootston and resizing the window: When the
window becomes larger, the new area is filled with black.
By just not setting a back pixel value, this commit gets rid of this
behaviour.
Signed-off-by: Uli Schlachter <psychon@znc.in>
handle_x11_event() and x11_handle_input_event() react to different kinds
of events, so it does not make much of a difference if
x11_handle_input_event() signals if it handled an event or not.
Signed-off-by: Uli Schlachter <psychon@znc.in>
The xcb_connection_t instance that is used here comes from
XGetXCBConnection(), is created by XOpenDisplay(), and is owned by the
returned Display*. Calling xcb_disconnect() directly on it leads to
various use-after-frees during shutdown, as reported by valgrind. The
first one of the about 30 errors is:
Invalid read of size 4
at 0x71F2051: xcb_take_socket (in /usr/lib64/libxcb.so.1.1.0)
by 0x78551DD: ??? (in /usr/lib64/libX11.so.6.3.0)
by 0x7855A14: _XFlush (in /usr/lib64/libX11.so.6.3.0)
by 0x7858504: _XGetRequest (in /usr/lib64/libX11.so.6.3.0)
by 0x7838966: XFreeGC (in /usr/lib64/libX11.so.6.3.0)
by 0x783238B: XCloseDisplay (in /usr/lib64/libX11.so.6.3.0)
by 0x4E680C2: wlr_x11_backend_destroy (backend.c:333)
by 0x4E57E94: wlr_backend_destroy (backend.c:39)
by 0x4E629FB: multi_backend_destroy (backend.c:47)
by 0x4E62B5A: handle_display_destroy (backend.c:90)
by 0x50B7E9F: ??? (in /usr/lib64/libwayland-server.so.0.1.0)
by 0x50B8476: wl_display_destroy (in /usr/lib64/libwayland-server.so.0.1.0)
Address 0xc14dda0 is 0 bytes inside a block of size 21,152 free'd
at 0x4C2DD18: free (vg_replace_malloc.c:530)
by 0x4E680A5: wlr_x11_backend_destroy (backend.c:330)
by 0x4E57E94: wlr_backend_destroy (backend.c:39)
by 0x4E629FB: multi_backend_destroy (backend.c:47)
by 0x4E62B5A: handle_display_destroy (backend.c:90)
by 0x50B7E9F: ??? (in /usr/lib64/libwayland-server.so.0.1.0)
by 0x50B8476: wl_display_destroy (in /usr/lib64/libwayland-server.so.0.1.0)
by 0x40C54E: main (main.c:84)
Block was alloc'd at
at 0x4C2EA1E: calloc (vg_replace_malloc.c:711)
by 0x71F0C60: xcb_connect_to_fd (in /usr/lib64/libxcb.so.1.1.0)
by 0x71F4BD4: xcb_connect_to_display_with_auth_info (in /usr/lib64/libxcb.so.1.1.0)
by 0x7854AA1: _XConnectXCB (in /usr/lib64/libX11.so.6.3.0)
by 0x7845481: XOpenDisplay (in /usr/lib64/libX11.so.6.3.0)
by 0x4E681B6: wlr_x11_backend_create (backend.c:376)
by 0x4E580EE: wlr_backend_autocreate (backend.c:99)
by 0x40C27D: main (main.c:35)
Normally, one would expect this to crash during XCloseDisplay() when
xcb_disconnect() is called again and frees the same data again (glibc would
detect a double free). However, XCloseDisplay() tries to clean up some internal
caches first for which it has to send requests to the X11 server (e.g. the
XFreeGC() above). This fails since the file descriptor was already closed,
which causes an IO error. Xlib's _XDefaultIOError() handles this by printing an
error message and calling exit(1).
Thus, the only symptom of this problem was compositors exiting
mid-shutdown and printing an error message:
XIO: fatal IO error 11 (Resource temporarily unavailable) on X server ":0"
after 6 requests (6 known processed) with 0 events remaining.
Fixes: https://github.com/swaywm/wlroots/issues/745
Signed-off-by: Uli Schlachter <psychon@znc.in>
- Textures are now immutable (apart from those created from raw
pixels), no more invalid textures
- Move all wl_drm stuff in wlr_renderer
- Most of wlr_texture fields are now private
- Remove some duplicated DMA-BUF code in the DRM backend
- Add more assertions
- Stride is now always given as bytes rather than pixels
- Drop wl_shm functions
Fun fact: this patch has been written 10,000 meters up in the air.
==12021==ERROR: AddressSanitizer: heap-use-after-free on address 0x617000015698 at pc 0x7f1a9abe1c09 bp 0x7ffe9068f6b0 sp 0x7ffe9068f6a0
WRITE of size 4 at 0x617000015698 thread T0
#0 0x7f1a9abe1c08 in pointer_handle_leave ../backend/wayland/wl_seat.c:40
#1 0x7f1a96ae7d1d in ffi_call_unix64 (/lib64/libffi.so.6+0x5d1d)
#2 0x7f1a96ae768e in ffi_call (/lib64/libffi.so.6+0x568e)
#3 0x7f1a988e0d8a (/lib64/libwayland-client.so.0+0x8d8a)
#4 0x7f1a988dd927 (/lib64/libwayland-client.so.0+0x5927)
#5 0x7f1a988debe3 in wl_display_dispatch_queue_pending (/lib64/libwayland-client.so.0+0x6be3)
#6 0x7f1a9abdd6d6 in dispatch_events ../backend/wayland/backend.c:28
#7 0x7f1a9a968c11 in wl_event_loop_dispatch (/lib64/libwayland-server.so.0+0x9c11)
#8 0x7f1a9a967449 in wl_display_run (/lib64/libwayland-server.so.0+0x8449)
#9 0x418dff in main ../rootston/main.c:81
#10 0x7f1a99b5ef29 in __libc_start_main (/lib64/libc.so.6+0x20f29)
#11 0x4057c9 in _start (/home/shared/wayland/wlroots/build/rootston/rootston+0x4057c9)
0x617000015698 is located 664 bytes inside of 696-byte region [0x617000015400,0x6170000156b8)
freed by thread T0 here:
#0 0x7f1a9af754b8 in __interceptor_free (/lib64/libasan.so.4+0xde4b8)
#1 0x7f1a9abe01ee in wlr_wl_output_destroy ../backend/wayland/output.c:194
#2 0x7f1a9ac12918 in wlr_output_destroy ../types/wlr_output.c:299
#3 0x7f1a9abe061b in xdg_toplevel_handle_close ../backend/wayland/output.c:255
#4 0x7f1a96ae7d1d in ffi_call_unix64 (/lib64/libffi.so.6+0x5d1d)
#5 0x7f1a96ae768e in ffi_call (/lib64/libffi.so.6+0x568e)
#6 0x7f1a988e0d8a (/lib64/libwayland-client.so.0+0x8d8a)
#7 0x7f1a988dd927 (/lib64/libwayland-client.so.0+0x5927)
#8 0x7f1a988debe3 in wl_display_dispatch_queue_pending (/lib64/libwayland-client.so.0+0x6be3)
#9 0x7f1a9abdd6d6 in dispatch_events ../backend/wayland/backend.c:28
#10 0x7f1a9a968c11 in wl_event_loop_dispatch (/lib64/libwayland-server.so.0+0x9c11)
#11 0x7f1a9a967449 in wl_display_run (/lib64/libwayland-server.so.0+0x8449)
#12 0x418dff in main ../rootston/main.c:81
#13 0x7f1a99b5ef29 in __libc_start_main (/lib64/libc.so.6+0x20f29)
#14 0x4057c9 in _start (/home/shared/wayland/wlroots/build/rootston/rootston+0x4057c9)
previously allocated by thread T0 here:
#0 0x7f1a9af75a38 in __interceptor_calloc (/lib64/libasan.so.4+0xdea38)
#1 0x7f1a9abe0703 in wlr_wl_output_create ../backend/wayland/output.c:272
#2 0x7f1a9abdd8eb in wlr_wl_backend_start ../backend/wayland/backend.c:55
#3 0x7f1a9abbeb49 in wlr_backend_start ../backend/backend.c:28
#4 0x7f1a9abd8ce1 in multi_backend_start ../backend/multi/backend.c:24
#5 0x7f1a9abbeb49 in wlr_backend_start ../backend/backend.c:28
#6 0x418c32 in main ../rootston/main.c:58
#7 0x7f1a99b5ef29 in __libc_start_main (/lib64/libc.so.6+0x20f29)
#8 0x4057c9 in _start (/home/shared/wayland/wlroots/build/rootston/rootston+0x4057c9)
The current mode was set to NULL to abuse it as state variable
persisting DRM suspend/resume, this results resulted in a segfault on
normal DPMS cycle.
This reverts that change and uses the wlr_output enabled variable, which
also persists and makes more sense.
Legacy gamma lut size now uses the new legacy_crtc member of
wlr_drm_crtc. This was Previously doen using old_crtc in
wlr_drm_connector, but since this refers to the crtc that was connected to
the ouput, this could give the wrong result.
On the drm output the wlr_drm_connector structs are reused.
This struct contains the wlr_output struct, which is reused as well.
The old code kept modes/edid and output state persistent over hotplug.
This nulls the relevant strings, reads newer edid data and removes old
modes on unplug.
The backend destroy signal is emitted before the output_remove
signal is. When the destroy signal is emitted listeners remove
their output_remove listener, so the output_remove signal is never
received and listeners have an invalid output pointer.
The correct way to solve this would be to remove the output_remove
signal completely and use the wlr_output.events.destroy signal
instead. This isn't yet possible because wl_signal_emit is unsafe
and listeners cannot be removed in listeners.
The wlr_drm_surface_init function is called (upon others) when the drm
mode is changed.
When the surface was used previously this replaced the gbm_surface, but
did not replace the gbm buffers (front/back).
With this, wlr_drm_surface_get_from never set up the new buffers with
the new glViewport because surf->front existed.
This frees the buffers to get new buffers on the new surface with the
new viewport.
Right now, we are adding systemd and elogind backends to the build
system as soon as their libraries are found on the build system.
Instead, we should only add them if the libraries have been found _and_
the user has actually requested them to be included.
since we're looking at pointer differences.
Otherwise the build fails on arm like
In file included from ../backend/drm/drm.c:19:0:
../include/wlr/util/log.h:34:17: error: format '%jd' expects argument of type 'intmax_t', but argument 7 has type 'int' [-Werror=format=]
_wlr_log(verb, "[%s:%d] " fmt, _strip_path(__FILE__), __LINE__, ##__VA_ARGS__)
^
../backend/drm/drm.c:462:2: note: in expansion of macro 'wlr_log'
wlr_log(L_DEBUG, "%s: crtc=%ju ovr=%jd pri=%jd cur=%jd", conn->output.name,
^~~~~~~
../backend/drm/drm.c:462:39: note: format string is defined here
wlr_log(L_DEBUG, "%s: crtc=%ju ovr=%jd pri=%jd cur=%jd", conn->output.name,
~~^
%d