drm: context_drm_egl: add support for enabling VRR

Variable Refresh Rate (VRR), aka Freesync or Adaptive Sync can be used
with DRM by setting the VRR_ENABLED property on a crtc if the
connector reports that it is VRR_CAPABLE. This is a useful feature
for us as it is common to play 24/25/50 fps content on displays that
are nominally locked to 60Hz. VRR can allow this content to play at
native framerates.

This is a simple change as we just need to check the capability
and set the enabled property if requested by the user. I've defaulted
it to disabled for now, but it might make sense to default to auto
in the long term.
This commit is contained in:
Philip Langdale 2022-04-03 20:08:33 -07:00 committed by Philip Langdale
parent f61eda0f5e
commit 73a06ffae6
6 changed files with 41 additions and 0 deletions

View File

@ -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=<no|yes|auto>``
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

View File

@ -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))

View File

@ -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;

View File

@ -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),
};

View File

@ -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 {

View File

@ -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);