diff --git a/backend/drm/atomic.c b/backend/drm/atomic.c index be6cfa3e..cf536746 100644 --- a/backend/drm/atomic.c +++ b/backend/drm/atomic.c @@ -196,6 +196,14 @@ static bool atomic_crtc_commit(struct wlr_drm_backend *drm, } } + bool prev_vrr_enabled = + output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED; + bool vrr_enabled = prev_vrr_enabled; + if ((output->pending.committed & WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED) && + drm_connector_supports_vrr(conn)) { + vrr_enabled = output->pending.adaptive_sync_enabled; + } + if (crtc->pending_modeset) { flags |= DRM_MODE_ATOMIC_ALLOW_MODESET; } else { @@ -217,6 +225,9 @@ static bool atomic_crtc_commit(struct wlr_drm_backend *drm, if (crtc->props.gamma_lut != 0) { atomic_add(&atom, crtc->id, crtc->props.gamma_lut, gamma_lut); } + if (crtc->props.vrr_enabled != 0) { + atomic_add(&atom, crtc->id, crtc->props.vrr_enabled, vrr_enabled); + } set_plane_props(&atom, drm, crtc->primary, crtc->id, 0, 0); if (crtc->cursor) { if (drm_connector_is_cursor_visible(conn)) { @@ -239,6 +250,14 @@ static bool atomic_crtc_commit(struct wlr_drm_backend *drm, if (ok && !(flags & DRM_MODE_ATOMIC_TEST_ONLY)) { commit_blob(drm, &crtc->mode_id, mode_id); commit_blob(drm, &crtc->gamma_lut, gamma_lut); + + if (vrr_enabled != prev_vrr_enabled) { + output->adaptive_sync_status = vrr_enabled ? + WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED : + WLR_OUTPUT_ADAPTIVE_SYNC_DISABLED; + wlr_log(WLR_DEBUG, "VRR %s on connector '%s'", + vrr_enabled ? "enabled" : "disabled", output->name); + } } else { rollback_blob(drm, &crtc->mode_id, mode_id); rollback_blob(drm, &crtc->gamma_lut, gamma_lut); diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 0680aeee..1d60bbfb 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -502,14 +502,13 @@ static bool drm_connector_commit_buffer(struct wlr_output *output) { return true; } -static void drm_connector_enable_adaptive_sync(struct wlr_output *output, - bool enabled) { - struct wlr_drm_connector *conn = get_drm_connector_from_output(output); - struct wlr_drm_backend *drm = get_drm_backend_from_backend(output->backend); +bool drm_connector_supports_vrr(struct wlr_drm_connector *conn) { + struct wlr_drm_backend *drm = + get_drm_backend_from_backend(conn->output.backend); struct wlr_drm_crtc *crtc = conn->crtc; if (!crtc) { - return; + return false; } uint64_t vrr_capable; @@ -517,26 +516,17 @@ static void drm_connector_enable_adaptive_sync(struct wlr_output *output, !get_drm_prop(drm->fd, conn->id, conn->props.vrr_capable, &vrr_capable) || !vrr_capable) { wlr_log(WLR_DEBUG, "Failed to enable adaptive sync: " - "connector '%s' doesn't support VRR", output->name); - return; + "connector '%s' doesn't support VRR", conn->output.name); + return false; } if (crtc->props.vrr_enabled == 0) { wlr_log(WLR_DEBUG, "Failed to enable adaptive sync: " "CRTC %"PRIu32" doesn't support VRR", crtc->id); - return; + return false; } - if (drmModeObjectSetProperty(drm->fd, crtc->id, DRM_MODE_OBJECT_CRTC, - crtc->props.vrr_enabled, enabled) != 0) { - wlr_log_errno(WLR_ERROR, "drmModeObjectSetProperty(VRR_ENABLED) failed"); - return; - } - - output->adaptive_sync_status = enabled ? WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED : - WLR_OUTPUT_ADAPTIVE_SYNC_DISABLED; - wlr_log(WLR_DEBUG, "VRR %s on connector '%s'", - enabled ? "enabled" : "disabled", output->name); + return true; } static bool drm_connector_commit(struct wlr_output *output) { @@ -574,11 +564,6 @@ static bool drm_connector_commit(struct wlr_output *output) { } } - if (output->pending.committed & WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED) { - drm_connector_enable_adaptive_sync(output, - output->pending.adaptive_sync_enabled); - } - // TODO: support modesetting with a buffer if (output->pending.committed & WLR_OUTPUT_STATE_BUFFER && !(output->pending.committed & WLR_OUTPUT_STATE_MODE)) { diff --git a/backend/drm/legacy.c b/backend/drm/legacy.c index 6acb87d4..98397c2d 100644 --- a/backend/drm/legacy.c +++ b/backend/drm/legacy.c @@ -62,6 +62,23 @@ static bool legacy_crtc_commit(struct wlr_drm_backend *drm, } } + if ((output->pending.committed & WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED) && + drm_connector_supports_vrr(conn)) { + if (drmModeObjectSetProperty(drm->fd, crtc->id, DRM_MODE_OBJECT_CRTC, + crtc->props.vrr_enabled, + output->pending.adaptive_sync_enabled) != 0) { + wlr_log_errno(WLR_ERROR, + "drmModeObjectSetProperty(VRR_ENABLED) failed"); + return false; + } + output->adaptive_sync_status = output->pending.adaptive_sync_enabled ? + WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED : + WLR_OUTPUT_ADAPTIVE_SYNC_DISABLED; + wlr_log(WLR_DEBUG, "VRR %s on connector '%s'", + output->pending.adaptive_sync_enabled ? "enabled" : "disabled", + output->name); + } + if (cursor != NULL && drm_connector_is_cursor_visible(conn)) { struct wlr_drm_fb *cursor_fb = plane_get_next_fb(cursor); struct gbm_bo *cursor_bo = diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index 83fb6293..c5685079 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -153,6 +153,7 @@ int handle_drm_event(int fd, uint32_t mask, void *data); bool drm_connector_set_mode(struct wlr_drm_connector *conn, struct wlr_output_mode *mode); bool drm_connector_is_cursor_visible(struct wlr_drm_connector *conn); +bool drm_connector_supports_vrr(struct wlr_drm_connector *conn); size_t drm_crtc_get_gamma_lut_size(struct wlr_drm_backend *drm, struct wlr_drm_crtc *crtc);