From 9538fb5a7af951e220f26c87c80aaaa2a5cfbc67 Mon Sep 17 00:00:00 2001 From: Anton Kindestam Date: Mon, 29 Jul 2019 19:32:29 +0200 Subject: drm: refactor page_flipped callback Avoid duplicating the same callback function in both context_drm_egl and vo_drm. --- video/out/drm_common.c | 48 ++++++++++++++++++++++++++++++ video/out/drm_common.h | 11 +++++++ video/out/opengl/context_drm_egl.c | 60 ++++--------------------------------- video/out/vo_drm.c | 61 ++++---------------------------------- 4 files changed, 71 insertions(+), 109 deletions(-) diff --git a/video/out/drm_common.c b/video/out/drm_common.c index fb02130bb0..a7a0b2759f 100644 --- a/video/out/drm_common.c +++ b/video/out/drm_common.c @@ -25,13 +25,16 @@ #include #include #include +#include #include "drm_common.h" #include "common/common.h" #include "common/msg.h" #include "osdep/io.h" +#include "osdep/timer.h" #include "misc/ctype.h" +#include "video/out/vo.h" #define EVT_RELEASE 1 #define EVT_ACQUIRE 2 @@ -900,3 +903,48 @@ void vt_switcher_poll(struct vt_switcher *s, int timeout_ms) break; } } + +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; + + vsync->ust = ust; + vsync->msc = msc; + + if (ready) { + // Convert to mp_time + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts)) + goto fail; + const uint64_t now_monotonic = ts.tv_sec * 1000000LL + ts.tv_nsec / 1000; + const uint64_t ust_mp_time = mp_time_us() - (now_monotonic - vsync->ust); + + 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 / 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); +} diff --git a/video/out/drm_common.h b/video/out/drm_common.h index ba4fceba45..6ddd0994e3 100644 --- a/video/out/drm_common.h +++ b/video/out/drm_common.h @@ -61,6 +61,13 @@ struct drm_vsync_tuple { unsigned int sbc; }; +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 +}; + bool vt_switcher_init(struct vt_switcher *s, struct mp_log *log); void vt_switcher_destroy(struct vt_switcher *s); void vt_switcher_poll(struct vt_switcher *s, int timeout_ms); @@ -78,4 +85,8 @@ struct kms *kms_create(struct mp_log *log, const char *connector_spec, void kms_destroy(struct kms *kms); double kms_get_display_fps(const struct kms *kms); +// DRM Page Flip callback +void drm_pflip_cb(int fd, unsigned int msc, unsigned int sec, + unsigned int usec, void *data); + #endif diff --git a/video/out/opengl/context_drm_egl.c b/video/out/opengl/context_drm_egl.c index 6962237123..fcc31df682 100644 --- a/video/out/opengl/context_drm_egl.c +++ b/video/out/opengl/context_drm_egl.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include @@ -106,11 +105,6 @@ struct priv { struct mpv_opengl_drm_draw_surface_size draw_surface_size; }; -struct pflip_cb_closure { - struct priv *priv; - struct gbm_frame *frame; -}; - // Not general. Limited to only the formats being used in this module static const char *gbm_format_to_string(uint32_t format) { @@ -460,9 +454,11 @@ 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 pflip_cb_closure *data = talloc(ctx, struct pflip_cb_closure); - data->priv = p; - data->frame = frame; + struct drm_pflip_cb_closure *data = talloc(ctx, struct drm_pflip_cb_closure); + data->frame_vsync = &frame->vsync; + data->vsync = &p->vsync; + data->vsync_info = &p->vsync_info; + data->waiting_for_flip = &p->waiting_for_flip; if (atomic_ctx) { drm_object_set_property(atomic_ctx->request, atomic_ctx->draw_plane, "FB_ID", p->fb->id); @@ -715,50 +711,6 @@ static bool probe_gbm_format(struct ra_ctx *ctx, uint32_t argb_format, uint32_t return result; } -static void page_flipped(int fd, unsigned int msc, unsigned int sec, - unsigned int usec, void *data) -{ - struct pflip_cb_closure *closure = data; - struct priv *p = closure->priv; - - // 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 gbm_frame *frame = closure->frame; - - const bool ready = - (p->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 - p->vsync.msc; - - p->vsync.ust = ust; - p->vsync.msc = msc; - - if (ready) { - // Convert to mp_time - struct timespec ts; - if (clock_gettime(CLOCK_MONOTONIC, &ts)) - goto fail; - const uint64_t now_monotonic = ts.tv_sec * 1000000LL + ts.tv_nsec / 1000; - const uint64_t ust_mp_time = mp_time_us() - (now_monotonic - p->vsync.ust); - - const uint64_t ust_since_enqueue = p->vsync.ust - frame->vsync.ust; - const unsigned int msc_since_enqueue = p->vsync.msc - frame->vsync.msc; - const unsigned int sbc_since_enqueue = p->vsync.sbc - frame->vsync.sbc; - - p->vsync_info.vsync_duration = ust_since_enqueue / msc_since_enqueue; - p->vsync_info.skipped_vsyncs = msc_since_last_flip - 1; // Valid iff swap_buffers is called every vsync - p->vsync_info.last_queue_display_time = ust_mp_time + (sbc_since_enqueue * p->vsync_info.vsync_duration); - } - -fail: - p->waiting_for_flip = false; - talloc_free(closure); -} - static void drm_egl_get_vsync(struct ra_ctx *ctx, struct vo_vsync_info *info) { struct priv *p = ctx->priv; @@ -774,7 +726,7 @@ static bool drm_egl_init(struct ra_ctx *ctx) struct priv *p = ctx->priv = talloc_zero(ctx, struct priv); p->ev.version = DRM_EVENT_CONTEXT_VERSION; - p->ev.page_flip_handler = page_flipped; + p->ev.page_flip_handler = &drm_pflip_cb; p->vt_switcher_active = vt_switcher_init(&p->vt_switcher, ctx->vo->log); if (p->vt_switcher_active) { diff --git a/video/out/vo_drm.c b/video/out/vo_drm.c index 80757486c6..8e2ee9ae1b 100644 --- a/video/out/vo_drm.c +++ b/video/out/vo_drm.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include @@ -65,11 +64,6 @@ struct kms_frame { struct drm_vsync_tuple vsync; }; -struct pflip_cb_closure { - struct priv *priv; - struct kms_frame *frame; -}; - struct priv { char *connector_spec; int mode_id; @@ -202,50 +196,6 @@ static bool fb_setup_buffers(struct vo *vo) return true; } -static void page_flipped(int fd, unsigned int msc, unsigned int sec, - unsigned int usec, void *data) -{ - struct pflip_cb_closure *closure = data; - struct priv *p = closure->priv; - - // 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 kms_frame *frame = closure->frame; - - const bool ready = - (p->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 - p->vsync.msc; - - p->vsync.ust = ust; - p->vsync.msc = msc; - - if (ready) { - // Convert to mp_time - struct timespec ts; - if (clock_gettime(CLOCK_MONOTONIC, &ts)) - goto fail; - const uint64_t now_monotonic = ts.tv_sec * 1000000LL + ts.tv_nsec / 1000; - const uint64_t ust_mp_time = mp_time_us() - (now_monotonic - p->vsync.ust); - - const uint64_t ust_since_enqueue = p->vsync.ust - frame->vsync.ust; - const unsigned int msc_since_enqueue = p->vsync.msc - frame->vsync.msc; - const unsigned int sbc_since_enqueue = p->vsync.sbc - frame->vsync.sbc; - - p->vsync_info.vsync_duration = ust_since_enqueue / msc_since_enqueue; - p->vsync_info.skipped_vsyncs = msc_since_last_flip - 1; // Valid iff swap_buffers is called every vsync - p->vsync_info.last_queue_display_time = ust_mp_time + (sbc_since_enqueue * p->vsync_info.vsync_duration); - } - -fail: - p->waiting_for_flip = false; - talloc_free(closure); -} - static void get_vsync(struct vo *vo, struct vo_vsync_info *info) { struct priv *p = vo->priv; @@ -538,9 +488,11 @@ static void queue_flip(struct vo *vo, struct kms_frame *frame) p->cur_fb = frame->fb; // Alloc and fill the data struct for the page flip callback - struct pflip_cb_closure *data = talloc(p, struct pflip_cb_closure); - data->priv = p; - data->frame = frame; + struct drm_pflip_cb_closure *data = talloc(p, struct drm_pflip_cb_closure); + data->frame_vsync = &frame->vsync; + data->vsync = &p->vsync; + data->vsync_info = &p->vsync_info; + data->waiting_for_flip = &p->waiting_for_flip; ret = drmModePageFlip(p->kms->fd, p->kms->crtc_id, p->cur_fb->fb, @@ -550,7 +502,6 @@ static void queue_flip(struct vo *vo, struct kms_frame *frame) } else { p->waiting_for_flip = true; } - } static void flip_page(struct vo *vo) @@ -607,7 +558,7 @@ static int preinit(struct vo *vo) struct priv *p = vo->priv; p->sws = mp_sws_alloc(vo); p->ev.version = DRM_EVENT_CONTEXT_VERSION; - p->ev.page_flip_handler = page_flipped; + p->ev.page_flip_handler = &drm_pflip_cb; p->vt_switcher_active = vt_switcher_init(&p->vt_switcher, vo->log); if (p->vt_switcher_active) { -- cgit v1.2.3