OSDN Git Service

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