summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCooper Yuan <cooperyuan@gmail.com>2011-08-25 14:18:46 +0800
committerCooper Yuan <cooperyuan@gmail.com>2011-08-25 14:18:46 +0800
commitb9b181fbd736c604fdb923d4570f007f89cde935 (patch)
tree93db1a2885788b88412dad1762f19fcda34618c0
parentdf36360d0b09a9165f0e83ca058703a6fb0704a9 (diff)
demos/egl: add two applications which validate creating Texture from
VGImage and creating VGImage from Texture through EGLImage
-rw-r--r--configure.ac1
-rw-r--r--src/egl/Makefile.am3
-rw-r--r--src/egl/oes_vg/Makefile.am48
-rw-r--r--src/egl/oes_vg/tex2vgimage.c428
-rw-r--r--src/egl/oes_vg/vgimage2tex.c425
5 files changed, 904 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac
index e17fbcfd..b5b2fcfd 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 15268177..d64a49e3 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 00000000..73038eb5
--- /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@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 00000000..6070ea68
--- /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@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 00000000..70ed3015
--- /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@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;
+}