OSDN Git Service

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