OSDN Git Service

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