Procházet zdrojové kódy

Check for GLX vblank extensions more properly.

Previously, the code checked for an extension by checking if the pointer returned from
glXGetProcAddress was NULL or not.

But in truth, you can get a non-NULL pointer even if that extension is not supported.
Now, we parse the glXQueryExtensionsString() results.

GLFW code that does similar checks, for reference: https://github.com/glfw/glfw/blob/51bb76c7c3de934b2dd3affcdc297a32e4817835/src/glx_context.c#L208

fixes #1367
JW před 6 roky
rodič
revize
97bafaa7b8
1 změnil soubory, kde provedl 48 přidání a 14 odebrání
  1. 48 14
      src/glcontext_glx.cpp

+ 48 - 14
src/glcontext_glx.cpp

@@ -57,6 +57,32 @@ namespace bgfx { namespace gl
 		GLXContext m_context;
 	};
 
+	static bool haveGlxExtension(const char* _ext, const char* _extList)
+	{
+		// _extList is assumed to be a space-separated, null-terminated list of
+		// extension names, and no extension name ever contains a space.
+		const char* end = _extList + bx::strLen(_extList);
+		const char* searchStart = _extList;
+		for(;;)
+		{
+			bx::StringView found = bx::strFind(searchStart, _ext);
+			if (found.isEmpty())
+			{
+				return false;
+			}
+
+			// We found the substring, but need an exact match, with a word
+			// boundary at both the front and back of the found spot.
+			if ((found.getPtr() == _extList || *(found.getPtr() - 1) == ' ')
+			&&  (found.getTerm() == end || *found.getTerm() == ' '))
+			{
+				return true;
+			}
+			// else, keep searching
+			searchStart = found.getTerm();
+		}
+	}
+
 	void GlContext::create(uint32_t _width, uint32_t _height)
 	{
 		BX_UNUSED(_width, _height);
@@ -196,27 +222,35 @@ namespace bgfx { namespace gl
 		glXMakeCurrent(m_display, (::Window)g_platformData.nwh, m_context);
 		m_current = NULL;
 
-		glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddress( (const GLubyte*)"glXSwapIntervalEXT");
-		if (NULL != glXSwapIntervalEXT)
+		const char* extensions = glXQueryExtensionsString(m_display, DefaultScreen(m_display));
+		if (NULL != extensions)
 		{
-			BX_TRACE("Using glXSwapIntervalEXT.");
-			glXSwapIntervalEXT(m_display, (::Window)g_platformData.nwh, 0);
-		}
-		else
-		{
-			glXSwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC)glXGetProcAddress( (const GLubyte*)"glXSwapIntervalMESA");
-			if (NULL != glXSwapIntervalMESA)
-			{
-				BX_TRACE("Using glXSwapIntervalMESA.");
-				glXSwapIntervalMESA(0);
+			bool foundSwapControl = false;
+			if (haveGlxExtension("GLX_EXT_swap_control", extensions)) {
+				glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddress( (const GLubyte*)"glXSwapIntervalEXT");
+				if (NULL != glXSwapIntervalEXT)
+				{
+					BX_TRACE("Using glXSwapIntervalEXT.");
+					glXSwapIntervalEXT(m_display, (::Window)g_platformData.nwh, 0);
+					foundSwapControl = true;
+				}
 			}
-			else
-			{
+			if (!foundSwapControl && haveGlxExtension("GLX_MESA_swap_control", extensions)) {
+				glXSwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC)glXGetProcAddress( (const GLubyte*)"glXSwapIntervalMESA");
+				if (NULL != glXSwapIntervalMESA)
+				{
+					BX_TRACE("Using glXSwapIntervalMESA.");
+					glXSwapIntervalMESA(0);
+					foundSwapControl = true;
+				}
+			}
+			if (!foundSwapControl && haveGlxExtension("GLX_SGI_swap_control", extensions)) {
 				glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddress( (const GLubyte*)"glXSwapIntervalSGI");
 				if (NULL != glXSwapIntervalSGI)
 				{
 					BX_TRACE("Using glXSwapIntervalSGI.");
 					glXSwapIntervalSGI(0);
+					foundSwapControl = true;
 				}
 			}
 		}