Previously, we were copying wlr_output_state on the stack and
patching it up to be guaranteed to have a proper drmModeModeInfo
stored in it (and not a custom mode). Also, we had a bunch of
helpers deriving DRM-specific information from the generic
wlr_output_state.
Copying the wlr_output_state worked fine so far, but with output
layers we'll be getting a wl_list in there. An empty wl_list stores
two pointers to itself, copying it on the stack blindly results in
infinite loops in wl_list_for_each.
To fix this, rework our DRM backend to stop copying wlr_output_state,
instead add a new struct wlr_drm_connector_state which holds both
the wlr_output_state and additional DRM-specific information.
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
Historically we haven't allowed direct scan-out for legacy KMS,
because legacy misses the functionality to make sure a buffer can
be scanned out. However with renderer v6 the backend can't figure
out anymore whether the buffer comes from its internal swap-chain,
because the backend doesn't have an internal swap-chain.
The legacy KMS API guarantees that the driver won't reject a buffer
as long as it's been allocated with the same parameters as the
previous one. Let's check this in legacy_crtc_test.
Right now callers of drm_crtc_commit need to check whether the
interface is legacy or atomic before passing the TEST_ONLY flag.
Additionally, the fallbacks for legacy are in-place in the common
code.
Add a test_only arg to the crtc_commit hook. This way, there's no
risk to pass atomic-only flags to the legacy function (add an assert
to ensure this) and all of the legacy-specific logic can be put back
into legacy.c (done in next commit).
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.
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.
Stop using wlr_drm_surface.{width,height} to figure out the size of a
gbm_bo. In the future we'll stop using wlr_drm_plane.surf, so these will
be zero. Instead, rely on gbm_bo_get_{width,height}.
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.
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.
GAMMA_LUT_SIZE isn't an atomic property. It can be used with the legacy
interface too. So we can unify both codepaths and remove
wlr_drm_interface.crtc_get_gamma_size.
It's no guaranteed to exist though, so we still need to keep the
fallback.
This requires functions without a prototype definition to be static.
This allows to detect dead code, export less symbols and put shared
functions in headers.
atomic and legacy now both pass the backend as the user data for the
pageflip event. We than retrieve the correct connector by matching on
the crtc_id passed to the page_flip_handler2.
Wlroots also requires the DRM_CRTC_IN_VBLANK_EVENT capability now.
Fixes#1297
The DRM subsystem needs a NULL modeset for connectors which disappear
from the system to disable the hardware pipes, otherwise the pixels get
rendered but are sent nowhere.
The atomic backend does the equivalent by removing the properties and
issuing a commit.
Fixes#1706
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.