OSDN Git Service

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