[Mesa-dev] [PATCH] egl: Return error on try to create multiple surfaces from window. (v3)

Adrian Pielech adrian.pielech at intel.com
Fri Mar 24 13:01:52 UTC 2017


According to the EGL 1.5 spec, section 3.5.1, page 34,35 on PDF
eglCreateWindowSurface should set EGL_BAD_ALLOC if there is already surface
for given window. Similarly it is written in EGL 1.4 spec, section 3.5.1,
page 29 on PDF.

v2: made it compilable(i'm porting it from other fork, so there was a typos)
v3: changed code with naming conventions, corrected comparision in one IF
statement, added mutex for list structure that holds information wnd-surf-dpy.

Signed-off-by: Adrian Pielech <adrian.pielech at intel.com>
---
Sorry for this ugly appendix that will be appended by proxy to this message.
---
 src/egl/main/eglapi.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 120 insertions(+), 2 deletions(-)

diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index 5694b5a..389998e 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -90,6 +90,7 @@
 #include "c11/threads.h"
 #include "GL/mesa_glinterop.h"
 #include "eglcompiler.h"
+#include "util/list.h"
 
 #include "eglglobals.h"
 #include "eglcontext.h"
@@ -102,6 +103,89 @@
 #include "eglimage.h"
 #include "eglsync.h"
 
+struct _egl_window_list_item {
+    struct list_head link;
+
+    EGLNativeWindowType native_window;
+    EGLSurface attached_surface;
+    EGLDisplay attached_display;
+};
+
+struct list_head _egl_window_list = {NULL, NULL};
+mtx_t _egl_window_list_mutex = _MTX_INITIALIZER_NP;
+
+#define ASSERT_UNINITIALIZED_WINDOW_LIST assert(_egl_window_list.next); \
+                                         assert(_egl_window_list.prev)
+#define MTX_LOCK_WINDOW_LIST mtx_lock(&_egl_window_list_mutex)
+#define MTX_UNLOCK_WINDOW_LIST mtx_unlock(&_egl_window_list_mutex)
+
+/* Checks if a EGLWindow already have a created surface */
+static inline bool
+_eglIsWindowAssociatedWithSurface(EGLNativeWindowType window)
+{
+   /* Mutex for this list is locked in eglCreateWindowSurface() */
+   ASSERT_UNINITIALIZED_WINDOW_LIST;
+
+   list_for_each_entry(struct _egl_window_list_item, item, &_egl_window_list,
+                       link) {
+      if (item->native_window == window) {
+         return true;
+      }
+   }
+
+   return false;
+}
+
+static inline void
+_eglAssociateWindowWithSurfaceList(EGLNativeWindowType window,
+                                   EGLSurface surface,
+                                   EGLDisplay display)
+{
+    /* Mutex for this list is locked in eglCreateWindowSurface() */
+   ASSERT_UNINITIALIZED_WINDOW_LIST;
+
+   struct _egl_window_list_item *item = malloc(sizeof(struct _egl_window_list_item));
+   assert(item);
+
+   item->native_window = window;
+   item->attached_surface = surface;
+   item->attached_display = display;
+
+   list_add(&item->link, &_egl_window_list);
+}
+
+static inline void
+_eglDisassociateWindowWithSurfaceList(EGLSurface surface)
+{
+   MTX_LOCK_WINDOW_LIST;
+   ASSERT_UNINITIALIZED_WINDOW_LIST;
+
+   list_for_each_entry(struct _egl_window_list_item, item, &_egl_window_list,
+                      link) {
+      if (item->attached_surface == surface) {
+         list_del(&item->link);
+         free(item);
+         break;
+      }
+   }
+   MTX_UNLOCK_WINDOW_LIST;
+}
+
+static inline void
+_eglDisassociateAllWindowSurfaceLinksByDisplay(EGLDisplay display)
+{
+   MTX_LOCK_WINDOW_LIST;
+   ASSERT_UNINITIALIZED_WINDOW_LIST;
+
+   list_for_each_entry_safe(struct _egl_window_list_item, item,
+                            &_egl_window_list, link) {
+      if (item->attached_display == display) {
+         list_del(&item->link);
+         free(item);
+      }
+   }
+   MTX_UNLOCK_WINDOW_LIST;
+}
 
 /**
  * Macros to help return an API entrypoint.
@@ -623,6 +707,12 @@ eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
       *minor = disp->Version % 10;
    }
 
+   MTX_LOCK_WINDOW_LIST;
+   if (!_egl_window_list.next || !_egl_window_list.prev) {
+      list_inithead(&_egl_window_list);
+   }
+   MTX_UNLOCK_WINDOW_LIST;
+
    RETURN_EGL_SUCCESS(disp, EGL_TRUE);
 }
 
@@ -640,6 +730,11 @@ eglTerminate(EGLDisplay dpy)
    if (disp->Initialized) {
       _EGLDriver *drv = disp->Driver;
 
+      /* User can call eglTerminate() without calling eglDestroySurface(), so
+       * let's clean up the list entries.
+       */
+      _eglDisassociateAllWindowSurfaceLinksByDisplay(dpy);
+
       drv->API.Terminate(drv, disp);
       /* do not reset disp->Driver */
       disp->ClientAPIsString[0] = 0;
@@ -897,11 +992,32 @@ eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
                        EGLNativeWindowType window, const EGLint *attrib_list)
 {
    _EGLDisplay *disp = _eglLockDisplay(dpy);
+   EGLSurface window_surface = NULL;
 
    _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
    STATIC_ASSERT(sizeof(void*) == sizeof(window));
-   return _eglCreateWindowSurfaceCommon(disp, config, (void*) window,
-                                        attrib_list);
+
+   /* Page 29 of the PDF fo the EGL 1.4 spec says:
+    *
+    * "If there is already an EGLSurface associated with win (as a result
+    * of a previous eglCreateWindowSurface call), then an EGL_BAD_ALLOC error
+    * is generated.
+    */
+   MTX_LOCK_WINDOW_LIST;
+
+   if (_eglIsWindowAssociatedWithSurface(window)) {
+      MTX_UNLOCK_WINDOW_LIST;
+      RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE);
+   }
+
+   window_surface = _eglCreateWindowSurfaceCommon(disp, config, (void*) window,
+                                                  attrib_list);
+
+   if (window_surface)
+      _eglAssociateWindowWithSurfaceList(window, window_surface, dpy);
+   MTX_UNLOCK_WINDOW_LIST;
+
+   return window_surface;
 }
 
 static void *
@@ -1099,6 +1215,8 @@ eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
    _eglUnlinkSurface(surf);
    ret = drv->API.DestroySurface(drv, disp, surf);
 
+   _eglDisassociateWindowWithSurfaceList(surface);
+
    RETURN_EGL_EVAL(disp, ret);
 }
 
-- 
2.7.4

--------------------------------------------------------------------

Intel Technology Poland sp. z o.o.
ul. Slowackiego 173 | 80-298 Gdansk | Sad Rejonowy Gdansk Polnoc | VII Wydzial Gospodarczy Krajowego Rejestru Sadowego - KRS 101882 | NIP 957-07-52-316 | Kapital zakladowy 200.000 PLN.

Ta wiadomosc wraz z zalacznikami jest przeznaczona dla okreslonego adresata i moze zawierac informacje poufne. W razie przypadkowego otrzymania tej wiadomosci, prosimy o powiadomienie nadawcy oraz trwale jej usuniecie; jakiekolwiek
przegladanie lub rozpowszechnianie jest zabronione.
This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). If you are not the intended recipient, please contact the sender and delete all copies; any review or distribution by
others is strictly prohibited.



More information about the mesa-dev mailing list