2020-01-26 22:59:51 +00:00
|
|
|
// Try to figure out when vblank is and notify steamcompmgr to render some time before it
|
|
|
|
|
|
|
|
#include <thread>
|
|
|
|
#include <vector>
|
|
|
|
#include <chrono>
|
2020-01-27 00:28:35 +00:00
|
|
|
#include <atomic>
|
2020-01-26 22:59:51 +00:00
|
|
|
|
2021-06-09 16:42:38 +00:00
|
|
|
#include <assert.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <unistd.h>
|
2020-01-26 22:59:51 +00:00
|
|
|
|
2020-01-27 00:28:35 +00:00
|
|
|
#include "gpuvis_trace_utils.h"
|
|
|
|
|
2020-01-26 22:59:51 +00:00
|
|
|
#include "vblankmanager.hpp"
|
|
|
|
#include "steamcompmgr.hpp"
|
2020-06-11 10:42:27 +00:00
|
|
|
#include "wlserver.hpp"
|
2020-01-26 22:59:51 +00:00
|
|
|
#include "main.hpp"
|
|
|
|
|
2021-06-09 16:42:38 +00:00
|
|
|
static int g_vblankPipe[2];
|
2020-01-26 22:59:51 +00:00
|
|
|
|
2020-09-05 16:53:27 +00:00
|
|
|
std::atomic<uint64_t> g_lastVblank;
|
2020-01-27 00:28:35 +00:00
|
|
|
|
2020-09-05 16:59:30 +00:00
|
|
|
uint64_t g_uVblankDrawBufferNS = 5'000'000;
|
2020-01-27 00:28:35 +00:00
|
|
|
|
2020-01-26 22:59:51 +00:00
|
|
|
void vblankThreadRun( void )
|
|
|
|
{
|
|
|
|
while ( true )
|
|
|
|
{
|
2020-09-05 16:59:30 +00:00
|
|
|
uint64_t lastVblank = g_lastVblank - g_uVblankDrawBufferNS;
|
|
|
|
uint64_t nsecInterval = 1'000'000'000ul / g_nOutputRefresh;
|
2020-01-27 00:28:35 +00:00
|
|
|
|
2020-09-15 21:46:12 +00:00
|
|
|
if ( g_nNestedRefresh != 0 )
|
|
|
|
{
|
|
|
|
nsecInterval = 1'000'000'000ul / g_nNestedRefresh;
|
|
|
|
}
|
|
|
|
|
2020-09-05 16:53:27 +00:00
|
|
|
uint64_t now = get_time_in_nanos();
|
|
|
|
uint64_t targetPoint = lastVblank + nsecInterval;
|
2020-01-27 00:28:35 +00:00
|
|
|
while ( targetPoint < now )
|
2020-09-05 16:53:27 +00:00
|
|
|
targetPoint += nsecInterval;
|
|
|
|
|
|
|
|
sleep_until_nanos( targetPoint );
|
2020-09-02 01:17:08 +00:00
|
|
|
|
|
|
|
// give the time of vblank to steamcompmgr
|
2020-09-05 16:24:20 +00:00
|
|
|
uint64_t vblanktime = get_time_in_nanos();
|
2021-06-09 16:42:38 +00:00
|
|
|
|
|
|
|
ssize_t ret = write( g_vblankPipe[ 1 ], &vblanktime, sizeof( vblanktime ) );
|
|
|
|
if ( ret <= 0 )
|
|
|
|
{
|
|
|
|
perror( "vblankmanager: write failed" );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gpuvis_trace_printf( "sent vblank" );
|
|
|
|
}
|
2020-01-27 00:28:35 +00:00
|
|
|
|
|
|
|
// Get on the other side of it now
|
2020-09-05 16:59:30 +00:00
|
|
|
sleep_for_nanos( g_uVblankDrawBufferNS + 1'000'000 );
|
2020-01-26 22:59:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-09 16:42:38 +00:00
|
|
|
int vblank_init( void )
|
2020-01-26 22:59:51 +00:00
|
|
|
{
|
2021-06-09 16:42:38 +00:00
|
|
|
if ( pipe2( g_vblankPipe, O_CLOEXEC | O_NONBLOCK ) != 0 )
|
|
|
|
{
|
|
|
|
perror( "vblankmanager: pipe failed" );
|
|
|
|
return -1;
|
|
|
|
}
|
2020-01-27 00:28:35 +00:00
|
|
|
|
2020-09-05 16:53:27 +00:00
|
|
|
g_lastVblank = get_time_in_nanos();
|
2020-01-26 22:59:51 +00:00
|
|
|
|
|
|
|
std::thread vblankThread( vblankThreadRun );
|
|
|
|
vblankThread.detach();
|
2021-06-09 16:42:38 +00:00
|
|
|
|
|
|
|
return g_vblankPipe[ 0 ];
|
2020-01-26 22:59:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void vblank_mark_possible_vblank( void )
|
|
|
|
{
|
2020-09-05 16:53:27 +00:00
|
|
|
g_lastVblank = get_time_in_nanos();
|
2020-01-26 22:59:51 +00:00
|
|
|
}
|