OSDN Git Service

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