From b4893840eb51573f53620e087b2cd77a9d08bf2e Mon Sep 17 00:00:00 2001 From: "Pierre-Loup A. Griffais" Date: Sun, 26 Jan 2020 16:28:35 -0800 Subject: [PATCH] vblank: more tweaks, align to DRM vblank. --- src/drm.cpp | 5 +++++ src/steamcompmgr.cpp | 11 +++++------ src/vblankmanager.cpp | 40 ++++++++++++++++++++++++++++++++++++---- 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/src/drm.cpp b/src/drm.cpp index 1248f3e..2c07a42 100644 --- a/src/drm.cpp +++ b/src/drm.cpp @@ -15,6 +15,7 @@ #include "drm.hpp" #include "main.hpp" +#include "vblankmanager.hpp" #include "gpuvis_trace_utils.h" @@ -191,6 +192,8 @@ static int get_plane_id(struct drm_t *drm) static void page_flip_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data) { + vblank_mark_possible_vblank(); + // TODO: get the fbids_in_req instance from data if we ever have more than one in flight if ( s_drm_log != 0 ) @@ -444,6 +447,8 @@ int init_drm(struct drm_t *drm, const char *device, const char *mode_str, unsign g_nOutputWidth = drm->mode->hdisplay; g_nOutputHeight = drm->mode->vdisplay; + + g_nOutputRefresh = drm->mode->vrefresh; if ( g_nOutputWidth < g_nOutputHeight ) { diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index dece0c3..1d8ce38 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -2371,6 +2371,7 @@ steamcompmgr_main (int argc, char **argv) if ( ev.xclient.data.l[0] == 24 && ev.xclient.data.l[1] == 8 ) { // Message from vblankmanager + gpuvis_trace_printf( "got vblank\n" ); vblank = true; } @@ -2456,12 +2457,11 @@ steamcompmgr_main (int argc, char **argv) check_new_wayland_res(); - bool bDidRepaint = false; - if ( hasRepaint == true && vblank == true ) { paint_all(dpy); - bDidRepaint = true; + + // Consumed the need to repaint here hasRepaint = false; } @@ -2511,9 +2511,8 @@ steamcompmgr_main (int argc, char **argv) } } - // Send frame done event to all Wayland surfaces - - if ( bDidRepaint == true ) + // Ask for a new surface every vblank + if ( vblank == true ) { for (win *w = list; w; w = w->next) { diff --git a/src/vblankmanager.cpp b/src/vblankmanager.cpp index 18ee4cc..d7e12e5 100644 --- a/src/vblankmanager.cpp +++ b/src/vblankmanager.cpp @@ -3,10 +3,13 @@ #include #include #include +#include #include "X11/Xlib.h" #include "assert.h" +#include "gpuvis_trace_utils.h" + #include "vblankmanager.hpp" #include "steamcompmgr.hpp" #include "wlserver.h" @@ -15,18 +18,42 @@ static Display *g_nestedDpy; static XEvent repaintMsg; +std::mutex g_vblankLock; +std::chrono::time_point< std::chrono::system_clock > g_lastVblank; + +float g_flVblankDrawBufferMS = 5.0; + void vblankThreadRun( void ) { while ( true ) { - int usec = 1.0 / g_nOutputRefresh * 1000.0 * 1000.0; - std::chrono::system_clock::time_point timePoint = - std::chrono::system_clock::now() + std::chrono::microseconds( usec ); + std::chrono::time_point< std::chrono::system_clock > lastVblank; + int usecInterval = 1.0 / g_nOutputRefresh * 1000.0 * 1000.0; - std::this_thread::sleep_until( timePoint ); + { + std::unique_lock lock( g_vblankLock ); + lastVblank = g_lastVblank; + } + + lastVblank -= std::chrono::microseconds( (int)(g_flVblankDrawBufferMS * 1000) ); + + std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); + std::chrono::system_clock::time_point targetPoint = lastVblank + std::chrono::microseconds( usecInterval ); + + while ( targetPoint < now ) + { + targetPoint += std::chrono::microseconds( usecInterval ); + } + + std::this_thread::sleep_until( targetPoint ); XSendEvent( g_nestedDpy , DefaultRootWindow( g_nestedDpy ), True, SubstructureRedirectMask, &repaintMsg); XFlush( g_nestedDpy ); + + gpuvis_trace_printf( "sent vblank\n" ); + + // Get on the other side of it now + std::this_thread::sleep_for( std::chrono::microseconds( (int)((g_flVblankDrawBufferMS + 1.0) * 1000) ) ); } } @@ -40,6 +67,8 @@ void vblank_init( void ) repaintMsg.xclient.format = 32; repaintMsg.xclient.data.l[0] = 24; repaintMsg.xclient.data.l[1] = 8; + + g_lastVblank = std::chrono::system_clock::now(); std::thread vblankThread( vblankThreadRun ); vblankThread.detach(); @@ -47,4 +76,7 @@ void vblank_init( void ) void vblank_mark_possible_vblank( void ) { + std::unique_lock lock( g_vblankLock ); + + g_lastVblank = std::chrono::system_clock::now(); }