Esempio n. 1
0
void CVideoSyncD3D::Run(CEvent& stopEvent)
{
  int64_t Now;
  int64_t LastVBlankTime;
  int NrVBlanks;
  double VBlankTime;
  int64_t systemFrequency = CurrentHostFrequency();

  // init the vblanktime
  Now = CurrentHostCounter();
  LastVBlankTime = Now;
  m_lastUpdateTime = Now - systemFrequency;
  while (!stopEvent.Signaled() && !m_displayLost && !m_displayReset)
  {
    // sleep until vblank
    Microsoft::WRL::ComPtr<IDXGIOutput> pOutput;
    DX::DeviceResources::Get()->GetOutput(&pOutput);
    HRESULT hr = pOutput->WaitForVBlank();

    // calculate how many vblanks happened
    Now = CurrentHostCounter();
    VBlankTime = (double)(Now - LastVBlankTime) / (double)systemFrequency;
    NrVBlanks = MathUtils::round_int(VBlankTime * m_fps);

    // update the vblank timestamp, update the clock and send a signal that we got a vblank
    UpdateClock(NrVBlanks, Now, m_refClock);

    // save the timestamp of this vblank so we can calculate how many vblanks happened next time
    LastVBlankTime = Now;

    if ((Now - m_lastUpdateTime) >= systemFrequency)
    {
      float fps = m_fps;
      if (fps != GetFps())
        break;
    }

    // because we had a vblank, sleep until half the refreshrate period because i think WaitForVBlank block any rendering stuf
    // without sleeping we have freeze rendering
    int SleepTime = (int)((LastVBlankTime + (systemFrequency / MathUtils::round_int(m_fps) / 2) - Now) * 1000 / systemFrequency);
    if (SleepTime > 50)
      SleepTime = 50; //failsafe
    if (SleepTime > 0)
      ::Sleep(SleepTime);
  }

  m_lostEvent.Set();
  while (!stopEvent.Signaled() && m_displayLost && !m_displayReset)
  {
    Sleep(10);
  }
}
Esempio n. 2
0
void CVideoSyncAML::Run(CEvent& stopEvent)
{
  // We use the wall clock for timout handling (no AML h/w, startup)
  std::chrono::time_point<std::chrono::system_clock> now(std::chrono::system_clock::now());
  unsigned int waittime (3000 / m_fps);
  uint64_t numVBlanks (0);

  /* This shouldn't be very busy and timing is important so increase priority */
  CThread::GetCurrentThread()->SetPriority(CThread::GetCurrentThread()->GetPriority() + 1);

  while (!stopEvent.Signaled() && !m_abort)
  {
    int countVSyncs(1);
    if( !g_aml_sync_event.WaitMSec(waittime))
    {
      std::chrono::milliseconds elapsed(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - now).count());
      uint64_t curVBlanks = (m_fps * elapsed.count()) / 1000;
      int64_t lastVBlankTime((curVBlanks * 1000) / m_fps);
      if (elapsed.count() > lastVBlankTime)
      {
        lastVBlankTime = (++curVBlanks * 1000) / m_fps;
        std::this_thread::sleep_for(std::chrono::milliseconds(lastVBlankTime - elapsed.count()));
      }
      countVSyncs = curVBlanks - numVBlanks;
      numVBlanks = curVBlanks;
    }
    else
      ++numVBlanks;

    uint64_t now = CurrentHostCounter();

    UpdateClock(countVSyncs, now, m_refClock);
  }
}
Esempio n. 3
0
void CVideoSyncGLX::Run(CEvent& stopEvent)
{
  unsigned int  PrevVblankCount;
  unsigned int  VblankCount;
  int           ReturnV;
  bool          IsReset = false;
  int64_t       Now;

  //get the current vblank counter
  m_glXGetVideoSyncSGI(&VblankCount);
  PrevVblankCount = VblankCount;

  while(!stopEvent.Signaled() && !m_displayLost && !m_displayReset)
  {
    //wait for the next vblank
    ReturnV = m_glXWaitVideoSyncSGI(2, (VblankCount + 1) % 2, &VblankCount);
    m_glXGetVideoSyncSGI(&VblankCount); //the vblank count returned by glXWaitVideoSyncSGI is not always correct
    Now = CurrentHostCounter();         //get the timestamp of this vblank

    if(ReturnV)
    {
      CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXWaitVideoSyncSGI returned %i", ReturnV);
      return;
    }

    if (VblankCount > PrevVblankCount)
    {
      UpdateClock((int)(VblankCount - PrevVblankCount), Now, m_refClock);
      IsReset = false;
    }
    else
    {
      CLog::Log(LOGDEBUG, "CVideoReferenceClock: Vblank counter has reset");

      //only try reattaching once
      if (IsReset)
        return;

      //because of a bug in the nvidia driver, glXWaitVideoSyncSGI breaks when the vblank counter resets
      CLog::Log(LOGDEBUG, "CVideoReferenceClock: Detaching glX context");
      ReturnV = glXMakeCurrent(m_Dpy, None, NULL);
      if (ReturnV != True)
      {
        CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXMakeCurrent returned %i", ReturnV);
        return;
      }

      //sleep here so we don't busy spin when this constantly happens, for example when the display went to sleep
      Sleep(1000);

      CLog::Log(LOGDEBUG, "CVideoReferenceClock: Attaching glX context");
      ReturnV = glXMakeCurrent(m_Dpy, m_Window, m_Context);
      if (ReturnV != True)
      {
        CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXMakeCurrent returned %i", ReturnV);
        return;
      }

      m_glXGetVideoSyncSGI(&VblankCount);

      IsReset = true;
    }
    PrevVblankCount = VblankCount;
  }
  m_lostEvent.Set();
  while(!stopEvent.Signaled() && m_displayLost && !m_displayReset)
  {
    Sleep(10);
  }
}