OSDN Git Service

Add va_MessagingInit().
[android-x86/hardware-intel-common-libva.git] / va / va.c
1 /*
2  * Copyright (c) 2007 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 #define _GNU_SOURCE 1
26 #include "sysdeps.h"
27 #include "va.h"
28 #include "va_backend.h"
29 #include "va_backend_vpp.h"
30 #include "va_trace.h"
31 #include "va_fool.h"
32
33 #include <assert.h>
34 #include <stdarg.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <dlfcn.h>
39 #include <unistd.h>
40 #ifdef ANDROID
41 #include <cutils/log.h>
42 /* support versions < JellyBean */
43 #ifndef ALOGE
44 #define ALOGE LOGE
45 #endif
46 #ifndef ALOGI
47 #define ALOGI LOGI
48 #endif
49 #endif
50
51 #define DRIVER_EXTENSION        "_drv_video.so"
52
53 #define CTX(dpy) (((VADisplayContextP)dpy)->pDriverContext)
54 #define CHECK_DISPLAY(dpy) if( !vaDisplayIsValid(dpy) ) { return VA_STATUS_ERROR_INVALID_DISPLAY; }
55
56 #define ASSERT          assert
57 #define CHECK_VTABLE(s, ctx, func) if (!va_checkVtable(ctx->vtable->va##func, #func)) s = VA_STATUS_ERROR_UNKNOWN;
58 #define CHECK_MAXIMUM(s, ctx, var) if (!va_checkMaximum(ctx->max_##var, #var)) s = VA_STATUS_ERROR_UNKNOWN;
59 #define CHECK_STRING(s, ctx, var) if (!va_checkString(ctx->str_##var, #var)) s = VA_STATUS_ERROR_UNKNOWN;
60
61 /*
62  * read a config "env" for libva.conf or from environment setting
63  * libva.conf has higher priority
64  * return 0: the "env" is set, and the value is copied into env_value
65  *        1: the env is not set
66  */
67 int va_parseConfig(char *env, char *env_value)
68 {
69     char *token, *value, *saveptr;
70     char oneline[1024];
71     FILE *fp=NULL;
72
73     if (env == NULL)
74         return 1;
75     
76     fp = fopen("/etc/libva.conf", "r");
77     while (fp && (fgets(oneline, 1024, fp) != NULL)) {
78         if (strlen(oneline) == 1)
79             continue;
80         token = strtok_r(oneline, "=\n", &saveptr);
81         value = strtok_r(NULL, "=\n", &saveptr);
82
83         if (NULL == token || NULL == value)
84             continue;
85
86         if (strcmp(token, env) == 0) {
87             if (env_value) {
88                 strncpy(env_value,value, 1024);
89                 env_value[1023] = '\0';
90             }
91
92             fclose(fp);
93
94             return 0;
95         }
96     }
97     if (fp)
98         fclose(fp);
99
100     /* no setting in config file, use env setting */
101     value = getenv(env);
102     if (value) {
103         if (env_value) {
104             strncpy(env_value, value, 1024);
105             env_value[1023] = '\0';
106         }
107         return 0;
108     }
109     
110     return 1;
111 }
112
113 int vaDisplayIsValid(VADisplay dpy)
114 {
115     VADisplayContextP pDisplayContext = (VADisplayContextP)dpy;
116     return pDisplayContext && (pDisplayContext->vadpy_magic == VA_DISPLAY_MAGIC) && pDisplayContext->vaIsValid(pDisplayContext);
117 }
118
119 static void default_log_error(const char *buffer)
120 {
121 # ifdef ANDROID
122     ALOGE("%s", buffer);
123 # else
124     fprintf(stderr, "libva error: %s", buffer);
125 # endif
126 }
127
128 static void default_log_info(const char *buffer)
129 {
130 # ifdef ANDROID
131     ALOGI("%s", buffer);
132 # else
133     fprintf(stderr, "libva info: %s", buffer);
134 # endif
135 }
136
137 static vaMessageCallback va_log_error = default_log_error;
138 static vaMessageCallback va_log_info = default_log_info;
139
140 /**
141  * Set the callback for error messages, or NULL for no logging.
142  * Returns the previous one, or NULL if it was disabled.
143  */
144 vaMessageCallback vaSetErrorCallback(vaMessageCallback callback)
145 {
146     vaMessageCallback old_callback = va_log_error;
147     va_log_error = callback;
148     return old_callback;
149 }
150
151 /**
152  * Set the callback for info messages, or NULL for no logging.
153  * Returns the previous one, or NULL if it was disabled.
154  */
155 vaMessageCallback vaSetInfoCallback(vaMessageCallback callback)
156 {
157     vaMessageCallback old_callback = va_log_info;
158     va_log_info = callback;
159     return old_callback;
160 }
161
162 void va_MessagingInit()
163 {
164 #if ENABLE_VA_MESSAGING
165     char env_value[1024];
166
167     if (va_parseConfig("LIBVA_MESSAGING_LEVEL", &env_value[0]) == 0) {
168         if (strcmp(env_value, "0") == 0) {
169             vaSetInfoCallback(NULL);
170             vaSetErrorCallback(NULL);
171         }
172
173         if (strcmp(env_value, "1") == 0) {
174             vaSetInfoCallback(NULL);
175         }
176     }
177 #endif
178 }
179
180 void va_errorMessage(const char *msg, ...)
181 {
182 #if ENABLE_VA_MESSAGING
183     char buf[512], *dynbuf;
184     va_list args;
185     int n, len;
186
187     if (va_log_error == NULL)
188         return;
189
190     va_start(args, msg);
191     len = vsnprintf(buf, sizeof(buf), msg, args);
192     va_end(args);
193
194     if (len >= (int)sizeof(buf)) {
195         dynbuf = malloc(len + 1);
196         if (!dynbuf)
197             return;
198         va_start(args, msg);
199         n = vsnprintf(dynbuf, len + 1, msg, args);
200         va_end(args);
201         if (n == len)
202             va_log_error(dynbuf);
203         free(dynbuf);
204     }
205     else if (len > 0)
206         va_log_error(buf);
207 #endif
208 }
209
210 void va_infoMessage(const char *msg, ...)
211 {
212 #if ENABLE_VA_MESSAGING
213     char buf[512], *dynbuf;
214     va_list args;
215     int n, len;
216
217     if (va_log_info == NULL)
218         return;
219
220     va_start(args, msg);
221     len = vsnprintf(buf, sizeof(buf), msg, args);
222     va_end(args);
223
224     if (len >= (int)sizeof(buf)) {
225         dynbuf = malloc(len + 1);
226         if (!dynbuf)
227             return;
228         va_start(args, msg);
229         n = vsnprintf(dynbuf, len + 1, msg, args);
230         va_end(args);
231         if (n == len)
232             va_log_info(dynbuf);
233         free(dynbuf);
234     }
235     else if (len > 0)
236         va_log_info(buf);
237 #endif
238 }
239
240 static bool va_checkVtable(void *ptr, char *function)
241 {
242     if (!ptr) {
243         va_errorMessage("No valid vtable entry for va%s\n", function);
244         return false;
245     }
246     return true;
247 }
248
249 static bool va_checkMaximum(int value, char *variable)
250 {
251     if (!value) {
252         va_errorMessage("Failed to define max_%s in init\n", variable);
253         return false;
254     }
255     return true;
256 }
257
258 static bool va_checkString(const char* value, char *variable)
259 {
260     if (!value) {
261         va_errorMessage("Failed to define str_%s in init\n", variable);
262         return false;
263     }
264     return true;
265 }
266
267 static inline int
268 va_getDriverInitName(char *name, int namelen, int major, int minor)
269 {
270     int ret = snprintf(name, namelen, "__vaDriverInit_%d_%d", major, minor);
271     return ret > 0 && ret < namelen;
272 }
273
274 static VAStatus va_getDriverName(VADisplay dpy, char **driver_name)
275 {
276     VADisplayContextP pDisplayContext = (VADisplayContextP)dpy;
277
278     return pDisplayContext->vaGetDriverName(pDisplayContext, driver_name);
279 }
280
281 static VAStatus va_openDriver(VADisplay dpy, char *driver_name)
282 {
283     VADriverContextP ctx = CTX(dpy);
284     VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
285     char *search_path = NULL;
286     char *saveptr;
287     char *driver_dir;
288     
289     if (geteuid() == getuid())
290         /* don't allow setuid apps to use LIBVA_DRIVERS_PATH */
291         search_path = getenv("LIBVA_DRIVERS_PATH");
292     if (!search_path)
293         search_path = VA_DRIVERS_PATH;
294
295     search_path = strdup((const char *)search_path);
296     driver_dir = strtok_r(search_path, ":", &saveptr);
297     while (driver_dir) {
298         void *handle = NULL;
299         char *driver_path = (char *) malloc( strlen(driver_dir) +
300                                              strlen(driver_name) +
301                                              strlen(DRIVER_EXTENSION) + 2 );
302         if (!driver_path) {
303             va_errorMessage("%s L%d Out of memory!n",
304                                 __FUNCTION__, __LINE__);
305             free(search_path);    
306             return VA_STATUS_ERROR_ALLOCATION_FAILED;
307         }
308
309         strncpy( driver_path, driver_dir, strlen(driver_dir) + 1);
310         strncat( driver_path, "/", strlen("/") );
311         strncat( driver_path, driver_name, strlen(driver_name) );
312         strncat( driver_path, DRIVER_EXTENSION, strlen(DRIVER_EXTENSION) );
313         
314         va_infoMessage("Trying to open %s\n", driver_path);
315 #ifndef ANDROID
316         handle = dlopen( driver_path, RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE );
317 #else
318         handle = dlopen( driver_path, RTLD_NOW| RTLD_GLOBAL);
319 #endif
320         if (!handle) {
321             /* Don't give errors for non-existing files */
322             if (0 == access( driver_path, F_OK))
323                 va_errorMessage("dlopen of %s failed: %s\n", driver_path, dlerror());
324         } else {
325             VADriverInit init_func = NULL;
326             char init_func_s[256];
327             int i;
328
329             static const struct {
330                 int major;
331                 int minor;
332             } compatible_versions[] = {
333                 { VA_MAJOR_VERSION, VA_MINOR_VERSION },
334                 { 0, 39 },
335                 { 0, 38 },
336                 { 0, 37 },
337                 { 0, 36 },
338                 { 0, 35 },
339                 { 0, 34 },
340                 { 0, 33 },
341                 { 0, 32 },
342                 { -1, }
343             };
344
345             for (i = 0; compatible_versions[i].major >= 0; i++) {
346                 if (va_getDriverInitName(init_func_s, sizeof(init_func_s),
347                                          compatible_versions[i].major,
348                                          compatible_versions[i].minor)) {
349                     init_func = (VADriverInit)dlsym(handle, init_func_s);
350                     if (init_func) {
351                         va_infoMessage("Found init function %s\n", init_func_s);
352                         break;
353                     }
354                 }
355             }
356
357             if (compatible_versions[i].major < 0) {
358                 va_errorMessage("%s has no function %s\n",
359                                 driver_path, init_func_s);
360                 dlclose(handle);
361             } else {
362                 struct VADriverVTable *vtable = ctx->vtable;
363                 struct VADriverVTableVPP *vtable_vpp = ctx->vtable_vpp;
364
365                 vaStatus = VA_STATUS_SUCCESS;
366                 if (!vtable) {
367                     vtable = calloc(1, sizeof(*vtable));
368                     if (!vtable)
369                         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
370                 }
371                 ctx->vtable = vtable;
372
373                 if (!vtable_vpp) {
374                     vtable_vpp = calloc(1, sizeof(*vtable_vpp));
375                     if (vtable_vpp)
376                         vtable_vpp->version = VA_DRIVER_VTABLE_VPP_VERSION;
377                     else
378                         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
379                 }
380                 ctx->vtable_vpp = vtable_vpp;
381
382                 if (init_func && VA_STATUS_SUCCESS == vaStatus)
383                     vaStatus = (*init_func)(ctx);
384
385                 if (VA_STATUS_SUCCESS == vaStatus) {
386                     CHECK_MAXIMUM(vaStatus, ctx, profiles);
387                     CHECK_MAXIMUM(vaStatus, ctx, entrypoints);
388                     CHECK_MAXIMUM(vaStatus, ctx, attributes);
389                     CHECK_MAXIMUM(vaStatus, ctx, image_formats);
390                     CHECK_MAXIMUM(vaStatus, ctx, subpic_formats);
391                     CHECK_MAXIMUM(vaStatus, ctx, display_attributes);
392                     CHECK_STRING(vaStatus, ctx, vendor);
393                     CHECK_VTABLE(vaStatus, ctx, Terminate);
394                     CHECK_VTABLE(vaStatus, ctx, QueryConfigProfiles);
395                     CHECK_VTABLE(vaStatus, ctx, QueryConfigEntrypoints);
396                     CHECK_VTABLE(vaStatus, ctx, QueryConfigAttributes);
397                     CHECK_VTABLE(vaStatus, ctx, CreateConfig);
398                     CHECK_VTABLE(vaStatus, ctx, DestroyConfig);
399                     CHECK_VTABLE(vaStatus, ctx, GetConfigAttributes);
400                     CHECK_VTABLE(vaStatus, ctx, CreateSurfaces);
401                     CHECK_VTABLE(vaStatus, ctx, DestroySurfaces);
402                     CHECK_VTABLE(vaStatus, ctx, CreateContext);
403                     CHECK_VTABLE(vaStatus, ctx, DestroyContext);
404                     CHECK_VTABLE(vaStatus, ctx, CreateBuffer);
405                     CHECK_VTABLE(vaStatus, ctx, BufferSetNumElements);
406                     CHECK_VTABLE(vaStatus, ctx, MapBuffer);
407                     CHECK_VTABLE(vaStatus, ctx, UnmapBuffer);
408                     CHECK_VTABLE(vaStatus, ctx, DestroyBuffer);
409                     CHECK_VTABLE(vaStatus, ctx, BeginPicture);
410                     CHECK_VTABLE(vaStatus, ctx, RenderPicture);
411                     CHECK_VTABLE(vaStatus, ctx, EndPicture);
412                     CHECK_VTABLE(vaStatus, ctx, SyncSurface);
413                     CHECK_VTABLE(vaStatus, ctx, QuerySurfaceStatus);
414                     CHECK_VTABLE(vaStatus, ctx, PutSurface);
415                     CHECK_VTABLE(vaStatus, ctx, QueryImageFormats);
416                     CHECK_VTABLE(vaStatus, ctx, CreateImage);
417                     CHECK_VTABLE(vaStatus, ctx, DeriveImage);
418                     CHECK_VTABLE(vaStatus, ctx, DestroyImage);
419                     CHECK_VTABLE(vaStatus, ctx, SetImagePalette);
420                     CHECK_VTABLE(vaStatus, ctx, GetImage);
421                     CHECK_VTABLE(vaStatus, ctx, PutImage);
422                     CHECK_VTABLE(vaStatus, ctx, QuerySubpictureFormats);
423                     CHECK_VTABLE(vaStatus, ctx, CreateSubpicture);
424                     CHECK_VTABLE(vaStatus, ctx, DestroySubpicture);
425                     CHECK_VTABLE(vaStatus, ctx, SetSubpictureImage);
426                     CHECK_VTABLE(vaStatus, ctx, SetSubpictureChromakey);
427                     CHECK_VTABLE(vaStatus, ctx, SetSubpictureGlobalAlpha);
428                     CHECK_VTABLE(vaStatus, ctx, AssociateSubpicture);
429                     CHECK_VTABLE(vaStatus, ctx, DeassociateSubpicture);
430                     CHECK_VTABLE(vaStatus, ctx, QueryDisplayAttributes);
431                     CHECK_VTABLE(vaStatus, ctx, GetDisplayAttributes);
432                     CHECK_VTABLE(vaStatus, ctx, SetDisplayAttributes);
433                 }
434                 if (VA_STATUS_SUCCESS != vaStatus) {
435                     va_errorMessage("%s init failed\n", driver_path);
436                     dlclose(handle);
437                 }
438                 if (VA_STATUS_SUCCESS == vaStatus)
439                     ctx->handle = handle;
440                 free(driver_path);
441                 break;
442             }
443         }
444         free(driver_path);
445         
446         driver_dir = strtok_r(NULL, ":", &saveptr);
447     }
448     
449     free(search_path);    
450     
451     return vaStatus;
452 }
453
454 VAPrivFunc vaGetLibFunc(VADisplay dpy, const char *func)
455 {
456     VADriverContextP ctx;
457     if (!vaDisplayIsValid(dpy))
458         return NULL;
459     ctx = CTX(dpy);
460
461     if (NULL == ctx->handle)
462         return NULL;
463         
464     return (VAPrivFunc) dlsym(ctx->handle, func);
465 }
466
467
468 /*
469  * Returns a short english description of error_status
470  */
471 const char *vaErrorStr(VAStatus error_status)
472 {
473     switch(error_status) {
474         case VA_STATUS_SUCCESS:
475             return "success (no error)";
476         case VA_STATUS_ERROR_OPERATION_FAILED:
477             return "operation failed";
478         case VA_STATUS_ERROR_ALLOCATION_FAILED:
479             return "resource allocation failed";
480         case VA_STATUS_ERROR_INVALID_DISPLAY:
481             return "invalid VADisplay";
482         case VA_STATUS_ERROR_INVALID_CONFIG:
483             return "invalid VAConfigID";
484         case VA_STATUS_ERROR_INVALID_CONTEXT:
485             return "invalid VAContextID";
486         case VA_STATUS_ERROR_INVALID_SURFACE:
487             return "invalid VASurfaceID";
488         case VA_STATUS_ERROR_INVALID_BUFFER:
489             return "invalid VABufferID";
490         case VA_STATUS_ERROR_INVALID_IMAGE:
491             return "invalid VAImageID";
492         case VA_STATUS_ERROR_INVALID_SUBPICTURE:
493             return "invalid VASubpictureID";
494         case VA_STATUS_ERROR_ATTR_NOT_SUPPORTED:
495             return "attribute not supported";
496         case VA_STATUS_ERROR_MAX_NUM_EXCEEDED:
497             return "list argument exceeds maximum number";
498         case VA_STATUS_ERROR_UNSUPPORTED_PROFILE:
499             return "the requested VAProfile is not supported";
500         case VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT:
501             return "the requested VAEntryPoint is not supported";
502         case VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT:
503             return "the requested RT Format is not supported";
504         case VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE:
505             return "the requested VABufferType is not supported";
506         case VA_STATUS_ERROR_SURFACE_BUSY:
507             return "surface is in use";
508         case VA_STATUS_ERROR_FLAG_NOT_SUPPORTED:
509             return "flag not supported";
510         case VA_STATUS_ERROR_INVALID_PARAMETER:
511             return "invalid parameter";
512         case VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED:
513             return "resolution not supported";
514         case VA_STATUS_ERROR_UNIMPLEMENTED:
515             return "the requested function is not implemented";
516         case VA_STATUS_ERROR_SURFACE_IN_DISPLAYING:
517             return "surface is in displaying (may by overlay)" ;
518         case VA_STATUS_ERROR_INVALID_IMAGE_FORMAT:
519             return "invalid VAImageFormat";
520         case VA_STATUS_ERROR_INVALID_VALUE:
521             return "an invalid/unsupported value was supplied";
522         case VA_STATUS_ERROR_UNSUPPORTED_FILTER:
523             return "the requested filter is not supported";
524         case VA_STATUS_ERROR_INVALID_FILTER_CHAIN:
525             return "an invalid filter chain was supplied";
526         case VA_STATUS_ERROR_UNKNOWN:
527             return "unknown libva error";
528     }
529     return "unknown libva error / description missing";
530 }
531
532 const static char *prefer_driver_list[4] = {
533     "i965",
534     "hybrid",
535     "pvr",
536     "iHD",
537 };
538
539 VAStatus vaSetDriverName(
540     VADisplay dpy,
541     char *driver_name
542 )
543 {
544     VADriverContextP ctx;
545     VAStatus vaStatus = VA_STATUS_SUCCESS;
546     char *override_driver_name = NULL;
547     int i, found;
548     ctx = CTX(dpy);
549
550     if (geteuid() != getuid()) {
551         vaStatus = VA_STATUS_ERROR_OPERATION_FAILED;
552         va_errorMessage("no permission to vaSetDriverName\n");
553         return vaStatus;
554     }
555
556     if (strlen(driver_name) == 0 || strlen(driver_name) >=256) {
557         vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
558         va_errorMessage("vaSetDriverName returns %s\n",
559                          vaErrorStr(vaStatus));
560         return vaStatus;
561     }
562
563     found = 0;
564     for (i = 0; i < sizeof(prefer_driver_list) / sizeof(char *); i++) {
565         if (strlen(prefer_driver_list[i]) != strlen(driver_name))
566             continue;
567         if (!strncmp(prefer_driver_list[i], driver_name, strlen(driver_name))) {
568             found = 1;
569             break;
570         }
571     }
572
573     if (!found) {
574         vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
575         va_errorMessage("vaSetDriverName returns %s. Incorrect parameter\n",
576                          vaErrorStr(vaStatus));
577         return vaStatus;
578     }
579
580     override_driver_name = strdup(driver_name);
581
582     if (!override_driver_name) {
583         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
584         va_errorMessage("vaSetDriverName returns %s. Out of Memory\n",
585                          vaErrorStr(vaStatus));
586         return vaStatus;
587     }
588
589     ctx->override_driver_name = override_driver_name;
590     return VA_STATUS_SUCCESS;
591 }
592
593 VAStatus vaInitialize (
594     VADisplay dpy,
595     int *major_version,  /* out */
596     int *minor_version   /* out */
597 )
598 {
599     const char *driver_name_env = NULL;
600     char *driver_name = NULL;
601     VAStatus vaStatus;
602     VADriverContextP ctx;
603
604     CHECK_DISPLAY(dpy);
605
606     ctx = CTX(dpy);
607
608     va_TraceInit(dpy);
609
610     va_FoolInit(dpy);
611
612     va_MessagingInit();
613
614     va_infoMessage("VA-API version %s\n", VA_VERSION_S);
615
616     vaStatus = va_getDriverName(dpy, &driver_name);
617
618     if (!ctx->override_driver_name) {
619         va_infoMessage("va_getDriverName() returns %d\n", vaStatus);
620
621         driver_name_env = getenv("LIBVA_DRIVER_NAME");
622     } else if (vaStatus == VA_STATUS_SUCCESS) {
623         if (driver_name)
624             free(driver_name);
625
626         driver_name = strdup(ctx->override_driver_name);
627         if (!driver_name) {
628             vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
629             va_errorMessage("vaInitialize() failed with %s, out of memory\n",
630                         vaErrorStr(vaStatus));
631             return vaStatus;
632         }
633         va_infoMessage("User requested driver '%s'\n", driver_name);
634     }
635
636     if (driver_name_env && (geteuid() == getuid())) {
637         /* Don't allow setuid apps to use LIBVA_DRIVER_NAME */
638         if (driver_name) /* memory is allocated in va_getDriverName */
639             free(driver_name);
640         
641         driver_name = strdup(driver_name_env);
642         vaStatus = VA_STATUS_SUCCESS;
643         va_infoMessage("User requested driver '%s'\n", driver_name);
644     }
645
646     if ((VA_STATUS_SUCCESS == vaStatus) && (driver_name != NULL)) {
647         vaStatus = va_openDriver(dpy, driver_name);
648         va_infoMessage("va_openDriver() returns %d\n", vaStatus);
649
650         *major_version = VA_MAJOR_VERSION;
651         *minor_version = VA_MINOR_VERSION;
652     } else
653         va_errorMessage("va_getDriverName() failed with %s,driver_name=%s\n",
654                         vaErrorStr(vaStatus), driver_name);
655
656     if (driver_name)
657         free(driver_name);
658     
659     VA_TRACE_LOG(va_TraceInitialize, dpy, major_version, minor_version);
660
661     return vaStatus;
662 }
663
664
665 /*
666  * After this call, all library internal resources will be cleaned up
667  */ 
668 VAStatus vaTerminate (
669     VADisplay dpy
670 )
671 {
672   VAStatus vaStatus = VA_STATUS_SUCCESS;
673   VADisplayContextP pDisplayContext = (VADisplayContextP)dpy;
674   VADriverContextP old_ctx;
675
676   CHECK_DISPLAY(dpy);
677   old_ctx = CTX(dpy);
678
679   if (old_ctx->handle) {
680       vaStatus = old_ctx->vtable->vaTerminate(old_ctx);
681       dlclose(old_ctx->handle);
682       old_ctx->handle = NULL;
683   }
684   free(old_ctx->vtable);
685   old_ctx->vtable = NULL;
686   free(old_ctx->vtable_vpp);
687   old_ctx->vtable_vpp = NULL;
688
689   if (old_ctx->override_driver_name) {
690       free(old_ctx->override_driver_name);
691       old_ctx->override_driver_name = NULL;
692   }
693
694   VA_TRACE_LOG(va_TraceTerminate, dpy);
695
696   va_TraceEnd(dpy);
697
698   va_FoolEnd(dpy);
699
700   if (VA_STATUS_SUCCESS == vaStatus)
701       pDisplayContext->vaDestroy(pDisplayContext);
702
703   return vaStatus;
704 }
705
706 /*
707  * vaQueryVendorString returns a pointer to a zero-terminated string
708  * describing some aspects of the VA implemenation on a specific
709  * hardware accelerator. The format of the returned string is:
710  * <vendorname>-<major_version>-<minor_version>-<addtional_info>
711  * e.g. for the Intel GMA500 implementation, an example would be:
712  * "IntelGMA500-1.0-0.2-patch3
713  */
714 const char *vaQueryVendorString (
715     VADisplay dpy
716 )
717 {
718   if (!vaDisplayIsValid(dpy))
719       return NULL;
720   
721   return CTX(dpy)->str_vendor;
722 }
723
724
725 /* Get maximum number of profiles supported by the implementation */
726 int vaMaxNumProfiles (
727     VADisplay dpy
728 )
729 {
730   if (!vaDisplayIsValid(dpy))
731       return 0;
732   
733   return CTX(dpy)->max_profiles;
734 }
735
736 /* Get maximum number of entrypoints supported by the implementation */
737 int vaMaxNumEntrypoints (
738     VADisplay dpy
739 )
740 {
741   if (!vaDisplayIsValid(dpy))
742       return 0;
743   
744   return CTX(dpy)->max_entrypoints;
745 }
746
747
748 /* Get maximum number of attributs supported by the implementation */
749 int vaMaxNumConfigAttributes (
750     VADisplay dpy
751 )
752 {
753   if (!vaDisplayIsValid(dpy))
754       return 0;
755   
756   return CTX(dpy)->max_attributes;
757 }
758
759 VAStatus vaQueryConfigEntrypoints (
760     VADisplay dpy,
761     VAProfile profile,
762     VAEntrypoint *entrypoints,  /* out */
763     int *num_entrypoints        /* out */
764 )
765 {
766   VADriverContextP ctx;
767   CHECK_DISPLAY(dpy);
768   ctx = CTX(dpy);
769
770   return ctx->vtable->vaQueryConfigEntrypoints ( ctx, profile, entrypoints, num_entrypoints);
771 }
772
773 VAStatus vaGetConfigAttributes (
774     VADisplay dpy,
775     VAProfile profile,
776     VAEntrypoint entrypoint,
777     VAConfigAttrib *attrib_list, /* in/out */
778     int num_attribs
779 )
780 {
781   VADriverContextP ctx;
782   CHECK_DISPLAY(dpy);
783   ctx = CTX(dpy);
784
785   return ctx->vtable->vaGetConfigAttributes ( ctx, profile, entrypoint, attrib_list, num_attribs );
786 }
787
788 VAStatus vaQueryConfigProfiles (
789     VADisplay dpy,
790     VAProfile *profile_list,    /* out */
791     int *num_profiles           /* out */
792 )
793 {
794   VADriverContextP ctx;
795   CHECK_DISPLAY(dpy);
796   ctx = CTX(dpy);
797
798   return ctx->vtable->vaQueryConfigProfiles ( ctx, profile_list, num_profiles );
799 }
800
801 VAStatus vaCreateConfig (
802     VADisplay dpy,
803     VAProfile profile, 
804     VAEntrypoint entrypoint, 
805     VAConfigAttrib *attrib_list,
806     int num_attribs,
807     VAConfigID *config_id /* out */
808 )
809 {
810   VADriverContextP ctx;
811   VAStatus vaStatus = VA_STATUS_SUCCESS;
812   
813   CHECK_DISPLAY(dpy);
814   ctx = CTX(dpy);
815
816   vaStatus = ctx->vtable->vaCreateConfig ( ctx, profile, entrypoint, attrib_list, num_attribs, config_id );
817
818   /* record the current entrypoint for further trace/fool determination */
819   VA_TRACE_ALL(va_TraceCreateConfig, dpy, profile, entrypoint, attrib_list, num_attribs, config_id);
820   VA_FOOL_FUNC(va_FoolCreateConfig, dpy, profile, entrypoint, attrib_list, num_attribs, config_id);
821   
822   return vaStatus;
823 }
824
825 VAStatus vaDestroyConfig (
826     VADisplay dpy,
827     VAConfigID config_id
828 )
829 {
830   VADriverContextP ctx;
831   VAStatus vaStatus = VA_STATUS_SUCCESS;
832
833   CHECK_DISPLAY(dpy);
834   ctx = CTX(dpy);
835
836   vaStatus = ctx->vtable->vaDestroyConfig ( ctx, config_id );
837
838   VA_TRACE_ALL(va_TraceDestroyConfig, dpy, config_id);
839
840   return vaStatus;
841 }
842
843 VAStatus vaQueryConfigAttributes (
844     VADisplay dpy,
845     VAConfigID config_id, 
846     VAProfile *profile,         /* out */
847     VAEntrypoint *entrypoint,   /* out */
848     VAConfigAttrib *attrib_list,/* out */
849     int *num_attribs            /* out */
850 )
851 {
852   VADriverContextP ctx;
853   CHECK_DISPLAY(dpy);
854   ctx = CTX(dpy);
855
856   return ctx->vtable->vaQueryConfigAttributes( ctx, config_id, profile, entrypoint, attrib_list, num_attribs);
857 }
858
859 /* XXX: this is a slow implementation that will be removed */
860 static VAStatus
861 va_impl_query_surface_attributes(
862     VADriverContextP    ctx,
863     VAConfigID          config,
864     VASurfaceAttrib    *out_attribs,
865     unsigned int       *out_num_attribs_ptr
866 )
867 {
868     VASurfaceAttrib *attribs = NULL;
869     unsigned int num_attribs, n;
870     VASurfaceAttrib *out_attrib;
871     unsigned int out_num_attribs;
872     VAImageFormat *image_formats = NULL;
873     int num_image_formats, i;
874     VAStatus va_status;
875
876     /* List of surface attributes to query */
877     struct va_surface_attrib_map {
878         VASurfaceAttribType type;
879         VAGenericValueType  value_type;
880     };
881     static const struct va_surface_attrib_map attribs_map[] = {
882         { VASurfaceAttribMinWidth,      VAGenericValueTypeInteger },
883         { VASurfaceAttribMaxWidth,      VAGenericValueTypeInteger },
884         { VASurfaceAttribMinHeight,     VAGenericValueTypeInteger },
885         { VASurfaceAttribMaxHeight,     VAGenericValueTypeInteger },
886         { VASurfaceAttribMemoryType,    VAGenericValueTypeInteger },
887         { VASurfaceAttribNone, }
888     };
889
890     if (!out_attribs || !out_num_attribs_ptr)
891         return VA_STATUS_ERROR_INVALID_PARAMETER;
892     if (!ctx->vtable->vaGetSurfaceAttributes)
893         return VA_STATUS_ERROR_UNIMPLEMENTED;
894
895     num_image_formats = ctx->max_image_formats;
896     image_formats = malloc(num_image_formats * sizeof(*image_formats));
897     if (!image_formats) {
898         va_status = VA_STATUS_ERROR_ALLOCATION_FAILED;
899         goto end;
900     }
901
902     va_status = ctx->vtable->vaQueryImageFormats(
903         ctx, image_formats, &num_image_formats);
904     if (va_status != VA_STATUS_SUCCESS)
905         goto end;
906
907     num_attribs = VASurfaceAttribCount + num_image_formats;
908     attribs = malloc(num_attribs * sizeof(*attribs));
909     if (!attribs) {
910         va_status = VA_STATUS_ERROR_ALLOCATION_FAILED;
911         goto end;
912     }
913
914     /* Initialize with base surface attributes, except pixel-formats */
915     for (n = 0; attribs_map[n].type != VASurfaceAttribNone; n++) {
916         VASurfaceAttrib * const attrib = &attribs[n];
917         attrib->type = attribs_map[n].type;
918         attrib->flags = VA_SURFACE_ATTRIB_GETTABLE;
919         attrib->value.type = attribs_map[n].value_type;
920     }
921
922     /* Append image formats */
923     for (i = 0; i < num_image_formats; i++) {
924         VASurfaceAttrib * const attrib = &attribs[n];
925         attrib->type = VASurfaceAttribPixelFormat;
926         attrib->flags = VA_SURFACE_ATTRIB_GETTABLE|VA_SURFACE_ATTRIB_SETTABLE;
927         attrib->value.type = VAGenericValueTypeInteger;
928         attrib->value.value.i = image_formats[i].fourcc;
929         if (++n == num_attribs) {
930             va_status = VA_STATUS_ERROR_ALLOCATION_FAILED;
931             goto end;
932         }
933     }
934     num_attribs = n;
935
936     va_status = ctx->vtable->vaGetSurfaceAttributes(
937         ctx, config, attribs, num_attribs);
938     if (va_status != VA_STATUS_SUCCESS)
939         goto end;
940
941     /* Remove invalid entries */
942     out_num_attribs = 0;
943     for (n = 0; n < num_attribs; n++) {
944         VASurfaceAttrib * const attrib = &attribs[n];
945
946         if (attrib->flags == VA_SURFACE_ATTRIB_NOT_SUPPORTED)
947             continue;
948
949         // Accept all surface attributes that are not pixel-formats
950         if (attrib->type != VASurfaceAttribPixelFormat) {
951             out_num_attribs++;
952             continue;
953         }
954
955         // Drop invalid pixel-format attribute
956         if (!attrib->value.value.i) {
957             attrib->flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED;
958             continue;
959         }
960
961         // Check for duplicates
962         int is_duplicate = 0;
963         for (i = n - 1; i >= 0 && !is_duplicate; i--) {
964             const VASurfaceAttrib * const prev_attrib = &attribs[i];
965             if (prev_attrib->type != VASurfaceAttribPixelFormat)
966                 break;
967             is_duplicate = prev_attrib->value.value.i == attrib->value.value.i;
968         }
969         if (is_duplicate)
970             attrib->flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED;
971         else
972             out_num_attribs++;
973     }
974
975     if (*out_num_attribs_ptr < out_num_attribs) {
976         *out_num_attribs_ptr = out_num_attribs;
977         va_status = VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
978         goto end;
979     }
980
981     out_attrib = out_attribs;
982     for (n = 0; n < num_attribs; n++) {
983         const VASurfaceAttrib * const attrib = &attribs[n];
984         if (attrib->flags == VA_SURFACE_ATTRIB_NOT_SUPPORTED)
985             continue;
986         *out_attrib++ = *attrib;
987     }
988
989 end:
990     free(attribs);
991     free(image_formats);
992     return va_status;
993 }
994
995 VAStatus
996 vaQuerySurfaceAttributes(
997     VADisplay           dpy,
998     VAConfigID          config,
999     VASurfaceAttrib    *attrib_list,
1000     unsigned int       *num_attribs
1001 )
1002 {
1003     VADriverContextP ctx;
1004     VAStatus vaStatus;
1005
1006     CHECK_DISPLAY(dpy);
1007     ctx = CTX(dpy);
1008     if (!ctx)
1009         return VA_STATUS_ERROR_INVALID_DISPLAY;
1010
1011     if (!ctx->vtable->vaQuerySurfaceAttributes)
1012         vaStatus = va_impl_query_surface_attributes(ctx, config,
1013                                                     attrib_list, num_attribs);
1014     else
1015         vaStatus = ctx->vtable->vaQuerySurfaceAttributes(ctx, config,
1016                                                          attrib_list, num_attribs);
1017
1018     VA_TRACE_LOG(va_TraceQuerySurfaceAttributes, dpy, config, attrib_list, num_attribs);
1019
1020     return vaStatus;
1021 }
1022
1023 VAStatus
1024 vaCreateSurfaces(
1025     VADisplay           dpy,
1026     unsigned int        format,
1027     unsigned int        width,
1028     unsigned int        height,
1029     VASurfaceID        *surfaces,
1030     unsigned int        num_surfaces,
1031     VASurfaceAttrib    *attrib_list,
1032     unsigned int        num_attribs
1033 )
1034 {
1035     VADriverContextP ctx;
1036     VAStatus vaStatus;
1037
1038     CHECK_DISPLAY(dpy);
1039     ctx = CTX(dpy);
1040     if (!ctx)
1041         return VA_STATUS_ERROR_INVALID_DISPLAY;
1042
1043     if (ctx->vtable->vaCreateSurfaces2)
1044         vaStatus = ctx->vtable->vaCreateSurfaces2(ctx, format, width, height,
1045                                               surfaces, num_surfaces,
1046                                               attrib_list, num_attribs);
1047     else if (attrib_list && num_attribs > 0)
1048         vaStatus = VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
1049     else
1050         vaStatus = ctx->vtable->vaCreateSurfaces(ctx, width, height, format,
1051                                                  num_surfaces, surfaces);
1052     VA_TRACE_LOG(va_TraceCreateSurfaces,
1053                  dpy, width, height, format, num_surfaces, surfaces,
1054                  attrib_list, num_attribs);
1055
1056     return vaStatus;
1057 }
1058
1059
1060 VAStatus vaDestroySurfaces (
1061     VADisplay dpy,
1062     VASurfaceID *surface_list,
1063     int num_surfaces
1064 )
1065 {
1066   VADriverContextP ctx;
1067   VAStatus vaStatus;
1068   
1069   CHECK_DISPLAY(dpy);
1070   ctx = CTX(dpy);
1071
1072   VA_TRACE_LOG(va_TraceDestroySurfaces,
1073                dpy, surface_list, num_surfaces);
1074   
1075   vaStatus = ctx->vtable->vaDestroySurfaces( ctx, surface_list, num_surfaces );
1076   
1077   return vaStatus;
1078 }
1079
1080 VAStatus vaCreateContext (
1081     VADisplay dpy,
1082     VAConfigID config_id,
1083     int picture_width,
1084     int picture_height,
1085     int flag,
1086     VASurfaceID *render_targets,
1087     int num_render_targets,
1088     VAContextID *context                /* out */
1089 )
1090 {
1091   VADriverContextP ctx;
1092   VAStatus vaStatus;
1093   
1094   CHECK_DISPLAY(dpy);
1095   ctx = CTX(dpy);
1096
1097   vaStatus = ctx->vtable->vaCreateContext( ctx, config_id, picture_width, picture_height,
1098                                       flag, render_targets, num_render_targets, context );
1099
1100   /* keep current encode/decode resoluton */
1101   VA_TRACE_ALL(va_TraceCreateContext, dpy, config_id, picture_width, picture_height, flag, render_targets, num_render_targets, context);
1102
1103   return vaStatus;
1104 }
1105
1106 VAStatus vaDestroyContext (
1107     VADisplay dpy,
1108     VAContextID context
1109 )
1110 {
1111   VADriverContextP ctx;
1112   VAStatus vaStatus;
1113
1114   CHECK_DISPLAY(dpy);
1115   ctx = CTX(dpy);
1116
1117   vaStatus = ctx->vtable->vaDestroyContext( ctx, context );
1118
1119   VA_TRACE_ALL(va_TraceDestroyContext, dpy, context);
1120
1121   return vaStatus;
1122 }
1123
1124 VAStatus vaCreateBuffer (
1125     VADisplay dpy,
1126     VAContextID context,        /* in */
1127     VABufferType type,          /* in */
1128     unsigned int size,          /* in */
1129     unsigned int num_elements,  /* in */
1130     void *data,                 /* in */
1131     VABufferID *buf_id          /* out */
1132 )
1133 {
1134   VADriverContextP ctx;
1135   VAStatus vaStatus;
1136   
1137   CHECK_DISPLAY(dpy);
1138   ctx = CTX(dpy);
1139
1140   VA_FOOL_FUNC(va_FoolCreateBuffer, dpy, context, type, size, num_elements, data, buf_id);
1141
1142   vaStatus = ctx->vtable->vaCreateBuffer( ctx, context, type, size, num_elements, data, buf_id);
1143
1144   VA_TRACE_LOG(va_TraceCreateBuffer,
1145                dpy, context, type, size, num_elements, data, buf_id);
1146   
1147   return vaStatus;
1148 }
1149
1150 VAStatus vaBufferSetNumElements (
1151     VADisplay dpy,
1152     VABufferID buf_id,  /* in */
1153     unsigned int num_elements /* in */
1154 )
1155 {
1156   VADriverContextP ctx;
1157   CHECK_DISPLAY(dpy);
1158   ctx = CTX(dpy);
1159
1160   VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
1161   
1162   return ctx->vtable->vaBufferSetNumElements( ctx, buf_id, num_elements );
1163 }
1164
1165
1166 VAStatus vaMapBuffer (
1167     VADisplay dpy,
1168     VABufferID buf_id,  /* in */
1169     void **pbuf         /* out */
1170 )
1171 {
1172   VADriverContextP ctx;
1173   VAStatus va_status;
1174   
1175   CHECK_DISPLAY(dpy);
1176   ctx = CTX(dpy);
1177   
1178   VA_FOOL_FUNC(va_FoolMapBuffer, dpy, buf_id, pbuf);
1179   
1180   va_status = ctx->vtable->vaMapBuffer( ctx, buf_id, pbuf );
1181
1182   VA_TRACE_ALL(va_TraceMapBuffer, dpy, buf_id, pbuf);
1183   
1184   return va_status;
1185 }
1186
1187 VAStatus vaUnmapBuffer (
1188     VADisplay dpy,
1189     VABufferID buf_id   /* in */
1190 )
1191 {
1192   VADriverContextP ctx;
1193   CHECK_DISPLAY(dpy);
1194   ctx = CTX(dpy);
1195
1196   VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
1197
1198   return ctx->vtable->vaUnmapBuffer( ctx, buf_id );
1199 }
1200
1201 VAStatus vaDestroyBuffer (
1202     VADisplay dpy,
1203     VABufferID buffer_id
1204 )
1205 {
1206   VADriverContextP ctx;
1207   CHECK_DISPLAY(dpy);
1208   ctx = CTX(dpy);
1209
1210   VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
1211
1212   VA_TRACE_LOG(va_TraceDestroyBuffer,
1213                dpy, buffer_id);
1214   
1215   return ctx->vtable->vaDestroyBuffer( ctx, buffer_id );
1216 }
1217
1218 VAStatus vaBufferInfo (
1219     VADisplay dpy,
1220     VAContextID context,        /* in */
1221     VABufferID buf_id,          /* in */
1222     VABufferType *type,         /* out */
1223     unsigned int *size,         /* out */
1224     unsigned int *num_elements  /* out */
1225 )
1226 {
1227   VADriverContextP ctx;
1228   
1229   CHECK_DISPLAY(dpy);
1230   ctx = CTX(dpy);
1231
1232   VA_FOOL_FUNC(va_FoolBufferInfo, dpy, buf_id, type, size, num_elements);
1233   
1234   return ctx->vtable->vaBufferInfo( ctx, buf_id, type, size, num_elements );
1235 }
1236
1237 /* Locks buffer for external API usage */
1238 VAStatus
1239 vaAcquireBufferHandle(VADisplay dpy, VABufferID buf_id, VABufferInfo *buf_info)
1240 {
1241     VADriverContextP ctx;
1242
1243     CHECK_DISPLAY(dpy);
1244     ctx = CTX(dpy);
1245
1246     if (!ctx->vtable->vaAcquireBufferHandle)
1247         return VA_STATUS_ERROR_UNIMPLEMENTED;
1248     return ctx->vtable->vaAcquireBufferHandle(ctx, buf_id, buf_info);
1249 }
1250
1251 /* Unlocks buffer after usage from external API */
1252 VAStatus
1253 vaReleaseBufferHandle(VADisplay dpy, VABufferID buf_id)
1254 {
1255     VADriverContextP ctx;
1256
1257     CHECK_DISPLAY(dpy);
1258     ctx = CTX(dpy);
1259
1260     if (!ctx->vtable->vaReleaseBufferHandle)
1261         return VA_STATUS_ERROR_UNIMPLEMENTED;
1262     return ctx->vtable->vaReleaseBufferHandle(ctx, buf_id);
1263 }
1264
1265 VAStatus vaBeginPicture (
1266     VADisplay dpy,
1267     VAContextID context,
1268     VASurfaceID render_target
1269 )
1270 {
1271   VADriverContextP ctx;
1272   VAStatus va_status;
1273
1274   CHECK_DISPLAY(dpy);
1275   ctx = CTX(dpy);
1276
1277   VA_TRACE_ALL(va_TraceBeginPicture, dpy, context, render_target);
1278   VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
1279   
1280   va_status = ctx->vtable->vaBeginPicture( ctx, context, render_target );
1281   
1282   return va_status;
1283 }
1284
1285 VAStatus vaRenderPicture (
1286     VADisplay dpy,
1287     VAContextID context,
1288     VABufferID *buffers,
1289     int num_buffers
1290 )
1291 {
1292   VADriverContextP ctx;
1293
1294   CHECK_DISPLAY(dpy);
1295   ctx = CTX(dpy);
1296
1297   VA_TRACE_LOG(va_TraceRenderPicture, dpy, context, buffers, num_buffers);
1298   VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
1299
1300   return ctx->vtable->vaRenderPicture( ctx, context, buffers, num_buffers );
1301 }
1302
1303 VAStatus vaEndPicture (
1304     VADisplay dpy,
1305     VAContextID context
1306 )
1307 {
1308   VAStatus va_status = VA_STATUS_SUCCESS;
1309   VADriverContextP ctx;
1310
1311   CHECK_DISPLAY(dpy);
1312   ctx = CTX(dpy);
1313
1314   VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
1315
1316   va_status = ctx->vtable->vaEndPicture( ctx, context );
1317
1318   /* dump surface content */
1319   VA_TRACE_ALL(va_TraceEndPicture, dpy, context, 1);
1320
1321   return va_status;
1322 }
1323
1324 VAStatus vaSyncSurface (
1325     VADisplay dpy,
1326     VASurfaceID render_target
1327 )
1328 {
1329   VAStatus va_status;
1330   VADriverContextP ctx;
1331
1332   CHECK_DISPLAY(dpy);
1333   ctx = CTX(dpy);
1334
1335   va_status = ctx->vtable->vaSyncSurface( ctx, render_target );
1336   VA_TRACE_LOG(va_TraceSyncSurface, dpy, render_target);
1337
1338   return va_status;
1339 }
1340
1341 VAStatus vaQuerySurfaceStatus (
1342     VADisplay dpy,
1343     VASurfaceID render_target,
1344     VASurfaceStatus *status     /* out */
1345 )
1346 {
1347   VAStatus va_status;
1348   VADriverContextP ctx;
1349   CHECK_DISPLAY(dpy);
1350   ctx = CTX(dpy);
1351
1352   va_status = ctx->vtable->vaQuerySurfaceStatus( ctx, render_target, status );
1353
1354   VA_TRACE_LOG(va_TraceQuerySurfaceStatus, dpy, render_target, status);
1355
1356   return va_status;
1357 }
1358
1359 VAStatus vaQuerySurfaceError (
1360         VADisplay dpy,
1361         VASurfaceID surface,
1362         VAStatus error_status,
1363         void **error_info /*out*/
1364 )
1365 {
1366   VAStatus va_status;
1367   VADriverContextP ctx;
1368   CHECK_DISPLAY(dpy);
1369   ctx = CTX(dpy);
1370
1371   va_status = ctx->vtable->vaQuerySurfaceError( ctx, surface, error_status, error_info );
1372
1373   VA_TRACE_LOG(va_TraceQuerySurfaceError, dpy, surface, error_status, error_info);
1374
1375   return va_status;
1376 }
1377
1378 /* Get maximum number of image formats supported by the implementation */
1379 int vaMaxNumImageFormats (
1380     VADisplay dpy
1381 )
1382 {
1383   if (!vaDisplayIsValid(dpy))
1384       return 0;
1385   
1386   return CTX(dpy)->max_image_formats;
1387 }
1388
1389 VAStatus vaQueryImageFormats (
1390     VADisplay dpy,
1391     VAImageFormat *format_list, /* out */
1392     int *num_formats            /* out */
1393 )
1394 {
1395   VADriverContextP ctx;
1396   CHECK_DISPLAY(dpy);
1397   ctx = CTX(dpy);
1398
1399   return ctx->vtable->vaQueryImageFormats ( ctx, format_list, num_formats);
1400 }
1401
1402 /* 
1403  * The width and height fields returned in the VAImage structure may get 
1404  * enlarged for some YUV formats. The size of the data buffer that needs
1405  * to be allocated will be given in the "data_size" field in VAImage.
1406  * Image data is not allocated by this function.  The client should
1407  * allocate the memory and fill in the VAImage structure's data field
1408  * after looking at "data_size" returned from the library.
1409  */
1410 VAStatus vaCreateImage (
1411     VADisplay dpy,
1412     VAImageFormat *format,
1413     int width,
1414     int height,
1415     VAImage *image      /* out */
1416 )
1417 {
1418   VADriverContextP ctx;
1419   CHECK_DISPLAY(dpy);
1420   ctx = CTX(dpy);
1421
1422   return ctx->vtable->vaCreateImage ( ctx, format, width, height, image);
1423 }
1424
1425 /*
1426  * Should call DestroyImage before destroying the surface it is bound to
1427  */
1428 VAStatus vaDestroyImage (
1429     VADisplay dpy,
1430     VAImageID image
1431 )
1432 {
1433   VADriverContextP ctx;
1434   CHECK_DISPLAY(dpy);
1435   ctx = CTX(dpy);
1436
1437   return ctx->vtable->vaDestroyImage ( ctx, image);
1438 }
1439
1440 VAStatus vaSetImagePalette (
1441     VADisplay dpy,
1442     VAImageID image,
1443     unsigned char *palette
1444 )
1445 {
1446   VADriverContextP ctx;
1447   CHECK_DISPLAY(dpy);
1448   ctx = CTX(dpy);
1449
1450   return ctx->vtable->vaSetImagePalette ( ctx, image, palette);
1451 }
1452
1453 /*
1454  * Retrieve surface data into a VAImage
1455  * Image must be in a format supported by the implementation
1456  */
1457 VAStatus vaGetImage (
1458     VADisplay dpy,
1459     VASurfaceID surface,
1460     int x,      /* coordinates of the upper left source pixel */
1461     int y,
1462     unsigned int width, /* width and height of the region */
1463     unsigned int height,
1464     VAImageID image
1465 )
1466 {
1467   VADriverContextP ctx;
1468   CHECK_DISPLAY(dpy);
1469   ctx = CTX(dpy);
1470
1471   return ctx->vtable->vaGetImage ( ctx, surface, x, y, width, height, image);
1472 }
1473
1474 /*
1475  * Copy data from a VAImage to a surface
1476  * Image must be in a format supported by the implementation
1477  */
1478 VAStatus vaPutImage (
1479     VADisplay dpy,
1480     VASurfaceID surface,
1481     VAImageID image,
1482     int src_x,
1483     int src_y,
1484     unsigned int src_width,
1485     unsigned int src_height,
1486     int dest_x,
1487     int dest_y,
1488     unsigned int dest_width,
1489     unsigned int dest_height
1490 )
1491 {
1492   VADriverContextP ctx;
1493   CHECK_DISPLAY(dpy);
1494   ctx = CTX(dpy);
1495
1496   return ctx->vtable->vaPutImage ( ctx, surface, image, src_x, src_y, src_width, src_height, dest_x, dest_y, dest_width, dest_height );
1497 }
1498
1499 /*
1500  * Derive an VAImage from an existing surface.
1501  * This interface will derive a VAImage and corresponding image buffer from
1502  * an existing VA Surface. The image buffer can then be mapped/unmapped for
1503  * direct CPU access. This operation is only possible on implementations with
1504  * direct rendering capabilities and internal surface formats that can be
1505  * represented with a VAImage. When the operation is not possible this interface
1506  * will return VA_STATUS_ERROR_OPERATION_FAILED. Clients should then fall back
1507  * to using vaCreateImage + vaPutImage to accomplish the same task in an
1508  * indirect manner.
1509  *
1510  * Implementations should only return success when the resulting image buffer
1511  * would be useable with vaMap/Unmap.
1512  *
1513  * When directly accessing a surface special care must be taken to insure
1514  * proper synchronization with the graphics hardware. Clients should call
1515  * vaQuerySurfaceStatus to insure that a surface is not the target of concurrent
1516  * rendering or currently being displayed by an overlay.
1517  *
1518  * Additionally nothing about the contents of a surface should be assumed
1519  * following a vaPutSurface. Implementations are free to modify the surface for
1520  * scaling or subpicture blending within a call to vaPutImage.
1521  *
1522  * Calls to vaPutImage or vaGetImage using the same surface from which the image
1523  * has been derived will return VA_STATUS_ERROR_SURFACE_BUSY. vaPutImage or
1524  * vaGetImage with other surfaces is supported.
1525  *
1526  * An image created with vaDeriveImage should be freed with vaDestroyImage. The
1527  * image and image buffer structures will be destroyed; however, the underlying
1528  * surface will remain unchanged until freed with vaDestroySurfaces.
1529  */
1530 VAStatus vaDeriveImage (
1531     VADisplay dpy,
1532     VASurfaceID surface,
1533     VAImage *image      /* out */
1534 )
1535 {
1536   VADriverContextP ctx;
1537   CHECK_DISPLAY(dpy);
1538   ctx = CTX(dpy);
1539
1540   return ctx->vtable->vaDeriveImage ( ctx, surface, image );
1541 }
1542
1543
1544 /* Get maximum number of subpicture formats supported by the implementation */
1545 int vaMaxNumSubpictureFormats (
1546     VADisplay dpy
1547 )
1548 {
1549   if (!vaDisplayIsValid(dpy))
1550       return 0;
1551   
1552   return CTX(dpy)->max_subpic_formats;
1553 }
1554
1555 /* 
1556  * Query supported subpicture formats 
1557  * The caller must provide a "format_list" array that can hold at
1558  * least vaMaxNumSubpictureFormats() entries. The flags arrary holds the flag 
1559  * for each format to indicate additional capabilities for that format. The actual 
1560  * number of formats returned in "format_list" is returned in "num_formats".
1561  */
1562 VAStatus vaQuerySubpictureFormats (
1563     VADisplay dpy,
1564     VAImageFormat *format_list, /* out */
1565     unsigned int *flags,        /* out */
1566     unsigned int *num_formats   /* out */
1567 )
1568 {
1569   VADriverContextP ctx;
1570
1571   CHECK_DISPLAY(dpy);
1572   ctx = CTX(dpy);
1573
1574   return ctx->vtable->vaQuerySubpictureFormats ( ctx, format_list, flags, num_formats);
1575 }
1576
1577 /* 
1578  * Subpictures are created with an image associated. 
1579  */
1580 VAStatus vaCreateSubpicture (
1581     VADisplay dpy,
1582     VAImageID image,
1583     VASubpictureID *subpicture  /* out */
1584 )
1585 {
1586   VADriverContextP ctx;
1587   CHECK_DISPLAY(dpy);
1588   ctx = CTX(dpy);
1589
1590   return ctx->vtable->vaCreateSubpicture ( ctx, image, subpicture );
1591 }
1592
1593 /*
1594  * Destroy the subpicture before destroying the image it is assocated to
1595  */
1596 VAStatus vaDestroySubpicture (
1597     VADisplay dpy,
1598     VASubpictureID subpicture
1599 )
1600 {
1601   VADriverContextP ctx;
1602   CHECK_DISPLAY(dpy);
1603   ctx = CTX(dpy);
1604
1605   return ctx->vtable->vaDestroySubpicture ( ctx, subpicture);
1606 }
1607
1608 VAStatus vaSetSubpictureImage (
1609     VADisplay dpy,
1610     VASubpictureID subpicture,
1611     VAImageID image
1612 )
1613 {
1614   VADriverContextP ctx;
1615   CHECK_DISPLAY(dpy);
1616   ctx = CTX(dpy);
1617
1618   return ctx->vtable->vaSetSubpictureImage ( ctx, subpicture, image);
1619 }
1620
1621
1622 /*
1623  * If chromakey is enabled, then the area where the source value falls within
1624  * the chromakey [min, max] range is transparent
1625  */
1626 VAStatus vaSetSubpictureChromakey (
1627     VADisplay dpy,
1628     VASubpictureID subpicture,
1629     unsigned int chromakey_min,
1630     unsigned int chromakey_max,
1631     unsigned int chromakey_mask
1632 )
1633 {
1634   VADriverContextP ctx;
1635   CHECK_DISPLAY(dpy);
1636   ctx = CTX(dpy);
1637
1638   return ctx->vtable->vaSetSubpictureChromakey ( ctx, subpicture, chromakey_min, chromakey_max, chromakey_mask );
1639 }
1640
1641
1642 /*
1643  * Global alpha value is between 0 and 1. A value of 1 means fully opaque and 
1644  * a value of 0 means fully transparent. If per-pixel alpha is also specified then
1645  * the overall alpha is per-pixel alpha multiplied by the global alpha
1646  */
1647 VAStatus vaSetSubpictureGlobalAlpha (
1648     VADisplay dpy,
1649     VASubpictureID subpicture,
1650     float global_alpha 
1651 )
1652 {
1653   VADriverContextP ctx;
1654   CHECK_DISPLAY(dpy);
1655   ctx = CTX(dpy);
1656
1657   return ctx->vtable->vaSetSubpictureGlobalAlpha ( ctx, subpicture, global_alpha );
1658 }
1659
1660 /*
1661   vaAssociateSubpicture associates the subpicture with the target_surface.
1662   It defines the region mapping between the subpicture and the target 
1663   surface through source and destination rectangles (with the same width and height).
1664   Both will be displayed at the next call to vaPutSurface.  Additional
1665   associations before the call to vaPutSurface simply overrides the association.
1666 */
1667 VAStatus vaAssociateSubpicture (
1668     VADisplay dpy,
1669     VASubpictureID subpicture,
1670     VASurfaceID *target_surfaces,
1671     int num_surfaces,
1672     short src_x, /* upper left offset in subpicture */
1673     short src_y,
1674     unsigned short src_width,
1675     unsigned short src_height,
1676     short dest_x, /* upper left offset in surface */
1677     short dest_y,
1678     unsigned short dest_width,
1679     unsigned short dest_height,
1680     /*
1681      * whether to enable chroma-keying or global-alpha
1682      * see VA_SUBPICTURE_XXX values
1683      */
1684     unsigned int flags
1685 )
1686 {
1687   VADriverContextP ctx;
1688   CHECK_DISPLAY(dpy);
1689   ctx = CTX(dpy);
1690
1691   return ctx->vtable->vaAssociateSubpicture ( ctx, subpicture, target_surfaces, num_surfaces, src_x, src_y, src_width, src_height, dest_x, dest_y, dest_width, dest_height, flags );
1692 }
1693
1694 /*
1695  * vaDeassociateSubpicture removes the association of the subpicture with target_surfaces.
1696  */
1697 VAStatus vaDeassociateSubpicture (
1698     VADisplay dpy,
1699     VASubpictureID subpicture,
1700     VASurfaceID *target_surfaces,
1701     int num_surfaces
1702 )
1703 {
1704   VADriverContextP ctx;
1705   CHECK_DISPLAY(dpy);
1706   ctx = CTX(dpy);
1707
1708   return ctx->vtable->vaDeassociateSubpicture ( ctx, subpicture, target_surfaces, num_surfaces );
1709 }
1710
1711
1712 /* Get maximum number of display attributes supported by the implementation */
1713 int vaMaxNumDisplayAttributes (
1714     VADisplay dpy
1715 )
1716 {
1717   int tmp;
1718     
1719   if (!vaDisplayIsValid(dpy))
1720       return 0;
1721   
1722   tmp = CTX(dpy)->max_display_attributes;
1723
1724   VA_TRACE_LOG(va_TraceMaxNumDisplayAttributes, dpy, tmp);
1725   
1726   return tmp;
1727 }
1728
1729 /* 
1730  * Query display attributes 
1731  * The caller must provide a "attr_list" array that can hold at
1732  * least vaMaxNumDisplayAttributes() entries. The actual number of attributes
1733  * returned in "attr_list" is returned in "num_attributes".
1734  */
1735 VAStatus vaQueryDisplayAttributes (
1736     VADisplay dpy,
1737     VADisplayAttribute *attr_list,      /* out */
1738     int *num_attributes                 /* out */
1739 )
1740 {
1741   VADriverContextP ctx;
1742   VAStatus va_status;
1743   
1744   CHECK_DISPLAY(dpy);
1745   ctx = CTX(dpy);
1746   va_status = ctx->vtable->vaQueryDisplayAttributes ( ctx, attr_list, num_attributes );
1747
1748   VA_TRACE_LOG(va_TraceQueryDisplayAttributes, dpy, attr_list, num_attributes);
1749
1750   return va_status;
1751   
1752 }
1753
1754 /* 
1755  * Get display attributes 
1756  * This function returns the current attribute values in "attr_list".
1757  * Only attributes returned with VA_DISPLAY_ATTRIB_GETTABLE set in the "flags" field
1758  * from vaQueryDisplayAttributes() can have their values retrieved.  
1759  */
1760 VAStatus vaGetDisplayAttributes (
1761     VADisplay dpy,
1762     VADisplayAttribute *attr_list,      /* in/out */
1763     int num_attributes
1764 )
1765 {
1766   VADriverContextP ctx;
1767   VAStatus va_status;
1768
1769   CHECK_DISPLAY(dpy);
1770   ctx = CTX(dpy);
1771   va_status = ctx->vtable->vaGetDisplayAttributes ( ctx, attr_list, num_attributes );
1772
1773   VA_TRACE_LOG(va_TraceGetDisplayAttributes, dpy, attr_list, num_attributes);
1774   
1775   return va_status;
1776 }
1777
1778 /* 
1779  * Set display attributes 
1780  * Only attributes returned with VA_DISPLAY_ATTRIB_SETTABLE set in the "flags" field
1781  * from vaQueryDisplayAttributes() can be set.  If the attribute is not settable or 
1782  * the value is out of range, the function returns VA_STATUS_ERROR_ATTR_NOT_SUPPORTED
1783  */
1784 VAStatus vaSetDisplayAttributes (
1785     VADisplay dpy,
1786     VADisplayAttribute *attr_list,
1787     int num_attributes
1788 )
1789 {
1790   VADriverContextP ctx;
1791   VAStatus va_status;
1792   CHECK_DISPLAY(dpy);
1793   ctx = CTX(dpy);
1794
1795   va_status = ctx->vtable->vaSetDisplayAttributes ( ctx, attr_list, num_attributes );
1796   VA_TRACE_LOG(va_TraceSetDisplayAttributes, dpy, attr_list, num_attributes);
1797   
1798   return va_status;
1799 }
1800
1801 VAStatus vaLockSurface(VADisplay dpy,
1802     VASurfaceID surface,
1803     unsigned int *fourcc, /* following are output argument */
1804     unsigned int *luma_stride,
1805     unsigned int *chroma_u_stride,
1806     unsigned int *chroma_v_stride,
1807     unsigned int *luma_offset,
1808     unsigned int *chroma_u_offset,
1809     unsigned int *chroma_v_offset,
1810     unsigned int *buffer_name,
1811     void **buffer 
1812 )
1813 {
1814   VADriverContextP ctx;
1815   CHECK_DISPLAY(dpy);
1816   ctx = CTX(dpy);
1817
1818   return ctx->vtable->vaLockSurface( ctx, surface, fourcc, luma_stride, chroma_u_stride, chroma_v_stride, luma_offset, chroma_u_offset, chroma_v_offset, buffer_name, buffer);
1819 }
1820
1821
1822 VAStatus vaUnlockSurface(VADisplay dpy,
1823     VASurfaceID surface
1824 )
1825 {
1826   VADriverContextP ctx;
1827   CHECK_DISPLAY(dpy);
1828   ctx = CTX(dpy);
1829
1830   return ctx->vtable->vaUnlockSurface( ctx, surface );
1831 }
1832
1833 /* Video Processing */
1834 #define VA_VPP_INIT_CONTEXT(ctx, dpy) do {              \
1835         CHECK_DISPLAY(dpy);                             \
1836         ctx = CTX(dpy);                                 \
1837         if (!ctx)                                       \
1838             return VA_STATUS_ERROR_INVALID_DISPLAY;     \
1839     } while (0)
1840
1841 #define VA_VPP_INVOKE(dpy, func, args) do {             \
1842         if (!ctx->vtable_vpp->va##func)                 \
1843             return VA_STATUS_ERROR_UNIMPLEMENTED;       \
1844         status = ctx->vtable_vpp->va##func args;        \
1845     } while (0)
1846
1847 VAStatus
1848 vaQueryVideoProcFilters(
1849     VADisplay           dpy,
1850     VAContextID         context,
1851     VAProcFilterType   *filters,
1852     unsigned int       *num_filters
1853 )
1854 {
1855     VADriverContextP ctx;
1856     VAStatus status;
1857
1858     VA_VPP_INIT_CONTEXT(ctx, dpy);
1859     VA_VPP_INVOKE(
1860         ctx,
1861         QueryVideoProcFilters,
1862         (ctx, context, filters, num_filters)
1863     );
1864     return status;
1865 }
1866
1867 VAStatus
1868 vaQueryVideoProcFilterCaps(
1869     VADisplay           dpy,
1870     VAContextID         context,
1871     VAProcFilterType    type,
1872     void               *filter_caps,
1873     unsigned int       *num_filter_caps
1874 )
1875 {
1876     VADriverContextP ctx;
1877     VAStatus status;
1878
1879     VA_VPP_INIT_CONTEXT(ctx, dpy);
1880     VA_VPP_INVOKE(
1881         ctx,
1882         QueryVideoProcFilterCaps,
1883         (ctx, context, type, filter_caps, num_filter_caps)
1884     );
1885     return status;
1886 }
1887
1888 VAStatus
1889 vaQueryVideoProcPipelineCaps(
1890     VADisplay           dpy,
1891     VAContextID         context,
1892     VABufferID         *filters,
1893     unsigned int        num_filters,
1894     VAProcPipelineCaps *pipeline_caps
1895 )
1896 {
1897     VADriverContextP ctx;
1898     VAStatus status;
1899
1900     VA_VPP_INIT_CONTEXT(ctx, dpy);
1901     VA_VPP_INVOKE(
1902         ctx,
1903         QueryVideoProcPipelineCaps,
1904         (ctx, context, filters, num_filters, pipeline_caps)
1905     );
1906     return status;
1907 }