[videodb] remove unused seasons table from episode_view
[xbmc.git] / xbmc / windowing / X11 / VideoSyncGLX.cpp
blob06b839a75f49e8ec39ecea0a90edc9d142df4014
1 /*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "VideoSyncGLX.h"
11 #include "cores/VideoPlayer/VideoReferenceClock.h"
12 #include "utils/TimeUtils.h"
13 #include "utils/XTimeUtils.h"
14 #include "utils/log.h"
15 #include "windowing/GraphicContext.h"
16 #include "windowing/X11/WinSystemX11GLContext.h"
18 #include <mutex>
19 #include <sstream>
21 #include <X11/extensions/Xrandr.h>
23 using namespace KODI::WINDOWING::X11;
25 using namespace std::chrono_literals;
27 Display* CVideoSyncGLX::m_Dpy = NULL;
29 void CVideoSyncGLX::OnLostDisplay()
31 if (!m_displayLost)
33 m_displayLost = true;
34 m_lostEvent.Wait();
38 void CVideoSyncGLX::OnResetDisplay()
40 m_displayReset = true;
43 bool CVideoSyncGLX::Setup()
45 std::unique_lock<CCriticalSection> lock(m_winSystem.GetGfxContext());
47 m_glXWaitVideoSyncSGI = NULL;
48 m_glXGetVideoSyncSGI = NULL;
49 m_vInfo = NULL;
50 m_Window = 0;
51 m_Context = NULL;
53 int singleBufferAttributes[] = {
54 GLX_RGBA,
55 GLX_RED_SIZE, 0,
56 GLX_GREEN_SIZE, 0,
57 GLX_BLUE_SIZE, 0,
58 None
61 int ReturnV, SwaMask;
62 unsigned int GlxTest;
63 XSetWindowAttributes Swa;
65 m_vInfo = NULL;
66 m_Context = NULL;
67 m_Window = 0;
69 CLog::Log(LOGDEBUG, "CVideoReferenceClock: Setting up GLX");
71 static_cast<CWinSystemX11*>(&m_winSystem)->Register(this);
73 m_displayLost = false;
74 m_displayReset = false;
75 m_lostEvent.Reset();
77 if (!m_Dpy)
79 m_Dpy = XOpenDisplay(NULL);
80 if (!m_Dpy)
82 CLog::Log(LOGDEBUG, "CVideoReferenceClock: Unable to open display");
83 return false;
87 if (!glXQueryExtension(m_Dpy, NULL, NULL))
89 CLog::Log(LOGDEBUG, "CVideoReferenceClock: X server does not support GLX");
90 return false;
93 bool ExtensionFound = false;
94 std::istringstream Extensions(glXQueryExtensionsString(m_Dpy, m_winSystem.GetScreen()));
95 std::string ExtensionStr;
97 while (!ExtensionFound)
99 Extensions >> ExtensionStr;
100 if (Extensions.fail())
101 break;
103 if (ExtensionStr == "GLX_SGI_video_sync")
104 ExtensionFound = true;
107 if (!ExtensionFound)
109 CLog::Log(LOGDEBUG, "CVideoReferenceClock: X server does not support GLX_SGI_video_sync");
110 return false;
113 m_vInfo = glXChooseVisual(m_Dpy, m_winSystem.GetScreen(), singleBufferAttributes);
114 if (!m_vInfo)
116 CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXChooseVisual returned NULL");
117 return false;
120 Swa.border_pixel = 0;
121 Swa.event_mask = StructureNotifyMask;
122 Swa.colormap = XCreateColormap(m_Dpy, m_winSystem.GetWindow(), m_vInfo->visual, AllocNone );
123 SwaMask = CWBorderPixel | CWColormap | CWEventMask;
125 m_Window = XCreateWindow(m_Dpy, m_winSystem.GetWindow(), 0, 0, 256, 256, 0,
126 m_vInfo->depth, InputOutput, m_vInfo->visual, SwaMask, &Swa);
128 m_Context = glXCreateContext(m_Dpy, m_vInfo, NULL, True);
129 if (!m_Context)
131 CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXCreateContext returned NULL");
132 return false;
135 ReturnV = glXMakeCurrent(m_Dpy, m_Window, m_Context);
136 if (ReturnV != True)
138 CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXMakeCurrent returned {}", ReturnV);
139 return false;
142 m_glXWaitVideoSyncSGI = (int (*)(int, int, unsigned int*))glXGetProcAddress((const GLubyte*)"glXWaitVideoSyncSGI");
143 if (!m_glXWaitVideoSyncSGI)
145 CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXWaitVideoSyncSGI not found");
146 return false;
149 ReturnV = m_glXWaitVideoSyncSGI(2, 0, &GlxTest);
150 if (ReturnV)
152 CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXWaitVideoSyncSGI returned {}", ReturnV);
153 return false;
156 m_glXGetVideoSyncSGI = (int (*)(unsigned int*))glXGetProcAddress((const GLubyte*)"glXGetVideoSyncSGI");
157 if (!m_glXGetVideoSyncSGI)
159 CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXGetVideoSyncSGI not found");
160 return false;
163 ReturnV = m_glXGetVideoSyncSGI(&GlxTest);
164 if (ReturnV)
166 CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXGetVideoSyncSGI returned {}", ReturnV);
167 return false;
170 return true;
173 void CVideoSyncGLX::Run(CEvent& stopEvent)
175 unsigned int PrevVblankCount;
176 unsigned int VblankCount;
177 int ReturnV;
178 bool IsReset = false;
179 int64_t Now;
181 //get the current vblank counter
182 m_glXGetVideoSyncSGI(&VblankCount);
183 PrevVblankCount = VblankCount;
185 while(!stopEvent.Signaled() && !m_displayLost && !m_displayReset)
187 //wait for the next vblank
188 ReturnV = m_glXWaitVideoSyncSGI(2, (VblankCount + 1) % 2, &VblankCount);
189 m_glXGetVideoSyncSGI(&VblankCount); //the vblank count returned by glXWaitVideoSyncSGI is not always correct
190 Now = CurrentHostCounter(); //get the timestamp of this vblank
192 if(ReturnV)
194 CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXWaitVideoSyncSGI returned {}", ReturnV);
195 return;
198 if (VblankCount > PrevVblankCount)
200 m_refClock->UpdateClock((int)(VblankCount - PrevVblankCount), Now);
201 IsReset = false;
203 else
205 CLog::Log(LOGDEBUG, "CVideoReferenceClock: Vblank counter has reset");
207 //only try reattaching once
208 if (IsReset)
209 return;
211 //because of a bug in the nvidia driver, glXWaitVideoSyncSGI breaks when the vblank counter resets
212 CLog::Log(LOGDEBUG, "CVideoReferenceClock: Detaching glX context");
213 ReturnV = glXMakeCurrent(m_Dpy, None, NULL);
214 if (ReturnV != True)
216 CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXMakeCurrent returned {}", ReturnV);
217 return;
220 //sleep here so we don't busy spin when this constantly happens, for example when the display went to sleep
221 KODI::TIME::Sleep(1s);
223 CLog::Log(LOGDEBUG, "CVideoReferenceClock: Attaching glX context");
224 ReturnV = glXMakeCurrent(m_Dpy, m_Window, m_Context);
225 if (ReturnV != True)
227 CLog::Log(LOGDEBUG, "CVideoReferenceClock: glXMakeCurrent returned {}", ReturnV);
228 return;
231 m_glXGetVideoSyncSGI(&VblankCount);
233 IsReset = true;
235 PrevVblankCount = VblankCount;
237 m_lostEvent.Set();
238 while(!stopEvent.Signaled() && m_displayLost && !m_displayReset)
240 KODI::TIME::Sleep(10ms);
244 void CVideoSyncGLX::Cleanup()
246 CLog::Log(LOGDEBUG, "CVideoReferenceClock: Cleaning up GLX");
249 std::unique_lock<CCriticalSection> lock(m_winSystem.GetGfxContext());
251 if (m_vInfo)
253 XFree(m_vInfo);
254 m_vInfo = NULL;
256 if (m_Context)
258 glXMakeCurrent(m_Dpy, None, NULL);
259 glXDestroyContext(m_Dpy, m_Context);
260 m_Context = NULL;
262 if (m_Window)
264 XDestroyWindow(m_Dpy, m_Window);
265 m_Window = 0;
269 m_lostEvent.Set();
270 m_winSystem.Unregister(this);
273 float CVideoSyncGLX::GetFps()
275 m_fps = m_winSystem.GetGfxContext().GetFPS();
276 return m_fps;