OSDN Git Service

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