From 7acfd5191daa1a0c9032e6bc31f664606346a759 Mon Sep 17 00:00:00 2001
From: Daniel Elstner <danielk@openismus.com>
Date: Thu, 12 Nov 2009 12:24:23 +0200
Subject: [PATCH 2/2] Parse the GLX extension string correctly

* src/opengl/qgl_x11.cpp (parse_extensions_string): New local utility
function for checking for the presence of an OpenGL or GLX extension
by name in a space-separated list of supported extensions.
(qglx_getProcAddress), (QGLContext::chooseContext),
(QGLContext::tryVisual), (QGLContext::swapBuffers),
(QGLContext::getProcAddress), (qt_resolveTextureFromPixmap): Call
parse_extensions_string() to check for GLX extensions.
---
 src/opengl/qgl_x11.cpp |   54 +++++++++++++++++++++++++++++++++++------------
 1 files changed, 40 insertions(+), 14 deletions(-)

diff --git a/src/opengl/qgl_x11.cpp b/src/opengl/qgl_x11.cpp
index e05cd0a..5925a3a 100644
--- a/src/opengl/qgl_x11.cpp
+++ b/src/opengl/qgl_x11.cpp
@@ -86,6 +86,9 @@
 #include <dlfcn.h>
 #endif
 
+#include <cstdlib>
+#include <cstring>
+
 QT_BEGIN_NAMESPACE
 
 extern Drawable qt_x11Handle(const QPaintDevice *pd);
@@ -332,6 +335,28 @@ static void find_trans_colors()
   QGLFormat UNIX/GLX-specific code
  *****************************************************************************/
 
+static bool parse_extensions_string(const char* extensions, const char* name)
+{
+  const size_t name_length = (name) ? strlen(name) : 0;
+
+  Q_ASSERT(name_length > 0);
+
+  if (extensions) {
+    const char* pos = extensions;
+
+    while (const char *const space = strchr(pos, ' ')) {
+      const size_t length = space - pos;
+
+      if (length == name_length && memcmp(pos, name, length) == 0)
+        return true;
+
+      pos = space + 1;
+    }
+    return (strcmp(pos, name) == 0);
+  }
+  return false;
+}
+
 void* qglx_getProcAddress(const char* procName)
 {
     // On systems where the GL driver is pluggable (like Mesa), we have to use
@@ -343,8 +368,8 @@ void* qglx_getProcAddress(const char* procName)
     static bool triedResolvingGlxGetProcAddress = false;
     if (!triedResolvingGlxGetProcAddress) {
         triedResolvingGlxGetProcAddress = true;
-        QString glxExt = QLatin1String(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS));
-        if (glxExt.contains(QLatin1String("GLX_ARB_get_proc_address"))) {
+        const char *const glxExt = glXGetClientString(QX11Info::display(), GLX_EXTENSIONS);
+        if (parse_extensions_string(glxExt, "GLX_ARB_get_proc_address")) {
 #if defined(Q_OS_LINUX) || defined(Q_OS_BSD4)
             void *handle = dlopen(NULL, RTLD_LAZY);
             if (handle) {
@@ -523,9 +548,9 @@ bool QGLContext::chooseContext(const QGLContext* shareContext)
         if (!d->gpm)
             return false;
     }
-    QString glxExt = QLatin1String(glXQueryExtensionsString(
-        qt_x11Info(d->paintDevice)->display(), qt_x11Info(d->paintDevice)->screen()));
-    if (glxExt.contains(QLatin1String("GLX_SGI_video_sync"))) {
+    const char *const glxExt = glXQueryExtensionsString(
+        qt_x11Info(d->paintDevice)->display(), qt_x11Info(d->paintDevice)->screen());
+    if (parse_extensions_string(glxExt, "GLX_SGI_video_sync")) {
         if (d->glFormat.swapInterval() == -1)
             d->glFormat.setSwapInterval(0);
     } else {
@@ -631,8 +656,9 @@ void *QGLContext::tryVisual(const QGLFormat& f, int bufDepth)
     static bool useTranspExt = false;
     static bool useTranspExtChecked = false;
     if (f.plane() && !useTranspExtChecked && d->paintDevice) {
-        QByteArray estr(glXQueryExtensionsString(xinfo->display(), xinfo->screen()));
-        useTranspExt = estr.contains("GLX_EXT_visual_info");
+        const char *const estr =
+            glXQueryExtensionsString(xinfo->display(), xinfo->screen());
+        useTranspExt = parse_extensions_string(estr, "GLX_EXT_visual_info");
         //# (A bit simplistic; that could theoretically be a substring)
         if (useTranspExt) {
             QByteArray cstr(glXGetClientString(xinfo->display(), GLX_VENDOR));
@@ -875,9 +901,9 @@ void QGLContext::swapBuffers() const
             static qt_glXWaitVideoSyncSGI glXWaitVideoSyncSGI = 0;
             static bool resolved = false;
             if (!resolved) {
-                QString glxExt = QLatin1String(glXQueryExtensionsString(
-                    qt_x11Info(d->paintDevice)->display(), qt_x11Info(d->paintDevice)->screen()));
-                if (glxExt.contains(QLatin1String("GLX_SGI_video_sync"))) {
+                const char *const glxExt = glXQueryExtensionsString(
+                    qt_x11Info(d->paintDevice)->display(), qt_x11Info(d->paintDevice)->screen());
+                if (parse_extensions_string(glxExt, "GLX_SGI_video_sync")) {
                     glXGetVideoSyncSGI =  (qt_glXGetVideoSyncSGI)qglx_getProcAddress("glXGetVideoSyncSGI");
                     glXWaitVideoSyncSGI = (qt_glXWaitVideoSyncSGI)qglx_getProcAddress("glXWaitVideoSyncSGI");
                 }
@@ -1108,8 +1134,8 @@ void *QGLContext::getProcAddress(const QString &proc) const
     if (resolved && !glXGetProcAddressARB)
         return 0;
     if (!glXGetProcAddressARB) {
-        QString glxExt = QLatin1String(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS));
-        if (glxExt.contains(QLatin1String("GLX_ARB_get_proc_address"))) {
+        const char *const glxExt = glXGetClientString(QX11Info::display(), GLX_EXTENSIONS);
+        if (parse_extensions_string(glxExt, "GLX_ARB_get_proc_address")) {
 #if defined(Q_OS_LINUX) || defined(Q_OS_BSD4)
             void *handle = dlopen(NULL, RTLD_LAZY);
             if (handle) {
@@ -1611,8 +1637,8 @@ bool qt_resolveTextureFromPixmap()
         }
 
         // FIXME: should supply correct display and screen
-        QString glxExt = QLatin1String(glXQueryExtensionsString(QX11Info::display(), 0));
-        if (glxExt.contains(QLatin1String("GLX_EXT_texture_from_pixmap"))) {
+        const char *const glxExt = glXQueryExtensionsString(QX11Info::display(), 0);
+        if (parse_extensions_string(glxExt, "GLX_EXT_texture_from_pixmap")) {
             glXBindTexImageEXT = (qt_glXBindTexImageEXT) qglx_getProcAddress("glXBindTexImageEXT");
             glXReleaseTexImageEXT = (qt_glXReleaseTexImageEXT) qglx_getProcAddress("glXReleaseTexImageEXT");
         }
-- 
1.6.3.3

