summaryrefslogtreecommitdiffstats
path: root/video/out/drm_atomic.c
diff options
context:
space:
mode:
Diffstat (limited to 'video/out/drm_atomic.c')
-rw-r--r--video/out/drm_atomic.c144
1 files changed, 144 insertions, 0 deletions
diff --git a/video/out/drm_atomic.c b/video/out/drm_atomic.c
index 8e68cdb074..5c6b3bbe21 100644
--- a/video/out/drm_atomic.c
+++ b/video/out/drm_atomic.c
@@ -290,9 +290,153 @@ fail:
void drm_atomic_destroy_context(struct drm_atomic_context *ctx)
{
+ drm_mode_destroy_blob(ctx->fd, &ctx->old_state.crtc.mode);
drm_object_free(ctx->crtc);
drm_object_free(ctx->connector);
drm_object_free(ctx->osd_plane);
drm_object_free(ctx->video_plane);
talloc_free(ctx);
}
+
+static bool drm_atomic_save_plane_state(struct drm_object *plane,
+ struct drm_atomic_plane_state *plane_state)
+{
+ bool ret = true;
+
+ if (0 > drm_object_get_property(plane, "FB_ID", &plane_state->fb_id))
+ ret = false;
+ if (0 > drm_object_get_property(plane, "CRTC_ID", &plane_state->crtc_id))
+ ret = false;
+ if (0 > drm_object_get_property(plane, "SRC_X", &plane_state->src_x))
+ ret = false;
+ if (0 > drm_object_get_property(plane, "SRC_Y", &plane_state->src_y))
+ ret = false;
+ if (0 > drm_object_get_property(plane, "SRC_W", &plane_state->src_w))
+ ret = false;
+ if (0 > drm_object_get_property(plane, "SRC_H", &plane_state->src_h))
+ ret = false;
+ if (0 > drm_object_get_property(plane, "CRTC_X", &plane_state->crtc_x))
+ ret = false;
+ if (0 > drm_object_get_property(plane, "CRTC_Y", &plane_state->crtc_y))
+ ret = false;
+ if (0 > drm_object_get_property(plane, "CRTC_W", &plane_state->crtc_w))
+ ret = false;
+ if (0 > drm_object_get_property(plane, "CRTC_H", &plane_state->crtc_h))
+ ret = false;
+ // ZPOS might not exist, so ignore whether or not this succeeds
+ drm_object_get_property(plane, "ZPOS", &plane_state->zpos);
+
+ return ret;
+}
+
+static bool drm_atomic_restore_plane_state(drmModeAtomicReq *request,
+ struct drm_object *plane,
+ const struct drm_atomic_plane_state *plane_state)
+{
+ bool ret = true;
+
+ if (0 > drm_object_set_property(request, plane, "FB_ID", plane_state->fb_id))
+ ret = false;
+ if (0 > drm_object_set_property(request, plane, "CRTC_ID", plane_state->crtc_id))
+ ret = false;
+ if (0 > drm_object_set_property(request, plane, "SRC_X", plane_state->src_x))
+ ret = false;
+ if (0 > drm_object_set_property(request, plane, "SRC_Y", plane_state->src_y))
+ ret = false;
+ if (0 > drm_object_set_property(request, plane, "SRC_W", plane_state->src_w))
+ ret = false;
+ if (0 > drm_object_set_property(request, plane, "SRC_H", plane_state->src_h))
+ ret = false;
+ if (0 > drm_object_set_property(request, plane, "CRTC_X", plane_state->crtc_x))
+ ret = false;
+ if (0 > drm_object_set_property(request, plane, "CRTC_Y", plane_state->crtc_y))
+ ret = false;
+ if (0 > drm_object_set_property(request, plane, "CRTC_W", plane_state->crtc_w))
+ ret = false;
+ if (0 > drm_object_set_property(request, plane, "CRTC_H", plane_state->crtc_h))
+ ret = false;
+ // ZPOS might not exist, so ignore whether or not this succeeds
+ drm_object_set_property(request, plane, "ZPOS", plane_state->zpos);
+
+ return ret;
+}
+
+bool drm_atomic_save_old_state(struct drm_atomic_context *ctx)
+{
+ if (ctx->old_state.saved)
+ return false;
+
+ bool ret = true;
+
+ drmModeCrtc *crtc = drmModeGetCrtc(ctx->fd, ctx->crtc->id);
+ if (crtc == NULL)
+ return false;
+ ctx->old_state.crtc.mode.mode = crtc->mode;
+ drmModeFreeCrtc(crtc);
+
+ if (0 > drm_object_get_property(ctx->crtc, "ACTIVE", &ctx->old_state.crtc.active))
+ ret = false;
+
+ if (0 > drm_object_get_property(ctx->connector, "CRTC_ID", &ctx->old_state.connector.crtc_id))
+ ret = false;
+
+ if (!drm_atomic_save_plane_state(ctx->osd_plane, &ctx->old_state.osd_plane))
+ ret = false;
+ if (!drm_atomic_save_plane_state(ctx->video_plane, &ctx->old_state.video_plane))
+ ret = false;
+
+ ctx->old_state.saved = true;
+
+ return ret;
+}
+
+bool drm_atomic_restore_old_state(drmModeAtomicReqPtr request, struct drm_atomic_context *ctx)
+{
+ if (!ctx->old_state.saved)
+ return false;
+
+ bool ret = true;
+
+ if (0 > drm_object_set_property(request, ctx->connector, "CRTC_ID", ctx->old_state.connector.crtc_id))
+ ret = false;
+
+ 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))
+ ret = false;
+ if (0 > drm_object_set_property(request, ctx->crtc, "ACTIVE", ctx->old_state.crtc.active))
+ ret = false;
+
+ if (!drm_atomic_restore_plane_state(request, ctx->osd_plane, &ctx->old_state.osd_plane))
+ ret = false;
+ if (!drm_atomic_restore_plane_state(request, ctx->video_plane, &ctx->old_state.video_plane))
+ ret = false;
+
+ ctx->old_state.saved = false;
+
+ return ret;
+}
+
+bool drm_mode_ensure_blob(int fd, struct drm_mode *mode)
+{
+ int ret = 0;
+
+ if (!mode->blob_id) {
+ ret = drmModeCreatePropertyBlob(fd, &mode->mode, sizeof(drmModeModeInfo),
+ &mode->blob_id);
+ }
+
+ return (ret == 0);
+}
+
+bool drm_mode_destroy_blob(int fd, struct drm_mode *mode)
+{
+ int ret = 0;
+
+ if (mode->blob_id) {
+ ret = drmModeDestroyPropertyBlob(fd, mode->blob_id);
+ mode->blob_id = 0;
+ }
+
+ return (ret == 0);
+}