Hi,

This series have 4 patches.  The first two patches make current surface
point to current context, and make current context point to current
thread.  This change is required to, for example, check that if a
context that is already bound to a thread is bound to current thread.
It is to prevent stealing another thread's current context, as specified
in the spec.  It is also needed by eglBindTexImage, which I am still
working on.  The second patch overhauls eglMakeCurrent to make it work
as just said.  It also adds more checks and fixes a leak.

The other two patches are logically unrelated to the first two.  They
add pbuffer support to egl_softpipe.

-- 
Regards,
olv
>From 78764b0f4eb777d1c3b057b0d902b551733f17a8 Mon Sep 17 00:00:00 2001
From: Chia-I Wu <[email protected]>
Date: Thu, 30 Jul 2009 15:11:53 +0800
Subject: [PATCH 1/4] egl: Replace IsBound by a pointer to the binding.

IsBound tells if a context or surface is current.  What it does not tell
is, to which thread a context is current, or to which context a surface
is current.  This commit replaces IsBound by a pointer to the binding
thread or context.

Signed-off-by: Chia-I Wu <[email protected]>
---
 src/egl/drivers/demo/demo.c                  |    4 ++--
 src/egl/drivers/dri/egldri.c                 |    4 ++--
 src/egl/drivers/glx/egl_glx.c                |    2 +-
 src/egl/drivers/xdri/egl_xdri.c              |    2 +-
 src/egl/main/eglcontext.c                    |   14 +++++++-------
 src/egl/main/eglcontext.h                    |   17 ++++++++++++++---
 src/egl/main/eglsurface.c                    |    2 +-
 src/egl/main/eglsurface.h                    |   19 +++++++++++++++----
 src/gallium/state_trackers/egl/egl_context.c |    2 +-
 src/gallium/state_trackers/egl/egl_surface.c |    2 +-
 src/gallium/winsys/egl_xlib/egl_xlib.c       |    4 ++--
 src/mesa/drivers/dri/fb/fb_egl.c             |    4 ++--
 12 files changed, 49 insertions(+), 27 deletions(-)

diff --git a/src/egl/drivers/demo/demo.c b/src/egl/drivers/demo/demo.c
index f316974..e8c0c1d 100644
--- a/src/egl/drivers/demo/demo.c
+++ b/src/egl/drivers/demo/demo.c
@@ -236,7 +236,7 @@ demoDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
 {
    DemoSurface *fs = LookupDemoSurface(surface);
    _eglUnlinkSurface(&fs->Base);
-   if (!fs->Base.IsBound)
+   if (!_eglIsSurfaceBound(&fs->Base))
       free(fs);
    return EGL_TRUE;
 }
@@ -247,7 +247,7 @@ demoDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext context)
 {
    DemoContext *fc = LookupDemoContext(context);
    _eglUnlinkContext(&fc->Base);
-   if (!fc->Base.IsBound)
+   if (!_eglIsContextBound(&fc->Base))
       free(fc);
    return EGL_TRUE;
 }
diff --git a/src/egl/drivers/dri/egldri.c b/src/egl/drivers/dri/egldri.c
index 3f9617a..9e400be 100644
--- a/src/egl/drivers/dri/egldri.c
+++ b/src/egl/drivers/dri/egldri.c
@@ -296,7 +296,7 @@ _eglDRIDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
 
    fs->drawable.destroyDrawable(disp, fs->drawable.private);
 
-   if (!fs->Base.IsBound)
+   if (!_eglIsSurfaceBound(&fs->Base))
       free(fs);
    return EGL_TRUE;
 }
@@ -312,7 +312,7 @@ _eglDRIDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext context)
 
    fc->driContext.destroyContext(disp, 0, fc->driContext.private);
 
-   if (!fc->Base.IsBound)
+   if (!_eglIsContextBound(&fc->Base))
       free(fc);
    return EGL_TRUE;
 }
