wlr_renderer and wlr_allocator will print out errors as they go, and end
with a final error if they fail to create anything. The caller of this
function will also log when it fails.
Skip the redundant errors emitted here.
We create a renderer for the sole purpose of blitting buffers from a
primary renderer that we might not be able to scan-out from. If we end
up with the pixman renderer, it either won't work becuase it cannot
import dmabufs from the primary renderer, or won't have any effect
because the primary renderer already uses dumb buffers.
We test for DMA-BUF capabilities specifically to make it clear what our
interest is, rather than focusing too much on the pixman renderer.
If init_drm_renderer failed, it would destroy the renderer but would not
set it to NULL, leading to use-after-free.
NULL the renderer after destroying it.
Since we only use the backend capabilities here we can simply pass
them in directly. This allows other locations to create an allocator
even if they don't have a backend. They can simply specify the caps
they want instead.
RMFB implicitly performs a modeset to turn off any CRTC which is
using the FB. This prevents seamless transitions between two DRM
masters from working.
Use the new CLOSEFB IOCTL which doesn't turn off anything and leave
it up to the compositor to turn off outputs on shutdown if it wants
to.
Based on five calls:
wlr_render_timer_create - creates a timer which can be reused across
frames on the same renderer
wlr_renderer_begin_buffer_pass - now takes a timer so that backends can
record when the rendering starts and finishes
wlr_render_timer_get_time - should be called as late as possible so that
queries can make their way back from the GPU
wlr_render_timer_destroy - self-explanatory
The timer is exposed as an opaque `struct wlr_render_timer` so that
backends can store whatever they want in there.
Commit 90d08f8f1c changed the way
wlr_drm_format_intersect worked, including passing in a destination
format list. This breaks scenarios where the intersection doesn't
find any matching formats, since we still have a valid destination
format set. This changes it to only return true if more than one
matching format is present in the intersection list.
We've had this struct for a while. It'd be useful for compositors
if they want to manage the swap chains themselves instead of being
forced to use wlr_output's. Some compositors might also want to use
a swapchain without an output.
Instead of having a pending_fb field on the struct wlr_drm_plane,
move it to struct wlr_drm_connector_state. That way, there's no
risk having a stale pending FB around: the state doesn't survive
across tests and commits.
The cursor is a special case because it's disconnected from the
atomic state: the wlr_backend_impl.set_cursor hook sets the cursor
for the next commit. Move the field to
wlr_drm_connector.cursor_pending_fb.
drmModeAddFB2 doesn't support explicit modifiers. Only accept INVALID
which indicates an implicit modifier and LINEAR which may indicate
that GBM_BO_USE_LINEAR has been used.
They are never used in practice, which makes all of our flag
handling effectively dead code. Also, APIs such as KMS don't
provide a good way to deal with the flags. Let's just fail the
DMA-BUF import when clients provide flags.
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
drmModeAddFB2 doesn't support explicit modifiers. Only accept INVALID
which indicates an implicit modifier and LINEAR which may indicate
that GBM_BO_USE_LINEAR has been used.
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.
drm_surface_make_current and drm_surface_unset_current set implicit
state and are an unnecessary mid-layer. Prefer to use directly
wlr_renderer_begin_with_buffer, which automatically unsets the back
buffer on wlr_renderer_end.
I'd like to get rid of drm_surface_make_current once we stop using
it for the primary swapchain.
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.
On multi-GPU setups, there is a primary DRM backend and secondary
DRM backends. wlr_backend_get_drm_fd will always return the parent
DRM FD even on secondary backends, so that users always use the
primary device for rendering.
However, for our internal rendering we want to use the secondary
device. Use allocator_autocreate_with_drm_fd to make sure the
allocator will create buffers on the secondary device.
We do something similar to ensure our internal rendering will
happen on the secondary device with renderer_autocreate_with_drm_fd.
Fixes: cc1b66364c ("backend: use wlr_allocator_autocreate")
This function is only required because the DRM backend still needs
to perform multi-GPU magic under-the-hood. Remove the wlr_ prefix
to make it clear it's not a candidate for being made public.