[Mesa-dev] [PATCH] egl: Create queryable strings in eglInitialize().

Matt Turner mattst88 at gmail.com
Tue Mar 10 17:20:08 PDT 2015


Creating/recreating the strings in eglQueryString() is extra work and
isn't thread-safe, as exhibited by shader-db's run.c using libepoxy.

Multiple threads in run.c call eglReleaseThread() around the same time.
libepoxy calls eglQueryString() to determine whether eglReleaseThread()
exists, and our EGL implementation passes a pointer to the version
string to libepoxy while simultaneously overwriting the string, leading
to a failure in libepoxy.

Moreover, the EGL spec says (emphasis mine):

"eglQueryString returns a pointer to a *static*, zero-terminated string"

This patch moves some auxiliary functions from eglmisc.c to eglapi.c so
that they may be used to create the extension, API, and version strings
once during eglInitialize(). The auxiliary functions are renamed from
_eglUpdate* to _eglCreate*, and some checks made unnecessary by calling
the functions from eglInitialize() are removed.

It was suggested to me to simply make the generation of the version
string behave like that of the extension and API strings -- to do a
check like

   if (exts[0])
      return;

before creating the string, but that is not thread-safe either.
---
 src/egl/main/eglapi.c  | 112 ++++++++++++++++++++++++++++++++++++++++++++
 src/egl/main/eglmisc.c | 125 -------------------------------------------------
 2 files changed, 112 insertions(+), 125 deletions(-)

diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index 2258830..cb4475e 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -100,6 +100,7 @@
 #include "eglmode.h"
 #include "eglimage.h"
 #include "eglsync.h"
+#include "eglstring.h"
 
 
 /**
@@ -341,6 +342,111 @@ eglGetPlatformDisplayEXT(EGLenum platform, void *native_display,
 }
 
 /**
+ * Copy the extension into the string and update the string pointer.
+ */
+static EGLint
+_eglAppendExtension(char **str, const char *ext)
+{
+   char *s = *str;
+   size_t len = strlen(ext);
+
+   if (s) {
+      memcpy(s, ext, len);
+      s[len++] = ' ';
+      s[len] = '\0';
+
+      *str += len;
+   }
+   else {
+      len++;
+   }
+
+   return (EGLint) len;
+}
+
+/**
+ * Examine the individual extension enable/disable flags and recompute
+ * the driver's Extensions string.
+ */
+static void
+_eglCreateExtensionsString(_EGLDisplay *dpy)
+{
+#define _EGL_CHECK_EXTENSION(ext)                                          \
+   do {                                                                    \
+      if (dpy->Extensions.ext) {                                           \
+         _eglAppendExtension(&exts, "EGL_" #ext);                          \
+         assert(exts <= dpy->ExtensionsString + _EGL_MAX_EXTENSIONS_LEN);  \
+      }                                                                    \
+   } while (0)
+
+   char *exts = dpy->ExtensionsString;
+
+   _EGL_CHECK_EXTENSION(MESA_screen_surface);
+   _EGL_CHECK_EXTENSION(MESA_copy_context);
+   _EGL_CHECK_EXTENSION(MESA_drm_display);
+   _EGL_CHECK_EXTENSION(MESA_drm_image);
+   _EGL_CHECK_EXTENSION(MESA_configless_context);
+
+   _EGL_CHECK_EXTENSION(WL_bind_wayland_display);
+   _EGL_CHECK_EXTENSION(WL_create_wayland_buffer_from_image);
+
+   _EGL_CHECK_EXTENSION(KHR_image_base);
+   _EGL_CHECK_EXTENSION(KHR_image_pixmap);
+   if (dpy->Extensions.KHR_image_base && dpy->Extensions.KHR_image_pixmap)
+      _eglAppendExtension(&exts, "EGL_KHR_image");
+
+   _EGL_CHECK_EXTENSION(KHR_vg_parent_image);
+   _EGL_CHECK_EXTENSION(KHR_get_all_proc_addresses);
+   _EGL_CHECK_EXTENSION(KHR_gl_texture_2D_image);
+   _EGL_CHECK_EXTENSION(KHR_gl_texture_cubemap_image);
+   _EGL_CHECK_EXTENSION(KHR_gl_texture_3D_image);
+   _EGL_CHECK_EXTENSION(KHR_gl_renderbuffer_image);
+
+   _EGL_CHECK_EXTENSION(KHR_reusable_sync);
+   _EGL_CHECK_EXTENSION(KHR_fence_sync);
+
+   _EGL_CHECK_EXTENSION(KHR_surfaceless_context);
+   _EGL_CHECK_EXTENSION(KHR_create_context);
+
+   _EGL_CHECK_EXTENSION(NOK_swap_region);
+   _EGL_CHECK_EXTENSION(NOK_texture_from_pixmap);
+
+   _EGL_CHECK_EXTENSION(ANDROID_image_native_buffer);
+
+   _EGL_CHECK_EXTENSION(CHROMIUM_sync_control);
+
+   _EGL_CHECK_EXTENSION(EXT_create_context_robustness);
+   _EGL_CHECK_EXTENSION(EXT_buffer_age);
+   _EGL_CHECK_EXTENSION(EXT_swap_buffers_with_damage);
+   _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import);
+
+   _EGL_CHECK_EXTENSION(NV_post_sub_buffer);
+#undef _EGL_CHECK_EXTENSION
+}
+
+static void
+_eglCreateAPIsString(_EGLDisplay *dpy)
+{
+   if (dpy->ClientAPIs & EGL_OPENGL_BIT)
+      strcat(dpy->ClientAPIsString, "OpenGL ");
+
+   if (dpy->ClientAPIs & EGL_OPENGL_ES_BIT)
+      strcat(dpy->ClientAPIsString, "OpenGL_ES ");
+
+   if (dpy->ClientAPIs & EGL_OPENGL_ES2_BIT)
+      strcat(dpy->ClientAPIsString, "OpenGL_ES2 ");
+
+   if (dpy->ClientAPIs & EGL_OPENGL_ES3_BIT_KHR)
+      strcat(dpy->ClientAPIsString, "OpenGL_ES3 ");
+
+   if (dpy->ClientAPIs & EGL_OPENVG_BIT)
+      strcat(dpy->ClientAPIsString, "OpenVG ");
+
+   assert(strlen(dpy->ClientAPIsString) < sizeof(dpy->ClientAPIsString));
+}
+
+
+/**
  * This is typically the second EGL function that an application calls.
  * Here we load/initialize the actual hardware driver.
  */
