Plumb the ability to disable V-sync through the video renderers

This commit is contained in:
Cameron Gutman
2018-08-20 18:19:42 -07:00
parent 6b395c816f
commit f7d3c10c9d
18 changed files with 90 additions and 49 deletions
+14 -5
View File
@@ -428,7 +428,7 @@ bool DXVA2Renderer::isDecoderBlacklisted()
return result;
}
bool DXVA2Renderer::initializeDevice(SDL_Window* window)
bool DXVA2Renderer::initializeDevice(SDL_Window* window, bool enableVsync)
{
SDL_SysWMinfo info;
@@ -487,13 +487,22 @@ bool DXVA2Renderer::initializeDevice(SDL_Window* window)
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Windowed mode with DWM running");
}
else {
// Uncomposited desktop or full-screen exclusive mode
else if (enableVsync) {
// Uncomposited desktop or full-screen exclusive mode with V-sync enabled
// We will enable V-sync in this scenario to avoid tearing.
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"V-Sync enabled");
}
else {
// Uncomposited desktop or full-screen exclusive mode with V-sync disabled
// We will allowing tearing for lowest latency.
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"V-Sync disabled in tearing mode");
}
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Windowed: %d | Present Interval: %x",
@@ -540,7 +549,7 @@ bool DXVA2Renderer::initializeDevice(SDL_Window* window)
return true;
}
bool DXVA2Renderer::initialize(SDL_Window* window, int videoFormat, int width, int height, int)
bool DXVA2Renderer::initialize(SDL_Window* window, int videoFormat, int width, int height, int, bool enableVsync)
{
m_VideoFormat = videoFormat;
m_VideoWidth = width;
@@ -569,7 +578,7 @@ bool DXVA2Renderer::initialize(SDL_Window* window, int videoFormat, int width, i
m_Desc.SampleFormat.SampleFormat = DXVA2_SampleProgressiveFrame;
m_Desc.Format = (D3DFORMAT)MAKEFOURCC('N','V','1','2');
if (!initializeDevice(window)) {
if (!initializeDevice(window, enableVsync)) {
return false;
}
+3 -2
View File
@@ -19,7 +19,8 @@ public:
int videoFormat,
int width,
int height,
int maxFps);
int maxFps,
bool enableVsync);
virtual bool prepareDecoderContext(AVCodecContext* context);
virtual void renderFrameAtVsync(AVFrame* frame);
virtual bool needsTestFrame();
@@ -27,7 +28,7 @@ public:
private:
bool initializeDecoder();
bool initializeRenderer();
bool initializeDevice(SDL_Window* window);
bool initializeDevice(SDL_Window* window, bool enableVsync);
bool isDecoderBlacklisted();
static
@@ -116,9 +116,10 @@ RenderNextFrame:
av_frame_free(&frame);
}
bool Pacer::initialize(SDL_Window* window, int maxVideoFps)
bool Pacer::initialize(SDL_Window* window, int maxVideoFps, bool enableVsync)
{
m_MaxVideoFps = maxVideoFps;
m_EnableVsync = enableVsync;
int displayIndex = SDL_GetWindowDisplayIndex(window);
if (displayIndex < 0) {
@@ -136,21 +137,28 @@ bool Pacer::initialize(SDL_Window* window, int maxVideoFps)
m_DisplayFps = mode.refresh_rate;
}
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Frame pacing: target %d Hz with %d FPS stream",
m_DisplayFps, m_MaxVideoFps);
if (m_EnableVsync) {
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Frame pacing in tear-free mode: target %d Hz with %d FPS stream",
m_DisplayFps, m_MaxVideoFps);
#if defined(Q_OS_DARWIN)
m_VsyncSource = new DisplayLinkVsyncSource(this);
#elif defined(Q_OS_WIN32)
m_VsyncSource = new DxVsyncSource(this);
#else
// Platforms without a VsyncSource will just render frames
// immediately like they used to.
#endif
#if defined(Q_OS_DARWIN)
m_VsyncSource = new DisplayLinkVsyncSource(this);
#elif defined(Q_OS_WIN32)
m_VsyncSource = new DxVsyncSource(this);
#else
// Platforms without a VsyncSource will just render frames
// immediately like they used to.
#endif
if (m_VsyncSource != nullptr && !m_VsyncSource->initialize(window, m_DisplayFps)) {
return false;
if (m_VsyncSource != nullptr && !m_VsyncSource->initialize(window, m_DisplayFps)) {
return false;
}
}
else {
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Minimal latency tearing mode: target %d Hz with %d FPS stream",
m_DisplayFps, m_MaxVideoFps);
}
return true;
@@ -19,7 +19,7 @@ public:
void submitFrame(AVFrame* frame);
bool initialize(SDL_Window* window, int maxVideoFps);
bool initialize(SDL_Window* window, int maxVideoFps, bool enableVsync);
void vsyncCallback(int timeUntilNextVsyncMillis);
@@ -34,4 +34,5 @@ private:
IFFmpegRenderer* m_VsyncRenderer;
int m_MaxVideoFps;
int m_DisplayFps;
bool m_EnableVsync;
};
@@ -13,7 +13,8 @@ public:
int videoFormat,
int width,
int height,
int maxFps) = 0;
int maxFps,
bool enableVsync) = 0;
virtual bool prepareDecoderContext(AVCodecContext* context) = 0;
virtual void renderFrameAtVsync(AVFrame* frame) = 0;
virtual bool needsTestFrame() = 0;
@@ -27,7 +28,8 @@ public:
int videoFormat,
int width,
int height,
int maxFps);
int maxFps,
bool enableVsync);
virtual bool prepareDecoderContext(AVCodecContext* context);
virtual void renderFrameAtVsync(AVFrame* frame);
virtual bool needsTestFrame();
+14 -2
View File
@@ -40,9 +40,21 @@ bool SdlRenderer::initialize(SDL_Window* window,
int,
int width,
int height,
int)
int,
bool enableVsync)
{
m_Renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
Uint32 rendererFlags = SDL_RENDERER_ACCELERATED;
if ((SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN) {
// In full-screen exclusive mode, we enable V-sync if requested. For other modes, Windows and Mac
// have compositors that make rendering tear-free. Linux compositor varies by distro and user
// configuration but doesn't seem feasible to detect here.
if (enableVsync) {
rendererFlags |= SDL_RENDERER_PRESENTVSYNC;
}
}
m_Renderer = SDL_CreateRenderer(window, -1, rendererFlags);
if (!m_Renderer) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_CreateRenderer() failed: %s",
@@ -27,7 +27,7 @@ VAAPIRenderer::~VAAPIRenderer()
}
bool
VAAPIRenderer::initialize(SDL_Window* window, int, int width, int height, int)
VAAPIRenderer::initialize(SDL_Window* window, int, int width, int height, int, bool)
{
int err;
SDL_SysWMinfo info;
+2 -1
View File
@@ -34,7 +34,8 @@ public:
int videoFormat,
int width,
int height,
int maxFps);
int maxFps,
bool enableVsync);
virtual bool prepareDecoderContext(AVCodecContext* context);
virtual void renderFrameAtVsync(AVFrame* frame);
virtual bool needsTestFrame();
@@ -54,7 +54,7 @@ VDPAURenderer::~VDPAURenderer()
}
}
bool VDPAURenderer::initialize(SDL_Window* window, int, int width, int height, int)
bool VDPAURenderer::initialize(SDL_Window* window, int, int width, int height, int, bool)
{
int err;
VdpStatus status;
+2 -1
View File
@@ -17,7 +17,8 @@ public:
int videoFormat,
int width,
int height,
int maxFps);
int maxFps,
bool enableVsync);
virtual bool prepareDecoderContext(AVCodecContext* context);
virtual void renderFrameAtVsync(AVFrame* frame);
virtual bool needsTestFrame();
+2 -1
View File
@@ -101,7 +101,8 @@ public:
int videoFormat,
int,
int,
int) override
int,
bool) override
{
int err;