summaryrefslogtreecommitdiff
path: root/test/putsurface
diff options
context:
space:
mode:
Diffstat (limited to 'test/putsurface')
-rw-r--r--test/putsurface/Makefile.am36
-rw-r--r--test/putsurface/loadsurface.h97
-rw-r--r--test/putsurface/putsurface.c343
3 files changed, 476 insertions, 0 deletions
diff --git a/test/putsurface/Makefile.am b/test/putsurface/Makefile.am
new file mode 100644
index 0000000..3e5c864
--- /dev/null
+++ b/test/putsurface/Makefile.am
@@ -0,0 +1,36 @@
+# Copyright (c) 2007 Intel Corporation. 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, sub license, 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 NON-INFRINGEMENT.
+# IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
+
+bin_PROGRAMS = putsurface
+
+AM_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/x11 -DIN_LIBVA
+
+TEST_LIBS = $(top_srcdir)/src/$(libvabackendlib)
+
+putsurface_LDADD = $(TEST_LIBS)
+putsurface_SOURCES = putsurface.c
+
+
+valgrind: $(bin_PROGRAMS)
+ for a in $(bin_PROGRAMS); do \
+ valgrind --leak-check=full --show-reachable=yes .libs/$$a; \
+ done
diff --git a/test/putsurface/loadsurface.h b/test/putsurface/loadsurface.h
new file mode 100644
index 0000000..4c5da2d
--- /dev/null
+++ b/test/putsurface/loadsurface.h
@@ -0,0 +1,97 @@
+
+
+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, int row_shift,
+ int field)
+{
+ 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;
+
+ /* fill garbage data into the other field */
+ if (((field == VA_TOP_FIELD) && (row &1))
+ || ((field == VA_BOTTOM_FIELD) && ((row &1)==0))) {
+ memset(Y_row, 0xff, width);
+ continue;
+ }
+
+ for (jj=0; jj<width; jj++) {
+ xpos = ((row_shift + jj) / box_width) & 0x1;
+
+ if ((xpos == 0) && (ypos == 0))
+ Y_row[jj] = 0xeb;
+ if ((xpos == 1) && (ypos == 1))
+ Y_row[jj] = 0xeb;
+
+ if ((xpos == 1) && (ypos == 0))
+ Y_row[jj] = 0x10;
+ if ((xpos == 0) && (ypos == 1))
+ Y_row[jj] = 0x10;
+ }
+ }
+
+ /* copy UV data */
+ for( row =0; row < height/2; row++) {
+ unsigned short value = 0x80;
+
+ /* fill garbage data into the other field */
+ if (((field == VA_TOP_FIELD) && (row &1))
+ || ((field == VA_BOTTOM_FIELD) && ((row &1)==0))) {
+ value = 0xff;
+ }
+
+ 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 upload_surface(VADisplay va_dpy, VASurfaceID surface_id,
+ int box_width, int row_shift,
+ int field)
+{
+ VAImage surface_image;
+ void *surface_p=NULL, *U_start,*V_start;
+ VAStatus va_status;
+
+ va_status = vaDeriveImage(va_dpy,surface_id,&surface_image);
+ CHECK_VASTATUS(va_status,"vaDeriveImage");
+
+ vaMapBuffer(va_dpy,surface_image.buf,&surface_p);
+ assert(VA_STATUS_SUCCESS == va_status);
+
+ U_start = surface_p + surface_image.offsets[1];
+ V_start = surface_p + surface_image.offsets[2];
+
+ /* assume surface is planar format */
+ yuvgen_planar(surface_image.width, surface_image.height,
+ surface_p, surface_image.pitches[0],
+ U_start, surface_image.pitches[1],
+ V_start, surface_image.pitches[2],
+ (surface_image.format.fourcc==VA_FOURCC_NV12),
+ box_width, row_shift, field);
+
+ vaUnmapBuffer(va_dpy,surface_image.buf);
+
+ vaDestroyImage(va_dpy,surface_image.image_id);
+
+ return 0;
+}
diff --git a/test/putsurface/putsurface.c b/test/putsurface/putsurface.c
new file mode 100644
index 0000000..359d1e0
--- /dev/null
+++ b/test/putsurface/putsurface.c
@@ -0,0 +1,343 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <sys/time.h>
+
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <va/va.h>
+#include <va/va_x11.h>
+
+#include <assert.h>
+
+#include <pthread.h>
+
+/*currently, if XCheckWindowEvent was called in more than one thread, it would cause
+ * XIO: fatal IO error 11 (Resource temporarily unavailable) on X server ":0.0"
+ * after 87 requests (83 known processed) with 0 events remaining.
+ *
+ * X Error of failed request: BadGC (invalid GC parameter)
+ * Major opcode of failed request: 60 (X_FreeGC)
+ * Resource id in failed request: 0x600034
+ * Serial number of failed request: 398
+ * Current serial number in output stream: 399
+ * The root cause is unknown. */
+
+#define CHECK_VASTATUS(va_status,func) \
+if (va_status != VA_STATUS_SUCCESS) { \
+ fprintf(stderr,"%s:%s (%d) failed,exit\n", __func__, func, __LINE__); \
+ exit(1); \
+}
+
+#include "loadsurface.h"
+
+
+#define SURFACE_NUM 5
+static VASurfaceID surface_id[SURFACE_NUM];
+static int surface_width=352, surface_height=288;
+static int win_width=352, win_height=288;
+static Window win_thread0, win_thread1;
+static Pixmap pixmap_thread0, pixmap_thread1;
+static GC context_thread0, context_thread1;
+static Display *x11_display;
+static VADisplay *va_dpy;
+static int multi_thread=0;
+static int put_pixmap = 0;
+static int test_clip = 1;
+static int display_field = VA_FRAME_PICTURE;
+static int check_event = 1;
+static int verbose=0;
+static pthread_mutex_t surface_mutex[SURFACE_NUM];
+
+static pthread_mutex_t gmutex;
+
+static int box_width=32;
+
+static Pixmap create_pixmap(int width, int height)
+{
+ int screen = DefaultScreen(x11_display);
+ Window root;
+ Pixmap pixmap;
+ XWindowAttributes attr;
+
+ root = RootWindow(x11_display, screen);
+
+ XGetWindowAttributes (x11_display, root, &attr);
+
+ printf("Create a pixmap from ROOT window %dx%d\n\n", attr.width, attr.height);
+ pixmap = XCreatePixmap(x11_display, root, attr.width, attr.height,
+ DefaultDepth(x11_display, DefaultScreen(x11_display)));
+
+ return pixmap;
+}
+
+static int create_window(int width, int height)
+{
+ int screen = DefaultScreen(x11_display);
+ Window root, win;
+
+ root = RootWindow(x11_display, screen);
+
+ printf("Create window0 for thread0\n");
+ win_thread0 = win = XCreateSimpleWindow(x11_display, root, 0, 0, width, height,
+ 0, 0, WhitePixel(x11_display, 0));
+ if (win) {
+ XSizeHints sizehints;
+ sizehints.width = width;
+ sizehints.height = height;
+ sizehints.flags = USSize;
+ XSetNormalHints(x11_display, win, &sizehints);
+ XSetStandardProperties(x11_display, win, "Thread 0", "Thread 0",
+ None, (char **)NULL, 0, &sizehints);
+
+ XMapWindow(x11_display, win);
+ }
+ context_thread0 = XCreateGC(x11_display, win, 0, 0);
+ XSelectInput(x11_display, win, KeyPressMask | StructureNotifyMask);
+ XSync(x11_display, False);
+
+ if (put_pixmap)
+ pixmap_thread0 = create_pixmap(width, height);
+
+ if (multi_thread == 0)
+ return 0;
+
+ printf("Create window1 for thread1\n");
+
+ win_thread1 = win = XCreateSimpleWindow(x11_display, root, width, 0, width, height,
+ 0, 0, WhitePixel(x11_display, 0));
+ if (win) {
+ XSizeHints sizehints;
+ sizehints.width = width;
+ sizehints.height = height;
+ sizehints.flags = USSize;
+ XSetNormalHints(x11_display, win, &sizehints);
+ XSetStandardProperties(x11_display, win, "Thread 1", "Thread 1",
+ None, (char **)NULL, 0, &sizehints);
+
+ XMapWindow(x11_display, win);
+ }
+ if (put_pixmap)
+ pixmap_thread1 = create_pixmap(width, height);
+
+ context_thread1 = XCreateGC(x11_display, win, 0, 0);
+ XSelectInput(x11_display, win, KeyPressMask | StructureNotifyMask);
+ XSync(x11_display, False);
+
+ return 0;
+}
+
+static VASurfaceID get_next_free_surface(int *index)
+{
+ VASurfaceStatus surface_status;
+ int i;
+
+ assert(index);
+
+ for (i=0; i<SURFACE_NUM; i++) {
+ surface_status = 0;
+ vaQuerySurfaceStatus(va_dpy, surface_id[i], &surface_status);
+ if (surface_status == VASurfaceReady)
+ {
+ if (0 == pthread_mutex_trylock(&surface_mutex[i]))
+ {
+ *index = i;
+ break;
+ }
+ }
+ }
+
+ if (i==SURFACE_NUM)
+ return VA_INVALID_SURFACE;
+ else
+ return surface_id[i];
+}
+
+static int putsurface_thread(void *data)
+{
+ int width=win_width, height=win_height;
+ Drawable draw;
+ Window win = (Window)data;
+ Pixmap pixmap = 0;
+ GC context = NULL;
+ int quit = 0;
+ VAStatus vaStatus;
+ int row_shift = 0;
+ int index = 0;
+ Bool is_event;
+ XEvent event;
+
+ if (win == win_thread0) {
+ printf("Enter into thread0\n\n");
+ pixmap = pixmap_thread0;
+ context = context_thread0;
+ }
+
+ if (win == win_thread1) {
+ printf("Enter into thread1\n\n");
+ pixmap = pixmap_thread1;
+ context = context_thread1;
+ }
+
+ if (put_pixmap) {
+ printf("vaPutSurface into a Pixmap, then copy into the Window\n\n");
+ draw = pixmap;
+ } else {
+ printf("vaPutSurface into a Window directly\n\n");
+ draw = win;
+ }
+
+ while (!quit) {
+ VASurfaceID surface_id = VA_INVALID_SURFACE;
+
+ while (surface_id == VA_INVALID_SURFACE)
+ surface_id = get_next_free_surface(&index);
+
+ if (verbose) printf("Thread %x Display surface 0x%p,\n", (unsigned int)win, (void *)surface_id);
+
+ upload_surface(va_dpy, surface_id, box_width, row_shift, display_field);
+
+ vaStatus = vaPutSurface(va_dpy, surface_id, draw,
+ 0,0,surface_width,surface_height,
+ 0,0,width,height,
+ NULL,0,display_field);
+ CHECK_VASTATUS(vaStatus,"vaPutSurface");
+
+ if (put_pixmap)
+ XCopyArea(x11_display, pixmap, win, context, 0, 0, width, height, 0, 0);
+
+ pthread_mutex_unlock(&surface_mutex[index]);
+
+ if (check_event) {
+ pthread_mutex_lock(&gmutex);
+ is_event =XCheckWindowEvent(x11_display, win, StructureNotifyMask|KeyPressMask,&event);
+ pthread_mutex_unlock(&gmutex);
+ if (is_event) {
+ /* bail on any focused key press */
+ if(event.type == KeyPress) {
+ quit = 1;
+ break;
+ }
+
+ /* rescale the video to fit the window */
+ if(event.type == ConfigureNotify) {
+ width = event.xconfigure.width;
+ height = event.xconfigure.height;
+ printf("Scale window to %dx%d\n", width, height);
+ }
+ }
+ }
+
+ row_shift++;
+ if (row_shift==(2*box_width)) row_shift= 0;
+ }
+
+ pthread_exit(NULL);
+}
+
+
+int main(int argc,char **argv)
+{
+ int major_ver, minor_ver;
+ VAStatus va_status;
+ pthread_t thread1;
+ int ret;
+ char c;
+ int i;
+
+ while ((c =getopt(argc,argv,"w:h:d:f:tep?nv") ) != EOF) {
+ switch (c) {
+ case '?':
+ printf("putsurface <options>\n");
+ printf(" -p output to pixmap\n");
+ printf(" -d the dimension of black/write square box, default is 32\n");
+ printf(" -t multi-threads\n");
+ printf(" -e don't check X11 event\n");
+ printf(" -c test clipbox\n");
+ printf(" -f <1/2> top field, or bottom field\n");
+ printf(" -v verbose output\n");
+ exit(0);
+ break;
+ case 'w':
+ win_width = atoi(optarg);
+ break;
+ case 'h':
+ win_height = atoi(optarg);
+ break;
+ case 'd':
+ box_width = atoi(optarg);
+ break;
+ case 't':
+ multi_thread = 1;
+ printf("Two threads to do vaPutSurface\n");
+ break;
+ case 'e':
+ check_event = 0;
+ break;
+ case 'p':
+ put_pixmap = 1;
+ break;
+ case 'c':
+ test_clip = 1;
+ break;
+ case 'f':
+ if (atoi(optarg) == 1) {
+ printf("Display TOP field\n");
+ display_field = VA_TOP_FIELD;
+ } else if (atoi(optarg) == 2) {
+ printf("Display BOTTOM field\n");
+ display_field = VA_BOTTOM_FIELD;
+ } else
+ printf("The validate input for -f is: 1(top field)/2(bottom field)\n");
+ break;
+ case 'v':
+ verbose = 1;
+ printf("Enable verbose output\n");
+ break;
+ }
+ }
+
+ x11_display = XOpenDisplay(":0.0");
+ if (x11_display == NULL) {
+ fprintf(stderr, "Can't connect X server!\n");
+ exit(-1);
+ }
+
+ create_window(win_width, win_height);
+
+ va_dpy = vaGetDisplay(x11_display);
+ va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
+ CHECK_VASTATUS(va_status, "vaInitialize");
+
+ surface_width = win_width;
+ surface_height = win_height;
+ va_status = vaCreateSurfaces(va_dpy,surface_width, surface_height,
+ VA_RT_FORMAT_YUV420, SURFACE_NUM, &surface_id[0]);
+ CHECK_VASTATUS(va_status, "vaCreateSurfaces");
+
+ if (check_event)
+ pthread_mutex_init(&gmutex, NULL);
+
+ for(i = 0; i< SURFACE_NUM; i++)
+ pthread_mutex_init(&surface_mutex[i], NULL);
+
+ if (multi_thread == 1)
+ ret = pthread_create(&thread1, NULL, (void *)putsurface_thread, (void*)win_thread1);
+
+ putsurface_thread((void *)win_thread0);
+
+ if (multi_thread == 1)
+ pthread_join(thread1, (void **)&ret);
+
+ vaDestroySurfaces(va_dpy,&surface_id[0],SURFACE_NUM);
+ vaTerminate(va_dpy);
+
+ return 0;
+}