Demos (master): demos/egl: add two applications which validate creating Texture from

Cooper Yuan cooperyuan at kemper.freedesktop.org
Wed Aug 24 23:21:13 PDT 2011


Module: Demos
Branch: master
Commit: b9b181fbd736c604fdb923d4570f007f89cde935
URL:    http://cgit.freedesktop.org/mesa/demos/commit/?id=b9b181fbd736c604fdb923d4570f007f89cde935

Author: Cooper Yuan <cooperyuan at gmail.com>
Date:   Thu Aug 25 14:18:46 2011 +0800

demos/egl: add two applications which validate creating Texture from
VGImage and creating VGImage from Texture through EGLImage

---

 configure.ac                 |    1 +
 src/egl/Makefile.am          |    3 +-
 src/egl/oes_vg/Makefile.am   |   48 +++++
 src/egl/oes_vg/tex2vgimage.c |  428 ++++++++++++++++++++++++++++++++++++++++++
 src/egl/oes_vg/vgimage2tex.c |  425 +++++++++++++++++++++++++++++++++++++++++
 5 files changed, 904 insertions(+), 1 deletions(-)

diff --git a/configure.ac b/configure.ac
index e17fbcf..b5b2fcf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -240,6 +240,7 @@ AC_OUTPUT([
 	src/egl/opengles2/Makefile
 	src/egl/openvg/Makefile
 	src/egl/openvg/trivial/Makefile
+	src/egl/oes_vg/Makefile
 	src/fp/Makefile
 	src/fpglsl/Makefile
 	src/glsl/Makefile
diff --git a/src/egl/Makefile.am b/src/egl/Makefile.am
index 1526817..d64a49e 100644
--- a/src/egl/Makefile.am
+++ b/src/egl/Makefile.am
@@ -27,4 +27,5 @@ SUBDIRS = \
 	opengl \
 	openvg \
 	opengles1 \
-	opengles2
+	opengles2 \
+	oes_vg
diff --git a/src/egl/oes_vg/Makefile.am b/src/egl/oes_vg/Makefile.am
new file mode 100644
index 0000000..73038eb
--- /dev/null
+++ b/src/egl/oes_vg/Makefile.am
@@ -0,0 +1,48 @@
+# Copyright © 2011 Cooper Yuan
+#
+# 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 (including the next
+# paragraph) 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
+# THE AUTHORS OR COPYRIGHT HOLDERS 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.
+#
+# Authors:
+#    Cooper Yuan <cooperyuan at gmail.com>
+
+AM_CFLAGS = \
+	$(GLESV1_CFLAGS) \
+	$(EGL_CFLAGS) \
+	$(VG_CFLAGS) \
+	$(X11_CFLAGS)
+
+AM_LDFLAGS = \
+	$(GLESV1_LIBS) \
+	$(EGL_LIBS) \
+	$(VG_LIBS) \
+	-lm
+
+if HAVE_EGL
+if HAVE_X11
+if HAVE_VG
+bin_PROGRAMS = \
+	vgimage2tex \
+	tex2vgimage
+endif
+endif
+endif
+
+vgimage2tex_LDADD = $(X11_LIBS)
+tex2vgimage_LDADD = $(X11_LIBS)
diff --git a/src/egl/oes_vg/tex2vgimage.c b/src/egl/oes_vg/tex2vgimage.c
new file mode 100644
index 0000000..6070ea6
--- /dev/null
+++ b/src/egl/oes_vg/tex2vgimage.c
@@ -0,0 +1,428 @@
+/*
+ * KHR_gl_texture_2D_image extension test
+ *
+ * This test aims to validate KHR_gl_texture_2D_image extension which provide
+ * a mechanism for creating EGLImage objects from OpenGL ES API resources,
+ *
+ * such as two- and three- dimensional textures, cube maps and render buffers.
+ *
+ * Texture->EGLImage->VGImage
+ *
+ * Cooper Yuan <cooperyuan at gmail.com>
+ * 20 Aug 2011
+ */
+#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 <VG/openvg.h>
+#include <GL/glu.h>
+#include <EGL/egl.h>
+
+#include <EGL/eglext.h>
+#include <VG/vgext.h>
+
+#define WINDOW_WIDTH   300
+#define WINDOW_HEIGHT  300
+#define TEXTURE_WIDTH  128
+#define TEXTURE_HEIGHT 128
+
+static PFNEGLCREATEIMAGEKHRPROC    eglCreateImageKHR                    = NULL;
+static PFNEGLDESTROYIMAGEKHRPROC   eglDestroyImageKHR                   = NULL;
+static PFNVGCREATEEGLIMAGETARGETKHRPROC vgCreateEGLImageTargetKHR_func  = NULL;
+
+typedef struct _egl_manager_t
+{
+    EGLNativeDisplayType xdpy;
+    EGLNativeWindowType  xwin;
+
+    EGLDisplay  dpy;
+    EGLConfig   conf;
+
+    // Rendering contexts
+    EGLContext  vg_ctx;
+    EGLContext  es_ctx;
+
+    // Surfaces
+    EGLSurface  win_surface;
+    EGLSurface  pbuf_surface;
+
+    VGImage     vg_image;
+    EGLImageKHR egl_image;
+    GLuint      texture;
+
+    EGLint      major_ver, minor_ver;
+}EGLmanager;
+
+
+static EGLBoolean check_ext(EGLmanager *eglman)
+{
+    const char* egl_ext_str = NULL;
+    egl_ext_str = eglQueryString(eglman->dpy, EGL_EXTENSIONS);
+
+    // check extension KHR_vg_parent_image
+    if (eglCreateImageKHR == NULL)
+    {
+        if (!strstr(egl_ext_str, "EGL_KHR_image"))
+        {
+            return EGL_FALSE;
+        }
+        else
+        {
+            eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR");
+            eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC)eglGetProcAddress("eglDestroyImageKHR");
+            if ((!eglCreateImageKHR) || (!eglDestroyImageKHR))
+            {
+                return EGL_FALSE;
+            }
+        }
+    }
+
+    // check extension VG_KHR_EGL_image
+    if (vgCreateEGLImageTargetKHR_func == NULL)
+    {
+        if (!strstr(egl_ext_str, "VG_KHR_EGL_image") )
+        {
+            return EGL_FALSE;
+        }
+        else
+        {
+            vgCreateEGLImageTargetKHR_func = (PFNVGCREATEEGLIMAGETARGETKHRPROC)eglGetProcAddress("vgCreateEGLImageTargetKHR");
+            if (!vgCreateEGLImageTargetKHR_func)
+            {
+                return EGL_FALSE;
+            }
+        }
+    }
+
+    return EGL_TRUE;
+}
+
+static EGLBoolean create_x_window(EGLmanager *eglman, const char *name)
+{
+    EGLint scrnum, num_conf, num_visuals;
+    Window root;
+    EGLint vid;
+    XVisualInfo *visInfo, visTemplate;
+    XSetWindowAttributes attr;
+    unsigned long mask;
+
+    EGLint config_attrib[] =
+    {
+        EGL_RED_SIZE,			1,
+        EGL_GREEN_SIZE, 		1,
+        EGL_BLUE_SIZE,			1,
+        EGL_DEPTH_SIZE,         1,
+        EGL_SURFACE_TYPE,       EGL_WINDOW_BIT|EGL_PBUFFER_BIT,
+        EGL_RENDERABLE_TYPE,	EGL_OPENVG_BIT | EGL_OPENGL_BIT,
+        EGL_NONE
+    };
+
+    scrnum = DefaultScreen(eglman->xdpy);
+    root = RootWindow(eglman->xdpy, scrnum);
+
+    if (!eglChooseConfig(eglman->dpy, config_attrib, &eglman->conf, 1, &num_conf) ||
+        num_conf == 0 ||
+        eglGetError() != EGL_SUCCESS)
+    {
+        printf("Error: couldn't get an EGL visual config\n");
+        return EGL_FALSE;
+    }
+
+    if (!eglGetConfigAttrib(eglman->dpy, eglman->conf, EGL_NATIVE_VISUAL_ID, &vid) ||
+        eglGetError() != EGL_SUCCESS)
+    {
+        printf("Error: eglGetConfigAttrib() failed\n");
+        return EGL_FALSE;
+    }
+
+    /* The X window visual must match the EGL config */
+    visTemplate.visualid = vid;
+    visInfo = XGetVisualInfo(eglman->xdpy, VisualIDMask, &visTemplate, &num_visuals);
+    if (!visInfo)
+    {
+        printf("Error: couldn't get X visual\n");
+        return EGL_FALSE;
+    }
+
+    /* window attributes */
+    attr.background_pixel = 0;
+    attr.border_pixel = 0;
+    attr.colormap = XCreateColormap(eglman->xdpy, root, visInfo->visual, AllocNone);
+    attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+    mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+    eglman->xwin = XCreateWindow(eglman->xdpy, root, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT,
+                                 0, visInfo->depth, InputOutput,
+                                 visInfo->visual, mask, &attr);
+
+    if (!eglman->xwin)
+    {
+        printf("Error: couldn't create X Window\n");
+        return EGL_FALSE;
+    }
+
+    /* set hints and properties */
+    {
+       XSizeHints sizehints;
+       sizehints.x = 0;
+       sizehints.y = 0;
+       sizehints.width  = WINDOW_WIDTH;
+       sizehints.height = WINDOW_HEIGHT;
+       sizehints.flags = USSize | USPosition;
+       XSetNormalHints(eglman->xdpy, eglman->xwin, &sizehints);
+       XSetStandardProperties(eglman->xdpy, eglman->xwin, name, name,
+                              None, (char **)NULL, 0, &sizehints);
+    }
+
+    XFree(visInfo);
+
+    return EGL_TRUE;
+}
+
+static EGLBoolean egl_init(EGLmanager *eglman)
+{
+    EGLint pbuffer_attrib[] =
+    {
+        EGL_WIDTH,  128,
+        EGL_HEIGHT, 128,
+        EGL_NONE
+    };
+
+    // Check extension support
+    if (check_ext(eglman) != EGL_TRUE)
+    {
+        return EGL_FALSE;
+    }
+
+    // Create GL context
+    eglBindAPI(EGL_OPENGL_ES_API);
+    eglman->es_ctx = eglCreateContext(eglman->dpy, eglman->conf, NULL, NULL);
+    if (eglman->es_ctx == EGL_NO_CONTEXT ||
+        eglGetError() != EGL_SUCCESS)
+    {
+        return EGL_FALSE;
+    }
+
+    // Create VG context
+    eglBindAPI(EGL_OPENVG_API);
+    eglman->vg_ctx = eglCreateContext(eglman->dpy, eglman->conf, NULL, NULL);
+    if (eglman->vg_ctx == EGL_NO_CONTEXT ||
+        eglGetError() != EGL_SUCCESS)
+    {
+        return EGL_FALSE;
+    }
+
+    // Create window surface
+    eglman->win_surface = eglCreateWindowSurface(eglman->dpy, eglman->conf, eglman->xwin, NULL);
+    if (eglman->win_surface == EGL_NO_SURFACE ||
+        eglGetError() != EGL_SUCCESS)
+    {
+        return EGL_FALSE;
+    }
+
+    // Create pbuffer surface
+    eglman->pbuf_surface = eglCreatePbufferSurface(eglman->dpy, eglman->conf, pbuffer_attrib);
+    if (eglman->pbuf_surface == EGL_NO_SURFACE ||
+        eglGetError() != EGL_SUCCESS)
+    {
+
+        return EGL_FALSE;
+    }
+
+    return EGL_TRUE;
+}
+
+static void egl_deinit(EGLmanager *eglman)
+{
+    eglBindAPI(EGL_OPENGL_ES_API);
+    eglMakeCurrent(eglman->dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+
+    eglBindAPI(EGL_OPENVG_API);
+    eglMakeCurrent(eglman->dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+
+    eglDestroySurface(eglman->dpy, eglman->win_surface);
+    eglDestroySurface(eglman->dpy, eglman->pbuf_surface);
+
+    eglDestroyContext(eglman->dpy, eglman->es_ctx);
+    eglDestroyContext(eglman->dpy, eglman->vg_ctx);
+}
+
+static EGLBoolean vg_es_init(EGLmanager *eglman)
+{
+    unsigned char* textureData = NULL;
+    int tsize = 0;
+
+    // Initialize GL
+    eglBindAPI(EGL_OPENGL_ES_API);
+    eglMakeCurrent(eglman->dpy, eglman->pbuf_surface, eglman->pbuf_surface, eglman->es_ctx);
+
+    // Create Texture Target from EGLImage
+    glGenTextures(1, &eglman->texture);
+    glBindTexture(GL_TEXTURE_2D, eglman->texture);
+    tsize = TEXTURE_WIDTH * TEXTURE_HEIGHT * 4;
+    textureData = (GLubyte*) malloc (tsize);
+    memset(textureData, 0, tsize);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData);
+
+    free (textureData);
+
+    // Create EGLImage from Texture
+    eglman->egl_image = (EGLImageKHR)eglCreateImageKHR(eglman->dpy, eglman->es_ctx, EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)eglman->texture, NULL);
+
+    // Initialize VG
+    eglBindAPI(EGL_OPENVG_API);
+    eglMakeCurrent(eglman->dpy, eglman->win_surface, eglman->win_surface, eglman->vg_ctx);
+
+    // Create VGImage from EGLImage
+    eglman->vg_image = vgCreateEGLImageTargetKHR_func((VGeglImageKHR)eglman->egl_image);
+
+    return EGL_TRUE;
+}
+
+static void vg_es_deinit(EGLmanager *eglman)
+{
+    // Destroy GL
+    eglDestroyImageKHR(eglman->dpy, eglman->egl_image);
+    eglBindAPI(EGL_OPENGL_ES_API);
+    eglMakeCurrent(eglman->dpy, eglman->pbuf_surface, eglman->pbuf_surface, eglman->es_ctx);
+    glDeleteTextures(1, &eglman->texture);
+    glBindTexture(GL_TEXTURE_2D, 0);
+
+    // Destroy VG
+    eglBindAPI(EGL_OPENVG_API);
+    eglMakeCurrent(eglman->dpy, eglman->win_surface, eglman->win_surface, eglman->vg_ctx);
+    vgDestroyImage(eglman->vg_image);
+}
+
+static void draw(EGLmanager *eglman)
+{
+    VGfloat black[]   = {0.f, 0.f, 0.f, 1.f};
+
+    // Render 3D scene by GL
+    eglBindAPI(EGL_OPENGL_ES_API);
+    eglMakeCurrent(eglman->dpy, eglman->pbuf_surface, eglman->pbuf_surface, eglman->es_ctx);
+
+    // Modify GL texture source
+    glClearColor(1.0, 0.0, 0.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, TEXTURE_WIDTH/2, TEXTURE_HEIGHT/2);
+    glClearColor(0.0, 1.0, 0.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, TEXTURE_WIDTH/2, 0, 0, 0, TEXTURE_WIDTH/2, TEXTURE_HEIGHT/2);
+    glClearColor(0.0, 0.0, 1.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, TEXTURE_HEIGHT/2, 0, 0, TEXTURE_WIDTH/2, TEXTURE_HEIGHT/2);
+    glClearColor(1.0, 1.0, 1.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, TEXTURE_WIDTH/2, TEXTURE_HEIGHT/2, 0, 0, TEXTURE_WIDTH/2, TEXTURE_HEIGHT/2);
+
+    // Make current to VG content
+    eglBindAPI(EGL_OPENVG_API);
+    eglMakeCurrent(eglman->dpy, eglman->win_surface, eglman->win_surface, eglman->vg_ctx);
+
+    // Draw VGImage target
+    vgSetfv(VG_CLEAR_COLOR, 4, black);
+    vgClear(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
+    vgSeti(VG_BLEND_MODE, VG_BLEND_SRC);
+    vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
+    vgLoadIdentity();
+    vgTranslate(WINDOW_WIDTH/2.0f, WINDOW_HEIGHT/2.0f);
+    vgScale((VGfloat)WINDOW_WIDTH/(VGfloat)TEXTURE_WIDTH * 0.8f, (VGfloat)WINDOW_HEIGHT/(VGfloat)TEXTURE_HEIGHT * 0.8f);
+    vgTranslate(-TEXTURE_WIDTH/2.0f, -TEXTURE_HEIGHT/2.0f);
+    vgDrawImage(eglman->vg_image);
+
+    // Swap buffer
+    eglSwapBuffers(eglman->dpy, eglman->win_surface);
+
+    return;
+}
+
+int main(int argc, char **argv)
+{
+    const char *s;
+
+    EGLmanager *eglman = calloc(1, sizeof(*eglman));
+
+    // Open X Display
+    Display *x_dpy = XOpenDisplay(NULL);
+    if (!x_dpy)
+    {
+        printf("error: can't open default display\n");
+        goto exit0;
+    }
+    eglman->xdpy = (EGLNativeDisplayType)x_dpy;
+
+    // Get EGL Display
+    eglman->dpy = eglGetDisplay(eglman->xdpy);
+    if (!eglman->dpy || eglGetError() != EGL_SUCCESS)
+    {
+        printf("error: can't get EGL display\n");
+        goto exit1;
+    }
+
+    // Initialize EGL
+    eglInitialize(eglman->dpy, &eglman->major_ver, &eglman->minor_ver);
+    if (eglGetError() != EGL_SUCCESS)
+    {
+        goto exit1;
+    }
+
+    // Query and print out information
+    s = eglQueryString(eglman->dpy, EGL_VERSION);
+    printf("EGL_VERSION = %s\n", s);
+
+    s = eglQueryString(eglman->dpy, EGL_VENDOR);
+    printf("EGL_VENDOR = %s\n", s);
+
+    s = eglQueryString(eglman->dpy, EGL_EXTENSIONS);
+    printf("EGL_EXTENSIONS = %s\n", s);
+
+    s = eglQueryString(eglman->dpy, EGL_CLIENT_APIS);
+    printf("EGL_CLIENT_APIS = %s\n", s);
+
+    // Create an RGB, double-buffered X window
+    if (create_x_window(eglman, "vgimage to texture") != EGL_TRUE)
+    {
+        goto exit2;
+    }
+
+    XMapWindow(eglman->xdpy, eglman->xwin);
+
+    // Initialize EGL
+    if (egl_init(eglman) != EGL_TRUE)
+    {
+        goto exit3;
+    }
+
+    // Initialize rendering API: OpenGL ES and OpenVG
+    if (vg_es_init(eglman) != EGL_TRUE)
+    {
+        goto exit3;
+    }
+
+    // Rendering
+    draw(eglman);
+
+    // Deinitialize rendering API
+    vg_es_deinit(eglman);
+
+    // Deinitialize EGL
+    egl_deinit(eglman);
+
+exit3:
+    XDestroyWindow(eglman->xdpy, eglman->xwin);
+exit2:
+    eglTerminate(eglman->dpy);
+exit1:
+    XCloseDisplay(eglman->xdpy);
+exit0:
+    free(eglman);
+
+    return 0;
+}
+
diff --git a/src/egl/oes_vg/vgimage2tex.c b/src/egl/oes_vg/vgimage2tex.c
new file mode 100644
index 0000000..70ed301
--- /dev/null
+++ b/src/egl/oes_vg/vgimage2tex.c
@@ -0,0 +1,425 @@
+/*
+ * KHR_vg_parent_image extension test
+ *
+ * This test aims to validate KHR_vg_parent_image extension which provides
+ * a mechanism for creating EGLImage objects from OpenVG VGImage resources,
+ * and then bind EGLImage with texture which will be used by OpenGL API.
+ *
+ * VGImage->EGLImage->Texture
+ *
+ * Cooper Yuan <cooperyuan at gmail.com>
+ * 20 Aug 2011
+ */
+
+#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 <VG/openvg.h>
+#include <GL/glu.h>
+#include <EGL/egl.h>
+
+#include <EGL/eglext.h>
+
+#define WINDOW_WIDTH   300
+#define WINDOW_HEIGHT  300
+
+static PFNEGLCREATEIMAGEKHRPROC    eglCreateImageKHR                    = NULL;
+static PFNEGLDESTROYIMAGEKHRPROC   eglDestroyImageKHR                   = NULL;
+static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES = NULL;
+
+typedef struct _egl_manager_t
+{
+    EGLNativeDisplayType xdpy;
+    EGLNativeWindowType  xwin;
+
+    EGLDisplay  dpy;
+    EGLConfig   conf;
+
+    // Rendering contexts
+    EGLContext  vg_ctx;
+    EGLContext  es_ctx;
+
+    // Surfaces
+    EGLSurface  win_surface;
+    EGLSurface  pbuf_surface;
+
+    VGImage     vg_image;
+    EGLImageKHR egl_image;
+    GLuint      texture;
+
+    EGLint      major_ver, minor_ver;
+}EGLmanager;
+
+
+static EGLBoolean check_ext(EGLmanager *eglman)
+{
+    const char* egl_ext_str = NULL;
+    egl_ext_str = eglQueryString(eglman->dpy, EGL_EXTENSIONS);
+
+    // check extension KHR_vg_parent_image
+    if (eglCreateImageKHR == NULL)
+    {
+        if (!strstr(egl_ext_str, "EGL_KHR_image"))
+        {
+            return EGL_FALSE;
+        }
+        else
+        {
+            eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR");
+            eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC)eglGetProcAddress("eglDestroyImageKHR");
+            if ((!eglCreateImageKHR) || (!eglDestroyImageKHR))
+            {
+                return EGL_FALSE;
+            }
+        }
+    }
+
+    // check extension GL_OES_EGL_image
+    if (glEGLImageTargetTexture2DOES == NULL)
+    {
+        glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES");
+        if (!glEGLImageTargetTexture2DOES)
+        {
+            return EGL_FALSE;
+        }
+    }
+
+    return EGL_TRUE;
+}
+
+static EGLBoolean create_x_window(EGLmanager *eglman, const char *name)
+{
+    EGLint scrnum, num_conf, num_visuals;
+    Window root;
+    EGLint vid;
+    XVisualInfo *visInfo, visTemplate;
+    XSetWindowAttributes attr;
+    unsigned long mask;
+
+    EGLint config_attrib[] =
+    {
+        EGL_RED_SIZE,			1,
+        EGL_GREEN_SIZE, 		1,
+        EGL_BLUE_SIZE,			1,
+        EGL_DEPTH_SIZE,         1,
+        EGL_SURFACE_TYPE,       EGL_WINDOW_BIT|EGL_PBUFFER_BIT,
+        EGL_RENDERABLE_TYPE,	EGL_OPENVG_BIT | EGL_OPENGL_BIT,
+        EGL_NONE
+    };
+
+    scrnum = DefaultScreen(eglman->xdpy);
+    root = RootWindow(eglman->xdpy, scrnum);
+
+    if (!eglChooseConfig(eglman->dpy, config_attrib, &eglman->conf, 1, &num_conf) ||
+        num_conf == 0 ||
+        eglGetError() != EGL_SUCCESS)
+    {
+        printf("Error: couldn't get an EGL visual config\n");
+        return EGL_FALSE;
+    }
+
+    if (!eglGetConfigAttrib(eglman->dpy, eglman->conf, EGL_NATIVE_VISUAL_ID, &vid) ||
+        eglGetError() != EGL_SUCCESS)
+    {
+        printf("Error: eglGetConfigAttrib() failed\n");
+        return EGL_FALSE;
+    }
+
+    /* The X window visual must match the EGL config */
+    visTemplate.visualid = vid;
+    visInfo = XGetVisualInfo(eglman->xdpy, VisualIDMask, &visTemplate, &num_visuals);
+    if (!visInfo)
+    {
+        printf("Error: couldn't get X visual\n");
+        return EGL_FALSE;
+    }
+
+    /* window attributes */
+    attr.background_pixel = 0;
+    attr.border_pixel = 0;
+    attr.colormap = XCreateColormap(eglman->xdpy, root, visInfo->visual, AllocNone);
+    attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+    mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+    eglman->xwin = XCreateWindow(eglman->xdpy, root, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT,
+                                 0, visInfo->depth, InputOutput,
+                                 visInfo->visual, mask, &attr);
+
+    if (!eglman->xwin)
+    {
+        printf("Error: couldn't create X Window\n");
+        return EGL_FALSE;
+    }
+
+    /* set hints and properties */
+    {
+       XSizeHints sizehints;
+       sizehints.x = 0;
+       sizehints.y = 0;
+       sizehints.width  = WINDOW_WIDTH;
+       sizehints.height = WINDOW_HEIGHT;
+       sizehints.flags = USSize | USPosition;
+       XSetNormalHints(eglman->xdpy, eglman->xwin, &sizehints);
+       XSetStandardProperties(eglman->xdpy, eglman->xwin, name, name,
+                              None, (char **)NULL, 0, &sizehints);
+    }
+
+    XFree(visInfo);
+
+    return EGL_TRUE;
+}
+
+static EGLBoolean egl_init(EGLmanager *eglman)
+{
+    EGLint pbuffer_attrib[] =
+    {
+        EGL_WIDTH,  128,
+        EGL_HEIGHT, 128,
+        EGL_NONE
+    };
+
+    // Check extension support
+    if (check_ext(eglman) != EGL_TRUE)
+    {
+        return EGL_FALSE;
+    }
+
+    // Create GL context
+    eglBindAPI(EGL_OPENGL_ES_API);
+    eglman->es_ctx = eglCreateContext(eglman->dpy, eglman->conf, NULL, NULL);
+    if (eglman->es_ctx == EGL_NO_CONTEXT ||
+        eglGetError() != EGL_SUCCESS)
+    {
+        return EGL_FALSE;
+    }
+
+    // Create VG context
+    eglBindAPI(EGL_OPENVG_API);
+    eglman->vg_ctx = eglCreateContext(eglman->dpy, eglman->conf, NULL, NULL);
+    if (eglman->vg_ctx == EGL_NO_CONTEXT ||
+        eglGetError() != EGL_SUCCESS)
+    {
+        return EGL_FALSE;
+    }
+
+    // Create window surface
+    eglman->win_surface = eglCreateWindowSurface(eglman->dpy, eglman->conf, eglman->xwin, NULL);
+    if (eglman->win_surface == EGL_NO_SURFACE ||
+        eglGetError() != EGL_SUCCESS)
+    {
+        return EGL_FALSE;
+    }
+
+    // Create pbuffer surface
+    eglman->pbuf_surface = eglCreatePbufferSurface(eglman->dpy, eglman->conf, pbuffer_attrib);
+    if (eglman->pbuf_surface == EGL_NO_SURFACE ||
+        eglGetError() != EGL_SUCCESS)
+    {
+
+        return EGL_FALSE;
+    }
+
+    return EGL_TRUE;
+}
+
+static void egl_deinit(EGLmanager *eglman)
+{
+    eglBindAPI(EGL_OPENGL_ES_API);
+    eglMakeCurrent(eglman->dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+
+    eglBindAPI(EGL_OPENVG_API);
+    eglMakeCurrent(eglman->dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+
+    eglDestroySurface(eglman->dpy, eglman->win_surface);
+    eglDestroySurface(eglman->dpy, eglman->pbuf_surface);
+
+    eglDestroyContext(eglman->dpy, eglman->es_ctx);
+    eglDestroyContext(eglman->dpy, eglman->vg_ctx);
+}
+
+static EGLBoolean vg_es_init(EGLmanager *eglman)
+{
+    // Initialize OpenVG
+    eglBindAPI(EGL_OPENVG_API);
+    eglMakeCurrent(eglman->dpy, eglman->pbuf_surface, eglman->pbuf_surface, eglman->vg_ctx);
+
+    // Create VGImage
+    eglman->vg_image = vgCreateImage(VG_sRGBA_8888, WINDOW_WIDTH, WINDOW_HEIGHT, VG_IMAGE_QUALITY_BETTER);
+
+    // Create EGLImage from VGImage
+    eglman->egl_image = (EGLImageKHR)eglCreateImageKHR(eglman->dpy, eglman->vg_ctx, EGL_VG_PARENT_IMAGE_KHR, (EGLClientBuffer)eglman->vg_image, NULL);
+
+    // Initialize OpenGL ES
+    eglBindAPI(EGL_OPENGL_ES_API);
+    eglMakeCurrent(eglman->dpy, eglman->win_surface, eglman->win_surface, eglman->es_ctx);
+
+    // Create Texture Target from EGLImage
+    glGenTextures(1, &eglman->texture);
+    glBindTexture(GL_TEXTURE_2D, eglman->texture);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)eglman->egl_image);
+
+    return EGL_TRUE;
+}
+
+static void vg_es_deinit(EGLmanager *eglman)
+{
+    // Destroy VG
+    eglBindAPI(EGL_OPENVG_API);
+    eglMakeCurrent(eglman->dpy, eglman->pbuf_surface, eglman->pbuf_surface, eglman->vg_ctx);
+    eglDestroyImageKHR(eglman->dpy, eglman->egl_image);
+    vgDestroyImage(eglman->vg_image);
+
+    // Destroy GL
+    eglBindAPI(EGL_OPENGL_ES_API);
+    eglMakeCurrent(eglman->dpy, eglman->win_surface, eglman->win_surface, eglman->es_ctx);
+    glDeleteTextures(1, &eglman->texture);
+    glBindTexture(GL_TEXTURE_2D, 0);
+
+}
+
+static void draw(EGLmanager *eglman)
+{
+    static const GLfloat red[4] = {1.0, 0.2, 0.2, 1.0};
+    static const GLfloat blue[4] = {0.2, 0.2, 1.0, 1.0};
+
+    GLfloat pVertex[12] =
+    {
+        -1.f, -1.f, 0.f,
+        1.f, -1.f, 0.f,
+        -1.f, 1.f, 0.f,
+        1.f, 1.f, 0.f
+    };
+    GLshort pTexCoord[8] =
+    {
+        0, 0,
+        1, 0,
+        0, 1,
+        1, 1,
+    };
+
+    // Make current to VG content
+    eglBindAPI(EGL_OPENVG_API);
+    eglMakeCurrent(eglman->dpy, eglman->pbuf_surface, eglman->pbuf_surface, eglman->vg_ctx);
+
+    vgSetfv(VG_CLEAR_COLOR, 4, red);
+    vgClearImage(eglman->vg_image, 0, 0, WINDOW_WIDTH/2, WINDOW_HEIGHT/2);
+
+    vgSetfv(VG_CLEAR_COLOR, 4, blue);
+    vgClearImage(eglman->vg_image, WINDOW_WIDTH/2, WINDOW_HEIGHT/2, WINDOW_WIDTH/2, WINDOW_HEIGHT/2);
+
+    // Make current to GL content
+    eglBindAPI(EGL_OPENGL_ES_API);
+    eglMakeCurrent(eglman->dpy, eglman->win_surface, eglman->win_surface, eglman->es_ctx);
+
+    glViewport(WINDOW_WIDTH / 8, WINDOW_HEIGHT / 8, WINDOW_WIDTH * 3 / 4, WINDOW_HEIGHT * 3 / 4);
+
+    glClearColor(1.0, 1.0, 1.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    glBindTexture(GL_TEXTURE_2D, eglman->texture);
+    glEnable(GL_TEXTURE_2D);
+    glEnableClientState( GL_VERTEX_ARRAY);
+    glVertexPointer(3, GL_FLOAT, 0, pVertex);
+    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+    glTexCoordPointer(2, GL_SHORT, 0, pTexCoord);
+
+    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+    // Swap buffer
+    eglSwapBuffers(eglman->dpy, eglman->win_surface);
+
+    return;
+}
+
+int main(int argc, char **argv)
+{
+    const char *s;
+
+    EGLmanager *eglman = calloc(1, sizeof(*eglman));
+
+    // Open X Display
+    Display *x_dpy = XOpenDisplay(NULL);
+    if (!x_dpy)
+    {
+        printf("error: can't open default display\n");
+        goto exit0;
+    }
+    eglman->xdpy = (EGLNativeDisplayType)x_dpy;
+
+    // Get EGL Display
+    eglman->dpy = eglGetDisplay(eglman->xdpy);
+    if (!eglman->dpy || eglGetError() != EGL_SUCCESS)
+    {
+        printf("error: can't get EGL display\n");
+        goto exit1;
+    }
+
+    // Initialize EGL
+    eglInitialize(eglman->dpy, &eglman->major_ver, &eglman->minor_ver);
+    if (eglGetError() != EGL_SUCCESS)
+    {
+        goto exit1;
+    }
+
+    // Query and print out information
+    s = eglQueryString(eglman->dpy, EGL_VERSION);
+    printf("EGL_VERSION = %s\n", s);
+
+    s = eglQueryString(eglman->dpy, EGL_VENDOR);
+    printf("EGL_VENDOR = %s\n", s);
+
+    s = eglQueryString(eglman->dpy, EGL_EXTENSIONS);
+    printf("EGL_EXTENSIONS = %s\n", s);
+
+    s = eglQueryString(eglman->dpy, EGL_CLIENT_APIS);
+    printf("EGL_CLIENT_APIS = %s\n", s);
+
+    // Create an RGB, double-buffered X window
+    if (create_x_window(eglman, "vgimage to texture") != EGL_TRUE)
+    {
+        goto exit2;
+    }
+
+    XMapWindow(eglman->xdpy, eglman->xwin);
+
+    // Initialize EGL
+    if (egl_init(eglman) != EGL_TRUE)
+    {
+        goto exit3;
+    }
+
+    // Initialize rendering API: OpenGL ES and OpenVG
+    if (vg_es_init(eglman) != EGL_TRUE)
+    {
+        goto exit3;
+    }
+
+    // Rendering
+    draw(eglman);
+
+    // Deinitialize rendering API
+    vg_es_deinit(eglman);
+
+    // Deinitialize EGL
+    egl_deinit(eglman);
+
+exit3:
+    XDestroyWindow(eglman->xdpy, eglman->xwin);
+exit2:
+    eglTerminate(eglman->dpy);
+exit1:
+    XCloseDisplay(eglman->xdpy);
+exit0:
+    free(eglman);
+
+    return 0;
+}



More information about the mesa-commit mailing list