[Mesa-dev] [PATCH] egl: fix for multiple window surfaces per single window

Pielech, Adrian adrian.pielech at intel.com
Fri Mar 11 09:04:21 UTC 2016


Current implementation of eglCreateWindowSurface() is against to the EGL specification, because it allows creating multiple surfaces per single window.


---
 src/egl/main/eglapi.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 107 insertions(+), 2 deletions(-)

diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index fbb14f1..3eb9fb6 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -102,6 +102,96 @@
 #include "eglsync.h"
 #include "eglstring.h"
 
+/**
+  * Bi direction linked list item structure for carrying window and surface fields.
+  */
+struct _window_list_item
+{
+    struct _window_list_item *prev;
+    struct _window_list_item *next;
+    EGLNativeWindowType native_window;
+    EGLSurface attached_surface;
+};
+
+typedef struct _window_list_item window_list_item;
+
+struct _window_list_item *window_surface_association_list_head = NULL;
+struct _window_list_item *window_surface_association_list_tail = NULL;
+
+static inline bool _isWindowAssociatedWithSurface(EGLNativeWindowType window)
+{
+    struct _window_list_item *it = window_surface_association_list_head;
+    for (; it != NULL; it = it->next)
+    {
+        if (it->native_window == window)
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+static inline void _associateWindowWithSurfaceList(EGLNativeWindowType window, EGLSurface surface)
+{
+    window_list_item * new_list_item = malloc(sizeof(window_list_item));
+    memset(new_list_item, 0, sizeof(window_list_item));
+
+    new_list_item->native_window = window;
+    new_list_item->attached_surface = surface;
+
+    if (window_surface_association_list_tail)
+    {
+        window_surface_association_list_tail->next = new_list_item;
+        new_list_item->prev = window_surface_association_list_tail;
+
+        window_surface_association_list_tail = new_list_item;
+    }
+    else
+    {
+        window_surface_association_list_head = new_list_item;
+        window_surface_association_list_tail = new_list_item;
+    }
+}
+
+static inline void _disassociateWindowWithSurfaceList(EGLSurface surface)
+{
+    if (window_surface_association_list_head != NULL)
+    {
+        if (window_surface_association_list_head == window_surface_association_list_tail &&
+                window_surface_association_list_head->attached_surface == surface)
+        {
+            free(window_surface_association_list_head);
+            window_surface_association_list_head = NULL;
+            window_surface_association_list_tail = NULL;
+        }
+        else
+        {
+            struct _window_list_item * it = window_surface_association_list_head;
+
+            for (;it != NULL; it = it->next)
+            {
+                if (it->attached_surface == surface)
+                {
+                    struct _window_list_item *next_element = it->next;
+                    struct _window_list_item *prev_element = it->prev;
+
+                    free (it);
+
+                    if (prev_element)
+                        prev_element->next = next_element;
+                    if (next_element)
+                        next_element->prev = prev_element;
+
+                    if (it == window_surface_association_list_tail)
+                        window_surface_association_list_tail = prev_element;
+
+                    if (it == window_surface_association_list_head)
+                        window_surface_association_list_head = next_element;
+                }
+            }
+        }
+    }
+}
 
 /**
  * Macros to help return an API entrypoint.
@@ -690,9 +780,20 @@ eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
                        EGLNativeWindowType window, const EGLint *attrib_list)
 {
    _EGLDisplay *disp = _eglLockDisplay(dpy);
+   EGLSurface window_surface = NULL;
    STATIC_ASSERT(sizeof(void*) == sizeof(window));
-   return _eglCreateWindowSurfaceCommon(disp, config, (void*) window,
-                                        attrib_list);
+
+   //check if window have already created surface to it
+   if (_isWindowAssociatedWithSurface(window))
+       RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE);
+
+   window_surface = _eglCreateWindowSurfaceCommon(disp, config, (void*) window,
+                                                  attrib_list);
+   //add window with attached surface to list,
+   //it will be freed when eglDestroySurface will be called
+   if (window_surface != EGL_NO_SURFACE)
+       _associateWindowWithSurfaceList(window, window_surface);
+
+   return window_surface;
 }
 
 
@@ -805,6 +906,9 @@ eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
    _eglUnlinkSurface(surf);
    ret = drv->API.DestroySurface(drv, disp, surf);
 
+   //remove surface association with window if exist
+   _disassociateWindowWithSurfaceList(surface);
+
    RETURN_EGL_EVAL(disp, ret);
 }
 
-- 
2.7.0.rc3

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

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