summaryrefslogtreecommitdiffstats
path: root/video/out
diff options
context:
space:
mode:
Diffstat (limited to 'video/out')
-rw-r--r--video/out/drm_common.c74
-rw-r--r--video/out/drm_common.h18
-rw-r--r--video/out/opengl/context_drm_egl.c26
-rw-r--r--video/out/present_sync.c9
-rw-r--r--video/out/present_sync.h3
-rw-r--r--video/out/vo_drm.c32
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,