[Mesa-dev] [PATCH] egl: Fix for not setting EGL_BAD_ALLOC on try to create multiple window surfaces on single window.

Adrian Pielech adrian.pielech at intel.com
Wed Mar 22 13:14:39 UTC 2017


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

Signed-off-by: Adrian Pielech <adrian.pielech at intel.com>
---
 src/egl/main/eglapi.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 87 insertions(+), 2 deletions(-)

diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index 5694b5a..388783f 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,64 @@
 #include "eglimage.h"
 #include "eglsync.h"
 
+struct window_list_item
+{
+    struct list_head link;
+
+    EGLNativeWindowType native_window;
+    EGLSurface attached_surface;
+    EGLDisplay attached_display;
+};
+
+struct list_head window_list = {NULL, NULL};
+
+/* Checks if a EGLWindow already have a created surface */
+static inline bool
+is_window_associated_with_surface(EGLNativeWindowType window)
+{
+   list_for_each_entry(struct window_list_item, item, &window_list, link) {
+      if (item->native_window = window) {
+         return true;
+      }
+   }
+
+   return false;
+}
+
+static inline void
+associate_window_with_surface_list(EGLNativeWindowType window, EGLSurface,
+                                   EGLDisplay display)
+{
+   struct window_list_item *item = malloc(sizeof(struct window_list_item));
+   assert(item);
+
+   item->native_window = window;
+   item->attached_surface = surface;
+   item->attached_display = display;
+
+   list_add(&item->link, &window_list);
+}
+
+static inline void
+disassociate_window_with_surface_list(EGLSurface surface)
+{
+   list_for_each_entry(struct window_list_item, item, &window_list, link) {
+      if (item->attched_surface == surface) {
+         list_del(&item->link);
+         free(item);
+         break;
+      }
+   }
+}
+
+static inline void
+disassociate_all_window_surface_links_by_display(EGLDisplay display)
+{
+   list_for_each_entry_safe(struct window_list_item, item, &window_list, link) {
+      list_del(&item->link);
+      free(item);
+   }
+}
 
 /**
  * Macros to help return an API entrypoint.
@@ -623,6 +682,10 @@ eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
       *minor = disp->Version % 10;
    }
 
+   if (!window_list.next || !window_list.prev) {
+      list_inithead(&window_list);
+   }
+
    RETURN_EGL_SUCCESS(disp, EGL_TRUE);
 }
 
@@ -640,6 +703,13 @@ eglTerminate(EGLDisplay dpy)
    if (disp->Initialized) {
       _EGLDriver *drv = disp->Driver;
 
+      /*
+       * In corner case, user could call eglTerminate without calling
+       * eglDestroySurface, so it is wise clean up list entries and free memory
+       * after his/her activities.
+       */
+      disassociate_all_window_surface_links_by_display(dpy);
+
       drv->API.Terminate(drv, disp);
       /* do not reset disp->Driver */
       disp->ClientAPIsString[0] = 0;
@@ -897,11 +967,24 @@ 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);
+
+   /* According to the EGL 1.5 spec, section 3.5.1, page 34,35
+    * eglCreateWindowSurface should return EGL_BAD_ALLOC if there is already
+    * created a surface for given window.
+    */
+   if (is_window_associated_with_surface(window))
+      RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE);
+
+   window_surface = _eglCreateWindowSurfaceCommon(disp, config, (void*) window,
+                                                  attrib_list);
+   if (window_surface)
+      associate_window_with_surface_list(window, window_surface, dpy);
+
+   return window_surface;
 }
 
 static void *
@@ -1099,6 +1182,8 @@ eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
    _eglUnlinkSurface(surf);
    ret = drv->API.DestroySurface(drv, disp, surf);
 
+   disassociate_window_with_surface_list(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