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.

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to