From 1ccc56eff0242123ba448638f4cc534fb69e3024 Mon Sep 17 00:00:00 2001 From: LongChair Date: Sat, 7 Apr 2018 08:56:59 +0200 Subject: drm/atomic: add atomic modesetting. This commit allows to add atomic modesetting when using the atomic renderer. This is actually needed when using and osd with a smaller size than screen resolution. It will also make the drm atomic path more consistent --- video/out/opengl/context_drm_egl.c | 115 +++++++++++++++++++++++++++++++++---- 1 file changed, 104 insertions(+), 11 deletions(-) diff --git a/video/out/opengl/context_drm_egl.c b/video/out/opengl/context_drm_egl.c index c0f7fa244e..1fddbb1c37 100644 --- a/video/out/opengl/context_drm_egl.c +++ b/video/out/opengl/context_drm_egl.c @@ -247,17 +247,105 @@ static void update_framebuffer_from_bo(struct ra_ctx *ctx, struct gbm_bo *bo) p->fb = fb; } +static bool crtc_setup_atomic(struct ra_ctx *ctx, drmModeModeInfo mode) +{ + struct priv *p = ctx->priv; + + struct drm_atomic_context *atomic_ctx = p->kms->atomic_context; + drmModeAtomicReqPtr request = drmModeAtomicAlloc(); + if (request) { + drm_object_set_property(request, atomic_ctx->connector, "CRTC_ID", p->kms->crtc_id); + + uint32_t blob_id; + if (drmModeCreatePropertyBlob(p->kms->fd, &mode, sizeof(drmModeModeInfo), + &blob_id) != 0) { + MP_ERR(ctx->vo, "Failed to DRM mode blob\n"); + return 0; + } + drm_object_set_property(request, atomic_ctx->crtc, "MODE_ID", blob_id); + drm_object_set_property(request, atomic_ctx->crtc, "ACTIVE", 1); + + drm_object_set_property(request, atomic_ctx->osd_plane, "SRC_X", 0); + drm_object_set_property(request, atomic_ctx->osd_plane, "SRC_Y", 0); + drm_object_set_property(request, atomic_ctx->osd_plane, "SRC_W", p->osd_size.width << 16); + drm_object_set_property(request, atomic_ctx->osd_plane, "SRC_H", p->osd_size.height << 16); + drm_object_set_property(request, atomic_ctx->osd_plane, "CRTC_X", 0); + drm_object_set_property(request, atomic_ctx->osd_plane, "CRTC_Y", 0); + drm_object_set_property(request, atomic_ctx->osd_plane, "CRTC_W", mode.hdisplay); + drm_object_set_property(request, atomic_ctx->osd_plane, "CRTC_H", mode.vdisplay); + + int ret = drmModeAtomicCommit(p->kms->fd, request, + DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT + | DRM_MODE_ATOMIC_ALLOW_MODESET, NULL); + + if (ret) + MP_WARN(ctx->vo, "Failed to commit ModeSetting atomic request (%d)\n", ret); + + drmModeAtomicFree(request); + + return ret == 0; + } else { + MP_ERR(ctx->vo, "Failed to allocate drm atomic request\n"); + } + + return false; +} + +static bool crtc_release_atomic(struct ra_ctx *ctx) +{ + struct priv *p = ctx->priv; + + struct drm_atomic_context *atomic_ctx = p->kms->atomic_context; + drmModeAtomicReqPtr request = drmModeAtomicAlloc(); + if (request) { + drm_object_set_property(request, atomic_ctx->connector, "CRTC_ID", p->old_crtc->crtc_id); + + uint32_t blob_id; + if (drmModeCreatePropertyBlob(p->kms->fd, &p->old_crtc->mode, sizeof(drmModeModeInfo), + &blob_id) != 0) { + MP_ERR(ctx->vo, "Failed to DRM mode blob\n"); + return 0; + } + drm_object_set_property(request, atomic_ctx->crtc, "MODE_ID", blob_id); + drm_object_set_property(request, atomic_ctx->crtc, "ACTIVE", 1); + drm_object_set_property(request, atomic_ctx->osd_plane, "FB_ID", p->old_crtc->buffer_id); + + int ret = drmModeAtomicCommit(p->kms->fd, request, + DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT + | DRM_MODE_ATOMIC_ALLOW_MODESET, NULL); + + if (ret) + MP_WARN(ctx->vo, "Failed to commit ModeSetting atomic request (%d)\n", ret); + + drmModeAtomicFree(request); + + return ret == 0; + } else { + MP_ERR(ctx->vo, "Failed to allocate drm atomic request\n"); + } + + return false; +} + static bool crtc_setup(struct ra_ctx *ctx) { struct priv *p = ctx->priv; if (p->active) return true; p->old_crtc = drmModeGetCrtc(p->kms->fd, p->kms->crtc_id); - int ret = drmModeSetCrtc(p->kms->fd, p->kms->crtc_id, p->fb->id, - 0, 0, &p->kms->connector->connector_id, 1, - &p->kms->mode); - p->active = true; - return ret == 0; + + if (p->kms->atomic_context) { + int ret = crtc_setup_atomic(ctx, p->kms->mode); + p->active = true; + return ret; + + } else { + int ret = drmModeSetCrtc(p->kms->fd, p->kms->crtc_id, p->fb->id, + 0, 0, &p->kms->connector->connector_id, 1, + &p->kms->mode); + p->active = true; + return ret == 0; + } } static void crtc_release(struct ra_ctx *ctx) @@ -278,12 +366,17 @@ static void crtc_release(struct ra_ctx *ctx) } if (p->old_crtc) { - drmModeSetCrtc(p->kms->fd, - p->old_crtc->crtc_id, p->old_crtc->buffer_id, - p->old_crtc->x, p->old_crtc->y, - &p->kms->connector->connector_id, 1, - &p->old_crtc->mode); - drmModeFreeCrtc(p->old_crtc); + if (p->kms->atomic_context) { + if (!crtc_release_atomic(ctx)) + MP_ERR(ctx->vo, "Failed to restore previous mode\n"); + } else { + drmModeSetCrtc(p->kms->fd, + p->old_crtc->crtc_id, p->old_crtc->buffer_id, + p->old_crtc->x, p->old_crtc->y, + &p->kms->connector->connector_id, 1, + &p->old_crtc->mode); + } + drmModeFreeCrtc(p->old_crtc); p->old_crtc = NULL; } } -- cgit v1.2.3