Esempio n. 1
0
bool CWinSystemX11GL::PresentRenderImpl(const CDirtyRegionList& dirty)
{
  CheckDisplayEvents();

  if(m_iVSyncMode == 3)
  {
    glFinish();
    unsigned int before = 0, after = 0;
    if(m_glXGetVideoSyncSGI(&before) != 0)
      CLog::Log(LOGERROR, "%s - glXGetVideoSyncSGI - Failed to get current retrace count", __FUNCTION__);

    glXSwapBuffers(m_dpy, m_glWindow);
    glFinish();

    if(m_glXGetVideoSyncSGI(&after) != 0)
      CLog::Log(LOGERROR, "%s - glXGetVideoSyncSGI - Failed to get current retrace count", __FUNCTION__);

    if(after == before)
      m_iVSyncErrors = 1;
    else
      m_iVSyncErrors--;

    if(m_iVSyncErrors > 0)
    {
      CLog::Log(LOGINFO, "GL: retrace count didn't change after buffer swap, switching to vsync mode 4");
      m_iVSyncErrors = 0;
      m_iVSyncMode   = 4;
    }

    if(m_iVSyncErrors < -200)
    {
      CLog::Log(LOGINFO, "GL: retrace count change for %d consecutive buffer swap, switching to vsync mode 2", -m_iVSyncErrors);
      m_iVSyncErrors = 0;
      m_iVSyncMode   = 2;
    }
  }
  else if (m_iVSyncMode == 4)
  {
    glFinish();
    unsigned int before = 0, swap = 0, after = 0;
    if(m_glXGetVideoSyncSGI(&before) != 0)
      CLog::Log(LOGERROR, "%s - glXGetVideoSyncSGI - Failed to get current retrace count", __FUNCTION__);

    if(m_glXWaitVideoSyncSGI(2, (before+1)%2, &swap) != 0)
      CLog::Log(LOGERROR, "%s - glXWaitVideoSyncSGI - Returned error", __FUNCTION__);

    glXSwapBuffers(m_dpy, m_glWindow);
    glFinish();

    if(m_glXGetVideoSyncSGI(&after) != 0)
      CLog::Log(LOGERROR, "%s - glXGetVideoSyncSGI - Failed to get current retrace count", __FUNCTION__);

    if(after == before)
      CLog::Log(LOGERROR, "%s - glXWaitVideoSyncSGI - Woke up early", __FUNCTION__);

    if(after > before + 1)
      m_iVSyncErrors++;
    else
      m_iVSyncErrors = 0;

    if(m_iVSyncErrors > 30)
    {
      CLog::Log(LOGINFO, "GL: retrace count seems to be changing due to the swapbuffers call, switching to vsync mode 3");
      m_iVSyncMode   = 3;
      m_iVSyncErrors = 0;
    }
  }
  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);
    else
      CLog::Log(LOGERROR, "%s - glXSwapBuffersMscOML - Failed to get current retrace count", __FUNCTION__);
  }
  else
    glXSwapBuffers(m_dpy, m_glWindow);

  return true;
}
Esempio n. 2
0
bool CVideoSyncGLX::Setup(PUPDATECLOCK func)
{
  CSingleLock lock(g_graphicsContext);

  m_glXWaitVideoSyncSGI = NULL;
  m_glXGetVideoSyncSGI = NULL;
  m_vInfo = NULL;
  m_Window = 0;
  m_Context = NULL;
  UpdateClock = func;

  int singleBufferAttributes[] = {
    GLX_RGBA,
    GLX_RED_SIZE,      0,
    GLX_GREEN_SIZE,    0,
    GLX_BLUE_SIZE,     0,
    None
  };

  int ReturnV, SwaMask;
  unsigned int GlxTest;
  XSetWindowAttributes Swa;

  m_vInfo = NULL;
  m_Context = NULL;
  m_Window = 0;

  CLog::Log(LOGDEBUG, "CVideoReferenceClock: Setting up GLX");

  m_winSystem.Register(this);

  m_displayLost = false;
  m_displayReset = false;
  m_lostEvent.Reset();

  if (!m_Dpy)
  {
    m_Dpy = XOpenDisplay(NULL);
    if (!m_Dpy)
    {
      CLog::Log(LOGDEBUG, "CVideoReferenceClock: Unable to open display");
      return false;
    }
  }

  if (!glXQueryExtension(m_Dpy, NULL, NULL))
  {
    CLog::Log(LOGDEBUG, "CVideoReferenceClock: X server does not support GLX");
    return false;
  }

  bool          ExtensionFound = false;
  std::istringstream Extensions(glXQueryExtensionsString(m_Dpy, m_winSystem.GetCurrentScreen()));
  std::string        ExtensionStr;

  while (!ExtensionFound)
  {
    Extensions >> ExtensionStr;
    if (Extensions.fail())
      break;

    if (ExtensionStr == "GLX_SGI_video_sync")
      ExtensionFound = true;
  }

  if (!ExtensionFound)
  {
    CLog::Log(LOGDEBUG, "CVideoReferenceClock: X server does not support GLX_SGI_video_sync");
    return false;
  }

  m_vInfo = glXChooseVisual(m_Dpy, m_winSystem.GetCurrentScreen(), singleBufferAttributes);
  if (!m_vInfo)
  {
    CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXChooseVisual returned NULL");
    return false;
  }

  Swa.border_pixel = 0;
  Swa.event_mask = StructureNotifyMask;
  Swa.colormap = XCreateColormap(m_Dpy, m_winSystem.GetWindow(), m_vInfo->visual, AllocNone );
  SwaMask = CWBorderPixel | CWColormap | CWEventMask;

  m_Window = XCreateWindow(m_Dpy, m_winSystem.GetWindow(), 0, 0, 256, 256, 0,
                           m_vInfo->depth, InputOutput, m_vInfo->visual, SwaMask, &Swa);

  m_Context = glXCreateContext(m_Dpy, m_vInfo, NULL, True);
  if (!m_Context)
  {
    CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXCreateContext returned NULL");
    return false;
  }

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

  m_glXWaitVideoSyncSGI = (int (*)(int, int, unsigned int*))glXGetProcAddress((const GLubyte*)"glXWaitVideoSyncSGI");
  if (!m_glXWaitVideoSyncSGI)
  {
    CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXWaitVideoSyncSGI not found");
    return false;
  }

  ReturnV = m_glXWaitVideoSyncSGI(2, 0, &GlxTest);
  if (ReturnV)
  {
    CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXWaitVideoSyncSGI returned %i", ReturnV);
    return false;
  }

  m_glXGetVideoSyncSGI = (int (*)(unsigned int*))glXGetProcAddress((const GLubyte*)"glXGetVideoSyncSGI");
  if (!m_glXGetVideoSyncSGI)
  {
    CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXGetVideoSyncSGI not found");
    return false;
  }

  ReturnV = m_glXGetVideoSyncSGI(&GlxTest);
  if (ReturnV)
  {
    CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXGetVideoSyncSGI returned %i", ReturnV);
    return false;
  }

  return true;
}
Esempio n. 3
0
void CGLContextGLX::SwapBuffers(int &mode)
{
  if(mode == 3)
  {
    glFinish();
    unsigned int before = 0, after = 0;
    if (m_glXGetVideoSyncSGI(&before) != 0)
      CLog::Log(LOGERROR, "%s - glXGetVideoSyncSGI - Failed to get current retrace count", __FUNCTION__);

    glXSwapBuffers(m_dpy, m_glxWindow);
    glFinish();

    if(m_glXGetVideoSyncSGI(&after) != 0)
      CLog::Log(LOGERROR, "%s - glXGetVideoSyncSGI - Failed to get current retrace count", __FUNCTION__);

    if (after == before)
      m_iVSyncErrors = 1;
    else
      m_iVSyncErrors--;

    if (m_iVSyncErrors > 0)
    {
      CLog::Log(LOGINFO, "GL: retrace count didn't change after buffer swap, switching to vsync mode 4");
      m_iVSyncErrors = 0;
      mode = 4;
    }

    if (m_iVSyncErrors < -200)
    {
      CLog::Log(LOGINFO, "GL: retrace count change for %d consecutive buffer swap, switching to vsync mode 2", -m_iVSyncErrors);
      m_iVSyncErrors = 0;
      mode = 2;
    }
  }
  else if (mode == 4)
  {
    glFinish();
    unsigned int before = 0, swap = 0, after = 0;
    if (m_glXGetVideoSyncSGI(&before) != 0)
      CLog::Log(LOGERROR, "%s - glXGetVideoSyncSGI - Failed to get current retrace count", __FUNCTION__);

    if(m_glXWaitVideoSyncSGI(2, (before+1)%2, &swap) != 0)
      CLog::Log(LOGERROR, "%s - glXWaitVideoSyncSGI - Returned error", __FUNCTION__);

    glXSwapBuffers(m_dpy, m_glxWindow);
    glFinish();

    if (m_glXGetVideoSyncSGI(&after) != 0)
      CLog::Log(LOGERROR, "%s - glXGetVideoSyncSGI - Failed to get current retrace count", __FUNCTION__);

    if (after == before)
      CLog::Log(LOGERROR, "%s - glXWaitVideoSyncSGI - Woke up early", __FUNCTION__);

    if (after > before + 1)
      m_iVSyncErrors++;
    else
      m_iVSyncErrors = 0;

    if (m_iVSyncErrors > 30)
    {
      CLog::Log(LOGINFO, "GL: retrace count seems to be changing due to the swapbuffers call, switching to vsync mode 3");
      mode = 3;
      m_iVSyncErrors = 0;
    }
  }
  else
    glXSwapBuffers(m_dpy, m_glxWindow);
}
Esempio n. 4
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);
  }
}