Hi,

I have spent a few full days debugging DRI configs and finally managed
to find the leaking parts. See the attached patches. Tested and works
with DRI2+intel and drisw.

Please review and apply.

Thanks,
Kristof
From 5ef3e20910b42ba33916f10af3a78bc7c6bf2fa0 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?RALOVICH,=20Krist=C3=B3f?= <[email protected]>
Date: Sun, 5 Jul 2009 15:41:43 +0200
Subject: [PATCH 1/4] glx: Free pdraw as __GLXDRIdrawablePrivate it is.

---
 src/glx/x11/dri2_glx.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/src/glx/x11/dri2_glx.c b/src/glx/x11/dri2_glx.c
index f4865ae..56529fa 100644
--- a/src/glx/x11/dri2_glx.c
+++ b/src/glx/x11/dri2_glx.c
@@ -154,7 +154,8 @@ static void dri2DestroyDrawable(__GLXDRIdrawable *pdraw)
 
     (*core->destroyDrawable)(pdraw->driDrawable);
     DRI2DestroyDrawable(pdraw->psc->dpy, pdraw->drawable);
-    Xfree(pdraw);
+    __GLXDRIdrawablePrivate *p = containerOf(pdraw, __GLXDRIdrawablePrivate, base);
+    Xfree(p);
 }
 
 static __GLXDRIdrawable *dri2CreateDrawable(__GLXscreenConfigs *psc,
-- 
1.6.3.3

From bc56676dae778f821be245824540f6e5028632b8 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?RALOVICH,=20Krist=C3=B3f?= <[email protected]>
Date: Sun, 5 Jul 2009 16:09:48 +0200
Subject: [PATCH 2/4] glx: implement _gl_context_modes_count()

---
 src/glx/x11/glcontextmodes.c |   25 +++++++++++++++++++++----
 src/glx/x11/glcontextmodes.h |    2 ++
 2 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/src/glx/x11/glcontextmodes.c b/src/glx/x11/glcontextmodes.c
index 232031c..3039dcf 100644
--- a/src/glx/x11/glcontextmodes.c
+++ b/src/glx/x11/glcontextmodes.c
@@ -29,6 +29,7 @@
  * code base.
  *
  * \author Ian Romanick <[email protected]>
+ * \author RALOVICH, Kristof <[email protected]>
  */
 
 #if defined(IN_MINI_GLX)
@@ -66,6 +67,7 @@
 
 #include "glcontextmodes.h"
 
+
 #if !defined(IN_MINI_GLX)
 #define NUM_VISUAL_TYPES   6
 
@@ -357,7 +359,6 @@ _gl_get_context_mode_data(const __GLcontextModes * mode, int attribute,
 }
 #endif /* !defined(IN_MINI_GLX) */
 
-
 /**
  * Allocate a linked list of \c __GLcontextModes structures.  The fields of
  * each structure will be initialized to "reasonable" default values.  In
@@ -427,7 +428,6 @@ _gl_context_modes_create(unsigned count, size_t minimum_size)
    return base;
 }
 
-
 /**
  * Destroy a linked list of \c __GLcontextModes structures created by
  * \c _gl_context_modes_create.
@@ -440,13 +440,11 @@ _gl_context_modes_destroy(__GLcontextModes * modes)
 {
    while (modes != NULL) {
       __GLcontextModes *const next = modes->next;
-
       _mesa_free(modes);
       modes = next;
    }
 }
 
-
 /**
  * Find a context mode matching a Visual ID.
  *
@@ -542,3 +540,22 @@ _gl_context_modes_are_same(const __GLcontextModes * a,
            (a->bindToTextureTargets == b->bindToTextureTargets) &&
            (a->yInverted == b->yInverted));
 }
+
+/**
+ * Calculate the length of a linked list of \c __GLcontextModes
+ * structures.
+ *
+ * \param modes  Linked list of structures to be counted.
+ */
+size_t
+_gl_context_modes_count(const __GLcontextModes* modes)
+{
+   __GLcontextModes *m;
+
+   size_t count = 0;
+
+   for (m = modes; m != NULL; m = m->next)
+      count++;
+
+   return count;
+}
diff --git a/src/glx/x11/glcontextmodes.h b/src/glx/x11/glcontextmodes.h
index 6676ae3..4b764a7 100644
--- a/src/glx/x11/glcontextmodes.h
+++ b/src/glx/x11/glcontextmodes.h
@@ -25,6 +25,7 @@
 /**
  * \file glcontextmodes.h
  * \author Ian Romanick <[email protected]>
+ * \author RALOVICH, Kristof <[email protected]>
  */
 
 #ifndef GLCONTEXTMODES_H
@@ -50,5 +51,6 @@ extern __GLcontextModes *_gl_context_modes_find_fbconfig(__GLcontextModes *
                                                          modes, int fbid);
 extern GLboolean _gl_context_modes_are_same(const __GLcontextModes * a,
                                             const __GLcontextModes * b);
+extern size_t _gl_context_modes_count(const __GLcontextModes* modes);
 
 #endif /* GLCONTEXTMODES_H */
-- 
1.6.3.3

From ad42cabf13abff6ea8342d5d1fe30a975a300349 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?RALOVICH,=20Krist=C3=B3f?= <[email protected]>
Date: Sun, 5 Jul 2009 16:10:55 +0200
Subject: [PATCH 3/4] glx: implement functions for proper handling of DRI configs

---
 src/glx/x11/dri_common.c |  140 ++++++++++++++++++++++++++++++++++++++++++++++
 src/glx/x11/dri_common.h |   14 +++++
 2 files changed, 154 insertions(+), 0 deletions(-)

diff --git a/src/glx/x11/dri_common.c b/src/glx/x11/dri_common.c
index 6de4111..be78c77 100644
--- a/src/glx/x11/dri_common.c
+++ b/src/glx/x11/dri_common.c
@@ -31,6 +31,7 @@
  *   Kevin E. Martin <[email protected]>
  *   Brian Paul <[email protected]>
  *   Kristian Høgsberg ([email protected])
+ *   RALOVICH, Kristof <[email protected]>
  */
 
 #ifdef GLX_DIRECT_RENDERING
@@ -294,6 +295,9 @@ createDriMode(const __DRIcoreExtension *core,
     if (driConfigs[i] == NULL)
 	return NULL;
 
+    /* Now modes == driconfigs[i], equality is defined by
+     * driConfigEqual(). */
+
     config = Xmalloc(sizeof *config);
     if (config == NULL)
 	return NULL;
@@ -328,6 +332,142 @@ driConvertConfigs(const __DRIcoreExtension *core,
     return head.next;
 }
 
+/* Free driver_configs[i] where createDriMode() didn't find a match. */
+_X_HIDDEN
+void
+driDestroyUnmatchedConfigs(const __DRIcoreExtension *core,
+                           __GLcontextModes *visuals,
+                           __GLcontextModes *fbconfigs,
+                           __DRIconfig     **driver_configs)
+{
+  int n;
+  for(n = 0; driver_configs[n]; n++) {
+  }
+
+  int *matched = calloc(1, n*sizeof(int));
+
+  __GLcontextModes* m;
+  for(m = visuals; m; m = m->next) {
+    for(unsigned int i = 0; driver_configs[i]; i++) {
+      if(driConfigEqual(core, m, driver_configs[i])) {
+        matched[i]++;
+        break;
+      }
+    }
+  }
+  for(m = fbconfigs; m; m = m->next) {
+    for(unsigned int i = 0; driver_configs[i]; i++) {
+      if(driConfigEqual(core, m, driver_configs[i])) {
+        matched[i]++;
+        break;
+      }
+    }
+  }
+
+  for(unsigned int i = 0; driver_configs[i]; i++) {
+    if(matched[i] < 1) {
+      free(driver_configs[i]);
+    }
+  }
+
+  free(matched);
+}
+
+/**
+ * Given a linked list of \c __GLcontextModes, put the \c
+ * __GLXDRIconfigPrivate and DRI \c __GLcontextModes (inside \c
+ * __DRIconfig) structures into respective sets filtering out
+ * duplicated instances.
+ *
+ * \param modes The input linked list of context modes.
+ * \param cpSet The output set (array) of \c __GLXDRIconfigPrivate* instances.
+ * \param cmSet The output set (array) of \c __GLcontextModes* instances.
+ */
+static
+void
+driConfigLinkedListToArraySet(const __GLcontextModes* modes,
+                              __GLXDRIconfigPrivate** cpSet,
+                              __GLcontextModes**      cmSet)
+{
+  __GLcontextModes* m;
+  for(m = (__GLcontextModes*)modes; m; m = m->next)
+  {
+    __GLXDRIconfigPrivate* cp = containerOf(m, __GLXDRIconfigPrivate, modes);
+
+    unsigned int i = 0;
+    for( ; cpSet[i]; i++) {
+      if(cp == cpSet[i])
+        goto cp_already_in;
+    }
+    cpSet[i] = cp;
+  cp_already_in:
+    ;
+
+    /* This would be the elegant way, but requires the definition of
+     * __DRIconfig/__DRIconfigRec from dri/common/utils.h.
+     *
+     * __GLcontextModes* cm =
+     *       containerOf((__DRIconfig*)cp->driConfig, __DRIconfig, modes);
+     *
+     */
+    __GLcontextModes* cm = (__GLcontextModes*)cp->driConfig;
+    unsigned int j = 0;
+    for( ; cmSet[j]; j++) {
+      if(cm == cmSet[j])
+        goto cm_already_in;
+    }
+    cmSet[j] = cm;
+  cm_already_in:
+    ;
+  }
+}
+
+/**
+ * Given two linked lists of Visuals and FBConfigs, put the \c
+ * __GLXDRIconfigPrivate and DRI \c __GLcontextModes (inside \c
+ * __DRIconfig) structures into respective sets filtering out
+ * duplicated instances. The output arrays must be zeroed where unused
+ * and must be large enough to accomodate all the different values of
+ * inputs.
+ *
+ * \param visuals The input linked list of Visuals.
+ * \param fbconfigs The input linked list of FBConfigs.
+ * \param cpSet The output set (array) of \c __GLXDRIconfigPrivate* instances.
+ * \param cmSet The output set (array) of \c __GLcontextModes* instances.
+ */
+_X_HIDDEN
+void
+driCollectConfigs(const __GLcontextModes* visuals,
+                  const __GLcontextModes* fbconfigs,
+                  __GLXDRIconfigPrivate** cpSet,
+                  __GLcontextModes**      cmSet)
+{
+  driConfigLinkedListToArraySet(visuals, cpSet, cmSet);
+  driConfigLinkedListToArraySet(fbconfigs, cpSet, cmSet);
+}
+
+/**
+ * Release \c NULL terminated arrays of \c __GLXDRIconfigPrivate and
+ * \c __GLcontextModes.
+ */
+_X_HIDDEN
+void
+driDestroyConfigs(__GLXDRIconfigPrivate** cpSet,
+                  __GLcontextModes**      cmSet)
+{
+  int i = 0;
+  for( ; cpSet[i]; i++)
+  {
+    free(cpSet[i]);
+  }
+
+  i=0;
+  for( ; cmSet[i]; i++)
+  {
+    free(cmSet[i]);
+  }
+}
+
 _X_HIDDEN void
 driBindExtensions(__GLXscreenConfigs *psc, int dri2)
 {
diff --git a/src/glx/x11/dri_common.h b/src/glx/x11/dri_common.h
index 61ac9c6..4715b42 100644
--- a/src/glx/x11/dri_common.h
+++ b/src/glx/x11/dri_common.h
@@ -31,6 +31,7 @@
  *   Kevin E. Martin <[email protected]>
  *   Brian Paul <[email protected]>
  *   Kristian Høgsberg ([email protected])
+ *   RALOVICH, Kristof <[email protected]>
  */
 
 #ifndef _DRI_COMMON_H
@@ -48,6 +49,19 @@ extern __GLcontextModes *driConvertConfigs(const __DRIcoreExtension * core,
                                            __GLcontextModes * modes,
                                            const __DRIconfig ** configs);
 
+extern void driDestroyUnmatchedConfigs(const __DRIcoreExtension *core,
+                                       __GLcontextModes *visuals,
+                                       __GLcontextModes *fbconfigs,
+                                       __DRIconfig     **driver_configs);
+
+extern void driCollectConfigs(const __GLcontextModes* visuals,
+                              const __GLcontextModes* fbconfigs,
+                              __GLXDRIconfigPrivate** cpSet,
+                              __GLcontextModes**      cmSet);
+
+extern void driDestroyConfigs(__GLXDRIconfigPrivate** cpSet,
+                              __GLcontextModes**      cmSet);
+
 extern const __DRIsystemTimeExtension systemTimeExtension;
 
 extern void InfoMessageF(const char *f, ...);
-- 
1.6.3.3

From b3fa73ca1e2897ea5f090e14ecabe94d624bde16 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?RALOVICH,=20Krist=C3=B3f?= <[email protected]>
Date: Sun, 5 Jul 2009 16:23:28 +0200
Subject: [PATCH 4/4] glx: release DRI context modes properly

This includes destroying those that are unmatched during
dri2CreateScreen().
---
 src/glx/x11/dri2_glx.c |    4 ++
 src/glx/x11/glxext.c   |   73 ++++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 68 insertions(+), 9 deletions(-)

diff --git a/src/glx/x11/dri2_glx.c b/src/glx/x11/dri2_glx.c
index 56529fa..9062419 100644
--- a/src/glx/x11/dri2_glx.c
+++ b/src/glx/x11/dri2_glx.c
@@ -28,6 +28,7 @@
  *
  * Authors:
  *   Kristian Høgsberg ([email protected])
+ *   RALOVICH, Kristof <[email protected]>
  */
 
 #ifdef GLX_DIRECT_RENDERING
@@ -489,6 +490,9 @@ static __GLXDRIscreen *dri2CreateScreen(__GLXscreenConfigs *psc, int screen,
     psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs);
     psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs);
 
+    driDestroyUnmatchedConfigs(psc->core, psc->visuals, psc->configs, driver_configs);
+    free(driver_configs);
+
     psp->destroyScreen = dri2DestroyScreen;
     psp->createContext = dri2CreateContext;
     psp->createDrawable = dri2CreateDrawable;
diff --git a/src/glx/x11/glxext.c b/src/glx/x11/glxext.c
index b296b7c..3b98c88 100644
--- a/src/glx/x11/glxext.c
+++ b/src/glx/x11/glxext.c
@@ -35,6 +35,7 @@
  * Direct rendering support added by Precision Insight, Inc.
  *
  * \author Kevin E. Martin <[email protected]>
+ * \author RALOVICH, Kristof <[email protected]>
  */
 
 #include <assert.h>
@@ -51,6 +52,9 @@
 #include <xcb/glx.h>
 #endif
 
+#ifdef GLX_DIRECT_RENDERING
+# include "dri_common.h"
+#endif
 
 #ifdef DEBUG
 void __glXDumpDrawBuffer(__GLXcontext * ctx);
@@ -122,6 +126,53 @@ XEXT_GENERATE_FIND_DISPLAY(__glXFindDisplay, __glXExtensionInfo,
                            __GLX_NUMBER_EVENTS, NULL)
 
 /************************************************************************/
+
+#ifdef GLX_DIRECT_RENDERING
+/**
+ * DRI is using the bigger __GLXDRIconfigPrivate structure inherited
+ * from __GLcontextModes structure. We nedd to walk the linked list of
+ * those and make sure shared instances are not freed more than once.
+ */
+static
+void
+DestroyDRIConfigs(__GLXdisplayPrivate * priv)
+{
+
+  __GLXscreenConfigs *psc;
+  GLint screens;
+  size_t modes = 0;
+
+  psc = priv->screenConfigs;
+  screens = ScreenCount(priv->dpy);
+
+  /* Count the length of the linked lists of configs to get an upper
+   * bound on the sizes of the required sets. */
+  for(unsigned int i = 0; i < screens; i++, psc++) {
+    if(psc->configs)
+      modes += _gl_context_modes_count(psc->configs);
+    if(psc->visuals)
+      modes += _gl_context_modes_count(psc->visuals);
+  }
+
+  /* Create large enough sets to hold the different configs. Inserting
+   * duplicated instances only once. */
+  __GLXDRIconfigPrivate** cpSet = calloc(1, modes * 2 * sizeof(*cpSet));
+  __GLcontextModes**      cmSet = calloc(1, modes * 2 * sizeof(*cmSet));
+
+  psc = priv->screenConfigs;
+  for(unsigned int i = 0; i < screens; i++, psc++) {
+    driCollectConfigs(psc->configs, psc->visuals, cpSet, cmSet);
+    psc->visuals = 0;
+    psc->configs = 0;
+  }
+
+  driDestroyConfigs(cpSet, cmSet);
+
+  free(cmSet);
+  free(cpSet);
+}
+#endif
+
 /*
 ** Free the per screen configs data as well as the array of
 ** __glXScreenConfigs.
@@ -132,20 +183,24 @@ FreeScreenConfigs(__GLXdisplayPrivate * priv)
    __GLXscreenConfigs *psc;
    GLint i, screens;
 
+#ifdef GLX_DIRECT_RENDERING
+   DestroyDRIConfigs(priv);
+#endif
+
    /* Free screen configuration information */
    psc = priv->screenConfigs;
    screens = ScreenCount(priv->dpy);
    for (i = 0; i < screens; i++, psc++) {
-      if (psc->configs) {
-         _gl_context_modes_destroy(psc->configs);
-         if (psc->effectiveGLXexts)
-            Xfree(psc->effectiveGLXexts);
-         psc->configs = NULL;   /* NOTE: just for paranoia */
-      }
-      if (psc->visuals) {
+
+#ifndef GLX_DIRECT_RENDERING
+      if(psc->visuals)
          _gl_context_modes_destroy(psc->visuals);
-         psc->visuals = NULL;   /* NOTE: just for paranoia */
-      }
+      if(psc->configs)
+         _gl_context_modes_destroy(psc->configs);
+#endif
+
+      if (psc->effectiveGLXexts)
+         Xfree(psc->effectiveGLXexts);
       Xfree((char *) psc->serverGLXexts);
 
 #ifdef GLX_DIRECT_RENDERING
-- 
1.6.3.3

------------------------------------------------------------------------------
_______________________________________________
Mesa3d-dev mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mesa3d-dev

Reply via email to