diff --git a/src/egl/drivers/glx/egl_glx.c b/src/egl/drivers/glx/egl_glx.c
index 207b1ea..5ed4b68 100644
--- a/src/egl/drivers/glx/egl_glx.c
+++ b/src/egl/drivers/glx/egl_glx.c
@@ -739,7 +739,7 @@ GLX_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
    return EGL_TRUE;
    if (surf) {
       _eglUnlinkSurface(surf);
-      if (!surf->IsBound)
+      if (!_eglIsSurfaceBound(surf))
          free(surf);
 
       return EGL_TRUE;
diff --git a/src/egl/drivers/xdri/egl_xdri.c b/src/egl/drivers/xdri/egl_xdri.c
index e040efd..d8d29fc 100644
--- a/src/egl/drivers/xdri/egl_xdri.c
+++ b/src/egl/drivers/xdri/egl_xdri.c
@@ -958,7 +958,7 @@ xdri_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
    struct xdri_egl_surface *xdri_surf = lookup_surface(surface);
    if (xdri_surf) {
       _eglUnlinkSurface(&xdri_surf->Base);
-      if (!xdri_surf->Base.IsBound) {
+      if (!_eglIsSurfaceBound(&xdri_surf->Base)) {
          /*
          st_unreference_framebuffer(surf->Framebuffer);
          */
diff --git a/src/egl/main/eglcontext.c b/src/egl/main/eglcontext.c
index 9ab4286..f8d5687 100644
--- a/src/egl/main/eglcontext.c
+++ b/src/egl/main/eglcontext.c
@@ -96,7 +96,7 @@ _eglDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx)
    _EGLContext *context = _eglLookupContext(ctx);
    if (context) {
       _eglUnlinkContext(context);
-      if (!context->IsBound)
+      if (!_eglIsContextBound(context))
          free(context);
       return EGL_TRUE;
    }
@@ -207,7 +207,7 @@ _eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d,
     * check if the old context or surfaces need to be deleted
     */
    if (oldDrawSurface != NULL) {
-      oldDrawSurface->IsBound = EGL_FALSE;
+      oldDrawSurface->Binding = NULL;
       if (!_eglIsSurfaceLinked(oldDrawSurface)) {
          /* make sure we don't try to rebind a deleted surface */
          if (draw == oldDrawSurface || draw == oldReadSurface) {
@@ -218,7 +218,7 @@ _eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d,
       }
    }
    if (oldReadSurface != NULL && oldReadSurface != oldDrawSurface) {
-      oldReadSurface->IsBound = EGL_FALSE;
+      oldReadSurface->Binding = NULL;
       if (!_eglIsSurfaceLinked(oldReadSurface)) {
          /* make sure we don't try to rebind a deleted surface */
          if (read == oldDrawSurface || read == oldReadSurface) {
@@ -229,7 +229,7 @@ _eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d,
       }
    }
    if (oldContext != NULL) {
-      oldContext->IsBound = EGL_FALSE;
+      oldContext->Binding = NULL;
       if (!_eglIsContextLinked(oldContext)) {
          /* make sure we don't try to rebind a deleted context */
          if (ctx == oldContext) {
@@ -248,9 +248,9 @@ _eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d,
       }
       ctx->DrawSurface = draw;
       ctx->ReadSurface = read;
-      ctx->IsBound = EGL_TRUE;
-      draw->IsBound = EGL_TRUE;
-      read->IsBound = EGL_TRUE;
+      ctx->Binding = t;
+      draw->Binding = ctx;
+      read->Binding = ctx;
       t->CurrentContexts[apiIndex] = ctx;
    }
    else {
diff --git a/src/egl/main/eglcontext.h b/src/egl/main/eglcontext.h
index 2fb28d3..4276c09 100644
--- a/src/egl/main/eglcontext.h
+++ b/src/egl/main/eglcontext.h
@@ -15,12 +15,12 @@ struct _egl_context
    _EGLDisplay *Display;
    _EGLContext *Next;
 
-   _EGLConfig *Config;
-
+   /* The bound status of the context */
+   _EGLThreadInfo *Binding;
    _EGLSurface *DrawSurface;
    _EGLSurface *ReadSurface;
 
-   EGLBoolean IsBound;
+   _EGLConfig *Config;
 
    EGLint ClientAPI; /**< EGL_OPENGL_ES_API, EGL_OPENGL_API, EGL_OPENVG_API */
    EGLint ClientVersion; /**< 1 = OpenGLES 1.x, 2 = OpenGLES 2.x */
@@ -51,4 +51,15 @@ _eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, EGLSurface rea
 extern EGLBoolean
 _eglCopyContextMESA(_EGLDriver *drv, EGLDisplay dpy, EGLContext source, EGLContext dest, EGLint mask);
 
+
+/**
+ * Return true if the context is bound to a thread.
+ */
+static INLINE EGLBoolean
+_eglIsContextBound(_EGLContext *ctx)
+{
+   return (ctx->Binding != NULL);
+}
+
+
 #endif /* EGLCONTEXT_INCLUDED */
diff --git a/src/egl/main/eglsurface.c b/src/egl/main/eglsurface.c
index 9821e63..bd263fe 100644
--- a/src/egl/main/eglsurface.c
+++ b/src/egl/main/eglsurface.c
@@ -413,7 +413,7 @@ _eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
    _EGLSurface *surf = _eglLookupSurface(surface);
    if (surf) {
       _eglUnlinkSurface(surf);
-      if (!surf->IsBound)
+      if (!_eglIsSurfaceBound(surf))
          free(surf);
       return EGL_TRUE;
    }
diff --git a/src/egl/main/eglsurface.h b/src/egl/main/eglsurface.h
index f9413eb..8864176 100644
--- a/src/egl/main/eglsurface.h
+++ b/src/egl/main/eglsurface.h
@@ -15,12 +15,12 @@ struct _egl_surface
    _EGLSurface *Next;
    EGLSurface Handle;
 
-   _EGLConfig *Config;
-
-   /* May need reference counting here */
-   EGLBoolean IsBound;
+   /* The bound status of the surface */
+   _EGLContext *Binding;
    EGLBoolean BoundToTexture;
 
+   _EGLConfig *Config;
+
    EGLint Type; /* one of EGL_WINDOW_BIT, EGL_PIXMAP_BIT or EGL_PBUFFER_BIT */
    EGLint Width, Height;
    EGLint TextureFormat, TextureTarget;
@@ -100,5 +100,16 @@ _eglCreatePbufferFromClientBuffer(_EGLDriver *drv, EGLDisplay dpy,
 #endif /* EGL_VERSION_1_2 */
 
 
+/**
+ * Return true if the surface is bound to a thread.
+ * A surface bound to a texutre is not considered bound by
+ * this function.
+ */
+static INLINE EGLBoolean
+_eglIsSurfaceBound(_EGLSurface *surf)
+{
+   return (surf->Binding != NULL);
+}
+
 
 #endif /* EGLSURFACE_INCLUDED */
diff --git a/src/gallium/state_trackers/egl/egl_context.c b/src/gallium/state_trackers/egl/egl_context.c
index e2da218..2c8f51c 100644
--- a/src/gallium/state_trackers/egl/egl_context.c
+++ b/src/gallium/state_trackers/egl/egl_context.c
@@ -148,7 +148,7 @@ drm_destroy_context(_EGLDriver *drv, EGLDisplay dpy, EGLContext context)
 {
 	struct drm_context *c = lookup_drm_context(context);
         _eglUnlinkContext(&c->base);
-	if (!c->base.IsBound) {
+	if (!_eglIsContextBound(&c->base)) {
 		st_destroy_context(c->st);
 		c->pipe->destroy(c->pipe);
 		free(c);
diff --git a/src/gallium/state_trackers/egl/egl_surface.c b/src/gallium/state_trackers/egl/egl_surface.c
index 86f2ea9..7413c9b 100644
--- a/src/gallium/state_trackers/egl/egl_surface.c
+++ b/src/gallium/state_trackers/egl/egl_surface.c
@@ -366,7 +366,7 @@ drm_destroy_surface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
 	struct drm_surface *surf = lookup_drm_surface(surface);
 	_eglUnlinkSurface(&surf->base);
 
-	if (!surf->base.IsBound) {
+	if (!_eglIsSurfaceBound(&surf->base)) {
 		if (surf->screen)
 			drm_takedown_shown_screen(drv, surf->screen);
 		st_unreference_framebuffer(surf->stfb);
diff --git a/src/gallium/winsys/egl_xlib/egl_xlib.c b/src/gallium/winsys/egl_xlib/egl_xlib.c
index e1ddcae..1a1dad6 100644
--- a/src/gallium/winsys/egl_xlib/egl_xlib.c
+++ b/src/gallium/winsys/egl_xlib/egl_xlib.c
@@ -382,7 +382,7 @@ xlib_eglDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx)
    struct xlib_egl_context *context = lookup_context(ctx);
    if (context) {
       _eglUnlinkContext(&context->Base);
-      if (!context->Base.IsBound) {
+      if (!_eglIsContextBound(&context->Base)) {
          /* API-dependent clean-up */
          switch (context->Base.ClientAPI) {
          case EGL_OPENGL_ES_API:
@@ -533,7 +533,7 @@ xlib_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
    struct xlib_egl_surface *surf = lookup_surface(surface);
    if (surf) {
       _eglUnlinkSurface(&surf->Base);
-      if (!surf->Base.IsBound) {
+      if (!_eglIsSurfaceBound(&surf->Base)) {
          XFreeGC(surf->Dpy, surf->Gc);
          st_unreference_framebuffer(surf->Framebuffer);
          free(surf);
diff --git a/src/mesa/drivers/dri/fb/fb_egl.c b/src/mesa/drivers/dri/fb/fb_egl.c
index dee67fe..4e41860 100644
--- a/src/mesa/drivers/dri/fb/fb_egl.c
+++ b/src/mesa/drivers/dri/fb/fb_egl.c
@@ -605,7 +605,7 @@ fbDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
 {
    fbSurface *fs = Lookup_fbSurface(surface);
    _eglUnlinkSurface(&fs->Base);
-   if (!fs->Base.IsBound)
+   if (!_eglIsSurfaceBound(&fs->Base))
       free(fs);
    return EGL_TRUE;
 }
@@ -616,7 +616,7 @@ fbDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext context)
 {
    fbContext *fc = Lookup_fbContext(context);
    _eglUnlinkContext(&fc->Base);
-   if (!fc->Base.IsBound)
+   if (!_eglIsContextBound(&fc->Base))
       free(fc);
    return EGL_TRUE;
 }
-- 
1.6.2.4

>From 1731678326195a4c2d7679d4d0b7b72169796a42 Mon Sep 17 00:00:00 2001
From: Chia-I Wu <[email protected]>
Date: Thu, 30 Jul 2009 16:12:26 +0800
Subject: [PATCH 2/4] egl: Make eglMakeCurrent more robust.

Now that a current surface points back to its binding context, and a
current context points back to its binding thread, make sure there is no
dangling pointers.  This commit reworks eglMakeCurrent, adds more checks
to avoid stealing context or surfaces from another thread, and correctly
destroys unlinked context and surfaces.

Signed-off-by: Chia-I Wu <[email protected]>
---
 src/egl/main/eglcontext.c |   98 +++++++++++++++++++++------------------------
 1 files changed, 46 insertions(+), 52 deletions(-)

diff --git a/src/egl/main/eglcontext.c b/src/egl/main/eglcontext.c
index f8d5687..88de60d 100644
--- a/src/egl/main/eglcontext.c
+++ b/src/egl/main/eglcontext.c
@@ -146,10 +146,11 @@ _eglQueryContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx,
  * Then, the driver will do its device-dependent Make-Current stuff.
  */
 EGLBoolean
-_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d,
+_eglMakeCurrent(_EGLDriver *drv, EGLDisplay display, EGLSurface d,
                 EGLSurface r, EGLContext context)
 {
    _EGLThreadInfo *t = _eglGetCurrentThread();
+   _EGLDisplay *dpy = _eglLookupDisplay(display);
    _EGLContext *ctx = _eglLookupContext(context);
    _EGLSurface *draw = _eglLookupSurface(d);
    _EGLSurface *read = _eglLookupSurface(r);
@@ -160,21 +161,23 @@ _eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d,
 
    if (_eglIsCurrentThreadDummy())
       return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent");
+   if (dpy == NULL)
+      return _eglError(EGL_BAD_DISPLAY, "eglMakeCurrent");
 
-   /* error checking */
    if (ctx) {
+      /* error checking */
+      if (ctx->Binding && ctx->Binding != t)
+         return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
       if (draw == NULL || read == NULL) {
-         _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
-         return EGL_FALSE;
-      }
-      if (draw->Config != ctx->Config) {
-         _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
-         return EGL_FALSE;
-      }
-      if (read->Config != ctx->Config) {
-         _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
-         return EGL_FALSE;
+         EGLint err = (d == EGL_NO_SURFACE || r == EGL_NO_SURFACE)
+                      ? EGL_BAD_MATCH : EGL_BAD_SURFACE;
+         return _eglError(err, "eglMakeCurrent");
       }
+      if (draw->Config != ctx->Config || read->Config != ctx->Config)
+         return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
+      if ((draw->Binding && draw->Binding->Binding != t) ||
+          (read->Binding && read->Binding->Binding != t))
+         return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
 
 #ifdef EGL_VERSION_1_4
       /* OpenGL and OpenGL ES are conflicting */
@@ -194,6 +197,10 @@ _eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d,
       apiIndex = _eglConvertApiToIndex(ctx->ClientAPI);
    }
    else {
+      if (context != EGL_NO_CONTEXT)
+         return _eglError(EGL_BAD_CONTEXT, "eglMakeCurrent");
+      if (draw != NULL || read != NULL)
+         return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
       apiIndex = t->CurrentAPIIndex;
    }
 
@@ -201,60 +208,47 @@ _eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d,
    if (oldContext) {
       oldDrawSurface = oldContext->DrawSurface;
       oldReadSurface = oldContext->ReadSurface;
-   }
+      assert(oldDrawSurface);
+      assert(oldReadSurface);
 
-   /*
-    * check if the old context or surfaces need to be deleted
-    */
-   if (oldDrawSurface != NULL) {
+      /* break old bindings */
+      t->CurrentContexts[apiIndex] = NULL;
+      oldContext->Binding = NULL;
+      oldContext->DrawSurface = NULL;
+      oldContext->ReadSurface = NULL;
       oldDrawSurface->Binding = NULL;
+      oldReadSurface->Binding = NULL;
+
+      /*
+       * check if the old context or surfaces need to be deleted
+       * FIXME They are linked so that they can be unlinked.  This is ugly.
+       */
       if (!_eglIsSurfaceLinked(oldDrawSurface)) {
-         /* make sure we don't try to rebind a deleted surface */
-         if (draw == oldDrawSurface || draw == oldReadSurface) {
-            draw = NULL;
-         }
-         /* really delete surface now */
-         drv->API.DestroySurface(drv, dpy, oldDrawSurface->Handle);
+         assert(draw != oldDrawSurface && read != oldDrawSurface);
+         drv->API.DestroySurface(drv, display,
+                                 _eglLinkSurface(oldDrawSurface, dpy));
       }
-   }
-   if (oldReadSurface != NULL && oldReadSurface != oldDrawSurface) {
-      oldReadSurface->Binding = NULL;
-      if (!_eglIsSurfaceLinked(oldReadSurface)) {
-         /* make sure we don't try to rebind a deleted surface */
-         if (read == oldDrawSurface || read == oldReadSurface) {
-            read = NULL;
-         }
-         /* really delete surface now */
-         drv->API.DestroySurface(drv, dpy, oldReadSurface->Handle);
+      if (oldReadSurface != oldDrawSurface &&
+          !_eglIsSurfaceLinked(oldReadSurface)) {
+         assert(draw != oldReadSurface && read != oldReadSurface);
+         drv->API.DestroySurface(drv, display,
+                                 _eglLinkSurface(oldReadSurface, dpy));
       }
-   }
-   if (oldContext != NULL) {
-      oldContext->Binding = NULL;
       if (!_eglIsContextLinked(oldContext)) {
-         /* make sure we don't try to rebind a deleted context */
-         if (ctx == oldContext) {
-            ctx = NULL;
-         }
-         /* really delete context now */
-         drv->API.DestroyContext(drv, dpy, _eglGetContextHandle(oldContext));
+         assert(ctx != oldContext);
+         drv->API.DestroyContext(drv, display,
+                                 _eglLinkContext(oldContext, dpy));
       }
    }
 
+   /* build new bindings */
    if (ctx) {
-      /* check read/draw again, in case we deleted them above */
-      if (draw == NULL || read == NULL) {
-         _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
-         return EGL_FALSE;
-      }
+      t->CurrentContexts[apiIndex] = ctx;
+      ctx->Binding = t;
       ctx->DrawSurface = draw;
       ctx->ReadSurface = read;
-      ctx->Binding = t;
       draw->Binding = ctx;
       read->Binding = ctx;
-      t->CurrentContexts[apiIndex] = ctx;
-   }
-   else {
-      t->CurrentContexts[apiIndex] = NULL;
    }
 
    return EGL_TRUE;
-- 
1.6.2.4

>From 65fc7c1bd61178c94e418023e746ed4e9155254e Mon Sep 17 00:00:00 2001
From: Chia-I Wu <[email protected]>
Date: Mon, 3 Aug 2009 15:10:30 +0800
Subject: [PATCH 3/4] egl: Correct the default values of surface attributes.

EGL_TEXTURE_FORMAT and EGL_TEXTURE_TARGET should default to
EGL_NO_TEXTURE.

Signed-off-by: Chia-I Wu <[email protected]>
---
 src/egl/main/eglsurface.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/src/egl/main/eglsurface.c b/src/egl/main/eglsurface.c
index bd263fe..3947051 100644
--- a/src/egl/main/eglsurface.c
+++ b/src/egl/main/eglsurface.c
@@ -26,7 +26,8 @@ _eglInitSurface(_EGLDriver *drv, _EGLSurface *surf, EGLint type,
 {
    const char *func;
    EGLint width = 0, height = 0, largest = 0;
-   EGLint texFormat = 0, texTarget = 0, mipmapTex = 0;
+   EGLint texFormat = EGL_NO_TEXTURE, texTarget = EGL_NO_TEXTURE;
+   EGLint mipmapTex = EGL_FALSE;
    EGLint renderBuffer = EGL_BACK_BUFFER;
 #ifdef EGL_VERSION_1_2
    EGLint colorspace = EGL_COLORSPACE_sRGB;
-- 
1.6.2.4

>From ceea0f1fb56947be302686fd78b264317259bdc8 Mon Sep 17 00:00:00 2001
From: Chia-I Wu <[email protected]>
Date: Fri, 31 Jul 2009 14:21:54 +0800
Subject: [PATCH 4/4] egl_softpipe: Add support for pbuffer surface.


Signed-off-by: Chia-I Wu <[email protected]>
---
 src/gallium/winsys/egl_xlib/egl_xlib.c |  103 +++++++++++++++++++++++++++++--
 1 files changed, 96 insertions(+), 7 deletions(-)

diff --git a/src/gallium/winsys/egl_xlib/egl_xlib.c b/src/gallium/winsys/egl_xlib/egl_xlib.c
index 1a1dad6..2acfbf8 100644
--- a/src/gallium/winsys/egl_xlib/egl_xlib.c
+++ b/src/gallium/winsys/egl_xlib/egl_xlib.c
@@ -82,6 +82,7 @@ struct xlib_egl_surface
 {
    _EGLSurface Base;   /**< base class */
 
+   /* These are set for window surface */
    Display *Dpy;  /**< The X Display of the window */
    Window Win;    /**< The user-created window ID */
    GC Gc;
@@ -101,7 +102,7 @@ xlib_egl_driver(_EGLDriver *drv)
 }
 
 
-static struct xlib_egl_surface *
+static INLINE struct xlib_egl_surface *
 lookup_surface(EGLSurface surf)
 {
    _EGLSurface *surface = _eglLookupSurface(surf);
@@ -109,10 +110,10 @@ lookup_surface(EGLSurface surf)
 }
 
 
-static struct xlib_egl_context *
-lookup_context(EGLContext surf)
+static INLINE struct xlib_egl_context *
+lookup_context(EGLContext ctx)
 {
-   _EGLContext *context = _eglLookupContext(surf);
+   _EGLContext *context = _eglLookupContext(ctx);
    return (struct xlib_egl_context *) context;
 }
 
@@ -180,7 +181,7 @@ create_configs(_EGLDriver *drv, EGLDisplay dpy)
       SET_CONFIG_ATTRIB(config, EGL_NATIVE_RENDERABLE, EGL_FALSE);
       SET_CONFIG_ATTRIB(config, EGL_CONFORMANT, all_apis);
       SET_CONFIG_ATTRIB(config, EGL_RENDERABLE_TYPE, all_apis);
-      SET_CONFIG_ATTRIB(config, EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
+      SET_CONFIG_ATTRIB(config, EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT);
 
       _eglAddConfig(disp, config);
    }
@@ -264,7 +265,13 @@ static void
 check_and_update_buffer_size(struct xlib_egl_surface *surface)
 {
    uint width, height;
-   get_drawable_size(surface->Dpy, surface->Win, &width, &height);
+   if (surface->Base.Type == EGL_PBUFFER_BIT) {
+      width = surface->Base.Width;
+      height = surface->Base.Height;
+   }
+   else {
+      get_drawable_size(surface->Dpy, surface->Win, &width, &height);
+   }
    st_resize_framebuffer(surface->Framebuffer, width, height);
    surface->Base.Width = width;
    surface->Base.Height = height;
@@ -281,6 +288,9 @@ display_surface(struct pipe_winsys *pws,
    XImage *ximage;
    void *data;
 
+   if (xsurf->Base.Type == EGL_PBUFFER_BIT)
+      return;
+
    ximage = XCreateImage(xsurf->Dpy,
                          xsurf->VisInfo.visual,
                          xsurf->VisInfo.depth,
@@ -527,6 +537,83 @@ xlib_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
 }
 
 
+static EGLSurface
+xlib_eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
+                             const EGLint *attrib_list)
+{
+   struct xlib_egl_driver *xdrv = xlib_egl_driver(drv);
+   _EGLDisplay *disp = _eglLookupDisplay(dpy);
+   _EGLConfig *conf = _eglLookupConfig(drv, dpy, config);
+   struct xlib_egl_surface *surf;
+   __GLcontextModes visual;
+   uint width, height;
+   EGLBoolean bind_texture;
+
+   if (!disp) {
+      _eglError(EGL_BAD_DISPLAY, "eglCreatePbufferSurface");
+      return EGL_NO_SURFACE;
+   }
+   if (!conf) {
+      _eglError(EGL_BAD_CONFIG, "eglCreatePbufferSurface");
+      return EGL_NO_SURFACE;
+   }
+
+   surf = CALLOC_STRUCT(xlib_egl_surface);
+   if (!surf) {
+      _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface");
+      return EGL_NO_SURFACE;
+   }
+
+   if (!_eglInitSurface(drv, &surf->Base, EGL_PBUFFER_BIT,
+                        conf, attrib_list)) {
+      free(surf);
+      return EGL_NO_SURFACE;
+   }
+   if (surf->Base.Width < 0 || surf->Base.Height < 0) {
+      _eglError(EGL_BAD_PARAMETER, "eglCreatePbufferSurface");
+      free(surf);
+      return EGL_NO_SURFACE;
+   }
+
+   bind_texture = (surf->Base.TextureFormat != EGL_NO_TEXTURE);
+   width = (uint) surf->Base.Width;
+   height = (uint) surf->Base.Height;
+   if ((surf->Base.TextureTarget == EGL_NO_TEXTURE && bind_texture) ||
+       (surf->Base.TextureTarget != EGL_NO_TEXTURE && !bind_texture)) {
+      _eglError(EGL_BAD_MATCH, "eglCreatePbufferSurface");
+      free(surf);
+      return EGL_NO_SURFACE;
+   }
+   /* a framebuffer of zero width or height confuses st */
+   if (width == 0 || height == 0) {
+      _eglError(EGL_BAD_MATCH, "eglCreatePbufferSurface");
+      free(surf);
+      return EGL_NO_SURFACE;
+   }
+   /* no mipmap generation */
+   if (surf->Base.MipmapTexture) {
+      _eglError(EGL_BAD_MATCH, "eglCreatePbufferSurface");
+      free(surf);
+      return EGL_NO_SURFACE;
+   }
+
+   surf->winsys = xdrv->winsys;
+
+   _eglConfigToContextModesRec(conf, &visual);
+
+   /* Create GL statetracker framebuffer */
+   surf->Framebuffer = st_create_framebuffer(&visual,
+                                             choose_color_format(&visual),
+                                             choose_depth_format(&visual),
+                                             choose_stencil_format(&visual),
+                                             width, height,
+                                             (void *) surf);
+   st_resize_framebuffer(surf->Framebuffer, width, height);
+
+   return _eglLinkSurface(&surf->Base, disp);
+}
+
+
 static EGLBoolean
 xlib_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
 {
@@ -534,7 +621,8 @@ xlib_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
    if (surf) {
       _eglUnlinkSurface(&surf->Base);
       if (!_eglIsSurfaceBound(&surf->Base)) {
-         XFreeGC(surf->Dpy, surf->Gc);
+         if (surf->Base.Type != EGL_PBUFFER_BIT)
+            XFreeGC(surf->Dpy, surf->Gc);
          st_unreference_framebuffer(surf->Framebuffer);
          free(surf);
       }
@@ -631,6 +719,7 @@ _eglMain(_EGLDisplay *dpy, const char *args)
    xdrv->Base.API.CreateContext = xlib_eglCreateContext;
    xdrv->Base.API.DestroyContext = xlib_eglDestroyContext;
    xdrv->Base.API.CreateWindowSurface = xlib_eglCreateWindowSurface;
+   xdrv->Base.API.CreatePbufferSurface = xlib_eglCreatePbufferSurface;
    xdrv->Base.API.DestroySurface = xlib_eglDestroySurface;
    xdrv->Base.API.MakeCurrent = xlib_eglMakeCurrent;
    xdrv->Base.API.SwapBuffers = xlib_eglSwapBuffers;
-- 
1.6.2.4

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with 
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Mesa3d-dev mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mesa3d-dev

Reply via email to