OSDN Git Service

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