Sfoglia il codice sorgente

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 6 anni fa
parent
commit
97bafaa7b8
1 ha cambiato i file con 48 aggiunte e 14 eliminazioni
  1. 48 14
      src/glcontext_glx.cpp

+ 48 - 14
src/glcontext_glx.cpp

@@ -57,6 +57,32 @@ namespace bgfx { namespace gl
 		GLXContext m_context;
 		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)
 	void GlContext::create(uint32_t _width, uint32_t _height)
 	{
 	{
 		BX_UNUSED(_width, _height);
 		BX_UNUSED(_width, _height);
@@ -196,27 +222,35 @@ namespace bgfx { namespace gl
 		glXMakeCurrent(m_display, (::Window)g_platformData.nwh, m_context);
 		glXMakeCurrent(m_display, (::Window)g_platformData.nwh, m_context);
 		m_current = NULL;
 		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");
 				glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddress( (const GLubyte*)"glXSwapIntervalSGI");
 				if (NULL != glXSwapIntervalSGI)
 				if (NULL != glXSwapIntervalSGI)
 				{
 				{
 					BX_TRACE("Using glXSwapIntervalSGI.");
 					BX_TRACE("Using glXSwapIntervalSGI.");
 					glXSwapIntervalSGI(0);
 					glXSwapIntervalSGI(0);
+					foundSwapControl = true;
 				}
 				}
 			}
 			}
 		}
 		}