@@ -375,6 +481,12 @@ eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
        * EGL_KHR_get_all_proc_addresses also.
        */
       disp->Extensions.KHR_get_all_proc_addresses = EGL_TRUE;
+
+      _eglCreateExtensionsString(disp);
+      _eglCreateAPIsString(disp);
+      _eglsnprintf(disp->VersionString, sizeof(disp->VersionString),
+              "%d.%d (%s)", disp->VersionMajor, disp->VersionMinor,
+              disp->Driver->Name);
    }
 
    /* Update applications version of major and minor if not NULL */
diff --git a/src/egl/main/eglmisc.c b/src/egl/main/eglmisc.c
index 2f49809..3ca3524 100644
--- a/src/egl/main/eglmisc.c
+++ b/src/egl/main/eglmisc.c
@@ -33,129 +33,9 @@
  */
 
 
-#include <assert.h>
-#include <string.h>
 #include "eglcurrent.h"
 #include "eglmisc.h"
 #include "egldisplay.h"
-#include "egldriver.h"
-#include "eglstring.h"
-
-
-/**
- * Copy the extension into the string and update the string pointer.
- */
-static EGLint
-_eglAppendExtension(char **str, const char *ext)
-{
-   char *s = *str;
-   size_t len = strlen(ext);
-
-   if (s) {
-      memcpy(s, ext, len);
-      s[len++] = ' ';
-      s[len] = '\0';
-
-      *str += len;
-   }
-   else {
-      len++;
-   }
-
-   return (EGLint) len;
-}
-
-
-/**
- * Examine the individual extension enable/disable flags and recompute
- * the driver's Extensions string.
- */
-static void
-_eglUpdateExtensionsString(_EGLDisplay *dpy)
-{
-#define _EGL_CHECK_EXTENSION(ext)                                          \
-   do {                                                                    \
-      if (dpy->Extensions.ext) {                                           \
-         _eglAppendExtension(&exts, "EGL_" #ext);                          \
-         assert(exts <= dpy->ExtensionsString + _EGL_MAX_EXTENSIONS_LEN);  \
-      }                                                                    \
-   } while (0)
-
-   char *exts = dpy->ExtensionsString;
-
-   if (exts[0])
-      return;
-
-   _EGL_CHECK_EXTENSION(MESA_screen_surface);
-   _EGL_CHECK_EXTENSION(MESA_copy_context);
-   _EGL_CHECK_EXTENSION(MESA_drm_display);
-   _EGL_CHECK_EXTENSION(MESA_drm_image);
-   _EGL_CHECK_EXTENSION(MESA_configless_context);
-
-   _EGL_CHECK_EXTENSION(WL_bind_wayland_display);
-   _EGL_CHECK_EXTENSION(WL_create_wayland_buffer_from_image);
-
-   _EGL_CHECK_EXTENSION(KHR_image_base);
-   _EGL_CHECK_EXTENSION(KHR_image_pixmap);
-   if (dpy->Extensions.KHR_image_base && dpy->Extensions.KHR_image_pixmap)
-      _eglAppendExtension(&exts, "EGL_KHR_image");
-
-   _EGL_CHECK_EXTENSION(KHR_vg_parent_image);
-   _EGL_CHECK_EXTENSION(KHR_get_all_proc_addresses);
-   _EGL_CHECK_EXTENSION(KHR_gl_texture_2D_image);
-   _EGL_CHECK_EXTENSION(KHR_gl_texture_cubemap_image);
-   _EGL_CHECK_EXTENSION(KHR_gl_texture_3D_image);
-   _EGL_CHECK_EXTENSION(KHR_gl_renderbuffer_image);
-
-   _EGL_CHECK_EXTENSION(KHR_reusable_sync);
-   _EGL_CHECK_EXTENSION(KHR_fence_sync);
-
-   _EGL_CHECK_EXTENSION(KHR_surfaceless_context);
-   _EGL_CHECK_EXTENSION(KHR_create_context);
-
-   _EGL_CHECK_EXTENSION(NOK_swap_region);
-   _EGL_CHECK_EXTENSION(NOK_texture_from_pixmap);
-
-   _EGL_CHECK_EXTENSION(ANDROID_image_native_buffer);
-
-   _EGL_CHECK_EXTENSION(CHROMIUM_sync_control);
-
-   _EGL_CHECK_EXTENSION(EXT_create_context_robustness);
-   _EGL_CHECK_EXTENSION(EXT_buffer_age);
-   _EGL_CHECK_EXTENSION(EXT_swap_buffers_with_damage);
-   _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import);
-
-   _EGL_CHECK_EXTENSION(NV_post_sub_buffer);
-#undef _EGL_CHECK_EXTENSION
-}
-
-
-static void
-_eglUpdateAPIsString(_EGLDisplay *dpy)
-{
-   char *apis = dpy->ClientAPIsString;
-
-   if (apis[0] || !dpy->ClientAPIs)
-      return;
-
-   if (dpy->ClientAPIs & EGL_OPENGL_BIT)
-      strcat(apis, "OpenGL ");
-
-   if (dpy->ClientAPIs & EGL_OPENGL_ES_BIT)
-      strcat(apis, "OpenGL_ES ");
-
-   if (dpy->ClientAPIs & EGL_OPENGL_ES2_BIT)
-      strcat(apis, "OpenGL_ES2 ");
-
-   if (dpy->ClientAPIs & EGL_OPENGL_ES3_BIT_KHR)
-      strcat(apis, "OpenGL_ES3 ");
-
-   if (dpy->ClientAPIs & EGL_OPENVG_BIT)
-      strcat(apis, "OpenVG ");
-
-   assert(strlen(apis) < sizeof(dpy->ClientAPIsString));
-}
-
 
 const char *
 _eglQueryString(_EGLDriver *drv, _EGLDisplay *dpy, EGLint name)
@@ -166,15 +46,10 @@ _eglQueryString(_EGLDriver *drv, _EGLDisplay *dpy, EGLint name)
    case EGL_VENDOR:
       return _EGL_VENDOR_STRING;
    case EGL_VERSION:
-      _eglsnprintf(dpy->VersionString, sizeof(dpy->VersionString),
-              "%d.%d (%s)", dpy->VersionMajor, dpy->VersionMinor,
-              dpy->Driver->Name);
       return dpy->VersionString;
    case EGL_EXTENSIONS:
-      _eglUpdateExtensionsString(dpy);
       return dpy->ExtensionsString;
    case EGL_CLIENT_APIS:
-      _eglUpdateAPIsString(dpy);
       return dpy->ClientAPIsString;
    default:
       _eglError(EGL_BAD_PARAMETER, "eglQueryString");
-- 
2.0.5



More information about the mesa-dev mailing list