Added the missing files
[profile/ivi/libva.git] / test / putsurface / putsurface.c
1 /*
2  * Copyright (c) 2008-2009 Intel Corporation. All Rights Reserved.
3  *
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:
11  * 
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial portions
14  * of the Software.
15  * 
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.
23  */
24
25
26 /* gcc -o putsurface putsurface.c -lva -lva-x11 */
27
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <getopt.h>
32 #include <X11/Xlib.h>
33 #include <X11/Xutil.h>
34 #include <sys/time.h>
35
36 #include <unistd.h>
37
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <fcntl.h>
41
42 #include <va/va.h>
43 #include <va/va_x11.h>
44
45 #include <assert.h>
46
47 #include <pthread.h>
48
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.
52  *
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. */
59
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__); \
63     exit(1);                                                            \
64 }
65
66 #include "loadsurface.h"
67
68
69 #define SURFACE_NUM 5
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;
83 static  int verbose=0;
84 static  pthread_mutex_t surface_mutex[SURFACE_NUM];
85
86 static pthread_mutex_t gmutex;
87
88 static  int box_width=32;
89
90 static Pixmap create_pixmap(int width, int height)
91 {
92     int screen = DefaultScreen(x11_display);
93     Window root;
94     Pixmap pixmap;
95     XWindowAttributes attr;
96     
97     root = RootWindow(x11_display, screen);
98
99     XGetWindowAttributes (x11_display, root, &attr);
100     
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)));
104
105     return pixmap;
106 }
107
108 static int create_window(int width, int height)
109 {
110     int screen = DefaultScreen(x11_display);
111     Window root, win;
112
113     root = RootWindow(x11_display, screen);
114
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));
118     if (win) {
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);
126
127         XMapWindow(x11_display, win);
128     }
129     context_thread0 = XCreateGC(x11_display, win, 0, 0);
130     XSelectInput(x11_display, win, KeyPressMask | StructureNotifyMask);
131     XSync(x11_display, False);
132
133     if (put_pixmap)
134         pixmap_thread0 = create_pixmap(width, height);
135     
136     if (multi_thread == 0)
137         return 0;
138
139     printf("Create window1 for thread1\n");
140     
141     win_thread1 = win = XCreateSimpleWindow(x11_display, root, width, 0, width, height,
142                                             0, 0, WhitePixel(x11_display, 0));
143     if (win) {
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);
151
152         XMapWindow(x11_display, win);
153     }
154     if (put_pixmap)
155         pixmap_thread1 = create_pixmap(width, height);
156
157     context_thread1 = XCreateGC(x11_display, win, 0, 0);
158     XSelectInput(x11_display, win, KeyPressMask | StructureNotifyMask);
159     XSync(x11_display, False);
160     
161     return 0;
162 }
163
164 static VASurfaceID get_next_free_surface(int *index)
165 {
166     VASurfaceStatus surface_status;
167     int i;
168
169     assert(index);
170
171     for (i=0; i<SURFACE_NUM; i++) {
172         surface_status = 0;
173         vaQuerySurfaceStatus(va_dpy, surface_id[i], &surface_status);
174         if (surface_status == VASurfaceReady)
175         {
176             if (0 == pthread_mutex_trylock(&surface_mutex[i]))
177             {
178                 *index = i;
179                 break;
180             }
181         }
182     }
183
184     if (i==SURFACE_NUM)
185         return VA_INVALID_SURFACE;
186     else
187         return surface_id[i];
188 }
189
190 /*
191  * Helper function for profiling purposes
192  */
193 static unsigned long get_tick_count(void)
194 {
195     struct timeval tv;
196     if (gettimeofday(&tv, NULL))
197         return 0;
198     return tv.tv_usec/1000+tv.tv_sec*1000;
199 }
200
201 static int putsurface_thread(void *data)
202 {
203     int width=win_width, height=win_height;
204     Drawable draw;
205     Window win = (Window)data;
206     Pixmap pixmap = 0;
207     GC context = NULL;
208     int quit = 0;
209     VAStatus vaStatus;
210     int row_shift = 0;
211     int index = 0;
212     Bool is_event; 
213     XEvent event;
214     unsigned int frame_num=0, start_time, putsurface_time;
215     VARectangle cliprects[2]; /* client supplied clip list */
216     
217     if (win == win_thread0) {
218         printf("Enter into thread0\n\n");
219         pixmap = pixmap_thread0;
220         context = context_thread0;
221     }
222     
223     if (win == win_thread1) {
224         printf("Enter into thread1\n\n");
225         pixmap = pixmap_thread1;
226         context = context_thread1;
227     }
228     
229     if (put_pixmap) {
230         printf("vaPutSurface into a Pixmap, then copy into the Window\n\n");
231         draw = pixmap;
232     } else {
233         printf("vaPutSurface into a Window directly\n\n");
234         draw = win;
235     }
236
237     putsurface_time = 0;
238     while (!quit) {
239         VASurfaceID surface_id = VA_INVALID_SURFACE;
240         
241         while (surface_id == VA_INVALID_SURFACE)
242             surface_id = get_next_free_surface(&index);
243
244         if (verbose) printf("Thread %x Display surface 0x%p,\n", (unsigned int)win, (void *)surface_id);
245
246         upload_surface(va_dpy, surface_id, box_width, row_shift, display_field);
247
248         start_time = get_tick_count();
249         vaStatus = vaPutSurface(va_dpy, surface_id, draw,
250                                 0,0,surface_width,surface_height,
251                                 0,0,width,height,
252                                 (test_clip==0)?NULL:&cliprects[0],
253                                 (test_clip==0)?0:2,
254                                 display_field);
255         CHECK_VASTATUS(vaStatus,"vaPutSurface");
256         putsurface_time += (get_tick_count() - start_time);
257         
258         if ((frame_num % 0xff) == 0) {
259             fprintf(stderr, "%.2f FPS             \r", 256000.0 / (float)putsurface_time);
260             putsurface_time = 0;
261
262             if (test_clip) {
263                 srand((unsigned)time(NULL));
264                 
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));
269
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);
277             }
278         }
279         
280         if (put_pixmap)
281             XCopyArea(x11_display, pixmap, win,  context, 0, 0, width, height, 0, 0);
282         
283         pthread_mutex_unlock(&surface_mutex[index]);
284
285         if (check_event) {
286             pthread_mutex_lock(&gmutex);
287             is_event = XCheckWindowEvent(x11_display, win, StructureNotifyMask|KeyPressMask,&event);
288             pthread_mutex_unlock(&gmutex);
289             if (is_event) {
290                 /* bail on any focused key press */
291                 if(event.type == KeyPress) {  
292                     quit = 1;
293                     break;
294                 }
295
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);
301                 }       
302             }
303         }
304         
305         row_shift++;
306         if (row_shift==(2*box_width)) row_shift= 0;
307
308         frame_num++;
309     }
310
311     pthread_exit(NULL);
312 }
313
314
315 int main(int argc,char **argv)
316 {
317     int major_ver, minor_ver;
318     VAStatus va_status;
319     pthread_t thread1;
320     int ret;
321     char c;
322     int i;
323
324     while ((c =getopt(argc,argv,"w:h:d:f:tcep?nv") ) != EOF) {
325         switch (c) {
326             case '?':
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");
335                 exit(0);
336                 break;
337             case 'w':
338                 win_width = atoi(optarg);
339                 break;
340             case 'h':
341                 win_height = atoi(optarg);
342                 break;
343             case 'd':
344                 box_width = atoi(optarg);
345                 break;
346             case 't':
347                 multi_thread = 1;
348                 printf("Two threads to do vaPutSurface\n");
349                 break;
350             case 'e':
351                 check_event = 0;
352                 break;
353             case 'p':
354                 put_pixmap = 1;
355                 break;
356             case 'c':
357                 test_clip = 1;
358                 break;
359             case 'f':
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;
366                 } else
367                     printf("The validate input for -f is: 1(top field)/2(bottom field)\n");
368                 break;
369             case 'v':
370                 verbose = 1;
371                 printf("Enable verbose output\n");
372                 break;
373         }
374     }
375     
376     x11_display = XOpenDisplay(":0.0");
377     if (x11_display == NULL) {
378         fprintf(stderr, "Can't connect X server!\n");
379         exit(-1);
380     }
381
382     create_window(win_width, win_height);
383
384     va_dpy = vaGetDisplay(x11_display);
385     va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
386     CHECK_VASTATUS(va_status, "vaInitialize");
387
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");
393
394     if (check_event)
395         pthread_mutex_init(&gmutex, NULL);
396     
397     for(i = 0; i< SURFACE_NUM; i++)
398         pthread_mutex_init(&surface_mutex[i], NULL);
399     
400     if (multi_thread == 1) 
401         ret = pthread_create(&thread1, NULL, (void *)putsurface_thread, (void*)win_thread1);
402
403     putsurface_thread((void *)win_thread0);
404
405     if (multi_thread == 1) 
406         pthread_join(thread1, (void **)&ret);
407
408     vaDestroySurfaces(va_dpy,&surface_id[0],SURFACE_NUM);    
409     vaTerminate(va_dpy);
410     
411     return 0;
412 }