OSDN Git Service

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