This patch series adds eglBindTexImage support for egl_softpipe.  The
API can be used to, for example, use OpenVG to render into a pbuffer and
bind it as an OpenGL texture.  The changes made to mesa st should also
be able to be used to implement EXT_texture_from_pixmap, if someone is
interested.

The first two patches are disscussed in another thread.  They should
have incorporated all the suggestions.  Better naming, more comments,
etc. 

The third patch makes eglMakeCurrent imply flushing in egl_softpipe, as
required by EGL.  As shown in the comments, there is some room for
improvement.

The last two patches implement eglBindTexImage and add a simple demo.

-- 
Regards,
olv
>From 086b5c5fae95da233281b014e1f483d3507d0da1 Mon Sep 17 00:00:00 2001
From: Chia-I Wu <olva...@gmail.com>
Date: Mon, 3 Aug 2009 16:38:26 +0800
Subject: [PATCH 1/5] mesa/main: Add functions to clear and dirty texture objects.

This commit adds a function to clear a texture object such that there is
no image data associated with it, and a function to dirty it so that it
will be re-tested for completeness.

Signed-off-by: Chia-I Wu <olva...@gmail.com>
---
 src/mesa/main/teximage.c |   17 +++++++++++++++++
 src/mesa/main/teximage.h |    4 ++++
 src/mesa/main/texobj.c   |   45 ++++++++++++++++++++++++++++++++++++++++++++-
 src/mesa/main/texobj.h   |    8 +++++++-
 4 files changed, 72 insertions(+), 2 deletions(-)

diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c
index 825f5e2..31416ff 100644
--- a/src/mesa/main/teximage.c
+++ b/src/mesa/main/teximage.c
@@ -1216,6 +1216,23 @@ _mesa_init_teximage_fields(GLcontext *ctx, GLenum target,
 
 
 /**
+ * Free and clear fields of the gl_texture_image struct.
+ *
+ * \param ctx GL context.
+ * \param texImage texture image structure to be cleared.
+ *
+ * After the call, \p texImage will have no data associated with it.  Its
+ * fields are cleared so that its parent object will test incomplete.
+ */
+void
+_mesa_clear_texture_image(GLcontext *ctx, struct gl_texture_image *texImage)
+{
+   ctx->Driver.FreeTexImageData(ctx, texImage);
+   clear_teximage_fields(texImage);
+}
+
+
+/**
  * This is the fallback for Driver.TestProxyTexImage().  Test the texture
  * level, width, height and depth against the ctx->Const limits for textures.
  *
diff --git a/src/mesa/main/teximage.h b/src/mesa/main/teximage.h
index eb60a1f..b0d7c1c 100644
--- a/src/mesa/main/teximage.h
+++ b/src/mesa/main/teximage.h
@@ -73,6 +73,10 @@ _mesa_init_teximage_fields(GLcontext *ctx, GLenum target,
 
 
 extern void
+_mesa_clear_texture_image(GLcontext *ctx, struct gl_texture_image *texImage);
+
+
+extern void
 _mesa_set_tex_image(struct gl_texture_object *tObj,
                     GLenum target, GLint level,
                     struct gl_texture_image *texImage);
diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c
index 2082f94..9a7773d 100644
--- a/src/mesa/main/texobj.c
+++ b/src/mesa/main/texobj.c
@@ -261,6 +261,32 @@ _mesa_copy_texture_object( struct gl_texture_object *dest,
 
 
 /**
+ * Clear all texture images of the given texture object.
+ *
+ * \param ctx GL context.
+ * \param t texture object.
+ *
+ * \sa _mesa_clear_texture_image().
+ */
+void
+_mesa_clear_texture_object(GLcontext *ctx, struct gl_texture_object *texObj)
+{
+   GLuint i, j;
+
+   if (texObj->Target == 0)
+      return;
+
+   for (i = 0; i < MAX_FACES; i++) {
+      for (j = 0; j < MAX_TEXTURE_LEVELS; j++) {
+         struct gl_texture_image *texImage = texObj->Image[i][j];
+         if (texImage)
+            _mesa_clear_texture_image(ctx, texImage);
+      }
+   }
+}
+
+
+/**
  * Check if the given texture object is valid by examining its Target field.
  * For debugging only.
  */
@@ -665,6 +691,24 @@ _mesa_test_texobj_completeness( const GLcontext *ctx,
 
 
 /**
+ * Mark a texture object dirty.  It forces the object to be incomplete
+ * and optionally forces the context to re-validate its state.
+ *
+ * \param ctx GL context.
+ * \param texObj texture object.
+ * \param invalidate_state also invalidate context state.
+ */
+void
+_mesa_dirty_texobj(GLcontext *ctx, struct gl_texture_object *texObj,
+                   GLboolean invalidate_state)
+{
+   texObj->_Complete = GL_FALSE;
+   if (invalidate_state)
+      ctx->NewState |= _NEW_TEXTURE;
+}
+
+
+/**
  * Return pointer to a default/fallback texture.
  * The texture is a 2D 8x8 RGBA texture with all texels = (0,0,0,1).
  * That's the value a sampler should get when sampling from an
@@ -715,7 +759,6 @@ _mesa_get_fallback_texture(GLcontext *ctx)
 }
 
 
-
 /*...@}*/
 
 
diff --git a/src/mesa/main/texobj.h b/src/mesa/main/texobj.h
index 2599c08..9bfebd4 100644
--- a/src/mesa/main/texobj.h
+++ b/src/mesa/main/texobj.h
@@ -58,6 +58,9 @@ _mesa_copy_texture_object( struct gl_texture_object *dest,
                            const struct gl_texture_object *src );
 
 extern void
+_mesa_clear_texture_object(GLcontext *ctx, struct gl_texture_object *obj);
+
+extern void
 _mesa_reference_texobj(struct gl_texture_object **ptr,
                        struct gl_texture_object *tex);
 
@@ -65,6 +68,10 @@ extern void
 _mesa_test_texobj_completeness( const GLcontext *ctx,
                                 struct gl_texture_object *obj );
 
+extern void
+_mesa_dirty_texobj(GLcontext *ctx, struct gl_texture_object *texObj,
+                   GLboolean invalidate_state);
+
 extern struct gl_texture_object *
 _mesa_get_fallback_texture(GLcontext *ctx);
 
@@ -76,7 +83,6 @@ _mesa_lock_context_textures( GLcontext *ctx );
 
 /*...@}*/
 
-
 /**
  * \name API functions
  */
-- 
1.6.2.4

>From 8198cfa55314b99757861e2cabec8ca1a5b54856 Mon Sep 17 00:00:00 2001
From: Chia-I Wu <olva...@gmail.com>
Date: Thu, 23 Jul 2009 18:57:49 +0800
Subject: [PATCH 2/5] mesa/st: Add support for binding pipe surface to texture.

This commit adds functions to bind a pipe surface to a texture.  This
allows texturing directly from the surface.

Signed-off-by: Chia-I Wu <olva...@gmail.com>
---
 src/mesa/state_tracker/st_cb_texture.c |    6 ++
 src/mesa/state_tracker/st_public.h     |    4 +-
 src/mesa/state_tracker/st_texture.c    |  108 +++++++++++++++++++++++++++-----
 src/mesa/state_tracker/st_texture.h    |    5 ++
 4 files changed, 107 insertions(+), 16 deletions(-)

diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c
index e8d7f70..90a059c 100644
--- a/src/mesa/state_tracker/st_cb_texture.c
+++ b/src/mesa/state_tracker/st_cb_texture.c
@@ -523,6 +523,12 @@ st_TexImage(GLcontext * ctx,
    DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__,
        _mesa_lookup_enum_by_nr(target), level, width, height, depth, border);
 
+   /* switch to "normal" */
+   if (stObj->surface_based) {
+      _mesa_clear_texture_object(ctx, texObj);
+      stObj->surface_based = GL_FALSE;
+   }
+
    /* gallium does not support texture borders, strip it off */
    if (border) {
       strip_texture_border(border, &width, &height, &depth, unpack, &unpackNB);
diff --git a/src/mesa/state_tracker/st_public.h b/src/mesa/state_tracker/st_public.h
index 04d3a3d..a5fdac3 100644
--- a/src/mesa/state_tracker/st_public.h
+++ b/src/mesa/state_tracker/st_public.h
@@ -107,7 +107,9 @@ void st_swapbuffers(struct st_framebuffer *stfb,
                     struct pipe_surface **front_left,
                     struct pipe_surface **front_right);
 
-int st_set_teximage(struct pipe_texture *pt, int target);
+int st_bind_texture_surface(struct pipe_surface *ps, int target, int level,
+                            enum pipe_format format);
+int st_unbind_texture_surface(struct pipe_surface *ps, int target, int level);
 
 /** Redirect rendering into stfb's surface to a texture image */
 int st_bind_teximage(struct st_framebuffer *stfb, uint surfIndex,
diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c
index 10faa63..d588039 100644
--- a/src/mesa/state_tracker/st_texture.c
+++ b/src/mesa/state_tracker/st_texture.c
@@ -32,6 +32,7 @@
 #include "st_cb_fbo.h"
 #include "st_inlines.h"
 #include "main/enums.h"
+#include "main/texobj.h"
 #include "main/teximage.h"
 #include "main/texstore.h"
 
@@ -353,25 +354,95 @@ st_texture_image_copy(struct pipe_context *pipe,
    }
 }
 
-/** Bind a pipe surface for use as a texture image */
+
+/**
+ * Bind a pipe surface to a texture object.  After the call,
+ * the texture object is marked dirty and will be (re-)validated.
+ *
+ * If this is the first surface bound, the texture object is said to
+ * switch from normal to surface based.  It will be cleared first in
+ * this case.
+ *
+ * \param ps      pipe surface to be unbound
+ * \param target  texture target
+ * \param level   image level
+ * \param format  internal format of the texture
+ */
 int
-st_set_teximage(struct pipe_texture *pt, int target)
+st_bind_texture_surface(struct pipe_surface *ps, int target, int level,
+                        enum pipe_format format)
 {
    GET_CURRENT_CONTEXT(ctx);
    const GLuint unit = ctx->Texture.CurrentUnit;
    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
    struct gl_texture_object *texObj;
    struct gl_texture_image *texImage;
+   struct st_texture_object *stObj;
    struct st_texture_image *stImage;
-   int internalFormat;
+   GLenum internalFormat;
 
-   switch (pt->format) {
-   case PIPE_FORMAT_A8R8G8B8_UNORM:
-      internalFormat = GL_RGBA8;
+   switch (target) {
+   case ST_TEXTURE_2D:
+      target = GL_TEXTURE_2D;
+      break;
+   case ST_TEXTURE_RECT:
+      target = GL_TEXTURE_RECTANGLE_ARB;
       break;
    default:
       return 0;
-   };
+   }
+
+   /* map pipe format to base format for now */
+   if (pf_get_component_bits(format, PIPE_FORMAT_COMP_A) > 0)
+      internalFormat = GL_RGBA;
+   else
+      internalFormat = GL_RGB;
+
+   texObj = _mesa_select_tex_object(ctx, texUnit, target);
+   _mesa_lock_texture(ctx, texObj);
+
+   stObj = st_texture_object(texObj);
+   /* switch to surface based */
+   if (!stObj->surface_based) {
+      _mesa_clear_texture_object(ctx, texObj);
+      stObj->surface_based = GL_TRUE;
+   }
+
+   texImage = _mesa_get_tex_image(ctx, texObj, target, level);
+   stImage = st_texture_image(texImage);
+
+   _mesa_init_teximage_fields(ctx, target, texImage,
+                              ps->width, ps->height, 1, 0, internalFormat);
+   texImage->TexFormat = st_ChooseTextureFormat(ctx, internalFormat,
+                                                GL_RGBA, GL_UNSIGNED_BYTE);
+   _mesa_set_fetch_functions(texImage, 2);
+   pipe_texture_reference(&stImage->pt, ps->texture);
+
+   _mesa_dirty_texobj(ctx, texObj, GL_TRUE);
+   _mesa_unlock_texture(ctx, texObj);
+   
+   return 1;
+}
+
+
+/**
+ * Unbind a pipe surface from a texture object.  After the call,
+ * the texture object is marked dirty and will be (re-)validated.
+ *
+ * \param ps      pipe surface to be unbound
+ * \param target  texture target
+ * \param level   image level
+ */
+int
+st_unbind_texture_surface(struct pipe_surface *ps, int target, int level)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   const GLuint unit = ctx->Texture.CurrentUnit;
+   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+   struct gl_texture_object *texObj;
+   struct gl_texture_image *texImage;
+   struct st_texture_object *stObj;
+   struct st_texture_image *stImage;
 
    switch (target) {
    case ST_TEXTURE_2D:
@@ -385,21 +456,28 @@ st_set_teximage(struct pipe_texture *pt, int target)
    }
 
    texObj = _mesa_select_tex_object(ctx, texUnit, target);
-   texImage = _mesa_get_tex_image(ctx, texObj, target, 0);
+
+   _mesa_lock_texture(ctx, texObj);
+
+   texImage = _mesa_get_tex_image(ctx, texObj, target, level);
+   stObj = st_texture_object(texObj);
    stImage = st_texture_image(texImage);
-   
-   _mesa_init_teximage_fields(ctx, GL_TEXTURE_2D, texImage, pt->width[0],
-                              pt->height[0], 1, 0, internalFormat);
 
-   texImage->TexFormat = st_ChooseTextureFormat(ctx, internalFormat, GL_RGBA,
-                                                GL_UNSIGNED_BYTE);
-   _mesa_set_fetch_functions(texImage, 2);
+   /* Make sure the pipe surface is still bound.  The texture object is still
+    * considered surface based even if this is the last bound surface. */
+   if (stImage->pt == ps->texture) {
+      pipe_texture_reference(&stImage->pt, NULL);
+      _mesa_clear_texture_image(ctx, texImage);
 
-   pipe_texture_reference(&stImage->pt, pt);
+      _mesa_dirty_texobj(ctx, texObj, GL_TRUE);
+   }
 
+   _mesa_unlock_texture(ctx, texObj);
+   
    return 1;
 }
 
+
 /** Redirect rendering into stfb's surface to a texture image */
 int
 st_bind_teximage(struct st_framebuffer *stfb, uint surfIndex,
diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h
index b9d447c..60868ce 100644
--- a/src/mesa/state_tracker/st_texture.h
+++ b/src/mesa/state_tracker/st_texture.h
@@ -69,6 +69,11 @@ struct st_texture_object
    struct pipe_texture *pt;
 
    GLboolean teximage_realloc;
+
+   /* True if there is/was a surface bound to this texture object.  It helps
+    * track whether the texture object is surface based or not.
+    */
+   GLboolean surface_based;
 };
 
 
-- 
1.6.2.4

>From 0704e6cf5d30ca5ff47013faff1673bf57137cb4 Mon Sep 17 00:00:00 2001
From: Chia-I Wu <olva...@gmail.com>
Date: Wed, 5 Aug 2009 11:48:38 +0800
Subject: [PATCH 3/5] egl_softpipe: Flush when switching current context.


Signed-off-by: Chia-I Wu <olva...@gmail.com>
---
 src/gallium/winsys/egl_xlib/egl_xlib.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/src/gallium/winsys/egl_xlib/egl_xlib.c b/src/gallium/winsys/egl_xlib/egl_xlib.c
index 2acfbf8..1ea4b72 100644
--- a/src/gallium/winsys/egl_xlib/egl_xlib.c
+++ b/src/gallium/winsys/egl_xlib/egl_xlib.c
@@ -425,10 +425,14 @@ xlib_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy,
    struct xlib_egl_context *context = lookup_context(ctx);
    struct xlib_egl_surface *draw_surf = lookup_surface(draw);
    struct xlib_egl_surface *read_surf = lookup_surface(read);
+   struct st_context *oldctx = st_get_current();
 
    if (!_eglMakeCurrent(drv, dpy, draw, read, context))
       return EGL_FALSE;
 
+   /* Flush before switching context.  Check client API? */
+   if (oldctx)
+      st_flush(oldctx, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
    st_make_current((context ? context->Context : NULL),
                    (draw_surf ? draw_surf->Framebuffer : NULL),
                    (read_surf ? read_surf->Framebuffer : NULL));
-- 
1.6.2.4

>From b2b2222844a184a003b1933ce3f84212a44b270f Mon Sep 17 00:00:00 2001
From: Chia-I Wu <olva...@gmail.com>
Date: Wed, 5 Aug 2009 11:47:08 +0800
Subject: [PATCH 4/5] egl_softpipe: Add support for pbuffer binding.

This adds support for eglBindTexImage and eglReleaseTexImage.  They rely
on the state tracker to do the real work.

Signed-off-by: Chia-I Wu <olva...@gmail.com>
---
 src/gallium/winsys/egl_xlib/egl_xlib.c |   84 ++++++++++++++++++++++++++++++++
 1 files changed, 84 insertions(+), 0 deletions(-)

diff --git a/src/gallium/winsys/egl_xlib/egl_xlib.c b/src/gallium/winsys/egl_xlib/egl_xlib.c
index 1ea4b72..f409a3f 100644
--- a/src/gallium/winsys/egl_xlib/egl_xlib.c
+++ b/src/gallium/winsys/egl_xlib/egl_xlib.c
@@ -182,6 +182,8 @@ create_configs(_EGLDriver *drv, EGLDisplay dpy)
       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 | EGL_PBUFFER_BIT);
+      SET_CONFIG_ATTRIB(config, EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE);
+      SET_CONFIG_ATTRIB(config, EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE);
 
       _eglAddConfig(disp, config);
    }
@@ -640,6 +642,86 @@ xlib_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
 
 
 static EGLBoolean
+xlib_eglBindTexImage(_EGLDriver *drv, EGLDisplay dpy,
+                     EGLSurface surface, EGLint buffer)
+{
+   struct xlib_egl_surface *xsurf = lookup_surface(surface);
+   struct xlib_egl_context *xctx;
+   struct pipe_surface *psurf;
+   enum pipe_format format;
+   int target;
+
+   if (!xsurf || xsurf->Base.Type != EGL_PBUFFER_BIT)
+      return _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
+   if (buffer != EGL_BACK_BUFFER)
+      return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
+   if (xsurf->Base.BoundToTexture)
+      return _eglError(EGL_BAD_ACCESS, "eglBindTexImage");
+
+   /* this should be updated when choose_color_format is */
+   switch (xsurf->Base.TextureFormat) {
+   case EGL_TEXTURE_RGB:
+      format = PIPE_FORMAT_R8G8B8_UNORM;
+      break;
+   case EGL_TEXTURE_RGBA:
+      format = PIPE_FORMAT_A8R8G8B8_UNORM;
+      break;
+   default:
+      return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
+   }
+
+   switch (xsurf->Base.TextureTarget) {
+   case EGL_TEXTURE_2D:
+      target = ST_TEXTURE_2D;
+      break;
+   default:
+      return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
+   }
+
+   /* flush properly */
+   if (eglGetCurrentSurface(EGL_DRAW) == surface) {
+      xctx = lookup_context(eglGetCurrentContext());
+      st_flush(xctx->Context, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME,
+               NULL);
+   }
+   else if (_eglIsSurfaceBound(&xsurf->Base)) {
+      xctx = lookup_context(_eglGetContextHandle(xsurf->Base.Binding));
+      if (xctx)
+         st_finish(xctx->Context);
+   }
+
+   st_get_framebuffer_surface(xsurf->Framebuffer, ST_SURFACE_BACK_LEFT,
+                              &psurf);
+   st_bind_texture_surface(psurf, target, xsurf->Base.MipmapLevel, format);
+   xsurf->Base.BoundToTexture = EGL_TRUE;
+
+   return EGL_TRUE;
+}
+
+
+static EGLBoolean
+xlib_eglReleaseTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface,
+                        EGLint buffer)
+{
+   struct xlib_egl_surface *xsurf = lookup_surface(surface);
+   struct pipe_surface *psurf;
+
+   if (!xsurf || xsurf->Base.Type != EGL_PBUFFER_BIT ||
+       !xsurf->Base.BoundToTexture)
+      return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
+   if (buffer != EGL_BACK_BUFFER)
+      return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
+
+   st_get_framebuffer_surface(xsurf->Framebuffer, ST_SURFACE_BACK_LEFT,
+                              &psurf);
+   st_unbind_texture_surface(psurf, ST_TEXTURE_2D, xsurf->Base.MipmapLevel);
+   xsurf->Base.BoundToTexture = EGL_FALSE;
+
+   return EGL_TRUE;
+}
+
+
+static EGLBoolean
 xlib_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw)
 {
    /* error checking step: */
@@ -725,6 +807,8 @@ _eglMain(_EGLDisplay *dpy, const char *args)
    xdrv->Base.API.CreateWindowSurface = xlib_eglCreateWindowSurface;
    xdrv->Base.API.CreatePbufferSurface = xlib_eglCreatePbufferSurface;
    xdrv->Base.API.DestroySurface = xlib_eglDestroySurface;
+   xdrv->Base.API.BindTexImage = xlib_eglBindTexImage;
+   xdrv->Base.API.ReleaseTexImage = xlib_eglReleaseTexImage;
    xdrv->Base.API.MakeCurrent = xlib_eglMakeCurrent;
    xdrv->Base.API.SwapBuffers = xlib_eglSwapBuffers;
 
-- 
1.6.2.4

>From 7002a6be1f919b3d22f7e50776ac96006f9da978 Mon Sep 17 00:00:00 2001
From: Chia-I Wu <olva...@gmail.com>
Date: Wed, 5 Aug 2009 16:00:45 +0800
Subject: [PATCH 5/5] progs/egl: Add xeglbindtex.

This is a simple demo for eglBindTexImage.  It uses a OpenGL context,
instead of the required OpenGL ES one.  But it still suffices the demo
and test purpose.

Signed-off-by: Chia-I Wu <olva...@gmail.com>
---
 progs/egl/Makefile      |    7 +
 progs/egl/xeglbindtex.c |  474 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 481 insertions(+), 0 deletions(-)
 create mode 100644 progs/egl/xeglbindtex.c

diff --git a/progs/egl/Makefile b/progs/egl/Makefile
index d3c32d4..fd72f54 100644
--- a/progs/egl/Makefile
+++ b/progs/egl/Makefile
@@ -17,6 +17,7 @@ PROGRAMS = \
 	eglgears \
 	eglscreen \
 	peglgears \
+	xeglbindtex \
 	xeglgears \
 	xeglthreads \
 	xegl_tri
@@ -84,6 +85,12 @@ peglgears.o: peglgears.c $(HEADERS)
 	$(CC) -c $(CFLAGS) -I$(TOP)/include peglgears.c
 
 
+xeglbindtex: xeglbindtex.o $(TOP)/$(LIB_DIR)/libEGL.so
+	$(CC) $(CFLAGS) xeglbindtex.o -L$(TOP)/$(LIB_DIR) -lEGL -lGL $(LIBDRM_LIB) $(APP_LIB_DEPS) -o $@
+
+xeglbindtex.o: xeglbindtex.c $(HEADERS)
+	$(CC) -c $(CFLAGS) -I$(TOP)/include xeglbindtex.c
+
 xeglgears: xeglgears.o $(TOP)/$(LIB_DIR)/libEGL.so
 	$(CC) $(CFLAGS) xeglgears.o -L$(TOP)/$(LIB_DIR) -lEGL -lGL $(LIBDRM_LIB) $(APP_LIB_DEPS) -o $@
 
diff --git a/progs/egl/xeglbindtex.c b/progs/egl/xeglbindtex.c
new file mode 100644
index 0000000..fdd9fe2
--- /dev/null
+++ b/progs/egl/xeglbindtex.c
@@ -0,0 +1,474 @@
+/*
+ * Simple demo for eglBindTexImage.  Based on xegl_tri.c by
+ *
+ * Copyright (C) 2008  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The spec says that eglBindTexImage supports only OpenGL ES context, but this
+ * demo uses OpenGL context.  Keep in mind that this is non-standard.
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+#include <GL/gl.h>
+#include <EGL/egl.h>
+
+static EGLDisplay dpy;
+static EGLContext ctx_win, ctx_pbuf;
+static EGLSurface surf_win, surf_pbuf;
+static GLuint tex_pbuf;
+
+static GLfloat view_rotx = 0.0, view_roty = 0.0, view_rotz = 0.0;
+static GLboolean blend = GL_TRUE;
+static GLuint color_flow;
+
+static void
+make_pbuffer(int width, int height)
+{
+   static const EGLint config_attribs[] = {
+      EGL_RED_SIZE, 8,
+      EGL_GREEN_SIZE, 8,
+      EGL_BLUE_SIZE, 8,
+      EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE,
+      EGL_NONE
+   };
+   EGLint pbuf_attribs[] = {
+      EGL_WIDTH, width,
+      EGL_HEIGHT, height,
+      EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB,
+      EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
+      EGL_NONE
+   };
+   EGLConfig config;
+   EGLint num_configs;
+
+   if (!eglChooseConfig(dpy, config_attribs, &config, 1, &num_configs)) {
+      printf("Error: couldn't get an EGL visual config for pbuffer\n");
+      exit(1);
+   }
+
+   eglBindAPI(EGL_OPENGL_API);
+   ctx_pbuf = eglCreateContext(dpy, config, EGL_NO_CONTEXT, NULL );
+   surf_pbuf = eglCreatePbufferSurface(dpy, config, pbuf_attribs);
+   if (surf_pbuf == EGL_NO_SURFACE) {
+      printf("failed to allocate pbuffer\n");
+      exit(1);
+   }
+
+   glGenTextures(1, &tex_pbuf);
+}
+
+static void
+use_pbuffer(void)
+{
+   static int initialized;
+
+   eglMakeCurrent(dpy, surf_pbuf, surf_pbuf, ctx_pbuf);
+   if (!initialized) {
+      EGLint width, height;
+      GLfloat ar;
+
+      initialized = 1;
+
+      eglQuerySurface(dpy, surf_pbuf, EGL_WIDTH, &width);
+      eglQuerySurface(dpy, surf_pbuf, EGL_WIDTH, &height);
+      ar = (GLfloat) width / (GLfloat) height;
+
+      glViewport(0, 0, (GLint) width, (GLint) height);
+
+      glMatrixMode(GL_PROJECTION);
+      glLoadIdentity();
+      glFrustum(-ar, ar, -1, 1, 1.0, 10.0);
+
+      glMatrixMode(GL_MODELVIEW);
+      glLoadIdentity();
+
+      /* y-inverted */
+      glScalef(1.0, -1.0, 1.0);
+
+      glTranslatef(0.0, 0.0, -5.0);
+
+      glClearColor(0.2, 0.2, 0.2, 0.0);
+   }
+}
+
+static void
+make_window(Display *x_dpy, const char *name,
+            int x, int y, int width, int height,
+            Window *winRet)
+{
+   static const EGLint attribs[] = {
+      EGL_RED_SIZE, 8,
+      EGL_GREEN_SIZE, 8,
+      EGL_BLUE_SIZE, 8,
+      EGL_ALPHA_SIZE, 8,
+      EGL_DEPTH_SIZE, 8,
+      EGL_NONE
+   };
+
+   int scrnum;
+   XSetWindowAttributes attr;
+   unsigned long mask;
+   Window root;
+   Window win;
+   XVisualInfo *visInfo, visTemplate;
+   int num_visuals;
+   EGLConfig config;
+   EGLint num_configs, vid;
+
+   scrnum = DefaultScreen( x_dpy );
+   root = RootWindow( x_dpy, scrnum );
+
+   if (!eglChooseConfig(dpy, attribs, &config, 1, &num_configs)) {
+      printf("Error: couldn't get an EGL visual config\n");
+      exit(1);
+   }
+
+   if (!eglGetConfigAttrib(dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
+      printf("Error: eglGetConfigAttrib() failed\n");
+      exit(1);
+   }
+
+   /* The X window visual must match the EGL config */
+   visTemplate.visualid = vid;
+   visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
+   if (!visInfo) {
+      printf("Error: couldn't get X visual\n");
+      exit(1);
+   }
+
+   /* window attributes */
+   attr.background_pixel = 0;
+   attr.border_pixel = 0;
+   attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone);
+   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+   attr.override_redirect = 0;
+   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect;
+
+   win = XCreateWindow( x_dpy, root, 0, 0, width, height,
+		        0, visInfo->depth, InputOutput,
+		        visInfo->visual, mask, &attr );
+
+   /* set hints and properties */
+   {
+      XSizeHints sizehints;
+      sizehints.x = x;
+      sizehints.y = y;
+      sizehints.width  = width;
+      sizehints.height = height;
+      sizehints.flags = USSize | USPosition;
+      XSetNormalHints(x_dpy, win, &sizehints);
+      XSetStandardProperties(x_dpy, win, name, name,
+                              None, (char **)NULL, 0, &sizehints);
+   }
+
+   eglBindAPI(EGL_OPENGL_API);
+   ctx_win = eglCreateContext(dpy, config, EGL_NO_CONTEXT, NULL );
+   if (!ctx_win) {
+      printf("Error: glXCreateContext failed\n");
+      exit(1);
+   }
+
+   surf_win = eglCreateWindowSurface(dpy, config, win, NULL);
+
+   XFree(visInfo);
+
+   *winRet = win;
+}
+
+static void
+use_window(void)
+{
+   static int initialized;
+
+   eglMakeCurrent(dpy, surf_win, surf_win, ctx_win);
+   if (!initialized) {
+      initialized = 1;
+      glEnable(GL_TEXTURE_2D);
+      glBindTexture(GL_TEXTURE_2D, tex_pbuf);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+   }
+}
+
+static void
+draw_triangle(void)
+{
+   static const GLfloat verts[3][2] = {
+      { -3, -3 },
+      {  3, -3 },
+      {  0,  3 }
+   };
+   GLfloat colors[3][3] = {
+      { 1, 0, 0 },
+      { 0, 1, 0 },
+      { 0, 0, 1 }
+   };
+   GLint i;
+
+   /* flow the color */
+   for (i = 0; i < 3; i++) {
+      GLint first = (i + color_flow / 256) % 3;
+      GLint second = (first + 1) % 3;
+      GLint third = (second + 1) % 3;
+      GLfloat c = (color_flow % 256) / 256.0f;
+
+      c = c * c * c;
+      colors[i][first] = 1.0f - c;
+      colors[i][second] = c;
+      colors[i][third] = 0.0f;
+   }
+
+   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+   glVertexPointer(2, GL_FLOAT, 0, verts);
+   glColorPointer(3, GL_FLOAT, 0, colors);
+   glEnableClientState(GL_VERTEX_ARRAY);
+   glEnableClientState(GL_COLOR_ARRAY);
+
+   glDrawArrays(GL_TRIANGLES, 0, 3);
+
+   glDisableClientState(GL_VERTEX_ARRAY);
+   glDisableClientState(GL_COLOR_ARRAY);
+}
+
+static void
+draw_textured_cube(void)
+{
+   static const GLfloat verts[][2] = {
+      { -4, -4 },
+      {  4, -4 },
+      {  4,  4 },
+      { -4,  4 }
+   };
+   static const GLfloat colors[][4] = {
+      { 1, 1, 1, 0.5 },
+      { 1, 1, 1, 0.5 },
+      { 1, 1, 1, 0.5 },
+      { 1, 1, 1, 0.5 }
+   };
+   static const GLfloat texs[][2] = {
+      { 0, 0 },
+      { 1, 0 },
+      { 1, 1 },
+      { 0, 1 }
+   };
+   static const GLfloat xforms[6][4] = {
+      {   0, 0, 1, 0 },
+      {  90, 0, 1, 0 },
+      { 180, 0, 1, 0 },
+      { 270, 0, 1, 0 },
+      {  90, 1, 0, 0 },
+      { -90, 1, 0, 0 }
+   };
+   GLint i;
+
+   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+   if (blend) {
+      glDisable(GL_DEPTH_TEST);
+      glEnable(GL_BLEND);
+   } else {
+      glEnable(GL_DEPTH_TEST);
+      glDisable(GL_BLEND);
+   }
+
+   glVertexPointer(2, GL_FLOAT, 0, verts);
+   glColorPointer(4, GL_FLOAT, 0, colors);
+   glTexCoordPointer(2, GL_FLOAT, 0, texs);
+
+   glEnableClientState(GL_VERTEX_ARRAY);
+   glEnableClientState(GL_COLOR_ARRAY);
+   glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+   for (i = 0; i < 6; i++) {
+      glPushMatrix();
+      glRotatef(xforms[i][0], xforms[i][1], xforms[i][2], xforms[i][3]);
+      glTranslatef(0, 0, 4.1);
+      glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+      glPopMatrix();
+   }
+
+   glDisableClientState(GL_VERTEX_ARRAY);
+   glDisableClientState(GL_COLOR_ARRAY);
+   glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+}
+
+static void
+draw(void)
+{
+   use_pbuffer();
+   draw_triangle();
+
+   use_window();
+
+   eglBindTexImage(dpy, surf_pbuf, EGL_BACK_BUFFER);
+
+   glPushMatrix();
+   glRotatef(view_rotx, 1, 0, 0);
+   glRotatef(view_roty, 0, 1, 0);
+   glRotatef(view_rotz, 0, 0, 1);
+
+   draw_textured_cube();
+
+   glPopMatrix();
+
+   eglReleaseTexImage(dpy, surf_pbuf, EGL_BACK_BUFFER);
+}
+
+/* new window size or exposure */
+static void
+reshape(int width, int height)
+{
+   GLfloat ar = (GLfloat) width / (GLfloat) height;
+
+   use_window();
+
+   glViewport(0, 0, (GLint) width, (GLint) height);
+
+   glMatrixMode(GL_PROJECTION);
+   glLoadIdentity();
+   glFrustum(-ar, ar, -1, 1, 5.0, 60.0);
+
+   glMatrixMode(GL_MODELVIEW);
+   glLoadIdentity();
+   glTranslatef(0.0, 0.0, -40.0);
+}
+
+static void
+event_loop(Display *x_dpy, Window win)
+{
+   while (1) {
+      int redraw = 1;
+
+      if (XPending(x_dpy) > 0) {
+         XEvent event;
+         XNextEvent(x_dpy, &event);
+
+         switch (event.type) {
+         case Expose:
+            redraw = 1;
+            break;
+         case ConfigureNotify:
+            reshape(event.xconfigure.width, event.xconfigure.height);
+            break;
+         case KeyPress:
+            {
+               char buffer[10];
+               int r, code;
+               code = XLookupKeysym(&event.xkey, 0);
+               if (code == XK_Left) {
+                  view_roty += 5.0;
+               }
+               else if (code == XK_Right) {
+                  view_roty -= 5.0;
+               }
+               else if (code == XK_Up) {
+                  view_rotx += 5.0;
+               }
+               else if (code == XK_Down) {
+                  view_rotx -= 5.0;
+               }
+               else if (code == XK_b) {
+                  blend = !blend;
+               }
+               else {
+                  r = XLookupString(&event.xkey, buffer, sizeof(buffer),
+                        NULL, NULL);
+                  if (buffer[0] == 27) {
+                     /* escape */
+                     return;
+                  }
+               }
+            }
+            redraw = 1;
+            break;
+         default:
+            ; /*no-op*/
+         }
+      }
+
+      if (redraw) {
+         view_rotx += 1.0;
+         view_roty += 2.0;
+         view_rotz += 1.5;
+         color_flow += 20;
+         draw();
+         eglSwapBuffers(dpy, surf_win);
+      }
+   }
+}
+
+int
+main(int argc, char *argv[])
+{
+   const int winWidth = 300, winHeight = 300;
+   Display *x_dpy;
+   Window win;
+   char *dpyName = NULL;
+   EGLint egl_major, egl_minor;
+   const char *s;
+
+   x_dpy = XOpenDisplay(dpyName);
+   if (!x_dpy) {
+      printf("Error: couldn't open display %s\n",
+	     dpyName ? dpyName : getenv("DISPLAY"));
+      return -1;
+   }
+
+   dpy = eglGetDisplay(x_dpy);
+   if (!dpy) {
+      printf("Error: eglGetDisplay() failed\n");
+      return -1;
+   }
+
+   if (!eglInitialize(dpy, &egl_major, &egl_minor)) {
+      printf("Error: eglInitialize() failed\n");
+      return -1;
+   }
+
+   s = eglQueryString(dpy, EGL_VERSION);
+   printf("EGL_VERSION = %s\n", s);
+
+   make_window(x_dpy, "color flow", 0, 0, winWidth, winHeight, &win);
+   make_pbuffer(winWidth, winHeight);
+
+   XMapWindow(x_dpy, win);
+
+   reshape(winWidth, winHeight);
+   event_loop(x_dpy, win);
+
+   glDeleteTextures(1, &tex_pbuf);
+
+   eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+   eglTerminate(dpy);
+
+   XDestroyWindow(x_dpy, win);
+   XCloseDisplay(x_dpy);
+
+   return 0;
+}
-- 
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
Mesa3d-dev@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mesa3d-dev

Reply via email to