Permalink
Browse files

[video] schedule frames using GLX_OML_sync_control

  • Loading branch information...
elupus committed Jun 10, 2012
1 parent 20b675f commit 000034faddda5d8061fbcc433706d1a2ffc55280
Showing with 68 additions and 9 deletions.
  1. +63 −9 xbmc/windowing/X11/WinSystemX11GL.cpp
  2. +5 −0 xbmc/windowing/X11/WinSystemX11GL.h
@@ -23,6 +23,8 @@
#include "WinSystemX11GL.h"
#include "utils/log.h"
+#include "cores/dvdplayer/DVDClock.h"
+#include <time.h>
CWinSystemX11GL::CWinSystemX11GL()
{
@@ -34,12 +36,57 @@ CWinSystemX11GL::CWinSystemX11GL()
m_glXSwapBuffersMscOML = NULL;
m_iVSyncErrors = 0;
+ m_Scheduled = 0;
+ m_UstOffset = 0;
}
CWinSystemX11GL::~CWinSystemX11GL()
{
}
+bool CWinSystemX11GL::SchedulePresent(int64_t timestamp)
+{
+ if(m_iVSyncMode == 5)
+ {
+ m_Scheduled = timestamp;
+ return true;
+ }
+ return false;
+}
+
+static int64_t UstToTics(int64_t ust)
+{
+ struct timespec mon, rel;
+ clock_gettime(CLOCK_MONOTONIC, &mon);
+ clock_gettime(CLOCK_REALTIME , &rel);
+
+ /* MONOTONIC doesn't include EPOCH which REALTIME does, so difference is always huge */
+ if(std::abs(ust - mon.tv_sec * 1000000) < std::abs(ust - rel.tv_sec * 1000000))
+ return ust * 1000; /* nice UST is in monotonic tics */
+
+ ust *= 1000;
+ ust -= (rel.tv_sec - mon.tv_sec) * 1000000000;
+ ust -= (rel.tv_nsec - mon.tv_nsec);
+ return ust;
+}
+
+
+bool CWinSystemX11GL::PresentStatus(struct SPresentStatus& info)
+{
+ int64_t ust, msc, sbc;
+ if(!m_glXGetSyncValuesOML(m_dpy, m_glWindow, &ust, &msc, &sbc))
+ return false;
+ int32_t num, den;
+ if(!m_glXGetMscRateOML(m_dpy, m_glWindow, &num, &den))
+ return false;
+
+ info.vsync_count = msc;
+ info.vsync_tick = UstToTics(ust);
+ info.vsync_rate_num = num;
+ info.vsync_rate_den = den;
+ return true;
+}
+
bool CWinSystemX11GL::PresentRenderImpl(const CDirtyRegionList& dirty)
{
CheckDisplayEvents();
@@ -109,15 +156,18 @@ bool CWinSystemX11GL::PresentRenderImpl(const CDirtyRegionList& dirty)
}
else if (m_iVSyncMode == 5)
{
- int64_t ust, msc, sbc;
- if(m_glXGetSyncValuesOML(m_dpy, m_glWindow, &ust, &msc, &sbc))
- m_glXSwapBuffersMscOML(m_dpy, m_glWindow, msc, 0, 0);
+ glFlush();
+ //fprintf(stderr, "%s - glXSwapBuffersMscOML - scheduled at %"PRId64"\n", __FUNCTION__, m_Scheduled);
+ if(m_Scheduled)
+ m_glXSwapBuffersMscOML(m_dpy, m_glWindow, m_Scheduled, 0, 0);
else
- CLog::Log(LOGERROR, "%s - glXSwapBuffersMscOML - Failed to get current retrace count", __FUNCTION__);
+ m_glXSwapBuffersMscOML(m_dpy, m_glWindow, 0, 0, 0);
}
else
glXSwapBuffers(m_dpy, m_glWindow);
+ m_Scheduled = 0;
+
return true;
}
@@ -181,6 +231,7 @@ void CWinSystemX11GL::SetVSyncImpl(bool enable)
CLog::Log(LOGWARNING, "%s - glXSwapIntervalMESA failed", __FUNCTION__);
}
+ CLog::Log(LOGDEBUG, "%s - Selected vertical sync method %d", __FUNCTION__, m_iVSyncMode);
}
bool CWinSystemX11GL::IsExtSupported(const char* extension)
@@ -210,14 +261,17 @@ bool CWinSystemX11GL::CreateNewWindow(const CStdString& name, bool fullScreen, R
/* any time window is recreated we need new pointers */
if (IsExtSupported("GLX_OML_sync_control"))
- m_glXGetSyncValuesOML = (Bool (*)(Display*, GLXDrawable, int64_t*, int64_t*, int64_t*))glXGetProcAddress((const GLubyte*)"glXGetSyncValuesOML");
- else
- m_glXGetSyncValuesOML = NULL;
-
- if (IsExtSupported("GLX_OML_sync_control"))
+ {
+ m_glXGetSyncValuesOML = (Bool (*)(Display*, GLXDrawable, int64_t*, int64_t*, int64_t*))glXGetProcAddress((const GLubyte*)"glXGetSyncValuesOML");
m_glXSwapBuffersMscOML = (int64_t (*)(Display*, GLXDrawable, int64_t, int64_t, int64_t))glXGetProcAddress((const GLubyte*)"glXSwapBuffersMscOML");
+ m_glXGetMscRateOML = (Bool (*)(Display*, GLXDrawable, int32_t*, int32_t*)) glXGetProcAddress((const GLubyte*)"glXGetMscRateOML");
+ }
else
+ {
+ m_glXGetSyncValuesOML = NULL;
m_glXSwapBuffersMscOML = NULL;
+ m_glXGetMscRateOML = NULL;
+ }
if (IsExtSupported("GLX_SGI_video_sync"))
m_glXWaitVideoSyncSGI = (int (*)(int, int, unsigned int*))glXGetProcAddress((const GLubyte*)"glXWaitVideoSyncSGI");
@@ -36,6 +36,8 @@ class CWinSystemX11GL : public CWinSystemX11, public CRenderSystemGL
virtual bool SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays);
virtual bool IsExtSupported(const char* extension);
+ virtual bool SchedulePresent(int64_t timestamp);
+ virtual bool PresentStatus(SPresentStatus& info);
protected:
virtual bool PresentRenderImpl(const CDirtyRegionList& dirty);
@@ -48,10 +50,13 @@ class CWinSystemX11GL : public CWinSystemX11, public CRenderSystemGL
int (*m_glXSwapIntervalSGI)(int);
int (*m_glXSwapIntervalMESA)(int);
+ Bool (*m_glXGetMscRateOML)(Display* dpy, GLXDrawable drawable, int32_t* numerator, int32_t* denominator);
Bool (*m_glXGetSyncValuesOML)(Display* dpy, GLXDrawable drawable, int64_t* ust, int64_t* msc, int64_t* sbc);
int64_t (*m_glXSwapBuffersMscOML)(Display* dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor,int64_t remainder);
int m_iVSyncErrors;
+ int64_t m_Scheduled;
+ int64_t m_UstOffset;
};
XBMC_GLOBAL_REF(CWinSystemX11GL,g_Windowing);

0 comments on commit 000034f

Please sign in to comment.