| Index: third_party/libva/test/egl/va_egl_x11.c
|
| diff --git a/third_party/libva/test/egl/va_egl_x11.c b/third_party/libva/test/egl/va_egl_x11.c
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..7d7521d3c9b0ad770a492294d79534aefdb183d9
|
| --- /dev/null
|
| +++ b/third_party/libva/test/egl/va_egl_x11.c
|
| @@ -0,0 +1,598 @@
|
| +#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;
|
| + unsigned int egl_target;
|
| + EGLClientBuffer egl_buffer;
|
| + EGLImageKHR egl_image;
|
| + PFNEGLCREATEIMAGEKHRPROC egl_create_image_khr;
|
| + PFNEGLDESTROYIMAGEKHRPROC egl_destroy_image_hkr;
|
| + PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glegl_image_target_texture2d_oes;
|
| +
|
| + 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 int
|
| +va_egl_init_extension(struct va_egl_context *ctx)
|
| +{
|
| + const char *exts;
|
| +
|
| + exts = eglQueryString(ctx->egl_dpy, EGL_EXTENSIONS);
|
| + ctx->egl_create_image_khr =
|
| + (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR");
|
| + ctx->egl_destroy_image_hkr =
|
| + (PFNEGLDESTROYIMAGEKHRPROC)eglGetProcAddress("eglDestroyImageKHR");
|
| +
|
| + if (!exts ||
|
| + !strstr(exts, "EGL_KHR_image_base") ||
|
| + !ctx->egl_create_image_khr ||
|
| + !ctx->egl_destroy_image_hkr) {
|
| + printf("EGL does not support EGL_KHR_image_base\n");
|
| + return -1;
|
| + }
|
| +
|
| + exts = (const char *)glGetString(GL_EXTENSIONS);
|
| + ctx->glegl_image_target_texture2d_oes =
|
| + (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES");
|
| +
|
| + if (!exts ||
|
| + !strstr(exts, "GL_OES_EGL_image") ||
|
| + !ctx->glegl_image_target_texture2d_oes) {
|
| + printf("OpenGL ES does not support GL_OES_EGL_image\n");
|
| + return -1;
|
| + }
|
| +
|
| + return 0;
|
| +}
|
| +
|
| +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)
|
| +{
|
| + if (ctx->egl_image)
|
| + ctx->egl_destroy_image_hkr(ctx->egl_dpy, ctx->egl_image);
|
| +
|
| + 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;
|
| + int num_max_targets = 0, num_targets = 0;
|
| + int num_max_attributes = 0, num_attribs = 0;
|
| + unsigned int *target_list = NULL;
|
| + EGLint *img_attribs = NULL;
|
| +
|
| + num_targets = num_max_targets = vaMaxNumSurfaceTargetsEGL(ctx->va_dpy);
|
| +
|
| + if (num_max_targets < 1) {
|
| + printf("Error: vaMaxNumSurfaceTargetsEGL() returns %d\n", num_max_targets);
|
| + return -1;
|
| + }
|
| +
|
| + num_attribs = num_max_attributes = vaMaxNumSurfaceAttributesEGL(ctx->va_dpy);
|
| +
|
| + if (num_max_attributes < 1) {
|
| + printf("Error: vaMaxNumSurfaceAttributesEGL() returns %d\n", num_max_attributes);
|
| + return -1;
|
| + }
|
| +
|
| + target_list = malloc(num_max_targets * sizeof(unsigned int));
|
| + va_status = vaQuerySurfaceTargetsEGL(ctx->va_dpy,
|
| + target_list,
|
| + &num_targets);
|
| +
|
| + if (va_status != VA_STATUS_SUCCESS || num_targets < 1) {
|
| + printf("Error: vaQuerySurfaceTargetsEGL() failed\n");
|
| + return -1;
|
| + }
|
| +
|
| + va_status = vaCreateSurfaceEGL(ctx->va_dpy,
|
| + target_list[0],
|
| + 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;
|
| + }
|
| +
|
| + img_attribs = malloc(2 * num_max_attributes * sizeof(EGLint));
|
| + va_status = vaGetSurfaceInfoEGL(ctx->va_dpy,
|
| + ctx->va_egl_surface,
|
| + &ctx->egl_target,
|
| + &ctx->egl_buffer,
|
| + img_attribs,
|
| + &num_attribs);
|
| +
|
| + if (va_status != VA_STATUS_SUCCESS) {
|
| + printf("Error: vaGetSurfaceInfoEGL() failed\n");
|
| + return -1;
|
| + }
|
| +
|
| + ctx->egl_image = ctx->egl_create_image_khr(ctx->egl_dpy,
|
| + EGL_NO_CONTEXT,
|
| + ctx->egl_target,
|
| + ctx->egl_buffer,
|
| + img_attribs);
|
| +
|
| + vaSyncSurfaceEGL(ctx->va_dpy, ctx->va_egl_surface);
|
| + ctx->glegl_image_target_texture2d_oes(GL_TEXTURE_2D,
|
| + (GLeglImageOES)ctx->egl_image);
|
| +
|
| + 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_extension(ctx);
|
| + 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);
|
| + vaSyncSurfaceEGL(ctx->va_dpy, ctx->va_egl_surface);
|
| + ctx->glegl_image_target_texture2d_oes(GL_TEXTURE_2D,
|
| + (GLeglImageOES)ctx->egl_image);
|
| + 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;
|
| +
|
| + printf("Usage: press 'y' to change Y plane \n\n");
|
| +
|
| + if (va_egl_init(&ctx, argc, argv) == 0) {
|
| + va_egl_run(&ctx);
|
| + va_egl_fini(&ctx);
|
| + }
|
| +
|
| + return 0;
|
| +}
|
|
|