diff --git a/xbmc/linux/RBP.cpp b/xbmc/linux/RBP.cpp index a6d2125d1b33f..0316b17d3621c 100644 --- a/xbmc/linux/RBP.cpp +++ b/xbmc/linux/RBP.cpp @@ -66,6 +66,7 @@ CRBP::CRBP() m_enabled = 0; m_mb = mbox_open(); vcsm_init(); + m_vsync_count = 0; } CRBP::~CRBP() @@ -146,11 +147,45 @@ void CRBP::LogFirmwareVerison() CLog::Log(LOGNOTICE, "Config:\n%s", response); } +static void vsync_callback_static(DISPMANX_UPDATE_HANDLE_T u, void *arg) +{ + CRBP *rbp = reinterpret_cast(arg); + rbp->VSyncCallback(); +} + +void CRBP::VSyncCallback() +{ + CSingleLock lock(m_vsync_lock); + m_vsync_count++; + m_vsync_cond.notifyAll(); +} + +unsigned int CRBP::WaitVsync(unsigned int target) +{ + CSingleLock lock(m_vsync_lock); + if (target == ~0U) + target = m_vsync_count+1; + + if (m_display == DISPMANX_NO_HANDLE) + { + CLog::Log(LOGDEBUG, "CRBP::%s skipping while display closed", __func__); + return m_vsync_count; + } + + while (m_vsync_count < target) + if (!m_vsync_cond.wait(lock, 100)) + break; + + return m_vsync_count; +} + DISPMANX_DISPLAY_HANDLE_T CRBP::OpenDisplay(uint32_t device) { if (m_display == DISPMANX_NO_HANDLE) { m_display = vc_dispmanx_display_open( 0 /*screen*/ ); + int s = vc_dispmanx_vsync_callback(m_display, vsync_callback_static, (void *)this); + assert(s == 0); init_cursor(); } return m_display; @@ -159,9 +194,11 @@ DISPMANX_DISPLAY_HANDLE_T CRBP::OpenDisplay(uint32_t device) void CRBP::CloseDisplay(DISPMANX_DISPLAY_HANDLE_T display) { assert(display == m_display); + int s = vc_dispmanx_vsync_callback(m_display, NULL, NULL); + assert(s == 0); + uninit_cursor(); vc_dispmanx_display_close(m_display); m_display = DISPMANX_NO_HANDLE; - uninit_cursor(); } void CRBP::GetDisplaySize(int &width, int &height) @@ -214,35 +251,6 @@ unsigned char *CRBP::CaptureDisplay(int width, int height, int *pstride, bool sw return image; } - -static void vsync_callback(DISPMANX_UPDATE_HANDLE_T u, void *arg) -{ - CEvent *sync = (CEvent *)arg; - sync->Set(); -} - -void CRBP::WaitVsync() -{ - int s; - DISPMANX_DISPLAY_HANDLE_T m_display = vc_dispmanx_display_open( 0 /*screen*/ ); - if (m_display == DISPMANX_NO_HANDLE) - { - CLog::Log(LOGDEBUG, "CRBP::%s skipping while display closed", __func__); - return; - } - m_vsync.Reset(); - s = vc_dispmanx_vsync_callback(m_display, vsync_callback, (void *)&m_vsync); - if (s == 0) - { - m_vsync.WaitMSec(1000); - } - else assert(0); - s = vc_dispmanx_vsync_callback(m_display, NULL, NULL); - assert(s == 0); - vc_dispmanx_display_close( m_display ); -} - - void CRBP::Deinitialize() { if (m_omx_image_init) diff --git a/xbmc/linux/RBP.h b/xbmc/linux/RBP.h index e938a3ab1c719..81d6db6c5335f 100644 --- a/xbmc/linux/RBP.h +++ b/xbmc/linux/RBP.h @@ -65,7 +65,8 @@ class CRBP // stride can be null for packed output unsigned char *CaptureDisplay(int width, int height, int *stride, bool swap_red_blue, bool video_only = true); DllOMX *GetDllOMX() { return m_OMX ? m_OMX->GetDll() : NULL; } - void WaitVsync(); + unsigned int WaitVsync(unsigned int target = ~0U); + void VSyncCallback(); void SuspendVideoOutput(); void ResumeVideoOutput(); @@ -82,7 +83,9 @@ class CRBP bool m_codec_wvc1_enabled; COMXCore *m_OMX; DISPMANX_DISPLAY_HANDLE_T m_display; - CEvent m_vsync; + CCriticalSection m_vsync_lock; + XbmcThreads::ConditionVariable m_vsync_cond; + unsigned int m_vsync_count; class DllLibOMXCore; CCriticalSection m_critSection;