summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXiang, Haihao <haihao.xiang@intel.com>2011-11-10 10:34:45 +0800
committerXiang, Haihao <haihao.xiang@intel.com>2011-12-14 08:27:03 +0800
commit2ac9bac5f4920584e612033078dfafcfe97694c5 (patch)
tree21633cbc76476413a2410d9f07ff3c24c389a262
parent1cda44018e922a4557f041735a2c903c6d40bfb2 (diff)
downloadlibva-2ac9bac5f4920584e612033078dfafcfe97694c5.tar.gz
a test case to use VA/EGL interfaces
Signed-off-by: Xiang, Haihao <haihao.xiang@intel.com>
-rw-r--r--configure.ac1
-rw-r--r--test/Makefile.am4
-rw-r--r--test/egl/Makefile.am15
-rw-r--r--test/egl/va_egl_x11.c502
4 files changed, 522 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac
index 2b5661b..52f27fc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -235,6 +235,7 @@ AC_OUTPUT([
test/Makefile
test/basic/Makefile
test/decode/Makefile
+ test/egl/Makefile
test/encode/Makefile
test/putsurface/Makefile
test/vainfo/Makefile
diff --git a/test/Makefile.am b/test/Makefile.am
index c55f6cb..79a0589 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -25,4 +25,8 @@ AM_CFLAGS = -I$(top_srcdir)/va -I$(top_srcdir)/test/basic -I$(top_srcdir)/src/x1
SUBDIRS = basic decode encode putsurface vainfo
+if USE_EGL
+SUBDIRS += egl
+endif
+
EXTRA_DIST = loadsurface.h loadsurface_yuv.h \ No newline at end of file
diff --git a/test/egl/Makefile.am b/test/egl/Makefile.am
new file mode 100644
index 0000000..caf7126
--- /dev/null
+++ b/test/egl/Makefile.am
@@ -0,0 +1,15 @@
+bin_PROGRAMS = va_egl
+
+INCLUDES = -I$(top_srcdir)
+
+TEST_LIBS = $(top_builddir)/va/$(libvabackendlib) $(top_builddir)/va/$(libvacorelib) $(top_builddir)/va/libva-egl.la -lpthread -lX11 -lEGL -lGLESv1_CM
+
+va_egl_LDADD = $(TEST_LIBS)
+va_egl_SOURCES = va_egl_x11.c
+
+EXTRA_DIST =
+
+valgrind: $(bin_PROGRAMS)
+ for a in $(bin_PROGRAMS); do \
+ valgrind --leak-check=full --show-reachable=yes .libs/$$a; \
+ done
diff --git a/test/egl/va_egl_x11.c b/test/egl/va_egl_x11.c
new file mode 100644
index 0000000..20d7415
--- /dev/null
+++ b/test/egl/va_egl_x11.c
@@ -0,0 +1,502 @@
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <va/va_x11.h>
+#include <va/va_egl.h>
+
+struct va_egl_context
+{
+ Display *x11_dpy;
+ Window win;
+
+ EGLDisplay egl_dpy;
+ EGLContext egl_ctx;
+ EGLSurface egl_surf;
+
+ VADisplay va_dpy;
+ VASurfaceID va_surface;
+ VASurfaceEGL va_egl_surface;
+
+ int x, y;
+ unsigned int width, height;
+ GLuint texture;
+ GLfloat ar;
+ unsigned int box_width;
+ unsigned char ydata;
+};
+
+static void
+va_egl_fini_egl(struct va_egl_context *ctx)
+{
+ eglMakeCurrent(ctx->egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglTerminate(ctx->egl_dpy);
+}
+
+static int
+va_egl_init_egl(struct va_egl_context *ctx)
+{
+ EGLint egl_major, egl_minor;
+ const char *s;
+
+ ctx->egl_dpy = eglGetDisplay(ctx->x11_dpy);
+
+ if (!ctx->egl_dpy) {
+ printf("Error: eglGetDisplay() failed\n");
+ return -1;
+ }
+
+ if (!eglInitialize(ctx->egl_dpy, &egl_major, &egl_minor)) {
+ printf("Error: eglInitialize() failed\n");
+ return -1;
+ }
+
+ s = eglQueryString(ctx->egl_dpy, EGL_VERSION);
+ printf("EGL_VERSION = %s\n", s);
+
+ return 0;
+}
+
+static int
+yuvgen_planar(int width, int height,
+ unsigned char *Y_start, int Y_pitch,
+ unsigned char *U_start, int U_pitch,
+ unsigned char *V_start, int V_pitch,
+ int UV_interleave, int box_width, unsigned char ydata)
+{
+ int row;
+
+ /* copy Y plane */
+ for (row = 0; row < height; row++) {
+ unsigned char *Y_row = Y_start + row * Y_pitch;
+ int jj, xpos, ypos;
+
+ ypos = (row / box_width) & 0x1;
+
+ for (jj = 0; jj < width; jj++) {
+ xpos = ((jj) / box_width) & 0x1;
+
+ if ((xpos == 0) && (ypos == 0))
+ Y_row[jj] = ydata;
+ if ((xpos == 1) && (ypos == 1))
+ Y_row[jj] = ydata;
+
+ if ((xpos == 1) && (ypos == 0))
+ Y_row[jj] = 0xff - ydata;
+ if ((xpos == 0) && (ypos == 1))
+ Y_row[jj] = 0xff - ydata;
+ }
+ }
+
+ /* copy UV data */
+ for( row = 0; row < height/2; row++) {
+ unsigned short value = 0x80;
+
+ if (UV_interleave) {
+ unsigned short *UV_row = (unsigned short *)(U_start + row * U_pitch);
+
+ memset(UV_row, value, width);
+ } else {
+ unsigned char *U_row = U_start + row * U_pitch;
+ unsigned char *V_row = V_start + row * V_pitch;
+
+ memset(U_row, value, width / 2);
+ memset(V_row, value, width / 2);
+ }
+ }
+
+ return 0;
+}
+
+static int
+va_egl_upload_surface(struct va_egl_context *ctx)
+{
+ VAImage surface_image;
+ void *surface_p = NULL, *U_start, *V_start;
+
+ vaDeriveImage(ctx->va_dpy, ctx->va_surface, &surface_image);
+
+ vaMapBuffer(ctx->va_dpy, surface_image.buf, &surface_p);
+
+ U_start = (char *)surface_p + surface_image.offsets[1];
+ V_start = (char *)surface_p + surface_image.offsets[2];
+
+ /* assume surface is planar format */
+ yuvgen_planar(surface_image.width, surface_image.height,
+ (unsigned char *)surface_p, surface_image.pitches[0],
+ (unsigned char *)U_start, surface_image.pitches[1],
+ (unsigned char *)V_start, surface_image.pitches[2],
+ (surface_image.format.fourcc==VA_FOURCC_NV12),
+ ctx->box_width, ctx->ydata);
+
+ vaUnmapBuffer(ctx->va_dpy,surface_image.buf);
+
+ vaDestroyImage(ctx->va_dpy,surface_image.image_id);
+
+ return 0;
+}
+
+static void
+va_egl_fini_va(struct va_egl_context *ctx)
+{
+ vaDestroySurfaces(ctx->va_dpy, &ctx->va_surface, 1);
+ vaTerminate(ctx->va_dpy);
+}
+
+static int
+va_egl_init_va(struct va_egl_context *ctx)
+{
+ VAStatus va_status;
+ int major_ver, minor_ver;
+
+ ctx->va_dpy = vaGetDisplayEGL(ctx->x11_dpy, ctx->egl_dpy);
+
+ if (!ctx->va_dpy) {
+ printf("Error: vaGetDisplayEGL() failed\n");
+ return -1;
+ }
+
+ va_status = vaInitialize(ctx->va_dpy, &major_ver, &minor_ver);
+
+ if (va_status != VA_STATUS_SUCCESS) {
+ printf("Error: vaInitialize() failed\n");
+ return -1;
+ }
+
+ va_status = vaCreateSurfaces(ctx->va_dpy,
+ ctx->width, ctx->height,
+ VA_RT_FORMAT_YUV420,
+ 1, &ctx->va_surface);
+
+ if (va_status != VA_STATUS_SUCCESS) {
+ printf("Error: vaCreateSurfaces() failed\n");
+ return -1;
+ }
+
+ va_egl_upload_surface(ctx);
+
+ return 0;
+}
+
+static void
+va_egl_make_window(struct va_egl_context *ctx, const char *title)
+{
+ int scrnum;
+ XSetWindowAttributes attr;
+ unsigned long mask;
+ Window root;
+ XVisualInfo *visInfo, visTemplate;
+ int num_visuals;
+ EGLConfig config;
+ EGLint num_configs, vid;
+ const EGLint attribs[] = {
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
+ EGL_NONE
+ };
+
+ scrnum = DefaultScreen(ctx->x11_dpy);
+ root = RootWindow(ctx->x11_dpy, scrnum);
+
+ if (!eglChooseConfig(ctx->egl_dpy, attribs, &config, 1, &num_configs) ||
+ !num_configs) {
+ printf("Error: couldn't get an EGL visual config\n");
+
+ return;
+ }
+
+ if (!eglGetConfigAttrib(ctx->egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
+ printf("Error: eglGetConfigAttrib() failed\n");
+
+ return;
+ }
+
+ /* The X window visual must match the EGL config */
+ visTemplate.visualid = vid;
+ visInfo = XGetVisualInfo(ctx->x11_dpy, VisualIDMask, &visTemplate, &num_visuals);
+
+ if (!visInfo) {
+ printf("Error: couldn't get X visual\n");
+
+ return;
+ }
+
+ /* window attributes */
+ attr.background_pixel = 0;
+ attr.border_pixel = 0;
+ attr.colormap = XCreateColormap(ctx->x11_dpy, root, visInfo->visual, AllocNone);
+ attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+ attr.override_redirect = 0;
+ mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect;
+
+ ctx->win = XCreateWindow(ctx->x11_dpy,
+ root,
+ ctx->x, ctx->y,
+ ctx->width, ctx->height,
+ 0, visInfo->depth, InputOutput,
+ visInfo->visual, mask, &attr);
+
+ /* set hints and properties */
+ {
+ XSizeHints sizehints;
+ sizehints.x = ctx->x;
+ sizehints.y = ctx->y;
+ sizehints.width = ctx->width;
+ sizehints.height = ctx->height;
+ sizehints.flags = USSize | USPosition;
+ XSetNormalHints(ctx->x11_dpy, ctx->win, &sizehints);
+ XSetStandardProperties(ctx->x11_dpy, ctx->win, title, title,
+ None, (char **)NULL, 0, &sizehints);
+ }
+
+ eglBindAPI(EGL_OPENGL_ES_API);
+
+ ctx->egl_ctx = eglCreateContext(ctx->egl_dpy, config, EGL_NO_CONTEXT, NULL);
+
+ if (!ctx->egl_ctx) {
+ printf("Error: eglCreateContext() failed\n");
+
+ return;
+ }
+
+ ctx->egl_surf = eglCreateWindowSurface(ctx->egl_dpy, config, ctx->win, NULL);
+ eglMakeCurrent(ctx->egl_dpy, ctx->egl_surf, ctx->egl_surf, ctx->egl_ctx);
+ XFree(visInfo);
+}
+
+static void
+va_egl_fini_gles(struct va_egl_context *ctx)
+{
+ glDeleteTextures(1, &ctx->texture);
+}
+
+static int
+va_egl_init_gles(struct va_egl_context *ctx)
+{
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ glColor4f(1.0, 1.0, 1.0, 1.0);
+
+ glDisable(GL_BLEND);
+ glDisable(GL_DEPTH_TEST);
+
+ glGenTextures(1, &ctx->texture);
+ glBindTexture(GL_TEXTURE_2D, ctx->texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glEnable(GL_TEXTURE_2D);
+
+ return 0;
+}
+
+static void
+va_egl_fini_va_egl(struct va_egl_context *ctx)
+{
+ vaDeassociateSurfaceEGL(ctx->va_dpy, ctx->va_egl_surface);
+ vaDestroySurfaceEGL(ctx->va_dpy, ctx->va_egl_surface);
+}
+
+static int
+va_egl_init_va_egl(struct va_egl_context *ctx)
+{
+ VAStatus va_status;
+
+ va_status = vaCreateSurfaceEGL(ctx->va_dpy,
+ GL_TEXTURE_2D, ctx->texture,
+ ctx->width, ctx->height,
+ &ctx->va_egl_surface);
+
+ if (va_status != VA_STATUS_SUCCESS) {
+ printf("Error: vaCreateSurfaceEGL() failed\n");
+ return -1;
+ }
+
+ va_status = vaAssociateSurfaceEGL(ctx->va_dpy,
+ ctx->va_egl_surface,
+ ctx->va_surface,
+ 0);
+
+ if (va_status != VA_STATUS_SUCCESS) {
+ printf("Error: vaAssociateSurfaceEGL() failed\n");
+ return -1;
+ }
+
+ vaUpdateAssociatedSurfaceEGL(ctx->va_dpy, ctx->va_egl_surface);
+
+ return 0;
+}
+
+static void
+va_egl_fini(struct va_egl_context *ctx)
+{
+ va_egl_fini_gles(ctx);
+ va_egl_fini_va(ctx);
+ va_egl_fini_egl(ctx);
+ va_egl_fini_gles(ctx);
+ va_egl_fini_va_egl(ctx);
+
+ // XDestroyWindow(ctx->x11_dpy, ctx->win);
+ XCloseDisplay(ctx->x11_dpy);
+}
+
+static int
+va_egl_init(struct va_egl_context *ctx, int argc, char **argv)
+{
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->x11_dpy = XOpenDisplay(NULL);
+ ctx->width = 320;
+ ctx->height = 320;
+ ctx->ar = 1.0;
+ ctx->box_width = 16;
+ ctx->ydata = 0xff;
+
+ if (!ctx->x11_dpy) {
+ printf("Error: couldn't open display %s\n", getenv("DISPLAY"));
+ return -1;
+ }
+
+ if (va_egl_init_egl(ctx) != 0)
+ return -1;
+
+ if (va_egl_init_va(ctx) != 0)
+ return -1;
+
+ va_egl_make_window(ctx, "VA/EGL");
+ va_egl_init_gles(ctx);
+ va_egl_init_va_egl(ctx);
+
+ return 0;
+}
+
+static void
+va_egl_reshape(struct va_egl_context *ctx, int width, int height)
+{
+ GLfloat ar = (GLfloat) width / (GLfloat) height;
+
+ ctx->width = width;
+ ctx->height = height;
+ ctx->ar = ar;
+
+ glViewport(0, 0, (GLint) width, (GLint) height);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrthof(-ar, ar, -ar, ar, -1.0, 1.0);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+}
+
+static void
+va_egl_draw(struct va_egl_context *ctx)
+{
+ const GLfloat verts[][3] = {
+ { -ctx->ar, -ctx->ar, 0 },
+ { ctx->ar, -ctx->ar, 0 },
+ { ctx->ar, ctx->ar, 0 },
+ { -ctx->ar, ctx->ar, 0 }
+ };
+ const GLfloat texs[][2] = {
+ { 0, 0 },
+ { 1, 0 },
+ { 1, 1 },
+ { 0, 1 }
+ };
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glVertexPointer(3, GL_FLOAT, 0, verts);
+ glTexCoordPointer(2, GL_FLOAT, 0, texs);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+}
+
+static void
+va_egl_event_loop(struct va_egl_context *ctx)
+{
+ while (1) {
+ int redraw = 0;
+
+ if (XPending(ctx->x11_dpy) > 0) {
+ XEvent event;
+ XNextEvent(ctx->x11_dpy, &event);
+
+ switch (event.type) {
+ case Expose:
+ redraw = 1;
+ break;
+
+ case ConfigureNotify:
+ va_egl_reshape(ctx, event.xconfigure.width, event.xconfigure.height);
+ redraw = 1;
+ break;
+
+ case KeyPress:
+ {
+ char buffer[10];
+ int code;
+ code = XLookupKeysym(&event.xkey, 0);
+
+ if (code == XK_y) {
+ ctx->ydata += 0x10;
+ va_egl_upload_surface(ctx);
+ vaUpdateAssociatedSurfaceEGL(ctx->va_dpy, ctx->va_egl_surface);
+ redraw = 1;
+ } else {
+ XLookupString(&event.xkey, buffer, sizeof(buffer),
+ NULL, NULL);
+
+ if (buffer[0] == 27) {
+ /* escape */
+ return;
+ }
+ }
+ }
+
+ break;
+
+ default:
+ ; /*no-op*/
+ }
+ }
+
+ if (redraw) {
+ va_egl_draw(ctx);
+ eglSwapBuffers(ctx->egl_dpy, ctx->egl_surf);
+ }
+ }
+}
+
+static void
+va_egl_run(struct va_egl_context *ctx)
+{
+ XMapWindow(ctx->x11_dpy, ctx->win);
+ va_egl_reshape(ctx, ctx->width, ctx->height);
+ va_egl_event_loop(ctx);
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct va_egl_context ctx;
+
+ if (va_egl_init(&ctx, argc, argv) == 0) {
+ va_egl_run(&ctx);
+ va_egl_fini(&ctx);
+ }
+
+ return 0;
+}