diff --git a/DOCS/man/vo.rst b/DOCS/man/vo.rst index 6207c7e9cb..290cc3ad96 100644 --- a/DOCS/man/vo.rst +++ b/DOCS/man/vo.rst @@ -647,6 +647,18 @@ Available video output drivers are: Note: this option is only available with DRM atomic support. (default: display resolution) + ``--drm-vrr-enabled=`` + Toggle use of Variable Refresh Rate (VRR), aka Freesync or Adapative Sync + on compatible systems. VRR allows for the display to be refreshed at any + rate within a range (usually ~40Hz-60Hz for 60Hz displays). This can help + with playback of 24/25/50fps content. Support depends on the use of a + compatible monitor, GPU, and a sufficiently new kernel with drivers + that support the feature. + + :no: Do not attempt to enable VRR. (default) + :yes: Attempt to enable VRR, whether the capability is reported or not. + :auto: Attempt to enable VRR if support is reported. + ``mediacodec_embed`` (Android) Renders ``IMGFMT_MEDIACODEC`` frames directly to an ``android.view.Surface``. Requires ``--hwdec=mediacodec`` for hardware decoding, along with diff --git a/video/out/drm_atomic.c b/video/out/drm_atomic.c index bf7012c155..e615d2f9c7 100644 --- a/video/out/drm_atomic.c +++ b/video/out/drm_atomic.c @@ -389,6 +389,9 @@ bool drm_atomic_save_old_state(struct drm_atomic_context *ctx) if (0 > drm_object_get_property(ctx->crtc, "ACTIVE", &ctx->old_state.crtc.active)) ret = false; + // This property was added in kernel 5.0. We will just ignore any errors. + drm_object_get_property(ctx->crtc, "VRR_ENABLED", &ctx->old_state.crtc.vrr_enabled); + if (0 > drm_object_get_property(ctx->connector, "CRTC_ID", &ctx->old_state.connector.crtc_id)) ret = false; @@ -412,6 +415,9 @@ bool drm_atomic_restore_old_state(drmModeAtomicReqPtr request, struct drm_atomic if (0 > drm_object_set_property(request, ctx->connector, "CRTC_ID", ctx->old_state.connector.crtc_id)) ret = false; + // This property was added in kernel 5.0. We will just ignore any errors. + drm_object_set_property(request, ctx->crtc, "VRR_ENABLED", ctx->old_state.crtc.vrr_enabled); + if (!drm_mode_ensure_blob(ctx->fd, &ctx->old_state.crtc.mode)) ret = false; if (0 > drm_object_set_property(request, ctx->crtc, "MODE_ID", ctx->old_state.crtc.mode.blob_id)) diff --git a/video/out/drm_atomic.h b/video/out/drm_atomic.h index 5b2dc5976d..32e56c7f97 100644 --- a/video/out/drm_atomic.h +++ b/video/out/drm_atomic.h @@ -56,6 +56,7 @@ struct drm_atomic_state { struct { struct drm_mode mode; uint64_t active; + uint64_t vrr_enabled; } crtc; struct drm_atomic_plane_state draw_plane; struct drm_atomic_plane_state drmprime_video_plane; diff --git a/video/out/drm_common.c b/video/out/drm_common.c index aa86b7750b..dad9aaf2fb 100644 --- a/video/out/drm_common.c +++ b/video/out/drm_common.c @@ -98,6 +98,8 @@ const struct m_sub_options drm_conf = { {"drm-osd-plane-id", OPT_REPLACED("drm-draw-plane")}, {"drm-video-plane-id", OPT_REPLACED("drm-drmprime-video-plane")}, {"drm-osd-size", OPT_REPLACED("drm-draw-surface-size")}, + {"drm-vrr-enabled", OPT_CHOICE(drm_vrr_enabled, + {"no", 0}, {"yes", 1}, {"auto", -1})}, {0}, }, .defaults = &(const struct drm_opts) { @@ -105,6 +107,7 @@ const struct m_sub_options drm_conf = { .drm_atomic = 1, .drm_draw_plane = DRM_OPTS_PRIMARY_PLANE, .drm_drmprime_video_plane = DRM_OPTS_OVERLAY_PLANE, + .drm_vrr_enabled = 0, }, .size = sizeof(struct drm_opts), }; diff --git a/video/out/drm_common.h b/video/out/drm_common.h index d8a550e4f1..5d884e3c80 100644 --- a/video/out/drm_common.h +++ b/video/out/drm_common.h @@ -57,6 +57,7 @@ struct drm_opts { int drm_drmprime_video_plane; int drm_format; struct m_geometry drm_draw_surface_size; + int drm_vrr_enabled; }; struct drm_vsync_tuple { diff --git a/video/out/opengl/context_drm_egl.c b/video/out/opengl/context_drm_egl.c index a7f99cfd0d..b571ca7057 100644 --- a/video/out/opengl/context_drm_egl.c +++ b/video/out/opengl/context_drm_egl.c @@ -372,6 +372,24 @@ static bool crtc_setup_atomic(struct ra_ctx *ctx) goto err; } + /* + * VRR related properties were added in kernel 5.0. We will not fail if we + * cannot query or set the value, but we will log as appropriate. + */ + uint64_t vrr_capable = 0; + drm_object_get_property(atomic_ctx->connector, "VRR_CAPABLE", &vrr_capable); + MP_VERBOSE(ctx->vo, "crtc is%s VRR capable\n", vrr_capable ? "" : " not"); + + uint64_t vrr_requested = ctx->vo->opts->drm_opts->drm_vrr_enabled; + if (vrr_requested == 1 || (vrr_capable && vrr_requested == -1)) { + if (drm_object_set_property(request, atomic_ctx->crtc, "VRR_ENABLED", 1) < 0) { + MP_WARN(ctx->vo, "Could not enable VRR on crtc\n"); + } else { + MP_VERBOSE(ctx->vo, "Enabled VRR on crtc\n"); + } + } + + drm_object_set_property(request, atomic_ctx->draw_plane, "FB_ID", p->fb->id); drm_object_set_property(request, atomic_ctx->draw_plane, "CRTC_ID", p->kms->crtc_id); drm_object_set_property(request, atomic_ctx->draw_plane, "SRC_X", 0);