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.c203
1 files changed, 177 insertions, 26 deletions
diff --git a/video/out/drm_atomic.c b/video/out/drm_atomic.c
index 8e68cdb074..51b3da89c6 100644
--- a/video/out/drm_atomic.c
+++ b/video/out/drm_atomic.c
@@ -138,7 +138,8 @@ void drm_object_print_info(struct mp_log *log, struct drm_object *object)
}
struct drm_atomic_context *drm_atomic_create_context(struct mp_log *log, int fd, int crtc_id,
- int connector_id, int osd_plane_id, int video_plane_id)
+ int connector_id,
+ int draw_plane_idx, int drmprime_video_plane_idx)
{
drmModePlaneRes *plane_res = NULL;
drmModeRes *res = NULL;
@@ -228,13 +229,13 @@ struct drm_atomic_context *drm_atomic_create_context(struct mp_log *log, int fd,
if ((!overlay_id) && (value == DRM_PLANE_TYPE_OVERLAY))
overlay_id = plane_id;
- if (layercount == osd_plane_id) {
- ctx->osd_plane = plane;
+ if (layercount == draw_plane_idx) {
+ ctx->draw_plane = plane;
continue;
}
- if (layercount == video_plane_id) {
- ctx->video_plane = plane;
+ if (layercount == drmprime_video_plane_idx) {
+ ctx->drmprime_video_plane = plane;
continue;
}
}
@@ -244,40 +245,40 @@ struct drm_atomic_context *drm_atomic_create_context(struct mp_log *log, int fd,
}
}
- // default OSD plane to primary if unspecified
- if (!ctx->osd_plane) {
- if (primary_id) {
- mp_verbose(log, "Using default plane %d for OSD\n", primary_id);
- ctx->osd_plane = drm_object_create(log, ctx->fd, primary_id, DRM_MODE_OBJECT_PLANE);
+ // draw plane was specified as either of the special options: any primary plane or any overlay plane
+ if (!ctx->draw_plane) {
+ const int draw_plane_id = (draw_plane_idx == DRM_OPTS_OVERLAY_PLANE) ? overlay_id : primary_id;
+ const char *plane_type = (draw_plane_idx == DRM_OPTS_OVERLAY_PLANE) ? "overlay" : "primary";
+ if (draw_plane_id) {
+ mp_verbose(log, "Using %s plane %d as draw plane\n", plane_type, draw_plane_id);
+ ctx->draw_plane = drm_object_create(log, ctx->fd, draw_plane_id, DRM_MODE_OBJECT_PLANE);
} else {
- mp_err(log, "Failed to find OSD plane with id=%d\n", osd_plane_id);
+ mp_err(log, "Failed to find draw plane with idx=%d\n", draw_plane_idx);
goto fail;
}
} else {
- mp_verbose(log, "Found OSD plane with ID %d\n", ctx->osd_plane->id);
+ mp_verbose(log, "Found draw plane with ID %d\n", ctx->draw_plane->id);
}
- // default video plane to overlay if unspecified
- if (!ctx->video_plane) {
- if (overlay_id) {
- mp_verbose(log, "Using default plane %d for video\n", overlay_id);
- ctx->video_plane = drm_object_create(log, ctx->fd, overlay_id, DRM_MODE_OBJECT_PLANE);
+ // drmprime plane was specified as either of the special options: any primary plane or any overlay plane
+ if (!ctx->drmprime_video_plane) {
+ const int drmprime_video_plane_id = (drmprime_video_plane_idx == DRM_OPTS_PRIMARY_PLANE) ? primary_id : overlay_id;
+ const char *plane_type = (drmprime_video_plane_idx == DRM_OPTS_PRIMARY_PLANE) ? "primary" : "overlay";
+
+ if (drmprime_video_plane_id) {
+ mp_verbose(log, "Using %s plane %d as drmprime plane\n", plane_type, drmprime_video_plane_id);
+ ctx->drmprime_video_plane = drm_object_create(log, ctx->fd, drmprime_video_plane_id, DRM_MODE_OBJECT_PLANE);
} else {
- mp_err(log, "Failed to find video plane with id=%d\n", video_plane_id);
- goto fail;
+ mp_verbose(log, "Failed to find drmprime plane with idx=%d. drmprime-drm hwdec interop will not work\n", drmprime_video_plane_idx);
}
} else {
- mp_verbose(log, "Found video plane with ID %d\n", ctx->video_plane->id);
+ mp_verbose(log, "Found drmprime plane with ID %d\n", ctx->drmprime_video_plane->id);
}
- mp_verbose(log, "Found Video plane with ID %d, OSD with ID %d\n",
- ctx->video_plane->id, ctx->osd_plane->id);
-
drmModeFreePlaneResources(plane_res);
drmModeFreeResources(res);
return ctx;
-
fail:
if (res)
drmModeFreeResources(res);
@@ -290,9 +291,159 @@ 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);
+ drm_object_free(ctx->draw_plane);
+ drm_object_free(ctx->drmprime_video_plane);
talloc_free(ctx);
}
+
+static bool drm_atomic_save_plane_state(struct drm_object *plane,
+ struct drm_atomic_plane_state *plane_state)
+{
+ if (!plane)
+ return true;
+
+ 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)
+{
+ if (!plane)
+ return true;
+
+ 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->draw_plane, &ctx->old_state.draw_plane))
+ ret = false;
+ if (!drm_atomic_save_plane_state(ctx->drmprime_video_plane, &ctx->old_state.drmprime_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->draw_plane, &ctx->old_state.draw_plane))
+ ret = false;
+ if (!drm_atomic_restore_plane_state(request, ctx->drmprime_video_plane, &ctx->old_state.drmprime_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);
+}