diff options
Diffstat (limited to 'video/out')
-rw-r--r-- | video/out/drm_common.c | 74 | ||||
-rw-r--r-- | video/out/drm_common.h | 18 | ||||
-rw-r--r-- | video/out/opengl/context_drm_egl.c | 26 | ||||
-rw-r--r-- | video/out/present_sync.c | 9 | ||||
-rw-r--r-- | video/out/present_sync.h | 3 | ||||
-rw-r--r-- | video/out/vo_drm.c | 32 |
6 files changed, 40 insertions, 122 deletions
diff --git a/video/out/drm_common.c b/video/out/drm_common.c index 293948b614..cc53757e43 100644 --- a/video/out/drm_common.c +++ b/video/out/drm_common.c @@ -40,11 +40,12 @@ #include "common/common.h" #include "common/msg.h" +#include "misc/ctype.h" #include "options/m_config.h" #include "osdep/io.h" #include "osdep/poll_wrapper.h" #include "osdep/timer.h" -#include "misc/ctype.h" +#include "present_sync.h" #include "video/out/vo.h" #define EVT_RELEASE 1 @@ -912,55 +913,12 @@ err: static void drm_pflip_cb(int fd, unsigned int msc, unsigned int sec, unsigned int usec, void *data) { - struct drm_pflip_cb_closure *closure = data; - - struct drm_vsync_tuple *vsync = closure->vsync; - // frame_vsync->ust is the timestamp of the pageflip that happened just before this flip was queued - // frame_vsync->msc is the sequence number of the pageflip that happened just before this flip was queued - // frame_vsync->sbc is the sequence number for the frame that was just flipped to screen - struct drm_vsync_tuple *frame_vsync = closure->frame_vsync; - struct vo_vsync_info *vsync_info = closure->vsync_info; - - const bool ready = - (vsync->msc != 0) && - (frame_vsync->ust != 0) && (frame_vsync->msc != 0); - - const uint64_t ust = (sec * 1000000LL) + usec; - - const unsigned int msc_since_last_flip = msc - vsync->msc; - if (ready && msc == vsync->msc) { - // Seems like some drivers only increment msc every other page flip when - // running in interlaced mode (I'm looking at you nouveau). Obviously we - // can't work with this, so shame the driver and bail. - mp_err(closure->log, - "Got the same msc value twice: (msc: %u, vsync->msc: %u). This shouldn't happen. Possibly broken driver/interlaced mode?\n", - msc, vsync->msc); - goto fail; - } - - vsync->ust = ust; - vsync->msc = msc; - - if (ready) { - // Convert to mp_time - struct timespec ts; - if (clock_gettime(CLOCK_MONOTONIC, &ts)) - goto fail; - int64_t now_monotonic = MP_TIME_S_TO_NS(ts.tv_sec) + ts.tv_nsec; - int64_t ust_mp_time = mp_time_ns() - (now_monotonic - vsync->ust * 1000); - - const uint64_t ust_since_enqueue = vsync->ust - frame_vsync->ust; - const unsigned int msc_since_enqueue = vsync->msc - frame_vsync->msc; - const unsigned int sbc_since_enqueue = vsync->sbc - frame_vsync->sbc; - - vsync_info->vsync_duration = ust_since_enqueue * 1000 / msc_since_enqueue; - vsync_info->skipped_vsyncs = msc_since_last_flip - 1; // Valid iff swap_buffers is called every vsync - vsync_info->last_queue_display_time = ust_mp_time + (sbc_since_enqueue * vsync_info->vsync_duration); - } - -fail: - *closure->waiting_for_flip = false; - talloc_free(closure); + struct vo_drm_state *drm = data; + + int64_t ust = MP_TIME_S_TO_NS(sec) + MP_TIME_US_TO_NS(usec); + present_sync_update_values(drm->present, ust, msc); + present_sync_swap(drm->present); + drm->waiting_for_flip = false; } int vo_drm_control(struct vo *vo, int *events, int request, void *arg) @@ -985,10 +943,7 @@ int vo_drm_control(struct vo *vo, int *events, int request, void *arg) return VO_TRUE; case VOCTRL_RESUME: drm->paused = false; - drm->vsync_info.last_queue_display_time = -1; - drm->vsync_info.skipped_vsyncs = 0; - drm->vsync.ust = 0; - drm->vsync.msc = 0; + present_sync_clear_values(drm->present); return VO_TRUE; } return VO_NOTIMPL; @@ -1075,10 +1030,7 @@ bool vo_drm_init(struct vo *vo) drm->ev.version = DRM_EVENT_CONTEXT_VERSION; drm->ev.page_flip_handler = &drm_pflip_cb; - - drm->vsync_info.vsync_duration = 0; - drm->vsync_info.skipped_vsyncs = -1; - drm->vsync_info.last_queue_display_time = -1; + drm->present = mp_present_initialize(drm, 8); // max swapchain depth allowed return true; @@ -1289,12 +1241,6 @@ double vo_drm_get_display_fps(struct vo_drm_state *drm) return mode_get_Hz(&drm->mode.mode); } -void vo_drm_get_vsync(struct vo *vo, struct vo_vsync_info *info) -{ - struct vo_drm_state *drm = vo->drm; - *info = drm->vsync_info; -} - void vo_drm_set_monitor_par(struct vo *vo) { struct vo_drm_state *drm = vo->drm; diff --git a/video/out/drm_common.h b/video/out/drm_common.h index cadef2019f..581151f94a 100644 --- a/video/out/drm_common.h +++ b/video/out/drm_common.h @@ -39,12 +39,6 @@ struct framebuffer { uint32_t id; }; -struct drm_vsync_tuple { - uint64_t ust; - unsigned int msc; - unsigned int sbc; -}; - struct drm_mode { drmModeModeInfo mode; uint32_t blob_id; @@ -77,12 +71,11 @@ struct vo_drm_state { struct drm_atomic_context *atomic_context; struct drm_mode mode; struct drm_opts *opts; - struct drm_vsync_tuple vsync; struct framebuffer *fb; struct mp_log *log; + struct mp_present *present; struct vo *vo; struct vt_switcher vt_switcher; - struct vo_vsync_info vsync_info; bool active; bool paused; @@ -99,19 +92,10 @@ struct vo_drm_state { uint32_t width; }; -struct drm_pflip_cb_closure { - struct drm_vsync_tuple *frame_vsync; // vsync tuple when the frame that just flipped was queued - struct drm_vsync_tuple *vsync; // vsync tuple of the latest page flip. drm_pflip_cb updates this - struct vo_vsync_info *vsync_info; // where the drm_pflip_cb routine writes its output - bool *waiting_for_flip; // drm_pflip_cb writes false here before returning - struct mp_log *log; // Needed to print error messages that shame bad drivers -}; - bool vo_drm_init(struct vo *vo); int vo_drm_control(struct vo *vo, int *events, int request, void *arg); double vo_drm_get_display_fps(struct vo_drm_state *drm); -void vo_drm_get_vsync(struct vo *vo, struct vo_vsync_info *info); void vo_drm_set_monitor_par(struct vo *vo); void vo_drm_uninit(struct vo *vo); void vo_drm_wait_events(struct vo *vo, int64_t until_time_ns); diff --git a/video/out/opengl/context_drm_egl.c b/video/out/opengl/context_drm_egl.c index 16046b1577..2db428f590 100644 --- a/video/out/opengl/context_drm_egl.c +++ b/video/out/opengl/context_drm_egl.c @@ -29,10 +29,11 @@ #include <drm_fourcc.h> #include "libmpv/render_gl.h" -#include "video/out/drm_atomic.h" -#include "video/out/drm_common.h" #include "common/common.h" #include "osdep/timer.h" +#include "video/out/drm_atomic.h" +#include "video/out/drm_common.h" +#include "video/out/present_sync.h" #include "egl_helpers.h" #include "common.h" @@ -48,7 +49,6 @@ struct gbm_frame { struct gbm_bo *bo; - struct drm_vsync_tuple vsync; }; struct gbm { @@ -322,26 +322,16 @@ static void queue_flip(struct ra_ctx *ctx, struct gbm_frame *frame) update_framebuffer_from_bo(ctx, frame->bo); - // Alloc and fill the data struct for the page flip callback - struct drm_pflip_cb_closure *data = talloc(ctx, struct drm_pflip_cb_closure); - data->frame_vsync = &frame->vsync; - data->vsync = &drm->vsync; - data->vsync_info = &drm->vsync_info; - data->waiting_for_flip = &drm->waiting_for_flip; - data->log = drm->log; - struct drm_atomic_context *atomic_ctx = drm->atomic_context; drm_object_set_property(atomic_ctx->request, atomic_ctx->draw_plane, "FB_ID", drm->fb->id); drm_object_set_property(atomic_ctx->request, atomic_ctx->draw_plane, "CRTC_ID", atomic_ctx->crtc->id); drm_object_set_property(atomic_ctx->request, atomic_ctx->draw_plane, "ZPOS", 1); int ret = drmModeAtomicCommit(drm->fd, atomic_ctx->request, - DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT, data); + DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT, drm); - if (ret) { + if (ret) MP_WARN(ctx->vo, "Failed to commit atomic request: %s\n", mp_strerror(ret)); - talloc_free(data); - } drm->waiting_for_flip = !ret; drmModeAtomicFree(atomic_ctx->request); @@ -351,12 +341,9 @@ static void queue_flip(struct ra_ctx *ctx, struct gbm_frame *frame) static void enqueue_bo(struct ra_ctx *ctx, struct gbm_bo *bo) { struct priv *p = ctx->priv; - struct vo_drm_state *drm = ctx->vo->drm; - drm->vsync.sbc++; struct gbm_frame *new_frame = talloc(p, struct gbm_frame); new_frame->bo = bo; - new_frame->vsync = drm->vsync; MP_TARRAY_APPEND(p, p->gbm.bo_queue, p->gbm.num_bos, new_frame); } @@ -590,7 +577,8 @@ static bool probe_gbm_modifiers(struct ra_ctx *ctx) static void drm_egl_get_vsync(struct ra_ctx *ctx, struct vo_vsync_info *info) { - vo_drm_get_vsync(ctx->vo, info); + struct vo_drm_state *drm = ctx->vo->drm; + present_sync_get_info(drm->present, info); } static bool drm_egl_init(struct ra_ctx *ctx) diff --git a/video/out/present_sync.c b/video/out/present_sync.c index 66ab8075a3..75004f56b5 100644 --- a/video/out/present_sync.c +++ b/video/out/present_sync.c @@ -107,6 +107,15 @@ void present_sync_swap(struct mp_present *present) cur->queue_display_time = ust_mp_time; } +void present_sync_clear_values(struct mp_present *present) +{ + struct mp_present_entry *cur = present->head; + while (cur) { + *cur = (struct mp_present_entry){0}; + cur = cur->list_node.next; + } +} + void present_sync_update_values(struct mp_present *present, int64_t ust, int64_t msc) { diff --git a/video/out/present_sync.h b/video/out/present_sync.h index dac574c4d7..361045548d 100644 --- a/video/out/present_sync.h +++ b/video/out/present_sync.h @@ -49,6 +49,9 @@ void present_sync_get_info(struct mp_present *present, struct vo_vsync_info *inf // Called after every buffer swap to update presentation statistics. void present_sync_swap(struct mp_present *present); +// Zero the entire list but keep the items. +void present_sync_clear_values(struct mp_present *present); + // Called anytime the backend delivers new ust/msc values. void present_sync_update_values(struct mp_present *present, int64_t ust, int64_t msc); diff --git a/video/out/vo_drm.c b/video/out/vo_drm.c index 1128a0dd4f..aae73f7be1 100644 --- a/video/out/vo_drm.c +++ b/video/out/vo_drm.c @@ -33,6 +33,7 @@ #include "sub/osd.h" #include "video/fmt-conversion.h" #include "video/mp_image.h" +#include "video/out/present_sync.h" #include "video/sws_utils.h" #include "vo.h" @@ -48,7 +49,6 @@ struct drm_frame { struct framebuffer *fb; - struct drm_vsync_tuple vsync; }; struct priv { @@ -200,10 +200,6 @@ static int reconfig(struct vo *vo, struct mp_image_params *params) if (mp_sws_reinit(p->sws) < 0) return -1; - drm->vsync_info.vsync_duration = 0; - drm->vsync_info.skipped_vsyncs = -1; - drm->vsync_info.last_queue_display_time = -1; - vo->want_redraw = true; return 0; } @@ -283,12 +279,9 @@ static void draw_image(struct vo *vo, mp_image_t *mpi, struct framebuffer *buf) static void enqueue_frame(struct vo *vo, struct framebuffer *fb) { struct priv *p = vo->priv; - struct vo_drm_state *drm = vo->drm; - drm->vsync.sbc++; struct drm_frame *new_frame = talloc(p, struct drm_frame); new_frame->fb = fb; - new_frame->vsync = drm->vsync; MP_TARRAY_APPEND(p, p->fb_queue, p->fb_queue_len, new_frame); } @@ -332,25 +325,14 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) static void queue_flip(struct vo *vo, struct drm_frame *frame) { - struct priv *p = vo->priv; struct vo_drm_state *drm = vo->drm; drm->fb = frame->fb; - // Alloc and fill the data struct for the page flip callback - struct drm_pflip_cb_closure *data = talloc(p, struct drm_pflip_cb_closure); - data->frame_vsync = &frame->vsync; - data->vsync = &drm->vsync; - data->vsync_info = &drm->vsync_info; - data->waiting_for_flip = &drm->waiting_for_flip; - data->log = vo->log; - int ret = drmModePageFlip(drm->fd, drm->crtc_id, - drm->fb->id, DRM_MODE_PAGE_FLIP_EVENT, data); - if (ret) { + drm->fb->id, DRM_MODE_PAGE_FLIP_EVENT, drm); + if (ret) MP_WARN(vo, "Failed to queue page flip: %s\n", mp_strerror(errno)); - talloc_free(data); - } drm->waiting_for_flip = !ret; } @@ -379,6 +361,12 @@ static void flip_page(struct vo *vo) } } +static void get_vsync(struct vo *vo, struct vo_vsync_info *info) +{ + struct vo_drm_state *drm = vo->drm; + present_sync_get_info(drm->present, info); +} + static void uninit(struct vo *vo) { struct priv *p = vo->priv; @@ -462,7 +450,7 @@ const struct vo_driver video_out_drm = { .control = control, .draw_frame = draw_frame, .flip_page = flip_page, - .get_vsync = vo_drm_get_vsync, + .get_vsync = get_vsync, .uninit = uninit, .wait_events = vo_drm_wait_events, .wakeup = vo_drm_wakeup, |