2 * Copyright (c) 2008-2009 Intel Corporation. All Rights Reserved.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sub license, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 /* gcc -o putsurface putsurface.c -lva -lva-x11 */
33 #include <X11/Xutil.h>
38 #include <sys/types.h>
43 #include <va/va_x11.h>
49 /*currently, if XCheckWindowEvent was called in more than one thread, it would cause
50 * XIO: fatal IO error 11 (Resource temporarily unavailable) on X server ":0.0"
51 * after 87 requests (83 known processed) with 0 events remaining.
53 * X Error of failed request: BadGC (invalid GC parameter)
54 * Major opcode of failed request: 60 (X_FreeGC)
55 * Resource id in failed request: 0x600034
56 * Serial number of failed request: 398
57 * Current serial number in output stream: 399
58 * The root cause is unknown. */
60 #define CHECK_VASTATUS(va_status,func) \
61 if (va_status != VA_STATUS_SUCCESS) { \
62 fprintf(stderr,"%s:%s (%d) failed,exit\n", __func__, func, __LINE__); \
66 #include "loadsurface.h"
70 static VASurfaceID surface_id[SURFACE_NUM];
71 static int surface_width=352, surface_height=288;
72 static int win_width=352, win_height=288;
73 static Window win_thread0, win_thread1;
74 static Pixmap pixmap_thread0, pixmap_thread1;
75 static GC context_thread0, context_thread1;
76 static Display *x11_display;
77 static VADisplay *va_dpy;
78 static int multi_thread=0;
79 static int put_pixmap = 0;
80 static int test_clip = 0;
81 static int display_field = VA_FRAME_PICTURE;
82 static int check_event = 1;
84 static pthread_mutex_t surface_mutex[SURFACE_NUM];
86 static pthread_mutex_t gmutex;
88 static int box_width=32;
90 static Pixmap create_pixmap(int width, int height)
92 int screen = DefaultScreen(x11_display);
95 XWindowAttributes attr;
97 root = RootWindow(x11_display, screen);
99 XGetWindowAttributes (x11_display, root, &attr);
101 printf("Create a pixmap from ROOT window %dx%d\n\n", attr.width, attr.height);
102 pixmap = XCreatePixmap(x11_display, root, attr.width, attr.height,
103 DefaultDepth(x11_display, DefaultScreen(x11_display)));
108 static int create_window(int width, int height)
110 int screen = DefaultScreen(x11_display);
113 root = RootWindow(x11_display, screen);
115 printf("Create window0 for thread0\n");
116 win_thread0 = win = XCreateSimpleWindow(x11_display, root, 0, 0, width, height,
117 0, 0, WhitePixel(x11_display, 0));
119 XSizeHints sizehints;
120 sizehints.width = width;
121 sizehints.height = height;
122 sizehints.flags = USSize;
123 XSetNormalHints(x11_display, win, &sizehints);
124 XSetStandardProperties(x11_display, win, "Thread 0", "Thread 0",
125 None, (char **)NULL, 0, &sizehints);
127 XMapWindow(x11_display, win);
129 context_thread0 = XCreateGC(x11_display, win, 0, 0);
130 XSelectInput(x11_display, win, KeyPressMask | StructureNotifyMask);
131 XSync(x11_display, False);
134 pixmap_thread0 = create_pixmap(width, height);
136 if (multi_thread == 0)
139 printf("Create window1 for thread1\n");
141 win_thread1 = win = XCreateSimpleWindow(x11_display, root, width, 0, width, height,
142 0, 0, WhitePixel(x11_display, 0));
144 XSizeHints sizehints;
145 sizehints.width = width;
146 sizehints.height = height;
147 sizehints.flags = USSize;
148 XSetNormalHints(x11_display, win, &sizehints);
149 XSetStandardProperties(x11_display, win, "Thread 1", "Thread 1",
150 None, (char **)NULL, 0, &sizehints);
152 XMapWindow(x11_display, win);
155 pixmap_thread1 = create_pixmap(width, height);
157 context_thread1 = XCreateGC(x11_display, win, 0, 0);
158 XSelectInput(x11_display, win, KeyPressMask | StructureNotifyMask);
159 XSync(x11_display, False);
164 static VASurfaceID get_next_free_surface(int *index)
166 VASurfaceStatus surface_status;
171 for (i=0; i<SURFACE_NUM; i++) {
173 vaQuerySurfaceStatus(va_dpy, surface_id[i], &surface_status);
174 if (surface_status == VASurfaceReady)
176 if (0 == pthread_mutex_trylock(&surface_mutex[i]))
185 return VA_INVALID_SURFACE;
187 return surface_id[i];
191 * Helper function for profiling purposes
193 static unsigned long get_tick_count(void)
196 if (gettimeofday(&tv, NULL))
198 return tv.tv_usec/1000+tv.tv_sec*1000;
201 static int putsurface_thread(void *data)
203 int width=win_width, height=win_height;
205 Window win = (Window)data;
214 unsigned int frame_num=0, start_time, putsurface_time;
215 VARectangle cliprects[2]; /* client supplied clip list */
217 if (win == win_thread0) {
218 printf("Enter into thread0\n\n");
219 pixmap = pixmap_thread0;
220 context = context_thread0;
223 if (win == win_thread1) {
224 printf("Enter into thread1\n\n");
225 pixmap = pixmap_thread1;
226 context = context_thread1;
230 printf("vaPutSurface into a Pixmap, then copy into the Window\n\n");
233 printf("vaPutSurface into a Window directly\n\n");
239 VASurfaceID surface_id = VA_INVALID_SURFACE;
241 while (surface_id == VA_INVALID_SURFACE)
242 surface_id = get_next_free_surface(&index);
244 if (verbose) printf("Thread %x Display surface 0x%p,\n", (unsigned int)win, (void *)surface_id);
246 upload_surface(va_dpy, surface_id, box_width, row_shift, display_field);
248 start_time = get_tick_count();
249 vaStatus = vaPutSurface(va_dpy, surface_id, draw,
250 0,0,surface_width,surface_height,
252 (test_clip==0)?NULL:&cliprects[0],
255 CHECK_VASTATUS(vaStatus,"vaPutSurface");
256 putsurface_time += (get_tick_count() - start_time);
258 if ((frame_num % 0xff) == 0) {
259 fprintf(stderr, "%.2f FPS \r", 256000.0 / (float)putsurface_time);
263 srand((unsigned)time(NULL));
265 cliprects[0].x = (rand() % width);
266 cliprects[0].y = (rand() % height);
267 cliprects[0].width = (rand() % (width - cliprects[0].x));
268 cliprects[0].height = (rand() % (height - cliprects[0].y));
270 cliprects[1].x = (rand() % width);
271 cliprects[1].y = (rand() % height);
272 cliprects[1].width = (rand() % (width - cliprects[1].x));
273 cliprects[1].height = (rand() % (height - cliprects[1].y));
274 printf("\nTest clip (%d,%d, %d x %d) and (%d,%d, %d x %d) \n",
275 cliprects[0].x, cliprects[0].y, cliprects[0].width, cliprects[0].height,
276 cliprects[1].x, cliprects[1].y, cliprects[1].width, cliprects[1].height);
281 XCopyArea(x11_display, pixmap, win, context, 0, 0, width, height, 0, 0);
283 pthread_mutex_unlock(&surface_mutex[index]);
286 pthread_mutex_lock(&gmutex);
287 is_event = XCheckWindowEvent(x11_display, win, StructureNotifyMask|KeyPressMask,&event);
288 pthread_mutex_unlock(&gmutex);
290 /* bail on any focused key press */
291 if(event.type == KeyPress) {
296 /* rescale the video to fit the window */
297 if(event.type == ConfigureNotify) {
298 width = event.xconfigure.width;
299 height = event.xconfigure.height;
300 printf("Scale window to %dx%d\n", width, height);
306 if (row_shift==(2*box_width)) row_shift= 0;
315 int main(int argc,char **argv)
317 int major_ver, minor_ver;
324 while ((c =getopt(argc,argv,"w:h:d:f:tcep?nv") ) != EOF) {
327 printf("putsurface <options>\n");
328 printf(" -p output to pixmap\n");
329 printf(" -d the dimension of black/write square box, default is 32\n");
330 printf(" -t multi-threads\n");
331 printf(" -e don't check X11 event\n");
332 printf(" -c test clipbox\n");
333 printf(" -f <1/2> top field, or bottom field\n");
334 printf(" -v verbose output\n");
338 win_width = atoi(optarg);
341 win_height = atoi(optarg);
344 box_width = atoi(optarg);
348 printf("Two threads to do vaPutSurface\n");
360 if (atoi(optarg) == 1) {
361 printf("Display TOP field\n");
362 display_field = VA_TOP_FIELD;
363 } else if (atoi(optarg) == 2) {
364 printf("Display BOTTOM field\n");
365 display_field = VA_BOTTOM_FIELD;
367 printf("The validate input for -f is: 1(top field)/2(bottom field)\n");
371 printf("Enable verbose output\n");
376 x11_display = XOpenDisplay(":0.0");
377 if (x11_display == NULL) {
378 fprintf(stderr, "Can't connect X server!\n");
382 create_window(win_width, win_height);
384 va_dpy = vaGetDisplay(x11_display);
385 va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
386 CHECK_VASTATUS(va_status, "vaInitialize");
388 surface_width = win_width;
389 surface_height = win_height;
390 va_status = vaCreateSurfaces(va_dpy,surface_width, surface_height,
391 VA_RT_FORMAT_YUV420, SURFACE_NUM, &surface_id[0]);
392 CHECK_VASTATUS(va_status, "vaCreateSurfaces");
395 pthread_mutex_init(&gmutex, NULL);
397 for(i = 0; i< SURFACE_NUM; i++)
398 pthread_mutex_init(&surface_mutex[i], NULL);
400 if (multi_thread == 1)
401 ret = pthread_create(&thread1, NULL, (void *)putsurface_thread, (void*)win_thread1);
403 putsurface_thread((void *)win_thread0);
405 if (multi_thread == 1)
406 pthread_join(thread1, (void **)&ret);
408 vaDestroySurfaces(va_dpy,&surface_id[0],SURFACE_NUM);