diff options
Diffstat (limited to 'video/out/drm_atomic.c')
-rw-r--r-- | video/out/drm_atomic.c | 203 |
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); +} |