This commit makes more output properties (mode, enabled, scale and transform)
atomic. This means that they are double-buffered and only applied on commit.
Compositors now need to call wlr_output_commit after setting any of those
properties.
Internally, backends still apply properties sequentially. The behaviour should
be exactly the same as before. Future commits will update some backends to take
advantage of the atomic interface. Some backends are non-atomic by design, e.g.
the X11 backend or the legacy DRM backend.
Updates: https://github.com/swaywm/wlroots/issues/1640
The documentation for wayland-server.h says:
> Use of this header file is discouraged. Prefer including
> wayland-server-core.h instead, which does not include the server protocol
> header and as such only defines the library PI, excluding the deprecated API
> below.
Replacing wayland-server.h with wayland-server-core.h allows us to drop the
WL_HIDE_DEPRECATED declaration.
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 backend doesn't need to handle transform changes, since everything is done
in software. In fact, all of the implementations were all identical and just
set the transform.
We could add support for hardware transforms, but:
- This would require a different field (something like hardware_transform)
- Not all combinations are possible because there often are hardware
limitations
- The Wayland protocol isn't ready for this (in particular xdg-output, see [1])
This belongs to a different patch series anyway.
[1]: https://patchwork.freedesktop.org/series/52324/
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
This updates the backend part of the output API. This is mostly renaming:
make_current becomes attach_render and swap_buffers becomes commit.
This also fixes the RDP backend to support NULL damage.
The deleted includes are redundant, because other headers will include
the necessary files. Additionally, they cause build failures, because
including EGL/egl.h or EGL/eglext.h directly, instead of through
wlr/render/egl.h or wlr/render/interface.h, will mean that
MESA_EGL_NO_X11_HEADERS will not have been defined, and so the EGL
headers will attempt to pull in unnecessary X11 headers that may not
exist on the system.
For the headers produced by glgen.sh, the includes couldn't simply be
deleted, because no other header would include the EGL headers. Neither
wlr/render/egl.h or wlr/render/interface.h felt appropriate to include,
so I opted instead to copy the MESA_EGL_NO_X11_HEADERS definition before
the EGL includes.
* wlr_output: Indicate modes link
* wlr_output: Introduce preferred flag
This indicates an outputs preferred mode.
* drm: Set preferred flag for an outputs preferred mode
If *changed_outputs is not supplied by the calling function, track the local
allocation with a bool variable and free the allocation at the end of the
function.
On DRM resume, such as switching back to a TTY, the output needs to be
modeset to the current mode. However, wlr_output_set_mode will return
early when attempting to set the mode to the current mode. This just
steps around wlr_output_set_mode and calls drm_connector_set_mode
directly.
There is no point in modesetting an output to a mode that it is already
set to. Modesetting will cause the output to briefly flicker which is
undesirable for a noop. This returns early in `drm_connector_set_mode`
when attempting to modeset to the current mode.
In order for a surface to be used as a cursor plane framebuffer, it
appears that requiring the buffer to be linear is sufficient.
GBM_BO_USE_SCANOUT is added in case GBM_BO_USE_LINEAR isn't sufficient
on untested hardware.
Fixes#1323
Removed wlr_drm_plane.cursor_bo as it does not serve any purpose
anymore.
Relevant analysis (taken from the PR description):
While trying to implement a fix for #1323, I found that when exporting
the rendered surface into a DMA-BUF and reimporting it with
`GBM_BO_USE_CURSOR`, the resulting object does not appear to be valid.
After some digging (turning on drm-kms debugging and switching to legacy
mode), I managed to extract the following error: ```
[drm:__setplane_check.isra.1 [drm]] Invalid pixel format AR24
little-endian (0x34325241), modifier 0x100000000000001 ``` The format
itself refers to ARGB8888 which is the same format as
`renderer->gbm_format` used in master to create the cursor bo. However,
using `gbm_bo_create` with `GBM_BO_USE_CURSOR` results in a modifier of
0. A modifier of zero represents a linear buffer while the modifier of
the surface that is rendered to is `I915_FORMAT_MOD_X_TILED` (see
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/include/uapi/drm/drm_fourcc.h?h=v4.20.6#n263).
In order to fix this mismatch in modifier, I added the
`GBM_BO_USE_LINEAR` to the render surface and everything started to work
just fine. I wondered however, whether the export and import is really
necessary. I then decided to test if the back buffer of the render
surface works as well, and at least on my hardware (Intel HD 530 and
Intel UHD 620) it does. This is the patch in this PR and this requires
no exporting and importing.
I have to note that I cheated in order to import DMA_BUFs into a cursor
bo when doing the first tests, since on import the Intel drivers check
that the cursor is 64x64. This is strange since cursor sizes other than
64x64 have been around for quite some time now
(https://lists.freedesktop.org/archives/mesa-commit/2014-June/050268.html).
Removing this check made everything work fine. I later (while writing
this PR) found out that `__DRI_IMAGE_USE_CURSOR` (to which
`GBM_BO_USE_CURSOR` translates) has been deprecated in mesa
(https://gitlab.freedesktop.org/mesa/mesa/blob/master/include/GL/internal/dri_interface.h#L1296),
which makes me wonder what the usecase of `GBM_BO_USE_CURSOR` is. The
reason we never encountered this is that when specifying
`GBM_BO_USE_WRITE`, a dumb buffer is created trough DRM and the usage
flag never reaches the Intel driver directly. The relevant code is in
https://gitlab.freedesktop.org/mesa/mesa/blob/master/src/gbm/backends/dri/gbm_dri.c#L1011-1089
. From this it seems that as long as the size, format and modifiers are
right, any surface can be used as a cursor.
We create the EGL config with GBM_FORMAT_ARGB8888, but then initialize GBM BOs
with GBM_FORMAT_XRGB8888. This mismatch confuses Mesa.
Instead, we can always use GBM_FORMAT_ARGB8888, and use DRM_FORMAT_XRGB8888
when calling drmModeAddFB2.
Fixes https://github.com/swaywm/wlroots/issues/1438
When there aren't enough CRTCs for all outputs, we try to move a CRTC from a
disabled output to an enabled one. When this happens, the old output's state
wasn't changed, so the compositor thought it was still enabled and rendering.
This commit marks the old output as WLR_DRM_CONN_NEEDS_MODESET and sets its
current mode to NULL.
Values from libdrm are likely more reliable than raw values from the EDID. We
were already using values from libdrm, but they were overwritten by parse_edid.
See drm.c:
wlr_conn->output.phys_width = drm_conn->mmWidth;
wlr_conn->output.phys_height = drm_conn->mmHeight;
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).
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