From 1b317902941a50574b22b96f9907243842bf7827 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 12 Jul 2020 21:33:08 +0300 Subject: [PATCH] Don't wait for vsync for late frames If multiple frames are ready to be displayed, then block only on the last one. This condition happens rarely in practice, usually when there is a high spike of CPU activity. This change may prevent unnecessary frame drops. --- src/presentation_queue.c | 20 ++++++++++++++++---- src/presentation_queue_target.c | 16 +++++++++------- src/vdpau_tegra.h | 2 +- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/presentation_queue.c b/src/presentation_queue.c index 17f2a28..abc1509 100644 --- a/src/presentation_queue.c +++ b/src/presentation_queue.c @@ -23,7 +23,7 @@ static void * presentation_queue_thr(void *opaque) { tegra_pq *pq = opaque; tegra_pqt *pqt = pq->pqt; - tegra_surface *surf, *tmp, *next; + tegra_surface *disp_surf, *surf, *tmp, *next; VdpTime earliest_time = UINT64_MAX; VdpTime time = UINT64_MAX; struct timespec tp; @@ -70,6 +70,8 @@ static void * presentation_queue_thr(void *opaque) } earliest_time = UINT64_MAX; + disp_surf = NULL; + next = NULL; LIST_FOR_EACH_ENTRY_SAFE(surf, tmp, &pq->surf_list, list_item) { pthread_mutex_lock(&surf->lock); @@ -95,13 +97,23 @@ static void * presentation_queue_thr(void *opaque) DebugMsg("displaying surface %u\n", surf->surface_id); - pqt_display_surface(pqt, surf, true, false); + if (disp_surf) { + pqt_display_surface(pqt, disp_surf, true, false, false); + } + + disp_surf = surf; + } + + if (disp_surf) { + pqt_display_surface(pqt, disp_surf, true, false, true); } time = earliest_time; if (time != UINT64_MAX) { - pqt_prepare_dri_surface(pqt, next); + if (next) { + pqt_prepare_dri_surface(pqt, next); + } DebugMsg("next wake on %llu\n", time); } else { @@ -356,7 +368,7 @@ VdpStatus vdp_presentation_queue_display( surf->disp_height = clip_height ?: surf->height; if (earliest_presentation_time == 0 || !_Xglobal_lock) { - pqt_display_surface(pq->pqt, surf, true, false); + pqt_display_surface(pq->pqt, surf, true, false, true); goto unlock_surf; } diff --git a/src/presentation_queue_target.c b/src/presentation_queue_target.c index aeb7196..4224f41 100644 --- a/src/presentation_queue_target.c +++ b/src/presentation_queue_target.c @@ -196,7 +196,7 @@ static bool initialize_dri2(tegra_pqt *pqt) return dev->dri2_ready; } -static void pqt_display_dri(tegra_pqt *pqt, tegra_surface *surf) +static void pqt_display_dri(tegra_pqt *pqt, tegra_surface *surf, bool vsync) { tegra_device *dev = pqt->dev; CARD64 ust, msc, sbc; @@ -206,7 +206,9 @@ static void pqt_display_dri(tegra_pqt *pqt, tegra_surface *surf) DRI2GetMSC(dev->display, pqt->drawable, &ust, &msc, &sbc); DRI2SwapBuffers(dev->display, pqt->drawable, msc + 1, 0, 0, &count); - DRI2WaitMSC(dev->display, pqt->drawable, msc + 1, 0, 0, &ust, &msc, &sbc); + if (vsync) { + DRI2WaitMSC(dev->display, pqt->drawable, msc + 1, 0, 0, &ust, &msc, &sbc); + } if (pqt->dri_prep_surf == surf) { pqt->dri_prep_surf = NULL; @@ -598,7 +600,7 @@ void pqt_prepare_dri_surface(tegra_pqt *pqt, tegra_surface *surf) } void pqt_display_surface(tegra_pqt *pqt, tegra_surface *surf, - bool update_status, bool transit) + bool update_status, bool transit, bool vsync) { tegra_device *dev = pqt->dev; @@ -618,13 +620,13 @@ void pqt_display_surface(tegra_pqt *pqt, tegra_surface *surf, dev->dri2_ready) { pqt_update_dri_buffer(pqt, surf); - pqt_display_dri(pqt, surf); + pqt_display_dri(pqt, surf, vsync); if (transit || pqt->disp_state != TEGRA_PQT_DRI) { transit_display_to_dri(pqt); } } else { - pqt_display_xv(pqt, surf, update_status); + pqt_display_xv(pqt, surf, vsync); if (transit || pqt->disp_state != TEGRA_PQT_XV) { transit_display_to_xv(pqt); @@ -671,14 +673,14 @@ static void * pqt_display_thr(void *opaque) pqt->overlapped_current = overlapped; if (pqt->disp_surf) { - pqt_display_surface(pqt, pqt->disp_surf, false, true); + pqt_display_surface(pqt, pqt->disp_surf, false, true, false); } } if (pqt->win_move) { pqt->win_move = false; if (pqt->disp_surf) { - pqt_display_surface(pqt, pqt->disp_surf, false, false); + pqt_display_surface(pqt, pqt->disp_surf, false, false, false); } } pthread_mutex_unlock(&pqt->lock); diff --git a/src/vdpau_tegra.h b/src/vdpau_tegra.h index 3bb900c..ad21d91 100644 --- a/src/vdpau_tegra.h +++ b/src/vdpau_tegra.h @@ -417,7 +417,7 @@ void set_presentation_queue_target(VdpPresentationQueueTarget target, tegra_pqt *pqt); void pqt_display_surface_to_idle_state(tegra_pqt *pqt); void pqt_display_surface(tegra_pqt *pqt, tegra_surface *surf, - bool update_status, bool transit); + bool update_status, bool transit, bool vsync); void pqt_prepare_dri_surface(tegra_pqt *pqt, tegra_surface *surf); tegra_pq * __get_presentation_queue(VdpPresentationQueue presentation_queue);