if (vdpau)
vdpau->ReturnRenderPicture(this);
}
+
+void CVdpauRenderPicture::Sync()
+{
+#ifdef GL_ARB_sync
+ CSingleLock lock(renderPicSection);
+ if (usefence)
+ {
+ if(glIsSync(fence))
+ {
+ glDeleteSync(fence);
+ fence = None;
+ }
+ fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+ }
+#endif
+}
+
//-----------------------------------------------------------------------------
// Mixer
//-----------------------------------------------------------------------------
case COutputDataProtocol::RETURNPIC:
CVdpauRenderPicture *pic;
pic = *((CVdpauRenderPicture**)msg->data);
- ProcessReturnPicture(pic);
+ QueueReturnPicture(pic);
return;
default:
break;
case COutputDataProtocol::RETURNPIC:
CVdpauRenderPicture *pic;
pic = *((CVdpauRenderPicture**)msg->data);
- ProcessReturnPicture(pic);
+ QueueReturnPicture(pic);
m_controlPort.SendInMessage(COutputControlProtocol::STATS);
m_state = O_TOP_CONFIGURED_WORK;
m_extTimeout = 0;
switch (signal)
{
case COutputControlProtocol::TIMEOUT:
+ if (ProcessSyncPicture())
+ m_extTimeout = 10;
+ else
+ m_extTimeout = 100;
+ if (HasWork())
+ {
+ m_state = O_TOP_CONFIGURED_WORK;
+ m_extTimeout = 0;
+ }
return;
default:
break;
else
{
m_state = O_TOP_CONFIGURED_IDLE;
- m_extTimeout = 100;
+ m_extTimeout = 0;
}
return;
default:
{
CVdpauRenderPicture *pic;
pic = *((CVdpauRenderPicture**)msg->data);
- ProcessReturnPicture(pic);
+ QueueReturnPicture(pic);
}
msg->Release();
}
{
CVdpauRenderPicture *pic;
pic = *((CVdpauRenderPicture**)msg->data);
- ProcessReturnPicture(pic);
+ QueueReturnPicture(pic);
}
}
return retPic;
}
-void COutput::ProcessReturnPicture(CVdpauRenderPicture *pic)
+void COutput::QueueReturnPicture(CVdpauRenderPicture *pic)
{
std::deque<int>::iterator it;
for (it = m_bufferPool.usedRenderPics.begin(); it != m_bufferPool.usedRenderPics.end(); ++it)
if (it == m_bufferPool.usedRenderPics.end())
{
- CLog::Log(LOGWARNING, "COutput::ProcessReturnPicture - pic not found");
+ CLog::Log(LOGWARNING, "COutput::QueueReturnPicture - pic not found");
return;
}
- m_bufferPool.freeRenderPics.push_back(*it);
- m_bufferPool.usedRenderPics.erase(it);
- if (!pic->valid)
+
+ // check if already queued
+ std::deque<int>::iterator it2 = find(m_bufferPool.syncRenderPics.begin(),
+ m_bufferPool.syncRenderPics.end(),
+ *it);
+ if (it2 == m_bufferPool.syncRenderPics.end())
{
- CLog::Log(LOGDEBUG, "COutput::%s - return of invalid render pic", __FUNCTION__);
- return;
+ m_bufferPool.syncRenderPics.push_back(*it);
}
+ ProcessSyncPicture();
+}
+
+bool COutput::ProcessSyncPicture()
+{
+ CVdpauRenderPicture *pic;
+ bool busy = false;
+
+ std::deque<int>::iterator it;
+ for (it = m_bufferPool.syncRenderPics.begin(); it != m_bufferPool.syncRenderPics.end(); )
+ {
+ pic = m_bufferPool.allRenderPics[*it];
+
+#ifdef GL_ARB_sync
+ if (pic->usefence)
+ {
+ if (glIsSync(pic->fence))
+ {
+ GLint state;
+ GLsizei length;
+ glGetSynciv(pic->fence, GL_SYNC_STATUS, 1, &length, &state);
+ if(state == GL_SIGNALED)
+ {
+ glDeleteSync(pic->fence);
+ pic->fence = None;
+ }
+ else
+ {
+ busy = true;
+ ++it;
+ continue;
+ }
+ }
+ }
+#endif
+
+ m_bufferPool.freeRenderPics.push_back(*it);
+
+ std::deque<int>::iterator it2 = find(m_bufferPool.usedRenderPics.begin(),
+ m_bufferPool.usedRenderPics.end(),
+ *it);
+ if (it2 == m_bufferPool.usedRenderPics.end())
+ {
+ CLog::Log(LOGERROR, "COutput::ProcessSyncPicture - pic not found in queue");
+ }
+ else
+ {
+ m_bufferPool.usedRenderPics.erase(it2);
+ }
+ it = m_bufferPool.syncRenderPics.erase(it);
+
+ if (pic->valid)
+ {
+ ProcessReturnPicture(pic);
+ }
+ else
+ {
+ CLog::Log(LOGDEBUG, "COutput::%s - return of invalid render pic", __FUNCTION__);
+ }
+ }
+ return busy;
+}
+
+void COutput::ProcessReturnPicture(CVdpauRenderPicture *pic)
+{
if (m_config.usePixmaps)
{
m_bufferPool.pixmaps[pic->sourceIdx].used = false;
}
m_bufferPool.outputSurfaces.clear();
+ // wait for all fences
+ XbmcThreads::EndTime timeout(1000);
+ for (int i = 0; i < m_bufferPool.allRenderPics.size(); i++)
+ {
+ CVdpauRenderPicture *pic = m_bufferPool.allRenderPics[i];
+ if (pic->usefence)
+ {
+#ifdef GL_ARB_sync
+ while (glIsSync(pic->fence))
+ {
+ GLint state;
+ GLsizei length;
+ glGetSynciv(pic->fence, GL_SYNC_STATUS, 1, &length, &state);
+ if(state == GL_SIGNALED || timeout.IsTimePast())
+ {
+ glDeleteSync(pic->fence);
+ }
+ else
+ {
+ Sleep(5);
+ }
+ }
+ pic->fence = None;
+#endif
+ }
+ }
+ if (timeout.IsTimePast())
+ {
+ CLog::Log(LOGERROR, "COutput::%s - timeout waiting for fence", __FUNCTION__);
+ }
+ ProcessSyncPicture();
+
// invalidate all used render pictures
for (unsigned int i = 0; i < m_bufferPool.usedRenderPics.size(); ++i)
{
- m_bufferPool.allRenderPics[m_bufferPool.usedRenderPics[i]]->valid = false;
+ CVdpauRenderPicture *pic = m_bufferPool.allRenderPics[m_bufferPool.usedRenderPics[i]];
+ pic->valid = false;
}
}
VdpStatus vdp_st;
m_mixer.Dispose();
+ ProcessSyncPicture();
CSingleLock lock(m_bufferPool.renderPicSec);
for (unsigned int i = 0; i < m_bufferPool.outputSurfaces.size(); ++i)
CLog::Log(LOGNOTICE, "VDPAU::COutput: vdpau gl interop initialized");
}
#endif
+
+#ifdef GL_ARB_sync
+ bool hasfence = glewIsSupported("GL_ARB_sync");
+ for (unsigned int i = 0; i < m_bufferPool.allRenderPics.size(); i++)
+ {
+ m_bufferPool.allRenderPics[i]->usefence = hasfence;
+ }
+#endif
+
return true;
}