Mesa (master): egl: _eglFilterArray should not allocate.

Chia-I Wu olv at kemper.freedesktop.org
Mon Dec 6 07:55:28 UTC 2010


Module: Mesa
Branch: master
Commit: 5ae4b6693a8254236435960ef84701fe405fe59b
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=5ae4b6693a8254236435960ef84701fe405fe59b

Author: Chia-I Wu <olv at lunarg.com>
Date:   Mon Dec  6 14:38:23 2010 +0800

egl: _eglFilterArray should not allocate.

Otherwise, when it is called from within a driver, the caller cannot
free the returned data (on Windows).

---

 src/egl/main/eglarray.c                            |   39 ++++++++++----------
 src/egl/main/eglarray.h                            |    4 +-
 src/egl/main/eglconfig.c                           |   13 ++++++-
 .../state_trackers/egl/common/egl_g3d_api.c        |   15 +++++++-
 4 files changed, 47 insertions(+), 24 deletions(-)

diff --git a/src/egl/main/eglarray.c b/src/egl/main/eglarray.c
index d686fa1..fe2f1a7 100644
--- a/src/egl/main/eglarray.c
+++ b/src/egl/main/eglarray.c
@@ -118,38 +118,39 @@ _eglFindArray(_EGLArray *array, void *elem)
 
 
 /**
- * Filter an array and return the filtered data.  The returned data pointer
- * should be freed.
+ * Filter an array and return the number of filtered elements.
  */
-void **
-_eglFilterArray(_EGLArray *array, EGLint *size,
+EGLint
+_eglFilterArray(_EGLArray *array, void **data, EGLint size,
                 _EGLArrayForEach filter, void *filter_data)
 {
-   void **data;
    EGLint count = 0, i;
 
-   if (!array) {
-      *size = 0;
-      return malloc(0);
-   }
-
-   data = malloc(array->Size * sizeof(array->Elements[0]));
-   if (!data)
-      return NULL;
+   if (!array)
+      return 0;
 
    if (filter) {
       for (i = 0; i < array->Size; i++) {
-         if (filter(array->Elements[i], filter_data))
-            data[count++] = array->Elements[i];
+         if (filter(array->Elements[i], filter_data)) {
+            if (data && count < size)
+               data[count] = array->Elements[i];
+            count++;
+         }
+         if (data && count >= size)
+            break;
       }
    }
    else {
-      memcpy(data, array->Elements, array->Size * sizeof(array->Elements[0]));
+      if (data) {
+         count = (size < array->Size) ? size : array->Size;
+         memcpy(data, array->Elements, count * sizeof(array->Elements[0]));
+      }
+      else {
+         count = array->Size;
+      }
    }
 
-   *size = count;
-
-   return data;
+   return count;
 }
 
 
diff --git a/src/egl/main/eglarray.h b/src/egl/main/eglarray.h
index c8309fb..a88189a 100644
--- a/src/egl/main/eglarray.h
+++ b/src/egl/main/eglarray.h
@@ -37,8 +37,8 @@ void *
 _eglFindArray(_EGLArray *array, void *elem);
 
 
-PUBLIC void **
-_eglFilterArray(_EGLArray *array, EGLint *size,
+PUBLIC EGLint
+_eglFilterArray(_EGLArray *array, void **data, EGLint size,
                 _EGLArrayForEach filter, void *filter_data);
 
 
diff --git a/src/egl/main/eglconfig.c b/src/egl/main/eglconfig.c
index fec94fb..5b377b7 100644
--- a/src/egl/main/eglconfig.c
+++ b/src/egl/main/eglconfig.c
@@ -697,11 +697,22 @@ _eglChooseConfig(_EGLDriver *drv, _EGLDisplay *disp, const EGLint *attrib_list,
    if (!_eglParseConfigAttribList(&criteria, disp, attrib_list))
       return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
 
-   configList = (_EGLConfig **) _eglFilterArray(disp->Configs, &count,
+   /* get the number of matched configs */
+   count = _eglFilterArray(disp->Configs, NULL, 0,
          (_EGLArrayForEach) _eglMatchConfig, (void *) &criteria);
+   if (!count) {
+      *num_configs = count;
+      return EGL_TRUE;
+   }
+
+   configList = malloc(sizeof(*configList) * count);
    if (!configList)
       return _eglError(EGL_BAD_ALLOC, "eglChooseConfig(out of memory)");
 
+   /* get the matched configs */
+   _eglFilterArray(disp->Configs, (void **) configList, count,
+         (_EGLArrayForEach) _eglMatchConfig, (void *) &criteria);
+
    /* perform sorting of configs */
    if (configs && count) {
       _eglSortConfigs((const _EGLConfig **) configList, count,
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_api.c b/src/gallium/state_trackers/egl/common/egl_g3d_api.c
index f505220..8e53e1d 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d_api.c
+++ b/src/gallium/state_trackers/egl/common/egl_g3d_api.c
@@ -141,11 +141,22 @@ egl_g3d_choose_config(_EGLDriver *drv, _EGLDisplay *dpy, const EGLint *attribs,
    if (!_eglParseConfigAttribList(&criteria, dpy, attribs))
       return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
 
-   tmp_configs = (_EGLConfig **) _eglFilterArray(dpy->Configs, &tmp_size,
+   /* get the number of matched configs */
+   tmp_size = _eglFilterArray(dpy->Configs, NULL, 0,
          (_EGLArrayForEach) egl_g3d_match_config, (void *) &criteria);
+   if (!tmp_size) {
+      *num_configs = tmp_size;
+      return EGL_TRUE;
+   }
+
+   tmp_configs = MALLOC(sizeof(tmp_configs[0]) * tmp_size);
    if (!tmp_configs)
       return _eglError(EGL_BAD_ALLOC, "eglChooseConfig(out of memory)");
 
+   /* get the matched configs */
+   _eglFilterArray(dpy->Configs, (void **) tmp_configs, tmp_size,
+         (_EGLArrayForEach) egl_g3d_match_config, (void *) &criteria);
+
    /* perform sorting of configs */
    if (tmp_configs && tmp_size) {
       _eglSortConfigs((const _EGLConfig **) tmp_configs, tmp_size,
@@ -155,7 +166,7 @@ egl_g3d_choose_config(_EGLDriver *drv, _EGLDisplay *dpy, const EGLint *attribs,
          configs[i] = _eglGetConfigHandle(tmp_configs[i]);
    }
 
-   free(tmp_configs);
+   FREE(tmp_configs);
 
    *num_configs = size;
 




More information about the mesa-commit mailing list