mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-11-25 22:25:58 +01:00
backend/drm: Add async page flip support to legacy
Atomic doesn't support such flags yet.
This commit is contained in:
parent
5dec1c8bcb
commit
c2aa7fd965
5 changed files with 30 additions and 2 deletions
|
@ -106,6 +106,10 @@ bool check_drm_features(struct wlr_drm_backend *drm) {
|
||||||
drm->iface = &atomic_iface;
|
drm->iface = &atomic_iface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (drm->iface == &legacy_iface) {
|
||||||
|
drm->supports_tearing_page_flips = drmGetCap(drm->fd, DRM_CAP_ASYNC_PAGE_FLIP, &cap) == 0 && cap == 1;
|
||||||
|
}
|
||||||
|
|
||||||
int ret = drmGetCap(drm->fd, DRM_CAP_TIMESTAMP_MONOTONIC, &cap);
|
int ret = drmGetCap(drm->fd, DRM_CAP_TIMESTAMP_MONOTONIC, &cap);
|
||||||
drm->clock = (ret == 0 && cap == 1) ? CLOCK_MONOTONIC : CLOCK_REALTIME;
|
drm->clock = (ret == 0 && cap == 1) ? CLOCK_MONOTONIC : CLOCK_REALTIME;
|
||||||
|
|
||||||
|
@ -650,6 +654,11 @@ static bool drm_connector_test(struct wlr_output *output,
|
||||||
if (!drm_connector_state_update_primary_fb(conn, &pending)) {
|
if (!drm_connector_state_update_primary_fb(conn, &pending)) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pending.base->tearing_page_flip && !conn->backend->supports_tearing_page_flips) {
|
||||||
|
wlr_log(WLR_ERROR, "Attempted to submit a tearing page flip to an unsupported backend!");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (state->committed & WLR_OUTPUT_STATE_LAYERS) {
|
if (state->committed & WLR_OUTPUT_STATE_LAYERS) {
|
||||||
if (!drm_connector_set_pending_layer_fbs(conn, pending.base)) {
|
if (!drm_connector_set_pending_layer_fbs(conn, pending.base)) {
|
||||||
|
@ -725,7 +734,7 @@ bool drm_connector_commit_state(struct wlr_drm_connector *conn,
|
||||||
// page-flip, either a blocking modeset. When performing a blocking modeset
|
// page-flip, either a blocking modeset. When performing a blocking modeset
|
||||||
// we'll wait for all queued page-flips to complete, so we don't need this
|
// we'll wait for all queued page-flips to complete, so we don't need this
|
||||||
// safeguard.
|
// safeguard.
|
||||||
if (conn->pending_page_flip_crtc && !pending.modeset) {
|
if (conn->pending_page_flip_crtc && !pending.modeset && !pending.base->tearing_page_flip) {
|
||||||
wlr_drm_conn_log(conn, WLR_ERROR, "Failed to page-flip output: "
|
wlr_drm_conn_log(conn, WLR_ERROR, "Failed to page-flip output: "
|
||||||
"a page-flip is already pending");
|
"a page-flip is already pending");
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -748,6 +757,9 @@ bool drm_connector_commit_state(struct wlr_drm_connector *conn,
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t flags = pending.active ? DRM_MODE_PAGE_FLIP_EVENT : 0;
|
uint32_t flags = pending.active ? DRM_MODE_PAGE_FLIP_EVENT : 0;
|
||||||
|
if (pending.base->tearing_page_flip) {
|
||||||
|
flags |= DRM_MODE_PAGE_FLIP_ASYNC;
|
||||||
|
}
|
||||||
|
|
||||||
ok = drm_crtc_commit(conn, &pending, flags, false);
|
ok = drm_crtc_commit(conn, &pending, flags, false);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
|
|
|
@ -175,8 +175,13 @@ static bool legacy_crtc_commit(struct wlr_drm_connector *conn,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & DRM_MODE_PAGE_FLIP_EVENT) {
|
if (flags & DRM_MODE_PAGE_FLIP_EVENT) {
|
||||||
|
uint32_t page_flags = DRM_MODE_PAGE_FLIP_EVENT;
|
||||||
|
if (flags & DRM_MODE_PAGE_FLIP_ASYNC) {
|
||||||
|
page_flags |= DRM_MODE_PAGE_FLIP_ASYNC;
|
||||||
|
}
|
||||||
|
|
||||||
if (drmModePageFlip(drm->fd, crtc->id, fb_id,
|
if (drmModePageFlip(drm->fd, crtc->id, fb_id,
|
||||||
DRM_MODE_PAGE_FLIP_EVENT, drm)) {
|
page_flags, drm)) {
|
||||||
wlr_drm_conn_log_errno(conn, WLR_ERROR, "drmModePageFlip failed");
|
wlr_drm_conn_log_errno(conn, WLR_ERROR, "drmModePageFlip failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,6 +114,8 @@ struct wlr_drm_backend {
|
||||||
uint64_t cursor_width, cursor_height;
|
uint64_t cursor_width, cursor_height;
|
||||||
|
|
||||||
struct wlr_drm_format_set mgpu_formats;
|
struct wlr_drm_format_set mgpu_formats;
|
||||||
|
|
||||||
|
bool supports_tearing_page_flips;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wlr_drm_mode {
|
struct wlr_drm_mode {
|
||||||
|
|
|
@ -89,6 +89,12 @@ struct wlr_output_state {
|
||||||
enum wl_output_subpixel subpixel;
|
enum wl_output_subpixel subpixel;
|
||||||
|
|
||||||
struct wlr_buffer *buffer;
|
struct wlr_buffer *buffer;
|
||||||
|
/* Request a tearing page-flip. When enabled, this may cause the output to
|
||||||
|
* display a part of the previous buffer and a part of the current buffer at
|
||||||
|
* the same time. The backend may reject the commit if a tearing page-flip
|
||||||
|
* cannot be performed, in which case the caller should fall back to a
|
||||||
|
* regular page-flip at the next wlr_output.frame event. */
|
||||||
|
bool tearing_page_flip;
|
||||||
|
|
||||||
enum wlr_output_state_mode_type mode_type;
|
enum wlr_output_state_mode_type mode_type;
|
||||||
struct wlr_output_mode *mode;
|
struct wlr_output_mode *mode;
|
||||||
|
|
|
@ -665,6 +665,9 @@ static bool output_basic_test(struct wlr_output *output,
|
||||||
wlr_log(WLR_DEBUG, "Primary buffer size mismatch");
|
wlr_log(WLR_DEBUG, "Primary buffer size mismatch");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
} else if (state->tearing_page_flip) {
|
||||||
|
wlr_log(WLR_ERROR, "Trying to commit a tearing page flip without a buffer?");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state->committed & WLR_OUTPUT_STATE_RENDER_FORMAT) {
|
if (state->committed & WLR_OUTPUT_STATE_RENDER_FORMAT) {
|
||||||
|
|
Loading…
Reference in a new issue