mirror of
https://github.com/mpv-player/mpv
synced 2025-01-30 03:32:50 +00:00
drm: refactor page_flipped callback
Avoid duplicating the same callback function in both context_drm_egl and vo_drm.
This commit is contained in:
parent
77980c8184
commit
9538fb5a7a
@ -25,13 +25,16 @@
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <poll.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <gbm.h>
|
||||
@ -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) {
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include <stdbool.h>
|
||||
#include <sys/mman.h>
|
||||
#include <poll.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <libswscale/swscale.h>
|
||||
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user