Hi,
This patch series consists of assorted minor fixes to EGL core. This is
a result of reviewing the implementaiton. There should be more bugs
here and there in EGL core, but hopefully they should all be easy to
fix. I will try to fix them in the process of reviewing.
The commit logs should be clear on what the pathces do. Patch 5 & 6
updates the comments in eglapi.c trying to clarify what errors are
checked in eglapi.c and what errors should be checked by drivers.
Basically, eglapi.c only checks for "bad" resources. The resources may
be given explicitly in function parameters, or implicitly, for functions
that operate on current display/context/surface/etc. Is the handle
valid? Does it belong to the display? Is it already deleted? This is
what eglapi.c checks and it returns one of the EGL_BAD_<RESOURCE> when
any of the checks fails.
--
Regards,
olv
>From f3163b992efd4d7254ec28857b51150e221075b5 Mon Sep 17 00:00:00 2001
From: Chia-I Wu <olva...@gmail.com>
Date: Thu, 1 Oct 2009 16:40:09 +0800
Subject: [PATCH 1/8] egl: Fix eglCheckConfigHandle.
A stupid bug by me made the check void.
Signed-off-by: Chia-I Wu <olva...@gmail.com>
---
src/egl/main/eglconfig.c | 9 ++++-----
1 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/src/egl/main/eglconfig.c b/src/egl/main/eglconfig.c
index 2c8d1c4..31d69a7 100644
--- a/src/egl/main/eglconfig.c
+++ b/src/egl/main/eglconfig.c
@@ -82,18 +82,17 @@ _eglAddConfig(_EGLDisplay *dpy, _EGLConfig *conf)
EGLBoolean
_eglCheckConfigHandle(EGLConfig config, _EGLDisplay *dpy)
{
- _EGLConfig *conf = NULL;
+ EGLint num_configs = (dpy) ? dpy->NumConfigs : 0;
EGLint i;
- for (i = 0; dpy && i < dpy->NumConfigs; i++) {
- conf = dpy->Configs[i];
+ for (i = 0; i < num_configs; i++) {
+ _EGLConfig *conf = dpy->Configs[i];
if (conf == (_EGLConfig *) config) {
assert(conf->Display == dpy);
break;
}
}
-
- return (conf != NULL);
+ return (i < num_configs);
}
--
1.6.3.3
>From 6c29951cb690f878fa9a4ab3bd3c376a6f7e6c3f Mon Sep 17 00:00:00 2001
From: Chia-I Wu <olva...@gmail.com>
Date: Sat, 10 Oct 2009 14:39:43 +0800
Subject: [PATCH 2/8] egl: Fix GLX_USE_TLS build.
Remove an extraneous semicolon.
Signed-off-by: Chia-I Wu <olva...@gmail.com>
---
src/egl/main/eglcurrent.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/egl/main/eglcurrent.c b/src/egl/main/eglcurrent.c
index ca7a077..df50615 100644
--- a/src/egl/main/eglcurrent.c
+++ b/src/egl/main/eglcurrent.c
@@ -16,7 +16,7 @@ static _EGLThreadInfo dummy_thread = _EGL_THREAD_INFO_INITIALIZER;
#ifdef GLX_USE_TLS
-static __thread const _EGLThreadInfo *_egl_TSD;
+static __thread const _EGLThreadInfo *_egl_TSD
__attribute__ ((tls_model("initial-exec")));
static INLINE void _eglSetTSD(const _EGLThreadInfo *t)
--
1.6.3.3
>From 80abf8f43dc829de8a6f885cc30fbbbfbf9eda34 Mon Sep 17 00:00:00 2001
From: Chia-I Wu <olva...@gmail.com>
Date: Thu, 1 Oct 2009 18:32:19 +0800
Subject: [PATCH 3/8] egl: Include GL header in eglconfigutil.h.
This is just a cosmetic change.
Signed-off-by: Chia-I Wu <olva...@gmail.com>
---
src/egl/main/eglconfigutil.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/egl/main/eglconfigutil.h b/src/egl/main/eglconfigutil.h
index ad85079..8c923ee 100644
--- a/src/egl/main/eglconfigutil.h
+++ b/src/egl/main/eglconfigutil.h
@@ -2,7 +2,7 @@
#define EGLCONFIGUTIL_INCLUDED
-#include "GLES/gl.h"
+#include "GL/gl.h"
#include "GL/internal/glcore.h"
#include "eglconfig.h"
--
1.6.3.3
>From 7a96b65582ff4a5cd3329bf0b234957774e80554 Mon Sep 17 00:00:00 2001
From: Chia-I Wu <olva...@gmail.com>
Date: Wed, 30 Sep 2009 15:34:45 +0800
Subject: [PATCH 4/8] egl: Rework error checking in eglGetCurrentSurface.
Signed-off-by: Chia-I Wu <olva...@gmail.com>
---
src/egl/main/eglapi.c | 22 ++++++++++++++++++++--
1 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index d86ef9c..1512c0a 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -568,8 +568,26 @@ eglGetCurrentContext(void)
EGLSurface EGLAPIENTRY
eglGetCurrentSurface(EGLint readdraw)
{
- _EGLSurface *s = _eglGetCurrentSurface(readdraw);
- return _eglGetSurfaceHandle(s);
+ _EGLContext *ctx = _eglGetCurrentContext();
+ _EGLSurface *surf;
+
+ if (!ctx)
+ return EGL_NO_SURFACE;
+
+ switch (readdraw) {
+ case EGL_DRAW:
+ surf = ctx->DrawSurface;
+ break;
+ case EGL_READ:
+ surf = ctx->ReadSurface;
+ break;
+ default:
+ _eglError(EGL_BAD_PARAMETER, __FUNCTION__);
+ surf = NULL;
+ break;
+ }
+
+ return _eglGetSurfaceHandle(surf);
}
--
1.6.3.3
>From 9315791cf29a1069eba56a29278f67a5adeb88f7 Mon Sep 17 00:00:00 2001
From: Chia-I Wu <olva...@gmail.com>
Date: Wed, 30 Sep 2009 15:08:34 +0800
Subject: [PATCH 5/8] egl: Update comments about eglapi.c.
Mention that opaque handles are looked up and checked.
Signed-off-by: Chia-I Wu <olva...@gmail.com>
---
src/egl/main/eglapi.c | 25 ++++++++++++++++++++-----
1 files changed, 20 insertions(+), 5 deletions(-)
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index 1512c0a..1d370db 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -9,12 +9,27 @@
* heterogeneous hardware devices in the future.
*
* The EGLDisplay, EGLConfig, EGLContext and EGLSurface types are
- * opaque handles implemented with 32-bit unsigned integers.
- * It's up to the driver function or fallback function to look up the
- * handle and get an object.
- * By using opaque handles, we leave open the possibility of having
- * indirect rendering in the future, like GLX.
+ * opaque handles. Internal objects are linked to a display to
+ * create the handles.
*
+ * For each public API entry point, the opaque handles are looked up
+ * before being dispatched to the drivers. When it fails to look up
+ * a handle, one of
+ *
+ * EGL_BAD_DISPLAY
+ * EGL_BAD_CONFIG
+ * EGL_BAD_CONTEXT
+ * EGL_BAD_SURFACE
+ * EGL_BAD_SCREEN_MESA
+ * EGL_BAD_MODE_MESA
+ *
+ * is generated and the driver function is not called. An
+ * uninitialized EGLDisplay has no driver associated with it. When
+ * such display is detected,
+ *
+ * EGL_NOT_INITIALIZED
+ *
+ * is generated.
*
* Notes on naming conventions:
*
--
1.6.3.3
>From d0e41db92f0bc60b9cdea3cc35d22ad3416979ba Mon Sep 17 00:00:00 2001
From: Chia-I Wu <olva...@gmail.com>
Date: Thu, 15 Oct 2009 11:08:33 +0800
Subject: [PATCH 6/8] egl: Rework error checking in eglSwapBuffers.
Signed-off-by: Chia-I Wu <olva...@gmail.com>
---
src/egl/main/eglapi.c | 15 +++++++++++++++
1 files changed, 15 insertions(+), 0 deletions(-)
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index 1d370db..3669018 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -31,6 +31,15 @@
*
* is generated.
*
+ * Some of the entry points use current display, context, or surface
+ * implicitly. For such entry points, the implicit objects are also
+ * checked before calling the driver function. Other than the
+ * errors listed above,
+ *
+ * EGL_BAD_CURRENT_SURFACE
+ *
+ * may also be generated.
+ *
* Notes on naming conventions:
*
* eglFooBar - public EGL function
@@ -519,7 +528,13 @@ eglSwapInterval(EGLDisplay dpy, EGLint interval)
EGLBoolean EGLAPIENTRY
eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
{
+ _EGLContext *ctx = _eglGetCurrentContext();
_EGL_DECLARE_DD_AND_SURFACE(dpy, surface);
+
+ /* surface must be bound to current context in EGL 1.4 */
+ if (!ctx || !_eglIsContextLinked(ctx) || surf != ctx->DrawSurface)
+ return _eglError(EGL_BAD_SURFACE, __FUNCTION__);
+
return drv->API.SwapBuffers(drv, disp, surf);
}
--
1.6.3.3
>From 4ba8c9fb399ad4a0f1c60cd133e832b6931467bd Mon Sep 17 00:00:00 2001
From: Chia-I Wu <olva...@gmail.com>
Date: Thu, 15 Oct 2009 11:08:48 +0800
Subject: [PATCH 7/8] egl: Rework eglSwapInterval.
This adds error checking to eglSwapInterval and clamps the swap
interval.
Signed-off-by: Chia-I Wu <olva...@gmail.com>
---
src/egl/main/eglapi.c | 12 +++++++++++-
src/egl/main/eglapi.h | 2 +-
src/egl/main/eglsurface.c | 27 ++++++++++++++++++++++-----
src/egl/main/eglsurface.h | 2 +-
4 files changed, 35 insertions(+), 8 deletions(-)
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index 3669018..5ce0469 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -520,8 +520,18 @@ eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
EGLBoolean EGLAPIENTRY
eglSwapInterval(EGLDisplay dpy, EGLint interval)
{
+ _EGLContext *ctx = _eglGetCurrentContext();
+ _EGLSurface *surf;
_EGL_DECLARE_DD(dpy);
- return drv->API.SwapInterval(drv, disp, interval);
+
+ if (!ctx || !_eglIsContextLinked(ctx) || ctx->Display != disp)
+ return _eglError(EGL_BAD_CONTEXT, __FUNCTION__);
+
+ surf = ctx->DrawSurface;
+ if (!_eglIsSurfaceLinked(surf))
+ return _eglError(EGL_BAD_SURFACE, __FUNCTION__);
+
+ return drv->API.SwapInterval(drv, disp, surf, interval);
}
diff --git a/src/egl/main/eglapi.h b/src/egl/main/eglapi.h
index 6081e58..feb35c8 100644
--- a/src/egl/main/eglapi.h
+++ b/src/egl/main/eglapi.h
@@ -35,7 +35,7 @@ typedef EGLBoolean (*QuerySurface_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurf
typedef EGLBoolean (*SurfaceAttrib_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, EGLint attribute, EGLint value);
typedef EGLBoolean (*BindTexImage_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, EGLint buffer);
typedef EGLBoolean (*ReleaseTexImage_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, EGLint buffer);
-typedef EGLBoolean (*SwapInterval_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLint interval);
+typedef EGLBoolean (*SwapInterval_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint interval);
typedef EGLBoolean (*SwapBuffers_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw);
typedef EGLBoolean (*CopyBuffers_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, NativePixmapType target);
diff --git a/src/egl/main/eglsurface.c b/src/egl/main/eglsurface.c
index e7a1a83..940a1b7 100644
--- a/src/egl/main/eglsurface.c
+++ b/src/egl/main/eglsurface.c
@@ -15,6 +15,22 @@
#include "eglsurface.h"
+static void
+_eglClampSwapInterval(_EGLSurface *surf, EGLint interval)
+{
+ EGLint bound = GET_CONFIG_ATTRIB(surf->Config, EGL_MAX_SWAP_INTERVAL);
+ if (interval >= bound) {
+ interval = bound;
+ }
+ else {
+ bound = GET_CONFIG_ATTRIB(surf->Config, EGL_MIN_SWAP_INTERVAL);
+ if (interval < bound)
+ interval = bound;
+ }
+ surf->SwapInterval = interval;
+}
+
+
/**
* Do error check on parameters and initialize the given _EGLSurface object.
* \return EGL_TRUE if no errors, EGL_FALSE otherwise.
@@ -194,7 +210,9 @@ _eglInitSurface(_EGLDriver *drv, _EGLSurface *surf, EGLint type,
surf->TextureTarget = texTarget;
surf->MipmapTexture = mipmapTex;
surf->MipmapLevel = 0;
- surf->SwapInterval = 0;
+ /* the default swap interval is 1 */
+ _eglClampSwapInterval(surf, 1);
+
#ifdef EGL_VERSION_1_2
surf->SwapBehavior = EGL_BUFFER_DESTROYED; /* XXX ok? */
surf->HorizontalResolution = EGL_UNKNOWN; /* set by caller */
@@ -466,11 +484,10 @@ _eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
EGLBoolean
-_eglSwapInterval(_EGLDriver *drv, _EGLDisplay *dpy, EGLint interval)
+_eglSwapInterval(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
+ EGLint interval)
{
- _EGLSurface *surf = _eglGetCurrentSurface(EGL_DRAW);
- if (surf)
- surf->SwapInterval = interval;
+ _eglClampSwapInterval(surf, interval);
return EGL_TRUE;
}
diff --git a/src/egl/main/eglsurface.h b/src/egl/main/eglsurface.h
index f6d44b5..b75fa9c 100644
--- a/src/egl/main/eglsurface.h
+++ b/src/egl/main/eglsurface.h
@@ -86,7 +86,7 @@ _eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint
extern EGLBoolean
-_eglSwapInterval(_EGLDriver *drv, _EGLDisplay *dpy, EGLint interval);
+_eglSwapInterval(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint interval);
#ifdef EGL_VERSION_1_2
--
1.6.3.3
>From 63a2b654c3a84e163865e75613a300acfa3624d3 Mon Sep 17 00:00:00 2001
From: Chia-I Wu <olva...@gmail.com>
Date: Mon, 28 Sep 2009 14:12:39 +0800
Subject: [PATCH 8/8] egl: Rework the synchronization primitives.
This adds error checking to the synchronization primitives. And
eglWaitGL is now implemented by eglWaitClient.
Signed-off-by: Chia-I Wu <olva...@gmail.com>
---
src/egl/main/eglapi.c | 66 +++++++++++++++++++++++++++++----------------
src/egl/main/eglapi.h | 6 +---
src/egl/main/egldriver.c | 2 +-
src/egl/main/eglmisc.c | 3 +-
src/egl/main/eglmisc.h | 2 +-
5 files changed, 48 insertions(+), 31 deletions(-)
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index 5ce0469..14cc5fa 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -558,32 +558,66 @@ eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, NativePixmapType target)
EGLBoolean EGLAPIENTRY
-eglWaitGL(void)
+eglWaitClient(void)
{
- _EGLDisplay *disp = _eglGetCurrentDisplay();
+ _EGLContext *ctx = _eglGetCurrentContext();
+ _EGLDisplay *disp;
_EGLDriver *drv;
- if (!disp)
+ if (!ctx)
return EGL_TRUE;
+ /* let bad current context imply bad current surface */
+ if (!_eglIsContextLinked(ctx) || !_eglIsSurfaceLinked(ctx->DrawSurface))
+ return _eglError(EGL_BAD_CURRENT_SURFACE, __FUNCTION__);
- /* a current display is always initialized */
+ /* a valid current context implies an initialized current display */
+ disp = ctx->Display;
drv = disp->Driver;
+ assert(drv);
+
+ return drv->API.WaitClient(drv, disp, ctx);
+}
+
- return drv->API.WaitGL(drv, disp);
+EGLBoolean EGLAPIENTRY
+eglWaitGL(void)
+{
+#ifdef EGL_VERSION_1_2
+ _EGLThreadInfo *t = _eglGetCurrentThread();
+ EGLint api_index = t->CurrentAPIIndex;
+ EGLint es_index = _eglConvertApiToIndex(EGL_OPENGL_ES_API);
+ EGLBoolean ret;
+
+ if (api_index != es_index && _eglIsCurrentThreadDummy())
+ return _eglError(EGL_BAD_ALLOC, "eglWaitGL");
+
+ t->CurrentAPIIndex = es_index;
+ ret = eglWaitClient();
+ t->CurrentAPIIndex = api_index;
+ return ret;
+#else
+ return eglWaitClient();
+#endif
}
EGLBoolean EGLAPIENTRY
eglWaitNative(EGLint engine)
{
- _EGLDisplay *disp = _eglGetCurrentDisplay();
+ _EGLContext *ctx = _eglGetCurrentContext();
+ _EGLDisplay *disp;
_EGLDriver *drv;
- if (!disp)
+ if (!ctx)
return EGL_TRUE;
+ /* let bad current context imply bad current surface */
+ if (!_eglIsContextLinked(ctx) || !_eglIsSurfaceLinked(ctx->DrawSurface))
+ return _eglError(EGL_BAD_CURRENT_SURFACE, __FUNCTION__);
- /* a current display is always initialized */
+ /* a valid current context implies an initialized current display */
+ disp = ctx->Display;
drv = disp->Driver;
+ assert(drv);
return drv->API.WaitNative(drv, disp, engine);
}
@@ -958,20 +992,4 @@ eglReleaseThread(void)
}
-EGLBoolean
-eglWaitClient(void)
-{
- _EGLDisplay *disp = _eglGetCurrentDisplay();
- _EGLDriver *drv;
-
- if (!disp)
- return EGL_TRUE;
-
- /* a current display is always initialized */
- drv = disp->Driver;
-
- return drv->API.WaitClient(drv, disp);
-}
-
-
#endif /* EGL_VERSION_1_2 */
diff --git a/src/egl/main/eglapi.h b/src/egl/main/eglapi.h
index feb35c8..aa0abe3 100644
--- a/src/egl/main/eglapi.h
+++ b/src/egl/main/eglapi.h
@@ -41,7 +41,7 @@ typedef EGLBoolean (*CopyBuffers_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurfa
/* misc funcs */
typedef const char *(*QueryString_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLint name);
-typedef EGLBoolean (*WaitGL_t)(_EGLDriver *drv, _EGLDisplay *dpy);
+typedef EGLBoolean (*WaitClient_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx);
typedef EGLBoolean (*WaitNative_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine);
typedef _EGLProc (*GetProcAddress_t)(const char *procname);
@@ -65,7 +65,6 @@ typedef const char * (*QueryModeStringMESA_t)(_EGLDriver *drv, _EGLDisplay *dpy,
#ifdef EGL_VERSION_1_2
-typedef EGLBoolean (*WaitClient_t)(_EGLDriver *drv, _EGLDisplay *dpy);
typedef _EGLSurface *(*CreatePbufferFromClientBuffer_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLenum buftype, EGLClientBuffer buffer, _EGLConfig *config, const EGLint *attrib_list);
#endif /* EGL_VERSION_1_2 */
@@ -101,7 +100,7 @@ struct _egl_api
CopyBuffers_t CopyBuffers;
QueryString_t QueryString;
- WaitGL_t WaitGL;
+ WaitClient_t WaitClient;
WaitNative_t WaitNative;
GetProcAddress_t GetProcAddress;
@@ -120,7 +119,6 @@ struct _egl_api
QueryModeStringMESA_t QueryModeStringMESA;
#ifdef EGL_VERSION_1_2
- WaitClient_t WaitClient;
CreatePbufferFromClientBuffer_t CreatePbufferFromClientBuffer;
#endif
};
diff --git a/src/egl/main/egldriver.c b/src/egl/main/egldriver.c
index 0c76c79..018b06d 100644
--- a/src/egl/main/egldriver.c
+++ b/src/egl/main/egldriver.c
@@ -408,7 +408,7 @@ _eglInitDriverFallbacks(_EGLDriver *drv)
drv->API.CopyBuffers = _eglCopyBuffers;
drv->API.QueryString = _eglQueryString;
- drv->API.WaitGL = _eglWaitGL;
+ drv->API.WaitClient = _eglWaitClient;
drv->API.WaitNative = _eglWaitNative;
#ifdef EGL_MESA_screen_surface
diff --git a/src/egl/main/eglmisc.c b/src/egl/main/eglmisc.c
index b37213f..e669133 100644
--- a/src/egl/main/eglmisc.c
+++ b/src/egl/main/eglmisc.c
@@ -108,11 +108,12 @@ _eglQueryString(_EGLDriver *drv, _EGLDisplay *dpy, EGLint name)
EGLBoolean
-_eglWaitGL(_EGLDriver *drv, _EGLDisplay *dpy)
+_eglWaitClient(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
{
/* just a placeholder */
(void) drv;
(void) dpy;
+ (void) ctx;
return EGL_TRUE;
}
diff --git a/src/egl/main/eglmisc.h b/src/egl/main/eglmisc.h
index a15c839..829d4cd 100644
--- a/src/egl/main/eglmisc.h
+++ b/src/egl/main/eglmisc.h
@@ -37,7 +37,7 @@ _eglQueryString(_EGLDriver *drv, _EGLDisplay *dpy, EGLint name);
extern EGLBoolean
-_eglWaitGL(_EGLDriver *drv, _EGLDisplay *dpy);
+_eglWaitClient(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx);
extern EGLBoolean
--
1.6.3.3
------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Mesa3d-dev mailing list
Mesa3d-dev@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mesa3d-dev